pygeodesy 24.5.6__py2.py3-none-any.whl → 24.5.8__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.5.6.dist-info → PyGeodesy-24.5.8.dist-info}/METADATA +4 -4
- {PyGeodesy-24.5.6.dist-info → PyGeodesy-24.5.8.dist-info}/RECORD +10 -10
- pygeodesy/__init__.py +3 -3
- pygeodesy/basics.py +12 -3
- pygeodesy/fmath.py +2 -2
- pygeodesy/fstats.py +276 -213
- pygeodesy/fsums.py +33 -18
- pygeodesy/interns.py +2 -1
- {PyGeodesy-24.5.6.dist-info → PyGeodesy-24.5.8.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.5.6.dist-info → PyGeodesy-24.5.8.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyGeodesy
|
|
3
|
-
Version: 24.5.
|
|
3
|
+
Version: 24.5.8
|
|
4
4
|
Summary: Pure Python geodesy tools
|
|
5
5
|
Home-page: https://GitHub.com/mrJean1/PyGeodesy
|
|
6
6
|
Author: Jean M. Brouwers
|
|
@@ -114,7 +114,7 @@ line: ``epydoc --html --no-private --no-source --name=PyGeodesy --url=... -v pyg
|
|
|
114
114
|
Tests
|
|
115
115
|
=====
|
|
116
116
|
|
|
117
|
-
The tests ran with Python 3.12.
|
|
117
|
+
The tests ran with Python 3.12.3 (with geographiclib_ 2.0), 3.11.5 (with geographiclib_ 2.0, numpy_
|
|
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
|
|
@@ -137,7 +137,7 @@ Python 3.11.5, 3.10.10 and 2.7.18 (all with geographiclib_ 1.52) on `Windows 10`
|
|
|
137
137
|
A single-File and single-Directory application with ``pygeodesy`` has been bundled using PyInstaller_
|
|
138
138
|
3.4 and 64-bit Python 3.7.4 and 3.7.3 on macOS 10.13.6 High Sierra.
|
|
139
139
|
|
|
140
|
-
Previously, the tests were run with Python 3.12.0-
|
|
140
|
+
Previously, the tests were run with Python 3.12.0-2, 3.11.2-4, 3.10.1-7, 3.9.1, 3.8.7, 3.7.1, 2.7.15, PyPy_
|
|
141
141
|
7.3.12 (Python 3.10.12), 7.3.1 (Python 3.6.9) and PyPy_ 7.1.1 (Python 2.7.13) (and geographiclib_ 1.52,
|
|
142
142
|
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, 1.4.1, 1.5.2 or 1.8.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,
|
|
@@ -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: May
|
|
161
|
+
*Last updated: May 08, 2024.*
|
|
162
162
|
|
|
163
163
|
License
|
|
164
164
|
=======
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
pygeodesy/LICENSE,sha256=YfgAiyxOwY6P9Kkb1_5XN81nueTLrpb3Ffkv3EuPgFU,1144
|
|
2
|
-
pygeodesy/__init__.py,sha256=
|
|
2
|
+
pygeodesy/__init__.py,sha256=aWftpUqOeH1Uul8uN_kDAXbFL0TqLXDhynBhCmgpxoQ,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=
|
|
6
|
+
pygeodesy/basics.py,sha256=GWsiv-Zl2qOZoW7wPwIG7yLd2FwYLUvsq8c6hZdgsFE,28453
|
|
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
|
|
@@ -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=RHZ_f1zcOIyLQYProiQznaAOhojbDPDR4XbblXJMuS0,27232
|
|
27
27
|
pygeodesy/etm.py,sha256=joEhU2lw9ehRv101nRpZvXq8hOYAEzdcYFpif9_obfk,44585
|
|
28
|
-
pygeodesy/fmath.py,sha256=
|
|
28
|
+
pygeodesy/fmath.py,sha256=MylYc4nkVtDWI6U-R4hGmXcq-9tUUBmnlM795weezec,33477
|
|
29
29
|
pygeodesy/formy.py,sha256=Rces4Q5ecED0WVfuI9mQzeyHE54LDowYfI6faBHpyeA,74536
|
|
30
30
|
pygeodesy/frechet.py,sha256=qgee-ISBtT7Ov3rJkcd_t-WeXTbeNoMSQuMa0j3MyQc,33512
|
|
31
|
-
pygeodesy/fstats.py,sha256=
|
|
32
|
-
pygeodesy/fsums.py,sha256=
|
|
31
|
+
pygeodesy/fstats.py,sha256=23XqQRoegfeE4xEbbcgcsuw4JGEAe0OPvR8Jn2W8U-8,28414
|
|
32
|
+
pygeodesy/fsums.py,sha256=M9btYPykj5JHvO4gg6wkKPGKlg9R4ZfdoFFKcgmQVno,78284
|
|
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,7 +37,7 @@ 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=
|
|
40
|
+
pygeodesy/interns.py,sha256=WuQe08kItPIwSJ9J1bUxI5yVOX_eNfpGIMpKHzoCqAw,30245
|
|
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
|
|
@@ -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.5.
|
|
113
|
-
PyGeodesy-24.5.
|
|
114
|
-
PyGeodesy-24.5.
|
|
115
|
-
PyGeodesy-24.5.
|
|
112
|
+
PyGeodesy-24.5.8.dist-info/METADATA,sha256=iiCbD7PToGDSIyOreeEG4YnJO2j2TZRnNvKeQdOVLQQ,19363
|
|
113
|
+
PyGeodesy-24.5.8.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
114
|
+
PyGeodesy-24.5.8.dist-info/top_level.txt,sha256=cEQPatCXzKZqrivpULC5V5fuy9_V_bAwaP_gUGid7pQ,10
|
|
115
|
+
PyGeodesy-24.5.8.dist-info/RECORD,,
|
pygeodesy/__init__.py
CHANGED
|
@@ -121,7 +121,7 @@ C{epydoc --html --no-private --no-source --name=PyGeodesy --url=... -v pygeodesy
|
|
|
121
121
|
Tests
|
|
122
122
|
=====
|
|
123
123
|
|
|
124
|
-
The tests ran with Python 3.12.
|
|
124
|
+
The tests ran with Python 3.12.3 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0,
|
|
125
125
|
Python 3.11.5 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0, U{numpy
|
|
126
126
|
<https://PyPI.org/project/numpy>} 1.24.2 and U{scipy<https://PyPI.org/project/scipy>} 1.10.1), Python
|
|
127
127
|
3.10.8 (with U{geographiclib <https://PyPI.org/project/geographiclib>} 2.0, U{numpy
|
|
@@ -155,7 +155,7 @@ U{Debian 11<https://Cirrus-CI.com/github/mrJean1/PyGeodesy/master>} in 64-bit on
|
|
|
155
155
|
A single-File and single-Directory application with C{pygeodesy} has been bundled using U{PyInstaller
|
|
156
156
|
<https://PyPI.org/project/pyinstaller>} 3.4 and 64-bit Python 3.7.3 on macOS 10.13.6 High Sierra.
|
|
157
157
|
|
|
158
|
-
Previously, the tests were run with Python 3.12.0-
|
|
158
|
+
Previously, the tests were run with Python 3.12.0-2, 3.11.2-4, 3.10.1-7, 3.9.1, 3.8.7, 3.7.1, 2.7.15, U{PyPy
|
|
159
159
|
<https://PyPy.org>} 7.3.12 (Python 3.10.12), 7.3.1 (Python 3.6.9) and U{PyPy<https://PyPy.org>} 7.1.1 (Python
|
|
160
160
|
2.7.13) (and U{geographiclib <https://PyPI.org/project/geographiclib>} 1.52, U{numpy<https://PyPI.org/project/numpy>}
|
|
161
161
|
1.16.3, 1.16.4, 1.16.6, 1.19.0, 1.19.4, 1.19.5 or 1.22.4 and U{scipy<https://PyPI.org/project/scipy>} 1.2.1, 1.4.1,
|
|
@@ -585,7 +585,7 @@ else:
|
|
|
585
585
|
_init__all__ = False
|
|
586
586
|
|
|
587
587
|
from pygeodesy.interns import _DOT_, _version2 # PYCHOK import
|
|
588
|
-
__version__ = '24.05.
|
|
588
|
+
__version__ = '24.05.08'
|
|
589
589
|
# see setup.py for similar logic
|
|
590
590
|
version = _DOT_(*_version2(__version__, n=3))
|
|
591
591
|
|
pygeodesy/basics.py
CHANGED
|
@@ -21,7 +21,8 @@ from pygeodesy.errors import _AttributeError, _ImportError, _NotImplementedError
|
|
|
21
21
|
_xkwds_get
|
|
22
22
|
from pygeodesy.interns import MISSING, NN, _1_, _by_, _COMMA_, _DOT_, _DEPRECATED_, \
|
|
23
23
|
_ELLIPSIS4_, _enquote, _EQUAL_, _in_, _invalid_, _N_A_, \
|
|
24
|
-
_not_scalar_, _SPACE_, _UNDER_, _version_,
|
|
24
|
+
_not_, _not_scalar_, _odd_, _SPACE_, _UNDER_, _version_, \
|
|
25
|
+
_version_info
|
|
25
26
|
# from pygeodesy.latlonBase import LatLonBase # _MODS
|
|
26
27
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _FOR_DOCS, \
|
|
27
28
|
_getenv, LazyImportError, _sys, _sys_version_info2
|
|
@@ -34,13 +35,12 @@ from math import copysign as _copysign
|
|
|
34
35
|
import inspect as _inspect
|
|
35
36
|
|
|
36
37
|
__all__ = _ALL_LAZY.basics
|
|
37
|
-
__version__ = '24.
|
|
38
|
+
__version__ = '24.05.08'
|
|
38
39
|
|
|
39
40
|
_0_0 = 0.0 # in .constants
|
|
40
41
|
_below_ = 'below'
|
|
41
42
|
_list_tuple_types = (list, tuple)
|
|
42
43
|
_list_tuple_set_types = (list, tuple, set)
|
|
43
|
-
_odd_ = 'odd'
|
|
44
44
|
_PYGEODESY_XPACKAGES_ = 'PYGEODESY_XPACKAGES'
|
|
45
45
|
_required_ = 'required'
|
|
46
46
|
|
|
@@ -786,6 +786,15 @@ def _xisscalar(**names_values):
|
|
|
786
786
|
raise _TypeError(n, v, txt=_not_scalar_)
|
|
787
787
|
|
|
788
788
|
|
|
789
|
+
def _xiterable(obj):
|
|
790
|
+
'''(INTERNAL) Raise C{TypeError} if C{obj} is not iterable.
|
|
791
|
+
'''
|
|
792
|
+
# https://PyPI.org/project/isiterable/
|
|
793
|
+
if not (hasattr(obj, '__iter__') or
|
|
794
|
+
hasattr(obj, '__getitem__')):
|
|
795
|
+
raise TypeError(_not_(_xiterable.__name__[2:]))
|
|
796
|
+
|
|
797
|
+
|
|
789
798
|
def _xnumpy(where, *required):
|
|
790
799
|
'''(INTERNAL) Import C{numpy} and check required version.
|
|
791
800
|
'''
|
pygeodesy/fmath.py
CHANGED
|
@@ -24,7 +24,7 @@ from math import fabs, sqrt # pow
|
|
|
24
24
|
import operator as _operator # in .datums, .trf, .utm
|
|
25
25
|
|
|
26
26
|
__all__ = _ALL_LAZY.fmath
|
|
27
|
-
__version__ = '24.05.
|
|
27
|
+
__version__ = '24.05.07'
|
|
28
28
|
|
|
29
29
|
# sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
|
|
30
30
|
_0_4142 = 0.41421356237309504880 # ... sqrt(2) - 1
|
|
@@ -539,7 +539,7 @@ def fidw(xs, ds, beta=2):
|
|
|
539
539
|
i += 1 # len(xs) < i < len(ds)
|
|
540
540
|
except Exception as X:
|
|
541
541
|
_I = Fmt.INDEX
|
|
542
|
-
raise _xError(X, _I(
|
|
542
|
+
raise _xError(X, _I(xs=i), x, _I(ds=i), d)
|
|
543
543
|
else: # b == 0
|
|
544
544
|
x = fsum(xs) / n # fmean(xs)
|
|
545
545
|
i = n
|
pygeodesy/fstats.py
CHANGED
|
@@ -7,43 +7,37 @@ L{pygeodesy.Fsum}, precision floating point summation.
|
|
|
7
7
|
# make sure int/int division yields float quotient, see .basics
|
|
8
8
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
9
9
|
|
|
10
|
-
from pygeodesy.basics import
|
|
11
|
-
_xsubclassof, _zip
|
|
12
|
-
from pygeodesy.constants import _0_0, _2_0, _3_0, _4_0, _6_0
|
|
13
|
-
from pygeodesy.errors import _AssertionError, _xError
|
|
14
|
-
from pygeodesy.fmath import
|
|
15
|
-
from pygeodesy.fsums import
|
|
16
|
-
_isAn,
|
|
17
|
-
from pygeodesy.interns import NN,
|
|
10
|
+
from pygeodesy.basics import isscalar, isodd, _xinstanceof, \
|
|
11
|
+
_xiterable, _xsubclassof, _zip
|
|
12
|
+
from pygeodesy.constants import _0_0, _1_0, _2_0, _3_0, _4_0, _6_0
|
|
13
|
+
from pygeodesy.errors import _AssertionError, _ValueError, _xError
|
|
14
|
+
from pygeodesy.fmath import Fsqrt
|
|
15
|
+
from pygeodesy.fsums import _2finite, _Float, Fsum, _iadd_op_, \
|
|
16
|
+
_isAn, _isFsumTuple, _Tuple, Fmt
|
|
17
|
+
from pygeodesy.interns import NN, _odd_, _SPACE_
|
|
18
18
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
|
|
19
19
|
from pygeodesy.named import _Named, _NotImplemented, property_RO
|
|
20
20
|
# from pygeodesy.props import property_RO # from .named
|
|
21
21
|
# from pygeodesy.streprs import Fmt # from .fsums
|
|
22
22
|
|
|
23
|
-
# from math import sqrt # from .fmath
|
|
24
|
-
|
|
25
23
|
__all__ = _ALL_LAZY.fstats
|
|
26
|
-
__version__ = '24.05.
|
|
27
|
-
|
|
28
|
-
_Floats = _Fsum_Fsum2Tuple_types + (_Float,)
|
|
29
|
-
_Scalar = _Floats + (int,) # XXX basics._Ints is ABCMeta in Python 2
|
|
30
|
-
try:
|
|
31
|
-
_Scalar += (long,)
|
|
32
|
-
except NameError: # Python 3+
|
|
33
|
-
pass
|
|
24
|
+
__version__ = '24.05.08'
|
|
34
25
|
|
|
35
26
|
|
|
36
27
|
def _2Floats(**xs):
|
|
37
28
|
'''(INTERNAL) Yield each value as C{float} or L{Fsum}.
|
|
38
29
|
'''
|
|
39
30
|
try:
|
|
40
|
-
|
|
41
|
-
except Exception as
|
|
42
|
-
raise _AssertionError(xs=xs, cause=
|
|
31
|
+
name, xs = xs.popitem()
|
|
32
|
+
except Exception as X:
|
|
33
|
+
raise _AssertionError(xs=xs, cause=X)
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
try:
|
|
36
|
+
i, x = 0, None
|
|
37
|
+
for i, x in enumerate(xs): # don't unravel Fsums
|
|
38
|
+
yield x._Fsum if _isFsumTuple(x) else _2finite(x)
|
|
39
|
+
except Exception as X:
|
|
40
|
+
raise _xError(X, Fmt.INDEX(name, i), x)
|
|
47
41
|
|
|
48
42
|
|
|
49
43
|
def _sampled(n, sample):
|
|
@@ -58,9 +52,11 @@ class _FstatsNamed(_Named):
|
|
|
58
52
|
_n = 0
|
|
59
53
|
|
|
60
54
|
def __add__(self, other):
|
|
61
|
-
'''Sum of this and
|
|
55
|
+
'''Sum of this and an other instance or a C{scalar} or an
|
|
56
|
+
L{Fsum}, L{Fsum2Tuple} or
|
|
57
|
+
.
|
|
62
58
|
'''
|
|
63
|
-
f = self.
|
|
59
|
+
f = self.copy(name=self.__add__.__name__) # PYCHOK expected
|
|
64
60
|
f += other
|
|
65
61
|
return f
|
|
66
62
|
|
|
@@ -73,7 +69,7 @@ class _FstatsNamed(_Named):
|
|
|
73
69
|
return _NotImplemented(self)
|
|
74
70
|
|
|
75
71
|
def __len__(self):
|
|
76
|
-
'''Return the I{total} number of accumulated
|
|
72
|
+
'''Return the I{total} number of accumulated C{Scalars} (C{int}).
|
|
77
73
|
'''
|
|
78
74
|
return self._n
|
|
79
75
|
|
|
@@ -90,14 +86,14 @@ class _FstatsNamed(_Named):
|
|
|
90
86
|
n = _SPACE_(self.classname, n) if n else self.classname
|
|
91
87
|
return Fmt.SQUARE(n, len(self))
|
|
92
88
|
|
|
93
|
-
def
|
|
89
|
+
def copy(self, deep=False, name=NN):
|
|
94
90
|
'''Copy this instance, C{shallow} or B{C{deep}}.
|
|
95
91
|
'''
|
|
96
|
-
n = name or self.
|
|
92
|
+
n = name or self.copy.__name__
|
|
97
93
|
f = _Named.copy(self, deep=deep, name=n)
|
|
98
94
|
return self._copy(f, self) # PYCHOK expected
|
|
99
95
|
|
|
100
|
-
|
|
96
|
+
fcopy = copy # for backward compatibility
|
|
101
97
|
|
|
102
98
|
|
|
103
99
|
class _FstatsBase(_FstatsNamed):
|
|
@@ -105,13 +101,13 @@ class _FstatsBase(_FstatsNamed):
|
|
|
105
101
|
'''
|
|
106
102
|
_Ms = ()
|
|
107
103
|
|
|
108
|
-
def _copy(self,
|
|
104
|
+
def _copy(self, d, s):
|
|
109
105
|
'''(INTERNAL) Copy C{B{c} = B{s}}.
|
|
110
106
|
'''
|
|
111
|
-
_xinstanceof(self.__class__,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return
|
|
107
|
+
_xinstanceof(self.__class__, d=d, s=s)
|
|
108
|
+
d._Ms = _Tuple(M.copy() for M in s._Ms) # deep=False
|
|
109
|
+
d._n = s._n
|
|
110
|
+
return d
|
|
115
111
|
|
|
116
112
|
def fadd(self, xs, sample=False): # PYCHOK no cover
|
|
117
113
|
'''I{Must be overloaded}.'''
|
|
@@ -120,84 +116,85 @@ class _FstatsBase(_FstatsNamed):
|
|
|
120
116
|
def fadd_(self, *xs, **sample):
|
|
121
117
|
'''Accumulate and return the current count.
|
|
122
118
|
|
|
123
|
-
@see: Method C{fadd}.
|
|
119
|
+
@see: Method C{fadd} for further details.
|
|
124
120
|
'''
|
|
125
121
|
return self.fadd(xs, **sample)
|
|
126
122
|
|
|
127
123
|
def fmean(self, xs=None):
|
|
128
124
|
'''Accumulate and return the current mean.
|
|
129
125
|
|
|
130
|
-
@kwarg xs: Iterable
|
|
126
|
+
@kwarg xs: Iterable of additional values (each C{scalar} or
|
|
127
|
+
an L{Fsum} or L{Fsum2Tuple} instance).
|
|
131
128
|
|
|
132
129
|
@return: Current, running mean (C{float}).
|
|
133
130
|
|
|
134
131
|
@see: Method C{fadd}.
|
|
135
132
|
'''
|
|
136
|
-
|
|
137
|
-
self.fadd(xs)
|
|
138
|
-
return self._M1.fsum()
|
|
133
|
+
return _Float(self._Mean(xs))
|
|
139
134
|
|
|
140
135
|
def fmean_(self, *xs):
|
|
141
136
|
'''Accumulate and return the current mean.
|
|
142
137
|
|
|
143
|
-
@see: Method C{fmean}.
|
|
138
|
+
@see: Method C{fmean} for further details.
|
|
144
139
|
'''
|
|
145
140
|
return self.fmean(xs)
|
|
146
141
|
|
|
147
|
-
def fstdev(self, xs=None, sample
|
|
142
|
+
def fstdev(self, xs=None, **sample):
|
|
148
143
|
'''Accumulate and return the current standard deviation.
|
|
149
144
|
|
|
150
|
-
@
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
@arg xs: Iterable of additional values (each C{scalar} or an
|
|
146
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
147
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} deviation
|
|
148
|
+
instead of the I{population} deviation (C{bool}).
|
|
153
149
|
|
|
154
150
|
@return: Current, running (sample) standard deviation (C{float}).
|
|
155
151
|
|
|
156
152
|
@see: Method C{fadd}.
|
|
157
153
|
'''
|
|
158
|
-
|
|
159
|
-
return sqrt(v) if v > 0 else _0_0
|
|
154
|
+
return _Float(self._Stdev(xs, **sample))
|
|
160
155
|
|
|
161
156
|
def fstdev_(self, *xs, **sample):
|
|
162
157
|
'''Accumulate and return the current standard deviation.
|
|
163
158
|
|
|
164
|
-
@see: Method C{fstdev}.
|
|
159
|
+
@see: Method C{fstdev} for further details.
|
|
165
160
|
'''
|
|
166
161
|
return self.fstdev(xs, **sample)
|
|
167
162
|
|
|
168
|
-
def fvariance(self, xs=None, sample
|
|
163
|
+
def fvariance(self, xs=None, **sample):
|
|
169
164
|
'''Accumulate and return the current variance.
|
|
170
165
|
|
|
171
|
-
@
|
|
172
|
-
|
|
173
|
-
|
|
166
|
+
@arg xs: Iterable of additional values (each C{scalar} or an
|
|
167
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
168
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} variance
|
|
169
|
+
instead of the I{population} variance (C{bool}).
|
|
174
170
|
|
|
175
171
|
@return: Current, running (sample) variance (C{float}).
|
|
176
172
|
|
|
177
173
|
@see: Method C{fadd}.
|
|
178
174
|
'''
|
|
179
|
-
|
|
180
|
-
return _Float(self._M2 / _Float(n)) if n > 0 else _0_0
|
|
175
|
+
return _Float(self._Variance(xs, **sample))
|
|
181
176
|
|
|
182
177
|
def fvariance_(self, *xs, **sample):
|
|
183
178
|
'''Accumulate and return the current variance.
|
|
184
179
|
|
|
185
|
-
@see: Method C{fvariance}.
|
|
180
|
+
@see: Method C{fvariance} for further details.
|
|
186
181
|
'''
|
|
187
182
|
return self.fvariance(xs, **sample)
|
|
188
183
|
|
|
189
184
|
def _iadd_other(self, other):
|
|
190
|
-
'''(INTERNAL) Add
|
|
191
|
-
'''
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
185
|
+
'''(INTERNAL) Add one or several values.
|
|
186
|
+
'''
|
|
187
|
+
try:
|
|
188
|
+
if _isFsumTuple(other):
|
|
189
|
+
self.fadd_(other._Fsum)
|
|
190
|
+
elif isscalar(other):
|
|
191
|
+
self.fadd_(_2finite(other))
|
|
192
|
+
else: # iterable?
|
|
193
|
+
_xiterable(other)
|
|
198
194
|
self.fadd(other)
|
|
199
|
-
|
|
200
|
-
|
|
195
|
+
except Exception as x:
|
|
196
|
+
t = _SPACE_(self, _iadd_op_, repr(other))
|
|
197
|
+
raise _xError(x, t)
|
|
201
198
|
|
|
202
199
|
@property_RO
|
|
203
200
|
def _M1(self):
|
|
@@ -209,6 +206,25 @@ class _FstatsBase(_FstatsNamed):
|
|
|
209
206
|
'''(INTERNAL) get the 2nd Moment accumulator.'''
|
|
210
207
|
return self._Ms[1]
|
|
211
208
|
|
|
209
|
+
def _Mean(self, xs=None):
|
|
210
|
+
'''(INTERNAL) Return the current mean as L{Fsum}.
|
|
211
|
+
'''
|
|
212
|
+
if xs:
|
|
213
|
+
self.fadd(xs)
|
|
214
|
+
return self._M1 # .copy()
|
|
215
|
+
|
|
216
|
+
def _Stdev(self, xs=None, **sample):
|
|
217
|
+
'''(INTERNAL) Return the current (sample) standard deviation as L{Fsum}.
|
|
218
|
+
'''
|
|
219
|
+
V = self._Variance(xs, **sample)
|
|
220
|
+
return Fsqrt(V) if V > 0 else _0_0
|
|
221
|
+
|
|
222
|
+
def _Variance(self, xs=None, **sample):
|
|
223
|
+
'''(INTERNAL) Return the current (sample) variance as L{Fsum}.
|
|
224
|
+
'''
|
|
225
|
+
n = self.fadd(xs, **sample)
|
|
226
|
+
return (self._M2 / n) if n > 0 else _0_0
|
|
227
|
+
|
|
212
228
|
|
|
213
229
|
class Fcook(_FstatsBase):
|
|
214
230
|
'''U{Cook<https://www.JohnDCook.com/blog/skewness_kurtosis>}'s
|
|
@@ -222,12 +238,13 @@ class Fcook(_FstatsBase):
|
|
|
222
238
|
def __init__(self, xs=None, name=NN):
|
|
223
239
|
'''New L{Fcook} stats accumulator.
|
|
224
240
|
|
|
225
|
-
@
|
|
241
|
+
@arg xs: Iterable of additional values (each C{scalar} or
|
|
242
|
+
an L{Fsum} or L{Fsum2Tuple} instance).
|
|
226
243
|
@kwarg name: Optional name (C{str}).
|
|
227
244
|
|
|
228
245
|
@see: Method L{Fcook.fadd}.
|
|
229
246
|
'''
|
|
230
|
-
self._Ms =
|
|
247
|
+
self._Ms = _Tuple(Fsum() for _ in range(4)) # 1st, 2nd ... Moment
|
|
231
248
|
if name:
|
|
232
249
|
self.name = name
|
|
233
250
|
if xs:
|
|
@@ -236,14 +253,15 @@ class Fcook(_FstatsBase):
|
|
|
236
253
|
def __iadd__(self, other):
|
|
237
254
|
'''Add B{C{other}} to this L{Fcook} instance.
|
|
238
255
|
|
|
239
|
-
@arg other: An L{Fcook} instance or
|
|
240
|
-
|
|
256
|
+
@arg other: An L{Fcook} instance or value or iterable
|
|
257
|
+
of values (each C{scalar} or an L{Fsum}
|
|
258
|
+
or L{Fsum2Tuple} instance).
|
|
241
259
|
|
|
242
260
|
@return: This instance, updated (L{Fcook}).
|
|
243
261
|
|
|
244
|
-
@raise TypeError: Invalid B{C{other}}
|
|
262
|
+
@raise TypeError: Invalid B{C{other}}.
|
|
245
263
|
|
|
246
|
-
@raise ValueError: Invalid B{C{other}}.
|
|
264
|
+
@raise ValueError: Invalid or non-finite B{C{other}}.
|
|
247
265
|
|
|
248
266
|
@see: Method L{Fcook.fadd}.
|
|
249
267
|
'''
|
|
@@ -256,9 +274,9 @@ class Fcook(_FstatsBase):
|
|
|
256
274
|
B1, B2, B3, B4 = other._Ms
|
|
257
275
|
|
|
258
276
|
n = na + nb
|
|
259
|
-
|
|
277
|
+
_n = _1_0 / n
|
|
260
278
|
D = A1 - B1 # b1 - a1
|
|
261
|
-
Dn = D
|
|
279
|
+
Dn = D * _n
|
|
262
280
|
Dn2 = Dn**2 # d**2 / n**2
|
|
263
281
|
nab = na * nb
|
|
264
282
|
Dn3 = Dn2 * (D * nab)
|
|
@@ -271,16 +289,16 @@ class Fcook(_FstatsBase):
|
|
|
271
289
|
A4 += (Dn * Dn3) * (na2 - nab + nb2) # d**4 / n**3
|
|
272
290
|
|
|
273
291
|
A3 += B3
|
|
274
|
-
A3 += (A2 *
|
|
292
|
+
A3 += (A2 * na - (B2 * nb)) * (Dn * _3_0)
|
|
275
293
|
A3 += Dn3 * (na - nb)
|
|
276
294
|
|
|
277
295
|
A2 += B2
|
|
278
|
-
A2 += Dn2 * (nab
|
|
296
|
+
A2 += Dn2 * (nab * _n)
|
|
279
297
|
|
|
280
298
|
B1n = B1 * nb # if other is self
|
|
281
299
|
A1 *= na
|
|
282
300
|
A1 += B1n
|
|
283
|
-
A1 *=
|
|
301
|
+
A1 *= _n
|
|
284
302
|
|
|
285
303
|
# self._Ms = A1, A2, A3, A4
|
|
286
304
|
self._n = n
|
|
@@ -293,18 +311,18 @@ class Fcook(_FstatsBase):
|
|
|
293
311
|
def fadd(self, xs, sample=False):
|
|
294
312
|
'''Accumulate and return the current count.
|
|
295
313
|
|
|
296
|
-
@arg xs: Iterable
|
|
297
|
-
|
|
298
|
-
@kwarg sample:
|
|
299
|
-
I{population} count (C{bool}).
|
|
314
|
+
@arg xs: Iterable of additional values (each C{scalar} or an
|
|
315
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
316
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} count
|
|
317
|
+
instead of the I{population} count (C{bool}).
|
|
300
318
|
|
|
301
319
|
@return: Current, running (sample) count (C{int}).
|
|
302
320
|
|
|
303
321
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
304
322
|
|
|
305
|
-
@raise TypeError:
|
|
323
|
+
@raise TypeError: Invalid B{C{xs}}.
|
|
306
324
|
|
|
307
|
-
@raise ValueError: Invalid or non-finite B{C{xs}}
|
|
325
|
+
@raise ValueError: Invalid or non-finite B{C{xs}}.
|
|
308
326
|
|
|
309
327
|
@see: U{online_kurtosis<https://WikiPedia.org/wiki/
|
|
310
328
|
Algorithms_for_calculating_variance>}.
|
|
@@ -312,7 +330,7 @@ class Fcook(_FstatsBase):
|
|
|
312
330
|
n = self._n
|
|
313
331
|
if xs:
|
|
314
332
|
M1, M2, M3, M4 = self._Ms
|
|
315
|
-
for x in _2Floats(xs=xs):
|
|
333
|
+
for x in _2Floats(xs=xs): # PYCHOK yield
|
|
316
334
|
n1 = n
|
|
317
335
|
n += 1
|
|
318
336
|
D = x - M1
|
|
@@ -342,38 +360,38 @@ class Fcook(_FstatsBase):
|
|
|
342
360
|
self._n = n
|
|
343
361
|
return _sampled(n, sample)
|
|
344
362
|
|
|
345
|
-
def fjb(self, xs=None,
|
|
363
|
+
def fjb(self, xs=None, excess=True, sample=True):
|
|
346
364
|
'''Accumulate and compute the current U{Jarque-Bera
|
|
347
365
|
<https://WikiPedia.org/wiki/Jarque–Bera_test>} normality.
|
|
348
366
|
|
|
349
|
-
@kwarg xs: Iterable
|
|
350
|
-
|
|
351
|
-
@kwarg excess:
|
|
367
|
+
@kwarg xs: Iterable of additional values (each C{scalar} or an
|
|
368
|
+
L{Fsum} or L{Fsum2Tuple}).
|
|
369
|
+
@kwarg excess: Apply the I{excess} kurtosis (C{bool}), default.
|
|
370
|
+
@kwarg sample: Use C{B{sample}=False} for the I{population}
|
|
371
|
+
normality instead of the I{sample} one (C{bool}).
|
|
352
372
|
|
|
353
373
|
@return: Current, running (sample) Jarque-Bera normality (C{float}).
|
|
354
374
|
|
|
355
375
|
@see: Method L{Fcook.fadd}.
|
|
356
376
|
'''
|
|
357
|
-
|
|
358
|
-
k = self.fkurtosis(sample=sample, excess=excess) / _2_0
|
|
359
|
-
s = self.fskewness(sample=sample)
|
|
360
|
-
return n * hypot2(k, s) / _6_0
|
|
377
|
+
return _Float(self._JarqueBera(xs, excess, sample=sample))
|
|
361
378
|
|
|
362
379
|
def fjb_(self, *xs, **sample_excess):
|
|
363
380
|
'''Accumulate and compute the current U{Jarque-Bera
|
|
364
381
|
<https://WikiPedia.org/wiki/Jarque–Bera_test>} normality.
|
|
365
382
|
|
|
366
|
-
@see: Method L{Fcook.fjb}.
|
|
383
|
+
@see: Method L{Fcook.fjb} for further details.
|
|
367
384
|
'''
|
|
368
385
|
return self.fjb(xs, **sample_excess)
|
|
369
386
|
|
|
370
|
-
def fkurtosis(self, xs=None,
|
|
387
|
+
def fkurtosis(self, xs=None, excess=True, **sample):
|
|
371
388
|
'''Accumulate and return the current kurtosis.
|
|
372
389
|
|
|
373
|
-
@
|
|
374
|
-
|
|
375
|
-
I{population} kurtosis (C{bool}).
|
|
390
|
+
@arg xs: Iterable of additional values (each C{scalar} or an
|
|
391
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
376
392
|
@kwarg excess: Return the I{excess} kurtosis (C{bool}), default.
|
|
393
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} kurtosis
|
|
394
|
+
instead of the I{population} kurtosis (C{bool}).
|
|
377
395
|
|
|
378
396
|
@return: Current, running (sample) kurtosis or I{excess} kurtosis (C{float}).
|
|
379
397
|
|
|
@@ -382,32 +400,21 @@ class Fcook(_FstatsBase):
|
|
|
382
400
|
|
|
383
401
|
@see: Method L{Fcook.fadd}.
|
|
384
402
|
'''
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
_, M2, _, M4 = self._Ms
|
|
388
|
-
m2 = _Float(M2 * M2)
|
|
389
|
-
if m2:
|
|
390
|
-
K, x = (M4 * (n / m2)), _3_0
|
|
391
|
-
if sample and 2 < n < len(self):
|
|
392
|
-
d = _Float((n - 1) * (n - 2))
|
|
393
|
-
K *= (n + 1) * (n + 2) / d
|
|
394
|
-
x *= n**2 / d
|
|
395
|
-
if excess:
|
|
396
|
-
K -= x
|
|
397
|
-
k = K.fsum()
|
|
398
|
-
return k
|
|
403
|
+
n = self.fadd(xs, **sample)
|
|
404
|
+
return _Float(self._Kurtosis(n, excess, **sample))
|
|
399
405
|
|
|
400
|
-
def fkurtosis_(self, *xs, **
|
|
406
|
+
def fkurtosis_(self, *xs, **excess_sample):
|
|
401
407
|
'''Accumulate and return the current kurtosis.
|
|
402
408
|
|
|
403
|
-
@see: Method L{Fcook.fkurtosis}.
|
|
409
|
+
@see: Method L{Fcook.fkurtosis} for further details.
|
|
404
410
|
'''
|
|
405
|
-
return self.fkurtosis(xs, **
|
|
411
|
+
return self.fkurtosis(xs, **excess_sample)
|
|
406
412
|
|
|
407
413
|
def fmedian(self, xs=None):
|
|
408
414
|
'''Accumulate and return the current median.
|
|
409
415
|
|
|
410
|
-
@
|
|
416
|
+
@arg xs: Iterable of additional values (each C{scalar} or an
|
|
417
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
411
418
|
|
|
412
419
|
@return: Current, running median (C{float}).
|
|
413
420
|
|
|
@@ -416,24 +423,22 @@ class Fcook(_FstatsBase):
|
|
|
416
423
|
https://TowardsDataScience.com/skewness-kurtosis-simplified-1338e094fc85>}
|
|
417
424
|
and method L{Fcook.fadd}.
|
|
418
425
|
'''
|
|
419
|
-
|
|
420
|
-
# median = mean - skewness * stdef / 3
|
|
421
|
-
m = _Float(self._M1) if xs is None else self.fmean(xs)
|
|
422
|
-
return m - self.fskewness() * self.fstdev() / _3_0
|
|
426
|
+
return _Float(self._Median(xs))
|
|
423
427
|
|
|
424
428
|
def fmedian_(self, *xs):
|
|
425
429
|
'''Accumulate and return the current median.
|
|
426
430
|
|
|
427
|
-
@see: Method L{Fcook.fmedian}.
|
|
431
|
+
@see: Method L{Fcook.fmedian} for further details.
|
|
428
432
|
'''
|
|
429
433
|
return self.fmedian(xs)
|
|
430
434
|
|
|
431
|
-
def fskewness(self, xs=None, sample
|
|
435
|
+
def fskewness(self, xs=None, **sample):
|
|
432
436
|
'''Accumulate and return the current skewness.
|
|
433
437
|
|
|
434
|
-
@
|
|
435
|
-
|
|
436
|
-
|
|
438
|
+
@arg xs: Iterable of additional values (each C{scalar} or an
|
|
439
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
440
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} skewness
|
|
441
|
+
instead of the I{population} skewness (C{bool}).
|
|
437
442
|
|
|
438
443
|
@return: Current, running (sample) skewness (C{float}).
|
|
439
444
|
|
|
@@ -442,29 +447,70 @@ class Fcook(_FstatsBase):
|
|
|
442
447
|
|
|
443
448
|
@see: Method L{Fcook.fadd}.
|
|
444
449
|
'''
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
_, M2, M3, _ = self._Ms
|
|
448
|
-
m = _Float(M2**3)
|
|
449
|
-
if m > 0:
|
|
450
|
-
S = M3 * sqrt(_Float(n) / m)
|
|
451
|
-
if sample and 1 < n < len(self):
|
|
452
|
-
S *= (n + 1) / _Float(n - 1)
|
|
453
|
-
s = S.fsum()
|
|
454
|
-
return s
|
|
450
|
+
n = self.fadd(xs, **sample)
|
|
451
|
+
return _Float(self._Skewness(n, **sample))
|
|
455
452
|
|
|
456
453
|
def fskewness_(self, *xs, **sample):
|
|
457
454
|
'''Accumulate and return the current skewness.
|
|
458
455
|
|
|
459
|
-
@see: Method L{Fcook.fskewness}.
|
|
456
|
+
@see: Method L{Fcook.fskewness} for further details.
|
|
460
457
|
'''
|
|
461
458
|
return self.fskewness(xs, **sample)
|
|
462
459
|
|
|
460
|
+
def _JarqueBera(self, xs, excess, **sample):
|
|
461
|
+
'''(INTERNAL) Return the (sample) Jarque-Bera normality as L{Fsum}.
|
|
462
|
+
'''
|
|
463
|
+
N, n = _0_0, self.fadd(xs, **sample)
|
|
464
|
+
if n > 0:
|
|
465
|
+
K = self._Kurtosis(n, excess, **sample) / _2_0
|
|
466
|
+
S = self._Skewness(n, **sample)
|
|
467
|
+
N = (K**2 + S**2) * (n / _6_0) # Fpowers(2, K, S) * ...
|
|
468
|
+
return N
|
|
469
|
+
|
|
470
|
+
def _Kurtosis(self, n, excess, sample=False):
|
|
471
|
+
'''(INTERNAL) Return the (sample) kurtosis as L{Fsum} or C{0.0}.
|
|
472
|
+
'''
|
|
473
|
+
K = _0_0
|
|
474
|
+
if n > 0:
|
|
475
|
+
_, M2, _, M4 = self._Ms
|
|
476
|
+
M = M2**2
|
|
477
|
+
if M > 0:
|
|
478
|
+
K, x = M.rdiv(M4 * n, raiser=False), _3_0
|
|
479
|
+
if sample and 2 < n < len(self):
|
|
480
|
+
d = (n - 1) * (n - 2)
|
|
481
|
+
K *= (n + 1) * (n + 2) / d
|
|
482
|
+
x *= n**2 / d
|
|
483
|
+
if excess:
|
|
484
|
+
K -= x
|
|
485
|
+
return K
|
|
486
|
+
|
|
487
|
+
def _Median(self, xs=None):
|
|
488
|
+
'''(INTERNAL) Return the median as L{Fsum}.
|
|
489
|
+
'''
|
|
490
|
+
# skewness = 3 * (mean - median) / stdev, i.e.
|
|
491
|
+
# median = mean - (skewness * stdef) / 3
|
|
492
|
+
return self._Mean(xs) - (self._Skewness(self._n) *
|
|
493
|
+
self._Stdev()) / _3_0
|
|
494
|
+
|
|
495
|
+
def _Skewness(self, n, sample=False):
|
|
496
|
+
'''(INTERNAL) Return the (sample) skewness as L{Fsum} or C{0.0}.
|
|
497
|
+
'''
|
|
498
|
+
S = _0_0
|
|
499
|
+
if n > 0:
|
|
500
|
+
_, M2, M3, _ = self._Ms
|
|
501
|
+
M = M2**3
|
|
502
|
+
if M > 0:
|
|
503
|
+
M = M.rdiv(n, raiser=False)
|
|
504
|
+
S = M3 * Fsqrt(M, raiser=False)
|
|
505
|
+
if sample and 1 < n < len(self):
|
|
506
|
+
S *= (n + 1) / (n - 1)
|
|
507
|
+
return S
|
|
508
|
+
|
|
463
509
|
def toFwelford(self, name=NN):
|
|
464
510
|
'''Return an L{Fwelford} equivalent.
|
|
465
511
|
'''
|
|
466
512
|
f = Fwelford(name=name or self.name)
|
|
467
|
-
f._Ms = self._M1.
|
|
513
|
+
f._Ms = self._M1.copy(), self._M2.copy() # deep=False
|
|
468
514
|
f._n = self._n
|
|
469
515
|
return f
|
|
470
516
|
|
|
@@ -478,7 +524,8 @@ class Fwelford(_FstatsBase):
|
|
|
478
524
|
def __init__(self, xs=None, name=NN):
|
|
479
525
|
'''New L{Fwelford} stats accumulator.
|
|
480
526
|
|
|
481
|
-
@
|
|
527
|
+
@arg xs: Iterable of initial values (each C{scalar} or an
|
|
528
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
482
529
|
@kwarg name: Optional name (C{str}).
|
|
483
530
|
|
|
484
531
|
@see: Method L{Fwelford.fadd}.
|
|
@@ -492,12 +539,13 @@ class Fwelford(_FstatsBase):
|
|
|
492
539
|
def __iadd__(self, other):
|
|
493
540
|
'''Add B{C{other}} to this L{Fwelford} instance.
|
|
494
541
|
|
|
495
|
-
@arg other: An L{Fwelford} or L{Fcook} instance or
|
|
496
|
-
|
|
542
|
+
@arg other: An L{Fwelford} or L{Fcook} instance or value
|
|
543
|
+
or an iterable of values (each C{scalar} or
|
|
544
|
+
an L{Fsum} or L{Fsum2Tuple} instance).
|
|
497
545
|
|
|
498
546
|
@return: This instance, updated (L{Fwelford}).
|
|
499
547
|
|
|
500
|
-
@raise TypeError: Invalid B{C{other}}
|
|
548
|
+
@raise TypeError: Invalid B{C{other}}.
|
|
501
549
|
|
|
502
550
|
@raise ValueError: Invalid B{C{other}}.
|
|
503
551
|
|
|
@@ -513,18 +561,18 @@ class Fwelford(_FstatsBase):
|
|
|
513
561
|
M_, S_ = other._Ms
|
|
514
562
|
|
|
515
563
|
n = na + nb
|
|
516
|
-
|
|
564
|
+
_n = _1_0 / n
|
|
517
565
|
|
|
518
566
|
D = M_ - M
|
|
519
567
|
D *= D # D**2
|
|
520
|
-
D *= na * nb
|
|
568
|
+
D *= na * nb * _n
|
|
521
569
|
S += D
|
|
522
570
|
S += S_
|
|
523
571
|
|
|
524
572
|
Mn = M_ * nb # if other is self
|
|
525
573
|
M *= na
|
|
526
574
|
M += Mn
|
|
527
|
-
M *=
|
|
575
|
+
M *= _n
|
|
528
576
|
|
|
529
577
|
# self._Ms = M, S
|
|
530
578
|
self._n = n
|
|
@@ -540,23 +588,23 @@ class Fwelford(_FstatsBase):
|
|
|
540
588
|
def fadd(self, xs, sample=False):
|
|
541
589
|
'''Accumulate and return the current count.
|
|
542
590
|
|
|
543
|
-
@arg xs: Iterable
|
|
544
|
-
|
|
545
|
-
@kwarg sample:
|
|
546
|
-
I{population} count (C{bool}).
|
|
591
|
+
@arg xs: Iterable of additional values (each C{scalar} or an
|
|
592
|
+
L{Fsum} or L{Fsum2Tuple} instance).
|
|
593
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} count
|
|
594
|
+
instead of the I{population} count (C{bool}).
|
|
547
595
|
|
|
548
596
|
@return: Current, running (sample) count (C{int}).
|
|
549
597
|
|
|
550
598
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
551
599
|
|
|
552
|
-
@raise TypeError:
|
|
600
|
+
@raise TypeError: Invalid B{C{xs}}.
|
|
553
601
|
|
|
554
|
-
@raise ValueError: Invalid or non-finite B{C{xs}}
|
|
602
|
+
@raise ValueError: Invalid or non-finite B{C{xs}}.
|
|
555
603
|
'''
|
|
556
604
|
n = self._n
|
|
557
605
|
if xs:
|
|
558
606
|
M, S = self._Ms
|
|
559
|
-
for x in _2Floats(xs=xs):
|
|
607
|
+
for x in _2Floats(xs=xs): # PYCHOK yield
|
|
560
608
|
n += 1
|
|
561
609
|
D = x - M
|
|
562
610
|
M += D / n
|
|
@@ -575,14 +623,16 @@ class Flinear(_FstatsNamed):
|
|
|
575
623
|
def __init__(self, xs=None, ys=None, Fstats=Fwelford, name=NN):
|
|
576
624
|
'''New L{Flinear} regression accumulator.
|
|
577
625
|
|
|
578
|
-
@kwarg xs: Iterable
|
|
579
|
-
|
|
580
|
-
@kwarg
|
|
581
|
-
|
|
626
|
+
@kwarg xs: Iterable of initial C{x} values (each C{scalar} or
|
|
627
|
+
an L{Fsum} or L{Fsum2Tuple} instance).
|
|
628
|
+
@kwarg ys: Iterable of initial C{y} values (each C{scalar} or
|
|
629
|
+
an L{Fsum} or L{Fsum2Tuple} instance).
|
|
630
|
+
@kwarg Fstats: Class for C{xs} and C{ys} values (L{Fcook} or
|
|
631
|
+
L{Fwelford}).
|
|
582
632
|
@kwarg name: Optional name (C{str}).
|
|
583
633
|
|
|
584
|
-
@raise TypeError:
|
|
585
|
-
|
|
634
|
+
@raise TypeError: B{C{Fstats}} not L{Fcook} or L{Fwelford}.
|
|
635
|
+
|
|
586
636
|
@see: Method L{Flinear.fadd}.
|
|
587
637
|
'''
|
|
588
638
|
_xsubclassof(Fcook, Fwelford, Fstats=Fstats)
|
|
@@ -598,8 +648,8 @@ class Flinear(_FstatsNamed):
|
|
|
598
648
|
def __iadd__(self, other):
|
|
599
649
|
'''Add B{C{other}} to this instance.
|
|
600
650
|
|
|
601
|
-
@arg other: An L{Flinear} instance or
|
|
602
|
-
|
|
651
|
+
@arg other: An L{Flinear} instance or an iterable of
|
|
652
|
+
C{x_ys} values, see method C{fadd_}.
|
|
603
653
|
|
|
604
654
|
@return: This instance, updated (L{Flinear}).
|
|
605
655
|
|
|
@@ -614,126 +664,139 @@ class Flinear(_FstatsNamed):
|
|
|
614
664
|
if _isAn(other, Flinear):
|
|
615
665
|
if len(other) > 0:
|
|
616
666
|
if len(self) > 0:
|
|
617
|
-
n =
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
667
|
+
n = other._n
|
|
668
|
+
D = (other._X._M1 - self._X._M1) * \
|
|
669
|
+
(other._Y._M1 - self._Y._M1) * \
|
|
670
|
+
(n * self._n / (self._n + n))
|
|
671
|
+
self._S += other._S + D
|
|
672
|
+
self._X += other._X
|
|
673
|
+
self._Y += other._Y
|
|
624
674
|
self._n += n
|
|
625
|
-
self._S += S + D
|
|
626
|
-
self._X += X
|
|
627
|
-
self._Y += Y
|
|
628
675
|
else:
|
|
629
676
|
self._copy(self, other)
|
|
630
677
|
else:
|
|
631
678
|
try:
|
|
632
|
-
|
|
633
|
-
raise TypeError(_SPACE_(_invalid_, _other_))
|
|
634
|
-
elif isodd(len(other)):
|
|
635
|
-
raise ValueError(Fmt.PAREN(isodd=Fmt.PAREN(len=_other_)))
|
|
679
|
+
_xiterable(other)
|
|
636
680
|
self.fadd_(*other)
|
|
637
681
|
except Exception as x:
|
|
638
|
-
|
|
682
|
+
op = _SPACE_(self, _iadd_op_, repr(other))
|
|
683
|
+
raise _xError(x, op)
|
|
639
684
|
return self
|
|
640
685
|
|
|
641
|
-
def _copy(self,
|
|
642
|
-
'''(INTERNAL) Copy C{B{
|
|
686
|
+
def _copy(self, d, s):
|
|
687
|
+
'''(INTERNAL) Copy C{B{d} = B{s}}.
|
|
688
|
+
'''
|
|
689
|
+
_xinstanceof(Flinear, d=d, s=s)
|
|
690
|
+
d._S = s._S.copy(deep=False)
|
|
691
|
+
d._X = s._X.copy(deep=False)
|
|
692
|
+
d._Y = s._Y.copy(deep=False)
|
|
693
|
+
d._n = s._n
|
|
694
|
+
return d
|
|
695
|
+
|
|
696
|
+
def _Correlation(self, **sample):
|
|
697
|
+
'''(INTERNAL) Return the current (sample) correlation as L{Fsum}.
|
|
643
698
|
'''
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
c._S = s._S.fcopy(deep=False)
|
|
647
|
-
c._X = s._X.fcopy(deep=False)
|
|
648
|
-
c._Y = s._Y.fcopy(deep=False)
|
|
649
|
-
return c
|
|
699
|
+
return self._Sampled(self._X._Stdev(**sample) *
|
|
700
|
+
self._Y._Stdev(**sample), **sample)
|
|
650
701
|
|
|
651
702
|
def fadd(self, xs, ys, sample=False):
|
|
652
703
|
'''Accumulate and return the current count.
|
|
653
704
|
|
|
654
|
-
@arg xs: Iterable
|
|
655
|
-
|
|
656
|
-
@arg ys: Iterable
|
|
657
|
-
|
|
658
|
-
@kwarg sample:
|
|
659
|
-
I{population} count (C{bool}).
|
|
705
|
+
@arg xs: Iterable of additional C{x} values (each C{scalar}
|
|
706
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
707
|
+
@arg ys: Iterable of additional C{y} values (each C{scalar}
|
|
708
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
709
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} count
|
|
710
|
+
instead of the I{population} count (C{bool}).
|
|
660
711
|
|
|
661
712
|
@return: Current, running (sample) count (C{int}).
|
|
662
713
|
|
|
663
714
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
664
715
|
|
|
665
|
-
@raise TypeError:
|
|
716
|
+
@raise TypeError: Invalid B{C{xs}} or B{C{ys}}.
|
|
666
717
|
|
|
667
|
-
@raise ValueError: Invalid or non-finite B{C{xs}} or B{C{ys}}
|
|
718
|
+
@raise ValueError: Invalid or non-finite B{C{xs}} or B{C{ys}}.
|
|
668
719
|
'''
|
|
669
720
|
n = self._n
|
|
670
721
|
if xs and ys:
|
|
671
722
|
S = self._S
|
|
672
723
|
X = self._X
|
|
673
724
|
Y = self._Y
|
|
674
|
-
for x, y in _zip(_2Floats(xs=xs), _2Floats(ys=ys)): # strict=True
|
|
725
|
+
for x, y in _zip(_2Floats(xs=xs), _2Floats(ys=ys)): # PYCHOK strict=True
|
|
675
726
|
n1 = n
|
|
676
727
|
n += 1
|
|
677
728
|
if n1 > 0:
|
|
678
|
-
S += (X._M1 - x) * (Y._M1 - y) * (n1 /
|
|
729
|
+
S += (X._M1 - x) * (Y._M1 - y) * (n1 / n)
|
|
679
730
|
X += x
|
|
680
731
|
Y += y
|
|
681
|
-
self._n
|
|
732
|
+
self._n = n
|
|
682
733
|
return _sampled(n, sample)
|
|
683
734
|
|
|
684
735
|
def fadd_(self, *x_ys, **sample):
|
|
685
736
|
'''Accumulate and return the current count.
|
|
686
737
|
|
|
687
|
-
@arg x_ys: Individual, alternating C{x, y, x, y, ...}
|
|
688
|
-
|
|
738
|
+
@arg x_ys: Individual, alternating C{x, y, x, y, ...} values
|
|
739
|
+
(each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
740
|
+
instance).
|
|
689
741
|
|
|
690
|
-
@see: Method C{Flinear.fadd}.
|
|
742
|
+
@see: Method C{Flinear.fadd} for further details.
|
|
691
743
|
'''
|
|
744
|
+
if isodd(len(x_ys)):
|
|
745
|
+
t = _SPACE_(_odd_, len.__name__)
|
|
746
|
+
raise _ValueError(t, len(x_ys))
|
|
692
747
|
return self.fadd(x_ys[0::2], x_ys[1::2], **sample)
|
|
693
748
|
|
|
694
|
-
def fcorrelation(self, sample
|
|
749
|
+
def fcorrelation(self, **sample):
|
|
695
750
|
'''Return the current, running (sample) correlation (C{float}).
|
|
696
751
|
|
|
697
|
-
@kwarg sample:
|
|
698
|
-
I{population} correlation (C{bool}).
|
|
752
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} correlation
|
|
753
|
+
instead of the I{population} correlation (C{bool}).
|
|
699
754
|
'''
|
|
700
|
-
return
|
|
701
|
-
self.y.fstdev(sample=sample), sample)
|
|
755
|
+
return _Float(self._Correlation(**sample))
|
|
702
756
|
|
|
703
|
-
def fintercept(self, sample
|
|
757
|
+
def fintercept(self, **sample):
|
|
704
758
|
'''Return the current, running (sample) intercept (C{float}).
|
|
705
759
|
|
|
706
|
-
@kwarg sample:
|
|
707
|
-
I{population} intercept (C{bool}).
|
|
760
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} intercept
|
|
761
|
+
instead of the I{population} intercept (C{bool}).
|
|
708
762
|
'''
|
|
709
|
-
return _Float(self.
|
|
710
|
-
(self.x._M1 * self.fslope(sample=sample)))
|
|
763
|
+
return _Float(self._Intercept(**sample))
|
|
711
764
|
|
|
712
|
-
def fslope(self, sample
|
|
765
|
+
def fslope(self, **sample):
|
|
713
766
|
'''Return the current, running (sample) slope (C{float}).
|
|
714
767
|
|
|
715
|
-
@kwarg sample:
|
|
716
|
-
I{population} slope (C{bool}).
|
|
768
|
+
@kwarg sample: Use C{B{sample}=True} for the I{sample} slope
|
|
769
|
+
instead of the I{population} slope (C{bool}).
|
|
717
770
|
'''
|
|
718
|
-
return
|
|
771
|
+
return _Float(self._Slope(**sample))
|
|
719
772
|
|
|
720
|
-
def
|
|
773
|
+
def _Intercept(self, **sample):
|
|
774
|
+
'''(INTERNAL) Return the current (sample) intercept as L{Fsum}.
|
|
775
|
+
'''
|
|
776
|
+
return self._Y._M1 - self._X._M1 * self._Slope(**sample)
|
|
777
|
+
|
|
778
|
+
def _Sampled(self, T, sample=False):
|
|
721
779
|
'''(INTERNAL) Compute the sampled or entire population result.
|
|
722
780
|
'''
|
|
723
|
-
|
|
724
|
-
return
|
|
781
|
+
T *= _sampled(self._n, sample)
|
|
782
|
+
return self._S.copy().fdiv(T, raiser=False) if T else T
|
|
783
|
+
|
|
784
|
+
def _Slope(self, **sample):
|
|
785
|
+
'''(INTERNAL) Return the current (sample) slope as L{Fsum}.
|
|
786
|
+
'''
|
|
787
|
+
return self._Sampled(self._X._Variance(**sample), **sample)
|
|
725
788
|
|
|
726
789
|
@property_RO
|
|
727
790
|
def x(self):
|
|
728
791
|
'''Get the C{x} accumulator (L{Fcook} or L{Fwelford}).
|
|
729
792
|
'''
|
|
730
|
-
return self._X
|
|
793
|
+
return self._X # .copy()
|
|
731
794
|
|
|
732
795
|
@property_RO
|
|
733
796
|
def y(self):
|
|
734
797
|
'''Get the C{y} accumulator (L{Fcook} or L{Fwelford}).
|
|
735
798
|
'''
|
|
736
|
-
return self._Y
|
|
799
|
+
return self._Y # .copy()
|
|
737
800
|
|
|
738
801
|
|
|
739
802
|
__all__ += _ALL_DOCS(_FstatsBase, _FstatsNamed)
|
pygeodesy/fsums.py
CHANGED
|
@@ -43,7 +43,7 @@ from pygeodesy.streprs import Fmt, fstr, unstr
|
|
|
43
43
|
from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
|
|
44
44
|
|
|
45
45
|
__all__ = _ALL_LAZY.fsums
|
|
46
|
-
__version__ = '24.05.
|
|
46
|
+
__version__ = '24.05.08'
|
|
47
47
|
|
|
48
48
|
_abs = abs
|
|
49
49
|
_add_op_ = _PLUS_ # in .auxilats.auxAngle
|
|
@@ -71,7 +71,7 @@ _significant_ = 'significant'
|
|
|
71
71
|
_sub_op_ = _DASH_ # in .auxilats.auxAngle
|
|
72
72
|
_threshold_ = 'threshold'
|
|
73
73
|
_truediv_op_ = _SLASH_
|
|
74
|
-
_Tuple = tuple
|
|
74
|
+
_Tuple = tuple # in .fstats
|
|
75
75
|
_divmod_op_ = _floordiv_op_ + _mod_op_
|
|
76
76
|
_isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
|
|
77
77
|
|
|
@@ -86,19 +86,25 @@ def _2delta(*ab):
|
|
|
86
86
|
return _Float(a if fabs(a) > fabs(b) else b)
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
def _2error(unused):
|
|
89
|
+
def _2error(unused): # in .fstats
|
|
90
90
|
'''(INTERNAL) Throw a C{not-finite} exception.
|
|
91
91
|
'''
|
|
92
92
|
raise ValueError(_not_finite_)
|
|
93
93
|
|
|
94
94
|
|
|
95
|
+
def _2finite(x):
|
|
96
|
+
'''(INTERNAL) return C{float(x)} if finite.
|
|
97
|
+
'''
|
|
98
|
+
x = _Float(x)
|
|
99
|
+
return x if _isfinite(x) else _2error(x)
|
|
100
|
+
|
|
101
|
+
|
|
95
102
|
def _2float(index=None, **name_value): # in .fmath, .fstats
|
|
96
103
|
'''(INTERNAL) Raise C{TypeError} or C{ValueError} if not scalar or infinite.
|
|
97
104
|
'''
|
|
98
105
|
n, v = name_value.popitem() # _xkwds_item2(name_value)
|
|
99
106
|
try:
|
|
100
|
-
|
|
101
|
-
return v if _isfinite(v) else _2error(v)
|
|
107
|
+
return _2finite(v)
|
|
102
108
|
except Exception as X:
|
|
103
109
|
raise _xError(X, Fmt.INDEX(n, index), v)
|
|
104
110
|
|
|
@@ -838,7 +844,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
838
844
|
c = _ceil(s) + int(r) - 1
|
|
839
845
|
while r > (c - s): # (s + r) > c
|
|
840
846
|
c += 1
|
|
841
|
-
return c
|
|
847
|
+
return c # _ceil(self._n_d)
|
|
842
848
|
|
|
843
849
|
cmp = __cmp__
|
|
844
850
|
|
|
@@ -1149,7 +1155,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1149
1155
|
f = _floor(s) + _floor(r) + 1
|
|
1150
1156
|
while (f - s) > r: # f > (s + r)
|
|
1151
1157
|
f -= 1
|
|
1152
|
-
return f
|
|
1158
|
+
return f # _floor(self._n_d)
|
|
1153
1159
|
|
|
1154
1160
|
# ffloordiv = __ifloordiv__ # for naming consistency
|
|
1155
1161
|
# floordiv = __floordiv__ # for naming consistency
|
|
@@ -1222,7 +1228,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1222
1228
|
@note: The precision running C{fsum} after a C{//=} or
|
|
1223
1229
|
C{//} C{floor} division is C{int} in Python 3+.
|
|
1224
1230
|
'''
|
|
1225
|
-
|
|
1231
|
+
s, _ = self._fprs2
|
|
1232
|
+
return s # ._fprs2.fsum
|
|
1226
1233
|
|
|
1227
1234
|
@Property_RO
|
|
1228
1235
|
def _fprs2(self):
|
|
@@ -1259,7 +1266,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1259
1266
|
|
|
1260
1267
|
@see: Method L{Fsum.fadd} for further details.
|
|
1261
1268
|
'''
|
|
1262
|
-
f =
|
|
1269
|
+
f = xs[0] if len(xs) == 1 else (
|
|
1270
|
+
Fsum(*xs) if xs else _0_0)
|
|
1263
1271
|
return self._fset(f)
|
|
1264
1272
|
|
|
1265
1273
|
def _fset(self, other, as_is=True, n=0, up=True):
|
|
@@ -1356,7 +1364,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1356
1364
|
return self._facc_1(xs)._fprs
|
|
1357
1365
|
|
|
1358
1366
|
@property_RO
|
|
1359
|
-
def _Fsum(self): # like L{Fsum2Tuple._Fsum}, for C{_2floats}.
|
|
1367
|
+
def _Fsum(self): # like L{Fsum2Tuple._Fsum}, for C{_2floats}, .fstats
|
|
1360
1368
|
return self # NOT @Property_RO, see .copy and ._copy_2
|
|
1361
1369
|
|
|
1362
1370
|
def Fsum_(self, *xs, **name):
|
|
@@ -1559,13 +1567,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1559
1567
|
'''
|
|
1560
1568
|
# assert isscalar(factor)
|
|
1561
1569
|
if self._ps and self._finite(factor, op):
|
|
1562
|
-
f = self if factor == _1_0
|
|
1570
|
+
f = self if factor == _1_0 else (
|
|
1563
1571
|
self._neg if factor == _N_1_0 else
|
|
1564
1572
|
self._ps_mul(op, factor).as_iscalar)
|
|
1565
1573
|
else:
|
|
1566
1574
|
f = _0_0
|
|
1567
1575
|
return f
|
|
1568
1576
|
|
|
1577
|
+
# @property_RO
|
|
1578
|
+
# def _n_d(self):
|
|
1579
|
+
# n, d = self.as_integer_ratio()
|
|
1580
|
+
# return n / d
|
|
1581
|
+
|
|
1569
1582
|
@property_RO
|
|
1570
1583
|
def _neg(self):
|
|
1571
1584
|
'''(INTERNAL) Return C{Fsum(-self)} or scalar C{NEG0}.
|
|
@@ -1751,8 +1764,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1751
1764
|
return ps
|
|
1752
1765
|
|
|
1753
1766
|
def _ps_mul(self, op, *factors):
|
|
1754
|
-
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1755
|
-
|
|
1767
|
+
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1768
|
+
each scalar C{factor} and accumulate into an C{Fsum}.
|
|
1756
1769
|
'''
|
|
1757
1770
|
def _pfs(ps, fs):
|
|
1758
1771
|
if _len(ps) < _len(fs):
|
|
@@ -1763,7 +1776,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1763
1776
|
p *= f
|
|
1764
1777
|
yield p if _fin(p) else self._finite(p, op)
|
|
1765
1778
|
|
|
1766
|
-
return
|
|
1779
|
+
return Fsum()._facc_scalar(_pfs(self._ps, factors), up=False)
|
|
1767
1780
|
|
|
1768
1781
|
@property_RO
|
|
1769
1782
|
def _ps_neg(self):
|
|
@@ -1773,7 +1786,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1773
1786
|
yield -p
|
|
1774
1787
|
|
|
1775
1788
|
def _ps_1sum(self, *less):
|
|
1776
|
-
'''(INTERNAL) Return the partials sum, 1-primed C{less}
|
|
1789
|
+
'''(INTERNAL) Return the partials sum, 1-primed C{less} some scalars.
|
|
1777
1790
|
'''
|
|
1778
1791
|
def _1pls(ps, ls):
|
|
1779
1792
|
yield _1_0
|
|
@@ -1800,6 +1813,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1800
1813
|
return dict(ratio=q, R=t)
|
|
1801
1814
|
return {}
|
|
1802
1815
|
|
|
1816
|
+
rdiv = __rtruediv__
|
|
1817
|
+
|
|
1803
1818
|
@property_RO
|
|
1804
1819
|
def real(self):
|
|
1805
1820
|
'''Get the C{real} part of this instance (C{float}).
|
|
@@ -1966,7 +1981,7 @@ class DivMod2Tuple(_NamedTuple):
|
|
|
1966
1981
|
_Units_ = (_Float_Int, Fsum)
|
|
1967
1982
|
|
|
1968
1983
|
|
|
1969
|
-
class Fsum2Tuple(_NamedTuple):
|
|
1984
|
+
class Fsum2Tuple(_NamedTuple): # in .fstats
|
|
1970
1985
|
'''2-Tuple C{(fsum, residual)} with the precision running C{fsum}
|
|
1971
1986
|
and the C{residual}, the sum of the remaining partials. Each
|
|
1972
1987
|
item is C{float} or C{int}.
|
|
@@ -2031,7 +2046,7 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
2031
2046
|
return self._Fsum._fprs2
|
|
2032
2047
|
|
|
2033
2048
|
@Property_RO
|
|
2034
|
-
def _Fsum(self): # this C{Fsum2Tuple} as L{Fsum}
|
|
2049
|
+
def _Fsum(self): # this C{Fsum2Tuple} as L{Fsum}, in .fstats
|
|
2035
2050
|
s, r = _s_r(*self)
|
|
2036
2051
|
ps = (r, s) if r else (s,)
|
|
2037
2052
|
return _Psum(ps, name=self.name)
|
|
@@ -2085,7 +2100,7 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
2085
2100
|
'''
|
|
2086
2101
|
return Fmt.PAREN(fstr(self, fmt=fmt, strepr=str, force=False, **prec_sep))
|
|
2087
2102
|
|
|
2088
|
-
_Fsum_Fsum2Tuple_types = Fsum, Fsum2Tuple # PYCHOK
|
|
2103
|
+
_Fsum_Fsum2Tuple_types = Fsum, Fsum2Tuple # PYCHOK lines
|
|
2089
2104
|
|
|
2090
2105
|
|
|
2091
2106
|
class ResidualError(_ValueError):
|
pygeodesy/interns.py
CHANGED
|
@@ -332,6 +332,7 @@ _null_ = 'null' # PYCHOK OK
|
|
|
332
332
|
_number_ = 'number' # PYCHOK OK
|
|
333
333
|
_numpy_ = 'numpy' # PYCHOK OK
|
|
334
334
|
_Nv00_ = 'Nv00' # PYCHOK OK
|
|
335
|
+
_odd_ = 'odd' # PYCHOK OK
|
|
335
336
|
_of_ = 'of' # PYCHOK OK
|
|
336
337
|
_on_ = 'on' # PYCHOK OK
|
|
337
338
|
_opposite_ = 'opposite' # PYCHOK OK
|
|
@@ -647,7 +648,7 @@ def _version_ints(vs):
|
|
|
647
648
|
__all__ = (_NN_, # not MISSING!
|
|
648
649
|
Str_.__name__, # classes
|
|
649
650
|
machine.__name__) # in .lazily
|
|
650
|
-
__version__ = '24.05.
|
|
651
|
+
__version__ = '24.05.08'
|
|
651
652
|
|
|
652
653
|
if __name__ == '__main__':
|
|
653
654
|
|
|
File without changes
|
|
File without changes
|