nmatrix 0.1.0.rc5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/Gemfile +0 -2
  4. data/History.txt +39 -4
  5. data/LICENSE.txt +3 -1
  6. data/Manifest.txt +2 -0
  7. data/README.rdoc +6 -14
  8. data/Rakefile +4 -1
  9. data/ext/nmatrix/data/data.cpp +1 -1
  10. data/ext/nmatrix/data/data.h +2 -1
  11. data/ext/nmatrix/data/rational.h +230 -226
  12. data/ext/nmatrix/extconf.rb +7 -4
  13. data/ext/nmatrix/math.cpp +259 -172
  14. data/ext/nmatrix/math/getri.h +2 -2
  15. data/ext/nmatrix/math/math.h +1 -1
  16. data/ext/nmatrix/ruby_constants.cpp +0 -1
  17. data/ext/nmatrix/ruby_nmatrix.c +55 -32
  18. data/ext/nmatrix/storage/dense/dense.cpp +1 -0
  19. data/ext/nmatrix/storage/yale/yale.cpp +12 -14
  20. data/ext/nmatrix/ttable_helper.rb +0 -1
  21. data/lib/nmatrix.rb +5 -0
  22. data/lib/nmatrix/homogeneous.rb +98 -0
  23. data/lib/nmatrix/io/fortran_format.rb +135 -0
  24. data/lib/nmatrix/io/harwell_boeing.rb +220 -0
  25. data/lib/nmatrix/io/market.rb +18 -8
  26. data/lib/nmatrix/io/mat5_reader.rb +16 -111
  27. data/lib/nmatrix/io/mat_reader.rb +3 -5
  28. data/lib/nmatrix/io/point_cloud.rb +27 -28
  29. data/lib/nmatrix/lapack.rb +3 -1
  30. data/lib/nmatrix/math.rb +112 -43
  31. data/lib/nmatrix/monkeys.rb +67 -11
  32. data/lib/nmatrix/nmatrix.rb +56 -33
  33. data/lib/nmatrix/rspec.rb +2 -2
  34. data/lib/nmatrix/shortcuts.rb +42 -25
  35. data/lib/nmatrix/version.rb +4 -4
  36. data/nmatrix.gemspec +4 -3
  37. data/spec/03_nmatrix_monkeys_spec.rb +72 -0
  38. data/spec/blas_spec.rb +4 -0
  39. data/spec/homogeneous_spec.rb +12 -4
  40. data/spec/io/fortran_format_spec.rb +88 -0
  41. data/spec/io/harwell_boeing_spec.rb +98 -0
  42. data/spec/io/test.rua +9 -0
  43. data/spec/math_spec.rb +51 -9
  44. metadata +38 -9
@@ -71,7 +71,6 @@ def create_conf_h(file) #:nodoc:
71
71
 
72
72
  # FIXME: Find a better way to do this:
73
73
  hfile.puts "#define RUBY_2 1" if RUBY_VERSION >= '2.0'
74
- hfile.puts "#define OLD_RB_SCAN_ARGS" if RUBY_VERSION < '1.9.3'
75
74
 
76
75
  for line in $defs
77
76
  line =~ /^-D(.*)/
@@ -123,7 +122,7 @@ def find_newer_gplusplus #:nodoc:
123
122
  false
124
123
  end
125
124
 
126
- def gplusplus_version #:nodoc:
125
+ def gplusplus_version
127
126
  cxxvar = proc { |n| `#{CONFIG['CXX']} -E -dM - </dev/null | grep #{n}`.chomp.split(' ')[2] }
128
127
  major = cxxvar.call('__GNUC__')
129
128
  minor = cxxvar.call('__GNUC_MINOR__')
@@ -209,8 +208,12 @@ else
209
208
  end
210
209
 
211
210
 
212
- have_func("clapack_dgetrf", ["cblas.h", "clapack.h"])
213
- have_func("clapack_dgetri", ["cblas.h", "clapack.h"])
211
+ # Although have_func is supposed to take a list as its second argument, I find that it simply
212
+ # applies a :to_s to the second arg and doesn't actually check each one. We may want to put
213
+ # have_func calls inside an :each block which checks atlas/clapack.h, cblas.h, clapack.h, and
214
+ # lastly lapack.h. On Ubuntu, it only works if I use atlas/clapack.h. --@mohawkjohn 8/20/14
215
+ have_func("clapack_dgetrf", "atlas/clapack.h")
216
+ have_func("clapack_dgetri", "atlas/clapack.h")
214
217
  have_func("dgesvd_", "clapack.h") # This may not do anything. dgesvd_ seems to be in LAPACK, not CLAPACK.
215
218
 
216
219
  have_func("cblas_dgemm", "cblas.h")
@@ -115,6 +115,7 @@
115
115
 
116
116
  #include <algorithm>
117
117
  #include <limits>
118
+ #include <cmath>
118
119
 
119
120
  #include "math/inc.h"
120
121
  #include "data/data.h"
@@ -199,185 +200,263 @@ extern "C" {
199
200
  // Math Functions //
200
201
  ////////////////////
201
202
 
202
- namespace nm { namespace math {
203
-
204
- /*
205
- * Calculate the determinant for a dense matrix (A [elements]) of size 2 or 3. Return the result.
206
- */
207
- template <typename DType>
208
- void det_exact(const int M, const void* A_elements, const int lda, void* result_arg) {
209
- DType* result = reinterpret_cast<DType*>(result_arg);
210
- const DType* A = reinterpret_cast<const DType*>(A_elements);
211
-
212
- typename LongDType<DType>::type x, y;
213
-
214
- if (M == 2) {
215
- *result = A[0] * A[lda+1] - A[1] * A[lda];
216
-
217
- } else if (M == 3) {
218
- x = A[lda+1] * A[2*lda+2] - A[lda+2] * A[2*lda+1]; // ei - fh
219
- y = A[lda] * A[2*lda+2] - A[lda+2] * A[2*lda]; // fg - di
220
- x = A[0]*x - A[1]*y ; // a*(ei-fh) - b*(fg-di)
221
-
222
- y = A[lda] * A[2*lda+1] - A[lda+1] * A[2*lda]; // dh - eg
223
- *result = A[2]*y + x; // c*(dh-eg) + _
224
- } else if (M < 2) {
225
- rb_raise(rb_eArgError, "can only calculate exact determinant of a square matrix of size 2 or larger");
226
- } else {
227
- rb_raise(rb_eNotImpError, "exact determinant calculation needed for matrices larger than 3x3");
228
- }
229
- }
203
+ namespace nm {
204
+ namespace math {
205
+
206
+ /*
207
+ * Calculate the determinant for a dense matrix (A [elements]) of size 2 or 3. Return the result.
208
+ */
209
+ template <typename DType>
210
+ void det_exact(const int M, const void* A_elements, const int lda, void* result_arg) {
211
+ DType* result = reinterpret_cast<DType*>(result_arg);
212
+ const DType* A = reinterpret_cast<const DType*>(A_elements);
213
+
214
+ typename LongDType<DType>::type x, y;
215
+
216
+ if (M == 2) {
217
+ *result = A[0] * A[lda+1] - A[1] * A[lda];
218
+
219
+ } else if (M == 3) {
220
+ x = A[lda+1] * A[2*lda+2] - A[lda+2] * A[2*lda+1]; // ei - fh
221
+ y = A[lda] * A[2*lda+2] - A[lda+2] * A[2*lda]; // fg - di
222
+ x = A[0]*x - A[1]*y ; // a*(ei-fh) - b*(fg-di)
223
+
224
+ y = A[lda] * A[2*lda+1] - A[lda+1] * A[2*lda]; // dh - eg
225
+ *result = A[2]*y + x; // c*(dh-eg) + _
226
+ } else if (M < 2) {
227
+ rb_raise(rb_eArgError, "can only calculate exact determinant of a square matrix of size 2 or larger");
228
+ } else {
229
+ rb_raise(rb_eNotImpError, "exact determinant calculation needed for matrices larger than 3x3");
230
+ }
231
+ }
230
232
 
231
233
 
232
- /*
233
- * Calculate the inverse for a dense matrix (A [elements]) of size 2 or 3. Places the result in B_elements.
234
- */
235
- template <typename DType>
236
- void inverse_exact(const int M, const void* A_elements, const int lda, void* B_elements, const int ldb) {
237
- const DType* A = reinterpret_cast<const DType*>(A_elements);
238
- DType* B = reinterpret_cast<DType*>(B_elements);
239
-
240
- if (M == 2) {
241
- DType det = A[0] * A[lda+1] - A[1] * A[lda];
242
- B[0] = A[lda+1] / det;
243
- B[1] = -A[1] / det;
244
- B[ldb] = -A[lda] / det;
245
- B[ldb+1] = -A[0] / det;
246
-
247
- } else if (M == 3) {
248
- // Calculate the exact determinant.
249
- DType det;
250
- det_exact<DType>(M, A_elements, lda, reinterpret_cast<void*>(&det));
251
- if (det == 0) {
252
- rb_raise(nm_eNotInvertibleError, "matrix must have non-zero determinant to be invertible (not getting this error does not mean matrix is invertible if you're dealing with floating points)");
234
+ /*
235
+ * Calculates in-place inverse of A_elements. Uses Gauss-Jordan elimination technique.
236
+ * In-place inversion of the matrix saves on memory and time.
237
+ *
238
+ * args - M - Shape of the matrix
239
+ * a_elements - A duplicate of the original expressed as a contiguos array
240
+ */
241
+ template <typename DType>
242
+ void inverse(const int M, void* a_elements) {
243
+ DType* matrix = reinterpret_cast<DType*>(a_elements);
244
+ int* row_index = new int[M]; // arrays for keeping track of column scrambling
245
+ int* col_index = new int[M];
246
+
247
+ for (int k = 0;k < M; ++k) {
248
+ DType akk = std::abs( matrix[k * (M + 1)] ) ; // diagonal element
249
+ int interchange = k;
250
+
251
+ for (int row = k + 1; row < M; ++row) {
252
+ DType big = std::abs( matrix[M*row + k] ); // element below the temp pivot
253
+
254
+ if ( big > akk ) {
255
+ interchange = row;
256
+ akk = big;
257
+ }
258
+ }
259
+
260
+ if (interchange != k) { // check if rows need flipping
261
+ DType temp;
262
+
263
+ for (int col = 0; col < M; ++col) {
264
+ NM_SWAP(matrix[interchange*M + col], matrix[k*M + col], temp);
265
+ }
266
+ }
267
+
268
+ row_index[k] = interchange;
269
+ col_index[k] = k;
270
+
271
+ if (matrix[k * (M + 1)] == (DType)(0)) {
272
+ rb_raise(rb_eZeroDivError, "Expected Non-Singular Matrix.");
273
+ }
274
+
275
+ DType pivot = matrix[k * (M + 1)];
276
+ matrix[k * (M + 1)] = (DType)(1); // set diagonal as 1 for in-place inversion
277
+
278
+ for (int col = 0; col < M; ++col) {
279
+ // divide each element in the kth row with the pivot
280
+ matrix[k*M + col] = matrix[k*M + col] / pivot;
281
+ }
282
+
283
+ for (int kk = 0; kk < M; ++kk) { // iterate and reduce all rows
284
+ if (kk == k) continue;
285
+
286
+ DType dum = matrix[k + M*kk];
287
+ matrix[k + M*kk] = (DType)(0); // prepare for inplace inversion
288
+ for (int col = 0; col < M; ++col) {
289
+ matrix[M*kk + col] = matrix[M*kk + col] - matrix[M*k + col] * dum;
290
+ }
291
+ }
292
+ }
293
+
294
+ // Unscramble columns
295
+ DType temp;
296
+
297
+ for (int k = M - 1; k >= 0; --k) {
298
+ if (row_index[k] != col_index[k]) {
299
+
300
+ for (int row = 0; row < M; ++row) {
301
+ NM_SWAP(matrix[row * M + row_index[k]], matrix[row * M + col_index[k]],
302
+ temp);
303
+ }
304
+ }
305
+ }
306
+
307
+ delete[] row_index;
308
+ delete[] col_index;
253
309
  }
254
310
 
255
- B[0] = ( A[lda+1] * A[2*lda+2] - A[lda+2] * A[2*lda+1]) / det; // A = ei - fh
256
- B[1] = (- A[1] * A[2*lda+2] + A[2] * A[2*lda+1]) / det; // D = -bi + ch
257
- B[2] = ( A[1] * A[lda+2] - A[2] * A[lda+1]) / det; // G = bf - ce
258
- B[ldb] = (- A[lda] * A[2*lda+2] + A[lda+2] * A[2*lda]) / det; // B = -di + fg
259
- B[ldb+1] = ( A[0] * A[2*lda+2] - A[2] * A[2*lda]) / det; // E = ai - cg
260
- B[ldb+2] = (- A[0] * A[lda+2] + A[2] * A[lda]) / det; // H = -af + cd
261
- B[2*ldb] = ( A[lda] * A[2*lda+1] - A[lda+1] * A[2*lda]) / det; // C = dh - eg
262
- B[2*ldb+1]= ( -A[0] * A[2*lda+1] + A[1] * A[2*lda]) / det; // F = -ah + bg
263
- B[2*ldb+2]= ( A[0] * A[lda+1] - A[1] * A[lda]) / det; // I = ae - bd
264
- } else if (M == 1) {
265
- B[0] = 1 / A[0];
266
- } else {
267
- rb_raise(rb_eNotImpError, "exact inverse calculation needed for matrices larger than 3x3");
268
- }
269
- }
270
-
311
+ /*
312
+ * Calculate the exact inverse for a dense matrix (A [elements]) of size 2 or 3. Places the result in B_elements.
313
+ */
314
+ template <typename DType>
315
+ void inverse_exact(const int M, const void* A_elements, const int lda, void* B_elements, const int ldb) {
316
+ const DType* A = reinterpret_cast<const DType*>(A_elements);
317
+ DType* B = reinterpret_cast<DType*>(B_elements);
318
+
319
+ if (M == 2) {
320
+ DType det = A[0] * A[lda+1] - A[1] * A[lda];
321
+ B[0] = A[lda+1] / det;
322
+ B[1] = -A[1] / det;
323
+ B[ldb] = -A[lda] / det;
324
+ B[ldb+1] = -A[0] / det;
325
+
326
+ } else if (M == 3) {
327
+ // Calculate the exact determinant.
328
+ DType det;
329
+ det_exact<DType>(M, A_elements, lda, reinterpret_cast<void*>(&det));
330
+ if (det == 0) {
331
+ rb_raise(nm_eNotInvertibleError, "matrix must have non-zero determinant to be invertible (not getting this error does not mean matrix is invertible if you're dealing with floating points)");
332
+ }
333
+
334
+ B[0] = ( A[lda+1] * A[2*lda+2] - A[lda+2] * A[2*lda+1]) / det; // A = ei - fh
335
+ B[1] = (- A[1] * A[2*lda+2] + A[2] * A[2*lda+1]) / det; // D = -bi + ch
336
+ B[2] = ( A[1] * A[lda+2] - A[2] * A[lda+1]) / det; // G = bf - ce
337
+ B[ldb] = (- A[lda] * A[2*lda+2] + A[lda+2] * A[2*lda]) / det; // B = -di + fg
338
+ B[ldb+1] = ( A[0] * A[2*lda+2] - A[2] * A[2*lda]) / det; // E = ai - cg
339
+ B[ldb+2] = (- A[0] * A[lda+2] + A[2] * A[lda]) / det; // H = -af + cd
340
+ B[2*ldb] = ( A[lda] * A[2*lda+1] - A[lda+1] * A[2*lda]) / det; // C = dh - eg
341
+ B[2*ldb+1]= ( -A[0] * A[2*lda+1] + A[1] * A[2*lda]) / det; // F = -ah + bg
342
+ B[2*ldb+2]= ( A[0] * A[lda+1] - A[1] * A[lda]) / det; // I = ae - bd
343
+ } else if (M == 1) {
344
+ B[0] = 1 / A[0];
345
+ } else {
346
+ rb_raise(rb_eNotImpError, "exact inverse calculation needed for matrices larger than 3x3");
347
+ }
348
+ }
271
349
 
272
- /*
273
- * Function signature conversion for calling CBLAS' gesvd functions as directly as possible.
274
- */
275
- template <typename DType, typename CType>
276
- inline static int lapack_gesvd(char jobu, char jobvt, int m, int n, void* a, int lda, void* s, void* u, int ldu, void* vt, int ldvt, void* work, int lwork, void* rwork) {
277
- return gesvd<DType,CType>(jobu, jobvt, m, n, reinterpret_cast<DType*>(a), lda, reinterpret_cast<DType*>(s), reinterpret_cast<DType*>(u), ldu, reinterpret_cast<DType*>(vt), ldvt, reinterpret_cast<DType*>(work), lwork, reinterpret_cast<CType*>(rwork));
278
- }
350
+ /*
351
+ * Function signature conversion for calling CBLAS' gesvd functions as directly as possible.
352
+ */
353
+ template <typename DType, typename CType>
354
+ inline static int lapack_gesvd(char jobu, char jobvt, int m, int n, void* a, int lda, void* s, void* u, int ldu, void* vt, int ldvt, void* work, int lwork, void* rwork) {
355
+ return gesvd<DType,CType>(jobu, jobvt, m, n, reinterpret_cast<DType*>(a), lda, reinterpret_cast<DType*>(s), reinterpret_cast<DType*>(u), ldu, reinterpret_cast<DType*>(vt), ldvt, reinterpret_cast<DType*>(work), lwork, reinterpret_cast<CType*>(rwork));
356
+ }
279
357
 
280
- /*
281
- * Function signature conversion for calling CBLAS' gesvd functions as directly as possible.
282
- */
283
- template <typename DType, typename CType>
284
- inline static int lapack_gesdd(char jobz, int m, int n, void* a, int lda, void* s, void* u, int ldu, void* vt, int ldvt, void* work, int lwork, int* iwork, void* rwork) {
285
- return gesdd<DType,CType>(jobz, m, n, reinterpret_cast<DType*>(a), lda, reinterpret_cast<DType*>(s), reinterpret_cast<DType*>(u), ldu, reinterpret_cast<DType*>(vt), ldvt, reinterpret_cast<DType*>(work), lwork, iwork, reinterpret_cast<CType*>(rwork));
286
- }
358
+ /*
359
+ * Function signature conversion for calling CBLAS' gesvd functions as directly as possible.
360
+ */
361
+ template <typename DType, typename CType>
362
+ inline static int lapack_gesdd(char jobz, int m, int n, void* a, int lda, void* s, void* u, int ldu, void* vt, int ldvt, void* work, int lwork, int* iwork, void* rwork) {
363
+ return gesdd<DType,CType>(jobz, m, n, reinterpret_cast<DType*>(a), lda, reinterpret_cast<DType*>(s), reinterpret_cast<DType*>(u), ldu, reinterpret_cast<DType*>(vt), ldvt, reinterpret_cast<DType*>(work), lwork, iwork, reinterpret_cast<CType*>(rwork));
364
+ }
287
365
 
288
- /*
289
- * Function signature conversion for calling CBLAS' gemm functions as directly as possible.
290
- *
291
- * For documentation: http://www.netlib.org/blas/dgemm.f
292
- */
293
- template <typename DType>
294
- inline static void cblas_gemm(const enum CBLAS_ORDER order,
295
- const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_TRANSPOSE trans_b,
296
- int m, int n, int k,
297
- void* alpha,
298
- void* a, int lda,
299
- void* b, int ldb,
300
- void* beta,
301
- void* c, int ldc)
302
- {
303
- gemm<DType>(order, trans_a, trans_b, m, n, k, reinterpret_cast<DType*>(alpha),
304
- reinterpret_cast<DType*>(a), lda,
305
- reinterpret_cast<DType*>(b), ldb, reinterpret_cast<DType*>(beta),
306
- reinterpret_cast<DType*>(c), ldc);
307
- }
366
+ /*
367
+ * Function signature conversion for calling CBLAS' gemm functions as directly as possible.
368
+ *
369
+ * For documentation: http://www.netlib.org/blas/dgemm.f
370
+ */
371
+ template <typename DType>
372
+ inline static void cblas_gemm(const enum CBLAS_ORDER order,
373
+ const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_TRANSPOSE trans_b,
374
+ int m, int n, int k,
375
+ void* alpha,
376
+ void* a, int lda,
377
+ void* b, int ldb,
378
+ void* beta,
379
+ void* c, int ldc)
380
+ {
381
+ gemm<DType>(order, trans_a, trans_b, m, n, k, reinterpret_cast<DType*>(alpha),
382
+ reinterpret_cast<DType*>(a), lda,
383
+ reinterpret_cast<DType*>(b), ldb, reinterpret_cast<DType*>(beta),
384
+ reinterpret_cast<DType*>(c), ldc);
385
+ }
308
386
 
309
387
 
310
- /*
311
- * Function signature conversion for calling CBLAS's gemv functions as directly as possible.
312
- *
313
- * For documentation: http://www.netlib.org/lapack/double/dgetrf.f
314
- */
315
- template <typename DType>
316
- inline static bool cblas_gemv(const enum CBLAS_TRANSPOSE trans,
317
- const int m, const int n,
318
- const void* alpha,
319
- const void* a, const int lda,
320
- const void* x, const int incx,
321
- const void* beta,
322
- void* y, const int incy)
323
- {
324
- return gemv<DType>(trans,
325
- m, n, reinterpret_cast<const DType*>(alpha),
326
- reinterpret_cast<const DType*>(a), lda,
327
- reinterpret_cast<const DType*>(x), incx, reinterpret_cast<const DType*>(beta),
328
- reinterpret_cast<DType*>(y), incy);
329
- }
388
+ /*
389
+ * Function signature conversion for calling CBLAS's gemv functions as directly as possible.
390
+ *
391
+ * For documentation: http://www.netlib.org/lapack/double/dgetrf.f
392
+ */
393
+ template <typename DType>
394
+ inline static bool cblas_gemv(const enum CBLAS_TRANSPOSE trans,
395
+ const int m, const int n,
396
+ const void* alpha,
397
+ const void* a, const int lda,
398
+ const void* x, const int incx,
399
+ const void* beta,
400
+ void* y, const int incy)
401
+ {
402
+ return gemv<DType>(trans,
403
+ m, n, reinterpret_cast<const DType*>(alpha),
404
+ reinterpret_cast<const DType*>(a), lda,
405
+ reinterpret_cast<const DType*>(x), incx, reinterpret_cast<const DType*>(beta),
406
+ reinterpret_cast<DType*>(y), incy);
407
+ }
330
408
 
331
409
 
332
- /*
333
- * Function signature conversion for calling CBLAS' trsm functions as directly as possible.
334
- *
335
- * For documentation: http://www.netlib.org/blas/dtrsm.f
336
- */
337
- template <typename DType>
338
- inline static void cblas_trsm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
339
- const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
340
- const int m, const int n, const void* alpha, const void* a,
341
- const int lda, void* b, const int ldb)
342
- {
343
- trsm<DType>(order, side, uplo, trans_a, diag, m, n, *reinterpret_cast<const DType*>(alpha),
344
- reinterpret_cast<const DType*>(a), lda, reinterpret_cast<DType*>(b), ldb);
345
- }
410
+ /*
411
+ * Function signature conversion for calling CBLAS' trsm functions as directly as possible.
412
+ *
413
+ * For documentation: http://www.netlib.org/blas/dtrsm.f
414
+ */
415
+ template <typename DType>
416
+ inline static void cblas_trsm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
417
+ const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
418
+ const int m, const int n, const void* alpha, const void* a,
419
+ const int lda, void* b, const int ldb)
420
+ {
421
+ trsm<DType>(order, side, uplo, trans_a, diag, m, n, *reinterpret_cast<const DType*>(alpha),
422
+ reinterpret_cast<const DType*>(a), lda, reinterpret_cast<DType*>(b), ldb);
423
+ }
346
424
 
347
425
 
348
- /*
349
- * Function signature conversion for calling CBLAS' trmm functions as directly as possible.
350
- *
351
- * For documentation: http://www.netlib.org/blas/dtrmm.f
352
- */
353
- template <typename DType>
354
- inline static void cblas_trmm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
355
- const enum CBLAS_TRANSPOSE ta, const enum CBLAS_DIAG diag, const int m, const int n, const void* alpha,
356
- const void* A, const int lda, void* B, const int ldb)
357
- {
358
- trmm<DType>(order, side, uplo, ta, diag, m, n, reinterpret_cast<const DType*>(alpha),
359
- reinterpret_cast<const DType*>(A), lda, reinterpret_cast<DType*>(B), ldb);
360
- }
426
+ /*
427
+ * Function signature conversion for calling CBLAS' trmm functions as directly as possible.
428
+ *
429
+ * For documentation: http://www.netlib.org/blas/dtrmm.f
430
+ */
431
+ template <typename DType>
432
+ inline static void cblas_trmm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
433
+ const enum CBLAS_TRANSPOSE ta, const enum CBLAS_DIAG diag, const int m, const int n, const void* alpha,
434
+ const void* A, const int lda, void* B, const int ldb)
435
+ {
436
+ trmm<DType>(order, side, uplo, ta, diag, m, n, reinterpret_cast<const DType*>(alpha),
437
+ reinterpret_cast<const DType*>(A), lda, reinterpret_cast<DType*>(B), ldb);
438
+ }
361
439
 
362
440
 
363
- /*
364
- * Function signature conversion for calling CBLAS' syrk functions as directly as possible.
365
- *
366
- * For documentation: http://www.netlib.org/blas/dsyrk.f
367
- */
368
- template <typename DType>
369
- inline static void cblas_syrk(const enum CBLAS_ORDER order, const enum CBLAS_UPLO uplo, const enum CBLAS_TRANSPOSE trans,
370
- const int n, const int k, const void* alpha,
371
- const void* A, const int lda, const void* beta, void* C, const int ldc)
372
- {
373
- syrk<DType>(order, uplo, trans, n, k, reinterpret_cast<const DType*>(alpha),
374
- reinterpret_cast<const DType*>(A), lda, reinterpret_cast<const DType*>(beta), reinterpret_cast<DType*>(C), ldc);
375
- }
441
+ /*
442
+ * Function signature conversion for calling CBLAS' syrk functions as directly as possible.
443
+ *
444
+ * For documentation: http://www.netlib.org/blas/dsyrk.f
445
+ */
446
+ template <typename DType>
447
+ inline static void cblas_syrk(const enum CBLAS_ORDER order, const enum CBLAS_UPLO uplo, const enum CBLAS_TRANSPOSE trans,
448
+ const int n, const int k, const void* alpha,
449
+ const void* A, const int lda, const void* beta, void* C, const int ldc)
450
+ {
451
+ syrk<DType>(order, uplo, trans, n, k, reinterpret_cast<const DType*>(alpha),
452
+ reinterpret_cast<const DType*>(A), lda, reinterpret_cast<const DType*>(beta), reinterpret_cast<DType*>(C), ldc);
453
+ }
376
454
 
377
455
 
378
456
 
379
457
 
380
- }} // end of namespace nm::math
458
+ }
459
+ } // end of namespace nm::math
381
460
 
382
461
 
383
462
  extern "C" {
@@ -1268,7 +1347,7 @@ static VALUE nm_clapack_lauum(VALUE self, VALUE order, VALUE uplo, VALUE n, VALU
1268
1347
  NULL, NULL, NULL, NULL, NULL,
1269
1348
  nm::math::clapack_lauum<false, float>,
1270
1349
  nm::math::clapack_lauum<false, double>,
1271
- #ifdef HAVE_CLAPACK_H
1350
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1272
1351
  clapack_clauum, clapack_zlauum, // call directly, same function signature!
1273
1352
  #else // Especially important for Mac OS, which doesn't seem to include the ATLAS clapack interface.
1274
1353
  nm::math::clapack_lauum<true, nm::Complex64>,
@@ -1323,7 +1402,7 @@ static VALUE nm_clapack_getrf(VALUE self, VALUE order, VALUE m, VALUE n, VALUE a
1323
1402
  NULL, NULL, NULL, NULL, NULL, // integers not allowed due to division
1324
1403
  nm::math::clapack_getrf<float>,
1325
1404
  nm::math::clapack_getrf<double>,
1326
- #ifdef HAVE_CLAPACK_H
1405
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1327
1406
  clapack_cgetrf, clapack_zgetrf, // call directly, same function signature!
1328
1407
  #else // Especially important for Mac OS, which doesn't seem to include the ATLAS clapack interface.
1329
1408
  nm::math::clapack_getrf<nm::Complex64>,
@@ -1370,7 +1449,7 @@ static VALUE nm_clapack_getrf(VALUE self, VALUE order, VALUE m, VALUE n, VALUE a
1370
1449
  * Returns an array giving the pivot indices (normally these are argument #5).
1371
1450
  */
1372
1451
  static VALUE nm_clapack_potrf(VALUE self, VALUE order, VALUE uplo, VALUE n, VALUE a, VALUE lda) {
1373
- #ifndef HAVE_CLAPACK_H
1452
+ #if !defined(HAVE_CLAPACK_H) && !defined(HAVE_ATLAS_CLAPACK_H)
1374
1453
  rb_raise(rb_eNotImpError, "potrf currently requires CLAPACK");
1375
1454
  #endif
1376
1455
 
@@ -1378,7 +1457,7 @@ static VALUE nm_clapack_potrf(VALUE self, VALUE order, VALUE uplo, VALUE n, VALU
1378
1457
  NULL, NULL, NULL, NULL, NULL, // integers not allowed due to division
1379
1458
  nm::math::clapack_potrf<float>,
1380
1459
  nm::math::clapack_potrf<double>,
1381
- #ifdef HAVE_CLAPACK_H
1460
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1382
1461
  clapack_cpotrf, clapack_zpotrf, // call directly, same function signature!
1383
1462
  #else // Especially important for Mac OS, which doesn't seem to include the ATLAS clapack interface.
1384
1463
  nm::math::clapack_potrf<nm::Complex64>,
@@ -1414,7 +1493,7 @@ static VALUE nm_clapack_getrs(VALUE self, VALUE order, VALUE trans, VALUE n, VAL
1414
1493
  NULL, NULL, NULL, NULL, NULL, // integers not allowed due to division
1415
1494
  nm::math::clapack_getrs<float>,
1416
1495
  nm::math::clapack_getrs<double>,
1417
- #ifdef HAVE_CLAPACK_H
1496
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1418
1497
  clapack_cgetrs, clapack_zgetrs, // call directly, same function signature!
1419
1498
  #else // Especially important for Mac OS, which doesn't seem to include the ATLAS clapack interface.
1420
1499
  nm::math::clapack_getrs<nm::Complex64>,
@@ -1460,7 +1539,7 @@ static VALUE nm_clapack_potrs(VALUE self, VALUE order, VALUE uplo, VALUE n, VALU
1460
1539
  NULL, NULL, NULL, NULL, NULL, // integers not allowed due to division
1461
1540
  nm::math::clapack_potrs<float,false>,
1462
1541
  nm::math::clapack_potrs<double,false>,
1463
- #ifdef HAVE_CLAPACK_H
1542
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1464
1543
  clapack_cpotrs, clapack_zpotrs, // call directly, same function signature!
1465
1544
  #else // Especially important for Mac OS, which doesn't seem to include the ATLAS clapack interface.
1466
1545
  nm::math::clapack_potrs<nm::Complex64,true>,
@@ -1492,7 +1571,7 @@ static VALUE nm_clapack_potrs(VALUE self, VALUE order, VALUE uplo, VALUE n, VALU
1492
1571
  * having to wait around for an exception to be thrown.
1493
1572
  */
1494
1573
  static VALUE nm_has_clapack(VALUE self) {
1495
- #ifndef HAVE_CLAPACK_H
1574
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1496
1575
  return Qfalse;
1497
1576
  #else
1498
1577
  return Qtrue;
@@ -1511,7 +1590,7 @@ static VALUE nm_has_clapack(VALUE self) {
1511
1590
  * Returns an array giving the pivot indices (normally these are argument #5).
1512
1591
  */
1513
1592
  static VALUE nm_clapack_getri(VALUE self, VALUE order, VALUE n, VALUE a, VALUE lda, VALUE ipiv) {
1514
- #ifndef HAVE_CLAPACK_H
1593
+ #if !defined (HAVE_CLAPACK_H) && !defined (HAVE_ATLAS_CLAPACK_H)
1515
1594
  rb_raise(rb_eNotImpError, "getri currently requires CLAPACK");
1516
1595
  #endif
1517
1596
 
@@ -1519,7 +1598,7 @@ static VALUE nm_clapack_getri(VALUE self, VALUE order, VALUE n, VALUE a, VALUE l
1519
1598
  NULL, NULL, NULL, NULL, NULL, // integers not allowed due to division
1520
1599
  nm::math::clapack_getri<float>,
1521
1600
  nm::math::clapack_getri<double>,
1522
- #ifdef HAVE_CLAPACK_H
1601
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1523
1602
  clapack_cgetri, clapack_zgetri, // call directly, same function signature!
1524
1603
  #else // Especially important for Mac OS, which doesn't seem to include the ATLAS clapack interface.
1525
1604
  nm::math::clapack_getri<nm::Complex64>,
@@ -1567,7 +1646,7 @@ static VALUE nm_clapack_getri(VALUE self, VALUE order, VALUE n, VALUE a, VALUE l
1567
1646
  * Returns an array giving the pivot indices (normally these are argument #5).
1568
1647
  */
1569
1648
  static VALUE nm_clapack_potri(VALUE self, VALUE order, VALUE uplo, VALUE n, VALUE a, VALUE lda) {
1570
- #ifndef HAVE_CLAPACK_H
1649
+ #if !defined (HAVE_CLAPACK_H) && !defined (HAVE_ATLAS_CLAPACK_H)
1571
1650
  rb_raise(rb_eNotImpError, "getri currently requires CLAPACK");
1572
1651
  #endif
1573
1652
 
@@ -1575,7 +1654,7 @@ static VALUE nm_clapack_potri(VALUE self, VALUE order, VALUE uplo, VALUE n, VALU
1575
1654
  NULL, NULL, NULL, NULL, NULL, // integers not allowed due to division
1576
1655
  nm::math::clapack_potri<float>,
1577
1656
  nm::math::clapack_potri<double>,
1578
- #ifdef HAVE_CLAPACK_H
1657
+ #if defined (HAVE_CLAPACK_H) || defined (HAVE_ATLAS_CLAPACK_H)
1579
1658
  clapack_cpotri, clapack_zpotri, // call directly, same function signature!
1580
1659
  #else // Especially important for Mac OS, which doesn't seem to include the ATLAS clapack interface.
1581
1660
  nm::math::clapack_potri<nm::Complex64>,
@@ -1656,6 +1735,15 @@ void nm_math_det_exact(const int M, const void* elements, const int lda, nm::dty
1656
1735
  ttable[dtype](M, elements, lda, result);
1657
1736
  }
1658
1737
 
1738
+ /*
1739
+ * C accessor for calculating an in-place inverse.
1740
+ */
1741
+ void nm_math_inverse(const int M, void* a_elements, nm::dtype_t dtype) {
1742
+ NAMED_DTYPE_TEMPLATE_TABLE(ttable, nm::math::inverse, void, const int, void*);
1743
+
1744
+ ttable[dtype](M, a_elements);
1745
+ }
1746
+
1659
1747
  /*
1660
1748
  * C accessor for calculating an exact inverse.
1661
1749
  */
@@ -1665,7 +1753,6 @@ void nm_math_inverse_exact(const int M, const void* A_elements, const int lda, v
1665
1753
  ttable[dtype](M, A_elements, lda, B_elements, ldb);
1666
1754
  }
1667
1755
 
1668
-
1669
1756
  /*
1670
1757
  * Transpose an array of elements that represent a row-major dense matrix. Does not allocate anything, only does an memcpy.
1671
1758
  */