multiarray 0.23.2 → 0.24.0
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 +49 -10
- data/lib/multiarray/argument.rb +95 -0
- data/lib/multiarray/components.rb +0 -4
- data/lib/multiarray/diagonal.rb +0 -4
- data/lib/multiarray/elementwise.rb +0 -4
- data/lib/multiarray/field.rb +2 -2
- data/lib/multiarray/histogram.rb +0 -4
- data/lib/multiarray/inject.rb +1 -5
- data/lib/multiarray/integral.rb +0 -4
- data/lib/multiarray/lambda.rb +0 -4
- data/lib/multiarray/lookup.rb +0 -4
- data/lib/multiarray/lut.rb +0 -4
- data/lib/multiarray/mask.rb +0 -4
- data/lib/multiarray/methods.rb +2 -2
- data/lib/multiarray/node.rb +5 -5
- data/lib/multiarray/operations.rb +10 -10
- data/lib/multiarray/pointer.rb +0 -4
- data/lib/multiarray/random.rb +0 -4
- data/lib/multiarray/store.rb +0 -4
- data/lib/multiarray/unmask.rb +0 -4
- data/lib/multiarray/variable.rb +0 -4
- data/test/tc_multiarray.rb +20 -0
- data/test/tc_sequence.rb +24 -0
- metadata +3 -2
data/Rakefile
CHANGED
data/lib/multiarray.rb
CHANGED
@@ -98,14 +98,6 @@ class Object
|
|
98
98
|
|
99
99
|
end
|
100
100
|
|
101
|
-
def sexp
|
102
|
-
self
|
103
|
-
end
|
104
|
-
|
105
|
-
def sexp?
|
106
|
-
false
|
107
|
-
end
|
108
|
-
|
109
101
|
def matched?
|
110
102
|
false
|
111
103
|
end
|
@@ -741,6 +733,7 @@ require 'multiarray/lookup'
|
|
741
733
|
require 'multiarray/elementwise'
|
742
734
|
require 'multiarray/inject'
|
743
735
|
require 'multiarray/diagonal'
|
736
|
+
require 'multiarray/argument'
|
744
737
|
require 'multiarray/histogram'
|
745
738
|
require 'multiarray/lut'
|
746
739
|
require 'multiarray/integral'
|
@@ -786,7 +779,7 @@ module Hornetseye
|
|
786
779
|
action.call *( args + [ index ] )
|
787
780
|
end
|
788
781
|
term = Node.match(term).new term unless term.matched?
|
789
|
-
Lambda.new index, term
|
782
|
+
Lambda.new index, term
|
790
783
|
end
|
791
784
|
ensure
|
792
785
|
Thread.current[ :lazy ] = previous
|
@@ -842,5 +835,51 @@ module Hornetseye
|
|
842
835
|
|
843
836
|
module_function :sum
|
844
837
|
|
845
|
-
|
838
|
+
def argument(block, options = {}, &action)
|
839
|
+
arity = options[:arity] || action.arity
|
840
|
+
if arity > 0
|
841
|
+
indices = options[:indices] ||
|
842
|
+
(0 ... arity).collect { Variable.new Hornetseye::INDEX(nil) }
|
843
|
+
term = options[:term] || action.call(*indices)
|
844
|
+
slices = indices[0 ... -1].inject(term) { |t,index| Lambda.new index, t }
|
845
|
+
var1 = options[:var1] || Variable.new(term.typecode)
|
846
|
+
var2 = options[:var2] || Variable.new(term.typecode)
|
847
|
+
block = options[:block] || block.call( var1, var2 )
|
848
|
+
lut = Argument.new(slices, indices.last, block, var1, var2, INT.new(0)).force
|
849
|
+
arr = options[:arr] || Lambda.new(indices.last, slices)
|
850
|
+
id = (0 ... arr.dimension - 1).collect { |j| lazy(*arr.shape[0 ... -1]) { |*i| i[j] } }
|
851
|
+
lut = INT.new(lut) unless lut.matched?
|
852
|
+
sub_arr = Lut.new(*(id + [lut] + [arr])).force
|
853
|
+
indices = (0 ... arity - 1).collect { Variable.new Hornetseye::INDEX(nil) }
|
854
|
+
term = indices.reverse.inject(sub_arr) { |t,index| t.element index }
|
855
|
+
sub_arg = argument nil, :arity => arity - 1, :indices => indices, :term => term,
|
856
|
+
:arr => sub_arr, :block => block, :var1 => var1, :var2 => var2
|
857
|
+
if sub_arg.empty?
|
858
|
+
[lut[]]
|
859
|
+
elsif sub_arg.first.is_a? Integer
|
860
|
+
sub_arg + [lut[*sub_arg]]
|
861
|
+
else
|
862
|
+
id = lazy(*sub_arg.first.shape) { |*i| i.last }
|
863
|
+
sub_arg + [lut.warp(*(sub_arg + [id]))]
|
864
|
+
end
|
865
|
+
else
|
866
|
+
[]
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
870
|
+
module_function :argument
|
871
|
+
|
872
|
+
def argmax(&action)
|
873
|
+
argument proc { |a,b| a > b }, &action
|
874
|
+
end
|
875
|
+
|
876
|
+
module_function :argmax
|
846
877
|
|
878
|
+
def argmin(&action)
|
879
|
+
argument proc { |a,b| a < b }, &action
|
880
|
+
end
|
881
|
+
|
882
|
+
module_function :argmin
|
883
|
+
|
884
|
+
end
|
885
|
+
|
@@ -0,0 +1,95 @@
|
|
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 Argument < Node
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def finalised?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(value, index, block, var1, var2, zero)
|
31
|
+
@value, @index, @block, @var1, @var2, @zero = value, index, block, var1, var2, zero
|
32
|
+
end
|
33
|
+
|
34
|
+
def descriptor(hash)
|
35
|
+
hash = hash.merge @index => ((hash.values.max || 0) + 1)
|
36
|
+
hash = hash.merge @var1 => ((hash.values.max || 0) + 1)
|
37
|
+
hash = hash.merge @var2 => ((hash.values.max || 0) + 1)
|
38
|
+
"Argument(#{@value.descriptor(hash)},#{@index.descriptor(hash)}," +
|
39
|
+
"#{@block.descriptor(hash)},#{@zero.descriptor(hash)})"
|
40
|
+
end
|
41
|
+
|
42
|
+
def typecode
|
43
|
+
INT
|
44
|
+
end
|
45
|
+
|
46
|
+
def shape
|
47
|
+
@value.shape
|
48
|
+
end
|
49
|
+
|
50
|
+
def demand
|
51
|
+
initial = @value.subst(@index => INT.new(0)).simplify
|
52
|
+
retval = @zero.simplify
|
53
|
+
INT.new(0).upto @index.size - 1 do |i|
|
54
|
+
sub = @value.subst @index => INT.new(i)
|
55
|
+
cond = @block.subst @var1 => sub, @var2 => initial
|
56
|
+
retval.assign cond.conditional(INT.new(i), retval)
|
57
|
+
initial.assign cond.conditional(sub, initial)
|
58
|
+
end
|
59
|
+
retval
|
60
|
+
end
|
61
|
+
|
62
|
+
def element(i)
|
63
|
+
self.class.new @value.element(i), @index, @block, @var1, @var2, @zero
|
64
|
+
end
|
65
|
+
|
66
|
+
def variables
|
67
|
+
@value.variables + @zero.variables - @index.variables
|
68
|
+
end
|
69
|
+
|
70
|
+
def strip
|
71
|
+
meta_vars, meta_values, var = @index.strip
|
72
|
+
vars, values, term = @value.subst(@index => var).strip
|
73
|
+
block_vars, block_values, block_term = @block.strip
|
74
|
+
zero_vars, zero_values, zero_term = @zero.strip
|
75
|
+
return vars + meta_vars + block_vars + zero_vars,
|
76
|
+
values + meta_values + block_values + zero_values,
|
77
|
+
self.class.new(term, var, block_term, @var1, @var2, zero_term)
|
78
|
+
end
|
79
|
+
|
80
|
+
def subst(hash)
|
81
|
+
subst_var = @index.subst hash
|
82
|
+
value = @value.subst(@index => subst_var).subst hash
|
83
|
+
block = @block.subst hash
|
84
|
+
zero = @zero.subst hash
|
85
|
+
self.class.new value, subst_var, block, @var1, @var2, zero
|
86
|
+
end
|
87
|
+
|
88
|
+
def compilable?
|
89
|
+
@value.compilable? and @block.compilable? and @zero.compilable?
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
data/lib/multiarray/diagonal.rb
CHANGED
data/lib/multiarray/field.rb
CHANGED
@@ -151,9 +151,9 @@ module Hornetseye
|
|
151
151
|
n = typecode.maxint.new n unless n.matched?
|
152
152
|
retval = new *shape
|
153
153
|
unless compilable? and dimension > 0
|
154
|
-
Random.new(retval
|
154
|
+
Random.new(retval, n).demand
|
155
155
|
else
|
156
|
-
GCCFunction.run Random.new(retval
|
156
|
+
GCCFunction.run Random.new(retval, n)
|
157
157
|
end
|
158
158
|
retval
|
159
159
|
end
|
data/lib/multiarray/histogram.rb
CHANGED
data/lib/multiarray/inject.rb
CHANGED
@@ -50,10 +50,6 @@ module Hornetseye
|
|
50
50
|
value, index, initial, block, var1, var2
|
51
51
|
end
|
52
52
|
|
53
|
-
def sexp?
|
54
|
-
true
|
55
|
-
end
|
56
|
-
|
57
53
|
# Get unique descriptor of this object
|
58
54
|
#
|
59
55
|
# @param [Hash] hash Labels for any variables.
|
@@ -95,7 +91,7 @@ module Hornetseye
|
|
95
91
|
end
|
96
92
|
offset.upto @index.size - 1 do |i|
|
97
93
|
sub = @value.subst @index => INT.new( i )
|
98
|
-
retval.assign @block.subst(
|
94
|
+
retval.assign @block.subst(@var1 => retval, @var2 => sub)
|
99
95
|
end
|
100
96
|
retval
|
101
97
|
end
|
data/lib/multiarray/integral.rb
CHANGED
data/lib/multiarray/lambda.rb
CHANGED
data/lib/multiarray/lookup.rb
CHANGED
data/lib/multiarray/lut.rb
CHANGED
data/lib/multiarray/mask.rb
CHANGED
data/lib/multiarray/methods.rb
CHANGED
@@ -66,7 +66,7 @@ module Hornetseye
|
|
66
66
|
Hornetseye::ElementWise( proc { |x| mod.send op, x },
|
67
67
|
"#{mod}.#{op}",
|
68
68
|
proc { |x| x.send conversion } ).
|
69
|
-
new(a
|
69
|
+
new(a).force
|
70
70
|
end
|
71
71
|
else
|
72
72
|
send "#{op}_without_hornetseye", a
|
@@ -102,7 +102,7 @@ module Hornetseye
|
|
102
102
|
Hornetseye::ElementWise( proc { |x,y| mod.send op, x, y },
|
103
103
|
"#{mod}.#{op}",
|
104
104
|
proc { |t,u| t.send coercion, u } ).
|
105
|
-
new(a
|
105
|
+
new(a, b).force
|
106
106
|
end
|
107
107
|
else
|
108
108
|
send "#{op}_without_hornetseye", a, b
|
data/lib/multiarray/node.rb
CHANGED
@@ -598,9 +598,9 @@ module Hornetseye
|
|
598
598
|
if indices.empty?
|
599
599
|
check_shape value
|
600
600
|
unless compilable? and value.compilable? and dimension > 0
|
601
|
-
Store.new(self, value
|
601
|
+
Store.new(self, value).demand
|
602
602
|
else
|
603
|
-
GCCFunction.run Store.new(self, value
|
603
|
+
GCCFunction.run Store.new(self, value)
|
604
604
|
end
|
605
605
|
value
|
606
606
|
else
|
@@ -660,11 +660,11 @@ module Hornetseye
|
|
660
660
|
self
|
661
661
|
elsif compilable?
|
662
662
|
retval = allocate
|
663
|
-
GCCFunction.run Store.new(retval
|
663
|
+
GCCFunction.run Store.new(retval, self)
|
664
664
|
retval.demand.get
|
665
665
|
else
|
666
666
|
retval = allocate
|
667
|
-
Store.new(retval
|
667
|
+
Store.new(retval, self).demand
|
668
668
|
retval.demand.get
|
669
669
|
end
|
670
670
|
end
|
@@ -689,7 +689,7 @@ module Hornetseye
|
|
689
689
|
# @private
|
690
690
|
def coerce(other)
|
691
691
|
if other.matched?
|
692
|
-
return other
|
692
|
+
return other, self
|
693
693
|
else
|
694
694
|
return Node.match(other, self).new(other), self
|
695
695
|
end
|
@@ -63,7 +63,7 @@ module Hornetseye
|
|
63
63
|
else
|
64
64
|
Hornetseye::ElementWise(proc { |x,y| x.send op, y }, op,
|
65
65
|
proc { |t,u| t.send coercion, u } ).
|
66
|
-
new(
|
66
|
+
new(self, other).force
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -221,7 +221,7 @@ module Hornetseye
|
|
221
221
|
else
|
222
222
|
Hornetseye::ElementWise(proc { |x,y,z| x.conditional y, z }, :conditional,
|
223
223
|
proc { |t,u,v| t.cond u, v }).
|
224
|
-
new(self, a
|
224
|
+
new(self, a, b).force
|
225
225
|
end
|
226
226
|
end
|
227
227
|
|
@@ -368,7 +368,7 @@ module Hornetseye
|
|
368
368
|
block = options[ :block ] || action.call( var1, var2 )
|
369
369
|
if dimension == 0
|
370
370
|
if initial
|
371
|
-
block.subst(
|
371
|
+
block.subst(var1 => initial, var2 => self).simplify
|
372
372
|
else
|
373
373
|
demand
|
374
374
|
end
|
@@ -577,7 +577,7 @@ module Hornetseye
|
|
577
577
|
filter = Node.match( filter, typecode ).new filter unless filter.matched?
|
578
578
|
array = self
|
579
579
|
(dimension - filter.dimension).times { array = array.roll }
|
580
|
-
array.table(filter
|
580
|
+
array.table(filter) { |a,b| a * b }.diagonal { |s,x| s + x }
|
581
581
|
end
|
582
582
|
|
583
583
|
# Erosion
|
@@ -723,7 +723,7 @@ module Hornetseye
|
|
723
723
|
# @return [Node] The integral image of this array.
|
724
724
|
def integral
|
725
725
|
left = allocate
|
726
|
-
block = Integral.new left
|
726
|
+
block = Integral.new left, self
|
727
727
|
if block.compilable?
|
728
728
|
GCCFunction.run block
|
729
729
|
else
|
@@ -750,8 +750,8 @@ module Hornetseye
|
|
750
750
|
labels = Sequence.new target, size; labels[0] = 0
|
751
751
|
rank = Sequence.uint size; rank[0] = 0
|
752
752
|
n = Hornetseye::Pointer( INT ).new; n.store INT.new( 0 )
|
753
|
-
block = Components.new left
|
754
|
-
labels
|
753
|
+
block = Components.new left, self, default, target.new(0),
|
754
|
+
labels, rank, n
|
755
755
|
if block.compilable?
|
756
756
|
Hornetseye::GCCFunction.run block
|
757
757
|
else
|
@@ -773,7 +773,7 @@ module Hornetseye
|
|
773
773
|
[ m.size ] )
|
774
774
|
index = Hornetseye::Pointer( INT ).new
|
775
775
|
index.store INT.new( 0 )
|
776
|
-
block = Mask.new left
|
776
|
+
block = Mask.new left, self, m, index
|
777
777
|
if block.compilable?
|
778
778
|
GCCFunction.run block
|
779
779
|
else
|
@@ -806,7 +806,7 @@ module Hornetseye
|
|
806
806
|
coercion(default.typecode).new *(shape[1 .. -1] + m.shape)
|
807
807
|
index = Hornetseye::Pointer(INT).new
|
808
808
|
index.store INT.new(0)
|
809
|
-
block = Unmask.new left
|
809
|
+
block = Unmask.new left, self, m, index, default
|
810
810
|
if block.compilable?
|
811
811
|
GCCFunction.run block
|
812
812
|
else
|
@@ -955,7 +955,7 @@ class Array
|
|
955
955
|
end
|
956
956
|
left = Hornetseye::MultiArray(weight.typecode, ret_shape.size).new *ret_shape
|
957
957
|
left[] = 0
|
958
|
-
block = Hornetseye::Histogram.new left
|
958
|
+
block = Hornetseye::Histogram.new left, weight, *self
|
959
959
|
if block.compilable?
|
960
960
|
Hornetseye::GCCFunction.run block
|
961
961
|
else
|
data/lib/multiarray/pointer.rb
CHANGED
data/lib/multiarray/random.rb
CHANGED
data/lib/multiarray/store.rb
CHANGED
data/lib/multiarray/unmask.rb
CHANGED
data/lib/multiarray/variable.rb
CHANGED
data/test/tc_multiarray.rb
CHANGED
@@ -52,6 +52,14 @@ class TC_MultiArray < Test::Unit::TestCase
|
|
52
52
|
Hornetseye::sum *args, &action
|
53
53
|
end
|
54
54
|
|
55
|
+
def argmin( *args, &action )
|
56
|
+
Hornetseye::argmin *args, &action
|
57
|
+
end
|
58
|
+
|
59
|
+
def argmax( *args, &action )
|
60
|
+
Hornetseye::argmax *args, &action
|
61
|
+
end
|
62
|
+
|
55
63
|
def finalise( *args, &action )
|
56
64
|
Hornetseye::finalise *args, &action
|
57
65
|
end
|
@@ -361,6 +369,18 @@ class TC_MultiArray < Test::Unit::TestCase
|
|
361
369
|
assert_equal [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ], sum { || m }.to_a
|
362
370
|
end
|
363
371
|
|
372
|
+
def test_argmin
|
373
|
+
assert_equal [[0, 0, 1]],
|
374
|
+
argmin { |i| M[[1, 2, 3], [4, 3, 2]][i] }.collect { |x| x.to_a }
|
375
|
+
assert_equal [2, 1], argmin { |i,j| M[[1, 2, 3], [4, 3, 0]][i,j] }
|
376
|
+
m = M[[[1,0,3,4],[5,4,3,2],[1,2,1,0]],[[3,2,4,1],[7,4,8,2],[2,1,9,1]]]
|
377
|
+
assert_equal [[[0, 0, 0, 1], [0, 0, 0, 0], [0, 1, 0, 0]]],
|
378
|
+
argmin { |i| m[i] }.collect { |x| x.to_a }
|
379
|
+
assert_equal [[0, 0, 2, 2], [0, 0, 0, 0]],
|
380
|
+
argmin { |i,j| m[i,j] }.collect { |x| x.to_a }
|
381
|
+
assert_equal [1, 0, 0], argmin { |i,j,k| m[i,j,k] }
|
382
|
+
end
|
383
|
+
|
364
384
|
def test_min
|
365
385
|
assert_equal 1, M[ [ 5, 3, 7 ], [ 2, 1, 6 ] ].min
|
366
386
|
end
|
data/test/tc_sequence.rb
CHANGED
@@ -48,6 +48,14 @@ class TC_Sequence < Test::Unit::TestCase
|
|
48
48
|
Hornetseye::sum *args, &action
|
49
49
|
end
|
50
50
|
|
51
|
+
def argmin( *args, &action )
|
52
|
+
Hornetseye::argmin *args, &action
|
53
|
+
end
|
54
|
+
|
55
|
+
def argmax( *args, &action )
|
56
|
+
Hornetseye::argmax *args, &action
|
57
|
+
end
|
58
|
+
|
51
59
|
def setup
|
52
60
|
end
|
53
61
|
|
@@ -307,6 +315,22 @@ class TC_Sequence < Test::Unit::TestCase
|
|
307
315
|
assert_equal 384, sum { |i| S[ 128, 128, 128 ][i] }
|
308
316
|
end
|
309
317
|
|
318
|
+
def test_argmin
|
319
|
+
[S(O), S(I)].each do |t|
|
320
|
+
assert_equal [], argmin { t[1, 0, 2] }
|
321
|
+
assert_equal [], argmin { || t[1, 0, 2] }
|
322
|
+
assert_equal [1], argmin { |i| t[1, 0, 2][i] }
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_argmax
|
327
|
+
[S(O), S(I)].each do |t|
|
328
|
+
assert_equal [], argmax { t[1, 3, 2] }
|
329
|
+
assert_equal [], argmax { || t[1, 3, 2] }
|
330
|
+
assert_equal [1], argmax { |i| t[1, 3, 2][i] }
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
310
334
|
def test_min
|
311
335
|
[O, I].each do |t|
|
312
336
|
assert_equal 2, S(t)[4, 2, 3].min
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: multiarray
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.24.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jan Wedekind
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-07-01 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: malloc
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- lib/multiarray/pointer.rb
|
66
66
|
- lib/multiarray/element.rb
|
67
67
|
- lib/multiarray/composite.rb
|
68
|
+
- lib/multiarray/argument.rb
|
68
69
|
- lib/multiarray/lookup.rb
|
69
70
|
- lib/multiarray/sequence.rb
|
70
71
|
- lib/multiarray/gcctype.rb
|