fast_matrix 0.1.66 → 0.2.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.
- checksums.yaml +4 -4
- data/.dockerignore +0 -1
- data/.travis.yml +2 -1
- data/README.md +3 -8
- data/ext/fast_matrix/{c_array_opeartions.c → Helper/c_array_opeartions.c} +39 -1
- data/ext/fast_matrix/{c_array_operations.h → Helper/c_array_operations.h} +6 -1
- data/ext/fast_matrix/{errors.c → Helper/errors.c} +8 -2
- data/ext/fast_matrix/{errors.h → Helper/errors.h} +3 -1
- data/ext/fast_matrix/Matrix/c_matrix.c +606 -0
- data/ext/fast_matrix/Matrix/c_matrix.h +49 -0
- data/ext/fast_matrix/Matrix/errors.h +28 -0
- data/ext/fast_matrix/Matrix/helper.h +27 -0
- data/ext/fast_matrix/Matrix/matrix.c +633 -0
- data/ext/fast_matrix/Matrix/matrix.h +11 -0
- data/ext/fast_matrix/Vector/c_vector.c +97 -0
- data/ext/fast_matrix/Vector/c_vector.h +24 -0
- data/ext/fast_matrix/Vector/errors.h +14 -0
- data/ext/fast_matrix/Vector/helper.h +26 -0
- data/ext/fast_matrix/Vector/vector.c +476 -0
- data/ext/fast_matrix/{vector.h → Vector/vector.h} +0 -10
- data/ext/fast_matrix/c_include.c +8 -0
- data/ext/fast_matrix/fast_matrix.h +3 -3
- data/fast_matrix.gemspec +1 -1
- data/lib/fast_matrix/version.rb +1 -1
- data/lib/matrix/constructors.rb +0 -63
- data/lib/matrix/matrix.rb +105 -4
- data/lib/vector/constructors.rb +5 -4
- data/lib/vector/vector.rb +29 -0
- metadata +21 -12
- data/ext/fast_matrix/matrix.c +0 -678
- data/ext/fast_matrix/matrix.h +0 -28
- data/ext/fast_matrix/vector.c +0 -277
@@ -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
|
+
}
|