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 CHANGED
@@ -6,7 +6,7 @@ require 'rake/packagetask'
6
6
  require 'rbconfig'
7
7
 
8
8
  PKG_NAME = 'multiarray'
9
- PKG_VERSION = '0.5.1'
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.0' ]
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.0' ]
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
- # type alignment for operators and methods, Math.sqrt( SFLOAT )
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
- # inject: n-d clips for warp
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
- # Composite numbers?
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
- # histogram
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/unaryop'
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
+