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: