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,29 +17,55 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # Ruby array supporting array views
21
+ #
22
+ # @see Malloc
20
23
  class List
21
24
 
25
+ # Initialise array
26
+ #
27
+ # @param [Integer] n Number of elements.
28
+ # @option options [Array] :array ([ nil ] * n) Existing Ruby array to create an
29
+ # array view.
30
+ # @option options [Integer] :offset (0) Offset for array view.
22
31
  def initialize( n, options = {} )
23
32
  @array = options[ :array ] || [ nil ] * n
24
33
  @offset = options[ :offset ] || 0
25
34
  end
26
35
 
36
+ # Display information about this object
37
+ #
38
+ # @return [String] String with information about this object (e.g. "List(5)").
27
39
  def inspect
28
40
  "List(#{@array.size - @offset})"
29
41
  end
30
42
 
43
+ # Display information about this object
44
+ #
45
+ # @return [String] String with information about this object (e.g. "List(5)").
31
46
  def to_s
32
- "List(#{@array[ @offset .. -1 ]})"
47
+ inspect
33
48
  end
34
49
 
50
+ # Create array view with specified offset
51
+ #
52
+ # @param [Integer] offset Offset for array view.
53
+ #
54
+ # @return [List] The resulting array view.
35
55
  def +( offset )
36
56
  List.new 0, :array => @array, :offset => @offset + offset
37
57
  end
38
58
 
59
+ # Retrieve value of specified typecode
60
+ #
61
+ # @param [Class] typecode The type of the value.
39
62
  def load( typecode )
40
63
  @array[ @offset ]
41
64
  end
42
65
 
66
+ # Store value
67
+ #
68
+ # @param [Node] value Value to store.
43
69
  def save( value )
44
70
  @array[ @offset ] = value.get
45
71
  value
@@ -17,12 +17,25 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # Class for lazy array lookup
20
21
  class Lookup < Node
21
22
 
23
+ # Create array lookup
24
+ #
25
+ # @param [Node] p Object supporting lookup.
26
+ # @param [Variable] index The array index.
27
+ # @param [Node] stride The array stride.
22
28
  def initialize( p, index, stride )
23
29
  @p, @index, @stride = p, index, stride
24
30
  end
25
31
 
32
+ def memory
33
+ if array_type.storage_size != @stride.get * typecode.storage_size
34
+ raise 'Memory is not contiguous'
35
+ end
36
+ @p.memory
37
+ end
38
+
26
39
  # Get unique descriptor of this object
27
40
  #
28
41
  # @param [Hash] hash Labels for any variables.
@@ -35,14 +48,33 @@ module Hornetseye
35
48
  "#{@stride.descriptor( hash )})"
36
49
  end
37
50
 
51
+ # Get type of result of delayed operation
52
+ #
53
+ # @return [Class] Type of result.
54
+ #
55
+ # @private
38
56
  def array_type
39
57
  @p.array_type
40
58
  end
41
59
 
60
+ # Substitute variables
61
+ #
62
+ # Substitute the variables with the values given in the hash.
63
+ #
64
+ # @param [Hash] hash Substitutions to apply.
65
+ #
66
+ # @return [Node] Term with substitutions applied.
67
+ #
68
+ # @private
42
69
  def subst( hash )
43
70
  @p.subst( hash ).lookup @index.subst( hash ), @stride.subst( hash )
44
71
  end
45
72
 
73
+ # Get variables contained in this object
74
+ #
75
+ # @return [Set] Returns +Set[ self ]+.
76
+ #
77
+ # @private
46
78
  def variables
47
79
  @p.variables + @index.variables + @stride.variables
48
80
  end
@@ -77,6 +109,14 @@ module Hornetseye
77
109
  end
78
110
  end
79
111
 
112
+ # Skip elements of an array
113
+ #
114
+ # @param [Variable] index Variable identifying index of array.
115
+ # @param [Node] start Wrapped integer with number of elements to skip.
116
+ #
117
+ # @return [Node] Lookup object with elements skipped.
118
+ #
119
+ # @private
80
120
  def skip( index, start )
81
121
  if @index == index
82
122
  Lookup.new @p.lookup( start, @stride ), @index, @stride
@@ -85,14 +125,34 @@ module Hornetseye
85
125
  end
86
126
  end
87
127
 
128
+ # Get element if lookup term
129
+ #
130
+ # @param [Integer,Node] i Index of desired element.
131
+ #
132
+ # @return [Node,Object] Element of lookup term.
133
+ #
134
+ # @private
88
135
  def element( i )
89
136
  Lookup.new @p.element( i ), @index, @stride
90
137
  end
91
138
 
139
+ # Extract array view with part of array
140
+ #
141
+ # @param [Integer,Node] start Number of elements to skip.
142
+ # @param [Integer,Node] length Size of array view.
143
+ #
144
+ # @return [Node] Array view with the specified elements.
145
+ #
146
+ # @private
92
147
  def slice( start, length )
93
148
  Lookup.new @p.slice( start, length ), @index, @stride
94
149
  end
95
150
 
151
+ # Decompose composite elements
152
+ #
153
+ # This method decomposes composite elements into array.
154
+ #
155
+ # @return [Node] Result of decomposition.
96
156
  def decompose
97
157
  if typecode < Composite
98
158
  Lookup.new @p.decompose, @index, @stride * typecode.num_elements
@@ -0,0 +1,102 @@
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
+ module Hornetseye
18
+
19
+ class Lut < Node
20
+
21
+ class << self
22
+
23
+ def finalised?
24
+ false
25
+ end
26
+
27
+ end
28
+
29
+ def initialize( source, table, n )
30
+ @source, @table = source, table
31
+ @n = n || @source.shape.first
32
+ end
33
+
34
+ def descriptor( hash )
35
+ "Lut(#{@source.descriptor( hash )},#{@table.descriptor( hash )},#{@n})"
36
+ end
37
+
38
+ def array_type
39
+ shape = @table.shape.first( @table.dimension - @n ) + @source.shape[ 1 .. -1 ]
40
+ Hornetseye::MultiArray @table.typecode, *shape
41
+ end
42
+
43
+ def demand
44
+ @source.lut @table, :n => @n, :safe => false
45
+ end
46
+
47
+ def subst( hash )
48
+ self.class.new @source.subst( hash ), @table.subst( hash ), @n
49
+ end
50
+
51
+ def variables
52
+ @source.variables + @table.variables
53
+ end
54
+
55
+ def strip
56
+ vars1, values1, term1 = @source.strip
57
+ vars2, values2, term2 = @table.strip
58
+ return vars1 + vars2, values1 + values2, self.class.new( term1, term2, @n )
59
+ end
60
+
61
+ def skip( index, start )
62
+ self.class.new @source.skip( index, start ), @table.skip( index, start ), @n
63
+ end
64
+
65
+ def element( i )
66
+ source, table = @source, @table
67
+ if source.dimension > 1
68
+ source = source.element i
69
+ self.class.new source, table, @n
70
+ elsif table.dimension > @n
71
+ self.class.new source, table.unroll( @n ).element( i ).roll( @n ), @n
72
+ else
73
+ super i
74
+ end
75
+ end
76
+
77
+ def slice( start, length )
78
+ source, table = @source, @table
79
+ if source.dimension > 1
80
+ source = source.slice( start, length ).roll
81
+ self.class.new( source, table, @n ).unroll
82
+ elsif table.dimension > @n
83
+ self.class.new( source,
84
+ table.unroll( @n ).slice( start, length ).roll( @n + 1 ),
85
+ @n ).unroll
86
+ else
87
+ super i
88
+ end
89
+ end
90
+
91
+ def decompose
92
+ self.class.new @source, @table.decompose, @n
93
+ end
94
+
95
+ def compilable?
96
+ @source.compilable? and @table.compilable?
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+
@@ -17,17 +17,33 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # Malloc is extended with a few methods
21
+ #
22
+ # @see List
20
23
  class Malloc
21
24
 
25
+ # Read typed value
26
+ #
27
+ # @param [Class] typecode Load typed value from memory.
28
+ #
29
+ # @return [Node] Value from memory.
22
30
  def load( typecode )
23
31
  read( typecode.storage_size ).unpack( typecode.directive )
24
32
  end
25
33
 
34
+ # Write typed value to memory
35
+ #
36
+ # @param [Node] value Value to write to memory.
37
+ #
38
+ # @return [Node] Returns +value+.
26
39
  def save( value )
27
40
  write value.values.pack( value.typecode.directive )
28
41
  value
29
42
  end
30
43
 
44
+ # Display information about this object.
45
+ #
46
+ # @return [String] String with information about this object.
31
47
  def to_s
32
48
  inspect
33
49
  end
@@ -19,9 +19,13 @@ module Hornetseye
19
19
 
20
20
  module Methods
21
21
 
22
+ # Extend some methods in the specified module.
23
+ #
24
+ # @param [Module] mod The mathematics module.
22
25
  def Methods.included( mod )
23
26
  define_unary_method mod, :sqrt , :float
24
27
  define_unary_method mod, :log , :float
28
+ define_unary_method mod, :log10, :float
25
29
  define_unary_method mod, :exp , :float
26
30
  define_unary_method mod, :cos , :float
27
31
  define_unary_method mod, :sin , :float
@@ -32,10 +36,18 @@ module Hornetseye
32
36
  define_unary_method mod, :cosh , :float
33
37
  define_unary_method mod, :sinh , :float
34
38
  define_unary_method mod, :tanh , :float
39
+ define_unary_method mod, :acosh, :float
40
+ define_unary_method mod, :asinh, :float
41
+ define_unary_method mod, :atanh, :float
35
42
  define_binary_method mod, :atan2, :floating
36
43
  define_binary_method mod, :hypot, :floating
37
44
  end
38
45
 
46
+ # Extend unary method with capability to handle arrays.
47
+ #
48
+ # @param [Module] mod The mathematics module.
49
+ # @param [Symbol,String] op The unary method to extend.
50
+ # @param [Symbol,String] conversion A method for doing the type conversion.
39
51
  def define_unary_method( mod, op, conversion = :contiguous )
40
52
  mod.module_eval do
41
53
  define_method( "#{op}_with_hornetseye" ) do |a|
@@ -61,6 +73,11 @@ module Hornetseye
61
73
 
62
74
  module_function :define_unary_method
63
75
 
76
+ # Extend binary method with capability to handle arrays.
77
+ #
78
+ # @param [Module] mod The mathematics module.
79
+ # @param [Symbol,String] op The binary method to extend.
80
+ # @param [Symbol,String] conversion A method for doing the type balancing.
64
81
  def define_binary_method( mod, op, coercion = :coercion )
65
82
  mod.module_eval do
66
83
  define_method( "#{op}_with_hornetseye" ) do |a,b|
@@ -17,26 +17,42 @@
17
17
  # Namespace of Hornetseye computer vision library
18
18
  module Hornetseye
19
19
 
20
+ # This class provides methods for initialising multi-dimensional arrays
20
21
  class MultiArray
21
22
 
22
23
  class << self
23
24
 
25
+ # Create new multi-dimensional array
26
+ #
27
+ # @param [Class] typecode The type of elements
28
+ # @param [Array<Integer>] *shape The shape of the multi-dimensional array.
24
29
  def new( typecode, *shape )
25
30
  options = shape.last.is_a?( Hash ) ? shape.pop : {}
26
31
  count = options[ :count ] || 1
27
32
  if shape.empty?
28
- memory = typecode.memory.new typecode.storage_size * count
33
+ memory = options[ :memory ] ||
34
+ typecode.memory.new( typecode.storage_size * count )
29
35
  Hornetseye::Pointer( typecode ).new memory
30
36
  else
31
37
  size = shape.pop
32
38
  stride = shape.inject( 1 ) { |a,b| a * b }
33
39
  Hornetseye::lazy( size ) do |index|
34
- pointer = new typecode, *( shape + [ :count => count * size ] )
40
+ pointer = new typecode, *( shape + [ :count => count * size,
41
+ :memory => options[ :memory ] ] )
35
42
  Lookup.new pointer, index, INT.new( stride )
36
43
  end
37
44
  end
38
45
  end
39
46
 
47
+ # Convert Ruby array to uniform multi-dimensional array
48
+ #
49
+ # Type matching is used to find a common element type. Furthermore the required
50
+ # shape of the array is determined. Finally the elements are coopied to the
51
+ # resulting array.
52
+ #
53
+ # @param [Array<Object>] *args
54
+ #
55
+ # @return [Node] Uniform multi-dimensional array.
40
56
  def []( *args )
41
57
  target = Node.fit args
42
58
  target[ *args ]
@@ -46,6 +62,12 @@ module Hornetseye
46
62
 
47
63
  end
48
64
 
65
+ # Create multi-dimensional array type
66
+ #
67
+ # @param [Class] element_type Type of elements.
68
+ # @param [Array<Integer>] *shape Shape of array type.
69
+ #
70
+ # @return [Class] The array type.
49
71
  def MultiArray( element_type, *shape )
50
72
  if shape.empty?
51
73
  element_type
@@ -66,17 +66,27 @@ module Hornetseye
66
66
  self
67
67
  end
68
68
 
69
+ # Base type of this data type
70
+ #
71
+ # @return [Class] Returns +element_type+.
72
+ #
73
+ # @private
69
74
  def basetype
70
75
  self
71
76
  end
72
77
 
78
+ # Get list of types of composite type
79
+ #
80
+ # @return [Array<Class>] List of types.
81
+ #
82
+ # @private
73
83
  def typecodes
74
84
  [ self ]
75
85
  end
76
86
 
77
- # Array type of this term
87
+ # Get type of result of delayed operation
78
88
  #
79
- # @return [Class] Resulting array type.
89
+ # @return [Class] Type of result.
80
90
  #
81
91
  # @private
82
92
  def array_type
@@ -90,6 +100,12 @@ module Hornetseye
90
100
  Hornetseye::Pointer( self )
91
101
  end
92
102
 
103
+ # Generate index array of this type
104
+ #
105
+ # @param [Object] offset First value.
106
+ # @param [Object] offset Increment for consecutive values.
107
+ #
108
+ # @return [Object] Returns +offset+.
93
109
  def indgen( offset = 0, increment = 1 )
94
110
  offset
95
111
  end
@@ -101,6 +117,14 @@ module Hornetseye
101
117
  []
102
118
  end
103
119
 
120
+ def width
121
+ shape[0]
122
+ end
123
+
124
+ def height
125
+ shape[1]
126
+ end
127
+
104
128
  # Get size (number of elements) of this value
105
129
  #
106
130
  # @return [Integer] Returns +1+.
@@ -108,6 +132,9 @@ module Hornetseye
108
132
  1
109
133
  end
110
134
 
135
+ # Check whether the type is an empty array
136
+ #
137
+ # @return [Boolean] Returns whether this type represents an empty array.
111
138
  def empty?
112
139
  size == 0
113
140
  end
@@ -135,10 +162,16 @@ module Hornetseye
135
162
  BOOL
136
163
  end
137
164
 
165
+ # Get corresponding scalar type
166
+ #
167
+ # @return [Class] Returns +self+.
138
168
  def scalar
139
169
  self
140
170
  end
141
171
 
172
+ # Get corresponding type based on floating-point scalars
173
+ #
174
+ # @return [Class] Corresponding type based on floating-point scalars.
142
175
  def float_scalar
143
176
  float.scalar
144
177
  end
@@ -150,29 +183,52 @@ module Hornetseye
150
183
  other.coercion( self ).bool
151
184
  end
152
185
 
186
+ # Get corresponding maximal integer type
187
+ #
188
+ # @return [Class] Returns +self+.
189
+ #
190
+ # @private
153
191
  def maxint
154
192
  self
155
193
  end
156
194
 
195
+ # Get maximum integer based datatype for binary operation
196
+ #
197
+ # @return [Class] Returns type based on maximum integer.
157
198
  def coercion_maxint( other )
158
199
  coercion( other ).maxint
159
200
  end
160
201
 
161
- # Get corresponding floating-point datatype
202
+ # Convert to type based on floating point numbers
203
+ #
204
+ # @return [Class] Corresponding type based on floating point numbers.
162
205
  #
163
- # @return [Class] Returns +DFLOAT+.
206
+ # @private
164
207
  def float
165
208
  DFLOAT
166
209
  end
167
210
 
211
+ # Get floating point based datatype for binary operation
212
+ #
213
+ # @return [Class] Returns type based on floating point numbers.
168
214
  def floating( other )
169
215
  other.coercion( self ).float
170
216
  end
171
217
 
218
+ # Convert to type based on bytes
219
+ #
220
+ # @return [Class] Corresponding type based on bytes.
221
+ #
222
+ # @private
172
223
  def byte
173
224
  BYTE
174
225
  end
175
226
 
227
+ # Get byte-based datatype for binary operation
228
+ #
229
+ # @param [Class] other The other type.
230
+ #
231
+ # @return [Class] Returns type based on bytes.
176
232
  def coercion_byte( other )
177
233
  coercion( other ).byte
178
234
  end
@@ -182,6 +238,11 @@ module Hornetseye
182
238
  Hornetseye::MultiArray( t.typecode, *shape ).coercion t
183
239
  end
184
240
 
241
+ # Convert to different element type
242
+ #
243
+ # @param [Class] dest Element type to convert to.
244
+ #
245
+ # @return [Class] Type based on the different element type.
185
246
  def to_type( dest )
186
247
  dest
187
248
  end
@@ -197,7 +258,7 @@ module Hornetseye
197
258
 
198
259
  # Category operator
199
260
  #
200
- # @return [FalseClass,TrueClass] Check for equality or kind.
261
+ # @return [Boolean] Check for equality or kind.
201
262
  def ===( other )
202
263
  ( other == self ) or ( other.is_a? self ) or ( other.class == self )
203
264
  end
@@ -230,22 +291,29 @@ module Hornetseye
230
291
 
231
292
  # Check whether this term is compilable
232
293
  #
233
- # @return [FalseClass,TrueClass] Returns +true+.
294
+ # @return [Boolean] Returns +true+.
234
295
  #
235
296
  # @private
236
297
  def compilable?
237
298
  true
238
299
  end
239
300
 
301
+ # Check whether objects of this class are finalised computations
302
+ #
303
+ # @return [Boolean] Returns +true+.
304
+ #
305
+ # @private
240
306
  def finalised?
241
307
  true
242
308
  end
243
309
 
244
310
  end
245
311
 
246
- # Array type of this term
312
+ # Get type of result of delayed operation
313
+ #
314
+ # @return [Class] Type of result.
247
315
  #
248
- # @return [Class] Resulting array type.
316
+ # @private
249
317
  def array_type
250
318
  self.class.array_type
251
319
  end
@@ -275,6 +343,14 @@ module Hornetseye
275
343
  array_type.shape
276
344
  end
277
345
 
346
+ def width
347
+ array_type.width
348
+ end
349
+
350
+ def height
351
+ array_type.height
352
+ end
353
+
278
354
  # Get size (number of elements) of this value
279
355
  #
280
356
  # @return [Integer] Returns +array_type.size+.
@@ -282,6 +358,9 @@ module Hornetseye
282
358
  array_type.size
283
359
  end
284
360
 
361
+ # Check whether this object is an empty array.
362
+ #
363
+ # @return [Boolean] Returns whether this object is an empty array.
285
364
  def empty?
286
365
  array_type.empty?
287
366
  end
@@ -337,7 +416,7 @@ module Hornetseye
337
416
  else
338
417
  retval = '[ '
339
418
  for i in 0 ... array_type.num_elements
340
- x = Hornetseye::lazy { element i }
419
+ x = element i
341
420
  if x.dimension > 0
342
421
  if i > 0
343
422
  retval += ",\n "
@@ -400,6 +479,9 @@ module Hornetseye
400
479
  'Node()'
401
480
  end
402
481
 
482
+ # Duplicate object
483
+ #
484
+ # @return [Node] Duplicate of +self+.
403
485
  def dup
404
486
  retval = array_type.new
405
487
  retval[] = self
@@ -421,13 +503,18 @@ module Hornetseye
421
503
 
422
504
  # Check whether this term is compilable
423
505
  #
424
- # @return [FalseClass,TrueClass] Returns +typecode.compilable?+.
506
+ # @return [Boolean] Returns +typecode.compilable?+.
425
507
  #
426
508
  # @private
427
509
  def compilable?
428
510
  typecode.compilable?
429
511
  end
430
512
 
513
+ # Check whether this object is a finalised computation
514
+ #
515
+ # @return [Boolean] Returns +self.class.finalised?+.
516
+ #
517
+ # @private
431
518
  def finalised?
432
519
  self.class.finalised?
433
520
  end
@@ -479,10 +566,11 @@ module Hornetseye
479
566
  if indices.empty?
480
567
  check_shape value
481
568
  unless compilable? and value.compilable? and dimension > 0
482
- store value
569
+ Store.new( self, value ).demand
483
570
  else
484
- GCCFunction.run self, value
571
+ GCCFunction.run Store.new( self, value )
485
572
  end
573
+ value
486
574
  else
487
575
  if indices.last.is_a? Range
488
576
  view = slice indices.last.min, indices.last.size
@@ -538,16 +626,17 @@ module Hornetseye
538
626
  self
539
627
  elsif finalised?
540
628
  get
629
+ elsif compilable?
630
+ retval = pointer_type.new
631
+ GCCFunction.run Store.new( retval, self )
632
+ retval.demand.get
541
633
  else
542
- unless compilable?
543
- Hornetseye::lazy do
544
- retval = array_type.new
545
- retval[] = self
546
- retval.get
547
- end
548
- else
549
- GCCFunction.run( pointer_type.new, self ).get
550
- end
634
+ Store.new( array_type.new, self ).demand.get
635
+ #Hornetseye::lazy do
636
+ # retval = array_type.new
637
+ # retval[] = self
638
+ # retval.get
639
+ #end
551
640
  end
552
641
  end
553
642
 
@@ -582,6 +671,11 @@ module Hornetseye
582
671
  end
583
672
  end
584
673
 
674
+ # Decompose composite elements
675
+ #
676
+ # This method decomposes composite elements into array.
677
+ #
678
+ # @return [Node] Returns +self+.
585
679
  def decompose
586
680
  self
587
681
  end