fast_matrix 0.1.66 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,16 +5,6 @@
5
5
 
6
6
  extern VALUE cVector;
7
7
  extern const rb_data_type_t vector_type;
8
-
9
- // vector
10
- struct vector
11
- {
12
- int n;
13
- double* data;
14
- };
15
-
16
- void c_vector_init(struct vector* vect, int n);
17
-
18
8
  void init_fm_vector();
19
9
 
20
10
  #endif /* FAST_MATRIX_VECTOR_H */
@@ -0,0 +1,8 @@
1
+ #include "Helper/errors.c"
2
+ #include "Helper/c_array_opeartions.c"
3
+
4
+ #include "Matrix/matrix.c"
5
+ #include "Matrix/c_matrix.c"
6
+
7
+ #include "Vector/vector.c"
8
+ #include "Vector/c_vector.c"
@@ -1,9 +1,9 @@
1
1
  #ifndef FAST_MATRIX_H
2
2
  #define FAST_MATRIX_H 1
3
3
 
4
- #include "errors.h"
5
- #include "matrix.h"
6
- #include "vector.h"
4
+ #include "Helper/errors.h"
5
+ #include "Matrix/matrix.h"
6
+ #include "Vector/vector.h"
7
7
 
8
8
  void Init_fast_matrix();
9
9
 
data/fast_matrix.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = %q{Ruby wrapper around C matrices implementation}
12
12
  spec.description = %q{Ruby wrapper around C matrices implementation}
13
- spec.homepage = "https://github.com/mmcs-ruby/fast_matrix"
13
+ spec.homepage = "https://github.com/mmcs-ruby/fast_matrix/wiki"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.metadata["homepage_uri"] = spec.homepage
@@ -1,3 +1,3 @@
1
1
  module FastMatrix
2
- VERSION = '0.1.66'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -95,17 +95,6 @@ module FastMatrix
95
95
  build(values.size, values.size) { |i, j| i == j ? values[i] : 0 }
96
96
  end
97
97
 
98
- #
99
- # Creates an +n+ by +n+ diagonal matrix where each diagonal element is
100
- # +value+.
101
- # Matrix.scalar(2, 5)
102
- # => 5 0
103
- # 0 5
104
- #
105
- def self.scalar(n, value)
106
- build(n, n) { |i, j| i == j ? value : 0 }
107
- end
108
-
109
98
  #
110
99
  # Creates an +n+ by +n+ identity matrix.
111
100
  # Matrix.identity(2)
@@ -147,58 +136,6 @@ module FastMatrix
147
136
  raise NotSupportedError, 'Empty matrices does not supported'
148
137
  end
149
138
 
150
- #
151
- # Create a matrix by stacking matrices vertically
152
- #
153
- # x = Matrix[[1, 2], [3, 4]]
154
- # y = Matrix[[5, 6], [7, 8]]
155
- # Matrix.vstack(x, y) # => Matrix[[1, 2], [3, 4], [5, 6], [7, 8]]
156
- # TODO: optimize (maybe in C)
157
- def self.vstack(x, *matrices)
158
- column_count = x.column_count
159
- row_count = x.row_count
160
- matrices.each do |matrix|
161
- raise IndexError unless matrix.column_count == column_count
162
-
163
- row_count += matrix.row_count
164
- end
165
- result = new(row_count, column_count)
166
- m_i = 0
167
- [x, *matrices].each do |matrix|
168
- matrix.each_with_index do |elem, i, j|
169
- result[m_i + i, j] = elem
170
- end
171
- m_i += matrix.row_count
172
- end
173
- result
174
- end
175
-
176
- #
177
- # Create a matrix by stacking matrices horizontally
178
- #
179
- # x = Matrix[[1, 2], [3, 4]]
180
- # y = Matrix[[5, 6], [7, 8]]
181
- # Matrix.hstack(x, y) # => Matrix[[1, 2, 5, 6], [3, 4, 7, 8]]
182
- #
183
- def self.hstack(x, *matrices)
184
- column_count = x.column_count
185
- row_count = x.row_count
186
- matrices.each do |matrix|
187
- raise IndexError unless matrix.row_count == row_count
188
-
189
- column_count += matrix.column_count
190
- end
191
- result = new(row_count, column_count)
192
- m_j = 0
193
- [x, *matrices].each do |matrix|
194
- matrix.each_with_index do |elem, i, j|
195
- result[i, m_j + j] = elem
196
- end
197
- m_j += matrix.column_count
198
- end
199
- result
200
- end
201
-
202
139
  #
203
140
  # Create a matrix by combining matrices entrywise, using the given block
204
141
  #
data/lib/matrix/matrix.rb CHANGED
@@ -19,14 +19,30 @@ module FastMatrix
19
19
  alias element []
20
20
  alias component []
21
21
 
22
- def to_s
23
- convert.to_s
22
+ def collect
23
+ collected_rows = []
24
+ rows.each do |i|
25
+ collected_rows.push(yield i)
26
+ end
27
+ collected_rows
24
28
  end
25
29
 
26
- def inspect
27
- convert.inspect
30
+ #
31
+ # Overrides Object#to_s
32
+ #
33
+ def to_s
34
+ "#{self.class}[#{collect do |row|
35
+ '[' + row.join(', ') + ']'
36
+ end.join(', ')}]"
28
37
  end
29
38
 
39
+ alias to_str to_s
40
+ alias inspect to_str
41
+
42
+ def to_a
43
+ rows.collect(&:dup)
44
+ end
45
+
30
46
  #
31
47
  # Create fast matrix from standard matrix
32
48
  #
@@ -40,14 +56,85 @@ module FastMatrix
40
56
  fast_matrix
41
57
  end
42
58
 
59
+ #
60
+ # Yields all elements of the matrix, starting with those of the first row
61
+ #
62
+ # Matrix[ [1,2], [3,4] ].each { |e| puts e }
63
+ # # => prints the numbers 1 to 4
64
+ def each(which = :all) # :yield: e
65
+ return to_enum :each, which unless block_given?
66
+ case which
67
+ when :all
68
+ (0...row_count).each do |i|
69
+ (0...column_count).each do |j|
70
+ yield self[i, j]
71
+ end
72
+ end
73
+ when :diagonal
74
+ (0...[row_count, column_count].min).each do |i|
75
+ yield self[i, i]
76
+ end
77
+ when :off_diagonal
78
+ (0...row_count).each do |i|
79
+ (0...column_count).each do |j|
80
+ if i != j
81
+ yield self[i, j]
82
+ end
83
+ end
84
+ end
85
+ when :lower
86
+ (0...row_count).each do |i|
87
+ (0..[i,column_count-1].min).each do |j|
88
+ yield self[i, j]
89
+ end
90
+ end
91
+ when :strict_lower
92
+ (1...row_count).each do |i|
93
+ (0...[i,column_count].min).each do |j|
94
+ yield self[i, j]
95
+ end
96
+ end
97
+ when :strict_upper
98
+ (0...row_count).each do |i|
99
+ (i+1...column_count).each do |j|
100
+ yield self[i, j]
101
+ end
102
+ end
103
+ when :upper
104
+ (0...row_count).each do |i|
105
+ (i...column_count).each do |j|
106
+ yield self[i, j]
107
+ end
108
+ end
109
+ else
110
+ raise ArgumentError, "expected #{which.inspect} to be one of :all, :diagonal, :off_diagonal, :lower, :strict_lower, :strict_upper or :upper"
111
+ end
112
+ self
113
+ end
114
+ #
115
+ # Same as #each, but the row index and column index in addition to the element
116
+ #
117
+ # Matrix[ [1,2], [3,4] ].each_with_index do |e, row, col|
118
+ # puts "#{e} at #{row}, #{col}"
119
+ # end
120
+ # # => Prints:
121
+ # # 1 at 0, 0
122
+ # # 2 at 0, 1
123
+ # # 3 at 1, 0
124
+ # # 4 at 1, 1
125
+ #
43
126
  def each_with_index
127
+ raise NotSupportedError unless block_given?
128
+
44
129
  (0...row_count).each do |i|
45
130
  (0...column_count).each do |j|
46
131
  yield self[i, j], i, j
47
132
  end
48
133
  end
134
+ self
49
135
  end
50
136
 
137
+ # don't use (Issue#1)
51
138
  def each_with_index!
52
139
  (0...row_count).each do |i|
53
140
  (0...column_count).each do |j|
@@ -76,5 +163,19 @@ module FastMatrix
76
163
  end
77
164
  result
78
165
  end
166
+
167
+ private
168
+
169
+ def rows
170
+ rows = []
171
+ (0...row_count).each do |i|
172
+ row = []
173
+ (0...column_count).each do |j|
174
+ row.push(element(i, j))
175
+ end
176
+ rows.push(row)
177
+ end
178
+ rows
179
+ end
79
180
  end
80
181
  end
@@ -26,9 +26,11 @@ module FastMatrix
26
26
  #
27
27
  # Returns a standard basis +n+-vector, where k is the index.
28
28
  #
29
- # Vector.basis(size, index) # => Vector[0, 1, 0]
29
+ # Vector.basis(size:, index:) # => Vector[0, 1, 0]
30
30
  #
31
- def self.basis(size, index)
31
+ def Vector.basis(size:, index:)
32
+ raise IndexError, "invalid size (#{size} for 1..)" if size < 1
33
+ raise IndexError, "invalid index (#{index} for 0...#{size})" unless 0 <= index && index < size
32
34
  result = zero(size)
33
35
  result[index] = 1
34
36
  result
@@ -41,8 +43,7 @@ module FastMatrix
41
43
  #
42
44
  def self.zero(size)
43
45
  result = new(size)
44
- result.each_with_index! { 0 }
45
- result
46
+ result.fill!(0)
46
47
  end
47
48
 
48
49
  class << Vector
data/lib/vector/vector.rb CHANGED
@@ -21,12 +21,32 @@ module FastMatrix
21
21
  Array.new(size) { |i| self[i] }
22
22
  end
23
23
 
24
+ def to_s
25
+ "#{self.class}[#{to_ary.join(', ')}]"
26
+ end
27
+ alias to_str to_s
28
+ alias inspect to_str
29
+
30
+ #
31
+ # Iterate over the elements of this vector
32
+ #
33
+ def each
34
+ raise NotSupportedError unless block_given?
35
+
36
+ (0...size).each do |i|
37
+ yield self[i]
38
+ end
39
+ self
40
+ end
41
+
24
42
  def each_with_index
25
43
  (0...size).each do |i|
26
44
  yield self[i], i
27
45
  end
46
+ self
28
47
  end
29
48
 
49
+ # don't use (Issue#1)
30
50
  def each_with_index!
31
51
  (0...size).each do |i|
32
52
  self[i] = yield self[i], i
@@ -46,5 +66,14 @@ module FastMatrix
46
66
  end
47
67
  result
48
68
  end
69
+
70
+ def independent?(*vs)
71
+ vs << self
72
+ Vector.independent?(*vs)
73
+ end
74
+
75
+ def cross_product(*vs)
76
+ Vector.cross_product(self, *vs)
77
+ end
49
78
  end
50
79
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_matrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.66
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mmcs_ruby
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-29 00:00:00.000000000 Z
11
+ date: 2019-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -97,17 +97,26 @@ files:
97
97
  - LICENSE.txt
98
98
  - README.md
99
99
  - Rakefile
100
- - ext/fast_matrix/c_array_opeartions.c
101
- - ext/fast_matrix/c_array_operations.h
102
- - ext/fast_matrix/errors.c
103
- - ext/fast_matrix/errors.h
100
+ - ext/fast_matrix/Helper/c_array_opeartions.c
101
+ - ext/fast_matrix/Helper/c_array_operations.h
102
+ - ext/fast_matrix/Helper/errors.c
103
+ - ext/fast_matrix/Helper/errors.h
104
+ - ext/fast_matrix/Matrix/c_matrix.c
105
+ - ext/fast_matrix/Matrix/c_matrix.h
106
+ - ext/fast_matrix/Matrix/errors.h
107
+ - ext/fast_matrix/Matrix/helper.h
108
+ - ext/fast_matrix/Matrix/matrix.c
109
+ - ext/fast_matrix/Matrix/matrix.h
110
+ - ext/fast_matrix/Vector/c_vector.c
111
+ - ext/fast_matrix/Vector/c_vector.h
112
+ - ext/fast_matrix/Vector/errors.h
113
+ - ext/fast_matrix/Vector/helper.h
114
+ - ext/fast_matrix/Vector/vector.c
115
+ - ext/fast_matrix/Vector/vector.h
116
+ - ext/fast_matrix/c_include.c
104
117
  - ext/fast_matrix/extconf.rb
105
118
  - ext/fast_matrix/fast_matrix.c
106
119
  - ext/fast_matrix/fast_matrix.h
107
- - ext/fast_matrix/matrix.c
108
- - ext/fast_matrix/matrix.h
109
- - ext/fast_matrix/vector.c
110
- - ext/fast_matrix/vector.h
111
120
  - fast_matrix.gemspec
112
121
  - lib/errors.rb
113
122
  - lib/fast_matrix.rb
@@ -117,11 +126,11 @@ files:
117
126
  - lib/scalar.rb
118
127
  - lib/vector/constructors.rb
119
128
  - lib/vector/vector.rb
120
- homepage: https://github.com/mmcs-ruby/fast_matrix
129
+ homepage: https://github.com/mmcs-ruby/fast_matrix/wiki
121
130
  licenses:
122
131
  - MIT
123
132
  metadata:
124
- homepage_uri: https://github.com/mmcs-ruby/fast_matrix
133
+ homepage_uri: https://github.com/mmcs-ruby/fast_matrix/wiki
125
134
  source_code_uri: https://github.com/mmcs-ruby/fast_matrix
126
135
  post_install_message:
127
136
  rdoc_options: []
@@ -1,678 +0,0 @@
1
- #include "matrix.h"
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
- };
23
-
24
- void matrix_free(void* data)
25
- {
26
- free(((*(struct matrix*)data)).data);
27
- free(data);
28
- }
29
-
30
- size_t matrix_size(const void* data)
31
- {
32
- return sizeof(struct matrix);
33
- }
34
-
35
- VALUE matrix_alloc(VALUE self)
36
- {
37
- struct matrix* mtx = malloc(sizeof(struct matrix));
38
- mtx->data = NULL;
39
- return TypedData_Wrap_Struct(self, &matrix_type, mtx);
40
- }
41
-
42
- void c_matrix_init(struct matrix* mtr, int m, int n)
43
- {
44
- mtr->m = m;
45
- mtr->n = n;
46
- mtr->data = malloc(m * n * sizeof(double));
47
- }
48
-
49
- VALUE matrix_initialize(VALUE self, VALUE rows_count, VALUE columns_count)
50
- {
51
- struct matrix* data;
52
- int m = raise_rb_value_to_int(columns_count);
53
- int n = raise_rb_value_to_int(rows_count);
54
-
55
- if(m <= 0 || n <= 0)
56
- rb_raise(fm_eIndexError, "Size cannot be negative or zero");
57
-
58
- TypedData_Get_Struct(self, struct matrix, &matrix_type, data);
59
-
60
- c_matrix_init(data, m, n);
61
-
62
- return self;
63
- }
64
-
65
- // []=
66
- VALUE matrix_set(VALUE self, VALUE row, VALUE column, VALUE v)
67
- {
68
- int m = raise_rb_value_to_int(column);
69
- int n = raise_rb_value_to_int(row);
70
- double x = raise_rb_value_to_double(v);
71
-
72
- struct matrix* data;
73
- TypedData_Get_Struct(self, struct matrix, &matrix_type, data);
74
-
75
- m = (m < 0) ? data->m + m : m;
76
- n = (n < 0) ? data->n + n : n;
77
-
78
- raise_check_range(m, 0, data->m);
79
- raise_check_range(n, 0, data->n);
80
-
81
- data->data[m + data->m * n] = x;
82
- return v;
83
- }
84
-
85
- // []
86
- VALUE matrix_get(VALUE self, VALUE row, VALUE column)
87
- {
88
- int m = raise_rb_value_to_int(column);
89
- int n = raise_rb_value_to_int(row);
90
-
91
- struct matrix* data;
92
- TypedData_Get_Struct(self, struct matrix, &matrix_type, data);
93
-
94
- m = (m < 0) ? data->m + m : m;
95
- n = (n < 0) ? data->n + n : n;
96
-
97
- if(m < 0 || n < 0 || n >= data->n || m >= data->m)
98
- return Qnil;
99
-
100
- return DBL2NUM(data->data[m + data->m * n]);
101
- }
102
-
103
- // in - matrix m x n
104
- // out - matrix n x m
105
- void matrix_transpose(int m, int n, const double* in, double* out)
106
- {
107
- for(int i = 0; i < m; ++i)
108
- for(int j = 0; j < n; ++j)
109
- out[j + n * i] = in[i + m * j];
110
- }
111
-
112
- // A - matrix k x n
113
- // B - matrix m x k
114
- // C - matrix m x n
115
- void c_matrix_multiply(int n, int k, int m, const double* A, const double* B, double* C)
116
- {
117
- fill_d_array(m * n, C, 0);
118
-
119
- for(int j = 0; j < n; ++j)
120
- {
121
- double* p_c = C + m * j;
122
- const double* p_a = A + k * j;
123
-
124
- for(int t = 0; t < k; ++t)
125
- {
126
- const double* p_b = B + m * t;
127
- double d_a = p_a[t];
128
- for(int i = 0; i < m; ++i)
129
- p_c[i] += d_a * p_b[i];
130
- }
131
- }
132
- }
133
-
134
- // M - matrix m x n
135
- // V - vector m
136
- // R - vector n
137
- void c_matrix_vector_multiply(int n, int m, const double* M, const double* V, double* R)
138
- {
139
- fill_d_array(n, R, 0);
140
-
141
- for(int j = 0; j < n; ++j)
142
- {
143
- const double* p_m = M + m * j;
144
- for(int i = 0; i < m; ++i)
145
- R[j] += V[i] * p_m[i];
146
- }
147
- }
148
-
149
- VALUE matrix_multiply_mv(VALUE self, VALUE other)
150
- {
151
- struct matrix* M;
152
- struct vector* V;
153
- TypedData_Get_Struct(self, struct matrix, &matrix_type, M);
154
- TypedData_Get_Struct(other, struct vector, &vector_type, V);
155
-
156
- if(M->m != V->n)
157
- rb_raise(fm_eIndexError, "Matrix columns differs from vector size");
158
-
159
- int m = M->m;
160
- int n = M->n;
161
-
162
- struct vector* R;
163
- VALUE result = TypedData_Make_Struct(cVector, struct vector, &vector_type, R);
164
-
165
- c_vector_init(R, n);
166
- c_matrix_vector_multiply(n, m, M->data, V->data, R->data);
167
-
168
- return result;
169
- }
170
-
171
- // A - matrix k x n
172
- // B - matrix m x k
173
- // C - matrix m x n
174
- 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)
175
- {
176
- for(int j = 0; j < n; ++j)
177
- {
178
- double* p_c = C + s_c * j;
179
- const double* p_a = A + s_a * j;
180
-
181
- for(int t = 0; t < k; ++t)
182
- {
183
- const double* p_b = B + s_b * t;
184
- double d_a = p_a[t];
185
- for(int i = 0; i < m; ++i)
186
- p_c[i] += d_a * p_b[i];
187
- }
188
- }
189
- }
190
-
191
- bool check_strassen(int m, int n, int k)
192
- {
193
- return n > 2 && m > 2 && k > 2 && (double)m * (double)n * (double)k > 100000000;
194
- }
195
-
196
-
197
- void strassen_copy(int m, int n, const double* A, double* B, int s_a, int s_b)
198
- {
199
- for(int i = 0; i < n; ++i)
200
- {
201
- const double* p_A = A + i * s_a;
202
- double* p_B = B + i * s_b;
203
- for(int j = 0; j < m; ++j)
204
- p_B[j] = p_A[j];
205
- }
206
- }
207
-
208
- void strassen_sum_to_first(int m, int n, double* A, const double* B, int s_a, int s_b)
209
- {
210
- for(int i = 0; i < n; ++i)
211
- {
212
- double* p_A = A + i * s_a;
213
- const double* p_B = B + i * s_b;
214
- for(int j = 0; j < m; ++j)
215
- p_A[j] += p_B[j];
216
- }
217
- }
218
-
219
- void strassen_sub_to_first(int m, int n, double* A, const double* B, int s_a, int s_b)
220
- {
221
- for(int i = 0; i < n; ++i)
222
- {
223
- double* p_A = A + i * s_a;
224
- const double* p_B = B + i * s_b;
225
- for(int j = 0; j < m; ++j)
226
- p_A[j] -= p_B[j];
227
- }
228
- }
229
-
230
- // A - matrix k x n
231
- // B - matrix m x k
232
- // C - matrix m x n
233
- void recursive_strassen(int n, int k, int m, const double* A, const double* B, double* C)
234
- {
235
- if(!check_strassen(m, n, k))
236
- return c_matrix_multiply(n, k, m, A, B, C);
237
-
238
- int k2 = k / 2;
239
- int k1 = k - k2;
240
- int m2 = m / 2;
241
- int m1 = m - m2;
242
- int n2 = n / 2;
243
- int n1 = n - n2;
244
-
245
- double* termA = malloc(k1 * n1 * sizeof(double));
246
- double* termB = malloc(m1 * k1 * sizeof(double));
247
-
248
- double* P1 = malloc(7 * m1 * n1 * sizeof(double));
249
- double* P2 = P1 + m1 * n1;
250
- double* P3 = P2 + m1 * n1;
251
- double* P4 = P3 + m1 * n1;
252
- double* P5 = P4 + m1 * n1;
253
- double* P6 = P5 + m1 * n1;
254
- double* P7 = P6 + m1 * n1;
255
- fill_d_array(7 * m1 * n1, P1, 0);
256
- fill_d_array(k1 * n1, termA, 0);
257
- fill_d_array(m1 * k1, termB, 0);
258
-
259
- // -----------P1-----------
260
- strassen_copy(k1, n1, A, termA, k, k1);
261
- strassen_sum_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
262
-
263
- strassen_copy(m1, k1, B, termB, m, m1);
264
- strassen_sum_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
265
-
266
- recursive_strassen(n1, k1, m1, termA, termB, P1);
267
- fill_d_array(k1 * n1, termA, 0);
268
- // -----------P2-----------
269
- strassen_copy(k1, n2, A + k * n1, termA, k, k1);
270
- strassen_sum_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
271
-
272
- strassen_copy(m1, k1, B, termB, m, m1);
273
-
274
- recursive_strassen(n1, k1, m1, termA, termB, P2);
275
- fill_d_array(m1 * k1, termB, 0);
276
- // -----------P3-----------
277
- strassen_copy(k1, n1, A, termA, k, k1);
278
-
279
- strassen_copy(m2, k1, B + m1, termB, m, m1);
280
- strassen_sub_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
281
-
282
- recursive_strassen(n1, k1, m1, termA, termB, P3);
283
- fill_d_array(k1 * n1, termA, 0);
284
- fill_d_array(m1 * k1, termB, 0);
285
- // -----------P4-----------
286
- strassen_copy(k2, n2, A + k1 + k * n1, termA, k, k1);
287
-
288
- strassen_copy(m1, k2, B + m * k1, termB, m, m1);
289
- strassen_sub_to_first(m1, k1, termB, B, m1, m);
290
-
291
- recursive_strassen(n1, k1, m1, termA, termB, P4);
292
- fill_d_array(m1 * k1, termB, 0);
293
- // -----------P5-----------
294
- strassen_copy(k1, n1, A, termA, k, k1);
295
- strassen_sum_to_first(k2, n1, termA, A + k1, k1, k);
296
-
297
- strassen_copy(m2, k2, B + m1 + m * k1, termB, m, m1);
298
-
299
- recursive_strassen(n1, k1, m1, termA, termB, P5);
300
- fill_d_array(k1 * n1, termA, 0);
301
- // -----------P6-----------
302
- strassen_copy(k1, n2, A + k * n1, termA, k, k1);
303
- strassen_sub_to_first(k1, n1, termA, A, k1, k);
304
-
305
- strassen_copy(m1, k1, B, termB, m, m1);
306
- strassen_sum_to_first(m2, k1, termB, B + m1, m1, m);
307
-
308
- recursive_strassen(n1, k1, m1, termA, termB, P6);
309
- fill_d_array(k1 * n1, termA, 0);
310
- fill_d_array(m1 * k1, termB, 0);
311
- // -----------P7-----------
312
- strassen_copy(k2, n1, A + k1, termA, k, k1);
313
- strassen_sub_to_first(k2, n2, termA, A + k1 + k * n1, k1, k);
314
-
315
- strassen_copy(m1, k2, B + k1 * m, termB, m, m1);
316
- strassen_sum_to_first(m2, k2, termB, B + m1 + m * k1, m1, m);
317
-
318
- recursive_strassen(n1, k1, m1, termA, termB, P7);
319
-
320
- // -----------C11-----------
321
- double* C11 = C;
322
- strassen_copy(m1, n1, P1, C11, m1, m);
323
- strassen_sum_to_first(m1, n1, C11, P4, m, m1);
324
- strassen_sub_to_first(m1, n1, C11, P5, m, m1);
325
- strassen_sum_to_first(m1, n1, C11, P7, m, m1);
326
- // -----------C12-----------
327
- double* C12 = C + m1;
328
- strassen_copy(m2, n1, P3, C12, m1, m);
329
- strassen_sum_to_first(m2, n1, C12, P5, m, m1);
330
- // -----------C21-----------
331
- double* C21 = C + m * n1;
332
- strassen_copy(m1, n2, P2, C21, m1, m);
333
- strassen_sum_to_first(m1, n2, C21, P4, m, m1);
334
- // -----------C22-----------
335
- double* C22 = C + m1 + m * n1;
336
- strassen_copy(m2, n2, P1, C22, m1, m);
337
- strassen_sub_to_first(m2, n2, C22, P2, m, m1);
338
- strassen_sum_to_first(m2, n2, C22, P3, m, m1);
339
- strassen_sum_to_first(m2, n2, C22, P6, m, m1);
340
-
341
- free(termA);
342
- free(termB);
343
- free(P1);
344
- }
345
-
346
- VALUE strassen(VALUE self, VALUE other)
347
- {
348
- struct matrix* A;
349
- struct matrix* B;
350
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
351
- TypedData_Get_Struct(other, struct matrix, &matrix_type, B);
352
-
353
- if(A->m != B->n)
354
- rb_raise(fm_eIndexError, "First columns differs from second rows");
355
-
356
- int m = B->m;
357
- int k = A->m;
358
- int n = A->n;
359
-
360
- struct matrix* C;
361
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C);
362
-
363
- c_matrix_init(C, m, n);
364
- fill_d_array(m * n, C->data, 0);
365
- recursive_strassen(n, k, m, A->data, B->data, C->data);
366
- return result;
367
- }
368
-
369
- VALUE matrix_multiply_mm(VALUE self, VALUE other)
370
- {
371
- struct matrix* A;
372
- struct matrix* B;
373
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
374
- TypedData_Get_Struct(other, struct matrix, &matrix_type, B);
375
-
376
- if(A->m != B->n)
377
- rb_raise(fm_eIndexError, "First columns differs from second rows");
378
-
379
- int m = B->m;
380
- int k = A->m;
381
- int n = A->n;
382
-
383
- struct matrix* C;
384
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C);
385
-
386
- c_matrix_init(C, m, n);
387
- c_matrix_multiply(n, k, m, A->data, B->data, C->data);
388
-
389
- return result;
390
- }
391
-
392
- VALUE matrix_multiply_mn(VALUE self, VALUE value)
393
- {
394
- struct matrix* A;
395
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
396
-
397
- double d = NUM2DBL(value);
398
-
399
- struct matrix* R;
400
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, R);
401
-
402
- c_matrix_init(R, A->m, A->n);
403
- copy_d_array(A->m * A->n, A->data, R->data);
404
- multiply_d_array(R->m * R->n, R->data, d);
405
-
406
- return result;
407
- }
408
-
409
- VALUE matrix_multiply(VALUE self, VALUE v)
410
- {
411
- if(RB_FLOAT_TYPE_P(v) || FIXNUM_P(v)
412
- || RB_TYPE_P(v, T_BIGNUM))
413
- return matrix_multiply_mn(self, v);
414
- if(RBASIC_CLASS(v) == cMatrix)
415
- return matrix_multiply_mm(self, v);
416
- if(RBASIC_CLASS(v) == cVector);
417
- return matrix_multiply_mv(self, v);
418
- rb_raise(fm_eTypeError, "Invalid klass for multiply");
419
- }
420
-
421
- VALUE matrix_copy(VALUE mtrx)
422
- {
423
- struct matrix* M;
424
- TypedData_Get_Struct(mtrx, struct matrix, &matrix_type, M);
425
-
426
- struct matrix* R;
427
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, R);
428
-
429
- c_matrix_init(R, M->m, M->n);
430
- copy_d_array(M->m * M->n, M->data, R->data);
431
-
432
- return result;
433
- }
434
-
435
- VALUE row_size(VALUE self)
436
- {
437
- struct matrix* data;
438
- TypedData_Get_Struct(self, struct matrix, &matrix_type, data);
439
- return INT2NUM(data->m);
440
- }
441
-
442
- VALUE column_size(VALUE self)
443
- {
444
- struct matrix* data;
445
- TypedData_Get_Struct(self, struct matrix, &matrix_type, data);
446
- return INT2NUM(data->n);
447
- }
448
-
449
- VALUE transpose(VALUE self)
450
- {
451
- struct matrix* M;
452
- TypedData_Get_Struct(self, struct matrix, &matrix_type, M);
453
-
454
- struct matrix* R;
455
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, R);
456
-
457
- c_matrix_init(R, M->n, M->m);
458
- matrix_transpose(M->m, M->n, M->data, R->data);
459
-
460
- return result;
461
- }
462
-
463
- VALUE matrix_add_with(VALUE self, VALUE value)
464
- {
465
- struct matrix* A;
466
- struct matrix* B;
467
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
468
- TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
469
-
470
- if(A->m != B->m && A->n != B->n)
471
- rb_raise(fm_eIndexError, "Different sizes matrices");
472
-
473
- int m = B->m;
474
- int n = A->n;
475
-
476
- struct matrix* C;
477
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C);
478
-
479
- c_matrix_init(C, m, n);
480
- add_d_arrays_to_result(n * m, A->data, B->data, C->data);
481
-
482
- return result;
483
- }
484
-
485
- VALUE matrix_add_from(VALUE self, VALUE value)
486
- {
487
- struct matrix* A;
488
- struct matrix* B;
489
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
490
- TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
491
-
492
- if(A->m != B->m && A->n != B->n)
493
- rb_raise(fm_eIndexError, "Different sizes matrices");
494
-
495
- int m = B->m;
496
- int n = A->n;
497
-
498
- add_d_arrays_to_first(n * m, A->data, B->data);
499
-
500
- return self;
501
- }
502
-
503
-
504
- VALUE matrix_sub_with(VALUE self, VALUE value)
505
- {
506
- struct matrix* A;
507
- struct matrix* B;
508
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
509
- TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
510
-
511
- if(A->m != B->m && A->n != B->n)
512
- rb_raise(fm_eIndexError, "Different sizes matrices");
513
-
514
- int m = B->m;
515
- int n = A->n;
516
-
517
- struct matrix* C;
518
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, C);
519
-
520
- c_matrix_init(C, m, n);
521
- sub_d_arrays_to_result(n * m, A->data, B->data, C->data);
522
-
523
- return result;
524
- }
525
-
526
- double determinant(int n, const double* A)
527
- {
528
- double* M = malloc(n * n * sizeof(double));
529
- double det = 1;
530
- copy_d_array(n * n, A, M);
531
-
532
- for(int i = 0; i < n; ++i)
533
- {
534
- const double* line_p = M + i + i * n;
535
- double current = *line_p;
536
- det *= current;
537
-
538
- if(current == 0)
539
- {
540
- free(M);
541
- return 0;
542
- }
543
-
544
- for(int j = i + 1; j < n; ++j)
545
- {
546
- double* t_line = M + i + j * n;
547
- double head = *t_line;
548
- for(int k = 1; k < n - i; ++k)
549
- t_line[k] -= line_p[k] * head / current;
550
- }
551
- }
552
-
553
- free(M);
554
- return det;
555
- }
556
-
557
- VALUE matrix_determinant(VALUE self)
558
- {
559
- struct matrix* A;
560
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
561
-
562
-
563
- int m = A->m;
564
- int n = A->n;
565
- if(m != n)
566
- rb_raise(fm_eIndexError, "Not a square matrix");
567
-
568
- return DBL2NUM(determinant(n, A->data));
569
- }
570
-
571
- VALUE matrix_sub_from(VALUE self, VALUE value)
572
- {
573
- struct matrix* A;
574
- struct matrix* B;
575
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
576
- TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
577
-
578
- if(A->m != B->m && A->n != B->n)
579
- rb_raise(fm_eIndexError, "Different sizes matrices");
580
-
581
- int m = B->m;
582
- int n = A->n;
583
-
584
- sub_d_arrays_to_first(n * m, A->data, B->data);
585
-
586
- return self;
587
- }
588
-
589
- VALUE matrix_fill(VALUE self, VALUE value)
590
- {
591
- double d = raise_rb_value_to_double(value);
592
- struct matrix* A;
593
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
594
-
595
- fill_d_array(A->m * A->n, A->data, d);
596
-
597
- return self;
598
- }
599
-
600
- VALUE matrix_equal(VALUE self, VALUE value)
601
- {
602
- struct matrix* A;
603
- struct matrix* B;
604
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
605
- TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
606
-
607
- if(A->n != B->n || A->m != B->m)
608
- return Qfalse;
609
-
610
- int n = A->n;
611
- int m = B->m;
612
-
613
- if(equal_d_arrays(n * m, A->data, B->data))
614
- return Qtrue;
615
- return Qfalse;
616
- }
617
-
618
- VALUE matrix_abs(VALUE self)
619
- {
620
- struct matrix* A;
621
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
622
-
623
- int m = A->m;
624
- int n = A->n;
625
-
626
- struct matrix* B;
627
- VALUE result = TypedData_Make_Struct(cMatrix, struct matrix, &matrix_type, B);
628
-
629
- c_matrix_init(B, m, n);
630
- abs_d_array(n * m, A->data, B->data);
631
-
632
- return result;
633
- }
634
-
635
- VALUE matrix_greater_or_equal(VALUE self, VALUE value)
636
- {
637
- struct matrix* A;
638
- struct matrix* B;
639
- TypedData_Get_Struct(self, struct matrix, &matrix_type, A);
640
- TypedData_Get_Struct(value, struct matrix, &matrix_type, B);
641
-
642
- if(A->m != B->m && A->n != B->n)
643
- rb_raise(fm_eIndexError, "Different sizes matrices");
644
-
645
- int m = B->m;
646
- int n = A->n;
647
-
648
- if(greater_or_equal_d_array(n * m, A->data, B->data))
649
- return Qtrue;
650
- return Qfalse;
651
- }
652
-
653
- void init_fm_matrix()
654
- {
655
- VALUE mod = rb_define_module("FastMatrix");
656
- cMatrix = rb_define_class_under(mod, "Matrix", rb_cData);
657
-
658
- rb_define_alloc_func(cMatrix, matrix_alloc);
659
-
660
- rb_define_method(cMatrix, "initialize", matrix_initialize, 2);
661
- rb_define_method(cMatrix, "[]", matrix_get, 2);
662
- rb_define_method(cMatrix, "[]=", matrix_set, 3);
663
- rb_define_method(cMatrix, "*", matrix_multiply, 1);
664
- rb_define_method(cMatrix, "column_count", row_size, 0);
665
- rb_define_method(cMatrix, "row_count", column_size, 0);
666
- rb_define_method(cMatrix, "clone", matrix_copy, 0);
667
- rb_define_method(cMatrix, "transpose", transpose, 0);
668
- rb_define_method(cMatrix, "+", matrix_add_with, 1);
669
- rb_define_method(cMatrix, "+=", matrix_add_from, 1);
670
- rb_define_method(cMatrix, "-", matrix_sub_with, 1);
671
- rb_define_method(cMatrix, "-=", matrix_sub_from, 1);
672
- rb_define_method(cMatrix, "fill!", matrix_fill, 1);
673
- rb_define_method(cMatrix, "strassen", strassen, 1);
674
- rb_define_method(cMatrix, "abs", matrix_abs, 0);
675
- rb_define_method(cMatrix, ">=", matrix_greater_or_equal, 1);
676
- rb_define_method(cMatrix, "determinant", matrix_determinant, 0);
677
- rb_define_method(cMatrix, "eql?", matrix_equal, 1);
678
- }