pygeodesy 24.8.24__py2.py3-none-any.whl → 24.9.24__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.
Files changed (49) hide show
  1. {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/METADATA +7 -7
  2. {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/RECORD +49 -48
  3. pygeodesy/__init__.py +7 -5
  4. pygeodesy/__main__.py +46 -47
  5. pygeodesy/auxilats/_CX_4.py +104 -181
  6. pygeodesy/auxilats/_CX_6.py +152 -277
  7. pygeodesy/auxilats/_CX_8.py +211 -438
  8. pygeodesy/auxilats/_CX_Rs.py +222 -0
  9. pygeodesy/auxilats/__init__.py +2 -2
  10. pygeodesy/auxilats/__main__.py +30 -38
  11. pygeodesy/auxilats/auxLat.py +28 -36
  12. pygeodesy/auxilats/auxily.py +30 -50
  13. pygeodesy/basics.py +24 -14
  14. pygeodesy/booleans.py +13 -14
  15. pygeodesy/clipy.py +7 -7
  16. pygeodesy/constants.py +44 -31
  17. pygeodesy/deprecated/__init__.py +1 -1
  18. pygeodesy/deprecated/functions.py +9 -1
  19. pygeodesy/elliptic.py +154 -88
  20. pygeodesy/errors.py +32 -5
  21. pygeodesy/etm.py +71 -59
  22. pygeodesy/fmath.py +125 -96
  23. pygeodesy/fstats.py +8 -12
  24. pygeodesy/fsums.py +802 -355
  25. pygeodesy/geodesici.py +6 -5
  26. pygeodesy/geodesicx/_C4_24.py +1 -3
  27. pygeodesy/geodesicx/_C4_27.py +1 -3
  28. pygeodesy/geodesicx/_C4_30.py +1 -3
  29. pygeodesy/geodesicx/__init__.py +1 -1
  30. pygeodesy/geodesicx/__main__.py +44 -46
  31. pygeodesy/geodesicx/gxarea.py +3 -3
  32. pygeodesy/geodesicx/gxbases.py +32 -18
  33. pygeodesy/internals.py +50 -9
  34. pygeodesy/interns.py +3 -2
  35. pygeodesy/karney.py +79 -60
  36. pygeodesy/ktm.py +4 -4
  37. pygeodesy/lazily.py +10 -5
  38. pygeodesy/mgrs.py +47 -42
  39. pygeodesy/named.py +4 -1
  40. pygeodesy/points.py +3 -3
  41. pygeodesy/props.py +7 -6
  42. pygeodesy/resections.py +2 -2
  43. pygeodesy/rhumb/__init__.py +1 -1
  44. pygeodesy/rhumb/aux_.py +42 -60
  45. pygeodesy/sphericalNvector.py +4 -4
  46. pygeodesy/sphericalTrigonometry.py +2 -2
  47. pygeodesy/triaxials.py +3 -3
  48. {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/WHEEL +0 -0
  49. {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/top_level.txt +0 -0
pygeodesy/fmath.py CHANGED
@@ -10,11 +10,11 @@ from pygeodesy.basics import _copysign, copysign0, isbool, isint, isscalar, \
10
10
  len2, map1, _xiterable
11
11
  from pygeodesy.constants import EPS0, EPS02, EPS1, NAN, PI, PI_2, PI_4, \
12
12
  _0_0, _0_125, _1_6th, _0_25, _1_3rd, _0_5, _1_0, \
13
- _N_1_0, _1_5, _copysign_0_0, _isfinite, remainder
13
+ _N_1_0, _1_5, _copysign_0_0, isfinite, remainder
14
14
  from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
15
15
  _xError, _xkwds_get1, _xkwds_pop2
16
- from pygeodesy.fsums import _2float, Fsum, fsum, fsum1_, _isFsumTuple, _1primed, \
17
- Fmt, unstr
16
+ from pygeodesy.fsums import _2float, Fsum, fsum, fsum1_, _isFsumTuple, \
17
+ _1primed, _Psum_, Fmt, unstr
18
18
  from pygeodesy.interns import MISSING, _negative_, _not_scalar_
19
19
  from pygeodesy.lazily import _ALL_LAZY, _sys_version_info2
20
20
  # from pygeodesy.streprs import Fmt, unstr # from .fsums
@@ -24,10 +24,10 @@ from math import fabs, sqrt # pow
24
24
  import operator as _operator # in .datums, .trf, .utm
25
25
 
26
26
  __all__ = _ALL_LAZY.fmath
27
- __version__ = '24.08.15'
27
+ __version__ = '24.09.19'
28
28
 
29
- # sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
30
- _0_4142 = 0.41421356237309504880 # ... sqrt(2) - 1
29
+ # sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
30
+ _0_4142 = 0.41421356237309504880 # ... ~ 3730904090310553 / 9007199254740992
31
31
  _2_3rd = _1_3rd * 2
32
32
  _h_lt_b_ = 'abs(h) < abs(b)'
33
33
 
@@ -36,13 +36,10 @@ class Fdot(Fsum):
36
36
  '''Precision dot product.
37
37
  '''
38
38
  def __init__(self, a, *b, **name_RESIDUAL):
39
- '''New L{Fdot} precision dot product M{sum(a[i] * b[i] for
40
- i=0..len(a)-1)}.
39
+ '''New L{Fdot} precision dot product M{sum(a[i] * b[i] for i=0..len(a)-1)}.
41
40
 
42
- @arg a: Iterable of values (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
43
- instance).
44
- @arg b: Other values (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
45
- all positional.
41
+ @arg a: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
42
+ @arg b: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
46
43
  @kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
47
44
  threshold (C{scalar}) for raising L{ResidualError}s, see class
48
45
  L{Fsum<Fsum.__init__>}.
@@ -64,14 +61,16 @@ class Fdot(Fsum):
64
61
  class Fhorner(Fsum):
65
62
  '''Precision polynomial evaluation using the Horner form.
66
63
  '''
67
- def __init__(self, x, *cs, **name_RESIDUAL):
68
- '''New L{Fhorner} evaluation of polynomial M{sum(cs[i] * x**i for
69
- i=0..len(cs)-1)}.
64
+ def __init__(self, x, *cs, **incx_name_RESIDUAL):
65
+ '''New L{Fhorner} evaluation of polynomial M{sum(cs[i] * x**i for i=0..n)} if
66
+ C{B{incx}=False} for decreasing exponent M{sum(... i=n..0)} where C{n =
67
+ len(cs) - 1}.
70
68
 
71
- @arg x: Polynomial argument (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
72
- @arg cs: Polynomial coeffients (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
73
- instance), all positional.
74
- @kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
69
+ @arg x: Polynomial argument (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
70
+ @arg cs: Polynomial coeffients (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}),
71
+ all positional.
72
+ @kwarg incx_name_RESIDUAL: Optional C{B{name}=NN} (C{str}), C{B{incx}=True}
73
+ for in-/decreasing exponents (C{bool}) and the C{B{RESIDUAL}=0.0}
75
74
  threshold (C{scalar}) for raising L{ResidualError}s, see class
76
75
  L{Fsum<Fsum.__init__>}.
77
76
 
@@ -83,9 +82,10 @@ class Fhorner(Fsum):
83
82
 
84
83
  @see: Function L{fhorner} and methods L{Fsum.fadd} and L{Fsum.fmul}.
85
84
  '''
85
+ incx, name_RESIDUAL = _xkwds_pop2(incx_name_RESIDUAL, incx=True)
86
86
  Fsum.__init__(self, **name_RESIDUAL)
87
87
  if cs:
88
- self._fhorner(x, cs, Fhorner.__name__)
88
+ self._fhorner(x, cs, Fhorner.__name__, incx=incx)
89
89
  else:
90
90
  self._fset_ps(_0_0)
91
91
 
@@ -94,11 +94,11 @@ class Fhypot(Fsum):
94
94
  '''Precision summation and hypotenuse, default C{root=2}.
95
95
  '''
96
96
  def __init__(self, *xs, **root_name_RESIDUAL_raiser):
97
- '''New L{Fhypot} hypotenuse of (the I{root} of) several components
98
- (raised to the power I{root}).
97
+ '''New L{Fhypot} hypotenuse of (the I{root} of) several components (raised
98
+ to the power I{root}).
99
99
 
100
- @arg xs: Components (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
101
- all positional.
100
+ @arg xs: Components (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
101
+ positional.
102
102
  @kwarg root_name_RESIDUAL_raiser: Optional, exponent and C{B{root}=2} order
103
103
  (C{scalar}), C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
104
104
  threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for
@@ -121,12 +121,12 @@ class Fpolynomial(Fsum):
121
121
  '''Precision polynomial evaluation.
122
122
  '''
123
123
  def __init__(self, x, *cs, **name_RESIDUAL):
124
- '''New L{Fpolynomial} evaluation of the polynomial
125
- M{sum(cs[i] * x**i for i=0..len(cs)-1)}.
124
+ '''New L{Fpolynomial} evaluation of the polynomial M{sum(cs[i] * x**i for
125
+ i=0..len(cs)-1)}.
126
126
 
127
- @arg x: Polynomial argument (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
128
- @arg cs: Polynomial coeffients (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
129
- instance), all positional.
127
+ @arg x: Polynomial argument (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
128
+ @arg cs: Polynomial coeffients (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}),
129
+ all positional.
130
130
  @kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
131
131
  threshold (C{scalar}) for raising L{ResidualError}s, see class
132
132
  L{Fsum<Fsum.__init__>}.
@@ -153,9 +153,9 @@ class Fpowers(Fsum):
153
153
  def __init__(self, power, *xs, **name_RESIDUAL_raiser):
154
154
  '''New L{Fpowers} sum of (the I{power} of) several bases.
155
155
 
156
- @arg power: The exponent (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
157
- @arg xs: One or more bases (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
158
- all positional.
156
+ @arg power: The exponent (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
157
+ @arg xs: One or more bases (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
158
+ positional.
159
159
  @kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
160
160
  threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for raising
161
161
  L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and method
@@ -175,9 +175,9 @@ class Froot(Fsum):
175
175
  def __init__(self, root, *xs, **name_RESIDUAL_raiser):
176
176
  '''New L{Froot} root of a precision sum.
177
177
 
178
- @arg root: The order (C{scalar} or an L{Fsum} or L{Fsum2Tuple}), non-zero.
179
- @arg xs: Items to summate (each a C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
180
- all positional.
178
+ @arg root: The order (C{scalar}, an L{Fsum} or L{Fsum2Tuple}), non-zero.
179
+ @arg xs: Items to summate (each a C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
180
+ positional.
181
181
  @kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
182
182
  threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for raising
183
183
  L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and method
@@ -226,7 +226,7 @@ def bqrt(x):
226
226
  '''Return the 4-th, I{bi-quadratic} or I{quartic} root, M{x**(1 / 4)},
227
227
  preserving C{type(B{x})}.
228
228
 
229
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
229
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
230
230
 
231
231
  @return: I{Quartic} root (C{float} or an L{Fsum}).
232
232
 
@@ -256,7 +256,7 @@ except ImportError: # Python 3.10-
256
256
  def cbrt(x):
257
257
  '''Compute the cube root M{x**(1/3)}, preserving C{type(B{x})}.
258
258
 
259
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
259
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
260
260
 
261
261
  @return: Cubic root (C{float} or L{Fsum}).
262
262
 
@@ -274,7 +274,7 @@ def cbrt(x):
274
274
  def cbrt2(x): # PYCHOK attr
275
275
  '''Compute the cube root I{squared} M{x**(2/3)}, preserving C{type(B{x})}.
276
276
 
277
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
277
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
278
278
 
279
279
  @return: Cube root I{squared} (C{float} or L{Fsum}).
280
280
 
@@ -284,11 +284,11 @@ def cbrt2(x): # PYCHOK attr
284
284
 
285
285
 
286
286
  def euclid(x, y):
287
- '''I{Appoximate} the norm M{sqrt(x**2 + y**2)} by
288
- M{max(abs(x), abs(y)) + min(abs(x), abs(y)) * 0.4142...}.
287
+ '''I{Appoximate} the norm M{sqrt(x**2 + y**2)} by M{max(abs(x),
288
+ abs(y)) + min(abs(x), abs(y)) * 0.4142...}.
289
289
 
290
- @arg x: X component (C{scalar} or L{Fsum} instance).
291
- @arg y: Y component (C{scalar} or L{Fsum} instance).
290
+ @arg x: X component (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
291
+ @arg y: Y component (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
292
292
 
293
293
  @return: Appoximate norm (C{float} or L{Fsum}).
294
294
 
@@ -301,11 +301,11 @@ def euclid(x, y):
301
301
 
302
302
 
303
303
  def euclid_(*xs):
304
- '''I{Appoximate} the norm M{sqrt(sum(x**2 for x in xs))} by
305
- cascaded L{euclid}.
304
+ '''I{Appoximate} the norm M{sqrt(sum(x**2 for x in xs))} by cascaded
305
+ L{euclid}.
306
306
 
307
- @arg xs: X arguments (each C{scalar} or an L{Fsum}
308
- instance), all positional.
307
+ @arg xs: X arguments (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}),
308
+ all positional.
309
309
 
310
310
  @return: Appoximate norm (C{float} or L{Fsum}).
311
311
 
@@ -404,10 +404,10 @@ def fatan2(y, x):
404
404
 
405
405
 
406
406
  def favg(a, b, f=_0_5):
407
- '''Return the precision average of two values.
407
+ '''Return the precise average of two values.
408
408
 
409
- @arg a: One (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
410
- @arg b: Other (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
409
+ @arg a: One (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
410
+ @arg b: Other (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
411
411
  @kwarg f: Optional fraction (C{float}).
412
412
 
413
413
  @return: M{a + f * (b - a)} (C{float}).
@@ -421,39 +421,35 @@ def favg(a, b, f=_0_5):
421
421
 
422
422
 
423
423
  def fdot(a, *b):
424
- '''Return the precision dot product M{sum(a[i] * b[i] for
425
- i=0..len(a))}.
424
+ '''Return the precision dot product M{sum(a[i] * b[i] for ni=0..len(a))}.
426
425
 
427
- @arg a: Iterable of values (each C{scalar}).
428
- @arg b: Other values (each C{scalar}), all positional.
426
+ @arg a: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
427
+ @arg b: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
428
+ positional.
429
429
 
430
430
  @return: Dot product (C{float}).
431
431
 
432
432
  @raise LenError: Unequal C{len(B{a})} and C{len(B{b})}.
433
433
 
434
- @see: Class L{Fdot} and U{Algorithm 5.10 B{DotK}
435
- <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}.
434
+ @see: Class L{Fdot}, U{Algorithm 5.10 B{DotK}
435
+ <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>} and function
436
+ C{math.sumprod} in Python 3.12 and later.
436
437
  '''
437
438
  return fsum(_map_mul(a, b, fdot))
438
439
 
439
440
 
440
441
  def fdot3(xs, ys, zs, start=0):
441
- '''Return the precision dot product M{start +
442
- sum(a[i] * b[i] * c[i] for i=0..len(a)-1)}.
443
-
444
- @arg xs: Iterable (each C{scalar} or an L{Fsum} or
445
- L{Fsum2Tuple} instance).
446
- @arg ys: Iterable (each C{scalar} or an L{Fsum} or
447
- L{Fsum2Tuple} instance).
448
- @arg zs: Iterable (each C{scalar} or an L{Fsum} or
449
- L{Fsum2Tuple} instance).
450
- @kwarg start: Optional bias (C{scalar} or an L{Fsum}
451
- or L{Fsum2Tuple}).
442
+ '''Return the precision dot product M{start + sum(a[i] * b[i] * c[i]
443
+ for i=0..len(a)-1)}.
444
+
445
+ @arg xs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
446
+ @arg ys: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
447
+ @arg zs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
448
+ @kwarg start: Optional bias (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
452
449
 
453
450
  @return: Dot product (C{float}).
454
451
 
455
- @raise LenError: Unequal C{len(B{xs})}, C{len(B{ys})}
456
- and/or C{len(B{zs})}.
452
+ @raise LenError: Unequal C{len(B{xs})}, C{len(B{ys})} and/or C{len(B{zs})}.
457
453
 
458
454
  @raise OverflowError: Partial C{2sum} overflow.
459
455
  '''
@@ -462,9 +458,8 @@ def fdot3(xs, ys, zs, start=0):
462
458
  yield s
463
459
  if p:
464
460
  yield _1_0
465
- _F = Fsum
466
461
  for x, y, z in zip(xs, ys, zs):
467
- yield (_F(x) * y) * z
462
+ yield (Fsum(x) * y) * z
468
463
  if p:
469
464
  yield _N_1_0
470
465
 
@@ -475,15 +470,16 @@ def fdot3(xs, ys, zs, start=0):
475
470
  return fsum(_mul3(xs, ys, zs, start, n < 4))
476
471
 
477
472
 
478
- def fhorner(x, *cs):
479
- '''Evaluate the polynomial M{sum(cs[i] * x**i for
480
- i=0..len(cs)-1)} using the Horner form.
473
+ def fhorner(x, *cs, **incx):
474
+ '''Evaluate a polynomial using the Horner form M{sum(cs[i] * x**i
475
+ for i=0..n)} or if C{B{incx}=False} for decreasing exponent
476
+ M{sum(... i=n..0)} where C{n = len(cs) - 1}.
481
477
 
482
478
  @return: Horner sum (C{float}).
483
479
 
484
480
  @see: Class L{Fhorner} for further details.
485
481
  '''
486
- H = Fhorner(x, *cs)
482
+ H = Fhorner(x, *cs, **incx)
487
483
  return float(H)
488
484
 
489
485
 
@@ -491,10 +487,9 @@ def fidw(xs, ds, beta=2):
491
487
  '''Interpolate using U{Inverse Distance Weighting
492
488
  <https://WikiPedia.org/wiki/Inverse_distance_weighting>} (IDW).
493
489
 
494
- @arg xs: Known values (each C{scalar} or an L{Fsum} or
495
- L{Fsum2Tuple} instance).
496
- @arg ds: Non-negative distances (each C{scalar} or an L{Fsum}
497
- or L{Fsum2Tuple} instance).
490
+ @arg xs: Known values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
491
+ @arg ds: Non-negative distances (each C{scalar}, an L{Fsum} or
492
+ L{Fsum2Tuple}).
498
493
  @kwarg beta: Inverse distance power (C{int}, 0, 1, 2, or 3).
499
494
 
500
495
  @return: Interpolated value C{x} (C{float}).
@@ -550,10 +545,26 @@ def fidw(xs, ds, beta=2):
550
545
  return x
551
546
 
552
547
 
548
+ def fma(x, y, z, **raiser):
549
+ '''Fused-multiply-add, using C{math.fma(x, y, z)} from Python 3.13+
550
+ or an equivalent implementation.
551
+
552
+ @arg x: Multiplicand (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
553
+ @arg y: Multiplier (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
554
+ @arg z: Addend (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
555
+ @kwarg raiser: Keyword argument C{B{raiser}=False}, if C{True},
556
+ throw an exception, otherwise pass any non-finite
557
+ result (C{bool}).
558
+
559
+ @return: C{(x * y) + z} (L{Fsum} or C{float}).
560
+ '''
561
+ return _Psum_(x).fma(y, z, raiser=raiser).as_iscalar
562
+
563
+
553
564
  def fmean(xs):
554
565
  '''Compute the accurate mean M{sum(xs) / len(xs)}.
555
566
 
556
- @arg xs: Values (C{scalar} or L{Fsum} instances).
567
+ @arg xs: Values (each C{scalar}, or L{Fsum} or L{Fsum2Tuple}).
557
568
 
558
569
  @return: Mean value (C{float}).
559
570
 
@@ -575,9 +586,25 @@ def fmean_(*xs):
575
586
  return fmean(xs)
576
587
 
577
588
 
589
+ def f2mul_(x, *ys, **raiser):
590
+ '''Cascaded, accurate multiplication C{B{x} * B{y} * B{y} ...} for all B{C{ys}}.
591
+
592
+ @arg x: Multiplicand (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
593
+ @arg ys: Multipliers (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
594
+ positional.
595
+ @kwarg raiser: Keyword argument C{B{raiser}=False}, if C{True}, throw an
596
+ exception, otherwise pass any non-finite result (C{bool}).
597
+
598
+ @return: The cascaded I{TwoProduct} (L{Fsum}, C{float} or C{int}).
599
+
600
+ @see: U{Equations 2.3<https://www.TUHH.De/ti3/paper/rump/OzOgRuOi06.pdf>}
601
+ '''
602
+ return _Psum_(x).f2mul_(*ys, **raiser).as_iscalar
603
+
604
+
578
605
  def fpolynomial(x, *cs, **over):
579
- '''Evaluate the polynomial M{sum(cs[i] * x**i for
580
- i=0..len(cs)) [/ over]}.
606
+ '''Evaluate the polynomial M{sum(cs[i] * x**i for i=0..len(cs))
607
+ [/ over]}.
581
608
 
582
609
  @kwarg over: Optional final, I{non-zero} divisor (C{scalar}).
583
610
 
@@ -593,7 +620,7 @@ def fpolynomial(x, *cs, **over):
593
620
  def fpowers(x, n, alts=0):
594
621
  '''Return a series of powers M{[x**i for i=1..n]}.
595
622
 
596
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
623
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
597
624
  @arg n: Highest exponent (C{int}).
598
625
  @kwarg alts: Only alternating powers, starting with this
599
626
  exponent (C{int}).
@@ -609,7 +636,7 @@ def fpowers(x, n, alts=0):
609
636
  elif n < 1:
610
637
  raise _ValueError(n=n)
611
638
 
612
- p = x if isint(x) or _isFsumTuple(x) else _2float(x=x)
639
+ p = x if isscalar(x) or _isFsumTuple(x) else _2float(x=x)
613
640
  ps = tuple(_powers(p, n))
614
641
 
615
642
  if alts > 0: # x**2, x**4, ...
@@ -627,7 +654,7 @@ except ImportError:
627
654
  '''Iterable product, like C{math.prod} or C{numpy.prod}.
628
655
 
629
656
  @arg xs: Iterable of values to be multiplied (each
630
- C{scalar} or an L{Fsum}).
657
+ C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
631
658
  @kwarg start: Initial value, also the value returned
632
659
  for an empty B{C{xs}} (C{scalar}).
633
660
 
@@ -746,7 +773,7 @@ def fremainder(x, y):
746
773
  # On Windows 32-bit with python 2.7, math.fmod(-0.0, 360)
747
774
  # == +0.0. This fixes this bug. See also Math::AngNormalize
748
775
  # in the C++ library, Math.sincosd has a similar fix.
749
- if _isfinite(x):
776
+ if isfinite(x):
750
777
  try:
751
778
  r = remainder(x, y) if x else x
752
779
  except Exception as e:
@@ -822,8 +849,8 @@ def hypot1(x):
822
849
  def hypot2(x, y):
823
850
  '''Compute the I{squared} norm M{x**2 + y**2}.
824
851
 
825
- @arg x: X (C{scalar} or L{Fsum} or L{Fsum2Tuple}).
826
- @arg y: Y (C{scalar} or L{Fsum} or L{Fsum2Tuple}).
852
+ @arg x: X (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
853
+ @arg y: Y (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
827
854
 
828
855
  @return: C{B{x}**2 + B{y}**2} (C{float}).
829
856
  '''
@@ -843,8 +870,8 @@ def hypot2(x, y):
843
870
  def hypot2_(*xs):
844
871
  '''Compute the I{squared} norm C{fsum(x**2 for x in B{xs})}.
845
872
 
846
- @arg xs: Components (each C{scalar} or an L{Fsum} or
847
- L{Fsum2Tuple} instance), all positional.
873
+ @arg xs: Components (each C{scalar}, an L{Fsum} or
874
+ L{Fsum2Tuple}), all positional.
848
875
 
849
876
  @return: Squared norm (C{float}).
850
877
 
@@ -899,9 +926,10 @@ def norm2(x, y):
899
926
 
900
927
 
901
928
  def norm_(*xs):
902
- '''Normalize all n-dimensional vector components.
929
+ '''Normalize the components of an n-dimensional vector.
903
930
 
904
- @arg xs: Components (C{scalar}s), all positional.
931
+ @arg xs: Components (each C{scalar}, an L{Fsum} or
932
+ L{Fsum2Tuple}), all positional.
905
933
 
906
934
  @return: Yield each component, normalized.
907
935
 
@@ -944,7 +972,7 @@ def sqrt0(x, Error=None):
944
972
  '''Return the square root C{sqrt(B{x})} iff C{B{x} > }L{EPS02},
945
973
  preserving C{type(B{x})}.
946
974
 
947
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
975
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
948
976
  @kwarg Error: Error to raise for negative B{C{x}}.
949
977
 
950
978
  @return: Square root (C{float} or L{Fsum}) or C{0.0}.
@@ -956,14 +984,15 @@ def sqrt0(x, Error=None):
956
984
  '''
957
985
  if Error and x < 0:
958
986
  raise Error(unstr(sqrt0, x))
959
- return _root(x, _0_5, sqrt0) if x > EPS02 else (_0_0 if x < EPS02 else EPS0)
987
+ return _root(x, _0_5, sqrt0) if x > EPS02 else (
988
+ _0_0 if x < EPS02 else EPS0)
960
989
 
961
990
 
962
991
  def sqrt3(x):
963
992
  '''Return the square root, I{cubed} M{sqrt(x)**3} or M{sqrt(x**3)},
964
993
  preserving C{type(B{x})}.
965
994
 
966
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
995
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
967
996
 
968
997
  @return: Square root I{cubed} (C{float} or L{Fsum}).
969
998
 
@@ -1019,7 +1048,7 @@ def zcrt(x):
1019
1048
  '''Return the 6-th, I{zenzi-cubic} root, M{x**(1 / 6)},
1020
1049
  preserving C{type(B{x})}.
1021
1050
 
1022
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
1051
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
1023
1052
 
1024
1053
  @return: I{Zenzi-cubic} root (C{float} or L{Fsum}).
1025
1054
 
@@ -1036,7 +1065,7 @@ def zqrt(x):
1036
1065
  '''Return the 8-th, I{zenzi-quartic} or I{squared-quartic} root,
1037
1066
  M{x**(1 / 8)}, preserving C{type(B{x})}.
1038
1067
 
1039
- @arg x: Value (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
1068
+ @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
1040
1069
 
1041
1070
  @return: I{Zenzi-quartic} root (C{float} or L{Fsum}).
1042
1071
 
pygeodesy/fstats.py CHANGED
@@ -10,9 +10,10 @@ from __future__ import division as _; del _ # PYCHOK semicolon
10
10
  from pygeodesy.basics import isscalar, isodd, _xinstanceof, \
11
11
  _xiterable, _xsubclassof, _zip
12
12
  from pygeodesy.constants import _0_0, _1_0, _2_0, _3_0, _4_0, _6_0
13
- from pygeodesy.errors import _AssertionError, _ValueError, _xError
13
+ from pygeodesy.errors import _ValueError, _xError, _xkwds_item2
14
14
  from pygeodesy.fmath import Fsqrt, Fmt
15
- from pygeodesy.fsums import _2finite, Fsum, _iadd_op_, _isFsumTuple
15
+ from pygeodesy.fsums import _2finite, Fsum, _iadd_op_, \
16
+ _isFsumTuple, _xsError
16
17
  from pygeodesy.interns import _odd_, _SPACE_
17
18
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
18
19
  from pygeodesy.named import _name__, _Named, _NotImplemented, \
@@ -21,24 +22,19 @@ from pygeodesy.named import _name__, _Named, _NotImplemented, \
21
22
  # from pygeodesy.streprs import Fmt # from .fmath
22
23
 
23
24
  __all__ = _ALL_LAZY.fstats
24
- __version__ = '24.05.21'
25
+ __version__ = '24.09.23'
25
26
 
26
27
 
27
28
  def _2Floats(**xs):
28
- '''(INTERNAL) Yield each value as C{float} or L{Fsum}.
29
+ '''(INTERNAL) Yield all C{xs} as C{float} or L{Fsum}.
29
30
  '''
31
+ name, xs = _xkwds_item2(xs)
30
32
  try:
31
- name, xs = xs.popitem()
32
- except Exception as X:
33
- raise _AssertionError(xs=xs, cause=X)
34
-
35
- try:
36
- i = None
33
+ i, x = None, xs
37
34
  for i, x in enumerate(_xiterable(xs)): # don't unravel Fsums
38
35
  yield x._Fsum if _isFsumTuple(x) else _2finite(x)
39
36
  except Exception as X:
40
- raise _xError(X, name, xs) if i is None else \
41
- _xError(X, Fmt.INDEX(name, i), x)
37
+ raise _xsError(X, xs, i, x, name)
42
38
 
43
39
 
44
40
  def _sampled(n, sample):