/*
Compute the series expansion for the rhumb area.

Copyright (c) Charles Karney (2014) <charles@karney.com> and licensed
under the MIT/X11 License.  For more information, see
https://geographiclib.sourceforge.io/

Instructions: edit the value of maxpow near the end of this file.  Then
load the file into maxima.

Area of rhumb quad

dA = c^2 sin(xi) * dlambda
c = authalic radius
xi = authalic latitude
Express sin(xi) in terms of chi and expand for small n
this can be written in terms of powers of sin(chi)
Subst sin(chi) = tanh(psi) = tanh(m*lambda)
Integrate over lambda to give

A = c^2 * S(chi)/m

S(chi) = log(sec(chi)) + sum(R[i]*cos(2*i*chi),i,0,maxpow)

R[0] = + 1/3 * n
       - 16/45 * n^2
       + 131/945 * n^3
       + 691/56700 * n^4
R[1] = - 1/3 * n
       + 22/45 * n^2
       - 356/945 * n^3
       + 1772/14175 * n^4;
R[2] = - 2/15 * n^2
       + 106/315 * n^3
       - 1747/4725 * n^4;
R[3] = - 31/315 * n^3
       + 104/315 * n^4;
R[4] = - 41/420 * n^4;

i=0 term is just the integration const so can be dropped.  However
including this terms gives S(0) = 0.

Evaluate A between limits lam1 and lam2 gives

A = c^2 * (lam2 - lam1) *
 (S(chi2) - S(chi1)) / (atanh(sin(chi2)) - atanh(sin(chi1)))

In limit chi2 -> chi, chi1 -> chi

diff(atanh(sin(chi)),chi) = sec(chi)
diff(log(sec(chi)),chi) = tan(chi)

c^2 * (lam2 - lam1) * [
  (1-R[1]) * sin(chi)
- (R[1]+2*R[2]) * sin(3*chi)
- (2*R[2]+3*R[3]) * sin(5*chi)
- (3*R[3]+4*R[4]) * sin(7*chi)
...
]
which is expansion of c^2 * (lam2 - lam1) * sin(xi) in terms of sin(chi)
Note:
 limit chi->0 = 0
 limit chi->pi/2 = c^2 * (lam2-lam1)

Express in terms of psi
A = c^2 * (lam2 - lam1) *
 (S(chi(psi2)) - S(chi(psi2))) / (psi2 - psi1)

sum(R[i]*cos(2*i*chi),i,0,maxpow) = sum(sin(chi),cos(chi))
S(chi(psi)) = log(cosh(psi)) + sum(tanh(psi),sech(psi))

(S(chi(psi2)) - S(chi(psi2))) / (psi2 - psi1)
  = Dlog(cosh(psi1),cosh(psi2)) * Dcosh(psi1,psi2)
    + Dsum(chi1,chi2) * Dgd(psi1,psi2)

*/

reverta(expr,var1,var2,eps,pow):=block([tauacc:1,sigacc:0,dsig],
  dsig:ratdisrep(taylor(expr-var1,eps,0,pow)),
  dsig:subst([var1=var2],dsig),
  for n:1 thru pow do (tauacc:trigreduce(ratdisrep(taylor(
    -dsig*tauacc/n,eps,0,pow))),
    sigacc:sigacc+expand(diff(tauacc,var2,n-1))),
  var2+sigacc)$

/* chi in terms of phi -- from auxlat.mac*/
chi_phi(maxpow):=block([psiv,tanchi,chiv,qq,e,atanexp,x,eps],
    /* Here qq = atanh(sin(phi)) = asinh(tan(phi)) */
    psiv:qq-e*atanh(e*tanh(qq)),
    psiv:subst([e=sqrt(4*n/(1+n)^2),qq=atanh(sin(phi))],
      ratdisrep(taylor(psiv,e,0,2*maxpow)))
    +asinh(sin(phi)/cos(phi))-atanh(sin(phi)),
    tanchi:subst([abs(cos(phi))=cos(phi),sqrt(sin(phi)^2+cos(phi)^2)=1],
      ratdisrep(taylor(sinh(psiv),n,0,maxpow)))+tan(phi)-sin(phi)/cos(phi),
    atanexp:ratdisrep(taylor(atan(x+eps),eps,0,maxpow)),
    chiv:subst([x=tan(phi),eps=tanchi-tan(phi)],atanexp),
    chiv:subst([atan(tan(phi))=phi,
      tan(phi)=sin(phi)/cos(phi)],
      (chiv-phi)/cos(phi))*cos(phi)+phi,
    chiv:ratdisrep(taylor(chiv,n,0,maxpow)),
    expand(trigreduce(chiv)))$

/* phi in terms of chi -- from auxlat.mac */
phi_chi(maxpow):=reverta(chi_phi(maxpow),phi,chi,n,maxpow)$

/* xi in terms of phi */
xi_phi(maxpow):=block([sinxi,asinexp,x,eps,v],
  sinxi:(sin(phi)/2*(1/(1-e^2*sin(phi)^2) + atanh(e*sin(phi))/(e*sin(phi))))/
  (1/2*(1/(1-e^2) + atanh(e)/e)),
  sinxi:ratdisrep(taylor(sinxi,e,0,2*maxpow)),
  sinxi:subst([e=2*sqrt(n)/(1+n)],sinxi),
  sinxi:expand(trigreduce(ratdisrep(taylor(sinxi,n,0,maxpow)))),
  asinexp:sqrt(1-x^2)*
  sum(ratsimp(diff(asin(x),x,i)/i!/sqrt(1-x^2))*eps^i,i,0,maxpow),
  v:subst([x=sin(phi),eps=sinxi-sin(phi)],asinexp),
  v:taylor(subst([sqrt(1-sin(phi)^2)=cos(phi),asin(sin(phi))=phi],
      v),n,0,maxpow),
  v:expand(ratdisrep(coeff(v,n,0))+sum(
      ratsimp(trigreduce(sin(phi)*ratsimp(
            subst([sin(phi)=sqrt(1-cos(phi)^2)],
              ratsimp(trigexpand(ratdisrep(coeff(v,n,i)))/sin(phi))))))
      *n^i,
      i,1,maxpow)))$

xi_chi(maxpow):=
expand(trigreduce(taylor(subst([phi=phi_chi(maxpow)],xi_phi(maxpow)),
      n,0,maxpow)))$

computeR(maxpow):=block([xichi,xxn,inttanh,yy,m,yyi,yyj,s],
  local(inttanh),
  xichi:xi_chi(maxpow),
  xxn:expand(subst([cos(chi)=sqrt(1-sin(chi)^2)],
      trigexpand(taylor(sin(xichi),n,0,maxpow)))),
  /* integrals of tanh(x)^l.  Use tanh(x)^2 + sech(x)^2 = 1. */
  inttanh[0](x):=x, /* Not needed -- only odd l occurs in this problem */
  inttanh[1](x):=log(cosh(x)),
  inttanh[l](x):=inttanh[l-2](x) - tanh(x)^(l-1)/(l-1),
  yy:subst([sin(chi)=tanh(m*lambda)],xxn),
  /*
  psi = atanh(sin(chi)) = m*lambda
  sin(chi)=tanh(m*lambda)
  sech(m*lambda) = sqrt(1-tanh(m*lambda))^2 = cos(chi)
  cosh(m*lambda) = sec(chi)
  m=(atanh(sin(chi2))-atanh(sin(chi1)))/(lam2-lam1)
  */
  yyi:block([v:yy/m,ii],
    local(ii),
    for j:2*maxpow+1 step -2 thru 1 do
    v:subst([tanh(m*lambda)^j=ii[j](m*lambda)],v),
    for j:2*maxpow+1 step -2 thru 1 do
    v:subst([ii[j](m*lambda)=inttanh[j](m*lambda)],v),
    expand(v)),
  yyj:expand(m*trigreduce(
      subst([tanh(m*lambda)=sin(chi),cosh(m*lambda)=sec(chi)],yyi)))/
  ( (atanh(sin(chi2))-atanh(sin(chi1)))/(lam2-lam1) ),
  s:( (atanh(sin(chi2))-atanh(sin(chi1)))/(lam2-lam1) )*yyj-log(sec(chi)),
  for i:1 thru maxpow do R[i]:coeff(s,cos(2*i*chi)),
  R[0]:s-expand(sum(R[i]*cos(2*i*chi),i,1,maxpow)),
  if expand(s-sum(R[i]*cos(2*i*chi),i,0,maxpow)) # 0 then
  error("Left over terms in R"),
  if expand(trigreduce(expand(
        diff(sum(R[i]*cos(2*i*chi),i,0,maxpow),chi)*cos(chi)+sin(chi))))-
  expand(trigreduce(expand(xxn))) # 0 then
  error("Derivative error in R"),
  'done)$

ataylor(expr,var,ord):=expand(ratdisrep(taylor(expr,var,0,ord)))$
dispR(ord):=for i:1 thru ord do
block([tt:ataylor(R[i],n,ord),ttt,linel:1200],
  print(),
  for j:max(i,1) step 1 thru ord do (ttt:coeff(tt,n,j), print(concat(
        if j = max(i,1) then concat("R[",string(i),"] = ") else "       ",
        if ttt<0 then "- " else "+ ",
        string(abs(ttt)), " * ", string(n^j),
        if j=ord then ";" else ""))))$

codeR(minpow,maxpow):=block([tab2:"    ",tab3:"      "],
  print("  // The coefficients R[l] in the Fourier expansion of rhumb area
    real nx = n;
    switch (maxpow_) {"),
  for k:minpow thru maxpow do (
    print(concat(tab2,"case ",string(k),":")),
    for m:1 thru k do block([q:nx*horner(
        ataylor(R[m],n,k)/n^m),
      linel:1200],
      if m>1 then print(concat(tab3,"nx *= n;")),
      print(concat(tab3,"c[",string(m),"] = ",string(q),";"))),
    print(concat(tab3,"break;"))),
  print(concat(tab2,"default:")),
  print(concat(tab3,"GEOGRAPHICLIB_STATIC_ASSERT(maxpow_ >= ",string(minpow),
      " && maxpow_ <= ",string(maxpow),", \"Bad value of maxpow_\");")),
  print("    }"),
'done)$

maxpow:8$
computeR(maxpow)$
dispR(maxpow)$
/* codeR(4,maxpow)$ */
load("polyprint.mac")$
printrhumb():=block([macro:GEOGRAPHICLIB_RHUMBAREA_ORDER],
  array1('R,'n,1,0))$
printrhumb()$
