multiarray 0.20.0 → 0.21.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.20.0'
9
+ PKG_VERSION = '0.21.0'
10
10
  RB_FILES = FileList[ 'lib/**/*.rb' ]
11
11
  TC_FILES = FileList[ 'test/tc_*.rb' ]
12
12
  TS_FILES = FileList[ 'test/ts_*.rb' ]
data/lib/multiarray.rb CHANGED
@@ -66,6 +66,18 @@ class Proc
66
66
 
67
67
  end
68
68
 
69
+ # An overloadable while loop
70
+ #
71
+ # @param [Proc] action The loop body
72
+ #
73
+ # @return [NilClass] Returns +nil+.
74
+ #
75
+ # @private
76
+ def while( &action )
77
+ action.call while call.get
78
+ nil
79
+ end
80
+
69
81
  end
70
82
 
71
83
  # +Object+ is extended with a few methods
@@ -698,6 +710,7 @@ require 'multiarray/lut'
698
710
  require 'multiarray/integral'
699
711
  require 'multiarray/mask'
700
712
  require 'multiarray/unmask'
713
+ require 'multiarray/components'
701
714
  require 'multiarray/operations'
702
715
  require 'multiarray/methods'
703
716
  require 'multiarray/rgb'
@@ -793,3 +806,4 @@ module Hornetseye
793
806
  module_function :sum
794
807
 
795
808
  end
809
+
@@ -98,7 +98,7 @@ module Hornetseye
98
98
  # @return [Object] Returns +value+.
99
99
  #
100
100
  # @private
101
- def store( value )
101
+ def assign( value )
102
102
  @real, @imag = value.real, value.imag
103
103
  end
104
104
 
@@ -862,8 +862,8 @@ module Hornetseye
862
862
  if Thread.current[ :function ]
863
863
  real = Thread.current[ :function ].variable self.class.element_type, 'v'
864
864
  imag = Thread.current[ :function ].variable self.class.element_type, 'v'
865
- real.store @value.real
866
- imag.store @value.imag
865
+ real.assign @value.real
866
+ imag.assign @value.imag
867
867
  self.class.new InternalComplex.new( real, imag )
868
868
  else
869
869
  self.class.new get
@@ -877,15 +877,15 @@ module Hornetseye
877
877
  # @return [Object] Returns +value+.
878
878
  #
879
879
  # @private
880
- def store( value )
880
+ def assign( value )
881
881
  value = value.simplify
882
- if @value.real.respond_to? :store
883
- @value.real.store value.get.real
882
+ if @value.real.respond_to? :assign
883
+ @value.real.assign value.get.real
884
884
  else
885
885
  @value.real = value.get.real
886
886
  end
887
- if @value.imag.respond_to? :store
888
- @value.imag.store value.get.imag
887
+ if @value.imag.respond_to? :assign
888
+ @value.imag.assign value.get.imag
889
889
  else
890
890
  @value.imag = value.get.imag
891
891
  end
@@ -0,0 +1,236 @@
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 for representing connected component analysis
21
+ class Components < Node
22
+
23
+ class << self
24
+
25
+ # Check whether objects of this class are finalised computations
26
+ #
27
+ # @return [Boolean] Returns +false+.
28
+ #
29
+ # @private
30
+ def finalised?
31
+ false
32
+ end
33
+
34
+ end
35
+
36
+ # Constructor
37
+ #
38
+ # @param [Node] dest Target array to write component labels to.
39
+ # @param [Node] source Array to extract components from.
40
+ # @param [Node] default Value of background pixel.
41
+ # @param [Node] zero Zero is used to aid compilation.
42
+ # @param [Node] labels Array to store label correspondences.
43
+ # @param [Node] rank Array to store number of indirections for each label.
44
+ # @param [Node] n Pointer to return number of components.
45
+ def initialize( dest, source, default, zero, labels, rank, n )
46
+ @dest, @source, @default, @zero, @labels, @rank, @n =
47
+ dest, source, default, zero, labels, rank, n
48
+ end
49
+
50
+ # Get unique descriptor of this object
51
+ #
52
+ # @param [Hash] hash Labels for any variables.
53
+ #
54
+ # @return [String] Descriptor of this object,
55
+ #
56
+ # @private
57
+ def descriptor( hash )
58
+ "Components(#{@dest.descriptor( hash )},#{@source.descriptor( hash )}," +
59
+ "#{@default.descriptor( hash )},#{@zero.descriptor( hash )}," +
60
+ "#{@labels.descriptor( hash )},#{@rank.descriptor( hash )}," +
61
+ "#{@n.descriptor( hash )})"
62
+ end
63
+
64
+ # Get type of result of delayed operation
65
+ #
66
+ # @return [Class] Type of result.
67
+ def array_type
68
+ retval = @dest.array_type
69
+ ( class << self; self; end ).instance_eval do
70
+ define_method( :array_type ) { retval }
71
+ end
72
+ retval
73
+ end
74
+
75
+ # Reevaluate computation
76
+ #
77
+ # @return [Node,Object] Result of computation
78
+ #
79
+ # @see #force
80
+ #
81
+ # @private
82
+ def demand
83
+ knot [], []
84
+ @dest
85
+ end
86
+
87
+ # Recursive function to perform connected component labelling
88
+ #
89
+ # @param [Array<Proc>] args Array with functions for locating neighbouring elements.
90
+ # @param [Array<Proc>] comp Array with functions for locating neighbouring labels.
91
+ #
92
+ # @private
93
+ def knot( args, comp )
94
+ n = @n.simplify
95
+ if dimension > 0
96
+ subargs1, subargs2, subargs3 = [], [], []
97
+ subcomp1, subcomp2, subcomp3 = [], [], []
98
+ args.each do |arg|
99
+ subargs1.push proc { |i| arg.element( i - 1 ).demand }
100
+ subargs2.push proc { |i| arg.element( i ).demand }
101
+ subargs3.push proc { |i| arg.element( i + 1 ).demand }
102
+ end
103
+ comp.each do |c|
104
+ subcomp1.push proc { |i| c.element( i - 1 ) }
105
+ subcomp2.push proc { |i| c.element( i ) }
106
+ subcomp3.push proc { |i| c.element( i + 1 ) }
107
+ end
108
+ self.class.new( @dest.element( INT.new( 0 ) ),
109
+ @source.element( INT.new( 0 ) ).demand, @default, @zero,
110
+ @labels, @rank, n ).
111
+ knot( ( subargs2 + subargs3 ).collect { |p| p.call INT.new( 0 ) },
112
+ ( subcomp2 + subcomp3 ).collect { |p| p.call INT.new( 0 ) } )
113
+ INT.new( 1 ).upto INT.new( @source.shape.last ) - 2 do |i|
114
+ self.class.new( @dest.element( INT.new( i ) ),
115
+ @source.element( INT.new( i ) ).demand, @default, @zero,
116
+ @labels, @rank, n ).
117
+ knot( ( subargs1 + subargs2 + subargs3 ).collect { |p| p.call INT.new( i ) } +
118
+ [ @source.element( INT.new( i ) - 1 ) ],
119
+ ( subcomp1 + subcomp2 + subcomp3 ).collect { |p| p.call INT.new( i ) } +
120
+ [ @dest.element( INT.new( i ) - 1 ) ] )
121
+ end
122
+ i = @source.shape.last - 1
123
+ self.class.new( @dest.element( INT.new( i ) ),
124
+ @source.element( INT.new( i ) ).demand, @default, @zero,
125
+ @labels, @rank, n ).
126
+ knot( ( subargs1 + subargs2 ).collect { |p| p.call INT.new( i ) } +
127
+ [ @source.element( INT.new( i ) - 1 ) ],
128
+ ( subcomp1 + subcomp2 ).collect { |p| p.call INT.new( i ) } +
129
+ [ @dest.element( INT.new( i ) - 1 ) ] )
130
+ else
131
+ @source.ne( @default ).if_else( proc do
132
+ label = @zero.simplify
133
+ args.zip( comp ).each do |arg,other|
134
+ @source.eq( arg ).if do
135
+ other = other.simplify
136
+ proc { other.ne( @labels.element( other ).demand ) }.while do
137
+ other.assign @labels.element( other ).demand
138
+ end
139
+ label.eq( @zero ).if_else( proc do
140
+ label.assign other
141
+ end, proc do
142
+ label.ne( other ).if do
143
+ ( @rank.element( label ).demand <= @rank.element( other ).demand ).if_else( proc do
144
+ @labels[ other ] = label
145
+ @rank.element( label ).demand.eq( @rank.element( other ).demand ).if do
146
+ @rank[ label ] = @rank.element( other ).demand + 1
147
+ end
148
+ end, proc do
149
+ @labels[ label ] = other
150
+ label.assign other
151
+ end )
152
+ end
153
+ end )
154
+ end
155
+ end
156
+ label.eq( @zero ).if do
157
+ n.assign n + 1
158
+ @labels[ n ] = n
159
+ @rank[ n ] = 0
160
+ label.assign n
161
+ end
162
+ @dest.store label
163
+ end, proc do
164
+ @dest.store INT.new( 0 )
165
+ end )
166
+ end
167
+ if @n.is_a? Pointer_
168
+ INT.new( 0 ).upto n do |i|
169
+ l = UINT.new( i ).simplify
170
+ proc { l.ne( @labels.element( l ).demand ) }.while do
171
+ l.assign @labels.element( l ).demand
172
+ end
173
+ @labels[ INT.new( i ) ] = l
174
+ end
175
+ @n.store n
176
+ else
177
+ @n.assign n
178
+ end
179
+ end
180
+
181
+ # Substitute variables
182
+ #
183
+ # Substitute the variables with the values given in the hash.
184
+ #
185
+ # @param [Hash] hash Substitutions to apply.
186
+ #
187
+ # @return [Node] Term with substitutions applied.
188
+ #
189
+ # @private
190
+ def subst( hash )
191
+ self.class.new @dest.subst( hash ), @source.subst( hash ), @default.subst( hash ),
192
+ @zero.subst( hash ), @labels.subst( hash ), @rank.subst( hash ), @n.subst( hash )
193
+ end
194
+
195
+ # Get variables contained in this term
196
+ #
197
+ # @return [Set] Returns list of variables.
198
+ #
199
+ # @private
200
+ def variables
201
+ @dest.variables + @source.variables + @default.variables + @zero.variables +
202
+ @labels.variables + @rank.variables + @n.variables
203
+ end
204
+
205
+ # Strip of all values
206
+ #
207
+ # Split up into variables, values, and a term where all values have been
208
+ # replaced with variables.
209
+ #
210
+ # @return [Array<Array,Node>] Returns an array of variables, an array of
211
+ # values, and the term based on variables.
212
+ #
213
+ # @private
214
+ def strip
215
+ stripped = [ @dest, @source, @default, @zero, @labels, @rank, @n ].
216
+ collect { |value| value.strip }
217
+ return stripped.inject( [] ) { |vars,elem| vars + elem[ 0 ] },
218
+ stripped.inject( [] ) { |values,elem| values + elem[ 1 ] },
219
+ self.class.new( *stripped.collect { |elem| elem[ 2 ] } )
220
+ end
221
+
222
+ # Get variables contained in this term
223
+ #
224
+ # @return [Set] Returns list of variables.
225
+ #
226
+ # @private
227
+ def compilable?
228
+ [ @dest, @source, @default, @zero, @labels, @rank, @n ].all? do |value|
229
+ value.compilable?
230
+ end
231
+ end
232
+
233
+ end
234
+
235
+ end
236
+
@@ -106,7 +106,7 @@ module Hornetseye
106
106
  j0.upto( ( @index2.size - 1 ).minor( @index0 + s1 ) ) do |j|
107
107
  i = @index0.get + s1.get - j
108
108
  sub = @value.subst @index1 => INT.new( i ), @index2 => INT.new( j )
109
- retval.store @block.subst( @var1 => retval, @var2 => sub )
109
+ retval.assign @block.subst( @var1 => retval, @var2 => sub )
110
110
  end
111
111
  retval
112
112
  end
@@ -93,7 +93,7 @@ module Hornetseye
93
93
  def dup
94
94
  if Thread.current[ :function ]
95
95
  value = Thread.current[ :function ].variable self.class, 'v'
96
- value.store get
96
+ value.assign get
97
97
  self.class.new value
98
98
  else
99
99
  self.class.new get
@@ -155,9 +155,9 @@ module Hornetseye
155
155
  # @return [Object] Returns +value+.
156
156
  #
157
157
  # @private
158
- def store( value )
159
- if @value.respond_to? :store
160
- @value.store value.simplify.get
158
+ def assign( value )
159
+ if @value.respond_to? :assign
160
+ @value.assign value.simplify.get
161
161
  else
162
162
  @value = value.simplify.get
163
163
  end
@@ -196,3 +196,32 @@ module Hornetseye
196
196
  end
197
197
 
198
198
  end
199
+
200
+ class Proc
201
+
202
+ # Overloaded while loop for handling compilation
203
+ #
204
+ # @param [Proc] action The loop body
205
+ #
206
+ # @return [NilClass] Returns +nil+.
207
+ #
208
+ # @private
209
+ def while_with_gcc( &action )
210
+ function = Thread.current[ :function ]
211
+ if function
212
+ function << "#{function.indent}while ( 1 ) {\n"
213
+ function.indent_offset +1
214
+ function << "#{function.indent}if ( !( #{call.get}) ) break;\n"
215
+ action.call
216
+ function.indent_offset -1
217
+ function << "#{function.indent}}\n"
218
+ nil
219
+ else
220
+ while_without_gcc &action
221
+ end
222
+ end
223
+
224
+ alias_method_chain :while, :gcc
225
+
226
+ end
227
+
@@ -163,7 +163,7 @@ module Hornetseye
163
163
  # @return [Object] Returns +value+.
164
164
  #
165
165
  # @private
166
- def store( value )
166
+ def assign( value )
167
167
  @function << "#{@function.indent}#{self} = #{value};\n"
168
168
  value
169
169
  end
@@ -370,7 +370,6 @@ module Hornetseye
370
370
  self
371
371
  end
372
372
 
373
-
374
373
  define_unary_op :not, '!'
375
374
  define_unary_op :~
376
375
  define_unary_op :-@, :-
@@ -96,7 +96,7 @@ module Hornetseye
96
96
  end
97
97
  offset.upto @index.size - 1 do |i|
98
98
  sub = @value.subst @index => INT.new( i )
99
- retval.store @block.subst( @var1 => retval, @var2 => sub )
99
+ retval.assign @block.subst( @var1 => retval, @var2 => sub )
100
100
  end
101
101
  retval
102
102
  end
@@ -109,7 +109,7 @@ module Hornetseye
109
109
  #
110
110
  # @private
111
111
  def element( i )
112
- Inject.new @value.element( i ), @index, @initial, @block, @var1, @var2
112
+ self.class.new @value.element( i ), @index, @initial, @block, @var1, @var2
113
113
  end
114
114
 
115
115
  # Get variables contained in this term
@@ -142,7 +142,7 @@ module Hornetseye
142
142
  vars3, values3, term3 = @block.strip
143
143
  return vars1 + vars2 + vars3 + meta_vars,
144
144
  values1 + values2 + values3 + meta_values,
145
- Inject.new( term1, var, term2, term3, @var1, @var2 )
145
+ self.class.new( term1, var, term2, term3, @var1, @var2 )
146
146
  end
147
147
 
148
148
  # Substitute variables
@@ -159,7 +159,7 @@ module Hornetseye
159
159
  value = @value.subst( @index => subst_var ).subst hash
160
160
  initial = @initial ? @initial.subst( hash ) : nil
161
161
  block = @block.subst hash
162
- Inject.new value, subst_var, initial, block, @var1, @var2
162
+ self.class.new value, subst_var, initial, block, @var1, @var2
163
163
  end
164
164
 
165
165
  # Check whether this term is compilable
@@ -81,12 +81,16 @@ module Hornetseye
81
81
  Mask.new( @dest, source, m, index ).demand
82
82
  end
83
83
  else
84
- @m.simplify.get.if do
84
+ @m.if do
85
85
  Store.new( @dest.element( index ), @source ).demand
86
- index.store index + 1
86
+ index.assign index + 1
87
87
  end
88
88
  end
89
- @index.store index
89
+ if @index.is_a? Pointer_
90
+ @index.store index
91
+ else
92
+ @index.assign index
93
+ end
90
94
  @dest
91
95
  else
92
96
  super
@@ -213,6 +213,34 @@ module Hornetseye
213
213
  end
214
214
  end
215
215
 
216
+ # Generate code for memory allocation
217
+ #
218
+ # @return [GCCValue] C value referring to result.
219
+ #
220
+ # @private
221
+ def malloc
222
+ get.malloc
223
+ end
224
+
225
+ # Conditional operation
226
+ #
227
+ # @param [Proc] action Action to perform if condition is +true+.
228
+ #
229
+ # @return [Object] The return value should be ignored.
230
+ def if( &action )
231
+ simplify.get.if &action
232
+ end
233
+
234
+ # Conditional operation
235
+ #
236
+ # @param [Proc] action1 Action to perform if condition is +true+.
237
+ # @param [Proc] action2 Action to perform if condition is +false+.
238
+ #
239
+ # @return [Object] The return value should be ignored.
240
+ def if_else( action1, action2 )
241
+ simplify.get.if_else action1, action2
242
+ end
243
+
216
244
  # Element-wise comparison of values
217
245
  #
218
246
  # @param [Node] other Array with values to compare with.
@@ -390,6 +418,13 @@ module Hornetseye
390
418
  min( initial ? initial.min : nil ) .. max( initial ? initial.max : nil )
391
419
  end
392
420
 
421
+ # Check values against boundaries
422
+ #
423
+ # @return [Node] Boolean array with result.
424
+ def between?( a, b )
425
+ Hornetseye::lazy { ( self >= a ).and self <= b }.force
426
+ end
427
+
393
428
  # Normalise values of array
394
429
  #
395
430
  # @param [Range] range Target range of normalisation.
@@ -621,12 +656,12 @@ module Hornetseye
621
656
  # @return [Node] The histogram.
622
657
  def histogram( *ret_shape )
623
658
  options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
624
- options = { :weight => UINT. new( 1 ), :safe => true }.merge options
659
+ options = { :weight => UINT.new( 1 ), :safe => true }.merge options
625
660
  unless options[ :weight ].is_a? Node
626
661
  options[ :weight ] =
627
662
  Node.match( options[ :weight ] ).maxint.new options[ :weight ]
628
663
  end
629
- if shape.first != 1 and ret_shape.size == 1
664
+ if ( shape.first != 1 or dimension == 1 ) and ret_shape.size == 1
630
665
  [ self ].histogram *( ret_shape + [ options ] )
631
666
  else
632
667
  ( 0 ... shape.first ).collect { |i| unroll[i] }.
@@ -642,7 +677,7 @@ module Hornetseye
642
677
  #
643
678
  # @return [Node] The result of the lookup operation.
644
679
  def lut( table, options = {} )
645
- if shape.first != 1 and table.dimension == 1
680
+ if ( shape.first != 1 or dimension == 1 ) and table.dimension == 1
646
681
  [ self ].lut table, options
647
682
  else
648
683
  ( 0 ... shape.first ).collect { |i| unroll[i] }.lut table, options
@@ -690,6 +725,35 @@ module Hornetseye
690
725
  left
691
726
  end
692
727
 
728
+ # Perform connected component labelling
729
+ #
730
+ # @option options [Object] :default (typecode.default) Value of background elements.
731
+ # @option options [Class] :target (UINT) Typecode of labels.
732
+ #
733
+ # @return [Node] Array with labels of connected components.
734
+ def components( options = {} )
735
+ if shape.any? { |x| x <= 1 }
736
+ raise "Every dimension must be greater than 1 (shape was #{shape})"
737
+ end
738
+ options = { :target => UINT, :default => typecode.default }.merge options
739
+ target = options[ :target ]
740
+ default = options[ :default ]
741
+ default = typecode.new default unless default.is_a? Node
742
+ left = Hornetseye::MultiArray( target, *shape ).new
743
+ labels = Sequence.new target, size; labels[0] = 0
744
+ rank = Sequence.uint size; rank[0] = 0
745
+ n = Hornetseye::Pointer( INT ).new; n.store INT.new( 0 )
746
+ block = Components.new left, self, default, target.new( 0 ), labels, rank, n
747
+ if block.compilable?
748
+ Hornetseye::GCCFunction.run block
749
+ else
750
+ block.demand
751
+ end
752
+ labels = labels[ 0 .. n.demand.get ]
753
+ left.lut labels.lut( labels.histogram( labels.size, :weight => target.new( 1 ) ).
754
+ minor( 1 ).integral - 1 )
755
+ end
756
+
693
757
  # Select values from array using a mask
694
758
  #
695
759
  # @param [Node] m Mask to apply to this array.
@@ -184,6 +184,22 @@ module Hornetseye
184
184
  "#{self.class.to_s}(#{@value.to_s})"
185
185
  end
186
186
 
187
+ # Store a value in this native element
188
+ #
189
+ # @param [Object] value New value for native element.
190
+ #
191
+ # @return [Object] Returns +value+.
192
+ #
193
+ # @private
194
+ def assign( value )
195
+ if @value.respond_to? :assign
196
+ @value.assign value.simplify.get
197
+ else
198
+ @value = value.simplify.get
199
+ end
200
+ value
201
+ end
202
+
187
203
  # Store new value in this pointer
188
204
  #
189
205
  # @param [Object] value New value for this pointer object.
@@ -125,7 +125,7 @@ module Hornetseye
125
125
  # @return [Object] Returns +value+.
126
126
  #
127
127
  # @private
128
- def store( value )
128
+ def assign( value )
129
129
  @r, @g, @b = value.r, value.g, value.b
130
130
  end
131
131
 
@@ -407,9 +407,9 @@ module Hornetseye
407
407
  r = Thread.current[ :function ].variable self.class.element_type, 'v'
408
408
  g = Thread.current[ :function ].variable self.class.element_type, 'v'
409
409
  b = Thread.current[ :function ].variable self.class.element_type, 'v'
410
- r.store @value.r
411
- g.store @value.g
412
- b.store @value.b
410
+ r.assign @value.r
411
+ g.assign @value.g
412
+ b.assign @value.b
413
413
  self.class.new RGB.new( r, g, b )
414
414
  else
415
415
  self.class.new get
@@ -423,20 +423,20 @@ module Hornetseye
423
423
  # @return [Object] Returns +value+.
424
424
  #
425
425
  # @private
426
- def store( value )
426
+ def assign( value )
427
427
  value = value.simplify
428
- if @value.r.respond_to? :store
429
- @value.r.store value.get.r
428
+ if @value.r.respond_to? :assign
429
+ @value.r.assign value.get.r
430
430
  else
431
431
  @value.r = value.get.r
432
432
  end
433
- if @value.g.respond_to? :store
434
- @value.g.store value.get.g
433
+ if @value.g.respond_to? :assign
434
+ @value.g.assign value.get.g
435
435
  else
436
436
  @value.g = value.get.g
437
437
  end
438
- if @value.b.respond_to? :store
439
- @value.b.store value.get.b
438
+ if @value.b.respond_to? :assign
439
+ @value.b.assign value.get.b
440
440
  else
441
441
  @value.b = value.get.b
442
442
  end
@@ -935,3 +935,19 @@ class Fixnum
935
935
 
936
936
  end
937
937
 
938
+ module Math
939
+
940
+ def sqrt_with_rgb( c )
941
+ if c.is_a? Hornetseye::RGB
942
+ Hornetseye::RGB.new sqrt( c.r ), sqrt( c.g ), sqrt( c.b )
943
+ else
944
+ sqrt_without_rgb c
945
+ end
946
+ end
947
+
948
+ alias_method_chain :sqrt, :rgb
949
+ module_function :sqrt_without_rgb
950
+ module_function :sqrt
951
+
952
+ end
953
+
@@ -65,8 +65,10 @@ module Hornetseye
65
65
  @source.element( INT.new( i ) )
66
66
  Store.new( dest, source ).demand
67
67
  end
68
- else
68
+ elsif @dest.class < Pointer_
69
69
  @dest.store @source.demand
70
+ else
71
+ @dest.assign @source.demand
70
72
  end
71
73
  @dest
72
74
  else
@@ -84,14 +84,18 @@ module Hornetseye
84
84
  Unmask.new( dest, @source, m, index, default ).demand
85
85
  end
86
86
  else
87
- @m.simplify.get.if_else( proc do
87
+ @m.if_else( proc do
88
88
  Store.new( @dest, @source.element( index ) ).demand
89
- index.store index + 1
89
+ index.assign index + 1
90
90
  end, proc do
91
91
  Store.new( @dest, @default ).demand
92
92
  end )
93
93
  end
94
- @index.store index
94
+ if @index.is_a? Pointer_
95
+ @index.store index
96
+ else
97
+ @index.assign index
98
+ end
95
99
  @dest
96
100
  else
97
101
  super
@@ -731,6 +731,11 @@ class TC_MultiArray < Test::Unit::TestCase
731
731
  M( I, 3, 2 )[ [ 1, 2, 3 ], [ 4, 5, 6 ] ].integral
732
732
  end
733
733
 
734
+ def test_components
735
+ assert_equal [ [ 1, 0, 2 ], [ 0, 0, 2 ], [ 2, 2, 2 ] ],
736
+ M[ [ 1, 0, 1 ], [ 0, 0, 1 ], [ 1, 1, 1 ] ].components.to_a
737
+ end
738
+
734
739
  def test_mask
735
740
  [ O, I ].each do |t|
736
741
  assert_equal M( O, 2, 2 )[ [ 1, 2 ], [ 5, 7 ] ],
data/test/tc_sequence.rb CHANGED
@@ -334,6 +334,10 @@ class TC_Sequence < Test::Unit::TestCase
334
334
  assert_equal C( 3, 2, 3 ), S[ C( 1, 2, 3 ), C( 3, 2, 1 ) ].max
335
335
  end
336
336
 
337
+ def test_between
338
+ assert_equal S[ false, true, true, false ], S[ 1, 2, 3, 4 ].between?( 2, 3 )
339
+ end
340
+
337
341
  def test_normalise
338
342
  assert_equal [ 0.0, 85.0, 255.0 ], S[ 1, 2, 4 ].normalise.to_a
339
343
  assert_equal [ C( 0.0, 85.0, 255.0 ) ], S[ C( 1, 2, 4 ) ].normalise.to_a
@@ -713,6 +717,12 @@ class TC_Sequence < Test::Unit::TestCase
713
717
  assert_in_delta x.real, y.real, 1.0e-5
714
718
  assert_in_delta x.imag, y.imag, 1.0e-5
715
719
  end
720
+ [ Math.sqrt( C( 1, 2, 3 ) ), Math.sqrt( C( 2, 4, 6 ) ) ].
721
+ zip( Math.sqrt( S[ C( 1, 2, 3 ), C( 2, 4, 6 ) ] ).to_a ).each do |x,y|
722
+ assert_in_delta x.r, y.r, 1.0e-5
723
+ assert_in_delta x.g, y.g, 1.0e-5
724
+ assert_in_delta x.b, y.b, 1.0e-5
725
+ end
716
726
  end
717
727
 
718
728
  def test_exp
@@ -928,6 +938,11 @@ class TC_Sequence < Test::Unit::TestCase
928
938
  assert_equal S( I, 3 )[ 1, 3, 6 ], S( I, 3 )[ 1, 2, 3 ].integral
929
939
  end
930
940
 
941
+ def test_components
942
+ assert_equal [ 0, 1, 1, 0, 2 ], S[ 0, 1, 1, 0, 1 ].components.to_a
943
+ assert_equal [ 0, 1, 1, 0, 2 ], S[ nil, 1, 1, nil, 1 ].components.to_a
944
+ end
945
+
931
946
  def test_mask
932
947
  assert_equal S( O, 2 )[ 2, 5 ], S( O, 3 )[ 2, 3, 5 ].
933
948
  mask( S[ true, false, true ] )
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 20
7
+ - 21
8
8
  - 0
9
- version: 0.20.0
9
+ version: 0.21.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jan Wedekind
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-26 00:00:00 +00:00
17
+ date: 2011-02-27 00:00:00 +00:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -66,6 +66,7 @@ files:
66
66
  - lib/multiarray/gcccontext.rb
67
67
  - lib/multiarray/unmask.rb
68
68
  - lib/multiarray/elementwise.rb
69
+ - lib/multiarray/components.rb
69
70
  - lib/multiarray/diagonal.rb
70
71
  - lib/multiarray/index.rb
71
72
  - lib/multiarray/variable.rb