multiarray 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,7 +24,7 @@ module Hornetseye
24
24
 
25
25
  # Get string with information about this class
26
26
  #
27
- # @return [String] Returns +'OBJECT'+.
27
+ # @return [String] Returns 'OBJECT'.
28
28
  def inspect
29
29
  'OBJECT'
30
30
  end
@@ -69,6 +69,13 @@ module Hornetseye
69
69
  nil
70
70
  end
71
71
 
72
+ # Compute balanced type for binary operation
73
+ #
74
+ # @param [Class] other Other type to coerce with.
75
+ #
76
+ # @return [Class] Result of coercion.
77
+ #
78
+ # @private
72
79
  def coercion( other )
73
80
  if other < Sequence_
74
81
  other.coercion self
@@ -77,7 +84,7 @@ module Hornetseye
77
84
  end
78
85
  end
79
86
 
80
- # Coerce with other object
87
+ # Type coercion for native elements
81
88
  #
82
89
  # @param [Node,Object] other Other object.
83
90
  #
@@ -86,17 +93,25 @@ module Hornetseye
86
93
  return self, self
87
94
  end
88
95
 
96
+ # Get corresponding boolean-based datatype
97
+ #
98
+ # @return [Class] Returns +self+.
89
99
  def bool
90
100
  self
91
101
  end
92
102
 
103
+ # Convert to type based on floating point numbers
104
+ #
105
+ # @return [Class] Corresponding type based on floating point numbers.
106
+ #
107
+ # @private
93
108
  def float
94
109
  OBJECT
95
110
  end
96
111
 
97
112
  # Check whether this term is compilable
98
113
  #
99
- # @return [FalseClass,TrueClass] Returns +false+.
114
+ # @return [Boolean] Returns +false+.
100
115
  #
101
116
  # @private
102
117
  def compilable?
@@ -115,7 +130,7 @@ module Hornetseye
115
130
  # Method for matching elements of type OBJECT
116
131
  #
117
132
  # @param [Array<Object>] *values Values to find matching native element
118
- # type for.
133
+ # type for.
119
134
  #
120
135
  # @return [Class] Native type fitting all values.
121
136
  #
@@ -126,6 +141,14 @@ module Hornetseye
126
141
  OBJECT
127
142
  end
128
143
 
144
+ # Perform type alignment
145
+ #
146
+ # Align this type to another. This is used to prefer single-precision
147
+ # floating point in certain cases.
148
+ #
149
+ # @param [Class] context Other type to align with.
150
+ #
151
+ # @private
129
152
  def align( context )
130
153
  self
131
154
  end
@@ -136,6 +159,13 @@ module Hornetseye
136
159
 
137
160
  end
138
161
 
162
+ # Shortcut for constructor
163
+ #
164
+ # The method calls +OBJECT.new+.
165
+ #
166
+ # @param [Object] value Ruby object.
167
+ #
168
+ # @return [OBJECT] The wrapped Ruby object.
139
169
  def OBJECT( value )
140
170
  OBJECT.new value
141
171
  end
@@ -64,11 +64,6 @@ module Hornetseye
64
64
  define_unary_op :floor
65
65
  define_unary_op :ceil
66
66
  define_unary_op :round
67
- define_unary_op :r, :scalar
68
- define_unary_op :g, :scalar
69
- define_unary_op :b, :scalar
70
- define_unary_op :real, :scalar
71
- define_unary_op :imag, :scalar
72
67
  define_binary_op :+
73
68
  define_binary_op :-
74
69
  define_binary_op :*
@@ -178,6 +173,8 @@ module Hornetseye
178
173
  Hornetseye::ElementWise( action, block.to_s, conversion ).new( self ).force
179
174
  end
180
175
 
176
+ alias_method :map, :collect
177
+
181
178
  def inject( initial = nil, options = {} )
182
179
  unless initial.nil?
183
180
  initial = Node.match( initial ).new initial unless initial.is_a? Node
@@ -204,7 +201,7 @@ module Hornetseye
204
201
 
205
202
  # Equality operator
206
203
  #
207
- # @return [FalseClass,TrueClass] Returns result of comparison.
204
+ # @return [Boolean] Returns result of comparison.
208
205
  def eq_with_multiarray( other )
209
206
  if other.is_a? Node
210
207
  if variables.empty?
@@ -231,6 +228,19 @@ module Hornetseye
231
228
  inject { |a,b| a.major b }
232
229
  end
233
230
 
231
+ def sum
232
+ inject { |a,b| a + b }
233
+ end
234
+
235
+ def range
236
+ min .. max
237
+ end
238
+
239
+ def fill!( value = typecode.default )
240
+ self[] = value
241
+ self
242
+ end
243
+
234
244
  # Apply accumulative operation over elements diagonally
235
245
  #
236
246
  # This method is used internally to implement convolutions.
@@ -239,7 +249,7 @@ module Hornetseye
239
249
  # @option options [Variable] :var1 First variable defining operation.
240
250
  # @option options [Variable] :var2 Second variable defining operation.
241
251
  # @option options [Variable] :block (yield( var1, var2 )) The operation to
242
- # apply diagonally.
252
+ # apply diagonally.
243
253
  # @yield Optional operation to apply diagonally.
244
254
  #
245
255
  # @return [Node] Result of operation.
@@ -308,124 +318,106 @@ module Hornetseye
308
318
  product( filter ).diagonal { |s,x| s + x }
309
319
  end
310
320
 
311
- def r_with_decompose
312
- if typecode < RGB_
313
- decompose.roll.element 0
314
- elsif typecode == OBJECT
315
- r_without_decompose
316
- else
317
- self
318
- end
319
- end
320
-
321
- alias_method_chain :r, :decompose
322
-
323
- def r=( value )
324
- if typecode < RGB_
325
- decompose.roll[ 0 ] = value
326
- elsif typecode == OBJECT
327
- self[] = Hornetseye::lazy do
328
- value * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 )
321
+ def histogram( *ret_shape )
322
+ options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
323
+ options = { :target => UINT, :safe => true }.merge options
324
+ if options[ :safe ]
325
+ if shape.first != 1 and ret_shape.size == 1
326
+ right = Hornetseye::lazy( 1 ) { |i| self }.unroll
327
+ else
328
+ if shape.first != ret_shape.size
329
+ raise "First dimension of array (#{shape.first}) differs from number of " +
330
+ "dimensions of histogram (#{ret_shape.size})"
331
+ end
332
+ right = self
329
333
  end
330
334
  else
331
- raise "Cannot assign red channel to object of type #{array_type.inspect}"
332
- end
333
- end
334
-
335
- def g_with_decompose
336
- if typecode < RGB_
337
- decompose.roll.element 1
338
- elsif typecode == OBJECT
339
- g_without_decompose
340
- else
341
- self
335
+ right = self
342
336
  end
343
- end
344
-
345
- alias_method_chain :g, :decompose
346
-
347
- def g=( value )
348
- if typecode < RGB_
349
- decompose.roll[ 1 ] = value
350
- elsif typecode == OBJECT
351
- self[] = Hornetseye::lazy do
352
- r * RGB.new( 1, 0, 0 ) + value * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 )
337
+ if options[ :safe ]
338
+ for i in 0 ... right.shape.first
339
+ range = right.roll[ i ].range
340
+ if range.begin < 0
341
+ raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
342
+ "(but was #{range.begin})"
343
+ end
344
+ if range.end >= ret_shape[ i ]
345
+ raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
346
+ "(but was #{range.end})"
347
+ end
353
348
  end
349
+ end
350
+ left = MultiArray.new options[ :target ], *ret_shape
351
+ left[] = 0
352
+ block = Histogram.new left, right
353
+ if block.compilable?
354
+ GCCFunction.run block
354
355
  else
355
- raise "Cannot assign green channel to object of type #{array_type.inspect}"
356
+ block.demand
356
357
  end
358
+ left
357
359
  end
358
360
 
359
- def b_with_decompose
360
- if typecode < RGB_
361
- decompose.roll.element 2
362
- elsif typecode == OBJECT
363
- b_without_decompose
364
- else
365
- self
366
- end
361
+ def histogram_with_composite( *ret_shape )
362
+ decompose.histogram_without_composite *ret_shape
367
363
  end
368
364
 
369
- alias_method_chain :b, :decompose
365
+ alias_method_chain :histogram, :composite
370
366
 
371
- def b=( value )
372
- if typecode < RGB_
373
- decompose.roll[ 2 ] = value
374
- elsif typecode == OBJECT
375
- self[] = Hornetseye::lazy do
376
- r * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + value * RGB.new( 0, 0, 1 )
367
+ def lut( table, options = {} )
368
+ options = { :safe => true }.merge options
369
+ if options[ :safe ]
370
+ if shape.first != 1 and table.dimension == 1
371
+ source = Hornetseye::lazy( 1 ) { |i| self }.unroll
372
+ else
373
+ if shape.first > table.dimension
374
+ raise "First dimension of array (#{shape.first}) is greater than the " +
375
+ " number of dimensions of LUT (#{table.dimension})"
376
+ end
377
+ source = self
377
378
  end
378
379
  else
379
- raise "Cannot assign blue channel to object of type #{array_type.inspect}"
380
+ source = self
380
381
  end
381
- end
382
-
383
- def real_with_decompose
384
- if typecode < COMPLEX_
385
- decompose.roll.element 0
386
- elsif typecode == OBJECT
387
- real_without_decompose
388
- else
389
- self
382
+ if options[ :safe ]
383
+ for i in 0 ... source.shape.first
384
+ range = source.roll[ i ].range
385
+ if range.begin < 0
386
+ raise "#{i+1}th dimension of index must be in 0 ... #{table.shape[i]} " +
387
+ "(but was #{range.begin})"
388
+ end
389
+ if range.end >= table.shape[ i ]
390
+ raise "#{i+1}th dimension of index must be in 0 ... #{table.shape[i]} " +
391
+ "(but was #{range.end})"
392
+ end
393
+ end
390
394
  end
391
- end
392
-
393
- alias_method_chain :real, :decompose
394
-
395
- def real=( value )
396
- if typecode < COMPLEX_
397
- decompose.roll[ 0 ] = value
398
- elsif typecode == OBJECT
399
- self[] = Hornetseye::lazy do
400
- value + imag * ::Complex::I
395
+ if source.dimension <= 1 and variables.empty?
396
+ result = table
397
+ ( table.dimension - 1 ).downto( 0 ) do |i|
398
+ result = result.element source.element( INT.new( i ) ).demand
401
399
  end
400
+ result
402
401
  else
403
- self[] = value
402
+ Lut.new( source, table, options[ :n ] ).force
404
403
  end
405
404
  end
406
405
 
407
- def imag_with_decompose
408
- if typecode < COMPLEX_
409
- decompose.roll.element 1
410
- elsif typecode == OBJECT
411
- imag_without_decompose
412
- else
413
- Hornetseye::lazy( *shape ) { typecode.new( 0 ) }
414
- end
406
+ def lut_with_composite( table, options = {} )
407
+ decompose.lut_without_composite table, options
415
408
  end
416
409
 
417
- alias_method_chain :imag, :decompose
410
+ alias_method_chain :lut, :composite
418
411
 
419
- def imag=( value )
420
- if typecode < COMPLEX_
421
- decompose.roll[ 1 ] = value
422
- elsif typecode == OBJECT
423
- self[] = Hornetseye::lazy do
424
- real + value * ::Complex::I
425
- end
412
+ def integral
413
+ left = pointer_type.new
414
+ block = Integral.new left, self
415
+ if block.compilable?
416
+ GCCFunction.run block
426
417
  else
427
- raise "Cannot assign imaginary values to object of type #{array_type.inspect}"
418
+ block.demand
428
419
  end
420
+ left
429
421
  end
430
422
 
431
423
  end
@@ -25,10 +25,20 @@ module Hornetseye
25
25
  # @return [Node] Type of object the pointer is pointing at.
26
26
  attr_accessor :target
27
27
 
28
+ # Construct new object from arguments
29
+ #
30
+ # @param [Array<Object>] *args Arguments for constructor.
31
+ #
32
+ # @return [Element] New object of this type.
33
+ #
34
+ # @private
28
35
  def construct( *args )
29
36
  new *args
30
37
  end
31
38
 
39
+ # Display string with information about this class
40
+ #
41
+ # @return [String] String with information about this class (e.g. '*(UBYTE)').
32
42
  def inspect
33
43
  "*(#{target.inspect})"
34
44
  end
@@ -46,40 +56,78 @@ module Hornetseye
46
56
 
47
57
  # Get default value for elements of this type
48
58
  #
49
- # @return [Memory,List] Memory for storing object of type +target+.
59
+ # @return [Memory,List] Memory for storing one object of type +target+.
50
60
  def default
51
61
  target.memory.new target.storage_size
52
62
  end
53
63
 
64
+ # Test equality of classes
65
+ #
66
+ # @param [Object] other Object to compare with.
67
+ #
68
+ # @return [Boolean] Boolean indicating whether classes are equal.
54
69
  def ==( other )
55
70
  other.is_a? Class and other < Pointer_ and
56
71
  target == other.target
57
72
  end
58
73
 
74
+ # Compute hash value for this class.
75
+ #
76
+ # @return [Fixnum] Hash value
77
+ #
78
+ # @private
59
79
  def hash
60
80
  [ :Pointer_, target ].hash
61
81
  end
62
82
 
83
+ # Equality for hash operations
84
+ #
85
+ # @param [Object] other Object to compare with.
86
+ #
87
+ # @return [Boolean] Returns +true+ if objects are equal.
88
+ #
89
+ # @private
63
90
  def eql?
64
91
  self == other
65
92
  end
66
93
 
94
+ # Get element type
95
+ #
96
+ # @return [Class] Returns the corresponding element type.
67
97
  def typecode
68
98
  target
69
99
  end
70
100
 
101
+ # Base type of this data type
102
+ #
103
+ # @return [Class] Returns +element_type+.
104
+ #
105
+ # @private
71
106
  def basetype
72
107
  target.basetype
73
108
  end
74
109
 
110
+ # Get type of result of delayed operation
111
+ #
112
+ # @return [Class] Type of result.
113
+ #
114
+ # @private
75
115
  def array_type
76
116
  target
77
117
  end
78
118
 
119
+ # Get corresponding pointer type
120
+ #
121
+ # @return [Class] Returns +self+.
79
122
  def pointer_type
80
123
  self
81
124
  end
82
125
 
126
+ # Check whether objects of this class are finalised computations
127
+ #
128
+ # @return [Boolean] Returns +false+.
129
+ #
130
+ # @private
83
131
  def finalised?
84
132
  false
85
133
  end
@@ -90,6 +138,10 @@ module Hornetseye
90
138
  @value = value
91
139
  end
92
140
 
141
+ def memory
142
+ @value
143
+ end
144
+
93
145
  # Strip of all values
94
146
  #
95
147
  # Split up into variables, values, and a term where all values have been
@@ -108,6 +160,13 @@ module Hornetseye
108
160
  "#{self.class.to_s}(#{@value.to_s})"
109
161
  end
110
162
 
163
+ # Store new value in this pointer
164
+ #
165
+ # @param [Object] value New value for this pointer object.
166
+ #
167
+ # @return [Object] Returns +value+.
168
+ #
169
+ # @private
111
170
  def store( value )
112
171
  result = value.simplify
113
172
  self.class.target.new( result.get ).write @value
@@ -140,6 +199,15 @@ module Hornetseye
140
199
  end
141
200
  end
142
201
 
202
+ def skip( index, start )
203
+ self
204
+ end
205
+
206
+ # Decompose composite elements
207
+ #
208
+ # This method decomposes composite elements into array.
209
+ #
210
+ # @return [Node] Result of decomposition.
143
211
  def decompose
144
212
  if self.class.target < Composite
145
213
  pointer = Hornetseye::Pointer( self.class.target.element_type ).new @value
@@ -151,6 +219,11 @@ module Hornetseye
151
219
  end
152
220
  end
153
221
 
222
+ # Get array with components of this value
223
+ #
224
+ # @return [Array<Object>] Get array with value of this object as single element.
225
+ #
226
+ # @private
154
227
  def values
155
228
  [ @value ]
156
229
  end