constants.tcl

Go to the documentation of this file.
00001 /*  constants.tcl --*/
00002 /*     Module defining common mathematical and numerical constants*/
00003 /* */
00004 /*  Copyright (c) 2004 by Arjen Markus.  All rights reserved.*/
00005 /* */
00006 /*  See the file "license.terms" for information on usage and redistribution*/
00007 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00008 /*  */
00009 /*  RCS: @(#) $Id: constants.tcl,v 1.8 2005/10/06 05:16:37 andreas_kupries Exp $*/
00010 /* */
00011 /* ----------------------------------------------------------------------*/
00012 
00013 package require Tcl 8.2
00014 
00015 package provide math::constants 1.0.1
00016 
00017 /*  namespace constants*/
00018 /*     Create a convenient namespace for the constants*/
00019 /* */
00020 namespace ::math::constants {
00021     /* */
00022     /*  List of constants and their description*/
00023     /* */
00024     variable constants {
00025         pi        3.14159265358979323846   "ratio of circle circumference and diameter"
00026         e         2.71828182845904523536   "base for natural logarithm"
00027         ln10      2.30258509299404568402   "natural logarithm of 10"
00028         phi       1.61803398874989484820   "golden ratio"
00029         gamma     0.57721566490153286061   "Euler's constant"
00030         sqrt2     1.41421356237309504880   "Square root of 2"
00031         thirdrt2  1.25992104989487316477   "One-third power of 2"
00032         sqrt3     1.73205080756887729533   "Square root of 3"
00033         radtodeg  57.2957795131            "Conversion from radians to degrees"
00034         degtorad  0.017453292519943        "Conversion from degrees to radians"
00035         onethird  1.0/3.0                  "One third (0.3333....)"
00036         twothirds 2.0/3.0                  "Two thirds (0.3333....)"
00037         onesixth  1.0/6.0                  "One sixth (0.1666....)"
00038         huge      [find_huge]              "(Approximately) largest number"
00039         tiny      [find_tiny]              "(Approximately) smallest number not equal zero"
00040         eps       [find_eps]               "Smallest number such that 1+eps != 1"
00041     }
00042     namespace export constants print-constants
00043 }
00044 
00045 /*  constants --*/
00046 /*     Expose the constants in the caller's routine or namespace*/
00047 /* */
00048 /*  Arguments:*/
00049 /*     args         List of constants to be exposed*/
00050 /*  Result:*/
00051 /*     None*/
00052 /* */
00053 ret  ::math::constants::constants (type args) {
00054 
00055     foreach const $args {
00056         uplevel 1 [list variable $const [set ::math::constants::$const]]
00057     }
00058 }
00059 
00060 /*  print-constants --*/
00061 /*     Print the selected or all constants to the screen*/
00062 /* */
00063 /*  Arguments:*/
00064 /*     args         List of constants to be exposed*/
00065 /*  Result:*/
00066 /*     None*/
00067 /* */
00068 ret  ::math::constants::print-constants (type args) {
00069     variable constants
00070 
00071     if { [llength $args] != 0 } {
00072         foreach const $args {
00073             set idx [lsearch $constants $const]
00074             if { $idx >= 0 } {
00075                 set descr [lindex $constants [expr {$idx+2}]]
00076                 puts "$const = [set ::math::constants::$const] = $descr"
00077             } else {
00078                 puts "*** $const unknown ***"
00079             }
00080         }
00081     } else {
00082         foreach {const value descr} $constants {
00083             puts "$const = [set ::math::constants::$const] = $descr"
00084         }
00085     }
00086 }
00087 
00088 /*  find_huge --*/
00089 /*     Find the largest possible number*/
00090 /* */
00091 /*  Arguments:*/
00092 /*     None*/
00093 /*  Result:*/
00094 /*     Estimate of the largest possible number*/
00095 /* */
00096 ret  ::math::constants::find_huge () {
00097 
00098     set result 1.0
00099     set Inf Inf
00100     while {1} {
00101     if {[catch {expr {2.0 * $result}} result]} {
00102         break
00103     }
00104     if { $result == $Inf } {
00105         break
00106     }
00107     set prev_result $result
00108     }
00109     set result $prev_result
00110     set adder [expr { $result / 2. }]
00111     while { $adder != 0.0 } {
00112     if {![catch {expr {$adder + $prev_result}} result]} {
00113         if { $result == $prev_result } break
00114         if { $result != $Inf } {
00115         set prev_result $result
00116         }
00117     }
00118     set adder [expr { $adder / 2. }]
00119     }
00120     return $prev_result
00121 
00122 }
00123 
00124 /*  find_tiny --*/
00125 /*     Find the smallest possible number*/
00126 /* */
00127 /*  Arguments:*/
00128 /*     None*/
00129 /*  Result:*/
00130 /*     Estimate of the smallest possible number*/
00131 /* */
00132 ret  ::math::constants::find_tiny () {
00133 
00134     set result 1.0
00135 
00136     while { ! [catch {set result [expr {$result/2.0}]}] && $result > 0.0 } {
00137         set prev_result $result
00138     }
00139     return $prev_result
00140 }
00141 
00142 /*  find_eps --*/
00143 /*     Find the smallest number eps such that 1+eps != 1*/
00144 /* */
00145 /*  Arguments:*/
00146 /*     None*/
00147 /*  Result:*/
00148 /*     Estimate of the machine epsilon*/
00149 /* */
00150 ret  ::math::constants::find_eps ( ) {
00151     set eps 1.0
00152     while { [expr {1.0+$eps}] != 1.0 } {
00153         set prev_eps $eps
00154         set eps  [expr {0.5*$eps}]
00155     }
00156     return $prev_eps
00157 }
00158 
00159 /*  Create the variables from the list:*/
00160 /*  - By using expr we ensure that the best double precision*/
00161 /*    approximation is assigned to the variable, rather than*/
00162 /*    just the string*/
00163 /*  - It also allows us to rely on IEEE arithmetic if available,*/
00164 /*    so that for instance 3.0*(1.0/3.0) is exactly 1.0*/
00165 /* */
00166 namespace ::math::constants {
00167     foreach {const value descr} $constants {
00168         /*  FRINK: nocheck*/
00169          [namespace =  current]::$const [expr 0.0+$value]
00170     }
00171     un value = 
00172     un const = 
00173     un descr =  
00174 
00175     rename find_eps  {}
00176     rename find_tiny {}
00177     rename find_huge {}
00178 }
00179 
00180 /*  some tests --*/
00181 /* */
00182 if { [info exists ::argv0]
00183      && [string equal $::argv0 [info script]] } {
00184     ::math::constants::constants pi e ln10 onethird eps
00185      tcl = _precision 17
00186     puts "$pi - [expr {1.0/$pi}]"
00187     puts $e
00188     puts $ln10
00189     puts "onethird: [expr {3.0*$onethird}]"
00190     ::math::constants::print-constants onethird pi e
00191     puts "All defined constants:"
00192     ::math::constants::print-constants
00193     
00194     if { 1.0+$eps == 1.0 } {
00195         puts "Something went wrong with eps!"
00196     } else {
00197         puts "Difference: [ ee =  [expr {1.0+$eps}]] - 1.0 = [expr {$ee-1.0}]"
00198     }
00199 }
00200 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1