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
@@ -0,0 +1,71 @@
|
|
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
|
+
module ConstructorShortcuts
|
21
|
+
|
22
|
+
def method_missing( name, *args )
|
23
|
+
if name.to_s =~ /^[a-z]+$/
|
24
|
+
target = name.to_s.upcase
|
25
|
+
if Hornetseye.const_defined? target
|
26
|
+
target = Hornetseye.const_get target
|
27
|
+
if target.is_a? Class and target < Element
|
28
|
+
new target, *args
|
29
|
+
else
|
30
|
+
super name, *args
|
31
|
+
end
|
32
|
+
else
|
33
|
+
super name, *args
|
34
|
+
end
|
35
|
+
else
|
36
|
+
super name, *args
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
Sequence.extend ConstructorShortcuts
|
43
|
+
|
44
|
+
MultiArray.extend ConstructorShortcuts
|
45
|
+
|
46
|
+
module ConversionShortcuts
|
47
|
+
|
48
|
+
def method_missing( name, *args )
|
49
|
+
if name.to_s =~ /^to_[a-z]+$/
|
50
|
+
target = name.to_s[ 3 .. -1 ].upcase
|
51
|
+
if Hornetseye.const_defined? target
|
52
|
+
target = Hornetseye.const_get target
|
53
|
+
if target.is_a? Class and target < Element
|
54
|
+
to_type target, *args
|
55
|
+
else
|
56
|
+
super target, *args
|
57
|
+
end
|
58
|
+
else
|
59
|
+
super name, *args
|
60
|
+
end
|
61
|
+
else
|
62
|
+
super name, *args
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
Node.class_eval { include ConversionShortcuts }
|
69
|
+
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,72 @@
|
|
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
|
+
module Hornetseye
|
18
|
+
|
19
|
+
class Store < Node
|
20
|
+
|
21
|
+
def initialize( dest, source )
|
22
|
+
@dest, @source = dest, source
|
23
|
+
end
|
24
|
+
|
25
|
+
def descriptor( hash )
|
26
|
+
"Store(#{@dest.descriptor( hash )},#{@source.descriptor( hash )})"
|
27
|
+
end
|
28
|
+
|
29
|
+
def array_type
|
30
|
+
@dest.array_type
|
31
|
+
end
|
32
|
+
|
33
|
+
def demand
|
34
|
+
if variables.empty?
|
35
|
+
if dimension > 0
|
36
|
+
shape.last.times do |i|
|
37
|
+
dest = @dest.element INT.new( i )
|
38
|
+
source = @source.dimension == 0 ? @source :
|
39
|
+
@source.element( INT.new( i ) )
|
40
|
+
Store.new( dest, source ).demand
|
41
|
+
end
|
42
|
+
else
|
43
|
+
@dest.store @source.demand
|
44
|
+
end
|
45
|
+
@dest
|
46
|
+
else
|
47
|
+
super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def subst( hash )
|
52
|
+
self.class.new @dest.subst( hash ), @source.subst( hash )
|
53
|
+
end
|
54
|
+
|
55
|
+
def variables
|
56
|
+
@dest.variables + @source.variables
|
57
|
+
end
|
58
|
+
|
59
|
+
def strip
|
60
|
+
vars1, values1, term1 = @dest.strip
|
61
|
+
vars2, values2, term2 = @source.strip
|
62
|
+
return vars1 + vars2, values1 + values2, Store.new( term1, term2 )
|
63
|
+
end
|
64
|
+
|
65
|
+
def compilable?
|
66
|
+
@dest.compilable? and @source.compilable?
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
data/lib/multiarray/variable.rb
CHANGED
@@ -28,6 +28,10 @@ module Hornetseye
|
|
28
28
|
@meta = meta
|
29
29
|
end
|
30
30
|
|
31
|
+
# Display string with information about this object
|
32
|
+
#
|
33
|
+
# @return [String] String with information about this object (e.g.
|
34
|
+
# 'Variable(INT)').
|
31
35
|
def inspect
|
32
36
|
"Variable(#{@meta.inspect})"
|
33
37
|
end
|
@@ -47,14 +51,27 @@ module Hornetseye
|
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
54
|
+
# Get array size for index variable
|
55
|
+
#
|
56
|
+
# @return [Node] Get the dimension of the array if this is an index variable.
|
50
57
|
def size
|
51
58
|
@meta.size
|
52
59
|
end
|
53
60
|
|
61
|
+
# Set array size for index variable
|
62
|
+
#
|
63
|
+
# Set the dimension of the array assuming this is an index variable.
|
64
|
+
#
|
65
|
+
# @param [Node] value The new size.
|
54
66
|
def size=( value )
|
55
67
|
@meta.size = value
|
56
68
|
end
|
57
69
|
|
70
|
+
# Get type of result of delayed operation
|
71
|
+
#
|
72
|
+
# @return [Class] Type of result.
|
73
|
+
#
|
74
|
+
# @private
|
58
75
|
def array_type
|
59
76
|
@meta.array_type
|
60
77
|
end
|
@@ -115,6 +132,14 @@ module Hornetseye
|
|
115
132
|
Lookup.new self, value, stride
|
116
133
|
end
|
117
134
|
|
135
|
+
# Skip elements of an array
|
136
|
+
#
|
137
|
+
# @param [Variable] index Variable identifying index of array.
|
138
|
+
# @param [Node] start Wrapped integer with number of elements to skip.
|
139
|
+
#
|
140
|
+
# @return [Node] Return variable with offset added or +self+.
|
141
|
+
#
|
142
|
+
# @private
|
118
143
|
def skip( index, start )
|
119
144
|
if index == self
|
120
145
|
self + start
|
data/lib/multiarray.rb
CHANGED
@@ -21,7 +21,13 @@ class Module
|
|
21
21
|
|
22
22
|
unless method_defined? :alias_method_chain
|
23
23
|
|
24
|
-
# Method for creating alias chains
|
24
|
+
# Method for creating alias chains
|
25
|
+
#
|
26
|
+
# @param [Symbol,String] target Method to rename.
|
27
|
+
# @param [Symbol,String] feature Feature to use for renaming.
|
28
|
+
# @param [Symbol,String] vocalize Override to use when renaming operators.
|
29
|
+
#
|
30
|
+
# @return [Module] Returns this module.
|
25
31
|
#
|
26
32
|
# @private
|
27
33
|
def alias_method_chain( target, feature, vocalize = target )
|
@@ -44,6 +50,8 @@ class Proc
|
|
44
50
|
#
|
45
51
|
# @param [Object] object Object to bind this instance of +Proc+ to.
|
46
52
|
#
|
53
|
+
# @return [Method] The bound method.
|
54
|
+
#
|
47
55
|
# @private
|
48
56
|
def bind( object )
|
49
57
|
block, time = self, Time.now
|
@@ -416,22 +424,39 @@ end
|
|
416
424
|
|
417
425
|
class Numeric
|
418
426
|
|
427
|
+
# Compute complex conjugate
|
428
|
+
#
|
429
|
+
# @return [Numeric] Returns +self+.
|
419
430
|
def conj
|
420
431
|
self
|
421
432
|
end
|
422
433
|
|
434
|
+
# Get red component
|
435
|
+
#
|
436
|
+
# @return [Numeric] Returns +self+.
|
423
437
|
def r
|
424
438
|
self
|
425
439
|
end
|
426
440
|
|
441
|
+
# Get green component
|
442
|
+
#
|
443
|
+
# @return [Numeric] Returns +self+.
|
427
444
|
def g
|
428
445
|
self
|
429
446
|
end
|
430
447
|
|
448
|
+
# Get blue component
|
449
|
+
#
|
450
|
+
# @return [Numeric] Returns +self+.
|
431
451
|
def b
|
432
452
|
self
|
433
453
|
end
|
434
454
|
|
455
|
+
# Get larger number of two numbers
|
456
|
+
#
|
457
|
+
# @param [Numeric] other The other number.
|
458
|
+
#
|
459
|
+
# @return [Numeric] The larger number of the two.
|
435
460
|
def major( other )
|
436
461
|
if other.is_a? Numeric
|
437
462
|
( self >= other ).conditional self, other
|
@@ -441,6 +466,11 @@ class Numeric
|
|
441
466
|
end
|
442
467
|
end
|
443
468
|
|
469
|
+
# Get smaller number of two numbers
|
470
|
+
#
|
471
|
+
# @param [Numeric] other The other number.
|
472
|
+
#
|
473
|
+
# @return [Numeric] The smaller number of the two.
|
444
474
|
def minor( other )
|
445
475
|
if other.is_a? Numeric
|
446
476
|
( self <= other ).conditional self, other
|
@@ -454,6 +484,13 @@ end
|
|
454
484
|
|
455
485
|
class Array
|
456
486
|
|
487
|
+
# Element-wise operation based on element and its index
|
488
|
+
#
|
489
|
+
# Same as +Array#collect+ but with index.
|
490
|
+
#
|
491
|
+
# @param &action Closure accepting an element and an index.
|
492
|
+
#
|
493
|
+
# @return [Array<Object>] Array with results.
|
457
494
|
def collect_with_index( &action )
|
458
495
|
zip( ( 0 ... size ).to_a ).collect &action
|
459
496
|
end
|
@@ -470,24 +507,29 @@ require 'multiarray/list'
|
|
470
507
|
require 'multiarray/node'
|
471
508
|
require 'multiarray/element'
|
472
509
|
require 'multiarray/composite'
|
510
|
+
require 'multiarray/store'
|
473
511
|
require 'multiarray/object'
|
474
512
|
require 'multiarray/index'
|
475
513
|
require 'multiarray/bool'
|
476
514
|
require 'multiarray/int'
|
477
515
|
require 'multiarray/float'
|
478
|
-
require 'multiarray/rgb'
|
479
|
-
require 'multiarray/complex'
|
480
516
|
require 'multiarray/pointer'
|
481
517
|
require 'multiarray/variable'
|
482
518
|
require 'multiarray/lambda'
|
483
519
|
require 'multiarray/lookup'
|
484
520
|
require 'multiarray/elementwise'
|
485
|
-
require 'multiarray/operations'
|
486
|
-
require 'multiarray/methods'
|
487
521
|
require 'multiarray/inject'
|
488
522
|
require 'multiarray/diagonal'
|
523
|
+
require 'multiarray/histogram'
|
524
|
+
require 'multiarray/lut'
|
525
|
+
require 'multiarray/integral'
|
526
|
+
require 'multiarray/operations'
|
527
|
+
require 'multiarray/methods'
|
528
|
+
require 'multiarray/rgb'
|
529
|
+
require 'multiarray/complex'
|
489
530
|
require 'multiarray/sequence'
|
490
531
|
require 'multiarray/multiarray'
|
532
|
+
require 'multiarray/shortcuts'
|
491
533
|
require 'multiarray/gcctype'
|
492
534
|
require 'multiarray/gccvalue'
|
493
535
|
require 'multiarray/gcccontext'
|
data/test/tc_int.rb
CHANGED
@@ -209,5 +209,15 @@ class TC_Int < Test::Unit::TestCase
|
|
209
209
|
assert_equal I( 4 ), I( 5 ).minor( I( 4 ) )
|
210
210
|
end
|
211
211
|
|
212
|
+
def test_fill
|
213
|
+
i = I 0
|
214
|
+
assert_equal I( 3 ), i.fill!( 3 )
|
215
|
+
assert_equal I( 3 ), i
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_integral
|
219
|
+
assert_equal I( 3 ), I( 3 ).integral
|
220
|
+
end
|
221
|
+
|
212
222
|
end
|
213
223
|
|
data/test/tc_multiarray.rb
CHANGED
@@ -364,6 +364,14 @@ class TC_MultiArray < Test::Unit::TestCase
|
|
364
364
|
assert_equal 7, M[ [ 5, 3, 7 ], [ 2, 1, 6 ] ].max
|
365
365
|
end
|
366
366
|
|
367
|
+
def test_sum
|
368
|
+
assert_equal 24, M[ [ 5, 3, 7 ], [ 2, 1, 6 ] ].sum
|
369
|
+
end
|
370
|
+
|
371
|
+
def test_range
|
372
|
+
assert_equal 1 .. 7, M[ [ 5, 3, 7 ], [ 2, 1, 6 ] ].range
|
373
|
+
end
|
374
|
+
|
367
375
|
def test_diagonal
|
368
376
|
assert_equal S[ 'b1a2', 'c1b2a3', 'c2b3' ],
|
369
377
|
M[ [ 'a1', 'a2', 'a3' ],
|
@@ -398,6 +406,32 @@ class TC_MultiArray < Test::Unit::TestCase
|
|
398
406
|
assert_raise( RuntimeError ) { M[ [ 1, 2, 3 ], [ 4, 5, 6 ] ].convolve S[ 1, 2 ] }
|
399
407
|
end
|
400
408
|
|
409
|
+
def test_histogram
|
410
|
+
assert_equal S( I, 5 )[ 0, 1, 1, 2, 0 ],
|
411
|
+
M[ [ 1, 2 ], [ 3, 3 ] ].histogram( 5, :target => I )
|
412
|
+
assert_equal M( I, 2, 2 )[ [ 1, 0 ], [ 1, 1 ] ],
|
413
|
+
M[ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ] ].histogram( 2, 2, :target => I )
|
414
|
+
assert_equal M( I, 2, 2, 1 )[ [ [ 0, 1 ], [ 1, 0 ] ] ],
|
415
|
+
S[ C( 1, 0, 0 ), C( 0, 1, 0 ) ].histogram( 2, 2, 1, :target => I )
|
416
|
+
assert_raise( RuntimeError ) { S[ 1, 2, 3 ].histogram 4, 4 }
|
417
|
+
assert_raise( RuntimeError ) { M[ [ -1, 0 ] ].histogram 3, 2 }
|
418
|
+
assert_raise( RuntimeError ) { M[ [ 0, -1 ] ].histogram 3, 2 }
|
419
|
+
assert_raise( RuntimeError ) { M[ [ 3, 0 ] ].histogram 3, 2 }
|
420
|
+
assert_raise( RuntimeError ) { M[ [ 0, 2 ] ].histogram 3, 2 }
|
421
|
+
end
|
422
|
+
|
423
|
+
def test_lut
|
424
|
+
assert_equal M[ [ 1, 2 ], [ 3, 1 ] ],
|
425
|
+
M[ [ 0, 1 ], [ 2, 0 ] ].lut( S[ 1, 2, 3, 4 ] )
|
426
|
+
assert_equal M[ 1, 3, 4 ],
|
427
|
+
M[ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ] ].lut( M[ [ 1, 2 ], [ 3, 4 ] ] )
|
428
|
+
assert_raise( RuntimeError ) { S[ 0, 1, 2 ].lut M[ [ 1, 2 ], [ 3, 4 ] ] }
|
429
|
+
assert_raise( RuntimeError ) { M[ [ -1, 0 ] ].lut M[ [ 1, 2 ] ] }
|
430
|
+
assert_raise( RuntimeError ) { M[ [ 0, -1 ] ].lut M[ [ 1, 2 ] ] }
|
431
|
+
assert_raise( RuntimeError ) { M[ [ 2, 0 ] ].lut M[ [ 1, 2 ] ] }
|
432
|
+
assert_raise( RuntimeError ) { M[ [ 0, 1 ] ].lut M[ [ 1, 2 ] ] }
|
433
|
+
end
|
434
|
+
|
401
435
|
def test_zero
|
402
436
|
assert_equal M[ [ false, true ], [ true, false ] ],
|
403
437
|
M[ [ -1, 0 ], [ 0, 1 ] ].zero?
|
@@ -554,10 +588,22 @@ class TC_MultiArray < Test::Unit::TestCase
|
|
554
588
|
assert_equal M[ [ 1, 1 ], [ 0, -1 ] ], 3 <=> M[ [ 1, 2 ], [ 3, 4 ] ]
|
555
589
|
end
|
556
590
|
|
591
|
+
def test_fill
|
592
|
+
m = M( I, 3, 2 )[ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
|
593
|
+
assert_equal M( I, 3, 2 )[ [ 1, 1, 1 ], [ 1, 1, 1 ] ], m.fill!( 1 )
|
594
|
+
assert_equal M( I, 3, 2 )[ [ 1, 1, 1 ], [ 1, 1, 1 ] ], m
|
595
|
+
end
|
596
|
+
|
557
597
|
def test_to_type
|
558
598
|
assert_equal M( C, 2, 2 )[ [ 1, 2 ], [ 3, 4 ] ],
|
559
|
-
M( I, 2, 2 )[ [ 1, 2 ], [ 3, 4 ] ].
|
599
|
+
M( I, 2, 2 )[ [ 1, 2 ], [ 3, 4 ] ].to_intrgb
|
560
600
|
end
|
561
601
|
|
602
|
+
def test_integral
|
603
|
+
assert_equal M( O, 3, 2 )[ [ 1, 3, 6 ], [ 5, 12, 21 ] ],
|
604
|
+
M( O, 3, 2 )[ [ 1, 2, 3 ], [ 4, 5, 6 ] ].integral
|
605
|
+
assert_equal M( I, 3, 2 )[ [ 1, 3, 6 ], [ 5, 12, 21 ] ],
|
606
|
+
M( I, 3, 2 )[ [ 1, 2, 3 ], [ 4, 5, 6 ] ].integral
|
607
|
+
end
|
562
608
|
|
563
609
|
end
|
data/test/tc_object.rb
CHANGED
@@ -134,4 +134,14 @@ class TC_Object < Test::Unit::TestCase
|
|
134
134
|
assert_equal O( 2 ), O( true ).conditional( O( 2 ), O( 1 ) )
|
135
135
|
end
|
136
136
|
|
137
|
+
def test_fill
|
138
|
+
o = O 3
|
139
|
+
assert_equal O( 1 ), o.fill!( 1 )
|
140
|
+
assert_equal O( 1 ), o
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_integral
|
144
|
+
assert_equal O( 3 ), O( 3 ).integral
|
145
|
+
end
|
146
|
+
|
137
147
|
end
|