multiarray 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|