Tk Library Source Code

Artifact [c6bb5e50ff]
Login

Artifact c6bb5e50ff1642413c57f37475fd9fbca76d586d:

Attachment "calc.patch" to ticket [553773ffff] added by dgp 2002-06-01 04:01:51.
Index: modules/math/calculus.CHANGES
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/calculus.CHANGES,v
retrieving revision 1.2
diff -u -r1.2 calculus.CHANGES
--- modules/math/calculus.CHANGES	15 Mar 2002 21:42:44 -0000	1.2
+++ modules/math/calculus.CHANGES	31 May 2002 20:59:52 -0000
@@ -10,6 +10,12 @@
 Version 0.2: november 2001
    Extended with Euler and Heun methods, 2D and 3D simple integration
 
-Version 0.3: november 2001
-   Implementation of Runge-Kutta method. Converted the documentation to
-   doctools format
+Version 0.3: march 2002
+   Implemented Runge-Kutta, converted documentation to doctools' 
+   man format
+
+Version 0.4: march 2002
+   Implemented Newton-Raphson method for finding roots of equations
+
+Version 0.5: may 2002
+   Fixed problem with namespaces
Index: modules/math/calculus.README
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/calculus.README,v
retrieving revision 1.2
diff -u -r1.2 calculus.README
--- modules/math/calculus.README	15 Mar 2002 21:42:44 -0000	1.2
+++ modules/math/calculus.README	31 May 2002 20:59:52 -0000
@@ -1,6 +1,6 @@
-Package: Calculus
-----------------
-The Calculus package is an all-Tcl package that implements
+Package: math::calculus
+-----------------------
+The math::calculus package is an all-Tcl package that implements 
 several basic numerical algorithms, such as the integration
 of functions of one variable or the integration of ordinary
 differential equations.
@@ -12,7 +12,10 @@
 calculus.test  - Several simple tests
 calculus.html  - Documentation of the package
 
-The current version is: 0.3, the first public release, march 2002
+The current version is: 0.5, may 2002
+
+This package is available as part of Tcllib at:
+   http://tcllib.sourceforge.net
 
 Please contact Arjen Markus ([email protected]) for questions,
 bug reports, enhancements and so on.
Index: modules/math/calculus.doc
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/calculus.doc,v
retrieving revision 1.1
diff -u -r1.1 calculus.doc
--- modules/math/calculus.doc	18 Jan 2002 20:28:22 -0000	1.1
+++ modules/math/calculus.doc	31 May 2002 20:59:52 -0000
@@ -1,4 +1,18 @@
 [pageheader "Package: Calculus"]
+[synopsis \
+{package require Tcl 8.2
+package require math::calculus 0.5
+::math::calculus::integral begin end nosteps func
+::math::calculus::integralExpr begin end nosteps expression
+::math::calculus::integral2D xinterval yinterval func
+::math::calculus::integral3D xinterval yinterval zinterval func
+::math::calculus::eulerStep t tstep xvec func
+::math::calculus::heunStep t tstep xvec func
+::math::calculus::rungeKuttaStep tstep xvec func
+::math::calculus::boundaryValueSecondOrder coeff_func force_func leftbnd rightbnd nostep}]
+::math::calculus::newtonRaphson func deriv initval
+::math::calculus::newtonRaphsonParameters maxiter tolerance
+
 [section "Introduction"]
 The package Calculus implements several simple mathematical algorithms,
 such as the integration of a function over an interval and the numerical
@@ -11,7 +25,7 @@
 This document describes the procedures and explains their usage.
 
 [section "Version and copyright"]
-This document describes [italic Calculus], version 0.3, december 2001.
+This document describes [italic ::math::calculus], version 0.5, may 2002.
 [par]
 Usage of Calculus is free, as long as you acknowledge the
 author, Arjen Markus (e-mail: [email protected]).
@@ -21,7 +35,7 @@
 [section "Procedures"]
 The Calculus package defines the following public procedures:
 [ulist]
-[item][italic "Integral begin end nosteps func"]
+[item][italic "integral begin end nosteps func"]
       [break]
       Determine the integral of the given function using the Simpson
       rule. The interval for the integration is [lb]begin,end[rb].
@@ -34,7 +48,7 @@
       single argument.
       [par]
 
-[item][italic "IntegralExpr begin end nosteps expression"]
+[item][italic "integralExpr begin end nosteps expression"]
       [break]
       Similar to the previous proc, this one determines the integral of
       the given [italic expression] using the Simpson rule.
@@ -48,9 +62,9 @@
       use the variable "x" as the only variable (the "integrate")
       [par]
 
-[item][italic "Integral2D xinterval yinterval func"]
+[item][italic "integral2D xinterval yinterval func"]
       [break]
-      The [italic Integral2D] procedure calculates the integral of
+      The [italic integral2D] procedure calculates the integral of
       a function of two variables over the rectangle given by the
       first two arguments, each a list of three items, the start and
       stop interval for the variable and the number of steps.
@@ -64,15 +78,15 @@
       value.
       [par]
 
-[item][italic "Integral3D xinterval yinterval zinterval func"]
+[item][italic "integral3D xinterval yinterval zinterval func"]
       [break]
-      The [italic Integral3D] procedure is the three-dimensional
-      equivalent of [italic Intergral2D]. The function taking three
+      The [italic integral3D] procedure is the three-dimensional
+      equivalent of [italic intergral2D]. The function taking three
       arguments is integrated over the block in 3D space given by the
       intervals.
       [par]
 
-[item][italic "EulerStep t tstep xvec func"]
+[item][italic "eulerStep t tstep xvec func"]
       [break]
       Set a single step in the numerical integration of a system of
       differential equations. The method used is Euler's.
@@ -89,7 +103,7 @@
       xvec and the return value of "func" must match).
       [par]
 
-[item][italic "HeunStep t tstep xvec func"]
+[item][italic "heunStep t tstep xvec func"]
       [break]
       Set a single step in the numerical integration of a system of
       differential equations. The method used is Heun's.
@@ -106,7 +120,7 @@
       xvec and the return value of "func" must match).
       [par]
 
-[item][italic "RungeKuttaStep tstep xvec func"]
+[item][italic "rungeKuttaStep tstep xvec func"]
       [break]
       Set a single step in the numerical integration of a system of
       differential equations. The method used is Runge-Kutta 4th
@@ -124,7 +138,7 @@
       xvec and the return value of "func" must match).
       [par]
 
-[item][italic "BoundaryValueSecondOrder coeff_func force_func leftbnd rightbnd nostep"]
+[item][italic "boundaryValueSecondOrder coeff_func force_func leftbnd rightbnd nostep"]
       [break]
       Solve a second order linear differential equation with boundary
       values at two sides. The equation has to be of the form:
@@ -164,7 +178,7 @@
       values of the solution.
       [par]
 
-[item][italic "SolveTriDiagonal acoeff bcoeff ccoeff dvalue"
+[item][italic "solveTriDiagonal acoeff bcoeff ccoeff dvalue"]
       [break]
       Solve a system of linear equations Ax = b with A a tridiagonal
       matrix. Returns the solution as a list.
@@ -173,13 +187,60 @@
       [italic bcoeff] - List of values on the main diagonal
       [italic ccoeff] - List of values on the upper diagonal
       [italic dvalue] - List of values on the righthand-side
+      [par]
+
+[item][italic "newtonRaphson func deriv initval"]
+      [break]
+      Determine the root of an equation given by [italic "f(x) = 0"],
+      using the Newton-Raphson method.
+      [break]
+      [italic func]    - Name of the procedure that calculates the function value
+      [italic deriv    - Name of the procedure that calculates the derivative of the function
+      [italic initval] - Initial value for the iteration
+      [par]
+
+[item][italic "newtonRaphsonParameters maxiter tolerance"]
+      [break]
+      Set new values for the two parameters that gouvern the Newton-Raphson method.
+      [break]
+      [italic maxiter]   - Maximum number of iterations
+      [italic tolerance] - Relative error in the calculation
+      [par]
 [endlist]
 
-[italic Note:]
-[break]
-The integration of the differential equations via Runge-Kutta
-is yet to be implemented.
+[italic Notes:]
 [break]
+Several of the above procedures take the [italic names] of procedures as
+arguments. To avoid problems with the [italic visibility] of these
+procedures, the fully-qualified name of these procedures is determined
+inside the calculus routines. For the user this has only one
+consequence: the named procedure must be visible in the calling
+procedure. For instance:
+
+[preserve]
+    namespace eval ::mySpace {
+       namespace export calcfunc
+       proc calcfunc { x } { return $x }
+    }
+    #
+    # Use a fully-qualified name
+    #
+    namespace eval ::myCalc {
+       proc detIntegral { begin end } {
+          return [lb]integral $begin $end 100 ::mySpace::calcfunc[rb]
+       }
+    }
+    #
+    # Import the name
+    #
+    namespace eval ::myCalc {
+       namespace import ::mySpace::calcfunc
+       proc detIntegral { begin end } {
+          return [lb]integral $begin $end 100 calcfunc[rb]
+       }
+    }
+[endpreserve]
+[par]
 Enhancements for the second-order boundary value problem:
 [ulist]
 [item]Other types of boundary conditions (zero gradient, zero flux)
@@ -193,11 +254,11 @@
 Integrate x over the interval [lb]0,100[rb] (20 steps):
 [preserve]
 proc linear_func { x } { return $x }
-puts "Integral: ::Calculus::Integral 0 100 20 linear_func"
+puts "Integral: [lb]::math::calculus::Integral 0 100 20 linear_func[rb]"
 [endpreserve]
 For simple functions, the alternative could be:
 [preserve]
-puts "Integral: ::Calculus::IntegralExpr 0 100 20 {$x}"
+puts "Integral: [lb]::math::calculus::IntegralExpr 0 100 20 {$x}[rb]"
 [endpreserve]
 Do not forget the braces!
 [par]
@@ -213,19 +274,19 @@
 Then this system can be solved with code like this:
 [preserve]
 proc dampened_oscillator { t xvec } {
-   set x  [lb]lindex $xvec 0[rb]
-   set x1 [lb]lindex $xvec 1[rb]
-   return [lb]list $x1 [lb]expr {-$x1-$x}[rb][rb]
+   set x  [lb]lindex \$xvec 0[rb]
+   set x1 [lb]lindex \$xvec 1[rb]
+   return [lb]list \$x1 [lb]expr {-\$x1-\$x}[rb][rb]
 }
 
 set xvec   { 1.0 0.0 }
 set t      0.0
 set tstep  0.1
-for { set i 0 } { $i < 20 } { incr i } {
-   set result [lb]::Calculus::EulerStep $t $tstep $xvec dampened_oscillator[rb]
-   puts "Result ($t): $result"
-   set t      [lb]expr {$t+$tstep}[rb]
-   set xvec   $result
+for { set i 0 } { \$i < 20 } { incr i } {
+   set result [lb]::math::calculus::eulerStep \$t \$tstep \$xvec dampened_oscillator[rb]
+   puts "Result (\$t): \$result"
+   set t      [lb]expr {\$t+\$tstep}[rb]
+   set xvec   \$result
 }
 [endpreserve]
 Suppose we have the boundary value problem:
@@ -239,12 +300,12 @@
 [par]
 It can be solved with the following fragment:
 [preserve]
-   proc coeffs { x } { return [list $::Diff 0.0 $::decay] }
+   proc coeffs { x } { return [lb]list \$::Diff 0.0 \$::decay[rb] }
    proc force  { x } { return 0.0 }
 
    set Diff   1.0e-2
    set decay  0.0001
    set length 100.0
-   set y [lb]::Calculus::BoundaryValueSecondOrder coeffs force {0.0 1.0} \
-      [list $length 0.0] 100
+   set y [lb]::math::calculus::boundaryValueSecondOrder coeffs force {0.0 1.0} \
+      [lb]list \$length 0.0[rb] 100[rb]
 [endpreserve]
Index: modules/math/calculus.man
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/calculus.man,v
retrieving revision 1.2
diff -u -r1.2 calculus.man
--- modules/math/calculus.man	26 Mar 2002 07:40:36 -0000	1.2
+++ modules/math/calculus.man	31 May 2002 20:59:52 -0000
@@ -3,7 +3,6 @@
 [titledesc {Integration and ordinary differential equations}]
 [description]
 [para]
-
 This package implements several simple mathematical algorithms:
 
 [list_begin bullet]
@@ -14,22 +13,20 @@
 The numerical integration of a system of ordinary differential
 equations.
 
+[bullet]
+Estimating the root(s) of an equation of one variable.
+
 [list_end]
 
 [para]
-
 The package is fully implemented in Tcl. No particular attention has
 been paid to the accuracy of the calculations. Instead, well-known
 algorithms have been used in a straightforward manner.
-
 [para]
-
 This document describes the procedures and explains their usage.
 
 [section "PROCEDURES"]
-
-It defines the following public procedures:
-
+This package defines the following public procedures:
 [list_begin definitions]
 
 [call [cmd ::math::calculus::integral] [arg begin] [arg end] [arg nosteps] [arg func]]
@@ -42,6 +39,7 @@
 [nl]
 [arg func] - Function to be integrated. It should take one
 single argument.
+[para]
 
 [call [cmd ::math::calculus::integralExpr] [arg begin] [arg end] [arg nosteps] [arg expression]]
 Similar to the previous proc, this one determines the integral of
@@ -54,6 +52,7 @@
 [nl]
 [arg expression] - Expression to be integrated. It should
 use the variable "x" as the only variable (the "integrate")
+[para]
 
 [call [cmd ::math::calculus::integral2D] [arg xinterval] [arg yinterval] [arg func]]
 The [strong Integral2D] procedure calculates the integral of
@@ -68,12 +67,14 @@
 [nl]
 The function must take two arguments and return the function
 value.
+[para]
 
 [call [cmd ::math::calculus::integral3D] [arg xinterval] [arg yinterval] [arg zinterval] [arg func]]
 The [strong Integral3D] procedure is the three-dimensional
 equivalent of [strong Intergral2D]. The function taking three
 arguments is integrated over the block in 3D space given by the
 intervals.
+[para]
 
 [call [cmd ::math::calculus::eulerStep] [arg t] [arg tstep] [arg xvec] [arg func]]
 Set a single step in the numerical integration of a system of
@@ -89,6 +90,7 @@
 [arg func] - Function of t and the dependent values, returning
 a list of the derivatives of the dependent values. (The lengths of
 xvec and the return value of "func" must match).
+[para]
 
 [call [cmd ::math::calculus::heunStep] [arg t] [arg tstep] [arg xvec] [arg func]]
 Set a single step in the numerical integration of a system of
@@ -104,6 +106,7 @@
 [arg func] - Function of t and the dependent values, returning
 a list of the derivatives of the dependent values. (The lengths of
 xvec and the return value of "func" must match).
+[para]
 
 [call [cmd ::math::calculus::rungeKuttaStep] [arg tstep] [arg xvec] [arg func]]
 Set a single step in the numerical integration of a system of
@@ -120,6 +123,7 @@
 [arg func] - Function of t and the dependent values, returning
 a list of the derivatives of the dependent values. (The lengths of
 xvec and the return value of "func" must match).
+[para]
 
 [call [cmd ::math::calculus::boundaryValueSecondOrder] [arg coeff_func] [arg force_func] [arg leftbnd] [arg rightbnd] [arg nostep]]
 Solve a second order linear differential equation with boundary
@@ -164,7 +168,7 @@
 [nl]
 The procedure returns a list of x-coordinates and the approximated
 values of the solution.
-
+[para]
 
 [call [cmd ::math::calculus::solveTriDiagonal] [arg acoeff] [arg bcoeff] [arg ccoeff] [arg dvalue]]
 Solve a system of linear equations Ax = b with A a tridiagonal
@@ -177,15 +181,63 @@
 [arg ccoeff] - List of values on the upper diagonal
 [nl]
 [arg dvalue] - List of values on the righthand-side
-[nl]
-[list_end]
+[para]
 
+[call [cmd ::math::calculus::newtonRaphson] [arg func] [arg deriv] [arg initval]]
+Determine the root of an equation given by
+[example_begin]
+    func(x) = 0
+[example_end]
+using the method of Newton-Raphson. The procedure takes the following
+arguments:
+[nl]
+[arg func] - Procedure that returns the value the function at x
+[nl]
+[arg deriv] - Procedure that returns the derivative of the function at x
+[nl]
+[arg initval] - Initial value for x
 [para]
 
-[strong Note:]
+[call [cmd ::math::calculus::newtonRaphsonParameters] [arg maxiter] [arg tolerance]]
+Set the numerical parameters for the Newton-Raphson method:
+[nl]
+[arg maxiter] - Maximum number of iteration steps (defaults to 20)
+[nl]
+[arg tolerance] - Relative precision (defaults to 0.001)
+[list_end]
 [para]
-The integration of the differential equations via Runge-Kutta
-is yet to be implemented.
+
+[strong Notes:]
+[nl]
+Several of the above procedures take the [strong names] of procedures as
+arguments. To avoid problems with the [strong visibility] of these
+procedures, the fully-qualified name of these procedures is determined
+inside the calculus routines. For the user this has only one
+consequence: the named procedure must be visible in the calling
+procedure. For instance:
+[example_begin]
+    namespace eval ::mySpace {
+       namespace export calcfunc
+       proc calcfunc { x } { return $x }
+    }
+    #
+    # Use a fully-qualified name
+    #
+    namespace eval ::myCalc {
+       proc detIntegral { begin end } {
+          return [lb]integral $begin $end 100 ::mySpace::calcfunc[rb]
+       }
+    }
+    #
+    # Import the name
+    #
+    namespace eval ::myCalc {
+       namespace import ::mySpace::calcfunc
+       proc detIntegral { begin end } {
+          return [lb]integral $begin $end 100 calcfunc[rb]
+       }
+    }
+[example_end]
 [para]
 Enhancements for the second-order boundary value problem:
 [list_begin bullet]
@@ -202,16 +254,16 @@
 Integrate x over the interval [lb]0,100[rb] (20 steps):
 [example_begin]
 proc linear_func { x } { return $x }
-puts "Integral: [lb]::math::calculus::integral 0 100 20 linear_func[rb]"
+puts "Integral: [lb]::math::calculus::Integral 0 100 20 linear_func[rb]"
 [example_end]
 For simple functions, the alternative could be:
 [example_begin]
-puts "Integral: [lb]::math::calculus::integralExpr 0 100 20 {$x}[rb]"
+puts "Integral: [lb]::math::calculus::IntegralExpr 0 100 20 {$x}[rb]"
 [example_end]
 Do not forget the braces!
 [para]
 The differential equation for a dampened oscillator:
-[para]
+[nl]
 [example_begin]
 x'' + rx' + wx = 0
 [example_end]
@@ -256,9 +308,10 @@
    set decay  0.0001
    set length 100.0
 
-   set y [lb]::math::calculus::boundaryValueSecondOrder coeffs force {0.0 1.0} \
-      [lb]list $length 0.0[rb] 100[rb]
+   set y [lb]::math::calculus::boundaryValueSecondOrder \
+      coeffs force {0.0 1.0} [lb]list $length 0.0[rb] 100[rb]
 [example_end]
 
-[keywords math calculus integration "differential equations"]
+[keywords math calculus integration "differential equations" roots]
+
 [manpage_end]
Index: modules/math/calculus.tcl
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/calculus.tcl,v
retrieving revision 1.2
diff -u -r1.2 calculus.tcl
--- modules/math/calculus.tcl	15 Mar 2002 21:42:44 -0000	1.2
+++ modules/math/calculus.tcl	31 May 2002 20:59:52 -0000
@@ -9,14 +9,19 @@
 # math::calculus --
 #    Namespace for the commands
 #
-
 namespace eval ::math::calculus {
-   namespace export integral integralExpr integral2D integral3D
-   namespace export eulerStep heunStep rungeKuttaStep
-   namespace export boundaryValueSecondOrder solveTriDiagonal
+   namespace export \
+          integral integralExpr integral2D integral3D \
+          eulerStep heunStep rungeKuttaStep           \
+          boundaryValueSecondOrder solveTriDiagonal   \
+          newtonRaphson newtonRaphsonParameters
+
+   variable nr_maxiter    20
+   variable nr_tolerance   0.001
+
 }
 
-# Integral --
+# integral --
 #    Integrate a function over a given interval using the Simpson rule
 #
 # Arguments:
@@ -34,11 +39,11 @@
    set hdelta   [expr {$delta/2.0}]
    set result   0.0
    set xval     $begin
-   set func_end [$func $xval]
+   set func_end [uplevel 1 [list $func $xval]]
    for { set i 1 } { $i <= $nosteps } { incr i } {
       set func_begin  $func_end
-      set func_middle [$func [expr {$xval+$hdelta}]]
-      set func_end    [$func [expr {$xval+$delta}]]
+      set func_middle [uplevel 1 [list $func [expr {$xval+$hdelta}]]]
+      set func_end    [uplevel 1 [list $func [expr {$xval+$delta}]]]
       set result      [expr  {$result+$func_begin+4.0*$func_middle+$func_end}]
 
       set xval        [expr {$begin+double($i)*$delta}]
@@ -47,7 +52,7 @@
    return [expr {$result*$delta/6.0}]
 }
 
-# IntegralExpr --
+# integralExpr --
 #    Integrate an expression with "x" as the integrate according to the
 #    Simpson rule
 #
@@ -83,7 +88,7 @@
    return [expr {$result*$delta/6.0}]
 }
 
-# Integral2D --
+# integral2D --
 #    Integrate a given fucntion of two variables over a block,
 #    using bilinear interpolation (for this moment: block function)
 #
@@ -109,7 +114,7 @@
       set y [expr {$hydelta+double($j)*$ydelta}]
       for { set i 0 } { $i < $xnumber } { incr i } {
          set x           [expr {$hxdelta+double($i)*$xdelta}]
-         set func_value  [$func $x $y]
+         set func_value  [uplevel 1 [list $func $x $y]]
          set result      [expr {$result+$func_value}]
       }
    }
@@ -117,7 +122,7 @@
    return [expr {$result*$dxdy}]
 }
 
-# Integral3D --
+# integral3D --
 #    Integrate a given fucntion of two variables over a block,
 #    using trilinear interpolation (for this moment: block function)
 #
@@ -149,7 +154,7 @@
          set y [expr {$hydelta+double($j)*$ydelta}]
          for { set i 0 } { $i < $xnumber } { incr i } {
             set x           [expr {$hxdelta+double($i)*$xdelta}]
-            set func_value  [$func $x $y $z]
+            set func_value  [uplevel 1 [list $func $x $y $z]]
             set result      [expr {$result+$func_value}]
          }
       }
@@ -158,7 +163,7 @@
    return [expr {$result*$dxdydz}]
 }
 
-# EulerStep --
+# eulerStep --
 #    Integrate a system of ordinary differential equations of the type
 #    x' = f(x,t), where x is a vector of quantities. Integration is
 #    done over a single step according to Euler's method.
@@ -174,7 +179,7 @@
 #
 proc ::math::calculus::eulerStep { t tstep xvec func } {
 
-   set xderiv   [$func $t $xvec]
+   set xderiv   [uplevel 1 [list $func $t $xvec]]
    set result   {}
    foreach xv $xvec dx $xderiv {
       set xnew [expr {$xv+$tstep*$dx}]
@@ -184,7 +189,7 @@
    return $result
 }
 
-# HeunStep --
+# heunStep --
 #    Integrate a system of ordinary differential equations of the type
 #    x' = f(x,t), where x is a vector of quantities. Integration is
 #    done over a single step according to Heun's method.
@@ -203,13 +208,14 @@
    #
    # Predictor step
    #
-   set xpred    [eulerStep $t $tstep $xvec $func]
+   set funcq    [uplevel 1 [list ::namespace which -command $func]]
+   set xpred    [eulerStep $t $tstep $xvec $funcq]
 
    #
    # Corrector step
    #
    set tcorr    [expr {$t+$tstep}]
-   set xcorr    [eulerStep $t     $tstep $xpred $func]
+   set xcorr    [eulerStep $t     $tstep $xpred $funcq]
 
    set result   {}
    foreach xv $xvec xc $xcorr {
@@ -220,7 +226,7 @@
    return $result
 }
 
-# RungeKuttaStep --
+# rungeKuttaStep --
 #    Integrate a system of ordinary differential equations of the type
 #    x' = f(x,t), where x is a vector of quantities. Integration is
 #    done over a single step according to Runge-Kutta 4th order.
@@ -236,6 +242,8 @@
 #
 proc ::math::calculus::rungeKuttaStep { t tstep xvec func } {
 
+   set funcq    [uplevel 1 [list ::namespace which -command $func]]
+
    #
    # Four steps:
    # - k1 = tstep*func(t,x0)
@@ -247,25 +255,25 @@
    set tstep2   [expr {$tstep/2.0}]
    set tstep6   [expr {$tstep/6.0}]
 
-   set xk1      [$func $t $xvec]
+   set xk1      [$funcq $t $xvec]
    set xvec2    {}
    foreach x1 $xvec xv $xk1 {
       lappend xvec2 [expr {$x1+$tstep2*$xv}]
    }
 
-   set xk2      [$func [expr {$t+$tstep2}] $xvec2]
+   set xk2      [$funcq [expr {$t+$tstep2}] $xvec2]
    set xvec3    {}
    foreach x1 $xvec xv $xk2 {
       lappend xvec3 [expr {$x1+$tstep2*$xv}]
    }
 
-   set xk3      [$func [expr {$t+$tstep2}] $xvec3]
+   set xk3      [$funcq [expr {$t+$tstep2}] $xvec3]
    set xvec4    {}
    foreach x1 $xvec xv $xk3 {
       lappend xvec4 [expr {$x1+$tstep2*$xv}]
    }
 
-   set xk4      [$func [expr {$t+$tstep}] $xvec4]
+   set xk4      [$funcq [expr {$t+$tstep}] $xvec4]
    set result   {}
    foreach x0 $xvec k1 $xk1 k2 $xk2 k3 $xk3 k4 $xk4 {
       set dx [expr {$k1+2.0*$k2+2.0*$k3+$k4}]
@@ -275,7 +283,7 @@
    return $result
 }
 
-# BoundaryValueSecondOrder --
+# boundaryValueSecondOrder --
 #    Integrate a second-order differential equation and solve for
 #    given boundary values.
 #
@@ -301,6 +309,9 @@
 proc ::math::calculus::boundaryValueSecondOrder {
    coeff_func force_func leftbnd rightbnd nostep } {
 
+   set coeffq    [uplevel 1 [list ::namespace which -command $coeff_func]]
+   set forceq    [uplevel 1 [list ::namespace which -command $force_func]]
+
    if { [llength $leftbnd] != 2 || [llength $rightbnd] != 2 } {
       error "Boundary condition(s) incorrect"
    }
@@ -322,7 +333,7 @@
    set dvalue {}
 
    set x $xleft
-   foreach {A B C} [$coeff_func $x] { break }
+   foreach {A B C} [$coeffq $x] { break }
 
    set A1 [expr {$A/$xstep-0.5*$B}]
    set B1 [expr {$A/$xstep+0.5*$B+0.5*$C*$xstep}]
@@ -333,7 +344,7 @@
       if { [expr {abs($x)-0.5*abs($xstep)}] < 0.0 } {
          set x 0.0
       }
-      foreach {A B C} [$coeff_func $x] { break }
+      foreach {A B C} [$coeffq $x] { break }
 
       set A2 0.0
       set B2 [expr {$A/$xstep-0.5*$B+0.5*$C*$xstep}]
@@ -352,7 +363,7 @@
          set x 0.0
       }
       lappend xvec   $x
-      lappend dvalue [expr {$xstep*[$force_func $x]}]
+      lappend dvalue [expr {$xstep*[$forceq $x]}]
    }
 
    #
@@ -374,7 +385,7 @@
    return $result
 }
 
-# SolveTriDiagonal --
+# solveTriDiagonal --
 #    Solve a system of equations Ax = b where A is a tridiagonal matrix
 #
 # Arguments:
@@ -429,5 +440,63 @@
    return $yvec
 }
 
-# Now we can announce our presence.
-package provide math::calculus 0.3
+# newtonRaphson --
+#    Determine the root of an equation via the Newton-Raphson method
+#
+# Arguments:
+#    func        Function (proc) in x
+#    deriv       Derivative (proc) of func w.r.t. x
+#    initval     Initial value for x
+# Return value:
+#    Estimate of root
+#
+proc ::math::calculus::newtonRaphson { func deriv initval } {
+   variable nr_maxiter
+   variable nr_tolerance
+
+   set funcq  [uplevel 1 [list ::namespace which -command $func]]
+   set derivq [uplevel 1 [list ::namespace which -command $deriv]]
+
+   set value $initval
+   set diff  [expr {10.0*$nr_tolerance}]
+
+   for { set i 0 } { $i < $nr_maxiter } { incr i } {
+      if { $diff < $nr_tolerance } {
+         break
+      }
+
+      set newval [expr {$value-[$funcq $value]/[$derivq $value]}]
+      if { $value != 0.0 } {
+         set diff   [expr {abs($newval-$value)/abs($value)}]
+      } else {
+         set diff   [expr {abs($newval-$value)}]
+      }
+      set value $newval
+   }
+
+   return $newval
+}
+
+# newtonRaphsonParameters --
+#    Set the parameters for the Newton-Raphson method
+#
+# Arguments:
+#    maxiter     Maximum number of iterations
+#    tolerance   Relative precisiion of the result
+# Return value:
+#    None
+#
+proc ::math::calculus::newtonRaphsonParameters { maxiter tolerance } {
+   variable nr_maxiter
+   variable nr_tolerance
+
+   if { $maxiter > 0 } {
+      set nr_maxiter $maxiter
+   }
+   if { $tolerance > 0 } {
+      set nr_tolerance $tolerance
+   }
+}
+
+# Now we can announce our presence
+package provide math::calculus 0.5
Index: modules/math/calculus.test
===================================================================
RCS file: /cvsroot/tcllib/tcllib/modules/math/calculus.test,v
retrieving revision 1.2
diff -u -r1.2 calculus.test
--- modules/math/calculus.test	8 May 2002 16:35:25 -0000	1.2
+++ modules/math/calculus.test	31 May 2002 20:59:52 -0000
@@ -13,16 +13,13 @@
 #
 # Simple test functions - exact result predictable!
 #
-proc ::const_func { x } {
+proc const_func { x } {
    return 1
 }
-proc ::linear_func { x } {
+proc linear_func { x } {
    return $x
 }
-proc ::downward_linear { x } {
-   return [expr {100.0-$x}]
-}
-proc ::downward_linear { x } {
+proc downward_linear { x } {
    return [expr {100.0-$x}]
 }
 
@@ -46,10 +43,10 @@
 } 5000.0
 
 
-proc ::const_func2d { x y } {
+proc const_func2d { x y } {
    return 1
 }
-proc ::linear_func2d { x y } {
+proc linear_func2d { x y } {
    return $x
 }
 
@@ -64,14 +61,19 @@
 } 250000.0
 
 #
+# Note:
+# Test cases for integral3D are missing!
+#
+
+#
 # Test cases: yet to be brought into the tcltest form!
 #
 
 # xvec should one long!
-proc ::const_func { t xvec } { return 1.0 }
+proc const_func { t xvec } { return 1.0 }
 
 # xvec should be two long!
-proc ::dampened_oscillator { t xvec } {
+proc dampened_oscillator { t xvec } {
    set x  [lindex $xvec 0]
    set x1 [lindex $xvec 1]
    return [list $x1 [expr {-$x1-$x}]]
@@ -103,13 +105,49 @@
 
 #
 # Boundary value problems:
-# use simple functions
 #
-proc ::coeffs { x } { return {1.0 0.0 0.0} }
-proc ::forces { x } { return 0.0 }
+proc coeffs { x } { return {1.0 0.0 0.0} }
+proc forces { x } { return 0.0 }
 
 puts [boundaryValueSecondOrder coeffs forces {0.0 1.0} {100.0 0.0} 10]
 puts [boundaryValueSecondOrder coeffs forces {0.0 0.0} {100.0 1.0} 10]
+
+#
+# Determining the root of an equation
+# use simple functions
+#
+proc func  { x } { expr {$x*$x-1.0} }
+proc deriv { x } { expr {2.0*$x} }
+
+test "NewtonRaphson-1.0" "Result should be 1" {
+   set result [newtonRaphson func deriv 2.0]
+   if { abs($result-1.0) < 0.0001 } {
+      set answer 1
+   }
+} 1
+test "NewtonRaphson-1.1" "Result should be -1" {
+   set result [newtonRaphson func deriv -0.5]
+   if { abs($result+1.0) < 0.0001 } {
+      set answer 1
+   }
+} 1
+
+proc func2  { x } { expr {$x*exp($x)-1.0} }
+proc deriv2 { x } { expr {exp($x)+$x*exp($x)} }
+
+test "NewtonRaphson-2.1" "Result should be nearly 0.56714" {
+   set result [newtonRaphson func2 deriv2 2.0]
+   if { abs($result-0.56714) < 0.0001 } {
+      set answer 1
+   }
+} 1
+
+test "NewtonRaphson-2.1" "Result should be nearly 0.56714" {
+   set result [newtonRaphson func2 deriv2 -0.5]
+   if { abs($result-0.56714) < 0.0001 } {
+      set answer 1
+   }
+} 1
 
 cleanupTests
 }