multiarray 0.22.0 → 0.23.1

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.
Files changed (51) hide show
  1. data/Rakefile +1 -1
  2. data/lib/multiarray.rb +53 -16
  3. data/lib/multiarray/bool.rb +1 -1
  4. data/lib/multiarray/complex.rb +76 -68
  5. data/lib/multiarray/components.rb +11 -10
  6. data/lib/multiarray/composite.rb +1 -1
  7. data/lib/multiarray/diagonal.rb +11 -12
  8. data/lib/multiarray/element.rb +3 -3
  9. data/lib/multiarray/elementwise.rb +14 -14
  10. data/lib/multiarray/field.rb +380 -0
  11. data/lib/multiarray/float.rb +10 -10
  12. data/lib/multiarray/gcccache.rb +1 -1
  13. data/lib/multiarray/gcccontext.rb +35 -54
  14. data/lib/multiarray/gccfunction.rb +12 -19
  15. data/lib/multiarray/gcctype.rb +1 -1
  16. data/lib/multiarray/gccvalue.rb +63 -43
  17. data/lib/multiarray/histogram.rb +17 -19
  18. data/lib/multiarray/index.rb +7 -8
  19. data/lib/multiarray/inject.rb +11 -12
  20. data/lib/multiarray/int.rb +12 -11
  21. data/lib/multiarray/integral.rb +11 -12
  22. data/lib/multiarray/lambda.rb +23 -18
  23. data/lib/multiarray/list.rb +1 -1
  24. data/lib/multiarray/lookup.rb +18 -13
  25. data/lib/multiarray/lut.rb +13 -16
  26. data/lib/multiarray/malloc.rb +1 -1
  27. data/lib/multiarray/mask.rb +11 -8
  28. data/lib/multiarray/methods.rb +10 -10
  29. data/lib/multiarray/multiarray.rb +15 -44
  30. data/lib/multiarray/node.rb +64 -138
  31. data/lib/multiarray/object.rb +2 -6
  32. data/lib/multiarray/operations.rb +116 -134
  33. data/lib/multiarray/pointer.rb +7 -19
  34. data/lib/multiarray/random.rb +11 -8
  35. data/lib/multiarray/rgb.rb +53 -53
  36. data/lib/multiarray/sequence.rb +11 -496
  37. data/lib/multiarray/shortcuts.rb +4 -4
  38. data/lib/multiarray/store.rb +14 -11
  39. data/lib/multiarray/unmask.rb +10 -7
  40. data/lib/multiarray/variable.rb +11 -3
  41. data/test/tc_bool.rb +0 -8
  42. data/test/tc_compile.rb +72 -0
  43. data/test/tc_float.rb +0 -8
  44. data/test/tc_int.rb +0 -8
  45. data/test/tc_lazy.rb +22 -3
  46. data/test/tc_multiarray.rb +100 -126
  47. data/test/tc_object.rb +0 -16
  48. data/test/tc_rgb.rb +0 -16
  49. data/test/tc_sequence.rb +151 -165
  50. data/test/ts_multiarray.rb +2 -0
  51. metadata +7 -4
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010, 2011 Jan Wedekind
2
+ # Copyright (C) 2010, 2011, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -47,6 +47,10 @@ module Hornetseye
47
47
  dest, source, default, zero, labels, rank, n
48
48
  end
49
49
 
50
+ def sexp?
51
+ true
52
+ end
53
+
50
54
  # Get unique descriptor of this object
51
55
  #
52
56
  # @param [Hash] hash Labels for any variables.
@@ -61,15 +65,12 @@ module Hornetseye
61
65
  "#{@n.descriptor( hash )})"
62
66
  end
63
67
 
64
- # Get type of result of delayed operation
65
- #
66
- # @return [Class] Type of result.
67
- def array_type
68
- retval = @dest.array_type
69
- ( class << self; self; end ).instance_eval do
70
- define_method( :array_type ) { retval }
71
- end
72
- retval
68
+ def typecode
69
+ @dest.typecode
70
+ end
71
+
72
+ def shape
73
+ @dest.shape
73
74
  end
74
75
 
75
76
  # Reevaluate computation
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -53,6 +53,10 @@ module Hornetseye
53
53
  value, index0, index1, index2, initial, block, var1, var2
54
54
  end
55
55
 
56
+ def sexp?
57
+ true
58
+ end
59
+
56
60
  # Get unique descriptor of this object
57
61
  #
58
62
  # @param [Hash] hash Labels for any variables.
@@ -71,17 +75,12 @@ module Hornetseye
71
75
  "#{@block.descriptor( hash )})"
72
76
  end
73
77
 
74
- # Get type of result of delayed operation
75
- #
76
- # @return [Class] Type of result.
77
- #
78
- # @private
79
- def array_type
80
- retval = Hornetseye::MultiArray @block.typecode, *@value.shape
81
- ( class << self; self; end ).instance_eval do
82
- define_method( :array_type ) { retval }
83
- end
84
- retval
78
+ def typecode
79
+ @block.typecode
80
+ end
81
+
82
+ def shape
83
+ @value.shape
85
84
  end
86
85
 
87
86
  # Reevaluate computation
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@ module Hornetseye
29
29
  # @see Malloc#load
30
30
  # @see List#load
31
31
  def fetch( ptr )
32
- construct *ptr.load( self )
32
+ construct *ptr.load(self)
33
33
  end
34
34
 
35
35
  # Construct new object from arguments
@@ -39,7 +39,7 @@ module Hornetseye
39
39
  # @return [Element] New object of this type.
40
40
  #
41
41
  # @private
42
- def construct( *args )
42
+ def construct(*args)
43
43
  new *args
44
44
  end
45
45
 
@@ -1,5 +1,5 @@
1
1
  # multiarray - Lazy multi-dimensional arrays for Ruby
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2010, 2011 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -74,6 +74,10 @@ module Hornetseye
74
74
  check_shape *values
75
75
  end
76
76
 
77
+ def sexp?
78
+ true
79
+ end
80
+
77
81
  # Get unique descriptor of this object
78
82
  #
79
83
  # @param [Hash] hash Labels for any variables.
@@ -86,18 +90,14 @@ module Hornetseye
86
90
  "(#{@values.collect { |value| value.descriptor( hash ) }.join ','})"
87
91
  end
88
92
 
89
- # Get type of result of delayed operation
90
- #
91
- # @return [Class] Type of result.
92
- #
93
- # @private
94
- def array_type
95
- array_types = @values.collect { |value| value.array_type }
96
- retval = self.class.conversion.call *array_types
97
- ( class << self; self; end ).instance_eval do
98
- define_method( :array_type ) { retval }
99
- end
100
- retval
93
+ def typecode
94
+ typecodes = @values.collect { |value| value.typecode }
95
+ self.class.conversion.call *typecodes
96
+ end
97
+
98
+ def shape
99
+ shapes = @values.collect { |value| value.shape }
100
+ shapes.inject { |a,b| a.size > b.size ? a : b }
101
101
  end
102
102
 
103
103
  # Reevaluate computation
@@ -208,7 +208,7 @@ module Hornetseye
208
208
  #
209
209
  # @private
210
210
  def compilable?
211
- array_type.compilable? and @values.all? { |value| value.compilable? }
211
+ typecode.compilable? and @values.all? { |value| value.compilable? }
212
212
  end
213
213
 
214
214
  end
@@ -0,0 +1,380 @@
1
+ # multiarray - Lazy multi-dimensional arrays for Ruby
2
+ # Copyright (C) 2010, 2011 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
+ # Namespace of Hornetseye computer vision library
18
+ module Hornetseye
19
+
20
+ # Class for representing n-dimensional native arrays
21
+ class Field_
22
+
23
+ class << self
24
+
25
+ # Type of array elements
26
+ #
27
+ # @return [Class] Type of array elements.
28
+ attr_accessor :typecode
29
+
30
+ # Number of dimensions
31
+ #
32
+ # @return [Integer] Number of dimensions.
33
+ attr_accessor :dimension
34
+
35
+ def inherit(typecode, dimension)
36
+ retval = Class.new self
37
+ retval.typecode = typecode
38
+ retval.dimension = dimension
39
+ retval
40
+ end
41
+
42
+ def new(*shape)
43
+ options = shape.last.is_a?( Hash ) ? shape.pop : {}
44
+ raise "Constructor requires #{dimension} arguments" unless dimension == shape.size
45
+ count = options[:count] || 1
46
+ if shape.empty?
47
+ memory = options[:memory] ||
48
+ typecode.memory_type.new(typecode.storage_size * count)
49
+ Hornetseye::Pointer( typecode ).new memory
50
+ else
51
+ size = shape.pop
52
+ stride = shape.inject 1, :*
53
+ Hornetseye::lazy(size) do |index|
54
+ pointer = Field_.inherit(typecode, dimension - 1).
55
+ new *(shape + [:count => count * size, :memory => options[:memory]])
56
+ Lookup.new pointer, index, INT.new(stride)
57
+ end
58
+ end
59
+ end
60
+
61
+ # Display this type
62
+ #
63
+ # @return [String] String with description of this type.
64
+ def inspect
65
+ if typecode and dimension
66
+ if dimension != 1
67
+ "MultiArray(#{typecode.inspect},#{dimension})"
68
+ else
69
+ "Sequence(#{typecode.inspect})"
70
+ end
71
+ else
72
+ 'Field(?,?)'
73
+ end
74
+ end
75
+
76
+ def to_s
77
+ inspect
78
+ end
79
+
80
+ # Construct native array from Ruby array
81
+ #
82
+ # @param [Array<Object>] args Array with Ruby values.
83
+ #
84
+ # @return [Node] Native array with specified values.
85
+ def [](*args)
86
+ def arr_shape(args)
87
+ if args.is_a? Array
88
+ args.collect do |arg|
89
+ arr_shape arg
90
+ end.inject([]) do |a,b|
91
+ (0 ... [a.size, b.size].max).collect do |i|
92
+ [i < a.size ? a[i] : 0, i < b.size ? b[i] : 0].max
93
+ end
94
+ end + [args.size]
95
+ else
96
+ []
97
+ end
98
+ end
99
+ retval = new *arr_shape(args)
100
+ def recursion(element, args)
101
+ if element.dimension > 0
102
+ args.each_with_index do |arg,i|
103
+ recursion element.element(INT.new(i)), arg
104
+ end
105
+ else
106
+ element[] = args
107
+ end
108
+ end
109
+ recursion retval, args
110
+ retval
111
+ end
112
+
113
+ # Create (lazy) index array
114
+ #
115
+ # @overload indgen(*shape, offset = 0, increment = 1)
116
+ # @param [Array<Integer>] shape Dimensions of resulting array.
117
+ # @param [Object] offset (0) First value of array.
118
+ # @param [Object] increment (1) Increment for subsequent values.
119
+ #
120
+ # @return [Node] Lazy term generating the array.
121
+ def indgen(*args)
122
+ unless args.size.between? dimension, dimension + 2
123
+ raise "#{inspect}.indgen requires between #{dimension} and #{dimension + 2} arguments"
124
+ end
125
+ shape = args[0 ... dimension]
126
+ offset = args.size > dimension ? args[dimension] : 0
127
+ increment = args.size > dimension + 1 ? args[dimension + 1] : 1
128
+ step = shape[0 ... -1].inject 1, :*
129
+ Hornetseye::lazy(shape.last) do |i|
130
+ (step * increment * i +
131
+ Hornetseye::MultiArray(typecode, dimension - 1).
132
+ indgen(*(shape[0 ... -1] + [offset, increment]))).to_type typecode
133
+ end
134
+ end
135
+
136
+ # Generate random number array
137
+ #
138
+ # Generate integer or floating point random numbers in the range 0 ... n.
139
+ #
140
+ # @overload random(*shape, n)
141
+ # @param [Array<Integer>] shape Dimensions of resulting array.
142
+ # @param [Integer,Float] n (1) Upper boundary for random numbers
143
+ #
144
+ # @return [Node] Array with random numbers.
145
+ def random(*args)
146
+ unless args.size.between? dimension, dimension + 1
147
+ raise "#{inspect}.random requires between #{dimension} and #{dimension + 1} arguments"
148
+ end
149
+ shape = args[0 ... dimension]
150
+ n = args.size > dimension ? args[dimension] : 1
151
+ n = typecode.maxint.new n unless n.matched?
152
+ retval = new *shape
153
+ unless compilable? and dimension > 0
154
+ Random.new(retval.sexp, n).demand
155
+ else
156
+ GCCFunction.run Random.new(retval.sexp, n)
157
+ end
158
+ retval
159
+ end
160
+
161
+ # Base type of this data type
162
+ #
163
+ # @return [Class] Returns +element_type+.
164
+ #
165
+ # @private
166
+ def basetype
167
+ typecode.basetype
168
+ end
169
+
170
+ # Get storage size of array type
171
+ #
172
+ # @param [Array<Integer>] shape Shape of desired array.
173
+ #
174
+ # @return [Integer] Storage size of array.
175
+ def storage_size(*shape)
176
+ shape.inject typecode.storage_size, :*
177
+ end
178
+
179
+ # Type coercion for native elements
180
+ #
181
+ # @param [Class] other Other native datatype to coerce with.
182
+ #
183
+ # @return [Class] Result of coercion.
184
+ #
185
+ # @private
186
+ def coercion( other )
187
+ Hornetseye::MultiArray typecode.coercion(other.typecode),
188
+ [dimension, other.dimension].max
189
+ end
190
+
191
+ # Check whether delayed operation will have colour
192
+ #
193
+ # @return [Boolean] Boolean indicating whether the array has elements of type
194
+ # RGB.
195
+ def rgb?
196
+ typecode.rgb?
197
+ end
198
+
199
+ # Get this type
200
+ #
201
+ # @return [Class] Returns +self+.
202
+ #
203
+ # @private
204
+ def identity
205
+ self
206
+ end
207
+
208
+ # Get corresponding boolean type
209
+ #
210
+ # @return [Class] Returns type for array of boolean values.
211
+ #
212
+ # @private
213
+ def bool
214
+ Hornetseye::MultiArray typecode.bool, dimension
215
+ end
216
+
217
+ # Coerce and convert to boolean type
218
+ #
219
+ # @return [Class] Returns type for array of boolean values.
220
+ #
221
+ # @private
222
+ def coercion_bool(other)
223
+ coercion(other).bool
224
+ end
225
+
226
+ # Get corresponding scalar type
227
+ #
228
+ # @return [Class] Returns type for array of scalars.
229
+ #
230
+ # @private
231
+ def scalar
232
+ Hornetseye::MultiArray typecode.scalar, dimension
233
+ end
234
+
235
+ # Get corresponding floating point type
236
+ #
237
+ # @return [Class] Returns type for array of floating point numbers.
238
+ #
239
+ # @private
240
+ def float_scalar
241
+ Hornetseye::MultiArray typecode.float_scalar, dimension
242
+ end
243
+
244
+ # Get corresponding maximum integer type
245
+ #
246
+ # @return [Class] Returns type based on maximum integers.
247
+ #
248
+ # @private
249
+ def maxint
250
+ Hornetseye::MultiArray typecode.maxint, dimension
251
+ end
252
+
253
+ # Coerce and convert to maximum integer type
254
+ #
255
+ # @return [Class] Returns type based on maximum integers.
256
+ #
257
+ # @private
258
+ def coercion_maxint(other)
259
+ coercion(other).maxint
260
+ end
261
+
262
+ # Get corresponding byte type
263
+ #
264
+ # @return [Class] Returns type based on byte.
265
+ #
266
+ # @private
267
+ def byte
268
+ Hornetseye::MultiArray typecode.byte, dimension
269
+ end
270
+
271
+ # Coerce and convert to byte type
272
+ #
273
+ # @return [Class] Returns type based on byte.
274
+ #
275
+ # @private
276
+ def coercion_byte(other)
277
+ coercion(other).byte
278
+ end
279
+
280
+ # Convert to type based on floating point numbers
281
+ #
282
+ # @return [Class] Corresponding type based on floating point numbers.
283
+ #
284
+ # @private
285
+ def float
286
+ Hornetseye::MultiArray typecode.field, dimension
287
+ end
288
+
289
+ # Coerce and convert to type based on floating point numbers
290
+ #
291
+ # @return [Class] Corresponding type based on floating point numbers.
292
+ #
293
+ # @private
294
+ def floating(other)
295
+ coercion(other).float
296
+ end
297
+
298
+ # Coerce with two other types
299
+ #
300
+ # @return [Class] Result of coercion.
301
+ #
302
+ # @private
303
+ def cond(a, b)
304
+ t = a.coercion b
305
+ Hornetseye::MultiArray t.typecode, dimension
306
+ end
307
+
308
+ # Replace element type
309
+ #
310
+ # @return [Class] Result of conversion.
311
+ #
312
+ # @private
313
+ def to_type(dest)
314
+ Hornetseye::MultiArray typecode.to_type(dest), dimension
315
+ end
316
+
317
+ # Check whether this array expression allows compilation
318
+ #
319
+ # @return [Boolean] Returns +true+ if this expression supports compilation.
320
+ def compilable?
321
+ typecode.compilable?
322
+ end
323
+
324
+ end
325
+
326
+ # Namespace containing method for matching elements of type Field_
327
+ #
328
+ # @see Field_
329
+ #
330
+ # @private
331
+ module Match
332
+
333
+ # Method for matching elements of type Field_
334
+ #
335
+ # @param [Array<Object>] *values Values to find matching native element
336
+ # type for.
337
+ #
338
+ # @return [Class] Native type fitting all values.
339
+ #
340
+ # @see Field_
341
+ #
342
+ # @private
343
+ def fit( *values )
344
+ n = values.inject 0 do |size,value|
345
+ value.is_a?(Array) ? [size, value.size].max : size
346
+ end
347
+ if n > 0
348
+ elements = values.inject [] do |flat,value|
349
+ flat + (value.is_a?(Array) ? value : [value])
350
+ end
351
+ Hornetseye::MultiArray fit( *elements ), 1
352
+ else
353
+ super *values
354
+ end
355
+ end
356
+
357
+ # Perform type alignment
358
+ #
359
+ # Align this type to another. This is used to prefer single-precision
360
+ # floating point in certain cases.
361
+ #
362
+ # @param [Class] context Other type to align with.
363
+ #
364
+ # @private
365
+ def align(context)
366
+ if self < Field_
367
+ Hornetseye::MultiArray typecode.align(context), dimension
368
+ else
369
+ super context
370
+ end
371
+ end
372
+
373
+ end
374
+
375
+ Node.extend Match
376
+
377
+ end
378
+
379
+ end
380
+