fast_matrix 0.1.66 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfb8428a0aae303ecb09400b55429bc1d388d1f8d168f7583318b3de93cd16f0
4
- data.tar.gz: b8c1bafdc23dbfcd02b801fb47f4bcfd7c865b4a545fe813327d3adaf2f41e64
3
+ metadata.gz: b0e98406e186191f8308eeca9cc81293343f44fd4a6e97559c6b4e3ce2d8b0b7
4
+ data.tar.gz: a6e2c1b4f49e62c76e27e23df7a358ca22c927099868f990488e5ea5c1ca21e6
5
5
  SHA512:
6
- metadata.gz: f7088df3f843e518dddd2dcabf92a5f8c7fe85fdd390dceb756c8e89f386e8b962e373790605246ab06bdae84be09ce09f92f9c1001a189c18d349f719161497
7
- data.tar.gz: 8784f020358a09ffe6aba60391e43cead8d18990e0c0a85841c13390caad7a856aa886ac6051034f16d6fac6b6f05683703253e39ac8d7c6b249a4e4a8681810
6
+ metadata.gz: 596d0c7a7bec078b328968e0a1a0c20e83076215594807395e2323eabf239fa5a61d88cde3564219b28f8520f97d40e06d34e39e5aea8ec0db0c08befddc2b39
7
+ data.tar.gz: a53d3c85372d7f9273cdee68789a2fadecae44f05f2f6244c6661970de890b246e81d44800354964ea32cf5f80292f2464ca7fb6b2b30683a90f6fcd3cdeba74
data/.dockerignore CHANGED
@@ -10,4 +10,3 @@
10
10
  *.gem
11
11
  Gemfile.lock
12
12
  *.so
13
- *.md
data/.travis.yml CHANGED
@@ -20,4 +20,5 @@ deploy:
20
20
  gem: fast_matrix
21
21
  on:
22
22
  tags: true
23
- repo: mmcs-ruby/fast_matrix
23
+ repo: mmcs-ruby/fast_matrix
24
+ branch: master
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # FastMatrix
6
6
 
7
- Ruby wrapper around C matrices implementation written as exercise by two MMCS students.
7
+ Ruby wrapper around C matrices implementation written as exercise by MMCS students.
8
8
 
9
9
  ## Installation
10
10
 
@@ -22,14 +22,9 @@ Or install it yourself as:
22
22
 
23
23
  $ gem install fast_matrix
24
24
 
25
- ## Usage
25
+ ## Usage and documentation
26
26
 
27
- TODO: Write usage instructions here
28
-
29
- ### Differences with the standard matrix
30
- * Supported only double values
31
- * Can't be empty
32
- * Some faster
27
+ See our [GitHub Wiki](https://github.com/mmcs-ruby/fast_matrix/wiki).
33
28
 
34
29
  ## Development
35
30
 
@@ -1,5 +1,6 @@
1
- #include "c_array_operations.h"
1
+ #include "Helper/c_array_operations.h"
2
2
  #include "math.h"
3
+ #include "stdlib.h"
3
4
 
4
5
  void fill_d_array(int len, double* a, double v)
5
6
  {
@@ -13,6 +14,18 @@ void multiply_d_array(int len, double* a, double v)
13
14
  a[i] *= v;
14
15
  }
15
16
 
17
+ void multiply_elems_d_array_to_result(int len, const double* a, const double* b, double* res)
18
+ {
19
+ for(int i = 0; i < len; ++i)
20
+ res[i] = a[i] * b[i];
21
+ }
22
+
23
+ void multiply_d_array_to_result(int len, const double* a, double v, double* res)
24
+ {
25
+ for(int i = 0; i < len; ++i)
26
+ res[i] = a[i] * v;
27
+ }
28
+
16
29
  void copy_d_array(int len, const double* input, double* output)
17
30
  {
18
31
  for(int i = 0; i < len; ++i)
@@ -64,3 +77,28 @@ bool greater_or_equal_d_array(int len, const double* A, const double* B)
64
77
  return false;
65
78
  return true;
66
79
  }
80
+
81
+ bool zero_d_array(int len, const double* A)
82
+ {
83
+ for(int i = 0; i < len; ++i)
84
+ if(A[i] != 0)
85
+ return false;
86
+ return true;
87
+ }
88
+
89
+ void swap_d_arrays(int len, double* A, double* B)
90
+ {
91
+ for(int i = 0; i < len; ++i)
92
+ {
93
+ double buf = A[i];
94
+ A[i] = B[i];
95
+ B[i] = buf;
96
+ }
97
+ }
98
+
99
+ void round_d_array(int len, const double* Input, double* Output, int acc)
100
+ {
101
+ double d = pow(10, acc);
102
+ for(int i = 0; i < len; ++i)
103
+ Output[i] = roundf(Input[i] * d) / d;
104
+ }
@@ -1,10 +1,12 @@
1
1
  #ifndef C_ARRAY_OPERATIONS
2
2
  #define C_ARRAY_OPERATIONS
3
3
 
4
- #include <stdbool.h>
4
+ #include <stdbool.h>
5
5
 
6
6
  void fill_d_array(int len, double* a, double v);
7
+ void multiply_elems_d_array_to_result(int len, const double* a, const double* b, double* res);
7
8
  void multiply_d_array(int len, double* a, double v);
9
+ void multiply_d_array_to_result(int len, const double* a, double v, double* res);
8
10
  void copy_d_array(int len, const double* input, double* output);
9
11
  void add_d_arrays_to_result(int len, const double* a1, const double* a2, double* result);
10
12
  void add_d_arrays_to_first(int len, double* sum, const double* added);
@@ -13,5 +15,8 @@ void sub_d_arrays_to_first(int len, double* dif, const double* sub);
13
15
  bool equal_d_arrays(int len, const double* A, const double* B);
14
16
  void abs_d_array(int len, const double* A, double* B);
15
17
  bool greater_or_equal_d_array(int len, const double* A, const double* B);
18
+ bool zero_d_array(int len, const double* A);
19
+ void swap_d_arrays(int len, double* A, double* B);
20
+ void round_d_array(int len, const double* Input, double* Output, int acc);
16
21
 
17
22
  #endif /*C_ARRAY_OPERATIONS*/
@@ -1,4 +1,4 @@
1
- #include "errors.h"
1
+ #include "Helper/errors.h"
2
2
 
3
3
  VALUE fm_eTypeError;
4
4
  VALUE fm_eIndexError;
@@ -28,10 +28,16 @@ void raise_check_range(int v, int min, int max)
28
28
  rb_raise(fm_eIndexError, "Index out of range");
29
29
  }
30
30
 
31
+ void raise_check_rbasic(VALUE v, VALUE rBasic, const char* rbasic_name)
32
+ {
33
+ if(RBASIC_CLASS(v) != rBasic)
34
+ rb_raise(fm_eTypeError, "Expected class %s", rbasic_name);
35
+ }
36
+
31
37
  void init_fm_errors()
32
38
  {
33
39
  VALUE mod = rb_define_module("FastMatrix");
34
40
 
35
41
  fm_eTypeError = rb_define_class_under(mod, "TypeError", rb_eTypeError);
36
42
  fm_eIndexError = rb_define_class_under(mod, "IndexError", rb_eIndexError);
37
- }
43
+ }
@@ -12,7 +12,9 @@ double raise_rb_value_to_double(VALUE v);
12
12
  int raise_rb_value_to_int(VALUE v);
13
13
  // check if the value is in range and raise an error if not
14
14
  void raise_check_range(int v, int min, int max);
15
+ // check if the basic class of value is rBasic and raise an error if not
16
+ void raise_check_rbasic(VALUE v, VALUE rBasic, const char* rbasic_name);
15
17
 
16
18
  void init_fm_errors();
17
19
 
18
- #endif /* FAST_MATRIX_ERRORS_H */
20
+ #endif /* FAST_MATRIX_ERRORS_H */
@@ -0,0 +1,606 @@
1
+ #include "c_matrix.h"
2
+
3
+ // in - matrix m x n
4
+ // out - matrix n x m
5
+ void c_matrix_transpose(int m, int n, const double* in, double* out)
6
+ {
7
+ for(int i = 0; i < m; ++i)
8
+ for(int j = 0; j < n; ++j)
9
+ out[j + n * i] = in[i + m * j];
10
+ }
11
+
12
+ // A - matrix k x n
13
+ // B - matrix m x k
14
+ // C - matrix m x n
15
+ void c_matrix_multiply(int n, int k, int m, const double* A, const double* B, double* C)
16
+ {
17
+ fill_d_array(m * n, C, 0);
18
+
19
+ for(int j = 0; j < n; ++j)
20
+ {
21
+ double* p_c = C + m * j;
22
+ const double* p_a = A + k * j;
23
+
24
+ for(int t = 0; t < k; ++t)
25
+ {
26
+ const double* p_b = B + m * t;
27
+ double d_a = p_a[t];
28
+ if(d_a != 0)
29
+ for(int i = 0; i < m; ++i)
30
+ p_c[i] += d_a * p_b[i];
31
+ }
32
+ }
33
+ }
34
+
35
+ // M - matrix m x n
36
+ // V - vector m
37
+ // R - vector n
38
+ void c_matrix_vector_multiply(int n, int m, const double* M, const double* V, double* R)
39
+ {
40
+ fill_d_array(n, R, 0);
41
+
42
+ for(int j = 0; j < n; ++j)
43
+ {
44
+ const double* p_m = M + m * j;
45
+ for(int i = 0; i < m; ++i)
46
+ R[j] += V[i] * p_m[i];
47
+ }
48
+ }
49
+
50
+
51
+ // A - matrix k x n
52
+ // B - matrix m x k
53
+ // C - matrix m x n
54
+ 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)
55
+ {
56
+ for(int j = 0; j < n; ++j)
57
+ {
58
+ double* p_c = C + s_c * j;
59
+ const double* p_a = A + s_a * j;
60
+
61
+ for(int t = 0; t < k; ++t)
62
+ {
63
+ const double* p_b = B + s_b * t;
64
+ double d_a = p_a[t];
65
+ for(int i = 0; i < m; ++i)
66
+ p_c[i] += d_a * p_b[i];
67
+ }
68
+ }
69
+ }
70
+
71
+ bool check_strassen(int m, int n, int k)
72
+ {
73
+ return n > 2 && m > 2 && k > 2 && (double)m * (double)n * (double)k > 1000000;
74
+ }
75
+
76
+ // A B
77
+ // [x x x] [x x x]
78
+ // [x x x] => [x x x]
79
+ // [x x x] [x x x]
80
+ void strassen_copy(int m, int n, const double* A, double* B, int s_a, int s_b)
81
+ {
82
+ for(int i = 0; i < n; ++i)
83
+ {
84
+ const double* p_A = A + i * s_a;
85
+ double* p_B = B + i * s_b;
86
+ for(int j = 0; j < m; ++j)
87
+ p_B[j] = p_A[j];
88
+ }
89
+ }
90
+
91
+ // if right = false and down = false | if right = true and down = false:
92
+ // A B | A B
93
+ // [x x x] [x x x] | [x x x] [x x x 0]
94
+ // [x x x] => [x x x] | [x x x] => [x x x 0]
95
+ // [x x x] [x x x] | [x x x] [x x x 0]
96
+ // |
97
+ // if right = false and down = true | if right = true and down = true:
98
+ // A B | A B
99
+ // [x x x] [x x x] | [x x x] [x x x 0]
100
+ // [x x x] => [x x x] | [x x x] => [x x x 0]
101
+ // [x x x] [x x x] | [x x x] [x x x 0]
102
+ // [0 0 0] | [0 0 0 0]
103
+ void strassen_copy_with_zero(int m, int n, const double* A, double* B, int s_a, int s_b, bool right, bool down)
104
+ {
105
+ double* p_B;
106
+ for(int i = 0; i < n; ++i)
107
+ {
108
+ const double* p_A = A + i * s_a;
109
+ p_B = B + i * s_b;
110
+ for(int j = 0; j < m; ++j)
111
+ p_B[j] = p_A[j];
112
+ if(right)
113
+ p_B[m] = 0;
114
+ }
115
+
116
+ if(down)
117
+ {
118
+ p_B = B + n * s_b;
119
+ for(int j = 0; j < m; ++j)
120
+ p_B[j] = 0;
121
+ if(right)
122
+ p_B[m] = 0;
123
+ }
124
+ }
125
+
126
+ void strassen_sum_to_first(int m, int n, double* A, const double* B, int s_a, int s_b)
127
+ {
128
+ for(int i = 0; i < n; ++i)
129
+ {
130
+ double* p_A = A + i * s_a;
131
+ const double* p_B = B + i * s_b;
132
+ for(int j = 0; j < m; ++j)
133
+ p_A[j] += p_B[j];
134
+ }
135
+ }
136
+
137
+ void strassen_sub_to_first(int m, int n, double* A, const double* B, int s_a, int s_b)
138
+ {
139
+ for(int i = 0; i < n; ++i)
140
+ {
141
+ double* p_A = A + i * s_a;
142
+ const double* p_B = B + i * s_b;
143
+ for(int j = 0; j < m; ++j)
144
+ p_A[j] -= p_B[j];
145
+ }
146
+ }
147
+
148
+ // A - matrix k x n
149
+ // B - matrix m x k
150
+ // C - matrix m x n
151
+ void c_matrix_strassen(int n, int k, int m, const double* A, const double* B, double* C)
152
+ {
153
+ if(!check_strassen(m, n, k))
154
+ return c_matrix_multiply(n, k, m, A, B, C);
155
+
156
+ int k2 = k / 2;
157
+ int k1 = k - k2;
158
+ int m2 = m / 2;
159
+ int m1 = m - m2;
160
+ int n2 = n / 2;
161
+ int n1 = n - n2;
162
+
163
+ double* termA = malloc(k1 * n1 * sizeof(double));
164
+ double* termB = malloc(m1 * k1 * sizeof(double));
165
+
166
+ double* P1 = malloc(7 * m1 * n1 * sizeof(double));
167
+ double* P2 = P1 + m1 * n1;
168
+ double* P3 = P2 + m1 * n1;
169
+ double* P4 = P3 + m1 * n1;
170
+ double* P5 = P4 + m1 * n1;
171
+ double* P6 = P5 + m1 * n1;
172
+ double* P7 = P6 + m1 * n1;
173
+ fill_d_array(7 * m1 * n1, P1, 0);
174
+
175
+ // -----------P1-----------
176
+ strassen_copy(k1, n1, A, termA, k, k1);
177
+ strassen_sum_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
178
+
179
+ strassen_copy(m1, k1, B, termB, m, m1);
180
+ strassen_sum_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
181
+
182
+ c_matrix_strassen(n1, k1, m1, termA, termB, P1);
183
+ // -----------P2-----------
184
+ strassen_copy_with_zero(k1, n2, A + k * n1, termA, k, k1, false, n1 != n2);
185
+ strassen_sum_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
186
+
187
+ strassen_copy(m1, k1, B, termB, m, m1);
188
+
189
+ c_matrix_strassen(n1, k1, m1, termA, termB, P2);
190
+ // -----------P3-----------
191
+ strassen_copy(k1, n1, A, termA, k, k1);
192
+
193
+ strassen_copy_with_zero(m2, k1, B + m1, termB, m, m1, m1 != m2, false);
194
+ strassen_sub_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
195
+
196
+ c_matrix_strassen(n1, k1, m1, termA, termB, P3);
197
+ // -----------P4-----------
198
+ strassen_copy_with_zero(k2, n2, A + k1 + k * n1, termA, k, k1, k1 != k2, n1 != n2);
199
+
200
+ strassen_copy_with_zero(m1, k2, B + m * k1, termB, m, m1, false, k1 != k2);
201
+ strassen_sub_to_first(m1, k1, termB, B, m1, m);
202
+
203
+ c_matrix_strassen(n1, k1, m1, termA, termB, P4);
204
+ // -----------P5-----------
205
+ strassen_copy(k1, n1, A, termA, k, k1);
206
+ strassen_sum_to_first(k2, n1, termA, A + k1, k1, k);
207
+
208
+ strassen_copy_with_zero(m2, k2, B + m1 + m * k1, termB, m, m1, m1 != m2, k1 != k2);
209
+
210
+ c_matrix_strassen(n1, k1, m1, termA, termB, P5);
211
+ // -----------P6-----------
212
+ strassen_copy_with_zero(k1, n2, A + k * n1, termA, k, k1, false, n1 != n2);
213
+ strassen_sub_to_first(k1, n1, termA, A, k1, k);
214
+
215
+ strassen_copy(m1, k1, B, termB, m, m1);
216
+ strassen_sum_to_first(m2, k1, termB, B + m1, m1, m);
217
+
218
+ c_matrix_strassen(n1, k1, m1, termA, termB, P6);
219
+ // -----------P7-----------
220
+ strassen_copy_with_zero(k2, n1, A + k1, termA, k, k1, k1 != k2, false);
221
+ strassen_sub_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
222
+
223
+ strassen_copy_with_zero(m1, k2, B + k1 * m, termB, m, m1, false, k1 != k2);
224
+ strassen_sum_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
225
+
226
+ c_matrix_strassen(n1, k1, m1, termA, termB, P7);
227
+
228
+ // -----------C11-----------
229
+ double* C11 = C;
230
+ strassen_copy(m1, n1, P1, C11, m1, m);
231
+ strassen_sum_to_first(m1, n1, C11, P4, m, m1);
232
+ strassen_sub_to_first(m1, n1, C11, P5, m, m1);
233
+ strassen_sum_to_first(m1, n1, C11, P7, m, m1);
234
+ // -----------C12-----------
235
+ double* C12 = C + m1;
236
+ strassen_copy(m2, n1, P3, C12, m1, m);
237
+ strassen_sum_to_first(m2, n1, C12, P5, m, m1);
238
+ // -----------C21-----------
239
+ double* C21 = C + m * n1;
240
+ strassen_copy(m1, n2, P2, C21, m1, m);
241
+ strassen_sum_to_first(m1, n2, C21, P4, m, m1);
242
+ // -----------C22-----------
243
+ double* C22 = C + m1 + m * n1;
244
+ strassen_copy(m2, n2, P1, C22, m1, m);
245
+ strassen_sub_to_first(m2, n2, C22, P2, m, m1);
246
+ strassen_sum_to_first(m2, n2, C22, P3, m, m1);
247
+ strassen_sum_to_first(m2, n2, C22, P6, m, m1);
248
+
249
+ free(termA);
250
+ free(termB);
251
+ free(P1);
252
+ }
253
+
254
+ void c_matrix_hstack(int argc, struct matrix** mtrs, double* C, int m)
255
+ {
256
+ for(int i = 0; i < argc; ++i)
257
+ {
258
+ struct matrix* M = mtrs[i];
259
+ // a little misuse of the method
260
+ strassen_copy(M->m, M->n, M->data, C, M->m, m);
261
+ C += M->m;
262
+ }
263
+ }
264
+
265
+ void c_matrix_column_vector(int m, int n, const double* M, double* V, int idx)
266
+ {
267
+ M = M + idx;
268
+ for(int i = 0; i < n; ++i)
269
+ {
270
+ V[i] = *M;
271
+ M += m;
272
+ }
273
+ }
274
+
275
+ void c_matrix_scalar(int n, double* C, double v)
276
+ {
277
+ int ptr = 0;
278
+
279
+ for(int i = 0; i < n * n; ++i)
280
+ {
281
+ if(i == ptr)
282
+ {
283
+ ptr += n + 1;
284
+ C[i] = v;
285
+ }else
286
+ C[i] = 0;
287
+ }
288
+ }
289
+
290
+ bool c_matrix_symmetric(int n, const double* C)
291
+ {
292
+ for(int i = 0; i < n; ++i)
293
+ for(int j = i; j < n; ++j)
294
+ if(C[i + j * n] != C[j + i * n])
295
+ return false;
296
+ return true;
297
+ }
298
+
299
+ bool c_matrix_antisymmetric(int n, const double* C)
300
+ {
301
+ for(int i = 0; i < n; ++i)
302
+ for(int j = i; j < n; ++j)
303
+ if(C[i + j * n] != -C[j + i * n])
304
+ return false;
305
+ return true;
306
+ }
307
+
308
+ bool c_matrix_diagonal(int n, const double* C)
309
+ {
310
+ int ptr = 0;
311
+
312
+ for(int i = 0; i < n * n; ++i)
313
+ {
314
+ if(i == ptr)
315
+ ptr += n + 1;
316
+ else if(C[i] != 0)
317
+ return false;
318
+ }
319
+ return true;
320
+ }
321
+
322
+ double c_matrix_trace(int n, const double* A)
323
+ {
324
+ int sum = 0;
325
+ for(int i = 0; i < n; ++i)
326
+ sum += A[i + i * n];
327
+ return sum;
328
+ }
329
+
330
+ void c_matrix_minor(int m, int n, const double* A, double* B, int m_idx, int n_idx)
331
+ {
332
+ for(int j = 0; j < n - 1; ++j)
333
+ {
334
+ int j_step = (j >= n_idx) ? 1 : 0;
335
+ for(int i = 0; i < m - 1; ++i)
336
+ {
337
+ int i_step = (i >= m_idx) ? 1 : 0;
338
+ B[i + j * (m - 1)] = A[(i + i_step) + (j + j_step) * m];
339
+ }
340
+ }
341
+ }
342
+
343
+ bool c_matrix_lower_triangular(int n, const double* A)
344
+ {
345
+ for(int i = 0; i < n; ++i)
346
+ {
347
+ const double* line = A + (i + 1) + n * i;
348
+ for(int j = 0; j < n - i - 1; ++j)
349
+ if(line[j] != 0)
350
+ return false;
351
+ }
352
+ return true;
353
+ }
354
+
355
+ bool c_matrix_upper_triangular(int n, const double* A)
356
+ {
357
+ for(int i = 1; i < n; ++i)
358
+ {
359
+ const double* line = A + n * i;
360
+ for(int j = 0; j < i; ++j)
361
+ if(line[j] != 0)
362
+ return false;
363
+ }
364
+ return true;
365
+ }
366
+
367
+ bool c_matrix_permutation(int n, const double* A)
368
+ {
369
+ bool* f = malloc(n * sizeof(bool));
370
+ for(int i = 0; i < n; ++i)
371
+ f[i] = false;
372
+
373
+ bool result;
374
+ for(int i = 0; i < n; ++i)
375
+ {
376
+ const double* line = A + n * i;
377
+ result = false;
378
+ for(int j = 0; j < n; ++j)
379
+ {
380
+ double v = line[j];
381
+ if(v == 0)
382
+ continue;
383
+
384
+ if(v != 1 || result || f[j])
385
+ {
386
+ result = false;
387
+ break;
388
+ }
389
+
390
+ result = f[j] = true;
391
+ }
392
+ if(!result)
393
+ break;
394
+ }
395
+
396
+ if(result)
397
+ for(int i = 0; i < n; ++i)
398
+ if(!f[i])
399
+ {
400
+ result = false;
401
+ break;
402
+ }
403
+ free(f);
404
+ return result;
405
+ }
406
+
407
+ bool c_matrix_identity(int n, const double* A)
408
+ {
409
+ for(int i = 0; i < n; ++i)
410
+ {
411
+ const double* p_a = A + i * n;
412
+ for(int j = 0; j < n; ++j)
413
+ if(i == j)
414
+ { if(p_a[j] != 1) return false; }
415
+ else
416
+ { if(p_a[j] != 0) return false; }
417
+ }
418
+ return true;
419
+ }
420
+
421
+ bool c_matrix_equal_by_m(int argc, struct matrix** mtrs)
422
+ {
423
+ int m = mtrs[0]->m;
424
+ for(int i = 1; i < argc; ++i)
425
+ if(m != mtrs[i]->m)
426
+ return false;
427
+ return true;
428
+ }
429
+
430
+ bool c_matrix_equal_by_n(int argc, struct matrix** mtrs)
431
+ {
432
+ int n = mtrs[0]->n;
433
+ for(int i = 1; i < argc; ++i)
434
+ if(n != mtrs[i]->n)
435
+ return false;
436
+ return true;
437
+ }
438
+
439
+ int c_matrix_sum_by_m(int argc, struct matrix** mtrs)
440
+ {
441
+ int sum = 0;
442
+ for(int i = 0; i < argc; ++i)
443
+ sum += mtrs[i]->m;
444
+ return sum;
445
+ }
446
+
447
+ int c_matrix_sum_by_n(int argc, struct matrix** mtrs)
448
+ {
449
+ int sum = 0;
450
+ for(int i = 0; i < argc; ++i)
451
+ sum += mtrs[i]->n;
452
+ return sum;
453
+ }
454
+
455
+ void c_matrix_vstack(int argc, struct matrix** mtrs, double* C)
456
+ {
457
+ for(int i = 0; i < argc; ++i)
458
+ {
459
+ struct matrix* M = mtrs[i];
460
+ int len = M->m * M->n;
461
+ copy_d_array(len, M->data, C);
462
+ C += len;
463
+ }
464
+ }
465
+
466
+ int c_matrix_rank(int m, int n, const double* C)
467
+ {
468
+ double* A = malloc(sizeof(double) * m * n);
469
+ copy_d_array(m * n, C, A);
470
+
471
+ int i = 0;
472
+ int c_ptr = 0;
473
+ while(i < n && c_ptr < m)
474
+ {
475
+ double* line = A + c_ptr + i * m;
476
+ double val = line[0];
477
+
478
+ if(val == 0)
479
+ for(int j = i + 1; j < n; ++j)
480
+ if(A[c_ptr + j * m] != 0)
481
+ {
482
+ double* buf = A + c_ptr + j * m;
483
+ swap_d_arrays(m - c_ptr, buf, line);
484
+ val = line[0];
485
+ break;
486
+ }
487
+
488
+ if(val == 0)
489
+ {
490
+ ++c_ptr;
491
+ continue;
492
+ }
493
+
494
+ for(int j = i + 1; j < n; ++j)
495
+ {
496
+ double* target = A + c_ptr + j * m;
497
+ double mul = target[0];
498
+ if(mul == 0)
499
+ continue;
500
+ for(int k = 1; k < m - c_ptr; ++k)
501
+ target[k] = val * target[k] - mul * line[k];
502
+ }
503
+ ++c_ptr;
504
+ ++i;
505
+ }
506
+ free(A);
507
+ return i;
508
+ }
509
+
510
+ double c_matrix_determinant(int n, const double* A)
511
+ {
512
+ double* M = malloc(n * n * sizeof(double));
513
+ double det = 1;
514
+ copy_d_array(n * n, A, M);
515
+
516
+ for(int i = 0; i < n; ++i)
517
+ {
518
+ double* line_p = M + i + i * n;
519
+ double current = *line_p;
520
+
521
+ if(current == 0)
522
+ for(int j = i + 1; j < n; ++j)
523
+ if(M[i + j * n] != 0)
524
+ {
525
+ double* buf = M + i + j * n;
526
+ swap_d_arrays(n - i, buf, line_p);
527
+ current = line_p[0];
528
+ det *= -1;
529
+ }
530
+
531
+ if(current == 0)
532
+ {
533
+ free(M);
534
+ return 0;
535
+ }
536
+
537
+ det *= current;
538
+
539
+ for(int j = i + 1; j < n; ++j)
540
+ {
541
+ double* t_line = M + i + j * n;
542
+ double head = *t_line;
543
+ for(int k = 1; k < n - i; ++k)
544
+ t_line[k] -= line_p[k] * head / current;
545
+ }
546
+ }
547
+
548
+ free(M);
549
+ return det;
550
+ }
551
+
552
+ void c_matrix_shift_identity(int n, double* A, int s_a)
553
+ {
554
+ for(int i = 0; i < n; ++i)
555
+ {
556
+ double* line_p = A + i * s_a;
557
+ for(int j = 0; j < n; ++j)
558
+ line_p[j] = (i == j) ? 1 : 0;
559
+ }
560
+ }
561
+
562
+ bool c_matrix_inverse(int n, const double* A, double* B)
563
+ {
564
+ int m = 2 * n;
565
+ double* M = malloc(m * n * sizeof(double));
566
+ strassen_copy(n, n, A, M, n, m);
567
+ c_matrix_shift_identity(n, M + n, m);
568
+
569
+ for(int i = 0; i < n; ++i)
570
+ {
571
+ double* line_p = M + i + i * m;
572
+ double current = *line_p;
573
+
574
+ if(current == 0)
575
+ for(int j = i + 1; j < n; ++j)
576
+ if(M[i + j * m] != 0)
577
+ {
578
+ double* buf = M + i + j * m;
579
+ swap_d_arrays(m - i, buf, line_p);
580
+ current = line_p[0];
581
+ }
582
+
583
+ if(current == 0)
584
+ {
585
+ free(M);
586
+ return false;
587
+ }
588
+
589
+ for(int j = 0; j < n; ++j)
590
+ {
591
+ double* t_line = M + i + j * m;
592
+ double head = *t_line;
593
+ if(i == j || head == 0)
594
+ continue;
595
+ for(int k = 1; k < m - i; ++k)
596
+ t_line[k] -= line_p[k] * head / current;
597
+ }
598
+ for(int k = 1; k < m - i; ++k)
599
+ line_p[k] = line_p[k] / current;
600
+ }
601
+
602
+ strassen_copy(n, n, M + n, B, m, n);
603
+
604
+ free(M);
605
+ return true;
606
+ }