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,20 +17,40 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # Representation for colour pixel
20
21
  class RGB
21
22
 
22
23
  class << self
23
24
 
25
+ # Check compatibility of other type
26
+ #
27
+ # This method checks whether binary operations with the other Ruby object can
28
+ # be performed without requiring coercion.
29
+ #
30
+ # @param [Object] value The other Ruby object.
31
+ #
32
+ # @return [Boolean] Returns +false+ if Ruby object requires
33
+ # coercion.
24
34
  def generic?( value )
25
35
  value.is_a?( Numeric ) or value.is_a?( GCCValue )
26
36
  end
27
37
 
38
+ # Defines a unary operation
39
+ #
40
+ # This method uses meta-programming to define channel-wise unary operations.
41
+ #
42
+ # @param [Symbol,String] op Operation to define channel-wise operation.
28
43
  def define_unary_op( op )
29
44
  define_method( op ) do
30
45
  RGB.new r.send( op ), g.send( op ), b.send( op )
31
46
  end
32
47
  end
33
48
 
49
+ # Defines a binary operation
50
+ #
51
+ # This method uses meta-programming to define channel-wise binary operations.
52
+ #
53
+ # @param [Symbol,String] op Operation to define channel-wise operation.
34
54
  def define_binary_op( op )
35
55
  define_method( op ) do |other|
36
56
  if other.is_a? RGB
@@ -48,20 +68,53 @@ module Hornetseye
48
68
 
49
69
  end
50
70
 
51
- attr_accessor :r, :g, :b
52
-
71
+ # Access red channel
72
+ #
73
+ # @return [Object] Value of red channel.
74
+ attr_accessor :r
75
+
76
+ # Access green channel
77
+ #
78
+ # @return [Object] Value of green channel.
79
+ attr_accessor :g
80
+
81
+ # Access blue channel
82
+ #
83
+ # @return [Object] Value of blue channel.
84
+ attr_accessor :b
85
+
86
+ # Constructor
87
+ #
88
+ # Create new RGB object.
89
+ #
90
+ # @param [Object] r Red colour component.
91
+ # @param [Object] g Green colour component.
92
+ # @param [Object] b Blue colour component.
53
93
  def initialize( r, g, b )
54
94
  @r, @g, @b = r, g, b
55
95
  end
56
96
 
97
+ # Return string with information about this object.
98
+ #
99
+ # @return [String] Returns a string (e.g. "RGB(1,2,3)").
57
100
  def inspect
58
101
  "RGB(#{@r.inspect},#{@g.inspect},#{@b.inspect})"
59
102
  end
60
103
 
104
+ # Return string with information about this object.
105
+ #
106
+ # @return [String] Returns a string (e.g. "RGB(1,2,3)").
61
107
  def to_s
62
108
  "RGB(#{@r.to_s},#{@g.to_s},#{@b.to_s})"
63
109
  end
64
110
 
111
+ # Store new value in this RGB object
112
+ #
113
+ # @param [Object] value New value for this object.
114
+ #
115
+ # @return [Object] Returns +value+.
116
+ #
117
+ # @private
65
118
  def store( value )
66
119
  @r, @g, @b = value.r, value.g, value.b
67
120
  end
@@ -111,6 +164,11 @@ module Hornetseye
111
164
  end
112
165
  end
113
166
 
167
+ # Decompose RGB number
168
+ #
169
+ # This method decomposes the RGB value into an array.
170
+ #
171
+ # @return [Node] An array with the three channel values as elements.
114
172
  def decompose
115
173
  Hornetseye::Sequence[ @r, @g, @b ]
116
174
  end
@@ -121,18 +179,38 @@ module Hornetseye
121
179
 
122
180
  class << self
123
181
 
182
+ # Set base class attribute
183
+ #
184
+ # Sets number of elements to three.
124
185
  def inherited( subclass )
125
186
  subclass.num_elements = 3
126
187
  end
127
188
 
189
+ # Construct new object from arguments
190
+ #
191
+ # @param [Object] r Value for red channel.
192
+ # @param [Object] g Value for green channel.
193
+ # @param [Object] b Value for blue channel.
194
+ #
195
+ # @return [RGB] New object of this type.
196
+ #
197
+ # @private
128
198
  def construct( r, g, b )
129
199
  new RGB.new( r, g, b )
130
200
  end
131
201
 
202
+ # Get default value for elements of this type
203
+ #
204
+ # @return [Object] Returns +RGB( 0, 0, 0 )+.
205
+ #
206
+ # @private
132
207
  def default
133
208
  RGB.new 0, 0, 0
134
209
  end
135
210
 
211
+ # Diplay information about this class
212
+ #
213
+ # @return [String] Text with information about this class (e.g. "DFLOATRGB").
136
214
  def inspect
137
215
  unless element_type.nil?
138
216
  { BYTE => 'BYTERGB',
@@ -151,14 +229,31 @@ module Hornetseye
151
229
  end
152
230
  end
153
231
 
232
+ # Get corresponding maximum integer type
233
+ #
234
+ # @return [Class] Returns RGB type based on integers.
235
+ #
236
+ # @private
154
237
  def maxint
155
238
  Hornetseye::RGB element_type.maxint
156
239
  end
157
240
 
241
+ # Convert to type based on floating point numbers
242
+ #
243
+ # @return [Class] Corresponding type based on floating point numbers.
244
+ #
245
+ # @private
158
246
  def float
159
247
  Hornetseye::RGB element_type.float
160
248
  end
161
249
 
250
+ # Compute balanced type for binary operation
251
+ #
252
+ # @param [Class] other Other native datatype to coerce with.
253
+ #
254
+ # @return [Class] Result of coercion.
255
+ #
256
+ # @private
162
257
  def coercion( other )
163
258
  if other < RGB_
164
259
  Hornetseye::RGB element_type.coercion( other.element_type )
@@ -169,6 +264,13 @@ module Hornetseye
169
264
  end
170
265
  end
171
266
 
267
+ # Type coercion for native elements
268
+ #
269
+ # @param [Class] other Other type to coerce with.
270
+ #
271
+ # @return [Array<Class>] Result of coercion.
272
+ #
273
+ # @private
172
274
  def coerce( other )
173
275
  if other < RGB_
174
276
  return other, self
@@ -179,15 +281,32 @@ module Hornetseye
179
281
  end
180
282
  end
181
283
 
284
+ # Test equality of classes
285
+ #
286
+ # @param [Object] other Object to compare with.
287
+ #
288
+ # @return [Boolean] Boolean indicating whether classes are equal.
182
289
  def ==( other )
183
290
  other.is_a? Class and other < RGB_ and
184
291
  element_type == other.element_type
185
292
  end
186
293
 
294
+ # Compute hash value for this class.
295
+ #
296
+ # @return [Fixnum] Hash value
297
+ #
298
+ # @private
187
299
  def hash
188
300
  [ :RGB_, element_type ].hash
189
301
  end
190
302
 
303
+ # Equality for hash operations
304
+ #
305
+ # @param [Object] other Object to compare with.
306
+ #
307
+ # @return [Boolean] Returns +true+ if objects are equal.
308
+ #
309
+ # @private
191
310
  def eql?( other )
192
311
  self == other
193
312
  end
@@ -206,6 +325,9 @@ module Hornetseye
206
325
  end
207
326
  end
208
327
 
328
+ # Duplicate object
329
+ #
330
+ # @return [RGB_] Duplicate of +self+.
209
331
  def dup
210
332
  if Thread.current[ :function ]
211
333
  r = Thread.current[ :function ].variable self.class.element_type, 'v'
@@ -220,6 +342,13 @@ module Hornetseye
220
342
  end
221
343
  end
222
344
 
345
+ # Store new value in this object
346
+ #
347
+ # @param [Object] value New value for this object.
348
+ #
349
+ # @return [Object] Returns +value+.
350
+ #
351
+ # @private
223
352
  def store( value )
224
353
  value = value.simplify
225
354
  if @value.r.respond_to? :store
@@ -240,12 +369,27 @@ module Hornetseye
240
369
  value
241
370
  end
242
371
 
372
+ # Get values of composite number
373
+ #
374
+ # @return [Array<Object>] Returns array with red, green, and blue component.
375
+ #
376
+ # @private
243
377
  def values
244
378
  [ @value.r, @value.g, @value.b ]
245
379
  end
246
380
 
247
381
  module Match
248
382
 
383
+ # Method for matching elements of type RGB_
384
+ #
385
+ # @param [Array<Object>] *values Values to find matching native element
386
+ # type for.
387
+ #
388
+ # @return [Class] Native type fitting all values.
389
+ #
390
+ # @see RGB_
391
+ #
392
+ # @private
249
393
  def fit( *values )
250
394
  if values.all? { |value| value.is_a? RGB or value.is_a? Float or
251
395
  value.is_a? Integer }
@@ -271,6 +415,14 @@ module Hornetseye
271
415
  end
272
416
  end
273
417
 
418
+ # Perform type alignment
419
+ #
420
+ # Align this type to another. This is used to prefer single-precision
421
+ # floating point in certain cases.
422
+ #
423
+ # @param [Class] context Other type to align with.
424
+ #
425
+ # @private
274
426
  def align( context )
275
427
  if self < RGB_
276
428
  Hornetseye::RGB element_type.align( context )
@@ -285,6 +437,86 @@ module Hornetseye
285
437
 
286
438
  end
287
439
 
440
+ module Operations
441
+
442
+ define_unary_op :r, :scalar
443
+ define_unary_op :g, :scalar
444
+ define_unary_op :b, :scalar
445
+
446
+ def r_with_decompose
447
+ if typecode < RGB_
448
+ decompose.roll.element 0
449
+ elsif typecode == OBJECT
450
+ r_without_decompose
451
+ else
452
+ self
453
+ end
454
+ end
455
+
456
+ alias_method_chain :r, :decompose
457
+
458
+ def r=( value )
459
+ if typecode < RGB_
460
+ decompose.roll[ 0 ] = value
461
+ elsif typecode == OBJECT
462
+ self[] = Hornetseye::lazy do
463
+ value * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 )
464
+ end
465
+ else
466
+ raise "Cannot assign red channel to object of type #{array_type.inspect}"
467
+ end
468
+ end
469
+
470
+ def g_with_decompose
471
+ if typecode < RGB_
472
+ decompose.roll.element 1
473
+ elsif typecode == OBJECT
474
+ g_without_decompose
475
+ else
476
+ self
477
+ end
478
+ end
479
+
480
+ alias_method_chain :g, :decompose
481
+
482
+ def g=( value )
483
+ if typecode < RGB_
484
+ decompose.roll[ 1 ] = value
485
+ elsif typecode == OBJECT
486
+ self[] = Hornetseye::lazy do
487
+ r * RGB.new( 1, 0, 0 ) + value * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 )
488
+ end
489
+ else
490
+ raise "Cannot assign green channel to object of type #{array_type.inspect}"
491
+ end
492
+ end
493
+
494
+ def b_with_decompose
495
+ if typecode < RGB_
496
+ decompose.roll.element 2
497
+ elsif typecode == OBJECT
498
+ b_without_decompose
499
+ else
500
+ self
501
+ end
502
+ end
503
+
504
+ alias_method_chain :b, :decompose
505
+
506
+ def b=( value )
507
+ if typecode < RGB_
508
+ decompose.roll[ 2 ] = value
509
+ elsif typecode == OBJECT
510
+ self[] = Hornetseye::lazy do
511
+ r * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + value * RGB.new( 0, 0, 1 )
512
+ end
513
+ else
514
+ raise "Cannot assign blue channel to object of type #{array_type.inspect}"
515
+ end
516
+ end
517
+
518
+ end
519
+
288
520
  def RGB( arg, g = nil, b = nil )
289
521
  if g.nil? and b.nil?
290
522
  retval = Class.new RGB_
@@ -317,42 +549,132 @@ module Hornetseye
317
549
 
318
550
  DFLOATRGB = RGB DFLOAT
319
551
 
552
+ # Shortcut for constructor
553
+ #
554
+ # The method calls +BYTERGB.new+.
555
+ #
556
+ # @param [RGB] value RGB value.
557
+ #
558
+ # @return [BYTERGB] The wrapped RGB value.
559
+ #
560
+ # @private
320
561
  def BYTERGB( value )
321
562
  BYTERGB.new value
322
563
  end
323
564
 
565
+ # Shortcut for constructor
566
+ #
567
+ # The method calls +UBYTERGB.new+.
568
+ #
569
+ # @param [RGB] value RGB value.
570
+ #
571
+ # @return [UBYTERGB] The wrapped RGB value.
572
+ #
573
+ # @private
324
574
  def UBYTERGB( value )
325
575
  UBYTERGB.new value
326
576
  end
327
577
 
578
+ # Shortcut for constructor
579
+ #
580
+ # The method calls +SINTRGB.new+.
581
+ #
582
+ # @param [RGB] value RGB value.
583
+ #
584
+ # @return [SINTRGB] The wrapped RGB value.
585
+ #
586
+ # @private
328
587
  def SINTRGB( value )
329
588
  SINTRGB.new value
330
589
  end
331
590
 
591
+ # Shortcut for constructor
592
+ #
593
+ # The method calls +USINTRGB.new+.
594
+ #
595
+ # @param [RGB] value RGB value.
596
+ #
597
+ # @return [USINTRGB] The wrapped RGB value.
598
+ #
599
+ # @private
332
600
  def USINTRGB( value )
333
601
  USINTRGB.new value
334
602
  end
335
603
 
604
+ # Shortcut for constructor
605
+ #
606
+ # The method calls +INTRGB.new+.
607
+ #
608
+ # @param [RGB] value RGB value.
609
+ #
610
+ # @return [INTRGB] The wrapped RGB value.
611
+ #
612
+ # @private
336
613
  def INTRGB( value )
337
614
  INTRGB.new value
338
615
  end
339
616
 
617
+ # Shortcut for constructor
618
+ #
619
+ # The method calls +UINTRGB.new+.
620
+ #
621
+ # @param [RGB] value RGB value.
622
+ #
623
+ # @return [UINTRGB] The wrapped RGB value.
624
+ #
625
+ # @private
340
626
  def UINTRGB( value )
341
627
  UINTRGB.new value
342
628
  end
343
629
 
630
+ # Shortcut for constructor
631
+ #
632
+ # The method calls +LONGRGB.new+.
633
+ #
634
+ # @param [RGB] value RGB value.
635
+ #
636
+ # @return [LONGRGB] The wrapped RGB value.
637
+ #
638
+ # @private
344
639
  def LONGRGB( value )
345
640
  LONGRGB.new value
346
641
  end
347
642
 
643
+ # Shortcut for constructor
644
+ #
645
+ # The method calls +ULONGRGB.new+.
646
+ #
647
+ # @param [RGB] value RGB value.
648
+ #
649
+ # @return [ULONGRGB] The wrapped RGB value.
650
+ #
651
+ # @private
348
652
  def ULONGRGB( value )
349
653
  ULONGRGB.new value
350
654
  end
351
655
 
656
+ # Shortcut for constructor
657
+ #
658
+ # The method calls +SFLOATRGB.new+.
659
+ #
660
+ # @param [RGB] value RGB value.
661
+ #
662
+ # @return [SFLOATRGB] The wrapped RGB value.
663
+ #
664
+ # @private
352
665
  def SFLOATRGB( value )
353
666
  SFLOATRGB.new value
354
667
  end
355
668
 
669
+ # Shortcut for constructor
670
+ #
671
+ # The method calls +DFLOATRGB.new+.
672
+ #
673
+ # @param [RGB] value RGB value.
674
+ #
675
+ # @return [DFLOATRGB] The wrapped RGB value.
676
+ #
677
+ # @private
356
678
  def DFLOATRGB( value )
357
679
  DFLOATRGB.new value
358
680
  end
@@ -69,6 +69,11 @@ module Hornetseye
69
69
  # @return [Integer] num_elements Number of elements.
70
70
  attr_accessor :num_elements
71
71
 
72
+ # Get default value for elements of this type
73
+ #
74
+ # @return [Object] Returns an array of default values.
75
+ #
76
+ # @private
72
77
  def default
73
78
  Hornetseye::lazy( num_elements ) do |i|
74
79
  if element_type.dimension > 0
@@ -105,10 +110,22 @@ module Hornetseye
105
110
  element_type.shape + [ num_elements ]
106
111
  end
107
112
 
113
+ def width
114
+ shape[0]
115
+ end
116
+
117
+ def height
118
+ shape[1]
119
+ end
120
+
108
121
  def size
109
122
  num_elements * element_type.size
110
123
  end
111
124
 
125
+ def storage_size
126
+ num_elements * element_type.storage_size
127
+ end
128
+
112
129
  def empty?
113
130
  size == 0
114
131
  end
@@ -117,10 +134,20 @@ module Hornetseye
117
134
  element_type.typecode
118
135
  end
119
136
 
137
+ # Base type of this data type
138
+ #
139
+ # @return [Class] Returns +element_type+.
140
+ #
141
+ # @private
120
142
  def basetype
121
143
  element_type.basetype
122
144
  end
123
145
 
146
+ # Get type of result of delayed operation
147
+ #
148
+ # @return [Class] Type of result.
149
+ #
150
+ # @private
124
151
  def array_type
125
152
  self
126
153
  end
@@ -145,6 +172,9 @@ module Hornetseye
145
172
  coercion( other ).bool
146
173
  end
147
174
 
175
+ # Get corresponding scalar type
176
+ #
177
+ # @return [Class] Returns type for array of scalars.
148
178
  def scalar
149
179
  Hornetseye::Sequence element_type.scalar, num_elements
150
180
  end
@@ -153,6 +183,9 @@ module Hornetseye
153
183
  Hornetseye::Sequence element_type.float_scalar, num_elements
154
184
  end
155
185
 
186
+ # Get corresponding maximum integer type
187
+ #
188
+ # @return [Class] Returns type based on maximum integers.
156
189
  def maxint
157
190
  Hornetseye::Sequence element_type.maxint, num_elements
158
191
  end
@@ -169,6 +202,11 @@ module Hornetseye
169
202
  coercion( other ).byte
170
203
  end
171
204
 
205
+ # Convert to type based on floating point numbers
206
+ #
207
+ # @return [Class] Corresponding type based on floating point numbers.
208
+ #
209
+ # @private
172
210
  def float
173
211
  Hornetseye::Sequence element_type.float, num_elements
174
212
  end
@@ -213,12 +251,24 @@ module Hornetseye
213
251
  end
214
252
  end
215
253
 
254
+ # Test equality of classes
255
+ #
256
+ # @param [Object] other Object to compare with.
257
+ #
258
+ # @return [Boolean] Boolean indicating whether classes are equal.
216
259
  def ==( other )
217
260
  other.is_a? Class and other < Sequence_ and
218
261
  other.element_type == element_type and
219
262
  other.num_elements == num_elements
220
263
  end
221
264
 
265
+ # Type coercion for native elements
266
+ #
267
+ # @param [Class] other Other native datatype to coerce with.
268
+ #
269
+ # @return [Class] Result of coercion.
270
+ #
271
+ # @private
222
272
  def coercion( other )
223
273
  if other < Sequence_
224
274
  Hornetseye::Sequence element_type.coercion( other.element_type ),
@@ -229,6 +279,13 @@ module Hornetseye
229
279
  end
230
280
  end
231
281
 
282
+ # Compute balanced type for binary operation
283
+ #
284
+ # @param [Class] other Other type to coerce with.
285
+ #
286
+ # @return [Array<Class>] Result of coercion.
287
+ #
288
+ # @private
232
289
  def coerce( other )
233
290
  if other < Sequence_
234
291
  return other, self
@@ -237,8 +294,8 @@ module Hornetseye
237
294
  end
238
295
  end
239
296
 
240
- def new
241
- MultiArray.new typecode, *shape
297
+ def new( memory = nil )
298
+ MultiArray.new typecode, *shape, :memory => memory
242
299
  end
243
300
 
244
301
  def compilable?
@@ -256,8 +313,8 @@ module Hornetseye
256
313
 
257
314
  # Method for matching elements of type Sequence_
258
315
  #
259
- # 'param [Array<Object>] *values Values to find matching native element
260
- # type for.
316
+ # @param [Array<Object>] *values Values to find matching native element
317
+ # type for.
261
318
  #
262
319
  # @return [Class] Native type fitting all values.
263
320
  #
@@ -278,6 +335,14 @@ module Hornetseye
278
335
  end
279
336
  end
280
337
 
338
+ # Perform type alignment
339
+ #
340
+ # Align this type to another. This is used to prefer single-precision
341
+ # floating point in certain cases.
342
+ #
343
+ # @param [Class] context Other type to align with.
344
+ #
345
+ # @private
281
346
  def align( context )
282
347
  if self < Sequence_
283
348
  Hornetseye::Sequence element_type.align( context ), num_elements