multiarray 0.5.1 → 0.5.2
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 +3 -3
- data/TODO +7 -31
- data/lib/multiarray.rb +8 -4
- data/lib/multiarray/complex.rb +360 -0
- data/lib/multiarray/composite.rb +65 -0
- data/lib/multiarray/diagonal.rb +8 -0
- data/lib/multiarray/element.rb +3 -3
- data/lib/multiarray/{unarymethod.rb → elementwise.rb} +66 -44
- data/lib/multiarray/gccfunction.rb +14 -20
- data/lib/multiarray/gcctype.rb +8 -8
- data/lib/multiarray/gccvalue.rb +57 -15
- data/lib/multiarray/inject.rb +10 -2
- data/lib/multiarray/lambda.rb +21 -3
- data/lib/multiarray/lookup.rb +8 -0
- data/lib/multiarray/methods.rb +10 -4
- data/lib/multiarray/node.rb +80 -15
- data/lib/multiarray/operations.rb +193 -12
- data/lib/multiarray/pointer.rb +19 -0
- data/lib/multiarray/rgb.rb +15 -45
- data/lib/multiarray/sequence.rb +34 -5
- data/test/tc_float.rb +20 -41
- data/test/tc_int.rb +10 -0
- data/test/tc_multiarray.rb +225 -49
- data/test/tc_object.rb +11 -0
- data/test/tc_rgb.rb +15 -0
- data/test/tc_sequence.rb +224 -11
- metadata +13 -9
- data/lib/multiarray/binarymethod.rb +0 -195
- data/lib/multiarray/binaryop.rb +0 -189
- data/lib/multiarray/unaryop.rb +0 -179
data/lib/multiarray/inject.rb
CHANGED
@@ -19,6 +19,14 @@ module Hornetseye
|
|
19
19
|
|
20
20
|
class Inject < Node
|
21
21
|
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def finalised?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
22
30
|
def initialize( value, index, initial, block, var1, var2 )
|
23
31
|
@value, @index, @initial, @block, @var1, @var2 =
|
24
32
|
value, index, initial, block, var1, var2
|
@@ -41,7 +49,7 @@ module Hornetseye
|
|
41
49
|
end
|
42
50
|
|
43
51
|
def array_type
|
44
|
-
@value.array_type
|
52
|
+
@value.to_type( @block.typecode ).array_type
|
45
53
|
end
|
46
54
|
|
47
55
|
# Reevaluate computation
|
@@ -53,7 +61,7 @@ module Hornetseye
|
|
53
61
|
# @private
|
54
62
|
def demand
|
55
63
|
if @initial
|
56
|
-
retval = @initial.simplify # !!!
|
64
|
+
retval = @initial.to_type( typecode ).simplify # !!!
|
57
65
|
offset = INT.new 0
|
58
66
|
else
|
59
67
|
retval = @value.subst( @index => INT.new( 0 ) ).simplify # !!!
|
data/lib/multiarray/lambda.rb
CHANGED
@@ -56,8 +56,7 @@ module Hornetseye
|
|
56
56
|
def strip
|
57
57
|
meta_vars, meta_values, var = @index.strip
|
58
58
|
vars, values, term = @term.subst( @index => var ).strip
|
59
|
-
return vars + meta_vars, values + meta_values,
|
60
|
-
Lambda.new( var, term )
|
59
|
+
return vars + meta_vars, values + meta_values, Lambda.new( var, term )
|
61
60
|
end
|
62
61
|
|
63
62
|
def subst( hash )
|
@@ -100,12 +99,23 @@ module Hornetseye
|
|
100
99
|
#
|
101
100
|
# @return [Node,Object] Result of inserting +i+ for lambda argument.
|
102
101
|
def element( i )
|
103
|
-
|
102
|
+
unless i.is_a? Node
|
103
|
+
unless ( 0 ... shape.last ).member? i
|
104
|
+
raise "Index must be in 0 ... #{shape.last} (was #{i})"
|
105
|
+
end
|
106
|
+
i = Node.match( i ).new i
|
107
|
+
end
|
104
108
|
i.size.store @index.size if @index.size.get and i.is_a? Variable
|
105
109
|
@term.subst @index => i
|
106
110
|
end
|
107
111
|
|
108
112
|
def slice( start, length )
|
113
|
+
unless start.is_a?( Node ) or length.is_a?( Node )
|
114
|
+
if start < 0 or start + length > shape.last
|
115
|
+
raise "Range must be in 0 ... #{shape.last} " +
|
116
|
+
"(was #{start} ... #{start + length})"
|
117
|
+
end
|
118
|
+
end
|
109
119
|
start = Node.match( start ).new start unless start.is_a? Node
|
110
120
|
length = Node.match( length ).new length unless length.is_a? Node
|
111
121
|
index = Variable.new Hornetseye::INDEX( length )
|
@@ -113,10 +123,18 @@ module Hornetseye
|
|
113
123
|
skip( index, start ) ).unroll
|
114
124
|
end
|
115
125
|
|
126
|
+
def decompose
|
127
|
+
Lambda.new @index, @term.decompose
|
128
|
+
end
|
129
|
+
|
116
130
|
def compilable?
|
117
131
|
@term.compilable?
|
118
132
|
end
|
119
133
|
|
134
|
+
def finalised?
|
135
|
+
@term.finalised?
|
136
|
+
end
|
137
|
+
|
120
138
|
end
|
121
139
|
|
122
140
|
end
|
data/lib/multiarray/lookup.rb
CHANGED
@@ -93,6 +93,14 @@ module Hornetseye
|
|
93
93
|
Lookup.new @p.slice( start, length ), @index, @stride
|
94
94
|
end
|
95
95
|
|
96
|
+
def decompose
|
97
|
+
if typecode < Composite
|
98
|
+
Lookup.new @p.decompose, @index, @stride * typecode.num_elements
|
99
|
+
else
|
100
|
+
Lookup.new @p.decompose, @index, @stride
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
96
104
|
end
|
97
105
|
|
98
106
|
end
|
data/lib/multiarray/methods.rb
CHANGED
@@ -44,7 +44,10 @@ module Hornetseye
|
|
44
44
|
target = a.typecode.send conversion
|
45
45
|
target.new mod.send( op, a.simplify.get )
|
46
46
|
else
|
47
|
-
Hornetseye::
|
47
|
+
Hornetseye::ElementWise( lambda { |x| mod.send op, x },
|
48
|
+
"#{mod}.#{op}",
|
49
|
+
lambda { |x| x.send conversion } ).
|
50
|
+
new( a ).force
|
48
51
|
end
|
49
52
|
else
|
50
53
|
send "#{op}_without_hornetseye", a
|
@@ -62,14 +65,17 @@ module Hornetseye
|
|
62
65
|
mod.module_eval do
|
63
66
|
define_method( "#{op}_with_hornetseye" ) do |a,b|
|
64
67
|
if a.is_a? Node or b.is_a? Node
|
65
|
-
a = Node.match( a, b
|
66
|
-
b = Node.match( b, a
|
68
|
+
a = Node.match( a, b ).new a unless a.is_a? Node
|
69
|
+
b = Node.match( b, a ).new b unless b.is_a? Node
|
67
70
|
if a.dimension == 0 and a.variables.empty? and
|
68
71
|
b.dimension == 0 and b.variables.empty?
|
69
72
|
target = a.typecode.send coercion, b.typecode
|
70
73
|
target.new mod.send( op, a.simplify.get, b.simplify.get )
|
71
74
|
else
|
72
|
-
Hornetseye::
|
75
|
+
Hornetseye::ElementWise( lambda { |x,y| mod.send op, x, y },
|
76
|
+
"#{mod}.#{op}",
|
77
|
+
lambda { |t,u| t.send coercion, u } ).
|
78
|
+
new( a, b ).force
|
73
79
|
end
|
74
80
|
else
|
75
81
|
send "#{op}_without_hornetseye", a, b
|
data/lib/multiarray/node.rb
CHANGED
@@ -135,10 +135,18 @@ module Hornetseye
|
|
135
135
|
BOOL
|
136
136
|
end
|
137
137
|
|
138
|
+
def scalar
|
139
|
+
self
|
140
|
+
end
|
141
|
+
|
142
|
+
def float_scalar
|
143
|
+
float.scalar
|
144
|
+
end
|
145
|
+
|
138
146
|
# Get boolean-based datatype for binary operation
|
139
147
|
#
|
140
148
|
# @return [Class] Returns +BOOL+.
|
141
|
-
def
|
149
|
+
def coercion_bool( other )
|
142
150
|
other.coercion( self ).bool
|
143
151
|
end
|
144
152
|
|
@@ -146,7 +154,7 @@ module Hornetseye
|
|
146
154
|
self
|
147
155
|
end
|
148
156
|
|
149
|
-
def
|
157
|
+
def coercion_maxint( other )
|
150
158
|
coercion( other ).maxint
|
151
159
|
end
|
152
160
|
|
@@ -161,6 +169,23 @@ module Hornetseye
|
|
161
169
|
other.coercion( self ).float
|
162
170
|
end
|
163
171
|
|
172
|
+
def byte
|
173
|
+
BYTE
|
174
|
+
end
|
175
|
+
|
176
|
+
def coercion_byte( other )
|
177
|
+
coercion( other ).byte
|
178
|
+
end
|
179
|
+
|
180
|
+
def cond( a, b )
|
181
|
+
t = a.coercion b
|
182
|
+
Hornetseye::MultiArray( t.typecode, *shape ).coercion t
|
183
|
+
end
|
184
|
+
|
185
|
+
def to_type( dest )
|
186
|
+
dest
|
187
|
+
end
|
188
|
+
|
164
189
|
# Get variables contained in this datatype
|
165
190
|
#
|
166
191
|
# @return [Set] Returns +Set[]+.
|
@@ -212,6 +237,10 @@ module Hornetseye
|
|
212
237
|
true
|
213
238
|
end
|
214
239
|
|
240
|
+
def finalised?
|
241
|
+
true
|
242
|
+
end
|
243
|
+
|
215
244
|
end
|
216
245
|
|
217
246
|
# Array type of this term
|
@@ -235,6 +264,10 @@ module Hornetseye
|
|
235
264
|
array_type.typecode
|
236
265
|
end
|
237
266
|
|
267
|
+
def basetype
|
268
|
+
array_type.basetype
|
269
|
+
end
|
270
|
+
|
238
271
|
# Get shape of this term
|
239
272
|
#
|
240
273
|
# @return [Array<Integer>] Returns +array_type.shape+.
|
@@ -367,6 +400,12 @@ module Hornetseye
|
|
367
400
|
'Node()'
|
368
401
|
end
|
369
402
|
|
403
|
+
def dup
|
404
|
+
retval = array_type.new
|
405
|
+
retval[] = self
|
406
|
+
retval
|
407
|
+
end
|
408
|
+
|
370
409
|
# Substitute variables
|
371
410
|
#
|
372
411
|
# Substitute the variables with the values given in the hash.
|
@@ -389,6 +428,10 @@ module Hornetseye
|
|
389
428
|
typecode.compilable?
|
390
429
|
end
|
391
430
|
|
431
|
+
def finalised?
|
432
|
+
self.class.finalised?
|
433
|
+
end
|
434
|
+
|
392
435
|
# Retrieve value of array element(s)
|
393
436
|
#
|
394
437
|
# @param [Array<Integer>] *indices Index/indices to select element.
|
@@ -407,6 +450,21 @@ module Hornetseye
|
|
407
450
|
end
|
408
451
|
end
|
409
452
|
|
453
|
+
def check_shape( *args )
|
454
|
+
args.each do |arg|
|
455
|
+
if dimension < arg.dimension
|
456
|
+
raise "#{arg.array_type.inspect} has #{arg.dimension} dimension(s) " +
|
457
|
+
"but should not have more than #{dimension}"
|
458
|
+
end
|
459
|
+
if ( shape + arg.shape ).all? { |s| s.is_a? Integer }
|
460
|
+
if shape.last( arg.dimension ) != arg.shape
|
461
|
+
raise "#{arg.array_type.inspect} has shape #{arg.shape.inspect} " +
|
462
|
+
"(does not match last value(s) of #{shape.inspect})"
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
410
468
|
# Assign value to array element(s)
|
411
469
|
#
|
412
470
|
# @overload []=( *indices, value )
|
@@ -419,7 +477,12 @@ module Hornetseye
|
|
419
477
|
value = indices.pop
|
420
478
|
value = Node.match( value ).new value unless value.is_a? Node
|
421
479
|
if indices.empty?
|
422
|
-
|
480
|
+
check_shape value
|
481
|
+
unless compilable? and value.compilable? and dimension > 0
|
482
|
+
store value
|
483
|
+
else
|
484
|
+
GCCFunction.run self, value
|
485
|
+
end
|
423
486
|
else
|
424
487
|
if indices.last.is_a? Range
|
425
488
|
view = slice indices.last.min, indices.last.size
|
@@ -463,15 +526,6 @@ module Hornetseye
|
|
463
526
|
self
|
464
527
|
end
|
465
528
|
|
466
|
-
# Check whether mode of computation is lazy
|
467
|
-
#
|
468
|
-
# @see #lazy
|
469
|
-
#
|
470
|
-
# @private
|
471
|
-
def lazy?
|
472
|
-
( dimension > 0 and Thread.current[ :lazy ] ) or not variables.empty?
|
473
|
-
end
|
474
|
-
|
475
529
|
# Force delayed computation unless in lazy mode
|
476
530
|
#
|
477
531
|
# @return [Node,Object] Result of computation
|
@@ -480,8 +534,10 @@ module Hornetseye
|
|
480
534
|
#
|
481
535
|
# @private
|
482
536
|
def force
|
483
|
-
if lazy?
|
537
|
+
if ( dimension > 0 and Thread.current[ :lazy ] ) or not variables.empty?
|
484
538
|
self
|
539
|
+
elsif finalised?
|
540
|
+
get
|
485
541
|
else
|
486
542
|
unless compilable?
|
487
543
|
Hornetseye::lazy do
|
@@ -490,7 +546,7 @@ module Hornetseye
|
|
490
546
|
retval.get
|
491
547
|
end
|
492
548
|
else
|
493
|
-
GCCFunction.run( self ).get
|
549
|
+
GCCFunction.run( pointer_type.new, self ).get
|
494
550
|
end
|
495
551
|
end
|
496
552
|
end
|
@@ -503,6 +559,11 @@ module Hornetseye
|
|
503
559
|
#
|
504
560
|
# @private
|
505
561
|
def simplify
|
562
|
+
#if Thread.current[ :function ] and dimension == 0
|
563
|
+
# demand.dup
|
564
|
+
#else
|
565
|
+
# demand
|
566
|
+
#end
|
506
567
|
dimension == 0 ? demand.dup : demand
|
507
568
|
end
|
508
569
|
|
@@ -517,10 +578,14 @@ module Hornetseye
|
|
517
578
|
if other.is_a? Node
|
518
579
|
return other, self
|
519
580
|
else
|
520
|
-
return Node.match( other,
|
581
|
+
return Node.match( other, self ).new( other ), self
|
521
582
|
end
|
522
583
|
end
|
523
584
|
|
585
|
+
def decompose
|
586
|
+
self
|
587
|
+
end
|
588
|
+
|
524
589
|
end
|
525
590
|
|
526
591
|
end
|
@@ -25,7 +25,9 @@ module Hornetseye
|
|
25
25
|
target = typecode.send conversion
|
26
26
|
target.new simplify.get.send( op )
|
27
27
|
else
|
28
|
-
Hornetseye::
|
28
|
+
Hornetseye::ElementWise( lambda { |x| x.send op }, op,
|
29
|
+
lambda { |t| t.send conversion } ).
|
30
|
+
new( self ).force
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -42,7 +44,9 @@ module Hornetseye
|
|
42
44
|
target = array_type.send coercion, other.array_type
|
43
45
|
target.new simplify.get.send( op, other.simplify.get )
|
44
46
|
else
|
45
|
-
Hornetseye::
|
47
|
+
Hornetseye::ElementWise( lambda { |x,y| x.send op, y }, op,
|
48
|
+
lambda { |t,u| t.send coercion, u } ).
|
49
|
+
new( self, other ).force
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
@@ -54,29 +58,37 @@ module Hornetseye
|
|
54
58
|
define_unary_op :not, :bool
|
55
59
|
define_unary_op :~
|
56
60
|
define_unary_op :-@
|
61
|
+
define_unary_op :conj
|
62
|
+
define_unary_op :abs, :scalar
|
63
|
+
define_unary_op :arg, :float_scalar
|
57
64
|
define_unary_op :floor
|
58
65
|
define_unary_op :ceil
|
59
66
|
define_unary_op :round
|
67
|
+
define_unary_op :r, :scalar
|
68
|
+
define_unary_op :g, :scalar
|
69
|
+
define_unary_op :b, :scalar
|
70
|
+
define_unary_op :real, :scalar
|
71
|
+
define_unary_op :imag, :scalar
|
60
72
|
define_binary_op :+
|
61
73
|
define_binary_op :-
|
62
74
|
define_binary_op :*
|
63
|
-
define_binary_op :**, :
|
75
|
+
define_binary_op :**, :coercion_maxint
|
64
76
|
define_binary_op :/
|
65
77
|
define_binary_op :%
|
66
|
-
define_binary_op :and, :
|
67
|
-
define_binary_op :or, :
|
78
|
+
define_binary_op :and, :coercion_bool
|
79
|
+
define_binary_op :or, :coercion_bool
|
68
80
|
define_binary_op :&
|
69
81
|
define_binary_op :|
|
70
82
|
define_binary_op :^
|
71
83
|
define_binary_op :<<
|
72
84
|
define_binary_op :>>
|
73
|
-
define_binary_op :eq, :
|
74
|
-
define_binary_op :ne, :
|
75
|
-
define_binary_op :<=, :
|
76
|
-
define_binary_op :<, :
|
77
|
-
define_binary_op :>=, :
|
78
|
-
define_binary_op :>, :
|
79
|
-
define_binary_op :<=>, :
|
85
|
+
define_binary_op :eq, :coercion_bool
|
86
|
+
define_binary_op :ne, :coercion_bool
|
87
|
+
define_binary_op :<=, :coercion_bool
|
88
|
+
define_binary_op :<, :coercion_bool
|
89
|
+
define_binary_op :>=, :coercion_bool
|
90
|
+
define_binary_op :>, :coercion_bool
|
91
|
+
define_binary_op :<=>, :coercion_byte
|
80
92
|
define_binary_op :minor
|
81
93
|
define_binary_op :major
|
82
94
|
|
@@ -84,6 +96,42 @@ module Hornetseye
|
|
84
96
|
self
|
85
97
|
end
|
86
98
|
|
99
|
+
def to_type( dest )
|
100
|
+
if dimension == 0 and variables.empty?
|
101
|
+
target = typecode.to_type dest
|
102
|
+
target.new simplify.get
|
103
|
+
else
|
104
|
+
key = "to_#{dest.to_s.downcase}"
|
105
|
+
Hornetseye::ElementWise( lambda { |x| x.to_type dest }, key,
|
106
|
+
lambda { |t| t.to_type dest } ).new( self ).force
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def conditional( a, b )
|
111
|
+
unless a.is_a? Node
|
112
|
+
a = Node.match( a, b.is_a?( Node ) ? b : nil ).new a
|
113
|
+
end
|
114
|
+
unless b.is_a? Node
|
115
|
+
b = Node.match( b, a.is_a?( Node ) ? a : nil ).new b
|
116
|
+
end
|
117
|
+
if dimension == 0 and variables.empty? and
|
118
|
+
a.dimension == 0 and a.variables.empty? and
|
119
|
+
b.dimension == 0 and b.variables.empty?
|
120
|
+
target = array_type.cond a.array_type, b.array_type
|
121
|
+
target.new simplify.get.conditional( a.simplify.get, b.simplify.get )
|
122
|
+
else
|
123
|
+
Hornetseye::ElementWise( lambda { |x,y,z| x.conditional y, z }, :conditional,
|
124
|
+
lambda { |t,u,v| t.cond u, v } ).
|
125
|
+
new( self, a, b ).force
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def <=>( other )
|
130
|
+
Hornetseye::lazy do
|
131
|
+
( self < other ).conditional -1, ( self > other ).conditional( 1, 0 )
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
87
135
|
# Lazy transpose of array
|
88
136
|
#
|
89
137
|
# Lazily compute transpose by swapping indices according to the specified
|
@@ -123,6 +171,13 @@ module Hornetseye
|
|
123
171
|
end
|
124
172
|
end
|
125
173
|
|
174
|
+
def collect( &action )
|
175
|
+
var = Variable.new typecode
|
176
|
+
block = action.call var
|
177
|
+
conversion = lambda { |t| t.to_type action.call( Variable.new( t.typecode ) ) }
|
178
|
+
Hornetseye::ElementWise( action, block.to_s, conversion ).new( self ).force
|
179
|
+
end
|
180
|
+
|
126
181
|
def inject( initial = nil, options = {} )
|
127
182
|
unless initial.nil?
|
128
183
|
initial = Node.match( initial ).new initial unless initial.is_a? Node
|
@@ -231,6 +286,11 @@ module Hornetseye
|
|
231
286
|
#
|
232
287
|
# @private
|
233
288
|
def product( filter )
|
289
|
+
filter = Node.match( filter, typecode ).new filter unless filter.is_a? Node
|
290
|
+
if dimension != filter.dimension
|
291
|
+
raise "Filter has #{filter.dimension} dimension(s) but should " +
|
292
|
+
"have #{dimension}"
|
293
|
+
end
|
234
294
|
if dimension == 0
|
235
295
|
self * filter
|
236
296
|
else
|
@@ -244,9 +304,130 @@ module Hornetseye
|
|
244
304
|
#
|
245
305
|
# @return [Node] Result of convolution.
|
246
306
|
def convolve( filter )
|
307
|
+
filter = Node.match( filter, typecode ).new filter unless filter.is_a? Node
|
247
308
|
product( filter ).diagonal { |s,x| s + x }
|
248
309
|
end
|
249
310
|
|
311
|
+
def r_with_decompose
|
312
|
+
if typecode < RGB_
|
313
|
+
decompose.roll.element 0
|
314
|
+
elsif typecode == OBJECT
|
315
|
+
r_without_decompose
|
316
|
+
else
|
317
|
+
self
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
alias_method_chain :r, :decompose
|
322
|
+
|
323
|
+
def r=( value )
|
324
|
+
if typecode < RGB_
|
325
|
+
decompose.roll[ 0 ] = value
|
326
|
+
elsif typecode == OBJECT
|
327
|
+
self[] = Hornetseye::lazy do
|
328
|
+
value * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 )
|
329
|
+
end
|
330
|
+
else
|
331
|
+
raise "Cannot assign red channel to object of type #{array_type.inspect}"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def g_with_decompose
|
336
|
+
if typecode < RGB_
|
337
|
+
decompose.roll.element 1
|
338
|
+
elsif typecode == OBJECT
|
339
|
+
g_without_decompose
|
340
|
+
else
|
341
|
+
self
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
alias_method_chain :g, :decompose
|
346
|
+
|
347
|
+
def g=( value )
|
348
|
+
if typecode < RGB_
|
349
|
+
decompose.roll[ 1 ] = value
|
350
|
+
elsif typecode == OBJECT
|
351
|
+
self[] = Hornetseye::lazy do
|
352
|
+
r * RGB.new( 1, 0, 0 ) + value * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 )
|
353
|
+
end
|
354
|
+
else
|
355
|
+
raise "Cannot assign green channel to object of type #{array_type.inspect}"
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def b_with_decompose
|
360
|
+
if typecode < RGB_
|
361
|
+
decompose.roll.element 2
|
362
|
+
elsif typecode == OBJECT
|
363
|
+
b_without_decompose
|
364
|
+
else
|
365
|
+
self
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
alias_method_chain :b, :decompose
|
370
|
+
|
371
|
+
def b=( value )
|
372
|
+
if typecode < RGB_
|
373
|
+
decompose.roll[ 2 ] = value
|
374
|
+
elsif typecode == OBJECT
|
375
|
+
self[] = Hornetseye::lazy do
|
376
|
+
r * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + value * RGB.new( 0, 0, 1 )
|
377
|
+
end
|
378
|
+
else
|
379
|
+
raise "Cannot assign blue channel to object of type #{array_type.inspect}"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def real_with_decompose
|
384
|
+
if typecode < COMPLEX_
|
385
|
+
decompose.roll.element 0
|
386
|
+
elsif typecode == OBJECT
|
387
|
+
real_without_decompose
|
388
|
+
else
|
389
|
+
self
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
alias_method_chain :real, :decompose
|
394
|
+
|
395
|
+
def real=( value )
|
396
|
+
if typecode < COMPLEX_
|
397
|
+
decompose.roll[ 0 ] = value
|
398
|
+
elsif typecode == OBJECT
|
399
|
+
self[] = Hornetseye::lazy do
|
400
|
+
value + imag * ::Complex::I
|
401
|
+
end
|
402
|
+
else
|
403
|
+
self[] = value
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def imag_with_decompose
|
408
|
+
if typecode < COMPLEX_
|
409
|
+
decompose.roll.element 1
|
410
|
+
elsif typecode == OBJECT
|
411
|
+
imag_without_decompose
|
412
|
+
else
|
413
|
+
Hornetseye::lazy( *shape ) { typecode.new( 0 ) }
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
alias_method_chain :imag, :decompose
|
418
|
+
|
419
|
+
def imag=( value )
|
420
|
+
if typecode < COMPLEX_
|
421
|
+
decompose.roll[ 1 ] = value
|
422
|
+
elsif typecode == OBJECT
|
423
|
+
self[] = Hornetseye::lazy do
|
424
|
+
real + value * ::Complex::I
|
425
|
+
end
|
426
|
+
else
|
427
|
+
raise "Cannot assign imaginary values to object of type #{array_type.inspect}"
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
250
431
|
end
|
251
432
|
|
252
433
|
class Node
|