fuzzy.tcl

Go to the documentation of this file.
00001 /*  fuzzy.tcl --*/
00002 /* */
00003 /*     Script to define tolerant floating-point comparisons*/
00004 /*     (Tcl-only version)*/
00005 /* */
00006 /*     version 0.2: improved and extended, march 2002*/
00007 
00008 package provide math::fuzzy 0.2
00009 
00010 namespace ::math::fuzzy {
00011    variable eps3 2.2e-16
00012 
00013    namespace export teq tne tge tgt tle tlt tfloor tceil tround troundn
00014 
00015 /*  DetermineTolerance*/
00016 /*     Determine the epsilon value*/
00017 /* */
00018 /*  Arguments:*/
00019 /*     None*/
00020 /* */
00021 /*  Result:*/
00022 /*     None*/
00023 /* */
00024 /*  Side effects:*/
00025 /*     Sets variable eps3*/
00026 /* */
00027 ret  DetermineTolerance ( ) {
00028    variable eps3
00029    set eps 1.0
00030    while { [expr {1.0+$eps}] != 1.0 } {
00031       set eps3 [expr 3.0*$eps]
00032       set eps  [expr 0.5*$eps]
00033    }
00034    #set check [expr {1.0+2.0*$eps}]
00035    #puts "Eps3: $eps3 ($eps) ([expr {1.0-$check}] [expr 1.0-$check]"
00036 }
00037 
00038 /*  Absmax --*/
00039 /*     Return the absolute maximum of two numbers*/
00040 /* */
00041 /*  Arguments:*/
00042 /*     first      First number*/
00043 /*     second     Second number*/
00044 /* */
00045 /*  Result:*/
00046 /*     Maximum of the absolute values*/
00047 /* */
00048 ret  Absmax ( type first , type second ) {
00049    return [expr {abs($first) > abs($second)? abs($first) : abs($second)}]
00050 }
00051 
00052 /*  teq, tne, tge, tgt, tle, tlt --*/
00053 /*     Compare two floating-point numbers and return the logical result*/
00054 /* */
00055 /*  Arguments:*/
00056 /*     first      First number*/
00057 /*     second     Second number*/
00058 /* */
00059 /*  Result:*/
00060 /*     1 if the condition holds, 0 if not.*/
00061 /* */
00062 ret  teq ( type first , type second ) {
00063    variable eps3
00064    set scale [Absmax $first $second]
00065    return [expr {abs($first-$second) <= $eps3 * $scale}]
00066 }
00067 
00068 ret  tne ( type first , type second ) {
00069    variable eps3
00070 
00071    return [expr {![teq $first $second]}]
00072 }
00073 
00074 ret  tgt ( type first , type second ) {
00075    variable eps3
00076    set scale [Absmax $first $second]
00077    return [expr {($first-$second) > $eps3 * $scale}]
00078 }
00079 
00080 ret  tle ( type first , type second ) {
00081    return [expr {![tgt $first $second]}]
00082 }
00083 
00084 ret  tlt ( type first , type second ) {
00085    if { [tgt $first $second] } {
00086       return 1
00087    } else {
00088       return [tne $first $second]
00089    }
00090 }
00091 
00092 ret  tge ( type first , type second ) {
00093    if { [tgt $first $second] } {
00094       return 1
00095    } else {
00096       return [teq $first $second]
00097    }
00098 }
00099 
00100 /*  tfloor --*/
00101 /*     Determine the "floor" of a number and return the result*/
00102 /* */
00103 /*  Arguments:*/
00104 /*     number     Number in question*/
00105 /* */
00106 /*  Result:*/
00107 /*     Largest integer number that is tolerantly smaller than the given*/
00108 /*     value*/
00109 /* */
00110 ret  tfloor ( type number ) {
00111    variable eps3
00112 
00113    set q      [expr {($number < 0.0)? (1.0-$eps3) : 1.0 }]
00114    set rmax   [expr {$q / (2.0 - $eps3)}]
00115    set eps5   [expr {$eps3/$q}]
00116    set vmin1  [expr {$eps5*abs(1.0+floor($number))}]
00117    set vmin2  [expr {($rmax < $vmin1)? $rmax : $vmin1}]
00118    set vmax   [expr {($eps3 > $vmin2)? $eps3 : $vmin2}]
00119    set result [expr {floor($number+$vmax)}]
00120    if { $number <= 0.0 || ($result-$number) < $rmax } {
00121       return $result
00122    } else {
00123       return [expr {$result-1.0}]
00124    }
00125 }
00126 
00127 /*  tceil --*/
00128 /*     Determine the "ceil" of a number and return the result*/
00129 /* */
00130 /*  Arguments:*/
00131 /*     number     Number in question*/
00132 /* */
00133 /*  Result:*/
00134 /*     Smallest integer number that is tolerantly greater than the given*/
00135 /*     value*/
00136 /* */
00137 ret  tceil ( type number ) {
00138    expr {-[tfloor [expr {-$number}]]}
00139 }
00140 
00141 /*  tround --*/
00142 /*     Round off a number and return the result*/
00143 /* */
00144 /*  Arguments:*/
00145 /*     number     Number in question*/
00146 /* */
00147 /*  Result:*/
00148 /*     Nearest integer number*/
00149 /* */
00150 ret  tround ( type number ) {
00151    tfloor [expr {$number+0.5}]
00152 }
00153 
00154 /*  troundn --*/
00155 /*     Round off a number to a given precision and return the result*/
00156 /* */
00157 /*  Arguments:*/
00158 /*     number     Number in question*/
00159 /*     ndec       Number of decimals to keep*/
00160 /* */
00161 /*  Result:*/
00162 /*     Nearest number with given precision*/
00163 /* */
00164 ret  troundn ( type number , type ndec ) {
00165    set scale   [expr {pow(10.0,$ndec)}]
00166    set rounded [tfloor [expr {$number*$scale+0.5}]]
00167    expr {$rounded/$scale}
00168 }
00169 
00170 /* */
00171 /*  Determine the tolerance once and for all*/
00172 /* */
00173 DetermineTolerance
00174 rename DetermineTolerance {}
00175 
00176 } ;/*  End of namespace*/
00177 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1