multiarray 0.23.2 → 0.24.0
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 +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
|