multiarray 0.11.4 → 0.12.0

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.
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