fast_matrix 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d2ffdbf4f0e25843620e0f1deef060ec8498cbd86571625bc265a20778b3fc8
4
- data.tar.gz: 8574ff18ebbfc3763de8944d7697dfd3cdc17f6206581140dc27f6de207322bb
3
+ metadata.gz: 31d4bbeb84c105ff8d28f067b375ff1b89120589baf84d5cff5a175db54f1522
4
+ data.tar.gz: d8988e813b690465c0716b62b61cf36b71696381688bdcbcb008effd70235cc3
5
5
  SHA512:
6
- metadata.gz: 98dc2ee472302bd8314ec63529c7b36065e09bb99ff2af62f063bcbd4d5af26cb88786a10f0c64737daa82d46613352af30cb2cb650b60e42ec2cd511d4a0310
7
- data.tar.gz: 75b445494ab54d32f46d79b1c2e9fb95d0b5e5b091bbbe4e3ed339a38ee9c7fbe650c7fcf9537b083e26bb7bde96f14862cfaa84c00c2b0ca654ce7665d60965
6
+ metadata.gz: d5d202092bbf94928f067f6c600db6075d5b2b7ff7a703a71a6811c667fe40b102611d676b185ebfc267dafb958ac547b1c6a1bcddecf3411306997cea050663
7
+ data.tar.gz: e829008f0decdf7193fd96f561605496489fab34b0eb67d66ec9d6070c4fa1459a206d375ba529980842a30bc4ffd52b0b34b5eff55dff875dbc5885508170fd
data/.dockerignore CHANGED
@@ -11,4 +11,3 @@
11
11
  Gemfile.lock
12
12
  *.so
13
13
  *.md
14
- *Dockerfile
data/Dockerfile CHANGED
@@ -10,9 +10,9 @@ RUN bundle install
10
10
 
11
11
  COPY Rakefile ./
12
12
  COPY ext/ ./ext
13
- RUN rake compile
13
+ RUN bundler exec rake compile
14
14
 
15
15
  COPY . .
16
- RUN rake test
16
+ RUN bundler exec rake test
17
17
 
18
- CMD /bin/bash
18
+ CMD rake test TESTOPTS='-v'
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
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
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 */
@@ -4,5 +4,7 @@
4
4
 
5
5
  void Init_fast_matrix()
6
6
  {
7
+ init_fm_errors();
7
8
  init_fm_matrix();
9
+ init_fm_vector();
8
10
  }
@@ -1,7 +1,9 @@
1
1
  #ifndef FAST_MATRIX_H
2
2
  #define FAST_MATRIX_H 1
3
3
 
4
+ #include "errors.h"
4
5
  #include "matrix.h"
6
+ #include "vector.h"
5
7
 
6
8
  void Init_fast_matrix();
7
9
 
@@ -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
- free(((*(struct matrix*)data)).data);
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(matrix_eIndexError, "Size cannot be negative or zero");
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(matrix_eIndexError, "First columns differs from second rows");
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
- return matrix_multiply_mm(self, v);
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 add_with(VALUE self, VALUE 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->m != B->m)
234
- rb_raise(matrix_eIndexError, "Different sizes matrices");
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->m != B->m)
257
- rb_raise(matrix_eIndexError, "Different sizes matrices");
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, "copy", matrix_copy, 0);
597
+ rb_define_method(cMatrix, "clone", matrix_copy, 0);
285
598
  rb_define_method(cMatrix, "transpose", transpose, 0);
286
-
287
- rb_define_method(cMatrix, "+", add_with, 1);
288
- rb_define_method(cMatrix, "+=", add_from, 1);
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
+ }