lib/numru/gphys/varraycomposite.rb in gphys-1.2.2.1 vs lib/numru/gphys/varraycomposite.rb in gphys-1.4.3

- old
+ new

@@ -75,47 +75,64 @@ raise ArgumentError, "argument must be a NArray of VArray (or nil)" end nvas = varrays.shape vrank = nvas.length - rank=0 varrays.each{|va| - if va.is_a?(VArray) + if !va.nil? @first_vary = va - @attr = @first_vary.attr + @attr = @first_vary.attr_copy @name = @first_vary.name - @rank = va.rank + @crank = va.rank # rank of the component VArrays break end } - if vrank > @rank - raise ArgumentError, "rank of varrays > rank of the VArray" - elsif vrank < @rank - (@rank - vrank).times{ - varrays = varrays.newdim(vrank) - nvas.push(1) - } - vrank = @rank + if vrank > @crank + @rank = vrank #=> @rank > @crank + else + @rank = @crank + if vrank < @crank + (@crank - vrank).times{ + varrays = varrays.newdim(vrank) + nvas.push(1) + } + vrank = @crank # rank of varrays is increased to @crank (==@rank) + end end + un0 = varrays[0].units + for i in 1...varrays.length + va = varrays[i] + varrays[i] = va.convert_units(un0) if va && va.units != un0 + end @bound_idx = Array.new # will be Array of Array for dim in 0...vrank @bound_idx[dim] = [0] # the frst element is always 0 for i in 0...nvas[dim] idx = [true]*dim + [i..i,false] set=false len=0 varrays[*idx].each{|va| if !set && va - if !va.is_a?(VArray) - raise ArgumentError,"Not a VArray: #{va.inspect}" - end - len = va.shape_current[dim] + ### commented out for the duck typing: + #if !va.is_a?(VArray) + # raise ArgumentError,"Not a VArray: #{va.inspect}" + #end + if dim < @crank + len = va.shape_current[dim] + else + len = 1 + end @bound_idx[dim][i+1] = @bound_idx[dim][i] + len set=true elsif va - if va.shape_current[dim] != len + if dim < @crank + lc = va.shape_current[dim] + else + lc = 1 + end + if lc != len raise ArgumentError,"Non-uniformity in the #{i}th element"+ " of the #{dim}th dimension (#{va.shape_current[dim]} for #{len})" end end } @@ -163,23 +180,32 @@ def val val = nil loop_multi_dim_index( @varrays.shape ){|index| vidx = Array.new for d in 0...@rank - vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1) + if d < @crank + vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1) + else + vidx[d] = @bound_idx[d][index[d]] + end end - v = @varrays[*index].val + units = @attr["units"] + if units + v = @varrays[*index].convert_units(units).val + else + v = @varrays[*index].val + end if !val if NArray===v val = NArray.new(v.typecode,*@shape) elsif NArrayMiss===v val = NArrayMiss.new(v.typecode,*@shape) else raise TypeError, "Unexpected type #{v.class}" end end - val[*vidx] = @varrays[*index].val + val[*vidx] = v } val end def val=(narray) @@ -188,11 +214,15 @@ sub = narray else __check_ary_class(narray) vidx = Array.new for d in 0...@rank - vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1) + if d < @crank + vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1) + else + vidx[d] = @bound_idx[d][index[d]] + end end sub=narray[*vidx] end @varrays[*index].val = sub } @@ -284,16 +314,16 @@ imask = Array.new isub = Array.new idx.each_with_index{ |ix, dim| size = @bound_idx[dim][-1] imask[dim] = Array.new - isub[dim] = Array.new + isub[dim] = Array.new if dim < @crank for j in 0...(@bound_idx[dim].length) match, isb = _imatch( size, ix, @bound_idx[dim][j..j+1] ) if match imask[dim].push(j) - isub[dim].push(isb) + isub[dim].push(isb) if dim < @crank end end } varrays = @varrays[ *imask ] loop_multi_dim_index( varrays.shape ){ |index| @@ -332,10 +362,15 @@ lst = index.exclude_end? ? index.last-1 : index.last lst += size if lst < 0 stp = 1 else # Hash range, stp = index.to_a[0] + if stp<=0 + raise(ArgumentError,"Currently only positive step is supported") + # development note: current handling of fst and lst assumes a + # positive step + end range = 0..-1 if range==true fst = range.first fst += size if fst < 0 lst = range.last lst += size if lst < 0 @@ -347,15 +382,32 @@ a = ( (fst >= first) ? fst-first : (fst - first).modulo(stp) ) b = ( (lst <= last) ? lst-first : last-first ) if stp==1 return [true, a..b ] else - return [true, {(a..b) => stp} ] + len = last-first+1 + if a<len + return [true, {(a..b) => stp} ] + else + return [false, nil] + end end else return [false, nil] end + when Array + match = false + isb = [] + index.each{ |idx| + idx += size if idx < 0 + if first <= idx && idx <= last + match = true + isb.push(idx-first) + end + } + isb = nil if isb == [] + return [match, isb] else raise "Unsupported type for indexing: #{index.class}" end end @@ -410,6 +462,37 @@ p va01.name vac.set_att('long_name', 'test data') p vac.get_att('long_name') p va01.get_att('long_name') p vac.typecode,vac.ntype + + puts "testing rank extension.." + va0 = VArray.new( NArray.float(3,2).indgen!, {"units"=>"m/s"}, 'V' ) + va1 = VArray.new( NArray.float(3,2).indgen!+100, {"units"=>"m/s"}, 'V' ) + va2 = VArray.new( NArray.float(3,2).indgen!+200, {"units"=>"m/s"}, 'V' ) + va3 = VArray.new( NArray.float(3,2).indgen!+300, {"units"=>"m/s"}, 'V' ) + varrays = NArray.to_na([ [[va0]], [[va1]], [[va2]], [[va3]] ]) + vac = VArrayComposite.new(varrays) + p vac, vac.val + if vac[1,1,1].val == 104.0 + puts "test OK" + else + raise "test failed" + end + + v = vac[0..1,0,{1..-1=>2}].val + ans = NArray.to_na( [ [100.0,101.0], [300.0, 301.0] ] ) + if v==ans + puts "test OK" + else + raise "test failed" + end + + vac[-1,true,1..2] = -999.0 + if vac[-1,true,1..2].val.to_a.flatten.uniq == [-999.0 ] + puts "test OK" + else + raise "test failed" + end + #vac.val = NArray.float(3,2,4).random! + #p vac.val end