numru-misc 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +41 -0
- data/LICENSE.txt +34 -0
- data/Rakefile +38 -0
- data/doc/emath.html +26 -0
- data/doc/index.html +83 -0
- data/doc/keywordopt.html +179 -0
- data/doc/md_iterators.html +86 -0
- data/doc/misc.html +83 -0
- data/install.rb +104 -0
- data/lib/numru/misc.rb +4 -0
- data/lib/numru/misc/emath.rb +75 -0
- data/lib/numru/misc/keywordopt.rb +498 -0
- data/lib/numru/misc/md_iterators.rb +180 -0
- data/lib/numru/misc/misc.rb +196 -0
- data/makedoc.csh +6 -0
- metadata +97 -0
@@ -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
|
data/makedoc.csh
ADDED
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
|
+
|