nmatrix 0.2.3 → 0.2.4
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.
- checksums.yaml +4 -4
- data/ext/nmatrix/data/ruby_object.h +1 -1
- data/ext/nmatrix/math.cpp +274 -33
- data/ext/nmatrix/math/math.h +8 -2
- data/ext/nmatrix/ruby_nmatrix.c +81 -65
- data/lib/nmatrix/blas.rb +6 -2
- data/lib/nmatrix/cruby/math.rb +744 -0
- data/lib/nmatrix/enumerate.rb +3 -2
- data/lib/nmatrix/jruby/decomposition.rb +24 -0
- data/lib/nmatrix/jruby/enumerable.rb +13 -0
- data/lib/nmatrix/jruby/error.rb +4 -0
- data/lib/nmatrix/jruby/math.rb +501 -0
- data/lib/nmatrix/jruby/nmatrix_java.rb +840 -0
- data/lib/nmatrix/jruby/operators.rb +283 -0
- data/lib/nmatrix/jruby/slice.rb +264 -0
- data/lib/nmatrix/math.rb +233 -635
- data/lib/nmatrix/mkmf.rb +6 -9
- data/lib/nmatrix/monkeys.rb +2 -4
- data/lib/nmatrix/nmatrix.rb +62 -32
- data/lib/nmatrix/shortcuts.rb +8 -3
- data/lib/nmatrix/version.rb +1 -1
- data/spec/00_nmatrix_spec.rb +110 -3
- data/spec/01_enum_spec.rb +7 -1
- data/spec/02_slice_spec.rb +19 -1
- data/spec/03_nmatrix_monkeys_spec.rb +2 -0
- data/spec/elementwise_spec.rb +10 -2
- data/spec/homogeneous_spec.rb +1 -0
- data/spec/io_spec.rb +11 -1
- data/spec/math_spec.rb +346 -102
- data/spec/rspec_spec.rb +1 -0
- data/spec/shortcuts_spec.rb +47 -23
- data/spec/slice_set_spec.rb +7 -2
- data/spec/stat_spec.rb +11 -0
- metadata +20 -41
- data/ext/nmatrix/ttable_helper.rb +0 -115
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0860add5c9502fe90139d362beaf61c116b07a9
|
4
|
+
data.tar.gz: c3880411c97cdf56a9bff9e2b35df05cf218f2c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9e8f203ce54fb5a53fef9011b6ba6fed3b4080e0d28364625ef63892cb5381153cb0aef6e5e6d1ad9d286f0df588f591263cd9f50872df543fba146da58ce73
|
7
|
+
data.tar.gz: 0c4e726871ca3c69d4b522acd9c5c05caba55bcce54339330762ca39d100c9159730ae16430f3319e9042e09b9a76b6d7cb54cb1b0bdfe77e1d25ad1f1693e79
|
@@ -110,7 +110,7 @@ class RubyObject {
|
|
110
110
|
inline operator VALUE() const { return rval; }
|
111
111
|
//inline operator uint32_t() const { return NUM2ULONG(this->rval); }
|
112
112
|
inline operator int64_t() const { RETURN_OBJ2NUM(NUM2LONG) }
|
113
|
-
inline operator uint64_t() const { RETURN_OBJ2NUM(NUM2ULONG) }
|
113
|
+
//inline operator uint64_t() const { RETURN_OBJ2NUM(NUM2ULONG) }
|
114
114
|
inline operator double() const { RETURN_OBJ2NUM(NUM2DBL) }
|
115
115
|
inline operator float() const { RETURN_OBJ2NUM(NUM2DBL) }
|
116
116
|
|
data/ext/nmatrix/math.cpp
CHANGED
@@ -188,14 +188,14 @@ extern "C" {
|
|
188
188
|
// Math Functions //
|
189
189
|
////////////////////
|
190
190
|
|
191
|
-
namespace nm {
|
191
|
+
namespace nm {
|
192
192
|
namespace math {
|
193
193
|
|
194
194
|
/*
|
195
195
|
* Calculate the determinant for a dense matrix (A [elements]) of size 2 or 3. Return the result.
|
196
196
|
*/
|
197
197
|
template <typename DType>
|
198
|
-
void
|
198
|
+
void det_exact_from_dense(const int M, const void* A_elements, const int lda, void* result_arg) {
|
199
199
|
DType* result = reinterpret_cast<DType*>(result_arg);
|
200
200
|
const DType* A = reinterpret_cast<const DType*>(A_elements);
|
201
201
|
|
@@ -203,7 +203,6 @@ namespace nm {
|
|
203
203
|
|
204
204
|
if (M == 2) {
|
205
205
|
*result = A[0] * A[lda+1] - A[1] * A[lda];
|
206
|
-
|
207
206
|
} else if (M == 3) {
|
208
207
|
x = A[lda+1] * A[2*lda+2] - A[lda+2] * A[2*lda+1]; // ei - fh
|
209
208
|
y = A[lda] * A[2*lda+2] - A[lda+2] * A[2*lda]; // fg - di
|
@@ -220,9 +219,99 @@ namespace nm {
|
|
220
219
|
|
221
220
|
//we can't do det_exact on byte, because it will want to return a byte (unsigned), but determinants can be negative, even if all elements of the matrix are positive
|
222
221
|
template <>
|
223
|
-
void
|
222
|
+
void det_exact_from_dense<uint8_t>(const int M, const void* A_elements, const int lda, void* result_arg) {
|
224
223
|
rb_raise(nm_eDataTypeError, "cannot call det_exact on unsigned type");
|
225
224
|
}
|
225
|
+
/*
|
226
|
+
* Calculate the determinant for a yale matrix (storage) of size 2 or 3. Return the result.
|
227
|
+
*/
|
228
|
+
template <typename DType>
|
229
|
+
void det_exact_from_yale(const int M, const YALE_STORAGE* storage, const int lda, void* result_arg) {
|
230
|
+
DType* result = reinterpret_cast<DType*>(result_arg);
|
231
|
+
IType* ija = reinterpret_cast<IType *>(storage->ija);
|
232
|
+
DType* a = reinterpret_cast<DType*>(storage->a);
|
233
|
+
IType col_pos = storage->shape[0] + 1;
|
234
|
+
if (M == 2) {
|
235
|
+
if (ija[2] - ija[0] == 2) {
|
236
|
+
*result = a[0] * a[1] - a[col_pos] * a[col_pos+1];
|
237
|
+
}
|
238
|
+
else { *result = a[0] * a[1]; }
|
239
|
+
} else if (M == 3) {
|
240
|
+
DType m[3][3];
|
241
|
+
for (int i = 0; i < 3; ++i) {
|
242
|
+
m[i][i] = a[i];
|
243
|
+
switch(ija[i+1] - ija[i]) {
|
244
|
+
case 2:
|
245
|
+
m[i][ija[col_pos]] = a[col_pos];
|
246
|
+
m[i][ija[col_pos+1]] = a[col_pos+1];
|
247
|
+
col_pos += 2;
|
248
|
+
break;
|
249
|
+
case 1:
|
250
|
+
m[i][(i+1)%3] = m[i][(i+2)%3] = 0;
|
251
|
+
m[i][ija[col_pos]] = a[col_pos];
|
252
|
+
++col_pos;
|
253
|
+
break;
|
254
|
+
case 0:
|
255
|
+
m[i][(i+1)%3] = m[i][(i+2)%3] = 0;
|
256
|
+
break;
|
257
|
+
default:
|
258
|
+
rb_raise(rb_eArgError, "some value in IJA is incorrect!");
|
259
|
+
}
|
260
|
+
}
|
261
|
+
*result =
|
262
|
+
m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0] + m[0][2] * m[1][0] * m[2][1]
|
263
|
+
- m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] - m[0][2] * m[1][1] * m[2][0];
|
264
|
+
|
265
|
+
} else if (M < 2) {
|
266
|
+
rb_raise(rb_eArgError, "can only calculate exact determinant of a square matrix of size 2 or larger");
|
267
|
+
} else {
|
268
|
+
rb_raise(rb_eNotImpError, "exact determinant calculation needed for matrices larger than 3x3");
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
/*
|
273
|
+
* Solve a system of linear equations using forward-substution followed by
|
274
|
+
* back substution from the LU factorization of the matrix of co-efficients.
|
275
|
+
* Replaces x_elements with the result. Works only with non-integer, non-object
|
276
|
+
* data types.
|
277
|
+
*
|
278
|
+
* args - r -> The number of rows of the matrix.
|
279
|
+
* lu_elements -> Elements of the LU decomposition of the co-efficients
|
280
|
+
* matrix, as a contiguos array.
|
281
|
+
* b_elements -> Elements of the the right hand sides, as a contiguous array.
|
282
|
+
* x_elements -> The array that will contain the results of the computation.
|
283
|
+
* pivot -> Positions of permuted rows.
|
284
|
+
*/
|
285
|
+
template <typename DType>
|
286
|
+
void solve(const int r, const void* lu_elements, const void* b_elements, void* x_elements, const int* pivot) {
|
287
|
+
int ii = 0, ip;
|
288
|
+
DType sum;
|
289
|
+
|
290
|
+
const DType* matrix = reinterpret_cast<const DType*>(lu_elements);
|
291
|
+
const DType* b = reinterpret_cast<const DType*>(b_elements);
|
292
|
+
DType* x = reinterpret_cast<DType*>(x_elements);
|
293
|
+
|
294
|
+
for (int i = 0; i < r; ++i) { x[i] = b[i]; }
|
295
|
+
for (int i = 0; i < r; ++i) { // forward substitution loop
|
296
|
+
ip = pivot[i];
|
297
|
+
sum = x[ip];
|
298
|
+
x[ip] = x[i];
|
299
|
+
|
300
|
+
if (ii != 0) {
|
301
|
+
for (int j = ii - 1;j < i; ++j) { sum = sum - matrix[i * r + j] * x[j]; }
|
302
|
+
}
|
303
|
+
else if (sum != 0.0) {
|
304
|
+
ii = i + 1;
|
305
|
+
}
|
306
|
+
x[i] = sum;
|
307
|
+
}
|
308
|
+
|
309
|
+
for (int i = r - 1; i >= 0; --i) { // back substitution loop
|
310
|
+
sum = x[i];
|
311
|
+
for (int j = i + 1; j < r; j++) { sum = sum - matrix[i * r + j] * x[j]; }
|
312
|
+
x[i] = sum/matrix[i * r + i];
|
313
|
+
}
|
314
|
+
}
|
226
315
|
|
227
316
|
/*
|
228
317
|
* Calculates in-place inverse of A_elements. Uses Gauss-Jordan elimination technique.
|
@@ -246,18 +335,18 @@ namespace nm {
|
|
246
335
|
for (int row = k + 1; row < M; ++row) {
|
247
336
|
typename MagnitudeDType<DType>::type big;
|
248
337
|
big = magnitude( matrix[M*row + k] ); // element below the temp pivot
|
249
|
-
|
338
|
+
|
250
339
|
if ( big > akk ) {
|
251
340
|
interchange = row;
|
252
|
-
akk = big;
|
341
|
+
akk = big;
|
253
342
|
}
|
254
|
-
}
|
343
|
+
}
|
255
344
|
|
256
345
|
if (interchange != k) { // check if rows need flipping
|
257
346
|
DType temp;
|
258
347
|
|
259
348
|
for (int col = 0; col < M; ++col) {
|
260
|
-
NM_SWAP(matrix[interchange*M + col], matrix[k*M + col], temp);
|
349
|
+
NM_SWAP(matrix[interchange*M + col], matrix[k*M + col], temp);
|
261
350
|
}
|
262
351
|
}
|
263
352
|
|
@@ -271,7 +360,7 @@ namespace nm {
|
|
271
360
|
DType pivot = matrix[k * (M + 1)];
|
272
361
|
matrix[k * (M + 1)] = (DType)(1); // set diagonal as 1 for in-place inversion
|
273
362
|
|
274
|
-
for (int col = 0; col < M; ++col) {
|
363
|
+
for (int col = 0; col < M; ++col) {
|
275
364
|
// divide each element in the kth row with the pivot
|
276
365
|
matrix[k*M + col] = matrix[k*M + col] / pivot;
|
277
366
|
}
|
@@ -280,7 +369,7 @@ namespace nm {
|
|
280
369
|
if (kk == k) continue;
|
281
370
|
|
282
371
|
DType dum = matrix[k + M*kk];
|
283
|
-
matrix[k + M*kk] = (DType)(0); // prepare for inplace inversion
|
372
|
+
matrix[k + M*kk] = (DType)(0); // prepare for inplace inversion
|
284
373
|
for (int col = 0; col < M; ++col) {
|
285
374
|
matrix[M*kk + col] = matrix[M*kk + col] - matrix[M*k + col] * dum;
|
286
375
|
}
|
@@ -295,7 +384,7 @@ namespace nm {
|
|
295
384
|
|
296
385
|
for (int row = 0; row < M; ++row) {
|
297
386
|
NM_SWAP(matrix[row * M + row_index[k]], matrix[row * M + col_index[k]],
|
298
|
-
temp);
|
387
|
+
temp);
|
299
388
|
}
|
300
389
|
}
|
301
390
|
}
|
@@ -321,14 +410,14 @@ namespace nm {
|
|
321
410
|
DType sum_of_squares, *p_row, *psubdiag, *p_a, scale, innerproduct;
|
322
411
|
int i, k, col;
|
323
412
|
|
324
|
-
// For each column use a Householder transformation to zero all entries
|
413
|
+
// For each column use a Householder transformation to zero all entries
|
325
414
|
// below the subdiagonal.
|
326
|
-
for (psubdiag = a + nrows, col = 0; col < nrows - 2; psubdiag += nrows + 1,
|
415
|
+
for (psubdiag = a + nrows, col = 0; col < nrows - 2; psubdiag += nrows + 1,
|
327
416
|
col++) {
|
328
417
|
// Calculate the signed square root of the sum of squares of the
|
329
418
|
// elements below the diagonal.
|
330
419
|
|
331
|
-
for (p_a = psubdiag, sum_of_squares = 0.0, i = col + 1; i < nrows;
|
420
|
+
for (p_a = psubdiag, sum_of_squares = 0.0, i = col + 1; i < nrows;
|
332
421
|
p_a += nrows, i++) {
|
333
422
|
sum_of_squares += *p_a * *p_a;
|
334
423
|
}
|
@@ -358,7 +447,7 @@ namespace nm {
|
|
358
447
|
*p_a -= u[k] * innerproduct;
|
359
448
|
}
|
360
449
|
}
|
361
|
-
|
450
|
+
|
362
451
|
// Postmultiply QA by Q
|
363
452
|
for (p_row = a, i = 0; i < nrows; p_row += nrows, i++) {
|
364
453
|
for (innerproduct = 0.0, k = col + 1; k < nrows; k++) {
|
@@ -375,33 +464,34 @@ namespace nm {
|
|
375
464
|
delete[] u;
|
376
465
|
}
|
377
466
|
|
467
|
+
void raise_not_invertible_error() {
|
468
|
+
rb_raise(nm_eNotInvertibleError,
|
469
|
+
"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)");
|
470
|
+
}
|
471
|
+
|
378
472
|
/*
|
379
473
|
* Calculate the exact inverse for a dense matrix (A [elements]) of size 2 or 3. Places the result in B_elements.
|
380
474
|
*/
|
381
475
|
template <typename DType>
|
382
|
-
void
|
476
|
+
void inverse_exact_from_dense(const int M, const void* A_elements,
|
477
|
+
const int lda, void* B_elements, const int ldb) {
|
478
|
+
|
383
479
|
const DType* A = reinterpret_cast<const DType*>(A_elements);
|
384
480
|
DType* B = reinterpret_cast<DType*>(B_elements);
|
385
481
|
|
386
482
|
if (M == 2) {
|
387
483
|
DType det = A[0] * A[lda+1] - A[1] * A[lda];
|
388
|
-
if (det == 0) {
|
389
|
-
rb_raise(nm_eNotInvertibleError,
|
390
|
-
"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)");
|
391
|
-
}
|
484
|
+
if (det == 0) { raise_not_invertible_error(); }
|
392
485
|
B[0] = A[lda+1] / det;
|
393
486
|
B[1] = -A[1] / det;
|
394
487
|
B[ldb] = -A[lda] / det;
|
395
|
-
B[ldb+1] =
|
488
|
+
B[ldb+1] = A[0] / det;
|
396
489
|
|
397
490
|
} else if (M == 3) {
|
398
491
|
// Calculate the exact determinant.
|
399
492
|
DType det;
|
400
|
-
|
401
|
-
if (det == 0) {
|
402
|
-
rb_raise(nm_eNotInvertibleError,
|
403
|
-
"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)");
|
404
|
-
}
|
493
|
+
det_exact_from_dense<DType>(M, A_elements, lda, reinterpret_cast<void*>(&det));
|
494
|
+
if (det == 0) { raise_not_invertible_error(); }
|
405
495
|
|
406
496
|
B[0] = ( A[lda+1] * A[2*lda+2] - A[lda+2] * A[2*lda+1]) / det; // A = ei - fh
|
407
497
|
B[1] = (- A[1] * A[2*lda+2] + A[2] * A[2*lda+1]) / det; // D = -bi + ch
|
@@ -419,6 +509,113 @@ namespace nm {
|
|
419
509
|
}
|
420
510
|
}
|
421
511
|
|
512
|
+
template <typename DType>
|
513
|
+
void inverse_exact_from_yale(const int M, const YALE_STORAGE* storage,
|
514
|
+
const int lda, YALE_STORAGE* inverse, const int ldb) {
|
515
|
+
|
516
|
+
// inverse is a clone of storage
|
517
|
+
const DType* a = reinterpret_cast<const DType*>(storage->a);
|
518
|
+
const IType* ija = reinterpret_cast<const IType *>(storage->ija);
|
519
|
+
DType* b = reinterpret_cast<DType*>(inverse->a);
|
520
|
+
IType* ijb = reinterpret_cast<IType *>(inverse->ija);
|
521
|
+
IType col_pos = storage->shape[0] + 1;
|
522
|
+
// Calculate the exact determinant.
|
523
|
+
DType det;
|
524
|
+
|
525
|
+
if (M == 2) {
|
526
|
+
IType ndnz = ija[2] - ija[0];
|
527
|
+
if (ndnz == 2) {
|
528
|
+
det = a[0] * a[1] - a[col_pos] * a[col_pos+1];
|
529
|
+
}
|
530
|
+
else { det = a[0] * a[1]; }
|
531
|
+
if (det == 0) { raise_not_invertible_error(); }
|
532
|
+
b[0] = a[1] / det;
|
533
|
+
b[1] = a[0] / det;
|
534
|
+
if (ndnz == 2) {
|
535
|
+
b[col_pos] = -a[col_pos] / det;
|
536
|
+
b[col_pos+1] = -a[col_pos+1] / det;
|
537
|
+
}
|
538
|
+
else if (ndnz == 1) {
|
539
|
+
b[col_pos] = -a[col_pos] / det;
|
540
|
+
}
|
541
|
+
|
542
|
+
} else if (M == 3) {
|
543
|
+
DType *A = new DType[lda*3];
|
544
|
+
for (int i = 0; i < lda; ++i) {
|
545
|
+
A[i*3+i] = a[i];
|
546
|
+
switch (ija[i+1] - ija[i]) {
|
547
|
+
case 2:
|
548
|
+
A[i*3 + ija[col_pos]] = a[col_pos];
|
549
|
+
A[i*3 + ija[col_pos+1]] = a[col_pos+1];
|
550
|
+
col_pos += 2;
|
551
|
+
break;
|
552
|
+
case 1:
|
553
|
+
A[i*3 + (i+1)%3] = A[i*3 + (i+2)%3] = 0;
|
554
|
+
A[i*3 + ija[col_pos]] = a[col_pos];
|
555
|
+
col_pos += 1;
|
556
|
+
break;
|
557
|
+
case 0:
|
558
|
+
A[i*3 + (i+1)%3] = A[i*3 + (i+2)%3] = 0;
|
559
|
+
break;
|
560
|
+
default:
|
561
|
+
rb_raise(rb_eArgError, "some value in IJA is incorrect!");
|
562
|
+
}
|
563
|
+
}
|
564
|
+
det =
|
565
|
+
A[0] * A[lda+1] * A[2*lda+2] + A[1] * A[lda+2] * A[2*lda] + A[2] * A[lda] * A[2*lda+1]
|
566
|
+
- A[0] * A[lda+2] * A[2*lda+1] - A[1] * A[lda] * A[2*lda+2] - A[2] * A[lda+1] * A[2*lda];
|
567
|
+
if (det == 0) { raise_not_invertible_error(); }
|
568
|
+
|
569
|
+
DType *B = new DType[3*ldb];
|
570
|
+
B[0] = ( A[lda+1] * A[2*lda+2] - A[lda+2] * A[2*lda+1]) / det; // A = ei - fh
|
571
|
+
B[1] = (- A[1] * A[2*lda+2] + A[2] * A[2*lda+1]) / det; // D = -bi + ch
|
572
|
+
B[2] = ( A[1] * A[lda+2] - A[2] * A[lda+1]) / det; // G = bf - ce
|
573
|
+
B[ldb] = (- A[lda] * A[2*lda+2] + A[lda+2] * A[2*lda]) / det; // B = -di + fg
|
574
|
+
B[ldb+1] = ( A[0] * A[2*lda+2] - A[2] * A[2*lda]) / det; // E = ai - cg
|
575
|
+
B[ldb+2] = (- A[0] * A[lda+2] + A[2] * A[lda]) / det; // H = -af + cd
|
576
|
+
B[2*ldb] = ( A[lda] * A[2*lda+1] - A[lda+1] * A[2*lda]) / det; // C = dh - eg
|
577
|
+
B[2*ldb+1]= ( -A[0] * A[2*lda+1] + A[1] * A[2*lda]) / det; // F = -ah + bg
|
578
|
+
B[2*ldb+2]= ( A[0] * A[lda+1] - A[1] * A[lda]) / det; // I = ae - bd
|
579
|
+
|
580
|
+
// Calculate the size of ijb and b, then reallocate them.
|
581
|
+
IType ndnz = 0;
|
582
|
+
for (int i = 0; i < 3; ++i) {
|
583
|
+
for (int j = 0; j < 3; ++j) {
|
584
|
+
if (j != i && B[i*ldb + j] != 0) { ++ndnz; }
|
585
|
+
}
|
586
|
+
}
|
587
|
+
inverse->ndnz = ndnz;
|
588
|
+
col_pos = 4; // shape[0] + 1
|
589
|
+
inverse->capacity = 4 + ndnz;
|
590
|
+
NM_REALLOC_N(inverse->a, DType, 4 + ndnz);
|
591
|
+
NM_REALLOC_N(inverse->ija, IType, 4 + ndnz);
|
592
|
+
b = reinterpret_cast<DType*>(inverse->a);
|
593
|
+
ijb = reinterpret_cast<IType *>(inverse->ija);
|
594
|
+
|
595
|
+
for (int i = 0; i < 3; ++i) {
|
596
|
+
ijb[i] = col_pos;
|
597
|
+
for (int j = 0; j < 3; ++j) {
|
598
|
+
if (j == i) {
|
599
|
+
b[i] = B[i*ldb + j];
|
600
|
+
}
|
601
|
+
else if (B[i*ldb + j] != 0) {
|
602
|
+
b[col_pos] = B[i*ldb + j];
|
603
|
+
ijb[col_pos] = j;
|
604
|
+
++col_pos;
|
605
|
+
}
|
606
|
+
}
|
607
|
+
}
|
608
|
+
b[3] = 0;
|
609
|
+
ijb[3] = col_pos;
|
610
|
+
delete [] B;
|
611
|
+
delete [] A;
|
612
|
+
} else if (M == 1) {
|
613
|
+
b[0] = 1 / a[0];
|
614
|
+
} else {
|
615
|
+
rb_raise(rb_eNotImpError, "exact inverse calculation needed for matrices larger than 3x3");
|
616
|
+
}
|
617
|
+
}
|
618
|
+
|
422
619
|
/*
|
423
620
|
* Function signature conversion for calling CBLAS' gemm functions as directly as possible.
|
424
621
|
*
|
@@ -1068,14 +1265,43 @@ static VALUE nm_clapack_laswp(VALUE self, VALUE n, VALUE a, VALUE lda, VALUE k1,
|
|
1068
1265
|
|
1069
1266
|
|
1070
1267
|
/*
|
1071
|
-
* C accessor for calculating an exact determinant.
|
1268
|
+
* C accessor for calculating an exact determinant. Dense matrix version.
|
1072
1269
|
*/
|
1073
|
-
void
|
1074
|
-
|
1270
|
+
void nm_math_det_exact_from_dense(const int M, const void* elements, const int lda,
|
1271
|
+
nm::dtype_t dtype, void* result) {
|
1272
|
+
NAMED_DTYPE_TEMPLATE_TABLE(ttable, nm::math::det_exact_from_dense, void, const int M,
|
1273
|
+
const void* A_elements, const int lda, void* result_arg);
|
1075
1274
|
|
1076
1275
|
ttable[dtype](M, elements, lda, result);
|
1077
1276
|
}
|
1078
1277
|
|
1278
|
+
/*
|
1279
|
+
* C accessor for calculating an exact determinant. Yale matrix version.
|
1280
|
+
*/
|
1281
|
+
void nm_math_det_exact_from_yale(const int M, const YALE_STORAGE* storage, const int lda,
|
1282
|
+
nm::dtype_t dtype, void* result) {
|
1283
|
+
NAMED_DTYPE_TEMPLATE_TABLE(ttable, nm::math::det_exact_from_yale, void, const int M,
|
1284
|
+
const YALE_STORAGE* storage, const int lda, void* result_arg);
|
1285
|
+
|
1286
|
+
ttable[dtype](M, storage, lda, result);
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
/*
|
1290
|
+
* C accessor for solving a system of linear equations.
|
1291
|
+
*/
|
1292
|
+
void nm_math_solve(VALUE lu, VALUE b, VALUE x, VALUE ipiv) {
|
1293
|
+
int* pivot = new int[RARRAY_LEN(ipiv)];
|
1294
|
+
|
1295
|
+
for (int i = 0; i < RARRAY_LEN(ipiv); ++i) {
|
1296
|
+
pivot[i] = FIX2INT(rb_ary_entry(ipiv, i));
|
1297
|
+
}
|
1298
|
+
|
1299
|
+
NAMED_DTYPE_TEMPLATE_TABLE(ttable, nm::math::solve, void, const int, const void*, const void*, void*, const int*);
|
1300
|
+
|
1301
|
+
ttable[NM_DTYPE(x)](NM_SHAPE0(b), NM_STORAGE_DENSE(lu)->elements,
|
1302
|
+
NM_STORAGE_DENSE(b)->elements, NM_STORAGE_DENSE(x)->elements, pivot);
|
1303
|
+
}
|
1304
|
+
|
1079
1305
|
/*
|
1080
1306
|
* C accessor for reducing a matrix to hessenberg form.
|
1081
1307
|
*/
|
@@ -1087,7 +1313,7 @@ void nm_math_hessenberg(VALUE a) {
|
|
1087
1313
|
NULL, NULL, // does not support Complex
|
1088
1314
|
NULL // no support for Ruby Object
|
1089
1315
|
};
|
1090
|
-
|
1316
|
+
|
1091
1317
|
ttable[NM_DTYPE(a)](NM_SHAPE0(a), NM_STORAGE_DENSE(a)->elements);
|
1092
1318
|
}
|
1093
1319
|
/*
|
@@ -1100,14 +1326,29 @@ void nm_math_inverse(const int M, void* a_elements, nm::dtype_t dtype) {
|
|
1100
1326
|
}
|
1101
1327
|
|
1102
1328
|
/*
|
1103
|
-
* C accessor for calculating an exact inverse.
|
1329
|
+
* C accessor for calculating an exact inverse. Dense matrix version.
|
1104
1330
|
*/
|
1105
|
-
void
|
1106
|
-
|
1331
|
+
void nm_math_inverse_exact_from_dense(const int M, const void* A_elements,
|
1332
|
+
const int lda, void* B_elements, const int ldb, nm::dtype_t dtype) {
|
1333
|
+
|
1334
|
+
NAMED_DTYPE_TEMPLATE_TABLE(ttable, nm::math::inverse_exact_from_dense, void,
|
1335
|
+
const int, const void*, const int, void*, const int);
|
1107
1336
|
|
1108
1337
|
ttable[dtype](M, A_elements, lda, B_elements, ldb);
|
1109
1338
|
}
|
1110
1339
|
|
1340
|
+
/*
|
1341
|
+
* C accessor for calculating an exact inverse. Yale matrix version.
|
1342
|
+
*/
|
1343
|
+
void nm_math_inverse_exact_from_yale(const int M, const YALE_STORAGE* storage,
|
1344
|
+
const int lda, YALE_STORAGE* inverse, const int ldb, nm::dtype_t dtype) {
|
1345
|
+
|
1346
|
+
NAMED_DTYPE_TEMPLATE_TABLE(ttable, nm::math::inverse_exact_from_yale, void,
|
1347
|
+
const int, const YALE_STORAGE*, const int, YALE_STORAGE*, const int);
|
1348
|
+
|
1349
|
+
ttable[dtype](M, storage, lda, inverse, ldb);
|
1350
|
+
}
|
1351
|
+
|
1111
1352
|
/*
|
1112
1353
|
* Transpose an array of elements that represent a row-major dense matrix. Does not allocate anything, only does an memcpy.
|
1113
1354
|
*/
|