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/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'rake/packagetask'
|
|
6
6
|
require 'rbconfig'
|
7
7
|
|
8
8
|
PKG_NAME = 'multiarray'
|
9
|
-
PKG_VERSION = '0.5.
|
9
|
+
PKG_VERSION = '0.5.2'
|
10
10
|
RB_FILES = FileList[ 'lib/**/*.rb' ]
|
11
11
|
TC_FILES = FileList[ 'test/tc_*.rb' ]
|
12
12
|
TS_FILES = FileList[ 'test/ts_*.rb' ]
|
@@ -86,7 +86,7 @@ begin
|
|
86
86
|
s.has_rdoc = 'yard'
|
87
87
|
s.extra_rdoc_files = []
|
88
88
|
s.rdoc_options = %w{--no-private}
|
89
|
-
s.add_dependency %q<malloc>, [ '~> 1.
|
89
|
+
s.add_dependency %q<malloc>, [ '~> 1.1' ]
|
90
90
|
s.add_development_dependency %q{rake}
|
91
91
|
end
|
92
92
|
GEM_SOURCE = "#{PKG_NAME}-#{PKG_VERSION}.gem"
|
@@ -107,7 +107,7 @@ begin
|
|
107
107
|
s.has_rdoc = 'yard'
|
108
108
|
s.extra_rdoc_files = []
|
109
109
|
s.rdoc_options = %w{--no-private}
|
110
|
-
s.add_dependency %q<malloc>, [ '~> 1.
|
110
|
+
s.add_dependency %q<malloc>, [ '~> 1.1' ]
|
111
111
|
end
|
112
112
|
GEM_BINARY = "#{PKG_NAME}-#{PKG_VERSION}-#{$BINSPEC.platform}.gem"
|
113
113
|
desc "Build the gem file #{GEM_SOURCE}"
|
data/TODO
CHANGED
@@ -1,18 +1,12 @@
|
|
1
|
-
#
|
2
|
-
# test floor, ceil, ..., factor out common stuff of UnaryOp and UnaryMethod
|
3
|
-
# complex numbers, factor out composite numbers
|
4
|
-
# Fast filling of arrays, duplication, type conversions
|
5
|
-
# use descriptors ('c','f',...)?
|
1
|
+
# use descriptors ('c','f',...)? GCCValue.identifiers is not modular
|
6
2
|
# pointer-increments for better efficiency, optimize Node#diagonal
|
7
|
-
# implement typecasts, how does contiguous work here?
|
8
|
-
# documentation!
|
9
3
|
|
10
4
|
# histogram (implement using injection)
|
11
|
-
#
|
5
|
+
# random numbers
|
6
|
+
# Geometric Hashing? Bounded Hough Transform!!! RANSAC? histogram weights?
|
7
|
+
# each, multi_each, collect, multi_collect, zip?
|
8
|
+
# inject: n-d masks for warp
|
12
9
|
# block(var1,var2,...) with smart subst?
|
13
|
-
# lazy( 3, 2 ) { |i,j| j.to_object }
|
14
|
-
|
15
|
-
# RSpec
|
16
10
|
|
17
11
|
# downsampling after correlation?
|
18
12
|
# YARD documentation with pictures, demo video
|
@@ -27,19 +21,10 @@
|
|
27
21
|
# end
|
28
22
|
#end
|
29
23
|
|
30
|
-
|
31
24
|
# cache <-> demand/get? what about store?
|
32
|
-
#
|
33
|
-
# change Convolve#demand to generate GCC code
|
34
|
-
# inspect method (type method to get MultiArray( ... ) or Sequence( ... ))
|
35
|
-
# put JIT-calls into 'force'-method, don't call JIT for OBJECT
|
36
|
-
# -> multiarray gem
|
37
|
-
# pointer-increments for better efficiency
|
38
|
-
# use pid, allow creation of library for pre-loading cache
|
25
|
+
# allow creation of library for pre-loading cache
|
39
26
|
|
40
|
-
#
|
41
|
-
# binary operations, equality: ( a == b ).inject( true ) { |e,b| e && b }
|
42
|
-
# inject: min, max, equal, n-d clips for warp
|
27
|
+
# use inject for n-d clips for warp
|
43
28
|
# block(var1,var2,...) with smart subst?
|
44
29
|
|
45
30
|
# downsampling after correlation?
|
@@ -55,7 +40,6 @@
|
|
55
40
|
# end
|
56
41
|
#end
|
57
42
|
|
58
|
-
ranges (rolling, lazy rolling, lazy ranges)
|
59
43
|
test type conversions
|
60
44
|
|
61
45
|
a = lazy( 16, 32 ) { |i,j| Sequence[ i, j ] } # ???
|
@@ -75,11 +59,3 @@ combined histograms?
|
|
75
59
|
circle:
|
76
60
|
[ sin( i ) * r, cos( i ) * r ].hist
|
77
61
|
|
78
|
-
Geometric Hashing? Bounded Hough Transform!!! RANSAC? histogram weights?
|
79
|
-
|
80
|
-
array: lazy retrieval? jit code for address computation
|
81
|
-
OBJECT: object with type information
|
82
|
-
Lazy( Sequence( INT, 3 ) )
|
83
|
-
|
84
|
-
interpretation: type coercion, actual operation, jit,
|
85
|
-
collection of jit arguments (e.g. tensor)
|
data/lib/multiarray.rb
CHANGED
@@ -416,6 +416,10 @@ end
|
|
416
416
|
|
417
417
|
class Numeric
|
418
418
|
|
419
|
+
def conj
|
420
|
+
self
|
421
|
+
end
|
422
|
+
|
419
423
|
def r
|
420
424
|
self
|
421
425
|
end
|
@@ -456,6 +460,7 @@ class Array
|
|
456
460
|
|
457
461
|
end
|
458
462
|
|
463
|
+
require 'complex'
|
459
464
|
require 'malloc'
|
460
465
|
require 'rbconfig'
|
461
466
|
require 'set'
|
@@ -464,20 +469,19 @@ require 'multiarray/malloc'
|
|
464
469
|
require 'multiarray/list'
|
465
470
|
require 'multiarray/node'
|
466
471
|
require 'multiarray/element'
|
472
|
+
require 'multiarray/composite'
|
467
473
|
require 'multiarray/object'
|
468
474
|
require 'multiarray/index'
|
469
475
|
require 'multiarray/bool'
|
470
476
|
require 'multiarray/int'
|
471
477
|
require 'multiarray/float'
|
472
478
|
require 'multiarray/rgb'
|
479
|
+
require 'multiarray/complex'
|
473
480
|
require 'multiarray/pointer'
|
474
481
|
require 'multiarray/variable'
|
475
482
|
require 'multiarray/lambda'
|
476
483
|
require 'multiarray/lookup'
|
477
|
-
require 'multiarray/
|
478
|
-
require 'multiarray/unarymethod'
|
479
|
-
require 'multiarray/binaryop'
|
480
|
-
require 'multiarray/binarymethod'
|
484
|
+
require 'multiarray/elementwise'
|
481
485
|
require 'multiarray/operations'
|
482
486
|
require 'multiarray/methods'
|
483
487
|
require 'multiarray/inject'
|
@@ -0,0 +1,360 @@
|
|
1
|
+
# multiarray - Lazy multi-dimensional arrays for Ruby
|
2
|
+
# Copyright (C) 2010 Jan Wedekind
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
# Namespace of Hornetseye computer vision library
|
18
|
+
module Hornetseye
|
19
|
+
|
20
|
+
class Complex
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def generic?( value )
|
25
|
+
value.is_a?( Numeric ) or value.is_a?( GCCValue )
|
26
|
+
end
|
27
|
+
|
28
|
+
def polar( r, theta )
|
29
|
+
new r * Math.cos( theta ), r * Math.sin( theta )
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_accessor :real, :imag
|
35
|
+
|
36
|
+
def initialize( real, imag )
|
37
|
+
@real, @imag = real, imag
|
38
|
+
end
|
39
|
+
|
40
|
+
def inspect
|
41
|
+
"Hornetseye::Complex(#{@real.inspect},#{@imag.inspect})"
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
"Complex(#{@real.to_s},#{@imag.to_s})"
|
46
|
+
end
|
47
|
+
|
48
|
+
def store( value )
|
49
|
+
@real, @imag = value.real, value.imag
|
50
|
+
end
|
51
|
+
|
52
|
+
def coerce( other )
|
53
|
+
if other.is_a? Complex
|
54
|
+
return other, self
|
55
|
+
elsif other.is_a? ::Complex
|
56
|
+
return Complex.new( other.real, other.imag ), self
|
57
|
+
else
|
58
|
+
return Complex.new( other, 0 ), self
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def conj
|
63
|
+
Complex.new @real, -@imag
|
64
|
+
end
|
65
|
+
|
66
|
+
def abs
|
67
|
+
Math.hypot @real, @imag
|
68
|
+
end
|
69
|
+
|
70
|
+
def arg
|
71
|
+
Math.atan2 @imag, @real
|
72
|
+
end
|
73
|
+
|
74
|
+
def polar
|
75
|
+
return abs, arg
|
76
|
+
end
|
77
|
+
|
78
|
+
def +@
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def -@
|
83
|
+
Complex.new -@real, -@imag
|
84
|
+
end
|
85
|
+
|
86
|
+
def +( other )
|
87
|
+
if other.is_a?( Complex ) or other.is_a?( ::Complex )
|
88
|
+
Complex.new @real + other.real, @imag + other.imag
|
89
|
+
elsif Complex.generic? other
|
90
|
+
Complex.new @real + other, @imag
|
91
|
+
else
|
92
|
+
x, y = other.coerce self
|
93
|
+
x + y
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def -( other )
|
98
|
+
if other.is_a?( Complex ) or other.is_a?( ::Complex )
|
99
|
+
Complex.new @real - other.real, @imag - other.imag
|
100
|
+
elsif Complex.generic? other
|
101
|
+
Complex.new @real - other, @imag
|
102
|
+
else
|
103
|
+
x, y = other.coerce self
|
104
|
+
x - y
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def *( other )
|
109
|
+
if other.is_a?( Complex ) or other.is_a?( ::Complex )
|
110
|
+
Complex.new @real * other.real - @imag * other.imag,
|
111
|
+
@real * other.imag + @imag * other.real
|
112
|
+
elsif Complex.generic? other
|
113
|
+
Complex.new @real * other, @imag * other
|
114
|
+
else
|
115
|
+
x, y = other.coerce self
|
116
|
+
x * y
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def /( other )
|
121
|
+
if other.is_a?( Complex ) or other.is_a?( ::Complex )
|
122
|
+
self * other.conj / other.abs2
|
123
|
+
elsif Complex.generic? other
|
124
|
+
Complex.new @real / other, @imag / other
|
125
|
+
else
|
126
|
+
x, y = other.coerce self
|
127
|
+
x / y
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def **( other )
|
132
|
+
if other.is_a?( Complex ) or other.is_a?( ::Complex )
|
133
|
+
r, theta = polar
|
134
|
+
ore = other.real
|
135
|
+
oim = other.imag
|
136
|
+
nr = Math.exp ore * Math.log( r ) - oim * theta
|
137
|
+
ntheta = theta * ore + oim * Math.log( r )
|
138
|
+
Complex.polar nr, ntheta
|
139
|
+
elsif Complex.generic? other
|
140
|
+
r, theta = polar
|
141
|
+
Complex.polar r ** other, theta * other
|
142
|
+
else
|
143
|
+
x, y = other.coerce self
|
144
|
+
x ** y
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def zero?
|
149
|
+
@real.zero?.and @imag.zero?
|
150
|
+
end
|
151
|
+
|
152
|
+
def nonzero?
|
153
|
+
@real.nonzero?.or @imag.nonzero?
|
154
|
+
end
|
155
|
+
|
156
|
+
def abs2
|
157
|
+
@real * @real + @imag * @imag
|
158
|
+
end
|
159
|
+
|
160
|
+
def ==( other )
|
161
|
+
if other.is_a?( Complex ) or other.is_a?( ::Complex )
|
162
|
+
@real.eq( other.real ).and( @imag.eq( other.imag ) )
|
163
|
+
elsif Complex.generic? other
|
164
|
+
@real.eq( other ).and( @imag.eq( 0 ) )
|
165
|
+
else
|
166
|
+
false
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def decompose
|
171
|
+
Hornetseye::Sequence[ @real, @imag ]
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
class COMPLEX_ < Composite
|
177
|
+
|
178
|
+
class << self
|
179
|
+
|
180
|
+
def inherited( subclass )
|
181
|
+
subclass.num_elements = 2
|
182
|
+
end
|
183
|
+
|
184
|
+
def construct( real, imag )
|
185
|
+
if Thread.current[ :function ]
|
186
|
+
new Complex.new( real, imag )
|
187
|
+
else
|
188
|
+
new Complex( real, imag )
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def default
|
193
|
+
if Thread.current[ :function ]
|
194
|
+
Complex.new 0, 0
|
195
|
+
else
|
196
|
+
Kernel::Complex 0, 0
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def inspect
|
201
|
+
unless element_type.nil?
|
202
|
+
{ SFLOAT => 'SCOMPLEX',
|
203
|
+
DFLOAT => 'DCOMPLEX' }[ element_type ] ||
|
204
|
+
"COMPLEX(#{element_type.inspect})"
|
205
|
+
else
|
206
|
+
super
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def maxint
|
211
|
+
Hornetseye::COMPLEX element_type.maxint
|
212
|
+
end
|
213
|
+
|
214
|
+
def float
|
215
|
+
Hornetseye::COMPLEX element_type.float
|
216
|
+
end
|
217
|
+
|
218
|
+
def coercion( other )
|
219
|
+
if other < COMPLEX_
|
220
|
+
Hornetseye::COMPLEX element_type.coercion( other.element_type )
|
221
|
+
elsif other < INT_ or other < FLOAT_
|
222
|
+
Hornetseye::COMPLEX element_type.coercion( other )
|
223
|
+
else
|
224
|
+
super other
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def coerce( other )
|
229
|
+
if other < COMPLEX_
|
230
|
+
return other, self
|
231
|
+
elsif other < INT_ or other < FLOAT_
|
232
|
+
return Hornetseye::COMPLEX( other ), self
|
233
|
+
else
|
234
|
+
super other
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def ==( other )
|
239
|
+
other.is_a? Class and other < COMPLEX_ and
|
240
|
+
element_type == other.element_type
|
241
|
+
end
|
242
|
+
|
243
|
+
def hash
|
244
|
+
[ :COMPLEX_, element_type ].hash
|
245
|
+
end
|
246
|
+
|
247
|
+
def eql?( other )
|
248
|
+
self == other
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
def initialize( value = self.class.default )
|
254
|
+
if Thread.current[ :function ].nil? or
|
255
|
+
[ value.real, value.imag ].all? { |c| c.is_a? GCCValue }
|
256
|
+
@value = value
|
257
|
+
else
|
258
|
+
real = GCCValue.new Thread.current[ :function ], value.real.to_s
|
259
|
+
imag = GCCValue.new Thread.current[ :function ], value.imag.to_s
|
260
|
+
@value = Complex.new real, imag
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def dup
|
265
|
+
if Thread.current[ :function ]
|
266
|
+
real = Thread.current[ :function ].variable self.class.element_type, 'v'
|
267
|
+
imag = Thread.current[ :function ].variable self.class.element_type, 'v'
|
268
|
+
real.store @value.real
|
269
|
+
imag.store @value.imag
|
270
|
+
self.class.new Complex.new( real, imag )
|
271
|
+
else
|
272
|
+
self.class.new get
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def store( value )
|
277
|
+
value = value.simplify
|
278
|
+
if @value.real.respond_to? :store
|
279
|
+
@value.real.store value.get.real
|
280
|
+
else
|
281
|
+
@value.real = value.get.real
|
282
|
+
end
|
283
|
+
if @value.imag.respond_to? :store
|
284
|
+
@value.imag.store value.get.imag
|
285
|
+
else
|
286
|
+
@value.imag = value.get.imag
|
287
|
+
end
|
288
|
+
value
|
289
|
+
end
|
290
|
+
|
291
|
+
def values
|
292
|
+
[ @value.real, @value.imag ]
|
293
|
+
end
|
294
|
+
|
295
|
+
module Match
|
296
|
+
|
297
|
+
def fit( *values )
|
298
|
+
if values.all? { |value| value.is_a? Complex or value.is_a? ::Complex or
|
299
|
+
value.is_a? Float or value.is_a? Integer }
|
300
|
+
if values.any? { |value| value.is_a? Complex or value.is_a? ::Complex }
|
301
|
+
elements = values.inject( [] ) do |arr,value|
|
302
|
+
if value.is_a? Complex or value.is_a? ::Complex
|
303
|
+
arr + [ value.real, value.imag ]
|
304
|
+
else
|
305
|
+
arr + [ value ]
|
306
|
+
end
|
307
|
+
end
|
308
|
+
element_fit = fit *elements
|
309
|
+
if element_fit == OBJECT
|
310
|
+
super *values
|
311
|
+
else
|
312
|
+
Hornetseye::COMPLEX element_fit
|
313
|
+
end
|
314
|
+
else
|
315
|
+
super *values
|
316
|
+
end
|
317
|
+
else
|
318
|
+
super *values
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def align( context )
|
323
|
+
if self < COMPLEX_
|
324
|
+
Hornetseye::COMPLEX element_type.align( context )
|
325
|
+
else
|
326
|
+
super context
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
331
|
+
|
332
|
+
Node.extend Match
|
333
|
+
|
334
|
+
end
|
335
|
+
|
336
|
+
def COMPLEX( arg )
|
337
|
+
retval = Class.new COMPLEX_
|
338
|
+
retval.element_type = arg
|
339
|
+
retval
|
340
|
+
end
|
341
|
+
|
342
|
+
module_function :COMPLEX
|
343
|
+
|
344
|
+
SCOMPLEX = COMPLEX SFLOAT
|
345
|
+
|
346
|
+
DCOMPLEX = COMPLEX DFLOAT
|
347
|
+
|
348
|
+
def SCOMPLEX( value )
|
349
|
+
SCOMPLEX.new value
|
350
|
+
end
|
351
|
+
|
352
|
+
def DCOMPLEX( value )
|
353
|
+
DCOMPLEX.new value
|
354
|
+
end
|
355
|
+
|
356
|
+
module_function :SCOMPLEX
|
357
|
+
module_function :DCOMPLEX
|
358
|
+
|
359
|
+
end
|
360
|
+
|