multiarray 0.20.0 → 0.21.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.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