fast_matrix 0.1.66 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ #ifndef FAST_MATRIX_MATRIX_C_MATRIX_H
2
+ #define FAST_MATRIX_MATRIX_C_MATRIX_H 1
3
+
4
+ #include <stdbool.h>
5
+
6
+ // matrix
7
+ // m --->
8
+ // [ 0, 1, .., m-1]
9
+ // n [ m, m+1, .., 2m-1]
10
+ // | [2m, 2m+1, .., 3m-1]
11
+ // V [ . . . . .
12
+ // . . . . nm-1]
13
+ struct matrix
14
+ {
15
+ int m;
16
+ int n;
17
+
18
+ double* data;
19
+ };
20
+
21
+ double c_matrix_trace(int n, const double* A);
22
+ double c_matrix_determinant(int n, const double* A);
23
+
24
+ void c_matrix_transpose(int m, int n, const double* in, double* out);
25
+ void c_matrix_multiply(int n, int k, int m, const double* A, const double* B, double* C);
26
+ void c_matrix_vector_multiply(int n, int m, const double* M, const double* V, double* R);
27
+ void c_matrix_strassen(int n, int k, int m, const double* A, const double* B, double* C);
28
+ void c_matrix_hstack(int argc, struct matrix** mtrs, double* C, int m);
29
+ void c_matrix_column_vector(int m, int n, const double* M, double* V, int idx);
30
+ void c_matrix_scalar(int n, double* C, double v);
31
+ void c_matrix_minor(int m, int n, const double* A, double* B, int m_idx, int n_idx);
32
+ void c_matrix_vstack(int argc, struct matrix** mtrs, double* C);
33
+
34
+ bool c_matrix_symmetric(int n, const double* C);
35
+ bool c_matrix_antisymmetric(int n, const double* C);
36
+ bool c_matrix_diagonal(int n, const double* C);
37
+ bool c_matrix_lower_triangular(int n, const double* A);
38
+ bool c_matrix_upper_triangular(int n, const double* A);
39
+ bool c_matrix_permutation(int n, const double* A);
40
+ bool c_matrix_identity(int n, const double* A);
41
+ bool c_matrix_equal_by_m(int argc, struct matrix** mtrs);
42
+ bool c_matrix_equal_by_n(int argc, struct matrix** mtrs);
43
+ bool c_matrix_inverse(int n, const double* A, double* B);
44
+
45
+ int c_matrix_sum_by_m(int argc, struct matrix** mtrs);
46
+ int c_matrix_sum_by_n(int argc, struct matrix** mtrs);
47
+ int c_matrix_rank(int m, int n, const double* C);
48
+
49
+ #endif /* FAST_MATRIX_MATRIX_C_MATRIX_H */
@@ -0,0 +1,28 @@
1
+ #ifndef FAST_MATRIX_MATRIX_ERRORS_H
2
+ #define FAST_MATRIX_MATRIX_ERRORS_H 1
3
+
4
+ #include "ruby.h"
5
+ #include "Matrix/matrix.h"
6
+
7
+ // check if the matrix is of equal size and raise an error if not
8
+ inline void raise_check_equal_size_matrix(struct matrix* A, struct matrix* B)
9
+ {
10
+ if(A->m != B->m || A->n != B->n)
11
+ rb_raise(fm_eIndexError, "Different sizes matrices");
12
+ }
13
+
14
+ // check if the matrix is square and raise an error if not
15
+ inline void raise_check_square_matrix(struct matrix* A)
16
+ {
17
+ if(A->n != A->m)
18
+ rb_raise(fm_eIndexError, "Expected square matrix");
19
+ }
20
+
21
+ // check if the value is zero and raise an error if not
22
+ inline void raise_check_no_arguments(int argc)
23
+ {
24
+ if(argc == 0)
25
+ rb_raise(fm_eIndexError, "No arguments");
26
+ }
27
+
28
+ #endif /* FAST_MATRIX_MATRIX_ERRORS_H */
@@ -0,0 +1,27 @@
1
+ #ifndef FAST_MATRIX_MATRIX_HELPER_H
2
+ #define FAST_MATRIX_MATRIX_HELPER_H 1
3
+
4
+ #include "ruby.h"
5
+ #include "Matrix/c_matrix.h"
6
+
7
+ inline struct matrix* get_matrix_from_rb_value(VALUE m)
8
+ {
9
+ struct matrix* data;
10
+ TypedData_Get_Struct(m, struct matrix, &matrix_type, data);
11
+ return data;
12
+ }
13
+
14
+ inline void c_matrix_init(struct matrix* mtr, int m, int n)
15
+ {
16
+ mtr->m = m;
17
+ mtr->n = n;
18
+ mtr->data = malloc(m * n * sizeof(double));
19
+ }
20
+
21
+ #define MAKE_MATRIX_AND_RB_VALUE(matrix_name, rb_value_name, m, n)\
22
+ struct matrix* matrix_name; \
23
+ VALUE rb_value_name = TypedData_Make_Struct( \
24
+ cMatrix, struct matrix, &matrix_type, matrix_name); \
25
+ c_matrix_init(matrix_name, m, n)
26
+
27
+ #endif /* FAST_MATRIX_MATRIX_HELPER_H */
@@ -0,0 +1,633 @@
1
+ #include "Matrix/matrix.h"
2
+ #include "Helper/c_array_operations.h"
3
+ #include "Helper/errors.h"
4
+ #include "Vector/vector.h"
5
+ #include "Matrix/errors.h"
6
+ #include "Matrix/helper.h"
7
+ #include "Vector/helper.h"
8
+
9
+ VALUE cMatrix;
10
+
11
+ void matrix_free(void* data);
12
+ size_t matrix_size(const void* data);
13
+
14
+ const rb_data_type_t matrix_type =
15
+ {
16
+ .wrap_struct_name = "matrix",
17
+ .function =
18
+ {
19
+ .dmark = NULL,
20
+ .dfree = matrix_free,
21
+ .dsize = matrix_size,
22
+ },
23
+ .data = NULL,
24
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
25
+ };
26
+
27
+ void matrix_free(void* data)
28
+ {
29
+ free(((*(struct matrix*)data)).data);
30
+ free(data);
31
+ }
32
+
33
+ size_t matrix_size(const void* data)
34
+ {
35
+ return sizeof(struct matrix);
36
+ }
37
+
38
+ VALUE matrix_alloc(VALUE self)
39
+ {
40
+ struct matrix* mtx = malloc(sizeof(struct matrix));
41
+ mtx->data = NULL;
42
+ return TypedData_Wrap_Struct(self, &matrix_type, mtx);
43
+ }
44
+
45
+ VALUE matrix_initialize(VALUE self, VALUE rows_count, VALUE columns_count)
46
+ {
47
+ int m = raise_rb_value_to_int(columns_count);
48
+ int n = raise_rb_value_to_int(rows_count);
49
+
50
+ if(m <= 0 || n <= 0)
51
+ rb_raise(fm_eIndexError, "Size cannot be negative or zero");
52
+
53
+ struct matrix* data = get_matrix_from_rb_value(self);
54
+ c_matrix_init(data, m, n);
55
+ return self;
56
+ }
57
+
58
+ // []=
59
+ VALUE matrix_set(VALUE self, VALUE row, VALUE column, VALUE v)
60
+ {
61
+ int m = raise_rb_value_to_int(column);
62
+ int n = raise_rb_value_to_int(row);
63
+ double x = raise_rb_value_to_double(v);
64
+ struct matrix* data = get_matrix_from_rb_value(self);
65
+
66
+ m = (m < 0) ? data->m + m : m;
67
+ n = (n < 0) ? data->n + n : n;
68
+
69
+ raise_check_range(m, 0, data->m);
70
+ raise_check_range(n, 0, data->n);
71
+
72
+ data->data[m + data->m * n] = x;
73
+ return v;
74
+ }
75
+
76
+ // []
77
+ VALUE matrix_get(VALUE self, VALUE row, VALUE column)
78
+ {
79
+ int m = raise_rb_value_to_int(column);
80
+ int n = raise_rb_value_to_int(row);
81
+ struct matrix* data = get_matrix_from_rb_value(self);
82
+
83
+ m = (m < 0) ? data->m + m : m;
84
+ n = (n < 0) ? data->n + n : n;
85
+
86
+ if(m < 0 || n < 0 || n >= data->n || m >= data->m)
87
+ return Qnil;
88
+
89
+ return DBL2NUM(data->data[m + data->m * n]);
90
+ }
91
+
92
+ VALUE matrix_multiply_mv(VALUE self, VALUE other)
93
+ {
94
+ struct matrix* M = get_matrix_from_rb_value(self);
95
+ struct vector* V = get_vector_from_rb_value(other);
96
+
97
+ if(M->m != V->n)
98
+ rb_raise(fm_eIndexError, "Matrix columns differs from vector size");
99
+
100
+ MAKE_VECTOR_AND_RB_VALUE(R, result, M->n);
101
+ c_matrix_vector_multiply(M->n, M->m, M->data, V->data, R->data);
102
+ return result;
103
+ }
104
+
105
+ VALUE matrix_strassen(VALUE self, VALUE other)
106
+ {
107
+ struct matrix* A = get_matrix_from_rb_value(self);
108
+ struct matrix* B = get_matrix_from_rb_value(other);
109
+
110
+ if(A->m != B->n)
111
+ rb_raise(fm_eIndexError, "First columns differs from second rows");
112
+
113
+ int m = B->m;
114
+ int k = A->m;
115
+ int n = A->n;
116
+
117
+ MAKE_MATRIX_AND_RB_VALUE(C, result, m, n);
118
+ fill_d_array(m * n, C->data, 0);
119
+
120
+ c_matrix_strassen(n, k, m, A->data, B->data, C->data);
121
+ return result;
122
+ }
123
+
124
+ VALUE matrix_multiply_mm(VALUE self, VALUE other)
125
+ {
126
+ struct matrix* A = get_matrix_from_rb_value(self);
127
+ struct matrix* B = get_matrix_from_rb_value(other);
128
+
129
+ if(A->m != B->n)
130
+ rb_raise(fm_eIndexError, "First columns differs from second rows");
131
+
132
+ int m = B->m;
133
+ int k = A->m;
134
+ int n = A->n;
135
+
136
+ MAKE_MATRIX_AND_RB_VALUE(C, result, m, n);
137
+ c_matrix_multiply(n, k, m, A->data, B->data, C->data);
138
+
139
+ return result;
140
+ }
141
+
142
+ VALUE matrix_multiply_mn(VALUE self, VALUE value)
143
+ {
144
+ double d = NUM2DBL(value);
145
+ struct matrix* A = get_matrix_from_rb_value(self);
146
+
147
+ MAKE_MATRIX_AND_RB_VALUE(R, result, A->m, A->n);
148
+ copy_d_array(A->m * A->n, A->data, R->data);
149
+ multiply_d_array(R->m * R->n, R->data, d);
150
+
151
+ return result;
152
+ }
153
+
154
+ VALUE matrix_multiply(VALUE self, VALUE v)
155
+ {
156
+ if(RB_FLOAT_TYPE_P(v) || FIXNUM_P(v)
157
+ || RB_TYPE_P(v, T_BIGNUM))
158
+ return matrix_multiply_mn(self, v);
159
+ if(RBASIC_CLASS(v) == cMatrix)
160
+ return matrix_strassen(self, v);
161
+ if(RBASIC_CLASS(v) == cVector);
162
+ return matrix_multiply_mv(self, v);
163
+ rb_raise(fm_eTypeError, "Invalid klass for multiply");
164
+ }
165
+
166
+ VALUE matrix_copy(VALUE self)
167
+ {
168
+ struct matrix* M = get_matrix_from_rb_value(self);
169
+ MAKE_MATRIX_AND_RB_VALUE(R, result, M->m, M->n);
170
+ copy_d_array(M->m * M->n, M->data, R->data);
171
+ return result;
172
+ }
173
+
174
+ VALUE matrix_row_size(VALUE self)
175
+ {
176
+ struct matrix* data = get_matrix_from_rb_value(self);
177
+ return INT2NUM(data->m);
178
+ }
179
+
180
+ VALUE matrix_column_size(VALUE self)
181
+ {
182
+ struct matrix* data = get_matrix_from_rb_value(self);
183
+ return INT2NUM(data->n);
184
+ }
185
+
186
+ VALUE matrix_transpose(VALUE self)
187
+ {
188
+ struct matrix* M = get_matrix_from_rb_value(self);
189
+ MAKE_MATRIX_AND_RB_VALUE(R, result, M->n, M->m);
190
+ c_matrix_transpose(M->m, M->n, M->data, R->data);
191
+ return result;
192
+ }
193
+
194
+ VALUE matrix_add_with(VALUE self, VALUE other)
195
+ {
196
+ raise_check_rbasic(other, cMatrix, "matrix");
197
+ struct matrix* A = get_matrix_from_rb_value(self);
198
+ struct matrix* B = get_matrix_from_rb_value(other);
199
+
200
+ raise_check_equal_size_matrix(A, B);
201
+
202
+ MAKE_MATRIX_AND_RB_VALUE(C, result, A->m, A->n);
203
+ add_d_arrays_to_result(A->n * A->m, A->data, B->data, C->data);
204
+
205
+ return result;
206
+ }
207
+
208
+ VALUE matrix_add_from(VALUE self, VALUE other)
209
+ {
210
+ raise_check_rbasic(other, cMatrix, "matrix");
211
+ struct matrix* A = get_matrix_from_rb_value(self);
212
+ struct matrix* B = get_matrix_from_rb_value(other);
213
+
214
+ raise_check_equal_size_matrix(A, B);
215
+
216
+ add_d_arrays_to_first(A->n * B->m, A->data, B->data);
217
+ return self;
218
+ }
219
+
220
+ VALUE matrix_sub_with(VALUE self, VALUE other)
221
+ {
222
+ raise_check_rbasic(other, cMatrix, "matrix");
223
+ struct matrix* A = get_matrix_from_rb_value(self);
224
+ struct matrix* B = get_matrix_from_rb_value(other);
225
+
226
+ raise_check_equal_size_matrix(A, B);
227
+
228
+ MAKE_MATRIX_AND_RB_VALUE(C, result, A->m, A->n);
229
+ sub_d_arrays_to_result(A->n * A->m, A->data, B->data, C->data);
230
+ return result;
231
+ }
232
+
233
+ VALUE matrix_sub_from(VALUE self, VALUE other)
234
+ {
235
+ raise_check_rbasic(other, cMatrix, "matrix");
236
+ struct matrix* A = get_matrix_from_rb_value(self);
237
+ struct matrix* B = get_matrix_from_rb_value(other);
238
+
239
+ raise_check_equal_size_matrix(A, B);
240
+
241
+ sub_d_arrays_to_first(A->n * B->m, A->data, B->data);
242
+ return self;
243
+ }
244
+
245
+ VALUE matrix_determinant(VALUE self)
246
+ {
247
+ struct matrix* A = get_matrix_from_rb_value(self);
248
+ raise_check_square_matrix(A);
249
+ return DBL2NUM(c_matrix_determinant(A->n, A->data));
250
+ }
251
+
252
+ VALUE matrix_fill(VALUE self, VALUE value)
253
+ {
254
+ double d = raise_rb_value_to_double(value);
255
+ struct matrix* A = get_matrix_from_rb_value(self);
256
+ fill_d_array(A->m * A->n, A->data, d);
257
+ return self;
258
+ }
259
+
260
+ VALUE matrix_equal(VALUE self, VALUE other)
261
+ {
262
+ if(RBASIC_CLASS(other) != cMatrix)
263
+ return Qfalse;
264
+ struct matrix* A = get_matrix_from_rb_value(self);
265
+ struct matrix* B = get_matrix_from_rb_value(other);
266
+
267
+ if(A->n != B->n || A->m != B->m)
268
+ return Qfalse;
269
+
270
+ if(equal_d_arrays(A->n * A->m, A->data, B->data))
271
+ return Qtrue;
272
+ return Qfalse;
273
+ }
274
+
275
+ VALUE matrix_abs(VALUE self)
276
+ {
277
+ struct matrix* A = get_matrix_from_rb_value(self);
278
+ MAKE_MATRIX_AND_RB_VALUE(R, result, A->m, A->n);
279
+ abs_d_array(A->n * A->m, A->data, R->data);
280
+ return result;
281
+ }
282
+
283
+ VALUE matrix_greater_or_equal(VALUE self, VALUE other)
284
+ {
285
+ raise_check_rbasic(other, cMatrix, "matrix");
286
+ struct matrix* A = get_matrix_from_rb_value(self);
287
+ struct matrix* B = get_matrix_from_rb_value(other);
288
+
289
+ raise_check_equal_size_matrix(A, B);
290
+
291
+ if(greater_or_equal_d_array(A->n * A->m, A->data, B->data))
292
+ return Qtrue;
293
+ return Qfalse;
294
+ }
295
+
296
+ struct matrix** convert_matrix_array(int argc, VALUE *argv, struct matrix*** mtrs)
297
+ {
298
+ for(int i = 0; i < argc; ++i)
299
+ raise_check_rbasic(argv[i], cMatrix, "matrix");
300
+
301
+ *mtrs = (struct matrix**)malloc(argc * sizeof(struct matrix*));
302
+
303
+ for(int i = 0; i < argc; ++i)
304
+ TypedData_Get_Struct(argv[i], struct matrix, &matrix_type, (*mtrs)[i]);
305
+ }
306
+
307
+ VALUE matrix_vstack(int argc, VALUE *argv, VALUE obj)
308
+ {
309
+ raise_check_no_arguments(argc);
310
+
311
+ struct matrix** mtrs;
312
+ convert_matrix_array(argc, argv, &mtrs);
313
+
314
+ if(!c_matrix_equal_by_m(argc, mtrs))
315
+ {
316
+ free(mtrs);
317
+ rb_raise(fm_eIndexError, "Rows of different size");
318
+ }
319
+
320
+ int m = mtrs[0]->m;
321
+ int n = c_matrix_sum_by_n(argc, mtrs);
322
+
323
+ MAKE_MATRIX_AND_RB_VALUE(C, result, m, n);
324
+ c_matrix_vstack(argc, mtrs, C->data);
325
+ free(mtrs);
326
+ return result;
327
+ }
328
+
329
+ VALUE matrix_hstack(int argc, VALUE *argv, VALUE obj)
330
+ {
331
+ raise_check_no_arguments(argc);
332
+
333
+ struct matrix** mtrs;
334
+ convert_matrix_array(argc, argv, &mtrs);
335
+
336
+ if(!c_matrix_equal_by_n(argc, mtrs))
337
+ {
338
+ free(mtrs);
339
+ rb_raise(fm_eIndexError, "Columns of different size");
340
+ }
341
+
342
+ int m = c_matrix_sum_by_m(argc, mtrs);
343
+ int n = mtrs[0]->n;
344
+
345
+ MAKE_MATRIX_AND_RB_VALUE(C, result, m, n);
346
+ c_matrix_hstack(argc, mtrs, C->data, m);
347
+
348
+ free(mtrs);
349
+ return result;
350
+ }
351
+
352
+ VALUE matrix_scalar(VALUE obj, VALUE size, VALUE value)
353
+ {
354
+ int n = raise_rb_value_to_int(size);
355
+ double v = raise_rb_value_to_double(value);
356
+
357
+ MAKE_MATRIX_AND_RB_VALUE(C, result, n, n);
358
+ c_matrix_scalar(n, C->data, v);
359
+ return result;
360
+ }
361
+
362
+ VALUE matrix_antisymmetric(VALUE self)
363
+ {
364
+ struct matrix* A = get_matrix_from_rb_value(self);
365
+ raise_check_square_matrix(A);
366
+
367
+ if(c_matrix_antisymmetric(A->n, A->data))
368
+ return Qtrue;
369
+ return Qfalse;
370
+ }
371
+
372
+ VALUE matrix_symmetric(VALUE self)
373
+ {
374
+ struct matrix* A = get_matrix_from_rb_value(self);
375
+ raise_check_square_matrix(A);
376
+ if(c_matrix_symmetric(A->n, A->data))
377
+ return Qtrue;
378
+ return Qfalse;
379
+ }
380
+
381
+ VALUE matrix_minus(VALUE self)
382
+ {
383
+ struct matrix* A = get_matrix_from_rb_value(self);
384
+ MAKE_MATRIX_AND_RB_VALUE(C, result, A->m, A->n);
385
+ multiply_d_array_to_result(A->n * A->m, A->data, -1, C->data);
386
+ return result;
387
+ }
388
+
389
+ VALUE matrix_plus(VALUE self)
390
+ {
391
+ return self;
392
+ }
393
+
394
+ VALUE matrix_row_vector(VALUE self, VALUE v)
395
+ {
396
+ int idx = raise_rb_value_to_int(v);
397
+ struct matrix* A = get_matrix_from_rb_value(self);
398
+
399
+ int m = A->m;
400
+ int n = A->n;
401
+ idx = (idx < 0) ? m + idx : idx;
402
+
403
+ if(idx < 0 || idx >= m)
404
+ return Qnil;
405
+
406
+ MAKE_VECTOR_AND_RB_VALUE(C, result, n);
407
+ copy_d_array(m, A->data + idx * m, C->data);
408
+ return result;
409
+ }
410
+
411
+ VALUE matrix_column_vector(VALUE self, VALUE v)
412
+ {
413
+ int idx = raise_rb_value_to_int(v);
414
+ struct matrix* A = get_matrix_from_rb_value(self);
415
+
416
+ int m = A->m;
417
+ int n = A->n;
418
+ idx = (idx < 0) ? n + idx : idx;
419
+
420
+ if(idx < 0 || idx >= n)
421
+ return Qnil;
422
+
423
+ MAKE_VECTOR_AND_RB_VALUE(C, result, n);
424
+ c_matrix_column_vector(m, n, A->data, C->data, idx);
425
+ return result;
426
+ }
427
+
428
+ VALUE matrix_diagonal(VALUE self)
429
+ {
430
+ struct matrix* A = get_matrix_from_rb_value(self);
431
+ raise_check_square_matrix(A);
432
+
433
+ if(c_matrix_diagonal(A->n, A->data))
434
+ return Qtrue;
435
+ return Qfalse;
436
+ }
437
+
438
+ VALUE matrix_hadamard_product(VALUE self, VALUE other)
439
+ {
440
+ raise_check_rbasic(other, cMatrix, "matrix");
441
+ struct matrix* A = get_matrix_from_rb_value(self);
442
+ struct matrix* B = get_matrix_from_rb_value(other);
443
+
444
+ raise_check_equal_size_matrix(A, B);
445
+
446
+ MAKE_MATRIX_AND_RB_VALUE(C, result, A->m, A->n);
447
+ multiply_elems_d_array_to_result(A->n * A->m, A->data, B->data, C->data);
448
+ return result;
449
+ }
450
+
451
+ VALUE matrix_trace(VALUE self)
452
+ {
453
+ struct matrix* A = get_matrix_from_rb_value(self);
454
+ raise_check_square_matrix(A);
455
+ return DBL2NUM(c_matrix_trace(A->n, A->data));
456
+ }
457
+
458
+ VALUE matrix_first_minor(VALUE self, VALUE row, VALUE column)
459
+ {
460
+ int i = raise_rb_value_to_int(column);
461
+ int j = raise_rb_value_to_int(row);
462
+ struct matrix* A = get_matrix_from_rb_value(self);
463
+
464
+ int m = A->m;
465
+ int n = A->n;
466
+ if(i < 0 || i >= m || j < 0 || j >= n)
467
+ rb_raise(fm_eIndexError, "Index out of range");
468
+
469
+ MAKE_MATRIX_AND_RB_VALUE(C, result, m - 1, n - 1);
470
+ c_matrix_minor(m, n, A->data, C->data, i, j);
471
+ return result;
472
+ }
473
+
474
+ VALUE matrix_cofactor(VALUE self, VALUE row, VALUE column)
475
+ {
476
+ int i = raise_rb_value_to_int(column);
477
+ int j = raise_rb_value_to_int(row);
478
+ struct matrix* A = get_matrix_from_rb_value(self);
479
+
480
+ int m = A->m;
481
+ int n = A->n;
482
+ if(i < 0 || i >= m || j < 0 || j >= n)
483
+ rb_raise(fm_eIndexError, "Index out of range");
484
+ raise_check_square_matrix(A);
485
+
486
+ double* D = malloc(sizeof(double) * (n - 1) * (n - 1));
487
+ c_matrix_minor(n, n, A->data, D, i, j);
488
+
489
+ int coefficient = ((i + j) % 2 == 1) ? -1 : 1;
490
+ double det = c_matrix_determinant(n - 1, D);
491
+
492
+ free(D);
493
+ return DBL2NUM(coefficient * det);
494
+ }
495
+
496
+ VALUE matrix_zero(VALUE self)
497
+ {
498
+ struct matrix* A = get_matrix_from_rb_value(self);
499
+ if(zero_d_array(A->m * A->n, A->data))
500
+ return Qtrue;
501
+ return Qfalse;
502
+ }
503
+
504
+ VALUE matrix_rank(VALUE self)
505
+ {
506
+ struct matrix* A = get_matrix_from_rb_value(self);
507
+ return INT2NUM(c_matrix_rank(A->m, A->n, A->data));
508
+ }
509
+
510
+ VALUE matrix_round(int argc, VALUE *argv, VALUE self)
511
+ {
512
+ if(argc > 1)
513
+ rb_raise(fm_eTypeError, "Wrong number of arguments");
514
+ int d;
515
+ if(argc == 1)
516
+ d = raise_rb_value_to_int(argv[0]);
517
+ else
518
+ d = 0;
519
+
520
+ struct matrix* A = get_matrix_from_rb_value(self);
521
+ MAKE_MATRIX_AND_RB_VALUE(R, result, A->m, A->n);
522
+ round_d_array(A->m * A->n, A->data, R->data, d);
523
+ return result;
524
+ }
525
+
526
+ VALUE matrix_lower_triangular(VALUE self)
527
+ {
528
+ struct matrix* A = get_matrix_from_rb_value(self);
529
+ raise_check_square_matrix(A);
530
+
531
+ if(c_matrix_lower_triangular(A->n, A->data))
532
+ return Qtrue;
533
+ return Qfalse;
534
+ }
535
+
536
+ VALUE matrix_upper_triangular(VALUE self)
537
+ {
538
+ struct matrix* A = get_matrix_from_rb_value(self);
539
+ raise_check_square_matrix(A);
540
+
541
+ if(c_matrix_upper_triangular(A->n, A->data))
542
+ return Qtrue;
543
+ return Qfalse;
544
+ }
545
+
546
+ VALUE matrix_permutation(VALUE self)
547
+ {
548
+ struct matrix* A = get_matrix_from_rb_value(self);
549
+ raise_check_square_matrix(A);
550
+
551
+ if(c_matrix_permutation(A->n, A->data))
552
+ return Qtrue;
553
+ return Qfalse;
554
+ }
555
+
556
+ VALUE matrix_orthogonal(VALUE self)
557
+ {
558
+ struct matrix* A = get_matrix_from_rb_value(self);
559
+ raise_check_square_matrix(A);
560
+
561
+ int n = A->n;
562
+ double* B = malloc(sizeof(double) * n * n);
563
+ double* C = malloc(sizeof(double) * n * n);
564
+
565
+ c_matrix_transpose(n, n, A->data, B);
566
+ fill_d_array(n * n, C, 0);
567
+ c_matrix_strassen(n, n, n, A->data, B, C);
568
+ bool result = c_matrix_identity(n, C);
569
+
570
+ free(B);
571
+ free(C);
572
+ if(result)
573
+ return Qtrue;
574
+ return Qfalse;
575
+ }
576
+
577
+ VALUE matrix_inverse(VALUE self)
578
+ {
579
+ struct matrix* A = get_matrix_from_rb_value(self);
580
+ raise_check_square_matrix(A);
581
+ MAKE_MATRIX_AND_RB_VALUE(R, result, A->n, A->n);
582
+ if(!c_matrix_inverse(R->n, A->data, R->data))
583
+ rb_raise(fm_eIndexError, "The discriminant is zero");
584
+ return result;
585
+ }
586
+
587
+ void init_fm_matrix()
588
+ {
589
+ VALUE mod = rb_define_module("FastMatrix");
590
+ cMatrix = rb_define_class_under(mod, "Matrix", rb_cData);
591
+
592
+ rb_define_alloc_func(cMatrix, matrix_alloc);
593
+
594
+ rb_define_method(cMatrix, "initialize", matrix_initialize, 2);
595
+ rb_define_method(cMatrix, "[]", matrix_get, 2);
596
+ rb_define_method(cMatrix, "[]=", matrix_set, 3);
597
+ rb_define_method(cMatrix, "*", matrix_multiply, 1);
598
+ rb_define_method(cMatrix, "column_count", matrix_row_size, 0);
599
+ rb_define_method(cMatrix, "row_count", matrix_column_size, 0);
600
+ rb_define_method(cMatrix, "clone", matrix_copy, 0);
601
+ rb_define_method(cMatrix, "transpose", matrix_transpose, 0);
602
+ rb_define_method(cMatrix, "+", matrix_add_with, 1);
603
+ rb_define_method(cMatrix, "+=", matrix_add_from, 1);
604
+ rb_define_method(cMatrix, "-", matrix_sub_with, 1);
605
+ rb_define_method(cMatrix, "-=", matrix_sub_from, 1);
606
+ rb_define_method(cMatrix, "fill!", matrix_fill, 1);
607
+ rb_define_method(cMatrix, "abs", matrix_abs, 0);
608
+ rb_define_method(cMatrix, ">=", matrix_greater_or_equal, 1);
609
+ rb_define_method(cMatrix, "determinant", matrix_determinant, 0);
610
+ rb_define_method(cMatrix, "eql?", matrix_equal, 1);
611
+ rb_define_method(cMatrix, "antisymmetric?", matrix_antisymmetric, 0);
612
+ rb_define_method(cMatrix, "symmetric?", matrix_symmetric, 0);
613
+ rb_define_method(cMatrix, "-@", matrix_minus, 0);
614
+ rb_define_method(cMatrix, "+@", matrix_plus, 0);
615
+ rb_define_method(cMatrix, "column", matrix_column_vector, 1);
616
+ rb_define_method(cMatrix, "row", matrix_row_vector, 1);
617
+ rb_define_method(cMatrix, "diagonal?", matrix_diagonal, 0);
618
+ rb_define_method(cMatrix, "hadamard_product", matrix_hadamard_product, 1);
619
+ rb_define_method(cMatrix, "trace", matrix_trace, 0);
620
+ rb_define_method(cMatrix, "first_minor", matrix_first_minor, 2);
621
+ rb_define_method(cMatrix, "cofactor", matrix_cofactor, 2);
622
+ rb_define_method(cMatrix, "zero?", matrix_zero, 0);
623
+ rb_define_method(cMatrix, "rank", matrix_rank, 0);
624
+ rb_define_method(cMatrix, "round", matrix_round, -1);
625
+ rb_define_method(cMatrix, "lower_triangular?", matrix_lower_triangular, 0);
626
+ rb_define_method(cMatrix, "upper_triangular?", matrix_upper_triangular, 0);
627
+ rb_define_method(cMatrix, "permutation?", matrix_permutation, 0);
628
+ rb_define_method(cMatrix, "orthogonal?", matrix_orthogonal, 0);
629
+ rb_define_method(cMatrix, "inverse", matrix_inverse, 0);
630
+ rb_define_module_function(cMatrix, "vstack", matrix_vstack, -1);
631
+ rb_define_module_function(cMatrix, "hstack", matrix_hstack, -1);
632
+ rb_define_module_function(cMatrix, "scalar", matrix_scalar, 2);
633
+ }