nmatrix_extras 0.0.4.1 → 0.0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,6 +24,5 @@ require "nmatrix_extras/version"
24
24
  require "nmatrix_extras/nmatrix"
25
25
 
26
26
  class NMatrix
27
- include Enumerable
28
27
  include NMatrixExtras
29
28
  end
@@ -24,132 +24,175 @@ require 'nmatrix'
24
24
 
25
25
  module NMatrixExtras
26
26
 
27
- ##
28
- # Successively yields submatrices at each coordinate along a specified dimension. Each submatrix will have the same number of dimensions as the matrix being iterated,
29
- # but with the specified dimension's size equal to 1.
30
- #
31
- # @param [Integer] dim the dimension being iterated over.
32
- #
33
- def each_along_dim(dim=0)
34
- dims = shape
35
- shape.each_index { |i| dims[i] = 0...(shape[i]) unless i == dim }
36
- 0.upto(shape[dim]-1) do |i|
37
- dims[dim] = i
38
- yield self[*dims]
39
- end
40
- end
41
-
42
- ##
43
- # Reduces an NMatrix using a supplied block over a specified dimension. The block should behave the same way as for Enumerable#reduce.
44
- #
45
- # @param [Integer] dim the dimension being reduced
46
- # @param [Numeric] initial the initial value for the reduction (i.e. the usual parameter to Enumerable#reduce). Note that unlike Enumerable#reduce, if not specified, this will default to 0.0.
47
- #
48
- # @return [NMatrix] an NMatrix with the same number of dimensions as the input, but with the input dimension now having size 1.
49
- # Each element is the result of the reduction at that position along the specified dimension.
50
- #
51
- def reduce_along_dim(dim=0, initial=0.0, &bl)
52
-
53
- if dim > shape.size then
54
- raise ArgumentError, "Requested dimension does not exist. Requested: #{dim}, shape: #{shape}"
55
- end
56
-
57
- new_shape = shape
58
- new_shape[dim] = 1
59
-
60
- acc = NMatrix.new(new_shape, initial)
61
-
62
- each_along_dim(dim) do |sub_mat|
63
- acc = bl.call(acc, sub_mat)
64
- end
65
-
66
- acc
67
-
68
- end
69
-
70
- ##
71
- # Calculates the mean along the specified dimension.
72
- #
73
- # @see #reduce_along_dim
74
- #
75
- def mean(dim=0)
76
- reduce_along_dim(dim, 0.0) do |mean, sub_mat|
77
- mean + sub_mat/shape[dim]
78
- end
79
- end
80
-
81
- ##
82
- # Calculates the minimum along the specified dimension.
83
- #
84
- # @see #reduce_along_dim
85
- #
86
- def min(dim=0)
87
- reduce_along_dim(dim, Float::MAX) do |min, sub_mat|
88
- min * (min <= sub_mat) + ((min)*0.0 + (min > sub_mat)) * sub_mat
89
- end
90
- end
91
-
92
- ##
93
- # Calculates the maximum along the specified dimension.
94
- #
95
- # @see #reduce_along_dim
96
- #
97
- def max(dim=0)
98
- reduce_along_dim(dim, -1.0*Float::MAX) do |max, sub_mat|
99
- max * (max >= sub_mat) + ((max)*0.0 + (max < sub_mat)) * sub_mat
100
- end
101
- end
102
-
103
- ##
104
- # Calculates the median along the specified dimension.
105
- #
106
- # Not yet implemented.
107
- #
108
- # @see #reduce_along_dim
109
- #
110
- def median(dim=0)
111
- raise NotImplementedError, "median not yet implemented"
112
- end
113
-
114
- ##
115
- # Calculates the sample variance along the specified dimension.
116
- #
117
- # @see #reduce_along_dim
118
- #
119
- def variance(dim=0)
120
- m = mean(dim)
121
- reduce_along_dim(dim, 0.0) do |var, sub_mat|
122
- var + (m - sub_mat)*(m - sub_mat)/(shape[dim]-1)
123
- end
124
- end
125
-
126
- ##
127
- # Converts an nmatrix with a single element (but any number of dimensions) to a float.
128
- #
129
- # Raises an IndexError if the matrix does not have just a single element.
130
- #
131
- def to_f
132
- raise IndexError, 'to_f only valid for matrices with a single element' unless shape.all? { |e| e == 1 }
133
- self[*Array.new(shape.size, 0)]
134
- end
135
-
136
- ##
137
- # See Enumerable#map
138
- #
139
- def map(&bl)
140
- cp = self.dup
141
- cp.map! &bl
142
- cp
143
- end
144
-
145
- ##
146
- # Maps in place.
147
- # See #map
148
- #
149
- def map!
150
- self.each_stored_with_indices do |e, *i|
151
- self[*i] = (yield e)
152
- end
153
- end
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
@@ -1,3 +1,3 @@
1
1
  module NmatrixExtras
2
- VERSION = "0.0.4.1"
2
+ VERSION = "0.0.4.2"
3
3
  end
@@ -25,95 +25,88 @@ require 'nmatrix_extras'
25
25
 
26
26
  describe NMatrix do
27
27
 
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
- pending
37
- end
38
-
39
- it "should create an nmatrix of zeros with dimensions and type the same as its argument" do
40
- pending
41
- end
42
-
43
- end
44
-
45
- it "should calculate the mean along the specified dimension" do
46
- @nm_1d.mean.should eq N[2.2]
47
- @nm_2d.mean.should eq N[[1.0,2.0]]
48
- end
49
-
50
- it "should calculate the minimum along the specified dimension" do
51
- @nm_1d.min.should eq N[0.0]
52
- @nm_2d.min.should eq N[[0.0, 1.0]]
53
- @nm_2d.min(1).should eq N[[0.0], [2.0]]
54
-
55
- end
56
-
57
- it "should calculate the maximum along the specified dimension" do
58
- @nm_1d.max.should eq N[5.0]
59
- @nm_2d.max.should eq N[[2.0, 3.0]]
60
- end
61
-
62
- it "should calculate the median along the specified dimension" do
63
- @nm_1d.median.should eq N[2.0]
64
- @nm_2d.median(1).should eq N[[0.5], [2.5]]
65
- end
66
-
67
- it "should calculate the variance along the specified dimension" do
68
- @nm_1d.variance.should eq N[3.7]
69
- @nm_2d.variance(1).should eq N[[0.5], [0.5]]
70
- end
71
-
72
- it "should calculate the sum along the specified dimension" do
73
- pending
74
- end
75
-
76
- it "should calculate the standard deviation along the specified dimension" do
77
- pending
78
- end
79
-
80
- it "should calculate the correlation coefficient with another same-sized nmatrix" do
81
- pending
82
- end
83
-
84
- it "should calculate the covariance with another same-sized nmatrix" do
85
- pending
86
- end
87
-
88
- it "should raise an ArgumentError when any invalid dimension is provided" do
89
- pending
90
- end
91
-
92
- it "should convert to float if it contains only a single element" do
93
- N[4.0].to_f.should eq 4.0
94
- N[[[[4.0]]]].to_f.should eq 4.0
95
- end
96
-
97
- it "should raise an index error if it contains more than a single element" do
98
- expect { @nm_1d.to_f }.to raise_error(IndexError)
99
- end
100
-
101
- it "should map a block to all elements" do
102
- @nm_1d.map { |e| e ** 2 }.should eq N[25.0,0.0,1.0,4.0,9.0]
103
- @nm_2d.map { |e| e ** 2 }.should eq N[[0.0,1.0],[4.0,9.0]]
104
- end
105
-
106
- it "should map! a block to all elements in place" do
107
- fct = Proc.new { |e| e ** 2 }
108
- expected1 = @nm_1d.map &fct
109
- expected2 = @nm_2d.map &fct
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.1
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-05-02 00:00:00.000000000 Z
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: 2.0.3
117
+ rubygems_version: 1.8.25
108
118
  signing_key:
109
- specification_version: 4
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=