pygeodesy 25.5.28__py2.py3-none-any.whl → 25.7.25__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pygeodesy/elliptic.py CHANGED
@@ -76,17 +76,18 @@ U{22<https://DLMF.NIST.gov/22>}.
76
76
  from __future__ import division as _; del _ # noqa: E702 ;
77
77
 
78
78
  from pygeodesy.basics import copysign0, map2, neg, neg_, typename
79
- from pygeodesy.constants import EPS, INF, NAN, PI, PI_2, PI_4, _0_0, \
80
- _0_25, _0_5, _1_0, _2_0, _N_2_0, _3_0, \
81
- _4_0, _6_0, _8_0, _64_0, _180_0, _360_0, \
82
- _EPStol as _TolJAC, _over, \
83
- _EPSjam as _TolJAM # PYCHOK used!
84
- # from pygeodesy.errors import _ValueError # from .fmath
85
- from pygeodesy.fmath import favg, hypot1, zqrt, _ValueError
86
- from pygeodesy.fsums import Fsum, _sum
79
+ from pygeodesy.constants import EPS, INF, NAN, PI, PI_2, PI_4, \
80
+ _EPStol as _TolJAC, _0_0, _0_25, \
81
+ _0_5, _1_0, _2_0, _N_2_0, _3_0, \
82
+ _4_0, _6_0, _8_0, _64_0, _180_0, \
83
+ _360_0, _over
84
+ from pygeodesy.constants import _EPSjam as _TolJAM # PYCHOK used!
85
+ # from pygeodesy.errors import _ValueError # from .fsums
86
+ from pygeodesy.fmath import favg, Fdot_, fma, hypot1, zqrt
87
+ from pygeodesy.fsums import Fsum, _fsum, _ValueError
87
88
  # from pygeodesy.internals import typename # from .basics
88
- from pygeodesy.interns import NN, _delta_, _DOT_, _f_, _invalid_, _invokation_, \
89
- _negative_, _SPACE_
89
+ from pygeodesy.interns import NN, _delta_, _DOT_, _f_, _invalid_, \
90
+ _invokation_, _negative_, _SPACE_
90
91
  from pygeodesy.karney import _K_2_0, _norm180, _signBit, _sincos2
91
92
  # from pygeodesy.lazily import _ALL_LAZY # from .named
92
93
  from pygeodesy.named import _Named, _NamedTuple, _ALL_LAZY, Fmt, unstr
@@ -99,48 +100,23 @@ from math import asin, asinh, atan, ceil, cosh, fabs, floor, radians, \
99
100
  sin, sinh, sqrt, tan, tanh # tan as _tan
100
101
 
101
102
  __all__ = _ALL_LAZY.elliptic
102
- __version__ = '25.05.28'
103
+ __version__ = '25.06.02'
103
104
 
104
105
  _TolRD = zqrt(EPS * 0.002)
105
106
  _TolRF = zqrt(EPS * 0.030)
106
107
  _TolRG0 = _TolJAC * 2.7
107
- _TRIPS = 25 # Max depth, 6-7 might be sufficient
108
+ _TRIPS = 28 # Max depth, 6-18 might be sufficient
108
109
 
109
110
 
110
111
  class _Cs(object):
111
112
  '''(INTERAL) Complete integrals cache.
112
113
  '''
113
114
  def __init__(self, **kwds):
115
+ # for n,v in kwds.items():
116
+ # setattr(self, n, v)
114
117
  self.__dict__ = kwds
115
118
 
116
119
 
117
- class _Dsum(list):
118
- '''(INTERNAL) Deferred C{Fsum}.
119
- '''
120
- def __call__(self, s):
121
- try: # Fsum *= s
122
- return Fsum(*self).fmul(s)
123
- except ValueError: # Fsum(NAN) exception
124
- return _sum(self) * s
125
-
126
- def __iadd__(self, x):
127
- list.append(self, x)
128
- return self
129
-
130
-
131
- class _Dadd(_Dsum):
132
- '''(INTERNAL) Deferred C{Fsum} for C{_List.amrs4}.
133
- '''
134
- def __init__(self, mul):
135
- self._mul = mul
136
-
137
- def __add__(self, x):
138
- self += x
139
- r = self(self._mul)
140
- _ = self.pop()
141
- return r # Fsum or float
142
-
143
-
144
120
  class Elliptic(_Named):
145
121
  '''Elliptic integrals and functions.
146
122
 
@@ -167,7 +143,7 @@ class Elliptic(_Named):
167
143
  '''
168
144
  if name:
169
145
  self.name = name
170
- self.reset(k2=k2, alpha2=alpha2, kp2=kp2, alphap2=alphap2)
146
+ self._reset(k2, alpha2, kp2, alphap2)
171
147
 
172
148
  @Property_RO
173
149
  def alpha2(self):
@@ -181,6 +157,32 @@ class Elliptic(_Named):
181
157
  '''
182
158
  return self._alphap2
183
159
 
160
+ @Property_RO
161
+ def _b4(self):
162
+ '''(INTERNAL) Get Bulirsch' 4-tuple C{(c, d, cd, mn)}.
163
+ '''
164
+ d, b = 0, self.kp2 # note, kp2 >= 0 always here
165
+ if _signBit(b): # PYCHOK no cover
166
+ d = _1_0 - b
167
+ b = neg(b / d)
168
+ d = sqrt(d)
169
+ ab, a = [], _1_0
170
+ for i in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC
171
+ b = sqrt(b)
172
+ ab.append((a, b))
173
+ c = favg(a, b)
174
+ r = fabs(a - b)
175
+ if r <= (a * _TolJAC): # 6 trips, quadratic
176
+ self._iteration += i
177
+ break
178
+ t = a
179
+ b *= a
180
+ a = c
181
+ else: # PYCHOK no cover
182
+ raise _convergenceError(r / t, _TolJAC)
183
+ cd = (c * d) if d else c
184
+ return c, d, cd, tuple(reversed(ab))
185
+
184
186
  @Property_RO
185
187
  def cD(self):
186
188
  '''Get Jahnke's complete integral C{D(k)} (C{float}),
@@ -190,28 +192,28 @@ class Elliptic(_Named):
190
192
 
191
193
  @Property_RO
192
194
  def _cDEKEeps(self):
193
- '''(INTERNAL) Get the complete integrals D, E, K and KE plus C{eps}.
195
+ '''(INTERNAL) Get the complete integrals D, E, K, KE and C{eps}.
194
196
  '''
195
197
  k2, kp2 = self.k2, self.kp2
196
198
  if k2:
197
199
  if kp2:
198
200
  try:
199
- self._iteration = 0
201
+ # self._iteration = 0
200
202
  # D(k) = (K(k) - E(k))/k2, Carlson eq.4.3
201
203
  # <https://DLMF.NIST.gov/19.25.E1>
202
- D = _RD(self, _0_0, kp2, _1_0, _3_0)
204
+ D = _RD(_0_0, kp2, _1_0, _3_0, self)
203
205
  cD = float(D)
204
206
  # Complete elliptic integral E(k), Carlson eq. 4.2
205
207
  # <https://DLMF.NIST.gov/19.25.E1>
206
- cE = _rG2(self, kp2, _1_0, PI_=PI_2)
208
+ cE = _rG2(kp2, _1_0, self, PI_=PI_2)
207
209
  # Complete elliptic integral K(k), Carlson eq. 4.1
208
210
  # <https://DLMF.NIST.gov/19.25.E1>
209
- cK = _rF2(self, kp2, _1_0)
211
+ cK = _rF2(kp2, _1_0, self)
210
212
  cKE = float(D.fmul(k2))
211
213
  eps = k2 / (sqrt(kp2) + _1_0)**2
212
214
 
213
- except Exception as e:
214
- raise _ellipticError(self.reset, k2=k2, kp2=kp2, cause=e)
215
+ except Exception as X:
216
+ raise _ellipticError(self._cDEKEeps, k2=k2, kp2=kp2, cause=X)
215
217
  else:
216
218
  cD = cK = cKE = INF
217
219
  cE = _1_0
@@ -244,17 +246,17 @@ class Elliptic(_Named):
244
246
  '''
245
247
  alpha2, alphap2, kp2 = self.alpha2, self.alphap2, self.kp2
246
248
  try:
247
- self._iteration = 0
249
+ # self._iteration = 0
248
250
  if alpha2:
249
251
  if alphap2:
250
252
  if kp2: # <https://DLMF.NIST.gov/19.25.E2>
251
253
  cK = self.cK
252
- Rj = _RJ(self, _0_0, kp2, _1_0, alphap2, _3_0)
253
- cG = float(Rj * (alpha2 - self.k2) + cK) # G(alpha2, k)
254
- cH = -float(Rj * alphap2 - cK) # H(alpha2, k)
255
- cPi = float(Rj * alpha2 + cK) # Pi(alpha2, k)
254
+ Rj = _RJfma(_0_0, kp2, _1_0, alphap2, _3_0, self)
255
+ cG = Rj.ma(alpha2 - self.k2, cK) # G(alpha2, k)
256
+ cH = -Rj.ma(alphap2, -cK) # H(alpha2, k)
257
+ cPi = Rj.ma(alpha2, cK) # Pi(alpha2, k)
256
258
  else:
257
- cG = cH = _rC(self, _1_0, alphap2)
259
+ cG = cH = _rC(_1_0, alphap2)
258
260
  cPi = INF # XXX or NAN?
259
261
  else:
260
262
  cG = cH = cPi = INF # XXX or NAN?
@@ -272,11 +274,11 @@ class Elliptic(_Named):
272
274
  # RF(x, 1) - RD(0, x, 1) / 3 = x * RD(0, 1, x) / 3 for x > 0
273
275
  # For k2 = 1 and alpha2 = 0, we have
274
276
  # H = int(cos(phi),...) = 1
275
- cH = float(_RD(self, _0_0, _1_0, kp2, _3_0 / kp2)) if kp2 else _1_0
277
+ cH = float(_RD(_0_0, _1_0, kp2, _3_0 / kp2, self)) if kp2 else _1_0
276
278
 
277
- except Exception as e:
278
- raise _ellipticError(self.reset, kp2=kp2, alpha2 =alpha2,
279
- alphap2=alphap2, cause=e)
279
+ except Exception as X:
280
+ raise _ellipticError(self._cGHPi, kp2=kp2, alpha2 =alpha2,
281
+ alphap2=alphap2, cause=X)
280
282
  return _Cs(cG=cG, cH=cH, cPi=cPi)
281
283
 
282
284
  @Property_RO
@@ -349,8 +351,8 @@ class Elliptic(_Named):
349
351
  t = atan2(stau, ctau)
350
352
  return self._Einv(t * self.cE / PI_2) - t
351
353
 
352
- except Exception as e:
353
- raise _ellipticError(self.deltaEinv, stau, ctau, cause=e)
354
+ except Exception as X:
355
+ raise _ellipticError(self.deltaEinv, stau, ctau, cause=X)
354
356
 
355
357
  def deltaF(self, sn, cn, dn):
356
358
  '''The periodic incomplete integral of the first kind.
@@ -416,7 +418,7 @@ class Elliptic(_Named):
416
418
  Phi = Fsum(phi)
417
419
  # first order correction
418
420
  phi = Phi.fsum_(self.eps * sin(phi * _2_0) / _N_2_0)
419
- self._iteration = 0
421
+ # self._iteration = 0
420
422
  # For kp2 close to zero use asin(r / cE) or J. P. Boyd,
421
423
  # Applied Math. and Computation 218, 7005-7013 (2012)
422
424
  # <https://DOI.org/10.1016/j.amc.2011.12.021>
@@ -429,7 +431,7 @@ class Elliptic(_Named):
429
431
  else: # PYCHOK no cover
430
432
  d = _0_0 # XXX or continue?
431
433
  if fabs(d) < _TolJAC: # 3-4 trips
432
- _iterations(self, i)
434
+ self._iteration += i
433
435
  break
434
436
  else: # PYCHOK no cover
435
437
  raise _convergenceError(d, _TolJAC)
@@ -457,7 +459,7 @@ class Elliptic(_Named):
457
459
  def _fD(sn, cn, dn):
458
460
  r = fabs(sn)**3
459
461
  if r:
460
- r = float(_RD(self, cn**2, dn**2, _1_0, _3_0 / r))
462
+ r = float(_RD(cn**2, dn**2, _1_0, _3_0 / r, self))
461
463
  return r
462
464
 
463
465
  return self._fXf(phi_or_sn, cn, dn, self.cD,
@@ -477,8 +479,8 @@ class Elliptic(_Named):
477
479
  (_1_0 - sn**2 * k2) if k2 < 0 else self.kp2)
478
480
  return sqrt(s) if s else _0_0
479
481
 
480
- except Exception as e:
481
- raise _ellipticError(self.fDelta, sn, cn, k2=k2, cause=e)
482
+ except Exception as X:
483
+ raise _ellipticError(self.fDelta, sn, cn, k2=k2, cause=X)
482
484
 
483
485
  def fE(self, phi_or_sn, cn=None, dn=None):
484
486
  '''The incomplete integral of the second kind in terms of
@@ -500,22 +502,21 @@ class Elliptic(_Named):
500
502
  cn2, dn2 = cn**2, dn**2
501
503
  kp2, k2 = self.kp2, self.k2
502
504
  if k2 <= 0: # Carlson, eq. 4.6, <https://DLMF.NIST.gov/19.25.E9>
503
- Ei = _RF3(self, cn2, dn2, _1_0)
505
+ Ei = _RF3(cn2, dn2, _1_0, self)
504
506
  if k2:
505
- Ei -= _RD(self, cn2, dn2, _1_0, _3over(k2, sn**2))
507
+ Ei -= _RD(cn2, dn2, _1_0, _3over(k2, sn**2), self)
506
508
  elif kp2 >= 0: # k2 > 0, <https://DLMF.NIST.gov/19.25.E10>
507
509
  Ei = _over(k2 * fabs(cn), dn) # float
508
510
  if kp2:
509
- Ei += (_RD( self, cn2, _1_0, dn2, _3over(k2, sn**2)) +
510
- _RF3(self, cn2, dn2, _1_0)) * kp2
511
- else: # kp2 < 0, <https://DLMF.NIST.gov/19.25.E11>
512
- Ei = _over(dn, fabs(cn))
513
- Ei -= _RD(self, dn2, _1_0, cn2, _3over(kp2, sn**2))
511
+ Ei += (_RD( cn2, _1_0, dn2, _3over(k2, sn**2), self) +
512
+ _RF3(cn2, dn2, _1_0, self)) * kp2
513
+ else: # PYCHOK no cover
514
+ Ei = _over(dn, fabs(cn)) # <https://DLMF.NIST.gov/19.25.E11>
515
+ Ei -= _RD(dn2, _1_0, cn2, _3over(kp2, sn**2), self)
514
516
  Ei *= fabs(sn)
515
- ei = float(Ei)
516
517
  else: # PYCHOK no cover
517
- ei = _0_0
518
- return ei
518
+ Ei = _0_0
519
+ return float(Ei)
519
520
 
520
521
  return self._fXf(phi_or_sn, cn, dn, self.cE,
521
522
  self.deltaE, _fE,
@@ -538,7 +539,8 @@ class Elliptic(_Named):
538
539
  else:
539
540
  e = ceil(deg / _360_0 - _0_5)
540
541
  deg -= e * _360_0
541
- return self.fE(radians(deg)) + e * self.cE * _4_0
542
+ e *= self.cE * _4_0
543
+ return self.fE(radians(deg)) + e
542
544
 
543
545
  def fEinv(self, x):
544
546
  '''The inverse of the incomplete integral of the second kind.
@@ -552,8 +554,8 @@ class Elliptic(_Named):
552
554
  '''
553
555
  try:
554
556
  return self._Einv(x)
555
- except Exception as e:
556
- raise _ellipticError(self.fEinv, x, cause=e)
557
+ except Exception as X:
558
+ raise _ellipticError(self.fEinv, x, cause=X)
557
559
 
558
560
  def fF(self, phi_or_sn, cn=None, dn=None):
559
561
  '''The incomplete integral of the first kind in terms of
@@ -571,7 +573,7 @@ class Elliptic(_Named):
571
573
  def _fF(sn, cn, dn):
572
574
  r = fabs(sn)
573
575
  if r:
574
- r = float(_RF3(self, cn**2, dn**2, _1_0).fmul(r))
576
+ r = float(_RF3(cn**2, dn**2, _1_0, self).fmul(r))
575
577
  return r
576
578
 
577
579
  return self._fXf(phi_or_sn, cn, dn, self.cK,
@@ -650,23 +652,22 @@ class Elliptic(_Named):
650
652
  def _fX(sn, cn, dn):
651
653
  if sn:
652
654
  cn2, dn2 = cn**2, dn**2
653
- R = _RF3(self, cn2, dn2, _1_0)
655
+ R = _RF3(cn2, dn2, _1_0, self)
654
656
  if aX:
655
657
  sn2 = sn**2
656
658
  p = sn2 * self.alphap2 + cn2
657
- R += _RJ(self, cn2, dn2, _1_0, p, _3over(aX, sn2))
659
+ R += _RJ(cn2, dn2, _1_0, p, _3over(aX, sn2), self)
658
660
  R *= fabs(sn)
659
- r = float(R)
660
661
  else: # PYCHOK no cover
661
- r = _0_0
662
- return r
662
+ R = _0_0
663
+ return float(R)
663
664
 
664
665
  return self._fXf(phi_or_sn, cn, dn, cX, deltaX, _fX)
665
666
 
666
667
  def _fXf(self, phi_or_sn, cn, dn, cX, deltaX, fX, k2_0=False, kp2_0=False):
667
668
  '''(INTERNAL) Helper for C{.fD}, C{.fE}, C{.fF} and C{._fXa}.
668
669
  '''
669
- self._iteration = 0 # aggregate
670
+ # self._iteration = 0 # aggregate
670
671
  phi = sn = phi_or_sn
671
672
  if cn is dn is None: # fX(phi) call
672
673
  if k2_0: # C++ version 2.4
@@ -712,7 +713,7 @@ class Elliptic(_Named):
712
713
  '''(INTERNAL) Get Jacobi amplitude 2-tuple C{(r, ac)}.
713
714
  '''
714
715
  a = r = _1_0
715
- b, c = self.kp2, self.k2
716
+ b, c = self.kp2, self.k2
716
717
  # assert b and c
717
718
  if c < 0: # Sala Eq. 5.8
718
719
  r = sqrt(b)
@@ -724,12 +725,12 @@ class Elliptic(_Named):
724
725
  c = favg(a, -b)
725
726
  a = favg(a, b) # == PI_2 / K
726
727
  ac.append((a, c))
727
- if c <= (a * _TolJAM): # 7 trips, quadratic
728
- _iterations(self, i)
728
+ if c <= (a * _TolJAM): # 7-18 trips, quadratic
729
+ self._iteration += i
729
730
  break
730
731
  else: # PYCHOK no cover
731
732
  raise _convergenceError(c / a, _TolJAM)
732
- r *= a * float(1 << i) # 2**i == 2**len(ac)
733
+ r *= a * pow(2, i) # 2**len(ac)
733
734
  return r, tuple(reversed(ac))
734
735
 
735
736
  @Property_RO
@@ -760,15 +761,18 @@ class Elliptic(_Named):
760
761
  that these conditions are met to enable accuracy to be
761
762
  maintained, e.g., when C{k} is very close to unity.
762
763
  '''
764
+ _update_all(self, Base=Property_RO, needed=4)
765
+ self._reset(k2, alpha2, kp2, alphap2)
766
+
767
+ def _reset(self, k2, alpha2, kp2, alphap2):
768
+ '''(INITERNAL) Reset this elliptic.
769
+ '''
763
770
  def _1p2(kp2, k2):
764
771
  return (_1_0 - k2) if kp2 is None else kp2
765
772
 
766
773
  def _S(**kwds):
767
774
  return Scalar_(Error=EllipticError, **kwds)
768
775
 
769
- if self.__dict__:
770
- _update_all(self, _Named.iteration._uname, Base=Property_RO)
771
-
772
776
  self._k2 = _S(k2 = k2, low=None, high=_1_0)
773
777
  self._kp2 = _S(kp2=_1p2(kp2, k2)) # low=_0_0
774
778
 
@@ -792,30 +796,31 @@ class Elliptic(_Named):
792
796
  # Pi(alpha2, 1) = inf
793
797
  # G( alpha2, 1) = H(alpha2, 1) = RC(1, alphap2)
794
798
 
799
+ self._iteration = 0
800
+
795
801
  def sncndn(self, x, jam=False):
796
802
  '''The Jacobi amplitude and elliptic function.
797
803
 
798
804
  @arg x: The argument (C{float}).
799
- @kwarg jam: If C{True}, use the Jacobi amplitude otherwise the
805
+ @kwarg jam: If C{True}, use the Jacobi amplitude otherwise
800
806
  Bulirsch' function (C{bool}).
801
807
 
802
808
  @return: An L{Elliptic3Tuple}C{(sn, cn, dn)} with C{*n(B{x}, k)}.
803
809
 
804
810
  @raise EllipticError: No convergence.
805
811
  '''
806
- self._iteration = 0 # reset
812
+ i = self._iteration
807
813
  try:
808
814
  if self.kp2:
809
- if jam: # Jacobi amplitude, C++ version 2.4
815
+ if jam: # Jacobi amplitude, C++ v 2.4
810
816
  sn, cn, dn = self._sncndn3(self._jam(x))
811
817
 
812
818
  else: # Bulirsch's sncndn routine, p 89 of
813
819
  # Numerische Mathematik 7, 78-90 (1965).
814
- # Implements DLMF Eqs 22.17.2 - 22.17.4,
815
- # but only good for .k2 > 1 or .kp2 < 0
816
- c, d, cd, mn = self._sncndn4
817
- dn = _1_0
820
+ # Implements DLMF Eqs 22.17.2 - 22.17.4
821
+ c, d, cd, mn = self._b4
818
822
  sn, cn = _sincos2(x * cd)
823
+ dn = _1_0
819
824
  if sn:
820
825
  a = cn / sn
821
826
  c *= a
@@ -834,10 +839,10 @@ class Elliptic(_Named):
834
839
  sn = tanh(x) # accurate for large abs(x)
835
840
  cn = dn = _1_0 / cosh(x)
836
841
 
837
- except Exception as e:
838
- raise _ellipticError(self.sncndn, x, kp2=self.kp2, cause=e)
842
+ except Exception as X:
843
+ raise _ellipticError(self.sncndn, x, kp2=self.kp2, cause=X)
839
844
 
840
- return Elliptic3Tuple(sn, cn, dn, iteration=self._iteration)
845
+ return Elliptic3Tuple(sn, cn, dn, iteration=self._iteration - i)
841
846
 
842
847
  def _sncndn3(self, phi):
843
848
  '''(INTERNAL) Helper for C{.fEinv}, C{._fXf} and C{.sncndn}.
@@ -845,32 +850,6 @@ class Elliptic(_Named):
845
850
  sn, cn = _sincos2(phi)
846
851
  return sn, cn, self.fDelta(sn, cn)
847
852
 
848
- @Property_RO
849
- def _sncndn4(self):
850
- '''(INTERNAL) Get Bulirsch' 4-tuple C{(c, d, cd, mn)}.
851
- '''
852
- d, b = 0, self.kp2
853
- if _signBit(b):
854
- d = _1_0 - b
855
- b = neg(b / d)
856
- d = sqrt(d)
857
- ab, a = [], _1_0
858
- for i in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC
859
- b = sqrt(b)
860
- ab.append((a, b))
861
- c = favg(a, b)
862
- r = fabs(a - b)
863
- if r <= (a * _TolJAC): # 6 trips, quadratic
864
- _iterations(self, i)
865
- break
866
- t = a
867
- b *= a
868
- a = c
869
- else: # PYCHOK no cover
870
- raise _convergenceError(r / t, _TolJAC)
871
- cd = (c * d) if d else c
872
- return c, d, cd, tuple(reversed(ab))
873
-
874
853
  @staticmethod
875
854
  def fRC(x, y):
876
855
  '''Degenerate symmetric integral of the first kind C{RC(x, y)}.
@@ -880,7 +859,7 @@ class Elliptic(_Named):
880
859
  @see: U{C{RC} definition<https://DLMF.NIST.gov/19.2.E17>} and
881
860
  U{Carlson<https://ArXiv.org/pdf/math/9409227.pdf>}.
882
861
  '''
883
- return _rC(None, x, y)
862
+ return _rC(x, y)
884
863
 
885
864
  @staticmethod
886
865
  def fRD(x, y, z, *over):
@@ -893,9 +872,9 @@ class Elliptic(_Named):
893
872
  U{Carlson<https://ArXiv.org/pdf/math/9409227.pdf>}.
894
873
  '''
895
874
  try:
896
- return float(_RD(None, x, y, z, *over))
897
- except Exception as e:
898
- raise _ellipticError(Elliptic.fRD, x, y, z, *over, cause=e)
875
+ return float(_RD(x, y, z, *over))
876
+ except Exception as X:
877
+ raise _ellipticError(Elliptic.fRD, x, y, z, *over, cause=X)
899
878
 
900
879
  @staticmethod
901
880
  def fRF(x, y, z=0):
@@ -908,9 +887,9 @@ class Elliptic(_Named):
908
887
  U{Carlson<https://ArXiv.org/pdf/math/9409227.pdf>}.
909
888
  '''
910
889
  try:
911
- return float(_RF3(None, x, y, z)) if z else _rF2(None, x, y)
912
- except Exception as e:
913
- raise _ellipticError(Elliptic.fRF, x, y, z, cause=e)
890
+ return float(_RF3(x, y, z)) if z else _rF2(x, y)
891
+ except Exception as X:
892
+ raise _ellipticError(Elliptic.fRF, x, y, z, cause=X)
914
893
 
915
894
  @staticmethod
916
895
  def fRG(x, y, z=0):
@@ -925,15 +904,15 @@ class Elliptic(_Named):
925
904
  EllipticFunction_8cpp_source.html#l00096>} version 2.3.
926
905
  '''
927
906
  try:
928
- return _rG2(None, x, y) if z == 0 else (
929
- _rG2(None, z, x) if y == 0 else (
930
- _rG2(None, y, z) if x == 0 else _rG3(None, x, y, z)))
931
- except Exception as e:
907
+ return _rG2(x, y) if z == 0 else (
908
+ _rG2(z, x) if y == 0 else (
909
+ _rG2(y, z) if x == 0 else _rG3(x, y, z)))
910
+ except Exception as X:
932
911
  t = _negative_ if min(x, y, z) < 0 else NN
933
- raise _ellipticError(Elliptic.fRG, x, y, z, cause=e, txt=t)
912
+ raise _ellipticError(Elliptic.fRG, x, y, z, cause=X, txt=t)
934
913
 
935
914
  @staticmethod
936
- def fRJ(x, y, z, p):
915
+ def fRJ(x, y, z, p): # *over
937
916
  '''Symmetric integral of the third kind C{RJ(x, y, z, p)}.
938
917
 
939
918
  @return: C{RJ(x, y, z, p)}.
@@ -942,19 +921,18 @@ class Elliptic(_Named):
942
921
  U{Carlson<https://ArXiv.org/pdf/math/9409227.pdf>}.
943
922
  '''
944
923
  try:
945
- return float(_RJ(None, x, y, z, p))
946
- except Exception as e:
947
- raise _ellipticError(Elliptic.fRJ, x, y, z, p, cause=e)
924
+ return float(_RJ(x, y, z, p))
925
+ except Exception as X:
926
+ raise _ellipticError(Elliptic.fRJ, x, y, z, p, cause=X)
948
927
 
949
928
  @staticmethod
950
- def _RFRD(x, y, z, m):
951
- # in .auxilats.AuxDLat.DE, .auxilats.AuxLat.Rectifying
929
+ def _RFRD(x, y, z, m): # in .auxilats.AuxDLat.DE, -.AuxLat.Rectifying
952
930
  try: # float(RF(x, y, z) - RD(x, y, z, 3 / m))
953
- R = _RF3(None, x, y, z)
931
+ R = _RF3(x, y, z)
954
932
  if m:
955
- R -= _RD(None, x, y, z, _3_0 / m)
956
- except Exception as e:
957
- raise _ellipticError(Elliptic._RFRD, x, y, z, m, cause=e)
933
+ R -= _RD(x, y, z, _3_0 / m)
934
+ except Exception as X:
935
+ raise _ellipticError(Elliptic._RFRD, x, y, z, m, cause=X)
958
936
  return float(R)
959
937
 
960
938
  _allPropertiesOf_n(16, Elliptic) # # PYCHOK assert, see Elliptic.reset
@@ -984,40 +962,38 @@ class _List(list):
984
962
  def a0(self, n):
985
963
  '''Compute the initial C{a}.
986
964
  '''
987
- A = _Dsum(self)
988
- while len(A) < n:
989
- A += A[-1]
990
- self._a0 = a = float(A(_1_0 / n))
991
- return a
992
-
993
- def amrs4(self, inst, y, Tol):
965
+ a = list(self)
966
+ m = n - len(a)
967
+ if m > 0:
968
+ a[-1] *= m + 1
969
+ self._a0 = a0 = _fsum(a) / n
970
+ return a0
971
+
972
+ def amrs4(self, y, Tol, inst=None):
994
973
  '''Yield Carlson 4-tuples C{(An, mul, lam, s)} plus sentinel, with
995
974
  C{lam = fdot(sqrt(x), ... (z))} and C{s = (sqrt(x), ... (p))}.
996
975
  '''
997
976
  L = self
998
977
  a = L.a0(5 if y else 3)
978
+ t = L.threshold(Tol)
999
979
  m = 1
1000
- t = max(fabs(a - _) for _ in L) / Tol # thresh
1001
980
  for i in range(_TRIPS):
1002
981
  d = fabs(a * m)
1003
982
  if d > t: # 3-6 trips
1004
- _iterations(inst, i)
1005
983
  break
1006
- s = map2(sqrt, L) # sqrt(x), srqt(y), sqrt(z) [, sqrt(p)]
1007
- # Deferred fdot(s[:3], s[1], s[2], s[0]) + ...
1008
- Q = _Dadd(_0_25)
1009
- Q += s[0] * s[1]
1010
- Q += s[1] * s[2]
1011
- Q += s[2] * s[0]
1012
- L[:] = (float(Q + _) for _ in L)
1013
- a = float(Q + a)
984
+ s = map2(sqrt, L) # sqrt(x), sqrt(y), sqrt(z) [, sqrt(p)]
985
+ Q = _Qot3(*s) # (s[0] * s[1], s[1] * s[2], s[2] * s[0])
986
+ a = Q(a) # An = sum(An, *Q)) / 4
987
+ L[:] = map(Q, L) # x = sum(x, *Q) / 4, ...
1014
988
  if y: # yield only if used
1015
- r = _sum(Q) # fdot
989
+ r = float(Q) # lam = sum(Q)
1016
990
  yield a, m, r, s # L[2] is next z
1017
991
  m *= 4
1018
992
  else: # PYCHOK no cover
1019
993
  raise _convergenceError(d, t, thresh=True)
1020
994
  yield a, m, None, () # sentinel: same a, next m, no r and s
995
+ if inst:
996
+ inst._iteration += i
1021
997
 
1022
998
  def rescale(self, am, *xs):
1023
999
  '''Rescale C{x}, C{y}, ...
@@ -1028,24 +1004,63 @@ class _List(list):
1028
1004
  for x in xs:
1029
1005
  yield (a0 - x) * _am
1030
1006
 
1007
+ def threshold(self, Tol):
1008
+ '''Get the convergence C{threshold}.
1009
+ '''
1010
+ a0 = self._a0
1011
+ return max(fabs(x - a0) for x in self) / Tol
1012
+
1013
+
1014
+ # class _Qot3(Fsum):
1015
+ # '''(INTERNAL) "Quarter" 3-dot product.
1016
+ # '''
1017
+ # def __init__(self, x, y, z, *unused): # PYCHOK signature
1018
+ # Fsum.__init__(self, x * y, y * z, z * x)
1019
+ #
1020
+ # def __call__(self, a): # PYCHOK signature
1021
+ # return (self + a).fover(_4_0)
1031
1022
 
1032
- def _ab2(inst, x, y):
1033
- '''(INTERNAL) Yield Carlson 2-tuples C{(xn, yn)}.
1023
+
1024
+ class _Qot3(list):
1025
+ '''(INTERNAL) "Quarter" 3-dot product.
1026
+ '''
1027
+ def __init__(self, x, y, z, *unused): # PYCHOK signature
1028
+ try:
1029
+ D = Fdot_(x, y, y, z, z, x, f2product=True)
1030
+ except (OverflowError, TypeError, ValueError):
1031
+ D = Fsum(x * y, y * z, z * x, nonfinites=True)
1032
+ list.__init__(self, (0,) + D.partials) # NOT D.fsum2()!
1033
+
1034
+ def __call__(self, a):
1035
+ try:
1036
+ self[0] = a
1037
+ q = float(self) * _0_25
1038
+ finally:
1039
+ self[0] = 0
1040
+ return q
1041
+
1042
+ def __float__(self):
1043
+ return _fsum(self) # nonfinites=True
1044
+
1045
+
1046
+ def _ab3(x, y, inst=None):
1047
+ '''(INTERNAL) Yield Carlson 3-tuples C{(xn, yn, i)}.
1034
1048
  '''
1035
1049
  a, b = sqrt(x), sqrt(y)
1036
1050
  if b > a:
1037
1051
  b, a = a, b
1038
- for i in range(_TRIPS):
1039
- yield a, b # xi, yi
1052
+ for i in range(_TRIPS): # see
1053
+ yield a, b, i # xi, yi, i
1040
1054
  d = fabs(a - b)
1041
1055
  if d <= (a * _TolRG0): # 3-4 trips
1042
- _iterations(inst, i)
1043
1056
  break
1044
1057
  t = a
1045
1058
  a = favg(t, b)
1046
1059
  b = sqrt(t * b)
1047
1060
  else: # PYCHOK no cover
1048
1061
  raise _convergenceError(d / t, _TolRG0)
1062
+ if inst:
1063
+ inst._iteration += i
1049
1064
 
1050
1065
 
1051
1066
  def _convergenceError(d, tol, **thresh):
@@ -1067,9 +1082,9 @@ def _deltaX(sn, cn, dn, cX, fX):
1067
1082
  r = fX(sn, cn, dn) * PI_2 / cX
1068
1083
  return r - atan2(sn, cn)
1069
1084
 
1070
- except Exception as e:
1085
+ except Exception as X:
1071
1086
  n = NN(_delta_, typename(fX)[1:])
1072
- raise _ellipticError(n, sn, cn, dn, cause=e)
1087
+ raise _ellipticError(n, sn, cn, dn, cause=X)
1073
1088
 
1074
1089
 
1075
1090
  def _ellipticError(where, *args, **kwds_cause_txt):
@@ -1087,8 +1102,8 @@ def _ellipticError(where, *args, **kwds_cause_txt):
1087
1102
  return EllipticError(u, cause=x, txt=t)
1088
1103
 
1089
1104
 
1090
- def _Horner(S, e1, E2, E3, E4, E5, *over):
1091
- '''(INTERNAL) Horner form for C{_RD} and C{_RJ} below.
1105
+ def _Horner(S, e1, E2, E3, E4, E5, over):
1106
+ '''(INTERNAL) Horner-like form for C{_RD} and C{_RJ} below.
1092
1107
  '''
1093
1108
  E22 = E2**2
1094
1109
  # Polynomial is <https://DLMF.NIST.gov/19.36.E2>
@@ -1098,33 +1113,25 @@ def _Horner(S, e1, E2, E3, E4, E5, *over):
1098
1113
  # converted to Horner-like form ...
1099
1114
  e = e1 * 4084080
1100
1115
  S *= e
1101
- S += Fsum(E2 * -540540, 471240).fmul(E5)
1102
- S += Fsum(E2 * 612612, E3 * -540540, -556920).fmul(E4)
1103
- S += Fsum(E2 * -706860, E22 * 675675, E3 * 306306, 680680).fmul(E3)
1104
- S += Fsum(E2 * 417690, E22 * -255255, -875160).fmul(E2)
1116
+ S += Fsum(-E2 * 540540, 471240).fmul(E5)
1117
+ S += Fsum( E2 * 612612, -E3 * 540540, -556920).fmul(E4)
1118
+ S += Fsum(-E2 * 706860, E22 * 675675, E3 * 306306, 680680).fmul(E3)
1119
+ S += Fsum( E2 * 417690, -E22 * 255255, -875160).fmul(E2)
1105
1120
  S += 4084080
1106
- if over:
1107
- e *= over[0]
1121
+ if over != _1_0:
1122
+ e *= over
1108
1123
  return S.fdiv(e) # Fsum
1109
1124
 
1110
1125
 
1111
- def _iterations(inst, i):
1112
- '''(INTERNAL) Aggregate iterations B{C{i}}.
1113
- '''
1114
- if inst and i > 0:
1115
- inst._iteration += i
1116
-
1117
-
1118
1126
  def _3over(a, b):
1119
1127
  '''(INTERNAL) Return C{3 / (a * b)}.
1120
1128
  '''
1121
1129
  return _over(_3_0, a * b)
1122
1130
 
1123
1131
 
1124
- def _rC(unused, x, y):
1132
+ def _rC(x, y):
1125
1133
  '''(INTERNAL) Defined only for C{y != 0} and C{x >= 0}.
1126
1134
  '''
1127
- d = x - y
1128
1135
  if x < y: # catch NaN
1129
1136
  # <https://DLMF.NIST.gov/19.2.E18>
1130
1137
  d = y - x
@@ -1132,20 +1139,24 @@ def _rC(unused, x, y):
1132
1139
  elif x == y: # XXX d < EPS0? or EPS02 or _EPSmin
1133
1140
  d, r = y, _1_0
1134
1141
  elif y > 0: # <https://DLMF.NIST.gov/19.2.E19>
1142
+ d = x - y
1135
1143
  r = asinh(sqrt(d / y)) # atanh(sqrt((x - y) / x))
1136
1144
  elif y < 0: # <https://DLMF.NIST.gov/19.2.E20>
1145
+ d = x - y
1137
1146
  r = asinh(sqrt(-x / y)) # atanh(sqrt(x / (x - y)))
1138
1147
  else: # PYCHOK no cover
1139
- raise _ellipticError(Elliptic.fRC, x, y)
1140
- return r / sqrt(d) # float
1148
+ d = 0 # y == 0
1149
+ if d > 0 and x >= 0:
1150
+ return r / sqrt(d) # float
1151
+ raise _ellipticError(Elliptic.fRC, x, y)
1141
1152
 
1142
1153
 
1143
- def _RD(inst, x, y, z, *over):
1154
+ def _RD(x, y, z, over=_1_0, inst=None):
1144
1155
  '''(INTERNAL) Carlson, eqs 2.28 - 2.34.
1145
1156
  '''
1146
1157
  L = _List(x, y, z)
1147
- S = _Dsum()
1148
- for a, m, r, s in L.amrs4(inst, True, _TolRF):
1158
+ S = Fsum()
1159
+ for a, m, r, s in L.amrs4(True, _TolRF, inst):
1149
1160
  if s:
1150
1161
  S += _over(_3_0, (r + z) * s[2] * m)
1151
1162
  z = L[2] # s[2] = sqrt(z)
@@ -1153,26 +1164,26 @@ def _RD(inst, x, y, z, *over):
1153
1164
  xy = x * y
1154
1165
  z = (x + y) / _3_0
1155
1166
  z2 = z**2
1156
- return _Horner(S(_1_0), sqrt(a) * a * m,
1167
+ return _Horner(S, sqrt(a) * a * m,
1157
1168
  (xy - z2 * _6_0),
1158
1169
  (xy * _3_0 - z2 * _8_0) * z,
1159
1170
  (xy - z2) * z2 * _3_0,
1160
- (xy * z2 * z), *over) # Fsum
1171
+ (xy * z2 * z), over) # Fsum
1161
1172
 
1162
1173
 
1163
- def _rF2(inst, x, y): # 2-arg version, z=0
1174
+ def _rF2(x, y, inst=None): # 2-arg version, z=0
1164
1175
  '''(INTERNAL) Carlson, eqs 2.36 - 2.38.
1165
1176
  '''
1166
- for a, b in _ab2(inst, x, y): # PYCHOK yield
1177
+ for a, b, _ in _ab3(x, y, inst): # PYCHOK yield
1167
1178
  pass
1168
1179
  return _over(PI, a + b) # float
1169
1180
 
1170
1181
 
1171
- def _RF3(inst, x, y, z): # 3-arg version
1182
+ def _RF3(x, y, z, inst=None): # 3-arg version
1172
1183
  '''(INTERNAL) Carlson, eqs 2.2 - 2.7.
1173
1184
  '''
1174
1185
  L = _List(x, y, z)
1175
- for a, m, _, _ in L.amrs4(inst, False, _TolRF):
1186
+ for a, m, _, _ in L.amrs4(False, _TolRF, inst):
1176
1187
  pass
1177
1188
  x, y = L.rescale(a * m, x, y)
1178
1189
  z = neg(x + y)
@@ -1190,33 +1201,32 @@ def _RF3(inst, x, y, z): # 3-arg version
1190
1201
  return S.fdiv(sqrt(a) * 240240) # Fsum
1191
1202
 
1192
1203
 
1193
- def _rG2(inst, x, y, PI_=PI_4): # 2-args
1204
+ def _rG2(x, y, inst=None, PI_=PI_4): # 2-args
1194
1205
  '''(INTERNAL) Carlson, eqs 2.36 - 2.39.
1195
1206
  '''
1196
- m = -1 # neg!
1197
- S = None
1198
- for a, b in _ab2(inst, x, y): # PYCHOK yield
1199
- if S is None: # initial
1200
- S = _Dsum()
1201
- S += (a + b)**2 * _0_5
1202
- else:
1203
- S += (a - b)**2 * m
1207
+ m = 1
1208
+ S = Fsum()
1209
+ for a, b, i in _ab3(x, y, inst): # PYCHOK yield
1210
+ if i:
1211
+ S -= (a - b)**2 * m
1204
1212
  m *= 2
1205
- return S(PI_).fover(a + b)
1213
+ else:
1214
+ S += (a + b)**2 * _0_5
1215
+ return S.fmul(PI_).fover(a + b) # float
1206
1216
 
1207
1217
 
1208
- def _rG3(inst, x, y, z): # 3-arg version
1218
+ def _rG3(x, y, z): # 3-arg version
1209
1219
  '''(INTERNAL) C{x}, C{y} and C{z} all non-zero, see C{.fRG}.
1210
1220
  '''
1211
- R = _RF3(inst, x, y, z) * z
1221
+ R = _RF3(x, y, z) * z
1212
1222
  rd = (x - z) * (z - y) # - (y - z)
1213
1223
  if rd: # Carlson, eq 1.7
1214
- R += _RD(inst, x, y, z, _3_0 / rd)
1224
+ R += _RD(x, y, z, _3_0 / rd)
1215
1225
  R += sqrt(x * y / z)
1216
- return R.fover(_2_0)
1226
+ return R.fover(_2_0) # float
1217
1227
 
1218
1228
 
1219
- def _RJ(inst, x, y, z, p, *over):
1229
+ def _RJ(x, y, z, p, over=_1_0, inst=None):
1220
1230
  '''(INTERNAL) Carlson, eqs 2.17 - 2.25.
1221
1231
  '''
1222
1232
  def _xyzp(x, y, z, p):
@@ -1224,17 +1234,17 @@ def _RJ(inst, x, y, z, p, *over):
1224
1234
 
1225
1235
  L = _List(x, y, z, p)
1226
1236
  n = neg(_xyzp(x, y, z, -p))
1227
- S = _Dsum()
1228
- for a, m, _, s in L.amrs4(inst, True, _TolRD):
1237
+ S = Fsum()
1238
+ for a, m, _, s in L.amrs4(True, _TolRD, inst):
1229
1239
  if s:
1230
1240
  d = _xyzp(*s)
1231
1241
  if d:
1232
1242
  if n:
1233
- rc = _rC(inst, _1_0, n / d**2 + _1_0)
1234
- n = n / _64_0 # /= chokes PyChecker
1243
+ r = _rC(_1_0, (n / d**2 + _1_0))
1244
+ n = n / _64_0 # /= chokes PyChecker
1235
1245
  else:
1236
- rc = _1_0 # == _rC(None, _1_0, _1_0)
1237
- S += rc / (d * m)
1246
+ r = _1_0 # == _rC(_1_0, _1_0)
1247
+ S += r / (d * m)
1238
1248
  else: # PYCHOK no cover
1239
1249
  return NAN
1240
1250
  x, y, z = L.rescale(a * m, x, y, z)
@@ -1244,10 +1254,21 @@ def _RJ(inst, x, y, z, p, *over):
1244
1254
  E2 = Fsum(x * y, x * z, y * z, -p2 * _3_0)
1245
1255
  E2p = E2 * p
1246
1256
  xyz = x * y * z
1247
- return _Horner(S(_6_0), sqrt(a) * a * m, E2,
1257
+ return _Horner(S.fmul(_6_0), sqrt(a) * a * m, E2,
1248
1258
  Fsum(p3 * _4_0, xyz, E2p * _2_0),
1249
1259
  Fsum(p3 * _3_0, E2p, xyz * _2_0).fmul(p),
1250
- xyz * p2, *over) # Fsum
1260
+ xyz * p2, over) # Fsum
1261
+
1262
+
1263
+ class _RJfma(object):
1264
+ '''(INTERNAL) Carlson, "fma"able.
1265
+ '''
1266
+ def __init__(self, *args):
1267
+ self._Rj = _RJ(*args)
1268
+
1269
+ def ma(self, b, c):
1270
+ r = fma(self._Rj, b, c)
1271
+ return float(r)
1251
1272
 
1252
1273
  # **) MIT License
1253
1274
  #