multiarray 0.5.2 → 0.6.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.
@@ -17,26 +17,55 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # Base class for composite types
20
21
  class Composite < Element
21
22
 
22
23
  class << self
23
24
 
25
+ # Access element type of composite type
26
+ #
27
+ # @return [Class] The element type.
24
28
  attr_accessor :element_type
25
29
 
30
+ # Get number of elements of composite type
31
+ #
32
+ # @return [Integer] Number of elements.
26
33
  attr_accessor :num_elements
27
34
 
35
+ # Memory type required to store elements of this type
36
+ #
37
+ # @return [Class] Returns +element_type.memory+.
38
+ #
39
+ # @private
28
40
  def memory
29
41
  element_type.memory
30
42
  end
31
43
 
44
+ # Get storage size to store an element of this type
45
+ #
46
+ # @return [Integer] Returns +element_type.storage_size * num_elements+.
47
+ #
48
+ # @private
32
49
  def storage_size
33
50
  element_type.storage_size * num_elements
34
51
  end
35
52
 
53
+ # Directive for packing/unpacking elements of this type
54
+ #
55
+ # @return [String] Returns string with directive.
56
+ #
57
+ # @private
36
58
  def directive
37
59
  element_type.directive * num_elements
38
60
  end
39
61
 
62
+ # Get unique descriptor of this class
63
+ #
64
+ # @param [Hash] hash Labels for any variables.
65
+ #
66
+ # @return [String] Descriptor of this class.
67
+ #
68
+ # @private
40
69
  def descriptor( hash )
41
70
  unless element_type.nil?
42
71
  inspect
@@ -45,14 +74,29 @@ module Hornetseye
45
74
  end
46
75
  end
47
76
 
77
+ # Base type of this data type
78
+ #
79
+ # @return [Class] Returns +element_type+.
80
+ #
81
+ # @private
48
82
  def basetype
49
83
  element_type
50
84
  end
51
85
 
86
+ # Get list of types of composite type
87
+ #
88
+ # @return [Array<Class>] List of types.
89
+ #
90
+ # @private
52
91
  def typecodes
53
92
  [ element_type ] * num_elements
54
93
  end
55
94
 
95
+ # Scalar type to this type
96
+ #
97
+ # @return [Class] Returns +element_type+.
98
+ #
99
+ # @private
56
100
  def scalar
57
101
  element_type
58
102
  end
@@ -22,6 +22,11 @@ module Hornetseye
22
22
 
23
23
  class << self
24
24
 
25
+ # Check whether objects of this class are finalised computations
26
+ #
27
+ # @return [Boolean] Returns +false+.
28
+ #
29
+ # @private
25
30
  def finalised?
26
31
  false
27
32
  end
@@ -56,9 +61,9 @@ module Hornetseye
56
61
  "#{@block.descriptor( hash )})"
57
62
  end
58
63
 
59
- # Array type of this term
64
+ # Get type of result of delayed operation
60
65
  #
61
- # @return [Class] Resulting array type.
66
+ # @return [Class] Type of result.
62
67
  #
63
68
  # @private
64
69
  def array_type
@@ -97,6 +102,8 @@ module Hornetseye
97
102
  # @param [Integer,Node] i Index of desired element.
98
103
  #
99
104
  # @return [Node,Object] Element of diagonal injection.
105
+ #
106
+ # @private
100
107
  def element( i )
101
108
  Diagonal.new @value.element( i ), @index0, @index1, @index2, @initial,
102
109
  @block, @var1, @var2
@@ -161,7 +168,7 @@ module Hornetseye
161
168
 
162
169
  # Check whether this term is compilable
163
170
  #
164
- # @return [FalseClass,TrueClass] Returns whether this term is compilable.
171
+ # @return [Boolean] Returns whether this term is compilable.
165
172
  #
166
173
  # @private
167
174
  def compilable?
@@ -32,15 +32,24 @@ module Hornetseye
32
32
  construct *ptr.load( self )
33
33
  end
34
34
 
35
+ # Construct new object from arguments
36
+ #
37
+ # @param [Array<Object>] *args Arguments for constructor.
38
+ #
39
+ # @return [Element] New object of this type.
40
+ #
41
+ # @private
35
42
  def construct( *args )
36
43
  new *args
37
44
  end
38
45
 
39
46
  # Type coercion for native elements
40
47
  #
41
- # @param [Node] other Other native datatype to coerce with.
48
+ # @param [Class] other Other native datatype to coerce with.
49
+ #
50
+ # @return [Class] Result of coercion.
42
51
  #
43
- # @return [Array<Node>] Result of coercion.
52
+ # @private
44
53
  def coercion( other )
45
54
  if self == other
46
55
  self
@@ -107,7 +116,7 @@ module Hornetseye
107
116
 
108
117
  # Check whether this term is compilable
109
118
  #
110
- # @return [FalseClass,TrueClass] Returns whether this term is compilable.
119
+ # @return [Boolean] Returns whether this term is compilable.
111
120
  #
112
121
  # @private
113
122
  def compilable?
@@ -118,6 +127,14 @@ module Hornetseye
118
127
  end
119
128
  end
120
129
 
130
+ # Skip elements of an array
131
+ #
132
+ # @param [Variable] index Variable identifying index of array.
133
+ # @param [Node] start Wrapped integer with number of elements to skip.
134
+ #
135
+ # @return [Node] Returns +self+.
136
+ #
137
+ # @private
121
138
  def skip( index, start )
122
139
  self
123
140
  end
@@ -125,6 +142,8 @@ module Hornetseye
125
142
  # Get value of this native element
126
143
  #
127
144
  # @return [Object] Value of this native element.
145
+ #
146
+ # @private
128
147
  def get
129
148
  @value
130
149
  end
@@ -134,6 +153,8 @@ module Hornetseye
134
153
  # @param [Object] value New value for native element.
135
154
  #
136
155
  # @return [Object] Returns +value+.
156
+ #
157
+ # @private
137
158
  def store( value )
138
159
  if @value.respond_to? :store
139
160
  @value.store value.simplify.get
@@ -155,6 +176,11 @@ module Hornetseye
155
176
  ptr.save self
156
177
  end
157
178
 
179
+ # Get array with components of this value
180
+ #
181
+ # @return [Array<Object>] Get array with value of this object as single element.
182
+ #
183
+ # @private
158
184
  def values
159
185
  [ @value ]
160
186
  end
@@ -54,6 +54,11 @@ module Hornetseye
54
54
  inspect
55
55
  end
56
56
 
57
+ # Check whether objects of this class are finalised computations
58
+ #
59
+ # @return [Boolean] Returns +false+.
60
+ #
61
+ # @private
57
62
  def finalised?
58
63
  false
59
64
  end
@@ -80,9 +85,9 @@ module Hornetseye
80
85
  "(#{@values.collect { |value| value.descriptor( hash ) }.join ','})"
81
86
  end
82
87
 
83
- # Array type of this term
88
+ # Get type of result of delayed operation
84
89
  #
85
- # @return [Class] Resulting array type.
90
+ # @return [Class] Type of result.
86
91
  #
87
92
  # @private
88
93
  def array_type
@@ -139,6 +144,15 @@ module Hornetseye
139
144
  self.class.new( *stripped.collect { |elem| elem[ 2 ] } )
140
145
  end
141
146
 
147
+ # Skip elements of an array
148
+ #
149
+ # @param [Variable] index Variable identifying index of array.
150
+ # @param [Node] start Wrapped integer with number of elements to skip.
151
+ #
152
+ # @return [Node] Returns element-wise operation with elements skipped on each
153
+ # operand.
154
+ #
155
+ # @private
142
156
  def skip( index, start )
143
157
  skipped = *@values.collect { |value| value.skip( index, start ) }
144
158
  self.class.new( *skipped ).demand
@@ -149,6 +163,8 @@ module Hornetseye
149
163
  # @param [Integer,Node] i Index of desired element.
150
164
  #
151
165
  # @return [Node,Object] Element of unary operation.
166
+ #
167
+ # @private
152
168
  def element( i )
153
169
  values = @values.collect do |value|
154
170
  value.dimension == 0 ? value : value.element( i )
@@ -156,6 +172,14 @@ module Hornetseye
156
172
  self.class.new( *values ).demand
157
173
  end
158
174
 
175
+ # Extract array view with part of array
176
+ #
177
+ # @param [Integer,Node] start Number of elements to skip.
178
+ # @param [Integer,Node] length Size of array view.
179
+ #
180
+ # @return [Node] Array view with the specified elements.
181
+ #
182
+ # @private
159
183
  def slice( start, length )
160
184
  values = @values.collect do |value|
161
185
  value.dimension == 0 ? value : value.slice( start, length )
@@ -163,6 +187,11 @@ module Hornetseye
163
187
  self.class.new( *values ).demand
164
188
  end
165
189
 
190
+ # Decompose composite elements
191
+ #
192
+ # This method decomposes composite elements into array.
193
+ #
194
+ # @return [Node] Result of decomposition.
166
195
  def decompose
167
196
  values = @values.collect { |value| value.decompose }
168
197
  self.class.new( *values ).demand
@@ -170,7 +199,7 @@ module Hornetseye
170
199
 
171
200
  # Check whether this term is compilable
172
201
  #
173
- # @return [FalseClass,TrueClass] Returns whether this term is compilable.
202
+ # @return [Boolean] Returns whether this term is compilable.
174
203
  #
175
204
  # @private
176
205
  def compilable?
@@ -23,18 +23,40 @@ module Hornetseye
23
23
 
24
24
  attr_accessor :double
25
25
 
26
+ # Memory type required to store elements of this type
27
+ #
28
+ # @return [Class] Returns +Malloc+.
29
+ #
30
+ # @private
26
31
  def memory
27
32
  Malloc
28
33
  end
29
34
 
35
+ # Get storage size to store an element of this type
36
+ #
37
+ # @return [Integer] Returns +4+ or +8+.
38
+ #
39
+ # @private
30
40
  def storage_size
31
41
  double ? 8 : 4
32
42
  end
33
43
 
44
+ # Get default value for elements of this type
45
+ #
46
+ # @return [Object] Returns +0.0+.
47
+ #
48
+ # @private
34
49
  def default
35
50
  0.0
36
51
  end
37
52
 
53
+ # Compute balanced type for binary operation
54
+ #
55
+ # @param [Class] other Other native datatype to coerce with.
56
+ #
57
+ # @return [Class] Result of coercion.
58
+ #
59
+ # @private
38
60
  def coercion( other )
39
61
  if other < FLOAT_
40
62
  Hornetseye::FLOAT( ( double or other.double ) )
@@ -45,6 +67,13 @@ module Hornetseye
45
67
  end
46
68
  end
47
69
 
70
+ # Type coercion for native elements
71
+ #
72
+ # @param [Class] other Other type to coerce with.
73
+ #
74
+ # @return [Array<Class>] Result of coercion.
75
+ #
76
+ # @private
48
77
  def coerce( other )
49
78
  if other < FLOAT_
50
79
  return other, self
@@ -55,63 +84,118 @@ module Hornetseye
55
84
  end
56
85
  end
57
86
 
87
+ # Convert to type based on floating point numbers
88
+ #
89
+ # @return [Class] Corresponding type based on floating point numbers.
90
+ #
91
+ # @private
58
92
  def float
59
93
  self
60
94
  end
61
95
 
96
+ # Directive for packing/unpacking elements of this type
97
+ #
98
+ # @return [String] Returns 'f' or 'd'.
99
+ #
100
+ # @private
62
101
  def directive
63
102
  double ? 'd' : 'f'
64
103
  end
65
104
 
105
+ # Return string with information about this class.
106
+ #
107
+ # @return [String] Returns a string (e.g. "SFLOAT").
66
108
  def inspect
67
109
  "#{ double ? 'D' : 'S' }FLOAT"
68
110
  end
69
111
 
112
+ # Get unique descriptor of this class
113
+ #
114
+ # @param [Hash] hash Labels for any variables.
115
+ #
116
+ # @return [String] Descriptor of this class.
117
+ #
118
+ # @private
70
119
  def descriptor( hash )
71
120
  inspect
72
121
  end
73
122
 
123
+ # Test equality of classes
124
+ #
125
+ # @param [Object] other Object to compare with.
126
+ #
127
+ # @return [Boolean] Boolean indicating whether classes are equal.
74
128
  def ==( other )
75
129
  other.is_a? Class and other < FLOAT_ and double == other.double
76
130
  end
77
131
 
132
+ # Compute hash value for this class.
133
+ #
134
+ # @return [Fixnum] Hash value
135
+ #
136
+ # @private
78
137
  def hash
79
138
  [ :FLOAT_, double ].hash
80
139
  end
81
140
 
141
+ # Equality for hash operations
142
+ #
143
+ # @param [Object] other Object to compare with.
144
+ #
145
+ # @return [Boolean] Returns +true+ if objects are equal.
146
+ #
147
+ # @private
82
148
  def eql?( other )
83
149
  self == other
84
150
  end
85
151
 
86
152
  end
87
153
 
88
- end
89
-
90
- module Match
91
-
92
- def fit( *values )
93
- if values.all? { |value| value.is_a? Float or value.is_a? Integer }
94
- if values.any? { |value| value.is_a? Float }
95
- DFLOAT
154
+ module Match
155
+
156
+ # Method for matching elements of type FLOAT_
157
+ #
158
+ # @param [Array<Object>] *values Values to find matching native element
159
+ # type for.
160
+ #
161
+ # @return [Class] Native type fitting all values.
162
+ #
163
+ # @see FLOAT_
164
+ #
165
+ # @private
166
+ def fit( *values )
167
+ if values.all? { |value| value.is_a? Float or value.is_a? Integer }
168
+ if values.any? { |value| value.is_a? Float }
169
+ DFLOAT
170
+ else
171
+ super *values
172
+ end
96
173
  else
97
174
  super *values
98
175
  end
99
- else
100
- super *values
101
176
  end
102
- end
103
177
 
104
- def align( context )
105
- if self < FLOAT_ and context < FLOAT_
106
- context
107
- else
108
- super context
178
+ # Perform type alignment
179
+ #
180
+ # Align this type to another. This is used to prefer single-precision
181
+ # floating point in certain cases.
182
+ #
183
+ # @param [Class] context Other type to align with.
184
+ #
185
+ # @private
186
+ def align( context )
187
+ if self < FLOAT_ and context < FLOAT_
188
+ context
189
+ else
190
+ super context
191
+ end
109
192
  end
193
+
110
194
  end
111
195
 
112
- end
196
+ Node.extend Match
113
197
 
114
- Node.extend Match
198
+ end
115
199
 
116
200
  SINGLE = false
117
201
  DOUBLE = true
@@ -127,12 +211,30 @@ module Hornetseye
127
211
  SFLOAT = FLOAT SINGLE
128
212
  DFLOAT = FLOAT DOUBLE
129
213
 
214
+ # Shortcut for constructor
215
+ #
216
+ # The method calls +SFLOAT.new+.
217
+ #
218
+ # @param [Float] value Floating point value.
219
+ #
220
+ # @return [SFLOAT] The wrapped floating point value.
221
+ #
222
+ # @private
130
223
  def SFLOAT( value )
131
224
  SFLOAT.new value
132
225
  end
133
226
 
134
227
  module_function :SFLOAT
135
228
 
229
+ # Shortcut for constructor
230
+ #
231
+ # The method calls +DFLOAT.new+.
232
+ #
233
+ # @param [Float] value Floating point value.
234
+ #
235
+ # @return [DFLOAT] The wrapped floating point value.
236
+ #
237
+ # @private
136
238
  def DFLOAT( value )
137
239
  DFLOAT.new value
138
240
  end
@@ -21,40 +21,30 @@ module Hornetseye
21
21
 
22
22
  class << self
23
23
 
24
- def run( retval, block )
24
+ def run( block )
25
25
  keys, values, term = block.strip
26
- labels = Hash[ *keys.
27
- zip( ( 0 ... keys.size ).to_a ).flatten ]
28
- retval_keys, retval_values, retval_term = retval.strip
29
- retval_labels = Hash[ *retval_keys.
30
- zip( ( 0 ... retval_keys.size ).to_a ).flatten ]
31
- method_name = ( '_' + retval_term.descriptor( retval_labels ) +
32
- '_' + term.descriptor( labels ) ).
33
- tr( '(),+\-*/%.@?~&|^<=>',
34
- '0123\456789ABCDEFGH' )
26
+ labels = Hash[ *keys.zip( ( 0 ... keys.size ).to_a ).flatten ]
27
+ method_name = ( '_' + term.descriptor( labels ) ).
28
+ tr( '(),+\-*/%.@?~&|^<=>',
29
+ '0123\456789ABCDEFGH' )
35
30
  unless GCCCache.respond_to? method_name
36
31
  GCCContext.build do |context|
37
- function = new context, method_name,
38
- *( retval_keys + keys ).collect { |var| var.meta }
32
+ function = GCCFunction.new context, method_name,
33
+ *keys.collect { |var| var.meta }
39
34
  Thread.current[ :function ] = function
40
35
  term_subst = ( 0 ... keys.size ).collect do |i|
41
- { keys[i] => function.param( i + retval_keys.size ) }
36
+ { keys[i] => function.param( i ) }
42
37
  end.inject( {} ) { |a,b| a.merge b }
43
- retval_subst = ( 0 ... retval_keys.size ).collect do |i|
44
- { retval_keys[ i ] => function.param( i ) }
45
- end.inject( {} ) { |a,b| a.merge b }
46
- # Thread.current[ :function ] = function
47
38
  Hornetseye::lazy do
48
- retval_term.subst( retval_subst ).store term.subst( term_subst )
39
+ term.subst( term_subst ).demand
49
40
  end
50
41
  Thread.current[ :function ] = nil
51
42
  function.insn_return
52
43
  function.compile
53
44
  end
54
45
  end
55
- args = ( retval_values + values ).collect { |arg| arg.values }.flatten
46
+ args = values.collect { |arg| arg.values }.flatten
56
47
  GCCCache.send method_name, *args
57
- retval.simplify
58
48
  end
59
49
 
60
50
  end
@@ -81,7 +71,7 @@ module Hornetseye
81
71
 
82
72
  def variable( typecode, prefix )
83
73
  retval = GCCValue.new( self, id( prefix ) )
84
- self << "#{indent}#{GCCType.new( typecode ).identifiers.first} #{retval};\n" # !!!
74
+ self << "#{indent}#{GCCType.new( typecode ).identifier} #{retval};\n"
85
75
  retval
86
76
  end
87
77
 
@@ -23,41 +23,47 @@ module Hornetseye
23
23
  @typecode = typecode
24
24
  end
25
25
 
26
- def identifiers
26
+ def identifier
27
27
  case @typecode
28
28
  when nil
29
- [ 'void' ]
29
+ 'void'
30
30
  when BOOL
31
- [ 'char' ]
31
+ 'char'
32
32
  when BYTE
33
- [ 'char' ]
33
+ 'char'
34
34
  when UBYTE
35
- [ 'unsigned char' ]
35
+ 'unsigned char'
36
36
  when SINT
37
- [ 'short int' ]
37
+ 'short int'
38
38
  when USINT
39
- [ 'unsigned short int' ]
39
+ 'unsigned short int'
40
40
  when INT
41
- [ 'int' ]
41
+ 'int'
42
42
  when UINT
43
- [ 'unsigned int' ]
43
+ 'unsigned int'
44
44
  when SFLOAT
45
- [ 'float' ]
46
- when DFLOAT
47
- [ 'double' ]
45
+ 'float'
46
+ when DFLOAT
47
+ 'double'
48
48
  else
49
49
  if @typecode < Pointer_
50
- [ 'void *' ]
50
+ 'void *'
51
51
  elsif @typecode < INDEX_
52
- [ 'int' ]
53
- elsif @typecode < Composite
54
- GCCType.new( @typecode.element_type ).identifiers * @typecode.num_elements
52
+ 'int'
55
53
  else
56
54
  raise "No identifier available for #{@typecode.inspect}"
57
55
  end
58
56
  end
59
57
  end
60
58
 
59
+ def identifiers
60
+ if @typecode < Composite
61
+ GCCType.new( @typecode.element_type ).identifiers * @typecode.num_elements
62
+ else
63
+ [ GCCType.new( @typecode ).identifier ]
64
+ end
65
+ end
66
+
61
67
  def r2c
62
68
  case @typecode
63
69
  when BOOL
@@ -68,7 +74,7 @@ module Hornetseye
68
74
  [ lambda { |expr| "NUM2DBL( #{expr} )" } ]
69
75
  else
70
76
  if @typecode < Pointer_
71
- [ lambda { |expr| "(#{identifiers.first})mallocToPtr( #{expr} )" } ] # !!!
77
+ [ lambda { |expr| "(#{identifier})mallocToPtr( #{expr} )" } ]
72
78
  elsif @typecode < Composite
73
79
  GCCType.new( @typecode.element_type ).r2c * @typecode.num_elements
74
80
  else