numru-misc 0.1.1

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.
@@ -0,0 +1,180 @@
1
+ =begin
2
+ =module NumRu::Misc::MD_Iterators
3
+
4
+ A Mixin.
5
+ To be included in a class with multi-dimension indexing support
6
+ (such as NArray).
7
+
8
+ ==Index
9
+
10
+ * ((<each_subary_at_dims>))
11
+ * ((<each_subary_at_dims_with_index>))
12
+
13
+ ==Methods
14
+ ---each_subary_at_dims( *dims )
15
+
16
+ Iterator for each sub-array (not each element) specified by dimensions.
17
+
18
+ ARGUMENT
19
+ * ((|dims|)) (integers) : specifies subsets at dimensions
20
+ specified here with the beginning-to-end selection.
21
+ For example, [0, 1] to specify the first 2 dimensions
22
+ (subsets will be 2D then), and [2] to specify the 3rd
23
+ dimension (subsets will be 1D). Duplication has no effect,
24
+ so [0,0] and [0] are the same. Also, its order has no effect.
25
+ See EXAMPLE below for more.
26
+
27
+ RETURN VALUE
28
+ * self
29
+
30
+ POSSIBLE EXCEPTIONS
31
+ * exception is raised if ( dims.min<0 || dims.max>=self.rank ).
32
+
33
+ EXAMPLE
34
+
35
+ * Suppose that you want to do something with 2D sub-arrays in a
36
+ multi-dimension NArray. First, you include this module as follows:
37
+
38
+ require "narray"
39
+ class NArray
40
+ include NumRu::Misc::MD_Iterators
41
+ end
42
+
43
+ And prepare the array if you have not (here, it is 4D):
44
+
45
+ na = NArray.int(10,2,5,2).indgen!
46
+
47
+ Then you do the job like this:
48
+
49
+ na.each_subary_at_dims(0,2){ |sub|
50
+ ... # do whatever with sub
51
+ }
52
+
53
+ This is equivalent to the following:
54
+
55
+ (0...na.shape[3]).each{|j|
56
+ (0...na.shape[1]).each{|i|
57
+ sub = na[0..-1, i, 0..-1, j]
58
+ ... # do whatever with sub
59
+ }
60
+ }
61
+
62
+ Note that the loop must be nested 3 times when (('na')) is a 5D array,
63
+ if the latter approach is used. On the other hand, it will still
64
+ require the same single loop with the former.
65
+
66
+ ---each_subary_at_dims_with_index( *dims )
67
+ Like ((<each_subary_at_dims>)) but the block takes two arguments:
68
+ subset and the subset specifier (index).
69
+
70
+ EXAMPLE
71
+ * Suppose the example above in ((<each_subary_at_dims>)) (EXAMPLE).
72
+ And suppose that you want to overwrite (('na')) with the result
73
+ you get. You can do it like this:
74
+
75
+ na.each_subary_at_dims_with_index(0,2){ |sub,idx|
76
+ result = (sub + 10) / 2
77
+ na[*idx] = result
78
+ }
79
+
80
+ Here, (('idx')) is an Array to be fed in the []= or [] methods
81
+ with asterisk (ungrouping).
82
+ =end
83
+
84
+ module NumRu
85
+ module Misc
86
+ module MD_Iterators
87
+
88
+ def each_subary_at_dims( *dims )
89
+ if dims.min<0 || dims.max>=rank
90
+ raise ArguemntError,"Invalid dims #{dims.inspect} for #{rank}D array"
91
+ end
92
+
93
+ loopdims = Array.new
94
+ sh = Array.new
95
+ len = 1
96
+ (0...rank).each{|i|
97
+ if !dims.include?(i)
98
+ loopdims.push(i)
99
+ sh.push(shape[i])
100
+ len *= shape[i]
101
+ end
102
+ }
103
+ if loopdims.length == 0
104
+ yield(self)
105
+ return self
106
+ end
107
+ cs = [1]
108
+ (1...sh.length).each{|i| cs[i] = sh[i-1]*cs[i-1]}
109
+ idx = Array.new
110
+ all = 0..-1
111
+ for i in 0...len do
112
+ loopdims.each_with_index{|d,j| idx[d] = ( (i/cs[j])%sh[j] )}
113
+ dims.each{|d| idx[d] = all}
114
+ sub = self[ *idx ]
115
+ yield(sub)
116
+ end
117
+ self
118
+ end
119
+
120
+ def each_subary_at_dims_with_index( *dims )
121
+ if dims.min<0 || dims.max>=rank
122
+ raise ArguemntError,"Invalid dims #{dims.inspect} for #{rank}D array"
123
+ end
124
+
125
+ loopdims = Array.new
126
+ sh = Array.new
127
+ len = 1
128
+ (0...rank).each{|i|
129
+ if !dims.include?(i)
130
+ loopdims.push(i)
131
+ sh.push(shape[i])
132
+ len *= shape[i]
133
+ end
134
+ }
135
+ if loopdims.length == 0
136
+ yield(self, false)
137
+ return self
138
+ end
139
+ cs = [1]
140
+ (1...sh.length).each{|i| cs[i] = sh[i-1]*cs[i-1]}
141
+ idx = Array.new
142
+ all = 0..-1
143
+ for i in 0...len do
144
+ loopdims.each_with_index{|d,j| idx[d] = ( (i/cs[j])%sh[j] )}
145
+ dims.each{|d| idx[d] = all}
146
+ sub = self[ *idx ]
147
+ yield(sub, idx)
148
+ end
149
+ self
150
+ end
151
+
152
+ end
153
+ end
154
+ end
155
+
156
+ ##################################
157
+
158
+ if __FILE__ == $0
159
+ require "narray"
160
+ class NArray
161
+ include NumRu::Misc::MD_Iterators
162
+ end
163
+ na = NArray.int(10,2,2,2).indgen!
164
+ puts "** test A **"
165
+ na.each_subary_at_dims(0,1){ |sub|
166
+ p sub
167
+ }
168
+ puts "** test B **"
169
+ na.each_subary_at_dims(0,3){ |sub|
170
+ p sub
171
+ }
172
+ puts "** test C **"
173
+ na.each_subary_at_dims(2,1,0){ |sub| # same as (0,1,2)
174
+ p sub
175
+ }
176
+ puts "** test C **"
177
+ na.each_subary_at_dims(0,1,2,3){ |sub|
178
+ p sub
179
+ }
180
+ end
@@ -0,0 +1,196 @@
1
+ =begin
2
+ = module NumRu::Misc
3
+
4
+ == Overview
5
+
6
+ Miscellaneous functions and classes to facilitate programming.
7
+
8
+ == Index
9
+
10
+ CLASSES
11
+
12
+ * ((<class KeywordOpt|URL:keywordopt.html>))
13
+ to support keyward arguments with default values.
14
+ * ((<class NArray (enhancement of NArray made by M Tanaka)|URL:narray_ext.html>))
15
+
16
+ MODULES
17
+
18
+ * ((<module MD_Iterators|URL:md_iterators.html>)) A Mixin for classes with
19
+ multi-dimension indexing support (such as NArray).
20
+ * ((<module EMath|URL:emath.html>))
21
+ To be included instead of the Math predefined module (or NMath in NArray).
22
+ Unlike Math and NMath, EMath handles unknown classes by calling its
23
+ native instance method (assuming the same name).
24
+
25
+
26
+ MODULE FUNCTIONS
27
+
28
+ * ((<check_shape_consistency>))
29
+
30
+ == Module functions
31
+ ---check_shape_consistency(cshapes, *args)
32
+ Check the consistency of array shapes (multi-dim such as NArray).
33
+ Exception is raised if inconsistent.
34
+
35
+ ARGUMENTS
36
+ * cshapes (String) : description of the shapes of the args.
37
+ Delimited by one-or-more spaces between arrays,
38
+ and the shape of each array is delimited by a comma. The lengths are
39
+ expressed with string names as identifiers (in that case, length
40
+ values are unquestioned) or specified as positive integers.
41
+ Use '..' or '...' for repetition of the last shape.
42
+ See EXAMPLES below.
43
+
44
+ * args (multi-dim arrays such as NArray): arrays to be checked
45
+
46
+ RETURN VALUE
47
+ * nil
48
+
49
+ POSSIBLE EXCEPTIONS
50
+ * exception is raised if cshapes and args are inconsistent:
51
+
52
+ * RuntimeError, if the arrays do not have shapes specified by cshapes.
53
+
54
+ * ArgeumentError, if the number of args are inconsistent with cshapes.
55
+ This is likely a coding error of the user.
56
+
57
+ EXAMPLES
58
+
59
+ * to check whether three arrays u, v, and w are shaped as
60
+ u[nx], v[ny], and w[nx,ny], where nx and ny are any integer:
61
+
62
+ NumRu::Misc.check_shape_consistency('nx ny nx,ny',u,v,w)
63
+
64
+ Or equivalently,
65
+
66
+ NumRu::Misc.check_shape_consistency('m n m,n',u,v,w)
67
+
68
+ because actual strings does not matter.
69
+
70
+ * To specify fixed lengths, use integers instead of names:
71
+
72
+ NumRu::Misc.check_shape_consistency('4 n 4,n',u,v,w)
73
+
74
+ In this case, u,v,w must have shapes [4], [ny], and [4,ny],
75
+ where ny is any length.
76
+
77
+ * Use '..' or '...' to repeat the same shape:
78
+
79
+ NumRu::Misc.check_shape_consistency('nx,ny ...',u,v,w)
80
+
81
+ This ensures that u, v, and w are 2D arrays with the same shape.
82
+ Note: '..' and '...' are the same, so you can use whichever you like.
83
+
84
+ =end
85
+
86
+ require "narray"
87
+
88
+ module NumRu
89
+ module Misc
90
+ module_function
91
+
92
+ def check_shape_consistency(cshapes, *args)
93
+ ranks = Array.new
94
+ elm2idx = Hash.new
95
+ spl = cshapes.split(' +')
96
+ if spl.length >= 2 && /^\.\.\.?$/ =~ spl[-1] # '..' or '...'
97
+ ((spl.length-1)...args.length).each{|i|
98
+ spl[i]=spl[i-1]
99
+ }
100
+ end
101
+ if spl.length != args.length
102
+ raise ArgumentError,"# of the argument (#{args.length}) is inconsistent with the 1st arg '#{cshapes}'"
103
+ end
104
+ spl.each_with_index{|csh,i|
105
+ sh = csh.split(',')
106
+ ranks.push( sh.length )
107
+ sh.each_with_index{|tag,j|
108
+ elm2idx[tag] = Array.new if !elm2idx[tag]
109
+ elm2idx[tag].push([i,j])
110
+ }
111
+ }
112
+ ranks.each_with_index{|len,i|
113
+ if args[i].rank != len
114
+ raise "(#{i+1}th arg) unexepected rank #{args[i].rank} for #{len}"
115
+ end
116
+ }
117
+ elm2idx.each{|tag,ary|
118
+ if tag.to_i > 0 # numeric (positive integer)
119
+ size = tag.to_i
120
+ start = 0
121
+ else # alphabet
122
+ size = args[ary[0][0]].shape[ary[0][1]]
123
+ start = 1
124
+ end
125
+ (start...ary.length).each{|i|
126
+ if args[ary[i][0]].shape[ary[i][1]] != size
127
+ if start == 0
128
+ raise "length of dim #{ary[i][1]} of #{ary[i][0]+1}th "+
129
+ "arg is unexpected " +
130
+ "(#{args[ary[i][0]].shape[ary[i][1]]} for #{size})"
131
+ else
132
+ raise "Dimension lengths inconsistent between "+
133
+ "dim #{ary[0][1]} of #{ary[0][0]+1}th arg and " +
134
+ "dim #{ary[i][1]} of #{ary[i][0]+1}th arg"
135
+ end
136
+ end
137
+ }
138
+ }
139
+ nil
140
+ end
141
+
142
+ end
143
+ end
144
+
145
+ if __FILE__ == $0
146
+ include NumRu
147
+
148
+ puts '* test A *'
149
+ u = NArray.float(3)
150
+ v = NArray.float(5)
151
+ w = NArray.float(3,5)
152
+ Misc.check_shape_consistency('nx ny nx,ny',u,v,w)
153
+ puts ' OK'
154
+ Misc.check_shape_consistency('3 ny 3,ny',u,v,w)
155
+ puts ' OK'
156
+ begin
157
+ Misc.check_shape_consistency('6 ny 6,ny',u,v,w)
158
+ rescue
159
+ puts " exception raised as expected\n"+$!
160
+ puts ' OK'
161
+ end
162
+
163
+ puts '* test B *'
164
+ Misc.check_shape_consistency('nx,ny ...',w,w,w,w)
165
+ puts ' OK'
166
+
167
+ puts '* test C *'
168
+ begin
169
+ u = NArray.float(4)
170
+ v = NArray.float(5)
171
+ w = NArray.float(3,5)
172
+ Misc.check_shape_consistency('nx ny nx,ny',u,v,w)
173
+ rescue
174
+ puts " exception raised as expected\n"+$!
175
+ puts ' OK'
176
+ end
177
+
178
+ puts '* test D *'
179
+ begin
180
+ u = NArray.float(3,5)
181
+ v = NArray.float(5)
182
+ w = NArray.float(3,5)
183
+ Misc.check_shape_consistency('nx ny nx,ny',u,v,w)
184
+ rescue
185
+ puts " exception raised as expected\n"+$!
186
+ puts ' OK'
187
+ end
188
+
189
+ puts '* test E *'
190
+ u = NArray.float(3,5,7)
191
+ v = NArray.float(5)
192
+ w = NArray.float(3,5)
193
+ 1000.times{ Misc.check_shape_consistency('nx,ny,nz ny nx,ny',u,v,w) }
194
+ puts ' OK'
195
+
196
+ end
@@ -0,0 +1,6 @@
1
+ #!/bin/csh
2
+ rd2 lib/numru/misc/misc.rb >! doc/misc.html
3
+ \cp -pf doc/misc.html doc/index.html
4
+ rd2 lib/numru/misc/keywordopt.rb >! doc/keywordopt.html
5
+ rd2 lib/numru/misc/md_iterators.rb >! doc/md_iterators.html
6
+ rd2 lib/numru/misc/emath.rb >! doc/emath.html
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: numru-misc
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Takeshi Horinouchi
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-02-20 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: narray
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: Miscellaneous functions and classes to help Ruby programming. To be used in other NumRu libraries.
36
+ email:
37
+ - eriko@gfd-dennou.org
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - Rakefile
46
+ - install.rb
47
+ - LICENSE.txt
48
+ - ChangeLog
49
+ - makedoc.csh
50
+ - lib/numru/misc/keywordopt.rb
51
+ - lib/numru/misc/md_iterators.rb
52
+ - lib/numru/misc/misc.rb
53
+ - lib/numru/misc/emath.rb
54
+ - lib/numru/misc.rb
55
+ - doc/emath.html
56
+ - doc/md_iterators.html
57
+ - doc/keywordopt.html
58
+ - doc/misc.html
59
+ - doc/index.html
60
+ has_rdoc: true
61
+ homepage: http://www.gfd-dennou.org/arch/ruby/products/numru-misc/
62
+ licenses:
63
+ - Takeshi Horinouchi
64
+ - GFD Dennou Club
65
+ post_install_message:
66
+ rdoc_options: []
67
+
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 1
78
+ - 6
79
+ version: "1.6"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ requirements: []
90
+
91
+ rubyforge_project:
92
+ rubygems_version: 1.3.7
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Collection of miscellaneous functions and classes to facilitate programming.
96
+ test_files: []
97
+