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