Michael Thomas Flanagan's Java Scientific Library

RealRoot Class:     Root Searching Methods

     

Last update: 30 January 2010                                                                                                                             PERMISSION TO COPY

This class contains the following root search procedures: plus methods returning
See the roots section of the ComplexPoly class for:
   roots of a complex quadratic,    roots of a complex cubic,    roots of a complex polynomial.

A function, whose root is required and will be found using one of the search procedures, is supplied by means of the interface, RealRootFunction or the interface, RealRootDerivFunction, if the first derivative is also needed, e.g. in the Newton-Raphson procedure.

import statement/s: import flanagan.roots.RealRoot;
import flanagan.roots.RealRootFunction; [all but Newton Raphson]
import flanagan.roots.RealRootDerivFunction; [Newton Raphson]

SUMMARY OF METHODS

Constructor public RealRoot()
Combined Bisection and Newton-Raphson method public double bisectNewtonRaphson(RealRootDerivFunction rrf, double lower, double upper)
public double bisectNewtonRaphson(RealRootDerivFunction rrf)
public static double bisectNewtonRaphson(RealRootDerivFunction rrf, double lower, double upper, double tolerance)
Newton-Raphson method public double newtonRaphson(RealRootDerivFunction rrf, double estimate)
public double newtonRaphson(RealRootDerivFunction rrf)
public static double newtonRaphson(RealRootDerivFunction rrf, double estimate, double tolerance)
Combined Bisection and Inverse Quadratic Interpolation [Brent] method public double brent(RealRootFunction rrf, double lower, double upper)
public double brent(RealRootFunction rrf)
public static double brent(RealRootFunction rrf, double lower, double upper, double tolerance)
Bisection method public double bisect(RealRootFunction rrf, double lower, double upper)
public double bisect(RealRootFunction rrf)
public static double bisect(RealRootFunction rrf, double lower, double upper, double tolerance)
False Position method public double falsePosition(RealRootFunction rrf, double lower, double upper)
public double falsePosition(RealRootFunction rrf)
public static double falsePosition(RealRootFunction rrf, double lower, double upper, double tolerance)
Root Accuracy public void setTolerance(double accuracy)
public double getTolerance()
Number of iterations public void setIterMax(int maxIter)
public static void setStaticIterMax(int maxIter)
public int getIterMax()
public static int getStaticIterMax()
public int getIterN()
Set initial estimate of the root public void setEstimate(double estimate)
Set bounds to the root public void setLowerBound(double lower)
public void setUpperBound(double upper)
Extension to initial estimates of the root bounds public void setMaximumBoundsExtensions(int maximumBoundsExtension)
public static void setStaticMaximumBoundsExtensions(int maximumBoundsExtension)
public void noBoundsExtensions()
public static void noStaticBoundsExtensions()
public void noLowerBoundExtension()
public static void noStaticLowerBoundExtension()
public void noUpperBoundExtension()
public static void noStaticUpperBoundExtension()
"NaN root" handling public void resetNaNexceptionToTrue()
public static void resetStaticNaNexceptionToTrue()
public void resetNaNexceptionToFalse()
public static void resetStaticNaNexceptionToFalse()
Suppress 'iteration limit reached' message public void suppressLimitReachedMessage()
Roots of a quadratic public static ArrayList<Object> quadratic(double a, double b, double c)
Roots of a cubic public static ArrayList<Object> cubic(double a, double b, double c, double d)
Roots of a polynomial public static ArrayList<Object> polynomial(double[] coefficients)
public static ArrayList<Object> polynomial(double[] coefficients, boolean polish)
public static ArrayList<Object> polynomial(double[] coefficients, double estimate)
public static ArrayList<Object> polynomial(double[] coefficients, boolean polish, double estimate)
Reset test for real roots public static void resetRealTest(double toleranceRatio)



CONSTRUCTOR

public RealRoot()
Usage:                     RealRoot rlrt = new RealRoot()

METHODS

COMBINED BISECTION AND NEWTON-RAPHSON METHOD
public double bisectNewtonRaphson(RealRootDerivFunction rrf, double lower, double upper)
public double bisectNewtonRaphson(RealRootDerivFunction rrf)
public static double bisectNewtonRaphson(RealRootDerivFunction rrf, double lower, double upper, double tolerance)

Usage:                     root = rlrt.bisectNewtonRaphson(rrf, lower, upper);
Returns the root, to root in the above usage, of the function coded in the RealRootDerivFunction, rrf [see below for coding the function and its derivative].
lower is the estimate of the lower bound of the bracket containing the root.
upper is the estimate of the upper bound of the bracket containing the root.
The tolerance for exiting the search and the maximum number of iterations are set by the methods listed below.
The search starts with a Newton-Raphson step with (lower+upper)/2 as the initial estimate of the root. If the next value of the root is projected outside the bracket defined by lower and lower the result is ignored and a Bisection step is used. After each Bisection step a Newton-Raphson step is attempted but ignored if the projected root value lies outside the bracket of updated lower and upper values. If a Newton-Raphson step is successful the Newton-Raphson procedure is continued until any projection outside the last updated set of brackets.
Also sets the lower and upper bounds for subsequent calls to a root search procedure that does not pass these as arguments.

Usage:                     root = rlrt.bisectNewtonRaphson(rrf);
As immediately above with the exception that the lower and upper bounds must have previously been set by either bounds set methods or a call to an instance method with lower and upper bounds as arguments.

Usage:                     root = RealRoot.bisectNewtonRaphson(rrf, lower, upper, tolerance);
A static method corresponding to the two above instance method but with the exit tolerance supplied as one of the method's arguments.



NEWTON-RAPHSON METHOD
public double NewtonRaphson(RealRootDerivFunction rrf, double estimate)
public double NewtonRaphson(RealRootDerivFunction rrf)
public static double NewtonRaphson(RealRootDerivFunction rrf, double estimate, double tolerance)

Usage:                     root = rlrt.NewtoRaphson(rrf, estimate);
Returns the root, to root in the above usage, of the function coded in the RealRootDerivFunction, rrf [see below for coding the function and its derivative].
estimate is the initial estimate of the root.
The tolerance for exiting the search and the maximum number of iterations are set by the methods listed below.
This method carries out a Newton-Raphson root search.
Also sets the initial estimate for subsequent calls to a root search procedure that does not pass this as an argument.

Usage:                     root = rlrt.NewtoRaphson(rrf);
As immediately above with the exception that the estimate must have previously been set by either an estimate set method or a call to an instance method with estimate as an argument.

Usage:                     root = RealRoot.NewtoRaphson(rrf, estimate, tolerance);
A static method corresponding to the two above instance method but with the exit tolerance supplied as one of the method's arguments.



COMBINED BISECTION AND INVERSE QUADRATIC INTERPOLATION METHOD [BRENT METHOD]
public double brent(RealRootFunction rrf, double lower, double upper)
public double brent(RealRootFunction rrf)
public static double brent(RealRootFunction rrf, double lower, double upper, double tolerance)

Usage:                     root = rlrt.brent(rrf, lower, upper);
Returns the root, to root in the above usage, of the function coded in the RealRootFunction, rrf [see below for coding the function].
lower is the estimate of the lower bound of the bracket containing the root.
upper is the estimate of the upper bound of the bracket containing the root. The tolerance for exiting the search and the maximum number of iterations are set by the methods listed below.
The search starts with an inverse quadratic interpolation step with lower, (lower+upper)/2 and upper as the three initial interpolation procedure points. If the next value of the root is projected outside the bracket defined by lower and lower the result is ignored and a Bisection step is used. After each Bisection step an inverse quadratic interpolation step is attempted but ignored if the projected root value lies outside the bracket of updated lower and upper values. If an inverse quadratic interpolation step is successful the inverse quadratic interpolationprocedure is continued until any projection outside the last updated set of brackets. This is an implementation of Brent's modification of the algorithm of van Wingaarden, Dekker et al. [Brent, R.P. 1973, Algorithms for Minimization without Derivatives (Englewood Cliffs, NJ: Prentice-Hall) Chapters 3 and 4.
Also sets the lower and upper bounds for subsequent calls to a root search procedure that does not pass these as arguments.

Usage:                     root = rlrt.brent(rrf, lower, upper);
As immediately above with the exception that the lower and upper bounds must have previously been set by either bounds set methods or a call to an instance method with lower and upper bounds as arguments.

Usage:                     root = RealRoot.brent(rrf, lower, upper, tolerance);
A static method corresponding to the two above instance method but with the exit tolerance supplied as one of the method's arguments.



BISECTION METHOD
public double bisect(RealRootFunction rrf, double lower, double upper)
public double bisect(RealRootFunction rrf)
public static double bisect(RealRootFunction rrf, double lower, double upper, double tolerance)

Usage:                     root = rlrt.bisect(rrf, lower, upper);
Returns the root, to root in the above usage, of the function coded in the RealRootFunction, rrf [see below for coding the function].
lower is the estimate of the lower bound of the bracket containing the root.
upper is the estimate of the upper bound of the bracket containing the root.
The tolerance for exiting the search and the maximum number of iterations are set by the methods listed below.
The method performs a bisection method root search. Also sets the lower and upper bounds for subsequent calls to a root search procedure that does not pass these as arguments.

Usage:                     root = rlrt.bisect(rrf);
As immediately above with the exception that the lower and upper bounds must have previously been set by either bounds set methods or a call to an instance method with lower and upper bounds as arguments.

Usage:                     root = RealRoot.bisect(rrf, lower, upper, tolerance);
A static method corresponding to the two above instance method but with the exit tolerance supplied as one of the method's arguments.



FALSE POSITION METHOD
public double falsePosition(RealRootFunction rrf, double lower, double upper)
public double falsePosition(RealRootFunction rrf)
public static double falsePosition(RealRootFunction rrf, double lower, double upper, double tolerance)

Usage:                     root = rlrt.falsePosition(rrf, lower, upper);
Returns the root, to root in the above usage, of the function coded in the RealRootFunction, rrf [see below for coding the function].
lower is the estimate of the lower bound of the bracket containing the root.
upper is the estimate of the upper bound of the bracket containing the root.
The tolerance for exiting the search and the maximum number of iterations are set by the methods listed below.
The method performs a false position method root search.
Also sets the lower and upper bounds for subsequent calls to a root search procedure that does not pass these as arguments.

Usage:                     root = rlrt.falsePosition(rrf);
As immediately above with the exception that the lower and upper bounds must have previously been set by either bounds set methods or a call to an instance method with lower and upper bounds as arguments.

Usage:                     root = RealRoot.falsePosition(rrf, lower, upper, tolerance);
A static method corresponding to the two above instance method but with the exit tolerance supplied as one of the method's arguments.



CODING THE FUNCTION WHOSE ROOT IS REQUIRED
The mathematical function whose root is required, func(x), must be coded as one of the following methods Any constants in the function, whose root is required, that are not fixed should be declared as public static members of the class of which function(x) is a member. Their values may be set in that declaration and can be reset within the calling program (see Example Program below)

The function is passed to the root search method as an instance of the class containing the method function(x). This instance should be created in the application or method that calls one of the above root search methods. This procedure can be seen more clearly in the Example program demonstrating the use of root searching.



ACCURACY OF THE VALUE OF THE RETURNED ROOT
Resetting the value of the required accuracy
public void setTolerance(double tolerance)
Usage:                     rlrt.setTolerance(tolerance);
Resets, for instance methods, the value of the tolerance [tolerance] in determining whether the search has converged on a root. The convergence is terminated when two successive estimates of the function differ by less than this tolerance [tolerance]. If this tolerance has not been met when the maximum number of iterations has been reached an error message is printed on the screen and the current estimate of the root is returned. The preset default value of the tolerance is 1e-9. This value is fixed in the static methods.

Getting the value of the required accuracy
public int getTolerance()
Usage:                     tolerance = rlrt.getTolerance();
Returns, for instance methods, the value of the root tolerance. The convergence is terminated when two successive estimates of the function differ by less than this tolerance [tolerance]. If this tolerance has not been met when the maximum number of iterations has been reached an error message is printed on the screen and the current estimate of the root is returned. The preset default value of the tolerance is 1e-9. This value is fixed in the static methods.



NUMBER OF ITERATIONS
Resetting the maximum number of iterations allowed
public void setIterMax(double accuracy)
Usage:                     rlrt.setIterMax(nmax);
Resets, for the instance methods, the value of the maximum number of iterations allowed in the search procedure [nmax]. The preset default value is 3000. If convergence does not occur before the maximum number of iterations has been reached an error message is printed on the screen and the current estimate of the root is returned. This value is fixed at 3000 in the static methods.

Getting the maximum number of iterations allowed
public int getIterMax()
Usage:                     maxN = rlrt.getIterMax();
Returns the value of the maximum number of iterations allowed in the instance method search procedures. The preset default value is 3000. If convergence does not occur before the maximum number of iterations has been reached an error message is printed on the screen and the current estimate of the root is returned.

Getting the number of iterations that occured
public int getIterN()
Usage:                     iterN = rlrt.getIterN();
Returns the value of the number of iterations, for instance methods, that occurred in the last search procedure.



SETTING THE ROOT ESTIMATE
public void setEstimate(double lestimate)
Usage:                     rlrt.setEstimate(estimate);
Sets the value of the estimate the root for the instance Newton-Raphson. This method also allow the estimate to be passed in its argument list.



SETTING THE BOUNDS
Setting the value of the lower bound
public void setLowerBound(double lowerBound)
Usage:                     rlrt.setLowerBound(lowerBound);
Sets the value of the lower bound to the root for the instance bisection and false position methods. All these methods also allow the bounds to be passed in their argument lists.

Setting the value of the upper bound
public void setLowerBound(double upperBound)
Usage:                     rlrt.setUpperBound(lowerBound);
Sets the value of the upper bound to the root for the instance bisection and false position methods. All these methods also allow the bounds to be passed in their argument lists.



EXTENSION TO THE INITIAL ESTIMATES OF THE ROOT BOUNDS
Resetting the maximum number of extensions allowed
public void setMaximumBoundsExtensions(int maximumBoundsExtension)
public staticvoid setStaticMaximumBoundsExtensions(int maximumBoundsExtension)
Usage:                     rlrt.setMaximumBoundsExtensions(maximumBoundsExtension);
Resets, for the instance rlrt, the value of the maximum number of extensions to the initial estimates of the bounds allowed. If the root is found not to be bounded by the initial estimates of the bounds the default option of the above methods is to extend the bounds in an attempt to encompass the root. If extensions to both the upper and lower bounds are allowed the lower and upper bound are both extended by half the difference between the initial lower and upper bound estimates on each extension. If either the lower or upper bound are fixed (see below) only the bound that is not fixed is extended. The default value of the maximum number of extensions is 100.

Usage:                     realRoot.setStaticMaximumBoundsExtensions(maximumBoundsExtension);
Resets, for the static methods within an application, the value of the maximum number of extensions to the initial estimates of the bounds allowed. If the root is found not to be bounded by the initial estimates of the bounds the default option of the above methods is to extend the bounds in an attempt to encompass the root. If extensions to both the upper and lower bounds are allowed the lower and upper bound are both extended by half the difference between the initial lower and upper bound estimates on each extension. If either the lower or upper bound are fixed (see below) only the bound that is not fixed is extended. The default value of the maximum number of extensions is 100.


Preventing any extension to the initial estimates of the bounds
public void noBoundsExtensions()
public static void noBoundsExtensions()
Usage:                     rlrt.noBoundsExtensions();
Calling this method prevents, in the instance rlrt, any extension to the initial estimates of the root bounds.

Usage:                     RealRoot.noStaticBoundsExtensions();
Calling this method prevents, in the static methods within an application, any extension to the initial estimates of the root bounds.

Preventing an extension to the estimate of the lower bound to the root value
public void noLowerBoundExtension()
public static void noStaticLowerBoundExtension()
Usage:                     rlrt.noLowerBoundExtension();
Calling this method prevents, in the instance rlrt, any extension to the initial estimate of the lower bound to the value of the root. The estimate of the upper bound only will be extended, on each extension, by half the difference between the initial lower and upper bound estimates.

Usage:                     RealRoot.noStaticLowerBoundExtension();
Calling this method prevents, in the static methods within an application, any extension to the initial estimate of the lower bound to the value of the root. The estimate of the upper bound only will be extended, on each extension, by half the difference between the initial lower and upper bound estimates.

Preventing an extension to the estimate of the upper bound to the root value
public void noUpperBoundExtension()
public static void noStaticUpperBoundExtension()
Usage:                     rlrt.noUpperBoundExtension();
Calling this method prevents, in the instance rlrt, any extension to the initial estimate of the upper bound to the value of the root. The estimate of the lower bound only will be extended, on each extension, by half the difference between the initial lower and upper bound estimates.

Usage:                     RealRoot.noStaticUpperBoundExtension();
Calling this method prevents, in the static methods within an application, any extension to the initial estimate of the upper bound to the value of the root. The estimate of the lower bound only will be extended, on each extension, by half the difference between the initial lower and upper bound estimates.



HANDLING ROOTS CALCULATED AS NaN
public void resetNaNexceptionToTrue()
public static void resetStaticNaNexceptionToTrue()
public void resetNaNexceptionToFalse()
public static void resetStaticNaNexceptionToFalse()
Usage:                     rlrt.resetNaNexceptionToTrue();
If the calculation of a root returns a NaN value the default option of this class is to throw an exception and terminate the execution of the program. This method overrides this option in the instance rlrt and allows the program to continue returning Double.NaN as the root.
USE WITH CARE: this method has been included to accomodate the use of RealRoot in certain methods in the PsRandom and Stat classes.

Usage:                     RealRoot.resetStaticNaNexceptionToTrue();
If the calculation of a root returns a NaN value the default option of this class is to throw an exception and terminate the execution of the program. This method overrides this option in the static methods within an application and allows the program to continue returning Double.NaN as the root.
USE WITH CARE: this method has been included to accomodate the use of RealRoot in certain methods in the PsRandom and Stat classes.

Usage:                     rlrt.resetNaNexceptionToFalse();
This method resets the handling of roots calculated as NaN, in the instance rlrt, to the default option. See above for a description of the options.

Usage:                     RealRoot.resetStaticNaNexceptionToFalsee();
This method resets the handling of roots calculated as NaN, in the static methods within an application, to the default option. See above for a description of the options.



SUPPRESSING THE 'ITERATION LIMIT REACHED' MESSAGE
public void suppressLimitReachedMessage()
Usage:                     rlrt.suppressLimitReachedMessage();
Suppresses the message that is printed to screen if the maximum number of iterations in the root search is reached and which prints the number of iterations, the difference between the last two estimates, the tolerance and the last estimate of the root which is the value returned.
USE WITH CARE: this method has been included to accomodate a specific application using this class.



ROOTS OF A QUADRATIC
public static ArrayList<Object> quadratic(double a, double b, double c)
Usage:                      arraylist = RealRoot.quadratic(a, b, c);
Calculates the roots of the quadratic
                     a + b.x + c.x2 = 0
If all the roots are real, the returned ArrayList, arraylist, contains the two elements
If one or more roots are complex, the returned ArrayList, arraylist, contains the two elements
NB the order of the coefficients a, b and c.
Uses the procedures needed to avoid rounding errors as described by Press et al.
NB the order of the coefficients a, b, c and d.
Uses the procedures needed to avoid rounding errors as described by Press et al.
See ComplexPoly for


ROOTS OF A CUBIC
public static ArrayList<Object> cubic(double a, double b, double c, double d)
Usage:                      arraylist = RealRoot.quadratic(a, b, c, d);
Calculates the roots of the cubic
                     a + b.x + c.x2 + d.x3 = 0
If all the roots are real, the returned ArrayList, arraylist, contains the two elements
If one or more roots are complex, the returned ArrayList, arraylist, contains the two elements
NB the order of the coefficients a, b, c and d.
Uses the procedures needed to avoid rounding errors as described by Press et al.
See ComplexPoly for


ROOT OF A POLYNOMIAL
For general details of root searching and a discussion of the rounding errors in root searching see Numerical Recipes, The Art of Scientific Computing by W H Press, S A Teukolsky, W T Vetterling & B P Flannery, Cambridge University Press (http://www.nr.com/).

public static ArrayList<Object> polynomial(double coefficients[])
public static ArrayList<Object> polynomial(double coefficients[], boolean polish)
public static ArrayList<Object> polynomial(double coefficients[], double estx)
public static ArrayList<Object> polynomial(double coefficients[], boolean polish, double estx)

Usage:                      arraylist = RealRoot.polynomial(coefficients);
Usage:                      arraylist = RealRoot.polynomial(coefficients, polish);
Usage:                      arraylist = RealRoot.polynomial(coefficients, estx);
Usage:                      arraylist = RealRoot.polynomial(coefficients, polish, estx);

Calculates the roots of the polynomial of degree, n,
                     a0 + a1.x + a2.x2 + a3.x3 + . . . + an.xn = 0
If all the roots are real, the returned ArrayList, arraylist, contains the two elements
If one or more roots are complex, the returned ArrayList, arraylist, contains the two elements
NB the order of the coefficients a0, a1, a2 ... an. The array, Coefficients, must contain the coefficients in this order.
  • Polynomial degree>3: The method polynomial(..) uses the Laguerre procedure to calculate the roots.
    The boolean variable polish invokes root polishing if true. If polish is not included in the argument list its default value is true.
    The double variable estx is the initial estimate of the roots needed by the Laguerre procedure. If estx is not included in the argument list its default value is zero. The default value of zero is the preferred value of estx.
    Though the Laguerre procedure is a robust method it is not possible to guarantee the return of the exact roots for polynomials of degree>3. If possible the results should be inspected as to their reasonableness in the light of the physical model that the polynomial represents.
  • Polynomial degree=3: This method calls the method RealRoot.cubic(a,b,c,d)
    polish and estx are NOT required.
  • Polynomial degree=2: This method calls the method RealRoot.quadratic(a,b,c)
    polish and estx are NOT required.
  • Polynomial degree=1: This method claculates the root as -coefficient[0]/coefficient[1].
    polish and estx are NOT required.
  • Polynomial degree=0: This method throws an IllegalArgumentException.
  • The roots for polynomials of degree 4 or higher are calculated in complex arithmetic. If all such roots have a ratio of the imaginary part over the real part less than 1.0 x 10-14 they are treated as real and their real parts stored as an array of double, to be returned as the roots. See below for a method allowing the resetting of this test value of 1.0 x 10-14.
    See ComplexPoly for


    RESETTING TEST FOR REAL ROOTS
    public static void resetRealTest(double toleranceRatio)
    Usage:                      RealRoot.resetRealTest(toleranceRatio);
    The roots for polynomials of degree 4 or higher are calculated in complex arithmetic. If all such roots have a ratio of the imaginary part over the real part less than 1.0 x 10-14 they are treated as real and their real parts stored as an array of double, to be returned as the roots. This method allows the resetting of this test value from 1.0 x 10-14 to the user value supplied as the argument, toleranceRatio.



    EXAMPLE PROGAM

    Source code for RealRootExample.java

    /*     Example of the use of the class RealRoot demonstrating
             the use of the method, RealRoot.bisectNewtonRaphson
             in finding a root of the function, y = a.x^b - 2 */


    import flanagan.roots.*;

    // Class to evaluate the function y = a.x^b -2 and its derivative, a.b.x^(b-1)
    class Funct implements RealRootDerivFunction{

             private double a = 1.0D;
             private double b = 2.0D;

             public double[ ] function(double x){
                      double[ ] y = new double[2];

                      y[0] = a*Math.pow(x,b) - 2.0D;
                      y[1] = a*b*Math.pow(x,b-1.0D);
                      return y;
             }

             public void setA(double a){
                      this.a = a;
             }

             public void setB(double b){
                      this.b = b;
             }
    }

    // Class to demonstrate method, RealRoot.bisectNewtonRaphson.
    public class RealRootExample{

             public static void main(String[] arg){

                      // Create instance of the class holding the function, y = ax^b - 2, and its derivative
                      Funct func = new Funct();

                      // Change value of constant a in the function
                      func.setA(2.0D);

                      // lower bound
                      double lowerBound = 0.0D;
                      // upper bound
                      double upperBound = 2.0D;
                      // required tolerance
                      double tolerance = 1e-6;

                      // Create instance of RealRoot
                      RealRoot  realR = new RealRoot();

                      // Set tolerance
                      realR.setTolerance(tolerance);

                      // Call root searching method, bisectNewtonRaphson
                      double root = realR.bisectNewtonRaphson(func, lowerBound, upperBound);

                      // Print root
                      System.out.println("root = " + root);

             }
    }




    OTHER CLASSES USED BY THIS CLASS

    This class uses the following classes in this library:



    PERMISSION TO COPY

    Permission to use, copy and modify this software and its documentation for NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement to the author, Dr Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies and associated documentation or publications. Dr Michael Thomas Flanagan makes no representations about the suitability or fitness of the software for any or for a particular purpose. Dr Michael Thomas Flanagan shall not be liable for any damages suffered as a result of using, modifying or distributing this software or its derivatives.

    Redistributions of the source code of this class, or parts of the source codes, must retain the copyright notice, this list of conditions and the following disclaimer (all at the top of the source code) and requires written permission from the Michael Thomas Flanagan:

    Redistribution in binary form of all or parts of this class must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution and requires written permission from the Michael Thomas Flanagan:
    .



    This page was prepared by Dr Michael Thomas Flanagan