multiarray 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,170 @@
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 representing unary operations on scalars and arrays
21
+ class Unary_ < Node
22
+
23
+ class << self
24
+
25
+ # Name of operation
26
+ #
27
+ # @return [Symbol,String] The name of this operation.
28
+ attr_accessor :operation
29
+
30
+ # Name of method for type conversion
31
+ #
32
+ # @return [Symbol,String] The name of the method for type conversion.
33
+ attr_accessor :conversion
34
+
35
+ # Get string with information about this class
36
+ #
37
+ # @return [String] Return string with information about this class.
38
+ def inspect
39
+ operation.to_s
40
+ end
41
+
42
+ # Get unique descriptor of this class
43
+ #
44
+ # @param [Hash] hash Labels for any variables.
45
+ #
46
+ # @return [String] Descriptor of this class.
47
+ #
48
+ # @private
49
+ def descriptor( hash )
50
+ operation.to_s
51
+ end
52
+
53
+ end
54
+
55
+ # Initialise unary operation
56
+ #
57
+ # @param [Node] value Value to apply operation to.
58
+ def initialize( value )
59
+ @value = value
60
+ end
61
+
62
+ # Get unique descriptor of this object
63
+ #
64
+ # @param [Hash] hash Labels for any variables.
65
+ #
66
+ # @return [String] Descriptor of this object,
67
+ #
68
+ # @private
69
+ def descriptor( hash )
70
+ "(#{@value.descriptor( hash )}).#{self.class.descriptor( hash )}"
71
+ end
72
+
73
+ # Array type of this term
74
+ #
75
+ # @return [Class] Resulting array type.
76
+ #
77
+ # @private
78
+ def array_type
79
+ @value.array_type.send self.class.conversion
80
+ end
81
+
82
+ # Substitute variables
83
+ #
84
+ # Substitute the variables with the values given in the hash.
85
+ #
86
+ # @param [Hash] hash Substitutions to apply.
87
+ #
88
+ # @return [Node] Term with substitutions applied.
89
+ #
90
+ # @private
91
+ def subst( hash )
92
+ self.class.new @value.subst( hash )
93
+ end
94
+
95
+ # Get variables contained in this term
96
+ #
97
+ # @return [Set] Returns set of variables.
98
+ #
99
+ # @private
100
+ def variables
101
+ @value.variables
102
+ end
103
+
104
+ # Strip of all values
105
+ #
106
+ # Split up into variables, values, and a term where all values have been
107
+ # replaced with variables.
108
+ #
109
+ # @return [Array<Array,Node>] Returns an array of variables, an array of
110
+ # values, and the term based on variables.
111
+ #
112
+ # @private
113
+ def strip
114
+ vars, values, term = @value.strip
115
+ return vars, values, self.class.new( term )
116
+ end
117
+
118
+ # Reevaluate computation
119
+ #
120
+ # @return [Node,Object] Result of computation
121
+ #
122
+ # @see #force
123
+ #
124
+ # @private
125
+ def demand
126
+ @value.send self.class.operation
127
+ end
128
+
129
+ # Get element of unary operation
130
+ #
131
+ # @param [Integer,Node] i Index of desired element.
132
+ #
133
+ # @return [Node,Object] Element of unary operation.
134
+ def element( i )
135
+ @value.element( i ).send self.class.operation
136
+ end
137
+
138
+ # Check whether this term is compilable
139
+ #
140
+ # @return [FalseClass,TrueClass] Returns whether this term is compilable.
141
+ #
142
+ # @private
143
+ def compilable?
144
+ @value.compilable?
145
+ end
146
+
147
+ end
148
+
149
+ # Create a class deriving from +Unary_+
150
+ #
151
+ # @param [Symbol,String] operation Name of operation.
152
+ # @param [Symbol,String] conversion Name of method for type conversion.
153
+ #
154
+ # @return [Class] A class deriving from +Unary_+.
155
+ #
156
+ # @see Unary_
157
+ # @see Unary_.operation
158
+ # @see Unary_.conversion
159
+ #
160
+ # @private
161
+ def Unary( operation, conversion = :contiguous )
162
+ retval = Class.new Unary_
163
+ retval.operation = operation
164
+ retval.conversion = conversion
165
+ retval
166
+ end
167
+
168
+ module_function :Unary
169
+
170
+ end
@@ -0,0 +1,120 @@
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 Variable < Node
21
+
22
+ # Type information about this variable
23
+ #
24
+ # @return [Class] Returns type information about this variable.
25
+ attr_reader :meta
26
+
27
+ def initialize( meta )
28
+ @meta = meta
29
+ end
30
+
31
+ def inspect
32
+ "Variable(#{@meta.inspect})"
33
+ end
34
+
35
+ # Get unique descriptor of this object
36
+ #
37
+ # @param [Hash] hash Labels for any variables.
38
+ #
39
+ # @return [String] Descriptor of this object,
40
+ #
41
+ # @private
42
+ def descriptor( hash )
43
+ if hash[ self ]
44
+ "Variable#{hash[ self ]}(#{@meta.descriptor( hash )})"
45
+ else
46
+ "Variable(#{@meta.descriptor( hash )})"
47
+ end
48
+ end
49
+
50
+ def size
51
+ @meta.size
52
+ end
53
+
54
+ def size=( value )
55
+ @meta.size = value
56
+ end
57
+
58
+ def array_type
59
+ @meta.array_type
60
+ end
61
+
62
+ # Strip of all values
63
+ #
64
+ # Split up into variables, values, and a term where all values have been
65
+ # replaced with variables.
66
+ #
67
+ # @return [Array<Array,Node>] Returns an array of variables, an array of
68
+ # values, and the term based on variables.
69
+ #
70
+ # @private
71
+ def strip
72
+ meta_vars, meta_values, meta_term = @meta.strip
73
+ if meta_vars.empty?
74
+ return [], [], self
75
+ else
76
+ return meta_vars, meta_values, Variable.new( meta_term )
77
+ end
78
+ end
79
+
80
+ # Substitute variables
81
+ #
82
+ # Substitute the variables with the values given in the hash.
83
+ #
84
+ # @param [Hash] hash Substitutions to apply.
85
+ #
86
+ # @return [Node] Term with substitutions applied.
87
+ #
88
+ # @private
89
+ def subst( hash )
90
+ if hash[ self ]
91
+ hash[ self ]
92
+ elsif not @meta.variables.empty? and hash[ @meta.variables.to_a.first ]
93
+ Variable.new @meta.subst( hash )
94
+ else
95
+ self
96
+ end
97
+ end
98
+
99
+ # Get variables contained in this object
100
+ #
101
+ # @return [Set] Returns +Set[ self ]+.
102
+ #
103
+ # @private
104
+ def variables
105
+ Set[ self ]
106
+ end
107
+
108
+ # Lookup element of an array
109
+ #
110
+ # @param [Node] value Index of element.
111
+ # @param [Node] stride Stride for iterating over elements.
112
+ #
113
+ # @private
114
+ def lookup( value, stride )
115
+ Lookup.new self, value, stride
116
+ end
117
+
118
+ end
119
+
120
+ end
data/test/tc_bool.rb ADDED
@@ -0,0 +1,117 @@
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_Bool < Test::Unit::TestCase
25
+
26
+ B = Hornetseye::BOOL
27
+
28
+ def setup
29
+ end
30
+
31
+ def teardown
32
+ end
33
+
34
+ def test_bool_inspect
35
+ assert_equal 'BOOL', B.inspect
36
+ end
37
+
38
+ def test_bool_to_s
39
+ assert_equal 'BOOL', B.to_s
40
+ end
41
+
42
+ def test_bool_default
43
+ assert_equal false, B.new[]
44
+ end
45
+
46
+ def test_bool_typecode
47
+ assert_equal B, B.typecode
48
+ end
49
+
50
+ def test_bool_dimension
51
+ assert_equal 0, B.dimension
52
+ end
53
+
54
+ def test_bool_shape
55
+ assert_equal [], B.shape
56
+ end
57
+
58
+ def test_inspect
59
+ assert_equal 'BOOL(true)', B.new( true ).inspect
60
+ end
61
+
62
+ def test_marshal
63
+ assert_equal B.new( true ), Marshal.load( Marshal.dump( B.new( true ) ) )
64
+ end
65
+
66
+ def test_typecode
67
+ assert_equal B, B.new.typecode
68
+ end
69
+
70
+ def test_dimension
71
+ assert_equal 0, B.new.dimension
72
+ end
73
+
74
+ def test_shape
75
+ assert_equal [], B.new.shape
76
+ end
77
+
78
+ def test_at_assign
79
+ b = B.new false
80
+ assert !b[]
81
+ assert b[] = true
82
+ assert b[]
83
+ end
84
+
85
+ def test_equal
86
+ assert_equal B.new( false ), B.new( false )
87
+ assert_not_equal B.new( false ), B.new( true )
88
+ assert_not_equal B.new( true ), B.new( false )
89
+ assert_equal B.new( true ), B.new( true )
90
+ end
91
+
92
+ def test_inject
93
+ assert B.new( true ).inject { |a,b| a.and b }[]
94
+ assert !B.new( false ).inject( true ) { |a,b| a.and b }[]
95
+ assert !B.new( true ).inject( false ) { |a,b| a.and b }[]
96
+ end
97
+
98
+ def test_not
99
+ assert_equal B.new( true ), B.new( false ).not
100
+ assert_equal B.new( false ), B.new( true ).not
101
+ end
102
+
103
+ def test_and
104
+ assert_equal B.new( false ), B.new( false ).and( B.new( false ) )
105
+ assert_equal B.new( false ), B.new( false ).and( B.new( true ) )
106
+ assert_equal B.new( false ), B.new( true ).and( B.new( false ) )
107
+ assert_equal B.new( true ), B.new( true ).and( B.new( true ) )
108
+ end
109
+
110
+ def test_or
111
+ assert_equal B.new( false ), B.new( false ).or( B.new( false ) )
112
+ assert_equal B.new( true ), B.new( false ).or( B.new( true ) )
113
+ assert_equal B.new( true ), B.new( true ).or( B.new( false ) )
114
+ assert_equal B.new( true ), B.new( true ).or( B.new( true ) )
115
+ end
116
+
117
+ end
data/test/tc_int.rb CHANGED
@@ -1,3 +1,19 @@
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
+
1
17
  require 'test/unit'
2
18
  begin
3
19
  require 'rubygems'
@@ -7,33 +23,24 @@ Kernel::require 'multiarray'
7
23
 
8
24
  class TC_Int < Test::Unit::TestCase
9
25
 
10
- U8 = Hornetseye::UBYTE
11
- S8 = Hornetseye::BYTE
26
+ I = Hornetseye::INT
27
+ U8 = Hornetseye::UBYTE
28
+ S8 = Hornetseye::BYTE
12
29
  U16 = Hornetseye::USINT
13
30
  S16 = Hornetseye::SINT
14
31
  U32 = Hornetseye::UINT
15
32
  S32 = Hornetseye::INT
16
- U64 = Hornetseye::ULONG
17
- S64 = Hornetseye::LONG
18
33
 
19
- T = [ U8, S8, U16, S16, U32, S32 ]
20
- INSPECT = {
21
- U8 => 'UBYTE', S8 => 'BYTE',
22
- U16 => 'USINT', S16 => 'SINT',
23
- U32 => 'UINT', S32 => 'INT'
24
- }
25
- SIGNED = {
26
- U8 => false, S8 => true,
27
- U16 => false, S16 => true,
28
- U32 => false, S32 => true
29
- }
34
+ def UI( bits )
35
+ Hornetseye::INT Hornetseye::UNSIGNED, bits
36
+ end
30
37
 
31
- def lazy( &action )
32
- Hornetseye::lazy &action
38
+ def SI( bits )
39
+ Hornetseye::INT Hornetseye::SIGNED, bits
33
40
  end
34
41
 
35
- def eager( &action )
36
- Hornetseye::eager &action
42
+ def sum( *args, &action )
43
+ Hornetseye::sum *args, &action
37
44
  end
38
45
 
39
46
  def setup
@@ -42,97 +49,127 @@ class TC_Int < Test::Unit::TestCase
42
49
  def teardown
43
50
  end
44
51
 
52
+ def test_int_inspect
53
+ assert_equal 'UBYTE', U8.inspect
54
+ assert_equal 'BYTE', S8.inspect
55
+ assert_equal 'USINT', U16.inspect
56
+ assert_equal 'SINT', S16.inspect
57
+ assert_equal 'UINT', U32.inspect
58
+ assert_equal 'INT', S32.inspect
59
+ end
60
+
61
+ def test_int_to_s
62
+ assert_equal 'UBYTE', U8.to_s
63
+ assert_equal 'BYTE', S8.to_s
64
+ assert_equal 'USINT', U16.to_s
65
+ assert_equal 'SINT', S16.to_s
66
+ assert_equal 'UINT', U32.to_s
67
+ assert_equal 'INT', S32.to_s
68
+ end
69
+
45
70
  def test_int_default
46
- T.each { |t| assert_equal 0, t.new[] }
71
+ assert_equal 0, I.new[]
47
72
  end
48
73
 
74
+ def test_int_typecode
75
+ assert_equal I, I.typecode
76
+ end
49
77
 
50
- def test_int_inspect
51
- T.each { |t| assert_equal INSPECT[ t ], t.inspect }
78
+ def test_int_dimension
79
+ assert_equal 0, I.dimension
52
80
  end
53
81
 
54
- def test_int_to_s
55
- T.each { |t| assert_equal INSPECT[ t ], t.to_s }
82
+ def test_int_shape
83
+ assert_equal [], I.shape
56
84
  end
57
85
 
58
86
  def test_inspect
59
- T.each { |t| assert_equal "#{t}(42)", t.new( 42 ).inspect }
87
+ assert_equal 'INT(42)', I.new( 42 ).inspect
60
88
  end
61
89
 
62
- def test_to_s
63
- T.each { |t| assert_equal '42', t.new( 42 ).to_s }
90
+ def test_marshal
91
+ assert_equal I.new( 42 ), Marshal.load( Marshal.dump( I.new( 42 ) ) )
64
92
  end
65
93
 
66
- def test_marshal
67
- T.each do |t|
68
- assert_equal t.new( 42 ),
69
- Marshal.load( Marshal.dump( t.new( 42 ) ) )
70
- end
94
+ def test_typecode
95
+ assert_equal I, I.new.typecode
96
+ end
97
+
98
+ def test_dimension
99
+ assert_equal 0, I.new.dimension
100
+ end
101
+
102
+ def test_shape
103
+ assert_equal [], I.new.shape
71
104
  end
72
105
 
73
106
  def test_at_assign
74
- T.each do |t|
75
- i = t.new 3
76
- assert_equal 3, i[]
77
- assert_equal 42, i[] = 42
78
- assert_equal 42, i[]
79
- end
107
+ i = I.new 42
108
+ assert_equal 42, i[]
109
+ assert_equal 3, i[] = 3
110
+ assert_equal 3, i[]
80
111
  end
81
112
 
82
113
  def test_equal
83
- T.each do |t1|
84
- T.each do |t2|
85
- assert_not_equal t1.new( 3 ), t2.new( 4 )
86
- assert_equal t1 == t2, t1.new( 3 ) == t2.new( 3 )
87
- end
88
- end
114
+ assert_not_equal I.new( 3 ), I.new( 4 )
115
+ assert_equal I.new( 3 ), I.new( 3 )
116
+ end
117
+
118
+ def test_inject
119
+ assert_equal 2, I.new( 2 ).inject { |a,b| a + b }[]
120
+ assert_equal 3, I.new( 2 ).inject( 1 ) { |a,b| a + b }[]
121
+ end
122
+
123
+ def test_not
124
+ assert !I.new( 0 ).not[]
125
+ assert !I.new( 3 ).not[]
126
+ end
127
+
128
+ def test_sum
129
+ assert_equal 3, sum { || 3 }
130
+ end
131
+
132
+ def test_zero
133
+ assert I.new( 0 ).zero?[]
134
+ assert !I.new( 3 ).zero?[]
135
+ end
136
+
137
+ def test_nonzero
138
+ assert !I.new( 0 ).nonzero?[]
139
+ assert I.new( 3 ).nonzero?[]
140
+ end
141
+
142
+ def test_bitwise_not
143
+ assert_equal I.new( -3 ), ~I.new( 2 )
144
+ end
145
+
146
+ def test_bitwise_and
147
+ assert_equal I.new( 2 ), I.new( 3 ) & I.new( 6 )
148
+ end
149
+
150
+ def test_bitwise_or
151
+ assert_equal I.new( 7 ), I.new( 3 ) | I.new( 6 )
152
+ end
153
+
154
+ def test_bitwise_xor
155
+ assert_equal I.new( 1 ), I.new( 3 ) ^ I.new( 2 )
156
+ end
157
+
158
+ def test_shl
159
+ assert_equal I.new( 4 ), I.new( 2 ) << I.new( 1 )
160
+ end
161
+
162
+ def test_shr
163
+ assert_equal I.new( 2 ), I.new( 4 ) >> I.new( 1 )
89
164
  end
90
165
 
91
166
  def test_negate
92
- T.select { |t| SIGNED[ t ] }.each do |t|
93
- assert_equal t.new( -5 ), -t.new( 5 )
94
- end
167
+ assert_equal I.new( -5 ), -I.new( 5 )
95
168
  end
96
169
 
97
170
  def test_plus
98
- T.each do |t1|
99
- T.each do |t2|
100
- assert_equal 5, ( t1.new( 3 ) + t2.new( 2 ) )[]
101
- end
102
- end
103
- end
104
-
105
- def test_lazy_unary
106
- T.select { |t| SIGNED[ t ] }.each do |t|
107
- i = lazy { -t.new( 3 ) }
108
- assert_not_equal t.new( -3 ), i
109
- assert_equal "#{t}(<delayed>)", i.inspect
110
- assert_equal t.new( -3 ), i.force
111
- i = lazy { --t.new( 3 ) }
112
- assert_equal "#{t}(<delayed>)", i.inspect
113
- assert_equal t.new( 3 ), i.force
114
- i = -lazy { -t.new( 3 ) }
115
- assert_equal t.new( 3 ), i
116
- i = lazy { -lazy { -t.new( 3 ) } }
117
- assert_equal "#{t}(<delayed>)", i.inspect
118
- assert_equal t.new( 3 ), i.force
119
- i = eager { lazy { -t.new( 3 ) } }
120
- assert_equal "#{t}(<delayed>)", i.inspect
121
- i = lazy { eager { -lazy { -t.new( 3 ) } } }
122
- assert_equal t.new( 3 ), i
123
- end
124
- end
125
-
126
- def test_lazy_binary
127
- a = U16.new 3
128
- b = S8.new -5
129
- i = lazy { a + b }
130
- assert_not_equal a + b, i
131
- assert_equal 'SINT(<delayed>)', i.inspect
132
- assert_equal S16.new( -2 ), i.force
133
- assert_equal S32.new( -1 ), i + S32.new( 1 )
134
- assert_equal S32.new( -1 ), S32.new( 1 ) + i
171
+ assert_equal I.new( 3 + 5 ), I.new( 3 ) + I.new( 5 )
135
172
  end
136
173
 
137
-
138
174
  end
175
+