multiarray 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -1
- data/TODO +7 -36
- data/lib/multiarray/bool.rb +14 -4
- data/lib/multiarray/complex.rb +467 -38
- data/lib/multiarray/composite.rb +44 -0
- data/lib/multiarray/diagonal.rb +10 -3
- data/lib/multiarray/element.rb +29 -3
- data/lib/multiarray/elementwise.rb +32 -3
- data/lib/multiarray/float.rb +120 -18
- data/lib/multiarray/gccfunction.rb +11 -21
- data/lib/multiarray/gcctype.rb +23 -17
- data/lib/multiarray/gccvalue.rb +25 -2
- data/lib/multiarray/histogram.rb +82 -0
- data/lib/multiarray/index.rb +23 -0
- data/lib/multiarray/inject.rb +13 -1
- data/lib/multiarray/int.rb +105 -9
- data/lib/multiarray/integral.rb +82 -0
- data/lib/multiarray/lambda.rb +58 -8
- data/lib/multiarray/list.rb +27 -1
- data/lib/multiarray/lookup.rb +60 -0
- data/lib/multiarray/lut.rb +102 -0
- data/lib/multiarray/malloc.rb +16 -0
- data/lib/multiarray/methods.rb +17 -0
- data/lib/multiarray/multiarray.rb +24 -2
- data/lib/multiarray/node.rb +115 -21
- data/lib/multiarray/object.rb +34 -4
- data/lib/multiarray/operations.rb +92 -100
- data/lib/multiarray/pointer.rb +74 -1
- data/lib/multiarray/rgb.rb +324 -2
- data/lib/multiarray/sequence.rb +69 -4
- data/lib/multiarray/shortcuts.rb +71 -0
- data/lib/multiarray/store.rb +72 -0
- data/lib/multiarray/variable.rb +25 -0
- data/lib/multiarray.rb +47 -5
- data/test/tc_int.rb +10 -0
- data/test/tc_multiarray.rb +47 -1
- data/test/tc_object.rb +10 -0
- data/test/tc_sequence.rb +237 -8
- metadata +9 -9
data/lib/multiarray/complex.rb
CHANGED
@@ -17,10 +17,19 @@
|
|
17
17
|
# Namespace of Hornetseye computer vision library
|
18
18
|
module Hornetseye
|
19
19
|
|
20
|
-
class
|
20
|
+
class InternalComplex
|
21
21
|
|
22
22
|
class << self
|
23
23
|
|
24
|
+
# Check compatibility of other type.
|
25
|
+
#
|
26
|
+
# This method checks whether binary operations with the other Ruby object can
|
27
|
+
# be performed without requiring coercion.
|
28
|
+
#
|
29
|
+
# @param [Object] value The other Ruby object.
|
30
|
+
#
|
31
|
+
# @return [Boolean] Returns +false+ if Ruby object requires
|
32
|
+
# coercion.
|
24
33
|
def generic?( value )
|
25
34
|
value.is_a?( Numeric ) or value.is_a?( GCCValue )
|
26
35
|
end
|
@@ -37,30 +46,43 @@ module Hornetseye
|
|
37
46
|
@real, @imag = real, imag
|
38
47
|
end
|
39
48
|
|
49
|
+
# Return string with information about this object.
|
50
|
+
#
|
51
|
+
# @return [String] Returns a string (e.g. "InternalComplex(1,2)").
|
40
52
|
def inspect
|
41
|
-
"
|
53
|
+
"InternalComplex(#{@real.inspect},#{@imag.inspect})"
|
42
54
|
end
|
43
55
|
|
56
|
+
# Return string with information about this object.
|
57
|
+
#
|
58
|
+
# @return [String] Returns a string (e.g. "InternalComplex(1,2)").
|
44
59
|
def to_s
|
45
|
-
"
|
60
|
+
"InternalComplex(#{@real.to_s},#{@imag.to_s})"
|
46
61
|
end
|
47
62
|
|
63
|
+
# Store other value in this object
|
64
|
+
#
|
65
|
+
# @param [Object] value New value for this object.
|
66
|
+
#
|
67
|
+
# @return [Object] Returns +value+.
|
68
|
+
#
|
69
|
+
# @private
|
48
70
|
def store( value )
|
49
71
|
@real, @imag = value.real, value.imag
|
50
72
|
end
|
51
73
|
|
52
74
|
def coerce( other )
|
53
|
-
if other.is_a?
|
75
|
+
if other.is_a? InternalComplex
|
54
76
|
return other, self
|
55
|
-
elsif other.is_a?
|
56
|
-
return
|
77
|
+
elsif other.is_a? Complex
|
78
|
+
return InternalComplex.new( other.real, other.imag ), self
|
57
79
|
else
|
58
|
-
return
|
80
|
+
return InternalComplex.new( other, 0 ), self
|
59
81
|
end
|
60
82
|
end
|
61
83
|
|
62
84
|
def conj
|
63
|
-
|
85
|
+
InternalComplex.new @real, -@imag
|
64
86
|
end
|
65
87
|
|
66
88
|
def abs
|
@@ -80,14 +102,14 @@ module Hornetseye
|
|
80
102
|
end
|
81
103
|
|
82
104
|
def -@
|
83
|
-
|
105
|
+
InternalComplex.new -@real, -@imag
|
84
106
|
end
|
85
107
|
|
86
108
|
def +( other )
|
87
|
-
if other.is_a?(
|
88
|
-
|
89
|
-
elsif
|
90
|
-
|
109
|
+
if other.is_a?( InternalComplex ) or other.is_a?( Complex )
|
110
|
+
InternalComplex.new @real + other.real, @imag + other.imag
|
111
|
+
elsif InternalComplex.generic? other
|
112
|
+
InternalComplex.new @real + other, @imag
|
91
113
|
else
|
92
114
|
x, y = other.coerce self
|
93
115
|
x + y
|
@@ -95,10 +117,10 @@ module Hornetseye
|
|
95
117
|
end
|
96
118
|
|
97
119
|
def -( other )
|
98
|
-
if other.is_a?(
|
99
|
-
|
100
|
-
elsif
|
101
|
-
|
120
|
+
if other.is_a?( InternalComplex ) or other.is_a?( Complex )
|
121
|
+
InternalComplex.new @real - other.real, @imag - other.imag
|
122
|
+
elsif InternalComplex.generic? other
|
123
|
+
InternalComplex.new @real - other, @imag
|
102
124
|
else
|
103
125
|
x, y = other.coerce self
|
104
126
|
x - y
|
@@ -106,11 +128,11 @@ module Hornetseye
|
|
106
128
|
end
|
107
129
|
|
108
130
|
def *( other )
|
109
|
-
if other.is_a?(
|
110
|
-
|
131
|
+
if other.is_a?( InternalComplex ) or other.is_a?( Complex )
|
132
|
+
InternalComplex.new @real * other.real - @imag * other.imag,
|
111
133
|
@real * other.imag + @imag * other.real
|
112
|
-
elsif
|
113
|
-
|
134
|
+
elsif InternalComplex.generic? other
|
135
|
+
InternalComplex.new @real * other, @imag * other
|
114
136
|
else
|
115
137
|
x, y = other.coerce self
|
116
138
|
x * y
|
@@ -118,10 +140,10 @@ module Hornetseye
|
|
118
140
|
end
|
119
141
|
|
120
142
|
def /( other )
|
121
|
-
if other.is_a?(
|
143
|
+
if other.is_a?( InternalComplex ) or other.is_a?( Complex )
|
122
144
|
self * other.conj / other.abs2
|
123
|
-
elsif
|
124
|
-
|
145
|
+
elsif InternalComplex.generic? other
|
146
|
+
InternalComplex.new @real / other, @imag / other
|
125
147
|
else
|
126
148
|
x, y = other.coerce self
|
127
149
|
x / y
|
@@ -129,16 +151,16 @@ module Hornetseye
|
|
129
151
|
end
|
130
152
|
|
131
153
|
def **( other )
|
132
|
-
if other.is_a?(
|
154
|
+
if other.is_a?( InternalComplex ) or other.is_a?( Complex )
|
133
155
|
r, theta = polar
|
134
156
|
ore = other.real
|
135
157
|
oim = other.imag
|
136
158
|
nr = Math.exp ore * Math.log( r ) - oim * theta
|
137
159
|
ntheta = theta * ore + oim * Math.log( r )
|
138
|
-
|
139
|
-
elsif
|
160
|
+
InternalComplex.polar nr, ntheta
|
161
|
+
elsif InternalComplex.generic? other
|
140
162
|
r, theta = polar
|
141
|
-
|
163
|
+
InternalComplex.polar r ** other, theta * other
|
142
164
|
else
|
143
165
|
x, y = other.coerce self
|
144
166
|
x ** y
|
@@ -157,46 +179,305 @@ module Hornetseye
|
|
157
179
|
@real * @real + @imag * @imag
|
158
180
|
end
|
159
181
|
|
182
|
+
# Test on equality
|
183
|
+
#
|
184
|
+
# @param [Object] other Object to compare with.
|
185
|
+
#
|
186
|
+
# @return [Boolean] Returns boolean indicating whether objects are
|
187
|
+
# equal or not.
|
160
188
|
def ==( other )
|
161
|
-
if other.is_a?(
|
189
|
+
if other.is_a?( InternalComplex ) or other.is_a?( Complex )
|
162
190
|
@real.eq( other.real ).and( @imag.eq( other.imag ) )
|
163
|
-
elsif
|
191
|
+
elsif InternalComplex.generic? other
|
164
192
|
@real.eq( other ).and( @imag.eq( 0 ) )
|
165
193
|
else
|
166
194
|
false
|
167
195
|
end
|
168
196
|
end
|
169
197
|
|
198
|
+
# Decompose complex number
|
199
|
+
#
|
200
|
+
# This method decomposes the complex number into an array.
|
201
|
+
#
|
202
|
+
# @return [Node] Returns an array with the real and imaginary component as
|
203
|
+
# elements.
|
170
204
|
def decompose
|
171
205
|
Hornetseye::Sequence[ @real, @imag ]
|
172
206
|
end
|
173
207
|
|
174
208
|
end
|
175
209
|
|
210
|
+
end
|
211
|
+
|
212
|
+
module Math
|
213
|
+
|
214
|
+
def sqrt_with_internalcomplex( z )
|
215
|
+
if z.is_a? Hornetseye::InternalComplex
|
216
|
+
real = sqrt( ( z.abs + z.real ) / 2 )
|
217
|
+
imag = ( z.imag < 0 ).conditional -sqrt( ( z.abs - z.real ) / 2 ),
|
218
|
+
sqrt( ( z.abs - z.real ) / 2 )
|
219
|
+
Hornetseye::InternalComplex.new real, imag
|
220
|
+
else
|
221
|
+
sqrt_without_internalcomplex z
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
alias_method_chain :sqrt, :internalcomplex
|
226
|
+
module_function :sqrt_without_internalcomplex
|
227
|
+
module_function :sqrt
|
228
|
+
|
229
|
+
def exp_with_internalcomplex( z )
|
230
|
+
if z.is_a? Hornetseye::InternalComplex
|
231
|
+
real = exp( z.real ) * cos( z.imag )
|
232
|
+
imag = exp( z.real ) * sin( z.imag )
|
233
|
+
Hornetseye::InternalComplex.new real, imag
|
234
|
+
else
|
235
|
+
exp_without_internalcomplex z
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
alias_method_chain :exp, :internalcomplex
|
240
|
+
module_function :exp_without_internalcomplex
|
241
|
+
module_function :exp
|
242
|
+
|
243
|
+
def cos_with_internalcomplex( z )
|
244
|
+
if z.is_a? Hornetseye::InternalComplex
|
245
|
+
real = cos( z.real ) * cosh( z.imag )
|
246
|
+
imag = -sin( z.real ) * sinh( z.imag )
|
247
|
+
Hornetseye::InternalComplex.new real, imag
|
248
|
+
else
|
249
|
+
cos_without_internalcomplex z
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
alias_method_chain :cos, :internalcomplex
|
254
|
+
module_function :cos_without_internalcomplex
|
255
|
+
module_function :cos
|
256
|
+
|
257
|
+
def sin_with_internalcomplex( z )
|
258
|
+
if z.is_a? Hornetseye::InternalComplex
|
259
|
+
real = sin( z.real ) * cosh( z.imag )
|
260
|
+
imag = cos( z.real ) * sinh( z.imag )
|
261
|
+
Hornetseye::InternalComplex.new real, imag
|
262
|
+
else
|
263
|
+
sin_without_internalcomplex z
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
alias_method_chain :sin, :internalcomplex
|
268
|
+
module_function :sin_without_internalcomplex
|
269
|
+
module_function :sin
|
270
|
+
|
271
|
+
def tan_with_internalcomplex( z )
|
272
|
+
if z.is_a? Hornetseye::InternalComplex
|
273
|
+
sin( z ) / cos( z )
|
274
|
+
else
|
275
|
+
tan_without_internalcomplex z
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
alias_method_chain :tan, :internalcomplex
|
280
|
+
module_function :tan_without_internalcomplex
|
281
|
+
module_function :tan
|
282
|
+
|
283
|
+
def cosh_with_internalcomplex( z )
|
284
|
+
if z.is_a? Hornetseye::InternalComplex
|
285
|
+
real = cosh( z.real ) * cos( z.imag )
|
286
|
+
imag = sinh( z.real ) * sin( z.imag )
|
287
|
+
Hornetseye::InternalComplex.new real, imag
|
288
|
+
else
|
289
|
+
cosh_without_internalcomplex z
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
alias_method_chain :cosh, :internalcomplex
|
294
|
+
module_function :cosh_without_internalcomplex
|
295
|
+
module_function :cosh
|
296
|
+
|
297
|
+
def sinh_with_internalcomplex( z )
|
298
|
+
if z.is_a? Hornetseye::InternalComplex
|
299
|
+
real = sinh( z.real ) * cos( z.imag )
|
300
|
+
imag = cosh( z.real ) * sin( z.imag )
|
301
|
+
Hornetseye::InternalComplex.new real, imag
|
302
|
+
else
|
303
|
+
sinh_without_internalcomplex z
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
alias_method_chain :sinh, :internalcomplex
|
308
|
+
module_function :sinh_without_internalcomplex
|
309
|
+
module_function :sinh
|
310
|
+
|
311
|
+
def tanh_with_internalcomplex( z )
|
312
|
+
if z.is_a? Hornetseye::InternalComplex
|
313
|
+
sinh( z ) / cosh( z )
|
314
|
+
else
|
315
|
+
tanh_without_internalcomplex z
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
alias_method_chain :tanh, :internalcomplex
|
320
|
+
module_function :tanh_without_internalcomplex
|
321
|
+
module_function :tanh
|
322
|
+
|
323
|
+
def log_with_internalcomplex( z )
|
324
|
+
if z.is_a? Hornetseye::InternalComplex
|
325
|
+
r, theta = z.polar
|
326
|
+
Hornetseye::InternalComplex.new log( r.abs ), theta
|
327
|
+
else
|
328
|
+
log_without_internalcomplex z
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
alias_method_chain :log, :internalcomplex
|
333
|
+
module_function :log_without_internalcomplex
|
334
|
+
module_function :log
|
335
|
+
|
336
|
+
def log10_with_internalcomplex( z )
|
337
|
+
if z.is_a? Hornetseye::InternalComplex
|
338
|
+
log( z ) / log( 10 )
|
339
|
+
else
|
340
|
+
log10_without_internalcomplex z
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
alias_method_chain :log10, :internalcomplex
|
345
|
+
module_function :log10_without_internalcomplex
|
346
|
+
module_function :log10
|
347
|
+
|
348
|
+
def acos_with_internalcomplex( z )
|
349
|
+
if z.is_a? Hornetseye::InternalComplex
|
350
|
+
-1.0.im * log( z + 1.0.im * sqrt( 1.0 - z * z ) )
|
351
|
+
else
|
352
|
+
acos_without_internalcomplex z
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
alias_method_chain :acos, :internalcomplex
|
357
|
+
module_function :acos_without_internalcomplex
|
358
|
+
module_function :acos
|
359
|
+
|
360
|
+
def asin_with_internalcomplex( z )
|
361
|
+
if z.is_a? Hornetseye::InternalComplex
|
362
|
+
-1.0.im * log( 1.0.im * z + sqrt( 1.0 - z * z ) )
|
363
|
+
else
|
364
|
+
asin_without_internalcomplex z
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
alias_method_chain :asin, :internalcomplex
|
369
|
+
module_function :asin_without_internalcomplex
|
370
|
+
module_function :asin
|
371
|
+
|
372
|
+
def atan_with_internalcomplex( z )
|
373
|
+
if z.is_a? Hornetseye::InternalComplex
|
374
|
+
1.0.im * log( ( 1.0.im + z ) / ( 1.0.im - z ) ) / 2.0
|
375
|
+
else
|
376
|
+
atan_without_internalcomplex z
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
alias_method_chain :atan, :internalcomplex
|
381
|
+
module_function :atan_without_internalcomplex
|
382
|
+
module_function :atan
|
383
|
+
|
384
|
+
def acosh_with_internalcomplex( z )
|
385
|
+
if z.is_a? Hornetseye::InternalComplex
|
386
|
+
log( z + sqrt( z * z - 1.0 ) )
|
387
|
+
else
|
388
|
+
acosh_without_internalcomplex z
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
alias_method_chain :acosh, :internalcomplex
|
393
|
+
module_function :acosh_without_internalcomplex
|
394
|
+
module_function :acosh
|
395
|
+
|
396
|
+
def asinh_with_internalcomplex( z )
|
397
|
+
if z.is_a? Hornetseye::InternalComplex
|
398
|
+
log( z + sqrt( 1.0 + z * z ) )
|
399
|
+
else
|
400
|
+
asinh_without_internalcomplex z
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
alias_method_chain :asinh, :internalcomplex
|
405
|
+
module_function :asinh_without_internalcomplex
|
406
|
+
module_function :asinh
|
407
|
+
|
408
|
+
def atanh_with_internalcomplex( z )
|
409
|
+
if z.is_a? Hornetseye::InternalComplex
|
410
|
+
log( ( 1.0 + z ) / ( 1.0 - z ) ) / 2.0
|
411
|
+
else
|
412
|
+
atanh_without_internalcomplex z
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
alias_method_chain :atanh, :internalcomplex
|
417
|
+
module_function :atanh_without_internalcomplex
|
418
|
+
module_function :atanh
|
419
|
+
|
420
|
+
def atan2_with_internalcomplex( y, x )
|
421
|
+
if [ x, y ].any? { |v| v.is_a? Hornetseye::InternalComplex }
|
422
|
+
-1.0.im * log( ( x + 1.0.im * y ) / sqrt( x * x + y * y ) )
|
423
|
+
else
|
424
|
+
atan2_without_internalcomplex y, x
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
alias_method_chain :atan2, :internalcomplex
|
429
|
+
module_function :atan2_without_internalcomplex
|
430
|
+
module_function :atan2
|
431
|
+
|
432
|
+
end
|
433
|
+
|
434
|
+
module Hornetseye
|
435
|
+
|
176
436
|
class COMPLEX_ < Composite
|
177
437
|
|
178
438
|
class << self
|
179
439
|
|
440
|
+
# Set base class attribute
|
441
|
+
#
|
442
|
+
# Sets number of elements to two.
|
180
443
|
def inherited( subclass )
|
181
444
|
subclass.num_elements = 2
|
182
445
|
end
|
183
446
|
|
447
|
+
# Construct new object from arguments
|
448
|
+
#
|
449
|
+
# @param [Object] real Real component of complex number.
|
450
|
+
# @param [Object] imag Imaginary component of complex number.
|
451
|
+
#
|
452
|
+
# @return [Complex,InternalComplex] New complex number object.
|
453
|
+
#
|
454
|
+
# @private
|
184
455
|
def construct( real, imag )
|
185
456
|
if Thread.current[ :function ]
|
186
|
-
new
|
457
|
+
new InternalComplex.new( real, imag )
|
187
458
|
else
|
188
459
|
new Complex( real, imag )
|
189
460
|
end
|
190
461
|
end
|
191
462
|
|
463
|
+
# Get default value for elements of this type
|
464
|
+
#
|
465
|
+
# @return [Object,InternalComplex] Returns complex number object with zero real
|
466
|
+
# and imaginary component.
|
467
|
+
#
|
468
|
+
# @private
|
192
469
|
def default
|
193
470
|
if Thread.current[ :function ]
|
194
|
-
|
471
|
+
InternalComplex.new 0, 0
|
195
472
|
else
|
196
|
-
|
473
|
+
Complex 0, 0
|
197
474
|
end
|
198
475
|
end
|
199
476
|
|
477
|
+
# Display information about this class
|
478
|
+
#
|
479
|
+
# @return [String] Returns string with information about this class (e.g.
|
480
|
+
# "SCOMPLEX").
|
200
481
|
def inspect
|
201
482
|
unless element_type.nil?
|
202
483
|
{ SFLOAT => 'SCOMPLEX',
|
@@ -207,14 +488,31 @@ module Hornetseye
|
|
207
488
|
end
|
208
489
|
end
|
209
490
|
|
491
|
+
# Get corresponding maximal integer type
|
492
|
+
#
|
493
|
+
# @return [Class] Corresponding type based on integers.
|
494
|
+
#
|
495
|
+
# @private
|
210
496
|
def maxint
|
211
497
|
Hornetseye::COMPLEX element_type.maxint
|
212
498
|
end
|
213
499
|
|
500
|
+
# Convert to type based on floating point numbers
|
501
|
+
#
|
502
|
+
# @return [Class] Corresponding type based on floating point numbers.
|
503
|
+
#
|
504
|
+
# @private
|
214
505
|
def float
|
215
506
|
Hornetseye::COMPLEX element_type.float
|
216
507
|
end
|
217
508
|
|
509
|
+
# Compute balanced type for binary operation
|
510
|
+
#
|
511
|
+
# @param [Class] other Other native datatype to coerce with.
|
512
|
+
#
|
513
|
+
# @return [Class] Result of coercion.
|
514
|
+
#
|
515
|
+
# @private
|
218
516
|
def coercion( other )
|
219
517
|
if other < COMPLEX_
|
220
518
|
Hornetseye::COMPLEX element_type.coercion( other.element_type )
|
@@ -225,6 +523,13 @@ module Hornetseye
|
|
225
523
|
end
|
226
524
|
end
|
227
525
|
|
526
|
+
# Type coercion for native elements
|
527
|
+
#
|
528
|
+
# @param [Class] other Other type to coerce with.
|
529
|
+
#
|
530
|
+
# @return [Array<Class>] Result of coercion.
|
531
|
+
#
|
532
|
+
# @private
|
228
533
|
def coerce( other )
|
229
534
|
if other < COMPLEX_
|
230
535
|
return other, self
|
@@ -235,15 +540,32 @@ module Hornetseye
|
|
235
540
|
end
|
236
541
|
end
|
237
542
|
|
543
|
+
# Test equality of classes
|
544
|
+
#
|
545
|
+
# @param [Object] other Object to compare with.
|
546
|
+
#
|
547
|
+
# @return [Boolean] Boolean indicating whether classes are equal.
|
238
548
|
def ==( other )
|
239
549
|
other.is_a? Class and other < COMPLEX_ and
|
240
550
|
element_type == other.element_type
|
241
551
|
end
|
242
552
|
|
553
|
+
# Compute hash value for this class.
|
554
|
+
#
|
555
|
+
# @return [Fixnum] Hash value
|
556
|
+
#
|
557
|
+
# @private
|
243
558
|
def hash
|
244
559
|
[ :COMPLEX_, element_type ].hash
|
245
560
|
end
|
246
561
|
|
562
|
+
# Equality for hash operations
|
563
|
+
#
|
564
|
+
# @param [Object] other Object to compare with.
|
565
|
+
#
|
566
|
+
# @return [Boolean] Returns +true+ if objects are equal.
|
567
|
+
#
|
568
|
+
# @private
|
247
569
|
def eql?( other )
|
248
570
|
self == other
|
249
571
|
end
|
@@ -257,22 +579,32 @@ module Hornetseye
|
|
257
579
|
else
|
258
580
|
real = GCCValue.new Thread.current[ :function ], value.real.to_s
|
259
581
|
imag = GCCValue.new Thread.current[ :function ], value.imag.to_s
|
260
|
-
@value =
|
582
|
+
@value = InternalComplex.new real, imag
|
261
583
|
end
|
262
584
|
end
|
263
585
|
|
586
|
+
# Duplicate object
|
587
|
+
#
|
588
|
+
# @return [COMPLEX_] Duplicate of +self+.
|
264
589
|
def dup
|
265
590
|
if Thread.current[ :function ]
|
266
591
|
real = Thread.current[ :function ].variable self.class.element_type, 'v'
|
267
592
|
imag = Thread.current[ :function ].variable self.class.element_type, 'v'
|
268
593
|
real.store @value.real
|
269
594
|
imag.store @value.imag
|
270
|
-
self.class.new
|
595
|
+
self.class.new InternalComplex.new( real, imag )
|
271
596
|
else
|
272
597
|
self.class.new get
|
273
598
|
end
|
274
599
|
end
|
275
600
|
|
601
|
+
# Store new value in this object
|
602
|
+
#
|
603
|
+
# @param [Object] value New value for this object.
|
604
|
+
#
|
605
|
+
# @return [Object] Returns +value+.
|
606
|
+
#
|
607
|
+
# @private
|
276
608
|
def store( value )
|
277
609
|
value = value.simplify
|
278
610
|
if @value.real.respond_to? :store
|
@@ -288,18 +620,34 @@ module Hornetseye
|
|
288
620
|
value
|
289
621
|
end
|
290
622
|
|
623
|
+
# Get array with components of this value
|
624
|
+
#
|
625
|
+
# @return [Array<Object>] Returns array with real and imaginary component as
|
626
|
+
# elements.
|
627
|
+
#
|
628
|
+
# @private
|
291
629
|
def values
|
292
630
|
[ @value.real, @value.imag ]
|
293
631
|
end
|
294
632
|
|
295
633
|
module Match
|
296
634
|
|
635
|
+
# Method for matching elements of type COMPLEX_
|
636
|
+
#
|
637
|
+
# @param [Array<Object>] *values Values to find matching native element
|
638
|
+
# type for.
|
639
|
+
#
|
640
|
+
# @return [Class] Native type fitting all values.
|
641
|
+
#
|
642
|
+
# @see COMPLEX_
|
643
|
+
#
|
644
|
+
# @private
|
297
645
|
def fit( *values )
|
298
|
-
if values.all? { |value| value.is_a?
|
646
|
+
if values.all? { |value| value.is_a? InternalComplex or value.is_a? Complex or
|
299
647
|
value.is_a? Float or value.is_a? Integer }
|
300
|
-
if values.any? { |value| value.is_a?
|
648
|
+
if values.any? { |value| value.is_a? InternalComplex or value.is_a? Complex }
|
301
649
|
elements = values.inject( [] ) do |arr,value|
|
302
|
-
if value.is_a?
|
650
|
+
if value.is_a? InternalComplex or value.is_a? Complex
|
303
651
|
arr + [ value.real, value.imag ]
|
304
652
|
else
|
305
653
|
arr + [ value ]
|
@@ -319,6 +667,14 @@ module Hornetseye
|
|
319
667
|
end
|
320
668
|
end
|
321
669
|
|
670
|
+
# Perform type alignment
|
671
|
+
#
|
672
|
+
# Align this type to another. This is used to prefer single-precision
|
673
|
+
# floating point in certain cases.
|
674
|
+
#
|
675
|
+
# @param [Class] context Other type to align with.
|
676
|
+
#
|
677
|
+
# @private
|
322
678
|
def align( context )
|
323
679
|
if self < COMPLEX_
|
324
680
|
Hornetseye::COMPLEX element_type.align( context )
|
@@ -333,6 +689,61 @@ module Hornetseye
|
|
333
689
|
|
334
690
|
end
|
335
691
|
|
692
|
+
module Operations
|
693
|
+
|
694
|
+
define_unary_op :real, :scalar
|
695
|
+
define_unary_op :imag, :scalar
|
696
|
+
|
697
|
+
def real_with_decompose
|
698
|
+
if typecode < COMPLEX_
|
699
|
+
decompose.roll.element 0
|
700
|
+
elsif typecode == OBJECT
|
701
|
+
real_without_decompose
|
702
|
+
else
|
703
|
+
self
|
704
|
+
end
|
705
|
+
end
|
706
|
+
|
707
|
+
alias_method_chain :real, :decompose
|
708
|
+
|
709
|
+
def real=( value )
|
710
|
+
if typecode < COMPLEX_
|
711
|
+
decompose.roll[ 0 ] = value
|
712
|
+
elsif typecode == OBJECT
|
713
|
+
self[] = Hornetseye::lazy do
|
714
|
+
value + imag * Complex::I
|
715
|
+
end
|
716
|
+
else
|
717
|
+
self[] = value
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
def imag_with_decompose
|
722
|
+
if typecode < COMPLEX_
|
723
|
+
decompose.roll.element 1
|
724
|
+
elsif typecode == OBJECT
|
725
|
+
imag_without_decompose
|
726
|
+
else
|
727
|
+
Hornetseye::lazy( *shape ) { typecode.new( 0 ) }
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
alias_method_chain :imag, :decompose
|
732
|
+
|
733
|
+
def imag=( value )
|
734
|
+
if typecode < COMPLEX_
|
735
|
+
decompose.roll[ 1 ] = value
|
736
|
+
elsif typecode == OBJECT
|
737
|
+
self[] = Hornetseye::lazy do
|
738
|
+
real + value * Complex::I
|
739
|
+
end
|
740
|
+
else
|
741
|
+
raise "Cannot assign imaginary values to object of type #{array_type.inspect}"
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
end
|
746
|
+
|
336
747
|
def COMPLEX( arg )
|
337
748
|
retval = Class.new COMPLEX_
|
338
749
|
retval.element_type = arg
|
@@ -345,10 +756,28 @@ module Hornetseye
|
|
345
756
|
|
346
757
|
DCOMPLEX = COMPLEX DFLOAT
|
347
758
|
|
759
|
+
# Shortcut for constructor
|
760
|
+
#
|
761
|
+
# The method calls +SCOMPLEX.new+.
|
762
|
+
#
|
763
|
+
# @param [Complex] value Complex value.
|
764
|
+
#
|
765
|
+
# @return [SCOMPLEX] The wrapped Complex value.
|
766
|
+
#
|
767
|
+
# @private
|
348
768
|
def SCOMPLEX( value )
|
349
769
|
SCOMPLEX.new value
|
350
770
|
end
|
351
771
|
|
772
|
+
# Shortcut for constructor
|
773
|
+
#
|
774
|
+
# The method calls +DCOMPLEX.new+.
|
775
|
+
#
|
776
|
+
# @param [Complex] value Complex value.
|
777
|
+
#
|
778
|
+
# @return [DCOMPLEX] The wrapped Complex value.
|
779
|
+
#
|
780
|
+
# @private
|
352
781
|
def DCOMPLEX( value )
|
353
782
|
DCOMPLEX.new value
|
354
783
|
end
|