pygeodesy 24.8.24__py2.py3-none-any.whl → 24.9.24__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/METADATA +7 -7
- {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/RECORD +49 -48
- pygeodesy/__init__.py +7 -5
- pygeodesy/__main__.py +46 -47
- pygeodesy/auxilats/_CX_4.py +104 -181
- pygeodesy/auxilats/_CX_6.py +152 -277
- pygeodesy/auxilats/_CX_8.py +211 -438
- pygeodesy/auxilats/_CX_Rs.py +222 -0
- pygeodesy/auxilats/__init__.py +2 -2
- pygeodesy/auxilats/__main__.py +30 -38
- pygeodesy/auxilats/auxLat.py +28 -36
- pygeodesy/auxilats/auxily.py +30 -50
- pygeodesy/basics.py +24 -14
- pygeodesy/booleans.py +13 -14
- pygeodesy/clipy.py +7 -7
- pygeodesy/constants.py +44 -31
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/functions.py +9 -1
- pygeodesy/elliptic.py +154 -88
- pygeodesy/errors.py +32 -5
- pygeodesy/etm.py +71 -59
- pygeodesy/fmath.py +125 -96
- pygeodesy/fstats.py +8 -12
- pygeodesy/fsums.py +802 -355
- pygeodesy/geodesici.py +6 -5
- pygeodesy/geodesicx/_C4_24.py +1 -3
- pygeodesy/geodesicx/_C4_27.py +1 -3
- pygeodesy/geodesicx/_C4_30.py +1 -3
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +44 -46
- pygeodesy/geodesicx/gxarea.py +3 -3
- pygeodesy/geodesicx/gxbases.py +32 -18
- pygeodesy/internals.py +50 -9
- pygeodesy/interns.py +3 -2
- pygeodesy/karney.py +79 -60
- pygeodesy/ktm.py +4 -4
- pygeodesy/lazily.py +10 -5
- pygeodesy/mgrs.py +47 -42
- pygeodesy/named.py +4 -1
- pygeodesy/points.py +3 -3
- pygeodesy/props.py +7 -6
- pygeodesy/resections.py +2 -2
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +42 -60
- pygeodesy/sphericalNvector.py +4 -4
- pygeodesy/sphericalTrigonometry.py +2 -2
- pygeodesy/triaxials.py +3 -3
- {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.8.24.dist-info → PyGeodesy-24.9.24.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -1,108 +1,114 @@
|
|
|
1
1
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
|
-
u'''Class L{Fsum} for precision floating point summation
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
4
|
+
u'''Class L{Fsum} for precision floating point summation similar to
|
|
5
|
+
Python's C{math.fsum} enhanced with I{running} summation and as an
|
|
6
|
+
option, accurate I{TwoProduct} multiplication.
|
|
7
|
+
|
|
8
|
+
Accurate multiplication is based on the C{math.fma} function for
|
|
9
|
+
Python 3.13 and newer or one of two equivalent C{fma} implementations
|
|
10
|
+
for Python 3.12 and older. To enable accurate multiplication, set
|
|
11
|
+
env variable C{PYGEODESY_FSUM_F2PRODUCT} to C{"std"} or any non-empty
|
|
12
|
+
string or invoke function C{pygeodesy.f2product(True)} or set. With
|
|
13
|
+
C{"std"} the C{fma} implemention follows the C{math.fma} function,
|
|
14
|
+
otherwise the C{PyGeodesy 24.09.09} release.
|
|
15
|
+
|
|
16
|
+
Generally, an L{Fsum} instance is considered a C{float} plus a small or
|
|
17
|
+
zero C{residue} aka C{residual} value, see property L{Fsum.residual}.
|
|
18
|
+
|
|
19
|
+
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater
|
|
20
|
+
than C{"0.0"} as the threshold to throw a L{ResidualError} for a division,
|
|
21
|
+
power or root operation of an L{Fsum} with a C{residual} I{ratio} exceeding
|
|
20
22
|
the threshold. See methods L{Fsum.RESIDUAL}, L{Fsum.pow}, L{Fsum.__ipow__}
|
|
21
23
|
and L{Fsum.__itruediv__}.
|
|
24
|
+
|
|
25
|
+
There are several C{integer} L{Fsum} cases, for example the result from
|
|
26
|
+
functions C{ceil}, C{floor}, C{Fsum.__floordiv__} and methods L{Fsum.fint},
|
|
27
|
+
L{Fsum.fint2} and L{Fsum.is_integer}. Also, L{Fsum} methods L{Fsum.pow},
|
|
28
|
+
L{Fsum.__ipow__}, L{Fsum.__pow__} and L{Fsum.__rpow__} return a (very long)
|
|
29
|
+
C{int} if invoked with optional argument C{mod} set to C{None}. The
|
|
30
|
+
C{residual} of an C{integer} L{Fsum} is between C{-1.0} and C{+1.0} and
|
|
31
|
+
will be C{INT0} if that is considered to be I{exact}.
|
|
32
|
+
|
|
33
|
+
Set env variable C{PYGEODESY_FSUM_NONFINITES} to C{"std"} or use function
|
|
34
|
+
C{pygeodesy.nonfiniterrors(False)} to allow I{non-finite} C{float}s like
|
|
35
|
+
C{inf}, C{INF}, C{NINF}, C{nan} and C{NAN} and to ignore C{OverflowError}
|
|
36
|
+
respectively C{ValueError} exceptions. However, in that case I{non-finite}
|
|
37
|
+
results may differ from Python's C{math.fsum} results.
|
|
22
38
|
'''
|
|
23
39
|
# make sure int/int division yields float quotient, see .basics
|
|
24
40
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
25
41
|
|
|
26
42
|
from pygeodesy.basics import isbool, iscomplex, isint, isscalar, \
|
|
27
43
|
_signOf, itemsorted, signOf, _xiterable, \
|
|
28
|
-
_xiterablen
|
|
29
|
-
from pygeodesy.constants import INT0,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
from pygeodesy.
|
|
36
|
-
|
|
37
|
-
_not_finite_,
|
|
38
|
-
_RANGLE_, _SLASH_, _SPACE_, _STAR_, _UNDER_
|
|
44
|
+
_xiterablen
|
|
45
|
+
from pygeodesy.constants import INF, INT0, MANT_DIG, NEG0, NINF, _0_0, \
|
|
46
|
+
_1_0, _N_1_0, _isfinite, _pos_self, \
|
|
47
|
+
Float, Int
|
|
48
|
+
from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
|
|
49
|
+
_ValueError, _xError, _xError2, _xkwds_get, \
|
|
50
|
+
_xkwds, _xkwds_get1, _xkwds_not, _xkwds_pop
|
|
51
|
+
from pygeodesy.internals import _enquote, _passarg
|
|
52
|
+
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DOT_, _from_, \
|
|
53
|
+
_not_finite_, _SPACE_, _std_, _UNDER_
|
|
39
54
|
from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
|
|
40
55
|
from pygeodesy.named import _name__, _name2__, _Named, _NamedTuple, \
|
|
41
56
|
_NotImplemented
|
|
42
|
-
from pygeodesy.props import _allPropertiesOf_n,
|
|
43
|
-
|
|
57
|
+
from pygeodesy.props import _allPropertiesOf_n, deprecated_method, \
|
|
58
|
+
deprecated_property_RO, Property, \
|
|
59
|
+
Property_RO, property_RO
|
|
44
60
|
from pygeodesy.streprs import Fmt, fstr, unstr
|
|
45
61
|
# from pygeodesy.units import Float, Int # from .constants
|
|
46
62
|
|
|
47
|
-
from math import
|
|
63
|
+
from math import fabs, isinf, isnan, \
|
|
64
|
+
ceil as _ceil, floor as _floor # PYCHOK used! .ltp
|
|
48
65
|
|
|
49
66
|
__all__ = _ALL_LAZY.fsums
|
|
50
|
-
__version__ = '24.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
__version__ = '24.09.25'
|
|
68
|
+
|
|
69
|
+
from pygeodesy.interns import (
|
|
70
|
+
_PLUS_ as _add_op_, # in .auxilats.auxAngle
|
|
71
|
+
_EQUAL_ as _fset_op_,
|
|
72
|
+
_RANGLE_ as _gt_op_,
|
|
73
|
+
_LANGLE_ as _lt_op_,
|
|
74
|
+
_PERCENT_ as _mod_op_,
|
|
75
|
+
_STAR_ as _mul_op_,
|
|
76
|
+
_NOTEQUAL_ as _ne_op_,
|
|
77
|
+
_DASH_ as _sub_op_, # in .auxilats.auxAngle
|
|
78
|
+
_SLASH_ as _truediv_op_
|
|
79
|
+
)
|
|
80
|
+
_eq_op_ = _fset_op_ * 2 # _DEQUAL_
|
|
81
|
+
_floordiv_op_ = _truediv_op_ * 2 # _DSLASH_
|
|
82
|
+
_divmod_op_ = _floordiv_op_ + _mod_op_
|
|
83
|
+
_F2PRODUCT = _getenv('PYGEODESY_FSUM_F2PRODUCT', NN)
|
|
84
|
+
_ge_op_ = _gt_op_ + _fset_op_
|
|
85
|
+
_iadd_op_ = _add_op_ + _fset_op_ # in .auxilats.auxAngle, .fstats
|
|
60
86
|
_integer_ = 'integer'
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
_mod_op_ = _PERCENT_
|
|
65
|
-
_mul_op_ = _STAR_
|
|
66
|
-
_ne_op_ = _NOTEQUAL_
|
|
87
|
+
_isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
|
|
88
|
+
_le_op_ = _lt_op_ + _fset_op_
|
|
89
|
+
_NONFINITES = _getenv('PYGEODESY_FSUM_NONFINITES', NN) == _std_
|
|
67
90
|
_non_zero_ = 'non-zero'
|
|
68
|
-
_pow_op_ =
|
|
91
|
+
_pow_op_ = _mul_op_ * 2 # _DSTAR_
|
|
92
|
+
_RESIDUAL_0_0 = _getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)
|
|
69
93
|
_significant_ = 'significant'
|
|
70
|
-
|
|
94
|
+
_2split3s = _passarg
|
|
71
95
|
_threshold_ = 'threshold'
|
|
72
|
-
_truediv_op_ = _SLASH_
|
|
73
|
-
_divmod_op_ = _floordiv_op_ + _mod_op_
|
|
74
|
-
_isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
|
|
75
96
|
|
|
76
97
|
|
|
77
|
-
def
|
|
78
|
-
'''(INTERNAL) Helper for C{Fsum._fsum2}.
|
|
79
|
-
'''
|
|
80
|
-
try:
|
|
81
|
-
a, b = _2sum(*ab)
|
|
82
|
-
except _OverflowError:
|
|
83
|
-
a, b = ab
|
|
84
|
-
return float(a if fabs(a) > fabs(b) else b)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def _2error(unused): # in .fstats
|
|
88
|
-
'''(INTERNAL) Throw a C{not-finite} exception.
|
|
89
|
-
'''
|
|
90
|
-
raise ValueError(_not_finite_)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def _2finite(x):
|
|
98
|
+
def _2finite(x): # in .fstats
|
|
94
99
|
'''(INTERNAL) return C{float(x)} if finite.
|
|
95
100
|
'''
|
|
96
|
-
x
|
|
97
|
-
|
|
101
|
+
return (float(x) if _isfinite(x) # and isscalar(x)
|
|
102
|
+
else _nfError(x))
|
|
98
103
|
|
|
99
104
|
|
|
100
|
-
def _2float(index=None, **name_value): # in .fmath, .fstats
|
|
105
|
+
def _2float(index=None, _isfine=_isfinite, **name_value): # in .fmath, .fstats
|
|
101
106
|
'''(INTERNAL) Raise C{TypeError} or C{ValueError} if not scalar or infinite.
|
|
102
107
|
'''
|
|
103
108
|
n, v = name_value.popitem() # _xkwds_item2(name_value)
|
|
104
109
|
try:
|
|
105
|
-
|
|
110
|
+
f = float(v)
|
|
111
|
+
return f if _isfine(f) else _nfError(f)
|
|
106
112
|
except Exception as X:
|
|
107
113
|
raise _xError(X, Fmt.INDEX(n, index), v)
|
|
108
114
|
|
|
@@ -111,34 +117,141 @@ def _X_ps(X): # for _2floats only
|
|
|
111
117
|
return X._ps
|
|
112
118
|
|
|
113
119
|
|
|
114
|
-
def _2floats(xs, origin=0, _X=_X_ps, _x=float):
|
|
120
|
+
def _2floats(xs, origin=0, _X=_X_ps, _x=float, _isfine=_isfinite):
|
|
115
121
|
'''(INTERNAL) Yield each B{C{xs}} as a C{float}.
|
|
116
122
|
'''
|
|
117
123
|
try:
|
|
118
|
-
i, x = origin,
|
|
119
|
-
_fin = _isfinite
|
|
124
|
+
i, x = origin, xs
|
|
120
125
|
_FsT = _Fsum_Fsum2Tuple_types
|
|
121
|
-
_isa = isinstance
|
|
122
126
|
for x in _xiterable(xs):
|
|
123
|
-
if
|
|
127
|
+
if isinstance(x, _FsT):
|
|
124
128
|
for p in _X(x._Fsum):
|
|
125
129
|
yield p
|
|
126
130
|
else:
|
|
127
131
|
f = _x(x)
|
|
128
|
-
yield f if
|
|
132
|
+
yield f if _isfine(f) else _nfError(f)
|
|
129
133
|
i += 1
|
|
130
134
|
except Exception as X:
|
|
131
|
-
raise
|
|
132
|
-
|
|
135
|
+
raise _xsError(X, xs, i, x)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
try: # MCCABE 17
|
|
139
|
+
from math import fma as _fma
|
|
140
|
+
except ImportError: # Python 3.12-
|
|
141
|
+
|
|
142
|
+
if _F2PRODUCT == _std_:
|
|
143
|
+
_2FACTOR = pow(2, (MANT_DIG + 1) // 2) + 1
|
|
133
144
|
|
|
145
|
+
def _fma(a, b, c):
|
|
146
|
+
# mimick C{math.fma} from Python 3.13+,
|
|
147
|
+
# the same accuracy, but ~13x slower
|
|
148
|
+
b3s = _2split3(b),
|
|
149
|
+
r = fsumf_(c, *_2products(a, b3s)) # two=True
|
|
150
|
+
return r if _isfinite(r) else _fmaX(r, a, b, c)
|
|
134
151
|
|
|
135
|
-
def
|
|
152
|
+
def _2split3(x):
|
|
153
|
+
# Split U{Algorithm 3.2
|
|
154
|
+
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
155
|
+
a = c = x * _2FACTOR
|
|
156
|
+
a -= c - x
|
|
157
|
+
b = x - a
|
|
158
|
+
return x, a, b
|
|
159
|
+
|
|
160
|
+
def _2split3s(xs): # overwrites
|
|
161
|
+
return tuple(map(_2split3, xs))
|
|
162
|
+
|
|
163
|
+
else:
|
|
164
|
+
def _fma(*a_b_c): # PYCHOK no cover
|
|
165
|
+
# mimick C{math.fma} from Python 3.13+,
|
|
166
|
+
# the same accuracy, but ~14x slower
|
|
167
|
+
(na, da), (nb, db), (nc, dc) = map(_2n_d, a_b_c)
|
|
168
|
+
n = na * nb * dc
|
|
169
|
+
n += da * db * nc
|
|
170
|
+
d = da * db * dc
|
|
171
|
+
try:
|
|
172
|
+
r = float(n / d)
|
|
173
|
+
except OverflowError: # "integer division result too large ..."
|
|
174
|
+
r = NINF if (_signOf(n, 0) * _signOf(d, 0)) < 0 else INF
|
|
175
|
+
return r if _isfinite(r) else _fmaX(r, *a_b_c) # "overflow in fma"
|
|
176
|
+
|
|
177
|
+
def _2n_d(x):
|
|
178
|
+
try: # int.as_integer_ratio in 3.8+
|
|
179
|
+
return x.as_integer_ratio()
|
|
180
|
+
except (AttributeError, OverflowError, TypeError, ValueError):
|
|
181
|
+
return (x if isint(x) else float(x)), 1
|
|
182
|
+
|
|
183
|
+
def _fmaX(r, *a_b_c): # like Python 3.13+ I{Modules/mathmodule.c}:
|
|
184
|
+
# raise a ValueError for a NAN result from non-NAN C{a_b_c}s or
|
|
185
|
+
# OverflowError for a non-NAN result from all finite C{a_b_c}s.
|
|
186
|
+
if isnan(r):
|
|
187
|
+
def _is(x):
|
|
188
|
+
return not isnan(x)
|
|
189
|
+
else:
|
|
190
|
+
_is = _isfinite
|
|
191
|
+
if all(map(_is, a_b_c)):
|
|
192
|
+
raise _nfError(r, unstr(_fma, *a_b_c))
|
|
193
|
+
return r
|
|
194
|
+
|
|
195
|
+
if _2split3s is _passarg: # math._fma or _fma(*a_b_c)
|
|
196
|
+
|
|
197
|
+
def _2products(x, ys, **unused):
|
|
198
|
+
# TwoProductFMA U{Algorithm 3.5
|
|
199
|
+
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
200
|
+
for y in ys:
|
|
201
|
+
f = x * y
|
|
202
|
+
yield f
|
|
203
|
+
yield _fma(x, y, -f)
|
|
204
|
+
|
|
205
|
+
else: # in _std_ _fma(a, b, c)
|
|
206
|
+
|
|
207
|
+
def _2products(x, y3s, two=False): # PYCHOK redef
|
|
208
|
+
# TwoProduct U{Algorithm 3.3
|
|
209
|
+
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
210
|
+
# also in Python 3.13+ C{Modules/marhmodule.c} under
|
|
211
|
+
# #ifndef UNRELIABLE_FMA ... #else ... #endif
|
|
212
|
+
_, a, b = _2split3(x)
|
|
213
|
+
for y, c, d in y3s:
|
|
214
|
+
y *= x
|
|
215
|
+
yield y
|
|
216
|
+
if two: # or not a:
|
|
217
|
+
yield b * d - (((y - a * c) - b * c) - a * d)
|
|
218
|
+
# = b * d + (a * d - ((y - a * c) - b * c))
|
|
219
|
+
# = b * d + (a * d + (b * c - (y - a * c)))
|
|
220
|
+
# = b * d + (a * d + (b * c + (a * c - y)))
|
|
221
|
+
else:
|
|
222
|
+
yield a * c - y
|
|
223
|
+
yield b * c
|
|
224
|
+
if d:
|
|
225
|
+
yield a * d
|
|
226
|
+
yield b * d
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def f2product(*two):
|
|
230
|
+
'''Turn accurate I{TwoProduct} multiplication on or off.
|
|
231
|
+
|
|
232
|
+
@arg two: If C{True}, turn I{TwoProduct} on, if C{False} off or
|
|
233
|
+
if C{None} or omitted, keep the current setting.
|
|
234
|
+
|
|
235
|
+
@return: The previous setting (C{bool}).
|
|
236
|
+
|
|
237
|
+
@see: I{TwoProduct} multiplication is based on the I{TwoProductFMA}
|
|
238
|
+
U{Algorithm 3.5 <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
239
|
+
using function C{math.fma} from Python 3.13 and later or an
|
|
240
|
+
equivalent, slower implementation when not available.
|
|
241
|
+
'''
|
|
242
|
+
t = Fsum._f2product
|
|
243
|
+
if two and two[0] is not None:
|
|
244
|
+
Fsum._f2product = bool(two[0])
|
|
245
|
+
return t
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _Fsumf_(*xs): # in .auxLat, .ltp, ...
|
|
136
249
|
'''(INTERNAL) An C{Fsum} of I{known scalars}.
|
|
137
250
|
'''
|
|
138
251
|
return Fsum()._facc_scalar(xs, up=False)
|
|
139
252
|
|
|
140
253
|
|
|
141
|
-
def _Fsum1f_(*xs): #
|
|
254
|
+
def _Fsum1f_(*xs): # in .albers
|
|
142
255
|
'''(INTERNAL) An C{Fsum} of I{known scalars}, 1-primed.
|
|
143
256
|
'''
|
|
144
257
|
return Fsum()._facc_scalar(_1primed(xs), up=False)
|
|
@@ -162,16 +275,60 @@ def _isFsum(x): # in .fmath
|
|
|
162
275
|
return isinstance(x, Fsum)
|
|
163
276
|
|
|
164
277
|
|
|
165
|
-
def _isFsumTuple(x): # in .fmath
|
|
278
|
+
def _isFsumTuple(x): # in .basics, .constants, .fmath, .fstats
|
|
166
279
|
'''(INTERNAL) Is C{x} an C{Fsum} or C{Fsum2Tuple} instance?
|
|
167
280
|
'''
|
|
168
281
|
return isinstance(x, _Fsum_Fsum2Tuple_types)
|
|
169
282
|
|
|
170
283
|
|
|
171
|
-
def
|
|
172
|
-
'''(INTERNAL)
|
|
284
|
+
def _isOK(unused):
|
|
285
|
+
'''(INTERNAL) Helper for C{nonfiniterrors} and C{Fsum.nonfinites}.
|
|
286
|
+
'''
|
|
287
|
+
return True
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _isOK_or_finite(x, _isfine=_isfinite):
|
|
291
|
+
'''(INTERNAL) Is C{x} finite or is I{non-finite} OK?.
|
|
292
|
+
'''
|
|
293
|
+
# assert _isfine in (_isOK, _isfinite)
|
|
294
|
+
return _isfine(x)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def _nfError(x, *args):
|
|
298
|
+
'''(INTERNAL) Throw a C{not-finite} exception.
|
|
299
|
+
'''
|
|
300
|
+
E = _NonfiniteError(x)
|
|
301
|
+
t = Fmt.PARENSPACED(_not_finite_, x)
|
|
302
|
+
if args: # in _fma, _2sum
|
|
303
|
+
return E(txt=t, *args)
|
|
304
|
+
raise E(t, txt=None)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def nonfiniterrors(*raiser):
|
|
308
|
+
'''Throw C{OverflowError} and C{ValueError} exceptions for or
|
|
309
|
+
handle I{non-finite} C{float}s as C{inf}, C{INF}, C{NINF},
|
|
310
|
+
C{nan} and C{NAN} in summations and multiplications.
|
|
311
|
+
|
|
312
|
+
@arg raiser: If C{True}, throw exceptions, if C{False} handle
|
|
313
|
+
I{non-finites} or if C{None} or omitted, leave
|
|
314
|
+
the setting unchanged.
|
|
315
|
+
|
|
316
|
+
@return: Previous setting (C{bool}).
|
|
317
|
+
|
|
318
|
+
@note: C{inf}, C{INF} and C{NINF} throw an C{OverflowError},
|
|
319
|
+
C{nan} and C{NAN} a C{ValueError}.
|
|
320
|
+
'''
|
|
321
|
+
d = Fsum._isfine
|
|
322
|
+
if raiser and raiser[0] is not None:
|
|
323
|
+
Fsum._isfine = {} if bool(raiser[0]) else Fsum._nonfinites_isfine_kwds[True]
|
|
324
|
+
return _xkwds_get1(d, _isfine=_isfinite) is _isfinite
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def _NonfiniteError(x):
|
|
328
|
+
'''(INTERNAL) Return the Error class for C{x}, I{non-finite}.
|
|
173
329
|
'''
|
|
174
|
-
return
|
|
330
|
+
return _OverflowError if isinf(x) else (
|
|
331
|
+
_ValueError if isnan(x) else _AssertionError)
|
|
175
332
|
|
|
176
333
|
|
|
177
334
|
def _1primed(xs): # in .fmath
|
|
@@ -184,16 +341,15 @@ def _1primed(xs): # in .fmath
|
|
|
184
341
|
yield _N_1_0
|
|
185
342
|
|
|
186
343
|
|
|
187
|
-
def _psum(ps): # PYCHOK used!
|
|
344
|
+
def _psum(ps, **_isfine): # PYCHOK used!
|
|
188
345
|
'''(INTERNAL) Partials summation, updating C{ps}.
|
|
189
346
|
'''
|
|
190
347
|
# assert isinstance(ps, list)
|
|
191
|
-
i
|
|
192
|
-
s
|
|
193
|
-
_2s = _2sum
|
|
348
|
+
i = len(ps) - 1
|
|
349
|
+
s = _0_0 if i < 0 else ps[i]
|
|
194
350
|
while i > 0:
|
|
195
351
|
i -= 1
|
|
196
|
-
s, r =
|
|
352
|
+
s, r = _2sum(s, ps[i], **_isfine)
|
|
197
353
|
if r: # sum(ps) became inexact
|
|
198
354
|
if s:
|
|
199
355
|
ps[i:] = r, s
|
|
@@ -201,24 +357,28 @@ def _psum(ps): # PYCHOK used!
|
|
|
201
357
|
s = _2halfeven(s, r, ps[i-1])
|
|
202
358
|
break # return s
|
|
203
359
|
s = r # PYCHOK no cover
|
|
360
|
+
elif not _isfinite(s): # non-finite OK
|
|
361
|
+
i = 0 # collapse ps
|
|
362
|
+
if ps:
|
|
363
|
+
s += _sum(ps) # _fsum(ps)
|
|
204
364
|
ps[i:] = s,
|
|
205
365
|
return s
|
|
206
366
|
|
|
207
367
|
|
|
208
|
-
def _Psum(ps, **
|
|
368
|
+
def _Psum(ps, **name_f2product_nonfinites_RESIDUAL):
|
|
209
369
|
'''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
|
|
210
370
|
'''
|
|
211
|
-
|
|
371
|
+
F = Fsum(**name_f2product_nonfinites_RESIDUAL)
|
|
212
372
|
if ps:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return
|
|
373
|
+
F._ps[:] = ps
|
|
374
|
+
F._n = len(F._ps)
|
|
375
|
+
return F
|
|
216
376
|
|
|
217
377
|
|
|
218
|
-
def _Psum_(*ps, **
|
|
219
|
-
'''(INTERNAL) Return an C{Fsum} from
|
|
378
|
+
def _Psum_(*ps, **name_f2product_nonfinites_RESIDUAL): # in .fmath
|
|
379
|
+
'''(INTERNAL) Return an C{Fsum} from I{known scalar} C{ps}.
|
|
220
380
|
'''
|
|
221
|
-
return _Psum(ps, **
|
|
381
|
+
return _Psum(ps, **name_f2product_nonfinites_RESIDUAL)
|
|
222
382
|
|
|
223
383
|
|
|
224
384
|
def _2scalar2(other):
|
|
@@ -242,7 +402,7 @@ def _2scalar2(other):
|
|
|
242
402
|
def _s_r(s, r):
|
|
243
403
|
'''(INTERNAL) Return C{(s, r)}, I{ordered}.
|
|
244
404
|
'''
|
|
245
|
-
if r:
|
|
405
|
+
if r and _isfinite(s):
|
|
246
406
|
if fabs(s) < fabs(r):
|
|
247
407
|
s, r = r, (s or INT0)
|
|
248
408
|
else:
|
|
@@ -254,7 +414,7 @@ def _strcomplex(s, *args):
|
|
|
254
414
|
'''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
|
|
255
415
|
'''
|
|
256
416
|
c = _strcomplex.__name__[4:]
|
|
257
|
-
n =
|
|
417
|
+
n = _sub_op_(len(args), _arg_)
|
|
258
418
|
t = unstr(pow, *args)
|
|
259
419
|
return _SPACE_(c, s, _from_, n, t)
|
|
260
420
|
|
|
@@ -270,9 +430,12 @@ def _stresidual(prefix, residual, R=0, **mod_ratio):
|
|
|
270
430
|
return _SPACE_(prefix, t, Fmt.exceeds_R(R), _threshold_)
|
|
271
431
|
|
|
272
432
|
|
|
273
|
-
def _2sum(a, b): #
|
|
274
|
-
'''(INTERNAL) Return C{a + b} as 2-tuple (sum, residual)
|
|
433
|
+
def _2sum(a, b, _isfine=_isfinite): # in .testFmath
|
|
434
|
+
'''(INTERNAL) Return C{a + b} as 2-tuple C{(sum, residual)} with finite C{sum},
|
|
435
|
+
otherwise as 2-tuple C{(nonfinite, 0)} iff I{non-finites} are OK.
|
|
275
436
|
'''
|
|
437
|
+
# FastTwoSum U{Algorithm 1.1<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
438
|
+
|
|
276
439
|
# Neumaier, A. U{Rundungsfehleranalyse einiger Verfahren zur Summation endlicher
|
|
277
440
|
# Summen<https://OnlineLibrary.Wiley.com/doi/epdf/10.1002/zamm.19740540106>},
|
|
278
441
|
# 1974, Zeitschrift für Angewandte Mathmatik und Mechanik, vol 51, nr 1, p 39-51
|
|
@@ -283,10 +446,12 @@ def _2sum(a, b): # by .testFmath
|
|
|
283
446
|
r = (b - s) + a
|
|
284
447
|
else:
|
|
285
448
|
r = (a - s) + b
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
449
|
+
elif _isfine(s):
|
|
450
|
+
r = 0
|
|
451
|
+
else: # non-finite and not OK
|
|
452
|
+
t = unstr(_2sum, a, b)
|
|
453
|
+
raise _nfError(s, t)
|
|
454
|
+
return s, r
|
|
290
455
|
|
|
291
456
|
|
|
292
457
|
def _threshold(threshold=_0_0, **kwds):
|
|
@@ -294,29 +459,28 @@ def _threshold(threshold=_0_0, **kwds):
|
|
|
294
459
|
optionally from single kwds C{B{RESIDUAL}=scalar}.
|
|
295
460
|
'''
|
|
296
461
|
if kwds:
|
|
297
|
-
threshold
|
|
298
|
-
# threshold = kwds.pop('RESIDUAL', threshold)
|
|
299
|
-
if kwds:
|
|
300
|
-
raise _UnexpectedError(**kwds)
|
|
462
|
+
threshold = _xkwds_get1(kwds, RESIDUAL=threshold)
|
|
301
463
|
try:
|
|
302
464
|
return _2finite(threshold) # PYCHOK None
|
|
303
465
|
except Exception as x:
|
|
304
466
|
raise ResidualError(threshold=threshold, cause=x)
|
|
305
467
|
|
|
306
468
|
|
|
307
|
-
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
308
|
-
'''Precision floating point summation
|
|
469
|
+
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats, ...
|
|
470
|
+
'''Precision floating point summation, I{running} summation and accurate multiplication.
|
|
309
471
|
|
|
310
472
|
Unlike Python's C{math.fsum}, this class accumulates values and provides intermediate,
|
|
311
473
|
I{running}, precision floating point summations. Accumulation may continue after any
|
|
312
474
|
intermediate, I{running} summuation.
|
|
313
475
|
|
|
314
476
|
@note: Values may be L{Fsum}, L{Fsum2Tuple}, C{int}, C{float} or C{scalar} instances,
|
|
315
|
-
any C{type} having method C{__float__}
|
|
316
|
-
C{float}, except C{complex}.
|
|
477
|
+
i.e. any C{type} having method C{__float__}.
|
|
317
478
|
|
|
318
|
-
@note: Handling of
|
|
319
|
-
|
|
479
|
+
@note: Handling of I{non-finites} as C{inf}, C{INF}, C{NINF}, C{nan} and C{NAN} is
|
|
480
|
+
determined globally by function L{nonfiniterrors<fsums.nonfiniterrors>} and
|
|
481
|
+
by method L{nonfinites<Fsum.nonfinites>} for individual C{Fsum} instances,
|
|
482
|
+
overruling the global setting. By default and for backward compatibility,
|
|
483
|
+
I{non-finites} raise exceptions.
|
|
320
484
|
|
|
321
485
|
@see: U{Hettinger<https://GitHub.com/ActiveState/code/tree/master/recipes/Python/
|
|
322
486
|
393090_Binary_floating_point_summatiaccurate_full/recipe-393090.py>},
|
|
@@ -324,40 +488,41 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
324
488
|
<https://Link.Springer.com/article/10.1007/s00607-005-0139-x>}, Python 2.6+
|
|
325
489
|
file I{Modules/mathmodule.c} and the issue log U{Full precision summation
|
|
326
490
|
<https://Bugs.Python.org/issue2819>}.
|
|
491
|
+
|
|
492
|
+
@see: Method L{f2product<Fsum.f2product>} for details about accurate I{TwoProduct}
|
|
493
|
+
multiplication.
|
|
494
|
+
|
|
495
|
+
@see: Module L{fsums<pygeodesy.fsums>} for env variables C{PYGEODESY_FSUM_F2PRODUCT},
|
|
496
|
+
C{PYGEODESY_FSUM_NONFINITES} and C{PYGEODESY_FSUM_RESIDUAL}.
|
|
327
497
|
'''
|
|
328
|
-
|
|
498
|
+
_f2product = _sys_version_info2 > (3, 12) or bool(_F2PRODUCT)
|
|
499
|
+
_isfine = {} # == _isfinite
|
|
329
500
|
_n = 0
|
|
330
501
|
# _ps = [] # partial sums
|
|
331
502
|
# _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps))
|
|
332
|
-
_RESIDUAL = _threshold(
|
|
503
|
+
_RESIDUAL = _threshold(_RESIDUAL_0_0)
|
|
333
504
|
|
|
334
|
-
def __init__(self, *xs, **
|
|
335
|
-
'''New L{Fsum}
|
|
505
|
+
def __init__(self, *xs, **name_f2product_nonfinites_RESIDUAL):
|
|
506
|
+
'''New L{Fsum}.
|
|
336
507
|
|
|
337
|
-
@arg xs: No, one or more initial items to
|
|
338
|
-
|
|
339
|
-
@kwarg
|
|
340
|
-
|
|
341
|
-
|
|
508
|
+
@arg xs: No, one or more initial items to accumulate (each C{scalar}, an
|
|
509
|
+
L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
510
|
+
@kwarg name_f2product_nonfinites_RESIDUAL: Optional C{B{name}=NN} (C{str})
|
|
511
|
+
and settings C{B{f2product}=None} (C{bool}), C{B{nonfinites}=None}
|
|
512
|
+
(C{bool}) and C{B{RESIDUAL}=0.0} threshold (C{scalar}) for this
|
|
513
|
+
L{Fsum}.
|
|
342
514
|
|
|
343
|
-
@see: Methods L{Fsum.
|
|
515
|
+
@see: Methods L{Fsum.f2product}, L{Fsum.nonfinites}, L{Fsum.RESIDUAL},
|
|
516
|
+
L{Fsum.fadd} and L{Fsum.fadd_}.
|
|
344
517
|
'''
|
|
345
|
-
if
|
|
346
|
-
|
|
347
|
-
if kwds:
|
|
348
|
-
R = Fsum._RESIDUAL
|
|
349
|
-
t = _threshold(R, **kwds)
|
|
350
|
-
if t != R:
|
|
351
|
-
self._RESIDUAL = t
|
|
352
|
-
if n:
|
|
353
|
-
self.name = n
|
|
354
|
-
|
|
518
|
+
if name_f2product_nonfinites_RESIDUAL:
|
|
519
|
+
self._optionals(**name_f2product_nonfinites_RESIDUAL)
|
|
355
520
|
self._ps = [] # [_0_0], see L{Fsum._fprs}
|
|
356
521
|
if xs:
|
|
357
|
-
self.
|
|
522
|
+
self._facc_args(xs, up=False)
|
|
358
523
|
|
|
359
524
|
def __abs__(self):
|
|
360
|
-
'''Return
|
|
525
|
+
'''Return C{abs(self)} as an L{Fsum}.
|
|
361
526
|
'''
|
|
362
527
|
s = self.signOf() # == self._cmp_0(0)
|
|
363
528
|
return (-self) if s < 0 else self._copy_2(self.__abs__)
|
|
@@ -375,7 +540,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
375
540
|
return f._fadd(other, _add_op_)
|
|
376
541
|
|
|
377
542
|
def __bool__(self): # PYCHOK Python 3+
|
|
378
|
-
'''Return C{True}
|
|
543
|
+
'''Return C{bool(B{self})}, C{True} iff C{residual} is zero.
|
|
379
544
|
'''
|
|
380
545
|
s, r = self._fprs2
|
|
381
546
|
return bool(s or r) and s != -r # == self != 0
|
|
@@ -418,7 +583,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
418
583
|
return f._fdivmod2(other, _divmod_op_, **raiser_RESIDUAL)
|
|
419
584
|
|
|
420
585
|
def __eq__(self, other):
|
|
421
|
-
'''
|
|
586
|
+
'''Return C{(B{self} == B{other})} as C{bool} where B{C{other}}
|
|
587
|
+
is C{scalar}, an other L{Fsum} or L{Fsum2Tuple}.
|
|
422
588
|
'''
|
|
423
589
|
return self._cmp_0(other, _eq_op_) == 0
|
|
424
590
|
|
|
@@ -455,19 +621,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
455
621
|
return _NotImplemented(self, *other)
|
|
456
622
|
|
|
457
623
|
def __ge__(self, other):
|
|
458
|
-
'''
|
|
624
|
+
'''Return C{(B{self} >= B{other})}, see C{__eq__}.
|
|
459
625
|
'''
|
|
460
626
|
return self._cmp_0(other, _ge_op_) >= 0
|
|
461
627
|
|
|
462
628
|
def __gt__(self, other):
|
|
463
|
-
'''
|
|
629
|
+
'''Return C{(B{self} > B{other})}, see C{__eq__}.
|
|
464
630
|
'''
|
|
465
631
|
return self._cmp_0(other, _gt_op_) > 0
|
|
466
632
|
|
|
467
633
|
def __hash__(self): # PYCHOK no cover
|
|
468
|
-
'''Return
|
|
634
|
+
'''Return C{hash(B{self})} as C{float}.
|
|
469
635
|
'''
|
|
470
|
-
|
|
636
|
+
# @see: U{Notes for type implementors<https://docs.Python.org/
|
|
637
|
+
# 3/library/numbers.html#numbers.Rational>}
|
|
638
|
+
return hash(self.partials) # tuple.__hash__()
|
|
471
639
|
|
|
472
640
|
def __iadd__(self, other):
|
|
473
641
|
'''Apply C{B{self} += B{other}} to this instance.
|
|
@@ -485,7 +653,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
485
653
|
try:
|
|
486
654
|
return self._fadd(other, _iadd_op_)
|
|
487
655
|
except TypeError:
|
|
488
|
-
|
|
656
|
+
pass
|
|
657
|
+
_xiterable(other)
|
|
658
|
+
return self._facc(other)
|
|
489
659
|
|
|
490
660
|
def __ifloordiv__(self, other):
|
|
491
661
|
'''Apply C{B{self} //= B{other}} to this instance.
|
|
@@ -499,7 +669,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
499
669
|
|
|
500
670
|
@raise TypeError: Invalid B{C{other}} type.
|
|
501
671
|
|
|
502
|
-
@raise ValueError: Invalid or non-finite B{C{other}}.
|
|
672
|
+
@raise ValueError: Invalid or I{non-finite} B{C{other}}.
|
|
503
673
|
|
|
504
674
|
@raise ZeroDivisionError: Zero B{C{other}}.
|
|
505
675
|
|
|
@@ -533,7 +703,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
533
703
|
|
|
534
704
|
@raise TypeError: Invalid B{C{other}} type.
|
|
535
705
|
|
|
536
|
-
@raise ValueError: Invalid or non-finite B{C{other}}.
|
|
706
|
+
@raise ValueError: Invalid or I{non-finite} B{C{other}}.
|
|
537
707
|
'''
|
|
538
708
|
return self._fmul(other, _mul_op_ + _fset_op_)
|
|
539
709
|
|
|
@@ -554,7 +724,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
554
724
|
def __ipow__(self, other, *mod, **raiser_RESIDUAL): # PYCHOK 2 vs 3 args
|
|
555
725
|
'''Apply C{B{self} **= B{other}} to this instance.
|
|
556
726
|
|
|
557
|
-
@arg other: The exponent (C{scalar}, L{Fsum} or L{Fsum2Tuple}).
|
|
727
|
+
@arg other: The exponent (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
558
728
|
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
559
729
|
C{pow(B{self}, B{other}, B{mod})} version.
|
|
560
730
|
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
|
|
@@ -604,7 +774,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
604
774
|
try:
|
|
605
775
|
return self._fsub(other, _isub_op_)
|
|
606
776
|
except TypeError:
|
|
607
|
-
|
|
777
|
+
pass
|
|
778
|
+
_xiterable(other)
|
|
779
|
+
return self._facc_neg(other)
|
|
608
780
|
|
|
609
781
|
def __iter__(self):
|
|
610
782
|
'''Return an C{iter}ator over a C{partials} duplicate.
|
|
@@ -628,7 +800,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
628
800
|
|
|
629
801
|
@raise TypeError: Invalid B{C{other}} type.
|
|
630
802
|
|
|
631
|
-
@raise ValueError: Invalid or non-finite B{C{other}}.
|
|
803
|
+
@raise ValueError: Invalid or I{non-finite} B{C{other}}.
|
|
632
804
|
|
|
633
805
|
@raise ZeroDivisionError: Zero B{C{other}}.
|
|
634
806
|
|
|
@@ -637,7 +809,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
637
809
|
return self._ftruediv(other, _truediv_op_ + _fset_op_, **raiser_RESIDUAL)
|
|
638
810
|
|
|
639
811
|
def __le__(self, other):
|
|
640
|
-
'''
|
|
812
|
+
'''Return C{(B{self} <= B{other})}, see C{__eq__}.
|
|
641
813
|
'''
|
|
642
814
|
return self._cmp_0(other, _le_op_) <= 0
|
|
643
815
|
|
|
@@ -647,7 +819,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
647
819
|
return self._n
|
|
648
820
|
|
|
649
821
|
def __lt__(self, other):
|
|
650
|
-
'''
|
|
822
|
+
'''Return C{(B{self} < B{other})}, see C{__eq__}.
|
|
651
823
|
'''
|
|
652
824
|
return self._cmp_0(other, _lt_op_) < 0
|
|
653
825
|
|
|
@@ -672,12 +844,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
672
844
|
return f._fmul(other, _mul_op_)
|
|
673
845
|
|
|
674
846
|
def __ne__(self, other):
|
|
675
|
-
'''
|
|
847
|
+
'''Return C{(B{self} != B{other})}, see C{__eq__}.
|
|
676
848
|
'''
|
|
677
849
|
return self._cmp_0(other, _ne_op_) != 0
|
|
678
850
|
|
|
679
851
|
def __neg__(self):
|
|
680
|
-
'''Return
|
|
852
|
+
'''Return C{copy(B{self})}, I{negated}.
|
|
681
853
|
'''
|
|
682
854
|
f = self._copy_2(self.__neg__)
|
|
683
855
|
return f._fset(self._neg)
|
|
@@ -825,11 +997,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
825
997
|
def as_integer_ratio(self):
|
|
826
998
|
'''Return this instance as the ratio of 2 integers.
|
|
827
999
|
|
|
828
|
-
@return: 2-Tuple C{(numerator, denominator)} both C{int}
|
|
829
|
-
|
|
830
|
-
non-
|
|
1000
|
+
@return: 2-Tuple C{(numerator, denominator)} both C{int} with
|
|
1001
|
+
C{numerator} signed and C{denominator} non-zero and
|
|
1002
|
+
positive. The C{numerator} is I{non-finite} if this
|
|
1003
|
+
instance is.
|
|
831
1004
|
|
|
832
|
-
@see:
|
|
1005
|
+
@see: Method L{Fsum.fint2} and C{float.as_integer_ratio} in
|
|
1006
|
+
Python 2.7+.
|
|
833
1007
|
'''
|
|
834
1008
|
n, r = self._fint2
|
|
835
1009
|
if r:
|
|
@@ -842,8 +1016,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
842
1016
|
|
|
843
1017
|
@property_RO
|
|
844
1018
|
def as_iscalar(self):
|
|
845
|
-
'''Get this instance I{as-is} (L{Fsum}
|
|
846
|
-
|
|
1019
|
+
'''Get this instance I{as-is} (L{Fsum} with C{non-zero residual},
|
|
1020
|
+
C{scalar} or I{non-finite}).
|
|
847
1021
|
'''
|
|
848
1022
|
s, r = self._fprs2
|
|
849
1023
|
return self if r else s
|
|
@@ -890,6 +1064,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
890
1064
|
f._ps = list(self._ps) # separate list
|
|
891
1065
|
if not deep:
|
|
892
1066
|
f._n = 1
|
|
1067
|
+
# assert f._f2product == self._f2product
|
|
893
1068
|
# assert f._Fsum is f
|
|
894
1069
|
return f
|
|
895
1070
|
|
|
@@ -901,6 +1076,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
901
1076
|
f = _Named.copy(self, deep=False, name=n)
|
|
902
1077
|
f._ps = list(self._ps) # separate list
|
|
903
1078
|
# assert f._n == self._n
|
|
1079
|
+
# assert f._f2product == self._f2product
|
|
904
1080
|
# assert f._Fsum is f
|
|
905
1081
|
return f
|
|
906
1082
|
|
|
@@ -910,13 +1086,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
910
1086
|
return other._copy_2(which) if _isFsum(other) else \
|
|
911
1087
|
self._copy_2(which)._fset(other)
|
|
912
1088
|
|
|
913
|
-
# def _copy_RESIDUAL(self, other):
|
|
914
|
-
# '''(INTERNAL) Copy C{other._RESIDUAL}.
|
|
915
|
-
# '''
|
|
916
|
-
# R = other._RESIDUAL
|
|
917
|
-
# if R is not Fsum._RESIDUAL:
|
|
918
|
-
# self._RESIDUAL = R
|
|
919
|
-
|
|
920
1089
|
divmod = __divmod__
|
|
921
1090
|
|
|
922
1091
|
def _Error(self, op, other, Error, **txt_cause):
|
|
@@ -943,28 +1112,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
943
1112
|
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s.
|
|
944
1113
|
'''
|
|
945
1114
|
if xs:
|
|
946
|
-
|
|
1115
|
+
kwds = _xkwds(self._isfine, **origin_X_x)
|
|
1116
|
+
_xs = _2floats(xs, **kwds) # PYCHOK yield
|
|
947
1117
|
ps = self._ps
|
|
948
1118
|
ps[:] = self._ps_acc(list(ps), _xs, up=up)
|
|
949
1119
|
return self
|
|
950
1120
|
|
|
951
|
-
def
|
|
952
|
-
'''(INTERNAL) Accumulate 0, 1 or more C{
|
|
953
|
-
|
|
1121
|
+
def _facc_args(self, xs, **up):
|
|
1122
|
+
'''(INTERNAL) Accumulate 0, 1 or more C{xs}, all positional
|
|
1123
|
+
arguments in the caller of this method.
|
|
954
1124
|
'''
|
|
955
|
-
return self.
|
|
956
|
-
self.
|
|
957
|
-
|
|
958
|
-
def _facc_inplace(self, other, op, _facc):
|
|
959
|
-
'''(INTERNAL) Accumulate from an iterable.
|
|
960
|
-
'''
|
|
961
|
-
try:
|
|
962
|
-
return _facc(other, origin=1) if _xiterable(other) else self
|
|
963
|
-
except Exception as X:
|
|
964
|
-
raise self._ErrorX(X, op, other)
|
|
1125
|
+
return self._facc(xs, origin=1, **up) if len(xs) != 1 else \
|
|
1126
|
+
self._fadd(xs[0], _add_op_, **up)
|
|
965
1127
|
|
|
966
1128
|
def _facc_neg(self, xs, **up_origin):
|
|
967
|
-
'''(INTERNAL) Accumulate more C{
|
|
1129
|
+
'''(INTERNAL) Accumulate more C{xs}, negated.
|
|
968
1130
|
'''
|
|
969
1131
|
def _N(X):
|
|
970
1132
|
return X._ps_neg
|
|
@@ -989,24 +1151,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
989
1151
|
p = s = int(p)
|
|
990
1152
|
m = Fsum._pow_int
|
|
991
1153
|
else:
|
|
992
|
-
p = s = _2float(power=p)
|
|
1154
|
+
p = s = _2float(power=p, **self._isfine)
|
|
993
1155
|
m = Fsum._pow_scalar
|
|
994
1156
|
return m, p, s, r
|
|
995
1157
|
|
|
996
1158
|
_Pow, p, s, r = _Pow4(power)
|
|
997
1159
|
if p: # and xs:
|
|
998
1160
|
op = which.__name__
|
|
999
|
-
|
|
1000
|
-
_Fs = Fsum
|
|
1001
|
-
_isa = isinstance
|
|
1161
|
+
_FsT = _Fsum_Fsum2Tuple_types
|
|
1002
1162
|
_pow = self._pow_2_3
|
|
1003
1163
|
|
|
1004
1164
|
def _P(X):
|
|
1005
1165
|
f = _Pow(X, p, power, op, **raiser_RESIDUAL)
|
|
1006
|
-
return f._ps if
|
|
1166
|
+
return f._ps if isinstance(f, _FsT) else (f,)
|
|
1007
1167
|
|
|
1008
1168
|
def _p(x):
|
|
1009
|
-
x =
|
|
1169
|
+
x = float(x)
|
|
1010
1170
|
f = _pow(x, s, power, op, **raiser_RESIDUAL)
|
|
1011
1171
|
if f and r:
|
|
1012
1172
|
f *= _pow(x, r, power, op, **raiser_RESIDUAL)
|
|
@@ -1057,12 +1217,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1057
1217
|
|
|
1058
1218
|
@raise TypeError: An invalid B{C{xs}} item.
|
|
1059
1219
|
|
|
1060
|
-
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
1220
|
+
@raise ValueError: Invalid or I{non-finite} B{C{xs}} value.
|
|
1061
1221
|
'''
|
|
1062
1222
|
if _isFsumTuple(xs):
|
|
1063
1223
|
self._facc_scalar(xs._ps)
|
|
1064
|
-
elif isscalar(xs):
|
|
1065
|
-
|
|
1224
|
+
elif isscalar(xs): # for backward compatibility # PYCHOK no cover
|
|
1225
|
+
x = _2float(x=xs, **self._isfine)
|
|
1226
|
+
self._facc_scalar_(x)
|
|
1066
1227
|
elif xs: # _xiterable(xs)
|
|
1067
1228
|
self._facc(xs)
|
|
1068
1229
|
return self
|
|
@@ -1075,17 +1236,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1075
1236
|
|
|
1076
1237
|
@see: Method L{Fsum.fadd} for further details.
|
|
1077
1238
|
'''
|
|
1078
|
-
return self.
|
|
1239
|
+
return self._facc_args(xs)
|
|
1079
1240
|
|
|
1080
1241
|
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
1081
1242
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
1082
1243
|
'''
|
|
1083
|
-
if
|
|
1084
|
-
self.
|
|
1085
|
-
|
|
1086
|
-
|
|
1244
|
+
if _isFsumTuple(other):
|
|
1245
|
+
if self._ps:
|
|
1246
|
+
self._facc_scalar(other._ps, **up)
|
|
1247
|
+
else:
|
|
1248
|
+
self._fset(other, op=op, **up)
|
|
1087
1249
|
elif self._scalar(other, op):
|
|
1088
|
-
self.
|
|
1250
|
+
if self._ps:
|
|
1251
|
+
self._facc_scalar_(other, **up)
|
|
1252
|
+
else:
|
|
1253
|
+
self._fset(other, op=op, **up)
|
|
1089
1254
|
return self
|
|
1090
1255
|
|
|
1091
1256
|
fcopy = copy # for backward compatibility
|
|
@@ -1100,7 +1265,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1100
1265
|
# but at least divmod(-3, 2) equals Cpython's result (-2, 1).
|
|
1101
1266
|
q = self._truediv(other, op, **raiser_RESIDUAL).floor
|
|
1102
1267
|
if q: # == float // other == floor(float / other)
|
|
1103
|
-
self -=
|
|
1268
|
+
self -= self._Fsum_as(q) * other # NOT other * q!
|
|
1104
1269
|
|
|
1105
1270
|
s = signOf(other) # make signOf(self) == signOf(other)
|
|
1106
1271
|
if s and self.signOf() == -s: # PYCHOK no cover
|
|
@@ -1111,33 +1276,34 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1111
1276
|
# raise self._Error(op, other, _AssertionError, txt__=signOf)
|
|
1112
1277
|
return DivMod2Tuple(q, self) # q is C{int} in Python 3+, but C{float} in Python 2-
|
|
1113
1278
|
|
|
1114
|
-
def _fhorner(self, x, cs, op): # in .fmath
|
|
1279
|
+
def _fhorner(self, x, cs, op, incx=True): # in .fmath
|
|
1115
1280
|
'''(INTERNAL) Add an L{Fhorner} evaluation of polynomial
|
|
1116
|
-
|
|
1281
|
+
C{sum(cs[i] * B{x}**i for i=0..len(cs)-1) if B{incx}
|
|
1282
|
+
else sum(... i=len(cs)-1..0)}.
|
|
1117
1283
|
'''
|
|
1118
1284
|
if _xiterablen(cs):
|
|
1119
|
-
H =
|
|
1285
|
+
H = self._Fsum_as(name__=self._fhorner)
|
|
1120
1286
|
if _isFsumTuple(x):
|
|
1121
1287
|
_mul = H._mul_Fsum
|
|
1122
1288
|
else:
|
|
1123
1289
|
_mul = H._mul_scalar
|
|
1124
|
-
x = _2float(x=x)
|
|
1290
|
+
x = _2float(x=x, **self._isfine)
|
|
1125
1291
|
if len(cs) > 1 and x:
|
|
1126
|
-
for c in reversed(cs):
|
|
1292
|
+
for c in (reversed(cs) if incx else cs):
|
|
1127
1293
|
H._fset_ps(_mul(x, op))
|
|
1128
1294
|
H._fadd(c, op, up=False)
|
|
1129
1295
|
else: # x == 0
|
|
1130
|
-
H = cs[0]
|
|
1296
|
+
H = cs[0] if cs else _0_0
|
|
1131
1297
|
self._fadd(H, op)
|
|
1132
1298
|
return self
|
|
1133
1299
|
|
|
1134
1300
|
def _finite(self, other, op=None):
|
|
1135
1301
|
'''(INTERNAL) Return B{C{other}} if C{finite}.
|
|
1136
1302
|
'''
|
|
1137
|
-
if
|
|
1303
|
+
if _isOK_or_finite(other, **self._isfine):
|
|
1138
1304
|
return other
|
|
1139
|
-
|
|
1140
|
-
|
|
1305
|
+
E = _NonfiniteError(other)
|
|
1306
|
+
raise self._Error(op, other, E, txt=_not_finite_)
|
|
1141
1307
|
|
|
1142
1308
|
def fint(self, name=NN, **raiser_RESIDUAL):
|
|
1143
1309
|
'''Return this instance' current running sum as C{integer}.
|
|
@@ -1161,7 +1327,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1161
1327
|
if R:
|
|
1162
1328
|
t = _stresidual(_integer_, r, **R)
|
|
1163
1329
|
raise ResidualError(_integer_, i, txt=t)
|
|
1164
|
-
return
|
|
1330
|
+
return self._Fsum_as(i, name=_name__(name, name__=self.fint))
|
|
1165
1331
|
|
|
1166
1332
|
def fint2(self, **name):
|
|
1167
1333
|
'''Return this instance' current running sum as C{int} and the
|
|
@@ -1172,6 +1338,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1172
1338
|
@return: An L{Fsum2Tuple}C{(fsum, residual)} with C{fsum}
|
|
1173
1339
|
an C{int} and I{integer} C{residual} a C{float} or
|
|
1174
1340
|
C{INT0} if the C{fsum} is considered to be I{exact}.
|
|
1341
|
+
The C{fsum} is I{non-finite} if this instance is.
|
|
1175
1342
|
'''
|
|
1176
1343
|
return Fsum2Tuple(*self._fint2, **name)
|
|
1177
1344
|
|
|
@@ -1179,18 +1346,35 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1179
1346
|
def _fint2(self): # see ._fset
|
|
1180
1347
|
'''(INTERNAL) Get 2-tuple (C{int}, I{integer} residual).
|
|
1181
1348
|
'''
|
|
1182
|
-
s,
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1349
|
+
s, _ = self._fprs2
|
|
1350
|
+
try:
|
|
1351
|
+
i = int(s)
|
|
1352
|
+
r = (self._ps_1sum(i) if len(self._ps) > 1 else
|
|
1353
|
+
float(s - i)) or INT0
|
|
1354
|
+
except (OverflowError, ValueError) as X:
|
|
1355
|
+
r = 0 # INF, NAN, NINF
|
|
1356
|
+
i = self._fintX(X, sum(self._ps))
|
|
1357
|
+
return i, r # Fsum2Tuple?
|
|
1358
|
+
|
|
1359
|
+
@_fint2.setter_ # PYCHOK setter_UNDERscore!
|
|
1360
|
+
def _fint2(self, s): # in _fset
|
|
1190
1361
|
'''(INTERNAL) Replace the C{_fint2} value.
|
|
1191
1362
|
'''
|
|
1192
|
-
|
|
1193
|
-
|
|
1363
|
+
try:
|
|
1364
|
+
i = int(s)
|
|
1365
|
+
r = (s - i) or INT0
|
|
1366
|
+
except (OverflowError, ValueError) as X:
|
|
1367
|
+
r = 0 # INF, NAN, NINF
|
|
1368
|
+
i = self._fintX(X, float(s))
|
|
1369
|
+
return i, r # like _fint2.getter
|
|
1370
|
+
|
|
1371
|
+
def _fintX(self, X, i): # PYCHOK X
|
|
1372
|
+
'''(INTERNAL) Handle I{non-finite} C{int}.
|
|
1373
|
+
'''
|
|
1374
|
+
# "cannot convert float infinity to integer"
|
|
1375
|
+
return i # ignore such Overflow-/ValueErrors
|
|
1376
|
+
# op = int.__name__
|
|
1377
|
+
# return self._nonfiniteX(X, op, i)
|
|
1194
1378
|
|
|
1195
1379
|
@deprecated_property_RO
|
|
1196
1380
|
def float_int(self): # PYCHOK no cover
|
|
@@ -1213,8 +1397,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1213
1397
|
f -= 1
|
|
1214
1398
|
return f # _floor(self._n_d)
|
|
1215
1399
|
|
|
1216
|
-
# ffloordiv = __ifloordiv__ # for naming consistency
|
|
1217
|
-
# floordiv = __floordiv__ # for naming consistency
|
|
1400
|
+
# ffloordiv = __ifloordiv__ # for naming consistency?
|
|
1401
|
+
# floordiv = __floordiv__ # for naming consistency?
|
|
1218
1402
|
|
|
1219
1403
|
def _floordiv(self, other, op, **raiser_RESIDUAL): # rather _ffloordiv?
|
|
1220
1404
|
'''Apply C{B{self} //= B{other}}.
|
|
@@ -1222,6 +1406,33 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1222
1406
|
q = self._ftruediv(other, op, **raiser_RESIDUAL) # == self
|
|
1223
1407
|
return self._fset(q.floor) # floor(q)
|
|
1224
1408
|
|
|
1409
|
+
def fma(self, other1, other2, raiser=False): # in .fmath.fma
|
|
1410
|
+
'''Fused-multiply-add C{self *= B{other1}; self += B{other2}}.
|
|
1411
|
+
|
|
1412
|
+
@arg other1: Multiplier (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
1413
|
+
@arg other2: Addend (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
1414
|
+
@kwarg raiser: If C{True}, throw an exception, otherwise pass
|
|
1415
|
+
the I{non-finite} result (C{bool}).
|
|
1416
|
+
|
|
1417
|
+
@note: Uses C{math.fma} in Python 3.13+, provided C{self},
|
|
1418
|
+
B{C{other1}} and B{C{other2}} are all C{scalar}.
|
|
1419
|
+
'''
|
|
1420
|
+
f, r = self._fprs2
|
|
1421
|
+
if r == 0 and isscalar(other1, both=True) \
|
|
1422
|
+
and isscalar(other2, both=True):
|
|
1423
|
+
try:
|
|
1424
|
+
f = _fma(f, other1, other2)
|
|
1425
|
+
except (OverflowError, TypeError, ValueError) as X: # from math.fma
|
|
1426
|
+
op = self.fma.__name__ # INF, NAN, NINF
|
|
1427
|
+
f = self._mul_reduce(op, f, other1)
|
|
1428
|
+
f = _sum(self._ps_other(op, f, other2))
|
|
1429
|
+
if raiser:
|
|
1430
|
+
f = self._nonfiniteX(X, op, f)
|
|
1431
|
+
else:
|
|
1432
|
+
f = self._f2mul(self.fma, other1, raiser=raiser)
|
|
1433
|
+
f += other2
|
|
1434
|
+
return self._fset(f)
|
|
1435
|
+
|
|
1225
1436
|
fmul = __imul__
|
|
1226
1437
|
|
|
1227
1438
|
def _fmul(self, other, op):
|
|
@@ -1231,14 +1442,56 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1231
1442
|
if len(self._ps) != 1:
|
|
1232
1443
|
f = self._mul_Fsum(other, op)
|
|
1233
1444
|
elif len(other._ps) != 1: # and len(self._ps) == 1
|
|
1234
|
-
f =
|
|
1445
|
+
f = self._ps_mul(op, *other._ps)
|
|
1446
|
+
elif self._f2product: # len(other._ps) == 1
|
|
1447
|
+
f = self._mul_scalar(other._ps[0], op)
|
|
1235
1448
|
else: # len(other._ps) == len(self._ps) == 1
|
|
1236
|
-
f = self._finite(self._ps[0] * other._ps[0])
|
|
1449
|
+
f = self._finite(self._ps[0] * other._ps[0], op=op)
|
|
1237
1450
|
else:
|
|
1238
1451
|
s = self._scalar(other, op)
|
|
1239
1452
|
f = self._mul_scalar(s, op)
|
|
1240
1453
|
return self._fset(f) # n=len(self) + 1
|
|
1241
1454
|
|
|
1455
|
+
@deprecated_method
|
|
1456
|
+
def f2mul(self, *others, **raiser):
|
|
1457
|
+
'''DEPRECATED on 2024.09.13, use method L{f2mul_<Fsum.f2mul_>}.'''
|
|
1458
|
+
return self._fset(self.f2mul_(*others, **raiser))
|
|
1459
|
+
|
|
1460
|
+
def f2mul_(self, *others, **raiser): # in .fmath.f2mul
|
|
1461
|
+
'''Return C{B{self} * B{other} * B{other} ...} for all B{C{others}} using cascaded,
|
|
1462
|
+
accurate multiplication like with L{f2product<Fsum.f2product>} set to C{True}.
|
|
1463
|
+
|
|
1464
|
+
@arg others: Multipliers (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
|
|
1465
|
+
positional.
|
|
1466
|
+
@kwarg raiser: Keyword argument C{B{raiser}=False}, if C{True}, throw an exception,
|
|
1467
|
+
otherwise pass the I{non-finite} result (C{bool}).
|
|
1468
|
+
|
|
1469
|
+
@return: The cascaded I{TwoProduct} (L{Fsum} or C{float}).
|
|
1470
|
+
|
|
1471
|
+
@see: U{Equations 2.3<https://www.TUHH.De/ti3/paper/rump/OzOgRuOi06.pdf>}
|
|
1472
|
+
'''
|
|
1473
|
+
return self._f2mul(self.f2mul_, *others, **raiser)
|
|
1474
|
+
|
|
1475
|
+
def _f2mul(self, where, *others, **raiser):
|
|
1476
|
+
'''(INTERNAL) See methods C{fma} and C{f2mul_}.
|
|
1477
|
+
'''
|
|
1478
|
+
f = self._copy_2(where)
|
|
1479
|
+
if others:
|
|
1480
|
+
op = where.__name__
|
|
1481
|
+
ps = f._ps
|
|
1482
|
+
if ps:
|
|
1483
|
+
try:
|
|
1484
|
+
for p in self._ps_other(op, *others):
|
|
1485
|
+
pfs = _2products(p, _2split3s(ps))
|
|
1486
|
+
ps[:] = f._ps_acc([], pfs, up=False)
|
|
1487
|
+
f._update()
|
|
1488
|
+
except (OverflowError, TypeError, ValueError) as X:
|
|
1489
|
+
r = self._mul_reduce(op, _sum(ps), *others) # INF, NAN, NINF
|
|
1490
|
+
if _xkwds_get1(raiser, raiser=False):
|
|
1491
|
+
r = self._nonfiniteX(X, op, r)
|
|
1492
|
+
f._fset(r)
|
|
1493
|
+
return f
|
|
1494
|
+
|
|
1242
1495
|
def fover(self, over, **raiser_RESIDUAL):
|
|
1243
1496
|
'''Apply C{B{self} /= B{over}} and summate.
|
|
1244
1497
|
|
|
@@ -1266,16 +1519,40 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1266
1519
|
f = self._pow_2_3(self, other, other, op, *mod, **raiser_RESIDUAL)
|
|
1267
1520
|
elif self.is_integer():
|
|
1268
1521
|
# return an exact C{int} for C{int}**C{int}
|
|
1269
|
-
i, _ =
|
|
1522
|
+
i, _ = self._fint2 # assert _ == 0
|
|
1270
1523
|
x, r = _2scalar2(other) # C{int}, C{float} or other
|
|
1271
|
-
f =
|
|
1272
|
-
self._pow_2_3(i, x,
|
|
1524
|
+
f = self._Fsum_as(i)._pow_Fsum(other, op, **raiser_RESIDUAL) if r else \
|
|
1525
|
+
self._pow_2_3(i, x, other, op, **raiser_RESIDUAL)
|
|
1273
1526
|
else: # mod[0] is None, power(self, other)
|
|
1274
|
-
f =
|
|
1527
|
+
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1275
1528
|
else: # pow(self, other)
|
|
1276
1529
|
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1277
1530
|
return self._fset(f) # n=max(len(self), 1)
|
|
1278
1531
|
|
|
1532
|
+
def f2product(self, *two):
|
|
1533
|
+
'''Get and set accurate I{TwoProduct} multiplication for this
|
|
1534
|
+
L{Fsum}, I{overriding the global setting} from function
|
|
1535
|
+
L{f2product<fsums.f2product>}.
|
|
1536
|
+
|
|
1537
|
+
@arg two: If omitted, leave the override unchanged, if C{True},
|
|
1538
|
+
turn I{TwoProduct} on, if C{False} off, if C{None}e
|
|
1539
|
+
remove th override (C{bool} or C{None}).
|
|
1540
|
+
|
|
1541
|
+
@return: The previous setting (C{bool} or C{None} if not set).
|
|
1542
|
+
|
|
1543
|
+
@see: Function L{f2product<fsums.f2product>}.
|
|
1544
|
+
|
|
1545
|
+
@note: Use C{f.f2product() or f2product()} to determine whether
|
|
1546
|
+
multiplication is accurate for L{Fsum} C{f}.
|
|
1547
|
+
'''
|
|
1548
|
+
if two: # delattrof(self, _f2product=None)
|
|
1549
|
+
t = _xkwds_pop(self.__dict__, _f2product=None)
|
|
1550
|
+
if two[0] is not None:
|
|
1551
|
+
self._f2product = bool(two[0])
|
|
1552
|
+
else: # getattrof(self, _f2product=None)
|
|
1553
|
+
t = _xkwds_get(self.__dict__, _f2product=None)
|
|
1554
|
+
return t
|
|
1555
|
+
|
|
1279
1556
|
@Property
|
|
1280
1557
|
def _fprs(self):
|
|
1281
1558
|
'''(INTERNAL) Get and cache this instance' precision
|
|
@@ -1299,21 +1576,26 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1299
1576
|
running sum and residual (L{Fsum2Tuple}).
|
|
1300
1577
|
'''
|
|
1301
1578
|
ps = self._ps
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1579
|
+
try:
|
|
1580
|
+
n = len(ps) - 2
|
|
1581
|
+
if n > 0: # len(ps) > 2
|
|
1582
|
+
s = _psum(ps, **self._isfine)
|
|
1583
|
+
n = len(ps) - 2
|
|
1584
|
+
if n > 0:
|
|
1585
|
+
r = self._ps_1sum(s)
|
|
1586
|
+
return Fsum2Tuple(*_s_r(s, r))
|
|
1587
|
+
if n == 0: # len(ps) == 2
|
|
1588
|
+
s, r = _s_r(*_2sum(*ps, **self._isfine))
|
|
1589
|
+
ps[:] = (r, s) if r else (s,)
|
|
1590
|
+
elif ps: # len(ps) == 1
|
|
1591
|
+
s, r = ps[0], INT0
|
|
1592
|
+
else: # len(ps) == 0
|
|
1593
|
+
s, r = _0_0, INT0
|
|
1594
|
+
ps[:] = s,
|
|
1595
|
+
except (OverflowError, ValueError) as X:
|
|
1596
|
+
op = _sum.__name__ # INF, NAN, NINF
|
|
1597
|
+
s = self._nonfiniteX(X, op, _sum(self._ps))
|
|
1598
|
+
r = _0_0
|
|
1317
1599
|
# assert self._ps is ps
|
|
1318
1600
|
return Fsum2Tuple(s, r)
|
|
1319
1601
|
|
|
@@ -1324,19 +1606,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1324
1606
|
return Fsum2Tuple(s_r)
|
|
1325
1607
|
|
|
1326
1608
|
def fset_(self, *xs):
|
|
1327
|
-
'''
|
|
1609
|
+
'''Apply C{B{self}.partials = Fsum(*B{xs}).partials}.
|
|
1328
1610
|
|
|
1329
1611
|
@arg xs: Optional, new values (each C{scalar} or
|
|
1330
|
-
an L{Fsum} or L{Fsum2Tuple} instance),
|
|
1331
|
-
|
|
1612
|
+
an L{Fsum} or L{Fsum2Tuple} instance), all
|
|
1613
|
+
positional.
|
|
1332
1614
|
|
|
1333
1615
|
@return: This instance, replaced (C{Fsum}).
|
|
1334
1616
|
|
|
1335
1617
|
@see: Method L{Fsum.fadd} for further details.
|
|
1336
1618
|
'''
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
return self._fset(f)
|
|
1619
|
+
return self._fset(xs[0], op=_fset_op_) if len(xs) == 1 else \
|
|
1620
|
+
self._fset(_0_0)._facc_args(xs)
|
|
1340
1621
|
|
|
1341
1622
|
def _fset(self, other, n=0, up=True, **op):
|
|
1342
1623
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
@@ -1346,7 +1627,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1346
1627
|
elif _isFsumTuple(other):
|
|
1347
1628
|
self._ps[:] = other._ps
|
|
1348
1629
|
self._n = n or other._n
|
|
1349
|
-
# self._copy_RESIDUAL(other)
|
|
1350
1630
|
if up: # use or zap the C{Property_RO} values
|
|
1351
1631
|
Fsum._fint2._update_from(self, other)
|
|
1352
1632
|
Fsum._fprs ._update_from(self, other)
|
|
@@ -1362,13 +1642,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1362
1642
|
self._fprs = s
|
|
1363
1643
|
self._fprs2 = s, INT0
|
|
1364
1644
|
# assert self._fprs is s
|
|
1365
|
-
else:
|
|
1645
|
+
else:
|
|
1366
1646
|
op = _xkwds_get1(op, op=_fset_op_)
|
|
1367
1647
|
raise self._Error(op, other, _TypeError)
|
|
1368
1648
|
return self
|
|
1369
1649
|
|
|
1370
|
-
def _fset_ps(self, other): # in .fmath
|
|
1371
|
-
'''(INTERNAL) Set partials from a known C{
|
|
1650
|
+
def _fset_ps(self, other): # in .fmath._Fsum__init__
|
|
1651
|
+
'''(INTERNAL) Set partials from a known C{other}.
|
|
1372
1652
|
'''
|
|
1373
1653
|
return self._fset(other, up=False)
|
|
1374
1654
|
|
|
@@ -1384,8 +1664,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1384
1664
|
|
|
1385
1665
|
@see: Method L{Fsum.fadd_} for further details.
|
|
1386
1666
|
'''
|
|
1387
|
-
return self.
|
|
1388
|
-
self.
|
|
1667
|
+
return self._facc_neg(xs, origin=1) if len(xs) != 1 else \
|
|
1668
|
+
self._fsub(xs[0], _sub_op_)
|
|
1389
1669
|
|
|
1390
1670
|
def _fsub(self, other, op):
|
|
1391
1671
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
@@ -1425,11 +1705,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1425
1705
|
|
|
1426
1706
|
@see: Methods L{Fsum.fsum}, L{Fsum.Fsum_} and L{Fsum.fsumf_}.
|
|
1427
1707
|
'''
|
|
1428
|
-
return self.
|
|
1429
|
-
|
|
1430
|
-
@property_RO
|
|
1431
|
-
def _Fsum(self): # like L{Fsum2Tuple._Fsum}, for C{_2floats}, .fstats
|
|
1432
|
-
return self # NOT @Property_RO, see .copy and ._copy_2
|
|
1708
|
+
return self._facc_args(xs)._fprs
|
|
1433
1709
|
|
|
1434
1710
|
def Fsum_(self, *xs, **name):
|
|
1435
1711
|
'''Like method L{Fsum.fsum_} but returning a named L{Fsum}.
|
|
@@ -1438,7 +1714,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1438
1714
|
|
|
1439
1715
|
@return: Copy of this updated instance (L{Fsum}).
|
|
1440
1716
|
'''
|
|
1441
|
-
return self.
|
|
1717
|
+
return self._facc_args(xs)._copy_2(self.Fsum_, **name)
|
|
1442
1718
|
|
|
1443
1719
|
def Fsum2Tuple_(self, *xs, **name):
|
|
1444
1720
|
'''Like method L{Fsum.fsum_} but returning a named L{Fsum2Tuple}.
|
|
@@ -1447,7 +1723,27 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1447
1723
|
|
|
1448
1724
|
@return: Precision running sum (L{Fsum2Tuple}).
|
|
1449
1725
|
'''
|
|
1450
|
-
return Fsum2Tuple(self.
|
|
1726
|
+
return Fsum2Tuple(self._facc_args(xs)._fprs2, **name)
|
|
1727
|
+
|
|
1728
|
+
@property_RO
|
|
1729
|
+
def _Fsum(self): # like L{Fsum2Tuple._Fsum}, for C{_2floats}, .fstats
|
|
1730
|
+
return self # NOT @Property_RO, see .copy and ._copy_2
|
|
1731
|
+
|
|
1732
|
+
def _Fsum_as(self, *xs, **name_f2product_nonfinites_RESIDUAL):
|
|
1733
|
+
'''(INTERNAL) Return an C{Fsum} with this C{Fsum}'s C{.f2product},
|
|
1734
|
+
C{.nonfinites} and C{.RESIDUAL} setting, optionally
|
|
1735
|
+
overridden with C{name_f2product_nonfinites_RESIDUAL} and
|
|
1736
|
+
with any C{xs} accumulated.
|
|
1737
|
+
'''
|
|
1738
|
+
kwds = _xkwds_not(None, Fsum._RESIDUAL, f2product =self.f2product(),
|
|
1739
|
+
nonfinites=self.nonfinites(),
|
|
1740
|
+
RESIDUAL =self.RESIDUAL())
|
|
1741
|
+
if name_f2product_nonfinites_RESIDUAL: # overwrites
|
|
1742
|
+
kwds.update(name_f2product_nonfinites_RESIDUAL)
|
|
1743
|
+
F = Fsum(**kwds)
|
|
1744
|
+
# assert all(v == self.__dict__[n] for n, v in F.__dict__.items())
|
|
1745
|
+
return F._fset(xs[0]) if len(xs) == 1 else (
|
|
1746
|
+
F._facc(xs, up=False) if xs else F)
|
|
1451
1747
|
|
|
1452
1748
|
def fsum2(self, xs=(), **name):
|
|
1453
1749
|
'''Add an iterable's items, summate and return the
|
|
@@ -1481,7 +1777,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1481
1777
|
|
|
1482
1778
|
@see: Methods L{Fsum.fsum_} and L{Fsum.fsum}.
|
|
1483
1779
|
'''
|
|
1484
|
-
return self._fsum2(xs, self.
|
|
1780
|
+
return self._fsum2(xs, self._facc_args)
|
|
1485
1781
|
|
|
1486
1782
|
def _fsum2(self, xs, _facc, **origin):
|
|
1487
1783
|
'''(INTERNAL) Helper for L{Fsum.fsum2_} and L{Fsum.fsum2f_}.
|
|
@@ -1489,7 +1785,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1489
1785
|
p, q = self._fprs2
|
|
1490
1786
|
if xs:
|
|
1491
1787
|
s, r = _facc(xs, **origin)._fprs2
|
|
1492
|
-
|
|
1788
|
+
if _isfinite(s): # _fsum(_1primed((s, -p, r, -q))
|
|
1789
|
+
d, r = _2sum(s - p, r - q, _isfine=_isOK)
|
|
1790
|
+
r, _ = _s_r(d, r)
|
|
1791
|
+
return s, (r if _isfinite(r) else _0_0)
|
|
1493
1792
|
else:
|
|
1494
1793
|
return p, _0_0
|
|
1495
1794
|
|
|
@@ -1554,8 +1853,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1554
1853
|
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1555
1854
|
B{C{RESIDUAL}}.
|
|
1556
1855
|
|
|
1557
|
-
@see: Methods L{Fsum.fint}, L{Fsum.fint2}, L{Fsum.
|
|
1558
|
-
property L{Fsum.as_iscalar}.
|
|
1856
|
+
@see: Methods L{Fsum.fint}, L{Fsum.fint2}, L{Fsum.is_integer},
|
|
1857
|
+
L{Fsum.RESIDUAL} and property L{Fsum.as_iscalar}.
|
|
1559
1858
|
'''
|
|
1560
1859
|
s, r = self._fint2
|
|
1561
1860
|
if r:
|
|
@@ -1574,27 +1873,38 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1574
1873
|
'''
|
|
1575
1874
|
return self.residual is INT0
|
|
1576
1875
|
|
|
1876
|
+
def is_finite(self): # in .constants
|
|
1877
|
+
'''Is this instance C{finite}? (C{bool}).
|
|
1878
|
+
|
|
1879
|
+
@see: Function L{isfinite<pygeodesy.isfinite>}.
|
|
1880
|
+
'''
|
|
1881
|
+
return _isfinite(_sum(self._ps)) # _sum(self)
|
|
1882
|
+
|
|
1577
1883
|
def is_integer(self):
|
|
1578
1884
|
'''Is this instance' running sum C{integer}? (C{bool}).
|
|
1579
1885
|
|
|
1580
1886
|
@see: Methods L{Fsum.fint}, L{Fsum.fint2} and L{Fsum.is_scalar}.
|
|
1581
1887
|
'''
|
|
1582
|
-
|
|
1583
|
-
return False if r else
|
|
1888
|
+
s, r = self._fint2
|
|
1889
|
+
return False if r else (_isfinite(s) and isint(s))
|
|
1890
|
+
|
|
1891
|
+
def is_math_fma(self):
|
|
1892
|
+
'''Is accurate L{f2product} multiplication based on Python's C{math.fma}?
|
|
1893
|
+
|
|
1894
|
+
@return: C{True} if accurate multiplication uses C{math.fma}, C{False}
|
|
1895
|
+
an C{fma} implementation as C{math.fma} or C{None}, a previous
|
|
1896
|
+
C{PyGeodesy} implementation.
|
|
1897
|
+
'''
|
|
1898
|
+
return (_fma.__module__ is fabs.__module__ or None) if _2split3s is _passarg else False
|
|
1584
1899
|
|
|
1585
1900
|
def is_math_fsum(self):
|
|
1586
|
-
'''
|
|
1587
|
-
L{fsum1_}
|
|
1588
|
-
C{math.fsum} or not.
|
|
1901
|
+
'''Are the summation functions L{fsum}, L{fsum_}, L{fsumf_}, L{fsum1},
|
|
1902
|
+
L{fsum1_} and L{fsum1f_} based on Python's C{math.fsum}?
|
|
1589
1903
|
|
|
1590
|
-
@return: C{
|
|
1591
|
-
|
|
1592
|
-
the functions are based on C{math.fsum} (and
|
|
1593
|
-
partials summation is not) or C{False} if
|
|
1594
|
-
none are.
|
|
1904
|
+
@return: C{True} if summation functions use C{math.fsum}, C{False}
|
|
1905
|
+
otherwise.
|
|
1595
1906
|
'''
|
|
1596
|
-
|
|
1597
|
-
return 2 if _psum is f else bool(f)
|
|
1907
|
+
return _sum is _fsum # _fsum.__module__ is fabs.__module__
|
|
1598
1908
|
|
|
1599
1909
|
def is_scalar(self, **raiser_RESIDUAL):
|
|
1600
1910
|
'''Is this instance' running sum C{scalar} without residual or with
|
|
@@ -1626,6 +1936,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1626
1936
|
f = _0_0
|
|
1627
1937
|
return f
|
|
1628
1938
|
|
|
1939
|
+
def _mul_reduce(self, op, start, *others):
|
|
1940
|
+
'''(INTERNAL) Like fmath.freduce(_operator.mul, ...)
|
|
1941
|
+
for I{non-finite} C{start} and/or C{others}.
|
|
1942
|
+
'''
|
|
1943
|
+
for p in self._ps_other(op, *others):
|
|
1944
|
+
start *= p
|
|
1945
|
+
return start
|
|
1946
|
+
|
|
1629
1947
|
def _mul_scalar(self, factor, op): # in .fmath.Fhorner
|
|
1630
1948
|
'''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum}, C{0.0} or C{self}.
|
|
1631
1949
|
'''
|
|
@@ -1649,6 +1967,67 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1649
1967
|
'''
|
|
1650
1968
|
return _Psum(self._ps_neg) if self._ps else NEG0
|
|
1651
1969
|
|
|
1970
|
+
def nonfinites(self, *OK):
|
|
1971
|
+
'''Handle I{non-finite} C{float}s as C{inf}, C{INF}, C{NINF}, C{nan}
|
|
1972
|
+
and C{NAN} for this L{Fsum} or throw C{OverflowError} respectively
|
|
1973
|
+
C{ValueError} exceptions, I{overriding the global setting} from
|
|
1974
|
+
function L{nonfiniterrors<fsums.nonfiniterrors>}.
|
|
1975
|
+
|
|
1976
|
+
@arg OK: If omitted, leave the override unchanged, if C{True},
|
|
1977
|
+
I{non-finites} are C{OK}, if C{False} throw exceptions
|
|
1978
|
+
or if C{None} remove the override (C{bool} or C{None}).
|
|
1979
|
+
|
|
1980
|
+
@return: The previous setting (C{bool} or C{None} if not set).
|
|
1981
|
+
|
|
1982
|
+
@see: Function L{nonfiniterrors<fsums.nonfiniterrors>}.
|
|
1983
|
+
|
|
1984
|
+
@note: Use C{f.nonfinites() or not nonfiniterrors()} to determine
|
|
1985
|
+
whether L{Fsum} C{f} handles I{non-finites}.
|
|
1986
|
+
'''
|
|
1987
|
+
_ks = Fsum._nonfinites_isfine_kwds
|
|
1988
|
+
if OK: # delattrof(self, _isfine=None)
|
|
1989
|
+
k = _xkwds_pop(self.__dict__, _isfine=None)
|
|
1990
|
+
if OK[0] is not None:
|
|
1991
|
+
self._isfine = _ks[bool(OK[0])]
|
|
1992
|
+
else: # getattrof(self, _isfine=None)
|
|
1993
|
+
k = _xkwds_get(self.__dict__, _isfine=None)
|
|
1994
|
+
# dict(map(reversed, _ks.items())).get(k, None)
|
|
1995
|
+
# raises a TypeError: unhashable type: 'dict'
|
|
1996
|
+
return True if k is _ks[True] else (
|
|
1997
|
+
False if k is _ks[False] else None)
|
|
1998
|
+
|
|
1999
|
+
_nonfinites_isfine_kwds = {True: dict(_isfine=_isOK),
|
|
2000
|
+
False: dict(_isfine=_isfinite)}
|
|
2001
|
+
|
|
2002
|
+
def _nonfiniteX(self, X, op, f):
|
|
2003
|
+
'''(INTERNAL) Handle a I{non-finite} exception.
|
|
2004
|
+
'''
|
|
2005
|
+
if not _isOK_or_finite(f, **self._isfine):
|
|
2006
|
+
raise self._ErrorX(X, op, f)
|
|
2007
|
+
return f
|
|
2008
|
+
|
|
2009
|
+
def _optionals(self, f2product=None, nonfinites=None, **name_RESIDUAL):
|
|
2010
|
+
'''(INTERNAL) Re/set options from keyword arguments.
|
|
2011
|
+
'''
|
|
2012
|
+
if f2product is not None:
|
|
2013
|
+
self.f2product(f2product)
|
|
2014
|
+
if nonfinites is not None:
|
|
2015
|
+
self.nonfinites(nonfinites)
|
|
2016
|
+
if name_RESIDUAL: # MUST be last
|
|
2017
|
+
n, kwds = _name2__(**name_RESIDUAL)
|
|
2018
|
+
if kwds:
|
|
2019
|
+
R = Fsum._RESIDUAL
|
|
2020
|
+
t = _threshold(R, **kwds)
|
|
2021
|
+
if t != R:
|
|
2022
|
+
self._RESIDUAL = t
|
|
2023
|
+
if n:
|
|
2024
|
+
self.name = n # self.rename(n)
|
|
2025
|
+
|
|
2026
|
+
def _1_Over(self, x, op, **raiser_RESIDUAL): # vs _1_over
|
|
2027
|
+
'''(INTERNAL) Return C{Fsum(1) / B{x}}.
|
|
2028
|
+
'''
|
|
2029
|
+
return self._Fsum_as(_1_0)._ftruediv(x, op, **raiser_RESIDUAL)
|
|
2030
|
+
|
|
1652
2031
|
@property_RO
|
|
1653
2032
|
def partials(self):
|
|
1654
2033
|
'''Get this instance' current, partial sums (C{tuple} of C{float}s).
|
|
@@ -1658,7 +2037,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1658
2037
|
def pow(self, x, *mod, **raiser_RESIDUAL):
|
|
1659
2038
|
'''Return C{B{self}**B{x}} as L{Fsum}.
|
|
1660
2039
|
|
|
1661
|
-
@arg x: The exponent (C{scalar}
|
|
2040
|
+
@arg x: The exponent (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
1662
2041
|
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
1663
2042
|
C{pow(B{self}, B{other}, B{mod})} version.
|
|
1664
2043
|
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
|
|
@@ -1745,7 +2124,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1745
2124
|
_mul_Fsum = Fsum._mul_Fsum
|
|
1746
2125
|
if x > 4:
|
|
1747
2126
|
p = self
|
|
1748
|
-
f = self if (x & 1) else
|
|
2127
|
+
f = self if (x & 1) else self._Fsum_as(_1_0)
|
|
1749
2128
|
m = x >> 1 # // 2
|
|
1750
2129
|
while m:
|
|
1751
2130
|
p = _mul_Fsum(p, p, op) # p **= 2
|
|
@@ -1783,14 +2162,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1783
2162
|
if _isFsum(f):
|
|
1784
2163
|
s, r = f._fprs2
|
|
1785
2164
|
if r:
|
|
1786
|
-
return _1_Over(f, op, **raiser_RESIDUAL)
|
|
2165
|
+
return self._1_Over(f, op, **raiser_RESIDUAL)
|
|
1787
2166
|
else: # scalar
|
|
1788
2167
|
s = f
|
|
1789
2168
|
# use s**(-1) to get the CPython
|
|
1790
2169
|
# float_pow error iff s is zero
|
|
1791
2170
|
x = -1
|
|
1792
2171
|
elif x < 0: # self**(-1)
|
|
1793
|
-
return _1_Over(self, op, **raiser_RESIDUAL) # 1 / self
|
|
2172
|
+
return self._1_Over(self, op, **raiser_RESIDUAL) # 1 / self
|
|
1794
2173
|
else: # self**1 or self**0
|
|
1795
2174
|
return self._pow_0_1(x, other) # self, 1 or 1.0
|
|
1796
2175
|
else: # self**fractional
|
|
@@ -1809,12 +2188,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1809
2188
|
'''
|
|
1810
2189
|
n = 0
|
|
1811
2190
|
_2s = _2sum
|
|
2191
|
+
_fi = self._isfine
|
|
1812
2192
|
for x in (tuple(xs) if xs is ps else xs):
|
|
1813
|
-
# assert isscalar(x) and
|
|
2193
|
+
# assert isscalar(x) and _isOK_or_finite(x, **self._isfine)
|
|
1814
2194
|
if x:
|
|
1815
2195
|
i = 0
|
|
1816
2196
|
for p in ps:
|
|
1817
|
-
x, p = _2s(x, p)
|
|
2197
|
+
x, p = _2s(x, p, **_fi)
|
|
1818
2198
|
if p:
|
|
1819
2199
|
ps[i] = p
|
|
1820
2200
|
i += 1
|
|
@@ -1822,6 +2202,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1822
2202
|
n += 1
|
|
1823
2203
|
if n:
|
|
1824
2204
|
self._n += n
|
|
2205
|
+
# if _fi: # collapse ps if non-finite
|
|
2206
|
+
# x = _sum(ps)
|
|
2207
|
+
# if not _isfinite(x):
|
|
2208
|
+
# ps[:] = x,
|
|
1825
2209
|
# Fsum._ps_max = max(Fsum._ps_max, len(ps))
|
|
1826
2210
|
if up:
|
|
1827
2211
|
self._update()
|
|
@@ -1831,16 +2215,23 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1831
2215
|
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1832
2216
|
each scalar C{factor} and accumulate into an C{Fsum}.
|
|
1833
2217
|
'''
|
|
1834
|
-
def
|
|
2218
|
+
def _psfs(ps, fs, _isfine=_isfinite):
|
|
1835
2219
|
if len(ps) < len(fs):
|
|
1836
2220
|
ps, fs = fs, ps
|
|
1837
|
-
|
|
2221
|
+
if self._f2product:
|
|
2222
|
+
ps = _2split3s(ps)
|
|
2223
|
+
_fps = _2products
|
|
2224
|
+
else:
|
|
2225
|
+
def _fps(f, ps):
|
|
2226
|
+
return (f * p for p in ps)
|
|
2227
|
+
|
|
1838
2228
|
for f in fs:
|
|
1839
|
-
for p in ps:
|
|
1840
|
-
p
|
|
1841
|
-
yield p if _fin(p) else self._finite(p, op)
|
|
2229
|
+
for p in _fps(f, ps):
|
|
2230
|
+
yield p if _isfine(p) else self._finite(p, op)
|
|
1842
2231
|
|
|
1843
|
-
|
|
2232
|
+
F = self._Fsum_as(name=op) # assert F._ps is not self._ps
|
|
2233
|
+
_s = _psfs(self._ps, factors, **self._isfine)
|
|
2234
|
+
return F._facc_scalar(_s, up=False)
|
|
1844
2235
|
|
|
1845
2236
|
@property_RO
|
|
1846
2237
|
def _ps_neg(self):
|
|
@@ -1849,10 +2240,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1849
2240
|
for p in self._ps:
|
|
1850
2241
|
yield -p
|
|
1851
2242
|
|
|
2243
|
+
def _ps_other(self, op, *others):
|
|
2244
|
+
'''(INTERNAL) Yield all C{other}s as C{scalar}.
|
|
2245
|
+
'''
|
|
2246
|
+
for other in others:
|
|
2247
|
+
if _isFsumTuple(other):
|
|
2248
|
+
for p in other._ps:
|
|
2249
|
+
yield p
|
|
2250
|
+
else:
|
|
2251
|
+
yield self._scalar(other, op)
|
|
2252
|
+
|
|
1852
2253
|
def _ps_1sum(self, *less):
|
|
1853
2254
|
'''(INTERNAL) Return the partials sum, 1-primed C{less} some scalars.
|
|
1854
2255
|
'''
|
|
1855
|
-
def
|
|
2256
|
+
def _1psls(ps, ls):
|
|
1856
2257
|
yield _1_0
|
|
1857
2258
|
for p in ps:
|
|
1858
2259
|
yield p
|
|
@@ -1860,7 +2261,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1860
2261
|
yield -p
|
|
1861
2262
|
yield _N_1_0
|
|
1862
2263
|
|
|
1863
|
-
return _fsum(
|
|
2264
|
+
return _fsum(_1psls(self._ps, less))
|
|
1864
2265
|
|
|
1865
2266
|
def _raiser(self, r, s, raiser=True, **RESIDUAL):
|
|
1866
2267
|
'''(INTERNAL) Does ratio C{r / s} exceed the RESIDUAL threshold
|
|
@@ -1887,12 +2288,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1887
2288
|
and properties L{Fsum.ceil}, L{Fsum.floor},
|
|
1888
2289
|
L{Fsum.imag} and L{Fsum.residual}.
|
|
1889
2290
|
'''
|
|
1890
|
-
return float(self
|
|
2291
|
+
return float(self)
|
|
1891
2292
|
|
|
1892
2293
|
@property_RO
|
|
1893
2294
|
def residual(self):
|
|
1894
|
-
'''Get this instance' residual (C{float} or C{int}):
|
|
1895
|
-
C{sum(partials)} less the precision running sum C{fsum}.
|
|
2295
|
+
'''Get this instance' residual or residue (C{float} or C{int}):
|
|
2296
|
+
the C{sum(partials)} less the precision running sum C{fsum}.
|
|
1896
2297
|
|
|
1897
2298
|
@note: The C{residual is INT0} iff the precision running
|
|
1898
2299
|
C{fsum} is considered to be I{exact}.
|
|
@@ -1907,7 +2308,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1907
2308
|
|
|
1908
2309
|
@arg threshold: If C{scalar}, the I{ratio} to exceed for raising
|
|
1909
2310
|
L{ResidualError}s in division and exponention, if
|
|
1910
|
-
C{None} restore the default set with env variable
|
|
2311
|
+
C{None}, restore the default set with env variable
|
|
1911
2312
|
C{PYGEODESY_FSUM_RESIDUAL} or if omitted, keep the
|
|
1912
2313
|
current setting.
|
|
1913
2314
|
|
|
@@ -1917,11 +2318,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1917
2318
|
|
|
1918
2319
|
@note: L{ResidualError}s may be thrown if (1) the non-zero I{ratio}
|
|
1919
2320
|
C{residual / fsum} exceeds the given B{C{threshold}} and (2)
|
|
1920
|
-
the C{residual} is non-zero and (3) I{significant} vs the
|
|
2321
|
+
the C{residual} is non-zero and (3) is I{significant} vs the
|
|
1921
2322
|
C{fsum}, i.e. C{(fsum + residual) != fsum} and (4) optional
|
|
1922
2323
|
keyword argument C{raiser=False} is missing. Specify a
|
|
1923
2324
|
negative B{C{threshold}} for only non-zero C{residual}
|
|
1924
|
-
testing without I{significant}.
|
|
2325
|
+
testing without the I{significant} case.
|
|
1925
2326
|
'''
|
|
1926
2327
|
r = self._RESIDUAL
|
|
1927
2328
|
if threshold:
|
|
@@ -1944,9 +2345,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1944
2345
|
def root(self, root, **raiser_RESIDUAL):
|
|
1945
2346
|
'''Return C{B{self}**(1 / B{root})} as L{Fsum}.
|
|
1946
2347
|
|
|
1947
|
-
@arg root: The order (C{scalar} or L{
|
|
1948
|
-
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
|
|
1949
|
-
L{ResidualError}s (C{bool})
|
|
2348
|
+
@arg root: The order (C{scalar}, L{Fsum} or L{Fsum2Tuple}), non-zero.
|
|
2349
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore any
|
|
2350
|
+
L{ResidualError}s (C{bool}) or C{B{RESIDUAL}=scalar}
|
|
1950
2351
|
to override the current L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1951
2352
|
|
|
1952
2353
|
@return: The C{self ** (1 / B{root})} result (L{Fsum}).
|
|
@@ -1956,8 +2357,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1956
2357
|
|
|
1957
2358
|
@see: Method L{Fsum.pow}.
|
|
1958
2359
|
'''
|
|
1959
|
-
x = _1_Over(root, _truediv_op_, **raiser_RESIDUAL)
|
|
1960
|
-
f =
|
|
2360
|
+
x = self._1_Over(root, _truediv_op_, **raiser_RESIDUAL)
|
|
2361
|
+
f = self._copy_2(self.root)
|
|
1961
2362
|
return f._fpow(x, f.name, **raiser_RESIDUAL) # == pow(f, x)
|
|
1962
2363
|
|
|
1963
2364
|
def _scalar(self, other, op, **txt):
|
|
@@ -2026,9 +2427,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2026
2427
|
|
|
2027
2428
|
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK see Fsum._update
|
|
2028
2429
|
|
|
2430
|
+
if _NONFINITES: # PYCHOK no cover
|
|
2431
|
+
_ = nonfiniterrors(False)
|
|
2432
|
+
|
|
2029
2433
|
|
|
2030
2434
|
def _Float_Int(arg, **name_Error):
|
|
2031
|
-
'''(INTERNAL)
|
|
2435
|
+
'''(INTERNAL) L{DivMod2Tuple}, L{Fsum2Tuple} Unit.
|
|
2032
2436
|
'''
|
|
2033
2437
|
U = Int if isint(arg) else Float
|
|
2034
2438
|
return U(arg, **name_Error)
|
|
@@ -2041,7 +2445,7 @@ class DivMod2Tuple(_NamedTuple):
|
|
|
2041
2445
|
@note: Quotient C{div} an C{int} in Python 3+ but a C{float}
|
|
2042
2446
|
in Python 2-. Remainder C{mod} an L{Fsum} instance.
|
|
2043
2447
|
'''
|
|
2044
|
-
_Names_ = (
|
|
2448
|
+
_Names_ = ('div', 'mod')
|
|
2045
2449
|
_Units_ = (_Float_Int, Fsum)
|
|
2046
2450
|
|
|
2047
2451
|
|
|
@@ -2115,17 +2519,23 @@ class Fsum2Tuple(_NamedTuple): # in .fstats
|
|
|
2115
2519
|
ps = (r, s) if r else (s,)
|
|
2116
2520
|
return _Psum(ps, name=self.name)
|
|
2117
2521
|
|
|
2118
|
-
def Fsum_(self, *xs, **
|
|
2522
|
+
def Fsum_(self, *xs, **name_f2product_nonfinites_RESIDUAL):
|
|
2119
2523
|
'''Return this C{Fsum2Tuple} as an L{Fsum} plus some C{xs}.
|
|
2120
2524
|
'''
|
|
2121
|
-
|
|
2122
|
-
return f._facc_1(xs, up=False) if xs else f
|
|
2525
|
+
return Fsum(self, *xs, **name_f2product_nonfinites_RESIDUAL)
|
|
2123
2526
|
|
|
2124
2527
|
def is_exact(self):
|
|
2125
2528
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
2126
2529
|
'''
|
|
2127
2530
|
return self._Fsum.is_exact()
|
|
2128
2531
|
|
|
2532
|
+
def is_finite(self): # in .constants
|
|
2533
|
+
'''Is this L{Fsum2Tuple} C{finite}? (C{bool}).
|
|
2534
|
+
|
|
2535
|
+
@see: Function L{isfinite<pygeodesy.isfinite>}.
|
|
2536
|
+
'''
|
|
2537
|
+
return self._Fsum.is_finite()
|
|
2538
|
+
|
|
2129
2539
|
def is_integer(self):
|
|
2130
2540
|
'''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
|
|
2131
2541
|
'''
|
|
@@ -2186,105 +2596,142 @@ try:
|
|
|
2186
2596
|
del _fsum # nope, remove _fsum ...
|
|
2187
2597
|
raise ImportError() # ... use _fsum below
|
|
2188
2598
|
|
|
2189
|
-
|
|
2599
|
+
_sum = _fsum # in .elliptic
|
|
2190
2600
|
except ImportError:
|
|
2191
|
-
_sum =
|
|
2601
|
+
_sum = sum # in .elliptic
|
|
2192
2602
|
|
|
2193
2603
|
def _fsum(xs):
|
|
2194
2604
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
2195
2605
|
'''
|
|
2196
|
-
F = Fsum()
|
|
2197
|
-
F.
|
|
2198
|
-
return F._facc(xs, up=False)._fprs2.fsum
|
|
2606
|
+
F = Fsum(name=_fsum.name, nonfinites=True)
|
|
2607
|
+
return float(F._facc(xs, up=False))
|
|
2199
2608
|
|
|
2200
2609
|
|
|
2201
|
-
def fsum(xs, floats
|
|
2202
|
-
'''Precision floating point summation
|
|
2610
|
+
def fsum(xs, nonfinites=None, **floats):
|
|
2611
|
+
'''Precision floating point summation from Python's C{math.fsum}.
|
|
2203
2612
|
|
|
2204
|
-
@arg xs: Iterable of items to add (each C{scalar}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2613
|
+
@arg xs: Iterable of items to add (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
2614
|
+
@kwarg nonfinites: Use C{B{nonfinites}=True} if I{non-finites} are C{OK}, if
|
|
2615
|
+
C{False} I{non-finites} raise an Overflow-/ValueError or if
|
|
2616
|
+
C{None}, apply C{B{nonfinites}=not }L{nonfiniterrors()}
|
|
2617
|
+
(C{bool} or C{None}).
|
|
2618
|
+
@kwarg floats: DEPRECATED keyword argument C{B{floats}=False} (C{bool}), use
|
|
2619
|
+
keyword argument C{B{nonfinites}=False} instead.
|
|
2208
2620
|
|
|
2209
2621
|
@return: Precision C{fsum} (C{float}).
|
|
2210
2622
|
|
|
2211
|
-
@raise OverflowError:
|
|
2212
|
-
|
|
2213
|
-
@raise TypeError: Non-scalar B{C{xs}} item.
|
|
2623
|
+
@raise OverflowError: Infinite B{C{xs}} item or intermediate C{math.fsum} overflow.
|
|
2214
2624
|
|
|
2215
|
-
@raise
|
|
2625
|
+
@raise TypeError: Invalid B{C{xs}} item.
|
|
2216
2626
|
|
|
2217
|
-
@
|
|
2218
|
-
on Python's C{math.fsum}.
|
|
2627
|
+
@raise ValueError: Invalid or C{NAN} B{C{xs}} item.
|
|
2219
2628
|
|
|
2220
|
-
@see:
|
|
2629
|
+
@see: Function L{nonfiniterrors}, class L{Fsum} and methods L{Fsum.nonfinites},
|
|
2630
|
+
L{Fsum.fsum}, L{Fsum.fadd} and L{Fsum.fadd_}.
|
|
2221
2631
|
'''
|
|
2222
|
-
return
|
|
2632
|
+
return _xsum(fsum, xs, nonfinites=nonfinites, **floats) if xs else _0_0
|
|
2223
2633
|
|
|
2224
2634
|
|
|
2225
|
-
def fsum_(*xs, **
|
|
2635
|
+
def fsum_(*xs, **nonfinites):
|
|
2226
2636
|
'''Precision floating point summation of all positional items.
|
|
2227
2637
|
|
|
2228
|
-
@arg xs: Items to add (each C{scalar}
|
|
2229
|
-
|
|
2230
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
|
|
2231
|
-
be scalar} (C{bool}).
|
|
2638
|
+
@arg xs: Items to add (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
2639
|
+
@kwarg nonfinites: Use C{B{nonfinites}=True} if I{non-finites} are C{OK} (C{bool}).
|
|
2232
2640
|
|
|
2233
2641
|
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2234
2642
|
'''
|
|
2235
|
-
return
|
|
2236
|
-
_2floats(xs, origin=1)) if xs else _0_0 # PYCHOK yield
|
|
2643
|
+
return _xsum(fsum_, xs, origin=1, **nonfinites) if xs else _0_0
|
|
2237
2644
|
|
|
2238
2645
|
|
|
2239
2646
|
def fsumf_(*xs):
|
|
2240
|
-
'''Precision floating point summation
|
|
2647
|
+
'''Precision floating point summation of all positional items with I{non-finites} C{OK}.
|
|
2648
|
+
|
|
2649
|
+
@arg xs: Items to add (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}),
|
|
2650
|
+
all positional.
|
|
2241
2651
|
|
|
2242
2652
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2243
2653
|
'''
|
|
2244
|
-
return
|
|
2654
|
+
return _xsum(fsumf_, xs, nonfinites=True, origin=1) if xs else _0_0
|
|
2245
2655
|
|
|
2246
2656
|
|
|
2247
|
-
def fsum1(xs,
|
|
2657
|
+
def fsum1(xs, **nonfinites):
|
|
2248
2658
|
'''Precision floating point summation, 1-primed.
|
|
2249
2659
|
|
|
2250
|
-
@arg xs: Iterable of items to add (each C{scalar}
|
|
2251
|
-
|
|
2252
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
|
|
2253
|
-
be scalar} (C{bool}).
|
|
2660
|
+
@arg xs: Iterable of items to add (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
2661
|
+
@kwarg nonfinites: Use C{B{nonfinites}=True} if I{non-finites} are C{OK} (C{bool}).
|
|
2254
2662
|
|
|
2255
2663
|
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2256
2664
|
'''
|
|
2257
|
-
return
|
|
2665
|
+
return _xsum(fsum1, xs, primed=1, **nonfinites) if xs else _0_0
|
|
2258
2666
|
|
|
2259
2667
|
|
|
2260
|
-
def fsum1_(*xs, **
|
|
2261
|
-
'''Precision floating point summation
|
|
2668
|
+
def fsum1_(*xs, **nonfinites):
|
|
2669
|
+
'''Precision floating point summation of all positional items, 1-primed.
|
|
2262
2670
|
|
|
2263
|
-
@arg xs: Items to add (each C{scalar}
|
|
2264
|
-
|
|
2265
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
|
|
2266
|
-
be scalar} (C{bool}).
|
|
2671
|
+
@arg xs: Items to add (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
2672
|
+
@kwarg nonfinites: Use C{B{nonfinites}=True} if I{non-finites} are C{OK} (C{bool}).
|
|
2267
2673
|
|
|
2268
2674
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2269
2675
|
'''
|
|
2270
|
-
return
|
|
2271
|
-
_2floats(xs, origin=1))) if xs else _0_0 # PYCHOK yield
|
|
2676
|
+
return _xsum(fsum1_, xs, origin=1, primed=1, **nonfinites) if xs else _0_0
|
|
2272
2677
|
|
|
2273
2678
|
|
|
2274
2679
|
def fsum1f_(*xs):
|
|
2275
|
-
'''Precision floating point summation
|
|
2680
|
+
'''Precision floating point summation of all positional items, 1-primed and
|
|
2681
|
+
with I{non-finites} C{OK}.
|
|
2276
2682
|
|
|
2277
2683
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2278
2684
|
'''
|
|
2279
|
-
return
|
|
2685
|
+
return _xsum(fsum1f_, xs, nonfinites=True, primed=1) if xs else _0_0
|
|
2280
2686
|
|
|
2281
2687
|
|
|
2282
|
-
|
|
2688
|
+
def _xs(xs, _x, i_x):
|
|
2689
|
+
'''(INTERNAL) Yield all C{xs} as C{scalar}.
|
|
2690
|
+
'''
|
|
2691
|
+
for i, x in enumerate(xs):
|
|
2692
|
+
i_x[:] = i, x
|
|
2693
|
+
if _isFsumTuple(x):
|
|
2694
|
+
for p in map(_x, x._ps):
|
|
2695
|
+
yield p
|
|
2696
|
+
else:
|
|
2697
|
+
yield _x(x)
|
|
2698
|
+
|
|
2699
|
+
|
|
2700
|
+
def _xsError(X, xs, i, x, *n): # in _2floats, ._fstats
|
|
2701
|
+
'''(INTERNAL) Error for C{xs} or C{x}, item C{xs[i]}.
|
|
2702
|
+
'''
|
|
2703
|
+
return ((_xError(X, n[0], xs) if n else
|
|
2704
|
+
_xError(X, xs=xs)) if x is xs else
|
|
2705
|
+
_xError(X, Fmt.INDEX(xs=i), x))
|
|
2283
2706
|
|
|
2284
|
-
# usage: [env _psum=fsum] python3 -m pygeodesy.fsums
|
|
2285
2707
|
|
|
2286
|
-
|
|
2287
|
-
|
|
2708
|
+
def _xsum(which, xs, nonfinites=None, origin=0, primed=0, **floats):
|
|
2709
|
+
'''(INTERNAL) Precision summation of C{xs} with conditions.
|
|
2710
|
+
'''
|
|
2711
|
+
i_x = [0, xs]
|
|
2712
|
+
try:
|
|
2713
|
+
if nonfinites is None:
|
|
2714
|
+
nonfinites = not nonfiniterrors()
|
|
2715
|
+
elif floats:
|
|
2716
|
+
nonfinites = _xkwds_get1(floats, floats=nonfinites)
|
|
2717
|
+
fs = _xs(xs, (_passarg if nonfinites else _2finite), i_x)
|
|
2718
|
+
return _fsum(_1primed(fs) if primed else fs)
|
|
2719
|
+
except (OverflowError, TypeError, ValueError) as X:
|
|
2720
|
+
i, x = i_x
|
|
2721
|
+
i += origin - (1 if primed else 0)
|
|
2722
|
+
t = _xsError(X, xs, i, x)
|
|
2723
|
+
t = _COMMASPACE_(unstr(which), t)
|
|
2724
|
+
raise _xError(X, t, txt=None)
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
# delete all decorators, etc.
|
|
2728
|
+
del _allPropertiesOf_n, deprecated_method, deprecated_property_RO, \
|
|
2729
|
+
Property, Property_RO, property_RO, _ALL_LAZY, _F2PRODUCT, \
|
|
2730
|
+
MANT_DIG, _NONFINITES, _RESIDUAL_0_0, _getenv, _std_
|
|
2731
|
+
|
|
2732
|
+
if __name__ == '__main__':
|
|
2733
|
+
|
|
2734
|
+
# usage: python3 -m pygeodesy.fsums
|
|
2288
2735
|
|
|
2289
2736
|
def _test(n):
|
|
2290
2737
|
# copied from Hettinger, see L{Fsum} reference
|