nmatrix 0.1.0.rc5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
  */