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.
Files changed (51) hide show
  1. data/Rakefile +1 -1
  2. data/lib/multiarray.rb +53 -16
  3. data/lib/multiarray/bool.rb +1 -1
  4. data/lib/multiarray/complex.rb +76 -68
  5. data/lib/multiarray/components.rb +11 -10
  6. data/lib/multiarray/composite.rb +1 -1
  7. data/lib/multiarray/diagonal.rb +11 -12
  8. data/lib/multiarray/element.rb +3 -3
  9. data/lib/multiarray/elementwise.rb +14 -14
  10. data/lib/multiarray/field.rb +380 -0
  11. data/lib/multiarray/float.rb +10 -10
  12. data/lib/multiarray/gcccache.rb +1 -1
  13. data/lib/multiarray/gcccontext.rb +35 -54
  14. data/lib/multiarray/gccfunction.rb +12 -19
  15. data/lib/multiarray/gcctype.rb +1 -1
  16. data/lib/multiarray/gccvalue.rb +63 -43
  17. data/lib/multiarray/histogram.rb +17 -19
  18. data/lib/multiarray/index.rb +7 -8
  19. data/lib/multiarray/inject.rb +11 -12
  20. data/lib/multiarray/int.rb +12 -11
  21. data/lib/multiarray/integral.rb +11 -12
  22. data/lib/multiarray/lambda.rb +23 -18
  23. data/lib/multiarray/list.rb +1 -1
  24. data/lib/multiarray/lookup.rb +18 -13
  25. data/lib/multiarray/lut.rb +13 -16
  26. data/lib/multiarray/malloc.rb +1 -1
  27. data/lib/multiarray/mask.rb +11 -8
  28. data/lib/multiarray/methods.rb +10 -10
  29. data/lib/multiarray/multiarray.rb +15 -44
  30. data/lib/multiarray/node.rb +64 -138
  31. data/lib/multiarray/object.rb +2 -6
  32. data/lib/multiarray/operations.rb +116 -134
  33. data/lib/multiarray/pointer.rb +7 -19
  34. data/lib/multiarray/random.rb +11 -8
  35. data/lib/multiarray/rgb.rb +53 -53
  36. data/lib/multiarray/sequence.rb +11 -496
  37. data/lib/multiarray/shortcuts.rb +4 -4
  38. data/lib/multiarray/store.rb +14 -11
  39. data/lib/multiarray/unmask.rb +10 -7
  40. data/lib/multiarray/variable.rb +11 -3
  41. data/test/tc_bool.rb +0 -8
  42. data/test/tc_compile.rb +72 -0
  43. data/test/tc_float.rb +0 -8
  44. data/test/tc_int.rb +0 -8
  45. data/test/tc_lazy.rb +22 -3
  46. data/test/tc_multiarray.rb +100 -126
  47. data/test/tc_object.rb +0 -16
  48. data/test/tc_rgb.rb +0 -16
  49. data/test/tc_sequence.rb +151 -165
  50. data/test/ts_multiarray.rb +2 -0
  51. metadata +7 -4
@@ -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, size
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::Sequence target, 0
66
+ target = Hornetseye::MultiArray target, 1
67
67
  elsif target.dimension > 1
68
- target = Hornetseye::Sequence OBJECT, args.size
68
+ target = Hornetseye::MultiArray OBJECT, 1
69
69
  end
70
- target[ *args ]
70
+ target[*args]
71
71
  end
72
72
 
73
73
  end
74
74
 
75
75
  end
76
76
 
77
- # Class for representing n-dimensional native arrays
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
- # @see Sequence_
562
- # @see Sequence_.element_type
563
- # @see Sequence_.num_elements
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