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 +1 -1
- data/lib/multiarray.rb +1 -1
- data/lib/multiarray/gccfunction.rb +12 -13
- data/lib/multiarray/histogram.rb +22 -15
- data/lib/multiarray/lut.rb +31 -23
- data/lib/multiarray/node.rb +27 -14
- data/lib/multiarray/operations.rb +100 -69
- data/lib/multiarray/rgb.rb +21 -0
- data/lib/multiarray/sequence.rb +25 -0
- data/test/tc_multiarray.rb +19 -2
- data/test/tc_sequence.rb +4 -0
- metadata +4 -4
data/Rakefile
CHANGED
data/lib/multiarray.rb
CHANGED
@@ -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 =
|
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
|
145
|
+
# Retrieve all parameters
|
148
146
|
#
|
149
|
-
# @
|
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
|
155
|
-
|
156
|
-
|
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
|
data/lib/multiarray/histogram.rb
CHANGED
@@ -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]
|
39
|
+
# @param [Array<Node>] sources Arrays with elements to compute histogram of.
|
40
40
|
#
|
41
41
|
# @private
|
42
|
-
def initialize( dest,
|
43
|
-
@dest, @
|
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 )}
|
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 >
|
80
|
-
@
|
81
|
-
|
82
|
-
|
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 @
|
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 ),
|
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 +
|
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
|
-
|
130
|
-
|
131
|
-
|
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
|
data/lib/multiarray/lut.rb
CHANGED
@@ -35,14 +35,13 @@ module Hornetseye
|
|
35
35
|
|
36
36
|
# Constructor
|
37
37
|
#
|
38
|
-
# @
|
39
|
-
#
|
40
|
-
#
|
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(
|
44
|
-
@
|
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 )}
|
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
|
-
|
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
|
-
@
|
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 @
|
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
|
-
@
|
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
|
-
|
117
|
-
|
118
|
-
|
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
|
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
|
-
|
143
|
-
if source.dimension >
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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 @
|
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
|
data/lib/multiarray/node.rb
CHANGED
@@ -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
|
-
|
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
|
467
|
-
|
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
|
-
|
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
|
-
|
512
|
-
|
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
|
-
|
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
|
+
|
data/lib/multiarray/rgb.rb
CHANGED
@@ -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
|
data/lib/multiarray/sequence.rb
CHANGED
@@ -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
|
data/test/tc_multiarray.rb
CHANGED
@@ -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
|
-
|
436
|
-
|
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
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
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-
|
17
|
+
date: 2010-12-05 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|