/* Implementation of methods given in B. C. Carlson Computation of elliptic integrals Numerical Algorithms 10, 13-26 (1995) Copyright (c) Charles Karney (2009-2013) and licensed under the MIT/X11 License. For more information, see https://geographiclib.sourceforge.io/ */ /* fpprec:120$ Should be set outside */ etol:0.1b0^fpprec$ /* For Carlson */ tolRF : (3 * etol)^(1/8b0)$ tolRD : (etol/5)^(1/8b0)$ tolRG0 : 2.7b0 * sqrt(etol)$ tolJAC:sqrt(etol)$ /* For Bulirsch */ pi:bfloat(%pi)$ atan2x(y,x) := -atan2(-y, x)$ /* fix atan2(0b0,-1b0) = -pi */ rf(x,y,z) := block([a0:(x+y+z)/3, q,x0:x,y0:y,z0:z, an,ln,xx,yy,zz,e2,e3,mul:1b0], q:max(abs(a0-x),abs(a0-y),abs(a0-z))/tolRF, an:a0, while q >= mul * abs(an) do ( ln:sqrt(x0)*sqrt(y0)+sqrt(y0)*sqrt(z0)+sqrt(z0)*sqrt(x0), an:(an+ln)/4, x0:(x0+ln)/4, y0:(y0+ln)/4, z0:(z0+ln)/4, mul:mul*4), xx:(a0-x)/(mul*an), yy:(a0-y)/(mul*an), zz:-xx-yy, e2:xx*yy-zz^2, e3:xx*yy*zz, (e3 * (6930 * e3 + e2 * (15015 * e2 - 16380) + 17160) + e2 * ((10010 - 5775 * e2) * e2 - 24024) + 240240) / (240240 * sqrt(an)))$ rd(x,y,z) := block([a0:(x+y+3*z)/5, q,x0:x,y0:y,z0:z, an,ln,xx,yy,zz,e2,e3,e4,e5,s:0b0,mul:1b0], q:max(abs(a0-x),abs(a0-y),abs(a0-z))/tolRD, an:a0, while q >= mul*abs(an) do ( ln:sqrt(x0)*sqrt(y0)+sqrt(y0)*sqrt(z0)+sqrt(z0)*sqrt(x0), s:s+1/(mul*sqrt(z0)*(z0+ln)), an:(an+ln)/4, x0:(x0+ln)/4, y0:(y0+ln)/4, z0:(z0+ln)/4, mul:4*mul), xx:(a0-x)/(mul*an), yy:(a0-y)/(mul*an), zz:-(xx+yy)/3, e2:xx*yy-6*zz^2, e3:(3*xx*yy-8*zz^2)*zz, e4:3*(xx*yy-zz^2)*zz^2, e5:xx*yy*zz^3, ((471240 - 540540 * e2) * e5 + (612612 * e2 - 540540 * e3 - 556920) * e4 + e3 * (306306 * e3 + e2 * (675675 * e2 - 706860) + 680680) + e2 * ((417690 - 255255 * e2) * e2 - 875160) + 4084080) / (4084080 * mul * an * sqrt(an)) + 3 * s)$ /* R_G(x,y,0) */ rg0(x,y) := block([x0:sqrt(max(x,y)),y0:sqrt(min(x,y)),xn,yn, t,s:0b0,mul:0.25b0], xn:x0, yn:y0, while abs(xn-yn) > tolRG0 * xn do ( t:(xn+yn)/2, yn:sqrt(xn*yn), xn:t, mul : 2*mul, s:s+mul*(xn-yn)^2), ((x0+y0)^2/4 - s)*pi/(2*(xn+yn)) )$ rg(x, y, z) := ( if z = 0b0 then (z:y, y:0b0), (z * rf(x, y, z) - (x-z) * (y-z) * rd(x, y, z) / 3 + sqrt(x * y / z)) / 2)$ rj(x, y, z, p) := block([A0:(x + y + z + 2*p)/5,An,delta:(p-x) * (p-y) * (p-z), Q,x0:x,y0:y,z0:z,p0:p,mul:1b0,mul3:1b0,s:0b0,X,Y,Z,P,E2,E3,E4,E5], An : A0, Q : max(abs(A0-x), abs(A0-y), abs(A0-z), abs(A0-p)) / tolRD, while Q >= mul * abs(An) do block([lam,d0,e0], lam : sqrt(x0)*sqrt(y0) + sqrt(y0)*sqrt(z0) + sqrt(z0)*sqrt(x0), d0 : (sqrt(p0)+sqrt(x0)) * (sqrt(p0)+sqrt(y0)) * (sqrt(p0)+sqrt(z0)), e0 : delta/(mul3 * d0^2), s : s + rc(1b0, 1b0 + e0)/(mul * d0), An : (An + lam)/4, x0 : (x0 + lam)/4, y0 : (y0 + lam)/4, z0 : (z0 + lam)/4, p0 : (p0 + lam)/4, mul : 4*mul, mul3 : 64*mul3), X : (A0 - x) / (mul * An), Y : (A0 - y) / (mul * An), Z : (A0 - z) / (mul * An), P : -(X + Y + Z) / 2, E2 : X*Y + X*Z + Y*Z - 3*P*P, E3 : X*Y*Z + 2*P * (E2 + 2*P*P), E4 : (2*X*Y*Z + P * (E2 + 3*P*P)) * P, E5 : X*Y*Z*P*P, ((471240 - 540540 * E2) * E5 + (612612 * E2 - 540540 * E3 - 556920) * E4 + E3 * (306306 * E3 + E2 * (675675 * E2 - 706860) + 680680) + E2 * ((417690 - 255255 * E2) * E2 - 875160) + 4084080) / (4084080 * mul * An * sqrt(An)) + 6 * s)$ rd(x, y, z) := block([A0:(x + y + 3*z)/5,An,Q,x0:x,y0:y,z0:z, mul:1b0,s:0b0,X,Y,Z,E2,E3,E4,E5], An : A0, Q : max(abs(A0-x), abs(A0-y), abs(A0-z)) / tolRD, while Q >= mul * abs(An) do block([lam], lam : sqrt(x0)*sqrt(y0) + sqrt(y0)*sqrt(z0) + sqrt(z0)*sqrt(x0), s : s + 1/(mul * sqrt(z0) * (z0 + lam)), An : (An + lam)/4, x0 : (x0 + lam)/4, y0 : (y0 + lam)/4, z0 : (z0 + lam)/4, mul : 4*mul), X : (A0 - x) / (mul * An), Y : (A0 - y) / (mul * An), Z : -(X + Y) / 3, E2 : X*Y - 6*Z*Z, E3 : (3*X*Y - 8*Z*Z)*Z, E4 : 3 * (X*Y - Z*Z) * Z*Z, E5 : X*Y*Z*Z*Z, ((471240 - 540540 * E2) * E5 + (612612 * E2 - 540540 * E3 - 556920) * E4 + E3 * (306306 * E3 + E2 * (675675 * E2 - 706860) + 680680) + E2 * ((417690 - 255255 * E2) * E2 - 875160) + 4084080) / (4084080 * mul * An * sqrt(An)) + 3 * s)$ rc(x, y):=if x < y then atan(sqrt((y - x) / x)) / sqrt(y - x) else ( if x = y and y > 0b0 then 1 / sqrt(y) else atanh( if y > 0b0 then sqrt((x - y) / x) else sqrt(x / (x - y)) ) / sqrt(x - y) )$ /* k^2 = m */ ec(k2):=2*rg0(1b0-k2,1b0)$ kc(k2):=rf(0b0,1b0-k2,1b0)$ dc(k2):=rd(0b0,1b0-k2,1b0)/3$ pic(k2,alpha2):=if alpha2 # 0b0 then kc(k2)+alpha2*rj(0b0,1b0-k2,1b0,1b0-alpha2)/3 else kc(k2)$ gc(k2,alpha2):=if alpha2 # 0b0 then (if k2 # 1b0 then kc(k2) + (alpha2-k2)*rj(0b0,1b0-k2,1b0,1b0-alpha2)/3 else rc(1b0,1b0-alpha2)) else ec(k2)$ hc(k2,alpha2):=if alpha2 # 0b0 then (if k2 # 1b0 then kc(k2) - (1b0-alpha2)*rj(0b0,1b0-k2,1b0,1b0-alpha2)/3 else rc(1b0,1b0-alpha2)) else kc(k2) - dc(k2)$ /* Implementation of methods given in Roland Bulirsch Numerical Calculation of Elliptic Integrals and Elliptic Functions Numericshe Mathematik 7, 78-90 (1965) */ sncndn(x,mc):=block([bo, a, b, c, d, l, sn, cn, dn, m, n], local(m, n), if mc # 0 then ( bo:is(mc < 0b0), if bo then ( d:1-mc, mc:-mc/d, d:sqrt(d), x:d*x), dn:a:1, for i:0 thru 12 do ( l:i, m[i]:a, n[i]:mc:sqrt(mc), c:(a+mc)/2, if abs(a-mc)<=tolJAC*a then return(false), mc:a*mc, a:c ), x:c*x, sn:sin(x), cn:cos(x), if sn#0b0 then ( a:cn/sn, c:a*c, for i:l step -1 thru 0 do ( b:m[i], a:c*a, c:dn*c, dn:(n[i]+a)/(b+a), a:c/b ), a:1/sqrt(c*c+1b0), sn:if sn<0b0 then -a else a, cn:c*sn ), if bo then ( a:dn, dn:cn, cn:a, sn:sn/d ) ) else /* mc = 0 */ ( sn:tanh(x), dn:cn:sech(x) /* d:exp(x), a:1/d, b:a+d, cn:dn:2/b, if x < 0.3b0 then ( d:x*x*x*x, d:(d*(d*(d*(d+93024b0)+3047466240b0)+24135932620800b0)+ 20274183401472000b0)/60822550204416000b0, sn:cn*(x*x*x*d+sin(x)) ) else sn:(d-a)/b */ ), [sn,cn,dn] )$ Delta(sn, k2):=sqrt(1 - k2 * sn*sn)$ /* Versions of incomplete functions in terms of Jacobi elliptic function with u = am(phi) real and in [0,K(k2)] */ eirx(sn,cn,dn,k2,ec):=block([t,cn2:cn*cn,dn2:dn*dn,sn2:sn*sn,ei,kp2:1b0-k2], ei : (if k2 <= 0b0 then rf(cn2, dn2, 1b0) - k2 * sn2 * rd(cn2, dn2, 1b0) / 3 else (if kp2 >= 0b0 then kp2 * rf(cn2, dn2, 1b0) + k2 * kp2 * sn2 * rd(cn2, 1b0, dn2) / 3 + k2 * abs(cn) / dn else - kp2 * sn2 * rd(dn2, 1b0, cn2) / 3 + dn / abs(cn) ) ), ei : ei * abs(sn), if cn < 0b0 then ei : 2 * ec - ei, if sn < 0 then ei : -ei, ei)$ dirx(sn, cn, dn, k2, dc):=block( [di:abs(sn) * sn*sn * rd(cn*cn, dn*dn, 1b0) / 3], if cn < 0b0 then di : 2 * dc - di, if sn < 0b0 then di : -di, di)$ hirx(sn, cn, dn, k2, alpha2, hc):=block( [cn2 : cn*cn, dn2 : dn*dn, sn2 : sn*sn, hi, alphap2:1b0-alpha2], hi : abs(sn) * (rf(cn2, dn2, 1b0) - alphap2 * sn2 * rj(cn2, dn2, 1b0, cn2 + alphap2 * sn2) / 3), if cn < 0 then hi : 2 * hc - hi, if sn < 0 then hi : -hi, hi)$ deltae(sn, cn, dn, k2, ec):=( if cn < 0 then (cn : -cn, sn : -sn), eirx(sn, cn, dn, k2, ec) * (pi/2) / ec - atan2x(sn, cn))$ deltad(sn, cn, dn, k2, dc):=( if cn < 0 then (cn : -cn, sn : -sn), dirx(sn, cn, dn, k2, ec) * (pi/2) / dc - atan2x(sn, cn))$ deltah(sn, cn, dn, k2, alpha2, hc):=( if cn < 0 then (cn : -cn, sn : -sn), hirx(sn, cn, dn, k2, alpha2, hc) * (pi/2) / hc - atan2x(sn, cn))$ einv(x, k2, ec):=block( [n : floor(x / (2 * ec) + 0.5b0), phi, eps : k2/(sqrt(1b0-k2) + 1b0)^2, err:1b0], x : x - 2 * ec * n, phi : pi * x / (2 * ec), phi : phi - eps * sin(2 * phi) / 2, while abs(err) > tolJAC do block([sn:sin(phi), cn:cos(phi), dn], dn : Delta(sn, k2), err : (eirx(sn, cn, dn, k2, ec) - x)/dn, phi : phi - err), n * pi + phi)$ deltaeinv(stau, ctau, k2, ec) := block([tau], if ctau < 0 then (ctau : -ctau, stau : -stau), tau : atan2x(stau, ctau), einv(tau * ec / (pi/2), k2, ec) - tau)$