multiarray 0.22.0 → 0.23.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/multiarray.rb +53 -16
- data/lib/multiarray/bool.rb +1 -1
- data/lib/multiarray/complex.rb +76 -68
- data/lib/multiarray/components.rb +11 -10
- data/lib/multiarray/composite.rb +1 -1
- data/lib/multiarray/diagonal.rb +11 -12
- data/lib/multiarray/element.rb +3 -3
- data/lib/multiarray/elementwise.rb +14 -14
- data/lib/multiarray/field.rb +380 -0
- data/lib/multiarray/float.rb +10 -10
- data/lib/multiarray/gcccache.rb +1 -1
- data/lib/multiarray/gcccontext.rb +35 -54
- data/lib/multiarray/gccfunction.rb +12 -19
- data/lib/multiarray/gcctype.rb +1 -1
- data/lib/multiarray/gccvalue.rb +63 -43
- data/lib/multiarray/histogram.rb +17 -19
- data/lib/multiarray/index.rb +7 -8
- data/lib/multiarray/inject.rb +11 -12
- data/lib/multiarray/int.rb +12 -11
- data/lib/multiarray/integral.rb +11 -12
- data/lib/multiarray/lambda.rb +23 -18
- data/lib/multiarray/list.rb +1 -1
- data/lib/multiarray/lookup.rb +18 -13
- data/lib/multiarray/lut.rb +13 -16
- data/lib/multiarray/malloc.rb +1 -1
- data/lib/multiarray/mask.rb +11 -8
- data/lib/multiarray/methods.rb +10 -10
- data/lib/multiarray/multiarray.rb +15 -44
- data/lib/multiarray/node.rb +64 -138
- data/lib/multiarray/object.rb +2 -6
- data/lib/multiarray/operations.rb +116 -134
- data/lib/multiarray/pointer.rb +7 -19
- data/lib/multiarray/random.rb +11 -8
- data/lib/multiarray/rgb.rb +53 -53
- data/lib/multiarray/sequence.rb +11 -496
- data/lib/multiarray/shortcuts.rb +4 -4
- data/lib/multiarray/store.rb +14 -11
- data/lib/multiarray/unmask.rb +10 -7
- data/lib/multiarray/variable.rb +11 -3
- data/test/tc_bool.rb +0 -8
- data/test/tc_compile.rb +72 -0
- data/test/tc_float.rb +0 -8
- data/test/tc_int.rb +0 -8
- data/test/tc_lazy.rb +22 -3
- data/test/tc_multiarray.rb +100 -126
- data/test/tc_object.rb +0 -16
- data/test/tc_rgb.rb +0 -16
- data/test/tc_sequence.rb +151 -165
- data/test/ts_multiarray.rb +2 -0
- metadata +7 -4
@@ -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
|
@@ -22,30 +22,8 @@ module Hornetseye
|
|
22
22
|
|
23
23
|
class << self
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
# @param [Class] element_type The type of the elements.
|
28
|
-
# @param [Array<Integer>] *array_shape The shape of the multi-dimensional array.
|
29
|
-
#
|
30
|
-
# @return [Node] Returns uninitialised native array.
|
31
|
-
def new( element_type, *array_shape )
|
32
|
-
typecode = element_type.typecode
|
33
|
-
shape = element_type.shape + array_shape
|
34
|
-
options = shape.last.is_a?( Hash ) ? shape.pop : {}
|
35
|
-
count = options[ :count ] || 1
|
36
|
-
if shape.empty?
|
37
|
-
memory = options[ :memory ] ||
|
38
|
-
typecode.memory_type.new( typecode.storage_size * count )
|
39
|
-
Hornetseye::Pointer( typecode ).new memory
|
40
|
-
else
|
41
|
-
size = shape.pop
|
42
|
-
stride = shape.inject( 1 ) { |a,b| a * b }
|
43
|
-
Hornetseye::lazy( size ) do |index|
|
44
|
-
pointer = new typecode, *( shape + [ :count => count * size,
|
45
|
-
:memory => options[ :memory ] ] )
|
46
|
-
Lookup.new pointer, index, INT.new( stride )
|
47
|
-
end
|
48
|
-
end
|
25
|
+
def new(typecode, *shape)
|
26
|
+
Hornetseye::MultiArray(typecode, shape.size).new *shape
|
49
27
|
end
|
50
28
|
|
51
29
|
# Import array from string
|
@@ -53,19 +31,19 @@ module Hornetseye
|
|
53
31
|
# Create an array from raw data provided as a string.
|
54
32
|
#
|
55
33
|
# @param [Class] typecode Type of the elements in the string.
|
56
|
-
# @param [String]
|
34
|
+
# @param [String,Malloc] data String or memory object with raw data.
|
57
35
|
# @param [Array<Integer>] shape Array with dimensions of array.
|
58
36
|
#
|
59
37
|
# @return [Node] Multi-dimensional array with imported data.
|
60
|
-
def import( typecode,
|
61
|
-
t = Hornetseye::MultiArray typecode,
|
62
|
-
if
|
63
|
-
memory =
|
38
|
+
def import( typecode, data, *shape )
|
39
|
+
t = Hornetseye::MultiArray typecode, shape.size
|
40
|
+
if data.is_a? Malloc
|
41
|
+
memory = data
|
64
42
|
else
|
65
|
-
memory = Malloc.new t.storage_size
|
66
|
-
memory.write
|
43
|
+
memory = Malloc.new t.storage_size(*shape)
|
44
|
+
memory.write data
|
67
45
|
end
|
68
|
-
t.new memory
|
46
|
+
t.new *(shape + [:memory => memory])
|
69
47
|
end
|
70
48
|
|
71
49
|
# Convert Ruby array to uniform multi-dimensional array
|
@@ -118,18 +96,11 @@ module Hornetseye
|
|
118
96
|
|
119
97
|
end
|
120
98
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
# @param [Array<Integer>] *shape Shape of array type.
|
125
|
-
#
|
126
|
-
# @return [Class] The array type.
|
127
|
-
def MultiArray( element_type, *shape )
|
128
|
-
if shape.empty?
|
129
|
-
element_type
|
99
|
+
def MultiArray(typecode, dimension)
|
100
|
+
if dimension > 0
|
101
|
+
Field_.inherit typecode.typecode, typecode.dimension + dimension
|
130
102
|
else
|
131
|
-
Hornetseye::
|
132
|
-
shape.last
|
103
|
+
Hornetseye::Pointer typecode
|
133
104
|
end
|
134
105
|
end
|
135
106
|
|
data/lib/multiarray/node.rb
CHANGED
@@ -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
|
@@ -84,20 +84,8 @@ module Hornetseye
|
|
84
84
|
[ self ]
|
85
85
|
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
# @return [Class] Type of result.
|
90
|
-
#
|
91
|
-
# @private
|
92
|
-
def array_type
|
93
|
-
self
|
94
|
-
end
|
95
|
-
|
96
|
-
# Convert to pointer type
|
97
|
-
#
|
98
|
-
# @return [Class] Corresponding pointer type.
|
99
|
-
def pointer_type
|
100
|
-
Hornetseye::Pointer( self )
|
87
|
+
def shape
|
88
|
+
[]
|
101
89
|
end
|
102
90
|
|
103
91
|
# Generate index array of this type
|
@@ -110,41 +98,6 @@ module Hornetseye
|
|
110
98
|
offset
|
111
99
|
end
|
112
100
|
|
113
|
-
# Get shape of this term
|
114
|
-
#
|
115
|
-
# @return [Array<Integer>] Returns +[]+.
|
116
|
-
def shape
|
117
|
-
[]
|
118
|
-
end
|
119
|
-
|
120
|
-
# Get width of two-dimensional array
|
121
|
-
#
|
122
|
-
# @return [Integer] Width of array.
|
123
|
-
def width
|
124
|
-
shape[0]
|
125
|
-
end
|
126
|
-
|
127
|
-
# Get height of two-dimensional array
|
128
|
-
#
|
129
|
-
# @return [Integer] Height of array.
|
130
|
-
def height
|
131
|
-
shape[1]
|
132
|
-
end
|
133
|
-
|
134
|
-
# Get size (number of elements) of this value
|
135
|
-
#
|
136
|
-
# @return [Integer] Returns +1+.
|
137
|
-
def size
|
138
|
-
1
|
139
|
-
end
|
140
|
-
|
141
|
-
# Check whether the type is an empty array
|
142
|
-
#
|
143
|
-
# @return [Boolean] Returns whether this type represents an empty array.
|
144
|
-
def empty?
|
145
|
-
size == 0
|
146
|
-
end
|
147
|
-
|
148
101
|
# Get dimension of this term
|
149
102
|
#
|
150
103
|
# @return [Array<Integer>] Returns +0+.
|
@@ -252,9 +205,8 @@ module Hornetseye
|
|
252
205
|
# @param [Class] a The third type.
|
253
206
|
#
|
254
207
|
# @return [Class] Returns type based on bytes.
|
255
|
-
def cond(
|
256
|
-
|
257
|
-
Hornetseye::MultiArray( t.typecode, *shape ).coercion t
|
208
|
+
def cond(a, b)
|
209
|
+
a.coercion b
|
258
210
|
end
|
259
211
|
|
260
212
|
# Convert to different element type
|
@@ -308,31 +260,6 @@ module Hornetseye
|
|
308
260
|
hash[ self ] || self
|
309
261
|
end
|
310
262
|
|
311
|
-
# Check arguments for compatible shape
|
312
|
-
#
|
313
|
-
# The method will throw an exception if one of the arguments has an incompatible
|
314
|
-
# shape.
|
315
|
-
#
|
316
|
-
# @param [Array<Class>] args Arguments to check for compatibility.
|
317
|
-
#
|
318
|
-
# @return [Object] The return value should be ignored.
|
319
|
-
def check_shape( *args )
|
320
|
-
_shape = shape
|
321
|
-
args.each do |arg|
|
322
|
-
_arg_shape = arg.shape
|
323
|
-
if _shape.size < _arg_shape.size
|
324
|
-
raise "#{arg.inspect} has #{arg.dimension} dimension(s) " +
|
325
|
-
"but should not have more than #{dimension}"
|
326
|
-
end
|
327
|
-
if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer }
|
328
|
-
if _shape.last( _arg_shape.size ) != _arg_shape
|
329
|
-
raise "#{arg.inspect} has shape #{arg.shape.inspect} " +
|
330
|
-
"(does not match last value(s) of #{shape.inspect})"
|
331
|
-
end
|
332
|
-
end
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
263
|
# Check whether this term is compilable
|
337
264
|
#
|
338
265
|
# @return [Boolean] Returns +true+.
|
@@ -353,69 +280,47 @@ module Hornetseye
|
|
353
280
|
|
354
281
|
end
|
355
282
|
|
356
|
-
|
357
|
-
|
358
|
-
# @return [Class] Type of result.
|
359
|
-
#
|
360
|
-
# @private
|
361
|
-
def array_type
|
362
|
-
self.class.array_type
|
283
|
+
def matched?
|
284
|
+
true
|
363
285
|
end
|
364
286
|
|
365
|
-
|
366
|
-
|
367
|
-
# @return [Class] Corresponding pointer type.
|
368
|
-
def pointer_type
|
369
|
-
array_type.pointer_type
|
287
|
+
def allocate
|
288
|
+
Hornetseye::MultiArray(typecode, dimension).new *shape
|
370
289
|
end
|
371
290
|
|
372
291
|
# Element-type of this term
|
373
292
|
#
|
374
293
|
# @return [Class] Element-type of this datatype.
|
375
294
|
def typecode
|
376
|
-
|
295
|
+
self.class.typecode
|
377
296
|
end
|
378
297
|
|
379
298
|
# Base-type of this term
|
380
299
|
#
|
381
300
|
# @return [Class] Base-type of this datatype.
|
382
301
|
def basetype
|
383
|
-
|
384
|
-
end
|
385
|
-
|
386
|
-
# Get shape of this term
|
387
|
-
#
|
388
|
-
# @return [Array<Integer>] Returns +array_type.shape+.
|
389
|
-
def shape
|
390
|
-
array_type.shape
|
302
|
+
self.class.basetype
|
391
303
|
end
|
392
304
|
|
393
305
|
# Get width of two-dimensional array
|
394
306
|
#
|
395
307
|
# @return [Integer] Width of array.
|
396
308
|
def width
|
397
|
-
|
309
|
+
shape[0]
|
398
310
|
end
|
399
311
|
|
400
312
|
# Get height of two-dimensional array
|
401
313
|
#
|
402
314
|
# @return [Integer] Height of array.
|
403
315
|
def height
|
404
|
-
|
316
|
+
shape[1]
|
405
317
|
end
|
406
318
|
|
407
319
|
# Get size (number of elements) of this value
|
408
320
|
#
|
409
|
-
# @return [Integer] Returns
|
321
|
+
# @return [Integer] Returns number of elements of this value.
|
410
322
|
def size
|
411
|
-
|
412
|
-
end
|
413
|
-
|
414
|
-
# Get memory size of object
|
415
|
-
#
|
416
|
-
# @return [Integer] Returns required storage size of this array.
|
417
|
-
def storage_size
|
418
|
-
array_type.storage_size
|
323
|
+
shape.inject(1) { |a,b| a * b }
|
419
324
|
end
|
420
325
|
|
421
326
|
# Duplicate array expression if it is not in row-major format
|
@@ -423,8 +328,8 @@ module Hornetseye
|
|
423
328
|
# @return [Node] Duplicate of array or +self+.
|
424
329
|
def memorise
|
425
330
|
if memory
|
426
|
-
contiguous_strides = (
|
427
|
-
shape[
|
331
|
+
contiguous_strides = (0 ... dimension).collect do |i|
|
332
|
+
shape[0 ... i].inject(1) { |a,b| a * b }
|
428
333
|
end
|
429
334
|
if strides == contiguous_strides
|
430
335
|
self
|
@@ -465,21 +370,28 @@ module Hornetseye
|
|
465
370
|
#
|
466
371
|
# @return [Boolean] Returns whether this object is an empty array.
|
467
372
|
def empty?
|
468
|
-
|
373
|
+
size == 0
|
374
|
+
end
|
375
|
+
|
376
|
+
# Get shape of this term
|
377
|
+
#
|
378
|
+
# @return [Array<Integer>] Returns +[]+.
|
379
|
+
def shape
|
380
|
+
self.class.shape
|
469
381
|
end
|
470
382
|
|
471
383
|
# Get dimension of this term
|
472
384
|
#
|
473
|
-
# @return [Array<Integer>] Returns
|
385
|
+
# @return [Array<Integer>] Returns number of dimensions of this term.
|
474
386
|
def dimension
|
475
|
-
|
387
|
+
shape.size
|
476
388
|
end
|
477
389
|
|
478
390
|
# Check whether this object is an RGB value
|
479
391
|
#
|
480
392
|
# @return [Boolean] Returns +false+.
|
481
393
|
def rgb?
|
482
|
-
|
394
|
+
typecode.rgb?
|
483
395
|
end
|
484
396
|
|
485
397
|
# Extract native value if this is an element
|
@@ -512,12 +424,12 @@ module Hornetseye
|
|
512
424
|
def inspect( indent = nil, lines = nil )
|
513
425
|
if variables.empty?
|
514
426
|
if dimension == 0 and not indent
|
515
|
-
"#{
|
427
|
+
"#{typecode.inspect}(#{force.inspect})"
|
516
428
|
else
|
517
429
|
if indent
|
518
430
|
prepend = ''
|
519
431
|
else
|
520
|
-
prepend = "#{
|
432
|
+
prepend = "#{Hornetseye::MultiArray(typecode, dimension).inspect}:\n"
|
521
433
|
indent = 0
|
522
434
|
lines = 0
|
523
435
|
end
|
@@ -525,7 +437,7 @@ module Hornetseye
|
|
525
437
|
retval = '[]'
|
526
438
|
else
|
527
439
|
retval = '[ '
|
528
|
-
for i in 0 ...
|
440
|
+
for i in 0 ... shape.last
|
529
441
|
x = element i
|
530
442
|
if x.dimension > 0
|
531
443
|
if i > 0
|
@@ -546,7 +458,7 @@ module Hornetseye
|
|
546
458
|
end
|
547
459
|
else
|
548
460
|
retval += ', ' if i > 0
|
549
|
-
str = x.force.inspect
|
461
|
+
str = x.force.inspect
|
550
462
|
if retval.size + str.size >= 74 - '...'.size -
|
551
463
|
'[ ]'.size * indent.succ
|
552
464
|
retval += '...'
|
@@ -593,7 +505,7 @@ module Hornetseye
|
|
593
505
|
#
|
594
506
|
# @return [Node] Duplicate of +self+.
|
595
507
|
def dup
|
596
|
-
retval =
|
508
|
+
retval = Hornetseye::MultiArray(typecode, dimension).new *shape
|
597
509
|
retval[] = self
|
598
510
|
retval
|
599
511
|
end
|
@@ -652,14 +564,26 @@ module Hornetseye
|
|
652
564
|
# The method will throw an exception if one of the arguments has an incompatible
|
653
565
|
# shape.
|
654
566
|
#
|
655
|
-
# @param [Array<
|
567
|
+
# @param [Array<Class>] args Arguments to check for compatibility.
|
656
568
|
#
|
657
569
|
# @return [Object] The return value should be ignored.
|
658
|
-
def check_shape(
|
659
|
-
|
570
|
+
def check_shape(*args)
|
571
|
+
_shape = shape
|
572
|
+
args.each do |arg|
|
573
|
+
_arg_shape = arg.shape
|
574
|
+
if _shape.size < _arg_shape.size
|
575
|
+
raise "#{arg.inspect} has #{arg.dimension} dimension(s) " +
|
576
|
+
"but should not have more than #{dimension}"
|
577
|
+
end
|
578
|
+
if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer }
|
579
|
+
if _shape.last( _arg_shape.size ) != _arg_shape
|
580
|
+
raise "#{arg.inspect} has shape #{arg.shape.inspect} " +
|
581
|
+
"(does not match last value(s) of #{shape.inspect})"
|
582
|
+
end
|
583
|
+
end
|
584
|
+
end
|
660
585
|
end
|
661
586
|
|
662
|
-
|
663
587
|
# Assign value to array element(s)
|
664
588
|
#
|
665
589
|
# @overload []=( *indices, value )
|
@@ -670,13 +594,13 @@ module Hornetseye
|
|
670
594
|
# @return [Object,Node] Returns the value.
|
671
595
|
def []=( *indices )
|
672
596
|
value = indices.pop
|
673
|
-
value = typecode.new value unless value.
|
597
|
+
value = typecode.new value unless value.matched?
|
674
598
|
if indices.empty?
|
675
599
|
check_shape value
|
676
600
|
unless compilable? and value.compilable? and dimension > 0
|
677
|
-
Store.new(
|
601
|
+
Store.new(self, value.sexp).demand
|
678
602
|
else
|
679
|
-
GCCFunction.run Store.new(
|
603
|
+
GCCFunction.run Store.new(self, value.sexp)
|
680
604
|
end
|
681
605
|
value
|
682
606
|
else
|
@@ -685,7 +609,7 @@ module Hornetseye
|
|
685
609
|
else
|
686
610
|
view = element indices.last
|
687
611
|
end
|
688
|
-
view[
|
612
|
+
view[*indices[0 ... -1]] = value
|
689
613
|
end
|
690
614
|
end
|
691
615
|
|
@@ -732,14 +656,16 @@ module Hornetseye
|
|
732
656
|
def force
|
733
657
|
if finalised?
|
734
658
|
get
|
735
|
-
elsif (
|
659
|
+
elsif (dimension > 0 and Thread.current[:lazy]) or not variables.empty?
|
736
660
|
self
|
737
661
|
elsif compilable?
|
738
|
-
retval =
|
739
|
-
GCCFunction.run Store.new(
|
662
|
+
retval = allocate
|
663
|
+
GCCFunction.run Store.new(retval.sexp, self)
|
740
664
|
retval.demand.get
|
741
665
|
else
|
742
|
-
|
666
|
+
retval = allocate
|
667
|
+
Store.new(retval.sexp, self).demand
|
668
|
+
retval.demand.get
|
743
669
|
end
|
744
670
|
end
|
745
671
|
|
@@ -756,16 +682,16 @@ module Hornetseye
|
|
756
682
|
|
757
683
|
# Coerce with other object
|
758
684
|
#
|
759
|
-
# @param [
|
685
|
+
# @param [Object] other Other object.
|
760
686
|
#
|
761
687
|
# @return [Array<Node>] Result of coercion.
|
762
688
|
#
|
763
689
|
# @private
|
764
|
-
def coerce(
|
765
|
-
if other.
|
766
|
-
return other, self
|
690
|
+
def coerce(other)
|
691
|
+
if other.matched?
|
692
|
+
return other.sexp, self
|
767
693
|
else
|
768
|
-
return Node.match(
|
694
|
+
return Node.match(other, self).new(other), self
|
769
695
|
end
|
770
696
|
end
|
771
697
|
|