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.
- checksums.yaml +4 -4
- data/.dockerignore +0 -1
- data/.travis.yml +2 -1
- data/README.md +3 -8
- data/ext/fast_matrix/{c_array_opeartions.c → Helper/c_array_opeartions.c} +39 -1
- data/ext/fast_matrix/{c_array_operations.h → Helper/c_array_operations.h} +6 -1
- data/ext/fast_matrix/{errors.c → Helper/errors.c} +8 -2
- data/ext/fast_matrix/{errors.h → Helper/errors.h} +3 -1
- data/ext/fast_matrix/Matrix/c_matrix.c +606 -0
- data/ext/fast_matrix/Matrix/c_matrix.h +49 -0
- data/ext/fast_matrix/Matrix/errors.h +28 -0
- data/ext/fast_matrix/Matrix/helper.h +27 -0
- data/ext/fast_matrix/Matrix/matrix.c +633 -0
- data/ext/fast_matrix/Matrix/matrix.h +11 -0
- data/ext/fast_matrix/Vector/c_vector.c +97 -0
- data/ext/fast_matrix/Vector/c_vector.h +24 -0
- data/ext/fast_matrix/Vector/errors.h +14 -0
- data/ext/fast_matrix/Vector/helper.h +26 -0
- data/ext/fast_matrix/Vector/vector.c +476 -0
- data/ext/fast_matrix/{vector.h → Vector/vector.h} +0 -10
- data/ext/fast_matrix/c_include.c +8 -0
- data/ext/fast_matrix/fast_matrix.h +3 -3
- data/fast_matrix.gemspec +1 -1
- data/lib/fast_matrix/version.rb +1 -1
- data/lib/matrix/constructors.rb +0 -63
- data/lib/matrix/matrix.rb +105 -4
- data/lib/vector/constructors.rb +5 -4
- data/lib/vector/vector.rb +29 -0
- metadata +21 -12
- data/ext/fast_matrix/matrix.c +0 -678
- data/ext/fast_matrix/matrix.h +0 -28
- data/ext/fast_matrix/vector.c +0 -277
@@ -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 */
|
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
|
data/lib/fast_matrix/version.rb
CHANGED
data/lib/matrix/constructors.rb
CHANGED
@@ -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
|
23
|
-
|
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
|
-
|
27
|
-
|
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
|
data/lib/vector/constructors.rb
CHANGED
@@ -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
|
29
|
+
# Vector.basis(size:, index:) # => Vector[0, 1, 0]
|
30
30
|
#
|
31
|
-
def
|
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.
|
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.
|
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-
|
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: []
|
data/ext/fast_matrix/matrix.c
DELETED
@@ -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
|
-
}
|