pygeodesy 24.8.4__py2.py3-none-any.whl → 24.9.9__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-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/METADATA +17 -16
- PyGeodesy-24.9.9.dist-info/RECORD +118 -0
- {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +23 -23
- pygeodesy/__main__.py +46 -47
- pygeodesy/auxilats/_CX_4.py +104 -181
- pygeodesy/auxilats/_CX_6.py +152 -277
- pygeodesy/auxilats/_CX_8.py +211 -438
- pygeodesy/auxilats/_CX_Rs.py +222 -0
- pygeodesy/auxilats/__init__.py +2 -2
- pygeodesy/auxilats/__main__.py +30 -38
- pygeodesy/auxilats/auxDST.py +2 -2
- pygeodesy/auxilats/auxLat.py +28 -36
- pygeodesy/auxilats/auxily.py +30 -50
- pygeodesy/basics.py +18 -7
- pygeodesy/booleans.py +10 -11
- pygeodesy/cartesianBase.py +5 -5
- pygeodesy/constants.py +35 -34
- pygeodesy/ellipsoidalBase.py +18 -15
- pygeodesy/ellipsoidalExact.py +2 -2
- pygeodesy/ellipsoidalGeodSolve.py +2 -2
- pygeodesy/ellipsoidalKarney.py +2 -2
- pygeodesy/ellipsoidalNvector.py +2 -2
- pygeodesy/ellipsoidalVincenty.py +7 -6
- pygeodesy/elliptic.py +154 -88
- pygeodesy/epsg.py +3 -3
- pygeodesy/etm.py +71 -59
- pygeodesy/fmath.py +99 -90
- pygeodesy/fsums.py +201 -14
- pygeodesy/gars.py +9 -8
- pygeodesy/geodesici.py +6 -5
- pygeodesy/geodesicx/_C4_24.py +1 -3
- pygeodesy/geodesicx/_C4_27.py +1 -3
- pygeodesy/geodesicx/_C4_30.py +1 -3
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +44 -46
- pygeodesy/geodesicx/gx.py +3 -3
- pygeodesy/geodesicx/gxarea.py +5 -5
- pygeodesy/geodesicx/gxbases.py +32 -18
- pygeodesy/geodsolve.py +3 -3
- pygeodesy/geohash.py +18 -11
- pygeodesy/geoids.py +293 -315
- pygeodesy/heights.py +150 -158
- pygeodesy/internals.py +70 -9
- pygeodesy/interns.py +4 -4
- pygeodesy/karney.py +83 -60
- pygeodesy/ktm.py +4 -4
- pygeodesy/latlonBase.py +13 -7
- pygeodesy/lazily.py +13 -8
- pygeodesy/ltp.py +5 -6
- pygeodesy/ltpTuples.py +7 -1
- pygeodesy/mgrs.py +47 -42
- pygeodesy/named.py +8 -4
- pygeodesy/namedTuples.py +14 -1
- pygeodesy/osgr.py +7 -7
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +7 -6
- pygeodesy/resections.py +7 -7
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +42 -60
- pygeodesy/rhumb/solve.py +3 -3
- pygeodesy/simplify.py +10 -10
- pygeodesy/sphericalBase.py +3 -3
- pygeodesy/sphericalTrigonometry.py +2 -2
- pygeodesy/streprs.py +3 -3
- pygeodesy/triaxials.py +207 -201
- pygeodesy/units.py +3 -3
- pygeodesy/unitsBase.py +4 -4
- pygeodesy/utmupsBase.py +3 -3
- pygeodesy/vector2d.py +158 -51
- pygeodesy/vector3d.py +13 -52
- pygeodesy/vector3dBase.py +81 -63
- pygeodesy/webmercator.py +3 -3
- pygeodesy/wgrs.py +20 -22
- PyGeodesy-24.8.4.dist-info/RECORD +0 -117
- {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
u'''Class L{Fsum} for precision floating point summation and I{running}
|
|
5
5
|
summation based on, respectively similar to Python's C{math.fsum}.
|
|
6
6
|
|
|
7
|
+
Class L{Fsum} also supports accurate multiplication for Python 3.13 and
|
|
8
|
+
later, but as an option for older Python versions. For more details, see
|
|
9
|
+
method L{f2product<Fsum.f2product>}, class L{Fsum2product} and U{Accurate
|
|
10
|
+
Sum and Dot Product<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}.
|
|
11
|
+
|
|
7
12
|
Generally, an L{Fsum} instance is considered a C{float} plus a small or zero
|
|
8
13
|
C{residual} value, see property L{Fsum.residual}. However, there are several
|
|
9
14
|
C{integer} L{Fsum} cases, for example the result of C{ceil}, C{floor},
|
|
@@ -25,13 +30,13 @@ from __future__ import division as _; del _ # PYCHOK semicolon
|
|
|
25
30
|
|
|
26
31
|
from pygeodesy.basics import isbool, iscomplex, isint, isscalar, \
|
|
27
32
|
_signOf, itemsorted, signOf, _xiterable, \
|
|
28
|
-
_xiterablen
|
|
29
|
-
from pygeodesy.constants import INT0, _isfinite, NEG0, _pos_self, \
|
|
33
|
+
_xiterablen
|
|
34
|
+
from pygeodesy.constants import INT0, _isfinite, MANT_DIG, NEG0, _pos_self, \
|
|
30
35
|
_0_0, _1_0, _N_1_0, Float, Int
|
|
31
36
|
from pygeodesy.errors import _OverflowError, _TypeError, _UnexpectedError, \
|
|
32
37
|
_ValueError, _xError, _xError2, _xkwds_get1, \
|
|
33
38
|
_xkwds_pop2
|
|
34
|
-
|
|
39
|
+
from pygeodesy.internals import _enquote, _passarg
|
|
35
40
|
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DASH_, _DOT_, \
|
|
36
41
|
_EQUAL_, _from_, _LANGLE_, _NOTEQUAL_, \
|
|
37
42
|
_not_finite_, _PERCENT_, _PLUS_, \
|
|
@@ -47,7 +52,7 @@ from pygeodesy.streprs import Fmt, fstr, unstr
|
|
|
47
52
|
from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
|
|
48
53
|
|
|
49
54
|
__all__ = _ALL_LAZY.fsums
|
|
50
|
-
__version__ = '24.
|
|
55
|
+
__version__ = '24.09.10'
|
|
51
56
|
|
|
52
57
|
_add_op_ = _PLUS_ # in .auxilats.auxAngle
|
|
53
58
|
_eq_op_ = _EQUAL_ * 2 # _DEQUAL_
|
|
@@ -132,6 +137,81 @@ def _2floats(xs, origin=0, _X=_X_ps, _x=float):
|
|
|
132
137
|
_xError(X, Fmt.INDEX(xs=i), x)
|
|
133
138
|
|
|
134
139
|
|
|
140
|
+
try: # MCCABE 14
|
|
141
|
+
from math import fma as _fma
|
|
142
|
+
|
|
143
|
+
def _2products(x, ys, **unused):
|
|
144
|
+
# TwoProductFMA U{Algorithm 3.5
|
|
145
|
+
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
146
|
+
for y in ys:
|
|
147
|
+
f = x * y
|
|
148
|
+
yield f
|
|
149
|
+
yield _fma(x, y, -f)
|
|
150
|
+
|
|
151
|
+
_2split3s = _passarg # NOP
|
|
152
|
+
|
|
153
|
+
except ImportError: # Python 3.12-
|
|
154
|
+
|
|
155
|
+
def _fma(*a_b_c): # in .fmath
|
|
156
|
+
# mimick C{math.fma} from Python 3.13+
|
|
157
|
+
# <https://MomentsInGraphics.De/FMA.html>
|
|
158
|
+
# >>> a = 1.00000011920929
|
|
159
|
+
# >>> b = 53400708
|
|
160
|
+
# >>> c = -b
|
|
161
|
+
# >>> _fma(a, b, c)
|
|
162
|
+
# 6.365860485903399
|
|
163
|
+
# >>> (a * b) + c
|
|
164
|
+
# 6.3658604845404625
|
|
165
|
+
|
|
166
|
+
def _as_n_d(x):
|
|
167
|
+
try:
|
|
168
|
+
if _isfinite(x):
|
|
169
|
+
# int.as_integer_ratio since 3.8
|
|
170
|
+
return x.as_integer_ratio()
|
|
171
|
+
except (AttributeError, OverflowError, TypeError, ValueError):
|
|
172
|
+
pass
|
|
173
|
+
return float(x), 1
|
|
174
|
+
|
|
175
|
+
(na, da), (nb, db), (nc, dc) = map(_as_n_d, a_b_c)
|
|
176
|
+
n = na * nb * dc + da * db * nc
|
|
177
|
+
d = da * db * dc
|
|
178
|
+
return float(n / d)
|
|
179
|
+
|
|
180
|
+
def _2products(x, y3s, two=False): # PYCHOK redef
|
|
181
|
+
# TwoProduct U{Algorithm 3.3
|
|
182
|
+
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
183
|
+
_, a, b = _2split3(x)
|
|
184
|
+
for y, c, d in y3s:
|
|
185
|
+
y *= x
|
|
186
|
+
yield y
|
|
187
|
+
if two:
|
|
188
|
+
yield b * d - (((y - a * c) - b * c) - a * d)
|
|
189
|
+
# = b * d + (a * d - ((y - a * c) - b * c))
|
|
190
|
+
# = b * d + (a * d + (b * c - (y - a * c)))
|
|
191
|
+
# = b * d + (a * d + (b * c + (a * c - y)))
|
|
192
|
+
else:
|
|
193
|
+
yield a * c - y
|
|
194
|
+
yield b * c
|
|
195
|
+
if d:
|
|
196
|
+
yield a * d
|
|
197
|
+
yield b * d
|
|
198
|
+
|
|
199
|
+
_2FACTOR = pow(2, (MANT_DIG + 1) // 2) + 1
|
|
200
|
+
|
|
201
|
+
def _2split3(x):
|
|
202
|
+
# Split U{Algorithm 3.2
|
|
203
|
+
# <ttps://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
204
|
+
a = c = x * _2FACTOR
|
|
205
|
+
a -= c - x
|
|
206
|
+
b = x - a
|
|
207
|
+
return x, a, b
|
|
208
|
+
|
|
209
|
+
def _2split3s(xs): # PYCHOK redef
|
|
210
|
+
return map(_2split3, xs)
|
|
211
|
+
|
|
212
|
+
del MANT_DIG
|
|
213
|
+
|
|
214
|
+
|
|
135
215
|
def _Fsumf_(*xs): # floats=True, in .auxLat, ...
|
|
136
216
|
'''(INTERNAL) An C{Fsum} of I{known scalars}.
|
|
137
217
|
'''
|
|
@@ -325,6 +405,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
325
405
|
file I{Modules/mathmodule.c} and the issue log U{Full precision summation
|
|
326
406
|
<https://Bugs.Python.org/issue2819>}.
|
|
327
407
|
'''
|
|
408
|
+
_f2product = _2split3s is _passarg # True for 3.13+
|
|
409
|
+
_math_fma = _fma if _f2product else None
|
|
328
410
|
_math_fsum = None
|
|
329
411
|
_n = 0
|
|
330
412
|
# _ps = [] # partial sums
|
|
@@ -467,7 +549,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
467
549
|
def __hash__(self): # PYCHOK no cover
|
|
468
550
|
'''Return this instance' C{hash}.
|
|
469
551
|
'''
|
|
470
|
-
|
|
552
|
+
# @see: U{Notes for type implementors<https://docs.Python.org/
|
|
553
|
+
# 3/library/numbers.html#numbers.Rational>}
|
|
554
|
+
return hash(self.partials) # tuple.__hash__()
|
|
471
555
|
|
|
472
556
|
def __iadd__(self, other):
|
|
473
557
|
'''Apply C{B{self} += B{other}} to this instance.
|
|
@@ -890,6 +974,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
890
974
|
f._ps = list(self._ps) # separate list
|
|
891
975
|
if not deep:
|
|
892
976
|
f._n = 1
|
|
977
|
+
# assert f._f2product == self._f2product
|
|
893
978
|
# assert f._Fsum is f
|
|
894
979
|
return f
|
|
895
980
|
|
|
@@ -901,6 +986,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
901
986
|
f = _Named.copy(self, deep=False, name=n)
|
|
902
987
|
f._ps = list(self._ps) # separate list
|
|
903
988
|
# assert f._n == self._n
|
|
989
|
+
# assert f._f2product == self._f2product
|
|
904
990
|
# assert f._Fsum is f
|
|
905
991
|
return f
|
|
906
992
|
|
|
@@ -1111,9 +1197,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1111
1197
|
# raise self._Error(op, other, _AssertionError, txt__=signOf)
|
|
1112
1198
|
return DivMod2Tuple(q, self) # q is C{int} in Python 3+, but C{float} in Python 2-
|
|
1113
1199
|
|
|
1114
|
-
def _fhorner(self, x, cs, op): # in .fmath
|
|
1200
|
+
def _fhorner(self, x, cs, op, incx=True): # in .fmath
|
|
1115
1201
|
'''(INTERNAL) Add an L{Fhorner} evaluation of polynomial
|
|
1116
|
-
|
|
1202
|
+
C{sum(cs[i] * B{x}**i for i=0..len(cs)-1) if B{incx}
|
|
1203
|
+
else sum(... i=len(cs)-1..0)}.
|
|
1117
1204
|
'''
|
|
1118
1205
|
if _xiterablen(cs):
|
|
1119
1206
|
H = Fsum(name__=self._fhorner)
|
|
@@ -1123,11 +1210,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1123
1210
|
_mul = H._mul_scalar
|
|
1124
1211
|
x = _2float(x=x)
|
|
1125
1212
|
if len(cs) > 1 and x:
|
|
1126
|
-
for c in reversed(cs):
|
|
1213
|
+
for c in (reversed(cs) if incx else cs):
|
|
1127
1214
|
H._fset_ps(_mul(x, op))
|
|
1128
1215
|
H._fadd(c, op, up=False)
|
|
1129
1216
|
else: # x == 0
|
|
1130
|
-
H = cs[0]
|
|
1217
|
+
H = cs[0] if cs else _0_0
|
|
1131
1218
|
self._fadd(H, op)
|
|
1132
1219
|
return self
|
|
1133
1220
|
|
|
@@ -1222,6 +1309,38 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1222
1309
|
q = self._ftruediv(other, op, **raiser_RESIDUAL) # == self
|
|
1223
1310
|
return self._fset(q.floor) # floor(q)
|
|
1224
1311
|
|
|
1312
|
+
def fma(self, other1, other2): #
|
|
1313
|
+
'''Fused-multiply-add C{self *= B{other1}; self += B{other2}}.
|
|
1314
|
+
|
|
1315
|
+
@arg other1: A C{scalar}, an L{Fsum} or L{Fsum2Tuple} instance.
|
|
1316
|
+
@arg other2: A C{scalar}, an L{Fsum} or L{Fsum2Tuple} instance.
|
|
1317
|
+
|
|
1318
|
+
@note: Uses C{math.fma} in Python 3.13+, provided C{self},
|
|
1319
|
+
B{C{other1}} and B{C{other2}} are all C{scalar}.
|
|
1320
|
+
'''
|
|
1321
|
+
if len(self._ps) == 1 and isscalar(other1, both=True) \
|
|
1322
|
+
and isscalar(other2, both=True):
|
|
1323
|
+
p = _fma(self._ps[0], other1, other2)
|
|
1324
|
+
self._ps[:] = self._finite(p, self.fma.__name__),
|
|
1325
|
+
if other2:
|
|
1326
|
+
self._n += 1
|
|
1327
|
+
else:
|
|
1328
|
+
self._f2mul(self.fma.__name__, other1)
|
|
1329
|
+
self += other2
|
|
1330
|
+
return self
|
|
1331
|
+
|
|
1332
|
+
# def _fma_scalar(self, op, x, *ys): # in .karney
|
|
1333
|
+
# '''(INTERNAL) Apply C{self.fma(B{x}, B{y}) for B{y} in B{ys}}
|
|
1334
|
+
# for scalar C{x} and C{y}s.
|
|
1335
|
+
# '''
|
|
1336
|
+
# ps = self._ps
|
|
1337
|
+
# if ps and ys:
|
|
1338
|
+
# for y in ys:
|
|
1339
|
+
# ps[:] = self._ps_acc(list(y), _2products(x, _2split3s(ps)))
|
|
1340
|
+
# for p in (ps if op else()):
|
|
1341
|
+
# self._finite(p, op)
|
|
1342
|
+
# return self
|
|
1343
|
+
|
|
1225
1344
|
fmul = __imul__
|
|
1226
1345
|
|
|
1227
1346
|
def _fmul(self, other, op):
|
|
@@ -1232,6 +1351,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1232
1351
|
f = self._mul_Fsum(other, op)
|
|
1233
1352
|
elif len(other._ps) != 1: # and len(self._ps) == 1
|
|
1234
1353
|
f = other._mul_scalar(self._ps[0], op)
|
|
1354
|
+
elif self._f2product: # len(other._ps) == 1
|
|
1355
|
+
f = self._mul_scalar(other._ps[0], op)
|
|
1235
1356
|
else: # len(other._ps) == len(self._ps) == 1
|
|
1236
1357
|
f = self._finite(self._ps[0] * other._ps[0])
|
|
1237
1358
|
else:
|
|
@@ -1239,6 +1360,29 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1239
1360
|
f = self._mul_scalar(s, op)
|
|
1240
1361
|
return self._fset(f) # n=len(self) + 1
|
|
1241
1362
|
|
|
1363
|
+
def f2mul(self, *others):
|
|
1364
|
+
'''Apply C{B{self} *= B{other} for B{other} in B{others}} where each B{other}
|
|
1365
|
+
is C{scalar}, an L{Fsum} or L{Fsum2Tuple} applying accurate multiplication
|
|
1366
|
+
as if L{f2product<Fsum.f2product>}C{=True}.
|
|
1367
|
+
|
|
1368
|
+
@see: U{Equations 2.3<https://www.TUHH.De/ti3/paper/rump/OzOgRuOi06.pdf>}
|
|
1369
|
+
'''
|
|
1370
|
+
return self._f2mul(self.f2mul.__name__, *others)
|
|
1371
|
+
|
|
1372
|
+
def _f2mul(self, op, *others):
|
|
1373
|
+
'''(INTERNAL) See method C{f2mul}.
|
|
1374
|
+
'''
|
|
1375
|
+
P = _Psum(self._ps)
|
|
1376
|
+
ps = P._ps
|
|
1377
|
+
if ps and others:
|
|
1378
|
+
for p in self._ps_other(op, *others):
|
|
1379
|
+
pfs = _2products(p, _2split3s(ps))
|
|
1380
|
+
ps[:] = P._ps_acc([], pfs, up=False)
|
|
1381
|
+
for p in ps:
|
|
1382
|
+
self._finite(p, op)
|
|
1383
|
+
self._fset(P, op=op)
|
|
1384
|
+
return self
|
|
1385
|
+
|
|
1242
1386
|
def fover(self, over, **raiser_RESIDUAL):
|
|
1243
1387
|
'''Apply C{B{self} /= B{over}} and summate.
|
|
1244
1388
|
|
|
@@ -1276,6 +1420,24 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1276
1420
|
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1277
1421
|
return self._fset(f) # n=max(len(self), 1)
|
|
1278
1422
|
|
|
1423
|
+
def f2product(self, *two):
|
|
1424
|
+
'''Turn this instance' accurate I{TwoProduct} multiplication or or off.
|
|
1425
|
+
|
|
1426
|
+
@arg two: If C{True}, turn I{TwoProduct} on, if C{False} off or if
|
|
1427
|
+
C{None} or if omitted, keep the current setting.
|
|
1428
|
+
|
|
1429
|
+
@return: The previous C{f2product} setting (C{bool}).
|
|
1430
|
+
|
|
1431
|
+
@see: On Python 3.13 and later I{TwoProduct} is based on I{TwoProductFMA}
|
|
1432
|
+
U{Algorithm 3.5<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
1433
|
+
otherwise on the slower I{TwoProduct} and I{Split} U{Algorithms
|
|
1434
|
+
3.3 and 3.2<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}.
|
|
1435
|
+
'''
|
|
1436
|
+
t = self._f2product
|
|
1437
|
+
if two and two[0] is not None:
|
|
1438
|
+
self._f2product = bool(two[0])
|
|
1439
|
+
return t
|
|
1440
|
+
|
|
1279
1441
|
@Property
|
|
1280
1442
|
def _fprs(self):
|
|
1281
1443
|
'''(INTERNAL) Get and cache this instance' precision
|
|
@@ -1834,10 +1996,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1834
1996
|
def _pfs(ps, fs):
|
|
1835
1997
|
if len(ps) < len(fs):
|
|
1836
1998
|
ps, fs = fs, ps
|
|
1999
|
+
if self._f2product:
|
|
2000
|
+
ps = tuple(_2split3s(ps))
|
|
2001
|
+
_xys = _2products
|
|
2002
|
+
else:
|
|
2003
|
+
def _xys(x, ys):
|
|
2004
|
+
return (x * y for y in ys)
|
|
2005
|
+
|
|
1837
2006
|
_fin = _isfinite
|
|
1838
2007
|
for f in fs:
|
|
1839
|
-
for p in ps:
|
|
1840
|
-
p *= f
|
|
2008
|
+
for p in _xys(f, ps):
|
|
1841
2009
|
yield p if _fin(p) else self._finite(p, op)
|
|
1842
2010
|
|
|
1843
2011
|
return Fsum()._facc_scalar(_pfs(self._ps, factors), up=False)
|
|
@@ -1849,6 +2017,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1849
2017
|
for p in self._ps:
|
|
1850
2018
|
yield -p
|
|
1851
2019
|
|
|
2020
|
+
def _ps_other(self, op, *others):
|
|
2021
|
+
'''(INTERNAL) Yield the partials of all C{other}s.
|
|
2022
|
+
'''
|
|
2023
|
+
for other in others:
|
|
2024
|
+
if _isFsumTuple(other):
|
|
2025
|
+
for p in other._ps:
|
|
2026
|
+
yield p
|
|
2027
|
+
else:
|
|
2028
|
+
yield self._scalar(other, op)
|
|
2029
|
+
|
|
1852
2030
|
def _ps_1sum(self, *less):
|
|
1853
2031
|
'''(INTERNAL) Return the partials sum, 1-primed C{less} some scalars.
|
|
1854
2032
|
'''
|
|
@@ -1970,8 +2148,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1970
2148
|
def signOf(self, res=True):
|
|
1971
2149
|
'''Determine the sign of this instance.
|
|
1972
2150
|
|
|
1973
|
-
@kwarg res: If C{True} consider, otherwise
|
|
1974
|
-
|
|
2151
|
+
@kwarg res: If C{True}, consider, otherwise ignore
|
|
2152
|
+
the residual (C{bool}).
|
|
1975
2153
|
|
|
1976
2154
|
@return: The sign (C{int}, -1, 0 or +1).
|
|
1977
2155
|
'''
|
|
@@ -1992,7 +2170,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1992
2170
|
def toStr(self, lenc=True, **prec_sep_fmt): # PYCHOK signature
|
|
1993
2171
|
'''Return this C{Fsum} instance as string.
|
|
1994
2172
|
|
|
1995
|
-
@kwarg lenc: If C{True} include the current C{[len]} of this
|
|
2173
|
+
@kwarg lenc: If C{True}, include the current C{[len]} of this
|
|
1996
2174
|
L{Fsum} enclosed in I{[brackets]} (C{bool}).
|
|
1997
2175
|
@kwarg prec_sep_fmt: Optional keyword arguments for method
|
|
1998
2176
|
L{Fsum2Tuple.toStr}.
|
|
@@ -2034,6 +2212,15 @@ def _Float_Int(arg, **name_Error):
|
|
|
2034
2212
|
return U(arg, **name_Error)
|
|
2035
2213
|
|
|
2036
2214
|
|
|
2215
|
+
def Fsum2product(*xs, **name_RESIDUAL):
|
|
2216
|
+
'''Return an L{Fsum} with L{f2product<Fsum.f2product>} accurate
|
|
2217
|
+
multiplication I{turned on}.
|
|
2218
|
+
'''
|
|
2219
|
+
F = Fsum(*xs, **name_RESIDUAL)
|
|
2220
|
+
F.f2product(True)
|
|
2221
|
+
return F
|
|
2222
|
+
|
|
2223
|
+
|
|
2037
2224
|
class DivMod2Tuple(_NamedTuple):
|
|
2038
2225
|
'''2-Tuple C{(div, mod)} with the quotient C{div} and remainder
|
|
2039
2226
|
C{mod} results of a C{divmod} operation.
|
pygeodesy/gars.py
CHANGED
|
@@ -18,8 +18,9 @@ Transcoded from I{Charles Karney}'s C++ class U{GARS
|
|
|
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
|
-
|
|
21
|
+
from pygeodesy.interns import NN, _0to9_, _AtoZnoIO_, _COMMA_, \
|
|
22
|
+
_INV_, _SPACE_
|
|
23
|
+
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
|
|
23
24
|
from pygeodesy.named import _name__, Fmt, isstr, Property_RO
|
|
24
25
|
from pygeodesy.namedTuples import LatLon2Tuple, LatLonPrec3Tuple
|
|
25
26
|
# from pygeodesy.props import Property_RO # from .named
|
|
@@ -29,7 +30,7 @@ from pygeodesy.units import Int_, Lat, Lon, Precision_, Scalar_, Str
|
|
|
29
30
|
from math import floor
|
|
30
31
|
|
|
31
32
|
__all__ = _ALL_LAZY.gars
|
|
32
|
-
__version__ = '24.08.
|
|
33
|
+
__version__ = '24.08.13'
|
|
33
34
|
|
|
34
35
|
_Digits = _0to9_
|
|
35
36
|
_LatLen = 2
|
|
@@ -86,7 +87,7 @@ def _2garstr2(garef):
|
|
|
86
87
|
try:
|
|
87
88
|
n, garstr = len(garef), garef.upper()
|
|
88
89
|
if n < _MinLen or n > _MaxLen \
|
|
89
|
-
or garstr
|
|
90
|
+
or garstr.startswith(_INV_) \
|
|
90
91
|
or not garstr.isalnum():
|
|
91
92
|
raise ValueError()
|
|
92
93
|
return garstr, _2Precision(n - _MinLen)
|
|
@@ -200,8 +201,8 @@ def decode3(garef, center=True, **name):
|
|
|
200
201
|
'''Decode a C{garef} to lat-, longitude and precision.
|
|
201
202
|
|
|
202
203
|
@arg garef: To be decoded (L{Garef} or C{str}).
|
|
203
|
-
@kwarg center: If C{True} the center, otherwise
|
|
204
|
-
lower-left corner (C{bool}).
|
|
204
|
+
@kwarg center: If C{True}, use the garef's center, otherwise
|
|
205
|
+
the south-west, lower-left corner (C{bool}).
|
|
205
206
|
|
|
206
207
|
@return: A L{LatLonPrec3Tuple}C{(lat, lon, precision)}.
|
|
207
208
|
|
|
@@ -339,8 +340,8 @@ def resolution(prec):
|
|
|
339
340
|
return _Resolutions[max(0, min(p, _MaxPrec))]
|
|
340
341
|
|
|
341
342
|
|
|
342
|
-
__all__ +=
|
|
343
|
-
|
|
343
|
+
__all__ += _ALL_DOCS(decode3, # functions
|
|
344
|
+
encode, precision, resolution)
|
|
344
345
|
|
|
345
346
|
# **) MIT License
|
|
346
347
|
#
|
pygeodesy/geodesici.py
CHANGED
|
@@ -28,8 +28,9 @@ from __future__ import division as _; del _ # PYCHOK semicolon
|
|
|
28
28
|
from pygeodesy.basics import _copy, _enumereverse, map1, \
|
|
29
29
|
_xinstanceof, _xor
|
|
30
30
|
from pygeodesy.constants import EPS, INF, INT0, PI, PI2, PI_4, \
|
|
31
|
-
_0_0, _0_5, _1_0, _1_5, _2_0,
|
|
32
|
-
_90_0, isfinite
|
|
31
|
+
_0_0, _0_5, _1_0, _1_5, _2_0, \
|
|
32
|
+
_3_0, _64_0, _90_0, isfinite, \
|
|
33
|
+
_EPSjam # PYCHOK used!
|
|
33
34
|
from pygeodesy.ellipsoids import _EWGS84, Fmt, unstr
|
|
34
35
|
from pygeodesy.errors import GeodesicError, IntersectionError, _an, \
|
|
35
36
|
_xgeodesics, _xkwds_get, _xkwds_kwds, \
|
|
@@ -56,7 +57,7 @@ from pygeodesy.utily import sincos2, atan2, fabs, radians
|
|
|
56
57
|
# from math import atan2, ceil as _ceil, fabs, radians # .fsums, .utily
|
|
57
58
|
|
|
58
59
|
__all__ = _ALL_LAZY.geodesici
|
|
59
|
-
__version__ = '24.
|
|
60
|
+
__version__ = '24.08.28'
|
|
60
61
|
|
|
61
62
|
_0t = 0, # int
|
|
62
63
|
_1_1t = -1, +1
|
|
@@ -1237,7 +1238,7 @@ class Intersector(_IntersectBase):
|
|
|
1237
1238
|
return sx, zx, sAx, sBx
|
|
1238
1239
|
|
|
1239
1240
|
def _polarB3(self, lats=False): # PYCHOK no cover
|
|
1240
|
-
latx =
|
|
1241
|
+
latx = _64_0
|
|
1241
1242
|
lat = _90_0 - latx
|
|
1242
1243
|
if self.f:
|
|
1243
1244
|
_d, _pD2 = fdot, self._polarDist2
|
|
@@ -1393,7 +1394,7 @@ class Intersector(_IntersectBase):
|
|
|
1393
1394
|
|
|
1394
1395
|
@Property_RO
|
|
1395
1396
|
def _Tol(self): # convergence tolerance
|
|
1396
|
-
return self._cHalf *
|
|
1397
|
+
return self._cHalf * _EPSjam
|
|
1397
1398
|
|
|
1398
1399
|
def toStr(self, **prec_sep_name): # PYCHOK signature
|
|
1399
1400
|
'''Return this C{Intersector} as string.
|
pygeodesy/geodesicx/_C4_24.py
CHANGED
|
@@ -13,7 +13,7 @@ U{GeographicLib<https://GeographicLib.SourceForge.io>} documentation.
|
|
|
13
13
|
from pygeodesy.geodesicx.gxbases import _Gfloats, _f, _f2
|
|
14
14
|
|
|
15
15
|
__all__ = ()
|
|
16
|
-
__version__ = '
|
|
16
|
+
__version__ = '24.09.04'
|
|
17
17
|
|
|
18
18
|
_g = _Gfloats(24)
|
|
19
19
|
_coeffs_24 = _g(( # GEOGRAPHICLIB_GEODESICEXACT_ORDER == 24
|
|
@@ -1672,8 +1672,6 @@ _coeffs_24 = _g(( # GEOGRAPHICLIB_GEODESICEXACT_ORDER == 24
|
|
|
1672
1672
|
# C4[23], coeff of eps^23, polynomial in n of order 0
|
|
1673
1673
|
_f(1 << 41), _f(0xc5e28ed2c935ab), # PYCHOK exported
|
|
1674
1674
|
)) # 2900 / 2708
|
|
1675
|
-
if __name__ == '__main__':
|
|
1676
|
-
_g.prints()
|
|
1677
1675
|
del _g, _Gfloats, _f, _f2
|
|
1678
1676
|
|
|
1679
1677
|
# **) MIT License
|
pygeodesy/geodesicx/_C4_27.py
CHANGED
|
@@ -13,7 +13,7 @@ U{GeographicLib<https://GeographicLib.SourceForge.io>} documentation.
|
|
|
13
13
|
from pygeodesy.geodesicx.gxbases import _Gfloats, _f, _f2
|
|
14
14
|
|
|
15
15
|
__all__ = ()
|
|
16
|
-
__version__ = '
|
|
16
|
+
__version__ = '24.09.04'
|
|
17
17
|
|
|
18
18
|
_g = _Gfloats(27)
|
|
19
19
|
_coeffs_27 = _g(( # GEOGRAPHICLIB_GEODESICEXACT_ORDER == 27
|
|
@@ -2368,8 +2368,6 @@ _coeffs_27 = _g(( # GEOGRAPHICLIB_GEODESICEXACT_ORDER == 27
|
|
|
2368
2368
|
# C4[26], coeff of eps^26, polynomial in n of order 0
|
|
2369
2369
|
_f(1 << 48), _f2(2126, 0x8c0e9e949456f), # PYCHOK exported
|
|
2370
2370
|
)) # 4032 / 3764
|
|
2371
|
-
if __name__ == '__main__':
|
|
2372
|
-
_g.prints()
|
|
2373
2371
|
del _g, _Gfloats, _f, _f2
|
|
2374
2372
|
|
|
2375
2373
|
# **) MIT License
|
pygeodesy/geodesicx/_C4_30.py
CHANGED
|
@@ -30,7 +30,7 @@ U{GeographicLib<https://GeographicLib.SourceForge.io>} documentation.
|
|
|
30
30
|
from pygeodesy.geodesicx.gxbases import _Gfloats, _f, _f2
|
|
31
31
|
|
|
32
32
|
__all__ = ()
|
|
33
|
-
__version__ = '
|
|
33
|
+
__version__ = '24.09.04'
|
|
34
34
|
|
|
35
35
|
_g = _Gfloats(30)
|
|
36
36
|
_coeffs_30 = _g(( # GEOGRAPHICLIB_GEODESICEXACT_ORDER == 30
|
|
@@ -3273,8 +3273,6 @@ _coeffs_30 = _g(( # GEOGRAPHICLIB_GEODESICEXACT_ORDER == 30
|
|
|
3273
3273
|
# C4[29], coeff of eps^29, polynomial in n of order 0
|
|
3274
3274
|
_f(1 << 53), _f2(88602, 0xec373d36a45df), # PYCHOK exported
|
|
3275
3275
|
)) # 5425 / 5107
|
|
3276
|
-
if __name__ == '__main__':
|
|
3277
|
-
_g.prints()
|
|
3278
3276
|
del _g, _Gfloats, _f, _f2
|
|
3279
3277
|
|
|
3280
3278
|
|
pygeodesy/geodesicx/__init__.py
CHANGED
pygeodesy/geodesicx/__main__.py
CHANGED
|
@@ -5,65 +5,63 @@ u'''Print L{geodesicx} version, etc. using C{python -m pygeodesy.geodesicx}.
|
|
|
5
5
|
'''
|
|
6
6
|
|
|
7
7
|
__all__ = ()
|
|
8
|
-
__version__ = '24.
|
|
8
|
+
__version__ = '24.09.06'
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def
|
|
12
|
-
'''(INTERNAL) Get the C{C4} stats.
|
|
13
|
-
'''
|
|
14
|
-
from pygeodesy import GeodesicExact, geodesicx
|
|
15
|
-
|
|
16
|
-
gX = GeodesicExact(C4order=nC4)
|
|
17
|
-
cs = geodesicx.gx._C4coeffs(gX.C4order)
|
|
18
|
-
ss = set(cs) # without duplicates
|
|
19
|
-
pc = '%.1f%%' % (len(ss) * 100.0 / len(cs))
|
|
20
|
-
cx = gX._C4x
|
|
21
|
-
return dict(C4order=gX.C4order, C4len=len(cs), C4set=len(ss), C4set_len=pc, C4x=len(cx))
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _main(): # PYCHOK no cover
|
|
25
|
-
|
|
26
|
-
import os.path as os_path
|
|
11
|
+
def _main(**C4order): # PYCHOK no cover
|
|
27
12
|
|
|
28
13
|
try:
|
|
29
|
-
from pygeodesy import
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
from pygeodesy.interns import _COMMASPACE_,
|
|
33
|
-
from pygeodesy.streprs import Fmt
|
|
34
|
-
|
|
35
|
-
def _dot_attr(name, value):
|
|
36
|
-
return Fmt.DOT(Fmt.EQUAL(name, value))
|
|
37
|
-
|
|
38
|
-
s = tuple(sorted(_C4stats().items()))
|
|
39
|
-
p = [_dot_attr(*t) for t in (((_version_, _gx.__version__),) + s)]
|
|
40
|
-
|
|
41
|
-
def _name_version(pkg):
|
|
42
|
-
return _SPACE_(pkg.__name__, pkg.__version__)
|
|
43
|
-
|
|
44
|
-
v = _Pythonarchine()
|
|
14
|
+
from pygeodesy import GeodesicExact, geodesicx
|
|
15
|
+
from pygeodesy.internals import _fper, _name_version, \
|
|
16
|
+
printf, _sizeof, _versions
|
|
17
|
+
from pygeodesy.interns import _COMMASPACE_, _EQUAL_
|
|
45
18
|
try:
|
|
46
|
-
import
|
|
47
|
-
v.append(_name_version(geographiclib))
|
|
19
|
+
import numpy
|
|
48
20
|
except ImportError:
|
|
49
|
-
|
|
21
|
+
numpy = None
|
|
22
|
+
|
|
23
|
+
gX = GeodesicExact(**C4order)
|
|
24
|
+
cs = geodesicx.gx._C4coeffs(gX.C4order)
|
|
25
|
+
n = len(cs)
|
|
26
|
+
u = n if numpy else len(set(cs))
|
|
27
|
+
z = cs.nbytes if numpy else _sizeof(cs)
|
|
28
|
+
p = dict(C4order=gX.C4order, C4n=n, C4u=u,
|
|
29
|
+
C4u_n=_fper(u, n), C4x=len(gX._C4x),
|
|
30
|
+
C4t=type(cs).__name__, C4z=z)
|
|
31
|
+
p = list(_EQUAL_(*t) for t in p.items())
|
|
32
|
+
if numpy:
|
|
33
|
+
p.append(_name_version(numpy))
|
|
50
34
|
try:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
except
|
|
35
|
+
import geographiclib
|
|
36
|
+
p.append(_name_version(geographiclib))
|
|
37
|
+
except ImportError:
|
|
54
38
|
pass
|
|
55
39
|
|
|
56
|
-
g =
|
|
57
|
-
|
|
58
|
-
if not g.startswith(x):
|
|
59
|
-
g = _DOT_(x, g)
|
|
60
|
-
printf('%s%s (%s)', g, _COMMASPACE_.join(p), _COMMASPACE_.join(v))
|
|
40
|
+
g = _name_version(geodesicx)
|
|
41
|
+
printf('%s: %s (%s)', g, _COMMASPACE_.join(p), _versions())
|
|
61
42
|
|
|
62
43
|
except ImportError:
|
|
63
|
-
|
|
44
|
+
from pygeodesy.internals import _usage
|
|
45
|
+
print(_usage(__file__))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
from sys import argv # .internals._isPyChecker
|
|
49
|
+
_main(C4order=int(argv[1])) if len(argv) == 2 and argv[1].isdigit() else _main()
|
|
50
|
+
|
|
51
|
+
# % python3.13 -m pygeodesy.geodesicx 30
|
|
52
|
+
# pygeodesy.geodesicx 24.09.06: C4order=30, C4n=5425, C4u=5107, C4u_n=94.1%, C4x=465, C4t=tuple, C4z=166008 (pygeodesy 24.9.6 Python 3.13.0rc1 64bit arm64 macOS 14.6.1)
|
|
53
|
+
# % python3.12 -m pygeodesy.geodesicx 30
|
|
54
|
+
# pygeodesy.geodesicx 24.09.06: C4order=30, C4n=5425, C4u=5425, C4u_n=100.0%, C4x=465, C4t=ndarray, C4z=43400, numpy 2.1.0, geographiclib 2.0 (pygeodesy 24.9.6 Python 3.12.5 64bit arm64 macOS 14.6.1)
|
|
64
55
|
|
|
56
|
+
# % python3.13 -m pygeodesy.geodesicx 27
|
|
57
|
+
# pygeodesy.geodesicx 24.09.06: C4order=27, C4n=4032, C4u=3764, C4u_n=93.4%, C4x=378, C4t=tuple, C4z=122632 (pygeodesy 24.9.6 Python 3.13.0rc1 64bit arm64 macOS 14.6.1)
|
|
58
|
+
# % python3.12 -m pygeodesy.geodesicx 27
|
|
59
|
+
# pygeodesy.geodesicx 24.09.06: C4order=27, C4n=4032, C4u=4032, C4u_n=100.0%, C4x=378, C4t=ndarray, C4z=32256, numpy 2.1.0, geographiclib 2.0 (pygeodesy 24.9.6 Python 3.12.5 64bit arm64 macOS 14.6.1)
|
|
65
60
|
|
|
66
|
-
|
|
61
|
+
# % python3.13 -m pygeodesy.geodesicx 24
|
|
62
|
+
# pygeodesy.geodesicx 24.09.06: C4order=24, C4n=2900, C4u=2708, C4u_n=93.4%, C4x=300, C4t=tuple, C4z=88232 (pygeodesy 24.9.6 Python 3.13.0rc1 64bit arm64 macOS 14.6.1)
|
|
63
|
+
# % python3.12 -m pygeodesy.geodesicx 24
|
|
64
|
+
# pygeodesy.geodesicx 24.09.06: C4order=24, C4n=2900, C4u=2900, C4u_n=100.0%, C4x=300, C4t=ndarray, C4z=23200, numpy 2.1.0, geographiclib 2.0 (pygeodesy 24.9.6 Python 3.12.5 64bit arm64 macOS 14.6.1)
|
|
67
65
|
|
|
68
66
|
# **) MIT License
|
|
69
67
|
#
|
pygeodesy/geodesicx/gx.py
CHANGED
|
@@ -63,7 +63,7 @@ from pygeodesy.utily import atan2d as _atan2d_reverse, _unrollon, _Wrap, wrap360
|
|
|
63
63
|
from math import atan2, copysign, cos, degrees, fabs, radians, sqrt
|
|
64
64
|
|
|
65
65
|
__all__ = ()
|
|
66
|
-
__version__ = '24.
|
|
66
|
+
__version__ = '24.08.13'
|
|
67
67
|
|
|
68
68
|
_MAXIT1 = 20
|
|
69
69
|
_MAXIT2 = 10 + _MAXIT1 + MANT_DIG # MANT_DIG == C++ digits
|
|
@@ -218,8 +218,8 @@ class GeodesicExact(_GeodesicBase):
|
|
|
218
218
|
'''Set up a L{GeodesicAreaExact} to compute area and
|
|
219
219
|
perimeter of a polygon.
|
|
220
220
|
|
|
221
|
-
@kwarg polyline: If C{True} perimeter only, otherwise
|
|
222
|
-
|
|
221
|
+
@kwarg polyline: If C{True}, compute the perimeter only, otherwise
|
|
222
|
+
the perimeter and area (C{bool}).
|
|
223
223
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
224
224
|
|
|
225
225
|
@return: A L{GeodesicAreaExact} instance.
|
pygeodesy/geodesicx/gxarea.py
CHANGED
|
@@ -21,7 +21,7 @@ from pygeodesy.basics import isodd, unsigned0
|
|
|
21
21
|
from pygeodesy.constants import NAN, _0_0, _0_5, _720_0
|
|
22
22
|
# from pygeodesy.interns import _COMMASPACE_ # from .lazily
|
|
23
23
|
from pygeodesy.karney import Area3Tuple, _diff182, GeodesicError, \
|
|
24
|
-
_norm180, _remainder,
|
|
24
|
+
_norm180, _remainder, _sum3
|
|
25
25
|
from pygeodesy.lazily import _ALL_DOCS, printf, _COMMASPACE_
|
|
26
26
|
from pygeodesy.named import ADict, callername, _NamedBase, pairs
|
|
27
27
|
from pygeodesy.props import Property, Property_RO, property_RO
|
|
@@ -30,7 +30,7 @@ from pygeodesy.props import Property, Property_RO, property_RO
|
|
|
30
30
|
from math import fmod as _fmod
|
|
31
31
|
|
|
32
32
|
__all__ = ()
|
|
33
|
-
__version__ = '24.
|
|
33
|
+
__version__ = '24.09.04'
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class GeodesicAreaExact(_NamedBase):
|
|
@@ -413,8 +413,8 @@ class PolygonArea(GeodesicAreaExact):
|
|
|
413
413
|
|
|
414
414
|
@arg earth: A geodesic (L{GeodesicExact}, I{wrapped}
|
|
415
415
|
C{Geodesic} or L{GeodesicSolve}).
|
|
416
|
-
@kwarg polyline: If C{True} perimeter only, otherwise
|
|
417
|
-
|
|
416
|
+
@kwarg polyline: If C{True}, compute the perimeter only, otherwise
|
|
417
|
+
perimeter and area (C{bool}).
|
|
418
418
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
419
419
|
|
|
420
420
|
@raise GeodesicError: Invalid B{C{earth}}.
|
|
@@ -451,7 +451,7 @@ class _Accumulator(_NamedBase):
|
|
|
451
451
|
@return: Current C{sum}.
|
|
452
452
|
'''
|
|
453
453
|
self._n += 1
|
|
454
|
-
self._s, self._t =
|
|
454
|
+
self._s, self._t, _ = _sum3(self._s, self._t, y)
|
|
455
455
|
return self._s # current .Sum()
|
|
456
456
|
|
|
457
457
|
def Negate(self):
|