lib/utils.rb in xrvg-0.0.3 vs lib/utils.rb in xrvg-0.0.4

- old
+ new

@@ -9,11 +9,10 @@ # - +Array+ extension require 'enumerator' require 'trace' require 'samplation' -require 'assertion' # # Extend class Range with module Samplable and other utilitary methods # = Intro # Range class is used in XRVG as a continuous 1D float interval. @@ -46,25 +45,52 @@ # (0.0..2.0*Math::PI) def Range.Angle return Range::Angle.clone end + # return symetric angle between 0 and of size .. 2*size + # (-size..size) + def Range.sym( size ) + size = size > 0.0 ? size : -size + return (-size..size) + end # compute the symetric of value in context of range # (0.0..1.0).complement( 0.3 ) => 0.7 # (1.0..2.0).complement( 1.3 ) => 1.7 def complement( value ) diff = value - self.begin return (self.end - diff) end + # utilitary method to force value to be in range + # (0.0..1.0).trim( 3.0 ) => 1.0 + # (0.0..1.0).trim( -3.0 ) => 0.0 + def trim( value ) + if value > self.max + value = self.max + elsif value < self.min + value = self.min + end + return value + end + # return max value of range + def max + return (self.begin > self.end) ? self.begin : self.end + end + + # return min value of range + def min + return (self.begin < self.end) ? self.begin : self.end + end + # ------------------------------------------------------------- # Samplable interface include and overriding # ------------------------------------------------------------- - include Samplable - include Splittable + include XRVG::Samplable + include XRVG::Splittable # Range base FloatFunctor overloading to do # (1.0..2.0).sample( 0.3 ) => 1.3 # (1.0..2.0).samples( 3 ) => [1.0, 1.5, 2.0] def transform( value ) @@ -129,18 +155,72 @@ end # inverse function of .sample # (1.0..2.0).abscissa( 0.3 ) => 1.3 def abscissa( value ) - return (value - self.begin) / (self.end - self.begin) + if self.begin == self.end + return self.begin + else + return (value - self.begin) / (self.end - self.begin) + end end # return a new range with boundaries translated of "value" # (1.0..2.0).translate( -1.0 ) => (0.0..1.0) def translate( value ) return (self.begin + value..self.end + value) end + + +# ------------------------------------------------------------- +# old methods to be refactored +# ------------------------------------------------------------- + + # deprecated + # + # ratios sum must be equal to 1.0 + def multisamples( nsamples, ratios ) + ratiosum = ratios.sum + samplesum = nsamples.sum + ratios = ratios.map {|ratio| ratio / ratiosum} + + rratios = ratios + index = 0 + ratios.each do |ratio| + rratios[index] = ratio / nsamples[index] + index += 1 + end + + sum = 0.0 + samples = [0.0] + periodindex = 0 + while sum <= 1.0 + sum += rratios[ periodindex ] + if sum > 1.0 + break + end + samples += [sum] + periodindex += 1 + if periodindex >= rratios.length + periodindex = 0.0 + end + end + return self.samples( samples ) + end + + # deprecated + # + # TODO : must add gauss parameters + def randgauss() + begin + x1 = 2.0 * Kernel::rand - 1.0 + x2 = 2.0 * Kernel::rand - 1.0 + w = x1 * x1 + x2 * x2 + end while w >= 1.0 + w = Math.sqrt( ( -2.0 * Math.log( w ) ) / w ) + return 1.0/2.0 * ( 1.0 + x1 * w ) + end end # # Array extension to synchronize enumerations, and also provide other recurrent services @@ -180,21 +260,14 @@ # [V2D[0.0,0.0], V2D[1.0,1.0]].mean => V2D[0.5,0.5] def mean return self.sum / self.size end - # compute range of an array - # - if proc nil, returns (min..max) - # - else, first compute new array with proc, then (min..max) on this array + # compute range of an array by returning (min..max) # [1.0, 3.0, 2.0].range => (1.0..3.0) def range( proc=nil ) - if not proc - return (self.min..self.max) - else - arraytmp = self.map {|item| item.send( proc )} - return arraytmp.range - end + return (self.min..self.max) end # alias for sub(2) # [1,2,3,4].half => [1,3] def half( &block ) @@ -312,12 +385,12 @@ end # ------------------------------------------------------------- # Samplable interface include and overriding # ------------------------------------------------------------- - include Samplable - include Splittable + include XRVG::Samplable + include XRVG::Splittable # FloatFunctor overloading to synchronize content sampling and splitting def compute( inputs, type, &block ) return self.map {|v| v.compute( inputs, type )}.forzip(nil,&block) end @@ -340,20 +413,41 @@ def complement( max = 1.0, min = 0.0 ) return ( max - ( self.to_f - min ) ) end - def fequal?( other ) - return ((self - other).abs < 0.0000000001) + def fequal?( other, epsilon=0.0000000001 ) + return ((self - other).abs < epsilon) end def randsplit(minsize=0.0) v = self.to_f rand = minsize + Kernel::rand * (1.0 - minsize ) min = v * rand max = v - min return [min, max] end + + def Float.sort_float_list( floatlist, epsilon=0.0000001 ) + floatlist = floatlist.uniq.sort + result = [floatlist[0]] + floatlist[1..-1].each do |item| + if not item.fequal?( result[-1], epsilon) + result.push( item ) + end + end + return result + end + + def Float.floatlist_include?( floatlist, float, epsilon=0.0000001 ) + floatlist.each do |item| + if item.fequal?( float, epsilon ) + return true + end + end + return false + end + end class Integer #:nodoc: