fast_matrix 0.1.4 → 0.1.5
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/Dockerfile +3 -3
- data/README.md +15 -1
- data/ext/fast_matrix/c_array_opeartions.c +36 -1
- data/ext/fast_matrix/c_array_operations.h +8 -1
- data/ext/fast_matrix/errors.c +37 -0
- data/ext/fast_matrix/errors.h +18 -0
- data/ext/fast_matrix/fast_matrix.c +2 -0
- data/ext/fast_matrix/fast_matrix.h +2 -0
- data/ext/fast_matrix/matrix.c +367 -49
- data/ext/fast_matrix/matrix.h +4 -19
- data/ext/fast_matrix/vector.c +273 -0
- data/ext/fast_matrix/vector.h +20 -0
- data/lib/errors.rb +9 -0
- data/lib/fast_matrix.rb +3 -72
- data/lib/fast_matrix/version.rb +1 -1
- data/lib/matrix/constructors.rb +253 -0
- data/lib/matrix/matrix.rb +80 -0
- data/lib/vector/constructors.rb +58 -0
- data/lib/vector/vector.rb +20 -0
- metadata +11 -5
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/constructors.rb +0 -109
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31d4bbeb84c105ff8d28f067b375ff1b89120589baf84d5cff5a175db54f1522
|
4
|
+
data.tar.gz: d8988e813b690465c0716b62b61cf36b71696381688bdcbcb008effd70235cc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5d202092bbf94928f067f6c600db6075d5b2b7ff7a703a71a6811c667fe40b102611d676b185ebfc267dafb958ac547b1c6a1bcddecf3411306997cea050663
|
7
|
+
data.tar.gz: e829008f0decdf7193fd96f561605496489fab34b0eb67d66ec9d6070c4fa1459a206d375ba529980842a30bc4ffd52b0b34b5eff55dff875dbc5885508170fd
|
data/.dockerignore
CHANGED
data/Dockerfile
CHANGED
data/README.md
CHANGED
@@ -24,9 +24,23 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
TODO: Write usage instructions here
|
26
26
|
|
27
|
+
### Differences with the standard matrix
|
28
|
+
* Supported only double values
|
29
|
+
* Can't be empty
|
30
|
+
* Some faster
|
31
|
+
|
27
32
|
## Development
|
28
33
|
|
29
|
-
|
34
|
+
Fast matrix is native extension in C, so, for development you need Linux (maybe, MacOS) or Docker.
|
35
|
+
|
36
|
+
After checking out the repo, run `gem install bundler -v 2.0.2`, `bundle install` and `bundler exec rake` or use `Dockerfile`.
|
37
|
+
|
38
|
+
Commands:
|
39
|
+
+ `bundler exec rake compile` - compile C part of gem;
|
40
|
+
+ `bundler exec rake test` - run tests;
|
41
|
+
+ `bundler exec rake test TESTOPTS='-v'` - run tests with more information (description skipped tests);
|
42
|
+
+ `bundler exec rake` - compile and run tests.
|
43
|
+
|
30
44
|
|
31
45
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
46
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#include "c_array_operations.h"
|
2
|
+
#include "math.h"
|
2
3
|
|
3
4
|
void fill_d_array(int len, double* a, double v)
|
4
5
|
{
|
@@ -28,4 +29,38 @@ void add_d_arrays_to_first(int len, double* sum, const double* added)
|
|
28
29
|
{
|
29
30
|
for(int i = 0; i < len; ++i)
|
30
31
|
sum[i] += added[i];
|
31
|
-
}
|
32
|
+
}
|
33
|
+
|
34
|
+
void sub_d_arrays_to_result(int len, const double* dec, const double* sub, double* dif)
|
35
|
+
{
|
36
|
+
for(int i = 0; i < len; ++i)
|
37
|
+
dif[i] = dec[i] - sub[i];
|
38
|
+
}
|
39
|
+
|
40
|
+
void sub_d_arrays_to_first(int len, double* dif, const double* sub)
|
41
|
+
{
|
42
|
+
for(int i = 0; i < len; ++i)
|
43
|
+
dif[i] -= sub[i];
|
44
|
+
}
|
45
|
+
|
46
|
+
bool equal_d_arrays(int len, const double* A, const double* B)
|
47
|
+
{
|
48
|
+
for(int i = 0; i < len; ++i)
|
49
|
+
if(A[i] != B[i])
|
50
|
+
return false;
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
|
54
|
+
void abs_d_array(int len, const double* A, double* B)
|
55
|
+
{
|
56
|
+
for(int i = 0; i < len; ++i)
|
57
|
+
B[i] = fabs(A[i]);
|
58
|
+
}
|
59
|
+
|
60
|
+
bool greater_or_equal_d_array(int len, const double* A, const double* B)
|
61
|
+
{
|
62
|
+
for(int i = 0; i < len; ++i)
|
63
|
+
if(A[i] < B[i])
|
64
|
+
return false;
|
65
|
+
return true;
|
66
|
+
}
|
@@ -1,10 +1,17 @@
|
|
1
1
|
#ifndef C_ARRAY_OPERATIONS
|
2
2
|
#define C_ARRAY_OPERATIONS
|
3
3
|
|
4
|
+
#include <stdbool.h>
|
5
|
+
|
4
6
|
void fill_d_array(int len, double* a, double v);
|
5
7
|
void multiply_d_array(int len, double* a, double v);
|
6
8
|
void copy_d_array(int len, const double* input, double* output);
|
7
9
|
void add_d_arrays_to_result(int len, const double* a1, const double* a2, double* result);
|
8
10
|
void add_d_arrays_to_first(int len, double* sum, const double* added);
|
11
|
+
void sub_d_arrays_to_result(int len, const double* dec, const double* sub, double* dif);
|
12
|
+
void sub_d_arrays_to_first(int len, double* dif, const double* sub);
|
13
|
+
bool equal_d_arrays(int len, const double* A, const double* B);
|
14
|
+
void abs_d_array(int len, const double* A, double* B);
|
15
|
+
bool greater_or_equal_d_array(int len, const double* A, const double* B);
|
9
16
|
|
10
|
-
#endif /*C_ARRAY_OPERATIONS*/
|
17
|
+
#endif /*C_ARRAY_OPERATIONS*/
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#include "errors.h"
|
2
|
+
|
3
|
+
VALUE fm_eTypeError;
|
4
|
+
VALUE fm_eIndexError;
|
5
|
+
|
6
|
+
double raise_rb_value_to_double(VALUE v)
|
7
|
+
{
|
8
|
+
if(RB_FLOAT_TYPE_P(v) || FIXNUM_P(v)
|
9
|
+
|| RB_TYPE_P(v, T_BIGNUM))
|
10
|
+
return NUM2DBL(v);
|
11
|
+
|
12
|
+
rb_raise(fm_eTypeError, "Value is not number");
|
13
|
+
return 0;
|
14
|
+
}
|
15
|
+
|
16
|
+
int raise_rb_value_to_int(VALUE v)
|
17
|
+
{
|
18
|
+
if(FIXNUM_P(v))
|
19
|
+
return NUM2INT(v);
|
20
|
+
|
21
|
+
rb_raise(fm_eTypeError, "Index is not integer");
|
22
|
+
return 0;
|
23
|
+
}
|
24
|
+
|
25
|
+
void raise_check_range(int v, int min, int max)
|
26
|
+
{
|
27
|
+
if(v < min || v >= max)
|
28
|
+
rb_raise(fm_eIndexError, "Index out of range");
|
29
|
+
}
|
30
|
+
|
31
|
+
void init_fm_errors()
|
32
|
+
{
|
33
|
+
VALUE mod = rb_define_module("FastMatrix");
|
34
|
+
|
35
|
+
fm_eTypeError = rb_define_class_under(mod, "TypeError", rb_eTypeError);
|
36
|
+
fm_eIndexError = rb_define_class_under(mod, "IndexError", rb_eIndexError);
|
37
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef FAST_MATRIX_ERRORS_H
|
2
|
+
#define FAST_MATRIX_ERRORS_H 1
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
extern VALUE fm_eTypeError;
|
7
|
+
extern VALUE fm_eIndexError;
|
8
|
+
|
9
|
+
// convert ruby value to double or raise an error if this is not possible
|
10
|
+
double raise_rb_value_to_double(VALUE v);
|
11
|
+
// convert ruby value to int or raise an error if this is not possible
|
12
|
+
int raise_rb_value_to_int(VALUE v);
|
13
|
+
// check if the value is in range and raise an error if not
|
14
|
+
void raise_check_range(int v, int min, int max);
|
15
|
+
|
16
|
+
void init_fm_errors();
|
17
|
+
|
18
|
+
#endif /* FAST_MATRIX_ERRORS_H */
|
data/ext/fast_matrix/matrix.c
CHANGED
@@ -1,9 +1,29 @@
|
|
1
1
|
#include "matrix.h"
|
2
2
|
#include "c_array_operations.h"
|
3
|
+
#include "errors.h"
|
4
|
+
#include "vector.h"
|
5
|
+
|
6
|
+
VALUE cMatrix;
|
7
|
+
|
8
|
+
void matrix_free(void* data);
|
9
|
+
size_t matrix_size(const void* data);
|
10
|
+
|
11
|
+
const rb_data_type_t matrix_type =
|
12
|
+
{
|
13
|
+
.wrap_struct_name = "matrix",
|
14
|
+
.function =
|
15
|
+
{
|
16
|
+
.dmark = NULL,
|
17
|
+
.dfree = matrix_free,
|
18
|
+
.dsize = matrix_size,
|
19
|
+
},
|
20
|
+
.data = NULL,
|
21
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
22
|
+
};
|
3
23
|
|
4
24
|
void matrix_free(void* data)
|
5
25
|
{
|
6
|
-
|
26
|
+
free(((*(struct matrix*)data)).data);
|
7
27
|
free(data);
|
8
28
|
}
|
9
29
|
|
@@ -15,35 +35,10 @@ size_t matrix_size(const void* data)
|
|
15
35
|
VALUE matrix_alloc(VALUE self)
|
16
36
|
{
|
17
37
|
struct matrix* mtx = malloc(sizeof(struct matrix));
|
18
|
-
|
38
|
+
mtx->data = NULL;
|
19
39
|
return TypedData_Wrap_Struct(self, &matrix_type, mtx);
|
20
40
|
}
|
21
41
|
|
22
|
-
double raise_rb_value_to_double(VALUE v)
|
23
|
-
{
|
24
|
-
if(RB_FLOAT_TYPE_P(v) || FIXNUM_P(v)
|
25
|
-
|| RB_TYPE_P(v, T_BIGNUM))
|
26
|
-
return NUM2DBL(v);
|
27
|
-
|
28
|
-
rb_raise(matrix_eTypeError, "Value is not number");
|
29
|
-
return 0;
|
30
|
-
}
|
31
|
-
|
32
|
-
int raise_rb_value_to_int(VALUE v)
|
33
|
-
{
|
34
|
-
if(FIXNUM_P(v))
|
35
|
-
return NUM2INT(v);
|
36
|
-
|
37
|
-
rb_raise(matrix_eTypeError, "Index is not integer");
|
38
|
-
return 0;
|
39
|
-
}
|
40
|
-
|
41
|
-
void raise_check_range(int v, int min, int max)
|
42
|
-
{
|
43
|
-
if(v < min || v >= max)
|
44
|
-
rb_raise(matrix_eIndexError, "Index out of range");
|
45
|
-
}
|
46
|
-
|
47
42
|
void c_matrix_init(struct matrix* mtr, int m, int n)
|
48
43
|
{
|
49
44
|
mtr->m = m;
|
@@ -58,7 +53,7 @@ VALUE matrix_initialize(VALUE self, VALUE rows_count, VALUE columns_count)
|
|
58
53
|
int n = raise_rb_value_to_int(rows_count);
|
59
54
|
|
60
55
|
if(m <= 0 || n <= 0)
|
61
|
-
rb_raise(
|
56
|
+
rb_raise(fm_eIndexError, "Size cannot be negative or zero");
|
62
57
|
|
63
58
|
TypedData_Get_Struct(self, struct matrix, &matrix_type, data);
|
64
59
|
|
@@ -113,7 +108,6 @@ void matrix_transpose(int m, int n, const double* in, double* out)
|
|
113
108
|
// C - matrix m x n
|
114
109
|
void c_matrix_multiply(int n, int k, int m, const double* A, const double* B, double* C)
|
115
110
|
{
|
116
|
-
|
117
111
|
fill_d_array(m * n, C, 0);
|
118
112
|
|
119
113
|
for(int j = 0; j < n; ++j)
|
@@ -126,13 +120,246 @@ void c_matrix_multiply(int n, int k, int m, const double* A, const double* B, do
|
|
126
120
|
const double* p_b = B + m * t;
|
127
121
|
double d_a = p_a[t];
|
128
122
|
for(int i = 0; i < m; ++i)
|
129
|
-
{
|
130
123
|
p_c[i] += d_a * p_b[i];
|
131
|
-
}
|
132
124
|
}
|
133
125
|
}
|
134
126
|
}
|
135
127
|
|
128
|
+
// M - matrix m x n
|
129
|
+
// V - vector m
|
130
|
+
// R - vector n
|
131
|
+
void c_matrix_vector_multiply(int n, int m, const double* M, const double* V, double* R)
|
132
|
+
{
|
133
|
+
fill_d_array(n, R, 0);
|
134
|
+
|
135
|
+
for(int j = 0; j < n; ++j)
|
136
|
+
{
|
137
|
+
const double* p_m = M + m * j;
|
138
|
+
for(int i = 0; i < m; ++i)
|
139
|
+
R[j] += V[i] * p_m[i];
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
VALUE matrix_multiply_mv(VALUE self, VALUE other)
|
144
|
+
{
|
145
|
+
struct matrix* M;
|
146
|
+
struct vector* V;
|
147
|
+
TypedData_Get_Struct(self, struct matrix, &matrix_type, M);
|
148
|
+
TypedData_Get_Struct(other, struct vector, &vector_type, V);
|
149
|
+
|
150
|
+
if(M->m != V->n)
|
151
|
+
rb_raise(fm_eIndexError, "Matrix columns differs from vector size");
|
152
|
+
|
153
|
+
int m = M->m;
|
154
|
+
int n = M->n;
|
155
|
+
|
156
|
+
struct vector* R;
|
157
|
+
VALUE result = TypedData_Make_Struct(cVector, struct vector, &vector_type, R);
|
158
|
+
|
159
|
+
c_vector_init(R, n);
|
160
|
+
c_matrix_vector_multiply(n, m, M->data, V->data, R->data);
|
161
|
+
|
162
|
+
return result;
|
163
|
+
}
|
164
|
+
|
165
|
+
// A - matrix k x n
|
166
|
+
// B - matrix m x k
|
167
|
+
// C - matrix m x n
|
168
|
+
void strassen_iteration(int n, int k, int m, const double* A, const double* B, double* C, int s_a, int s_b, int s_c)
|
169
|
+
{
|
170
|
+
for(int j = 0; j < n; ++j)
|
171
|
+
{
|
172
|
+
double* p_c = C + s_c * j;
|
173
|
+
const double* p_a = A + s_a * j;
|
174
|
+
|
175
|
+
for(int t = 0; t < k; ++t)
|
176
|
+
{
|
177
|
+
const double* p_b = B + s_b * t;
|
178
|
+
double d_a = p_a[t];
|
179
|
+
for(int i = 0; i < m; ++i)
|
180
|
+
p_c[i] += d_a * p_b[i];
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
bool check_strassen(int m, int n, int k)
|
186
|
+
{
|
187
|
+
return n > 2 && m > 2 && k > 2 && (double)m * (double)n * (double)k > 100000000;
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
void strassen_copy(int m, int n, const double* A, double* B, int s_a, int s_b)
|
192
|
+
{
|
193
|
+
for(int i = 0; i < n; ++i)
|
194
|
+
{
|
195
|
+
const double* p_A = A + i * s_a;
|
196
|
+
double* p_B = B + i * s_b;
|
197
|
+
for(int j = 0; j < m; ++j)
|
198
|
+
p_B[j] = p_A[j];
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
void strassen_sum_to_first(int m, int n, double* A, const double* B, int s_a, int s_b)
|
203
|
+
{
|
204
|
+
for(int i = 0; i < n; ++i)
|
205
|
+
{
|
206
|
+
double* p_A = A + i * s_a;
|
207
|
+
const double* p_B = B + i * s_b;
|
208
|
+
for(int j = 0; j < m; ++j)
|
209
|
+
p_A[j] += p_B[j];
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
void strassen_sub_to_first(int m, int n, double* A, const double* B, int s_a, int s_b)
|
214
|
+
{
|
215
|
+
for(int i = 0; i < n; ++i)
|
216
|
+
{
|
217
|
+
double* p_A = A + i * s_a;
|
218
|
+
const double* p_B = B + i * s_b;
|
219
|
+
for(int j = 0; j < m; ++j)
|
220
|
+
p_A[j] -= p_B[j];
|
221
|
+
}
|
222
|
+
}
|
223
|
+
|
224
|
+
// A - matrix k x n
|
225
|
+
// B - matrix m x k
|
226
|
+
// C - matrix m x n
|
227
|
+
void recursive_strassen(int n, int k, int m, const double* A, const double* B, double* C)
|
228
|
+
{
|
229
|
+
if(!check_strassen(m, n, k))
|
230
|
+
return c_matrix_multiply(n, k, m, A, B, C);
|
231
|
+
|
232
|
+
int k2 = k / 2;
|
233
|
+
int k1 = k - k2;
|
234
|
+
int m2 = m / 2;
|
235
|
+
int m1 = m - m2;
|
236
|
+
int n2 = n / 2;
|
237
|
+
int n1 = n - n2;
|
238
|
+
|
239
|
+
double* termA = malloc(k1 * n1 * sizeof(double));
|
240
|
+
double* termB = malloc(m1 * k1 * sizeof(double));
|
241
|
+
|
242
|
+
double* P1 = malloc(7 * m1 * n1 * sizeof(double));
|
243
|
+
double* P2 = P1 + m1 * n1;
|
244
|
+
double* P3 = P2 + m1 * n1;
|
245
|
+
double* P4 = P3 + m1 * n1;
|
246
|
+
double* P5 = P4 + m1 * n1;
|
247
|
+
double* P6 = P5 + m1 * n1;
|
248
|
+
double* P7 = P6 + m1 * n1;
|
249
|
+
fill_d_array(7 * m1 * n1, P1, 0);
|
250
|
+
fill_d_array(k1 * n1, termA, 0);
|
251
|
+
fill_d_array(m1 * k1, termB, 0);
|
252
|
+
|
253
|
+
// -----------P1-----------
|
254
|
+
strassen_copy(k1, n1, A, termA, k, k1);
|
255
|
+
strassen_sum_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
|
256
|
+
|
257
|
+
strassen_copy(m1, k1, B, termB, m, m1);
|
258
|
+
strassen_sum_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
|
259
|
+
|
260
|
+
recursive_strassen(n1, k1, m1, termA, termB, P1);
|
261
|
+
fill_d_array(k1 * n1, termA, 0);
|
262
|
+
// -----------P2-----------
|
263
|
+
strassen_copy(k1, n2, A + k * n1, termA, k, k1);
|
264
|
+
strassen_sum_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
|
265
|
+
|
266
|
+
strassen_copy(m1, k1, B, termB, m, m1);
|
267
|
+
|
268
|
+
recursive_strassen(n1, k1, m1, termA, termB, P2);
|
269
|
+
fill_d_array(m1 * k1, termB, 0);
|
270
|
+
// -----------P3-----------
|
271
|
+
strassen_copy(k1, n1, A, termA, k, k1);
|
272
|
+
|
273
|
+
strassen_copy(m2, k1, B + m1, termB, m, m1);
|
274
|
+
strassen_sub_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
|
275
|
+
|
276
|
+
recursive_strassen(n1, k1, m1, termA, termB, P3);
|
277
|
+
fill_d_array(k1 * n1, termA, 0);
|
278
|
+
fill_d_array(m1 * k1, termB, 0);
|
279
|
+
// -----------P4-----------
|
280
|
+
strassen_copy(k2, n2, A + k1 + k * n1, termA, k, k1);
|
281
|
+
|
282
|
+
strassen_copy(m1, k2, B + m * k1, termB, m, m1);
|
283
|
+
strassen_sub_to_first(m1, k1, termB, B, m1, m);
|
284
|
+
|
285
|
+
recursive_strassen(n1, k1, m1, termA, termB, P4);
|
286
|
+
fill_d_array(m1 * k1, termB, 0);
|
287
|
+
// -----------P5-----------
|
288
|
+
strassen_copy(k1, n1, A, termA, k, k1);
|
289
|
+
strassen_sum_to_first(k2, n1, termA, A + k1, k1, k);
|
290
|
+
|
291
|
+
strassen_copy(m2, k2, B + m1 + m * k1, termB, m, m1);
|
292
|
+
|
293
|
+
recursive_strassen(n1, k1, m1, termA, termB, P5);
|
294
|
+
fill_d_array(k1 * n1, termA, 0);
|
295
|
+
// -----------P6-----------
|
296
|
+
strassen_copy(k1, n2, A + k * n1, termA, k, k1);
|
297
|
+
strassen_sub_to_first(k1, n1, termA, A, k1, k);
|
298
|
+
|
299
|
+
strassen_copy(m1, k1, B, termB, m, m1);
|
300
|
+
strassen_sum_to_first(m2, k1, termB, B + m1, m1, m);
|
301
|
+
|
302
|
+
recursive_strassen(n1, k1, m1, termA, termB, P6);
|
303
|
+
fill_d_array(k1 * n1, termA, 0);
|
304
|
+
fill_d_array(m1 * k1, termB, 0);
|
305
|
+
// -----------P7-----------
|
306
|
+
strassen_copy(k2, n1, A + k1, termA, k, k1);
|
307
|
+
strassen_sub_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
|
308
|
+
|
309
|
+
strassen_copy(m1, k2, B + k1 * m, termB, m, m1);
|
310
|
+
strassen_sum_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
|
311
|
+
|
312
|
+
recursive_strassen(n1, k1, m1, termA, termB, P7);
|
313
|
+
|
314
|
+
// -----------C11-----------
|
315
|
+
double* C11 = C;
|
316
|
+
strassen_copy(m1, n1, P1, C11, m1, m);
|
317
|
+
strassen_sum_to_first(m1, n1, C11, P4, m, m1);
|
318
|
+
strassen_sub_to_first(m1, n1, C11, P5, m, m1);
|
319
|
+
strassen_sum_to_first(m1, n1, C11, P7, m, m1);
|
320
|
+
// -----------C12-----------
|
321
|
+
double* C12 = C + m1;
|
322
|
+
strassen_copy(m2, n1, P3, C12, m1, m);
|
323
|
+
strassen_sum_to_first(m2, n1, C12, P5, m, m1);
|
324
|
+
// -----------C21-----------
|
325
|
+
double* C21 = C + m * n1;
|
326
|
+
strassen_copy(m1, n2, P2, C21, m1, m);
|
327
|
+
strassen_sum_to_first(m1, n2, C21, P4, m, m1);
|
328
|
+
// -----------C22-----------
|
329
|
+
double* C22 = C + m1 + m * n1;
|
330
|
+
strassen_copy(m2, n2, P1, C22, m1, m);
|
331
|
+
strassen_sub_to_first(m2, n2, C22, P2, m, m1);
|
332
|
+
strassen_sum_to_first(m2, n2, C22, P3, m, m1);
|
333
|
+
strassen_sum_to_first(m2, n2, C22, P6, m, m1);
|
334
|
+
|
335
|
+
free(termA);
|
336
|
+
free(termB);
|
337
|
+
free(P1);
|
338
|
+
}
|
339
|
+
|
340
|
+
VALUE strassen(VALUE self, VALUE other)
|
341
|
+
{
|
342
|
+
struct matrix* A;
|
343
|
+
struct matrix* B;
|
344
|
+
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
345
|
+
TypedData_Get_Struct(other, struct matrix, &matrix_type, B);
|
346
|
+
|
347
|
+
if(A->m != B->n)
|
348
|
+
rb_raise(fm_eIndexError, "First columns differs from second rows");
|
349
|
+
|
350
|
+
int m = B->m;
|
351
|
+
int k = A->m;
|
352
|
+
int n = A->n;
|
353
|
+
|
354
|
+
struct matrix* C;
|
355
|
+
VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C);
|
356
|
+
|
357
|
+
c_matrix_init(C, m, n);
|
358
|
+
fill_d_array(m * n, C->data, 0);
|
359
|
+
recursive_strassen(n, k, m, A->data, B->data, C->data);
|
360
|
+
return result;
|
361
|
+
}
|
362
|
+
|
136
363
|
VALUE matrix_multiply_mm(VALUE self, VALUE other)
|
137
364
|
{
|
138
365
|
struct matrix* A;
|
@@ -141,7 +368,7 @@ VALUE matrix_multiply_mm(VALUE self, VALUE other)
|
|
141
368
|
TypedData_Get_Struct(other, struct matrix, &matrix_type, B);
|
142
369
|
|
143
370
|
if(A->m != B->n)
|
144
|
-
rb_raise(
|
371
|
+
rb_raise(fm_eIndexError, "First columns differs from second rows");
|
145
372
|
|
146
373
|
int m = B->m;
|
147
374
|
int k = A->m;
|
@@ -178,7 +405,11 @@ VALUE matrix_multiply(VALUE self, VALUE v)
|
|
178
405
|
if(RB_FLOAT_TYPE_P(v) || FIXNUM_P(v)
|
179
406
|
|| RB_TYPE_P(v, T_BIGNUM))
|
180
407
|
return matrix_multiply_mn(self, v);
|
181
|
-
|
408
|
+
if(RBASIC_CLASS(v) == cMatrix)
|
409
|
+
return matrix_multiply_mm(self, v);
|
410
|
+
if(RBASIC_CLASS(v) == cVector);
|
411
|
+
return matrix_multiply_mv(self, v);
|
412
|
+
rb_raise(fm_eTypeError, "Invalid klass for multiply");
|
182
413
|
}
|
183
414
|
|
184
415
|
VALUE matrix_copy(VALUE mtrx)
|
@@ -223,15 +454,15 @@ VALUE transpose(VALUE self)
|
|
223
454
|
return result;
|
224
455
|
}
|
225
456
|
|
226
|
-
VALUE
|
457
|
+
VALUE matrix_add_with(VALUE self, VALUE value)
|
227
458
|
{
|
228
459
|
struct matrix* A;
|
229
460
|
struct matrix* B;
|
230
461
|
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
231
462
|
TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
|
232
463
|
|
233
|
-
if(A->m != B->m && A->
|
234
|
-
rb_raise(
|
464
|
+
if(A->m != B->m && A->n != B->n)
|
465
|
+
rb_raise(fm_eIndexError, "Different sizes matrices");
|
235
466
|
|
236
467
|
int m = B->m;
|
237
468
|
int n = A->n;
|
@@ -245,16 +476,15 @@ VALUE add_with(VALUE self, VALUE value)
|
|
245
476
|
return result;
|
246
477
|
}
|
247
478
|
|
248
|
-
|
249
|
-
VALUE add_from(VALUE self, VALUE value)
|
479
|
+
VALUE matrix_add_from(VALUE self, VALUE value)
|
250
480
|
{
|
251
481
|
struct matrix* A;
|
252
482
|
struct matrix* B;
|
253
483
|
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
254
484
|
TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
|
255
485
|
|
256
|
-
if(A->m != B->m && A->
|
257
|
-
rb_raise(
|
486
|
+
if(A->m != B->m && A->n != B->n)
|
487
|
+
rb_raise(fm_eIndexError, "Different sizes matrices");
|
258
488
|
|
259
489
|
int m = B->m;
|
260
490
|
int n = A->n;
|
@@ -264,15 +494,98 @@ VALUE add_from(VALUE self, VALUE value)
|
|
264
494
|
return self;
|
265
495
|
}
|
266
496
|
|
497
|
+
|
498
|
+
VALUE matrix_sub_with(VALUE self, VALUE value)
|
499
|
+
{
|
500
|
+
struct matrix* A;
|
501
|
+
struct matrix* B;
|
502
|
+
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
503
|
+
TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
|
504
|
+
|
505
|
+
if(A->m != B->m && A->n != B->n)
|
506
|
+
rb_raise(fm_eIndexError, "Different sizes matrices");
|
507
|
+
|
508
|
+
int m = B->m;
|
509
|
+
int n = A->n;
|
510
|
+
|
511
|
+
struct matrix* C;
|
512
|
+
VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C);
|
513
|
+
|
514
|
+
c_matrix_init(C, m, n);
|
515
|
+
sub_d_arrays_to_result(n * m, A->data, B->data, C->data);
|
516
|
+
|
517
|
+
return result;
|
518
|
+
}
|
519
|
+
|
520
|
+
VALUE matrix_sub_from(VALUE self, VALUE value)
|
521
|
+
{
|
522
|
+
struct matrix* A;
|
523
|
+
struct matrix* B;
|
524
|
+
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
525
|
+
TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
|
526
|
+
|
527
|
+
if(A->m != B->m && A->n != B->n)
|
528
|
+
rb_raise(fm_eIndexError, "Different sizes matrices");
|
529
|
+
|
530
|
+
int m = B->m;
|
531
|
+
int n = A->n;
|
532
|
+
|
533
|
+
sub_d_arrays_to_first(n * m, A->data, B->data);
|
534
|
+
|
535
|
+
return self;
|
536
|
+
}
|
537
|
+
|
538
|
+
VALUE matrix_fill(VALUE self, VALUE value)
|
539
|
+
{
|
540
|
+
double d = raise_rb_value_to_double(value);
|
541
|
+
struct matrix* A;
|
542
|
+
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
543
|
+
|
544
|
+
fill_d_array(A->m * A->n, A->data, d);
|
545
|
+
|
546
|
+
return self;
|
547
|
+
}
|
548
|
+
|
549
|
+
VALUE matrix_abs(VALUE self)
|
550
|
+
{
|
551
|
+
struct matrix* A;
|
552
|
+
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
553
|
+
|
554
|
+
int m = A->m;
|
555
|
+
int n = A->n;
|
556
|
+
|
557
|
+
struct matrix* B;
|
558
|
+
VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, B);
|
559
|
+
|
560
|
+
c_matrix_init(B, m, n);
|
561
|
+
abs_d_array(n * m, A->data, B->data);
|
562
|
+
|
563
|
+
return result;
|
564
|
+
}
|
565
|
+
|
566
|
+
VALUE matrix_greater_or_equal(VALUE self, VALUE value)
|
567
|
+
{
|
568
|
+
struct matrix* A;
|
569
|
+
struct matrix* B;
|
570
|
+
TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
|
571
|
+
TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
|
572
|
+
|
573
|
+
if(A->m != B->m && A->n != B->n)
|
574
|
+
rb_raise(fm_eIndexError, "Different sizes matrices");
|
575
|
+
|
576
|
+
int m = B->m;
|
577
|
+
int n = A->n;
|
578
|
+
|
579
|
+
if(greater_or_equal_d_array(n * m, A->data, B->data))
|
580
|
+
return Qtrue;
|
581
|
+
return Qfalse;
|
582
|
+
}
|
583
|
+
|
267
584
|
void init_fm_matrix()
|
268
585
|
{
|
269
586
|
VALUE mod = rb_define_module("FastMatrix");
|
270
587
|
cMatrix = rb_define_class_under(mod, "Matrix", rb_cData);
|
271
588
|
|
272
|
-
matrix_eTypeError = rb_define_class_under(cMatrix, "TypeError", rb_eTypeError);
|
273
|
-
matrix_eIndexError = rb_define_class_under(cMatrix, "IndexError", rb_eIndexError);
|
274
|
-
|
275
|
-
|
276
589
|
rb_define_alloc_func(cMatrix, matrix_alloc);
|
277
590
|
|
278
591
|
rb_define_method(cMatrix, "initialize", matrix_initialize, 2);
|
@@ -281,9 +594,14 @@ void init_fm_matrix()
|
|
281
594
|
rb_define_method(cMatrix, "*", matrix_multiply, 1);
|
282
595
|
rb_define_method(cMatrix, "column_count", row_size, 0);
|
283
596
|
rb_define_method(cMatrix, "row_count", column_size, 0);
|
284
|
-
rb_define_method(cMatrix, "
|
597
|
+
rb_define_method(cMatrix, "clone", matrix_copy, 0);
|
285
598
|
rb_define_method(cMatrix, "transpose", transpose, 0);
|
286
|
-
|
287
|
-
rb_define_method(cMatrix, "
|
288
|
-
rb_define_method(cMatrix, "
|
289
|
-
|
599
|
+
rb_define_method(cMatrix, "+", matrix_add_with, 1);
|
600
|
+
rb_define_method(cMatrix, "+=", matrix_add_from, 1);
|
601
|
+
rb_define_method(cMatrix, "-", matrix_sub_with, 1);
|
602
|
+
rb_define_method(cMatrix, "-=", matrix_sub_from, 1);
|
603
|
+
rb_define_method(cMatrix, "fill!", matrix_fill, 1);
|
604
|
+
rb_define_method(cMatrix, "strassen", strassen, 1);
|
605
|
+
rb_define_method(cMatrix, "abs", matrix_abs, 0);
|
606
|
+
rb_define_method(cMatrix, ">=", matrix_greater_or_equal, 1);
|
607
|
+
}
|