special.tcl

Go to the documentation of this file.
00001 /*  special.tcl --*/
00002 /*     Provide well-known special mathematical functions*/
00003 /* */
00004 /*  This file contains a collection of tests for one or more of the Tcllib*/
00005 /*  procedures.  Sourcing this file into Tcl runs the tests and*/
00006 /*  generates output for errors.  No output means no errors were found.*/
00007 /* */
00008 /*  Copyright (c) 2004 by Arjen Markus. All rights reserved.*/
00009 /* */
00010 /*  RCS: @(#) $Id: special.tcl,v 1.10 2007/06/26 18:55:18 kennykb Exp $*/
00011 /* */
00012 package require math
00013 package require math::constants
00014 package require math::statistics
00015 
00016 /*  namespace special*/
00017 /*     Create a convenient namespace for the "special" mathematical functions*/
00018 /* */
00019 namespace ::math::special {
00020     /* */
00021     /*  Define a number of common mathematical constants*/
00022     /* */
00023     ::math::constants::constants pi
00024     variable halfpi [expr {$pi/2.0}]
00025 
00026     /* */
00027     /*  Functions defined in other math submodules*/
00028     /* */
00029     if { [info commands Beta] == {} } {
00030        namespace import ::math::Beta
00031     }
00032     if { [info commands Beta] == {} } {
00033        namespace import ::math::ln_Gamma
00034     }
00035 
00036     /* */
00037     /*  Export the various functions*/
00038     /* */
00039     namespace export Beta ln_Gamma Gamma erf erfc fresnel_C fresnel_S sinc
00040 }
00041 
00042 /*  Gamma --*/
00043 /*     The Gamma function - synonym for "factorial"*/
00044 /* */
00045 ret  ::math::special::Gamma (type x) {
00046     ::math::factorial [expr { $x + 1 }]
00047 }
00048 
00049 /*  erf --*/
00050 /*     The error function*/
00051 /*  Arguments:*/
00052 /*     x          The value for which the function must be evaluated*/
00053 /*  Result:*/
00054 /*     erf(x)*/
00055 /* */
00056 ret  ::math::special::erf (type x) {
00057     set x2 $x
00058     if { $x > 0.0 } {
00059         set x2 [expr {-$x}]
00060     }
00061     if { $x2 != 0.0 } {
00062         set r [::math::statistics::cdf-normal 0.0 [expr {sqrt(0.5)}] $x2]
00063         if { $x > 0.0 } {
00064             return [expr {1.0-2.0*$r}]
00065         } else {
00066             return [expr {2.0*$r-1.0}]
00067         }
00068     } else {
00069         return 0.0
00070     }
00071 }
00072 
00073 /*  erfc --*/
00074 /*     The complement of the error function*/
00075 /*  Arguments:*/
00076 /*     x          The value for which the function must be evaluated*/
00077 /*  Result:*/
00078 /*     erfc(x) = 1.0-erf(x)*/
00079 /* */
00080 ret  ::math::special::erfc (type x) {
00081     set x2 $x
00082     if { $x > 0.0 } {
00083         set x2 [expr {-$x}]
00084     }
00085     if { $x2 != 0.0 } {
00086         set r [::math::statistics::cdf-normal 0.0 [expr {sqrt(0.5)}] $x2]
00087         if { $x > 0.0 } {
00088             return [expr {2.0*$r}]
00089         } else {
00090             return [expr {2.0-2.0*$r}]
00091         }
00092     } else {
00093         return 1.0
00094     }
00095 }
00096 
00097 /*  ComputeFG --*/
00098 /*     Compute the auxiliary functions f and g*/
00099 /* */
00100 /*  Arguments:*/
00101 /*     x            Parameter of the integral (x>=0)*/
00102 /*  Result:*/
00103 /*     Approximate values for f and g*/
00104 /*  Note:*/
00105 /*     See Abramowitz and Stegun. The accuracy is 2.0e-3.*/
00106 /* */
00107 ret  ::math::special::ComputeFG (type x) {
00108     list [expr {(1.0+0.926*$x)/(2.0+1.792*$x+3.104*$x*$x)}] \
00109         [expr {1.0/(2.0+4.142*$x+3.492*$x*$x+6.670*$x*$x*$x)}]
00110 }
00111 
00112 /*  fresnel_C --*/
00113 /*     Compute the Fresnel cosine integral*/
00114 /* */
00115 /*  Arguments:*/
00116 /*     x            Parameter of the integral (x>=0)*/
00117 /*  Result:*/
00118 /*     Value of C(x) = integral from 0 to x of cos(0.5*pi*x^2)*/
00119 /*  Note:*/
00120 /*     This relies on a rational approximation of the two auxiliary functions f and g*/
00121 /* */
00122 ret  ::math::special::fresnel_C (type x) {
00123     variable halfpi
00124     if { $x < 0.0 } {
00125         error "Domain error: x must be non-negative"
00126     }
00127 
00128     if { $x == 0.0 } {
00129         return 0.0
00130     }
00131 
00132     foreach {f g} [ComputeFG $x] {break}
00133 
00134     set xarg [expr {$halfpi*$x*$x}]
00135 
00136     return [expr {0.5+$f*sin($xarg)-$g*cos($xarg)}]
00137 }
00138 
00139 /*  fresnel_S --*/
00140 /*     Compute the Fresnel sine integral*/
00141 /* */
00142 /*  Arguments:*/
00143 /*     x            Parameter of the integral (x>=0)*/
00144 /*  Result:*/
00145 /*     Value of S(x) = integral from 0 to x of sin(0.5*pi*x^2)*/
00146 /*  Note:*/
00147 /*     This relies on a rational approximation of the two auxiliary functions f and g*/
00148 /* */
00149 ret  ::math::special::fresnel_S (type x) {
00150     variable halfpi
00151     if { $x < 0.0 } {
00152         error "Domain error: x must be non-negative"
00153     }
00154 
00155     if { $x == 0.0 } {
00156         return 0.0
00157     }
00158 
00159     foreach {f g} [ComputeFG $x] {break}
00160 
00161     set xarg [expr {$halfpi*$x*$x}]
00162 
00163     return [expr {0.5-$f*cos($xarg)-$g*sin($xarg)}]
00164 }
00165 
00166 /*  sinc --*/
00167 /*     Compute the sinc function*/
00168 /*  Arguments:*/
00169 /*     x       Value of the argument*/
00170 /*  Result:*/
00171 /*     sin(x)/x*/
00172 /* */
00173 ret  ::math::special::sinc (type x) {
00174     if { $x == 0.0 } {
00175         return 1.0
00176     } else {
00177         return [expr {sin($x)/$x}]
00178     }
00179 }
00180 
00181 /*  Bessel functions and elliptic integrals --*/
00182 /* */
00183 source [file join [file dirname [info script]] "bessel.tcl"]
00184 source [file join [file dirname [info script]] "classic_polyns.tcl"]
00185 source [file join [file dirname [info script]] "elliptic.tcl"]
00186 source [file join [file dirname [info script]] "exponential.tcl"]
00187 
00188 package provide math::special 0.2.1
00189 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1