multiarray 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,46 @@
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
1
18
  module Hornetseye
2
19
 
3
20
  # Class for representing Ruby objects
4
- class OBJECT < Type
21
+ class OBJECT < Element
5
22
 
6
23
  class << self
7
24
 
8
- # Get memory type for storing objects of this type
25
+ # Get string with information about this class
26
+ #
27
+ # @return [String] Returns +'OBJECT'+.
28
+ def inspect
29
+ 'OBJECT'
30
+ end
31
+
32
+ # Get unique descriptor of this class
33
+ #
34
+ # @param [Hash] hash Labels for any variables.
35
+ #
36
+ # @return [String] Descriptor of this class.
37
+ #
38
+ # @private
39
+ def descriptor( hash )
40
+ 'OBJECT'
41
+ end
42
+
43
+ # Get memory type required to store elements of this type
9
44
  #
10
45
  # @return [Class] Returns +List+.
11
46
  #
@@ -16,21 +51,16 @@ module Hornetseye
16
51
  List
17
52
  end
18
53
 
19
- # Get string with information about this type
54
+ # Get storage size to store an element of this type
20
55
  #
21
- # @return [String] Returns +'OBJECT'+.
22
- def to_s
23
- 'OBJECT'
24
- end
25
-
26
- # Get string with information about this type
56
+ # @return [Integer] Returns +1+.
27
57
  #
28
- # @return [String] Returns +'OBJECT'+.
29
- def inspect
30
- to_s
58
+ # @private
59
+ def storage_size
60
+ 1
31
61
  end
32
62
 
33
- # Default value for Ruby objects
63
+ # Get default value for elements of this type
34
64
  #
35
65
  # @return [Object] Returns +nil+.
36
66
  #
@@ -39,45 +69,58 @@ module Hornetseye
39
69
  nil
40
70
  end
41
71
 
42
- # Size of storage required to store an element of this type
43
- #
44
- # @return [Integer] Size of storage required. Returns +1+.
45
- #
46
- # @private
47
- def storage_size
48
- 1
49
- end
50
-
51
72
  def coercion( other )
52
- if other < Pointer_
73
+ if other < Sequence_
53
74
  other.coercion self
54
75
  else
55
76
  self
56
77
  end
57
78
  end
58
79
 
80
+ # Coerce with other object
81
+ #
82
+ # @param [Node,Object] other Other object.
83
+ #
84
+ # @return [Array<Node>] Result of coercion.
59
85
  def coerce( other )
60
86
  return self, self
61
87
  end
62
88
 
63
- end
89
+ # Check whether this term is compilable
90
+ #
91
+ # @return [FalseClass,TrueClass] Returns +false+.
92
+ #
93
+ # @private
94
+ def compilable?
95
+ false
96
+ end
64
97
 
65
- def store( ptr )
66
- ptr.write @value
67
- self
68
98
  end
69
99
 
70
- raise '\'multiarray/object\' must be loaded first' if Type.respond_to? :fit
71
-
72
- module RubyMatching
100
+ # Namespace containing method for matching elements of type OBJECT
101
+ #
102
+ # @see OBJECT
103
+ #
104
+ # @private
105
+ module Match
73
106
 
107
+ # Method for matching elements of type OBJECT
108
+ #
109
+ # @param [Array<Object>] *values Values to find matching native element
110
+ # type for.
111
+ #
112
+ # @return [Class] Native type fitting all values.
113
+ #
114
+ # @see OBJECT
115
+ #
116
+ # @private
74
117
  def fit( *values )
75
118
  OBJECT
76
119
  end
77
120
 
78
121
  end
79
122
 
80
- Type.extend RubyMatching
123
+ Node.extend Match
81
124
 
82
125
  end
83
126
 
@@ -0,0 +1,78 @@
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 Operations
21
+
22
+ def define_unary_op( op, conversion = :contiguous )
23
+ define_method( op ) do
24
+ if dimension == 0 and variables.empty?
25
+ target = typecode.send conversion
26
+ target.new simplify.get.send( op )
27
+ else
28
+ Hornetseye::Unary( op, conversion ).new( self ).force
29
+ end
30
+ end
31
+ end
32
+
33
+ module_function :define_unary_op
34
+
35
+ def define_binary_op( op, coercion = :coercion )
36
+ define_method( op ) do |other|
37
+ other = Node.match( other, typecode ).new other unless other.is_a? Node
38
+ if dimension == 0 and variables.empty? and
39
+ other.dimension == 0 and other.variables.empty?
40
+ target = array_type.send coercion, other.array_type
41
+ target.new demand.get.send( op, other.simplify.get )
42
+ else
43
+ Hornetseye::Binary( op, coercion ).new( self, other ).force
44
+ end
45
+ end
46
+ end
47
+
48
+ module_function :define_binary_op
49
+
50
+ define_unary_op :zero? , :bool
51
+ define_unary_op :nonzero?, :bool
52
+ define_unary_op :not, :bool
53
+ define_unary_op :~
54
+ define_unary_op :-@
55
+ define_binary_op :+
56
+ define_binary_op :-
57
+ define_binary_op :*
58
+ define_binary_op :/
59
+ define_binary_op :%
60
+ define_binary_op :and, :bool_binary
61
+ define_binary_op :or, :bool_binary
62
+ define_binary_op :&
63
+ define_binary_op :|
64
+ define_binary_op :^
65
+ define_binary_op :<<
66
+ define_binary_op :>>
67
+ define_binary_op :eq, :bool_binary
68
+ define_binary_op :ne, :bool_binary
69
+
70
+ end
71
+
72
+ class Node
73
+
74
+ include Operations
75
+
76
+ end
77
+
78
+ end
@@ -1,9 +1,139 @@
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
  module Hornetseye
2
18
 
3
- def Pointer( primitive )
4
- retval = Class.new Pointer_
5
- retval.primitive = primitive
6
- retval
19
+ class Pointer_ < Node
20
+
21
+ class << self
22
+
23
+ # Target type of pointer
24
+ #
25
+ # @return [Node] Type of object the pointer is pointing at.
26
+ attr_accessor :target
27
+
28
+ def inspect
29
+ "*(#{target.inspect})"
30
+ end
31
+
32
+ # Get unique descriptor of this class
33
+ #
34
+ # @param [Hash] hash Labels for any variables.
35
+ #
36
+ # @return [String] Descriptor of this class.
37
+ #
38
+ # @private
39
+ def descriptor( hash )
40
+ "*(#{target.to_s})"
41
+ end
42
+
43
+ # Get default value for elements of this type
44
+ #
45
+ # @return [Memory,List] Memory for storing object of type +target+.
46
+ def default
47
+ target.memory.new target.storage_size
48
+ end
49
+
50
+ def ==( other )
51
+ other.is_a? Class and other < Pointer_ and
52
+ target == other.target
53
+ end
54
+
55
+ def hash
56
+ [ :Pointer_, target ].hash
57
+ end
58
+
59
+ def eql?
60
+ self == other
61
+ end
62
+
63
+ def typecode
64
+ target
65
+ end
66
+
67
+ def array_type
68
+ target
69
+ end
70
+
71
+ def pointer_type
72
+ self
73
+ end
74
+
75
+ end
76
+
77
+ def initialize( value = self.class.default )
78
+ @value = value
79
+ end
80
+
81
+ # Strip of all values
82
+ #
83
+ # Split up into variables, values, and a term where all values have been
84
+ # replaced with variables.
85
+ #
86
+ # @return [Array<Array,Node>] Returns an array of variables, an array of
87
+ # values, and the term based on variables.
88
+ #
89
+ # @private
90
+ def strip
91
+ variable = Variable.new self.class
92
+ return [ variable ], [ self ], variable
93
+ end
94
+
95
+ def descriptor( hash )
96
+ "#{self.class.to_s}(#{@value.to_s})"
97
+ end
98
+
99
+ def store( value )
100
+ result = value.simplify
101
+ self.class.target.new( result.get ).write @value
102
+ result
103
+ end
104
+
105
+ # Reevaluate computation
106
+ #
107
+ # @return [Node,Object] Result of computation
108
+ #
109
+ # @see #force
110
+ #
111
+ # @private
112
+ def demand
113
+ self.class.target.fetch( @value ).simplify
114
+ end
115
+
116
+ # Lookup element of an array
117
+ #
118
+ # @param [Node] value Index of element.
119
+ # @param [Node] stride Stride for iterating over elements.
120
+ #
121
+ # @private
122
+ def lookup( value, stride )
123
+ if value.is_a? Variable
124
+ Lookup.new self, value, stride
125
+ else
126
+ self.class.new @value + ( stride.get *
127
+ self.class.target.storage_size ) * value.get
128
+ end
129
+ end
130
+
131
+ end
132
+
133
+ def Pointer( target )
134
+ p = Class.new Pointer_
135
+ p.target = target
136
+ p
7
137
  end
8
138
 
9
139
  module_function :Pointer
@@ -1,32 +1,50 @@
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
1
18
  module Hornetseye
2
19
 
20
+ # Class for representing uniform arrays
3
21
  class Sequence
4
22
 
5
23
  class << self
6
24
 
7
- # Create a one-dimensional array
8
- #
9
- # Create an array with +num_elements+ elements of type +element_type+.
25
+ # Allocate new uniform array
10
26
  #
11
- # @param [Class] element_type Element type of the array. Should derive
12
- # from +Type+.
13
- # @param [Integer] num_elements Number of elements of the array.
14
- # @return [Sequence_] An array with the specified element type and the
15
- # specified number of elements.
27
+ # @param [Class] typecode Type of array elements.
28
+ # @param [Integer] size Number of elements.
16
29
  #
17
- # @see #Sequence
18
- # @see MultiArray.new
19
- def new( element_type, num_elements )
20
- Hornetseye::Sequence( element_type, num_elements ).new
30
+ # @return [Node] Returns uninitialised native array.
31
+ def new( typecode, size )
32
+ MultiArray.new typecode, size
21
33
  end
22
34
 
35
+ # Convert array to uniform array
36
+ #
37
+ # A native type which fits all elements is determined and used to create
38
+ # a uniform array of those elements.
39
+ #
40
+ # @param [Array<Object>] *args Elements of array.
41
+ #
42
+ # @return [Node] Returns native array with values.
23
43
  def []( *args )
24
- target = Type.fit args
25
- if target.primitive.dimension > 1
26
- target = Hornetseye::Sequence OBJECT, args.size
27
- end
44
+ target = Node.fit args
45
+ target = Hornetseye::Sequence OBJECT, args.size if target.dimension > 1
28
46
  retval = target.new
29
- retval[] = args
47
+ args.each_with_index { |arg,i| retval[ i ] = arg }
30
48
  retval
31
49
  end
32
50
 
@@ -34,27 +52,180 @@ module Hornetseye
34
52
 
35
53
  end
36
54
 
37
- # Create an array class
38
- #
39
- # The parameters +element_type+, +num_elements+, and +stride+ are assigned
40
- # to the corresponding attributes of the resulting class.
41
- #
42
- # @param [Class] element_type Element type of the array type. Should derive
43
- # from +Type+.
44
- # @param [Integer] num_elements Number of elements of the array type.
45
- # @param [Integer] stride Optional stride size for transposed or
46
- # non-contiguous array types.
47
- # @return [Class] An array class deriving from +Pointer_+.
48
- #
49
- # @see Sequence.new
50
- # @see #MultiArray
51
- def Sequence( element_type, num_elements,
52
- stride = element_type.dereference.size )
53
- sequence = Class.new Sequence_
54
- sequence.element_type = element_type.dereference
55
- sequence.num_elements = num_elements
56
- sequence.stride = stride
57
- Pointer sequence
55
+ # Class for representing n-dimensional native arrays
56
+ class Sequence_
57
+
58
+ class << self
59
+
60
+ # Type of array elements
61
+ #
62
+ # @return [Class] element_type Type of array elements.
63
+ attr_accessor :element_type
64
+
65
+ # Number of array elements
66
+ #
67
+ # @return [Integer] num_elements Number of elements.
68
+ attr_accessor :num_elements
69
+
70
+ def default
71
+ Hornetseye::lazy( num_elements ) do |i|
72
+ if element_type.dimension > 0
73
+ element = element_type.default
74
+ else
75
+ element = element_type.new
76
+ end
77
+ end
78
+ end
79
+
80
+ def indgen( offset = 0, increment = 1 )
81
+ Hornetseye::lazy( num_elements ) do |i|
82
+ if offset == 0
83
+ if increment == 1
84
+ i
85
+ else
86
+ increment * i
87
+ end
88
+ else
89
+ if increment == 1
90
+ offset + i
91
+ else
92
+ offset + increment * i
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def shape
99
+ element_type.shape + [ num_elements ]
100
+ end
101
+
102
+ def typecode
103
+ element_type.typecode
104
+ end
105
+
106
+ def array_type
107
+ self
108
+ end
109
+
110
+ def pointer_type
111
+ self
112
+ end
113
+
114
+ def dimension
115
+ element_type.dimension + 1
116
+ end
117
+
118
+ def contiguous
119
+ self
120
+ end
121
+
122
+ def bool
123
+ Hornetseye::Sequence element_type.bool, num_elements
124
+ end
125
+
126
+ def bool_binary( other )
127
+ coercion( other ).bool
128
+ end
129
+
130
+ def inspect
131
+ if dimension == 1
132
+ "Sequence(#{typecode.inspect},#{num_elements.inspect})"
133
+ else
134
+ "MultiArray(#{typecode.inspect},#{shape.join ','})"
135
+ end
136
+ end
137
+
138
+ def to_s
139
+ descriptor( {} )
140
+ end
141
+
142
+ # Get unique descriptor of this class
143
+ #
144
+ # @param [Hash] hash Labels for any variables.
145
+ #
146
+ # @return [String] Descriptor of this class.
147
+ #
148
+ # @private
149
+ def descriptor( hash )
150
+ if dimension == 1
151
+ "Sequence(#{typecode.descriptor( hash )},#{num_elements.to_s})"
152
+ else
153
+ "MultiArray(#{typecode.descriptor( hash )},#{shape.join ','})"
154
+ end
155
+ end
156
+
157
+ def ==( other )
158
+ other.is_a? Class and other < Sequence_ and
159
+ other.element_type == element_type and
160
+ other.num_elements == num_elements
161
+ end
162
+
163
+ def coercion( other )
164
+ if other < Sequence_
165
+ Hornetseye::Sequence element_type.coercion( other.element_type ),
166
+ num_elements
167
+ else
168
+ Hornetseye::Sequence element_type.coercion( other ),
169
+ num_elements
170
+ end
171
+ end
172
+
173
+ def coerce( other )
174
+ if other < Sequence_
175
+ return other, self
176
+ else
177
+ return Hornetseye::Sequence( other, num_elements ), self
178
+ end
179
+ end
180
+
181
+ def new
182
+ MultiArray.new typecode, *shape
183
+ end
184
+
185
+ end
186
+
187
+ # Namespace containing method for matching elements of type Sequence_
188
+ #
189
+ # @see Sequence_
190
+ #
191
+ # @private
192
+ module Match
193
+
194
+ # Method for matching elements of type Sequence_
195
+ #
196
+ # 'param [Array<Object>] *values Values to find matching native element
197
+ # type for.
198
+ #
199
+ # @return [Class] Native type fitting all values.
200
+ #
201
+ # @see Sequence_
202
+ #
203
+ # @private
204
+ def fit( *values )
205
+ n = values.inject 0 do |size,value|
206
+ value.is_a?( Array ) ? [ size, value.size ].max : size
207
+ end
208
+ if n > 0
209
+ elements = values.inject [] do |flat,value|
210
+ flat + ( value.is_a?( Array ) ? value : [ value ] )
211
+ end
212
+ Hornetseye::Sequence fit( *elements ), n
213
+ else
214
+ super *values
215
+ end
216
+ end
217
+
218
+ end
219
+
220
+ Node.extend Match
221
+
222
+ end
223
+
224
+ def Sequence( element_type, num_elements )
225
+ retval = Class.new Sequence_
226
+ retval.element_type = element_type
227
+ retval.num_elements = num_elements
228
+ retval
58
229
  end
59
230
 
60
231
  module_function :Sequence