Arjen Markus (15 june 2004) While looking for some background information on
special mathematical functions I found a very convenient formula to approximate zeroth and first order Bessel functions (for small enough arguments). It is based on Gaussian quadrature, a well-known approximation of definite integrals. So, here are the humble beginnings of a new mathematical module ...
# bessel.tcl --
# Evaluate the most common Bessel functions via quadrature formulas
#
# namespace special
# Create a convenient namespace for the "special" mathematical functions
#
namespace eval ::math::special {
#
# Define a number of common mathematical constants
#
variable pi 3.1415926
}
# J0 --
# Zeroth-order Bessel function
#
# Arguments:
# x Value of the x-coordinate
# Result:
# Value of J0(x)
#
proc ::math::special::J0 {x} {
variable pi
#
# Determine the number of components (very crude heuristic)
# (We use a quadrature formula here and use the symmetry of
# the cos function to reduce the number of actually computed
# components by a gfactor 2.
#
set ncomps [expr {2*int($x/2.0+0.5)}]
if { $ncomps < 6 } {
set ncomps 6
}
set result 0.0
for { set i 1 } { $i < $ncomps } { incr i 2 } {
set result [expr {$result + cos( $x * cos((2*$i-1)*$pi/(2.0*$ncomps)) ) }]
}
expr {2.0*$result/$ncomps}
}
# J1 --
# First-order Bessel function
#
# Arguments:
# x Value of the x-coordinate
# Result:
# Value of J1(x)
#
proc ::math::special::J1 {x} {
variable pi
#
# Determine the number of components (very crude heuristic)
# (We use a quadrature formula here and use the symmetry of
# the cos function to reduce the number of actually computed
# components by a gfactor 2.
#
set ncomps [expr {2*int($x/2.0+0.5)}]
if { $ncomps < 6 } {
set ncomps 6
}
set result 0.0
for { set i 1 } { $i < $ncomps } { incr i 2 } {
set factor [expr {cos((2*$i-1)*$pi/(2.0*$ncomps))}]
set result [expr {$result + $factor * sin( $x * $factor) }]
}
expr {2.0*$result/$ncomps}
}
# J1/2 --
# Half-order Bessel function
#
# Arguments:
# x Value of the x-coordinate
# Result:
# Value of J1/2(x)
#
proc ::math::special::J1/2 {x} {
variable pi
#
# This Bessel function can be expressed in terms of elementary
# functions. Therefore use the explicit formula
#
if { $x != 0.0 } {
expr {sqrt(2.0/$pi/$x)*sin($x)}
} else {
return 0
}
}
# some tests --
#
foreach x {0.0 2.0 4.4 6.0} {
puts "J0($x) = [::math::special::J0 $x] - J1($x) = [::math::special::J1 $x] \
- J1/2($x) = [::math::special::J1/2 $x]"
}