pygeodesy 25.12.12__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.
- pygeodesy/__init__.py +27 -19
- pygeodesy/constants.py +2 -0
- pygeodesy/ellipsoids.py +24 -12
- pygeodesy/fmath.py +5 -7
- pygeodesy/formy.py +243 -104
- pygeodesy/fsums.py +40 -28
- pygeodesy/geod3solve.py +10 -9
- pygeodesy/geodesici.py +5 -4
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/gxarea.py +53 -23
- pygeodesy/geodsolve.py +4 -3
- pygeodesy/karney.py +21 -36
- pygeodesy/lazily.py +2 -2
- pygeodesy/named.py +2 -2
- pygeodesy/props.py +5 -3
- pygeodesy/trf.py +1 -3
- pygeodesy/triaxials/bases.py +51 -20
- pygeodesy/triaxials/triaxial3.py +12 -13
- {pygeodesy-25.12.12.dist-info → pygeodesy-25.12.31.dist-info}/METADATA +22 -15
- {pygeodesy-25.12.12.dist-info → pygeodesy-25.12.31.dist-info}/RECORD +22 -22
- {pygeodesy-25.12.12.dist-info → pygeodesy-25.12.31.dist-info}/WHEEL +0 -0
- {pygeodesy-25.12.12.dist-info → pygeodesy-25.12.31.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -5,16 +5,16 @@ u'''Class L{Fsum} for precision floating point summation similar to
|
|
|
5
5
|
Python's C{math.fsum}, but enhanced with I{precision running} summation
|
|
6
6
|
plus optionally, accurate I{TwoProduct} multiplication.
|
|
7
7
|
|
|
8
|
-
Accurate multiplication is based on the C{math.fma} function from
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
Accurate multiplication is based on the C{math.fma} function from Python
|
|
9
|
+
3.13 and newer or an equivalent C{fma} implementation for Python 3.12 and
|
|
10
|
+
older. Set env variable C{PYGEODESY_FSUM_F2PRODUCT} to C{"std"} or any
|
|
11
|
+
non-empty string or invoke function C{pygeodesy.f2product(True)} to enable
|
|
12
|
+
accurate multiplication. With C{"std"} the C{fma} implemention follows
|
|
13
|
+
the C{math.fma} function, otherwise the implementation of the C{PyGeodesy
|
|
14
|
+
24.09.09} release.
|
|
15
15
|
|
|
16
16
|
Generally, an L{Fsum} instance is considered a C{float} plus a small or
|
|
17
|
-
zero C{residue} aka C{residual}
|
|
17
|
+
zero C{residue} aka C{residual}, see property L{Fsum.residual}.
|
|
18
18
|
|
|
19
19
|
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater
|
|
20
20
|
than C{"0.0"} as the threshold to throw a L{ResidualError} for a division,
|
|
@@ -28,7 +28,7 @@ L{Fsum.fint2} and L{Fsum.is_integer}. Also, L{Fsum} methods L{Fsum.pow},
|
|
|
28
28
|
L{Fsum.__ipow__}, L{Fsum.__pow__} and L{Fsum.__rpow__} return a (very long)
|
|
29
29
|
C{int} if invoked with optional argument C{mod} set to C{None}. The
|
|
30
30
|
C{residual} of an C{integer} L{Fsum} is between C{-1.0} and C{+1.0} and
|
|
31
|
-
will be C{INT0} if that is
|
|
31
|
+
will be C{INT0} if that L{Fsum} is an I{exact float} or I{exact integer}.
|
|
32
32
|
|
|
33
33
|
Set env variable C{PYGEODESY_FSUM_NONFINITES} to C{"std"} or use function
|
|
34
34
|
C{pygeodesy.nonfiniterrors(False)} to allow I{non-finite} C{float}s like
|
|
@@ -62,7 +62,7 @@ from math import fabs, isinf, isnan, \
|
|
|
62
62
|
ceil as _ceil, floor as _floor # PYCHOK used! .ltp
|
|
63
63
|
|
|
64
64
|
__all__ = _ALL_LAZY.fsums
|
|
65
|
-
__version__ = '25.
|
|
65
|
+
__version__ = '25.12.24'
|
|
66
66
|
|
|
67
67
|
from pygeodesy.interns import (
|
|
68
68
|
_PLUS_ as _add_op_, # in .auxilats.auxAngle
|
|
@@ -321,8 +321,8 @@ def nonfiniterrors(raiser=None):
|
|
|
321
321
|
'''
|
|
322
322
|
d = Fsum._isfine
|
|
323
323
|
if raiser is not None:
|
|
324
|
-
Fsum._isfine = {} if bool(raiser) else
|
|
325
|
-
return (False if d is
|
|
324
|
+
Fsum._isfine = {} if bool(raiser) else _nonfinites_isfine_kwds[True]
|
|
325
|
+
return (False if d is _nonfinites_isfine_kwds[True] else
|
|
326
326
|
_xkwds_get1(d, _isfine=_isfinite) is _isfinite) if d else True
|
|
327
327
|
|
|
328
328
|
|
|
@@ -370,7 +370,7 @@ def _Psum(ps, **name_f2product_nonfinites_RESIDUAL):
|
|
|
370
370
|
return F
|
|
371
371
|
|
|
372
372
|
|
|
373
|
-
def _Psum_(*ps, **name_f2product_nonfinites_RESIDUAL):
|
|
373
|
+
def _Psum_(*ps, **name_f2product_nonfinites_RESIDUAL):
|
|
374
374
|
'''(INTERNAL) Return an C{Fsum} from I{known scalar} C{ps}.
|
|
375
375
|
'''
|
|
376
376
|
return _Psum(ps, **name_f2product_nonfinites_RESIDUAL)
|
|
@@ -486,7 +486,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
486
486
|
|
|
487
487
|
@note: Handling of I{non-finites} as C{inf}, C{INF}, C{NINF}, C{nan} and C{NAN} is
|
|
488
488
|
determined by function L{nonfiniterrors<fsums.nonfiniterrors>} for the default
|
|
489
|
-
|
|
489
|
+
or by method L{nonfinites<Fsum.nonfinites>} for individual C{Fsum} instances,
|
|
490
490
|
overruling the default. For backward compatibility, I{non-finites} raise
|
|
491
491
|
exceptions by default.
|
|
492
492
|
|
|
@@ -829,7 +829,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
829
829
|
return self._cmp_0(other, _lt_op_ + _fset_op_) <= 0
|
|
830
830
|
|
|
831
831
|
def __len__(self):
|
|
832
|
-
'''Return the number of values accumulated (C{int}).
|
|
832
|
+
'''Return the number of (non-zero) values accumulated (C{int}).
|
|
833
833
|
'''
|
|
834
834
|
return self._n
|
|
835
835
|
|
|
@@ -1447,7 +1447,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1447
1447
|
@arg other2: Addend (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
1448
1448
|
@kwarg nonfinites: Use C{B{nonfinites}=True} or C{False}, to
|
|
1449
1449
|
override L{nonfinites<Fsum.nonfinites>} and
|
|
1450
|
-
L{nonfiniterrors} default (C{bool}).
|
|
1450
|
+
the L{nonfiniterrors} default (C{bool}).
|
|
1451
1451
|
'''
|
|
1452
1452
|
op = typename(self.fma)
|
|
1453
1453
|
_fs = self._ps_other
|
|
@@ -1479,7 +1479,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1479
1479
|
an L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
1480
1480
|
@kwarg nonfinites: Use C{B{nonfinites}=True} or C{False}, to
|
|
1481
1481
|
override L{nonfinites<Fsum.nonfinites>} and
|
|
1482
|
-
L{nonfiniterrors} default (C{bool}).
|
|
1482
|
+
the L{nonfiniterrors} default (C{bool}).
|
|
1483
1483
|
|
|
1484
1484
|
@note: Equivalent to L{fdot_<pygeodesy.fmath.fdot_>}C{(*xys,
|
|
1485
1485
|
start=self)}.
|
|
@@ -1615,8 +1615,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1615
1615
|
'''
|
|
1616
1616
|
if two: # delattrof(self, _f2product=None)
|
|
1617
1617
|
t = _xkwds_pop(self.__dict__, _f2product=None)
|
|
1618
|
-
|
|
1619
|
-
self._f2product = bool(two[0])
|
|
1618
|
+
self._optionals(f2product=two[0])
|
|
1620
1619
|
else: # getattrof(self, _f2product=None)
|
|
1621
1620
|
t = _xkwds_get(self.__dict__, _f2product=None)
|
|
1622
1621
|
return t
|
|
@@ -2070,25 +2069,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2070
2069
|
@see: Function L{nonfiniterrors<fsums.nonfiniterrors>}.
|
|
2071
2070
|
|
|
2072
2071
|
@note: Use property L{nonfinitesOK<Fsum.nonfinitesOK>} to determine
|
|
2073
|
-
whether I{non-finites} are C{OK} for this L{Fsum}
|
|
2072
|
+
whether I{non-finites} are C{OK} for this L{Fsum} or by the
|
|
2074
2073
|
L{nonfiniterrors} default.
|
|
2075
2074
|
'''
|
|
2076
|
-
_ks = Fsum._nonfinites_isfine_kwds
|
|
2077
2075
|
if OK: # delattrof(self, _isfine=None)
|
|
2078
2076
|
k = _xkwds_pop(self.__dict__, _isfine=None)
|
|
2079
|
-
|
|
2080
|
-
self._isfine = _ks[bool(OK[0])]
|
|
2077
|
+
self._optionals(nonfinites=OK[0])
|
|
2081
2078
|
self._update()
|
|
2082
2079
|
else: # getattrof(self, _isfine=None)
|
|
2083
2080
|
k = _xkwds_get(self.__dict__, _isfine=None)
|
|
2081
|
+
_ks = _nonfinites_isfine_kwds
|
|
2084
2082
|
# dict(map(reversed, _ks.items())).get(k, None)
|
|
2085
2083
|
# raises a TypeError: unhashable type: 'dict'
|
|
2086
2084
|
return True if k is _ks[True] else (
|
|
2087
2085
|
False if k is _ks[False] else None)
|
|
2088
2086
|
|
|
2089
|
-
_nonfinites_isfine_kwds = {True: dict(_isfine=_isOK),
|
|
2090
|
-
False: dict(_isfine=_isfinite)}
|
|
2091
|
-
|
|
2092
2087
|
@property_RO
|
|
2093
2088
|
def nonfinitesOK(self):
|
|
2094
2089
|
'''Are I{non-finites} C{OK} for this L{Fsum} or by default? (C{bool}).
|
|
@@ -2111,9 +2106,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2111
2106
|
'''(INTERNAL) Re/set options from keyword arguments.
|
|
2112
2107
|
'''
|
|
2113
2108
|
if f2product is not None:
|
|
2114
|
-
self.
|
|
2109
|
+
self._f2product = bool(f2product)
|
|
2115
2110
|
if nonfinites is not None:
|
|
2116
|
-
self.
|
|
2111
|
+
self._isfine = _nonfinites_isfine_kwds[bool(nonfinites)]
|
|
2117
2112
|
if name_RESIDUAL: # MUST be last
|
|
2118
2113
|
n, kwds = _name2__(**name_RESIDUAL)
|
|
2119
2114
|
if kwds:
|
|
@@ -2535,6 +2530,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2535
2530
|
|
|
2536
2531
|
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK see Fsum._update
|
|
2537
2532
|
|
|
2533
|
+
_nonfinites_isfine_kwds = {True: dict(_isfine=_isOK),
|
|
2534
|
+
False: dict(_isfine=_isfinite)}
|
|
2538
2535
|
if _NONFINITES == _std_: # PYCHOK no cover
|
|
2539
2536
|
_ = nonfiniterrors(False)
|
|
2540
2537
|
|
|
@@ -2685,6 +2682,21 @@ class Fsum2Tuple(_NamedTuple): # in .fstats
|
|
|
2685
2682
|
_Fsum_2Tuple_types = Fsum, Fsum2Tuple # PYCHOK lines
|
|
2686
2683
|
|
|
2687
2684
|
|
|
2685
|
+
class _Ksum(Fsum):
|
|
2686
|
+
'''(INTERNAL) For C{.karney._sum3}, specifically and only.
|
|
2687
|
+
'''
|
|
2688
|
+
_isfine = _nonfinites_isfine_kwds[True]
|
|
2689
|
+
|
|
2690
|
+
def __init__(self, s, t, *xs):
|
|
2691
|
+
ps = [t, s] if t else [s]
|
|
2692
|
+
self._ps = self._ps_acc(ps, xs, up=False)
|
|
2693
|
+
|
|
2694
|
+
@property_RO
|
|
2695
|
+
def _s_t_n3(self):
|
|
2696
|
+
s, t = self._fprs2
|
|
2697
|
+
return s, t, self._n
|
|
2698
|
+
|
|
2699
|
+
|
|
2688
2700
|
class ResidualError(_ValueError):
|
|
2689
2701
|
'''Error raised for a division, power or root operation of
|
|
2690
2702
|
an L{Fsum} instance with a C{residual} I{ratio} exceeding
|
pygeodesy/geod3solve.py
CHANGED
|
@@ -5,13 +5,14 @@ u'''Wrapper to invoke I{Karney}'s U{Geod3Solve
|
|
|
5
5
|
<https://GeographicLib.SourceForge.io/C++/doc/Geod3Solve.1.html>} utility
|
|
6
6
|
as a C{triaxial} geodesic, but intended I{mainly for testing purposes}.
|
|
7
7
|
|
|
8
|
-
Set env variable C{PYGEODESY_GEOD3SOLVE} to the (fully qualified) path
|
|
9
|
-
|
|
8
|
+
Set env variable C{PYGEODESY_GEOD3SOLVE} to the (fully qualified) path of
|
|
9
|
+
the C{Geod3Solve} executable or use property L{Geodesic3Solve.Geod3Solve
|
|
10
|
+
<geod3solve._Geodesic3SolveBase.Geod3Solve>}.
|
|
10
11
|
'''
|
|
11
12
|
|
|
12
13
|
from pygeodesy.angles import Ang, Deg, isAng, hypot
|
|
13
14
|
from pygeodesy.basics import _xinstanceof # typename
|
|
14
|
-
from pygeodesy.constants import _0_0, _0_5, _360_0
|
|
15
|
+
from pygeodesy.constants import _0_0, _0_5, _360_0, _over
|
|
15
16
|
from pygeodesy.errors import GeodesicError, _xkwds_get
|
|
16
17
|
# from pygeodesy.fmath import hypot # from .angles
|
|
17
18
|
# from pygeodesy.geodesicx import GeodesicAreaExact # _MODS
|
|
@@ -25,7 +26,7 @@ from pygeodesy.units import Degrees, Meter
|
|
|
25
26
|
# from pygeodesy.utily import sincos2d # from .karney
|
|
26
27
|
|
|
27
28
|
__all__ = _ALL_LAZY.geod3solve
|
|
28
|
-
__version__ = '25.12.
|
|
29
|
+
__version__ = '25.12.31'
|
|
29
30
|
|
|
30
31
|
_Triaxial3_WGS84 = Triaxial3s.WGS84_3r # a=6378172, b=6378102, c=6356752
|
|
31
32
|
|
|
@@ -39,8 +40,8 @@ class Geodesic3Error(GeodesicError):
|
|
|
39
40
|
class Geod3Solve8Tuple(_GTuple):
|
|
40
41
|
'''8-Tuple C{(bet1, omg1, alp1, bet2, omg2, alp2, s12, a12)} with C{ellipsoidal}
|
|
41
42
|
latitudes C{bet1} and C{bet2}, C{ellipsoidal} longitudes C{omg1} and C{omg2},
|
|
42
|
-
forward azimuths C{alp1} and C{alp2} in bearings from North,
|
|
43
|
-
C{meter}, conventionally and I{approximate} arc length {a12} in degrees, see
|
|
43
|
+
forward azimuths C{alp1} and C{alp2} in bearings from North, distance C{s12} in
|
|
44
|
+
C{meter}, conventionally and I{approximate} arc length C{a12} in degrees, see
|
|
44
45
|
U{Geod3Solve<https://GeographicLib.SourceForge.io/C++/doc/Geod3Solve.1.html>}.
|
|
45
46
|
'''
|
|
46
47
|
# from Geod3Solve --help option -f ... bet1 omg1 alp1 bet2 omg2 alp2 s12
|
|
@@ -161,11 +162,11 @@ class Geodesic3Solve(_Geodesic3SolveBase):
|
|
|
161
162
|
'''
|
|
162
163
|
a = r.s12 or _0_0
|
|
163
164
|
if a:
|
|
165
|
+
t = self.triaxial3
|
|
164
166
|
z = _toAzi(r.alp1) + _toAzi(r.alp2)
|
|
165
167
|
s, c = sincos2d(z * _0_5)
|
|
166
|
-
t
|
|
167
|
-
|
|
168
|
-
c / t._bc_elliperim) * _360_0
|
|
168
|
+
a *= hypot(_over(s, t.perimeter4ab), # azimuth!
|
|
169
|
+
_over(c, t.perimeter4bc)) * _360_0
|
|
169
170
|
r[_a12_] = a
|
|
170
171
|
return r
|
|
171
172
|
|
pygeodesy/geodesici.py
CHANGED
|
@@ -7,10 +7,11 @@ Class L{Intersector} is a pure Python version of I{Karney}'s C++ class U{Interse
|
|
|
7
7
|
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Intersect.html>}.
|
|
8
8
|
|
|
9
9
|
Class L{Intersectool} is a wrapper to invoke I{Karney}'s U{IntersectTool
|
|
10
|
-
<https://GeographicLib.SourceForge.io/C++/doc/IntersectTool.1.html>} utility,
|
|
10
|
+
<https://GeographicLib.SourceForge.io/C++/doc/IntersectTool.1.html>} utility, mainly intended I{for testing purposes}.
|
|
11
11
|
|
|
12
|
-
Set env variable C{PYGEODESY_INTERSECTTOOL} to the (fully qualified) path of the C{IntersectTool} executable
|
|
13
|
-
and some examples run C{"env PYGEODESY_INTERSECTTOOL=<IntersectTool-path>
|
|
12
|
+
Set env variable C{PYGEODESY_INTERSECTTOOL} to the (fully qualified) path of the C{IntersectTool} executable or use
|
|
13
|
+
property L{Intersectool.IntersectTool}. For usage and some examples run C{"env PYGEODESY_INTERSECTTOOL=<IntersectTool-path>
|
|
14
|
+
python3 -m pygeodesy.geodesici --help"}.
|
|
14
15
|
|
|
15
16
|
Both L{Intersectool} and L{Intersector} provide methods C{All}, C{Closest}, C{Next} and C{Segment} and produce
|
|
16
17
|
L{XDict} instances with 4 or more items. Adjacent methods C{All5}, C{Closest5}, C{Next5} and C{Segment} return
|
|
@@ -57,7 +58,7 @@ from pygeodesy.utily import atan2, sincos2, fabs, radians
|
|
|
57
58
|
# from math import ceil as _ceil, fabs, radians # .fsums, .utily
|
|
58
59
|
|
|
59
60
|
__all__ = _ALL_LAZY.geodesici
|
|
60
|
-
__version__ = '25.
|
|
61
|
+
__version__ = '25.12.31'
|
|
61
62
|
|
|
62
63
|
_0t = 0, # int
|
|
63
64
|
_1_1t = -1, +1
|
pygeodesy/geodesicx/__init__.py
CHANGED
pygeodesy/geodesicx/gxarea.py
CHANGED
|
@@ -19,19 +19,20 @@ from __future__ import division as _; del _ # noqa: E702 ;
|
|
|
19
19
|
|
|
20
20
|
from pygeodesy.basics import _copysign, isodd, unsigned0
|
|
21
21
|
from pygeodesy.constants import NAN, _0_0, _0_5, _720_0
|
|
22
|
+
from pygeodesy.fmath import _fma
|
|
22
23
|
from pygeodesy.internals import printf, typename
|
|
23
24
|
# from pygeodesy.interns import _COMMASPACE_ # from .lazily
|
|
24
25
|
from pygeodesy.karney import Area3Tuple, _diff182, GeodesicError, \
|
|
25
|
-
_norm180, _remainder,
|
|
26
|
+
_norm180, _remainder, _sum2
|
|
26
27
|
from pygeodesy.lazily import _ALL_DOCS, _COMMASPACE_
|
|
27
28
|
from pygeodesy.named import ADict, callername, _NamedBase, pairs
|
|
28
29
|
from pygeodesy.props import Property, Property_RO, property_RO
|
|
29
30
|
# from pygeodesy.streprs import pairs # from .named
|
|
30
31
|
|
|
31
|
-
from math import fmod as _fmod
|
|
32
|
+
from math import fabs, fmod as _fmod
|
|
32
33
|
|
|
33
34
|
__all__ = ()
|
|
34
|
-
__version__ = '25.
|
|
35
|
+
__version__ = '25.12.23'
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
class GeodesicAreaExact(_NamedBase):
|
|
@@ -427,30 +428,39 @@ class _Accumulator(_NamedBase):
|
|
|
427
428
|
@kwarg y: Initial value (C{scalar}).
|
|
428
429
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
429
430
|
'''
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
elif y:
|
|
433
|
-
self._s, self._n = float(y), 1
|
|
431
|
+
self._s_t(*_s_t2(y))
|
|
432
|
+
self._n = 1
|
|
434
433
|
if name:
|
|
435
434
|
self.name = name
|
|
436
435
|
|
|
437
|
-
def Add(self,
|
|
438
|
-
'''Add
|
|
436
|
+
def Add(self, *ys):
|
|
437
|
+
'''Add one or more scalars or L{_Accumulator}s.
|
|
439
438
|
|
|
440
439
|
@return: Current C{sum}.
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
440
|
+
|
|
441
|
+
@see: C++ U{Accumulator.Add<https://GeographicLib.sourceforge.io/C++/doc/Accumulator_8hpp_source.html>}
|
|
442
|
+
for more details about Karney's and Shewchuk's addition.
|
|
443
|
+
'''
|
|
444
|
+
# _Accumulator().Add(1, 1e20, 2, 100, 5000, -1e20) ... 5103.0
|
|
445
|
+
s, t = self._s, self._t
|
|
446
|
+
for y in ys:
|
|
447
|
+
for y in _s_t2(y):
|
|
448
|
+
if y:
|
|
449
|
+
t, u = _sum2(t, y)
|
|
450
|
+
s, t = _sum2(s, t)
|
|
451
|
+
if s: # accumlate u in t
|
|
452
|
+
t += u
|
|
453
|
+
else: # s == 0 implies t == 0
|
|
454
|
+
s = u
|
|
455
|
+
self._n += 1
|
|
456
|
+
return self._s_t(s, t)
|
|
445
457
|
|
|
446
458
|
def Negate(self):
|
|
447
459
|
'''Negate sum.
|
|
448
460
|
|
|
449
461
|
@return: Current C{sum}.
|
|
450
462
|
'''
|
|
451
|
-
self._s
|
|
452
|
-
self._t = -self._t
|
|
453
|
-
return s # current .Sum()
|
|
463
|
+
return self._s_t(-self._s, -self._t)
|
|
454
464
|
|
|
455
465
|
@property_RO
|
|
456
466
|
def num(self):
|
|
@@ -459,22 +469,27 @@ class _Accumulator(_NamedBase):
|
|
|
459
469
|
return self._n
|
|
460
470
|
|
|
461
471
|
def Remainder(self, y):
|
|
462
|
-
'''Remainder
|
|
472
|
+
'''Remainder of division by B{C{y}}.
|
|
463
473
|
|
|
464
474
|
@return: Remainder of C{sum} / B{C{y}}.
|
|
465
475
|
'''
|
|
466
|
-
self.
|
|
467
|
-
|
|
468
|
-
self._n = -1
|
|
469
|
-
return self.Add(_0_0)
|
|
476
|
+
return self._s_t(_remainder(self._s, y),
|
|
477
|
+
_remainder(self._t, y))
|
|
470
478
|
|
|
471
479
|
def Reset(self, y=0):
|
|
472
|
-
'''
|
|
480
|
+
'''Reset from scalar or L{_Accumulator}.
|
|
473
481
|
'''
|
|
474
|
-
self.
|
|
482
|
+
self._s_t(*_s_t2(y))
|
|
483
|
+
self._n = 0
|
|
475
484
|
|
|
476
485
|
Set = Reset
|
|
477
486
|
|
|
487
|
+
def _s_t(self, s, t=0):
|
|
488
|
+
if t and fabs(s) < fabs(t):
|
|
489
|
+
s, t = t, s
|
|
490
|
+
self._s, self._t = s, t
|
|
491
|
+
return s
|
|
492
|
+
|
|
478
493
|
def Sum(self, y=0):
|
|
479
494
|
'''Return C{sum + B{y}}.
|
|
480
495
|
|
|
@@ -488,6 +503,17 @@ class _Accumulator(_NamedBase):
|
|
|
488
503
|
s = self
|
|
489
504
|
return s._s
|
|
490
505
|
|
|
506
|
+
def Times(self, y):
|
|
507
|
+
'''Multiply by a scalar.
|
|
508
|
+
|
|
509
|
+
@return: Current C{sum}.
|
|
510
|
+
'''
|
|
511
|
+
s = d = self._s
|
|
512
|
+
s *= y
|
|
513
|
+
d = _fma(y, d, -s)
|
|
514
|
+
t = _fma(y, self._t, d)
|
|
515
|
+
return self._s_t(s, t) # current .Sum()
|
|
516
|
+
|
|
491
517
|
def toStr(self, prec=6, sep=_COMMASPACE_, **unused): # PYCHOK signature
|
|
492
518
|
'''Return this C{_Accumulator} as string.
|
|
493
519
|
|
|
@@ -502,6 +528,10 @@ class _Accumulator(_NamedBase):
|
|
|
502
528
|
return sep.join(pairs(d, prec=prec))
|
|
503
529
|
|
|
504
530
|
|
|
531
|
+
def _s_t2(y):
|
|
532
|
+
return (y._s, y._t) if isinstance(y, _Accumulator) else (float(y),) # PYCHOK OK
|
|
533
|
+
|
|
534
|
+
|
|
505
535
|
__all__ += _ALL_DOCS(GeodesicAreaExact, PolygonArea)
|
|
506
536
|
|
|
507
537
|
# **) MIT License
|
pygeodesy/geodsolve.py
CHANGED
|
@@ -5,8 +5,9 @@ u'''Wrapper to invoke I{Karney}'s U{GeodSolve
|
|
|
5
5
|
<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>} utility
|
|
6
6
|
as an (exact) geodesic, but intended I{mainly for testing purposes}.
|
|
7
7
|
|
|
8
|
-
Set env variable C{PYGEODESY_GEODSOLVE} to the (fully qualified) path
|
|
9
|
-
|
|
8
|
+
Set env variable C{PYGEODESY_GEODSOLVE} to the (fully qualified) path of
|
|
9
|
+
the C{GeodSolve} executable or use property L{GeodesicSolve.GeodSolve
|
|
10
|
+
<geodsolve._GeodesicSolveBase.GeodSolve>}.
|
|
10
11
|
'''
|
|
11
12
|
|
|
12
13
|
from pygeodesy.basics import _xinstanceof # typename
|
|
@@ -28,7 +29,7 @@ from pygeodesy.solveBase import _SolveGDictBase, _SolveGDictLineBase
|
|
|
28
29
|
from pygeodesy.utily import _unrollon, _Wrap, wrap360
|
|
29
30
|
|
|
30
31
|
__all__ = _ALL_LAZY.geodsolve
|
|
31
|
-
__version__ = '25.12.
|
|
32
|
+
__version__ = '25.12.31'
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class GeodSolve12Tuple(_GTuple):
|
pygeodesy/karney.py
CHANGED
|
@@ -153,14 +153,14 @@ in C{pygeodesy} are based on I{Karney}'s post U{Area of a spherical polygon
|
|
|
153
153
|
# make sure int/int division yields float quotient, see .basics
|
|
154
154
|
from __future__ import division as _; del _ # noqa: E702 ;
|
|
155
155
|
|
|
156
|
-
from pygeodesy.basics import _copysign, _isin, isint, neg,
|
|
157
|
-
_xgeographiclib, _zip
|
|
156
|
+
from pygeodesy.basics import _copysign, _isin, isint, neg, _xgeographiclib, _zip
|
|
158
157
|
from pygeodesy.constants import NAN, _isfinite as _math_isfinite, \
|
|
159
158
|
_0_0, _1_0, _2_0, _180_0, _N_180_0, _360_0
|
|
160
159
|
# from pygeodesy.deprecated.classes import Rhumb7Tuple # _MODS
|
|
161
160
|
from pygeodesy.errors import GeodesicError, _ValueError, _xkwds
|
|
162
161
|
# from pygeodesy.geod3Solve import Geod3Solve8Tuple # _MODS
|
|
163
|
-
from pygeodesy.fmath import cbrt, fremainder, norm2
|
|
162
|
+
from pygeodesy.fmath import cbrt, fhorner, fremainder, norm2
|
|
163
|
+
from pygeodesy.fsums import _Ksum
|
|
164
164
|
from pygeodesy.internals import _getenv, _popen2, _PYGEODESY_ENV, typename, \
|
|
165
165
|
_version_info
|
|
166
166
|
from pygeodesy.interns import NN, _a12_, _area_, _azi2_, _azi12_, _composite_, \
|
|
@@ -177,7 +177,7 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
|
|
|
177
177
|
# from math import fabs # from .utily
|
|
178
178
|
|
|
179
179
|
__all__ = _ALL_LAZY.karney
|
|
180
|
-
__version__ = '25.12.
|
|
180
|
+
__version__ = '25.12.23'
|
|
181
181
|
|
|
182
182
|
_1_16th = _1_0 / 16
|
|
183
183
|
_2_4_ = '2.4'
|
|
@@ -913,20 +913,18 @@ try:
|
|
|
913
913
|
|
|
914
914
|
except ImportError: # Python 3.12-
|
|
915
915
|
|
|
916
|
-
def _poly_fma(x,
|
|
917
|
-
|
|
918
|
-
for c in cs:
|
|
919
|
-
s, t, _ = _sum3(s * x, t * x, c)
|
|
920
|
-
return s + t
|
|
916
|
+
def _poly_fma(x, *cs): # PYCHOK redef
|
|
917
|
+
return fhorner(x, *cs, incx=False)
|
|
921
918
|
|
|
922
919
|
# def _poly_fma(x, s, *cs):
|
|
923
|
-
#
|
|
924
|
-
#
|
|
925
|
-
#
|
|
920
|
+
# t = _0_0
|
|
921
|
+
# for c in cs:
|
|
922
|
+
# s, t, _ = _sum3(s * x, t * x, c)
|
|
923
|
+
# return s + t
|
|
926
924
|
|
|
927
925
|
def _polynomial(x, cs, i, j): # PYCHOK shared
|
|
928
|
-
'''(INTERNAL) Like C++ C{GeographicLib.Math.hpp.polyval} but
|
|
929
|
-
signature and cascaded summation
|
|
926
|
+
'''(INTERNAL) Like C++ C{GeographicLib.Math.hpp.polyval} but
|
|
927
|
+
with a different signature and cascaded summation.
|
|
930
928
|
|
|
931
929
|
@return: M{sum(x**(j - k - 1) * cs[k] for k in range(i, j)}
|
|
932
930
|
'''
|
|
@@ -1007,18 +1005,18 @@ def _sum2(a, b): # mimick geomath.Math.sum, actually sum2
|
|
|
1007
1005
|
r = s - b
|
|
1008
1006
|
t = s - r
|
|
1009
1007
|
# elif C_CPP: # Math::sum C/C++
|
|
1010
|
-
# r -= a; t -= b; t += r; t = -t
|
|
1011
|
-
# else:
|
|
1012
|
-
t = (a - r) + (b - t)
|
|
1008
|
+
# r -= a; t -= b; t += r; t = (-t) if s else s
|
|
1009
|
+
# else: # if s == 0: t = _copysign_0_0(s)
|
|
1010
|
+
t = ((a - r) + (b - t)) if s else s
|
|
1013
1011
|
# assert fabs(s) >= fabs(t)
|
|
1014
1012
|
return s, t
|
|
1015
1013
|
|
|
1016
1014
|
|
|
1017
1015
|
def _sum3(s, t, *xs):
|
|
1018
|
-
'''Accumulate
|
|
1016
|
+
'''Accumulate all B{C{xs}} scalars into a previous C{_sum2(s, t)}.
|
|
1019
1017
|
|
|
1020
1018
|
@return: 3-Tuple C{(s, t, n)} where C{s} is the sum of B{s}, B{t} and all
|
|
1021
|
-
B{xs}, C{t} the residual and C{n} the number of zero C{xs}.
|
|
1019
|
+
B{xs}, C{t} the residual and C{n} the number of non-zero C{xs}.
|
|
1022
1020
|
|
|
1023
1021
|
@see: I{Karney's} C++ U{Accumulator<https://GeographicLib.SourceForge.io/
|
|
1024
1022
|
C++/doc/Accumulator_8hpp_source.html>} comments for more details and
|
|
@@ -1026,23 +1024,10 @@ def _sum3(s, t, *xs):
|
|
|
1026
1024
|
|
|
1027
1025
|
@note: Not "error-free", see C{pygeodesy.test/testKarney.py}.
|
|
1028
1026
|
'''
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
if s:
|
|
1034
|
-
s, t = _sum2(s, t) # -significant end
|
|
1035
|
-
if s:
|
|
1036
|
-
t += r # accumulate r into t
|
|
1037
|
-
else:
|
|
1038
|
-
# assert t == 0 # s == 0 implies t == 0
|
|
1039
|
-
s = unsigned0(r) # result is r, t = 0
|
|
1040
|
-
else:
|
|
1041
|
-
s, t = unsigned0(t), r
|
|
1042
|
-
else:
|
|
1043
|
-
z += 1
|
|
1044
|
-
# assert fabs(s) >= fabs(t)
|
|
1045
|
-
return s, t, z
|
|
1027
|
+
return _Ksum(s, t, *xs)._s_t_n3 if xs else (s, t, 0)
|
|
1028
|
+
# previous _sum3 in .geodesicx.gxarea._Accumulator.Add
|
|
1029
|
+
# which fails .fmath.frandoms tests, but does pass
|
|
1030
|
+
# _sum3(1e20, 1, 2, 100, 5000, -1e20) ... 5103.0, 0.0, 4
|
|
1046
1031
|
|
|
1047
1032
|
|
|
1048
1033
|
def _tand(x):
|
pygeodesy/lazily.py
CHANGED
|
@@ -250,7 +250,7 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
|
|
|
250
250
|
'fpolynomial', 'fpowers', 'fprod', 'frandoms', 'frange', 'freduce', 'fremainder',
|
|
251
251
|
'hypot', 'hypot_', 'hypot1', 'hypot2', 'hypot2_',
|
|
252
252
|
'norm2', 'norm_', 'sqrt0', 'sqrt3', 'sqrt_a', 'zcrt', 'zqrt'),
|
|
253
|
-
formy=_a('Radical2Tuple',
|
|
253
|
+
formy=_a('Elliperim', 'Radical2Tuple',
|
|
254
254
|
'angle2chord', 'antipode', 'antipode_', 'bearing', 'bearing_',
|
|
255
255
|
'chord2angle', 'compassAngle', 'cosineLaw', 'cosineLaw_',
|
|
256
256
|
'elliperim', 'equirectangular', 'equirectangular4', 'euclidean', 'euclidean_',
|
|
@@ -520,7 +520,7 @@ class _ALL_MODS(_internals._MODS_Base):
|
|
|
520
520
|
_internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
|
|
521
521
|
|
|
522
522
|
__all__ = _ALL_LAZY.lazily
|
|
523
|
-
__version__ = '25.12.
|
|
523
|
+
__version__ = '25.12.23'
|
|
524
524
|
|
|
525
525
|
|
|
526
526
|
def _ALL_OTHER(*objs):
|
pygeodesy/named.py
CHANGED
|
@@ -35,7 +35,7 @@ from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
|
|
|
35
35
|
# from pygeodesy.units import _toUnit # _MODS
|
|
36
36
|
|
|
37
37
|
__all__ = _ALL_LAZY.named
|
|
38
|
-
__version__ = '25.11.
|
|
38
|
+
__version__ = '25.11.13'
|
|
39
39
|
|
|
40
40
|
_COMMANL_ = _COMMA_ + _NL_
|
|
41
41
|
_COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
|
|
@@ -1188,7 +1188,7 @@ def callername(up=1, dflt=NN, source=False, underOK=False):
|
|
|
1188
1188
|
|
|
1189
1189
|
@return: The callable name (C{str}) or B{C{dflt}} if none found.
|
|
1190
1190
|
'''
|
|
1191
|
-
try: # see .
|
|
1191
|
+
try: # see .internals._caller3
|
|
1192
1192
|
for u in range(up, up + 32):
|
|
1193
1193
|
n, f, s = _caller3(u)
|
|
1194
1194
|
if n and (underOK or n.startswith(_DUNDER_) or
|
pygeodesy/props.py
CHANGED
|
@@ -26,7 +26,7 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, \
|
|
|
26
26
|
from functools import wraps as _wraps
|
|
27
27
|
|
|
28
28
|
__all__ = _ALL_LAZY.props
|
|
29
|
-
__version__ = '25.
|
|
29
|
+
__version__ = '25.12.31'
|
|
30
30
|
|
|
31
31
|
_class_ = 'class'
|
|
32
32
|
_DNL_ = _NL_ * 2 # PYCHOK used!
|
|
@@ -696,8 +696,10 @@ class DeprecationWarnings(object):
|
|
|
696
696
|
'''
|
|
697
697
|
return self._Warnings if _WARNINGS_X_DEV else None
|
|
698
698
|
|
|
699
|
-
|
|
700
|
-
|
|
699
|
+
if not _FOR_DOCS: # PYCHOK force epydoc
|
|
700
|
+
DeprecationWarnings = DeprecationWarnings() # singleton
|
|
701
|
+
_throwarning = DeprecationWarnings.throw
|
|
702
|
+
# del _FOR_DOCS
|
|
701
703
|
|
|
702
704
|
# **) MIT License
|
|
703
705
|
#
|
pygeodesy/trf.py
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
|
-
u'''I{Veness}' Terrestrial Reference Frames (TRF).
|
|
5
|
-
|
|
6
|
-
Classes L{RefFrame}, registry L{RefFrames} and L{TRFError}.
|
|
4
|
+
u'''I{Veness}' Terrestrial Reference Frames (TRF), classes L{RefFrame}, registry L{RefFrames} and L{TRFError}.
|
|
7
5
|
|
|
8
6
|
Transcoded from I{Chris Veness'} (C) 2006-2024 JavaScript originals U{latlon-ellipsoidal-referenceframe.js
|
|
9
7
|
<https://GitHub.com/ChrisVeness/geodesy/blob/master/latlon-ellipsoidal-referenceframe.js>} and
|