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
@@ -77,11 +77,7 @@ module Hornetseye
77
77
  #
78
78
  # @private
79
79
  def coercion( other )
80
- if other < Sequence_
81
- other.coercion self
82
- else
83
- self
84
- end
80
+ self
85
81
  end
86
82
 
87
83
  # Type coercion for native elements
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010, 2011 Jan Wedekind
2
+ # Copyright (C) 2010, 2011, 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
@@ -17,59 +17,59 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
- # Module providing the operations to manipulate array expressions
21
- module Operations
20
+ # Base class for representing native datatypes and operations (terms)
21
+ class Node
22
22
 
23
- # Meta-programming method to define a unary operation
24
- #
25
- # @param [Symbol,String] op Name of unary operation.
26
- # @param [Symbol,String] conversion Name of method for type conversion.
27
- #
28
- # @return [Proc] The new method.
29
- #
30
- # @private
31
- def define_unary_op( op, conversion = :identity )
32
- define_method( op ) do
33
- if dimension == 0 and variables.empty?
34
- target = typecode.send conversion
35
- target.new simplify.get.send( op )
36
- else
37
- Hornetseye::ElementWise( lambda { |x| x.send op }, op,
38
- lambda { |t| t.send conversion } ).
39
- new( self ).force
23
+ class << self
24
+
25
+ # Meta-programming method to define a unary operation
26
+ #
27
+ # @param [Symbol,String] op Name of unary operation.
28
+ # @param [Symbol,String] conversion Name of method for type conversion.
29
+ #
30
+ # @return [Proc] The new method.
31
+ #
32
+ # @private
33
+ def define_unary_op(op, conversion = :identity)
34
+ Node.class_eval do
35
+ define_method op do
36
+ if dimension == 0 and variables.empty?
37
+ target = typecode.send conversion
38
+ target.new simplify.get.send(op)
39
+ else
40
+ Hornetseye::ElementWise(lambda { |x| x.send op }, op,
41
+ lambda { |t| t.send conversion }).
42
+ new(self).force
43
+ end
44
+ end
40
45
  end
41
46
  end
42
- end
43
-
44
- module_function :define_unary_op
45
47
 
46
- # Meta-programming method to define a binary operation
47
- #
48
- # @param [Symbol,String] op Name of binary operation.
49
- # @param [Symbol,String] conversion Name of method for type conversion.
50
- #
51
- # @return [Proc] The new method.
52
- #
53
- # @private
54
- def define_binary_op( op, coercion = :coercion )
55
- define_method( op ) do |other|
56
- unless other.is_a? Node
57
- other = Node.match( other, typecode ).new other
58
- end
59
- if dimension == 0 and variables.empty? and
60
- other.dimension == 0 and other.variables.empty?
61
- target = array_type.send coercion, other.array_type
62
- target.new simplify.get.send( op, other.simplify.get )
63
- else
64
- Hornetseye::ElementWise( lambda { |x,y| x.send op, y }, op,
65
- lambda { |t,u| t.send coercion, u } ).
66
- new( self, other ).force
48
+ # Meta-programming method to define a binary operation
49
+ #
50
+ # @param [Symbol,String] op Name of binary operation.
51
+ # @param [Symbol,String] conversion Name of method for type conversion.
52
+ #
53
+ # @return [Proc] The new method.
54
+ #
55
+ # @private
56
+ def define_binary_op(op, coercion = :coercion)
57
+ define_method op do |other|
58
+ other = Node.match(other, typecode).new other unless other.matched?
59
+ if dimension == 0 and variables.empty? and
60
+ other.dimension == 0 and other.variables.empty?
61
+ target = typecode.send coercion, other.typecode
62
+ target.new simplify.get.send(op, other.simplify.get)
63
+ else
64
+ Hornetseye::ElementWise(lambda { |x,y| x.send op, y }, op,
65
+ lambda { |t,u| t.send coercion, u } ).
66
+ new(sexp, other.sexp).force
67
+ end
67
68
  end
68
69
  end
69
- end
70
-
71
- module_function :define_binary_op
72
70
 
71
+ end
72
+
73
73
  define_unary_op :zero?, :bool
74
74
  define_unary_op :nonzero?, :bool
75
75
  define_unary_op :not, :bool
@@ -101,7 +101,6 @@ module Hornetseye
101
101
  define_binary_op :<, :coercion_bool
102
102
  define_binary_op :>=, :coercion_bool
103
103
  define_binary_op :>, :coercion_bool
104
- define_binary_op :<=>, :coercion_byte
105
104
  define_binary_op :minor
106
105
  define_binary_op :major
107
106
 
@@ -121,9 +120,7 @@ module Hornetseye
121
120
  #
122
121
  # @return [Node] Array with result of operation.
123
122
  def fmod_with_float( other )
124
- unless other.is_a? Node
125
- other = Node.match( other, typecode ).new other
126
- end
123
+ other = Node.match( other, typecode ).new other unless other.matched?
127
124
  if typecode < FLOAT_ or other.typecode < FLOAT_
128
125
  fmod other
129
126
  else
@@ -138,14 +135,14 @@ module Hornetseye
138
135
  # @param [Class] dest Element type to convert to.
139
136
  #
140
137
  # @return [Node] Array based on the different element type.
141
- def to_type( dest )
138
+ def to_type(dest)
142
139
  if dimension == 0 and variables.empty?
143
140
  target = typecode.to_type dest
144
- target.new( simplify.get ).simplify
141
+ target.new(simplify.get).simplify
145
142
  else
146
143
  key = "to_#{dest.to_s.downcase}"
147
144
  Hornetseye::ElementWise( lambda { |x| x.to_type dest }, key,
148
- lambda { |t| t.to_type dest } ).new( self ).force
145
+ lambda { |t| t.to_type dest } ).new(self).force
149
146
  end
150
147
  end
151
148
 
@@ -156,12 +153,12 @@ module Hornetseye
156
153
  # @param [Class] dest Element type to convert to.
157
154
  #
158
155
  # @return [Node] Array based on the different element type.
159
- def to_type_with_rgb( dest )
156
+ def to_type_with_rgb(dest)
160
157
  if typecode < RGB_
161
158
  if dest < FLOAT_
162
159
  lazy { r * 0.299 + g * 0.587 + b * 0.114 }.to_type dest
163
160
  elsif dest < INT_
164
- lazy { ( r * 0.299 + g * 0.587 + b * 0.114 ).round }.to_type dest
161
+ lazy { (r * 0.299 + g * 0.587 + b * 0.114).round }.to_type dest
165
162
  else
166
163
  to_type_without_rgb dest
167
164
  end
@@ -197,13 +194,13 @@ module Hornetseye
197
194
  # @param [Array<Integer>] ret_shape Desired shape of return value
198
195
  #
199
196
  # @return [Node] Array with desired shape.
200
- def reshape( *ret_shape )
201
- target = Hornetseye::MultiArray( typecode, *ret_shape )
202
- if target.size != size
203
- raise "#{target.size} is of size #{target.size} but should be of size " +
204
- "#{size}"
197
+ def reshape(*ret_shape)
198
+ target_size = ret_shape.inject { |a,b| a * b }
199
+ if target_size != size
200
+ raise "Target is of size #{target_size} but should be of size #{size}"
205
201
  end
206
- target.new memorise.memory
202
+ Hornetseye::MultiArray(typecode, ret_shape.size).
203
+ new *(ret_shape + [:memory => memorise.memory])
207
204
  end
208
205
 
209
206
  # Element-wise conditional selection of values
@@ -212,24 +209,19 @@ module Hornetseye
212
209
  # @param [Node] b Second array of values.
213
210
  #
214
211
  # @return [Node] Array with selected values.
215
- def conditional( a, b )
216
- unless a.is_a? Node
217
- a = Node.match( a, b.is_a?( Node ) ? b : nil ).new a
218
- end
219
- unless b.is_a? Node
220
- b = Node.match( b, a.is_a?( Node ) ? a : nil ).new b
221
- end
212
+ def conditional(a, b)
213
+ a = Node.match(a, b.matched? ? b : nil).new a unless a.matched?
214
+ b = Node.match(b, a.matched? ? a : nil).new b unless b.matched?
222
215
  if dimension == 0 and variables.empty? and
223
216
  a.dimension == 0 and a.variables.empty? and
224
217
  b.dimension == 0 and b.variables.empty?
225
- target = array_type.cond a.array_type, b.array_type
226
- #target.new simplify.get.conditional( a.simplify.get, b.simplify.get )
227
- target.new simplify.get.conditional( proc { a.simplify.get },
228
- proc { b.simplify.get } )
218
+ target = typecode.cond a.typecode, b.typecode
219
+ target.new simplify.get.conditional(proc { a.simplify.get },
220
+ proc { b.simplify.get })
229
221
  else
230
- Hornetseye::ElementWise( lambda { |x,y,z| x.conditional y, z }, :conditional,
231
- lambda { |t,u,v| t.cond u, v } ).
232
- new( self, a, b ).force
222
+ Hornetseye::ElementWise(lambda { |x,y,z| x.conditional y, z }, :conditional,
223
+ lambda { |t,u,v| t.cond u, v }).
224
+ new(self, a.sexp, b.sexp).force
233
225
  end
234
226
  end
235
227
 
@@ -266,10 +258,10 @@ module Hornetseye
266
258
  # @param [Node] other Array with values to compare with.
267
259
  #
268
260
  # @return [Node] Array with results.
269
- def <=>( other )
270
- Hornetseye::finalise do
271
- ( self < other ).conditional -1, ( self > other ).conditional( 1, 0 )
272
- end
261
+ def <=>(other)
262
+ Hornetseye::lazy do
263
+ (self < other).conditional -1, (self > other).conditional(1, 0)
264
+ end.force
273
265
  end
274
266
 
275
267
  # Lazy transpose of array
@@ -329,7 +321,7 @@ module Hornetseye
329
321
  def collect( &action )
330
322
  var = Variable.new typecode
331
323
  block = action.call var
332
- conversion = lambda { |t| t.to_type action.call( Variable.new( t.typecode ) ) }
324
+ conversion = lambda { |t| t.to_type action.call(Variable.new(t.typecode)).typecode }
333
325
  Hornetseye::ElementWise( action, block.to_s, conversion ).new( self ).force
334
326
  end
335
327
 
@@ -351,7 +343,7 @@ module Hornetseye
351
343
  # @return [Object] Result of injection.
352
344
  def inject( initial = nil, options = {} )
353
345
  unless initial.nil?
354
- initial = Node.match( initial ).new initial unless initial.is_a? Node
346
+ initial = Node.match( initial ).new initial unless initial.matched?
355
347
  initial_typecode = initial.typecode
356
348
  else
357
349
  initial_typecode = typecode
@@ -369,7 +361,7 @@ module Hornetseye
369
361
  index = Variable.new Hornetseye::INDEX( nil )
370
362
  value = element( index ).inject nil, :block => block,
371
363
  :var1 => var1, :var2 => var2
372
- value = typecode.new value unless value.is_a? Node
364
+ value = typecode.new value unless value.matched?
373
365
  if initial.nil? and index.size.get == 0
374
366
  raise "Array was empty and no initial value for injection was given"
375
367
  end
@@ -388,11 +380,11 @@ module Hornetseye
388
380
  # Equality operator
389
381
  #
390
382
  # @return [Boolean] Returns result of comparison.
391
- def eq_with_multiarray( other )
392
- if other.is_a? Node
383
+ def eq_with_multiarray(other)
384
+ if other.matched?
393
385
  if variables.empty?
394
- if other.array_type == array_type
395
- Hornetseye::finalise { eq( other ).inject( true ) { |a,b| a.and b } }
386
+ if other.typecode == typecode and other.shape == shape
387
+ Hornetseye::finalise { eq(other).inject( true ) { |a,b| a.and b } }
396
388
  else
397
389
  false
398
390
  end
@@ -515,9 +507,7 @@ module Hornetseye
515
507
  demand
516
508
  else
517
509
  if initial
518
- unless initial.is_a? Node
519
- initial = Node.match( initial ).new initial
520
- end
510
+ initial = Node.match( initial ).new initial unless initial.matched?
521
511
  initial_typecode = initial.typecode
522
512
  else
523
513
  initial_typecode = typecode
@@ -532,7 +522,7 @@ module Hornetseye
532
522
  diagonal initial, :block => block, :var1 => var1, :var2 => var2
533
523
  term = Diagonal.new( value, index0, index1, index2, initial,
534
524
  block, var1, var2 )
535
- index0.size[] ||= index1.size[]
525
+ index0.size = index1.size
536
526
  Lambda.new( index0, term ).force
537
527
  end
538
528
  end
@@ -550,7 +540,7 @@ module Hornetseye
550
540
  #
551
541
  # @private
552
542
  def table( filter, &action )
553
- filter = Node.match( filter, typecode ).new filter unless filter.is_a? Node
543
+ filter = Node.match( filter, typecode ).new filter unless filter.matched?
554
544
  if filter.dimension > dimension
555
545
  raise "Filter has #{filter.dimension} dimension(s) but should " +
556
546
  "not have more than #{dimension}"
@@ -569,10 +559,10 @@ module Hornetseye
569
559
  #
570
560
  # @return [Node] Result of convolution.
571
561
  def convolve( filter )
572
- filter = Node.match( filter, typecode ).new filter unless filter.is_a? Node
562
+ filter = Node.match( filter, typecode ).new filter unless filter.matched?
573
563
  array = self
574
- ( dimension - filter.dimension ).times { array = array.roll }
575
- array.table( filter ) { |a,b| a* b }.diagonal { |s,x| s + x }
564
+ (dimension - filter.dimension).times { array = array.roll }
565
+ array.table(filter.sexp) { |a,b| a * b }.diagonal { |s,x| s + x }
576
566
  end
577
567
 
578
568
  # Erosion
@@ -606,8 +596,8 @@ module Hornetseye
606
596
  # @return [Node] Result of Sobel operator.
607
597
  def sobel( direction )
608
598
  ( dimension - 1 ).downto( 0 ).inject self do |retval,i|
609
- filter = i == direction ? Hornetseye::Sequence( SINT, 3 )[ 1, 0, -1 ] :
610
- Hornetseye::Sequence( SINT, 3 )[ 1, 2, 1 ]
599
+ filter = i == direction ? Hornetseye::Sequence(SINT)[1, 0, -1] :
600
+ Hornetseye::Sequence(SINT)[1, 2, 1]
611
601
  Hornetseye::lazy { retval.convolve filter }
612
602
  end.force
613
603
  end
@@ -660,9 +650,8 @@ module Hornetseye
660
650
  def histogram( *ret_shape )
661
651
  options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
662
652
  options = { :weight => UINT.new( 1 ), :safe => true }.merge options
663
- unless options[ :weight ].is_a? Node
664
- options[ :weight ] =
665
- Node.match( options[ :weight ] ).maxint.new options[ :weight ]
653
+ unless options[:weight].matched?
654
+ options[:weight] = Node.match(options[:weight]).maxint.new options[:weight]
666
655
  end
667
656
  if ( shape.first != 1 or dimension == 1 ) and ret_shape.size == 1
668
657
  [ self ].histogram *( ret_shape + [ options ] )
@@ -718,8 +707,8 @@ module Hornetseye
718
707
  #
719
708
  # @return [Node] The integral image of this array.
720
709
  def integral
721
- left = pointer_type.new
722
- block = Integral.new left, self
710
+ left = allocate
711
+ block = Integral.new left.sexp, self
723
712
  if block.compilable?
724
713
  GCCFunction.run block
725
714
  else
@@ -741,20 +730,21 @@ module Hornetseye
741
730
  options = { :target => UINT, :default => typecode.default }.merge options
742
731
  target = options[ :target ]
743
732
  default = options[ :default ]
744
- default = typecode.new default unless default.is_a? Node
745
- left = Hornetseye::MultiArray( target, *shape ).new
733
+ default = typecode.new default unless default.matched?
734
+ left = Hornetseye::MultiArray(target, dimension).new *shape
746
735
  labels = Sequence.new target, size; labels[0] = 0
747
736
  rank = Sequence.uint size; rank[0] = 0
748
737
  n = Hornetseye::Pointer( INT ).new; n.store INT.new( 0 )
749
- block = Components.new left, self, default, target.new( 0 ), labels, rank, n
738
+ block = Components.new left.sexp, self, default.sexp, target.new(0),
739
+ labels.sexp, rank.sexp, n
750
740
  if block.compilable?
751
741
  Hornetseye::GCCFunction.run block
752
742
  else
753
743
  block.demand
754
744
  end
755
- labels = labels[ 0 .. n.demand.get ]
756
- left.lut labels.lut( labels.histogram( labels.size, :weight => target.new( 1 ) ).
757
- minor( 1 ).integral - 1 )
745
+ labels = labels[0 .. n.demand.get]
746
+ left.lut labels.lut(labels.histogram(labels.size, :weight => target.new(1)).
747
+ minor(1).integral - 1)
758
748
  end
759
749
 
760
750
  # Select values from array using a mask
@@ -768,13 +758,13 @@ module Hornetseye
768
758
  [ m.size ] )
769
759
  index = Hornetseye::Pointer( INT ).new
770
760
  index.store INT.new( 0 )
771
- block = Mask.new left, self, m, index
761
+ block = Mask.new left.sexp, self, m.sexp, index
772
762
  if block.compilable?
773
763
  GCCFunction.run block
774
764
  else
775
765
  block.demand
776
766
  end
777
- left[ 0 ... index[] ].roll
767
+ left[0 ... index[]].roll
778
768
  end
779
769
 
780
770
  # Distribute values in a new array using a mask
@@ -788,8 +778,8 @@ module Hornetseye
788
778
  # @return [Node] The result of the inverse masking operation.
789
779
  def unmask( m, options = {} )
790
780
  options = { :safe => true, :default => typecode.default }.merge options
791
- default = options[ :default ]
792
- default = typecode.new default unless default.is_a? Node
781
+ default = options[:default]
782
+ default = typecode.new default unless default.matched?
793
783
  m.check_shape default
794
784
  if options[ :safe ]
795
785
  if m.to_ubyte.sum > shape.last
@@ -797,11 +787,11 @@ module Hornetseye
797
787
  "dimension of the array for unmasking only has #{shape.last} value(s)"
798
788
  end
799
789
  end
800
- left = Hornetseye::MultiArray( array_type.element_type, *m.shape ).
801
- coercion( default.array_type ).new
802
- index = Hornetseye::Pointer( INT ).new
803
- index.store INT.new( 0 )
804
- block = Unmask.new left, self, m, index, default
790
+ left = Hornetseye::MultiArray(typecode, dimension - 1 + m.dimension).
791
+ coercion(default.typecode).new *(shape[1 .. -1] + m.shape)
792
+ index = Hornetseye::Pointer(INT).new
793
+ index.store INT.new(0)
794
+ block = Unmask.new left.sexp, self, m.sexp, index, default.sexp
805
795
  if block.compilable?
806
796
  GCCFunction.run block
807
797
  else
@@ -836,7 +826,7 @@ module Hornetseye
836
826
  raise "#{offset.size} offset(s) were given but array has " +
837
827
  "#{dimension} dimension(s)"
838
828
  end
839
- retval = array_type.new
829
+ retval = Hornetseye::MultiArray(typecode, dimension).new *shape
840
830
  target, source, open, close = [], [], [], []
841
831
  ( shape.size - 1 ).step( 0, -1 ) do |i|
842
832
  callcc do |pass|
@@ -905,12 +895,6 @@ module Hornetseye
905
895
 
906
896
  end
907
897
 
908
- class Node
909
-
910
- include Operations
911
-
912
- end
913
-
914
898
  end
915
899
 
916
900
  # The +Array+ class is extended with a few methods
@@ -929,8 +913,8 @@ class Array
929
913
  def histogram( *ret_shape )
930
914
  options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
931
915
  options = { :weight => Hornetseye::UINT. new( 1 ), :safe => true }.merge options
932
- unless options[ :weight ].is_a? Hornetseye::Node
933
- options[ :weight ] =
916
+ unless options[:weight].matched?
917
+ options[:weight] =
934
918
  Hornetseye::Node.match( options[ :weight ] ).maxint.new options[ :weight ]
935
919
  end
936
920
  weight = options[ :weight ]
@@ -939,9 +923,8 @@ class Array
939
923
  raise "Number of arrays for histogram (#{size}) differs from number of " +
940
924
  "dimensions of histogram (#{ret_shape.size})"
941
925
  end
942
- array_types = collect { |source| source.array_type }
943
- source_type = array_types.inject { |a,b| a.coercion b }
944
- source_type.check_shape *array_types
926
+ source_type = inject { |a,b| a.dimension > b.dimension ? a : b }
927
+ source_type.check_shape *self
945
928
  source_type.check_shape options[ :weight ]
946
929
  for i in 0 ... size
947
930
  range = self[ i ].range 0 ... ret_shape[ i ]
@@ -955,9 +938,9 @@ class Array
955
938
  end
956
939
  end
957
940
  end
958
- left = Hornetseye::MultiArray.new weight.typecode, *ret_shape
941
+ left = Hornetseye::MultiArray(weight.typecode, ret_shape.size).new *ret_shape
959
942
  left[] = 0
960
- block = Hornetseye::Histogram.new left, weight, *self
943
+ block = Hornetseye::Histogram.new left.sexp, weight.sexp, *self
961
944
  if block.compilable?
962
945
  Hornetseye::GCCFunction.run block
963
946
  else
@@ -980,9 +963,8 @@ class Array
980
963
  raise "Number of arrays for lookup (#{size}) is greater than the " +
981
964
  "number of dimensions of LUT (#{table.dimension})"
982
965
  end
983
- array_types = collect { |source| source.array_type }
984
- source_type = array_types.inject { |a,b| a.coercion b }
985
- source_type.check_shape *array_types
966
+ source_type = inject { |a,b| a.dimension > b.dimension ? a : b }
967
+ source_type.check_shape *self
986
968
  for i in 0 ... size
987
969
  offset = table.dimension - size
988
970
  range = self[ i ].range 0 ... table.shape[ i + offset ]