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 CHANGED
@@ -6,7 +6,7 @@ require 'rake/packagetask'
6
6
  require 'rbconfig'
7
7
 
8
8
  PKG_NAME = 'multiarray'
9
- PKG_VERSION = '0.23.2'
9
+ PKG_VERSION = '0.24.0'
10
10
  RB_FILES = FileList[ 'lib/**/*.rb' ]
11
11
  TC_FILES = FileList[ 'test/tc_*.rb' ]
12
12
  TS_FILES = FileList[ 'test/ts_*.rb' ]
@@ -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.sexp
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
- end
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
+
@@ -47,10 +47,6 @@ module Hornetseye
47
47
  dest, source, default, zero, labels, rank, n
48
48
  end
49
49
 
50
- def sexp?
51
- true
52
- end
53
-
54
50
  # Get unique descriptor of this object
55
51
  #
56
52
  # @param [Hash] hash Labels for any variables.
@@ -53,10 +53,6 @@ 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
-
60
56
  # Get unique descriptor of this object
61
57
  #
62
58
  # @param [Hash] hash Labels for any variables.
@@ -74,10 +74,6 @@ module Hornetseye
74
74
  check_shape *values
75
75
  end
76
76
 
77
- def sexp?
78
- true
79
- end
80
-
81
77
  # Get unique descriptor of this object
82
78
  #
83
79
  # @param [Hash] hash Labels for any variables.
@@ -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.sexp, n).demand
154
+ Random.new(retval, n).demand
155
155
  else
156
- GCCFunction.run Random.new(retval.sexp, n)
156
+ GCCFunction.run Random.new(retval, n)
157
157
  end
158
158
  retval
159
159
  end
@@ -44,10 +44,6 @@ module Hornetseye
44
44
  @dest, @weight, @sources = dest, weight, sources
45
45
  end
46
46
 
47
- def sexp?
48
- true
49
- end
50
-
51
47
  # Get unique descriptor of this object
52
48
  #
53
49
  # @param [Hash] hash Labels for any variables.
@@ -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( @var1 => retval, @var2 => sub )
94
+ retval.assign @block.subst(@var1 => retval, @var2 => sub)
99
95
  end
100
96
  retval
101
97
  end
@@ -43,10 +43,6 @@ module Hornetseye
43
43
  @dest, @source = dest, source
44
44
  end
45
45
 
46
- def sexp?
47
- true
48
- end
49
-
50
46
  # Get unique descriptor of this object
51
47
  #
52
48
  # @param [Hash] hash Labels for any variables.
@@ -31,10 +31,6 @@ module Hornetseye
31
31
  @term = term
32
32
  end
33
33
 
34
- def sexp?
35
- true
36
- end
37
-
38
34
  # Get storage object if there is any
39
35
  #
40
36
  # @return [Malloc,List,NilClass] Object storing the data.
@@ -29,10 +29,6 @@ module Hornetseye
29
29
  @p, @index, @stride = p, index, stride
30
30
  end
31
31
 
32
- def sexp?
33
- true
34
- end
35
-
36
32
  # Get storage object if there is any
37
33
  #
38
34
  # @return [Malloc,List,NilClass] Object storing the data.
@@ -44,10 +44,6 @@ module Hornetseye
44
44
  @sources, @table = args[ 0 ... -1 ], args.last
45
45
  end
46
46
 
47
- def sexp?
48
- true
49
- end
50
-
51
47
  # Get unique descriptor of this object
52
48
  #
53
49
  # @param [Hash] hash Labels for any variables.
@@ -45,10 +45,6 @@ module Hornetseye
45
45
  @dest, @source, @m, @index = dest, source, m, index
46
46
  end
47
47
 
48
- def sexp?
49
- true
50
- end
51
-
52
48
  # Get unique descriptor of this object
53
49
  #
54
50
  # @param [Hash] hash Labels for any variables.
@@ -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.sexp).force
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.sexp, b.sexp).force
105
+ new(a, b).force
106
106
  end
107
107
  else
108
108
  send "#{op}_without_hornetseye", a, b
@@ -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.sexp).demand
601
+ Store.new(self, value).demand
602
602
  else
603
- GCCFunction.run Store.new(self, value.sexp)
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.sexp, self)
663
+ GCCFunction.run Store.new(retval, self)
664
664
  retval.demand.get
665
665
  else
666
666
  retval = allocate
667
- Store.new(retval.sexp, self).demand
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.sexp, self
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(sexp, other.sexp).force
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.sexp, b.sexp).force
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( var1 => initial, var2 => self ).simplify
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.sexp) { |a,b| a * b }.diagonal { |s,x| s + x }
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.sexp, self
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.sexp, self, default.sexp, target.new(0),
754
- labels.sexp, rank.sexp, n
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.sexp, self, m.sexp, index
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.sexp, self, m.sexp, index, default.sexp
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.sexp, weight.sexp, *self
958
+ block = Hornetseye::Histogram.new left, weight, *self
959
959
  if block.compilable?
960
960
  Hornetseye::GCCFunction.run block
961
961
  else
@@ -127,10 +127,6 @@ module Hornetseye
127
127
  @value = value
128
128
  end
129
129
 
130
- def sexp?
131
- true
132
- end
133
-
134
130
  # Get access to storage object
135
131
  #
136
132
  # @return [Malloc,List] The object used to store the data.
@@ -29,10 +29,6 @@ module Hornetseye
29
29
  @dest, @n = dest, n
30
30
  end
31
31
 
32
- def sexp?
33
- true
34
- end
35
-
36
32
  # Get unique descriptor of this object
37
33
  #
38
34
  # @param [Hash] hash Labels for any variables.
@@ -29,10 +29,6 @@ module Hornetseye
29
29
  @dest, @source = dest, source
30
30
  end
31
31
 
32
- def sexp?
33
- true
34
- end
35
-
36
32
  # Get unique descriptor of this object
37
33
  #
38
34
  # @param [Hash] hash Labels for any variables.
@@ -45,10 +45,6 @@ module Hornetseye
45
45
  @dest, @source, @m, @index, @default = dest, source, m, index, default
46
46
  end
47
47
 
48
- def sexp?
49
- true
50
- end
51
-
52
48
  # Get unique descriptor of this object
53
49
  #
54
50
  # @param [Hash] hash Labels for any variables.
@@ -38,10 +38,6 @@ module Hornetseye
38
38
  @meta = meta
39
39
  end
40
40
 
41
- def sexp?
42
- true
43
- end
44
-
45
41
  # Display string with information about this object
46
42
  #
47
43
  # @return [String] String with information about this object (e.g.
@@ -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
@@ -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.23.2
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-06-29 00:00:00 Z
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