nmatrix_extras 0.0.4.1 → 0.0.4.2
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.
- data/lib/nmatrix_extras.rb +0 -1
- data/lib/nmatrix_extras/nmatrix.rb +170 -127
- data/lib/nmatrix_extras/version.rb +1 -1
- data/spec/nmatrix_extras_spec.rb +82 -89
- metadata +15 -5
- checksums.yaml +0 -15
data/lib/nmatrix_extras.rb
CHANGED
@@ -24,132 +24,175 @@ require 'nmatrix'
|
|
24
24
|
|
25
25
|
module NMatrixExtras
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
27
|
+
def self.included(base)
|
28
|
+
base.extend(ClassMethods)
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Successively yields submatrices at each coordinate along a specified dimension. Each submatrix will have the same number of dimensions as the matrix being iterated,
|
33
|
+
# but with the specified dimension's size equal to 1.
|
34
|
+
#
|
35
|
+
# @param [Integer] dim the dimension being iterated over.
|
36
|
+
#
|
37
|
+
def each_along_dim(dim=0)
|
38
|
+
dims = shape
|
39
|
+
shape.each_index { |i| dims[i] = 0...(shape[i]) unless i == dim }
|
40
|
+
0.upto(shape[dim]-1) do |i|
|
41
|
+
dims[dim] = i
|
42
|
+
yield self[*dims]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Reduces an NMatrix using a supplied block over a specified dimension. The block should behave the same way as for Enumerable#reduce.
|
48
|
+
#
|
49
|
+
# @param [Integer] dim the dimension being reduced
|
50
|
+
# @param [Numeric] initial the initial value for the reduction (i.e. the usual parameter to Enumerable#reduce). Supply nil or do not supply
|
51
|
+
# this argument to have it follow the usual Enumerable#reduce behavior of using the first element as the initial value.
|
52
|
+
# @return [NMatrix] an NMatrix with the same number of dimensions as the input, but with the input dimension now having size 1.
|
53
|
+
# Each element is the result of the reduction at that position along the specified dimension.
|
54
|
+
#
|
55
|
+
def reduce_along_dim(dim=0, initial=nil, &bl)
|
56
|
+
|
57
|
+
if dim > shape.size then
|
58
|
+
raise ArgumentError, "Requested dimension does not exist. Requested: #{dim}, shape: #{shape}"
|
59
|
+
end
|
60
|
+
|
61
|
+
new_shape = shape
|
62
|
+
new_shape[dim] = 1
|
63
|
+
|
64
|
+
first_as_acc = false
|
65
|
+
|
66
|
+
if initial then
|
67
|
+
acc = NMatrix.new(new_shape, initial)
|
68
|
+
else
|
69
|
+
each_along_dim(dim) do |sub_mat|
|
70
|
+
acc = sub_mat
|
71
|
+
break
|
72
|
+
end
|
73
|
+
first_as_acc = true
|
74
|
+
end
|
75
|
+
|
76
|
+
each_along_dim(dim) do |sub_mat|
|
77
|
+
if first_as_acc then
|
78
|
+
first_as_acc = false
|
79
|
+
next
|
80
|
+
end
|
81
|
+
acc = bl.call(acc, sub_mat)
|
82
|
+
end
|
83
|
+
|
84
|
+
acc
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
alias_method :inject_along_dim, :reduce_along_dim
|
89
|
+
|
90
|
+
##
|
91
|
+
# Calculates the mean along the specified dimension.
|
92
|
+
#
|
93
|
+
# @see #reduce_along_dim
|
94
|
+
#
|
95
|
+
def mean(dim=0)
|
96
|
+
reduce_along_dim(dim, 0.0) do |mean, sub_mat|
|
97
|
+
mean + sub_mat/shape[dim]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Calculates the sum along the specified dimension.
|
103
|
+
#
|
104
|
+
# @see #reduce_along_dim
|
105
|
+
def sum(dim=0)
|
106
|
+
reduce_along_dim(dim, 0.0) do |sum, sub_mat|
|
107
|
+
sum + sub_mat
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
##
|
113
|
+
# Calculates the minimum along the specified dimension.
|
114
|
+
#
|
115
|
+
# @see #reduce_along_dim
|
116
|
+
#
|
117
|
+
def min(dim=0)
|
118
|
+
reduce_along_dim(dim, Float::MAX) do |min, sub_mat|
|
119
|
+
min * (min <= sub_mat) + ((min)*0.0 + (min > sub_mat)) * sub_mat
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Calculates the maximum along the specified dimension.
|
125
|
+
#
|
126
|
+
# @see #reduce_along_dim
|
127
|
+
#
|
128
|
+
def max(dim=0)
|
129
|
+
reduce_along_dim(dim, -1.0*Float::MAX) do |max, sub_mat|
|
130
|
+
max * (max >= sub_mat) + ((max)*0.0 + (max < sub_mat)) * sub_mat
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
##
|
136
|
+
# Calculates the sample variance along the specified dimension.
|
137
|
+
#
|
138
|
+
# @see #reduce_along_dim
|
139
|
+
#
|
140
|
+
def variance(dim=0)
|
141
|
+
m = mean(dim)
|
142
|
+
reduce_along_dim(dim, 0.0) do |var, sub_mat|
|
143
|
+
var + (m - sub_mat)*(m - sub_mat)/(shape[dim]-1)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Calculates the sample standard deviation along the specified dimension.
|
149
|
+
#
|
150
|
+
# @see #reduce_along_dim
|
151
|
+
#
|
152
|
+
def std(dim=0)
|
153
|
+
variance(dim).map! { |e| Math.sqrt(e) }
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Converts an nmatrix with a single element (but any number of dimensions) to a float.
|
158
|
+
#
|
159
|
+
# Raises an IndexError if the matrix does not have just a single element.
|
160
|
+
#
|
161
|
+
def to_f
|
162
|
+
raise IndexError, 'to_f only valid for matrices with a single element' unless shape.all? { |e| e == 1 }
|
163
|
+
self[*Array.new(shape.size, 0)]
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# See Enumerable#map
|
168
|
+
#
|
169
|
+
def map(&bl)
|
170
|
+
cp = self.dup
|
171
|
+
cp.map! &bl
|
172
|
+
cp
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Maps in place.
|
177
|
+
# See #map
|
178
|
+
#
|
179
|
+
def map!
|
180
|
+
self.each_stored_with_indices do |e, *i|
|
181
|
+
self[*i] = (yield e)
|
182
|
+
end
|
183
|
+
self
|
184
|
+
end
|
185
|
+
|
186
|
+
module ClassMethods
|
187
|
+
|
188
|
+
def ones_like(nm)
|
189
|
+
NMatrix.ones(nm.shape, nm.dtype)
|
190
|
+
end
|
191
|
+
|
192
|
+
def zeros_like(nm)
|
193
|
+
NMatrix.zeros(nm.stype, nm.shape, nm.dtype)
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
154
197
|
|
155
198
|
end
|
data/spec/nmatrix_extras_spec.rb
CHANGED
@@ -25,95 +25,88 @@ require 'nmatrix_extras'
|
|
25
25
|
|
26
26
|
describe NMatrix do
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
@nm_1d.map! &fct
|
111
|
-
@nm_1d.should eq expected1
|
112
|
-
@nm_2d.map! &fct
|
113
|
-
@nm_2d.should eq expected2
|
114
|
-
end
|
115
|
-
|
116
|
-
|
28
|
+
before :each do
|
29
|
+
@nm_1d = N[5.0,0.0,1.0,2.0,3.0]
|
30
|
+
@nm_2d = N[[0.0,1.0],[2.0,3.0]]
|
31
|
+
end
|
32
|
+
|
33
|
+
context "_like constructors" do
|
34
|
+
|
35
|
+
it "should create an nmatrix of ones with dimensions and type the same as its argument" do
|
36
|
+
NMatrix.ones_like(@nm_1d).should eq N[1.0, 1.0, 1.0, 1.0, 1.0]
|
37
|
+
NMatrix.ones_like(@nm_2d).should eq N[[1.0, 1.0], [1.0, 1.0]]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should create an nmatrix of zeros with dimensions and type the same as its argument" do
|
41
|
+
NMatrix.zeros_like(@nm_1d).should eq N[0.0, 0.0, 0.0, 0.0, 0.0]
|
42
|
+
NMatrix.zeros_like(@nm_2d).should eq N[[0.0, 0.0], [0.0, 0.0]]
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
it "behaves like Enumerable#reduce with no argument to reduce" do
|
48
|
+
@nm_1d.reduce_along_dim(0) { |acc, el| acc + el }.to_f.should eq 11
|
49
|
+
@nm_2d.reduce_along_dim(1) { |acc, el| acc + el }.should eq N[[1, 5]]
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should calculate the mean along the specified dimension" do
|
53
|
+
@nm_1d.mean.should eq N[2.2]
|
54
|
+
@nm_2d.mean.should eq N[[1.0,2.0]]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should calculate the minimum along the specified dimension" do
|
58
|
+
@nm_1d.min.should eq N[0.0]
|
59
|
+
@nm_2d.min.should eq N[[0.0, 1.0]]
|
60
|
+
@nm_2d.min(1).should eq N[[0.0], [2.0]]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should calculate the maximum along the specified dimension" do
|
64
|
+
@nm_1d.max.should eq N[5.0]
|
65
|
+
@nm_2d.max.should eq N[[2.0, 3.0]]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should calculate the variance along the specified dimension" do
|
69
|
+
@nm_1d.variance.should eq N[3.7]
|
70
|
+
@nm_2d.variance(1).should eq N[[0.5], [0.5]]
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should calculate the sum along the specified dimension" do
|
74
|
+
@nm_1d.sum.should eq N[11]
|
75
|
+
@nm_2d.sum.should eq N[[2], [4]]
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should calculate the standard deviation along the specified dimension" do
|
79
|
+
@nm_1d.std.should eq N[Math.sqrt(3.7)]
|
80
|
+
@nm_2d.std(1).should eq N[[Math.sqrt(0.5)], [Math.sqrt(0.5)]]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise an ArgumentError when any invalid dimension is provided" do
|
84
|
+
expect { @nm_1d.mean(3) }.to raise_exception(ArgumentError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should convert to float if it contains only a single element" do
|
88
|
+
N[4.0].to_f.should eq 4.0
|
89
|
+
N[[[[4.0]]]].to_f.should eq 4.0
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should raise an index error if it contains more than a single element" do
|
93
|
+
expect { @nm_1d.to_f }.to raise_error(IndexError)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should map a block to all elements" do
|
97
|
+
@nm_1d.map { |e| e ** 2 }.should eq N[25.0,0.0,1.0,4.0,9.0]
|
98
|
+
@nm_2d.map { |e| e ** 2 }.should eq N[[0.0,1.0],[4.0,9.0]]
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should map! a block to all elements in place" do
|
102
|
+
fct = Proc.new { |e| e ** 2 }
|
103
|
+
expected1 = @nm_1d.map &fct
|
104
|
+
expected2 = @nm_2d.map &fct
|
105
|
+
@nm_1d.map! &fct
|
106
|
+
@nm_1d.should eq expected1
|
107
|
+
@nm_2d.map! &fct
|
108
|
+
@nm_2d.should eq expected2
|
109
|
+
end
|
117
110
|
|
118
111
|
end
|
119
112
|
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nmatrix_extras
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.4.
|
4
|
+
version: 0.0.4.2
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Colin J. Fuller
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-
|
12
|
+
date: 2013-06-03 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -27,6 +30,7 @@ dependencies:
|
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rake
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ! '>='
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,6 +46,7 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: rspec
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ! '>='
|
46
52
|
- !ruby/object:Gem::Version
|
@@ -48,6 +54,7 @@ dependencies:
|
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ! '>='
|
53
60
|
- !ruby/object:Gem::Version
|
@@ -55,6 +62,7 @@ dependencies:
|
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
63
|
name: nmatrix
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
67
|
- - ! '>='
|
60
68
|
- !ruby/object:Gem::Version
|
@@ -62,6 +70,7 @@ dependencies:
|
|
62
70
|
type: :runtime
|
63
71
|
prerelease: false
|
64
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
65
74
|
requirements:
|
66
75
|
- - ! '>='
|
67
76
|
- !ruby/object:Gem::Version
|
@@ -87,26 +96,27 @@ files:
|
|
87
96
|
homepage: ''
|
88
97
|
licenses:
|
89
98
|
- MIT
|
90
|
-
metadata: {}
|
91
99
|
post_install_message:
|
92
100
|
rdoc_options: []
|
93
101
|
require_paths:
|
94
102
|
- lib
|
95
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
96
105
|
requirements:
|
97
106
|
- - ! '>='
|
98
107
|
- !ruby/object:Gem::Version
|
99
108
|
version: '0'
|
100
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
101
111
|
requirements:
|
102
112
|
- - ! '>='
|
103
113
|
- !ruby/object:Gem::Version
|
104
114
|
version: '0'
|
105
115
|
requirements: []
|
106
116
|
rubyforge_project:
|
107
|
-
rubygems_version:
|
117
|
+
rubygems_version: 1.8.25
|
108
118
|
signing_key:
|
109
|
-
specification_version:
|
119
|
+
specification_version: 3
|
110
120
|
summary: Adds a number of basic functions present in numpy to nmatrix and adds mapping
|
111
121
|
and reduction.
|
112
122
|
test_files:
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
YWQ1N2MxY2ExZTI5YTg0MzNmMTI5M2FmY2NmYjI4ZDRmZDZlMmVhYw==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MGQ2NjRiYmY4ZDg0YzE2YzFhYmIxMzU5Yzc4YWRjMjk3NGViZDg0Mg==
|
7
|
-
!binary "U0hBNTEy":
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
NzIwMWY3MzRiMTUzMzdjNDQwMDkwMmIzZjEzNTQxMDU1NWU3ZTc1ZWYzODk4
|
10
|
-
ZTNiNTI5YzM4YWRlNDAyYWFjYTg3ZmVjN2QzODViM2YxNzkwY2RkNGQ0NWRl
|
11
|
-
ZGY5YTcyMDdkMDdhMWZmMTY0YTk5MGIwZjVjMDA3ODRlMTU0ZmM=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjZkZmYzYTczYTI5YjdlNmYwYTU1ODE4ZTMwZTkwZDg2MzNiOTdkNGUxYzQx
|
14
|
-
YzljZDI1MjRmZjZkODE0NmMyZTM5M2ZjNTkxZmFmNGU0MzMxYzhiYWU1MzMy
|
15
|
-
OWFkZjYyMDAwMGE4NWM2OGFjYjZjZjZmYmUzMmZkMjFlZDQ0NTg=
|