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.
@@ -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=