You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ext/nmatrix/math.cpp
+260-19
Original file line number
Diff line number
Diff line change
@@ -195,15 +195,14 @@ namespace nm {
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
-
voiddet_exact(constint M, constvoid* A_elements, constint lda, void* result_arg) {
198
+
voiddet_exact_from_dense(constint M, constvoid* A_elements, constint 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
202
202
typename LongDType<DType>::type x, y;
203
203
204
204
if (M == 2) {
205
205
*result = A[0] * A[lda+1] - A[1] * A[lda];
206
-
207
206
} elseif (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
-
voiddet_exact<uint8_t>(constint M, constvoid* A_elements, constint lda, void* result_arg) {
222
+
voiddet_exact_from_dense<uint8_t>(constint M, constvoid* A_elements, constint 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
+
voiddet_exact_from_yale(constint M, const YALE_STORAGE* storage, constint lda, void* result_arg) {
230
+
DType* result = reinterpret_cast<DType*>(result_arg);
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
+
elseif (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.
@@ -375,20 +464,24 @@ namespace nm {
375
464
delete[] u;
376
465
}
377
466
467
+
voidraise_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.
voidinverse_exact_from_dense(constint M, constvoid* A_elements,
477
+
constint lda, void* B_elements, constint 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)");
"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)");
0 commit comments