source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/math/fuzzy.tcl @ 8597867d

1941-docker-image-to-testdevel
Last change on this file since 8597867d was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 3.6 KB
Line 
1# fuzzy.tcl --
2#
3#    Script to define tolerant floating-point comparisons
4#    (Tcl-only version)
5#
6#    version 0.2: improved and extended, march 2002
7
8package provide math::fuzzy 0.2
9
10namespace eval ::math::fuzzy {
11   variable eps3 2.2e-16
12
13   namespace export teq tne tge tgt tle tlt tfloor tceil tround troundn
14
15# DetermineTolerance
16#    Determine the epsilon value
17#
18# Arguments:
19#    None
20#
21# Result:
22#    None
23#
24# Side effects:
25#    Sets variable eps3
26#
27proc DetermineTolerance { } {
28   variable eps3
29   set eps 1.0
30   while { [expr {1.0+$eps}] != 1.0 } {
31      set eps3 [expr 3.0*$eps]
32      set eps  [expr 0.5*$eps]
33   }
34   #set check [expr {1.0+2.0*$eps}]
35   #puts "Eps3: $eps3 ($eps) ([expr {1.0-$check}] [expr 1.0-$check]"
36}
37
38# Absmax --
39#    Return the absolute maximum of two numbers
40#
41# Arguments:
42#    first      First number
43#    second     Second number
44#
45# Result:
46#    Maximum of the absolute values
47#
48proc Absmax { first second } {
49   return [expr {abs($first) > abs($second)? abs($first) : abs($second)}]
50}
51
52# teq, tne, tge, tgt, tle, tlt --
53#    Compare two floating-point numbers and return the logical result
54#
55# Arguments:
56#    first      First number
57#    second     Second number
58#
59# Result:
60#    1 if the condition holds, 0 if not.
61#
62proc teq { first second } {
63   variable eps3
64   set scale [Absmax $first $second]
65   return [expr {abs($first-$second) <= $eps3 * $scale}]
66}
67
68proc tne { first second } {
69   variable eps3
70
71   return [expr {![teq $first $second]}]
72}
73
74proc tgt { first second } {
75   variable eps3
76   set scale [Absmax $first $second]
77   return [expr {($first-$second) > $eps3 * $scale}]
78}
79
80proc tle { first second } {
81   return [expr {![tgt $first $second]}]
82}
83
84proc tlt { first second } {
85   if { [tgt $first $second] } {
86      return 1
87   } else {
88      return [tne $first $second]
89   }
90}
91
92proc tge { first second } {
93   if { [tgt $first $second] } {
94      return 1
95   } else {
96      return [teq $first $second]
97   }
98}
99
100# tfloor --
101#    Determine the "floor" of a number and return the result
102#
103# Arguments:
104#    number     Number in question
105#
106# Result:
107#    Largest integer number that is tolerantly smaller than the given
108#    value
109#
110proc tfloor { number } {
111   variable eps3
112
113   set q      [expr {($number < 0.0)? (1.0-$eps3) : 1.0 }]
114   set rmax   [expr {$q / (2.0 - $eps3)}]
115   set eps5   [expr {$eps3/$q}]
116   set vmin1  [expr {$eps5*abs(1.0+floor($number))}]
117   set vmin2  [expr {($rmax < $vmin1)? $rmax : $vmin1}]
118   set vmax   [expr {($eps3 > $vmin2)? $eps3 : $vmin2}]
119   set result [expr {floor($number+$vmax)}]
120   if { $number <= 0.0 || ($result-$number) < $rmax } {
121      return $result
122   } else {
123      return [expr {$result-1.0}]
124   }
125}
126
127# tceil --
128#    Determine the "ceil" of a number and return the result
129#
130# Arguments:
131#    number     Number in question
132#
133# Result:
134#    Smallest integer number that is tolerantly greater than the given
135#    value
136#
137proc tceil { number } {
138   expr {-[tfloor [expr {-$number}]]}
139}
140
141# tround --
142#    Round off a number and return the result
143#
144# Arguments:
145#    number     Number in question
146#
147# Result:
148#    Nearest integer number
149#
150proc tround { number } {
151   tfloor [expr {$number+0.5}]
152}
153
154# troundn --
155#    Round off a number to a given precision and return the result
156#
157# Arguments:
158#    number     Number in question
159#    ndec       Number of decimals to keep
160#
161# Result:
162#    Nearest number with given precision
163#
164proc troundn { number ndec } {
165   set scale   [expr {pow(10.0,$ndec)}]
166   set rounded [tfloor [expr {$number*$scale+0.5}]]
167   expr {$rounded/$scale}
168}
169
170#
171# Determine the tolerance once and for all
172#
173DetermineTolerance
174rename DetermineTolerance {}
175
176} ;# End of namespace
Note: See TracBrowser for help on using the repository browser.