multiarray 0.11.4 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rake/packagetask'
6
6
  require 'rbconfig'
7
7
 
8
8
  PKG_NAME = 'multiarray'
9
- PKG_VERSION = '0.11.4'
9
+ PKG_VERSION = '0.12.0'
10
10
  RB_FILES = FileList[ 'lib/**/*.rb' ]
11
11
  TC_FILES = FileList[ 'test/tc_*.rb' ]
12
12
  TS_FILES = FileList[ 'test/ts_*.rb' ]
data/lib/multiarray.rb CHANGED
@@ -523,7 +523,7 @@ class Numeric
523
523
 
524
524
  end
525
525
 
526
- # The +Array+ class is extended
526
+ # The +Array+ class is extended with a few methods
527
527
  class Array
528
528
 
529
529
  # Element-wise operation based on element and its index
@@ -56,9 +56,7 @@ module Hornetseye
56
56
  function = GCCFunction.new context, method_name,
57
57
  *keys.collect { |var| var.meta }
58
58
  Thread.current[ :function ] = function
59
- term_subst = ( 0 ... keys.size ).collect do |i|
60
- { keys[i] => function.param( i ) }
61
- end.inject( {} ) { |a,b| a.merge b }
59
+ term_subst = Hash[ *keys.zip( function.params ).flatten ]
62
60
  Hornetseye::lazy do
63
61
  term.subst( term_subst ).demand
64
62
  end
@@ -144,20 +142,21 @@ module Hornetseye
144
142
  @indent += offset
145
143
  end
146
144
 
147
- # Retrieve a parameter
145
+ # Retrieve all parameters
148
146
  #
149
- # @param [Integer] i Parameter to retrieve.
150
- #
151
- # @return [Node] Object for handling the parameter.
147
+ # @return [Array<Node>] Objects for handling the parameters.
152
148
  #
153
149
  # @private
154
- def param( i )
155
- offset = ( 0 ... i ).inject( 0 ) do |s,idx|
156
- s + GCCType.new( @param_types[ idx ] ).identifiers.size
150
+ def params
151
+ idx = 0
152
+ @param_types.collect do |param_type|
153
+ args = GCCType.new( param_type ).identifiers.collect do
154
+ arg = GCCValue.new self, "param#{idx}"
155
+ idx += 1
156
+ arg
157
+ end
158
+ param_type.construct *args
157
159
  end
158
- args = ( 0 ... GCCType.new( @param_types[ i ] ).identifiers.size ).
159
- collect { |idx| GCCValue.new self, "param#{ offset + idx }" }
160
- @param_types[ i ].construct *args
161
160
  end
162
161
 
163
162
  # Call the native method
@@ -36,11 +36,11 @@ module Hornetseye
36
36
  # Constructor
37
37
  #
38
38
  # @param [Node] dest Target array to write histogram to.
39
- # @param [Node] source Expression to compute histogram of.
39
+ # @param [Array<Node>] sources Arrays with elements to compute histogram of.
40
40
  #
41
41
  # @private
42
- def initialize( dest, source )
43
- @dest, @source = dest, source
42
+ def initialize( dest, *sources )
43
+ @dest, @sources = dest, sources
44
44
  end
45
45
 
46
46
  # Get unique descriptor of this object
@@ -51,7 +51,8 @@ module Hornetseye
51
51
  #
52
52
  # @private
53
53
  def descriptor( hash )
54
- "Histogram(#{@dest.descriptor( hash )},#{@source.descriptor( hash )})"
54
+ "Histogram(#{@dest.descriptor( hash )}," +
55
+ "#{@sources.collect { |source| source.descriptor( hash ) }.join ','})"
55
56
  end
56
57
 
57
58
  # Get type of result of delayed operation
@@ -76,15 +77,19 @@ module Hornetseye
76
77
  # @private
77
78
  def demand
78
79
  if variables.empty?
79
- if @source.dimension > 1
80
- @source.shape.last.times do |i|
81
- source = @source.element INT.new( i )
82
- Histogram.new( @dest, source ).demand
80
+ if @sources.any? { |source| source.dimension > 0 }
81
+ source_type = @sources.collect { |source| source.array_type }.
82
+ inject { |a,b| a.coercion b }
83
+ source_type.shape.last.times do |i|
84
+ sources = @sources.collect do |source|
85
+ source.dimension > 0 ? source.element( INT.new( i ) ) : source
86
+ end
87
+ Histogram.new( @dest, *sources ).demand
83
88
  end
84
89
  else
85
90
  dest = @dest
86
91
  ( @dest.dimension - 1 ).downto( 0 ) do |i|
87
- dest = dest.element @source.element( INT.new( i ) ).demand
92
+ dest = dest.element @sources[ i ].demand
88
93
  end
89
94
  dest.store dest + 1
90
95
  end
@@ -104,7 +109,8 @@ module Hornetseye
104
109
  #
105
110
  # @private
106
111
  def subst( hash )
107
- self.class.new @dest.subst( hash ), @source.subst( hash )
112
+ self.class.new @dest.subst( hash ),
113
+ *@sources.collect { |source| source.subst hash }
108
114
  end
109
115
 
110
116
  # Get variables contained in this term
@@ -113,7 +119,7 @@ module Hornetseye
113
119
  #
114
120
  # @private
115
121
  def variables
116
- @dest.variables + @source.variables
122
+ @sources.inject( @dest.variables ) { |a,b| a + b.variables }
117
123
  end
118
124
 
119
125
  # Strip of all values
@@ -126,9 +132,10 @@ module Hornetseye
126
132
  #
127
133
  # @private
128
134
  def strip
129
- vars1, values1, term1 = @dest.strip
130
- vars2, values2, term2 = @source.strip
131
- return vars1 + vars2, values1 + values2, self.class.new( term1, term2 )
135
+ stripped = ( [ @dest ] + @sources ).collect { |source| source.strip }
136
+ return stripped.inject( [] ) { |vars,elem| vars + elem[ 0 ] },
137
+ stripped.inject( [] ) { |values,elem| values + elem[ 1 ] },
138
+ self.class.new( *stripped.collect { |elem| elem[ 2 ] } )
132
139
  end
133
140
 
134
141
  # Check whether this term is compilable
@@ -137,7 +144,7 @@ module Hornetseye
137
144
  #
138
145
  # @private
139
146
  def compilable?
140
- @dest.compilable? and @source.compilable?
147
+ @dest.compilable? and @sources.all? { |source| source.compilable? }
141
148
  end
142
149
 
143
150
  end
@@ -35,14 +35,13 @@ module Hornetseye
35
35
 
36
36
  # Constructor
37
37
  #
38
- # @param [Node] dest Target array to write histogram to.
39
- # @param [Node] source Expression to compute histogram of.
40
- # @param [Integer] n Number of dimensions of lookup.
38
+ # @overload initialize( *sources, table )
39
+ # @param [Array<Node>] sources Arrays with elements for lookup
40
+ # @param [Node] table Lookup table
41
41
  #
42
42
  # @private
43
- def initialize( source, table, n = nil )
44
- @source, @table = source, table
45
- @n = n || @source.shape.first
43
+ def initialize( *args )
44
+ @sources, @table = args[ 0 ... -1 ], args.last
46
45
  end
47
46
 
48
47
  # Get unique descriptor of this object
@@ -53,7 +52,8 @@ module Hornetseye
53
52
  #
54
53
  # @private
55
54
  def descriptor( hash )
56
- "Lut(#{@source.descriptor( hash )},#{@table.descriptor( hash )},#{@n})"
55
+ "Lut(#{@sources.collect { |source| source.descriptor( hash ) }.join ','}," +
56
+ "#{@table.descriptor( hash )})"
57
57
  end
58
58
 
59
59
  # Get type of result of delayed operation
@@ -62,7 +62,10 @@ module Hornetseye
62
62
  #
63
63
  # @private
64
64
  def array_type
65
- shape = @table.shape.first( @table.dimension - @n ) + @source.shape[ 1 .. -1 ]
65
+ source_type = @sources.collect { |source| source.array_type }.
66
+ inject { |a,b| a.coercion b }
67
+ shape = @table.shape.first( @table.dimension - @sources.size ) +
68
+ source_type.shape
66
69
  retval = Hornetseye::MultiArray @table.typecode, *shape
67
70
  ( class << self; self; end ).instance_eval do
68
71
  define_method( :array_type ) { retval }
@@ -78,7 +81,7 @@ module Hornetseye
78
81
  #
79
82
  # @private
80
83
  def demand
81
- @source.lut @table, :n => @n, :safe => false
84
+ @sources.lut @table, :safe => false
82
85
  end
83
86
 
84
87
  # Substitute variables
@@ -91,7 +94,8 @@ module Hornetseye
91
94
  #
92
95
  # @private
93
96
  def subst( hash )
94
- self.class.new @source.subst( hash ), @table.subst( hash ), @n
97
+ self.class.new *( @sources.collect { |source| source.subst hash } +
98
+ [ @table.subst( hash ) ] )
95
99
  end
96
100
 
97
101
  # Get variables contained in this term
@@ -100,7 +104,7 @@ module Hornetseye
100
104
  #
101
105
  # @private
102
106
  def variables
103
- @source.variables + @table.variables
107
+ @sources.inject( @table.variables ) { |a,b| a + b.variables }
104
108
  end
105
109
 
106
110
  # Strip of all values
@@ -113,9 +117,10 @@ module Hornetseye
113
117
  #
114
118
  # @private
115
119
  def strip
116
- vars1, values1, term1 = @source.strip
117
- vars2, values2, term2 = @table.strip
118
- return vars1 + vars2, values1 + values2, self.class.new( term1, term2, @n )
120
+ stripped = ( @sources + [ @table ] ).collect { |source| source.strip }
121
+ return stripped.inject( [] ) { |vars,elem| vars + elem[ 0 ] },
122
+ stripped.inject( [] ) { |values,elem| values + elem[ 1 ] },
123
+ self.class.new( *stripped.collect { |elem| elem[ 2 ] } )
119
124
  end
120
125
 
121
126
  # Skip elements of an array
@@ -128,7 +133,8 @@ module Hornetseye
128
133
  #
129
134
  # @private
130
135
  def skip( index, start )
131
- self.class.new @source.skip( index, start ), @table.skip( index, start ), @n
136
+ self.class.new *( @sources.skip( index, start ) +
137
+ [ @table.skip( index, start ) ] )
132
138
  end
133
139
 
134
140
  # Get element of unary operation
@@ -139,12 +145,14 @@ module Hornetseye
139
145
  #
140
146
  # @private
141
147
  def element( i )
142
- source, table = @source, @table
143
- if source.dimension > 1
144
- source = source.element i
145
- self.class.new source, table, @n
146
- elsif table.dimension > @n
147
- self.class.new source, table.unroll( @n ).element( i ).roll( @n ), @n
148
+ sources, table = @sources, @table
149
+ if sources.any? { |source| source.dimension > 0 }
150
+ sources = sources.
151
+ collect { |source| source.dimension > 0 ? source.element( i ) : source }
152
+ self.class.new *( sources + [ table ] )
153
+ elsif table.dimension > sources.size
154
+ n = sources.size
155
+ self.class.new *( sources + [ table.unroll( n ).element( i ).roll( n ) ] )
148
156
  else
149
157
  super i
150
158
  end
@@ -178,7 +186,7 @@ module Hornetseye
178
186
  #
179
187
  # @return [Node] Result of decomposition.
180
188
  def decompose( i )
181
- self.class.new @source, @table.decompose( i ), @n
189
+ self.class.new *( @sources + [ @table.decompose( i ) ] )
182
190
  end
183
191
 
184
192
  # Check whether this term is compilable
@@ -187,7 +195,7 @@ module Hornetseye
187
195
  #
188
196
  # @private
189
197
  def compilable?
190
- @source.compilable? and @table.compilable?
198
+ @sources.all? { |source| source.compilable? } and @table.compilable?
191
199
  end
192
200
 
193
201
  end
@@ -308,6 +308,31 @@ module Hornetseye
308
308
  hash[ self ] || self
309
309
  end
310
310
 
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
+
311
336
  # Check whether this term is compilable
312
337
  #
313
338
  # @return [Boolean] Returns +true+.
@@ -595,22 +620,10 @@ module Hornetseye
595
620
  #
596
621
  # @return [Object] The return value should be ignored.
597
622
  def check_shape( *args )
598
- _shape = shape
599
- args.each do |arg|
600
- _arg_shape = arg.shape
601
- if _shape.size < _arg_shape.size
602
- raise "#{arg.array_type.inspect} has #{arg.dimension} dimension(s) " +
603
- "but should not have more than #{dimension}"
604
- end
605
- if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer }
606
- if _shape.last( _arg_shape.size ) != _arg_shape
607
- raise "#{arg.array_type.inspect} has shape #{arg.shape.inspect} " +
608
- "(does not match last value(s) of #{shape.inspect})"
609
- end
610
- end
611
- end
623
+ array_type.check_shape *args.collect { |arg| arg.array_type }
612
624
  end
613
625
 
626
+
614
627
  # Assign value to array element(s)
615
628
  #
616
629
  # @overload []=( *indices, value )
@@ -121,7 +121,7 @@ module Hornetseye
121
121
  def to_type( dest )
122
122
  if dimension == 0 and variables.empty?
123
123
  target = typecode.to_type dest
124
- target.new simplify.get
124
+ target.new( simplify.get ).simplify
125
125
  else
126
126
  key = "to_#{dest.to_s.downcase}"
127
127
  Hornetseye::ElementWise( lambda { |x| x.to_type dest }, key,
@@ -456,6 +456,7 @@ module Hornetseye
456
456
  #
457
457
  # @overload histogram( *ret_shape, options = {} )
458
458
  # @param [Array<Integer>] ret_shape Dimensions of resulting histogram.
459
+ # @option options [Class] :target (UINT) Element-type of resulting histogram.
459
460
  # @option options [Boolean] :safe (true) Do a boundary check before creating the
460
461
  # histogram.
461
462
  #
@@ -463,41 +464,12 @@ module Hornetseye
463
464
  def histogram( *ret_shape )
464
465
  options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
465
466
  options = { :target => UINT, :safe => true }.merge options
466
- if options[ :safe ]
467
- if shape.first != 1 and ret_shape.size == 1
468
- right = Hornetseye::lazy( 1 ) { self }.unroll
469
- else
470
- if shape.first != ret_shape.size
471
- raise "First dimension of array (#{shape.first}) differs from number of " +
472
- "dimensions of histogram (#{ret_shape.size})"
473
- end
474
- right = self
475
- end
476
- else
477
- right = self
478
- end
479
- if options[ :safe ]
480
- for i in 0 ... right.shape.first
481
- range = right.roll[ i ].range
482
- if range.begin < 0
483
- raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
484
- "(but was #{range.begin})"
485
- end
486
- if range.end >= ret_shape[ i ]
487
- raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
488
- "(but was #{range.end})"
489
- end
490
- end
491
- end
492
- left = MultiArray.new options[ :target ], *ret_shape
493
- left[] = 0
494
- block = Histogram.new left, right
495
- if block.compilable?
496
- GCCFunction.run block
467
+ if shape.first != 1 and ret_shape.size == 1
468
+ [ self ].histogram *( ret_shape + [ options ] )
497
469
  else
498
- block.demand
470
+ ( 0 ... shape.first ).collect { |i| unroll[i] }.
471
+ histogram *( ret_shape + [ options ] )
499
472
  end
500
- left
501
473
  end
502
474
 
503
475
  # Perform element-wise lookup
@@ -508,42 +480,10 @@ module Hornetseye
508
480
  #
509
481
  # @return [Node] The result of the lookup operation.
510
482
  def lut( table, options = {} )
511
- options = { :safe => true }.merge options
512
- if options[ :safe ]
513
- if shape.first != 1 and table.dimension == 1
514
- source = Hornetseye::lazy( 1 ) { |i| self }.unroll
515
- else
516
- if shape.first > table.dimension
517
- raise "First dimension of array (#{shape.first}) is greater than the " +
518
- " number of dimensions of LUT (#{table.dimension})"
519
- end
520
- source = self
521
- end
483
+ if shape.first != 1 and table.dimension == 1
484
+ [ self ].lut table, options
522
485
  else
523
- source = self
524
- end
525
- if options[ :safe ]
526
- for i in 0 ... source.shape.first
527
- range = source.roll[ i ].range
528
- if range.begin < 0
529
- raise "#{i+1}th dimension of index must be in 0 ... #{table.shape[i]} " +
530
- "(but was #{range.begin})"
531
- end
532
- offset = table.dimension - source.shape.first
533
- if range.end >= table.shape[ i + offset ]
534
- raise "#{i+1}th dimension of index must be in 0 ... " +
535
- "#{table.shape[ i + offset ]} (but was #{range.end})"
536
- end
537
- end
538
- end
539
- if source.dimension <= 1 and variables.empty?
540
- result = table
541
- ( table.dimension - 1 ).downto( 0 ) do |i|
542
- result = result.element source.element( INT.new( i ) ).demand
543
- end
544
- result
545
- else
546
- Lut.new( source, table, options[ :n ] ).force
486
+ ( 0 ... shape.first ).collect { |i| unroll[i] }.lut table, options
547
487
  end
548
488
  end
549
489
 
@@ -570,3 +510,94 @@ module Hornetseye
570
510
  end
571
511
 
572
512
  end
513
+
514
+ # The +Array+ class is extended with a few methods
515
+ class Array
516
+
517
+ # Compute histogram of this array
518
+ #
519
+ # @overload histogram( *ret_shape, options = {} )
520
+ # @param [Array<Integer>] ret_shape Dimensions of resulting histogram.
521
+ # @option options [Class] :target (Hornetseye::UINT) Element-type of resulting
522
+ # histogram.
523
+ # @option options [Boolean] :safe (true) Do a boundary check before creating the
524
+ # histogram.
525
+ #
526
+ # @return [Node] The histogram.
527
+ def histogram( *ret_shape )
528
+ options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
529
+ options = { :target => Hornetseye::UINT, :safe => true }.merge options
530
+ if options[ :safe ]
531
+ if size != ret_shape.size
532
+ raise "Number of arrays for histogram (#{size}) differs from number of " +
533
+ "dimensions of histogram (#{ret_shape.size})"
534
+ end
535
+ array_types = collect { |source| source.array_type }
536
+ source_type = array_types.inject { |a,b| a.coercion b }
537
+ source_type.check_shape *array_types
538
+ for i in 0 ... size
539
+ range = self[ i ].range
540
+ if range.begin < 0
541
+ raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
542
+ "(but was #{range.begin})"
543
+ end
544
+ if range.end >= ret_shape[ i ]
545
+ raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
546
+ "(but was #{range.end})"
547
+ end
548
+ end
549
+ end
550
+ left = Hornetseye::MultiArray.new options[ :target ], *ret_shape
551
+ left[] = 0
552
+ block = Hornetseye::Histogram.new left, *self
553
+ if block.compilable?
554
+ Hornetseye::GCCFunction.run block
555
+ else
556
+ block.demand
557
+ end
558
+ left
559
+ end
560
+
561
+ # Perform element-wise lookup
562
+ #
563
+ # @param [Node] table The lookup table (LUT).
564
+ # @option options [Boolean] :safe (true) Do a boundary check before creating the
565
+ # element-wise lookup.
566
+ #
567
+ # @return [Node] The result of the lookup operation.
568
+ def lut( table, options = {} )
569
+ options = { :safe => true }.merge options
570
+ if options[ :safe ]
571
+ if size > table.dimension
572
+ raise "Number of arrays for lookup (#{size}) is greater than the " +
573
+ " number of dimensions of LUT (#{table.dimension})"
574
+ end
575
+ array_types = collect { |source| source.array_type }
576
+ source_type = array_types.inject { |a,b| a.coercion b }
577
+ source_type.check_shape *array_types
578
+ for i in 0 ... size
579
+ range = self[ i ].range
580
+ if range.begin < 0
581
+ raise "#{i+1}th index must be in 0 ... #{table.shape[i]} " +
582
+ "(but was #{range.begin})"
583
+ end
584
+ offset = table.dimension - size
585
+ if range.end >= table.shape[ i + offset ]
586
+ raise "#{i+1}th index must be in 0 ... " +
587
+ "#{table.shape[ i + offset ]} (but was #{range.end})"
588
+ end
589
+ end
590
+ end
591
+ if all? { |source| source.dimension == 0 and source.variables.empty? }
592
+ result = table
593
+ ( table.dimension - 1 ).downto( 0 ) do |i|
594
+ result = result.element self[ i ].demand
595
+ end
596
+ result
597
+ else
598
+ Hornetseye::Lut.new( *( self + [ table ] ) ).force
599
+ end
600
+ end
601
+
602
+ end
603
+
@@ -617,6 +617,27 @@ module Hornetseye
617
617
  end
618
618
  end
619
619
 
620
+ # Histograms
621
+ def histogram_with_rgb( *ret_shape )
622
+ if typecode < RGB_
623
+ [ r, g, b ].histogram *ret_shape
624
+ else
625
+ histogram_without_rgb *ret_shape
626
+ end
627
+ end
628
+
629
+ alias_method_chain :histogram, :rgb
630
+
631
+ def lut_with_rgb( table, options = {} )
632
+ if typecode < RGB_
633
+ [ r, g, b ].lut table, options
634
+ else
635
+ lut_without_rgb table, options
636
+ end
637
+ end
638
+
639
+ alias_method_chain :lut, :rgb
640
+
620
641
  end
621
642
 
622
643
  # Create a class deriving from +RGB_+ or instantiate an +RGB+ object
@@ -220,6 +220,31 @@ module Hornetseye
220
220
  element_type.dimension + 1
221
221
  end
222
222
 
223
+ # Check arguments for compatible shape
224
+ #
225
+ # The method will throw an exception if one of the arguments has an incompatible
226
+ # shape.
227
+ #
228
+ # @param [Array<Class>] args Arguments to check for compatibility.
229
+ #
230
+ # @return [Object] The return value should be ignored.
231
+ def check_shape( *args )
232
+ _shape = shape
233
+ args.each do |arg|
234
+ _arg_shape = arg.shape
235
+ if _shape.size < _arg_shape.size
236
+ raise "#{arg.inspect} has #{arg.dimension} dimension(s) " +
237
+ "but should not have more than #{dimension}"
238
+ end
239
+ if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer }
240
+ if _shape.last( _arg_shape.size ) != _arg_shape
241
+ raise "#{arg.inspect} has shape #{arg.shape.inspect} " +
242
+ "(does not match last value(s) of #{shape.inspect})"
243
+ end
244
+ end
245
+ end
246
+ end
247
+
223
248
  # Check whether delayed operation will have colour
224
249
  #
225
250
  # @return [Boolean] Boolean indicating whether the array has elements of type
@@ -432,13 +432,19 @@ class TC_MultiArray < Test::Unit::TestCase
432
432
  M[ [ 1, 2 ], [ 3, 3 ] ].histogram( 5, :target => I )
433
433
  assert_equal M( I, 2, 2 )[ [ 1, 0 ], [ 1, 1 ] ],
434
434
  M[ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ] ].histogram( 2, 2, :target => I )
435
- #assert_equal M( I, 2, 2, 1 )[ [ [ 0, 1 ], [ 1, 0 ] ] ],
436
- # S[ C( 1, 0, 0 ), C( 0, 1, 0 ) ].histogram( 2, 2, 1, :target => I )
435
+ assert_equal M( I, 2, 2 )[ [ 1, 0 ], [ 1, 1 ] ],
436
+ [ S[ 0, 0, 1 ], S[ 0, 1, 1 ] ].histogram( 2, 2, :target => I )
437
+ assert_equal M( I, 2, 2, 1 )[ [ [ 0, 1 ], [ 1, 0 ] ] ],
438
+ S[ C( 1, 0, 0 ), C( 0, 1, 0 ) ].histogram( 2, 2, 1, :target => I )
437
439
  assert_raise( RuntimeError ) { S[ 1, 2, 3 ].histogram 4, 4 }
438
440
  assert_raise( RuntimeError ) { M[ [ -1, 0 ] ].histogram 3, 2 }
439
441
  assert_raise( RuntimeError ) { M[ [ 0, -1 ] ].histogram 3, 2 }
440
442
  assert_raise( RuntimeError ) { M[ [ 3, 0 ] ].histogram 3, 2 }
441
443
  assert_raise( RuntimeError ) { M[ [ 0, 2 ] ].histogram 3, 2 }
444
+ assert_raise( RuntimeError ) { [ S[ -1, 0 ], S[ 0, 1 ] ].histogram 3, 2 }
445
+ assert_raise( RuntimeError ) { [ S[ 0, 3 ], S[ 0, 1 ] ].histogram 3, 2 }
446
+ assert_raise( RuntimeError ) { [ S[ 0, 0, 1 ], S[ 0, 1 ] ].histogram 3, 2 }
447
+ assert_raise( RuntimeError ) { [ S[ 0, 1 ], S[ 0, 1 ] ].histogram 3 }
442
448
  end
443
449
 
444
450
  def test_lut
@@ -446,14 +452,25 @@ class TC_MultiArray < Test::Unit::TestCase
446
452
  M[ [ 0, 1 ], [ 2, 0 ] ].lut( S[ 1, 2, 3, 4 ] )
447
453
  assert_equal M[ 1, 3, 4 ],
448
454
  M[ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ] ].lut( M[ [ 1, 2 ], [ 3, 4 ] ] )
455
+ assert_equal M[ 1, 3, 4 ],
456
+ [ S[ 0, 0, 1 ], S[ 0, 1, 1 ] ].lut( M[ [ 1, 2 ], [ 3, 4 ] ] )
449
457
  assert_equal M[ [ 3, 4 ], [ 1, 2 ] ],
450
458
  M[ [ 1 ], [ 0 ] ].lut( M[ [ 1, 2 ], [ 3, 4 ] ] )
459
+ assert_equal S[ 2, 3 ], S[ C( 1, 0, 0 ), C( 0, 1, 0 ) ].
460
+ lut( M[ [ [ 1, 2 ], [ 3, 4 ] ] ] )
451
461
  assert_raise( RuntimeError ) { S[ 0, 1, 2 ].lut M[ [ 1, 2 ], [ 3, 4 ] ] }
452
462
  assert_raise( RuntimeError ) { M[ [ -1, 0 ] ].lut M[ [ 1, 2 ] ] }
453
463
  assert_raise( RuntimeError ) { M[ [ 0, -1 ] ].lut M[ [ 1, 2 ] ] }
454
464
  assert_raise( RuntimeError ) { M[ [ 2, 0 ] ].lut M[ [ 1, 2 ] ] }
455
465
  assert_raise( RuntimeError ) { M[ [ 0, 1 ] ].lut M[ [ 1, 2 ] ] }
456
466
  assert_raise( RuntimeError ) { M[ [ 1 ], [ 2 ] ].lut M[ [ 1, 2 ], [ 3, 4 ] ] }
467
+ assert_raise( RuntimeError ) { [ S[ -1, 0 ], S[ 0, 1 ] ].
468
+ lut M[ [ 1, 2 ], [ 3, 4 ] ] }
469
+ assert_raise( RuntimeError ) { [ S[ 0, 0 ], S[ 0, 2 ] ].
470
+ lut M[ [ 1, 2 ], [ 3, 4 ] ] }
471
+ assert_raise( RuntimeError ) { [ S[ 0, 0, 1 ], S[ 0, 1 ] ].
472
+ lut M[ [ 1, 2 ], [ 3, 4 ] ] }
473
+ assert_raise( RuntimeError ) { [ S[ 0, 1 ], S[ 0, 1 ] ].lut S[ 1, 2 ] }
457
474
  end
458
475
 
459
476
  def test_zero
data/test/tc_sequence.rb CHANGED
@@ -345,6 +345,8 @@ class TC_Sequence < Test::Unit::TestCase
345
345
  [ O, I ].each do |t|
346
346
  assert_equal S( t, 5 )[ 0, 1, 2, 1, 1 ],
347
347
  S( t, 5 )[ 1, 2, 2, 3, 4 ].histogram( 5, :target => t )
348
+ assert_equal S( t, 4 )[ 0, 1, 1, 0 ],
349
+ S( t, 2 )[ 1.0, 2.0 ].histogram( 4, :target => t )
348
350
  end
349
351
  assert_raise( RuntimeError ) { S[ -1, 0, 1 ].histogram 3 }
350
352
  assert_raise( RuntimeError ) { S[ 1, 2, 3 ].histogram 3 }
@@ -355,6 +357,8 @@ class TC_Sequence < Test::Unit::TestCase
355
357
  [ O, I ].each do |t|
356
358
  assert_equal S( t, 4 )[ 3, 1, 2, 1 ],
357
359
  S( t, 4 )[ 0, 2, 1, 2 ].lut( S( t, 3 )[ 3, 2, 1 ] )
360
+ assert_equal S( t, 2 )[ 2, 1 ],
361
+ S( t, 2 )[ 1.0, 2.0 ].lut( S( t, 3 )[ 3, 2, 1 ] )
358
362
  end
359
363
  assert_raise( RuntimeError ) { S[ -1, 0 ].lut S[ 0, 1 ] }
360
364
  assert_raise( RuntimeError ) { S[ 1, 2 ].lut S[ 0, 1 ] }
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 11
8
- - 4
9
- version: 0.11.4
7
+ - 12
8
+ - 0
9
+ version: 0.12.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jan Wedekind
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-18 00:00:00 +00:00
17
+ date: 2010-12-05 00:00:00 +00:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency