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 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
+