fast_matrix 0.1.5 → 0.1.6
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/.travis.yml +11 -0
- data/README.md +2 -0
- data/ext/fast_matrix/matrix.c +74 -3
- data/ext/fast_matrix/vector.c +6 -2
- data/fast_matrix.gemspec +1 -0
- data/lib/fast_matrix.rb +1 -0
- data/lib/fast_matrix/version.rb +1 -1
- data/lib/matrix/constructors.rb +31 -18
- data/lib/matrix/matrix.rb +1 -1
- data/lib/scalar.rb +58 -0
- data/lib/vector/vector.rb +30 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b595a00ec07bf1d240037d16e3691d99f02b1313f0601ddc384c1bbc46378511
|
4
|
+
data.tar.gz: 0bc5cd22534b4add7364cc0531a438e5b909ab157c4778af1aaa3eb13e0afe9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1eebf62db5b0214d6a04414cff95b6179bcfea2fc972397da325bb8a4efd871768711a9989572d18f7eb6ca1f51da7b0de84d3c1aa56547703ed4e0d72c4958b
|
7
|
+
data.tar.gz: 823754bfaf70c9ec3b1dafe6ba409ec954e332a7d48f66ef8e9327bbddcd9288a8d4dc55f053c990279f1ad17455384d92a68bd7b214e074dbd9f295b98f3019
|
data/.travis.yml
CHANGED
@@ -2,7 +2,18 @@ language: ruby
|
|
2
2
|
cache: bundler
|
3
3
|
rvm:
|
4
4
|
- 2.6.5
|
5
|
+
env:
|
6
|
+
global:
|
7
|
+
- CC_TEST_REPORTER_ID=$TEST_ID
|
5
8
|
before_install: gem install bundler -v 2.0.2
|
9
|
+
before_script:
|
10
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
11
|
+
- chmod +x ./cc-test-reporter
|
12
|
+
- ./cc-test-reporter before-build
|
13
|
+
script:
|
14
|
+
- bundle exec rake
|
15
|
+
after_script:
|
16
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
6
17
|
deploy:
|
7
18
|
provider: rubygems
|
8
19
|
api_key: $API_KEY
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
[](https://travis-ci.org/mmcs-ruby/fast_matrix)
|
2
|
+
[](https://codeclimate.com/github/mmcs-ruby/fast_matrix/maintainability)
|
3
|
+
[](https://codeclimate.com/github/mmcs-ruby/fast_matrix/test_coverage)
|
2
4
|
|
3
5
|
# FastMatrix
|
4
6
|
|
data/ext/fast_matrix/matrix.c
CHANGED
@@ -71,6 +71,9 @@ VALUE matrix_set(VALUE self, VALUE row, VALUE column, VALUE v)
|
|
71
71
|
|
72
72
|
struct matrix* data;
|
73
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;
|
74
77
|
|
75
78
|
raise_check_range(m, 0, data->m);
|
76
79
|
raise_check_range(n, 0, data->n);
|
@@ -87,9 +90,12 @@ VALUE matrix_get(VALUE self, VALUE row, VALUE column)
|
|
87
90
|
|
88
91
|
struct matrix* data;
|
89
92
|
TypedData_Get_Struct(self, struct matrix, &matrix_type, data);
|
90
|
-
|
91
|
-
|
92
|
-
|
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;
|
93
99
|
|
94
100
|
return DBL2NUM(data->data[m + data->m * n]);
|
95
101
|
}
|
@@ -517,6 +523,51 @@ VALUE matrix_sub_with(VALUE self, VALUE value)
|
|
517
523
|
return result;
|
518
524
|
}
|
519
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
|
+
|
520
571
|
VALUE matrix_sub_from(VALUE self, VALUE value)
|
521
572
|
{
|
522
573
|
struct matrix* A;
|
@@ -546,6 +597,24 @@ VALUE matrix_fill(VALUE self, VALUE value)
|
|
546
597
|
return self;
|
547
598
|
}
|
548
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
|
+
|
549
618
|
VALUE matrix_abs(VALUE self)
|
550
619
|
{
|
551
620
|
struct matrix* A;
|
@@ -604,4 +673,6 @@ void init_fm_matrix()
|
|
604
673
|
rb_define_method(cMatrix, "strassen", strassen, 1);
|
605
674
|
rb_define_method(cMatrix, "abs", matrix_abs, 0);
|
606
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);
|
607
678
|
}
|
data/ext/fast_matrix/vector.c
CHANGED
@@ -69,6 +69,7 @@ VALUE vector_set(VALUE self, VALUE idx, VALUE v)
|
|
69
69
|
struct vector* data;
|
70
70
|
TypedData_Get_Struct(self, struct vector, &vector_type, data);
|
71
71
|
|
72
|
+
i = (i < 0) ? data->n + i : i;
|
72
73
|
raise_check_range(i, 0, data->n);
|
73
74
|
|
74
75
|
data->data[i] = x;
|
@@ -83,7 +84,10 @@ VALUE vector_get(VALUE self, VALUE idx)
|
|
83
84
|
struct vector* data;
|
84
85
|
TypedData_Get_Struct(self, struct vector, &vector_type, data);
|
85
86
|
|
86
|
-
|
87
|
+
i = (i < 0) ? data->n + i : i;
|
88
|
+
|
89
|
+
if(i < 0 || i >= data->n)
|
90
|
+
return Qnil;
|
87
91
|
|
88
92
|
return DBL2NUM(data->data[i]);
|
89
93
|
}
|
@@ -267,7 +271,7 @@ void init_fm_vector()
|
|
267
271
|
rb_define_method(cVector, "size", c_vector_size, 0);
|
268
272
|
rb_define_method(cVector, "+", vector_add_with, 1);
|
269
273
|
rb_define_method(cVector, "+=", vector_add_from, 1);
|
270
|
-
rb_define_method(cVector, "
|
274
|
+
rb_define_method(cVector, "eql?", vector_equal, 1);
|
271
275
|
rb_define_method(cVector, "clone", vector_copy, 0);
|
272
276
|
rb_define_method(cVector, "*", vector_multiply, 1);
|
273
277
|
}
|
data/fast_matrix.gemspec
CHANGED
data/lib/fast_matrix.rb
CHANGED
data/lib/fast_matrix/version.rb
CHANGED
data/lib/matrix/constructors.rb
CHANGED
@@ -6,7 +6,6 @@ module FastMatrix
|
|
6
6
|
# Constructors as in the standard matrix
|
7
7
|
#
|
8
8
|
class Matrix
|
9
|
-
|
10
9
|
#
|
11
10
|
# Creates a matrix of size +row_count+ x +column_count+.
|
12
11
|
# It fills the values by calling the given block,
|
@@ -19,10 +18,10 @@ module FastMatrix
|
|
19
18
|
# => a 3x3 matrix with random elements
|
20
19
|
#
|
21
20
|
def self.build(row_count, column_count = row_count, &block)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
matrix
|
21
|
+
matrix = create_with_check(row_count, column_count)
|
22
|
+
raise NotImplementedError, 'Issue#17' unless block_given?
|
23
|
+
|
24
|
+
matrix.each_with_index! { |_, i, j| block.call(i, j) }
|
26
25
|
end
|
27
26
|
|
28
27
|
#
|
@@ -68,7 +67,7 @@ module FastMatrix
|
|
68
67
|
# 6
|
69
68
|
#
|
70
69
|
def self.column_vector(column)
|
71
|
-
matrix =
|
70
|
+
matrix = create_with_check(column.size, 1)
|
72
71
|
column.each_with_index { |elem, i| matrix[i, 0] = elem }
|
73
72
|
matrix
|
74
73
|
end
|
@@ -80,7 +79,7 @@ module FastMatrix
|
|
80
79
|
# => 4 5 6
|
81
80
|
#
|
82
81
|
def self.row_vector(row)
|
83
|
-
matrix =
|
82
|
+
matrix = create_with_check(1, row.size)
|
84
83
|
row.each_with_index { |elem, j| matrix[0, j] = elem }
|
85
84
|
matrix
|
86
85
|
end
|
@@ -93,8 +92,7 @@ module FastMatrix
|
|
93
92
|
# 0 0 -3
|
94
93
|
#
|
95
94
|
def self.diagonal(*values)
|
96
|
-
|
97
|
-
matrix
|
95
|
+
build(values.size, values.size) { |i, j| i == j ? values[i] : 0 }
|
98
96
|
end
|
99
97
|
|
100
98
|
#
|
@@ -105,7 +103,7 @@ module FastMatrix
|
|
105
103
|
# 0 5
|
106
104
|
#
|
107
105
|
def self.scalar(n, value)
|
108
|
-
|
106
|
+
build(n, n) { |i, j| i == j ? value : 0 }
|
109
107
|
end
|
110
108
|
|
111
109
|
#
|
@@ -122,14 +120,24 @@ module FastMatrix
|
|
122
120
|
alias I identity
|
123
121
|
end
|
124
122
|
|
123
|
+
##
|
124
|
+
# Creates a filled matrix
|
125
|
+
# Matrix.fill(42, 2, 4)
|
126
|
+
# => 42 42 42 42
|
127
|
+
# 42 42 42 42
|
128
|
+
##
|
129
|
+
def self.fill(value, row_count, column_count = row_count)
|
130
|
+
create_with_check(row_count, column_count).fill!(value)
|
131
|
+
end
|
132
|
+
|
125
133
|
#
|
126
|
-
# Creates a zero matrix +
|
127
|
-
# Matrix.zero(2)
|
128
|
-
# => 0 0
|
129
|
-
# 0 0
|
134
|
+
# Creates a zero matrix +row_count+ by +column_count+.
|
135
|
+
# Matrix.zero(2, 3)
|
136
|
+
# => 0 0 0
|
137
|
+
# 0 0 0
|
130
138
|
#
|
131
|
-
def self.zero(
|
132
|
-
|
139
|
+
def self.zero(row_count, column_count = row_count)
|
140
|
+
fill(0, row_count, column_count)
|
133
141
|
end
|
134
142
|
|
135
143
|
#
|
@@ -199,7 +207,7 @@ module FastMatrix
|
|
199
207
|
# Matrix.combine(x, y) {|a, b| a - b} # => Matrix[[5, 4], [1, 0]]
|
200
208
|
# TODO: optimize in C
|
201
209
|
def self.combine(*matrices)
|
202
|
-
return
|
210
|
+
return empty if matrices.empty?
|
203
211
|
|
204
212
|
result = convert(matrices.first)
|
205
213
|
matrices[1..matrices.size].each do |m|
|
@@ -214,6 +222,11 @@ module FastMatrix
|
|
214
222
|
class << Matrix
|
215
223
|
private
|
216
224
|
|
225
|
+
def create_with_check(row_count, column_count)
|
226
|
+
check_dimensions(row_count, column_count)
|
227
|
+
new(row_count, column_count)
|
228
|
+
end
|
229
|
+
|
217
230
|
def check_empty_matrix(row_count, column_count)
|
218
231
|
empty if row_count.zero? || column_count.zero?
|
219
232
|
end
|
@@ -237,7 +250,7 @@ module FastMatrix
|
|
237
250
|
def lines(lines, main_is_rows)
|
238
251
|
sizes = [lines.size, (lines[0] || []).size]
|
239
252
|
offset = main_is_rows ? 0 : -1
|
240
|
-
matrix =
|
253
|
+
matrix = create_with_check(sizes[offset], sizes[1 + offset])
|
241
254
|
lines.each_with_index do |second_dim, main_index|
|
242
255
|
raise IndexError if second_dim.size != sizes[1]
|
243
256
|
|
data/lib/matrix/matrix.rb
CHANGED
@@ -66,7 +66,7 @@ module FastMatrix
|
|
66
66
|
|
67
67
|
# FIXME: for compare with standard matrix
|
68
68
|
def ==(other)
|
69
|
-
|
69
|
+
return eql?(other) if other.class == Matrix
|
70
70
|
return false unless %i[row_size column_size \[\]].all? { |x| other.respond_to? x }
|
71
71
|
return false unless self.row_size == other.row_size && self.column_size == other.column_size
|
72
72
|
|
data/lib/scalar.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'fast_matrix/fast_matrix'
|
2
|
+
|
3
|
+
module FastMatrix
|
4
|
+
|
5
|
+
class Matrix
|
6
|
+
#
|
7
|
+
# The coerce method provides support for Ruby type coercion.
|
8
|
+
# This coercion mechanism is used by Ruby to handle mixed-type
|
9
|
+
# numeric operations: it is intended to find a compatible common
|
10
|
+
# type between the two operands of the operator.
|
11
|
+
# See also Numeric#coerce.
|
12
|
+
#
|
13
|
+
def coerce(other)
|
14
|
+
case other
|
15
|
+
when Numeric
|
16
|
+
return Scalar.new(other), self
|
17
|
+
else
|
18
|
+
raise TypeError, "#{self.class} can't be coerced into #{other.class}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Vector
|
24
|
+
#
|
25
|
+
# The coerce method provides support for Ruby type coercion.
|
26
|
+
# This coercion mechanism is used by Ruby to handle mixed-type
|
27
|
+
# numeric operations: it is intended to find a compatible common
|
28
|
+
# type between the two operands of the operator.
|
29
|
+
# See also Numeric#coerce.
|
30
|
+
#
|
31
|
+
def coerce(other)
|
32
|
+
case other
|
33
|
+
when Numeric
|
34
|
+
return Scalar.new(other), self
|
35
|
+
else
|
36
|
+
raise TypeError, "#{self.class} can't be coerced into #{other.class}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
class Scalar < Numeric # :nodoc:
|
44
|
+
|
45
|
+
def initialize(value)
|
46
|
+
@value = value
|
47
|
+
end
|
48
|
+
|
49
|
+
def *(other)
|
50
|
+
case other
|
51
|
+
when Vector, Matrix
|
52
|
+
other * @value
|
53
|
+
else
|
54
|
+
Scalar.new(@value * other)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/vector/vector.rb
CHANGED
@@ -3,6 +3,24 @@ require 'vector/constructors'
|
|
3
3
|
module FastMatrix
|
4
4
|
class Vector
|
5
5
|
|
6
|
+
#
|
7
|
+
# Create fast vector from standard vector
|
8
|
+
#
|
9
|
+
def self.convert(vector)
|
10
|
+
elements(vector)
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Convert to standard ruby vector.
|
15
|
+
#
|
16
|
+
def convert
|
17
|
+
::Vector.elements(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_ary
|
21
|
+
Array.new(size) { |i| self[i] }
|
22
|
+
end
|
23
|
+
|
6
24
|
def each_with_index
|
7
25
|
(0...size).each do |i|
|
8
26
|
yield self[i], i
|
@@ -16,5 +34,17 @@ module FastMatrix
|
|
16
34
|
self
|
17
35
|
end
|
18
36
|
|
37
|
+
# FIXME: for compare with standard vector
|
38
|
+
def ==(other)
|
39
|
+
return eql?(other) if other.class == Vector
|
40
|
+
return false unless %i[size \[\]].all? { |x| other.respond_to? x }
|
41
|
+
return false unless self.size == other.size
|
42
|
+
|
43
|
+
result = true
|
44
|
+
each_with_index do |elem, i|
|
45
|
+
result &&= elem == other[i].to_f
|
46
|
+
end
|
47
|
+
result
|
48
|
+
end
|
19
49
|
end
|
20
50
|
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.
|
4
|
+
version: 0.1.6
|
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-
|
11
|
+
date: 2019-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
description: Ruby wrapper around C matrices implementation
|
70
84
|
email:
|
71
85
|
- poganesyan@sfedu.ru
|
@@ -100,6 +114,7 @@ files:
|
|
100
114
|
- lib/fast_matrix/version.rb
|
101
115
|
- lib/matrix/constructors.rb
|
102
116
|
- lib/matrix/matrix.rb
|
117
|
+
- lib/scalar.rb
|
103
118
|
- lib/vector/constructors.rb
|
104
119
|
- lib/vector/vector.rb
|
105
120
|
homepage: https://github.com/mmcs-ruby/fast_matrix
|