numru-misc 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+