multiarray 0.4.1 → 0.5.0

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.
@@ -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