elliptic-integrals-0.1.0.0: src/Math/EllipticIntegrals/Elliptic.hs
module Math.EllipticIntegrals.Elliptic
where
import Math.EllipticIntegrals.Carlson
import Data.Complex
import Math.EllipticIntegrals.Internal
-- | Elliptic integral of the first kind.
ellipticF' ::
Double -- ^ bound on the relative error passed to `carlsonRF'`
-> Cplx -- ^ amplitude
-> Cplx -- ^ parameter
-> Cplx
ellipticF' err phi m
| phi == 0 =
toCplx 0
| m == 1 && abs(realPart phi) == pi/2 =
toCplx (0/0)
| m == 1 && abs(realPart phi) < pi/2 =
atanh(sin phi)
| abs(realPart phi) <= pi/2 =
if m == 0
then
phi
else
let sine = sin phi in
let sine2 = sine*sine in
let (cosine2, oneminusmsine2) = (1 - sine2, 1 - m*sine2) in
sine * carlsonRF' err cosine2 oneminusmsine2 1
| otherwise =
let (phi', k) = getPhiK phi in
2 * fromIntegral k * ellipticF' err (pi/2) m + ellipticF' err phi' m
-- | Elliptic integral of the first kind.
ellipticF ::
Cplx -- ^ amplitude
-> Cplx -- ^ parameter
-> Cplx
ellipticF = ellipticF' 1e-15
-- | Elliptic integral of the second kind.
ellipticE' ::
Double -- ^ bound on the relative error passed to `carlsonRF'` and `carlsonRD'`
-> Cplx -- ^ amplitude
-> Cplx -- ^ parameter
-> Cplx
ellipticE' err phi m
| phi == 0 =
toCplx 0
| abs(realPart phi) <= pi/2 =
case m of
0 -> phi
1 -> sin phi
_ ->
let sine = sin phi in
let sine2 = sine*sine in
let (cosine2, oneminusmsine2) = (1 - sine2, 1 - m*sine2) in
sine * (carlsonRF' err cosine2 oneminusmsine2 1 -
m * sine2 / 3 * carlsonRD' err cosine2 oneminusmsine2 1)
| otherwise =
let (phi', k) = getPhiK phi in
2 * fromIntegral k * ellipticE' err (pi/2) m + ellipticE' err phi' m
-- | Elliptic integral of the second kind.
ellipticE ::
Cplx -- ^ amplitude
-> Cplx -- ^ parameter
-> Cplx
ellipticE = ellipticE' 1e-15
-- | Elliptic integral of the third kind.
ellipticPI' ::
Double -- ^ bound on the relative error passed to `carlsonRF'` and `carlsonRJ'`
-> Cplx -- ^ amplitude
-> Cplx -- ^ characteristic
-> Cplx -- ^ parameter
-> Cplx
ellipticPI' err phi n m
| phi == 0 =
toCplx 0
| phi == pi/2 && n == 1 =
0/0
| phi == pi/2 && m == 0 =
pi/2/sqrt(1-n)
| phi == pi/2 && m == n =
ellipticE' err (pi/2) m / (1-m)
| phi == pi/2 && n == 0 =
ellipticF' err (pi/2) m
| abs(realPart phi) <= pi/2 =
let sine = sin phi in
let sine2 = sine*sine in
let (cosine2, oneminusmsine2) = (1 - sine2, 1 - m*sine2) in
sine * (carlsonRF' err cosine2 oneminusmsine2 1 +
n * sine2 / 3 * carlsonRJ' err cosine2 oneminusmsine2 1 (1-n*sine2))
| otherwise =
let (phi', k) = getPhiK phi in
2 * fromIntegral k * ellipticPI' err (pi/2) n m + ellipticPI' err phi' n m
-- | Elliptic integral of the third kind.
ellipticPI ::
Cplx -- ^ amplitude
-> Cplx -- ^ characteristic
-> Cplx -- ^ parameter
-> Cplx
ellipticPI = ellipticPI' 1e-15
-- | Jacobi zeta function.
jacobiZeta' ::
Double -- ^ bound on the relative error passed to `ellipticF'` and `ellipticE'`
-> Cplx -- ^ amplitude
-> Cplx -- ^ parameter
-> Cplx
jacobiZeta' err phi m =
if m == 1
then
if abs(realPart phi) <= pi/2
then sin phi
else let (phi',_) = getPhiK phi in sin phi'
else
ellipticE' err phi m -
ellipticE' err (pi/2) m / ellipticF' err (pi/2) m *
ellipticF' err phi m
-- | Jacobi zeta function.
jacobiZeta ::
Cplx -- ^ amplitude
-> Cplx -- ^ parameter
-> Cplx
jacobiZeta = jacobiZeta' 1e-15