EllipticFunction.hpp
Go to the documentation of this file.
00001 /**
00002  * \file EllipticFunction.hpp
00003  * \brief Header for GeographicLib::EllipticFunction class
00004  *
00005  * Copyright (c) Charles Karney (2008) <charles@karney.com>
00006  * and licensed under the LGPL.
00007  **********************************************************************/
00008 
00009 #if !defined(ELLIPTICFUNCTION_HPP)
00010 #define ELLIPTICFUNCTION_HPP "$Id: EllipticFunction.hpp 6535 2009-02-10 22:37:07Z ckarney $"
00011 
00012 
00013 namespace GeographicLib {
00014 
00015   /**
00016    * \brief Elliptic functions needed for TransverseMercatorExact
00017    *
00018    * This provides the subset of elliptic functions needed for
00019    * TransverseMercatorExact.  For a given ellipsoid, only parameters \e
00020    * e<sup>2</sup> and 1 - \e e<sup>2</sup> are needed.  This class taken the
00021    * parameter as a constructor parameters and caches the values of the
00022    * required complete integrals.  A method is provided for Jacobi elliptic
00023    * functions and for the incomplete elliptic integral of the second kind in
00024    * terms of the amplitude.
00025    *
00026    * The computation of the elliptic integrals uses the algorithms given in
00027    * - B. C. Carlson,
00028    *   <a href="http://dx.doi.org/10.1007/BF02198293"> Computation of elliptic
00029    *   integrals</a>, Numerical Algorithms 10, 13&ndash;26 (1995).
00030    * .
00031    * The computation of the Jacobi elliptic functions uses the algorithm given
00032    * in
00033    * - R. Bulirsch,
00034    *   <a href="http://dx.doi.org/10.1007/BF01397975"> Numerical Calculation of
00035    *   Elliptic Integrals and Elliptic Functions</a>, Numericshe Mathematik 7,
00036    *   78&ndash;90 (1965).
00037    * .
00038    * The notation follows Abramowitz and Stegun, Chapters 16 and 17.
00039    **********************************************************************/
00040   class EllipticFunction {
00041   private:
00042     static const double tol, tolRF, tolRD, tolRG0, tolJAC, tolJAC1;
00043     enum { num = 10 }; // Max depth required for sncndn.  Probably 5 is enough.
00044     static double RF(double x, double y, double z) throw();
00045     static double RD(double x, double y, double z) throw();
00046     static double RG0(double x, double y) throw();
00047     const double _m, _m1;
00048     mutable bool _init;
00049     mutable double _kc, _ec, _kec;
00050     bool Init() const throw();
00051   public:
00052 
00053     /**
00054      * Constructor with parameter \e m.
00055      **********************************************************************/
00056     EllipticFunction(double m) throw();
00057 
00058     /**
00059      * The parameter \e m.
00060      **********************************************************************/
00061     double m() const throw() { return _m; }
00062 
00063     /**
00064      * The complementary parameter \e m' = (1 - \e m).
00065      **********************************************************************/
00066     double m1() const throw() { return _m1; }
00067 
00068     /**
00069      * The complete integral of first kind, \e K(\e m).
00070      **********************************************************************/
00071     double K() const throw() { _init || Init(); return _kc; }
00072 
00073     /**
00074      * The complete integral of second kind, \e E(\e m).
00075      **********************************************************************/
00076     double E() const throw() { _init || Init(); return _ec; }
00077 
00078     /**
00079      * The difference \e K(\e m) - \e E(\e m) (which can be computed directly).
00080      **********************************************************************/
00081     double KE() const throw() { _init || Init(); return _kec; }
00082 
00083     /**
00084      * The Jacobi elliptic functions sn(<i>x</i>|<i>m</i>),
00085      * cn(<i>x</i>|<i>m</i>), and dn(<i>x</i>|<i>m</i>) with argument \e x.
00086      * The results are returned in \e sn, \e cn, and \e dn.
00087      **********************************************************************/
00088     void sncndn(double x, double& sn, double& cn, double& dn) const throw();
00089 
00090     /**
00091      * The incomplete integral of the second kind = int dn(\e w)<sup>2</sup> \e
00092      * dw (A+S 17.2.10).  Instead of specifying the ampltiude \e phi, we
00093      * provide \e sn = sin(\e phi), \e cn = cos(\e phi), \e dn = sqrt(1 - \e m
00094      * sin<sup>2</sup>(\e phi)).
00095      **********************************************************************/
00096     double E(double sn, double cn, double dn) const throw();
00097   };
00098 
00099 
00100 } // namespace GeographicLib
00101 
00102 #endif