pygeodesy 24.4.18__py2.py3-none-any.whl → 24.5.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyGeodesy
3
- Version: 24.4.18
3
+ Version: 24.5.2
4
4
  Summary: Pure Python geodesy tools
5
5
  Home-page: https://GitHub.com/mrJean1/PyGeodesy
6
6
  Author: Jean M. Brouwers
@@ -158,7 +158,7 @@ and McCabe_ using Python 2.7.18 and with Flake8_ using Python 3.11.5, both in 64
158
158
 
159
159
  For a summary of all *Karney*-based functionality in ``pygeodesy``, see module karney_.
160
160
 
161
- *Last updated: April 18, 2024.*
161
+ *Last updated: May 02, 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=Wx1Zo8hUxl6CV1eZZvLbrQSQ6VSB8mHBTmPqxcG0Mpc,40824
2
+ pygeodesy/__init__.py,sha256=LsshXEtTCo0kRJI0vJfZzKu5Lo0Q0j5fiTf1bnCvefs,40733
3
3
  pygeodesy/__main__.py,sha256=qMFG3caY8ZXWu6uGiemzyT4OqTFZnsFtlxcGCAgkVJw,4637
4
4
  pygeodesy/albers.py,sha256=g2AVlpV8JO2AYFCthoIbRC2h1OJqjb9P3hpwF0C3TI8,30994
5
5
  pygeodesy/azimuthal.py,sha256=tc4JxgLi-0jzU08m4Bvi-t-kzHXYPeGuzL3j_tyVFUA,50125
6
- pygeodesy/basics.py,sha256=_BMYLzGKA6OIS3qv25HfHy7MIh0kAbmkzyScb59clUs,28160
6
+ pygeodesy/basics.py,sha256=Mh70LwAH185gr8aYhdOhfqAa-SkHvAatlJEOFIH7N8Y,28162
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=ypxYsWB6tNAVgrD9QVpukJAPscaLgHtPLqPuot1gUfU,19174
10
+ pygeodesy/constants.py,sha256=RxO8dMe_3AEfmZyKaRIy_44QnOTdEpzgYwimN0_w9Qs,19113
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=XRVpmpdm3hbztM4P-qhWKQizbgsXDUxWujgmOrIpgiQ,42428
25
25
  pygeodesy/epsg.py,sha256=ldHoLWqJWR4FUiBVnDTtrI_e7TNjjtr9OkxDlri1g5E,8165
26
26
  pygeodesy/errors.py,sha256=mUaacHJKcSCowlcbzamaBMDqjI2dqsTM5O4ozIITtAk,27233
27
27
  pygeodesy/etm.py,sha256=joEhU2lw9ehRv101nRpZvXq8hOYAEzdcYFpif9_obfk,44585
28
- pygeodesy/fmath.py,sha256=9jjm_QxrQKNtOUxgNk02j-UVMFVjC1cDPaEqXznKgzk,30716
28
+ pygeodesy/fmath.py,sha256=cRisVRkuarEwu4pKOCWmBa-98lV2PP9oJVkkODQLc2E,32480
29
29
  pygeodesy/formy.py,sha256=Rces4Q5ecED0WVfuI9mQzeyHE54LDowYfI6faBHpyeA,74536
30
30
  pygeodesy/frechet.py,sha256=qgee-ISBtT7Ov3rJkcd_t-WeXTbeNoMSQuMa0j3MyQc,33512
31
- pygeodesy/fstats.py,sha256=r8O2aIknHuoHsW8gZUIY42zpHZy7syHvCB7uCVtPpkc,25559
32
- pygeodesy/fsums.py,sha256=QjV9B-YGbhFALMPEQMKT8-1j7JFDWnabakAdZDvFsSs,72501
31
+ pygeodesy/fstats.py,sha256=3IUmOJclp3XIzTLKVrwj24N0yCRvVMPSD2-BV7CY3_g,25559
32
+ pygeodesy/fsums.py,sha256=xGA9nNeAHndWhs8pXJ4n46ZlNPIT2sn2f_6HmFOTnPs,76188
33
33
  pygeodesy/gars.py,sha256=fCiWBJ4kOJxPfNOxadX-OzBGDXj7C9g02NuGHiZa_88,11342
34
34
  pygeodesy/geodesicw.py,sha256=5yjJ2rLekSsjT7e-Km6v592ZcFlA41flQP_E42jU9Sw,26901
35
35
  pygeodesy/geodsolve.py,sha256=3GLI2_4gglzTpZwKchNzAv-XhWFBzWRKjcWsjCC3dvI,21900
@@ -37,12 +37,12 @@ pygeodesy/geohash.py,sha256=HwukecfkWvyfz9LHKfoA-WddQHYot_mB04o0lyWrKyU,32382
37
37
  pygeodesy/geoids.py,sha256=EwZJ50qRXeZb1591N99hnamM_EC2NP6MIhLb5swVHf4,80605
38
38
  pygeodesy/hausdorff.py,sha256=LJULGbDop4xqiWeRH5-Uayvk5WVCZQpxK4PCYu4kqSs,34192
39
39
  pygeodesy/heights.py,sha256=tjr-5eb8UXn2MAp6-157sb6qxPREFk5dtDjHtBgIgZ8,42528
40
- pygeodesy/interns.py,sha256=JqIAp_-TOzijDShKSmKIarz009vIXtqfB-JoD8ILvKo,30177
40
+ pygeodesy/interns.py,sha256=ZeNGk2WIHLunBGSeOkU4Ihc9CNSfVDFZGNkbBQy2_8M,30120
41
41
  pygeodesy/iters.py,sha256=CfU365eE9F4oWZbBx0qTEvfodMhpa8rGOepLIv67xF8,20181
42
42
  pygeodesy/karney.py,sha256=lYdsSHis8xQJVS1V0F3cphx6Dhgd77xTlMOdVR8MN8I,34994
43
43
  pygeodesy/ktm.py,sha256=sCvbLvJItavlruilAyjeZ0sOZx2yJumzGe_UiIVbGi4,27315
44
44
  pygeodesy/latlonBase.py,sha256=LimCMj91J3Q4D_rTu7VN7c63cLL_KzxXagFQfedobmc,77730
45
- pygeodesy/lazily.py,sha256=4ZxBVj1Yu4Db-dw_e6oxXx7EtDSrgdGBV-ypUefMPGY,48633
45
+ pygeodesy/lazily.py,sha256=YeOQQ2Tu0LTD-AMDABc0bemeLRKTteTEJXJDl3_7vZU,48645
46
46
  pygeodesy/lcc.py,sha256=yNpmAdOwv3HNh2ZLopF5QtvDokeQYCmnxSc8UFUPHO4,25737
47
47
  pygeodesy/ltp.py,sha256=8se8dYG7LG__Ru0FoK939DJBF9GCQGeJik_Un1Im8Xw,48609
48
48
  pygeodesy/ltpTuples.py,sha256=iKzvDfv33HfmEevjNISUS4c9KXIkiISEkVlQopyKgfY,55769
@@ -59,9 +59,9 @@ pygeodesy/solveBase.py,sha256=cBe3QQWEaJlPWUlXoiYo1eFMh4z6GDZbQyt8ZiwMfos,16687
59
59
  pygeodesy/sphericalBase.py,sha256=sH2WwmY_RL0STyr1OhtCDKvGhO0Ks7o3V-MHLddpiHQ,31944
60
60
  pygeodesy/sphericalNvector.py,sha256=TBs_nid_DTcox7bBegh_Djv4zZRGRY4mH6dd1xIHGms,56963
61
61
  pygeodesy/sphericalTrigonometry.py,sha256=Q9qsqzIK43xBken2G8uP9snPXPuBoZ20pMHqbT_IjG0,64216
62
- pygeodesy/streprs.py,sha256=-29aUO7dYe-YWfTjflljesxGUp7IfEAjk5dJLHWMPVs,23413
62
+ pygeodesy/streprs.py,sha256=NIiLVzXLnJR7w5fNTkivpbQN5XdZYJIc189Iv_bjpYw,23513
63
63
  pygeodesy/trf.py,sha256=4gVtF780EEZEqWwMBDe4x1AEkIz3hB8h4l0_0NXWM5U,118903
64
- pygeodesy/triaxials.py,sha256=fkUcWkXkykZNbTq62LcdnEjhNu9q-e2UaSpRotdzuu8,61546
64
+ pygeodesy/triaxials.py,sha256=nYFQcLimivcxpeXMj9a83iWuENDU1gI-2zNgCkZzL0U,61549
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
@@ -79,7 +79,7 @@ pygeodesy/auxilats/_CX_6.py,sha256=x4hrHxunjqqkEsZbVW1dyn3R5mR8EWYOuX77RzDEyh4,1
79
79
  pygeodesy/auxilats/_CX_8.py,sha256=t-OO48t4cCOsOgMi1FoyPw2DQqybVZFsgQMqAYP-jKY,25304
80
80
  pygeodesy/auxilats/__init__.py,sha256=yOa5RDYOOed9Z4dvcKlatH0JBgohAJ8ADXjU9mZGTfQ,2881
81
81
  pygeodesy/auxilats/__main__.py,sha256=TVN8evCKEzBKdANU5-Ucps8bZySqBTQmEGU4hy_U1cw,2980
82
- pygeodesy/auxilats/auxAngle.py,sha256=3tTYEuiX2YmEOmoyqGPYrSN3gLXbcKWKFH1TNt3NqbI,16738
82
+ pygeodesy/auxilats/auxAngle.py,sha256=LEa1GVR1EOYnTxR-mBLUj4mGoLO6jRrpsyG4v7N8W_0,16727
83
83
  pygeodesy/auxilats/auxDLat.py,sha256=U3BHF6AkW5--nrwH9whL5wZVIZLH_keRLfUz6c6KBx4,10950
84
84
  pygeodesy/auxilats/auxDST.py,sha256=bdNEh3TdABWH7qW6ngZx5SnzDM3B5rtPLvYhvCnFsKc,10497
85
85
  pygeodesy/auxilats/auxLat.py,sha256=U6thEwMEoUm4OFb2_JviEtEn2-nqyVjNbII7oyMf0hM,31282
@@ -109,7 +109,7 @@ pygeodesy/rhumb/aux_.py,sha256=W4HkgoHAQz_aWaysfsmOA5010nCGvBfUs2Q-bymnHYU,16660
109
109
  pygeodesy/rhumb/bases.py,sha256=kzU_Dgt4FNPMgTg5rqbw-HiNpflDPKpmq9jhPbQmR4U,53851
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.18.dist-info/METADATA,sha256=kwVbSazBaM7cCqqiNZ0-SQbbnG7-Y3vLtmAh_yGMK3s,19366
113
- PyGeodesy-24.4.18.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
114
- PyGeodesy-24.4.18.dist-info/top_level.txt,sha256=cEQPatCXzKZqrivpULC5V5fuy9_V_bAwaP_gUGid7pQ,10
115
- PyGeodesy-24.4.18.dist-info/RECORD,,
112
+ PyGeodesy-24.5.2.dist-info/METADATA,sha256=CCvKPsW0UUmlWkrNk0W6dlZb8J--2lIS-wHNpMJGPwk,19363
113
+ PyGeodesy-24.5.2.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
114
+ PyGeodesy-24.5.2.dist-info/top_level.txt,sha256=cEQPatCXzKZqrivpULC5V5fuy9_V_bAwaP_gUGid7pQ,10
115
+ PyGeodesy-24.5.2.dist-info/RECORD,,
pygeodesy/__init__.py CHANGED
@@ -194,7 +194,6 @@ The following environment variables are observed by C{PyGeodesy}:
194
194
 
195
195
  - C{PYGEODESY_EXCEPTION_CHAINING} - see module L{pygeodesy.errors}.
196
196
  - C{PYGEODESY_FMT_FORM} - see module L{pygeodesy.dms}.
197
- - C{PYGEODESY_FSUM_PARTIALS} - see module L{pygeodesy.fsums} and class L{pygeodesy.Fsum}.
198
197
  - C{PYGEODESY_FSUM_RESIDUAL} - see module L{pygeodesy.fsums} and class L{pygeodesy.Fsum}.
199
198
  - C{PYGEODESY_GEOCONVERT} - see module L{pygeodesy.mgrs}.
200
199
  - C{PYGEODESY_GEODSOLVE} - see module L{pygeodesy.geodsolve}.
@@ -586,7 +585,7 @@ else:
586
585
  _init__all__ = False
587
586
 
588
587
  from pygeodesy.interns import _DOT_, _version2 # PYCHOK import
589
- __version__ = '24.04.18'
588
+ __version__ = '24.05.02'
590
589
  # see setup.py for similar logic
591
590
  version = _DOT_(*_version2(__version__, n=3))
592
591
 
@@ -20,8 +20,8 @@ from pygeodesy.constants import EPS, _INF_NAN_NINF, MAX, NAN, _0_0, _0_5, _1_0,
20
20
  _copysign_1_0, _over, _pos_self, isfinite, isnan
21
21
  # from pygeodesy.errors import AuxError, _xkwds_get # from .auxily, .basics
22
22
  from pygeodesy.fmath import hypot, unstr
23
- from pygeodesy.fsums import _add_op_, _isub_op_, _sub_op_, _iadd_op_, _Named, NN
24
- # from pygeodesy.interns import NN, _iadd_op_ # from .fsums
23
+ from pygeodesy.fsums import _add_op_, _iadd_op_, _isub_op_, _sub_op_, _Named, NN
24
+ # from pygeodesy.interns import NN # from .fsums
25
25
  # from pygeodesy.named import _Named # from .fsums
26
26
  from pygeodesy.lazily import _ALL_DOCS, _ALL_MODS as _MODS
27
27
  from pygeodesy.props import Property, Property_RO, property_RO, _update_all
@@ -32,7 +32,7 @@ from pygeodesy.utily import atan2d, sincos2, sincos2d
32
32
  from math import asinh, atan2, copysign, degrees, fabs, radians, sinh
33
33
 
34
34
  __all__ = ()
35
- __version__ = '23.12.02'
35
+ __version__ = '24.04.26'
36
36
 
37
37
  _0_INF_NAN_NINF = (0, _0_0) + _INF_NAN_NINF
38
38
  _MAX_2 = MAX * _0_5 # PYCHOK used!
pygeodesy/basics.py CHANGED
@@ -34,7 +34,7 @@ from math import copysign as _copysign
34
34
  import inspect as _inspect
35
35
 
36
36
  __all__ = _ALL_LAZY.basics
37
- __version__ = '24.04.04'
37
+ __version__ = '24.04.28'
38
38
 
39
39
  _0_0 = 0.0 # in .constants
40
40
  _below_ = 'below'
@@ -576,7 +576,7 @@ def signBit(x):
576
576
  def _signOf(x, ref): # in .fsums
577
577
  '''(INTERNAL) Return the sign of B{C{x}} versus B{C{ref}}.
578
578
  '''
579
- return +1 if x > ref else (-1 if x < ref else 0)
579
+ return (-1) if x < ref else (+1 if x > ref else 0)
580
580
 
581
581
 
582
582
  def signOf(x):
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.04.04'
26
+ __version__ = '24.04.23'
27
27
 
28
28
 
29
29
  def _copysign_0_0(y):
@@ -247,7 +247,6 @@ _1_16th = _Float(_1_16th =_1_0 / _16_0) # PYCHOK in .ellipsoids, .karney
247
247
  _1_64th = _Float(_1_64th =_1_0 / 64) # PYCHOK in .elliptic, pow(2.0, -6)
248
248
  _1_3rd = _Float(_1_3rd =_1_0 / _3_0) # PYCHOK in .fmath
249
249
  _1_6th = _Float(_1_6th =_1_0 / _6_0) # PYCHOK in .fmath
250
- _2_3rd = _Float(_2_3rd =_2_0 / _3_0) # PYCHOK in .fmath
251
250
 
252
251
  _K0_UTM = _Float(_K0_UTM = 0.9996) # PYCHOK in .etm, .ktm, .utm, UTM scale at central meridian
253
252
  # sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
pygeodesy/fmath.py CHANGED
@@ -6,17 +6,14 @@ u'''Utilities using precision floating point summation.
6
6
  # make sure int/int division yields float quotient, see .basics
7
7
  from __future__ import division as _; del _ # PYCHOK semicolon
8
8
 
9
- from pygeodesy.basics import _copysign, copysign0, isint, len2
9
+ from pygeodesy.basics import _copysign, copysign0, isbool, isint, isscalar, 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, _1_3rd, \
12
- _1_5, _1_6th, _2_0, _2_3rd, _3_0, \
13
- _copysign_0_0, _isfinite, _over, remainder
11
+ _0_0, _0_125, _1_6th, _0_25, _1_3rd, _0_5, _1_0, \
12
+ _1_5, _copysign_0_0, _isfinite, _over, remainder
14
13
  from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
15
14
  _xError, _xkwds_get, _xkwds_pop2
16
- from pygeodesy.fsums import _2float, Fsum, _fsum, fsum, fsum1_, _1primed, \
17
- Fmt, unstr
18
- from pygeodesy.interns import MISSING, _few_, _h_, _invokation_, _negative_, \
19
- _not_scalar_, _SPACE_, _too_
15
+ from pygeodesy.fsums import _2float, Fsum, fsum, fsum1_, _1primed, Fmt, unstr
16
+ from pygeodesy.interns import MISSING, _few_, _negative_, _not_scalar_, _too_
20
17
  from pygeodesy.lazily import _ALL_LAZY, _sys_version_info2
21
18
  # from pygeodesy.streprs import Fmt, unstr # from .fsums
22
19
  from pygeodesy.units import Int_, _isHeight, _isRadius, Float_ # PYCHOK for .heights
@@ -25,21 +22,14 @@ from math import fabs, sqrt # pow
25
22
  import operator as _operator # in .datums, .trf, .utm
26
23
 
27
24
  __all__ = _ALL_LAZY.fmath
28
- __version__ = '24.04.17'
25
+ __version__ = '24.04.24'
29
26
 
30
27
  # sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
31
28
  _0_4142 = 0.41421356237309504880 # ... sqrt(2) - 1
29
+ _2_3rd = _1_3rd * 2
32
30
  _h_lt_b_ = 'abs(h) < abs(b)'
33
31
 
34
32
 
35
- def _Fsum__init__(inst, raiser=MISSING, **name_RESIDUAL):
36
- '''(INTERNAL) Init an C{Fsum} instance.
37
- '''
38
- Fsum.__init__(inst, **name_RESIDUAL) # PYCHOK self
39
- inst._fset_ps(_0_0)
40
- return {} if raiser is MISSING else dict(raiser=raiser)
41
-
42
-
43
33
  class Fdot(Fsum):
44
34
  '''Precision dot product.
45
35
  '''
@@ -104,7 +94,7 @@ class Fhorner(Fsum):
104
94
 
105
95
 
106
96
  class Fhypot(Fsum):
107
- '''Precision summation and hypotenuse, default C{power=2}.
97
+ '''Precision summation and hypotenuse, default C{root=2}.
108
98
  '''
109
99
  def __init__(self, *xs, **root_name_RESIDUAL_raiser):
110
100
  '''New L{Fhypot} hypotenuse of (the I{root} of) several components.
@@ -189,7 +179,7 @@ class Froot(Fsum):
189
179
  try:
190
180
  raiser = _Fsum__init__(self, **name_RESIDUAL_raiser)
191
181
  if xs:
192
- self. fadd(xs)
182
+ self.fadd(xs)
193
183
  self._fset(self.root(root, **raiser))
194
184
  except Exception as X:
195
185
  raise self._ErrorXs(X, xs, root=root)
@@ -203,7 +193,7 @@ class Fcbrt(Froot):
203
193
 
204
194
  @see: Class L{Froot} for further details.
205
195
  '''
206
- Froot.__init__(self, _3_0, *xs, **name_RESIDUAL_raiser)
196
+ Froot.__init__(self, 3, *xs, **name_RESIDUAL_raiser)
207
197
 
208
198
 
209
199
  class Fsqrt(Froot):
@@ -214,15 +204,24 @@ class Fsqrt(Froot):
214
204
 
215
205
  @see: Class L{Froot} for further details.
216
206
  '''
217
- Froot.__init__(self, _2_0, *xs, **name_RESIDUAL_raiser)
207
+ Froot.__init__(self, 2, *xs, **name_RESIDUAL_raiser)
208
+
209
+
210
+ def _Fsum__init__(inst, raiser=MISSING, **name_RESIDUAL):
211
+ '''(INTERNAL) Init an C{F...} instance above.
212
+ '''
213
+ Fsum.__init__(inst, **name_RESIDUAL) # PYCHOK self
214
+ inst._fset_ps(_0_0)
215
+ return {} if raiser is MISSING else dict(raiser=raiser)
218
216
 
219
217
 
220
218
  def bqrt(x):
221
- '''Return the 4-th, I{bi-quadratic} or I{quartic} root, M{x**(1 / 4)}.
219
+ '''Return the 4-th, I{bi-quadratic} or I{quartic} root, M{x**(1 / 4)},
220
+ preserving C{type(B{x})}.
222
221
 
223
- @arg x: Value (C{scalar}).
222
+ @arg x: Value (C{scalar} or L{Fsum} instance).
224
223
 
225
- @return: I{Quartic} root (C{float}).
224
+ @return: I{Quartic} root (C{float} or L{Fsum}).
226
225
 
227
226
  @raise ValueError: Negative B{C{x}}.
228
227
 
@@ -232,70 +231,76 @@ def bqrt(x):
232
231
 
233
232
 
234
233
  try:
235
- from math import cbrt # Python 3.11+
236
-
237
- def cbrt2(x):
238
- '''Compute the cube root I{squared} M{x**(2/3)}.
239
- '''
240
- return cbrt(x)**2 # cbrt(-0.0*2) == -0.0
234
+ from math import cbrt as _cbrt # Python 3.11+
241
235
 
242
236
  except ImportError: # Python 3.10-
243
237
 
244
- def cbrt(x):
245
- '''Compute the cube root M{x**(1/3)}.
246
-
247
- @arg x: Value (C{scalar}).
248
-
249
- @return: Cubic root (C{float}).
250
-
251
- @see: Functions L{cbrt2} and L{sqrt3}.
238
+ def _cbrt(x):
239
+ '''(INTERNAL) Compute the I{signed}, cube root M{x**(1/3)}.
252
240
  '''
253
241
  # <https://archive.lib.MSU.edu/crcmath/math/math/r/r021.htm>
254
242
  # simpler and more accurate than Ken Turkowski's CubeRoot, see
255
243
  # <https://People.FreeBSD.org/~lstewart/references/apple_tr_kt32_cuberoot.pdf>
256
- return _copysign(pow(fabs(x), _1_3rd), x) # cbrt(-0.0) == -0.0
244
+ return _copysign(pow(fabs(x), _1_3rd), x) # to avoid complex
257
245
 
258
- def cbrt2(x): # PYCHOK attr
259
- '''Compute the cube root I{squared} M{x**(2/3)}.
260
246
 
261
- @arg x: Value (C{scalar}).
247
+ def cbrt(x):
248
+ '''Compute the cube root M{x**(1/3)}, preserving C{type(B{x})}.
262
249
 
263
- @return: Cube root I{squared} (C{float}).
250
+ @arg x: Value (C{scalar} or L{Fsum} instance).
264
251
 
265
- @see: Functions L{cbrt} and L{sqrt3}.
266
- '''
267
- return pow(fabs(x), _2_3rd) # XXX pow(fabs(x), _1_3rd)**2
252
+ @return: Cubic root (C{float} or L{Fsum}).
253
+
254
+ @see: Functions L{cbrt2} and L{sqrt3}.
255
+ '''
256
+ if isinstance(x, Fsum):
257
+ r = (-(-x).pow(_1_3rd)) if x < 0 else x.pow(_1_3rd)
258
+ else:
259
+ r = _cbrt(x)
260
+ return r # cbrt(-0.0) == -0.0
261
+
262
+
263
+ def cbrt2(x): # PYCHOK attr
264
+ '''Compute the cube root I{squared} M{x**(2/3)}, preserving C{type(B{x})}.
265
+
266
+ @arg x: Value (C{scalar} or L{Fsum} instance).
267
+
268
+ @return: Cube root I{squared} (C{float} or L{Fsum}).
269
+
270
+ @see: Functions L{cbrt} and L{sqrt3}.
271
+ '''
272
+ return abs(x).pow(_2_3rd) if isinstance(x, Fsum) else _cbrt(x**2)
268
273
 
269
274
 
270
275
  def euclid(x, y):
271
276
  '''I{Appoximate} the norm M{sqrt(x**2 + y**2)} by
272
277
  M{max(abs(x), abs(y)) + min(abs(x), abs(y)) * 0.4142...}.
273
278
 
274
- @arg x: X component (C{scalar}).
275
- @arg y: Y component (C{scalar}).
279
+ @arg x: X component (C{scalar} or L{Fsum} instance).
280
+ @arg y: Y component (C{scalar} or L{Fsum} instance).
276
281
 
277
- @return: Appoximate norm (C{float}).
282
+ @return: Appoximate norm (C{float} or L{Fsum}).
278
283
 
279
284
  @see: Function L{euclid_}.
280
285
  '''
281
- x, y = fabs(x), fabs(y)
286
+ x, y = abs(x), abs(y) # NOT fabs!
282
287
  if x < y:
283
288
  x, y = y, x
284
289
  return x + y * _0_4142 # XXX * _0_5 before 20.10.02
285
290
 
286
291
 
287
292
  def euclid_(*xs):
288
- '''I{Appoximate} the norm M{sqrt(sum(x**2 for x in xs))}
289
- by cascaded L{euclid}.
293
+ '''I{Appoximate} the norm M{sqrt(sum(x**2 for x in xs))} by
294
+ cascaded L{euclid}.
290
295
 
291
- @arg xs: X arguments, positional (C{scalar}s).
296
+ @arg xs: X arguments, positional (C{scalar}s or L{Fsum} instances).
292
297
 
293
- @return: Appoximate norm (C{float}).
298
+ @return: Appoximate norm (C{float} or L{Fsum}).
294
299
 
295
300
  @see: Function L{euclid}.
296
301
  '''
297
302
  e = _0_0
298
- for x in sorted(map(fabs, xs)): # XXX not reverse=True
303
+ for x in sorted(map(abs, xs)): # NOT fabs, reverse=True!
299
304
  # e = euclid(x, e)
300
305
  if e < x:
301
306
  e, x = x, e
@@ -388,8 +393,8 @@ def fatan2(y, x):
388
393
  def favg(v1, v2, f=_0_5):
389
394
  '''Return the average of two values.
390
395
 
391
- @arg v1: One value (C{scalar}).
392
- @arg v2: Other value (C{scalar}).
396
+ @arg v1: One value (C{scalar} or L{Fsum} instance).
397
+ @arg v2: Other value (C{scalar} or L{Fsum} instance).
393
398
  @kwarg f: Optional fraction (C{float}).
394
399
 
395
400
  @return: M{v1 + f * (v2 - v1)} (C{float}).
@@ -606,6 +611,39 @@ except ImportError:
606
611
  return freduce(_operator.mul, xs, start)
607
612
 
608
613
 
614
+ def frandoms(n, seeded=None):
615
+ '''Generate C{n} (long) lists of random C{floats}.
616
+
617
+ @arg n: Number of lists to generate (C{int}, non-negative).
618
+ @kwarg seeded: If C{scalar}, use C{random.seed(B{seeded})} or
619
+ if C{True}, seed using today's C{year-day}.
620
+
621
+ @see: U{Hettinger<https://GitHub.com/ActiveState/code/tree/master/recipes/
622
+ Python/393090_Binary_floating_point_summatiaccurate_full/recipe-393090.py>}.
623
+ '''
624
+ from random import gauss, random, seed, shuffle
625
+
626
+ if seeded is None:
627
+ pass
628
+ elif seeded and isbool(seeded):
629
+ from time import localtime
630
+ seed(localtime().tm_yday)
631
+ elif isscalar(seeded):
632
+ seed(seeded)
633
+
634
+ c = (7, 1e100, -7, -1e100, -9e-20, 8e-20) * 7
635
+ for _ in range(n):
636
+ s = 0
637
+ t = list(c)
638
+ _a = t.append
639
+ for _ in range(n * 8):
640
+ v = gauss(0, random())**7 - s
641
+ _a(v)
642
+ s += v
643
+ shuffle(t)
644
+ yield t
645
+
646
+
609
647
  def frange(start, number, step=1):
610
648
  '''Generate a range of C{float}s.
611
649
 
@@ -715,8 +753,8 @@ if _sys_version_info2 < (3, 8): # PYCHOK no cover
715
753
  computed as M{hypot_(*((c1 - c2) for c1, c2 in zip(p1, p2)))},
716
754
  provided I{p1} and I{p2} have the same, non-zero length I{n}.
717
755
  '''
718
- h, x2 = _h_x2(xs, hypot_)
719
- return (h * sqrt(x2)) if x2 else _0_0
756
+ _, R = _h_xs2(xs, True, hypot_)
757
+ return float(R)
720
758
 
721
759
  elif _sys_version_info2 < (3, 10):
722
760
  # In Python 3.8 and 3.9 C{math.hypot} is inaccurate, see
@@ -732,13 +770,8 @@ elif _sys_version_info2 < (3, 10):
732
770
 
733
771
  @return: C{sqrt(B{x}**2 + B{y}**2)} (C{float}).
734
772
  '''
735
- if x:
736
- h = sqrt(x**2 + y**2) if y else fabs(x)
737
- elif y:
738
- h = fabs(y)
739
- else:
740
- h = _0_0
741
- return h
773
+ return (float(Fhypot(x, y, raiser=False)) if y else
774
+ fabs(x)) if x else fabs(y)
742
775
 
743
776
  from math import hypot as hypot_ # PYCHOK in Python 3.8 and 3.9
744
777
  else:
@@ -746,29 +779,32 @@ else:
746
779
  hypot_ = hypot
747
780
 
748
781
 
749
- def _h_x2(xs, which):
782
+ def _h_xs2(xs, pot_, which):
750
783
  '''(INTERNAL) Helper for L{hypot_} and L{hypot2_}.
751
784
  '''
752
785
  n, xs = len2(xs)
753
786
  if n > 0:
754
- h = float(max(map(fabs, xs)))
787
+ h = float(max(map(abs, xs))) # NOT fabs!
755
788
  if h < EPS0:
756
- x2 = _0_0
789
+ R = _0_0
757
790
  elif n > 1:
758
- _h = (_1_0 / h) if h != _1_0 else _1_0
759
- x2 = _fsum(_1primed((x * _h)**2 for x in xs))
791
+ if pot_:
792
+ if h != _1_0:
793
+ xs = ((x / h) for x in xs)
794
+ R = Fhypot(*xs, raiser=False) * h
795
+ else:
796
+ R = Fpowers(2, *xs)
760
797
  else:
761
- x2 = _1_0
762
- return h, x2
798
+ R = h if pot_ else (h**2)
799
+ return h, R
763
800
 
764
- t = Fmt.PAREN(which.__name__, xs)
765
- raise _ValueError(t, txt=_too_(_few_))
801
+ raise _ValueError(unstr(which, xs), txt=_too_(_few_))
766
802
 
767
803
 
768
804
  def hypot1(x):
769
805
  '''Compute the norm M{sqrt(1 + x**2)}.
770
806
 
771
- @arg x: Argument (C{scalar}).
807
+ @arg x: Argument (C{scalar} or L{Fsum} instance).
772
808
 
773
809
  @return: Norm (C{float}).
774
810
  '''
@@ -778,12 +814,12 @@ def hypot1(x):
778
814
  def hypot2(x, y):
779
815
  '''Compute the I{squared} norm M{x**2 + y**2}.
780
816
 
781
- @arg x: X argument (C{scalar}).
782
- @arg y: Y argument (C{scalar}).
817
+ @arg x: X argument (C{scalar} or L{Fsum} instance).
818
+ @arg y: Y argument (C{scalar} or L{Fsum} instance).
783
819
 
784
- @return: C{B{x}**2 + B{y}**2} (C{float}).
820
+ @return: C{B{x}**2 + B{y}**2} (C{float} or L{Fsum}).
785
821
  '''
786
- if fabs(x) < fabs(y):
822
+ if abs(x) < abs(y): # NOT fabs!
787
823
  x, y = y, x
788
824
  if x:
789
825
  h2 = x**2
@@ -795,9 +831,10 @@ def hypot2(x, y):
795
831
 
796
832
 
797
833
  def hypot2_(*xs):
798
- '''Compute the I{squared} norm C{sum(x**2 for x in B{xs})}.
834
+ '''Compute the I{squared} norm C{fsum(x**2 for x in B{xs})}.
799
835
 
800
- @arg xs: X arguments (C{scalar}s), all positional.
836
+ @arg xs: X arguments (C{scalar}s or L{Fsum} instances),
837
+ all positional.
801
838
 
802
839
  @return: Squared norm (C{float}).
803
840
 
@@ -807,8 +844,8 @@ def hypot2_(*xs):
807
844
 
808
845
  @see: Function L{hypot_}.
809
846
  '''
810
- h, x2 = _h_x2(xs, hypot2_)
811
- return (h**2 * x2) if x2 else _0_0
847
+ _, R = _h_xs2(xs, False, hypot2_)
848
+ return float(R)
812
849
 
813
850
 
814
851
  def _map_mul(a, b, where):
@@ -860,12 +897,13 @@ def norm_(*xs):
860
897
  or zero norm.
861
898
  '''
862
899
  try:
900
+ i = x = h = None
863
901
  h = hypot_(*xs)
864
902
  _h = (_1_0 / h) if h else _0_0
865
903
  for i, x in enumerate(xs):
866
904
  yield x * _h
867
- except Exception as e:
868
- raise _xError(e, Fmt.SQUARE(xs=i), x, _h_, h)
905
+ except Exception as X:
906
+ raise _xError(X, Fmt.SQUARE(xs=i), x, h=h)
869
907
 
870
908
 
871
909
  def _powers(x, n):
@@ -880,34 +918,40 @@ def _powers(x, n):
880
918
  def _root(x, p, where):
881
919
  '''(INTERNAL) Raise C{x} to power C{0 < p < 1}.
882
920
  '''
883
- if x < 0:
884
- t = _SPACE_(_invokation_, where.__name__)
885
- raise _ValueError(unstr(t, x), txt=_negative_)
886
- return pow(x, p) if x else _0_0
921
+ try:
922
+ if x > 0:
923
+ return pow(x, p)
924
+ elif x < 0:
925
+ raise ValueError(_negative_)
926
+ except Exception as X:
927
+ raise _xError(X, unstr(where, x))
928
+ return _0_0
887
929
 
888
930
 
889
931
  def sqrt0(x, Error=None):
890
- '''Return the square root iff C{B{x} >} L{EPS02}.
932
+ '''Return the square root C{sqrt(B{x})} iff C{B{x} > }L{EPS02},
933
+ preserving C{type(B{x})}.
891
934
 
892
- @arg x: Value (C{scalar}).
935
+ @arg x: Value (C{scalar} or L{Fsum} instance).
893
936
  @kwarg Error: Error to raise for negative B{C{x}}.
894
937
 
895
- @return: Square root (C{float}) or C{0.0}.
938
+ @return: Square root (C{float} or L{Fsum}) or C{0.0}.
896
939
 
897
940
  @note: Any C{B{x} < }L{EPS02} I{including} C{B{x} < 0}
898
941
  returns C{0.0}.
899
942
  '''
900
943
  if Error and x < 0:
901
- raise Error(Fmt.PAREN(sqrt=x))
902
- return sqrt(x) if x > EPS02 else (_0_0 if x < EPS02 else EPS0)
944
+ raise Error(unstr(sqrt0, x))
945
+ return _root(x, _0_5, sqrt0) if x > EPS02 else (_0_0 if x < EPS02 else EPS0)
903
946
 
904
947
 
905
948
  def sqrt3(x):
906
- '''Return the square root, I{cubed} M{sqrt(x)**3} or M{sqrt(x**3)}.
949
+ '''Return the square root, I{cubed} M{sqrt(x)**3} or M{sqrt(x**3)},
950
+ preserving C{type(B{x})}.
907
951
 
908
- @arg x: Value (C{scalar}).
952
+ @arg x: Value (C{scalar} or L{Fsum} instance).
909
953
 
910
- @return: Square root I{cubed} (C{float}).
954
+ @return: Square root I{cubed} (C{float} or L{Fsum}).
911
955
 
912
956
  @raise ValueError: Negative B{C{x}}.
913
957
 
@@ -956,11 +1000,12 @@ def sqrt_a(h, b):
956
1000
 
957
1001
 
958
1002
  def zcrt(x):
959
- '''Return the 6-th, I{zenzi-cubic} root, M{x**(1 / 6)}.
1003
+ '''Return the 6-th, I{zenzi-cubic} root, M{x**(1 / 6)},
1004
+ preserving C{type(B{x})}.
960
1005
 
961
- @arg x: Value (C{scalar}).
1006
+ @arg x: Value (C{scalar} or L{Fsum} instance).
962
1007
 
963
- @return: I{Zenzi-cubic} root (C{float}).
1008
+ @return: I{Zenzi-cubic} root (C{float} or L{Fsum}).
964
1009
 
965
1010
  @see: Functions L{bqrt} and L{zqrt}.
966
1011
 
@@ -970,11 +1015,12 @@ def zcrt(x):
970
1015
 
971
1016
 
972
1017
  def zqrt(x):
973
- '''Return the 8-th, I{zenzi-quartic} or I{squared-quartic} root, M{x**(1 / 8)}.
1018
+ '''Return the 8-th, I{zenzi-quartic} or I{squared-quartic} root,
1019
+ M{x**(1 / 8)}, preserving C{type(B{x})}.
974
1020
 
975
- @arg x: Value (C{scalar}).
1021
+ @arg x: Value (C{scalar} or L{Fsum} instance).
976
1022
 
977
- @return: I{Zenzi-quartic} root (C{float}).
1023
+ @return: I{Zenzi-quartic} root (C{float} or L{Fsum}).
978
1024
 
979
1025
  @see: Functions L{bqrt} and L{zcrt}.
980
1026
 
pygeodesy/fstats.py CHANGED
@@ -12,8 +12,8 @@ from pygeodesy.basics import isodd, islistuple, _xinstanceof, \
12
12
  from pygeodesy.constants import _0_0, _2_0, _3_0, _4_0, _6_0, _xError
13
13
  # from pygeodesy.errors import _xError # from .constants
14
14
  from pygeodesy.fmath import hypot2, sqrt
15
- from pygeodesy.fsums import _2float, Fsum, Fmt
16
- from pygeodesy.interns import NN, _iadd_op_, _invalid_, _other_, _SPACE_
15
+ from pygeodesy.fsums import _2float, Fsum, _iadd_op_, Fmt
16
+ from pygeodesy.interns import NN, _invalid_, _other_, _SPACE_
17
17
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
18
18
  from pygeodesy.named import _Named, _NotImplemented, property_RO
19
19
  # from pygeodesy.props import property_RO # from .named
@@ -22,7 +22,7 @@ from pygeodesy.named import _Named, _NotImplemented, property_RO
22
22
  # from math import sqrt # from .fmath
23
23
 
24
24
  __all__ = _ALL_LAZY.fstats
25
- __version__ = '24.04.07'
25
+ __version__ = '24.04.26'
26
26
 
27
27
  _Floats = Fsum, float
28
28
  _Scalar = _Floats + (int,) # XXX basics._Ints is ABCMeta in Python 2