multiarray 0.22.0 → 0.23.1

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