pygeodesy 24.4.2__py2.py3-none-any.whl → 24.4.4__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.4.2.dist-info → PyGeodesy-24.4.4.dist-info}/METADATA +5 -5
- {PyGeodesy-24.4.2.dist-info → PyGeodesy-24.4.4.dist-info}/RECORD +11 -11
- pygeodesy/__init__.py +4 -4
- pygeodesy/basics.py +16 -5
- pygeodesy/constants.py +2 -2
- pygeodesy/fmath.py +45 -49
- pygeodesy/fsums.py +147 -100
- pygeodesy/resections.py +6 -5
- pygeodesy/utily.py +11 -10
- {PyGeodesy-24.4.2.dist-info → PyGeodesy-24.4.4.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.4.2.dist-info → PyGeodesy-24.4.4.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyGeodesy
|
|
3
|
-
Version: 24.4.
|
|
3
|
+
Version: 24.4.4
|
|
4
4
|
Summary: Pure Python geodesy tools
|
|
5
5
|
Home-page: https://GitHub.com/mrJean1/PyGeodesy
|
|
6
6
|
Author: Jean M. Brouwers
|
|
@@ -118,7 +118,7 @@ The tests ran with Python 3.12.2 (with geographiclib_ 2.0), 3.11.5 (with geograp
|
|
|
118
118
|
1.24.2 and scipy_ 1.10.1), Python 3.10.8 (with geographiclib_ 2.0, numpy_ 1.23.3, scipy_ 1.9.1,
|
|
119
119
|
GeoConvert_ 2.2, GeodSolve_ 2.2 and RhumbSolve_ 2.2), Python 3.9.6 and Python 2.7.18 (with geographiclib_
|
|
120
120
|
1.50, numpy_ 1.16.6, scipy_ 1.2.2, GeoConvert_ 2.2, GeodSolve_ 2.2 and RhumbSolve_ 2.2), all on macOS
|
|
121
|
-
14.
|
|
121
|
+
14.4.1 Sonoma and in 64-bit only.
|
|
122
122
|
|
|
123
123
|
All tests ran with and without ``lazy import`` for Python 3 and with command line option ``-W default``
|
|
124
124
|
and env variable ``PYGEODESY_WARNINGS=on`` for all Python versions. The results of those tests are
|
|
@@ -143,7 +143,7 @@ numpy_ 1.16.3, 1.16.4, 1.16.6, 1.19.0, 1.19.4, 1.19.5 or 1.22.4 and scipy_ 1.2.1
|
|
|
143
143
|
on `Ubuntu 16.04`_, with Python 3.10.0-1, 3.9.0-5, 3.8.0-6, 3.7.2-6, 3.7.0, 3.6.2-5, 3.5.3, 2.7.13-17,
|
|
144
144
|
2.7.10 and 2.6.9 (and numpy_ 1.19.0, 1.16.5, 1.16.2, 1.15.2, 1.14.0, 1.13.1, 1.8.0rc1 or 1.6.2 and scipy_
|
|
145
145
|
1.5.0), PyPy_ 7.3.0 (Python 2.7.13 and 3.6.9), PyPy_ 6.0.0 (Python 2.7.13 and 3.5.3) and `Intel-Python`_
|
|
146
|
-
3.5.3 (and numpy_ 1.11.3) on macOS 14.0-
|
|
146
|
+
3.5.3 (and numpy_ 1.11.3) on macOS 14.0-3.1 Sonoma, 13.0-5.2 Ventura, 12.1-6 Monterey, 11.0-5.2-6.1 Big
|
|
147
147
|
Sur (aka 10.16), 10.15.3, 10.15.5-7 Catalina, 10.14 Mojave, 10.13.6 High Sierra and 10.12 Sierra, MacOS X
|
|
148
148
|
10.11 El Capitan and/or MacOS X 10.10 Yosemite, with Pythonista_ 3.2 (with geographiclib 1.50 or 1.49 and
|
|
149
149
|
numpy 1.8.0) on iOS 14.4.2, 11.4.1, 12.0-3 on iPad4, iPhone6, iPhone10 and/or iPhone12, with Pythonista_
|
|
@@ -154,11 +154,11 @@ Notes
|
|
|
154
154
|
=====
|
|
155
155
|
|
|
156
156
|
All Python source code has been statically checked_ with PyChecker_, PyFlakes_, PyCodeStyle_ (formerly Pep8)
|
|
157
|
-
and McCabe_ using Python 2.7.18 and with Flake8_ using Python 3.11.5, both in 64-bit on macOS 14.
|
|
157
|
+
and McCabe_ using Python 2.7.18 and with Flake8_ using Python 3.11.5, both in 64-bit on macOS 14.4.1 Sonoma.
|
|
158
158
|
|
|
159
159
|
For a summary of all *Karney*-based functionality in ``pygeodesy``, see module karney_.
|
|
160
160
|
|
|
161
|
-
*Last updated: April
|
|
161
|
+
*Last updated: April 04, 2024.*
|
|
162
162
|
|
|
163
163
|
License
|
|
164
164
|
=======
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
pygeodesy/LICENSE,sha256=YfgAiyxOwY6P9Kkb1_5XN81nueTLrpb3Ffkv3EuPgFU,1144
|
|
2
|
-
pygeodesy/__init__.py,sha256=
|
|
2
|
+
pygeodesy/__init__.py,sha256=3Zu_6m7CtOUuHraPspTn-gTN03b8oW_SyNpfhSibkTI,40824
|
|
3
3
|
pygeodesy/__main__.py,sha256=qMFG3caY8ZXWu6uGiemzyT4OqTFZnsFtlxcGCAgkVJw,4637
|
|
4
4
|
pygeodesy/albers.py,sha256=UpWNezHXFuA_kT5PhH_2V_gGFJjcmVLLogl5ScJloPU,31098
|
|
5
5
|
pygeodesy/azimuthal.py,sha256=e796vtU5ol5ZG2yBX3E5YBXsONJuCrhyEX60YzGzFi0,50115
|
|
6
|
-
pygeodesy/basics.py,sha256=
|
|
6
|
+
pygeodesy/basics.py,sha256=_BMYLzGKA6OIS3qv25HfHy7MIh0kAbmkzyScb59clUs,28160
|
|
7
7
|
pygeodesy/booleans.py,sha256=HZbwoL-S7Ww9d4C2D1BVqXfmcuqqVpEVSU9_S0uyUyo,74204
|
|
8
8
|
pygeodesy/cartesianBase.py,sha256=I3q29mRdBB3NCDmPoJsJ0QOFfLzkdMWc8X9zG4IwJyA,47264
|
|
9
9
|
pygeodesy/clipy.py,sha256=VU3ynQ1IZ0v5hJlicqD48oW0imRgiL5_ZzRPrIjpfPw,27683
|
|
10
|
-
pygeodesy/constants.py,sha256=
|
|
10
|
+
pygeodesy/constants.py,sha256=ypxYsWB6tNAVgrD9QVpukJAPscaLgHtPLqPuot1gUfU,19174
|
|
11
11
|
pygeodesy/css.py,sha256=sKXsahUiyruDcUk-tGjA6mxq-xzwBoBKxKo9_b2uBmY,25394
|
|
12
12
|
pygeodesy/datums.py,sha256=gJZPgV4bELZvZ8Sj2zE3MBysVtsLxqsN8zm0xjOKvpo,33851
|
|
13
13
|
pygeodesy/dms.py,sha256=op3MU-59CoJQRdybnu21aVM9wtocd_-XFNAZFqmozSo,44439
|
|
@@ -25,11 +25,11 @@ pygeodesy/elliptic.py,sha256=n2R-3H1ruMnwBewEtn75ahjpgeEU93irzcvFxarCyPs,42393
|
|
|
25
25
|
pygeodesy/epsg.py,sha256=ldHoLWqJWR4FUiBVnDTtrI_e7TNjjtr9OkxDlri1g5E,8165
|
|
26
26
|
pygeodesy/errors.py,sha256=fRGrdnb81Y9KB4Y1ua1nvB9zuuiv8IL6c6YN_cb3kBo,27280
|
|
27
27
|
pygeodesy/etm.py,sha256=ADIMY8zxVu3cAiP9rUGj3Mq3LyO2C5w3ejdW2YY1eJ8,44583
|
|
28
|
-
pygeodesy/fmath.py,sha256=
|
|
28
|
+
pygeodesy/fmath.py,sha256=cmObX2axb8BfPyhaSDGFFVRs63kBP4ZWhWzGzPhl6OQ,30286
|
|
29
29
|
pygeodesy/formy.py,sha256=Rces4Q5ecED0WVfuI9mQzeyHE54LDowYfI6faBHpyeA,74536
|
|
30
30
|
pygeodesy/frechet.py,sha256=1tiLc6WZou8YVbizB0QisVhYH-VOP03pMZQ5GOAb9Dc,33527
|
|
31
31
|
pygeodesy/fstats.py,sha256=X79Qd8pL4R-kUIYN0CZDuA7L1UArtBFvWqaFoHASNqs,25605
|
|
32
|
-
pygeodesy/fsums.py,sha256=
|
|
32
|
+
pygeodesy/fsums.py,sha256=a2rhCX73eZbyiKYvk06T4q9l1QkGxYQ50T7N21oGRl8,68591
|
|
33
33
|
pygeodesy/gars.py,sha256=fCiWBJ4kOJxPfNOxadX-OzBGDXj7C9g02NuGHiZa_88,11342
|
|
34
34
|
pygeodesy/geodesicw.py,sha256=Rw1pmT8UabWsBKfecsd4VR5Ks3uMrhH8sufydJS_MMs,26901
|
|
35
35
|
pygeodesy/geodsolve.py,sha256=J75l_bbPPsPr4NZXm1hCASl9TrXAS5DSeufXYkz2Qzs,21863
|
|
@@ -53,7 +53,7 @@ pygeodesy/nvectorBase.py,sha256=vpuGECs038I-8z_MDFJ9gZMY_6Een-EG2Y_llRLpl-o,2879
|
|
|
53
53
|
pygeodesy/osgr.py,sha256=5JB6b_nvyZ6rFMlC7ZB45mvYtjc_aiLb4DPdeaui-KY,30995
|
|
54
54
|
pygeodesy/points.py,sha256=8LiAH1dMiNN6mLmBZAisI0VsccD9PSy97XhDtJUfBuw,64441
|
|
55
55
|
pygeodesy/props.py,sha256=ZnXRuSOkfkeJY3Of-iT06FNWZkTYgLZQBPBNF6aS0jE,21421
|
|
56
|
-
pygeodesy/resections.py,sha256=
|
|
56
|
+
pygeodesy/resections.py,sha256=WGGsWgN9LCcJ9YCo-lbgtuA9VqEWnYvoe3OFOJ4nYFk,43619
|
|
57
57
|
pygeodesy/simplify.py,sha256=FT3AzXiFjFfvwJ-X2q8iA9cQOUVdBT1vD_BIskM3gK8,25223
|
|
58
58
|
pygeodesy/solveBase.py,sha256=cBe3QQWEaJlPWUlXoiYo1eFMh4z6GDZbQyt8ZiwMfos,16687
|
|
59
59
|
pygeodesy/sphericalBase.py,sha256=sH2WwmY_RL0STyr1OhtCDKvGhO0Ks7o3V-MHLddpiHQ,31944
|
|
@@ -65,7 +65,7 @@ pygeodesy/triaxials.py,sha256=Yet0J9Fr4FbTEIL9_p3ziollRR3PzUN2-qt7Z9ZSODU,61537
|
|
|
65
65
|
pygeodesy/units.py,sha256=ofFTYc7mF9wOpfvpYHN83dGszMM18rTdsxfEXVzaIko,38705
|
|
66
66
|
pygeodesy/unitsBase.py,sha256=xRZlNlO7S47Mwy0FGBg_cefvB4fEtWFM5dAE-Nlw-NE,13111
|
|
67
67
|
pygeodesy/ups.py,sha256=07AG-Rb1D4EvmN3g-xk3ZxKzyaNYvOzztcyYbx7t8jc,23229
|
|
68
|
-
pygeodesy/utily.py,sha256=
|
|
68
|
+
pygeodesy/utily.py,sha256=jP82RmCPCVghxTQv4ZRuIS89afmsD-roz2iafHfyHXA,36128
|
|
69
69
|
pygeodesy/utm.py,sha256=0qF5Kjw8Wf9zxGWOaCF-LSweibat-EkHvvmy7dFO_KE,30981
|
|
70
70
|
pygeodesy/utmups.py,sha256=u2hlWSnmZKwR-ApgKw16R9p75sW_yaqQAmbcBUE8Zfg,13007
|
|
71
71
|
pygeodesy/utmupsBase.py,sha256=5mKmo2cGSCJM8Q5oRQ7tmGJgRTdIgRVncCwG_BqB030,18816
|
|
@@ -109,7 +109,7 @@ pygeodesy/rhumb/aux_.py,sha256=W4HkgoHAQz_aWaysfsmOA5010nCGvBfUs2Q-bymnHYU,16660
|
|
|
109
109
|
pygeodesy/rhumb/bases.py,sha256=ZZ4Ba0Cl45tQdfEquyQPSQdH2vXgemF3tCw6UuzHphs,53893
|
|
110
110
|
pygeodesy/rhumb/ekx.py,sha256=lF3tZ-ZY9fPJV8y1kgHW-7EOZCyb3gJr-kR-jj5Fbf8,23871
|
|
111
111
|
pygeodesy/rhumb/solve.py,sha256=NZfwx7xv5UriQs7A0c7ZhoxxVUeAT15UwXK_jtwEXQw,27802
|
|
112
|
-
PyGeodesy-24.4.
|
|
113
|
-
PyGeodesy-24.4.
|
|
114
|
-
PyGeodesy-24.4.
|
|
115
|
-
PyGeodesy-24.4.
|
|
112
|
+
PyGeodesy-24.4.4.dist-info/METADATA,sha256=pWgDCMFWPNFawFtWPa1q4SpV_5XDSJx4r5MvNyFpXjE,19365
|
|
113
|
+
PyGeodesy-24.4.4.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
114
|
+
PyGeodesy-24.4.4.dist-info/top_level.txt,sha256=cEQPatCXzKZqrivpULC5V5fuy9_V_bAwaP_gUGid7pQ,10
|
|
115
|
+
PyGeodesy-24.4.4.dist-info/RECORD,,
|
pygeodesy/__init__.py
CHANGED
|
@@ -133,7 +133,7 @@ U{geographiclib<https://PyPI.org/project/geographiclib>} 1.50, U{numpy<https://P
|
|
|
133
133
|
1.16.6, U{scipy<https://PyPI.org/project/scipy>} 1.2.2, U{GeoConvert
|
|
134
134
|
<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.2, U{GeodSolve
|
|
135
135
|
<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.2 and U{RhumbSolve
|
|
136
|
-
<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.2), all on macOS 14.
|
|
136
|
+
<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.2), all on macOS 14.4.1 Sonoma and
|
|
137
137
|
in 64-bit only.
|
|
138
138
|
|
|
139
139
|
All tests ran with and without C{lazy import} for Python 3 and with command line option C{-W default} and
|
|
@@ -164,7 +164,7 @@ Previously, the tests were run with Python 3.12.0-1, 3.11.2-4, 3.10.1-7, 3.9.1,
|
|
|
164
164
|
1.16.5, 1.16.2, 1.15.2, 1.14.0, 1.13.1, 1.8.0rc1 or 1.6.2 and U{scipy<https://PyPI.org/project/scipy>} 1.5.0), U{PyPy
|
|
165
165
|
<https://PyPy.org>} 7.3.0 (Python 2.7.13 and 3.6.9), U{PyPy<https://PyPy.org>} 6.0.0 (Python 2.7.13 and 3.5.3)
|
|
166
166
|
and U{Intel-Python<https://software.Intel.com/en-us/distribution-for-python>} 3.5.3 (and U{numpy
|
|
167
|
-
<https://PyPI.org/project/numpy>} 1.11.3) on macOS 14.0-
|
|
167
|
+
<https://PyPI.org/project/numpy>} 1.11.3) on macOS 14.0-3.1 Sonoma, 13.0-5.2 Ventura, 12.1-6 Monterey, 11.0-5.2-6.1
|
|
168
168
|
Big Sur (aka 10.16), 10.15.3, 10.15.5-7 Catalina, 10.14 Mojave, 10.13.6 High Sierra and 10.12 Sierra, MacOS X
|
|
169
169
|
10.11 El Capitan and/or MacOS X 10.10 Yosemite, with U{Pythonista<https://OMZ-Software.com/pythonista>}3.2 (with
|
|
170
170
|
geographiclib 1.50 or 1.49 and numpy 1.8.0) on iOS 14.4.2, 11.4.1, 12.0-3 on iPad4, iPhone6, iPhone10 and/or
|
|
@@ -179,7 +179,7 @@ All Python source code has been statically U{checked<https://GitHub.com/ActiveSt
|
|
|
179
179
|
Python/546532_PyChecker_postprocessor>} with U{PyChecker<https://PyPI.org/project/pychecker>}, U{PyFlakes
|
|
180
180
|
<https://PyPI.org/project/pyflakes>}, U{PyCodeStyle<https://PyPI.org/project/pycodestyle>} (formerly Pep8) and
|
|
181
181
|
U{McCabe<https://PyPI.org/project/mccabe>} using Python 2.7.18 and with U{Flake8<https://PyPI.org/project/flake8>}
|
|
182
|
-
using Python 3.11.5, both in 64-bit on macOS 14.
|
|
182
|
+
using Python 3.11.5, both in 64-bit on macOS 14.4.1 Sonoma.
|
|
183
183
|
|
|
184
184
|
For a summary of all I{Karney}-based functionality in C{pygeodesy}, see module U{karney
|
|
185
185
|
<https://mrJean1.GitHub.io/PyGeodesy/docs/pygeodesy.karney-module.html>}.
|
|
@@ -586,7 +586,7 @@ else:
|
|
|
586
586
|
_init__all__ = False
|
|
587
587
|
|
|
588
588
|
from pygeodesy.interns import _DOT_, _version2 # PYCHOK import
|
|
589
|
-
__version__ = '24.04.
|
|
589
|
+
__version__ = '24.04.04'
|
|
590
590
|
# see setup.py for similar logic
|
|
591
591
|
version = _DOT_(*_version2(__version__, n=3))
|
|
592
592
|
|
pygeodesy/basics.py
CHANGED
|
@@ -14,21 +14,27 @@ if not division:
|
|
|
14
14
|
raise ImportError('%s 1/2 == %s' % ('division', division))
|
|
15
15
|
del division
|
|
16
16
|
|
|
17
|
+
# from pygeodesy.cartesianBase import CartesianBase # _MODS
|
|
18
|
+
# from pygeodesy.constants import isneg0, NEG0 # _MODS
|
|
17
19
|
from pygeodesy.errors import _AttributeError, _ImportError, _NotImplementedError, \
|
|
18
20
|
_TypeError, _TypesError, _ValueError, _xAssertionError, \
|
|
19
21
|
_xkwds_get
|
|
20
22
|
from pygeodesy.interns import MISSING, NN, _1_, _by_, _COMMA_, _DOT_, _DEPRECATED_, \
|
|
21
23
|
_ELLIPSIS4_, _enquote, _EQUAL_, _in_, _invalid_, _N_A_, \
|
|
22
24
|
_not_scalar_, _SPACE_, _UNDER_, _version_, _version_info
|
|
25
|
+
# from pygeodesy.latlonBase import LatLonBase # _MODS
|
|
23
26
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _FOR_DOCS, \
|
|
24
27
|
_getenv, LazyImportError, _sys, _sys_version_info2
|
|
28
|
+
# from pygeodesy.named import classname, modulename # _MODS
|
|
29
|
+
# from pygeodesy.nvectorBase import NvectorBase # _MODS
|
|
30
|
+
# from pygeodesy.props import _update_all # _MODS
|
|
25
31
|
|
|
26
32
|
from copy import copy as _copy, deepcopy as _deepcopy
|
|
27
33
|
from math import copysign as _copysign
|
|
28
34
|
import inspect as _inspect
|
|
29
35
|
|
|
30
36
|
__all__ = _ALL_LAZY.basics
|
|
31
|
-
__version__ = '24.04.
|
|
37
|
+
__version__ = '24.04.04'
|
|
32
38
|
|
|
33
39
|
_0_0 = 0.0 # in .constants
|
|
34
40
|
_below_ = 'below'
|
|
@@ -537,14 +543,19 @@ def neg_(*xs):
|
|
|
537
543
|
return map(neg, xs)
|
|
538
544
|
|
|
539
545
|
|
|
540
|
-
def
|
|
546
|
+
def _neg0(x):
|
|
547
|
+
'''(INTERNAL) Return C{NEG0 if x < 0 else _0_0},
|
|
548
|
+
unlike C{_copysign_0_0} which returns C{_N_0_0}.
|
|
549
|
+
'''
|
|
550
|
+
return _MODS.constants.NEG0 if x < 0 else _0_0
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def _req_d_by(where, name=NN): # in .basics
|
|
541
554
|
'''(INTERNAL) Get the fully qualified name.
|
|
542
555
|
'''
|
|
543
556
|
m = _MODS.named.modulename(where, prefixed=True)
|
|
544
557
|
if name:
|
|
545
|
-
|
|
546
|
-
if n:
|
|
547
|
-
m = _DOT_(m, n)
|
|
558
|
+
m = _DOT_(m, name)
|
|
548
559
|
return _SPACE_(_required_, _by_, m)
|
|
549
560
|
|
|
550
561
|
|
pygeodesy/constants.py
CHANGED
|
@@ -23,7 +23,7 @@ except ImportError: # Python 2-
|
|
|
23
23
|
_inf, _nan = float(_INF_), float(_NAN_)
|
|
24
24
|
|
|
25
25
|
__all__ = _ALL_LAZY.constants
|
|
26
|
-
__version__ = '24.
|
|
26
|
+
__version__ = '24.04.04'
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def _copysign_0_0(y):
|
|
@@ -137,7 +137,7 @@ def _over(p, q):
|
|
|
137
137
|
'''(INTERNAL) Return C{B{p} / B{q}} avoiding C{ZeroDivisionError} exceptions.
|
|
138
138
|
'''
|
|
139
139
|
try:
|
|
140
|
-
return (p / q)
|
|
140
|
+
return (p / q) # if p else _copysign_0_0(q)
|
|
141
141
|
except ZeroDivisionError:
|
|
142
142
|
return (_copysignINF(p) if isfinite(p) else NAN) if p else p
|
|
143
143
|
|
pygeodesy/fmath.py
CHANGED
|
@@ -8,9 +8,9 @@ from __future__ import division as _; del _ # PYCHOK semicolon
|
|
|
8
8
|
|
|
9
9
|
from pygeodesy.basics import _copysign, copysign0, isint, len2
|
|
10
10
|
from pygeodesy.constants import EPS0, EPS02, EPS1, NAN, PI, PI_2, PI_4, \
|
|
11
|
-
_0_0, _0_125, _0_25, _0_5, _1_0,
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
_0_0, _0_125, _0_25, _0_5, _1_0, _1_3rd, \
|
|
12
|
+
_1_5, _1_6th, _2_0, _2_3rd, _3_0, \
|
|
13
|
+
_copysign_0_0, _isfinite, _over, remainder
|
|
14
14
|
from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
|
|
15
15
|
_xError, _xkwds_get, _xkwds_pop2
|
|
16
16
|
from pygeodesy.fsums import _2float, Fsum, _fsum, fsum, fsum1_, _pow_op_, \
|
|
@@ -25,7 +25,7 @@ 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__ = '24.
|
|
28
|
+
__version__ = '24.04.04'
|
|
29
29
|
|
|
30
30
|
# sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
|
|
31
31
|
_0_4142 = 0.41421356237309504880 # ... sqrt(2) - 1
|
|
@@ -116,8 +116,8 @@ class Fhypot(Fsum):
|
|
|
116
116
|
self._fpow(r, _pow_op_)
|
|
117
117
|
else:
|
|
118
118
|
self._fset(_0_0)
|
|
119
|
-
except Exception as
|
|
120
|
-
raise self.
|
|
119
|
+
except Exception as x:
|
|
120
|
+
raise self._ErrorXs(x, xs, power=p)
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
class Fpolynomial(Fsum):
|
|
@@ -169,7 +169,7 @@ class Fpowers(Fsum):
|
|
|
169
169
|
else:
|
|
170
170
|
self._fset(_0_0)
|
|
171
171
|
except Exception as x:
|
|
172
|
-
raise self.
|
|
172
|
+
raise self._ErrorXs(x, xs, power=power)
|
|
173
173
|
|
|
174
174
|
|
|
175
175
|
class Fn_rt(Fsum):
|
|
@@ -193,7 +193,7 @@ class Fn_rt(Fsum):
|
|
|
193
193
|
else:
|
|
194
194
|
self._fset(_0_0)
|
|
195
195
|
except Exception as x:
|
|
196
|
-
raise self.
|
|
196
|
+
raise self._ErrorXs(x, xs, root=root)
|
|
197
197
|
|
|
198
198
|
|
|
199
199
|
class Fcbrt(Fn_rt):
|
|
@@ -359,7 +359,7 @@ def fatan1(x):
|
|
|
359
359
|
# Eq (9): PI_4 * x - x * (abs(x) - 1) * (0.2447 + 0.0663 * abs(x)), for -1 < x < 1
|
|
360
360
|
# PI_4 * x - (x**2 - x) * (0.2447 + 0.0663 * x), for 0 < x - 1
|
|
361
361
|
# x * (1.0300981633974482 + x * (-0.1784 - x * 0.0663))
|
|
362
|
-
H = Fhorner(x, _0_0, 1.
|
|
362
|
+
H = Fhorner(x, _0_0, 1.0300981634, -0.1784, -0.0663)
|
|
363
363
|
return float(H)
|
|
364
364
|
|
|
365
365
|
|
|
@@ -716,7 +716,7 @@ if _sys_version_info2 < (3, 8): # PYCHOK no cover
|
|
|
716
716
|
computed as M{hypot_(*((c1 - c2) for c1, c2 in zip(p1, p2)))},
|
|
717
717
|
provided I{p1} and I{p2} have the same, non-zero length I{n}.
|
|
718
718
|
'''
|
|
719
|
-
h, x2 = _h_x2(xs)
|
|
719
|
+
h, x2 = _h_x2(xs, hypot_)
|
|
720
720
|
return (h * sqrt(x2)) if x2 else _0_0
|
|
721
721
|
|
|
722
722
|
elif _sys_version_info2 < (3, 10):
|
|
@@ -747,22 +747,23 @@ else:
|
|
|
747
747
|
hypot_ = hypot
|
|
748
748
|
|
|
749
749
|
|
|
750
|
-
def _h_x2(xs):
|
|
750
|
+
def _h_x2(xs, which):
|
|
751
751
|
'''(INTERNAL) Helper for L{hypot_} and L{hypot2_}.
|
|
752
752
|
'''
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
753
|
+
n, xs = len2(xs)
|
|
754
|
+
if n > 0:
|
|
755
|
+
h = float(max(map(fabs, xs)))
|
|
756
|
+
if h < EPS0:
|
|
757
|
+
x2 = _0_0
|
|
758
|
+
elif n > 1:
|
|
759
|
+
_h = (_1_0 / h) if h != _1_0 else _1_0
|
|
760
|
+
x2 = _fsum(_1primed((x * _h)**2 for x in xs))
|
|
761
|
+
else:
|
|
762
|
+
x2 = _1_0
|
|
763
|
+
return h, x2
|
|
764
764
|
|
|
765
|
-
|
|
765
|
+
t = Fmt.PAREN(which.__name__, xs)
|
|
766
|
+
raise _ValueError(t, txt=_too_(_few_))
|
|
766
767
|
|
|
767
768
|
|
|
768
769
|
def hypot1(x):
|
|
@@ -783,15 +784,12 @@ def hypot2(x, y):
|
|
|
783
784
|
|
|
784
785
|
@return: C{B{x}**2 + B{y}**2} (C{float}).
|
|
785
786
|
'''
|
|
787
|
+
if fabs(x) < fabs(y):
|
|
788
|
+
x, y = y, x
|
|
786
789
|
if x:
|
|
790
|
+
h2 = x**2
|
|
787
791
|
if y:
|
|
788
|
-
|
|
789
|
-
x, y = y, x
|
|
790
|
-
h2 = x**2 * ((y / x)**2 + _1_0)
|
|
791
|
-
else:
|
|
792
|
-
h2 = x**2
|
|
793
|
-
elif y:
|
|
794
|
-
h2 = y**2
|
|
792
|
+
h2 *= (y / x)**2 + _1_0
|
|
795
793
|
else:
|
|
796
794
|
h2 = _0_0
|
|
797
795
|
return h2
|
|
@@ -810,7 +808,7 @@ def hypot2_(*xs):
|
|
|
810
808
|
|
|
811
809
|
@see: Function L{hypot_}.
|
|
812
810
|
'''
|
|
813
|
-
h, x2 = _h_x2(xs)
|
|
811
|
+
h, x2 = _h_x2(xs, hypot2_)
|
|
814
812
|
return (h**2 * x2) if x2 else _0_0
|
|
815
813
|
|
|
816
814
|
|
|
@@ -840,14 +838,15 @@ def norm2(x, y):
|
|
|
840
838
|
@raise ValueError: Invalid B{C{x}} or B{C{y}}
|
|
841
839
|
or zero norm.
|
|
842
840
|
'''
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
x
|
|
849
|
-
|
|
850
|
-
|
|
841
|
+
try:
|
|
842
|
+
h = hypot(x, y)
|
|
843
|
+
if h:
|
|
844
|
+
x, y = (x / h), (y / h)
|
|
845
|
+
else:
|
|
846
|
+
x = _copysign_0_0(x) # pass?
|
|
847
|
+
y = _copysign_0_0(y)
|
|
848
|
+
except Exception as e:
|
|
849
|
+
raise _xError(e, x=x, y=y, h=h)
|
|
851
850
|
return x, y
|
|
852
851
|
|
|
853
852
|
|
|
@@ -861,16 +860,13 @@ def norm_(*xs):
|
|
|
861
860
|
@raise ValueError: Invalid or insufficent B{C{xs}}
|
|
862
861
|
or zero norm.
|
|
863
862
|
'''
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
else:
|
|
872
|
-
for _ in xs:
|
|
873
|
-
yield _0_0
|
|
863
|
+
try:
|
|
864
|
+
h = hypot_(*xs)
|
|
865
|
+
_h = (_1_0 / h) if h else _0_0
|
|
866
|
+
for i, x in enumerate(xs):
|
|
867
|
+
yield x * _h
|
|
868
|
+
except Exception as e:
|
|
869
|
+
raise _xError(e, Fmt.SQUARE(xs=i), x, _h_, h)
|
|
874
870
|
|
|
875
871
|
|
|
876
872
|
def _powers(x, n):
|
pygeodesy/fsums.py
CHANGED
|
@@ -14,8 +14,8 @@ L{Fsum.__rpow__} return a (very long) C{int} if invoked with optional argument
|
|
|
14
14
|
C{mod} set to C{None}. The C{residual} of an C{integer} L{Fsum} may be between
|
|
15
15
|
C{-1.0} and C{+1.0}, including C{INT0} if considered to be I{exact}.
|
|
16
16
|
|
|
17
|
-
Set env variable C{PYGEODESY_FSUM_PARTIALS} to
|
|
18
|
-
|
|
17
|
+
Set env variable C{PYGEODESY_FSUM_PARTIALS} to string C{"fsum"}) for summation
|
|
18
|
+
of L{Fsum} partials by Python function C{math.fsum}.
|
|
19
19
|
|
|
20
20
|
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater
|
|
21
21
|
than C{"0.0"} as the threshold to throw a L{ResidualError} in division or
|
|
@@ -46,7 +46,7 @@ from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
|
46
46
|
from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
|
|
47
47
|
|
|
48
48
|
__all__ = _ALL_LAZY.fsums
|
|
49
|
-
__version__ = '24.04.
|
|
49
|
+
__version__ = '24.04.04'
|
|
50
50
|
|
|
51
51
|
_add_op_ = _PLUS_ # in .auxilats.auxAngle
|
|
52
52
|
_eq_op_ = _EQUAL_ * 2 # _DEQUAL_
|
|
@@ -81,8 +81,8 @@ def _2float(index=None, **name_value): # in .fmath, .fstats
|
|
|
81
81
|
if _isfinite(v):
|
|
82
82
|
return v
|
|
83
83
|
raise ValueError(_not_finite_)
|
|
84
|
-
except Exception as
|
|
85
|
-
raise _xError(
|
|
84
|
+
except Exception as X:
|
|
85
|
+
raise _xError(X, Fmt.INDEX(n, index), v)
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
def _2floats(xs, origin=0, neg=False):
|
|
@@ -123,28 +123,28 @@ def _2ps(s, r):
|
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
def _psum(ps): # PYCHOK used!
|
|
126
|
-
'''(INTERNAL) Partials
|
|
126
|
+
'''(INTERNAL) Partials sum, updating C{ps}, I{overridden below}.
|
|
127
127
|
'''
|
|
128
128
|
# assert isinstance(ps, list)
|
|
129
|
-
i
|
|
130
|
-
if i < 0
|
|
131
|
-
return _0_0
|
|
132
|
-
s = ps[i]
|
|
129
|
+
i = len(ps) - 1
|
|
130
|
+
s = _0_0 if i < 0 else ps[i]
|
|
133
131
|
_2s = _2sum
|
|
134
132
|
while i > 0:
|
|
135
133
|
i -= 1
|
|
136
134
|
s, r = _2s(s, ps[i])
|
|
137
135
|
if r: # sum(ps) became inexact
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
136
|
+
if s:
|
|
137
|
+
ps[i:] = r, s
|
|
138
|
+
if i > 0:
|
|
139
|
+
p = ps[i-1] # round half-even
|
|
140
|
+
if (p > 0 and r > 0) or \
|
|
141
|
+
(p < 0 and r < 0): # signs match
|
|
142
|
+
r *= 2
|
|
143
|
+
t = s + r
|
|
144
|
+
if r == (t - s):
|
|
145
|
+
s = t
|
|
146
|
+
break # return s
|
|
147
|
+
s = r # PYCHOK no cover
|
|
148
148
|
ps[i:] = s,
|
|
149
149
|
return s
|
|
150
150
|
|
|
@@ -168,24 +168,24 @@ def _2scalar(other, _raiser=None):
|
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
def _strcomplex(s, *args):
|
|
171
|
-
'''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error C{str}.
|
|
171
|
+
'''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
|
|
172
172
|
'''
|
|
173
|
-
c =
|
|
173
|
+
c = _strcomplex.__name__[4:]
|
|
174
174
|
n = _DASH_(len(args), _arg_)
|
|
175
|
-
t =
|
|
176
|
-
return
|
|
175
|
+
t = unstr(pow, *args)
|
|
176
|
+
return _SPACE_(c, s, _from_, n, t)
|
|
177
177
|
|
|
178
178
|
|
|
179
179
|
def _stresidual(prefix, residual, **name_values):
|
|
180
|
-
'''(INTERNAL) Residual error C{str}.
|
|
180
|
+
'''(INTERNAL) Residual error as C{str}.
|
|
181
181
|
'''
|
|
182
|
-
p =
|
|
182
|
+
p = _stresidual.__name__[3:]
|
|
183
183
|
t = Fmt.PARENSPACED(p, Fmt(residual))
|
|
184
184
|
for n, v in itemsorted(name_values):
|
|
185
185
|
n = n.replace(_UNDER_, _SPACE_)
|
|
186
186
|
p = Fmt.PARENSPACED(n, Fmt(v))
|
|
187
187
|
t = _COMMASPACE_(t, p)
|
|
188
|
-
return t
|
|
188
|
+
return _SPACE_(prefix, t)
|
|
189
189
|
|
|
190
190
|
|
|
191
191
|
def _2sum(a, b): # by .testFmath
|
|
@@ -219,8 +219,8 @@ def _2yield(xs, i, _X_ps, _x):
|
|
|
219
219
|
raise ValueError(_not_finite_)
|
|
220
220
|
yield f
|
|
221
221
|
i += 1
|
|
222
|
-
except Exception as
|
|
223
|
-
raise _xError(
|
|
222
|
+
except Exception as X:
|
|
223
|
+
raise _xError(X, Fmt.INDEX(xs=i), x)
|
|
224
224
|
|
|
225
225
|
|
|
226
226
|
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
@@ -756,14 +756,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
756
756
|
def _cmp_0(self, other, op):
|
|
757
757
|
'''(INTERNAL) Return C{scalar(self - B{other})} for 0-comparison.
|
|
758
758
|
'''
|
|
759
|
-
if
|
|
759
|
+
if isinstance(other, Fsum):
|
|
760
|
+
s = _fsum(self._ps_1(*other._ps))
|
|
761
|
+
elif isscalar(other):
|
|
760
762
|
if other:
|
|
761
763
|
s = _fsum(self._ps_1(other))
|
|
762
764
|
else:
|
|
763
765
|
s, r = self._fprs2
|
|
764
766
|
s = _signOf(s, -r)
|
|
765
|
-
elif isinstance(other, Fsum):
|
|
766
|
-
s = _fsum(self._ps_1(*other._ps))
|
|
767
767
|
else:
|
|
768
768
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
769
769
|
return s
|
|
@@ -816,13 +816,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
816
816
|
f = self._copy_2(self.divmod)
|
|
817
817
|
return f._fdivmod2(other, _divmod_op_)
|
|
818
818
|
|
|
819
|
-
def _Error(self, op, other, Error, **
|
|
819
|
+
def _Error(self, op, other, Error, **txt_cause):
|
|
820
820
|
'''(INTERNAL) Format an B{C{Error}} for C{{self} B{op} B{other}}.
|
|
821
821
|
'''
|
|
822
|
-
return Error(_SPACE_(self.toRepr(), op, repr(other)), **
|
|
822
|
+
return Error(_SPACE_(self.toRepr(), op, repr(other)), **txt_cause)
|
|
823
823
|
|
|
824
|
-
def _ErrorX(self, X,
|
|
825
|
-
'''(INTERNAL) Format
|
|
824
|
+
def _ErrorX(self, X, op, other, *mod):
|
|
825
|
+
'''(INTERNAL) Format the caught exception C{X}.
|
|
826
|
+
'''
|
|
827
|
+
E, t = _xError2(X)
|
|
828
|
+
if mod:
|
|
829
|
+
t = _COMMASPACE_(Fmt.PARENSPACED(mod=mod[0]), t)
|
|
830
|
+
return self._Error(op, other, E, txt=t, cause=X)
|
|
831
|
+
|
|
832
|
+
def _ErrorXs(self, X, xs, **kwds): # in .fmath
|
|
833
|
+
'''(INTERNAL) Format the caught exception C{X}.
|
|
826
834
|
'''
|
|
827
835
|
E, t = _xError2(X)
|
|
828
836
|
n = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
|
|
@@ -834,13 +842,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
834
842
|
n, ps, _2s = 0, self._ps, _2sum
|
|
835
843
|
for x in xs: # _iter()
|
|
836
844
|
# assert isscalar(x) and isfinite(x)
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
845
|
+
if x:
|
|
846
|
+
i = 0
|
|
847
|
+
for p in ps:
|
|
848
|
+
x, p = _2s(x, p)
|
|
849
|
+
if p:
|
|
850
|
+
ps[i] = p
|
|
851
|
+
i += 1
|
|
852
|
+
ps[i:] = (x,) if x else ()
|
|
844
853
|
n += 1
|
|
845
854
|
# assert self._ps is ps
|
|
846
855
|
if n:
|
|
@@ -858,30 +867,29 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
858
867
|
def _facc_power(self, power, xs, which): # in .fmath
|
|
859
868
|
'''(INTERNAL) Add each C{xs} as C{float(x**power)}.
|
|
860
869
|
'''
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
870
|
+
p = power
|
|
871
|
+
if isinstance(p, Fsum):
|
|
872
|
+
if p.is_exact:
|
|
873
|
+
return self._facc_power(p._fprs, xs, which)
|
|
864
874
|
_Pow = Fsum._pow_any
|
|
865
|
-
elif isint(
|
|
866
|
-
_Pow = Fsum._pow_int
|
|
867
|
-
power = int(power)
|
|
875
|
+
elif isint(p, both=True) and p >= 0:
|
|
876
|
+
_Pow, p = Fsum._pow_int, int(p)
|
|
868
877
|
else:
|
|
869
|
-
_Pow = Fsum._pow_scalar
|
|
870
|
-
power = _2float(power=power)
|
|
878
|
+
_Pow, p = Fsum._pow_scalar, _2float(power=p)
|
|
871
879
|
|
|
872
|
-
if
|
|
880
|
+
if p:
|
|
873
881
|
from math import pow as _pow
|
|
874
882
|
op = which.__name__
|
|
875
883
|
|
|
876
884
|
def _X(X):
|
|
877
|
-
f = _Pow(X,
|
|
885
|
+
f = _Pow(X, p, power, op)
|
|
878
886
|
try: # isinstance(f, Fsum)
|
|
879
887
|
return f._ps
|
|
880
888
|
except AttributeError: # scalar
|
|
881
889
|
return f,
|
|
882
890
|
|
|
883
891
|
def _x(x):
|
|
884
|
-
return _pow(float(x),
|
|
892
|
+
return _pow(float(x), p)
|
|
885
893
|
|
|
886
894
|
self._facc(_2yield(xs, 1, _X, _x)) # PYCHOK yield
|
|
887
895
|
else:
|
|
@@ -985,7 +993,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
985
993
|
'''
|
|
986
994
|
if _isfinite(other):
|
|
987
995
|
return other
|
|
988
|
-
raise ValueError(_not_finite_) if
|
|
996
|
+
raise ValueError(_not_finite_) if op is None else \
|
|
989
997
|
self._ValueError(op, other, txt=_not_finite_)
|
|
990
998
|
|
|
991
999
|
def fint(self, raiser=True, **name):
|
|
@@ -1123,11 +1131,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1123
1131
|
running sum and residual (L{Fsum2Tuple}).
|
|
1124
1132
|
'''
|
|
1125
1133
|
ps = self._ps
|
|
1126
|
-
n = len(ps)
|
|
1127
|
-
if n >
|
|
1134
|
+
n = len(ps) - 2
|
|
1135
|
+
if n > 0: # len(ps) > 2
|
|
1128
1136
|
s = _psum(ps)
|
|
1129
1137
|
r = _fsum(self._ps_1(s)) or INT0
|
|
1130
|
-
elif n
|
|
1138
|
+
elif n == 0: # len(ps) == 2
|
|
1131
1139
|
ps[:] = _2ps(*_2sum(*ps))
|
|
1132
1140
|
r, s = (INT0, ps[0]) if len(ps) != 2 else ps
|
|
1133
1141
|
elif ps: # len(ps) == 1
|
|
@@ -1145,6 +1153,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1145
1153
|
# _ = self._fprs
|
|
1146
1154
|
# return self
|
|
1147
1155
|
|
|
1156
|
+
def fset_(self, *xs):
|
|
1157
|
+
'''Replace this instance' value with C{xs}.
|
|
1158
|
+
|
|
1159
|
+
@arg xs: Optional, new values (C{scalar} or L{Fsum}
|
|
1160
|
+
instances), all positional.
|
|
1161
|
+
|
|
1162
|
+
@return: This instance (C{Fsum}).
|
|
1163
|
+
|
|
1164
|
+
@see: Method L{Fsum.fadd} for further details.
|
|
1165
|
+
'''
|
|
1166
|
+
self._n = 0
|
|
1167
|
+
self._ps[:] = 0,
|
|
1168
|
+
return self.fadd(xs) if xs else self._update()
|
|
1169
|
+
|
|
1148
1170
|
def _fset(self, other, asis=True, n=0):
|
|
1149
1171
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
1150
1172
|
'''
|
|
@@ -1249,7 +1271,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1249
1271
|
f = self._facc(_2floats(xs, origin=1)) if xs else self # PYCHOK yield
|
|
1250
1272
|
return f._fprs
|
|
1251
1273
|
|
|
1252
|
-
def fsum2(self, xs=(),
|
|
1274
|
+
def fsum2(self, xs=(), name=NN):
|
|
1253
1275
|
'''Add more C{scalar} or L{Fsum} instances and return the
|
|
1254
1276
|
current precision running sum and the C{residual}.
|
|
1255
1277
|
|
|
@@ -1268,9 +1290,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1268
1290
|
f = self._facc(_2floats(xs)) if xs else self # PYCHOK yield
|
|
1269
1291
|
t = f._fprs2
|
|
1270
1292
|
if name:
|
|
1271
|
-
|
|
1272
|
-
if n:
|
|
1273
|
-
t = t.dup(name=n)
|
|
1293
|
+
t = t.dup(name=name)
|
|
1274
1294
|
return t
|
|
1275
1295
|
|
|
1276
1296
|
def fsum2_(self, *xs):
|
|
@@ -1306,16 +1326,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1306
1326
|
'''
|
|
1307
1327
|
n = _1_0
|
|
1308
1328
|
if isinstance(other, Fsum):
|
|
1309
|
-
if other is self or other
|
|
1329
|
+
if other is self or other == self:
|
|
1310
1330
|
return self._fset(_1_0) # n=len(self)
|
|
1311
1331
|
d, r = other._fprs2
|
|
1312
1332
|
if r:
|
|
1313
|
-
if
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
raise self._ResidualError(op, other, r)
|
|
1317
|
-
else:
|
|
1333
|
+
if d:
|
|
1334
|
+
if self._raiser(r, d):
|
|
1335
|
+
raise self._ResidualError(op, other, r)
|
|
1318
1336
|
d, n = other.as_integer_ratio()
|
|
1337
|
+
else: # PYCHOK no cover
|
|
1338
|
+
d = r
|
|
1319
1339
|
elif isscalar(other):
|
|
1320
1340
|
d = other
|
|
1321
1341
|
else: # PYCHOK no cover
|
|
@@ -1323,9 +1343,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1323
1343
|
try:
|
|
1324
1344
|
s = 0 if isinf(d) else (
|
|
1325
1345
|
d if isnan(d) else self._finite(n / d))
|
|
1326
|
-
except Exception as
|
|
1327
|
-
|
|
1328
|
-
raise self._Error(op, other, E, txt=t)
|
|
1346
|
+
except Exception as X:
|
|
1347
|
+
raise self._ErrorX(X, op, other)
|
|
1329
1348
|
f = self._mul_scalar(s, _mul_op_) # handles 0, NAN, etc.
|
|
1330
1349
|
return self._fset(f, asis=False)
|
|
1331
1350
|
|
|
@@ -1444,7 +1463,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1444
1463
|
def _pow_0_1(self, x, other):
|
|
1445
1464
|
'''(INTERNAL) Return B{C{self}**1} or C{B{self}**0 == 1.0}.
|
|
1446
1465
|
'''
|
|
1447
|
-
return self if x else (1 if
|
|
1466
|
+
return self if x else (1 if isint(other) and self.is_integer() else _1_0)
|
|
1448
1467
|
|
|
1449
1468
|
def _pow_2(self, b, x, other, op):
|
|
1450
1469
|
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} embellishing errors.
|
|
@@ -1455,10 +1474,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1455
1474
|
if not iscomplex(s):
|
|
1456
1475
|
return self._finite(s) # 0**INF == 0.0, 1**INF==1.0
|
|
1457
1476
|
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1458
|
-
|
|
1459
|
-
except Exception as
|
|
1460
|
-
|
|
1461
|
-
raise self._Error(op, other, E, txt=t)
|
|
1477
|
+
raise ValueError(_strcomplex(s, b, x)) # PYCHOK no cover
|
|
1478
|
+
except Exception as X:
|
|
1479
|
+
raise self._ErrorX(X, op, other)
|
|
1462
1480
|
|
|
1463
1481
|
def _pow_3(self, other, mod, op):
|
|
1464
1482
|
'''(INTERNAL) 3-arg C{pow(B{self}, B{other}, int B{mod} or C{None})}.
|
|
@@ -1466,19 +1484,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1466
1484
|
b, r = self._fprs2 if mod is None else self._fint2
|
|
1467
1485
|
if r and self._raiser(r, b):
|
|
1468
1486
|
t = _non_zero_ if mod is None else _integer_
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
raise self._Error(op, other, E, txt=t)
|
|
1487
|
+
t = _stresidual(t, r, mod=mod)
|
|
1488
|
+
raise self._Error(op, other, ResidualError, txt=t)
|
|
1489
|
+
|
|
1490
|
+
try: # b, other, mod all C{int}, unless C{mod} is C{None}
|
|
1491
|
+
x = _2scalar(other, _raiser=self._raiser)
|
|
1492
|
+
s = pow(b, x, mod)
|
|
1493
|
+
if not iscomplex(s):
|
|
1494
|
+
return self._finite(s)
|
|
1495
|
+
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1496
|
+
raise ValueError(_strcomplex(s, b, x, mod)) # PYCHOK no cover
|
|
1497
|
+
except Exception as X:
|
|
1498
|
+
raise self._ErrorX(X, op, other, mod)
|
|
1482
1499
|
|
|
1483
1500
|
def _pow_any(self, other, unused, op):
|
|
1484
1501
|
'''Return C{B{self} ** B{other}}.
|
|
@@ -1569,14 +1586,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1569
1586
|
def _ps_1(self, *less):
|
|
1570
1587
|
'''(INTERNAL) Yield partials, 1-primed and subtract any C{less}.
|
|
1571
1588
|
'''
|
|
1572
|
-
|
|
1589
|
+
n = len(self._ps) + len(less) - 4
|
|
1590
|
+
if n < 0:
|
|
1591
|
+
yield _1_0
|
|
1573
1592
|
for p in self._ps:
|
|
1574
|
-
|
|
1575
|
-
yield p
|
|
1593
|
+
yield p
|
|
1576
1594
|
for p in less:
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1595
|
+
yield -p
|
|
1596
|
+
if n < 0:
|
|
1597
|
+
yield _N_1_0
|
|
1580
1598
|
|
|
1581
1599
|
def _ps_mul(self, op, *factors): # see .fmath.Fhorner
|
|
1582
1600
|
'''(INTERNAL) Yield all C{partials} times each B{C{factor}},
|
|
@@ -1636,12 +1654,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1636
1654
|
C{PYGEODESY_FSUM_RESIDUAL} or if omitted, keep the
|
|
1637
1655
|
current setting.
|
|
1638
1656
|
|
|
1639
|
-
@return: The previous C{RESIDUAL} setting (C{float}).
|
|
1657
|
+
@return: The previous C{RESIDUAL} setting (C{float}), default C{0}.
|
|
1640
1658
|
|
|
1641
1659
|
@raise ValueError: Negative B{C{threshold}}.
|
|
1642
1660
|
|
|
1643
1661
|
@note: A L{ResidualError} is thrown if the non-zero I{ratio}
|
|
1644
|
-
C{residual
|
|
1662
|
+
C{residual / fsum} exceeds the B{C{threshold}}.
|
|
1645
1663
|
'''
|
|
1646
1664
|
r = self._RESIDUAL
|
|
1647
1665
|
if threshold:
|
|
@@ -1659,7 +1677,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1659
1677
|
'''(INTERNAL) Non-zero B{C{residual}} etc.
|
|
1660
1678
|
'''
|
|
1661
1679
|
t = _stresidual(_non_zero_, residual, ratio=self._ratio,
|
|
1662
|
-
|
|
1680
|
+
RESIDUAL=self._RESIDUAL)
|
|
1663
1681
|
t = t.replace(_COMMASPACE_R_, _exceeds_R_)
|
|
1664
1682
|
return self._Error(op, other, ResidualError, txt=t)
|
|
1665
1683
|
|
|
@@ -1721,7 +1739,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1721
1739
|
# Fsum._fint2._update(self)
|
|
1722
1740
|
# Fsum._fprs ._update(self)
|
|
1723
1741
|
# Fsum._fprs2._update(self)
|
|
1724
|
-
return self
|
|
1742
|
+
return self # for .fset_
|
|
1725
1743
|
|
|
1726
1744
|
def _ValueError(self, op, other, **txt): # PYCHOK no cover
|
|
1727
1745
|
'''(INTERNAL) Return a C{ValueError}.
|
|
@@ -1820,7 +1838,7 @@ try:
|
|
|
1820
1838
|
|
|
1821
1839
|
Fsum._math_fsum = _sum = _fsum # PYCHOK exported
|
|
1822
1840
|
|
|
1823
|
-
if _getenv('PYGEODESY_FSUM_PARTIALS',
|
|
1841
|
+
if _getenv('PYGEODESY_FSUM_PARTIALS', NN) == _fsum.__name__:
|
|
1824
1842
|
_psum = _fsum # PYCHOK re-def
|
|
1825
1843
|
|
|
1826
1844
|
except ImportError:
|
|
@@ -1915,6 +1933,35 @@ def fsum1f_(*xs):
|
|
|
1915
1933
|
return _fsum(_1primed(xs)) if xs else _0_0
|
|
1916
1934
|
|
|
1917
1935
|
|
|
1936
|
+
if __name__ == '__main__':
|
|
1937
|
+
|
|
1938
|
+
# usage: [env PYGEODESY_FSUM_PARTIALS=fsum] python3 -m pygeodesy.fsums
|
|
1939
|
+
|
|
1940
|
+
def _test(n):
|
|
1941
|
+
# copied from Hettinger, see L{Fsum} reference
|
|
1942
|
+
from pygeodesy import printf
|
|
1943
|
+
from random import gauss, random, shuffle
|
|
1944
|
+
|
|
1945
|
+
printf(_fsum.__name__, end=_COMMASPACE_)
|
|
1946
|
+
printf(_psum.__name__, end=_COMMASPACE_)
|
|
1947
|
+
|
|
1948
|
+
F = Fsum()
|
|
1949
|
+
if F.is_math_fsum:
|
|
1950
|
+
c = (7, 1e100, -7, -1e100, -9e-20, 8e-20) * 10
|
|
1951
|
+
for _ in range(n):
|
|
1952
|
+
t = list(c)
|
|
1953
|
+
s = 0
|
|
1954
|
+
for _ in range(n * 8):
|
|
1955
|
+
v = gauss(0, random())**7 - s
|
|
1956
|
+
t.append(v)
|
|
1957
|
+
s += v
|
|
1958
|
+
shuffle(t)
|
|
1959
|
+
assert float(F.fset_(*t)) == _fsum(t)
|
|
1960
|
+
printf(_DOT_, end=NN)
|
|
1961
|
+
printf(NN)
|
|
1962
|
+
|
|
1963
|
+
_test(128)
|
|
1964
|
+
|
|
1918
1965
|
# **) MIT License
|
|
1919
1966
|
#
|
|
1920
1967
|
# Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
|
pygeodesy/resections.py
CHANGED
|
@@ -13,9 +13,10 @@ L{triAngle}, L{triAngle5}, L{triSide}, L{triSide2} and L{triSide4}.
|
|
|
13
13
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
14
14
|
|
|
15
15
|
from pygeodesy.basics import map1, map2, _zip, _ALL_LAZY
|
|
16
|
-
from pygeodesy.constants import EPS, EPS0, EPS02, INT0,
|
|
17
|
-
_0_0, _0_5, _1_0, _N_1_0, _2_0, _N_2_0, _4_0,
|
|
18
|
-
_180_0, _360_0,
|
|
16
|
+
from pygeodesy.constants import EPS, EPS0, EPS02, INT0, PI, PI2, PI_2, PI_4, \
|
|
17
|
+
_0_0, _0_5, _1_0, _N_1_0, _2_0, _N_2_0, _4_0, \
|
|
18
|
+
_16_0, _180_0, _360_0, _copysign_0_0, isnear0, \
|
|
19
|
+
_over, _umod_360
|
|
19
20
|
from pygeodesy.errors import _and, _or, TriangleError, _ValueError, _xcallable, \
|
|
20
21
|
_xkwds, _xkwds_pop2
|
|
21
22
|
from pygeodesy.fmath import favg, Fdot, fidw, fmean, hypot, hypot2_
|
|
@@ -33,7 +34,7 @@ from pygeodesy.vector3d import _otherV3d, Vector3d
|
|
|
33
34
|
from math import cos, atan2, degrees, fabs, radians, sin, sqrt
|
|
34
35
|
|
|
35
36
|
__all__ = _ALL_LAZY.resections
|
|
36
|
-
__version__ = '24.
|
|
37
|
+
__version__ = '24.04.04'
|
|
37
38
|
|
|
38
39
|
_concyclic_ = 'concyclic'
|
|
39
40
|
_PA_ = 'PA'
|
|
@@ -457,7 +458,7 @@ def pierlotx(point1, point2, point3, alpha1, alpha2, alpha3, useZ=False,
|
|
|
457
458
|
|
|
458
459
|
def _cot(s, c): # I{exact} cotangent
|
|
459
460
|
try:
|
|
460
|
-
return (c / s) if c else (
|
|
461
|
+
return (c / s) if c else _copysign_0_0(s)
|
|
461
462
|
except ZeroDivisionError:
|
|
462
463
|
raise ValueError(_or(_coincident_, _colinear_))
|
|
463
464
|
|
pygeodesy/utily.py
CHANGED
|
@@ -10,12 +10,14 @@ U{Vector-based geodesy<https://www.Movable-Type.co.UK/scripts/latlong-vectors.ht
|
|
|
10
10
|
# make sure int/int division yields float quotient, see .basics
|
|
11
11
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
12
12
|
|
|
13
|
-
from pygeodesy.basics import _copysign, isinstanceof, isint, isstr, neg,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
from pygeodesy.basics import _copysign, isinstanceof, isint, isstr, neg, \
|
|
14
|
+
_passargs
|
|
15
|
+
from pygeodesy.constants import EPS, EPS0, INF, NAN, PI, PI2, PI_2, R_M, \
|
|
16
|
+
_M_KM, _M_NM, _M_SM, _0_0, _1__90, _0_5, _1_0, \
|
|
17
|
+
_N_1_0, _2__PI, _10_0, _90_0, _N_90_0, _180_0, \
|
|
18
|
+
_N_180_0, _360_0, _400_0, _copysign_0_0, \
|
|
19
|
+
_float as _F, _isfinite, isnan, isnear0, \
|
|
20
|
+
_over, _umod_360, _umod_PI2
|
|
19
21
|
from pygeodesy.errors import _ValueError, _xkwds, _xkwds_get, _ALL_LAZY, _MODS
|
|
20
22
|
from pygeodesy.interns import _edge_, _radians_, _semi_circular_, _SPACE_
|
|
21
23
|
# from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
|
|
@@ -25,7 +27,7 @@ from pygeodesy.units import Degrees, Degrees_, Feet, Float, Lam, Lam_, \
|
|
|
25
27
|
from math import acos, asin, atan2, cos, degrees, fabs, radians, sin, tan # pow
|
|
26
28
|
|
|
27
29
|
__all__ = _ALL_LAZY.utily
|
|
28
|
-
__version__ = '24.
|
|
30
|
+
__version__ = '24.04.04'
|
|
29
31
|
|
|
30
32
|
# read constant name "_M_Unit" as "meter per Unit"
|
|
31
33
|
_M_CHAIN = _F( 20.1168) # yard2m(1) * 22
|
|
@@ -683,7 +685,7 @@ def _sin0cos2(q, r, sign):
|
|
|
683
685
|
# else: # r == 0, testUtility failures
|
|
684
686
|
# t = _0_0, _1_0, _0_0, _N_1_0, _0_0
|
|
685
687
|
# q &= 3
|
|
686
|
-
s = t[q] or (
|
|
688
|
+
s = t[q] or _copysign_0_0(sign)
|
|
687
689
|
c = t[q + 1] or _0_0
|
|
688
690
|
return s, c
|
|
689
691
|
|
|
@@ -691,8 +693,7 @@ def _sin0cos2(q, r, sign):
|
|
|
691
693
|
def SinCos2(x):
|
|
692
694
|
'''Get C{sin} and C{cos} of I{typed} angle.
|
|
693
695
|
|
|
694
|
-
@arg x: Angle (L{Degrees}, L{
|
|
695
|
-
or scalar C{radians}).
|
|
696
|
+
@arg x: Angle (L{Degrees}, L{Radians} or scalar C{radians}).
|
|
696
697
|
|
|
697
698
|
@return: 2-Tuple (C{sin(B{x})}, C{cos(B{x})}).
|
|
698
699
|
'''
|
|
File without changes
|
|
File without changes
|