multiarray 0.22.0 → 0.23.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.
- data/Rakefile +1 -1
- data/lib/multiarray.rb +53 -16
- data/lib/multiarray/bool.rb +1 -1
- data/lib/multiarray/complex.rb +76 -68
- data/lib/multiarray/components.rb +11 -10
- data/lib/multiarray/composite.rb +1 -1
- data/lib/multiarray/diagonal.rb +11 -12
- data/lib/multiarray/element.rb +3 -3
- data/lib/multiarray/elementwise.rb +14 -14
- data/lib/multiarray/field.rb +380 -0
- data/lib/multiarray/float.rb +10 -10
- data/lib/multiarray/gcccache.rb +1 -1
- data/lib/multiarray/gcccontext.rb +35 -54
- data/lib/multiarray/gccfunction.rb +12 -19
- data/lib/multiarray/gcctype.rb +1 -1
- data/lib/multiarray/gccvalue.rb +63 -43
- data/lib/multiarray/histogram.rb +17 -19
- data/lib/multiarray/index.rb +7 -8
- data/lib/multiarray/inject.rb +11 -12
- data/lib/multiarray/int.rb +12 -11
- data/lib/multiarray/integral.rb +11 -12
- data/lib/multiarray/lambda.rb +23 -18
- data/lib/multiarray/list.rb +1 -1
- data/lib/multiarray/lookup.rb +18 -13
- data/lib/multiarray/lut.rb +13 -16
- data/lib/multiarray/malloc.rb +1 -1
- data/lib/multiarray/mask.rb +11 -8
- data/lib/multiarray/methods.rb +10 -10
- data/lib/multiarray/multiarray.rb +15 -44
- data/lib/multiarray/node.rb +64 -138
- data/lib/multiarray/object.rb +2 -6
- data/lib/multiarray/operations.rb +116 -134
- data/lib/multiarray/pointer.rb +7 -19
- data/lib/multiarray/random.rb +11 -8
- data/lib/multiarray/rgb.rb +53 -53
- data/lib/multiarray/sequence.rb +11 -496
- data/lib/multiarray/shortcuts.rb +4 -4
- data/lib/multiarray/store.rb +14 -11
- data/lib/multiarray/unmask.rb +10 -7
- data/lib/multiarray/variable.rb +11 -3
- data/test/tc_bool.rb +0 -8
- data/test/tc_compile.rb +72 -0
- data/test/tc_float.rb +0 -8
- data/test/tc_int.rb +0 -8
- data/test/tc_lazy.rb +22 -3
- data/test/tc_multiarray.rb +100 -126
- data/test/tc_object.rb +0 -16
- data/test/tc_rgb.rb +0 -16
- data/test/tc_sequence.rb +151 -165
- data/test/ts_multiarray.rb +2 -0
- metadata +7 -4
data/lib/multiarray/sequence.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# multiarray - Lazy multi-dimensional arrays for Ruby
|
2
|
-
# Copyright (C) 2010 Jan Wedekind
|
2
|
+
# Copyright (C) 2010, 2011 Jan Wedekind
|
3
3
|
#
|
4
4
|
# This program is free software: you can redistribute it and/or modify
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
@@ -42,14 +42,14 @@ module Hornetseye
|
|
42
42
|
#
|
43
43
|
# @return [Node] One-dimensional array with imported data.
|
44
44
|
def import( typecode, string, size )
|
45
|
-
t = Hornetseye::Sequence typecode
|
45
|
+
t = Hornetseye::Sequence typecode
|
46
46
|
if string.is_a? Malloc
|
47
47
|
memory = string
|
48
48
|
else
|
49
|
-
memory = Malloc.new t.storage_size
|
49
|
+
memory = Malloc.new t.storage_size(size)
|
50
50
|
memory.write string
|
51
51
|
end
|
52
|
-
t.new memory
|
52
|
+
t.new size, :memory => memory
|
53
53
|
end
|
54
54
|
|
55
55
|
# Convert array to uniform array
|
@@ -63,509 +63,24 @@ module Hornetseye
|
|
63
63
|
def []( *args )
|
64
64
|
target = Node.fit args
|
65
65
|
if target.dimension == 0
|
66
|
-
target = Hornetseye::
|
66
|
+
target = Hornetseye::MultiArray target, 1
|
67
67
|
elsif target.dimension > 1
|
68
|
-
target = Hornetseye::
|
68
|
+
target = Hornetseye::MultiArray OBJECT, 1
|
69
69
|
end
|
70
|
-
target[
|
70
|
+
target[*args]
|
71
71
|
end
|
72
72
|
|
73
73
|
end
|
74
74
|
|
75
75
|
end
|
76
76
|
|
77
|
-
#
|
78
|
-
class Sequence_
|
79
|
-
|
80
|
-
class << self
|
81
|
-
|
82
|
-
# Type of array elements
|
83
|
-
#
|
84
|
-
# @return [Class] element_type Type of array elements.
|
85
|
-
attr_accessor :element_type
|
86
|
-
|
87
|
-
# Number of array elements
|
88
|
-
#
|
89
|
-
# @return [Integer] num_elements Number of elements.
|
90
|
-
attr_accessor :num_elements
|
91
|
-
|
92
|
-
# Get default value for elements of this type
|
93
|
-
#
|
94
|
-
# @return [Object] Returns an array of default values.
|
95
|
-
#
|
96
|
-
# @private
|
97
|
-
def default
|
98
|
-
Hornetseye::lazy( num_elements ) do |i|
|
99
|
-
if element_type.dimension > 0
|
100
|
-
element = element_type.default
|
101
|
-
else
|
102
|
-
element = element_type.new
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Create (lazy) index array
|
108
|
-
#
|
109
|
-
# @param [Integer] offset First value of array.
|
110
|
-
# @param [Integer] increment Increment for subsequent values.
|
111
|
-
#
|
112
|
-
# @return [Node] Lazy term generating the array.
|
113
|
-
def indgen( offset = 0, increment = 1 )
|
114
|
-
Hornetseye::lazy( num_elements ) do |i|
|
115
|
-
( element_type.size * increment * i +
|
116
|
-
element_type.indgen( offset, increment ) ).to_type typecode
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Generate random number array
|
121
|
-
#
|
122
|
-
# Generate integer or floating point random numbers in the range 0 ... n.
|
123
|
-
#
|
124
|
-
# @param [Integer,Float] n Upper boundary for random numbers
|
125
|
-
#
|
126
|
-
# @return [Node] Array with random numbers.
|
127
|
-
def random( n = 1 )
|
128
|
-
n = typecode.maxint.new n unless n.is_a? Node
|
129
|
-
retval = new
|
130
|
-
unless compilable? and dimension > 0
|
131
|
-
Random.new( retval, n ).demand
|
132
|
-
else
|
133
|
-
GCCFunction.run Random.new( retval, n )
|
134
|
-
end
|
135
|
-
retval
|
136
|
-
end
|
137
|
-
|
138
|
-
# Construct native array from Ruby array
|
139
|
-
#
|
140
|
-
# @param [Array<Object>] args Array with Ruby values.
|
141
|
-
#
|
142
|
-
# @return [Node] Native array with specified values.
|
143
|
-
def []( *args )
|
144
|
-
retval = new
|
145
|
-
recursion = lambda do |element,args|
|
146
|
-
if element.dimension > 0
|
147
|
-
args.each_with_index do |arg,i|
|
148
|
-
recursion.call element.element( i ), arg
|
149
|
-
end
|
150
|
-
else
|
151
|
-
element[] = args
|
152
|
-
end
|
153
|
-
end
|
154
|
-
recursion.call retval, args
|
155
|
-
retval
|
156
|
-
end
|
157
|
-
|
158
|
-
# Get dimensions of array type
|
159
|
-
#
|
160
|
-
# @return [Array<Integer>]
|
161
|
-
def shape
|
162
|
-
element_type.shape + [ num_elements ]
|
163
|
-
end
|
164
|
-
|
165
|
-
# Get width of two-dimensional array type
|
166
|
-
#
|
167
|
-
# @return [Integer] Width of array.
|
168
|
-
def width
|
169
|
-
shape[0]
|
170
|
-
end
|
171
|
-
|
172
|
-
# Get height of two-dimensional array
|
173
|
-
#
|
174
|
-
# @return [Integer] Height of array.
|
175
|
-
def height
|
176
|
-
shape[1]
|
177
|
-
end
|
178
|
-
|
179
|
-
# Get size of array type
|
180
|
-
#
|
181
|
-
# @return [Integer] Size of array.
|
182
|
-
def size
|
183
|
-
num_elements * element_type.size
|
184
|
-
end
|
185
|
-
|
186
|
-
# Get storage size of array type
|
187
|
-
#
|
188
|
-
# @return [Integer] Storage size of array.
|
189
|
-
def storage_size
|
190
|
-
num_elements * element_type.storage_size
|
191
|
-
end
|
192
|
-
|
193
|
-
# Check whether type denotes an empty array
|
194
|
-
#
|
195
|
-
# @return [Boolean] Return +true+ for empty array.
|
196
|
-
def empty?
|
197
|
-
size == 0
|
198
|
-
end
|
199
|
-
|
200
|
-
# Get element type of array type
|
201
|
-
#
|
202
|
-
# @return [Class] Element type of array.
|
203
|
-
def typecode
|
204
|
-
element_type.typecode
|
205
|
-
end
|
206
|
-
|
207
|
-
# Base type of this data type
|
208
|
-
#
|
209
|
-
# @return [Class] Returns +element_type+.
|
210
|
-
#
|
211
|
-
# @private
|
212
|
-
def basetype
|
213
|
-
element_type.basetype
|
214
|
-
end
|
215
|
-
|
216
|
-
# Get type of result of delayed operation
|
217
|
-
#
|
218
|
-
# @return [Class] Type of result.
|
219
|
-
#
|
220
|
-
# @private
|
221
|
-
def array_type
|
222
|
-
self
|
223
|
-
end
|
224
|
-
|
225
|
-
# Get pointer type of delayed operation
|
226
|
-
#
|
227
|
-
# @return [Class] Type of result.
|
228
|
-
#
|
229
|
-
# @private
|
230
|
-
def pointer_type
|
231
|
-
self
|
232
|
-
end
|
233
|
-
|
234
|
-
# Get dimension of type of delayed operation
|
235
|
-
#
|
236
|
-
# @return [Integer] Number of dimensions.
|
237
|
-
def dimension
|
238
|
-
element_type.dimension + 1
|
239
|
-
end
|
240
|
-
|
241
|
-
# Check arguments for compatible shape
|
242
|
-
#
|
243
|
-
# The method will throw an exception if one of the arguments has an incompatible
|
244
|
-
# shape.
|
245
|
-
#
|
246
|
-
# @param [Array<Class>] args Arguments to check for compatibility.
|
247
|
-
#
|
248
|
-
# @return [Object] The return value should be ignored.
|
249
|
-
def check_shape( *args )
|
250
|
-
_shape = shape
|
251
|
-
args.each do |arg|
|
252
|
-
_arg_shape = arg.shape
|
253
|
-
if _shape.size < _arg_shape.size
|
254
|
-
raise "#{arg.inspect} has #{arg.dimension} dimension(s) " +
|
255
|
-
"but should not have more than #{dimension}"
|
256
|
-
end
|
257
|
-
if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer }
|
258
|
-
if _shape.last( _arg_shape.size ) != _arg_shape
|
259
|
-
raise "#{arg.inspect} has shape #{arg.shape.inspect} " +
|
260
|
-
"(does not match last value(s) of #{shape.inspect})"
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
# Check whether delayed operation will have colour
|
267
|
-
#
|
268
|
-
# @return [Boolean] Boolean indicating whether the array has elements of type
|
269
|
-
# RGB.
|
270
|
-
def rgb?
|
271
|
-
element_type.rgb?
|
272
|
-
end
|
273
|
-
|
274
|
-
# Get this type
|
275
|
-
#
|
276
|
-
# @return [Class] Returns +self+.
|
277
|
-
#
|
278
|
-
# @private
|
279
|
-
def identity
|
280
|
-
self
|
281
|
-
end
|
282
|
-
|
283
|
-
# Get corresponding boolean type
|
284
|
-
#
|
285
|
-
# @return [Class] Returns type for array of boolean values.
|
286
|
-
#
|
287
|
-
# @private
|
288
|
-
def bool
|
289
|
-
Hornetseye::Sequence element_type.bool, num_elements
|
290
|
-
end
|
291
|
-
|
292
|
-
# Coerce and convert to boolean type
|
293
|
-
#
|
294
|
-
# @return [Class] Returns type for array of boolean values.
|
295
|
-
#
|
296
|
-
# @private
|
297
|
-
def coercion_bool( other )
|
298
|
-
coercion( other ).bool
|
299
|
-
end
|
300
|
-
|
301
|
-
# Get corresponding scalar type
|
302
|
-
#
|
303
|
-
# @return [Class] Returns type for array of scalars.
|
304
|
-
#
|
305
|
-
# @private
|
306
|
-
def scalar
|
307
|
-
Hornetseye::Sequence element_type.scalar, num_elements
|
308
|
-
end
|
309
|
-
|
310
|
-
# Get corresponding floating point type
|
311
|
-
#
|
312
|
-
# @return [Class] Returns type for array of floating point numbers.
|
313
|
-
#
|
314
|
-
# @private
|
315
|
-
def float_scalar
|
316
|
-
Hornetseye::Sequence element_type.float_scalar, num_elements
|
317
|
-
end
|
318
|
-
|
319
|
-
# Get corresponding maximum integer type
|
320
|
-
#
|
321
|
-
# @return [Class] Returns type based on maximum integers.
|
322
|
-
#
|
323
|
-
# @private
|
324
|
-
def maxint
|
325
|
-
Hornetseye::Sequence element_type.maxint, num_elements
|
326
|
-
end
|
327
|
-
|
328
|
-
# Coerce and convert to maximum integer type
|
329
|
-
#
|
330
|
-
# @return [Class] Returns type based on maximum integers.
|
331
|
-
#
|
332
|
-
# @private
|
333
|
-
def coercion_maxint( other )
|
334
|
-
coercion( other ).maxint
|
335
|
-
end
|
336
|
-
|
337
|
-
# Get corresponding byte type
|
338
|
-
#
|
339
|
-
# @return [Class] Returns type based on byte.
|
340
|
-
#
|
341
|
-
# @private
|
342
|
-
def byte
|
343
|
-
Hornetseye::Sequence element_type.byte, num_elements
|
344
|
-
end
|
345
|
-
|
346
|
-
# Coerce and convert to byte type
|
347
|
-
#
|
348
|
-
# @return [Class] Returns type based on byte.
|
349
|
-
#
|
350
|
-
# @private
|
351
|
-
def coercion_byte( other )
|
352
|
-
coercion( other ).byte
|
353
|
-
end
|
354
|
-
|
355
|
-
# Convert to type based on floating point numbers
|
356
|
-
#
|
357
|
-
# @return [Class] Corresponding type based on floating point numbers.
|
358
|
-
#
|
359
|
-
# @private
|
360
|
-
def float
|
361
|
-
Hornetseye::Sequence element_type.float, num_elements
|
362
|
-
end
|
363
|
-
|
364
|
-
# Coerce and convert to type based on floating point numbers
|
365
|
-
#
|
366
|
-
# @return [Class] Corresponding type based on floating point numbers.
|
367
|
-
#
|
368
|
-
# @private
|
369
|
-
def floating( other )
|
370
|
-
coercion( other ).float
|
371
|
-
end
|
372
|
-
|
373
|
-
# Coerce with two other types
|
374
|
-
#
|
375
|
-
# @return [Class] Result of coercion.
|
376
|
-
#
|
377
|
-
# @private
|
378
|
-
def cond( a, b )
|
379
|
-
t = a.coercion b
|
380
|
-
Hornetseye::MultiArray( t.typecode, *shape ).coercion t
|
381
|
-
end
|
382
|
-
|
383
|
-
# Replace element type
|
384
|
-
#
|
385
|
-
# @return [Class] Result of conversion.
|
386
|
-
#
|
387
|
-
# @private
|
388
|
-
def to_type( dest )
|
389
|
-
Hornetseye::Sequence element_type.to_type( dest ), num_elements
|
390
|
-
end
|
391
|
-
|
392
|
-
# Display this type
|
393
|
-
#
|
394
|
-
# @return [String] String with description of this type.
|
395
|
-
def inspect
|
396
|
-
if element_type and num_elements
|
397
|
-
if dimension == 1
|
398
|
-
retval = "Sequence(#{typecode.inspect},#{num_elements.inspect})"
|
399
|
-
else
|
400
|
-
retval = "MultiArray(#{typecode.inspect},#{shape.join ','})"
|
401
|
-
end
|
402
|
-
( class << self; self; end ).instance_eval do
|
403
|
-
define_method( :inspect ) { retval }
|
404
|
-
end
|
405
|
-
retval
|
406
|
-
else
|
407
|
-
'MultiArray(?,?)'
|
408
|
-
end
|
409
|
-
end
|
410
|
-
|
411
|
-
# Compute unique descriptor
|
412
|
-
#
|
413
|
-
# @return [String] Unique descriptor of this type.
|
414
|
-
def to_s
|
415
|
-
descriptor( {} )
|
416
|
-
end
|
417
|
-
|
418
|
-
# Get unique descriptor of this class
|
419
|
-
#
|
420
|
-
# @param [Hash] hash Labels for any variables.
|
421
|
-
#
|
422
|
-
# @return [String] Descriptor of this class.
|
423
|
-
#
|
424
|
-
# @private
|
425
|
-
def descriptor( hash )
|
426
|
-
if element_type and num_elements
|
427
|
-
if dimension == 1
|
428
|
-
"Sequence(#{typecode.descriptor( hash )},#{num_elements.to_s})"
|
429
|
-
else
|
430
|
-
"MultiArray(#{typecode.descriptor( hash )},#{shape.join ','})"
|
431
|
-
end
|
432
|
-
else
|
433
|
-
'MultiArray(?,?)'
|
434
|
-
end
|
435
|
-
end
|
436
|
-
|
437
|
-
# Test equality of classes
|
438
|
-
#
|
439
|
-
# @param [Object] other Object to compare with.
|
440
|
-
#
|
441
|
-
# @return [Boolean] Boolean indicating whether classes are equal.
|
442
|
-
def ==( other )
|
443
|
-
other.is_a? Class and other < Sequence_ and
|
444
|
-
other.element_type == element_type and
|
445
|
-
other.num_elements == num_elements
|
446
|
-
end
|
447
|
-
|
448
|
-
# Type coercion for native elements
|
449
|
-
#
|
450
|
-
# @param [Class] other Other native datatype to coerce with.
|
451
|
-
#
|
452
|
-
# @return [Class] Result of coercion.
|
453
|
-
#
|
454
|
-
# @private
|
455
|
-
def coercion( other )
|
456
|
-
if other < Sequence_
|
457
|
-
Hornetseye::Sequence element_type.coercion( other.element_type ),
|
458
|
-
num_elements
|
459
|
-
else
|
460
|
-
Hornetseye::Sequence element_type.coercion( other ),
|
461
|
-
num_elements
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
# Compute balanced type for binary operation
|
466
|
-
#
|
467
|
-
# @param [Class] other Other type to coerce with.
|
468
|
-
#
|
469
|
-
# @return [Array<Class>] Result of coercion.
|
470
|
-
#
|
471
|
-
# @private
|
472
|
-
def coerce( other )
|
473
|
-
if other < Sequence_
|
474
|
-
return other, self
|
475
|
-
else
|
476
|
-
return Hornetseye::Sequence( other, num_elements ), self
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
|
-
# Instantiate array of this type
|
481
|
-
#
|
482
|
-
# @param [Malloc,List] memory Object for storing array elements.
|
483
|
-
#
|
484
|
-
# @return [Node] The array expression.
|
485
|
-
def new( memory = nil )
|
486
|
-
MultiArray.new typecode, *( shape + [ :memory => memory ] )
|
487
|
-
end
|
488
|
-
|
489
|
-
# Check whether this array expression allows compilation
|
490
|
-
#
|
491
|
-
# @return [Boolean] Returns +true+ if this expression supports compilation.
|
492
|
-
def compilable?
|
493
|
-
element_type.compilable?
|
494
|
-
end
|
495
|
-
|
496
|
-
end
|
497
|
-
|
498
|
-
# Namespace containing method for matching elements of type Sequence_
|
499
|
-
#
|
500
|
-
# @see Sequence_
|
501
|
-
#
|
502
|
-
# @private
|
503
|
-
module Match
|
504
|
-
|
505
|
-
# Method for matching elements of type Sequence_
|
506
|
-
#
|
507
|
-
# @param [Array<Object>] *values Values to find matching native element
|
508
|
-
# type for.
|
509
|
-
#
|
510
|
-
# @return [Class] Native type fitting all values.
|
511
|
-
#
|
512
|
-
# @see Sequence_
|
513
|
-
#
|
514
|
-
# @private
|
515
|
-
def fit( *values )
|
516
|
-
n = values.inject 0 do |size,value|
|
517
|
-
value.is_a?( Array ) ? [ size, value.size ].max : size
|
518
|
-
end
|
519
|
-
if n > 0
|
520
|
-
elements = values.inject [] do |flat,value|
|
521
|
-
flat + ( value.is_a?( Array ) ? value : [ value ] )
|
522
|
-
end
|
523
|
-
Hornetseye::Sequence fit( *elements ), n
|
524
|
-
else
|
525
|
-
super *values
|
526
|
-
end
|
527
|
-
end
|
528
|
-
|
529
|
-
# Perform type alignment
|
530
|
-
#
|
531
|
-
# Align this type to another. This is used to prefer single-precision
|
532
|
-
# floating point in certain cases.
|
533
|
-
#
|
534
|
-
# @param [Class] context Other type to align with.
|
535
|
-
#
|
536
|
-
# @private
|
537
|
-
def align( context )
|
538
|
-
if self < Sequence_
|
539
|
-
Hornetseye::Sequence element_type.align( context ), num_elements
|
540
|
-
else
|
541
|
-
super context
|
542
|
-
end
|
543
|
-
end
|
544
|
-
|
545
|
-
end
|
546
|
-
|
547
|
-
Node.extend Match
|
548
|
-
|
549
|
-
end
|
550
|
-
|
551
|
-
# Create a class deriving from +Sequence_+
|
552
|
-
#
|
553
|
-
# Create a class deriving from +Sequence_+. The parameters +element_type+ and
|
554
|
-
# +num_elements+ are assigned to the corresponding attribute of the resulting class.
|
77
|
+
# Create a class to represent one-dimensional uniform arrays
|
555
78
|
#
|
556
79
|
# @param [Class] element_type The element type of the native array.
|
557
|
-
# @param [Integer] num_elements The number of elements.
|
558
|
-
#
|
559
|
-
# @return [Class] A class deriving from +Sequence_+.
|
560
80
|
#
|
561
|
-
# @
|
562
|
-
|
563
|
-
|
564
|
-
def Sequence( element_type, num_elements )
|
565
|
-
retval = Class.new Sequence_
|
566
|
-
retval.element_type = element_type
|
567
|
-
retval.num_elements = num_elements
|
568
|
-
retval
|
81
|
+
# @return [Class] A class representing a one-dimensional uniform array.
|
82
|
+
def Sequence(element_type)
|
83
|
+
Hornetseye::MultiArray element_type, 1
|
569
84
|
end
|
570
85
|
|
571
86
|
module_function :Sequence
|