pygeodesy 24.9.9__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.9.9.dist-info → PyGeodesy-24.9.24.dist-info}/METADATA +6 -6
- {PyGeodesy-24.9.9.dist-info → PyGeodesy-24.9.24.dist-info}/RECORD +21 -21
- pygeodesy/__init__.py +7 -5
- pygeodesy/basics.py +9 -10
- pygeodesy/booleans.py +4 -4
- pygeodesy/clipy.py +7 -7
- pygeodesy/constants.py +19 -7
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/functions.py +9 -1
- pygeodesy/errors.py +32 -5
- pygeodesy/fmath.py +36 -15
- pygeodesy/fstats.py +8 -12
- pygeodesy/fsums.py +726 -466
- pygeodesy/karney.py +1 -5
- pygeodesy/lazily.py +6 -6
- pygeodesy/points.py +3 -3
- pygeodesy/resections.py +2 -2
- pygeodesy/sphericalNvector.py +4 -4
- pygeodesy/sphericalTrigonometry.py +2 -2
- {PyGeodesy-24.9.9.dist-info → PyGeodesy-24.9.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.9.9.dist-info → PyGeodesy-24.9.24.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -1,29 +1,40 @@
|
|
|
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
|
-
C{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
C{
|
|
21
|
-
|
|
22
|
-
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater than
|
|
23
|
-
C{"0.0"} as the threshold to throw a L{ResidualError} for a division, power or
|
|
24
|
-
root operation of an L{Fsum} instance with a C{residual} I{ratio} exceeding
|
|
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
|
|
25
22
|
the threshold. See methods L{Fsum.RESIDUAL}, L{Fsum.pow}, L{Fsum.__ipow__}
|
|
26
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.
|
|
27
38
|
'''
|
|
28
39
|
# make sure int/int division yields float quotient, see .basics
|
|
29
40
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
@@ -31,83 +42,73 @@ from __future__ import division as _; del _ # PYCHOK semicolon
|
|
|
31
42
|
from pygeodesy.basics import isbool, iscomplex, isint, isscalar, \
|
|
32
43
|
_signOf, itemsorted, signOf, _xiterable, \
|
|
33
44
|
_xiterablen
|
|
34
|
-
from pygeodesy.constants import
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
39
51
|
from pygeodesy.internals import _enquote, _passarg
|
|
40
|
-
from pygeodesy.interns import NN, _arg_, _COMMASPACE_,
|
|
41
|
-
|
|
42
|
-
_not_finite_, _PERCENT_, _PLUS_, \
|
|
43
|
-
_RANGLE_, _SLASH_, _SPACE_, _STAR_, _UNDER_
|
|
52
|
+
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DOT_, _from_, \
|
|
53
|
+
_not_finite_, _SPACE_, _std_, _UNDER_
|
|
44
54
|
from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
|
|
45
55
|
from pygeodesy.named import _name__, _name2__, _Named, _NamedTuple, \
|
|
46
56
|
_NotImplemented
|
|
47
|
-
from pygeodesy.props import _allPropertiesOf_n,
|
|
48
|
-
|
|
57
|
+
from pygeodesy.props import _allPropertiesOf_n, deprecated_method, \
|
|
58
|
+
deprecated_property_RO, Property, \
|
|
59
|
+
Property_RO, property_RO
|
|
49
60
|
from pygeodesy.streprs import Fmt, fstr, unstr
|
|
50
61
|
# from pygeodesy.units import Float, Int # from .constants
|
|
51
62
|
|
|
52
|
-
from math import
|
|
63
|
+
from math import fabs, isinf, isnan, \
|
|
64
|
+
ceil as _ceil, floor as _floor # PYCHOK used! .ltp
|
|
53
65
|
|
|
54
66
|
__all__ = _ALL_LAZY.fsums
|
|
55
|
-
__version__ = '24.09.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
65
86
|
_integer_ = 'integer'
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
_mod_op_ = _PERCENT_
|
|
70
|
-
_mul_op_ = _STAR_
|
|
71
|
-
_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_
|
|
72
90
|
_non_zero_ = 'non-zero'
|
|
73
|
-
_pow_op_ =
|
|
91
|
+
_pow_op_ = _mul_op_ * 2 # _DSTAR_
|
|
92
|
+
_RESIDUAL_0_0 = _getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)
|
|
74
93
|
_significant_ = 'significant'
|
|
75
|
-
|
|
94
|
+
_2split3s = _passarg
|
|
76
95
|
_threshold_ = 'threshold'
|
|
77
|
-
_truediv_op_ = _SLASH_
|
|
78
|
-
_divmod_op_ = _floordiv_op_ + _mod_op_
|
|
79
|
-
_isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
|
|
80
96
|
|
|
81
97
|
|
|
82
|
-
def
|
|
83
|
-
'''(INTERNAL) Helper for C{Fsum._fsum2}.
|
|
84
|
-
'''
|
|
85
|
-
try:
|
|
86
|
-
a, b = _2sum(*ab)
|
|
87
|
-
except _OverflowError:
|
|
88
|
-
a, b = ab
|
|
89
|
-
return float(a if fabs(a) > fabs(b) else b)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _2error(unused): # in .fstats
|
|
93
|
-
'''(INTERNAL) Throw a C{not-finite} exception.
|
|
94
|
-
'''
|
|
95
|
-
raise ValueError(_not_finite_)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def _2finite(x):
|
|
98
|
+
def _2finite(x): # in .fstats
|
|
99
99
|
'''(INTERNAL) return C{float(x)} if finite.
|
|
100
100
|
'''
|
|
101
|
-
x
|
|
102
|
-
|
|
101
|
+
return (float(x) if _isfinite(x) # and isscalar(x)
|
|
102
|
+
else _nfError(x))
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
def _2float(index=None, **name_value): # in .fmath, .fstats
|
|
105
|
+
def _2float(index=None, _isfine=_isfinite, **name_value): # in .fmath, .fstats
|
|
106
106
|
'''(INTERNAL) Raise C{TypeError} or C{ValueError} if not scalar or infinite.
|
|
107
107
|
'''
|
|
108
108
|
n, v = name_value.popitem() # _xkwds_item2(name_value)
|
|
109
109
|
try:
|
|
110
|
-
|
|
110
|
+
f = float(v)
|
|
111
|
+
return f if _isfine(f) else _nfError(f)
|
|
111
112
|
except Exception as X:
|
|
112
113
|
raise _xError(X, Fmt.INDEX(n, index), v)
|
|
113
114
|
|
|
@@ -116,29 +117,82 @@ def _X_ps(X): # for _2floats only
|
|
|
116
117
|
return X._ps
|
|
117
118
|
|
|
118
119
|
|
|
119
|
-
def _2floats(xs, origin=0, _X=_X_ps, _x=float):
|
|
120
|
+
def _2floats(xs, origin=0, _X=_X_ps, _x=float, _isfine=_isfinite):
|
|
120
121
|
'''(INTERNAL) Yield each B{C{xs}} as a C{float}.
|
|
121
122
|
'''
|
|
122
123
|
try:
|
|
123
|
-
i, x = origin,
|
|
124
|
-
_fin = _isfinite
|
|
124
|
+
i, x = origin, xs
|
|
125
125
|
_FsT = _Fsum_Fsum2Tuple_types
|
|
126
|
-
_isa = isinstance
|
|
127
126
|
for x in _xiterable(xs):
|
|
128
|
-
if
|
|
127
|
+
if isinstance(x, _FsT):
|
|
129
128
|
for p in _X(x._Fsum):
|
|
130
129
|
yield p
|
|
131
130
|
else:
|
|
132
131
|
f = _x(x)
|
|
133
|
-
yield f if
|
|
132
|
+
yield f if _isfine(f) else _nfError(f)
|
|
134
133
|
i += 1
|
|
135
134
|
except Exception as X:
|
|
136
|
-
raise
|
|
137
|
-
_xError(X, Fmt.INDEX(xs=i), x)
|
|
135
|
+
raise _xsError(X, xs, i, x)
|
|
138
136
|
|
|
139
137
|
|
|
140
|
-
try: # MCCABE
|
|
138
|
+
try: # MCCABE 17
|
|
141
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
|
|
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)
|
|
151
|
+
|
|
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)
|
|
142
196
|
|
|
143
197
|
def _2products(x, ys, **unused):
|
|
144
198
|
# TwoProductFMA U{Algorithm 3.5
|
|
@@ -148,47 +202,22 @@ try: # MCCABE 14
|
|
|
148
202
|
yield f
|
|
149
203
|
yield _fma(x, y, -f)
|
|
150
204
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
except ImportError: # Python 3.12-
|
|
154
|
-
|
|
155
|
-
def _fma(*a_b_c): # in .fmath
|
|
156
|
-
# mimick C{math.fma} from Python 3.13+
|
|
157
|
-
# <https://MomentsInGraphics.De/FMA.html>
|
|
158
|
-
# >>> a = 1.00000011920929
|
|
159
|
-
# >>> b = 53400708
|
|
160
|
-
# >>> c = -b
|
|
161
|
-
# >>> _fma(a, b, c)
|
|
162
|
-
# 6.365860485903399
|
|
163
|
-
# >>> (a * b) + c
|
|
164
|
-
# 6.3658604845404625
|
|
165
|
-
|
|
166
|
-
def _as_n_d(x):
|
|
167
|
-
try:
|
|
168
|
-
if _isfinite(x):
|
|
169
|
-
# int.as_integer_ratio since 3.8
|
|
170
|
-
return x.as_integer_ratio()
|
|
171
|
-
except (AttributeError, OverflowError, TypeError, ValueError):
|
|
172
|
-
pass
|
|
173
|
-
return float(x), 1
|
|
174
|
-
|
|
175
|
-
(na, da), (nb, db), (nc, dc) = map(_as_n_d, a_b_c)
|
|
176
|
-
n = na * nb * dc + da * db * nc
|
|
177
|
-
d = da * db * dc
|
|
178
|
-
return float(n / d)
|
|
205
|
+
else: # in _std_ _fma(a, b, c)
|
|
179
206
|
|
|
180
207
|
def _2products(x, y3s, two=False): # PYCHOK redef
|
|
181
208
|
# TwoProduct U{Algorithm 3.3
|
|
182
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
|
|
183
212
|
_, a, b = _2split3(x)
|
|
184
213
|
for y, c, d in y3s:
|
|
185
214
|
y *= x
|
|
186
215
|
yield y
|
|
187
|
-
if two:
|
|
216
|
+
if two: # or not a:
|
|
188
217
|
yield b * d - (((y - a * c) - b * c) - a * d)
|
|
189
|
-
#
|
|
190
|
-
#
|
|
191
|
-
#
|
|
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)))
|
|
192
221
|
else:
|
|
193
222
|
yield a * c - y
|
|
194
223
|
yield b * c
|
|
@@ -196,29 +225,33 @@ except ImportError: # Python 3.12-
|
|
|
196
225
|
yield a * d
|
|
197
226
|
yield b * d
|
|
198
227
|
|
|
199
|
-
_2FACTOR = pow(2, (MANT_DIG + 1) // 2) + 1
|
|
200
228
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
# <ttps://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
204
|
-
a = c = x * _2FACTOR
|
|
205
|
-
a -= c - x
|
|
206
|
-
b = x - a
|
|
207
|
-
return x, a, b
|
|
229
|
+
def f2product(*two):
|
|
230
|
+
'''Turn accurate I{TwoProduct} multiplication on or off.
|
|
208
231
|
|
|
209
|
-
|
|
210
|
-
|
|
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.
|
|
211
234
|
|
|
212
|
-
|
|
235
|
+
@return: The previous setting (C{bool}).
|
|
213
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
|
|
214
246
|
|
|
215
|
-
|
|
247
|
+
|
|
248
|
+
def _Fsumf_(*xs): # in .auxLat, .ltp, ...
|
|
216
249
|
'''(INTERNAL) An C{Fsum} of I{known scalars}.
|
|
217
250
|
'''
|
|
218
251
|
return Fsum()._facc_scalar(xs, up=False)
|
|
219
252
|
|
|
220
253
|
|
|
221
|
-
def _Fsum1f_(*xs): #
|
|
254
|
+
def _Fsum1f_(*xs): # in .albers
|
|
222
255
|
'''(INTERNAL) An C{Fsum} of I{known scalars}, 1-primed.
|
|
223
256
|
'''
|
|
224
257
|
return Fsum()._facc_scalar(_1primed(xs), up=False)
|
|
@@ -242,16 +275,60 @@ def _isFsum(x): # in .fmath
|
|
|
242
275
|
return isinstance(x, Fsum)
|
|
243
276
|
|
|
244
277
|
|
|
245
|
-
def _isFsumTuple(x): # in .fmath
|
|
278
|
+
def _isFsumTuple(x): # in .basics, .constants, .fmath, .fstats
|
|
246
279
|
'''(INTERNAL) Is C{x} an C{Fsum} or C{Fsum2Tuple} instance?
|
|
247
280
|
'''
|
|
248
281
|
return isinstance(x, _Fsum_Fsum2Tuple_types)
|
|
249
282
|
|
|
250
283
|
|
|
251
|
-
def
|
|
252
|
-
'''(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}.
|
|
253
320
|
'''
|
|
254
|
-
|
|
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}.
|
|
329
|
+
'''
|
|
330
|
+
return _OverflowError if isinf(x) else (
|
|
331
|
+
_ValueError if isnan(x) else _AssertionError)
|
|
255
332
|
|
|
256
333
|
|
|
257
334
|
def _1primed(xs): # in .fmath
|
|
@@ -264,16 +341,15 @@ def _1primed(xs): # in .fmath
|
|
|
264
341
|
yield _N_1_0
|
|
265
342
|
|
|
266
343
|
|
|
267
|
-
def _psum(ps): # PYCHOK used!
|
|
344
|
+
def _psum(ps, **_isfine): # PYCHOK used!
|
|
268
345
|
'''(INTERNAL) Partials summation, updating C{ps}.
|
|
269
346
|
'''
|
|
270
347
|
# assert isinstance(ps, list)
|
|
271
|
-
i
|
|
272
|
-
s
|
|
273
|
-
_2s = _2sum
|
|
348
|
+
i = len(ps) - 1
|
|
349
|
+
s = _0_0 if i < 0 else ps[i]
|
|
274
350
|
while i > 0:
|
|
275
351
|
i -= 1
|
|
276
|
-
s, r =
|
|
352
|
+
s, r = _2sum(s, ps[i], **_isfine)
|
|
277
353
|
if r: # sum(ps) became inexact
|
|
278
354
|
if s:
|
|
279
355
|
ps[i:] = r, s
|
|
@@ -281,24 +357,28 @@ def _psum(ps): # PYCHOK used!
|
|
|
281
357
|
s = _2halfeven(s, r, ps[i-1])
|
|
282
358
|
break # return s
|
|
283
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)
|
|
284
364
|
ps[i:] = s,
|
|
285
365
|
return s
|
|
286
366
|
|
|
287
367
|
|
|
288
|
-
def _Psum(ps, **
|
|
368
|
+
def _Psum(ps, **name_f2product_nonfinites_RESIDUAL):
|
|
289
369
|
'''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
|
|
290
370
|
'''
|
|
291
|
-
|
|
371
|
+
F = Fsum(**name_f2product_nonfinites_RESIDUAL)
|
|
292
372
|
if ps:
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
return
|
|
373
|
+
F._ps[:] = ps
|
|
374
|
+
F._n = len(F._ps)
|
|
375
|
+
return F
|
|
296
376
|
|
|
297
377
|
|
|
298
|
-
def _Psum_(*ps, **
|
|
299
|
-
'''(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}.
|
|
300
380
|
'''
|
|
301
|
-
return _Psum(ps, **
|
|
381
|
+
return _Psum(ps, **name_f2product_nonfinites_RESIDUAL)
|
|
302
382
|
|
|
303
383
|
|
|
304
384
|
def _2scalar2(other):
|
|
@@ -322,7 +402,7 @@ def _2scalar2(other):
|
|
|
322
402
|
def _s_r(s, r):
|
|
323
403
|
'''(INTERNAL) Return C{(s, r)}, I{ordered}.
|
|
324
404
|
'''
|
|
325
|
-
if r:
|
|
405
|
+
if r and _isfinite(s):
|
|
326
406
|
if fabs(s) < fabs(r):
|
|
327
407
|
s, r = r, (s or INT0)
|
|
328
408
|
else:
|
|
@@ -334,7 +414,7 @@ def _strcomplex(s, *args):
|
|
|
334
414
|
'''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
|
|
335
415
|
'''
|
|
336
416
|
c = _strcomplex.__name__[4:]
|
|
337
|
-
n =
|
|
417
|
+
n = _sub_op_(len(args), _arg_)
|
|
338
418
|
t = unstr(pow, *args)
|
|
339
419
|
return _SPACE_(c, s, _from_, n, t)
|
|
340
420
|
|
|
@@ -350,9 +430,12 @@ def _stresidual(prefix, residual, R=0, **mod_ratio):
|
|
|
350
430
|
return _SPACE_(prefix, t, Fmt.exceeds_R(R), _threshold_)
|
|
351
431
|
|
|
352
432
|
|
|
353
|
-
def _2sum(a, b): #
|
|
354
|
-
'''(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.
|
|
355
436
|
'''
|
|
437
|
+
# FastTwoSum U{Algorithm 1.1<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
438
|
+
|
|
356
439
|
# Neumaier, A. U{Rundungsfehleranalyse einiger Verfahren zur Summation endlicher
|
|
357
440
|
# Summen<https://OnlineLibrary.Wiley.com/doi/epdf/10.1002/zamm.19740540106>},
|
|
358
441
|
# 1974, Zeitschrift für Angewandte Mathmatik und Mechanik, vol 51, nr 1, p 39-51
|
|
@@ -363,10 +446,12 @@ def _2sum(a, b): # by .testFmath
|
|
|
363
446
|
r = (b - s) + a
|
|
364
447
|
else:
|
|
365
448
|
r = (a - s) + b
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
|
370
455
|
|
|
371
456
|
|
|
372
457
|
def _threshold(threshold=_0_0, **kwds):
|
|
@@ -374,29 +459,28 @@ def _threshold(threshold=_0_0, **kwds):
|
|
|
374
459
|
optionally from single kwds C{B{RESIDUAL}=scalar}.
|
|
375
460
|
'''
|
|
376
461
|
if kwds:
|
|
377
|
-
threshold
|
|
378
|
-
# threshold = kwds.pop('RESIDUAL', threshold)
|
|
379
|
-
if kwds:
|
|
380
|
-
raise _UnexpectedError(**kwds)
|
|
462
|
+
threshold = _xkwds_get1(kwds, RESIDUAL=threshold)
|
|
381
463
|
try:
|
|
382
464
|
return _2finite(threshold) # PYCHOK None
|
|
383
465
|
except Exception as x:
|
|
384
466
|
raise ResidualError(threshold=threshold, cause=x)
|
|
385
467
|
|
|
386
468
|
|
|
387
|
-
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
388
|
-
'''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.
|
|
389
471
|
|
|
390
472
|
Unlike Python's C{math.fsum}, this class accumulates values and provides intermediate,
|
|
391
473
|
I{running}, precision floating point summations. Accumulation may continue after any
|
|
392
474
|
intermediate, I{running} summuation.
|
|
393
475
|
|
|
394
476
|
@note: Values may be L{Fsum}, L{Fsum2Tuple}, C{int}, C{float} or C{scalar} instances,
|
|
395
|
-
any C{type} having method C{__float__}
|
|
396
|
-
C{float}, except C{complex}.
|
|
477
|
+
i.e. any C{type} having method C{__float__}.
|
|
397
478
|
|
|
398
|
-
@note: Handling of
|
|
399
|
-
|
|
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.
|
|
400
484
|
|
|
401
485
|
@see: U{Hettinger<https://GitHub.com/ActiveState/code/tree/master/recipes/Python/
|
|
402
486
|
393090_Binary_floating_point_summatiaccurate_full/recipe-393090.py>},
|
|
@@ -404,42 +488,41 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
404
488
|
<https://Link.Springer.com/article/10.1007/s00607-005-0139-x>}, Python 2.6+
|
|
405
489
|
file I{Modules/mathmodule.c} and the issue log U{Full precision summation
|
|
406
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}.
|
|
407
497
|
'''
|
|
408
|
-
_f2product =
|
|
409
|
-
|
|
410
|
-
_math_fsum = None
|
|
498
|
+
_f2product = _sys_version_info2 > (3, 12) or bool(_F2PRODUCT)
|
|
499
|
+
_isfine = {} # == _isfinite
|
|
411
500
|
_n = 0
|
|
412
501
|
# _ps = [] # partial sums
|
|
413
502
|
# _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps))
|
|
414
|
-
_RESIDUAL = _threshold(
|
|
503
|
+
_RESIDUAL = _threshold(_RESIDUAL_0_0)
|
|
415
504
|
|
|
416
|
-
def __init__(self, *xs, **
|
|
417
|
-
'''New L{Fsum}
|
|
505
|
+
def __init__(self, *xs, **name_f2product_nonfinites_RESIDUAL):
|
|
506
|
+
'''New L{Fsum}.
|
|
418
507
|
|
|
419
|
-
@arg xs: No, one or more initial items to
|
|
420
|
-
|
|
421
|
-
@kwarg
|
|
422
|
-
|
|
423
|
-
|
|
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}.
|
|
424
514
|
|
|
425
|
-
@see: Methods L{Fsum.
|
|
515
|
+
@see: Methods L{Fsum.f2product}, L{Fsum.nonfinites}, L{Fsum.RESIDUAL},
|
|
516
|
+
L{Fsum.fadd} and L{Fsum.fadd_}.
|
|
426
517
|
'''
|
|
427
|
-
if
|
|
428
|
-
|
|
429
|
-
if kwds:
|
|
430
|
-
R = Fsum._RESIDUAL
|
|
431
|
-
t = _threshold(R, **kwds)
|
|
432
|
-
if t != R:
|
|
433
|
-
self._RESIDUAL = t
|
|
434
|
-
if n:
|
|
435
|
-
self.name = n
|
|
436
|
-
|
|
518
|
+
if name_f2product_nonfinites_RESIDUAL:
|
|
519
|
+
self._optionals(**name_f2product_nonfinites_RESIDUAL)
|
|
437
520
|
self._ps = [] # [_0_0], see L{Fsum._fprs}
|
|
438
521
|
if xs:
|
|
439
|
-
self.
|
|
522
|
+
self._facc_args(xs, up=False)
|
|
440
523
|
|
|
441
524
|
def __abs__(self):
|
|
442
|
-
'''Return
|
|
525
|
+
'''Return C{abs(self)} as an L{Fsum}.
|
|
443
526
|
'''
|
|
444
527
|
s = self.signOf() # == self._cmp_0(0)
|
|
445
528
|
return (-self) if s < 0 else self._copy_2(self.__abs__)
|
|
@@ -457,7 +540,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
457
540
|
return f._fadd(other, _add_op_)
|
|
458
541
|
|
|
459
542
|
def __bool__(self): # PYCHOK Python 3+
|
|
460
|
-
'''Return C{True}
|
|
543
|
+
'''Return C{bool(B{self})}, C{True} iff C{residual} is zero.
|
|
461
544
|
'''
|
|
462
545
|
s, r = self._fprs2
|
|
463
546
|
return bool(s or r) and s != -r # == self != 0
|
|
@@ -500,7 +583,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
500
583
|
return f._fdivmod2(other, _divmod_op_, **raiser_RESIDUAL)
|
|
501
584
|
|
|
502
585
|
def __eq__(self, other):
|
|
503
|
-
'''
|
|
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}.
|
|
504
588
|
'''
|
|
505
589
|
return self._cmp_0(other, _eq_op_) == 0
|
|
506
590
|
|
|
@@ -537,17 +621,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
537
621
|
return _NotImplemented(self, *other)
|
|
538
622
|
|
|
539
623
|
def __ge__(self, other):
|
|
540
|
-
'''
|
|
624
|
+
'''Return C{(B{self} >= B{other})}, see C{__eq__}.
|
|
541
625
|
'''
|
|
542
626
|
return self._cmp_0(other, _ge_op_) >= 0
|
|
543
627
|
|
|
544
628
|
def __gt__(self, other):
|
|
545
|
-
'''
|
|
629
|
+
'''Return C{(B{self} > B{other})}, see C{__eq__}.
|
|
546
630
|
'''
|
|
547
631
|
return self._cmp_0(other, _gt_op_) > 0
|
|
548
632
|
|
|
549
633
|
def __hash__(self): # PYCHOK no cover
|
|
550
|
-
'''Return
|
|
634
|
+
'''Return C{hash(B{self})} as C{float}.
|
|
551
635
|
'''
|
|
552
636
|
# @see: U{Notes for type implementors<https://docs.Python.org/
|
|
553
637
|
# 3/library/numbers.html#numbers.Rational>}
|
|
@@ -569,7 +653,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
569
653
|
try:
|
|
570
654
|
return self._fadd(other, _iadd_op_)
|
|
571
655
|
except TypeError:
|
|
572
|
-
|
|
656
|
+
pass
|
|
657
|
+
_xiterable(other)
|
|
658
|
+
return self._facc(other)
|
|
573
659
|
|
|
574
660
|
def __ifloordiv__(self, other):
|
|
575
661
|
'''Apply C{B{self} //= B{other}} to this instance.
|
|
@@ -583,7 +669,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
583
669
|
|
|
584
670
|
@raise TypeError: Invalid B{C{other}} type.
|
|
585
671
|
|
|
586
|
-
@raise ValueError: Invalid or non-finite B{C{other}}.
|
|
672
|
+
@raise ValueError: Invalid or I{non-finite} B{C{other}}.
|
|
587
673
|
|
|
588
674
|
@raise ZeroDivisionError: Zero B{C{other}}.
|
|
589
675
|
|
|
@@ -617,7 +703,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
617
703
|
|
|
618
704
|
@raise TypeError: Invalid B{C{other}} type.
|
|
619
705
|
|
|
620
|
-
@raise ValueError: Invalid or non-finite B{C{other}}.
|
|
706
|
+
@raise ValueError: Invalid or I{non-finite} B{C{other}}.
|
|
621
707
|
'''
|
|
622
708
|
return self._fmul(other, _mul_op_ + _fset_op_)
|
|
623
709
|
|
|
@@ -638,7 +724,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
638
724
|
def __ipow__(self, other, *mod, **raiser_RESIDUAL): # PYCHOK 2 vs 3 args
|
|
639
725
|
'''Apply C{B{self} **= B{other}} to this instance.
|
|
640
726
|
|
|
641
|
-
@arg other: The exponent (C{scalar}, L{Fsum} or L{Fsum2Tuple}).
|
|
727
|
+
@arg other: The exponent (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
642
728
|
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
643
729
|
C{pow(B{self}, B{other}, B{mod})} version.
|
|
644
730
|
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
|
|
@@ -688,7 +774,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
688
774
|
try:
|
|
689
775
|
return self._fsub(other, _isub_op_)
|
|
690
776
|
except TypeError:
|
|
691
|
-
|
|
777
|
+
pass
|
|
778
|
+
_xiterable(other)
|
|
779
|
+
return self._facc_neg(other)
|
|
692
780
|
|
|
693
781
|
def __iter__(self):
|
|
694
782
|
'''Return an C{iter}ator over a C{partials} duplicate.
|
|
@@ -712,7 +800,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
712
800
|
|
|
713
801
|
@raise TypeError: Invalid B{C{other}} type.
|
|
714
802
|
|
|
715
|
-
@raise ValueError: Invalid or non-finite B{C{other}}.
|
|
803
|
+
@raise ValueError: Invalid or I{non-finite} B{C{other}}.
|
|
716
804
|
|
|
717
805
|
@raise ZeroDivisionError: Zero B{C{other}}.
|
|
718
806
|
|
|
@@ -721,7 +809,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
721
809
|
return self._ftruediv(other, _truediv_op_ + _fset_op_, **raiser_RESIDUAL)
|
|
722
810
|
|
|
723
811
|
def __le__(self, other):
|
|
724
|
-
'''
|
|
812
|
+
'''Return C{(B{self} <= B{other})}, see C{__eq__}.
|
|
725
813
|
'''
|
|
726
814
|
return self._cmp_0(other, _le_op_) <= 0
|
|
727
815
|
|
|
@@ -731,7 +819,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
731
819
|
return self._n
|
|
732
820
|
|
|
733
821
|
def __lt__(self, other):
|
|
734
|
-
'''
|
|
822
|
+
'''Return C{(B{self} < B{other})}, see C{__eq__}.
|
|
735
823
|
'''
|
|
736
824
|
return self._cmp_0(other, _lt_op_) < 0
|
|
737
825
|
|
|
@@ -756,12 +844,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
756
844
|
return f._fmul(other, _mul_op_)
|
|
757
845
|
|
|
758
846
|
def __ne__(self, other):
|
|
759
|
-
'''
|
|
847
|
+
'''Return C{(B{self} != B{other})}, see C{__eq__}.
|
|
760
848
|
'''
|
|
761
849
|
return self._cmp_0(other, _ne_op_) != 0
|
|
762
850
|
|
|
763
851
|
def __neg__(self):
|
|
764
|
-
'''Return
|
|
852
|
+
'''Return C{copy(B{self})}, I{negated}.
|
|
765
853
|
'''
|
|
766
854
|
f = self._copy_2(self.__neg__)
|
|
767
855
|
return f._fset(self._neg)
|
|
@@ -909,11 +997,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
909
997
|
def as_integer_ratio(self):
|
|
910
998
|
'''Return this instance as the ratio of 2 integers.
|
|
911
999
|
|
|
912
|
-
@return: 2-Tuple C{(numerator, denominator)} both C{int}
|
|
913
|
-
|
|
914
|
-
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.
|
|
915
1004
|
|
|
916
|
-
@see:
|
|
1005
|
+
@see: Method L{Fsum.fint2} and C{float.as_integer_ratio} in
|
|
1006
|
+
Python 2.7+.
|
|
917
1007
|
'''
|
|
918
1008
|
n, r = self._fint2
|
|
919
1009
|
if r:
|
|
@@ -926,8 +1016,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
926
1016
|
|
|
927
1017
|
@property_RO
|
|
928
1018
|
def as_iscalar(self):
|
|
929
|
-
'''Get this instance I{as-is} (L{Fsum}
|
|
930
|
-
|
|
1019
|
+
'''Get this instance I{as-is} (L{Fsum} with C{non-zero residual},
|
|
1020
|
+
C{scalar} or I{non-finite}).
|
|
931
1021
|
'''
|
|
932
1022
|
s, r = self._fprs2
|
|
933
1023
|
return self if r else s
|
|
@@ -996,13 +1086,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
996
1086
|
return other._copy_2(which) if _isFsum(other) else \
|
|
997
1087
|
self._copy_2(which)._fset(other)
|
|
998
1088
|
|
|
999
|
-
# def _copy_RESIDUAL(self, other):
|
|
1000
|
-
# '''(INTERNAL) Copy C{other._RESIDUAL}.
|
|
1001
|
-
# '''
|
|
1002
|
-
# R = other._RESIDUAL
|
|
1003
|
-
# if R is not Fsum._RESIDUAL:
|
|
1004
|
-
# self._RESIDUAL = R
|
|
1005
|
-
|
|
1006
1089
|
divmod = __divmod__
|
|
1007
1090
|
|
|
1008
1091
|
def _Error(self, op, other, Error, **txt_cause):
|
|
@@ -1029,28 +1112,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1029
1112
|
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s.
|
|
1030
1113
|
'''
|
|
1031
1114
|
if xs:
|
|
1032
|
-
|
|
1115
|
+
kwds = _xkwds(self._isfine, **origin_X_x)
|
|
1116
|
+
_xs = _2floats(xs, **kwds) # PYCHOK yield
|
|
1033
1117
|
ps = self._ps
|
|
1034
1118
|
ps[:] = self._ps_acc(list(ps), _xs, up=up)
|
|
1035
1119
|
return self
|
|
1036
1120
|
|
|
1037
|
-
def
|
|
1038
|
-
'''(INTERNAL) Accumulate 0, 1 or more C{
|
|
1039
|
-
|
|
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.
|
|
1040
1124
|
'''
|
|
1041
|
-
return self.
|
|
1042
|
-
self.
|
|
1043
|
-
|
|
1044
|
-
def _facc_inplace(self, other, op, _facc):
|
|
1045
|
-
'''(INTERNAL) Accumulate from an iterable.
|
|
1046
|
-
'''
|
|
1047
|
-
try:
|
|
1048
|
-
return _facc(other, origin=1) if _xiterable(other) else self
|
|
1049
|
-
except Exception as X:
|
|
1050
|
-
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)
|
|
1051
1127
|
|
|
1052
1128
|
def _facc_neg(self, xs, **up_origin):
|
|
1053
|
-
'''(INTERNAL) Accumulate more C{
|
|
1129
|
+
'''(INTERNAL) Accumulate more C{xs}, negated.
|
|
1054
1130
|
'''
|
|
1055
1131
|
def _N(X):
|
|
1056
1132
|
return X._ps_neg
|
|
@@ -1075,24 +1151,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1075
1151
|
p = s = int(p)
|
|
1076
1152
|
m = Fsum._pow_int
|
|
1077
1153
|
else:
|
|
1078
|
-
p = s = _2float(power=p)
|
|
1154
|
+
p = s = _2float(power=p, **self._isfine)
|
|
1079
1155
|
m = Fsum._pow_scalar
|
|
1080
1156
|
return m, p, s, r
|
|
1081
1157
|
|
|
1082
1158
|
_Pow, p, s, r = _Pow4(power)
|
|
1083
1159
|
if p: # and xs:
|
|
1084
1160
|
op = which.__name__
|
|
1085
|
-
|
|
1086
|
-
_Fs = Fsum
|
|
1087
|
-
_isa = isinstance
|
|
1161
|
+
_FsT = _Fsum_Fsum2Tuple_types
|
|
1088
1162
|
_pow = self._pow_2_3
|
|
1089
1163
|
|
|
1090
1164
|
def _P(X):
|
|
1091
1165
|
f = _Pow(X, p, power, op, **raiser_RESIDUAL)
|
|
1092
|
-
return f._ps if
|
|
1166
|
+
return f._ps if isinstance(f, _FsT) else (f,)
|
|
1093
1167
|
|
|
1094
1168
|
def _p(x):
|
|
1095
|
-
x =
|
|
1169
|
+
x = float(x)
|
|
1096
1170
|
f = _pow(x, s, power, op, **raiser_RESIDUAL)
|
|
1097
1171
|
if f and r:
|
|
1098
1172
|
f *= _pow(x, r, power, op, **raiser_RESIDUAL)
|
|
@@ -1143,12 +1217,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1143
1217
|
|
|
1144
1218
|
@raise TypeError: An invalid B{C{xs}} item.
|
|
1145
1219
|
|
|
1146
|
-
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
1220
|
+
@raise ValueError: Invalid or I{non-finite} B{C{xs}} value.
|
|
1147
1221
|
'''
|
|
1148
1222
|
if _isFsumTuple(xs):
|
|
1149
1223
|
self._facc_scalar(xs._ps)
|
|
1150
|
-
elif isscalar(xs):
|
|
1151
|
-
|
|
1224
|
+
elif isscalar(xs): # for backward compatibility # PYCHOK no cover
|
|
1225
|
+
x = _2float(x=xs, **self._isfine)
|
|
1226
|
+
self._facc_scalar_(x)
|
|
1152
1227
|
elif xs: # _xiterable(xs)
|
|
1153
1228
|
self._facc(xs)
|
|
1154
1229
|
return self
|
|
@@ -1161,17 +1236,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1161
1236
|
|
|
1162
1237
|
@see: Method L{Fsum.fadd} for further details.
|
|
1163
1238
|
'''
|
|
1164
|
-
return self.
|
|
1239
|
+
return self._facc_args(xs)
|
|
1165
1240
|
|
|
1166
1241
|
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
1167
1242
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
1168
1243
|
'''
|
|
1169
|
-
if
|
|
1170
|
-
self.
|
|
1171
|
-
|
|
1172
|
-
|
|
1244
|
+
if _isFsumTuple(other):
|
|
1245
|
+
if self._ps:
|
|
1246
|
+
self._facc_scalar(other._ps, **up)
|
|
1247
|
+
else:
|
|
1248
|
+
self._fset(other, op=op, **up)
|
|
1173
1249
|
elif self._scalar(other, op):
|
|
1174
|
-
self.
|
|
1250
|
+
if self._ps:
|
|
1251
|
+
self._facc_scalar_(other, **up)
|
|
1252
|
+
else:
|
|
1253
|
+
self._fset(other, op=op, **up)
|
|
1175
1254
|
return self
|
|
1176
1255
|
|
|
1177
1256
|
fcopy = copy # for backward compatibility
|
|
@@ -1186,7 +1265,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1186
1265
|
# but at least divmod(-3, 2) equals Cpython's result (-2, 1).
|
|
1187
1266
|
q = self._truediv(other, op, **raiser_RESIDUAL).floor
|
|
1188
1267
|
if q: # == float // other == floor(float / other)
|
|
1189
|
-
self -=
|
|
1268
|
+
self -= self._Fsum_as(q) * other # NOT other * q!
|
|
1190
1269
|
|
|
1191
1270
|
s = signOf(other) # make signOf(self) == signOf(other)
|
|
1192
1271
|
if s and self.signOf() == -s: # PYCHOK no cover
|
|
@@ -1203,12 +1282,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1203
1282
|
else sum(... i=len(cs)-1..0)}.
|
|
1204
1283
|
'''
|
|
1205
1284
|
if _xiterablen(cs):
|
|
1206
|
-
H =
|
|
1285
|
+
H = self._Fsum_as(name__=self._fhorner)
|
|
1207
1286
|
if _isFsumTuple(x):
|
|
1208
1287
|
_mul = H._mul_Fsum
|
|
1209
1288
|
else:
|
|
1210
1289
|
_mul = H._mul_scalar
|
|
1211
|
-
x = _2float(x=x)
|
|
1290
|
+
x = _2float(x=x, **self._isfine)
|
|
1212
1291
|
if len(cs) > 1 and x:
|
|
1213
1292
|
for c in (reversed(cs) if incx else cs):
|
|
1214
1293
|
H._fset_ps(_mul(x, op))
|
|
@@ -1221,10 +1300,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1221
1300
|
def _finite(self, other, op=None):
|
|
1222
1301
|
'''(INTERNAL) Return B{C{other}} if C{finite}.
|
|
1223
1302
|
'''
|
|
1224
|
-
if
|
|
1303
|
+
if _isOK_or_finite(other, **self._isfine):
|
|
1225
1304
|
return other
|
|
1226
|
-
|
|
1227
|
-
|
|
1305
|
+
E = _NonfiniteError(other)
|
|
1306
|
+
raise self._Error(op, other, E, txt=_not_finite_)
|
|
1228
1307
|
|
|
1229
1308
|
def fint(self, name=NN, **raiser_RESIDUAL):
|
|
1230
1309
|
'''Return this instance' current running sum as C{integer}.
|
|
@@ -1248,7 +1327,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1248
1327
|
if R:
|
|
1249
1328
|
t = _stresidual(_integer_, r, **R)
|
|
1250
1329
|
raise ResidualError(_integer_, i, txt=t)
|
|
1251
|
-
return
|
|
1330
|
+
return self._Fsum_as(i, name=_name__(name, name__=self.fint))
|
|
1252
1331
|
|
|
1253
1332
|
def fint2(self, **name):
|
|
1254
1333
|
'''Return this instance' current running sum as C{int} and the
|
|
@@ -1259,6 +1338,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1259
1338
|
@return: An L{Fsum2Tuple}C{(fsum, residual)} with C{fsum}
|
|
1260
1339
|
an C{int} and I{integer} C{residual} a C{float} or
|
|
1261
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.
|
|
1262
1342
|
'''
|
|
1263
1343
|
return Fsum2Tuple(*self._fint2, **name)
|
|
1264
1344
|
|
|
@@ -1266,18 +1346,35 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1266
1346
|
def _fint2(self): # see ._fset
|
|
1267
1347
|
'''(INTERNAL) Get 2-tuple (C{int}, I{integer} residual).
|
|
1268
1348
|
'''
|
|
1269
|
-
s,
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
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
|
|
1277
1361
|
'''(INTERNAL) Replace the C{_fint2} value.
|
|
1278
1362
|
'''
|
|
1279
|
-
|
|
1280
|
-
|
|
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)
|
|
1281
1378
|
|
|
1282
1379
|
@deprecated_property_RO
|
|
1283
1380
|
def float_int(self): # PYCHOK no cover
|
|
@@ -1300,8 +1397,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1300
1397
|
f -= 1
|
|
1301
1398
|
return f # _floor(self._n_d)
|
|
1302
1399
|
|
|
1303
|
-
# ffloordiv = __ifloordiv__ # for naming consistency
|
|
1304
|
-
# floordiv = __floordiv__ # for naming consistency
|
|
1400
|
+
# ffloordiv = __ifloordiv__ # for naming consistency?
|
|
1401
|
+
# floordiv = __floordiv__ # for naming consistency?
|
|
1305
1402
|
|
|
1306
1403
|
def _floordiv(self, other, op, **raiser_RESIDUAL): # rather _ffloordiv?
|
|
1307
1404
|
'''Apply C{B{self} //= B{other}}.
|
|
@@ -1309,37 +1406,32 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1309
1406
|
q = self._ftruediv(other, op, **raiser_RESIDUAL) # == self
|
|
1310
1407
|
return self._fset(q.floor) # floor(q)
|
|
1311
1408
|
|
|
1312
|
-
def fma(self, other1, other2): #
|
|
1409
|
+
def fma(self, other1, other2, raiser=False): # in .fmath.fma
|
|
1313
1410
|
'''Fused-multiply-add C{self *= B{other1}; self += B{other2}}.
|
|
1314
1411
|
|
|
1315
|
-
@arg other1:
|
|
1316
|
-
@arg other2:
|
|
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}).
|
|
1317
1416
|
|
|
1318
1417
|
@note: Uses C{math.fma} in Python 3.13+, provided C{self},
|
|
1319
1418
|
B{C{other1}} and B{C{other2}} are all C{scalar}.
|
|
1320
1419
|
'''
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
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)
|
|
1327
1431
|
else:
|
|
1328
|
-
self._f2mul(self.fma
|
|
1329
|
-
|
|
1330
|
-
return self
|
|
1331
|
-
|
|
1332
|
-
# def _fma_scalar(self, op, x, *ys): # in .karney
|
|
1333
|
-
# '''(INTERNAL) Apply C{self.fma(B{x}, B{y}) for B{y} in B{ys}}
|
|
1334
|
-
# for scalar C{x} and C{y}s.
|
|
1335
|
-
# '''
|
|
1336
|
-
# ps = self._ps
|
|
1337
|
-
# if ps and ys:
|
|
1338
|
-
# for y in ys:
|
|
1339
|
-
# ps[:] = self._ps_acc(list(y), _2products(x, _2split3s(ps)))
|
|
1340
|
-
# for p in (ps if op else()):
|
|
1341
|
-
# self._finite(p, op)
|
|
1342
|
-
# return self
|
|
1432
|
+
f = self._f2mul(self.fma, other1, raiser=raiser)
|
|
1433
|
+
f += other2
|
|
1434
|
+
return self._fset(f)
|
|
1343
1435
|
|
|
1344
1436
|
fmul = __imul__
|
|
1345
1437
|
|
|
@@ -1350,38 +1442,55 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1350
1442
|
if len(self._ps) != 1:
|
|
1351
1443
|
f = self._mul_Fsum(other, op)
|
|
1352
1444
|
elif len(other._ps) != 1: # and len(self._ps) == 1
|
|
1353
|
-
f =
|
|
1445
|
+
f = self._ps_mul(op, *other._ps)
|
|
1354
1446
|
elif self._f2product: # len(other._ps) == 1
|
|
1355
1447
|
f = self._mul_scalar(other._ps[0], op)
|
|
1356
1448
|
else: # len(other._ps) == len(self._ps) == 1
|
|
1357
|
-
f = self._finite(self._ps[0] * other._ps[0])
|
|
1449
|
+
f = self._finite(self._ps[0] * other._ps[0], op=op)
|
|
1358
1450
|
else:
|
|
1359
1451
|
s = self._scalar(other, op)
|
|
1360
1452
|
f = self._mul_scalar(s, op)
|
|
1361
1453
|
return self._fset(f) # n=len(self) + 1
|
|
1362
1454
|
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
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))
|
|
1367
1459
|
|
|
1368
|
-
|
|
1369
|
-
'''
|
|
1370
|
-
|
|
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}).
|
|
1371
1468
|
|
|
1372
|
-
|
|
1373
|
-
|
|
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>}
|
|
1374
1472
|
'''
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
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
|
|
1385
1494
|
|
|
1386
1495
|
def fover(self, over, **raiser_RESIDUAL):
|
|
1387
1496
|
'''Apply C{B{self} /= B{over}} and summate.
|
|
@@ -1410,32 +1519,38 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1410
1519
|
f = self._pow_2_3(self, other, other, op, *mod, **raiser_RESIDUAL)
|
|
1411
1520
|
elif self.is_integer():
|
|
1412
1521
|
# return an exact C{int} for C{int}**C{int}
|
|
1413
|
-
i, _ =
|
|
1522
|
+
i, _ = self._fint2 # assert _ == 0
|
|
1414
1523
|
x, r = _2scalar2(other) # C{int}, C{float} or other
|
|
1415
|
-
f =
|
|
1416
|
-
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)
|
|
1417
1526
|
else: # mod[0] is None, power(self, other)
|
|
1418
|
-
f =
|
|
1527
|
+
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1419
1528
|
else: # pow(self, other)
|
|
1420
1529
|
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1421
1530
|
return self._fset(f) # n=max(len(self), 1)
|
|
1422
1531
|
|
|
1423
1532
|
def f2product(self, *two):
|
|
1424
|
-
'''
|
|
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>}.
|
|
1425
1536
|
|
|
1426
|
-
@arg two: If
|
|
1427
|
-
|
|
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}).
|
|
1428
1540
|
|
|
1429
|
-
@return: The previous C{
|
|
1541
|
+
@return: The previous setting (C{bool} or C{None} if not set).
|
|
1430
1542
|
|
|
1431
|
-
@see:
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
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}.
|
|
1435
1547
|
'''
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
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)
|
|
1439
1554
|
return t
|
|
1440
1555
|
|
|
1441
1556
|
@Property
|
|
@@ -1461,21 +1576,26 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1461
1576
|
running sum and residual (L{Fsum2Tuple}).
|
|
1462
1577
|
'''
|
|
1463
1578
|
ps = self._ps
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
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
|
|
1479
1599
|
# assert self._ps is ps
|
|
1480
1600
|
return Fsum2Tuple(s, r)
|
|
1481
1601
|
|
|
@@ -1486,19 +1606,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1486
1606
|
return Fsum2Tuple(s_r)
|
|
1487
1607
|
|
|
1488
1608
|
def fset_(self, *xs):
|
|
1489
|
-
'''
|
|
1609
|
+
'''Apply C{B{self}.partials = Fsum(*B{xs}).partials}.
|
|
1490
1610
|
|
|
1491
1611
|
@arg xs: Optional, new values (each C{scalar} or
|
|
1492
|
-
an L{Fsum} or L{Fsum2Tuple} instance),
|
|
1493
|
-
|
|
1612
|
+
an L{Fsum} or L{Fsum2Tuple} instance), all
|
|
1613
|
+
positional.
|
|
1494
1614
|
|
|
1495
1615
|
@return: This instance, replaced (C{Fsum}).
|
|
1496
1616
|
|
|
1497
1617
|
@see: Method L{Fsum.fadd} for further details.
|
|
1498
1618
|
'''
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
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)
|
|
1502
1621
|
|
|
1503
1622
|
def _fset(self, other, n=0, up=True, **op):
|
|
1504
1623
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
@@ -1508,7 +1627,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1508
1627
|
elif _isFsumTuple(other):
|
|
1509
1628
|
self._ps[:] = other._ps
|
|
1510
1629
|
self._n = n or other._n
|
|
1511
|
-
# self._copy_RESIDUAL(other)
|
|
1512
1630
|
if up: # use or zap the C{Property_RO} values
|
|
1513
1631
|
Fsum._fint2._update_from(self, other)
|
|
1514
1632
|
Fsum._fprs ._update_from(self, other)
|
|
@@ -1524,13 +1642,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1524
1642
|
self._fprs = s
|
|
1525
1643
|
self._fprs2 = s, INT0
|
|
1526
1644
|
# assert self._fprs is s
|
|
1527
|
-
else:
|
|
1645
|
+
else:
|
|
1528
1646
|
op = _xkwds_get1(op, op=_fset_op_)
|
|
1529
1647
|
raise self._Error(op, other, _TypeError)
|
|
1530
1648
|
return self
|
|
1531
1649
|
|
|
1532
|
-
def _fset_ps(self, other): # in .fmath
|
|
1533
|
-
'''(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}.
|
|
1534
1652
|
'''
|
|
1535
1653
|
return self._fset(other, up=False)
|
|
1536
1654
|
|
|
@@ -1546,8 +1664,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1546
1664
|
|
|
1547
1665
|
@see: Method L{Fsum.fadd_} for further details.
|
|
1548
1666
|
'''
|
|
1549
|
-
return self.
|
|
1550
|
-
self.
|
|
1667
|
+
return self._facc_neg(xs, origin=1) if len(xs) != 1 else \
|
|
1668
|
+
self._fsub(xs[0], _sub_op_)
|
|
1551
1669
|
|
|
1552
1670
|
def _fsub(self, other, op):
|
|
1553
1671
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
@@ -1587,11 +1705,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1587
1705
|
|
|
1588
1706
|
@see: Methods L{Fsum.fsum}, L{Fsum.Fsum_} and L{Fsum.fsumf_}.
|
|
1589
1707
|
'''
|
|
1590
|
-
return self.
|
|
1591
|
-
|
|
1592
|
-
@property_RO
|
|
1593
|
-
def _Fsum(self): # like L{Fsum2Tuple._Fsum}, for C{_2floats}, .fstats
|
|
1594
|
-
return self # NOT @Property_RO, see .copy and ._copy_2
|
|
1708
|
+
return self._facc_args(xs)._fprs
|
|
1595
1709
|
|
|
1596
1710
|
def Fsum_(self, *xs, **name):
|
|
1597
1711
|
'''Like method L{Fsum.fsum_} but returning a named L{Fsum}.
|
|
@@ -1600,7 +1714,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1600
1714
|
|
|
1601
1715
|
@return: Copy of this updated instance (L{Fsum}).
|
|
1602
1716
|
'''
|
|
1603
|
-
return self.
|
|
1717
|
+
return self._facc_args(xs)._copy_2(self.Fsum_, **name)
|
|
1604
1718
|
|
|
1605
1719
|
def Fsum2Tuple_(self, *xs, **name):
|
|
1606
1720
|
'''Like method L{Fsum.fsum_} but returning a named L{Fsum2Tuple}.
|
|
@@ -1609,7 +1723,27 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1609
1723
|
|
|
1610
1724
|
@return: Precision running sum (L{Fsum2Tuple}).
|
|
1611
1725
|
'''
|
|
1612
|
-
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)
|
|
1613
1747
|
|
|
1614
1748
|
def fsum2(self, xs=(), **name):
|
|
1615
1749
|
'''Add an iterable's items, summate and return the
|
|
@@ -1643,7 +1777,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1643
1777
|
|
|
1644
1778
|
@see: Methods L{Fsum.fsum_} and L{Fsum.fsum}.
|
|
1645
1779
|
'''
|
|
1646
|
-
return self._fsum2(xs, self.
|
|
1780
|
+
return self._fsum2(xs, self._facc_args)
|
|
1647
1781
|
|
|
1648
1782
|
def _fsum2(self, xs, _facc, **origin):
|
|
1649
1783
|
'''(INTERNAL) Helper for L{Fsum.fsum2_} and L{Fsum.fsum2f_}.
|
|
@@ -1651,7 +1785,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1651
1785
|
p, q = self._fprs2
|
|
1652
1786
|
if xs:
|
|
1653
1787
|
s, r = _facc(xs, **origin)._fprs2
|
|
1654
|
-
|
|
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)
|
|
1655
1792
|
else:
|
|
1656
1793
|
return p, _0_0
|
|
1657
1794
|
|
|
@@ -1716,8 +1853,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1716
1853
|
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1717
1854
|
B{C{RESIDUAL}}.
|
|
1718
1855
|
|
|
1719
|
-
@see: Methods L{Fsum.fint}, L{Fsum.fint2}, L{Fsum.
|
|
1720
|
-
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}.
|
|
1721
1858
|
'''
|
|
1722
1859
|
s, r = self._fint2
|
|
1723
1860
|
if r:
|
|
@@ -1736,27 +1873,38 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1736
1873
|
'''
|
|
1737
1874
|
return self.residual is INT0
|
|
1738
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
|
+
|
|
1739
1883
|
def is_integer(self):
|
|
1740
1884
|
'''Is this instance' running sum C{integer}? (C{bool}).
|
|
1741
1885
|
|
|
1742
1886
|
@see: Methods L{Fsum.fint}, L{Fsum.fint2} and L{Fsum.is_scalar}.
|
|
1743
1887
|
'''
|
|
1744
|
-
|
|
1745
|
-
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
|
|
1746
1899
|
|
|
1747
1900
|
def is_math_fsum(self):
|
|
1748
|
-
'''
|
|
1749
|
-
L{fsum1_}
|
|
1750
|
-
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}?
|
|
1751
1903
|
|
|
1752
|
-
@return: C{
|
|
1753
|
-
|
|
1754
|
-
the functions are based on C{math.fsum} (and
|
|
1755
|
-
partials summation is not) or C{False} if
|
|
1756
|
-
none are.
|
|
1904
|
+
@return: C{True} if summation functions use C{math.fsum}, C{False}
|
|
1905
|
+
otherwise.
|
|
1757
1906
|
'''
|
|
1758
|
-
|
|
1759
|
-
return 2 if _psum is f else bool(f)
|
|
1907
|
+
return _sum is _fsum # _fsum.__module__ is fabs.__module__
|
|
1760
1908
|
|
|
1761
1909
|
def is_scalar(self, **raiser_RESIDUAL):
|
|
1762
1910
|
'''Is this instance' running sum C{scalar} without residual or with
|
|
@@ -1788,6 +1936,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1788
1936
|
f = _0_0
|
|
1789
1937
|
return f
|
|
1790
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
|
+
|
|
1791
1947
|
def _mul_scalar(self, factor, op): # in .fmath.Fhorner
|
|
1792
1948
|
'''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum}, C{0.0} or C{self}.
|
|
1793
1949
|
'''
|
|
@@ -1811,6 +1967,67 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1811
1967
|
'''
|
|
1812
1968
|
return _Psum(self._ps_neg) if self._ps else NEG0
|
|
1813
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
|
+
|
|
1814
2031
|
@property_RO
|
|
1815
2032
|
def partials(self):
|
|
1816
2033
|
'''Get this instance' current, partial sums (C{tuple} of C{float}s).
|
|
@@ -1820,7 +2037,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1820
2037
|
def pow(self, x, *mod, **raiser_RESIDUAL):
|
|
1821
2038
|
'''Return C{B{self}**B{x}} as L{Fsum}.
|
|
1822
2039
|
|
|
1823
|
-
@arg x: The exponent (C{scalar}
|
|
2040
|
+
@arg x: The exponent (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
1824
2041
|
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
1825
2042
|
C{pow(B{self}, B{other}, B{mod})} version.
|
|
1826
2043
|
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
|
|
@@ -1907,7 +2124,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1907
2124
|
_mul_Fsum = Fsum._mul_Fsum
|
|
1908
2125
|
if x > 4:
|
|
1909
2126
|
p = self
|
|
1910
|
-
f = self if (x & 1) else
|
|
2127
|
+
f = self if (x & 1) else self._Fsum_as(_1_0)
|
|
1911
2128
|
m = x >> 1 # // 2
|
|
1912
2129
|
while m:
|
|
1913
2130
|
p = _mul_Fsum(p, p, op) # p **= 2
|
|
@@ -1945,14 +2162,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1945
2162
|
if _isFsum(f):
|
|
1946
2163
|
s, r = f._fprs2
|
|
1947
2164
|
if r:
|
|
1948
|
-
return _1_Over(f, op, **raiser_RESIDUAL)
|
|
2165
|
+
return self._1_Over(f, op, **raiser_RESIDUAL)
|
|
1949
2166
|
else: # scalar
|
|
1950
2167
|
s = f
|
|
1951
2168
|
# use s**(-1) to get the CPython
|
|
1952
2169
|
# float_pow error iff s is zero
|
|
1953
2170
|
x = -1
|
|
1954
2171
|
elif x < 0: # self**(-1)
|
|
1955
|
-
return _1_Over(self, op, **raiser_RESIDUAL) # 1 / self
|
|
2172
|
+
return self._1_Over(self, op, **raiser_RESIDUAL) # 1 / self
|
|
1956
2173
|
else: # self**1 or self**0
|
|
1957
2174
|
return self._pow_0_1(x, other) # self, 1 or 1.0
|
|
1958
2175
|
else: # self**fractional
|
|
@@ -1971,12 +2188,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1971
2188
|
'''
|
|
1972
2189
|
n = 0
|
|
1973
2190
|
_2s = _2sum
|
|
2191
|
+
_fi = self._isfine
|
|
1974
2192
|
for x in (tuple(xs) if xs is ps else xs):
|
|
1975
|
-
# assert isscalar(x) and
|
|
2193
|
+
# assert isscalar(x) and _isOK_or_finite(x, **self._isfine)
|
|
1976
2194
|
if x:
|
|
1977
2195
|
i = 0
|
|
1978
2196
|
for p in ps:
|
|
1979
|
-
x, p = _2s(x, p)
|
|
2197
|
+
x, p = _2s(x, p, **_fi)
|
|
1980
2198
|
if p:
|
|
1981
2199
|
ps[i] = p
|
|
1982
2200
|
i += 1
|
|
@@ -1984,6 +2202,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1984
2202
|
n += 1
|
|
1985
2203
|
if n:
|
|
1986
2204
|
self._n += n
|
|
2205
|
+
# if _fi: # collapse ps if non-finite
|
|
2206
|
+
# x = _sum(ps)
|
|
2207
|
+
# if not _isfinite(x):
|
|
2208
|
+
# ps[:] = x,
|
|
1987
2209
|
# Fsum._ps_max = max(Fsum._ps_max, len(ps))
|
|
1988
2210
|
if up:
|
|
1989
2211
|
self._update()
|
|
@@ -1993,22 +2215,23 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1993
2215
|
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1994
2216
|
each scalar C{factor} and accumulate into an C{Fsum}.
|
|
1995
2217
|
'''
|
|
1996
|
-
def
|
|
2218
|
+
def _psfs(ps, fs, _isfine=_isfinite):
|
|
1997
2219
|
if len(ps) < len(fs):
|
|
1998
2220
|
ps, fs = fs, ps
|
|
1999
2221
|
if self._f2product:
|
|
2000
|
-
ps =
|
|
2001
|
-
|
|
2222
|
+
ps = _2split3s(ps)
|
|
2223
|
+
_fps = _2products
|
|
2002
2224
|
else:
|
|
2003
|
-
def
|
|
2004
|
-
return (
|
|
2225
|
+
def _fps(f, ps):
|
|
2226
|
+
return (f * p for p in ps)
|
|
2005
2227
|
|
|
2006
|
-
_fin = _isfinite
|
|
2007
2228
|
for f in fs:
|
|
2008
|
-
for p in
|
|
2009
|
-
yield p if
|
|
2229
|
+
for p in _fps(f, ps):
|
|
2230
|
+
yield p if _isfine(p) else self._finite(p, op)
|
|
2010
2231
|
|
|
2011
|
-
|
|
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)
|
|
2012
2235
|
|
|
2013
2236
|
@property_RO
|
|
2014
2237
|
def _ps_neg(self):
|
|
@@ -2018,7 +2241,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2018
2241
|
yield -p
|
|
2019
2242
|
|
|
2020
2243
|
def _ps_other(self, op, *others):
|
|
2021
|
-
'''(INTERNAL) Yield
|
|
2244
|
+
'''(INTERNAL) Yield all C{other}s as C{scalar}.
|
|
2022
2245
|
'''
|
|
2023
2246
|
for other in others:
|
|
2024
2247
|
if _isFsumTuple(other):
|
|
@@ -2030,7 +2253,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2030
2253
|
def _ps_1sum(self, *less):
|
|
2031
2254
|
'''(INTERNAL) Return the partials sum, 1-primed C{less} some scalars.
|
|
2032
2255
|
'''
|
|
2033
|
-
def
|
|
2256
|
+
def _1psls(ps, ls):
|
|
2034
2257
|
yield _1_0
|
|
2035
2258
|
for p in ps:
|
|
2036
2259
|
yield p
|
|
@@ -2038,7 +2261,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2038
2261
|
yield -p
|
|
2039
2262
|
yield _N_1_0
|
|
2040
2263
|
|
|
2041
|
-
return _fsum(
|
|
2264
|
+
return _fsum(_1psls(self._ps, less))
|
|
2042
2265
|
|
|
2043
2266
|
def _raiser(self, r, s, raiser=True, **RESIDUAL):
|
|
2044
2267
|
'''(INTERNAL) Does ratio C{r / s} exceed the RESIDUAL threshold
|
|
@@ -2065,12 +2288,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2065
2288
|
and properties L{Fsum.ceil}, L{Fsum.floor},
|
|
2066
2289
|
L{Fsum.imag} and L{Fsum.residual}.
|
|
2067
2290
|
'''
|
|
2068
|
-
return float(self
|
|
2291
|
+
return float(self)
|
|
2069
2292
|
|
|
2070
2293
|
@property_RO
|
|
2071
2294
|
def residual(self):
|
|
2072
|
-
'''Get this instance' residual (C{float} or C{int}):
|
|
2073
|
-
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}.
|
|
2074
2297
|
|
|
2075
2298
|
@note: The C{residual is INT0} iff the precision running
|
|
2076
2299
|
C{fsum} is considered to be I{exact}.
|
|
@@ -2085,7 +2308,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2085
2308
|
|
|
2086
2309
|
@arg threshold: If C{scalar}, the I{ratio} to exceed for raising
|
|
2087
2310
|
L{ResidualError}s in division and exponention, if
|
|
2088
|
-
C{None} restore the default set with env variable
|
|
2311
|
+
C{None}, restore the default set with env variable
|
|
2089
2312
|
C{PYGEODESY_FSUM_RESIDUAL} or if omitted, keep the
|
|
2090
2313
|
current setting.
|
|
2091
2314
|
|
|
@@ -2095,11 +2318,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2095
2318
|
|
|
2096
2319
|
@note: L{ResidualError}s may be thrown if (1) the non-zero I{ratio}
|
|
2097
2320
|
C{residual / fsum} exceeds the given B{C{threshold}} and (2)
|
|
2098
|
-
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
|
|
2099
2322
|
C{fsum}, i.e. C{(fsum + residual) != fsum} and (4) optional
|
|
2100
2323
|
keyword argument C{raiser=False} is missing. Specify a
|
|
2101
2324
|
negative B{C{threshold}} for only non-zero C{residual}
|
|
2102
|
-
testing without I{significant}.
|
|
2325
|
+
testing without the I{significant} case.
|
|
2103
2326
|
'''
|
|
2104
2327
|
r = self._RESIDUAL
|
|
2105
2328
|
if threshold:
|
|
@@ -2122,9 +2345,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2122
2345
|
def root(self, root, **raiser_RESIDUAL):
|
|
2123
2346
|
'''Return C{B{self}**(1 / B{root})} as L{Fsum}.
|
|
2124
2347
|
|
|
2125
|
-
@arg root: The order (C{scalar} or L{
|
|
2126
|
-
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
|
|
2127
|
-
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}
|
|
2128
2351
|
to override the current L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
2129
2352
|
|
|
2130
2353
|
@return: The C{self ** (1 / B{root})} result (L{Fsum}).
|
|
@@ -2134,8 +2357,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2134
2357
|
|
|
2135
2358
|
@see: Method L{Fsum.pow}.
|
|
2136
2359
|
'''
|
|
2137
|
-
x = _1_Over(root, _truediv_op_, **raiser_RESIDUAL)
|
|
2138
|
-
f =
|
|
2360
|
+
x = self._1_Over(root, _truediv_op_, **raiser_RESIDUAL)
|
|
2361
|
+
f = self._copy_2(self.root)
|
|
2139
2362
|
return f._fpow(x, f.name, **raiser_RESIDUAL) # == pow(f, x)
|
|
2140
2363
|
|
|
2141
2364
|
def _scalar(self, other, op, **txt):
|
|
@@ -2204,23 +2427,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
2204
2427
|
|
|
2205
2428
|
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK see Fsum._update
|
|
2206
2429
|
|
|
2430
|
+
if _NONFINITES: # PYCHOK no cover
|
|
2431
|
+
_ = nonfiniterrors(False)
|
|
2432
|
+
|
|
2207
2433
|
|
|
2208
2434
|
def _Float_Int(arg, **name_Error):
|
|
2209
|
-
'''(INTERNAL)
|
|
2435
|
+
'''(INTERNAL) L{DivMod2Tuple}, L{Fsum2Tuple} Unit.
|
|
2210
2436
|
'''
|
|
2211
2437
|
U = Int if isint(arg) else Float
|
|
2212
2438
|
return U(arg, **name_Error)
|
|
2213
2439
|
|
|
2214
2440
|
|
|
2215
|
-
def Fsum2product(*xs, **name_RESIDUAL):
|
|
2216
|
-
'''Return an L{Fsum} with L{f2product<Fsum.f2product>} accurate
|
|
2217
|
-
multiplication I{turned on}.
|
|
2218
|
-
'''
|
|
2219
|
-
F = Fsum(*xs, **name_RESIDUAL)
|
|
2220
|
-
F.f2product(True)
|
|
2221
|
-
return F
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
2441
|
class DivMod2Tuple(_NamedTuple):
|
|
2225
2442
|
'''2-Tuple C{(div, mod)} with the quotient C{div} and remainder
|
|
2226
2443
|
C{mod} results of a C{divmod} operation.
|
|
@@ -2228,7 +2445,7 @@ class DivMod2Tuple(_NamedTuple):
|
|
|
2228
2445
|
@note: Quotient C{div} an C{int} in Python 3+ but a C{float}
|
|
2229
2446
|
in Python 2-. Remainder C{mod} an L{Fsum} instance.
|
|
2230
2447
|
'''
|
|
2231
|
-
_Names_ = (
|
|
2448
|
+
_Names_ = ('div', 'mod')
|
|
2232
2449
|
_Units_ = (_Float_Int, Fsum)
|
|
2233
2450
|
|
|
2234
2451
|
|
|
@@ -2302,17 +2519,23 @@ class Fsum2Tuple(_NamedTuple): # in .fstats
|
|
|
2302
2519
|
ps = (r, s) if r else (s,)
|
|
2303
2520
|
return _Psum(ps, name=self.name)
|
|
2304
2521
|
|
|
2305
|
-
def Fsum_(self, *xs, **
|
|
2522
|
+
def Fsum_(self, *xs, **name_f2product_nonfinites_RESIDUAL):
|
|
2306
2523
|
'''Return this C{Fsum2Tuple} as an L{Fsum} plus some C{xs}.
|
|
2307
2524
|
'''
|
|
2308
|
-
|
|
2309
|
-
return f._facc_1(xs, up=False) if xs else f
|
|
2525
|
+
return Fsum(self, *xs, **name_f2product_nonfinites_RESIDUAL)
|
|
2310
2526
|
|
|
2311
2527
|
def is_exact(self):
|
|
2312
2528
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
2313
2529
|
'''
|
|
2314
2530
|
return self._Fsum.is_exact()
|
|
2315
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
|
+
|
|
2316
2539
|
def is_integer(self):
|
|
2317
2540
|
'''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
|
|
2318
2541
|
'''
|
|
@@ -2373,105 +2596,142 @@ try:
|
|
|
2373
2596
|
del _fsum # nope, remove _fsum ...
|
|
2374
2597
|
raise ImportError() # ... use _fsum below
|
|
2375
2598
|
|
|
2376
|
-
|
|
2599
|
+
_sum = _fsum # in .elliptic
|
|
2377
2600
|
except ImportError:
|
|
2378
|
-
_sum =
|
|
2601
|
+
_sum = sum # in .elliptic
|
|
2379
2602
|
|
|
2380
2603
|
def _fsum(xs):
|
|
2381
2604
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
2382
2605
|
'''
|
|
2383
|
-
F = Fsum()
|
|
2384
|
-
F.
|
|
2385
|
-
return F._facc(xs, up=False)._fprs2.fsum
|
|
2606
|
+
F = Fsum(name=_fsum.name, nonfinites=True)
|
|
2607
|
+
return float(F._facc(xs, up=False))
|
|
2386
2608
|
|
|
2387
2609
|
|
|
2388
|
-
def fsum(xs, floats
|
|
2389
|
-
'''Precision floating point summation
|
|
2610
|
+
def fsum(xs, nonfinites=None, **floats):
|
|
2611
|
+
'''Precision floating point summation from Python's C{math.fsum}.
|
|
2390
2612
|
|
|
2391
|
-
@arg xs: Iterable of items to add (each C{scalar}
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
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.
|
|
2395
2620
|
|
|
2396
2621
|
@return: Precision C{fsum} (C{float}).
|
|
2397
2622
|
|
|
2398
|
-
@raise OverflowError:
|
|
2399
|
-
|
|
2400
|
-
@raise TypeError: Non-scalar B{C{xs}} item.
|
|
2623
|
+
@raise OverflowError: Infinite B{C{xs}} item or intermediate C{math.fsum} overflow.
|
|
2401
2624
|
|
|
2402
|
-
@raise
|
|
2625
|
+
@raise TypeError: Invalid B{C{xs}} item.
|
|
2403
2626
|
|
|
2404
|
-
@
|
|
2405
|
-
on Python's C{math.fsum}.
|
|
2627
|
+
@raise ValueError: Invalid or C{NAN} B{C{xs}} item.
|
|
2406
2628
|
|
|
2407
|
-
@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_}.
|
|
2408
2631
|
'''
|
|
2409
|
-
return
|
|
2632
|
+
return _xsum(fsum, xs, nonfinites=nonfinites, **floats) if xs else _0_0
|
|
2410
2633
|
|
|
2411
2634
|
|
|
2412
|
-
def fsum_(*xs, **
|
|
2635
|
+
def fsum_(*xs, **nonfinites):
|
|
2413
2636
|
'''Precision floating point summation of all positional items.
|
|
2414
2637
|
|
|
2415
|
-
@arg xs: Items to add (each C{scalar}
|
|
2416
|
-
|
|
2417
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
|
|
2418
|
-
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}).
|
|
2419
2640
|
|
|
2420
2641
|
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2421
2642
|
'''
|
|
2422
|
-
return
|
|
2423
|
-
_2floats(xs, origin=1)) if xs else _0_0 # PYCHOK yield
|
|
2643
|
+
return _xsum(fsum_, xs, origin=1, **nonfinites) if xs else _0_0
|
|
2424
2644
|
|
|
2425
2645
|
|
|
2426
2646
|
def fsumf_(*xs):
|
|
2427
|
-
'''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.
|
|
2428
2651
|
|
|
2429
2652
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2430
2653
|
'''
|
|
2431
|
-
return
|
|
2654
|
+
return _xsum(fsumf_, xs, nonfinites=True, origin=1) if xs else _0_0
|
|
2432
2655
|
|
|
2433
2656
|
|
|
2434
|
-
def fsum1(xs,
|
|
2657
|
+
def fsum1(xs, **nonfinites):
|
|
2435
2658
|
'''Precision floating point summation, 1-primed.
|
|
2436
2659
|
|
|
2437
|
-
@arg xs: Iterable of items to add (each C{scalar}
|
|
2438
|
-
|
|
2439
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
|
|
2440
|
-
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}).
|
|
2441
2662
|
|
|
2442
2663
|
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2443
2664
|
'''
|
|
2444
|
-
return
|
|
2665
|
+
return _xsum(fsum1, xs, primed=1, **nonfinites) if xs else _0_0
|
|
2445
2666
|
|
|
2446
2667
|
|
|
2447
|
-
def fsum1_(*xs, **
|
|
2448
|
-
'''Precision floating point summation
|
|
2668
|
+
def fsum1_(*xs, **nonfinites):
|
|
2669
|
+
'''Precision floating point summation of all positional items, 1-primed.
|
|
2449
2670
|
|
|
2450
|
-
@arg xs: Items to add (each C{scalar}
|
|
2451
|
-
|
|
2452
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
|
|
2453
|
-
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}).
|
|
2454
2673
|
|
|
2455
2674
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2456
2675
|
'''
|
|
2457
|
-
return
|
|
2458
|
-
_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
|
|
2459
2677
|
|
|
2460
2678
|
|
|
2461
2679
|
def fsum1f_(*xs):
|
|
2462
|
-
'''Precision floating point summation
|
|
2680
|
+
'''Precision floating point summation of all positional items, 1-primed and
|
|
2681
|
+
with I{non-finites} C{OK}.
|
|
2463
2682
|
|
|
2464
2683
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2465
2684
|
'''
|
|
2466
|
-
return
|
|
2685
|
+
return _xsum(fsum1f_, xs, nonfinites=True, primed=1) if xs else _0_0
|
|
2467
2686
|
|
|
2468
2687
|
|
|
2469
|
-
|
|
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))
|
|
2470
2706
|
|
|
2471
|
-
# usage: [env _psum=fsum] python3 -m pygeodesy.fsums
|
|
2472
2707
|
|
|
2473
|
-
|
|
2474
|
-
|
|
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
|
|
2475
2735
|
|
|
2476
2736
|
def _test(n):
|
|
2477
2737
|
# copied from Hettinger, see L{Fsum} reference
|