multiarray 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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