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
@@ -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 ]