pygeodesy 25.1.9__py2.py3-none-any.whl → 25.4.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.
Files changed (96) hide show
  1. pygeodesy/__init__.py +35 -31
  2. pygeodesy/__main__.py +3 -3
  3. pygeodesy/albers.py +29 -36
  4. pygeodesy/auxilats/_CX_4.py +2 -2
  5. pygeodesy/auxilats/_CX_6.py +2 -2
  6. pygeodesy/auxilats/_CX_8.py +2 -2
  7. pygeodesy/auxilats/_CX_Rs.py +59 -40
  8. pygeodesy/auxilats/__init__.py +3 -3
  9. pygeodesy/auxilats/__main__.py +9 -7
  10. pygeodesy/auxilats/auxAngle.py +2 -2
  11. pygeodesy/auxilats/auxLat.py +13 -13
  12. pygeodesy/auxilats/auxily.py +13 -9
  13. pygeodesy/azimuthal.py +7 -6
  14. pygeodesy/basics.py +65 -22
  15. pygeodesy/booleans.py +12 -10
  16. pygeodesy/cartesianBase.py +21 -20
  17. pygeodesy/clipy.py +11 -10
  18. pygeodesy/constants.py +11 -10
  19. pygeodesy/css.py +14 -11
  20. pygeodesy/datums.py +8 -8
  21. pygeodesy/deprecated/bases.py +2 -2
  22. pygeodesy/deprecated/classes.py +2 -2
  23. pygeodesy/deprecated/consterns.py +4 -4
  24. pygeodesy/dms.py +8 -8
  25. pygeodesy/ecef.py +10 -7
  26. pygeodesy/elevations.py +9 -8
  27. pygeodesy/ellipsoidalBase.py +19 -8
  28. pygeodesy/ellipsoidalBaseDI.py +17 -15
  29. pygeodesy/ellipsoidalNvector.py +6 -3
  30. pygeodesy/ellipsoidalVincenty.py +4 -1
  31. pygeodesy/ellipsoids.py +167 -138
  32. pygeodesy/elliptic.py +9 -9
  33. pygeodesy/errors.py +44 -43
  34. pygeodesy/etm.py +9 -9
  35. pygeodesy/fmath.py +10 -9
  36. pygeodesy/formy.py +11 -12
  37. pygeodesy/frechet.py +216 -109
  38. pygeodesy/fstats.py +5 -4
  39. pygeodesy/fsums.py +107 -122
  40. pygeodesy/gars.py +7 -7
  41. pygeodesy/geodesici.py +15 -14
  42. pygeodesy/geodesicw.py +34 -32
  43. pygeodesy/geodesicx/__init__.py +1 -1
  44. pygeodesy/geodesicx/__main__.py +12 -10
  45. pygeodesy/geodesicx/gx.py +30 -33
  46. pygeodesy/geodesicx/gxarea.py +2 -2
  47. pygeodesy/geodesicx/gxline.py +5 -5
  48. pygeodesy/geodsolve.py +18 -17
  49. pygeodesy/geohash.py +7 -8
  50. pygeodesy/geoids.py +35 -34
  51. pygeodesy/hausdorff.py +17 -13
  52. pygeodesy/heights.py +2 -4
  53. pygeodesy/internals.py +31 -46
  54. pygeodesy/interns.py +12 -9
  55. pygeodesy/iters.py +8 -8
  56. pygeodesy/karney.py +73 -66
  57. pygeodesy/ktm.py +5 -5
  58. pygeodesy/latlonBase.py +14 -18
  59. pygeodesy/lazily.py +73 -74
  60. pygeodesy/lcc.py +11 -9
  61. pygeodesy/ltp.py +8 -7
  62. pygeodesy/ltpTuples.py +2 -2
  63. pygeodesy/mgrs.py +7 -6
  64. pygeodesy/named.py +47 -31
  65. pygeodesy/nvectorBase.py +7 -7
  66. pygeodesy/osgr.py +9 -8
  67. pygeodesy/points.py +12 -10
  68. pygeodesy/props.py +25 -25
  69. pygeodesy/resections.py +11 -10
  70. pygeodesy/rhumb/__init__.py +1 -1
  71. pygeodesy/rhumb/aux_.py +14 -14
  72. pygeodesy/rhumb/bases.py +22 -20
  73. pygeodesy/rhumb/ekx.py +6 -6
  74. pygeodesy/rhumb/solve.py +15 -15
  75. pygeodesy/solveBase.py +3 -3
  76. pygeodesy/sphericalBase.py +6 -6
  77. pygeodesy/sphericalNvector.py +6 -5
  78. pygeodesy/sphericalTrigonometry.py +8 -7
  79. pygeodesy/streprs.py +14 -14
  80. pygeodesy/trf.py +14 -12
  81. pygeodesy/triaxials.py +29 -26
  82. pygeodesy/units.py +5 -4
  83. pygeodesy/unitsBase.py +5 -4
  84. pygeodesy/ups.py +3 -3
  85. pygeodesy/utily.py +4 -4
  86. pygeodesy/utmups.py +4 -4
  87. pygeodesy/utmupsBase.py +88 -18
  88. pygeodesy/vector2d.py +18 -11
  89. pygeodesy/vector3d.py +7 -6
  90. pygeodesy/webmercator.py +6 -5
  91. pygeodesy/wgrs.py +6 -5
  92. {pygeodesy-25.1.9.dist-info → pygeodesy-25.4.25.dist-info}/METADATA +35 -31
  93. pygeodesy-25.4.25.dist-info/RECORD +118 -0
  94. pygeodesy-25.1.9.dist-info/RECORD +0 -118
  95. {pygeodesy-25.1.9.dist-info → pygeodesy-25.4.25.dist-info}/WHEEL +0 -0
  96. {pygeodesy-25.1.9.dist-info → pygeodesy-25.4.25.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py CHANGED
@@ -2,13 +2,13 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  u'''Class L{Fsum} for precision floating point summation similar to
5
- Python's C{math.fsum} enhanced with I{running} summation and as an
6
- option, accurate I{TwoProduct} multiplication.
5
+ Python's C{math.fsum}, but enhanced with I{precision running} summation
6
+ plus optionally, accurate I{TwoProduct} multiplication.
7
7
 
8
- Accurate multiplication is based on the C{math.fma} function for
9
- Python 3.13 and newer or one of two equivalent C{fma} implementations
10
- for Python 3.12 and older. To enable accurate multiplication, set
11
- env variable C{PYGEODESY_FSUM_F2PRODUCT} to C{"std"} or any non-empty
8
+ Accurate multiplication is based on the C{math.fma} function from
9
+ Python 3.13 and newer or an equivalent C{fma} implementation for
10
+ Python 3.12 and older. To enable accurate multiplication, set env
11
+ variable C{PYGEODESY_FSUM_F2PRODUCT} to C{"std"} or any non-empty
12
12
  string or invoke function C{pygeodesy.f2product(True)} or set. With
13
13
  C{"std"} the C{fma} implemention follows the C{math.fma} function,
14
14
  otherwise the C{PyGeodesy 24.09.09} release.
@@ -39,8 +39,8 @@ results may differ from Python's C{math.fsum} results.
39
39
  # make sure int/int division yields float quotient, see .basics
40
40
  from __future__ import division as _; del _ # PYCHOK semicolon
41
41
 
42
- from pygeodesy.basics import isbool, iscomplex, isint, isscalar, \
43
- _signOf, itemsorted, signOf, _xiterable
42
+ from pygeodesy.basics import _gcd, isbool, iscomplex, isint, isscalar, \
43
+ _signOf, itemsorted, signOf, _xiterable
44
44
  from pygeodesy.constants import INF, INT0, MANT_DIG, NEG0, NINF, _0_0, \
45
45
  _1_0, _N_1_0, _isfinite, _pos_self, \
46
46
  Float, Int
@@ -48,12 +48,12 @@ from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
48
48
  _ValueError, _xError, _xError2, _xkwds, \
49
49
  _xkwds_get, _xkwds_get1, _xkwds_not, \
50
50
  _xkwds_pop, _xsError
51
- from pygeodesy.internals import _enquote, _getPYGEODESY, _MODS, _passarg
52
- from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DOT_, _from_, \
51
+ from pygeodesy.internals import _enquote, _envPYGEODESY, _passarg, typename
52
+ from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DMAIN_, _DOT_, _from_, \
53
53
  _not_finite_, _SPACE_, _std_, _UNDER_
54
- # from pygeodesy.lazily import _ALL_LAZY # from .named
54
+ # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .named
55
55
  from pygeodesy.named import _name__, _name2__, _Named, _NamedTuple, \
56
- _NotImplemented, _ALL_LAZY
56
+ _NotImplemented, _ALL_LAZY, _MODS
57
57
  from pygeodesy.props import _allPropertiesOf_n, deprecated_method, \
58
58
  deprecated_property_RO, Property, \
59
59
  Property_RO, property_RO
@@ -64,30 +64,30 @@ from math import fabs, isinf, isnan, \
64
64
  ceil as _ceil, floor as _floor # PYCHOK used! .ltp
65
65
 
66
66
  __all__ = _ALL_LAZY.fsums
67
- __version__ = '24.12.02'
67
+ __version__ = '25.04.14'
68
68
 
69
69
  from pygeodesy.interns import (
70
70
  _PLUS_ as _add_op_, # in .auxilats.auxAngle
71
+ _DSLASH_ as _floordiv_op_,
71
72
  _EQUAL_ as _fset_op_,
72
73
  _RANGLE_ as _gt_op_,
73
74
  _LANGLE_ as _lt_op_,
74
75
  _PERCENT_ as _mod_op_,
75
76
  _STAR_ as _mul_op_,
76
77
  _NOTEQUAL_ as _ne_op_,
78
+ _DSTAR_ as _pow_op_,
77
79
  _DASH_ as _sub_op_, # in .auxilats.auxAngle
78
80
  _SLASH_ as _truediv_op_
79
81
  )
80
- _floordiv_op_ = _truediv_op_ * 2 # _DSLASH_
81
82
  _divmod_op_ = _floordiv_op_ + _mod_op_
82
- _F2PRODUCT = _getPYGEODESY('FSUM_F2PRODUCT')
83
+ _F2PRODUCT = _envPYGEODESY('FSUM_F2PRODUCT')
83
84
  _iadd_op_ = _add_op_ + _fset_op_ # in .auxilats.auxAngle, .fstats
84
85
  _integer_ = 'integer'
85
86
  _isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
86
87
  _NONFINITEr = _0_0 # NOT INT0!
87
- _NONFINITES = _getPYGEODESY('FSUM_NONFINITES')
88
+ _NONFINITES = _envPYGEODESY('FSUM_NONFINITES')
88
89
  _non_zero_ = 'non-zero'
89
- _pow_op_ = _mul_op_ * 2 # _DSTAR_
90
- _RESIDUAL_0_0 = _getPYGEODESY('FSUM_RESIDUAL', _0_0)
90
+ _RESIDUAL_0_0 = _envPYGEODESY('FSUM_RESIDUAL', _0_0)
91
91
  _significant_ = 'significant'
92
92
  _threshold_ = 'threshold'
93
93
 
@@ -96,7 +96,7 @@ def _2finite(x, _isfine=_isfinite): # in .fstats
96
96
  '''(INTERNAL) return C{float(x)} if finite.
97
97
  '''
98
98
  return (float(x) if _isfine(x) # and isscalar(x)
99
- else _nfError(x))
99
+ else _nfError(x))
100
100
 
101
101
 
102
102
  def _2float(index=None, _isfine=_isfinite, **name_x): # in .fmath, .fstats
@@ -132,27 +132,25 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
132
132
 
133
133
  if _F2PRODUCT and _F2PRODUCT != _std_:
134
134
  # backward to PyGeodesy 24.09.09, with _fmaX
135
+ from pygeodesy.basics import _integer_ratio2
135
136
 
136
137
  def _fma(*a_b_c): # PYCHOK no cover
137
138
  # mimick C{math.fma} from Python 3.13+,
138
139
  # the same accuracy, but ~14x slower
139
- (na, da), (nb, db), (nc, dc) = map(_2n_d, a_b_c)
140
- n = na * nb * dc
141
- n += da * db * nc
142
- d = da * db * dc
140
+ (n, d), (nb, db), (nc, dc) = map(_integer_ratio2, a_b_c)
141
+ # n, d = (n * nb * dc + d * db * nc), (d * db * dc)
142
+ d *= db
143
+ n *= nb * dc
144
+ n += nc * d
145
+ d *= dc
143
146
  try:
144
- n, d = _n_d2(n, d)
147
+ n, d = _n_d2(n, d)
145
148
  r = float(n / d)
146
149
  except OverflowError: # "integer division result too large ..."
147
150
  r = NINF if (_signOf(n, 0) * _signOf(d, 0)) < 0 else INF
148
151
  return r if _isfinite(r) else _fmaX(r, *a_b_c) # "overflow in fma"
149
-
150
- def _2n_d(x): # PYCHOK no cover
151
- try: # int.as_integer_ratio in 3.8+
152
- return x.as_integer_ratio()
153
- except (AttributeError, OverflowError, TypeError, ValueError):
154
- return (x if isint(x) else float(x)), 1
155
152
  else:
153
+ _integer_ratio2 = None # redef, in Fsum.is_math_fma
156
154
 
157
155
  def _fma(a, b, c): # PYCHOK redef
158
156
  # mimick C{math.fma} from Python 3.13+,
@@ -161,17 +159,15 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
161
159
  r = _fsum(_2products(a, b3s, c))
162
160
  return r if _isfinite(r) else _fmaX(r, a, b, c)
163
161
 
164
- _2n_d = None # redef
165
-
166
162
  def _fmaX(r, *a_b_c): # PYCHOK no cover
167
- # handle non-finite as Python 3.13+ C-function U{math_fma_impl<https://
168
- # GitHub.com/python/cpython/blob/main/Modules/mathmodule.c#L2305>}:
169
- # raise a ValueError for a NAN result from non-NAN C{a_b_c}s or an
170
- # OverflowError for a non-NAN non-finite from all finite C{a_b_c}s.
163
+ # handle non-finite fma result as Python 3.13+ C-function U{math_fma_impl
164
+ # <https://GitHub.com/python/cpython/blob/main/Modules/mathmodule.c#L2305>}:
165
+ # raise a ValueError for a NAN result from non-NAN C{a_b_c}s otherwise an
166
+ # OverflowError for a non-finite, non-NAN result from all finite C{a_b_c}s.
171
167
  if isnan(r):
172
168
  def _x(x):
173
169
  return not isnan(x)
174
- else: # non-NAN non-finite
170
+ else: # non-finite, non-NAN
175
171
  _x = _isfinite
176
172
  if all(map(_x, a_b_c)):
177
173
  raise _nfError(r, unstr(_fma, *a_b_c))
@@ -179,10 +175,8 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
179
175
 
180
176
  def _2products(x, y3s, *zs): # PYCHOK in _fma, ...
181
177
  # yield(x * y3 for y3 in y3s) + yield(z in zs)
182
- # TwoProduct U{Algorithm 3.3
183
- # <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
184
- # also in Python 3.13+ C{Modules/mathmodule.c} under
185
- # #ifndef UNRELIABLE_FMA ... #else ... #endif
178
+ # TwoProduct U{Algorithm 3.3<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}, also
179
+ # in Python 3.13+ C{Modules/mathmodule.c} under #ifndef UNRELIABLE_FMA ... #else ...
186
180
  _, a, b = _2split3(x)
187
181
  for y, c, d in y3s:
188
182
  y *= x
@@ -278,29 +272,20 @@ def _isOK(unused):
278
272
  def _isOK_or_finite(x, _isfine=_isfinite):
279
273
  '''(INTERNAL) Is C{x} finite or is I{non-finite} OK?
280
274
  '''
281
- # assert _isfine in (_isOK, _isfinite)
275
+ # assert _isin(_isfine, _isOK, _isfinite)
282
276
  return _isfine(x) # C{bool}
283
277
 
284
278
 
285
- try:
286
- from math import gcd as _gcd
287
-
288
- def _n_d2(n, d):
289
- '''(INTERNAL) Reduce C{n} and C{d} by C{gcd}.
290
- '''
291
- if n and d:
292
- try:
293
- c = _gcd(n, d)
294
- if c > 1:
295
- n, d = (n // c), (d // c)
296
- except TypeError: # non-int float
297
- pass
298
- return n, d
299
-
300
- except ImportError: # 3.4-
301
-
302
- def _n_d2(*n_d): # PYCHOK redef
303
- return n_d
279
+ def _n_d2(n, d):
280
+ '''(INTERNAL) Reduce C{n} and C{d} by C{gcd}.
281
+ '''
282
+ try:
283
+ c = _gcd(n, d)
284
+ if c > 1:
285
+ return (n // c), (d // c)
286
+ except TypeError: # non-int float
287
+ pass
288
+ return n, d
304
289
 
305
290
 
306
291
  def _nfError(x, *args):
@@ -418,7 +403,7 @@ def _s_r2(s, r):
418
403
  def _strcomplex(s, *args):
419
404
  '''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
420
405
  '''
421
- c = _strcomplex.__name__[4:]
406
+ c = typename(_strcomplex)[4:]
422
407
  n = _sub_op_(len(args), _arg_)
423
408
  t = unstr(pow, *args)
424
409
  return _SPACE_(c, s, _from_, n, t)
@@ -427,8 +412,8 @@ def _strcomplex(s, *args):
427
412
  def _stresidual(prefix, residual, R=0, **mod_ratio):
428
413
  '''(INTERNAL) Residual error txt C{str}.
429
414
  '''
430
- p = _stresidual.__name__[3:]
431
- t = Fmt.PARENSPACED(p, Fmt(residual))
415
+ p = typename(_stresidual)[3:]
416
+ t = Fmt.PARENSPACED(p, Fmt(residual))
432
417
  for n, v in itemsorted(mod_ratio):
433
418
  p = Fmt.PARENSPACED(n, Fmt(v))
434
419
  t = _COMMASPACE_(t, p)
@@ -548,7 +533,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
548
533
  '''Return C{abs(self)} as an L{Fsum}.
549
534
  '''
550
535
  s = self.signOf() # == self._cmp_0(0)
551
- return (-self) if s < 0 else self._copy_2(self.__abs__)
536
+ return (-self) if s < 0 else self._copyd(self.__abs__)
552
537
 
553
538
  def __add__(self, other):
554
539
  '''Return C{B{self} + B{other}} as an L{Fsum}.
@@ -559,7 +544,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
559
544
 
560
545
  @see: Methods L{Fsum.fadd_} and L{Fsum.fadd}.
561
546
  '''
562
- f = self._copy_2(self.__add__)
547
+ f = self._copyd(self.__add__)
563
548
  return f._fadd(other)
564
549
 
565
550
  def __bool__(self): # PYCHOK Python 3+
@@ -592,7 +577,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
592
577
 
593
578
  @raise TypeError: Incompatible B{C{other}} C{type}.
594
579
  '''
595
- s = self._cmp_0(other, self.cmp.__name__)
580
+ s = self._cmp_0(other, typename(self.cmp))
596
581
  return _signOf(s, 0)
597
582
 
598
583
  def __divmod__(self, other, **raiser_RESIDUAL):
@@ -610,7 +595,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
610
595
 
611
596
  @see: Method L{Fsum.fdiv}.
612
597
  '''
613
- f = self._copy_2(self.__divmod__)
598
+ f = self._copyd(self.__divmod__)
614
599
  return f._fdivmod2(other, _divmod_op_, **raiser_RESIDUAL)
615
600
 
616
601
  def __eq__(self, other):
@@ -644,7 +629,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
644
629
 
645
630
  @see: Methods L{Fsum.__ifloordiv__}.
646
631
  '''
647
- f = self._copy_2(self.__floordiv__)
632
+ f = self._copyd(self.__floordiv__)
648
633
  return f._floordiv(other, _floordiv_op_)
649
634
 
650
635
  def __ge__(self, other):
@@ -859,7 +844,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
859
844
 
860
845
  @see: Method L{Fsum.__imod__}.
861
846
  '''
862
- f = self._copy_2(self.__mod__)
847
+ f = self._copyd(self.__mod__)
863
848
  return f._fdivmod2(other, _mod_op_).mod
864
849
 
865
850
  def __mul__(self, other):
@@ -867,7 +852,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
867
852
 
868
853
  @see: Method L{Fsum.__imul__}.
869
854
  '''
870
- f = self._copy_2(self.__mul__)
855
+ f = self._copyd(self.__mul__)
871
856
  return f._fmul(other, _mul_op_)
872
857
 
873
858
  def __ne__(self, other):
@@ -878,20 +863,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
878
863
  def __neg__(self):
879
864
  '''Return C{copy(B{self})}, I{negated}.
880
865
  '''
881
- f = self._copy_2(self.__neg__)
866
+ f = self._copyd(self.__neg__)
882
867
  return f._fset(self._neg)
883
868
 
884
869
  def __pos__(self):
885
870
  '''Return this instance I{as-is}, like C{float.__pos__()}.
886
871
  '''
887
- return self if _pos_self else self._copy_2(self.__pos__)
872
+ return self if _pos_self else self._copyd(self.__pos__)
888
873
 
889
874
  def __pow__(self, other, *mod): # PYCHOK 2 vs 3 args
890
875
  '''Return C{B{self}**B{other}} as an L{Fsum}.
891
876
 
892
877
  @see: Method L{Fsum.__ipow__}.
893
878
  '''
894
- f = self._copy_2(self.__pow__)
879
+ f = self._copyd(self.__pow__)
895
880
  return f._fpow(other, _pow_op_, *mod)
896
881
 
897
882
  def __radd__(self, other):
@@ -899,7 +884,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
899
884
 
900
885
  @see: Method L{Fsum.__iadd__}.
901
886
  '''
902
- f = self._copy_2r(other, self.__radd__)
887
+ f = self._rcopyd(other, self.__radd__)
903
888
  return f._fadd(self)
904
889
 
905
890
  def __rdivmod__(self, other):
@@ -908,7 +893,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
908
893
 
909
894
  @see: Method L{Fsum.__divmod__}.
910
895
  '''
911
- f = self._copy_2r(other, self.__rdivmod__)
896
+ f = self._rcopyd(other, self.__rdivmod__)
912
897
  return f._fdivmod2(self, _divmod_op_)
913
898
 
914
899
  # turned off, called by _deepcopy and _copy
@@ -917,7 +902,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
917
902
  # <https://docs.Python.org/3/library/pickle.html#object.__reduce__>}
918
903
  # '''
919
904
  # dict_ = self._Fsum_as().__dict__ # no __setstate__
920
- # return (self.__class__, self.partials, dict_)
905
+ # return (type(self), self.partials, dict_)
921
906
 
922
907
  # def __repr__(self):
923
908
  # '''Return the default C{repr(this)}.
@@ -929,7 +914,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
929
914
 
930
915
  @see: Method L{Fsum.__ifloordiv__}.
931
916
  '''
932
- f = self._copy_2r(other, self.__rfloordiv__)
917
+ f = self._rcopyd(other, self.__rfloordiv__)
933
918
  return f._floordiv(self, _floordiv_op_)
934
919
 
935
920
  def __rmatmul__(self, other): # PYCHOK no coveS
@@ -941,7 +926,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
941
926
 
942
927
  @see: Method L{Fsum.__imod__}.
943
928
  '''
944
- f = self._copy_2r(other, self.__rmod__)
929
+ f = self._rcopyd(other, self.__rmod__)
945
930
  return f._fdivmod2(self, _mod_op_).mod
946
931
 
947
932
  def __rmul__(self, other):
@@ -949,7 +934,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
949
934
 
950
935
  @see: Method L{Fsum.__imul__}.
951
936
  '''
952
- f = self._copy_2r(other, self.__rmul__)
937
+ f = self._rcopyd(other, self.__rmul__)
953
938
  return f._fmul(self, _mul_op_)
954
939
 
955
940
  def __round__(self, *ndigits): # PYCHOK Python 3+
@@ -957,7 +942,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
957
942
 
958
943
  @arg ndigits: Optional number of digits (C{int}).
959
944
  '''
960
- f = self._copy_2(self.__round__)
945
+ f = self._copyd(self.__round__)
961
946
  # <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
962
947
  return f._fset(round(float(self), *ndigits)) # can be C{int}
963
948
 
@@ -966,7 +951,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
966
951
 
967
952
  @see: Method L{Fsum.__ipow__}.
968
953
  '''
969
- f = self._copy_2r(other, self.__rpow__)
954
+ f = self._rcopyd(other, self.__rpow__)
970
955
  return f._fpow(self, _pow_op_, *mod)
971
956
 
972
957
  def __rsub__(self, other):
@@ -974,7 +959,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
974
959
 
975
960
  @see: Method L{Fsum.__isub__}.
976
961
  '''
977
- f = self._copy_2r(other, self.__rsub__)
962
+ f = self._rcopyd(other, self.__rsub__)
978
963
  return f._fsub(self, _sub_op_)
979
964
 
980
965
  def __rtruediv__(self, other, **raiser_RESIDUAL):
@@ -982,7 +967,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
982
967
 
983
968
  @see: Method L{Fsum.__itruediv__}.
984
969
  '''
985
- f = self._copy_2r(other, self.__rtruediv__)
970
+ f = self._rcopyd(other, self.__rtruediv__)
986
971
  return f._ftruediv(self, _truediv_op_, **raiser_RESIDUAL)
987
972
 
988
973
  def __str__(self):
@@ -999,7 +984,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
999
984
 
1000
985
  @see: Method L{Fsum.__isub__}.
1001
986
  '''
1002
- f = self._copy_2(self.__sub__)
987
+ f = self._copyd(self.__sub__)
1003
988
  return f._fsub(other, _sub_op_)
1004
989
 
1005
990
  def __truediv__(self, other, **raiser_RESIDUAL):
@@ -1104,10 +1089,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1104
1089
  # assert f._RESIDUAL is self._RESIDUAL
1105
1090
  return f
1106
1091
 
1107
- def _copy_2(self, which, name=NN):
1092
+ def _copyd(self, which, name=NN):
1108
1093
  '''(INTERNAL) Copy for I{dyadic} operators.
1109
1094
  '''
1110
- n = name or which.__name__ # _DUNDER_nameof
1095
+ n = name or typename(which)
1111
1096
  # NOT .classof due to .Fdot(a, *b) args, etc.
1112
1097
  f = _Named.copy(self, deep=False, name=n)
1113
1098
  f._ps = list(self._ps) # separate list
@@ -1118,12 +1103,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1118
1103
  # assert f._RESIDUAL is self._RESIDUAL
1119
1104
  return f
1120
1105
 
1121
- def _copy_2r(self, other, which):
1122
- '''(INTERNAL) Copy for I{reverse-dyadic} operators.
1123
- '''
1124
- return other._copy_2(which) if _isFsum(other) else \
1125
- self._copy_2(which)._fset(other)
1126
-
1127
1106
  divmod = __divmod__
1128
1107
 
1129
1108
  def _Error(self, op, other, Error, **txt_cause):
@@ -1209,7 +1188,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1209
1188
 
1210
1189
  _Pow, p, s, r = _Pow4(power)
1211
1190
  if p: # and xs:
1212
- op = which.__name__
1191
+ op = typename(which)
1213
1192
  _FsT = _Fsum_2Tuple_types
1214
1193
  _pow = self._pow_2_3
1215
1194
 
@@ -1246,8 +1225,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1246
1225
  '''(INTERNAL) Accumulate all C{xs}, each C{scalar}, an L{Fsum} or
1247
1226
  L{Fsum2Tuple}, like function C{_xsum}.
1248
1227
  '''
1249
- _C = self.__class__
1250
- fs = _xs(xs, **_x_isfine(self.nonfinitesOK, _Cdot=_C,
1228
+ fs = _xs(xs, **_x_isfine(self.nonfinitesOK, _Cdot=type(self),
1251
1229
  **origin_which)) # PYCHOK yield
1252
1230
  return self._facc_scalar(fs, up=up)
1253
1231
 
@@ -1332,16 +1310,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1332
1310
 
1333
1311
  def _fhorner(self, x, cs, where, incx=True): # in .fmath
1334
1312
  '''(INTERNAL) Add an L{Fhorner} evaluation of polynomial
1335
- C{sum(cs[i] * B{x}**i for i=0..len(cs)-1) if B{incx}
1336
- else sum(... i=len(cs)-1..0)}.
1313
+ C{sum(c * B{x}**i for i, c in _e(cs))} where C{_e =
1314
+ enumerate if B{incx} else _enumereverse}.
1337
1315
  '''
1338
1316
  # assert _xiterablen(cs)
1339
1317
  try:
1340
- n = len(cs)
1341
- H = self._Fsum_as(name__=self._fhorner)
1342
- _m = H._mul_Fsum if _isFsum_2Tuple(x) else \
1343
- H._mul_scalar
1344
- if _2finite(x, **self._isfine) and n > 1:
1318
+ n = len(cs)
1319
+ if n > 1 and _2finite(x, **self._isfine):
1320
+ H = self._Fsum_as(name__=self._fhorner)
1321
+ _m = H._mul_Fsum if _isFsum_2Tuple(x) else \
1322
+ H._mul_scalar
1345
1323
  for c in (reversed(cs) if incx else cs):
1346
1324
  H._fset(_m(x, _mul_op_), up=False)
1347
1325
  H._fadd(c, up=False)
@@ -1463,7 +1441,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1463
1441
  override L{nonfinites<Fsum.nonfinites>} and
1464
1442
  L{nonfiniterrors} default (C{bool}).
1465
1443
  '''
1466
- op = self.fma.__name__
1444
+ op = typename(self.fma)
1467
1445
  _fs = self._ps_other
1468
1446
  try:
1469
1447
  s, r = self._fprs2
@@ -1528,7 +1506,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1528
1506
  def _f2mul(self, where, others, f2product=True, **nonfinites_raiser):
1529
1507
  '''(INTERNAL) See methods C{fma} and C{f2mul_}.
1530
1508
  '''
1531
- f = _Psum(self._ps, f2product=f2product, name=where.__name__)
1509
+ n = typename(where)
1510
+ f = _Psum(self._ps, f2product=f2product, name=n)
1532
1511
  if others and f:
1533
1512
  if f.f2product():
1534
1513
  def _pfs(f, ps):
@@ -1537,7 +1516,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1537
1516
  def _pfs(f, ps): # PYCHOK redef
1538
1517
  return (f * p for p in ps)
1539
1518
 
1540
- op, ps = where.__name__, f._ps
1519
+ op, ps = n, f._ps
1541
1520
  try: # as if self.f2product(True)
1542
1521
  for other in others: # to pinpoint errors
1543
1522
  for p in self._ps_other(op, other):
@@ -1776,7 +1755,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1776
1755
 
1777
1756
  @return: Copy of this updated instance (L{Fsum}).
1778
1757
  '''
1779
- return self._facc_args(xs)._copy_2(self.Fsum_, **name)
1758
+ return self._facc_args(xs)._copyd(self.Fsum_, **name)
1780
1759
 
1781
1760
  def Fsum2Tuple_(self, *xs, **name):
1782
1761
  '''Like method L{Fsum.fsum_} but returning a named L{Fsum2Tuple}.
@@ -1789,7 +1768,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1789
1768
 
1790
1769
  @property_RO
1791
1770
  def _Fsum(self): # like L{Fsum2Tuple._Fsum}, in .fstats
1792
- return self # NOT @Property_RO, see .copy and ._copy_2
1771
+ return self # NOT @Property_RO, see .copy and ._copyd
1793
1772
 
1794
1773
  def _Fsum_as(self, *xs, **name_f2product_nonfinites_RESIDUAL):
1795
1774
  '''(INTERNAL) Return an C{Fsum} with this C{Fsum}'s C{.f2product},
@@ -1804,8 +1783,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1804
1783
  kwds.update(name_f2product_nonfinites_RESIDUAL)
1805
1784
  f = Fsum(**kwds)
1806
1785
  # assert all(v == self.__dict__[n] for n, v in f.__dict__.items())
1807
- return f._fset(xs[0], op=_fset_op_) if len(xs) == 1 else (
1808
- f._facc(xs, up=False) if xs else f)
1786
+ return (f._facc(xs, up=False) if len(xs) > 1 else
1787
+ f._fset(xs[0], op=_fset_op_)) if xs else f
1809
1788
 
1810
1789
  def fsum2(self, xs=(), **name):
1811
1790
  '''Add an iterable's items, summate and return the
@@ -1864,7 +1843,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1864
1843
  '''Like method L{Fsum.Fsum_} iff I{all} C{B{xs}}, each I{known to be}
1865
1844
  C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
1866
1845
  '''
1867
- return self._facc_scalarf(xs, which=self.Fsumf_)._copy_2(self.Fsumf_) # origin=1?
1846
+ return self._facc_scalarf(xs, which=self.Fsumf_)._copyd(self.Fsumf_) # origin=1?
1868
1847
 
1869
1848
  def fsum2f_(self, *xs):
1870
1849
  '''Like method L{Fsum.fsum2_} iff I{all} C{B{xs}}, each I{known to be}
@@ -1960,7 +1939,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1960
1939
  an C{fma} implementation as C{math.fma} or C{None}, a previous
1961
1940
  C{PyGeodesy} implementation.
1962
1941
  '''
1963
- return (_2split3s is _passarg) or (False if _2n_d is None else None)
1942
+ return (_2split3s is _passarg) or (False if _integer_ratio2 is None else None)
1964
1943
 
1965
1944
  def is_math_fsum(self):
1966
1945
  '''Are the summation functions L{fsum}, L{fsum_}, L{fsumf_}, L{fsum1},
@@ -2148,7 +2127,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2148
2127
  @see: Methods L{Fsum.__ipow__}, L{Fsum.fint}, L{Fsum.is_integer}
2149
2128
  and L{Fsum.root}.
2150
2129
  '''
2151
- f = self._copy_2(self.pow)
2130
+ f = self._copyd(self.pow)
2152
2131
  return f._fpow(x, _pow_op_, *mod, **raiser_RESIDUAL) # f = pow(f, x, *mod)
2153
2132
 
2154
2133
  def _pow(self, other, unused, op, **raiser_RESIDUAL):
@@ -2370,6 +2349,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2370
2349
  return dict(ratio=q, R=t)
2371
2350
  return {}
2372
2351
 
2352
+ def _rcopyd(self, other, which):
2353
+ '''(INTERNAL) Copy for I{reverse-dyadic} operators.
2354
+ '''
2355
+ return other._copyd(which) if _isFsum(other) else \
2356
+ self._copyd(which)._fset(other)
2357
+
2373
2358
  rdiv = __rtruediv__
2374
2359
 
2375
2360
  @property_RO
@@ -2450,7 +2435,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2450
2435
  @see: Method L{Fsum.pow}.
2451
2436
  '''
2452
2437
  x = self._1_Over(root, _truediv_op_, **raiser_RESIDUAL)
2453
- f = self._copy_2(self.root)
2438
+ f = self._copyd(self.root)
2454
2439
  return f._fpow(x, f.name, **raiser_RESIDUAL) # == pow(f, x)
2455
2440
 
2456
2441
  def _scalar(self, other, op, **txt):
@@ -2502,7 +2487,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2502
2487
  def _truediv(self, other, op, **raiser_RESIDUAL):
2503
2488
  '''(INTERNAL) Return C{B{self} / B{other}} as an L{Fsum}.
2504
2489
  '''
2505
- f = self._copy_2(self.__truediv__)
2490
+ f = self._copyd(self.__truediv__)
2506
2491
  return f._ftruediv(other, op, **raiser_RESIDUAL)
2507
2492
 
2508
2493
  def _update(self, updated=True): # see ._fset
@@ -2549,8 +2534,8 @@ class Fsum2Tuple(_NamedTuple): # in .fstats
2549
2534
  @note: If the C{residual is INT0}, the C{fsum} is considered
2550
2535
  to be I{exact}, see method L{Fsum2Tuple.is_exact}.
2551
2536
  '''
2552
- _Names_ = ( Fsum.fsum.__name__, Fsum.residual.name)
2553
- _Units_ = (_Float_Int, _Float_Int)
2537
+ _Names_ = ( typename(Fsum.fsum), Fsum.residual.name)
2538
+ _Units_ = (_Float_Int, _Float_Int)
2554
2539
 
2555
2540
  def __abs__(self): # in .fmath
2556
2541
  return self._Fsum.__abs__()
@@ -2642,7 +2627,7 @@ class Fsum2Tuple(_NamedTuple): # in .fstats
2642
2627
 
2643
2628
  def _other_op(self, other, which):
2644
2629
  C, s = (tuple, self) if isinstance(other, tuple) else (Fsum, self._Fsum)
2645
- return getattr(C, which.__name__)(s, other)
2630
+ return getattr(C, typename(which))(s, other)
2646
2631
 
2647
2632
  @property_RO
2648
2633
  def _ps(self):
@@ -2823,9 +2808,9 @@ def _xsum(which, xs, nonfinites=None, primed=0, **floats): # origin=0
2823
2808
  # delete all decorators, etc.
2824
2809
  del _allPropertiesOf_n, deprecated_method, deprecated_property_RO, \
2825
2810
  Property, Property_RO, property_RO, _ALL_LAZY, _F2PRODUCT, \
2826
- MANT_DIG, _NONFINITES, _RESIDUAL_0_0, _getPYGEODESY, _std_
2811
+ MANT_DIG, _NONFINITES, _RESIDUAL_0_0, _envPYGEODESY, _std_
2827
2812
 
2828
- if __name__ == '__main__':
2813
+ if __name__ == _DMAIN_:
2829
2814
 
2830
2815
  # usage: python3 -m pygeodesy.fsums
2831
2816
 
@@ -2833,8 +2818,8 @@ if __name__ == '__main__':
2833
2818
  # copied from Hettinger, see L{Fsum} reference
2834
2819
  from pygeodesy import frandoms, printf
2835
2820
 
2836
- printf(_fsum.__name__, end=_COMMASPACE_)
2837
- printf(_psum.__name__, end=_COMMASPACE_)
2821
+ printf(typename(_fsum), end=_COMMASPACE_)
2822
+ printf(typename(_psum), end=_COMMASPACE_)
2838
2823
 
2839
2824
  F = Fsum()
2840
2825
  if F.is_math_fsum():
pygeodesy/gars.py CHANGED
@@ -14,14 +14,14 @@ Transcoded from I{Charles Karney}'s C++ class U{GARS
14
14
  (GARS)<https://Earth-Info.NGA.mil/GandG/coordsys/grids/gars.html>}.
15
15
  '''
16
16
 
17
- # from pygeodesy.basics import isstr # from .named
17
+ from pygeodesy.basics import isstr, _splituple, typename
18
18
  from pygeodesy.constants import _off90, _1_over, _0_5, \
19
19
  _1_0 # PYCHOK used!
20
20
  from pygeodesy.errors import _ValueError, _xkwds, _xStrError
21
- from pygeodesy.interns import NN, _0to9_, _AtoZnoIO_, _COMMA_, \
22
- _INV_, _SPACE_
21
+ # from pygeodesy.internals import typename # from .basics
22
+ from pygeodesy.interns import NN, _0to9_, _AtoZnoIO_, _INV_
23
23
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
24
- from pygeodesy.named import _name__, Fmt, isstr, Property_RO
24
+ from pygeodesy.named import _name__, Fmt, Property_RO
25
25
  from pygeodesy.namedTuples import LatLon2Tuple, LatLonPrec3Tuple
26
26
  # from pygeodesy.props import Property_RO # from .named
27
27
  # from pygeodesy.streprs import Fmt # from .named
@@ -30,7 +30,7 @@ from pygeodesy.units import Int_, Lat, Lon, Precision_, Scalar_, Str
30
30
  from math import floor
31
31
 
32
32
  __all__ = _ALL_LAZY.gars
33
- __version__ = '24.08.13'
33
+ __version__ = '25.04.14'
34
34
 
35
35
  _Digits = _0to9_
36
36
  _LatLen = 2
@@ -93,7 +93,7 @@ def _2garstr2(garef):
93
93
  return garstr, _2Precision(n - _MinLen)
94
94
 
95
95
  except (AttributeError, TypeError, ValueError) as x:
96
- raise GARSError(Garef.__name__, garef, cause=x)
96
+ raise GARSError(typename(Garef), garef, cause=x)
97
97
 
98
98
 
99
99
  def _2Precision(precision):
@@ -136,7 +136,7 @@ class Garef(Str):
136
136
  if isinstance(lat_gll, Garef):
137
137
  g, ll, p = str(lat_gll), lat_gll.latlon, lat_gll.precision
138
138
  elif isstr(lat_gll):
139
- ll = lat_gll.replace(_COMMA_, _SPACE_).split()
139
+ ll = _splituple(lat_gll)
140
140
  if len(ll) > 1:
141
141
  g, ll, p = _encode3(ll[0], ll[1], precision)
142
142
  else: