pygeodesy 25.8.25__py2.py3-none-any.whl → 25.10.10__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 (48) hide show
  1. pygeodesy/__init__.py +21 -20
  2. pygeodesy/auxilats/__init__.py +1 -1
  3. pygeodesy/auxilats/auxAngle.py +4 -3
  4. pygeodesy/auxilats/auxily.py +1 -1
  5. pygeodesy/azimuthal.py +10 -12
  6. pygeodesy/basics.py +4 -4
  7. pygeodesy/booleans.py +25 -25
  8. pygeodesy/constants.py +59 -33
  9. pygeodesy/deprecated/functions.py +1 -0
  10. pygeodesy/dms.py +2 -2
  11. pygeodesy/ecef.py +3 -3
  12. pygeodesy/ellipsoidalExact.py +4 -4
  13. pygeodesy/ellipsoidalGeodSolve.py +3 -3
  14. pygeodesy/ellipsoids.py +52 -41
  15. pygeodesy/elliptic.py +9 -12
  16. pygeodesy/errors.py +18 -5
  17. pygeodesy/etm.py +10 -10
  18. pygeodesy/fmath.py +5 -3
  19. pygeodesy/geodesicx/__init__.py +1 -1
  20. pygeodesy/geodesicx/__main__.py +1 -0
  21. pygeodesy/geodesicx/gx.py +40 -46
  22. pygeodesy/geodesicx/gxarea.py +4 -4
  23. pygeodesy/geodesicx/gxbases.py +1 -5
  24. pygeodesy/geodesicx/gxline.py +43 -34
  25. pygeodesy/geodsolve.py +10 -17
  26. pygeodesy/geohash.py +6 -6
  27. pygeodesy/geoids.py +2 -2
  28. pygeodesy/heights.py +2 -2
  29. pygeodesy/internals.py +42 -19
  30. pygeodesy/karney.py +27 -26
  31. pygeodesy/ktm.py +1 -1
  32. pygeodesy/lazily.py +12 -11
  33. pygeodesy/lcc.py +5 -5
  34. pygeodesy/named.py +11 -14
  35. pygeodesy/rhumb/__init__.py +1 -1
  36. pygeodesy/rhumb/aux_.py +1 -1
  37. pygeodesy/rhumb/bases.py +7 -8
  38. pygeodesy/rhumb/ekx.py +9 -9
  39. pygeodesy/solveBase.py +14 -3
  40. pygeodesy/sphericalTrigonometry.py +4 -4
  41. pygeodesy/streprs.py +9 -9
  42. pygeodesy/trf.py +4 -4
  43. pygeodesy/utily.py +200 -159
  44. pygeodesy/vector3dBase.py +6 -6
  45. {pygeodesy-25.8.25.dist-info → pygeodesy-25.10.10.dist-info}/METADATA +21 -20
  46. {pygeodesy-25.8.25.dist-info → pygeodesy-25.10.10.dist-info}/RECORD +48 -48
  47. {pygeodesy-25.8.25.dist-info → pygeodesy-25.10.10.dist-info}/WHEEL +0 -0
  48. {pygeodesy-25.8.25.dist-info → pygeodesy-25.10.10.dist-info}/top_level.txt +0 -0
pygeodesy/ellipsoids.py CHANGED
@@ -67,8 +67,8 @@ from __future__ import division as _; del _ # noqa: E702 ;
67
67
  # from pygeodesy.albers import AlbersEqualAreaCylindrical # _MODS
68
68
  from pygeodesy.basics import copysign0, isbool, _isin, isint, typename
69
69
  from pygeodesy.constants import EPS, EPS_2, EPS0, EPS02, EPS1, INF, NINF, \
70
- _over, PI_2, PI_3, PI4, R_M, R_MA, R_FM, \
71
- _EPSqrt, _EPStol as _TOL, _floatuple as _T, _isfinite, \
70
+ _over, PI_2, PI_3, PI4, R_M, R_MA, R_FM, _EPSqrt, \
71
+ _EPStol as _TOL, _floatuple as _T, _isfinite, \
72
72
  _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
73
73
  _0_25, _3_0 # PYCHOK used!
74
74
  from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
@@ -96,7 +96,7 @@ from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians
96
96
  from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan # as _tan
97
97
 
98
98
  __all__ = _ALL_LAZY.ellipsoids
99
- __version__ = '25.08.25'
99
+ __version__ = '25.08.31'
100
100
 
101
101
  _f_0_0 = Float(f =_0_0) # zero flattening
102
102
  _f__0_0 = Float(f_=_0_0) # zero inverse flattening
@@ -443,7 +443,7 @@ class Ellipsoid(_NamedEnumItem):
443
443
  eps=eps, f0=f0, **name_value))
444
444
 
445
445
  def auxAuthalic(self, lat, inverse=False):
446
- '''Compute the I{authalic} auxiliary latitude or the I{inverse} thereof.
446
+ '''Compute the I{authalic} auxiliary latitude (Xi) or the I{inverse} thereof.
447
447
 
448
448
  @arg lat: The geodetic (or I{authalic}) latitude (C{degrees90}).
449
449
  @kwarg inverse: If C{True}, B{C{lat}} is the I{authalic} and
@@ -463,7 +463,7 @@ class Ellipsoid(_NamedEnumItem):
463
463
  return _aux(lat, inverse, Ellipsoid.auxAuthalic)
464
464
 
465
465
  def auxConformal(self, lat, inverse=False):
466
- '''Compute the I{conformal} auxiliary latitude or the I{inverse} thereof.
466
+ '''Compute the I{conformal} auxiliary latitude (Chi) or the I{inverse} thereof.
467
467
 
468
468
  @arg lat: The geodetic (or I{conformal}) latitude (C{degrees90}).
469
469
  @kwarg inverse: If C{True}, B{C{lat}} is the I{conformal} and
@@ -481,12 +481,13 @@ class Ellipsoid(_NamedEnumItem):
481
481
  lat = atan1d(f(tan(Phid(lat)))) # PYCHOK attr
482
482
  return _aux(lat, inverse, Ellipsoid.auxConformal)
483
483
 
484
- def auxGeocentric(self, lat, inverse=False):
485
- '''Compute the I{geocentric} auxiliary latitude or the I{inverse} thereof.
484
+ def auxGeocentric(self, lat, inverse=False, height=_0_0):
485
+ '''Compute the I{geocentric} auxiliary latitude (Theta) or the I{inverse} thereof.
486
486
 
487
487
  @arg lat: The geodetic (or I{geocentric}) latitude (C{degrees90}).
488
488
  @kwarg inverse: If C{True}, B{C{lat}} is the geocentric and
489
489
  return the I{geocentric} latitude (C{bool}).
490
+ @kwarg height: Optional, ellipsoidal height (C{meter}).
490
491
 
491
492
  @return: The I{geocentric} (or geodetic) latitude in C{degrees90}.
492
493
 
@@ -495,13 +496,24 @@ class Ellipsoid(_NamedEnumItem):
495
496
  <https://WikiPedia.org/wiki/Latitude#Geocentric_latitude>}, and
496
497
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 17-18.
497
498
  '''
498
- if self.f:
499
- f = self.a2_b2 if inverse else self.b2_a2
500
- lat = atan1d(tan(Phid(lat)) * f)
499
+ if self.f: # and lat
500
+ t = tan(Phid(lat))
501
+ f = self.b2_a2
502
+ if height:
503
+ if inverse:
504
+ lat = atan1d(t * f) # geodetic n
505
+ d, f = f, _1_0
506
+ else:
507
+ d = _1_0
508
+ n = self.rocPrimeVertical(lat)
509
+ f = _over(n * f + height, n * d + height)
510
+ elif inverse:
511
+ f = self.a2_b2
512
+ lat = atan1d(t * f)
501
513
  return _aux(lat, inverse, Ellipsoid.auxGeocentric)
502
514
 
503
515
  def auxIsometric(self, lat, inverse=False):
504
- '''Compute the I{isometric} auxiliary latitude or the I{inverse} thereof.
516
+ '''Compute the I{isometric} auxiliary latitude (Psi) or the I{inverse} thereof.
505
517
 
506
518
  @arg lat: The geodetic (or I{isometric}) latitude (C{degrees}).
507
519
  @kwarg inverse: If C{True}, B{C{lat}} is the I{isometric} and
@@ -510,8 +522,8 @@ class Ellipsoid(_NamedEnumItem):
510
522
  @return: The I{isometric} (or geodetic) latitude in C{degrees}.
511
523
 
512
524
  @note: The I{isometric} latitude for geodetic C{+/-90} is far
513
- outside the C{[-90..+90]} range but the inverse
514
- thereof is the original geodetic latitude.
525
+ outside the C{[-90..+90]} range but the inverse thereof
526
+ is the original geodetic latitude.
515
527
 
516
528
  @see: U{Inverse-/IsometricLatitude<https://GeographicLib.SourceForge.io/
517
529
  C++/doc/classGeographicLib_1_1Ellipsoid.html>}, U{Isometric latitude
@@ -526,7 +538,7 @@ class Ellipsoid(_NamedEnumItem):
526
538
  return _aux(lat, inverse, Ellipsoid.auxIsometric, clip=0)
527
539
 
528
540
  def auxParametric(self, lat, inverse=False):
529
- '''Compute the I{parametric} auxiliary latitude or the I{inverse} thereof.
541
+ '''Compute the I{parametric} auxiliary latitude (Beta) or the I{inverse} thereof.
530
542
 
531
543
  @arg lat: The geodetic (or I{parametric}) latitude (C{degrees90}).
532
544
  @kwarg inverse: If C{True}, B{C{lat}} is the I{parametric} and
@@ -546,7 +558,7 @@ class Ellipsoid(_NamedEnumItem):
546
558
  auxReduced = auxParametric # synonymous
547
559
 
548
560
  def auxRectifying(self, lat, inverse=False):
549
- '''Compute the I{rectifying} auxiliary latitude or the I{inverse} thereof.
561
+ '''Compute the I{rectifying} auxiliary latitude (Mu) or the I{inverse} thereof.
550
562
 
551
563
  @arg lat: The geodetic (or I{rectifying}) latitude (C{degrees90}).
552
564
  @kwarg inverse: If C{True}, B{C{lat}} is the I{rectifying} and
@@ -692,23 +704,23 @@ class Ellipsoid(_NamedEnumItem):
692
704
  '''
693
705
  lat = Lat(lat)
694
706
  if lat:
695
- b = lat
707
+ B = lat # beta
696
708
  if fabs(lat) < _90_0:
697
709
  if self.f:
698
- b = self._beta(lat)
699
- z, r = sincos2d(b)
710
+ B = self._beta(lat)
711
+ z, r = sincos2d(B)
700
712
  r *= self.a
701
713
  z *= self.b
702
714
  else: # near-polar
703
715
  r, z = _0_0, copysign0(self.b, lat)
704
716
  else: # equator
705
717
  r = self.a
706
- z = lat = b = _0_0
707
- return Circle4Tuple(r, z, lat, b)
718
+ z = lat = B = _0_0
719
+ return Circle4Tuple(r, z, lat, B)
708
720
 
709
721
  def degrees2m(self, deg, lat=0):
710
- '''Convert an angle to the distance along the equator or
711
- along a parallel of (geodetic) latitude.
722
+ '''Convert an angle along the equator or along a parallel
723
+ of (geodetic) latitude to the distance.
712
724
 
713
725
  @arg deg: The angle (C{degrees}).
714
726
  @kwarg lat: Parallel latitude (C{degrees90}, C{str}).
@@ -878,10 +890,10 @@ class Ellipsoid(_NamedEnumItem):
878
890
 
879
891
  @raise ValueError: Invalid B{C{s}}.
880
892
  '''
881
- r = _1_0
882
- if self.e2:
893
+ r, e2 = _1_0, self.e2
894
+ if e2: # and s
883
895
  try:
884
- r -= self.e2 * Scalar(s=s)**2
896
+ r -= e2 * Scalar(s=s)**2
885
897
  if r < 0:
886
898
  raise ValueError(_negative_)
887
899
  except (TypeError, ValueError) as x:
@@ -1468,19 +1480,18 @@ class Ellipsoid(_NamedEnumItem):
1468
1480
  @see: U{Geocentric Radius
1469
1481
  <https://WikiPedia.org/wiki/Earth_radius#Geocentric_radius>}
1470
1482
  '''
1471
- r, a = self.a, Phid(lat)
1472
- if a and self.f:
1473
- if fabs(a) < PI_2:
1474
- s2, c2 = _s2_c2(a)
1475
- b2_a2_s2 = self.b2_a2 * s2
1483
+ r, p = self.a, Phid(lat)
1484
+ if p and self.f:
1485
+ if fabs(p) < PI_2:
1486
+ s2, c2 = _s2_c2(p)
1476
1487
  # R == sqrt((a2**2 * c2 + b2**2 * s2) / (a2 * c2 + b2 * s2))
1477
1488
  # == sqrt(a2**2 * (c2 + (b2 / a2)**2 * s2) / (a2 * (c2 + b2 / a2 * s2)))
1478
1489
  # == sqrt(a2 * (c2 + (b2 / a2)**2 * s2) / (c2 + (b2 / a2) * s2))
1479
1490
  # == a * sqrt((c2 + b2_a2 * b2_a2 * s2) / (c2 + b2_a2 * s2))
1480
- # == a * sqrt((c2 + b2_a2 * b2_a2_s2) / (c2 + b2_a2_s2))
1481
- r *= sqrt((c2 + b2_a2_s2 * self.b2_a2) / (c2 + b2_a2_s2))
1491
+ s2 *= self.b2_a2
1492
+ r *= sqrt((c2 + self.b2_a2 * s2) / (c2 + s2))
1482
1493
  else:
1483
- r = self.b
1494
+ r = self.b
1484
1495
  return Radius(Rgeocentric=r)
1485
1496
 
1486
1497
  @Property_RO
@@ -1653,18 +1664,18 @@ class Ellipsoid(_NamedEnumItem):
1653
1664
  and the meridional and prime vertical U{Radii of Curvature
1654
1665
  <https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
1655
1666
  '''
1656
- a = fabs(Phi(phi))
1667
+ p = fabs(Phi(phi))
1657
1668
  if self.f:
1658
- r = self.e2s2(sin(a))
1669
+ r = self.e2s2(sin(p))
1659
1670
  if r > EPS02:
1660
- n = self.a / sqrt(r)
1661
- m = n * self.e21 / r
1671
+ n = sqrt(self.a2 / r)
1672
+ m = n * self.e21 / r
1662
1673
  else:
1663
1674
  m = n = _0_0
1664
1675
  else:
1665
1676
  m = n = self.a
1666
- if scaled and a:
1667
- n *= cos(a) if a < PI_2 else _0_0
1677
+ if scaled and p:
1678
+ n *= cos(p) if p < PI_2 else _0_0
1668
1679
  return Curvature2Tuple(m, n)
1669
1680
 
1670
1681
  def rocAzimuth(self, lat, azimuth):
@@ -1795,8 +1806,8 @@ class Ellipsoid(_NamedEnumItem):
1795
1806
  U{Radii of Curvature<https://WikiPedia.org/wiki/
1796
1807
  Earth_radius#Radii_of_curvature>}.
1797
1808
  '''
1798
- r = self.roc2_(Phid(lat)) if lat else self.rocEquatorial2
1799
- return Radius(rocPrimeVertical=r.prime_vertical)
1809
+ r = self.roc1_(sin(Phid(lat))) if lat else self.a
1810
+ return Radius(rocPrimeVertical=r)
1800
1811
 
1801
1812
  rocTransverse = rocPrimeVertical # synonymous
1802
1813
 
pygeodesy/elliptic.py CHANGED
@@ -75,7 +75,7 @@ U{22<https://DLMF.NIST.gov/22>}.
75
75
  # make sure int/int division yields float quotient, see .basics
76
76
  from __future__ import division as _; del _ # noqa: E702 ;
77
77
 
78
- from pygeodesy.basics import copysign0, map2, neg, neg_, typename
78
+ from pygeodesy.basics import copysign0, map2, neg, neg_
79
79
  from pygeodesy.constants import EPS, INF, NAN, PI, PI_2, PI_4, \
80
80
  _EPStol as _TolJAC, _0_0, _0_25, \
81
81
  _0_5, _1_0, _2_0, _N_2_0, _3_0, \
@@ -85,7 +85,7 @@ from pygeodesy.constants import _EPSjam as _TolJAM # PYCHOK used!
85
85
  # from pygeodesy.errors import _ValueError # from .fsums
86
86
  from pygeodesy.fmath import favg, Fdot_, fma, hypot1, zqrt
87
87
  from pygeodesy.fsums import Fsum, _fsum, _ValueError
88
- # from pygeodesy.internals import typename # from .basics
88
+ from pygeodesy.internals import _Enum, typename
89
89
  from pygeodesy.interns import NN, _delta_, _DOT_, _f_, _invalid_, \
90
90
  _invokation_, _negative_, _SPACE_
91
91
  from pygeodesy.karney import _K_2_0, _norm180, _signBit, _sincos2
@@ -100,7 +100,7 @@ from math import asin, asinh, atan, ceil, cosh, fabs, floor, radians, \
100
100
  sin, sinh, sqrt, tan, tanh # tan as _tan
101
101
 
102
102
  __all__ = _ALL_LAZY.elliptic
103
- __version__ = '25.06.02'
103
+ __version__ = '25.10.10'
104
104
 
105
105
  _TolRD = zqrt(EPS * 0.002)
106
106
  _TolRF = zqrt(EPS * 0.030)
@@ -108,13 +108,10 @@ _TolRG0 = _TolJAC * 2.7
108
108
  _TRIPS = 28 # Max depth, 6-18 might be sufficient
109
109
 
110
110
 
111
- class _Cs(object):
112
- '''(INTERAL) Complete integrals cache.
111
+ class _Cs(_Enum):
112
+ '''(INTERAL) Complete Integrals cache.
113
113
  '''
114
- def __init__(self, **kwds):
115
- # for n,v in kwds.items():
116
- # setattr(self, n, v)
117
- self.__dict__ = kwds
114
+ pass
118
115
 
119
116
 
120
117
  class Elliptic(_Named):
@@ -773,8 +770,8 @@ class Elliptic(_Named):
773
770
  def _S(**kwds):
774
771
  return Scalar_(Error=EllipticError, **kwds)
775
772
 
776
- self._k2 = _S(k2 = k2, low=None, high=_1_0)
777
- self._kp2 = _S(kp2=_1p2(kp2, k2)) # low=_0_0
773
+ self._k2 = _S(k2 = k2, low=None, high=_1_0)
774
+ self._kp2 = _S(kp2=_1p2(kp2, k2)) # low=_0_0
778
775
 
779
776
  self._alpha2 = _S(alpha2 = alpha2, low=None, high=_1_0)
780
777
  self._alphap2 = _S(alphap2=_1p2(alphap2, alpha2)) # low=_0_0
@@ -935,7 +932,7 @@ class Elliptic(_Named):
935
932
  raise _ellipticError(Elliptic._RFRD, x, y, z, m, cause=X)
936
933
  return float(R)
937
934
 
938
- _allPropertiesOf_n(16, Elliptic) # # PYCHOK assert, see Elliptic.reset
935
+ _allPropertiesOf_n(16, Elliptic) # PYCHOK assert, see Elliptic.reset
939
936
 
940
937
 
941
938
  class EllipticError(_ValueError):
pygeodesy/errors.py CHANGED
@@ -16,9 +16,10 @@ C{PYGEODESY_EXCEPTION_CHAINING=std} or to any non-empty string.
16
16
  # from pygeodesy import errors # _MODS, _MODS.getattr
17
17
  from pygeodesy.internals import _envPYGEODESY, _plural, _tailof, typename
18
18
  from pygeodesy.interns import MISSING, NN, _a_, _an_, _and_, _clip_, _COLON_, _COLONSPACE_, \
19
- _COMMASPACE_, _datum_, _ELLIPSIS_, _ellipsoidal_, _incompatible_, \
20
- _invalid_, _keyword_, _LatLon_, _len_, _not_, _or_, _SPACE_, \
21
- _specified_, _UNDER_, _vs_, _with_
19
+ _COMMASPACE_, _datum_, _DOT_, _ELLIPSIS_, _ellipsoidal_, \
20
+ _EQUALSPACED_, _immutable_, _incompatible_, _invalid_, _keyword_, \
21
+ _LatLon_, _len_, _not_, _or_, _SPACE_, _specified_, _UNDER_, \
22
+ _vs_, _with_
22
23
  from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYTHON_X_DEV
23
24
  # from pygeodesy import streprs as _streprs # _MODS.into
24
25
  # from pygeodesy.unitsBase import Str # _MODS
@@ -27,11 +28,12 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYTHON_X_DEV
27
28
  from copy import copy as _copy
28
29
 
29
30
  __all__ = _ALL_LAZY.errors # _ALL_DOCS('_InvalidError', '_IsnotError') _under
30
- __version__ = '25.05.19'
31
+ __version__ = '25.09.04'
31
32
 
32
33
  _argument_ = 'argument'
33
34
  _basics = _MODS.into(basics=__name__)
34
35
  _box_ = 'box'
36
+ _del_ = 'del'
35
37
  _expected_ = 'expected'
36
38
  _limiterrors = True # in .formy
37
39
  _name_value_ = repr('name=value')
@@ -224,7 +226,8 @@ class IntersectionError(_ValueError): # in .ellipsoidalBaseDI, .formy, ...
224
226
  '''New L{IntersectionError}.
225
227
  '''
226
228
  if args:
227
- _ValueError.__init__(self, _SPACE_(*args), **kwds)
229
+ t = _COMMASPACE_(*map(repr, args))
230
+ _ValueError.__init__(self, t, **kwds)
228
231
  else:
229
232
  _ValueError.__init__(self, **kwds)
230
233
 
@@ -474,6 +477,16 @@ def exception_chaining(exc=None):
474
477
  getattr(exc, '__cause__', None) # _DCAUSE_
475
478
 
476
479
 
480
+ def _ImmutableError(inst, attr, value=_del_, Error=_TypeError): # PYCHOK self
481
+ '''(INTERNAL) Format an C{immutable _TypeError}.
482
+ '''
483
+ n = typename(inst)
484
+ n = _DOT_(_xattr(inst, name=n), attr)
485
+ t = _SPACE_(_del_, n) if value is _del_ else \
486
+ _EQUALSPACED_(n, repr(value))
487
+ return Error(_immutable_, txt=t)
488
+
489
+
477
490
  def _incompatible(this):
478
491
  '''(INTERNAL) Format an C{"incompatible with ..."} text.
479
492
  '''
pygeodesy/etm.py CHANGED
@@ -67,7 +67,7 @@ from pygeodesy.basics import _isin, map1, neg, neg_, _xinstanceof
67
67
  from pygeodesy.constants import EPS, EPS02, PI_2, PI_4, _K0_UTM, \
68
68
  _1_EPS, _0_0, _0_1, _0_5, _1_0, _2_0, \
69
69
  _3_0, _90_0, isnear0, isnear90
70
- from pygeodesy.constants import _4_0 # PYCHOK used!
70
+ from pygeodesy.constants import _0_75, _4_0 # PYCHOK used!
71
71
  from pygeodesy.datums import _ellipsoidal_datum, _WGS84, _EWGS84
72
72
  # from pygeodesy.ellipsoids import _EWGS84 # from .datums
73
73
  # from pygeodesy.elliptic import Elliptic # _MODS
@@ -75,8 +75,8 @@ from pygeodesy.datums import _ellipsoidal_datum, _WGS84, _EWGS84
75
75
  # from pygeodesy.fsums import Fsum # from .fmath
76
76
  from pygeodesy.fmath import cbrt, hypot, hypot1, hypot2, Fsum
77
77
  from pygeodesy.interns import _COMMASPACE_, _DMAIN_, _near_, _SPACE_, _spherical_
78
- from pygeodesy.karney import _K_2_4, _copyBit, _diff182, _fix90, _norm2, \
79
- _norm180, _tand, _unsigned2
78
+ from pygeodesy.karney import _K_2_4, _diff182, _fix90, _norm2, _norm180, \
79
+ _signBit, _tand, _unsigned2
80
80
  # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .named
81
81
  from pygeodesy.named import callername, _incompatible, _NamedBase, \
82
82
  _ALL_LAZY, _MODS
@@ -93,7 +93,7 @@ from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
93
93
  from math import asinh, degrees, radians, sinh, sqrt
94
94
 
95
95
  __all__ = _ALL_LAZY.etm
96
- __version__ = '25.05.12'
96
+ __version__ = '25.09.15'
97
97
 
98
98
  _OVERFLOW = _1_EPS**2 # ~2e+31
99
99
  _TAYTOL = pow(EPS, 0.6)
@@ -410,7 +410,7 @@ class ExactTransverseMercator(_NamedBase):
410
410
  def _Ev_3cKE_4(self):
411
411
  '''(INTERNAL) Get and cache C{_Ev.cKE * 3 / 4}.
412
412
  '''
413
- return self._Ev_cKE * 0.75 # _0_75
413
+ return self._Ev_cKE * _0_75
414
414
 
415
415
  @Property_RO
416
416
  def _Ev_5cKE_4(self):
@@ -790,7 +790,7 @@ class ExactTransverseMercator(_NamedBase):
790
790
  mu = mu / d2
791
791
  mv = mv / d2
792
792
  else:
793
- mu, mv = map1(_overflow, mu, mv)
793
+ mu, mv = map1(_copysignOVERFLOW, mu, mv)
794
794
  xi = self._Eu.fE(snu, cnu, dnu) - mu
795
795
  v -= self._Ev.fE(snv, cnv, dnv) - mv
796
796
  return xi, v, d2
@@ -910,12 +910,12 @@ class ExactTransverseMercator(_NamedBase):
910
910
  if d1 > EPS02: # _EPSmin
911
911
  t1 = snu * dnv / sqrt(d1)
912
912
  else: # like atan(overflow) = pi/2
913
- t1, d1 = _overflow(snu), 0
913
+ t1, d1 = _copysignOVERFLOW(snu), 0
914
914
  d2 = cnu2 * self._mu + cnv**2 * mv
915
915
  if d2 > EPS02: # _EPSmin
916
916
  t2 = sinh(e * asinh(e * snu / sqrt(d2)))
917
917
  else:
918
- t2, d2 = _overflow(snu), 0
918
+ t2, d2 = _copysignOVERFLOW(snu), 0
919
919
  # psi = asinh(t1) - asinh(t2)
920
920
  # taup = sinh(psi)
921
921
  taup = t1 * hypot1(t2) - t2 * hypot1(t1)
@@ -1026,10 +1026,10 @@ _allPropertiesOf_n(22, ExactTransverseMercator, Property_RO) # PYCHOK assert _R
1026
1026
  del _0_1, _allPropertiesOf_n, EPS, _1_EPS, _EWGS84
1027
1027
 
1028
1028
 
1029
- def _overflow(x):
1029
+ def _copysignOVERFLOW(x):
1030
1030
  '''(INTERNAL) Like C{copysign0(OVERFLOW, B{x})}.
1031
1031
  '''
1032
- return _copyBit(_OVERFLOW, x)
1032
+ return (-_OVERFLOW) if _signBit(x) else _OVERFLOW
1033
1033
 
1034
1034
 
1035
1035
  def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, **name):
pygeodesy/fmath.py CHANGED
@@ -10,8 +10,8 @@ from __future__ import division as _; del _ # noqa: E702 ;
10
10
  from pygeodesy.basics import _copysign, copysign0, isbool, isint, isodd, \
11
11
  isscalar, len2, map1, _xiterable, typename
12
12
  from pygeodesy.constants import EPS0, EPS02, EPS1, NAN, PI, PI_2, PI_4, \
13
- _0_0, _0_125, _1_6th, _0_25, _1_3rd, _0_5, _1_0, \
14
- _1_5, _copysign_0_0, isfinite, remainder
13
+ _0_0, _0_125, _0_25, _0_5, _1_0, _1_5, \
14
+ _copysign_0_0, isfinite, remainder
15
15
  from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
16
16
  _xError, _xkwds, _xkwds_pop2, _xsError
17
17
  from pygeodesy.fsums import _2float, Fsum, fsum, _isFsum_2Tuple, Fmt, unstr
@@ -25,10 +25,12 @@ from math import fabs, sqrt # pow
25
25
  import operator as _operator # in .datums, .trf, .utm
26
26
 
27
27
  __all__ = _ALL_LAZY.fmath
28
- __version__ = '25.06.03'
28
+ __version__ = '25.09.15'
29
29
 
30
30
  # sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
31
31
  _0_4142 = 0.41421356237309504880 # ~ 3_730_904_090_310_553 / 9_007_199_254_740_992
32
+ _1_3rd = _1_0 / 3
33
+ _1_6th = _1_0 / 6
32
34
  _2_3rd = _1_3rd * 2
33
35
  _h_lt_b_ = 'abs(h) < abs(b)'
34
36
 
@@ -23,7 +23,7 @@ from pygeodesy.karney import Caps, GeodesicError
23
23
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
24
24
 
25
25
  __all__ = _ALL_LAZY.geodesicx + _ALL_DOCS(Caps, GeodesicError)
26
- __version__ = '25.06.04'
26
+ __version__ = '25.09.02'
27
27
 
28
28
  # **) MIT License
29
29
  #
@@ -46,6 +46,7 @@ def _main(**C4order): # PYCHOK no cover
46
46
  from sys import argv # .internals._isPyChOK
47
47
  _main(C4order=int(argv[1])) if len(argv) == 2 and argv[1].isdigit() else _main()
48
48
 
49
+
49
50
  # % python3.13 -m pygeodesy.geodesicx
50
51
  # pygeodesy.geodesicx 25.06.01: C4order=30, C4n=5425, C4u=5107, C4u_n=94.1%, C4x=465, C4t=tuple, C4z=166008, geographiclib 2.0 (pygeodesy 25.5.28 Python 3.13.3 64bit arm64 macOS 15.5)
51
52