multiarray 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +39 -5
- data/TODO +11 -66
- data/lib/multiarray.rb +59 -12
- data/lib/multiarray/binarymethod.rb +195 -0
- data/lib/multiarray/{binary.rb → binaryop.rb} +27 -12
- data/lib/multiarray/bool.rb +8 -2
- data/lib/multiarray/diagonal.rb +26 -27
- data/lib/multiarray/element.rb +23 -5
- data/lib/multiarray/float.rb +142 -0
- data/lib/multiarray/gcccontext.rb +29 -25
- data/lib/multiarray/gccfunction.rb +24 -7
- data/lib/multiarray/gcctype.rb +26 -16
- data/lib/multiarray/gccvalue.rb +144 -74
- data/lib/multiarray/inject.rb +12 -15
- data/lib/multiarray/int.rb +109 -82
- data/lib/multiarray/lambda.rb +23 -1
- data/lib/multiarray/lookup.rb +14 -1
- data/lib/multiarray/malloc.rb +2 -2
- data/lib/multiarray/methods.rb +93 -0
- data/lib/multiarray/multiarray.rb +2 -12
- data/lib/multiarray/node.rb +103 -173
- data/lib/multiarray/object.rb +19 -1
- data/lib/multiarray/operations.rb +189 -9
- data/lib/multiarray/pointer.rb +9 -1
- data/lib/multiarray/rgb.rb +401 -0
- data/lib/multiarray/sequence.rb +56 -14
- data/lib/multiarray/unarymethod.rb +185 -0
- data/lib/multiarray/{unary.rb → unaryop.rb} +20 -11
- data/lib/multiarray/variable.rb +8 -0
- data/test/tc_bool.rb +32 -20
- data/test/tc_float.rb +192 -0
- data/test/tc_int.rb +52 -24
- data/test/tc_lazy.rb +109 -0
- data/test/tc_multiarray.rb +136 -2
- data/test/tc_object.rb +29 -11
- data/test/tc_rgb.rb +217 -0
- data/test/tc_sequence.rb +184 -52
- data/test/ts_multiarray.rb +3 -0
- metadata +42 -15
@@ -0,0 +1,185 @@
|
|
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 for applying a unary method to scalars and arrays
|
21
|
+
class UnaryMethod_ < Node
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
# Name of module
|
26
|
+
#
|
27
|
+
# @return [Module] The module with the method.
|
28
|
+
attr_accessor :mod
|
29
|
+
|
30
|
+
# Name of operation
|
31
|
+
#
|
32
|
+
# @return [Symbol,String] The name of this operation.
|
33
|
+
attr_accessor :operation
|
34
|
+
|
35
|
+
# Name of method for type conversion
|
36
|
+
#
|
37
|
+
# @return [Symbol,String] The name of the method for type conversion.
|
38
|
+
attr_accessor :conversion
|
39
|
+
|
40
|
+
# Get string with information about this class
|
41
|
+
#
|
42
|
+
# @return [String] Return string with information about this class.
|
43
|
+
def inspect
|
44
|
+
"#{mod.to_s}.#{operation.to_s}"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get unique descriptor of this class
|
48
|
+
#
|
49
|
+
# @param [Hash] hash Labels for any variables.
|
50
|
+
#
|
51
|
+
# @return [String] Descriptor of this class.
|
52
|
+
#
|
53
|
+
# @private
|
54
|
+
def descriptor( hash )
|
55
|
+
inspect
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
# Initialise unary operation
|
61
|
+
#
|
62
|
+
# @param [Node] value Value to apply operation to.
|
63
|
+
def initialize( value )
|
64
|
+
@value = value
|
65
|
+
end
|
66
|
+
|
67
|
+
# Get unique descriptor of this object
|
68
|
+
#
|
69
|
+
# @param [Hash] hash Labels for any variables.
|
70
|
+
#
|
71
|
+
# @return [String] Descriptor of this object,
|
72
|
+
#
|
73
|
+
# @private
|
74
|
+
def descriptor( hash )
|
75
|
+
"#{self.class.descriptor( hash )}(#{@value.descriptor( hash )})"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Array type of this term
|
79
|
+
#
|
80
|
+
# @return [Class] Resulting array type.
|
81
|
+
#
|
82
|
+
# @private
|
83
|
+
def array_type
|
84
|
+
@value.array_type.send self.class.conversion
|
85
|
+
end
|
86
|
+
|
87
|
+
# Substitute variables
|
88
|
+
#
|
89
|
+
# Substitute the variables with the values given in the hash.
|
90
|
+
#
|
91
|
+
# @param [Hash] hash Substitutions to apply.
|
92
|
+
#
|
93
|
+
# @return [Node] Term with substitutions applied.
|
94
|
+
#
|
95
|
+
# @private
|
96
|
+
def subst( hash )
|
97
|
+
self.class.new @value.subst( hash )
|
98
|
+
end
|
99
|
+
|
100
|
+
# Get variables contained in this term
|
101
|
+
#
|
102
|
+
# @return [Set] Returns set of variables.
|
103
|
+
#
|
104
|
+
# @private
|
105
|
+
def variables
|
106
|
+
@value.variables
|
107
|
+
end
|
108
|
+
|
109
|
+
# Strip of all values
|
110
|
+
#
|
111
|
+
# Split up into variables, values, and a term where all values have been
|
112
|
+
# replaced with variables.
|
113
|
+
#
|
114
|
+
# @return [Array<Array,Node>] Returns an array of variables, an array of
|
115
|
+
# values, and the term based on variables.
|
116
|
+
#
|
117
|
+
# @private
|
118
|
+
def strip
|
119
|
+
vars, values, term = @value.strip
|
120
|
+
return vars, values, self.class.new( term )
|
121
|
+
end
|
122
|
+
|
123
|
+
# Reevaluate computation
|
124
|
+
#
|
125
|
+
# @return [Node,Object] Result of computation
|
126
|
+
#
|
127
|
+
# @see #force
|
128
|
+
#
|
129
|
+
# @private
|
130
|
+
def demand
|
131
|
+
self.class.mod.send self.class.operation, @value
|
132
|
+
end
|
133
|
+
|
134
|
+
def skip( index, start )
|
135
|
+
self.class.new( @value.skip( index, start ) ).demand
|
136
|
+
end
|
137
|
+
|
138
|
+
# Get element of unary operation
|
139
|
+
#
|
140
|
+
# @param [Integer,Node] i Index of desired element.
|
141
|
+
#
|
142
|
+
# @return [Node,Object] Element of unary operation.
|
143
|
+
def element( i )
|
144
|
+
self.class.new( @value.element( i ) ).demand
|
145
|
+
end
|
146
|
+
|
147
|
+
def slice( start, length )
|
148
|
+
self.class.new( @value.slice( start, length ) ).demand
|
149
|
+
end
|
150
|
+
|
151
|
+
# Check whether this term is compilable
|
152
|
+
#
|
153
|
+
# @return [FalseClass,TrueClass] Returns whether this term is compilable.
|
154
|
+
#
|
155
|
+
# @private
|
156
|
+
def compilable?
|
157
|
+
@value.compilable?
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
# Create a class deriving from +UnaryMethod_+
|
163
|
+
#
|
164
|
+
# @param [Symbol,String] operation Name of operation.
|
165
|
+
# @param [Symbol,String] conversion Name of method for type conversion.
|
166
|
+
#
|
167
|
+
# @return [Class] A class deriving from +UnaryMethod_+.
|
168
|
+
#
|
169
|
+
# @see UnaryMethod_
|
170
|
+
# @see UnaryMethod_.operation
|
171
|
+
# @see UnaryMethod_.conversion
|
172
|
+
#
|
173
|
+
# @private
|
174
|
+
def UnaryMethod( mod, operation, conversion = :contiguous )
|
175
|
+
retval = Class.new UnaryMethod_
|
176
|
+
retval.mod = mod
|
177
|
+
retval.operation = operation
|
178
|
+
retval.conversion = conversion
|
179
|
+
retval
|
180
|
+
end
|
181
|
+
|
182
|
+
module_function :UnaryMethod
|
183
|
+
|
184
|
+
end
|
185
|
+
|
@@ -18,7 +18,7 @@
|
|
18
18
|
module Hornetseye
|
19
19
|
|
20
20
|
# Class for representing unary operations on scalars and arrays
|
21
|
-
class
|
21
|
+
class UnaryOp_ < Node
|
22
22
|
|
23
23
|
class << self
|
24
24
|
|
@@ -47,7 +47,7 @@ module Hornetseye
|
|
47
47
|
#
|
48
48
|
# @private
|
49
49
|
def descriptor( hash )
|
50
|
-
|
50
|
+
inspect
|
51
51
|
end
|
52
52
|
|
53
53
|
end
|
@@ -126,13 +126,21 @@ module Hornetseye
|
|
126
126
|
@value.send self.class.operation
|
127
127
|
end
|
128
128
|
|
129
|
+
def skip( index, start )
|
130
|
+
self.class.new( @value.skip( index, start ) ).demand
|
131
|
+
end
|
132
|
+
|
129
133
|
# Get element of unary operation
|
130
134
|
#
|
131
135
|
# @param [Integer,Node] i Index of desired element.
|
132
136
|
#
|
133
137
|
# @return [Node,Object] Element of unary operation.
|
134
138
|
def element( i )
|
135
|
-
@value.element( i )
|
139
|
+
self.class.new( @value.element( i ) ).demand
|
140
|
+
end
|
141
|
+
|
142
|
+
def slice( start, length )
|
143
|
+
self.class.new( @value.slice( start, length ) ).demand
|
136
144
|
end
|
137
145
|
|
138
146
|
# Check whether this term is compilable
|
@@ -146,25 +154,26 @@ module Hornetseye
|
|
146
154
|
|
147
155
|
end
|
148
156
|
|
149
|
-
# Create a class deriving from +
|
157
|
+
# Create a class deriving from +UnaryOp_+
|
150
158
|
#
|
151
159
|
# @param [Symbol,String] operation Name of operation.
|
152
160
|
# @param [Symbol,String] conversion Name of method for type conversion.
|
153
161
|
#
|
154
|
-
# @return [Class] A class deriving from +
|
162
|
+
# @return [Class] A class deriving from +UnaryOp_+.
|
155
163
|
#
|
156
|
-
# @see
|
157
|
-
# @see
|
158
|
-
# @see
|
164
|
+
# @see UnaryOp_
|
165
|
+
# @see UnaryOp_.operation
|
166
|
+
# @see UnaryOp_.conversion
|
159
167
|
#
|
160
168
|
# @private
|
161
|
-
def
|
162
|
-
retval = Class.new
|
169
|
+
def UnaryOp( operation, conversion = :contiguous )
|
170
|
+
retval = Class.new UnaryOp_
|
163
171
|
retval.operation = operation
|
164
172
|
retval.conversion = conversion
|
165
173
|
retval
|
166
174
|
end
|
167
175
|
|
168
|
-
module_function :
|
176
|
+
module_function :UnaryOp
|
169
177
|
|
170
178
|
end
|
179
|
+
|
data/lib/multiarray/variable.rb
CHANGED
data/test/tc_bool.rb
CHANGED
@@ -25,6 +25,10 @@ class TC_Bool < Test::Unit::TestCase
|
|
25
25
|
|
26
26
|
B = Hornetseye::BOOL
|
27
27
|
|
28
|
+
def B( *args )
|
29
|
+
Hornetseye::BOOL *args
|
30
|
+
end
|
31
|
+
|
28
32
|
def setup
|
29
33
|
end
|
30
34
|
|
@@ -55,12 +59,16 @@ class TC_Bool < Test::Unit::TestCase
|
|
55
59
|
assert_equal [], B.shape
|
56
60
|
end
|
57
61
|
|
62
|
+
def test_bool_size
|
63
|
+
assert_equal 1, B.size
|
64
|
+
end
|
65
|
+
|
58
66
|
def test_inspect
|
59
|
-
assert_equal 'BOOL(true)', B
|
67
|
+
assert_equal 'BOOL(true)', B( true ).inspect
|
60
68
|
end
|
61
69
|
|
62
70
|
def test_marshal
|
63
|
-
assert_equal B
|
71
|
+
assert_equal B( true ), Marshal.load( Marshal.dump( B( true ) ) )
|
64
72
|
end
|
65
73
|
|
66
74
|
def test_typecode
|
@@ -75,43 +83,47 @@ class TC_Bool < Test::Unit::TestCase
|
|
75
83
|
assert_equal [], B.new.shape
|
76
84
|
end
|
77
85
|
|
86
|
+
def test_size
|
87
|
+
assert_equal 1, B.new.size
|
88
|
+
end
|
89
|
+
|
78
90
|
def test_at_assign
|
79
|
-
b = B
|
91
|
+
b = B false
|
80
92
|
assert !b[]
|
81
93
|
assert b[] = true
|
82
94
|
assert b[]
|
83
95
|
end
|
84
96
|
|
85
97
|
def test_equal
|
86
|
-
assert_equal B
|
87
|
-
assert_not_equal B
|
88
|
-
assert_not_equal B
|
89
|
-
assert_equal B
|
98
|
+
assert_equal B( false ), B( false )
|
99
|
+
assert_not_equal B( false ), B( true )
|
100
|
+
assert_not_equal B( true ), B( false )
|
101
|
+
assert_equal B( true ), B( true )
|
90
102
|
end
|
91
103
|
|
92
104
|
def test_inject
|
93
|
-
assert B
|
94
|
-
assert !B
|
95
|
-
assert !B
|
105
|
+
assert B( true ).inject { |a,b| a.and b }[]
|
106
|
+
assert !B( false ).inject( true ) { |a,b| a.and b }[]
|
107
|
+
assert !B( true ).inject( false ) { |a,b| a.and b }[]
|
96
108
|
end
|
97
109
|
|
98
110
|
def test_not
|
99
|
-
assert_equal B
|
100
|
-
assert_equal B
|
111
|
+
assert_equal B( true ), B( false ).not
|
112
|
+
assert_equal B( false ), B( true ).not
|
101
113
|
end
|
102
114
|
|
103
115
|
def test_and
|
104
|
-
assert_equal B
|
105
|
-
assert_equal B
|
106
|
-
assert_equal B
|
107
|
-
assert_equal B
|
116
|
+
assert_equal B( false ), B( false ).and( B( false ) )
|
117
|
+
assert_equal B( false ), B( false ).and( B( true ) )
|
118
|
+
assert_equal B( false ), B( true ).and( B( false ) )
|
119
|
+
assert_equal B( true ), B( true ).and( B( true ) )
|
108
120
|
end
|
109
121
|
|
110
122
|
def test_or
|
111
|
-
assert_equal B
|
112
|
-
assert_equal B
|
113
|
-
assert_equal B
|
114
|
-
assert_equal B
|
123
|
+
assert_equal B( false ), B( false ).or( B( false ) )
|
124
|
+
assert_equal B( true ), B( false ).or( B( true ) )
|
125
|
+
assert_equal B( true ), B( true ).or( B( false ) )
|
126
|
+
assert_equal B( true ), B( true ).or( B( true ) )
|
115
127
|
end
|
116
128
|
|
117
129
|
end
|
data/test/tc_float.rb
ADDED
@@ -0,0 +1,192 @@
|
|
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
|
+
require 'test/unit'
|
18
|
+
begin
|
19
|
+
require 'rubygems'
|
20
|
+
rescue LoadError
|
21
|
+
end
|
22
|
+
Kernel::require 'multiarray'
|
23
|
+
|
24
|
+
class TC_Float < Test::Unit::TestCase
|
25
|
+
|
26
|
+
F = Hornetseye::SFLOAT
|
27
|
+
D = Hornetseye::DFLOAT
|
28
|
+
|
29
|
+
def F( *args )
|
30
|
+
Hornetseye::SFLOAT *args
|
31
|
+
end
|
32
|
+
|
33
|
+
def D( *args )
|
34
|
+
Hornetseye::DFLOAT *args
|
35
|
+
end
|
36
|
+
|
37
|
+
def sum( *args, &action )
|
38
|
+
Hornetseye::sum *args, &action
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
end
|
43
|
+
|
44
|
+
def teardown
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_float_inspect
|
48
|
+
assert_equal 'SFLOAT', F.inspect
|
49
|
+
assert_equal 'DFLOAT', D.inspect
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_float_to_s
|
53
|
+
assert_equal 'SFLOAT', F.to_s
|
54
|
+
assert_equal 'DFLOAT', D.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_float_default
|
58
|
+
assert_equal 0.0, F.new[]
|
59
|
+
assert_equal 0.0, D.new[]
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_float_indgen
|
63
|
+
assert_equal 0, F.indgen
|
64
|
+
assert_equal 1, F.indgen( 1 )
|
65
|
+
assert_equal 1, F.indgen( 1, 2 )
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_float_typecode
|
69
|
+
assert_equal F, F.typecode
|
70
|
+
assert_equal D, D.typecode
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_float_dimension
|
74
|
+
assert_equal 0, F.dimension
|
75
|
+
end
|
76
|
+
!
|
77
|
+
def test_float_shape
|
78
|
+
assert_equal [], F.shape
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_float_size
|
82
|
+
assert_equal 1, F.size
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_inspect
|
86
|
+
assert_equal 'DFLOAT(42.0)', D( 42.0 ).inspect
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_marshal
|
90
|
+
assert_equal D( 42.0 ), Marshal.load( Marshal.dump( D( 42.0 ) ) )
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_typecode
|
94
|
+
assert_equal D, D.new.typecode
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_dimension
|
98
|
+
assert_equal 0.0, D.new.dimension
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_shape
|
102
|
+
assert_equal [], D.new.shape
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_size
|
106
|
+
assert_equal 1, D.new.size
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_at_assign
|
110
|
+
d = D 42.0
|
111
|
+
assert_equal 42.0, d[]
|
112
|
+
assert_equal 3.0, d[] = 3
|
113
|
+
assert_equal 3.0, d[]
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_equal
|
117
|
+
assert_not_equal D( 3.0 ), D( 4.0 )
|
118
|
+
assert_equal D( 3.0 ), D( 3.0 )
|
119
|
+
end
|
120
|
+
|
121
|
+
if false
|
122
|
+
|
123
|
+
def test_inject
|
124
|
+
assert_equal 2, I( 2 ).inject { |a,b| a + b }[]
|
125
|
+
assert_equal 3, I( 2 ).inject( 1 ) { |a,b| a + b }[]
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_not
|
129
|
+
assert !I( 0 ).not[]
|
130
|
+
assert !I( 3 ).not[]
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_sum
|
134
|
+
assert_equal 3, sum { || 3 }
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_zero
|
138
|
+
assert I( 0 ).zero?[]
|
139
|
+
assert !I( 3 ).zero?[]
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_nonzero
|
143
|
+
assert !I( 0 ).nonzero?[]
|
144
|
+
assert I( 3 ).nonzero?[]
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_bitwise_not
|
148
|
+
assert_equal I( -3 ), ~I( 2 )
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_bitwise_and
|
152
|
+
assert_equal I( 2 ), I( 3 ) & I( 6 )
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_bitwise_or
|
156
|
+
assert_equal I( 7 ), I( 3 ) | I( 6 )
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_bitwise_xor
|
160
|
+
assert_equal I( 1 ), I( 3 ) ^ I( 2 )
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_shl
|
164
|
+
assert_equal I( 4 ), I( 2 ) << I( 1 )
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_shr
|
168
|
+
assert_equal I( 2 ), I( 4 ) >> I( 1 )
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_negate
|
172
|
+
assert_equal I( -5 ), -I( 5 )
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_plus
|
176
|
+
assert_equal I( 3 + 5 ), I( 3 ) + I( 5 )
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_major
|
180
|
+
assert_equal I( 4 ), I( 3 ).major( I( 4 ) )
|
181
|
+
assert_equal I( 5 ), I( 5 ).major( I( 3 ) )
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_minor
|
185
|
+
assert_equal I( 3 ), I( 3 ).minor( I( 4 ) )
|
186
|
+
assert_equal I( 4 ), I( 5 ).minor( I( 4 ) )
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|