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
@@ -22,30 +22,8 @@ module Hornetseye
22
22
 
23
23
  class << self
24
24
 
25
- # Create new multi-dimensional array
26
- #
27
- # @param [Class] element_type The type of the elements.
28
- # @param [Array<Integer>] *array_shape The shape of the multi-dimensional array.
29
- #
30
- # @return [Node] Returns uninitialised native array.
31
- def new( element_type, *array_shape )
32
- typecode = element_type.typecode
33
- shape = element_type.shape + array_shape
34
- options = shape.last.is_a?( Hash ) ? shape.pop : {}
35
- count = options[ :count ] || 1
36
- if shape.empty?
37
- memory = options[ :memory ] ||
38
- typecode.memory_type.new( typecode.storage_size * count )
39
- Hornetseye::Pointer( typecode ).new memory
40
- else
41
- size = shape.pop
42
- stride = shape.inject( 1 ) { |a,b| a * b }
43
- Hornetseye::lazy( size ) do |index|
44
- pointer = new typecode, *( shape + [ :count => count * size,
45
- :memory => options[ :memory ] ] )
46
- Lookup.new pointer, index, INT.new( stride )
47
- end
48
- end
25
+ def new(typecode, *shape)
26
+ Hornetseye::MultiArray(typecode, shape.size).new *shape
49
27
  end
50
28
 
51
29
  # Import array from string
@@ -53,19 +31,19 @@ module Hornetseye
53
31
  # Create an array from raw data provided as a string.
54
32
  #
55
33
  # @param [Class] typecode Type of the elements in the string.
56
- # @param [String] string String with raw data.
34
+ # @param [String,Malloc] data String or memory object with raw data.
57
35
  # @param [Array<Integer>] shape Array with dimensions of array.
58
36
  #
59
37
  # @return [Node] Multi-dimensional array with imported data.
60
- def import( typecode, string, *shape )
61
- t = Hornetseye::MultiArray typecode, *shape
62
- if string.is_a? Malloc
63
- memory = string
38
+ def import( typecode, data, *shape )
39
+ t = Hornetseye::MultiArray typecode, shape.size
40
+ if data.is_a? Malloc
41
+ memory = data
64
42
  else
65
- memory = Malloc.new t.storage_size
66
- memory.write string
43
+ memory = Malloc.new t.storage_size(*shape)
44
+ memory.write data
67
45
  end
68
- t.new memory
46
+ t.new *(shape + [:memory => memory])
69
47
  end
70
48
 
71
49
  # Convert Ruby array to uniform multi-dimensional array
@@ -118,18 +96,11 @@ module Hornetseye
118
96
 
119
97
  end
120
98
 
121
- # Create multi-dimensional array type
122
- #
123
- # @param [Class] element_type Type of elements.
124
- # @param [Array<Integer>] *shape Shape of array type.
125
- #
126
- # @return [Class] The array type.
127
- def MultiArray( element_type, *shape )
128
- if shape.empty?
129
- element_type
99
+ def MultiArray(typecode, dimension)
100
+ if dimension > 0
101
+ Field_.inherit typecode.typecode, typecode.dimension + dimension
130
102
  else
131
- Hornetseye::Sequence MultiArray( element_type, *shape[ 0 ... -1 ] ),
132
- shape.last
103
+ Hornetseye::Pointer typecode
133
104
  end
134
105
  end
135
106
 
@@ -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
@@ -84,20 +84,8 @@ module Hornetseye
84
84
  [ self ]
85
85
  end
86
86
 
87
- # Get type of result of delayed operation
88
- #
89
- # @return [Class] Type of result.
90
- #
91
- # @private
92
- def array_type
93
- self
94
- end
95
-
96
- # Convert to pointer type
97
- #
98
- # @return [Class] Corresponding pointer type.
99
- def pointer_type
100
- Hornetseye::Pointer( self )
87
+ def shape
88
+ []
101
89
  end
102
90
 
103
91
  # Generate index array of this type
@@ -110,41 +98,6 @@ module Hornetseye
110
98
  offset
111
99
  end
112
100
 
113
- # Get shape of this term
114
- #
115
- # @return [Array<Integer>] Returns +[]+.
116
- def shape
117
- []
118
- end
119
-
120
- # Get width of two-dimensional array
121
- #
122
- # @return [Integer] Width of array.
123
- def width
124
- shape[0]
125
- end
126
-
127
- # Get height of two-dimensional array
128
- #
129
- # @return [Integer] Height of array.
130
- def height
131
- shape[1]
132
- end
133
-
134
- # Get size (number of elements) of this value
135
- #
136
- # @return [Integer] Returns +1+.
137
- def size
138
- 1
139
- end
140
-
141
- # Check whether the type is an empty array
142
- #
143
- # @return [Boolean] Returns whether this type represents an empty array.
144
- def empty?
145
- size == 0
146
- end
147
-
148
101
  # Get dimension of this term
149
102
  #
150
103
  # @return [Array<Integer>] Returns +0+.
@@ -252,9 +205,8 @@ module Hornetseye
252
205
  # @param [Class] a The third type.
253
206
  #
254
207
  # @return [Class] Returns type based on bytes.
255
- def cond( a, b )
256
- t = a.coercion b
257
- Hornetseye::MultiArray( t.typecode, *shape ).coercion t
208
+ def cond(a, b)
209
+ a.coercion b
258
210
  end
259
211
 
260
212
  # Convert to different element type
@@ -308,31 +260,6 @@ module Hornetseye
308
260
  hash[ self ] || self
309
261
  end
310
262
 
311
- # Check arguments for compatible shape
312
- #
313
- # The method will throw an exception if one of the arguments has an incompatible
314
- # shape.
315
- #
316
- # @param [Array<Class>] args Arguments to check for compatibility.
317
- #
318
- # @return [Object] The return value should be ignored.
319
- def check_shape( *args )
320
- _shape = shape
321
- args.each do |arg|
322
- _arg_shape = arg.shape
323
- if _shape.size < _arg_shape.size
324
- raise "#{arg.inspect} has #{arg.dimension} dimension(s) " +
325
- "but should not have more than #{dimension}"
326
- end
327
- if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer }
328
- if _shape.last( _arg_shape.size ) != _arg_shape
329
- raise "#{arg.inspect} has shape #{arg.shape.inspect} " +
330
- "(does not match last value(s) of #{shape.inspect})"
331
- end
332
- end
333
- end
334
- end
335
-
336
263
  # Check whether this term is compilable
337
264
  #
338
265
  # @return [Boolean] Returns +true+.
@@ -353,69 +280,47 @@ module Hornetseye
353
280
 
354
281
  end
355
282
 
356
- # Get type of result of delayed operation
357
- #
358
- # @return [Class] Type of result.
359
- #
360
- # @private
361
- def array_type
362
- self.class.array_type
283
+ def matched?
284
+ true
363
285
  end
364
286
 
365
- # Convert to pointer type
366
- #
367
- # @return [Class] Corresponding pointer type.
368
- def pointer_type
369
- array_type.pointer_type
287
+ def allocate
288
+ Hornetseye::MultiArray(typecode, dimension).new *shape
370
289
  end
371
290
 
372
291
  # Element-type of this term
373
292
  #
374
293
  # @return [Class] Element-type of this datatype.
375
294
  def typecode
376
- array_type.typecode
295
+ self.class.typecode
377
296
  end
378
297
 
379
298
  # Base-type of this term
380
299
  #
381
300
  # @return [Class] Base-type of this datatype.
382
301
  def basetype
383
- array_type.basetype
384
- end
385
-
386
- # Get shape of this term
387
- #
388
- # @return [Array<Integer>] Returns +array_type.shape+.
389
- def shape
390
- array_type.shape
302
+ self.class.basetype
391
303
  end
392
304
 
393
305
  # Get width of two-dimensional array
394
306
  #
395
307
  # @return [Integer] Width of array.
396
308
  def width
397
- array_type.width
309
+ shape[0]
398
310
  end
399
311
 
400
312
  # Get height of two-dimensional array
401
313
  #
402
314
  # @return [Integer] Height of array.
403
315
  def height
404
- array_type.height
316
+ shape[1]
405
317
  end
406
318
 
407
319
  # Get size (number of elements) of this value
408
320
  #
409
- # @return [Integer] Returns +array_type.size+.
321
+ # @return [Integer] Returns number of elements of this value.
410
322
  def size
411
- array_type.size
412
- end
413
-
414
- # Get memory size of object
415
- #
416
- # @return [Integer] Returns required storage size of this array.
417
- def storage_size
418
- array_type.storage_size
323
+ shape.inject(1) { |a,b| a * b }
419
324
  end
420
325
 
421
326
  # Duplicate array expression if it is not in row-major format
@@ -423,8 +328,8 @@ module Hornetseye
423
328
  # @return [Node] Duplicate of array or +self+.
424
329
  def memorise
425
330
  if memory
426
- contiguous_strides = ( 0 ... dimension ).collect do |i|
427
- shape[ 0 ... i ].inject( 1 ) { |a,b| a * b }
331
+ contiguous_strides = (0 ... dimension).collect do |i|
332
+ shape[0 ... i].inject(1) { |a,b| a * b }
428
333
  end
429
334
  if strides == contiguous_strides
430
335
  self
@@ -465,21 +370,28 @@ module Hornetseye
465
370
  #
466
371
  # @return [Boolean] Returns whether this object is an empty array.
467
372
  def empty?
468
- array_type.empty?
373
+ size == 0
374
+ end
375
+
376
+ # Get shape of this term
377
+ #
378
+ # @return [Array<Integer>] Returns +[]+.
379
+ def shape
380
+ self.class.shape
469
381
  end
470
382
 
471
383
  # Get dimension of this term
472
384
  #
473
- # @return [Array<Integer>] Returns +array_type.dimension+.
385
+ # @return [Array<Integer>] Returns number of dimensions of this term.
474
386
  def dimension
475
- array_type.dimension
387
+ shape.size
476
388
  end
477
389
 
478
390
  # Check whether this object is an RGB value
479
391
  #
480
392
  # @return [Boolean] Returns +false+.
481
393
  def rgb?
482
- array_type.rgb?
394
+ typecode.rgb?
483
395
  end
484
396
 
485
397
  # Extract native value if this is an element
@@ -512,12 +424,12 @@ module Hornetseye
512
424
  def inspect( indent = nil, lines = nil )
513
425
  if variables.empty?
514
426
  if dimension == 0 and not indent
515
- "#{array_type.inspect}(#{force.inspect})" # !!!
427
+ "#{typecode.inspect}(#{force.inspect})"
516
428
  else
517
429
  if indent
518
430
  prepend = ''
519
431
  else
520
- prepend = "#{array_type.inspect}:\n"
432
+ prepend = "#{Hornetseye::MultiArray(typecode, dimension).inspect}:\n"
521
433
  indent = 0
522
434
  lines = 0
523
435
  end
@@ -525,7 +437,7 @@ module Hornetseye
525
437
  retval = '[]'
526
438
  else
527
439
  retval = '[ '
528
- for i in 0 ... array_type.num_elements
440
+ for i in 0 ... shape.last
529
441
  x = element i
530
442
  if x.dimension > 0
531
443
  if i > 0
@@ -546,7 +458,7 @@ module Hornetseye
546
458
  end
547
459
  else
548
460
  retval += ', ' if i > 0
549
- str = x.force.inspect # !!!
461
+ str = x.force.inspect
550
462
  if retval.size + str.size >= 74 - '...'.size -
551
463
  '[ ]'.size * indent.succ
552
464
  retval += '...'
@@ -593,7 +505,7 @@ module Hornetseye
593
505
  #
594
506
  # @return [Node] Duplicate of +self+.
595
507
  def dup
596
- retval = array_type.new
508
+ retval = Hornetseye::MultiArray(typecode, dimension).new *shape
597
509
  retval[] = self
598
510
  retval
599
511
  end
@@ -652,14 +564,26 @@ module Hornetseye
652
564
  # The method will throw an exception if one of the arguments has an incompatible
653
565
  # shape.
654
566
  #
655
- # @param [Array<Node>] args Arguments to check for compatibility.
567
+ # @param [Array<Class>] args Arguments to check for compatibility.
656
568
  #
657
569
  # @return [Object] The return value should be ignored.
658
- def check_shape( *args )
659
- array_type.check_shape *args.collect { |arg| arg.array_type }
570
+ def check_shape(*args)
571
+ _shape = shape
572
+ args.each do |arg|
573
+ _arg_shape = arg.shape
574
+ if _shape.size < _arg_shape.size
575
+ raise "#{arg.inspect} has #{arg.dimension} dimension(s) " +
576
+ "but should not have more than #{dimension}"
577
+ end
578
+ if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer }
579
+ if _shape.last( _arg_shape.size ) != _arg_shape
580
+ raise "#{arg.inspect} has shape #{arg.shape.inspect} " +
581
+ "(does not match last value(s) of #{shape.inspect})"
582
+ end
583
+ end
584
+ end
660
585
  end
661
586
 
662
-
663
587
  # Assign value to array element(s)
664
588
  #
665
589
  # @overload []=( *indices, value )
@@ -670,13 +594,13 @@ module Hornetseye
670
594
  # @return [Object,Node] Returns the value.
671
595
  def []=( *indices )
672
596
  value = indices.pop
673
- value = typecode.new value unless value.is_a? Node
597
+ value = typecode.new value unless value.matched?
674
598
  if indices.empty?
675
599
  check_shape value
676
600
  unless compilable? and value.compilable? and dimension > 0
677
- Store.new( self, value ).demand
601
+ Store.new(self, value.sexp).demand
678
602
  else
679
- GCCFunction.run Store.new( self, value )
603
+ GCCFunction.run Store.new(self, value.sexp)
680
604
  end
681
605
  value
682
606
  else
@@ -685,7 +609,7 @@ module Hornetseye
685
609
  else
686
610
  view = element indices.last
687
611
  end
688
- view[ *indices[ 0 ... -1 ] ] = value
612
+ view[*indices[0 ... -1]] = value
689
613
  end
690
614
  end
691
615
 
@@ -732,14 +656,16 @@ module Hornetseye
732
656
  def force
733
657
  if finalised?
734
658
  get
735
- elsif ( dimension > 0 and Thread.current[ :lazy ] ) or not variables.empty?
659
+ elsif (dimension > 0 and Thread.current[:lazy]) or not variables.empty?
736
660
  self
737
661
  elsif compilable?
738
- retval = pointer_type.new
739
- GCCFunction.run Store.new( retval, self )
662
+ retval = allocate
663
+ GCCFunction.run Store.new(retval.sexp, self)
740
664
  retval.demand.get
741
665
  else
742
- Store.new( array_type.new, self ).demand.get
666
+ retval = allocate
667
+ Store.new(retval.sexp, self).demand
668
+ retval.demand.get
743
669
  end
744
670
  end
745
671
 
@@ -756,16 +682,16 @@ module Hornetseye
756
682
 
757
683
  # Coerce with other object
758
684
  #
759
- # @param [Node,Object] other Other object.
685
+ # @param [Object] other Other object.
760
686
  #
761
687
  # @return [Array<Node>] Result of coercion.
762
688
  #
763
689
  # @private
764
- def coerce( other )
765
- if other.is_a? Node
766
- return other, self
690
+ def coerce(other)
691
+ if other.matched?
692
+ return other.sexp, self
767
693
  else
768
- return Node.match( other, self ).new( other ), self
694
+ return Node.match(other, self).new(other), self
769
695
  end
770
696
  end
771
697