pygeodesy 25.11.5__py2.py3-none-any.whl → 25.12.31__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 (125) hide show
  1. pygeodesy/__init__.py +46 -25
  2. pygeodesy/__main__.py +1 -1
  3. pygeodesy/albers.py +1 -1
  4. pygeodesy/angles.py +960 -0
  5. pygeodesy/auxilats/_CX_4.py +1 -1
  6. pygeodesy/auxilats/_CX_6.py +1 -1
  7. pygeodesy/auxilats/_CX_8.py +1 -1
  8. pygeodesy/auxilats/_CX_Rs.py +1 -1
  9. pygeodesy/auxilats/__init__.py +2 -2
  10. pygeodesy/auxilats/__main__.py +1 -1
  11. pygeodesy/auxilats/auxAngle.py +7 -8
  12. pygeodesy/auxilats/auxDLat.py +1 -1
  13. pygeodesy/auxilats/auxDST.py +1 -1
  14. pygeodesy/auxilats/auxLat.py +1 -1
  15. pygeodesy/auxilats/auxily.py +1 -1
  16. pygeodesy/azimuthal.py +6 -5
  17. pygeodesy/basics.py +14 -10
  18. pygeodesy/booleans.py +1 -1
  19. pygeodesy/cartesianBase.py +7 -7
  20. pygeodesy/clipy.py +1 -1
  21. pygeodesy/constants.py +29 -24
  22. pygeodesy/css.py +1 -1
  23. pygeodesy/datums.py +1 -1
  24. pygeodesy/deprecated/__init__.py +1 -1
  25. pygeodesy/deprecated/bases.py +1 -1
  26. pygeodesy/deprecated/classes.py +14 -7
  27. pygeodesy/deprecated/consterns.py +1 -1
  28. pygeodesy/deprecated/datum.py +1 -1
  29. pygeodesy/deprecated/functions.py +1 -1
  30. pygeodesy/deprecated/nvector.py +1 -1
  31. pygeodesy/deprecated/rhumbBase.py +1 -1
  32. pygeodesy/deprecated/rhumbaux.py +1 -1
  33. pygeodesy/deprecated/rhumbsolve.py +1 -1
  34. pygeodesy/deprecated/rhumbx.py +1 -1
  35. pygeodesy/dms.py +1 -1
  36. pygeodesy/ecef.py +1 -1
  37. pygeodesy/ecefLocals.py +1 -1
  38. pygeodesy/elevations.py +1 -1
  39. pygeodesy/ellipsoidalBase.py +1 -1
  40. pygeodesy/ellipsoidalBaseDI.py +1 -1
  41. pygeodesy/ellipsoidalExact.py +1 -1
  42. pygeodesy/ellipsoidalGeodSolve.py +1 -1
  43. pygeodesy/ellipsoidalKarney.py +1 -1
  44. pygeodesy/ellipsoidalNvector.py +1 -1
  45. pygeodesy/ellipsoidalVincenty.py +1 -1
  46. pygeodesy/ellipsoids.py +30 -17
  47. pygeodesy/elliptic.py +1 -1
  48. pygeodesy/epsg.py +1 -1
  49. pygeodesy/errors.py +8 -4
  50. pygeodesy/etm.py +1 -1
  51. pygeodesy/fmath.py +19 -14
  52. pygeodesy/formy.py +251 -10
  53. pygeodesy/frechet.py +1 -1
  54. pygeodesy/fstats.py +1 -1
  55. pygeodesy/fsums.py +41 -29
  56. pygeodesy/gars.py +1 -1
  57. pygeodesy/geod3solve.py +489 -0
  58. pygeodesy/geodesici.py +9 -8
  59. pygeodesy/geodesicw.py +1 -1
  60. pygeodesy/geodesicx/_C4_24.py +1 -1
  61. pygeodesy/geodesicx/_C4_27.py +1 -1
  62. pygeodesy/geodesicx/_C4_30.py +1 -1
  63. pygeodesy/geodesicx/__init__.py +2 -2
  64. pygeodesy/geodesicx/__main__.py +1 -1
  65. pygeodesy/geodesicx/gx.py +1 -1
  66. pygeodesy/geodesicx/gxarea.py +54 -24
  67. pygeodesy/geodesicx/gxbases.py +1 -1
  68. pygeodesy/geodesicx/gxline.py +1 -1
  69. pygeodesy/geodsolve.py +73 -104
  70. pygeodesy/geohash.py +1 -1
  71. pygeodesy/geoids.py +1 -1
  72. pygeodesy/hausdorff.py +1 -1
  73. pygeodesy/heights.py +1 -1
  74. pygeodesy/internals.py +1 -1
  75. pygeodesy/interns.py +3 -3
  76. pygeodesy/iters.py +1 -1
  77. pygeodesy/karney.py +152 -151
  78. pygeodesy/ktm.py +1 -1
  79. pygeodesy/latlonBase.py +1 -1
  80. pygeodesy/lazily.py +24 -13
  81. pygeodesy/lcc.py +1 -1
  82. pygeodesy/ltp.py +1 -1
  83. pygeodesy/ltpTuples.py +1 -1
  84. pygeodesy/mgrs.py +3 -3
  85. pygeodesy/named.py +15 -10
  86. pygeodesy/namedTuples.py +1 -1
  87. pygeodesy/nvectorBase.py +1 -1
  88. pygeodesy/osgr.py +1 -1
  89. pygeodesy/points.py +1 -1
  90. pygeodesy/props.py +6 -4
  91. pygeodesy/resections.py +1 -1
  92. pygeodesy/rhumb/__init__.py +8 -6
  93. pygeodesy/rhumb/aux_.py +1 -1
  94. pygeodesy/rhumb/bases.py +1 -1
  95. pygeodesy/rhumb/ekx.py +1 -1
  96. pygeodesy/rhumb/solve.py +91 -84
  97. pygeodesy/simplify.py +1 -1
  98. pygeodesy/solveBase.py +72 -49
  99. pygeodesy/sphericalBase.py +1 -1
  100. pygeodesy/sphericalNvector.py +1 -1
  101. pygeodesy/sphericalTrigonometry.py +1 -1
  102. pygeodesy/streprs.py +6 -4
  103. pygeodesy/trf.py +2 -4
  104. pygeodesy/triaxials/__init__.py +70 -0
  105. pygeodesy/triaxials/bases.py +966 -0
  106. pygeodesy/triaxials/conformal3.py +617 -0
  107. pygeodesy/triaxials/triaxial3.py +968 -0
  108. pygeodesy/{triaxials.py → triaxials/triaxial5.py} +353 -781
  109. pygeodesy/units.py +1 -1
  110. pygeodesy/unitsBase.py +1 -1
  111. pygeodesy/ups.py +2 -3
  112. pygeodesy/utily.py +17 -14
  113. pygeodesy/utm.py +1 -1
  114. pygeodesy/utmups.py +1 -1
  115. pygeodesy/utmupsBase.py +1 -1
  116. pygeodesy/vector2d.py +1 -1
  117. pygeodesy/vector3d.py +1 -1
  118. pygeodesy/vector3dBase.py +1 -1
  119. pygeodesy/webmercator.py +1 -1
  120. pygeodesy/wgrs.py +1 -1
  121. {pygeodesy-25.11.5.dist-info → pygeodesy-25.12.31.dist-info}/METADATA +28 -21
  122. pygeodesy-25.12.31.dist-info/RECORD +125 -0
  123. pygeodesy-25.11.5.dist-info/RECORD +0 -119
  124. {pygeodesy-25.11.5.dist-info → pygeodesy-25.12.31.dist-info}/WHEEL +0 -0
  125. {pygeodesy-25.11.5.dist-info → pygeodesy-25.12.31.dist-info}/top_level.txt +0 -0
@@ -1153,7 +1153,7 @@ __all__ += _ALL_DOCS(CartesianEllipsoidalBase, LatLonEllipsoidalBase)
1153
1153
 
1154
1154
  # **) MIT License
1155
1155
  #
1156
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1156
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
1157
1157
  #
1158
1158
  # Permission is hereby granted, free of charge, to any person obtaining a
1159
1159
  # copy of this software and associated documentation files (the "Software"),
@@ -888,7 +888,7 @@ del _1_0, _0_01
888
888
 
889
889
  # **) MIT License
890
890
  #
891
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
891
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
892
892
  #
893
893
  # Permission is hereby granted, free of charge, to any person obtaining a
894
894
  # copy of this software and associated documentation files (the "Software"),
@@ -315,7 +315,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
315
315
 
316
316
  # **) MIT License
317
317
  #
318
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
318
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
319
319
  #
320
320
  # Permission is hereby granted, free of charge, to any person obtaining a
321
321
  # copy of this software and associated documentation files (the "Software"),
@@ -314,7 +314,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
314
314
 
315
315
  # **) MIT License
316
316
  #
317
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
317
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
318
318
  #
319
319
  # Permission is hereby granted, free of charge, to any person obtaining a
320
320
  # copy of this software and associated documentation files (the "Software"),
@@ -354,7 +354,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
354
354
 
355
355
  # **) MIT License
356
356
  #
357
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
357
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
358
358
  #
359
359
  # Permission is hereby granted, free of charge, to any person obtaining a
360
360
  # copy of this software and associated documentation files (the "Software"),
@@ -660,7 +660,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, Ned, Nvector, # classes
660
660
 
661
661
  # **) MIT License
662
662
  #
663
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
663
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
664
664
  #
665
665
  # Permission is hereby granted, free of charge, to any person obtaining a
666
666
  # copy of this software and associated documentation files (the "Software"),
@@ -573,7 +573,7 @@ __all__ += _ALL_DOCS(Cartesian, LatLon, intersecant2, # from .ellipsoidalBaseDI
573
573
 
574
574
  # **) MIT License
575
575
  #
576
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
576
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
577
577
  #
578
578
  # Permission is hereby granted, free of charge, to any person obtaining a
579
579
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/ellipsoids.py CHANGED
@@ -67,10 +67,10 @@ 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, _EPSqrt, \
70
+ _EPSqrt, PI_2, PI_3, PI2, PI4, R_M, R_MA, R_FM, \
71
71
  _EPStol as _TOL, _floatuple as _T, _isfinite, \
72
- _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
73
- _0_25, _3_0 # PYCHOK used!
72
+ _over, _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, \
73
+ _4_0, _90_0, _0_25, _3_0 # PYCHOK used!
74
74
  from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
75
75
  from pygeodesy.fmath import cbrt, cbrt2, fdot, Fhorner, fpowers, hypot, hypot_, \
76
76
  hypot1, hypot2, sqrt3, Fsum
@@ -88,7 +88,7 @@ from pygeodesy.namedTuples import Distance2Tuple, Vector3Tuple, Vector4Tuple
88
88
  from pygeodesy.props import deprecated_Property_RO, Property_RO, property_doc_, \
89
89
  deprecated_property_RO, property_RO, property_ROver
90
90
  from pygeodesy.streprs import Fmt, fstr, instr, strs, unstr
91
- # from pygeodesy.triaxials import _hartzell3 # _MODS
91
+ # from pygeodesy.triaxials.triaxial5 import _hartzell3, _plumbTo3 # _MODS
92
92
  from pygeodesy.units import Azimuth, Bearing, Distance, Float, Float_, Height, Lamd, Lat, \
93
93
  Meter, Meter2, Meter3, Phi, Phid, Radius, Radius_, Scalar
94
94
  from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians2m, sincos2d
@@ -96,11 +96,12 @@ 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.31'
99
+ __version__ = '25.12.14'
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
103
103
  # see U{WGS84_f<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Constants.html>}
104
+ # _f_WGS84 = Float(f =_1_0 / (298257223563 / 1000000000)) # 0.003_352_810_664_747_480_5
104
105
  _f__WGS84 = Float(f_=_1_0 / (1000000000 / 298257223563)) # 298.257223562_999_97 vs 298.257223563
105
106
 
106
107
 
@@ -110,19 +111,19 @@ def _aux(lat, inverse, auxLat, clip=90):
110
111
  return Lat(lat, clip=clip, name=_lat_ if inverse else typename(auxLat))
111
112
 
112
113
 
113
- def _s2_c2(phi):
114
+ def _sin2cos2(rad):
114
115
  '''(INTERNAL) Return 2-tuple C{(sin(B{phi})**2, cos(B{phi})**2)}.
115
116
  '''
116
- if phi:
117
- s2 = sin(phi)**2
117
+ if rad:
118
+ s2 = sin(rad)**2
118
119
  if s2 > EPS:
119
120
  c2 = _1_0 - s2
120
121
  if c2 > EPS:
121
122
  if c2 < EPS1:
122
123
  return s2, c2
123
124
  else:
124
- return _1_0, _0_0 # phi == PI_2
125
- return _0_0, _1_0 # phi == 0
125
+ return _1_0, _0_0 # rad == PI_2
126
+ return _0_0, _1_0 # rad == 0
126
127
 
127
128
 
128
129
  class a_f2Tuple(_NamedTuple):
@@ -870,6 +871,12 @@ class Ellipsoid(_NamedEnumItem):
870
871
 
871
872
  equatoradius = a # Requatorial
872
873
 
874
+ @Property_RO
875
+ def equatorimeter(self):
876
+ '''Get the ellipsoid's I{equatorial} perimeter (C{meter}).
877
+ '''
878
+ return Meter(equatorimeter=self.a * PI2)
879
+
873
880
  def e2s(self, s):
874
881
  '''Compute norm M{sqrt(1 - e2 * s**2)}.
875
882
 
@@ -1133,7 +1140,7 @@ class Ellipsoid(_NamedEnumItem):
1133
1140
  methods L{Ellipsoid.height4} and L{Triaxial.hartzell4}.
1134
1141
  '''
1135
1142
  try:
1136
- v, d, i = _MODS.triaxials._hartzell3(pov, los, self._triaxial)
1143
+ v, d, i = _MODS.triaxials.triaxial5._hartzell3(pov, los, self._triaxial)
1137
1144
  except Exception as x:
1138
1145
  raise IntersectionError(pov=pov, los=los, cause=x)
1139
1146
  return Vector4Tuple(v.x, v.y, v.z, d, iteration=i, name__=self.hartzell4)
@@ -1187,7 +1194,7 @@ class Ellipsoid(_NamedEnumItem):
1187
1194
  v = v.times_(t, t, 0) # force z=0.0
1188
1195
  h = x - a # equatorial
1189
1196
  else: # normal in 1st quadrant
1190
- x, y, i = _MODS.triaxials._plumbTo3(x, y, self)
1197
+ x, y, i = _MODS.triaxials.triaxial5._plumbTo3(x, y, self)
1191
1198
  t, v = v, v.times_(x, x, y)
1192
1199
  h = t.minus(v).length
1193
1200
 
@@ -1380,6 +1387,12 @@ class Ellipsoid(_NamedEnumItem):
1380
1387
 
1381
1388
  polaradius = b # Rpolar
1382
1389
 
1390
+ @property_RO
1391
+ def polarimeter(self):
1392
+ '''Get the ellipsoid's I{polar}, meridional perimeter (C{meter}).
1393
+ '''
1394
+ return Meter(polarimeter=self.L * _4_0)
1395
+
1383
1396
  # Q = A # I{meridian arc unit} C{Q}, the mean, meridional length I{per radian}
1384
1397
 
1385
1398
  @deprecated_Property_RO
@@ -1483,7 +1496,7 @@ class Ellipsoid(_NamedEnumItem):
1483
1496
  r, p = self.a, Phid(lat)
1484
1497
  if p and self.f:
1485
1498
  if fabs(p) < PI_2:
1486
- s2, c2 = _s2_c2(p)
1499
+ s2, c2 = _sin2cos2(p)
1487
1500
  # R == sqrt((a2**2 * c2 + b2**2 * s2) / (a2 * c2 + b2 * s2))
1488
1501
  # == sqrt(a2**2 * (c2 + (b2 / a2)**2 * s2) / (a2 * (c2 + b2 / a2 * s2)))
1489
1502
  # == sqrt(a2 * (c2 + (b2 / a2)**2 * s2) / (c2 + (b2 / a2) * s2))
@@ -1708,7 +1721,7 @@ class Ellipsoid(_NamedEnumItem):
1708
1721
  '''(INTERNAL) Helper for C{rocAzimuth} and C{rocBearing}.
1709
1722
  '''
1710
1723
  if self.f:
1711
- s2, c2 = _s2_c2(radians(deg))
1724
+ s2, c2 = _sin2cos2(radians(deg))
1712
1725
  m, n = self.roc2_(Phid(lat))
1713
1726
  if n < m: # == n / (c2 * n / m + s2)
1714
1727
  c2 *= n / m
@@ -1750,7 +1763,7 @@ class Ellipsoid(_NamedEnumItem):
1750
1763
  # ... requires 1 or 2 sqrt
1751
1764
  g = self.b
1752
1765
  if self.f:
1753
- s2, c2 = _s2_c2(Phid(lat))
1766
+ s2, c2 = _sin2cos2(Phid(lat))
1754
1767
  g = _over(g, c2 + self.b2_a2 * s2)
1755
1768
  return Radius(rocGauss=g)
1756
1769
 
@@ -2411,7 +2424,7 @@ Ellipsoids._assert( # <https://WikiPedia.org/wiki/Earth_ellipsoid>
2411
2424
  WGS60 = _lazy('WGS60', *_T(6378165.0, 6356783.28695944, 298.3)),
2412
2425
  WGS66 = _lazy('WGS66', *_T(6378145.0, 6356759.76948868, 298.25)),
2413
2426
  WGS72 = _lazy(_WGS72_, *_T(6378135.0, _0_0, 298.26)), # b=6356750.52
2414
- WGS84 = _lazy(_WGS84_, *_T(R_MA, _0_0, _f__WGS84)), # GPS b=6356752.3142451793
2427
+ WGS84 = _lazy(_WGS84_, *_T(R_MA, _0_0, _f__WGS84)), # b=6356752.3142451793
2415
2428
  # U{NOAA/NOS/NGS/inverse<https://GitHub.com/noaa-ngs/inverse/blob/main/invers3d.f>}
2416
2429
  WGS84_NGS = _lazy('WGS84_NGS', *_T(R_MA, _0_0, 298.257222100882711243162836600094))
2417
2430
  )
@@ -2475,7 +2488,7 @@ if __name__ == _DMAIN_:
2475
2488
 
2476
2489
  # **) MIT License
2477
2490
  #
2478
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
2491
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
2479
2492
  #
2480
2493
  # Permission is hereby granted, free of charge, to any person obtaining a
2481
2494
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/elliptic.py CHANGED
@@ -1269,7 +1269,7 @@ class _RJfma(object):
1269
1269
 
1270
1270
  # **) MIT License
1271
1271
  #
1272
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1272
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
1273
1273
  #
1274
1274
  # Permission is hereby granted, free of charge, to any person obtaining a
1275
1275
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/epsg.py CHANGED
@@ -223,7 +223,7 @@ __all__ += _ALL_DOCS(decode2, encode)
223
223
 
224
224
  # **) MIT License
225
225
  #
226
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
226
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
227
227
  #
228
228
  # Permission is hereby granted, free of charge, to any person obtaining a
229
229
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/errors.py CHANGED
@@ -28,7 +28,7 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYTHON_X_DEV
28
28
  from copy import copy as _copy
29
29
 
30
30
  __all__ = _ALL_LAZY.errors # _ALL_DOCS('_InvalidError', '_IsnotError') _under
31
- __version__ = '25.10.30'
31
+ __version__ = '25.12.02'
32
32
 
33
33
  _argument_ = 'argument'
34
34
  _basics = _MODS.into(basics=__name__)
@@ -214,7 +214,8 @@ class CrossError(_ValueError):
214
214
 
215
215
  class GeodesicError(_ValueError):
216
216
  '''Error raised for convergence or other issues in L{geodesicx<pygeodesy.geodesicx>},
217
- L{geodesicw<pygeodesy.geodesicw>} or L{karney<pygeodesy.karney>}.
217
+ L{geodesicw<pygeodesy.geodesicw>}, L{geodsolve<pygeodesy.geodsolve>} or
218
+ L{karney<pygeodesy.karney>}.
218
219
  '''
219
220
  pass
220
221
 
@@ -626,7 +627,10 @@ def _xattr(obj, **name_default):
626
627
  '''
627
628
  if len(name_default) == 1:
628
629
  for n, d in name_default.items():
629
- return getattr(obj, n, d)
630
+ try: # obj is tuple
631
+ return getattr(obj, n, d)
632
+ except ValueError:
633
+ return d
630
634
  raise _xAssertionError(_xattr, obj, **name_default)
631
635
 
632
636
 
@@ -928,7 +932,7 @@ def _xStrError(*Refs, **name_value_Error): # in .gars, .geohash, .wgrs
928
932
 
929
933
  # **) MIT License
930
934
  #
931
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
935
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
932
936
  #
933
937
  # Permission is hereby granted, free of charge, to any person obtaining a
934
938
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/etm.py CHANGED
@@ -1197,7 +1197,7 @@ if __name__ == _DMAIN_: # MCCABE 16
1197
1197
 
1198
1198
  # **) MIT License
1199
1199
  #
1200
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1200
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
1201
1201
  #
1202
1202
  # Permission is hereby granted, free of charge, to any person obtaining a
1203
1203
  # copy of this software and associated documentation files (the "Software"),
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, _0_25, _0_5, _1_0, _1_5, \
14
- _copysign_0_0, isfinite, remainder
13
+ _0_0, _0_125, _0_25, _1_3rd, _0_5, _2_3rd, \
14
+ _1_0, _1_5, _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,13 +25,11 @@ 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.09.15'
28
+ __version__ = '25.12.23'
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
34
- _2_3rd = _1_3rd * 2
32
+ _1_6th = 1 / 6
35
33
  _h_lt_b_ = 'abs(h) < abs(b)'
36
34
 
37
35
 
@@ -260,7 +258,6 @@ def bqrt(x):
260
258
 
261
259
  try:
262
260
  from math import cbrt as _cbrt # Python 3.11+
263
-
264
261
  except ImportError: # Python 3.10-
265
262
 
266
263
  def _cbrt(x):
@@ -314,8 +311,9 @@ def euclid(x, y):
314
311
  @see: Function L{euclid_}.
315
312
  '''
316
313
  x, y = abs(x), abs(y) # NOT fabs!
317
- return (x + y * _0_4142) if x > y else \
318
- (y + x * _0_4142) # * _0_5 before 20.10.02
314
+ if x < y:
315
+ x, y = y, x
316
+ return x + y * _0_4142 # * _0_5 before 20.10.02
319
317
 
320
318
 
321
319
  def euclid_(*xs):
@@ -332,10 +330,17 @@ def euclid_(*xs):
332
330
  e = _0_0
333
331
  for x in sorted(map(abs, xs)): # NOT fabs, reverse=True!
334
332
  # e = euclid(x, e)
335
- if e < x:
336
- e, x = x, e
337
333
  if x:
338
- e += x * _0_4142
334
+ if e < x:
335
+ e, x = x, e
336
+ x *= _0_4142
337
+ # s = e + x
338
+ # if e < x: # like .fsums._2sum
339
+ # x -= s # e = (x - s) + e
340
+ # else:
341
+ # e -= s # e = (e - s) + x
342
+ e += x
343
+ # e += s
339
344
  return e
340
345
 
341
346
 
@@ -1042,7 +1047,7 @@ def sqrt3(x):
1042
1047
 
1043
1048
 
1044
1049
  def sqrt_a(h, b):
1045
- '''Compute C{I{a}} side of a right-angled triangle from
1050
+ '''Compute the C{I{a}} side of a right-angled triangle from
1046
1051
  C{sqrt(B{h}**2 - B{b}**2)}.
1047
1052
 
1048
1053
  @arg h: Hypotenuse or outer annulus radius (C{scalar}).
@@ -1115,7 +1120,7 @@ def zqrt(x):
1115
1120
 
1116
1121
  # **) MIT License
1117
1122
  #
1118
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1123
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
1119
1124
  #
1120
1125
  # Permission is hereby granted, free of charge, to any person obtaining a
1121
1126
  # copy of this software and associated documentation files (the "Software"),