mdarray 0.4.0-java
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.
- data/LICENSE.txt +54 -0
- data/LICENSE.txt~ +32 -0
- data/README.md +21 -0
- data/Rakefile +40 -0
- data/lib/env.rb +11 -0
- data/lib/mdarray.rb +414 -0
- data/lib/mdarray/access.rb +237 -0
- data/lib/mdarray/counter.rb +779 -0
- data/lib/mdarray/creation.rb +413 -0
- data/lib/mdarray/fast_non_numerical.rb +102 -0
- data/lib/mdarray/function_creation.rb +100 -0
- data/lib/mdarray/function_map.rb +56 -0
- data/lib/mdarray/hierarchy.rb +177 -0
- data/lib/mdarray/operators.rb +220 -0
- data/lib/mdarray/printing.rb +275 -0
- data/lib/mdarray/proc_util.rb +159 -0
- data/lib/mdarray/ruby_functions.rb +78 -0
- data/lib/mdarray/ruby_generic_functions.rb +37 -0
- data/lib/mdarray/ruby_math.rb +57 -0
- data/lib/mdarray/ruby_numeric_functions.rb +187 -0
- data/lib/mdarray/ruby_operators.rb +201 -0
- data/lib/mdarray/ruby_stats.rb +149 -0
- data/lib/mdarray/slices.rb +185 -0
- data/lib/mdarray/statistics.rb +86 -0
- data/test/arithmetic_casting.rb +195 -0
- data/test/env.rb +50 -0
- data/test/test_access.rb +247 -0
- data/test/test_boolean.rb +67 -0
- data/test/test_comparison.rb +126 -0
- data/test/test_complete.rb +69 -0
- data/test/test_counter.rb +184 -0
- data/test/test_creation.rb +364 -0
- data/test/test_error.rb +53 -0
- data/test/test_lazy.rb +52 -0
- data/test/test_operator.rb +337 -0
- data/test/test_printing.rb +66 -0
- data/test/test_shape.rb +96 -0
- data/test/test_slices.rb +146 -0
- data/test/test_speed.rb +311 -0
- data/test/test_statistics.rb +45 -0
- data/test/test_trigonometry.rb +60 -0
- data/vendor/netcdfAll-4.3.16.jar +0 -0
- data/version.rb +2 -0
- metadata +197 -0
@@ -0,0 +1,237 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##########################################################################################
|
4
|
+
# Copyright © 2013 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
|
5
|
+
# and distribute this software and its documentation, without fee and without a signed
|
6
|
+
# licensing agreement, is hereby granted, provided that the above copyright notice, this
|
7
|
+
# paragraph and the following two paragraphs appear in all copies, modifications, and
|
8
|
+
# distributions.
|
9
|
+
#
|
10
|
+
# IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
11
|
+
# INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
12
|
+
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
|
13
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
14
|
+
#
|
15
|
+
# RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
16
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
17
|
+
# SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
18
|
+
# RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
19
|
+
# OR MODIFICATIONS.
|
20
|
+
##########################################################################################
|
21
|
+
|
22
|
+
class MDArray
|
23
|
+
|
24
|
+
#------------------------------------------------------------------------------------
|
25
|
+
#
|
26
|
+
#------------------------------------------------------------------------------------
|
27
|
+
|
28
|
+
def get_current_index
|
29
|
+
@local_iterator.get_current_index
|
30
|
+
end
|
31
|
+
|
32
|
+
#------------------------------------------------------------------------------------
|
33
|
+
# Returns the next element of the local_iterator or nil if no next element available
|
34
|
+
#------------------------------------------------------------------------------------
|
35
|
+
|
36
|
+
def next
|
37
|
+
|
38
|
+
if (@local_iterator && @local_iterator.has_next?)
|
39
|
+
@local_iterator.get_next
|
40
|
+
else
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
#------------------------------------------------------------------------------------
|
47
|
+
# When get is used to retrieve an element, it is assumed that the index does not need
|
48
|
+
# correction, for instance, no negative index is allowed. If one wants to use
|
49
|
+
# negative indexes, then method [] should be used. So mat.get([-1, 0, 0]) raises an
|
50
|
+
# exception while mat[-1, 0, 0] gets the last value for the first dimension.
|
51
|
+
#------------------------------------------------------------------------------------
|
52
|
+
|
53
|
+
def [](*index)
|
54
|
+
|
55
|
+
if (index.size != 0)
|
56
|
+
@local_index[*index]
|
57
|
+
elsif (@local_iterator)
|
58
|
+
@local_iterator.get_current
|
59
|
+
else
|
60
|
+
raise "No iterator defined! Cannot get element"
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
#------------------------------------------------------------------------------------
|
66
|
+
#
|
67
|
+
#------------------------------------------------------------------------------------
|
68
|
+
|
69
|
+
def get(index = nil)
|
70
|
+
@local_index.get(index)
|
71
|
+
end
|
72
|
+
|
73
|
+
#------------------------------------------------------------------------------------
|
74
|
+
# Gets the next element of the local iterator
|
75
|
+
#------------------------------------------------------------------------------------
|
76
|
+
|
77
|
+
def get_next
|
78
|
+
|
79
|
+
if (@local_iterator)
|
80
|
+
@local_iterator.get_next
|
81
|
+
else
|
82
|
+
raise "No iterator defined! Cannot get next element"
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
#------------------------------------------------------------------------------------
|
88
|
+
#
|
89
|
+
#------------------------------------------------------------------------------------
|
90
|
+
|
91
|
+
def []=(*index, value)
|
92
|
+
|
93
|
+
if (index.size != 0)
|
94
|
+
@local_index[index] = value
|
95
|
+
elsif (@local_iterator)
|
96
|
+
@local_iterator.set_current(value)
|
97
|
+
else
|
98
|
+
raise "No iterator defined! Cannot set element value"
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
#---------------------------------------------------------------------------------------
|
104
|
+
# When set is used to assign to an element, it is assumed that the index does not need
|
105
|
+
# correction, for instance, no negative index is allowed. If one wants to use
|
106
|
+
# negative indexes, then method set should be used. So mat[-1, 0, 0] = 10, raises an
|
107
|
+
# exection while mat.set([-1, 0, 0], 10) sets the last value for the first dimension.
|
108
|
+
# *<tt>index</tt>: array with the index position
|
109
|
+
# *<tt>value</tt>: value to be set
|
110
|
+
#---------------------------------------------------------------------------------------
|
111
|
+
|
112
|
+
def set(index, value)
|
113
|
+
@local_index.set(index, value)
|
114
|
+
end
|
115
|
+
|
116
|
+
#---------------------------------------------------------------------------------------
|
117
|
+
#
|
118
|
+
#---------------------------------------------------------------------------------------
|
119
|
+
|
120
|
+
def set_next(value)
|
121
|
+
|
122
|
+
if (@local_iterator)
|
123
|
+
@local_iterator.set_next(value)
|
124
|
+
else
|
125
|
+
raise "No iterator defined! Cannot set element value"
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
#------------------------------------------------------------------------------------
|
131
|
+
#
|
132
|
+
#------------------------------------------------------------------------------------
|
133
|
+
|
134
|
+
def get_counter
|
135
|
+
Counter.new(self)
|
136
|
+
end
|
137
|
+
|
138
|
+
#------------------------------------------------------------------------------------
|
139
|
+
#
|
140
|
+
#------------------------------------------------------------------------------------
|
141
|
+
|
142
|
+
def reset_traversal
|
143
|
+
@local_iterator = get_iterator_fast
|
144
|
+
end
|
145
|
+
|
146
|
+
#------------------------------------------------------------------------------------
|
147
|
+
#
|
148
|
+
#------------------------------------------------------------------------------------
|
149
|
+
|
150
|
+
def each
|
151
|
+
|
152
|
+
iterator = get_iterator_fast
|
153
|
+
while (iterator.has_next?)
|
154
|
+
yield iterator.get_next if block_given?
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
# (1) Each creates a new iterator and does not touch the @local_iterator so that
|
160
|
+
# one should be able to call each from different threads. Still, should be careful
|
161
|
+
# if another thread adds or removes elements from the array. Needs to check what
|
162
|
+
# happens in this situation
|
163
|
+
|
164
|
+
#------------------------------------------------------------------------------------
|
165
|
+
# Cycles through the whole list of elements yielding to a block (if given) the next
|
166
|
+
# element and its index. The index is a ruby array.
|
167
|
+
#------------------------------------------------------------------------------------
|
168
|
+
|
169
|
+
def each_with_counter
|
170
|
+
|
171
|
+
iterator = get_iterator_fast
|
172
|
+
while (iterator.has_next?)
|
173
|
+
yield iterator.get_next, iterator.get_current_counter if block_given?
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
#------------------------------------------------------------------------------------
|
179
|
+
# Continues a each from the position the @local_iterator is in. each_cont cannot be
|
180
|
+
# called from multiple threads as there is only one @local_iterator.
|
181
|
+
#------------------------------------------------------------------------------------
|
182
|
+
|
183
|
+
def each_cont
|
184
|
+
|
185
|
+
while (elmt = self.next)
|
186
|
+
yield elmt if block_given?
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
#------------------------------------------------------------------------------------
|
192
|
+
#
|
193
|
+
#------------------------------------------------------------------------------------
|
194
|
+
|
195
|
+
def each_along_axes(axes)
|
196
|
+
|
197
|
+
counter = Counter.new(self)
|
198
|
+
|
199
|
+
sizes = Array.new
|
200
|
+
(0..rank - 1).each do |axis|
|
201
|
+
if (axes.include?(axis))
|
202
|
+
sizes[axis] = 1
|
203
|
+
else
|
204
|
+
sizes[axis] = shape[axis]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
counter.each_along_axes(axes) do |ct|
|
209
|
+
# yield ct, sizes if block_given?
|
210
|
+
yield section(ct, sizes, true) if block_given?
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
#------------------------------------------------------------------------------------
|
216
|
+
#
|
217
|
+
#------------------------------------------------------------------------------------
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
#------------------------------------------------------------------------------------
|
222
|
+
# Cycles through the whole list of elements yielding to a block (if given) the next
|
223
|
+
# element and its iterator. Was made private so that users do not need to know about
|
224
|
+
# iterator. Giving iterator could be a speed up usefule for final users concerned
|
225
|
+
# about performance.
|
226
|
+
#------------------------------------------------------------------------------------
|
227
|
+
|
228
|
+
def each_with_iterator
|
229
|
+
|
230
|
+
iterator = get_iterator_fast
|
231
|
+
while (iterator.has_next?)
|
232
|
+
yield iterator.get_next, iterator if block_given?
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
@@ -0,0 +1,779 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##########################################################################################
|
4
|
+
# Copyright © 2013 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
|
5
|
+
# and distribute this software and its documentation, without fee and without a signed
|
6
|
+
# licensing agreement, is hereby granted, provided that the above copyright notice, this
|
7
|
+
# paragraph and the following two paragraphs appear in all copies, modifications, and
|
8
|
+
# distributions.
|
9
|
+
#
|
10
|
+
# IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
11
|
+
# INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
12
|
+
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
|
13
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
14
|
+
#
|
15
|
+
# RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
16
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
17
|
+
# SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
18
|
+
# RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
19
|
+
# OR MODIFICATIONS.
|
20
|
+
##########################################################################################
|
21
|
+
|
22
|
+
#=========================================================================================
|
23
|
+
#
|
24
|
+
#=========================================================================================
|
25
|
+
|
26
|
+
class MDArray
|
27
|
+
java_import 'java.lang.ClassCastException'
|
28
|
+
|
29
|
+
#---------------------------------------------------------------------------------------
|
30
|
+
#
|
31
|
+
#---------------------------------------------------------------------------------------
|
32
|
+
|
33
|
+
def get_index
|
34
|
+
MDArray::Counter.new(self)
|
35
|
+
end
|
36
|
+
|
37
|
+
#---------------------------------------------------------------------------------------
|
38
|
+
# Counters for Multidimensional arrays. A Counter refers to a particular element of an
|
39
|
+
# array. This is a generalization of index as int[].
|
40
|
+
#---------------------------------------------------------------------------------------
|
41
|
+
|
42
|
+
class Counter
|
43
|
+
include Enumerable
|
44
|
+
|
45
|
+
attr_reader :mdarray
|
46
|
+
attr_reader :nc_index
|
47
|
+
attr_reader :shape
|
48
|
+
attr_reader :start
|
49
|
+
attr_reader :finish
|
50
|
+
attr_reader :counter
|
51
|
+
|
52
|
+
#------------------------------------------------------------------------------------
|
53
|
+
#
|
54
|
+
#------------------------------------------------------------------------------------
|
55
|
+
|
56
|
+
def initialize(mdarray)
|
57
|
+
|
58
|
+
@mdarray = mdarray
|
59
|
+
@nc_index = mdarray.nc_array.getIndex()
|
60
|
+
@shape = @nc_index.getShape().to_a
|
61
|
+
|
62
|
+
# by default the starting index is the [0] index (first element)
|
63
|
+
shape = @shape.dup
|
64
|
+
set_start(shape.fill(0))
|
65
|
+
# by default the finish index is the last element of the array
|
66
|
+
finish = Array.new
|
67
|
+
@shape.each do |val|
|
68
|
+
finish << val - 1
|
69
|
+
end
|
70
|
+
|
71
|
+
set_finish(finish)
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
#-------------------------------------------------------------------------------------
|
76
|
+
# Sets the starting position of the index
|
77
|
+
#-------------------------------------------------------------------------------------
|
78
|
+
|
79
|
+
def set_start(start)
|
80
|
+
|
81
|
+
start = reshape(start)
|
82
|
+
if (start[0])
|
83
|
+
raise "Cannot set index starting position to an array section"
|
84
|
+
else
|
85
|
+
@start = start[1].reverse
|
86
|
+
reset_counter
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
#-------------------------------------------------------------------------------------
|
92
|
+
# Sets the finishing position of the index
|
93
|
+
#-------------------------------------------------------------------------------------
|
94
|
+
|
95
|
+
def set_finish(finish)
|
96
|
+
|
97
|
+
finish = reshape(finish)
|
98
|
+
if (finish[0])
|
99
|
+
raise "Cannot set index finish position to an array section"
|
100
|
+
else
|
101
|
+
@finish = finish[1].reverse
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
#-------------------------------------------------------------------------------------
|
107
|
+
# Accessor methods for start, finish and position.
|
108
|
+
#-------------------------------------------------------------------------------------
|
109
|
+
|
110
|
+
def start
|
111
|
+
@start.reverse
|
112
|
+
end
|
113
|
+
|
114
|
+
def finish
|
115
|
+
@finish.reverse
|
116
|
+
end
|
117
|
+
|
118
|
+
def counter
|
119
|
+
@counter.reverse
|
120
|
+
end
|
121
|
+
|
122
|
+
#------------------------------------------------------------------------------------
|
123
|
+
# Reset the counter to the defined start value
|
124
|
+
#------------------------------------------------------------------------------------
|
125
|
+
|
126
|
+
def reset_counter
|
127
|
+
@counter = @start.dup
|
128
|
+
end
|
129
|
+
|
130
|
+
#-------------------------------------------------------------------------------------
|
131
|
+
#
|
132
|
+
#-------------------------------------------------------------------------------------
|
133
|
+
|
134
|
+
def each
|
135
|
+
|
136
|
+
reset_counter
|
137
|
+
begin
|
138
|
+
yield self.counter if block_given?
|
139
|
+
end while(get_next_counter)
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
#-------------------------------------------------------------------------------------
|
144
|
+
# Walks the counter along each of the axes. For instance if given axes [0, 2] and
|
145
|
+
# the array shape is [4, 3, 2], then the counter will be [0, 0, 0], [0, 0, 1],
|
146
|
+
# [1, 0, 1], [1, 0, 1], [2, 0, 0], ... [3, 0, 1]
|
147
|
+
#-------------------------------------------------------------------------------------
|
148
|
+
|
149
|
+
def each_along_axes(axes)
|
150
|
+
|
151
|
+
reset_counter
|
152
|
+
@axes = axes
|
153
|
+
|
154
|
+
axis = [0, self.counter.size - 2]
|
155
|
+
begin
|
156
|
+
yield self.counter, axis[1] if block_given?
|
157
|
+
end while (axis = walk_along_axes)
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
#------------------------------------------------------------------------------------
|
162
|
+
# Gets the element at the given counter. If counter is not basic, try to fix it to
|
163
|
+
# its basic form.
|
164
|
+
#------------------------------------------------------------------------------------
|
165
|
+
|
166
|
+
def [](*counter)
|
167
|
+
set_counter(counter)
|
168
|
+
get_at_counter
|
169
|
+
end
|
170
|
+
|
171
|
+
#------------------------------------------------------------------------------------
|
172
|
+
# Gets the element at the given counter. Assumes that the counter is of the proper
|
173
|
+
# shape.
|
174
|
+
#------------------------------------------------------------------------------------
|
175
|
+
|
176
|
+
def get(counter)
|
177
|
+
set_counter_fast(counter)
|
178
|
+
get_at_counter
|
179
|
+
end
|
180
|
+
|
181
|
+
#------------------------------------------------------------------------------------
|
182
|
+
# Gets element at current counter. Can be done fast, as counter is always of the
|
183
|
+
# proper shape.
|
184
|
+
#------------------------------------------------------------------------------------
|
185
|
+
|
186
|
+
def get_current
|
187
|
+
set_counter_fast(self.counter)
|
188
|
+
get_at_counter
|
189
|
+
end
|
190
|
+
|
191
|
+
#------------------------------------------------------------------------------------
|
192
|
+
# Sets the value of counter. If counter is not basic, try to fix it to its basic
|
193
|
+
# form.
|
194
|
+
#------------------------------------------------------------------------------------
|
195
|
+
|
196
|
+
def []= (counter, value)
|
197
|
+
set_counter(counter)
|
198
|
+
set_at_counter(value)
|
199
|
+
end
|
200
|
+
|
201
|
+
#------------------------------------------------------------------------------------
|
202
|
+
# Sets the value of counter. Assume that counter is on its basic form.
|
203
|
+
#------------------------------------------------------------------------------------
|
204
|
+
|
205
|
+
def set(counter, value)
|
206
|
+
set_counter_fast(counter)
|
207
|
+
set_at_counter(value)
|
208
|
+
end
|
209
|
+
|
210
|
+
#------------------------------------------------------------------------------------
|
211
|
+
# Sets value of current counter. Can be done fast, as the current counter is always
|
212
|
+
# in its basic shape.
|
213
|
+
#------------------------------------------------------------------------------------
|
214
|
+
|
215
|
+
def set_current(value)
|
216
|
+
set_counter_fast(self.counter)
|
217
|
+
set_at_counter(value)
|
218
|
+
end
|
219
|
+
|
220
|
+
#-------------------------------------------------------------------------------------
|
221
|
+
#
|
222
|
+
#-------------------------------------------------------------------------------------
|
223
|
+
|
224
|
+
private
|
225
|
+
|
226
|
+
#-------------------------------------------------------------------------------------
|
227
|
+
# Returns next counter if no overflow, otherwise returns nil
|
228
|
+
#-------------------------------------------------------------------------------------
|
229
|
+
|
230
|
+
def get_next_counter
|
231
|
+
|
232
|
+
# gets the next counter
|
233
|
+
shape = @shape.dup.reverse
|
234
|
+
|
235
|
+
@counter.each_with_index do |val, index|
|
236
|
+
|
237
|
+
if val < shape[index] - 1
|
238
|
+
@counter[index] = val + 1
|
239
|
+
return counter
|
240
|
+
else
|
241
|
+
@counter[index] = 0
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
return nil
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
#-------------------------------------------------------------------------------------
|
251
|
+
#
|
252
|
+
#-------------------------------------------------------------------------------------
|
253
|
+
|
254
|
+
def walk_along_axes
|
255
|
+
|
256
|
+
axes = @axes.dup.reverse
|
257
|
+
|
258
|
+
axes.each do |axis|
|
259
|
+
|
260
|
+
index = @counter.size - axis - 1
|
261
|
+
if (@counter[index] < @shape[axis] - 1)
|
262
|
+
@counter[index] = @counter[index] + 1
|
263
|
+
return @counter, axis
|
264
|
+
else
|
265
|
+
@counter[index] = 0
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
|
270
|
+
return nil
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
#-------------------------------------------------------------------------------------
|
275
|
+
# If given index has negative values, then reshape it so that it only has positive
|
276
|
+
# values.
|
277
|
+
# check if it is a range: regex of the form /x/ or /x:y/ or /x:y:z/
|
278
|
+
#-------------------------------------------------------------------------------------
|
279
|
+
|
280
|
+
def reshape(counter)
|
281
|
+
|
282
|
+
if (counter.size != @shape.size)
|
283
|
+
raise "Counter shape #{counter} is not compatible with iterator shape #{@shape}"
|
284
|
+
end
|
285
|
+
|
286
|
+
reshaped_counter = Array.new
|
287
|
+
section = false
|
288
|
+
|
289
|
+
counter.each_with_index do |val, ind|
|
290
|
+
|
291
|
+
if (val.is_a? Integer)
|
292
|
+
if (val < 0)
|
293
|
+
new_ind = @shape[ind] + val
|
294
|
+
if (new_ind < 0)
|
295
|
+
raise "Counter shape #{counter} is not compatible with iterator shape #{@shape}"
|
296
|
+
end
|
297
|
+
reshaped_counter[ind] = new_ind
|
298
|
+
elsif (val >= @shape[ind])
|
299
|
+
raise "Counter shape #{counter} is not compatible with iterator shape #{@shape}"
|
300
|
+
else
|
301
|
+
reshaped_counter[ind] = counter[ind]
|
302
|
+
end
|
303
|
+
|
304
|
+
elsif (val.is_a? Regexp)
|
305
|
+
section = true
|
306
|
+
else
|
307
|
+
raise "Invalid index format: #{val}"
|
308
|
+
end
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
[section, reshaped_counter]
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
#-------------------------------------------------------------------------------------
|
317
|
+
# Sets this index to point to the given counter. assumes that the counter respects
|
318
|
+
# the shape constraints.
|
319
|
+
#-------------------------------------------------------------------------------------
|
320
|
+
|
321
|
+
def set_counter_fast(counter)
|
322
|
+
|
323
|
+
begin
|
324
|
+
@nc_index.set(counter.to_java :int)
|
325
|
+
rescue java.lang.ArrayIndexOutOfBoundsException
|
326
|
+
raise RangeError, "Invalid counter: #{counter}"
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
#-------------------------------------------------------------------------------------
|
332
|
+
# Sets this index to point to the given counter. If given counter has negative values
|
333
|
+
# then convert them to positive values, making sure that the counter respects the
|
334
|
+
# shape constraints. The given counter is a list of elements as (2, 3, 3) and not and
|
335
|
+
# array.
|
336
|
+
#-------------------------------------------------------------------------------------
|
337
|
+
|
338
|
+
def set_counter(counter)
|
339
|
+
|
340
|
+
counter = reshape(counter)
|
341
|
+
set_counter_fast(counter[1])
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
#------------------------------------------------------------------------------------
|
346
|
+
# Sets the value of the array at counter with value. If type is given, cast the value
|
347
|
+
# to type before assignment
|
348
|
+
#------------------------------------------------------------------------------------
|
349
|
+
|
350
|
+
def set_at_counter(value)
|
351
|
+
|
352
|
+
begin
|
353
|
+
|
354
|
+
case @type
|
355
|
+
when "boolean"
|
356
|
+
@mdarray.nc_array.setBoolean(@nc_index, value)
|
357
|
+
when "byte"
|
358
|
+
@mdarray.nc_array.setByte(@nc_index, value)
|
359
|
+
when "char"
|
360
|
+
@mdarray.nc_array.setChar(@nc_index, value)
|
361
|
+
when "short"
|
362
|
+
@mdarray.nc_array.setShort(@nc_index, value)
|
363
|
+
when "unsigned"
|
364
|
+
@mdarray.nc_array.setUnsigned(@nc_index, value)
|
365
|
+
when "int"
|
366
|
+
@mdarray.nc_array.setInt(@nc_index, value)
|
367
|
+
when "long"
|
368
|
+
@mdarray.nc_array.setLong(@nc_index, value)
|
369
|
+
when "float"
|
370
|
+
@mdarray.nc_array.setFloat(@nc_index, value)
|
371
|
+
when "double"
|
372
|
+
@mdarray.nc_array.setDouble(@nc_index, value)
|
373
|
+
else
|
374
|
+
@mdarray.nc_array.setObject(@nc_index, value)
|
375
|
+
end
|
376
|
+
|
377
|
+
rescue ClassCastException
|
378
|
+
raise "Cannot cast element to array type"
|
379
|
+
end
|
380
|
+
|
381
|
+
end
|
382
|
+
|
383
|
+
#------------------------------------------------------------------------------------
|
384
|
+
#
|
385
|
+
#------------------------------------------------------------------------------------
|
386
|
+
|
387
|
+
def get_at_counter
|
388
|
+
|
389
|
+
case @type
|
390
|
+
when "boolean"
|
391
|
+
@mdarray.nc_array.getBoolean(@nc_index)
|
392
|
+
when "byte"
|
393
|
+
@mdarra.nc_array.getByte(@nc_index)
|
394
|
+
when "char"
|
395
|
+
@mdarray.nc_array.getChar(@nc_index)
|
396
|
+
when "double"
|
397
|
+
@mdarray.nc_array.getDouble(@nc_index)
|
398
|
+
when "float"
|
399
|
+
@mdarray.nc_array.getFloat(@nc_index)
|
400
|
+
when "int"
|
401
|
+
@mdarray.nc_array.getInt(@nc_index)
|
402
|
+
when "long"
|
403
|
+
@mdarray.nc_array.getLong(@nc_index)
|
404
|
+
when "short"
|
405
|
+
@mdarray.nc_array.getShort(@nc_index)
|
406
|
+
when "unsigned"
|
407
|
+
@mdarray.nc_array.getUnsigned(@nc_index)
|
408
|
+
else
|
409
|
+
@mdarray.nc_array.getObject(@nc_index)
|
410
|
+
end
|
411
|
+
|
412
|
+
end
|
413
|
+
|
414
|
+
#------------------------------------------------------------------------------------
|
415
|
+
#
|
416
|
+
#------------------------------------------------------------------------------------
|
417
|
+
|
418
|
+
def set_i(dim, index)
|
419
|
+
|
420
|
+
index = reshape(index)
|
421
|
+
|
422
|
+
case dim
|
423
|
+
when 0
|
424
|
+
@nc_index.set0(index)
|
425
|
+
when 1
|
426
|
+
@nc_index.set1(index)
|
427
|
+
when 2
|
428
|
+
@nc_index.set2(index)
|
429
|
+
when 3
|
430
|
+
@nc_index.set3(index)
|
431
|
+
when 4
|
432
|
+
@nc_index.set4(index)
|
433
|
+
when 5
|
434
|
+
@nc_index.set5(index)
|
435
|
+
when 6
|
436
|
+
@nc_index.set6(index)
|
437
|
+
else
|
438
|
+
raise "Maximum allowed dimension is 6. Please, use method set to set this index"
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
|
443
|
+
#------------------------------------------------------------------------------------
|
444
|
+
#
|
445
|
+
#------------------------------------------------------------------------------------
|
446
|
+
|
447
|
+
def set_i_fast(dim, index)
|
448
|
+
|
449
|
+
case dim
|
450
|
+
when 0
|
451
|
+
@nc_index.set0(index)
|
452
|
+
when 1
|
453
|
+
@nc_index.set1(index)
|
454
|
+
when 2
|
455
|
+
@nc_index.set2(index)
|
456
|
+
when 3
|
457
|
+
@nc_index.set3(index)
|
458
|
+
when 4
|
459
|
+
@nc_index.set4(index)
|
460
|
+
when 5
|
461
|
+
@nc_index.set5(index)
|
462
|
+
when 6
|
463
|
+
@nc_index.set6(index)
|
464
|
+
else
|
465
|
+
raise "Maximum allowed dimension is 6. Please, use method set to set this index"
|
466
|
+
end
|
467
|
+
|
468
|
+
end
|
469
|
+
|
470
|
+
#------------------------------------------------------------------------------------
|
471
|
+
# Increment the current element by 1.
|
472
|
+
#------------------------------------------------------------------------------------
|
473
|
+
|
474
|
+
def incr
|
475
|
+
@nc_index.incr()
|
476
|
+
end
|
477
|
+
|
478
|
+
#------------------------------------------------------------------------------------
|
479
|
+
# Get the length of the ith dimension.
|
480
|
+
#------------------------------------------------------------------------------------
|
481
|
+
|
482
|
+
def get_shape(dim_i)
|
483
|
+
@nc_index.getShape(dim_i)
|
484
|
+
end
|
485
|
+
|
486
|
+
#------------------------------------------------------------------------------------
|
487
|
+
# Compute total number of elements in the array.
|
488
|
+
#------------------------------------------------------------------------------------
|
489
|
+
|
490
|
+
def compute_size
|
491
|
+
@nc_index.computeSize(@mdarray.nc_array.getShape())
|
492
|
+
end
|
493
|
+
|
494
|
+
#------------------------------------------------------------------------------------
|
495
|
+
# Gets the current counter from the underlining storage. Should be the same as
|
496
|
+
# @counter
|
497
|
+
#------------------------------------------------------------------------------------
|
498
|
+
|
499
|
+
def get_current_counter
|
500
|
+
@nc_index.getCurrentCounter().to_a
|
501
|
+
end
|
502
|
+
|
503
|
+
end # Counter
|
504
|
+
|
505
|
+
|
506
|
+
#---------------------------------------------------------------------------------------
|
507
|
+
#
|
508
|
+
#---------------------------------------------------------------------------------------
|
509
|
+
|
510
|
+
class IteratorFast
|
511
|
+
|
512
|
+
attr_reader :mdarray
|
513
|
+
attr_reader :iterator
|
514
|
+
|
515
|
+
#-------------------------------------------------------------------------------------
|
516
|
+
#
|
517
|
+
#-------------------------------------------------------------------------------------
|
518
|
+
|
519
|
+
def initialize(mdarray)
|
520
|
+
@mdarray = mdarray
|
521
|
+
@iterator = mdarray.nc_array.getIndexIterator()
|
522
|
+
end
|
523
|
+
|
524
|
+
#------------------------------------------------------------------------------------
|
525
|
+
#
|
526
|
+
#------------------------------------------------------------------------------------
|
527
|
+
|
528
|
+
def has_next?
|
529
|
+
@iterator.hasNext()
|
530
|
+
end
|
531
|
+
|
532
|
+
#------------------------------------------------------------------------------------
|
533
|
+
#
|
534
|
+
#------------------------------------------------------------------------------------
|
535
|
+
|
536
|
+
def next
|
537
|
+
@iterator.next()
|
538
|
+
end
|
539
|
+
|
540
|
+
#------------------------------------------------------------------------------------
|
541
|
+
# Returns the current counter as a ruby array
|
542
|
+
#------------------------------------------------------------------------------------
|
543
|
+
|
544
|
+
def get_current_counter
|
545
|
+
@iterator.getCurrentCounter().to_a
|
546
|
+
end
|
547
|
+
|
548
|
+
#------------------------------------------------------------------------------------
|
549
|
+
#
|
550
|
+
#------------------------------------------------------------------------------------
|
551
|
+
|
552
|
+
def get_current
|
553
|
+
@iterator.getObjectCurrent()
|
554
|
+
end
|
555
|
+
|
556
|
+
alias :[] :get_current
|
557
|
+
|
558
|
+
#------------------------------------------------------------------------------------
|
559
|
+
#
|
560
|
+
#------------------------------------------------------------------------------------
|
561
|
+
|
562
|
+
def get_next
|
563
|
+
@iterator.getObjectNext()
|
564
|
+
end
|
565
|
+
|
566
|
+
#------------------------------------------------------------------------------------
|
567
|
+
#
|
568
|
+
#------------------------------------------------------------------------------------
|
569
|
+
|
570
|
+
def set_current(value)
|
571
|
+
@iterator.setObjectCurrent(value)
|
572
|
+
end
|
573
|
+
|
574
|
+
alias :[]= :set_current
|
575
|
+
|
576
|
+
#------------------------------------------------------------------------------------
|
577
|
+
#
|
578
|
+
#------------------------------------------------------------------------------------
|
579
|
+
|
580
|
+
def set_next(value)
|
581
|
+
@iterator.setObjectNext(value)
|
582
|
+
end
|
583
|
+
|
584
|
+
end # IteratorFast
|
585
|
+
|
586
|
+
#---------------------------------------------------------------------------------------
|
587
|
+
#
|
588
|
+
#---------------------------------------------------------------------------------------
|
589
|
+
|
590
|
+
class IteratorFastBoolean < IteratorFast
|
591
|
+
|
592
|
+
def get_current
|
593
|
+
@iterator.getBoolenaCurrent
|
594
|
+
end
|
595
|
+
|
596
|
+
def get_next
|
597
|
+
@iterator.getBooleanNext
|
598
|
+
end
|
599
|
+
|
600
|
+
def set_current(value)
|
601
|
+
@iterator.setBooleanCurrent(value)
|
602
|
+
end
|
603
|
+
|
604
|
+
def set_next(value)
|
605
|
+
@iterator.setBooleanNext(value)
|
606
|
+
end
|
607
|
+
|
608
|
+
end # IteratorFastBoolean
|
609
|
+
|
610
|
+
#---------------------------------------------------------------------------------------
|
611
|
+
#
|
612
|
+
#---------------------------------------------------------------------------------------
|
613
|
+
|
614
|
+
|
615
|
+
class IteratorFastByte < IteratorFast
|
616
|
+
|
617
|
+
def get_current
|
618
|
+
@iterator.getByteCurrent
|
619
|
+
end
|
620
|
+
|
621
|
+
def get_next
|
622
|
+
@iterator.getByteNext
|
623
|
+
end
|
624
|
+
|
625
|
+
def set_current(value)
|
626
|
+
@iterator.setByteCurrent(value)
|
627
|
+
end
|
628
|
+
|
629
|
+
def set_next(value)
|
630
|
+
@iterator.setByteNext(value)
|
631
|
+
end
|
632
|
+
|
633
|
+
end # IteratorFastByte
|
634
|
+
|
635
|
+
#---------------------------------------------------------------------------------------
|
636
|
+
#
|
637
|
+
#---------------------------------------------------------------------------------------
|
638
|
+
|
639
|
+
class IteratorFastChar < IteratorFast
|
640
|
+
|
641
|
+
def get_current
|
642
|
+
@iterator.getCharCurrent
|
643
|
+
end
|
644
|
+
|
645
|
+
def get_next
|
646
|
+
@iterator.getCharNext
|
647
|
+
end
|
648
|
+
|
649
|
+
def set_current(value)
|
650
|
+
@iterator.setCharCurrent(value)
|
651
|
+
end
|
652
|
+
|
653
|
+
def set_next(value)
|
654
|
+
@iterator.setCharNext(value)
|
655
|
+
end
|
656
|
+
|
657
|
+
end # IteratorFastChar
|
658
|
+
|
659
|
+
#---------------------------------------------------------------------------------------
|
660
|
+
#
|
661
|
+
#---------------------------------------------------------------------------------------
|
662
|
+
|
663
|
+
class IteratorFastShort < IteratorFast
|
664
|
+
|
665
|
+
def get_current
|
666
|
+
@iterator.getShortCurrent
|
667
|
+
end
|
668
|
+
|
669
|
+
def get_next
|
670
|
+
@iterator.getShortNext
|
671
|
+
end
|
672
|
+
|
673
|
+
def set_current(value)
|
674
|
+
@iterator.setShortCurrent(value)
|
675
|
+
end
|
676
|
+
|
677
|
+
def set_next(value)
|
678
|
+
@iterator.setShortNext(value)
|
679
|
+
end
|
680
|
+
|
681
|
+
end # IteratorFastShort
|
682
|
+
|
683
|
+
#---------------------------------------------------------------------------------------
|
684
|
+
#
|
685
|
+
#---------------------------------------------------------------------------------------
|
686
|
+
|
687
|
+
class IteratorFastInt < IteratorFast
|
688
|
+
|
689
|
+
def get_current
|
690
|
+
@iterator.getIntCurrent
|
691
|
+
end
|
692
|
+
|
693
|
+
def get_next
|
694
|
+
@iterator.getIntNext
|
695
|
+
end
|
696
|
+
|
697
|
+
def set_current(value)
|
698
|
+
@iterator.setIntCurrent(value)
|
699
|
+
end
|
700
|
+
|
701
|
+
def set_next(value)
|
702
|
+
@iterator.setIntNext(value)
|
703
|
+
end
|
704
|
+
|
705
|
+
end # IteratorFastInt
|
706
|
+
|
707
|
+
#---------------------------------------------------------------------------------------
|
708
|
+
#
|
709
|
+
#---------------------------------------------------------------------------------------
|
710
|
+
|
711
|
+
class IteratorFastLong < IteratorFast
|
712
|
+
|
713
|
+
def get_current
|
714
|
+
@iterator.getLongCurrent
|
715
|
+
end
|
716
|
+
|
717
|
+
def get_next
|
718
|
+
@iterator.getLongNext
|
719
|
+
end
|
720
|
+
|
721
|
+
def set_current(value)
|
722
|
+
@iterator.setLongCurrent(value)
|
723
|
+
end
|
724
|
+
|
725
|
+
def set_next(value)
|
726
|
+
@iterator.setLongNext(value)
|
727
|
+
end
|
728
|
+
|
729
|
+
end # IteratorFastLong
|
730
|
+
|
731
|
+
#---------------------------------------------------------------------------------------
|
732
|
+
#
|
733
|
+
#---------------------------------------------------------------------------------------
|
734
|
+
|
735
|
+
class IteratorFastFloat < IteratorFast
|
736
|
+
|
737
|
+
def get_current
|
738
|
+
@iterator.getFloatCurrent
|
739
|
+
end
|
740
|
+
|
741
|
+
def get_next
|
742
|
+
@iterator.getFloatNext
|
743
|
+
end
|
744
|
+
|
745
|
+
def set_current(value)
|
746
|
+
@iterator.setFloatCurrent(value)
|
747
|
+
end
|
748
|
+
|
749
|
+
def set_next(value)
|
750
|
+
@iterator.setFloatNext(value)
|
751
|
+
end
|
752
|
+
|
753
|
+
end # IteratorFastFloat
|
754
|
+
|
755
|
+
#---------------------------------------------------------------------------------------
|
756
|
+
#
|
757
|
+
#---------------------------------------------------------------------------------------
|
758
|
+
|
759
|
+
class IteratorFastDouble < IteratorFast
|
760
|
+
|
761
|
+
def get_current
|
762
|
+
@iterator.getDoubleCurrent
|
763
|
+
end
|
764
|
+
|
765
|
+
def get_next
|
766
|
+
@iterator.getDoubleNext
|
767
|
+
end
|
768
|
+
|
769
|
+
def set_current(value)
|
770
|
+
@iterator.setDoubleCurrent(value)
|
771
|
+
end
|
772
|
+
|
773
|
+
def set_next(value)
|
774
|
+
@iterator.setDoubleNext(value)
|
775
|
+
end
|
776
|
+
|
777
|
+
end # IteratorFastDouble
|
778
|
+
|
779
|
+
end
|