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.
- 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
|
|