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 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
+ }