pygeodesy 24.9.24__py2.py3-none-any.whl → 24.10.10__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.24.dist-info → PyGeodesy-24.10.10.dist-info}/METADATA +10 -10
- {PyGeodesy-24.9.24.dist-info → PyGeodesy-24.10.10.dist-info}/RECORD +17 -17
- pygeodesy/__init__.py +10 -9
- pygeodesy/basics.py +5 -5
- pygeodesy/booleans.py +3 -4
- pygeodesy/constants.py +4 -2
- pygeodesy/ellipsoidalBaseDI.py +4 -4
- pygeodesy/errors.py +17 -4
- pygeodesy/fmath.py +193 -180
- pygeodesy/formy.py +2 -1
- pygeodesy/fstats.py +58 -60
- pygeodesy/fsums.py +474 -398
- pygeodesy/internals.py +1 -0
- pygeodesy/streprs.py +19 -9
- pygeodesy/vector3d.py +5 -5
- {PyGeodesy-24.9.24.dist-info → PyGeodesy-24.10.10.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.9.24.dist-info → PyGeodesy-24.10.10.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -40,14 +40,14 @@ results may differ from Python's C{math.fsum} results.
|
|
|
40
40
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
41
41
|
|
|
42
42
|
from pygeodesy.basics import isbool, iscomplex, isint, isscalar, \
|
|
43
|
-
_signOf, itemsorted, signOf, _xiterable
|
|
44
|
-
_xiterablen
|
|
43
|
+
_signOf, itemsorted, signOf, _xiterable
|
|
45
44
|
from pygeodesy.constants import INF, INT0, MANT_DIG, NEG0, NINF, _0_0, \
|
|
46
45
|
_1_0, _N_1_0, _isfinite, _pos_self, \
|
|
47
46
|
Float, Int
|
|
48
47
|
from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
|
|
49
|
-
_ValueError, _xError, _xError2,
|
|
50
|
-
|
|
48
|
+
_ValueError, _xError, _xError2, _xkwds, \
|
|
49
|
+
_xkwds_get, _xkwds_get1, _xkwds_not, \
|
|
50
|
+
_xkwds_pop, _xsError
|
|
51
51
|
from pygeodesy.internals import _enquote, _passarg
|
|
52
52
|
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DOT_, _from_, \
|
|
53
53
|
_not_finite_, _SPACE_, _std_, _UNDER_
|
|
@@ -64,7 +64,7 @@ from math import fabs, isinf, isnan, \
|
|
|
64
64
|
ceil as _ceil, floor as _floor # PYCHOK used! .ltp
|
|
65
65
|
|
|
66
66
|
__all__ = _ALL_LAZY.fsums
|
|
67
|
-
__version__ = '24.09
|
|
67
|
+
__version__ = '24.10.09'
|
|
68
68
|
|
|
69
69
|
from pygeodesy.interns import (
|
|
70
70
|
_PLUS_ as _add_op_, # in .auxilats.auxAngle
|
|
@@ -77,90 +77,62 @@ from pygeodesy.interns import (
|
|
|
77
77
|
_DASH_ as _sub_op_, # in .auxilats.auxAngle
|
|
78
78
|
_SLASH_ as _truediv_op_
|
|
79
79
|
)
|
|
80
|
-
_eq_op_ = _fset_op_ * 2 # _DEQUAL_
|
|
81
80
|
_floordiv_op_ = _truediv_op_ * 2 # _DSLASH_
|
|
82
81
|
_divmod_op_ = _floordiv_op_ + _mod_op_
|
|
83
82
|
_F2PRODUCT = _getenv('PYGEODESY_FSUM_F2PRODUCT', NN)
|
|
84
|
-
_ge_op_ = _gt_op_ + _fset_op_
|
|
85
83
|
_iadd_op_ = _add_op_ + _fset_op_ # in .auxilats.auxAngle, .fstats
|
|
86
84
|
_integer_ = 'integer'
|
|
87
85
|
_isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
|
|
88
|
-
|
|
89
|
-
_NONFINITES = _getenv('PYGEODESY_FSUM_NONFINITES', NN)
|
|
86
|
+
_NONFINITEr = _0_0 # NOT INT0!
|
|
87
|
+
_NONFINITES = _getenv('PYGEODESY_FSUM_NONFINITES', NN)
|
|
90
88
|
_non_zero_ = 'non-zero'
|
|
91
89
|
_pow_op_ = _mul_op_ * 2 # _DSTAR_
|
|
92
90
|
_RESIDUAL_0_0 = _getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)
|
|
93
91
|
_significant_ = 'significant'
|
|
94
|
-
_2split3s = _passarg
|
|
95
92
|
_threshold_ = 'threshold'
|
|
96
93
|
|
|
97
94
|
|
|
98
|
-
def _2finite(x): # in .fstats
|
|
95
|
+
def _2finite(x, _isfine=_isfinite): # in .fstats
|
|
99
96
|
'''(INTERNAL) return C{float(x)} if finite.
|
|
100
97
|
'''
|
|
101
|
-
return (float(x) if
|
|
98
|
+
return (float(x) if _isfine(x) # and isscalar(x)
|
|
102
99
|
else _nfError(x))
|
|
103
100
|
|
|
104
101
|
|
|
105
|
-
def _2float(index=None, _isfine=_isfinite, **
|
|
106
|
-
'''(INTERNAL) Raise C{TypeError} or C{ValueError} if not
|
|
102
|
+
def _2float(index=None, _isfine=_isfinite, **name_x): # in .fmath, .fstats
|
|
103
|
+
'''(INTERNAL) Raise C{TypeError} or C{Overflow-/ValueError} if not finite.
|
|
107
104
|
'''
|
|
108
|
-
n,
|
|
105
|
+
n, x = name_x.popitem() # _xkwds_item2(name_x)
|
|
109
106
|
try:
|
|
110
|
-
f = float(
|
|
111
|
-
return f if _isfine(f) else _nfError(
|
|
107
|
+
f = float(x)
|
|
108
|
+
return f if _isfine(f) else _nfError(x)
|
|
112
109
|
except Exception as X:
|
|
113
|
-
raise _xError(X, Fmt.INDEX(n, index),
|
|
110
|
+
raise _xError(X, Fmt.INDEX(n, index), x)
|
|
114
111
|
|
|
115
112
|
|
|
116
|
-
|
|
117
|
-
return X._ps
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def _2floats(xs, origin=0, _X=_X_ps, _x=float, _isfine=_isfinite):
|
|
121
|
-
'''(INTERNAL) Yield each B{C{xs}} as a C{float}.
|
|
122
|
-
'''
|
|
123
|
-
try:
|
|
124
|
-
i, x = origin, xs
|
|
125
|
-
_FsT = _Fsum_Fsum2Tuple_types
|
|
126
|
-
for x in _xiterable(xs):
|
|
127
|
-
if isinstance(x, _FsT):
|
|
128
|
-
for p in _X(x._Fsum):
|
|
129
|
-
yield p
|
|
130
|
-
else:
|
|
131
|
-
f = _x(x)
|
|
132
|
-
yield f if _isfine(f) else _nfError(f)
|
|
133
|
-
i += 1
|
|
134
|
-
except Exception as X:
|
|
135
|
-
raise _xsError(X, xs, i, x)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
try: # MCCABE 17
|
|
113
|
+
try: # MCCABE 26
|
|
139
114
|
from math import fma as _fma
|
|
140
|
-
except ImportError: # Python 3.12-
|
|
141
115
|
|
|
142
|
-
|
|
143
|
-
|
|
116
|
+
def _2products(x, ys, *zs):
|
|
117
|
+
# yield(x * y for y in ys) + yield(z in zs)
|
|
118
|
+
# TwoProductFMA U{Algorithm 3.5
|
|
119
|
+
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
120
|
+
for y in ys:
|
|
121
|
+
f = x * y
|
|
122
|
+
yield f
|
|
123
|
+
if _isfinite(f):
|
|
124
|
+
yield _fma(x, y, -f)
|
|
125
|
+
for z in zs:
|
|
126
|
+
yield z
|
|
144
127
|
|
|
145
|
-
|
|
146
|
-
|
|
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)
|
|
128
|
+
# _2split3 = \
|
|
129
|
+
_2split3s = _passarg # in Fsum.is_math_fma
|
|
151
130
|
|
|
152
|
-
|
|
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
|
|
131
|
+
except ImportError: # PYCHOK DSPACE! Python 3.12-
|
|
159
132
|
|
|
160
|
-
|
|
161
|
-
|
|
133
|
+
if _F2PRODUCT and _F2PRODUCT != _std_:
|
|
134
|
+
# backward to PyGeodesy 24.09.09, with _fmaX
|
|
162
135
|
|
|
163
|
-
else:
|
|
164
136
|
def _fma(*a_b_c): # PYCHOK no cover
|
|
165
137
|
# mimick C{math.fma} from Python 3.13+,
|
|
166
138
|
# the same accuracy, but ~14x slower
|
|
@@ -169,61 +141,75 @@ except ImportError: # Python 3.12-
|
|
|
169
141
|
n += da * db * nc
|
|
170
142
|
d = da * db * dc
|
|
171
143
|
try:
|
|
172
|
-
|
|
144
|
+
n, d = _n_d2(n, d)
|
|
145
|
+
r = float(n / d)
|
|
173
146
|
except OverflowError: # "integer division result too large ..."
|
|
174
147
|
r = NINF if (_signOf(n, 0) * _signOf(d, 0)) < 0 else INF
|
|
175
148
|
return r if _isfinite(r) else _fmaX(r, *a_b_c) # "overflow in fma"
|
|
176
149
|
|
|
177
|
-
def _2n_d(x):
|
|
150
|
+
def _2n_d(x): # PYCHOK no cover
|
|
178
151
|
try: # int.as_integer_ratio in 3.8+
|
|
179
152
|
return x.as_integer_ratio()
|
|
180
153
|
except (AttributeError, OverflowError, TypeError, ValueError):
|
|
181
154
|
return (x if isint(x) else float(x)), 1
|
|
155
|
+
else:
|
|
156
|
+
|
|
157
|
+
def _fma(a, b, c): # PYCHOK redef
|
|
158
|
+
# mimick C{math.fma} from Python 3.13+,
|
|
159
|
+
# the same accuracy, but ~13x slower
|
|
160
|
+
b3s = _2split3(b), # 1-tuple of 3-tuple
|
|
161
|
+
r = _fsum(_2products(a, b3s, c))
|
|
162
|
+
return r if _isfinite(r) else _fmaX(r, a, b, c)
|
|
163
|
+
|
|
164
|
+
_2n_d = None # redef
|
|
182
165
|
|
|
183
166
|
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
|
|
167
|
+
# raise a ValueError for a NAN result from non-NAN C{a_b_c}s or an
|
|
168
|
+
# OverflowError for a non-NAN non-finite from all finite C{a_b_c}s.
|
|
186
169
|
if isnan(r):
|
|
187
|
-
def
|
|
170
|
+
def _x(x):
|
|
188
171
|
return not isnan(x)
|
|
189
|
-
else:
|
|
190
|
-
|
|
191
|
-
if all(map(
|
|
172
|
+
else: # non-NAN non-finite
|
|
173
|
+
_x = _isfinite
|
|
174
|
+
if all(map(_x, a_b_c)):
|
|
192
175
|
raise _nfError(r, unstr(_fma, *a_b_c))
|
|
193
176
|
return r
|
|
194
177
|
|
|
195
|
-
|
|
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
|
|
178
|
+
def _2products(x, y3s, *zs): # PYCHOK in _fma, ...
|
|
179
|
+
# yield(x * y3 for y3 in y3s) + yield(z in zs)
|
|
208
180
|
# TwoProduct U{Algorithm 3.3
|
|
209
181
|
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
210
|
-
# also in Python 3.13+ C{Modules/
|
|
182
|
+
# also in Python 3.13+ C{Modules/mathmodule.c} under
|
|
211
183
|
# #ifndef UNRELIABLE_FMA ... #else ... #endif
|
|
212
184
|
_, a, b = _2split3(x)
|
|
213
185
|
for y, c, d in y3s:
|
|
214
186
|
y *= x
|
|
215
187
|
yield y
|
|
216
|
-
if
|
|
217
|
-
yield b * d - (((y - a * c) - b * c) - a * d)
|
|
218
|
-
#
|
|
219
|
-
#
|
|
220
|
-
#
|
|
221
|
-
else:
|
|
188
|
+
if _isfinite(y):
|
|
189
|
+
# yield b * d - (((y - a * c) - b * c) - a * d)
|
|
190
|
+
# = b * d + (a * d - ((y - a * c) - b * c))
|
|
191
|
+
# = b * d + (a * d + (b * c - (y - a * c)))
|
|
192
|
+
# = b * d + (a * d + (b * c + (a * c - y)))
|
|
222
193
|
yield a * c - y
|
|
223
194
|
yield b * c
|
|
224
195
|
if d:
|
|
225
196
|
yield a * d
|
|
226
197
|
yield b * d
|
|
198
|
+
for z in zs:
|
|
199
|
+
yield z
|
|
200
|
+
|
|
201
|
+
_2FACTOR = pow(2, (MANT_DIG + 1) // 2) + _1_0 # 134217729 if MANT_DIG == 53
|
|
202
|
+
|
|
203
|
+
def _2split3(x):
|
|
204
|
+
# Split U{Algorithm 3.2
|
|
205
|
+
# <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
|
|
206
|
+
a = c = x * _2FACTOR
|
|
207
|
+
a -= c - x
|
|
208
|
+
b = x - a
|
|
209
|
+
return x, a, b
|
|
210
|
+
|
|
211
|
+
def _2split3s(xs): # in Fsum.is_math_fma
|
|
212
|
+
return map(_2split3, xs)
|
|
227
213
|
|
|
228
214
|
|
|
229
215
|
def f2product(*two):
|
|
@@ -246,18 +232,18 @@ def f2product(*two):
|
|
|
246
232
|
|
|
247
233
|
|
|
248
234
|
def _Fsumf_(*xs): # in .auxLat, .ltp, ...
|
|
249
|
-
'''(INTERNAL) An C{Fsum}
|
|
235
|
+
'''(INTERNAL) An C{Fsum(xs)}, all C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
|
|
250
236
|
'''
|
|
251
|
-
return Fsum().
|
|
237
|
+
return Fsum()._facc_scalarf(xs, up=False)
|
|
252
238
|
|
|
253
239
|
|
|
254
240
|
def _Fsum1f_(*xs): # in .albers
|
|
255
|
-
'''(INTERNAL) An C{Fsum}
|
|
241
|
+
'''(INTERNAL) An C{Fsum(xs)}, all C{scalar}, an L{Fsum} or L{Fsum2Tuple}, 1-primed.
|
|
256
242
|
'''
|
|
257
|
-
return Fsum().
|
|
243
|
+
return Fsum()._facc_scalarf(_1primed(xs), origin=-1, up=False)
|
|
258
244
|
|
|
259
245
|
|
|
260
|
-
def
|
|
246
|
+
def _halfeven(s, r, p):
|
|
261
247
|
'''(INTERNAL) Round half-even.
|
|
262
248
|
'''
|
|
263
249
|
if (p > 0 and r > 0) or \
|
|
@@ -275,23 +261,44 @@ def _isFsum(x): # in .fmath
|
|
|
275
261
|
return isinstance(x, Fsum)
|
|
276
262
|
|
|
277
263
|
|
|
278
|
-
def
|
|
264
|
+
def _isFsum_2Tuple(x): # in .basics, .constants, .fmath, .fstats
|
|
279
265
|
'''(INTERNAL) Is C{x} an C{Fsum} or C{Fsum2Tuple} instance?
|
|
280
266
|
'''
|
|
281
|
-
return isinstance(x,
|
|
267
|
+
return isinstance(x, _Fsum_2Tuple_types)
|
|
282
268
|
|
|
283
269
|
|
|
284
270
|
def _isOK(unused):
|
|
285
|
-
'''(INTERNAL) Helper for C{
|
|
271
|
+
'''(INTERNAL) Helper for C{Fsum._fsum2} and C{Fsum.nonfinites}.
|
|
286
272
|
'''
|
|
287
273
|
return True
|
|
288
274
|
|
|
289
275
|
|
|
290
276
|
def _isOK_or_finite(x, _isfine=_isfinite):
|
|
291
|
-
'''(INTERNAL) Is C{x} finite or is I{non-finite} OK
|
|
277
|
+
'''(INTERNAL) Is C{x} finite or is I{non-finite} OK?
|
|
292
278
|
'''
|
|
293
279
|
# assert _isfine in (_isOK, _isfinite)
|
|
294
|
-
return _isfine(x)
|
|
280
|
+
return _isfine(x) # C{bool}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
try:
|
|
284
|
+
from math import gcd as _gcd
|
|
285
|
+
|
|
286
|
+
def _n_d2(n, d):
|
|
287
|
+
'''(INTERNAL) Reduce C{n} and C{d} by C{gcd}.
|
|
288
|
+
'''
|
|
289
|
+
if n and d:
|
|
290
|
+
try:
|
|
291
|
+
c = _gcd(n, d)
|
|
292
|
+
if c > 1:
|
|
293
|
+
n, d = (n // c), (d // c)
|
|
294
|
+
except TypeError: # non-int float
|
|
295
|
+
pass
|
|
296
|
+
return n, d
|
|
297
|
+
|
|
298
|
+
except ImportError: # 3.4-
|
|
299
|
+
|
|
300
|
+
def _n_d2(*n_d): # PYCHOK redef
|
|
301
|
+
return n_d
|
|
295
302
|
|
|
296
303
|
|
|
297
304
|
def _nfError(x, *args):
|
|
@@ -299,11 +306,18 @@ def _nfError(x, *args):
|
|
|
299
306
|
'''
|
|
300
307
|
E = _NonfiniteError(x)
|
|
301
308
|
t = Fmt.PARENSPACED(_not_finite_, x)
|
|
302
|
-
if args: # in
|
|
309
|
+
if args: # in _fmaX, _2sum
|
|
303
310
|
return E(txt=t, *args)
|
|
304
311
|
raise E(t, txt=None)
|
|
305
312
|
|
|
306
313
|
|
|
314
|
+
def _NonfiniteError(x):
|
|
315
|
+
'''(INTERNAL) Return the Error class for C{x}, I{non-finite}.
|
|
316
|
+
'''
|
|
317
|
+
return _OverflowError if isinf(x) else (
|
|
318
|
+
_ValueError if isnan(x) else _AssertionError)
|
|
319
|
+
|
|
320
|
+
|
|
307
321
|
def nonfiniterrors(*raiser):
|
|
308
322
|
'''Throw C{OverflowError} and C{ValueError} exceptions for or
|
|
309
323
|
handle I{non-finite} C{float}s as C{inf}, C{INF}, C{NINF},
|
|
@@ -321,14 +335,8 @@ def nonfiniterrors(*raiser):
|
|
|
321
335
|
d = Fsum._isfine
|
|
322
336
|
if raiser and raiser[0] is not None:
|
|
323
337
|
Fsum._isfine = {} if bool(raiser[0]) else Fsum._nonfinites_isfine_kwds[True]
|
|
324
|
-
return
|
|
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)
|
|
338
|
+
return (False if d is Fsum._nonfinites_isfine_kwds[True] else
|
|
339
|
+
_xkwds_get1(d, _isfine=_isfinite) is _isfinite) if d else True
|
|
332
340
|
|
|
333
341
|
|
|
334
342
|
def _1primed(xs): # in .fmath
|
|
@@ -354,13 +362,13 @@ def _psum(ps, **_isfine): # PYCHOK used!
|
|
|
354
362
|
if s:
|
|
355
363
|
ps[i:] = r, s
|
|
356
364
|
if i > 0:
|
|
357
|
-
s =
|
|
365
|
+
s = _halfeven(s, r, ps[i-1])
|
|
358
366
|
break # return s
|
|
359
367
|
s = r # PYCHOK no cover
|
|
360
368
|
elif not _isfinite(s): # non-finite OK
|
|
361
369
|
i = 0 # collapse ps
|
|
362
370
|
if ps:
|
|
363
|
-
s +=
|
|
371
|
+
s += sum(ps)
|
|
364
372
|
ps[i:] = s,
|
|
365
373
|
return s
|
|
366
374
|
|
|
@@ -381,14 +389,38 @@ def _Psum_(*ps, **name_f2product_nonfinites_RESIDUAL): # in .fmath
|
|
|
381
389
|
return _Psum(ps, **name_f2product_nonfinites_RESIDUAL)
|
|
382
390
|
|
|
383
391
|
|
|
384
|
-
def
|
|
392
|
+
def _residue(other):
|
|
393
|
+
'''(INTERNAL) Return the C{residual} or C{None} for C{scalar}.
|
|
394
|
+
'''
|
|
395
|
+
try:
|
|
396
|
+
r = other.residual
|
|
397
|
+
except AttributeError:
|
|
398
|
+
r = None # float, int, other
|
|
399
|
+
return r
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def _s_r(s, r):
|
|
403
|
+
'''(INTERNAL) Return C{(s, r)}, I{ordered}.
|
|
404
|
+
'''
|
|
405
|
+
if _isfinite(s):
|
|
406
|
+
if r:
|
|
407
|
+
if fabs(s) < fabs(r):
|
|
408
|
+
s, r = r, (s or INT0)
|
|
409
|
+
else:
|
|
410
|
+
r = INT0
|
|
411
|
+
else:
|
|
412
|
+
r = _NONFINITEr
|
|
413
|
+
return s, r
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def _2s_r(other):
|
|
385
417
|
'''(INTERNAL) Return 2-tuple C{(other, r)} with C{other} as C{int},
|
|
386
|
-
C{float} or C{as-is} and C{r} the residual of C{as-is}.
|
|
418
|
+
C{float} or C{as-is} and C{r} the residual of C{as-is} or 0.
|
|
387
419
|
'''
|
|
388
|
-
if
|
|
420
|
+
if _isFsum_2Tuple(other):
|
|
389
421
|
s, r = other._fint2
|
|
390
422
|
if r:
|
|
391
|
-
s, r = other.
|
|
423
|
+
s, r = other._nfprs2
|
|
392
424
|
if r: # PYCHOK no cover
|
|
393
425
|
s = other # L{Fsum} as-is
|
|
394
426
|
else:
|
|
@@ -399,17 +431,6 @@ def _2scalar2(other):
|
|
|
399
431
|
return s, r
|
|
400
432
|
|
|
401
433
|
|
|
402
|
-
def _s_r(s, r):
|
|
403
|
-
'''(INTERNAL) Return C{(s, r)}, I{ordered}.
|
|
404
|
-
'''
|
|
405
|
-
if r and _isfinite(s):
|
|
406
|
-
if fabs(s) < fabs(r):
|
|
407
|
-
s, r = r, (s or INT0)
|
|
408
|
-
else:
|
|
409
|
-
r = INT0
|
|
410
|
-
return s, r
|
|
411
|
-
|
|
412
|
-
|
|
413
434
|
def _strcomplex(s, *args):
|
|
414
435
|
'''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
|
|
415
436
|
'''
|
|
@@ -447,9 +468,9 @@ def _2sum(a, b, _isfine=_isfinite): # in .testFmath
|
|
|
447
468
|
else:
|
|
448
469
|
r = (a - s) + b
|
|
449
470
|
elif _isfine(s):
|
|
450
|
-
r =
|
|
471
|
+
r = _NONFINITEr
|
|
451
472
|
else: # non-finite and not OK
|
|
452
|
-
t =
|
|
473
|
+
t = unstr(_2sum, a, b)
|
|
453
474
|
raise _nfError(s, t)
|
|
454
475
|
return s, r
|
|
455
476
|
|
|
@@ -477,10 +498,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
477
498
|
i.e. any C{type} having method C{__float__}.
|
|
478
499
|
|
|
479
500
|
@note: Handling of I{non-finites} as C{inf}, C{INF}, C{NINF}, C{nan} and C{NAN} is
|
|
480
|
-
determined
|
|
481
|
-
by method L{nonfinites<Fsum.nonfinites>} for individual C{Fsum} instances,
|
|
482
|
-
overruling the
|
|
483
|
-
|
|
501
|
+
determined by function L{nonfiniterrors<fsums.nonfiniterrors>} for the default
|
|
502
|
+
and by method L{nonfinites<Fsum.nonfinites>} for individual C{Fsum} instances,
|
|
503
|
+
overruling the default. For backward compatibility, I{non-finites} raise
|
|
504
|
+
exceptions by default.
|
|
484
505
|
|
|
485
506
|
@see: U{Hettinger<https://GitHub.com/ActiveState/code/tree/master/recipes/Python/
|
|
486
507
|
393090_Binary_floating_point_summatiaccurate_full/recipe-393090.py>},
|
|
@@ -496,10 +517,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
496
517
|
C{PYGEODESY_FSUM_NONFINITES} and C{PYGEODESY_FSUM_RESIDUAL}.
|
|
497
518
|
'''
|
|
498
519
|
_f2product = _sys_version_info2 > (3, 12) or bool(_F2PRODUCT)
|
|
499
|
-
_isfine = {} # == _isfinite
|
|
520
|
+
_isfine = {} # == _isfinite, see nonfiniterrors()
|
|
500
521
|
_n = 0
|
|
501
522
|
# _ps = [] # partial sums
|
|
502
|
-
# _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps))
|
|
523
|
+
# _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps)) # 41
|
|
503
524
|
_RESIDUAL = _threshold(_RESIDUAL_0_0)
|
|
504
525
|
|
|
505
526
|
def __init__(self, *xs, **name_f2product_nonfinites_RESIDUAL):
|
|
@@ -537,14 +558,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
537
558
|
@see: Methods L{Fsum.fadd_} and L{Fsum.fadd}.
|
|
538
559
|
'''
|
|
539
560
|
f = self._copy_2(self.__add__)
|
|
540
|
-
return f._fadd(other
|
|
561
|
+
return f._fadd(other)
|
|
541
562
|
|
|
542
563
|
def __bool__(self): # PYCHOK Python 3+
|
|
543
564
|
'''Return C{bool(B{self})}, C{True} iff C{residual} is zero.
|
|
544
565
|
'''
|
|
545
|
-
s, r = self.
|
|
566
|
+
s, r = self._nfprs2
|
|
546
567
|
return bool(s or r) and s != -r # == self != 0
|
|
547
568
|
|
|
569
|
+
def __call__(self, other, **up): # in .fmath
|
|
570
|
+
'''Reset this C{Fsum} to C{other}, default C{B{up}=True}.
|
|
571
|
+
'''
|
|
572
|
+
self._ps[:] = 0, # clear for errors
|
|
573
|
+
self._fset(other, op=_fset_op_, **up)
|
|
574
|
+
return self
|
|
575
|
+
|
|
576
|
+
|
|
548
577
|
def __ceil__(self): # PYCHOK not special in Python 2-
|
|
549
578
|
'''Return this instance' C{math.ceil} as C{int} or C{float}.
|
|
550
579
|
|
|
@@ -586,7 +615,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
586
615
|
'''Return C{(B{self} == B{other})} as C{bool} where B{C{other}}
|
|
587
616
|
is C{scalar}, an other L{Fsum} or L{Fsum2Tuple}.
|
|
588
617
|
'''
|
|
589
|
-
return self._cmp_0(other,
|
|
618
|
+
return self._cmp_0(other, _fset_op_ + _fset_op_) == 0
|
|
590
619
|
|
|
591
620
|
def __float__(self):
|
|
592
621
|
'''Return this instance' current, precision running sum as C{float}.
|
|
@@ -623,7 +652,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
623
652
|
def __ge__(self, other):
|
|
624
653
|
'''Return C{(B{self} >= B{other})}, see C{__eq__}.
|
|
625
654
|
'''
|
|
626
|
-
return self._cmp_0(other,
|
|
655
|
+
return self._cmp_0(other, _gt_op_ + _fset_op_) >= 0
|
|
627
656
|
|
|
628
657
|
def __gt__(self, other):
|
|
629
658
|
'''Return C{(B{self} > B{other})}, see C{__eq__}.
|
|
@@ -651,7 +680,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
651
680
|
@see: Methods L{Fsum.fadd_} and L{Fsum.fadd}.
|
|
652
681
|
'''
|
|
653
682
|
try:
|
|
654
|
-
return self._fadd(other, _iadd_op_)
|
|
683
|
+
return self._fadd(other, op=_iadd_op_)
|
|
655
684
|
except TypeError:
|
|
656
685
|
pass
|
|
657
686
|
_xiterable(other)
|
|
@@ -811,7 +840,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
811
840
|
def __le__(self, other):
|
|
812
841
|
'''Return C{(B{self} <= B{other})}, see C{__eq__}.
|
|
813
842
|
'''
|
|
814
|
-
return self._cmp_0(other,
|
|
843
|
+
return self._cmp_0(other, _lt_op_ + _fset_op_) <= 0
|
|
815
844
|
|
|
816
845
|
def __len__(self):
|
|
817
846
|
'''Return the number of values accumulated (C{int}).
|
|
@@ -873,7 +902,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
873
902
|
@see: Method L{Fsum.__iadd__}.
|
|
874
903
|
'''
|
|
875
904
|
f = self._copy_2r(other, self.__radd__)
|
|
876
|
-
return f._fadd(self
|
|
905
|
+
return f._fadd(self)
|
|
877
906
|
|
|
878
907
|
def __rdivmod__(self, other):
|
|
879
908
|
'''Return C{divmod(B{other}, B{self})} as 2-tuple
|
|
@@ -1007,9 +1036,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1007
1036
|
'''
|
|
1008
1037
|
n, r = self._fint2
|
|
1009
1038
|
if r:
|
|
1010
|
-
i, d =
|
|
1011
|
-
n
|
|
1012
|
-
n += i
|
|
1039
|
+
i, d = float(r).as_integer_ratio()
|
|
1040
|
+
n, d = _n_d2(n * d + i, d)
|
|
1013
1041
|
else: # PYCHOK no cover
|
|
1014
1042
|
d = 1
|
|
1015
1043
|
return n, d
|
|
@@ -1019,7 +1047,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1019
1047
|
'''Get this instance I{as-is} (L{Fsum} with C{non-zero residual},
|
|
1020
1048
|
C{scalar} or I{non-finite}).
|
|
1021
1049
|
'''
|
|
1022
|
-
s, r = self.
|
|
1050
|
+
s, r = self._nfprs2
|
|
1023
1051
|
return self if r else s
|
|
1024
1052
|
|
|
1025
1053
|
@property_RO
|
|
@@ -1043,7 +1071,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1043
1071
|
def _cmp_0(self, other, op):
|
|
1044
1072
|
'''(INTERNAL) Return C{scalar(self - B{other})} for 0-comparison.
|
|
1045
1073
|
'''
|
|
1046
|
-
if
|
|
1074
|
+
if _isFsum_2Tuple(other):
|
|
1047
1075
|
s = self._ps_1sum(*other._ps)
|
|
1048
1076
|
elif self._scalar(other, op):
|
|
1049
1077
|
s = self._ps_1sum(other)
|
|
@@ -1066,6 +1094,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1066
1094
|
f._n = 1
|
|
1067
1095
|
# assert f._f2product == self._f2product
|
|
1068
1096
|
# assert f._Fsum is f
|
|
1097
|
+
# assert f._isfine is self._isfine
|
|
1098
|
+
# assert f._RESIDUAL is self._RESIDUAL
|
|
1069
1099
|
return f
|
|
1070
1100
|
|
|
1071
1101
|
def _copy_2(self, which, name=NN):
|
|
@@ -1078,6 +1108,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1078
1108
|
# assert f._n == self._n
|
|
1079
1109
|
# assert f._f2product == self._f2product
|
|
1080
1110
|
# assert f._Fsum is f
|
|
1111
|
+
# assert f._isfine is self._isfine
|
|
1112
|
+
# assert f._RESIDUAL is self._RESIDUAL
|
|
1081
1113
|
return f
|
|
1082
1114
|
|
|
1083
1115
|
def _copy_2r(self, other, which):
|
|
@@ -1091,7 +1123,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1091
1123
|
def _Error(self, op, other, Error, **txt_cause):
|
|
1092
1124
|
'''(INTERNAL) Format an B{C{Error}} for C{{self} B{op} B{other}}.
|
|
1093
1125
|
'''
|
|
1094
|
-
|
|
1126
|
+
# self.as_iscalar causes RecursionError for ._fprs2 errors
|
|
1127
|
+
s = _Psum(self._ps, nonfinites=True, name=self.name)
|
|
1128
|
+
return Error(_SPACE_(s.as_iscalar, op, other), **txt_cause)
|
|
1095
1129
|
|
|
1096
1130
|
def _ErrorX(self, X, op, other, *mod):
|
|
1097
1131
|
'''(INTERNAL) Format the caught exception C{X}.
|
|
@@ -1105,25 +1139,27 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1105
1139
|
'''(INTERNAL) Format the caught exception C{X}.
|
|
1106
1140
|
'''
|
|
1107
1141
|
E, t = _xError2(X)
|
|
1108
|
-
u = unstr(self.named3, *xs
|
|
1142
|
+
u = unstr(self.named3, *xs, _ELLIPSIS=4, **kwds)
|
|
1109
1143
|
return E(u, txt=t, cause=X)
|
|
1110
1144
|
|
|
1111
|
-
def _facc(self, xs, up=True, **
|
|
1112
|
-
'''(INTERNAL) Accumulate more C{
|
|
1145
|
+
def _facc(self, xs, up=True, **_X_x_origin):
|
|
1146
|
+
'''(INTERNAL) Accumulate more C{scalar}s or L{Fsum}s.
|
|
1113
1147
|
'''
|
|
1114
1148
|
if xs:
|
|
1115
|
-
kwds
|
|
1116
|
-
|
|
1149
|
+
kwds = self._isfine
|
|
1150
|
+
if _X_x_origin:
|
|
1151
|
+
kwds = _xkwds(_X_x_origin, **kwds)
|
|
1152
|
+
fs = _xs(xs, **kwds) # PYCHOK yield
|
|
1117
1153
|
ps = self._ps
|
|
1118
|
-
ps[:] = self._ps_acc(list(ps),
|
|
1154
|
+
ps[:] = self._ps_acc(list(ps), fs, up=up)
|
|
1119
1155
|
return self
|
|
1120
1156
|
|
|
1121
1157
|
def _facc_args(self, xs, **up):
|
|
1122
1158
|
'''(INTERNAL) Accumulate 0, 1 or more C{xs}, all positional
|
|
1123
1159
|
arguments in the caller of this method.
|
|
1124
1160
|
'''
|
|
1125
|
-
return self.
|
|
1126
|
-
self.
|
|
1161
|
+
return self._fadd(xs[0], **up) if len(xs) == 1 else \
|
|
1162
|
+
self._facc(xs, **up) # origin=1?
|
|
1127
1163
|
|
|
1128
1164
|
def _facc_neg(self, xs, **up_origin):
|
|
1129
1165
|
'''(INTERNAL) Accumulate more C{xs}, negated.
|
|
@@ -1141,7 +1177,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1141
1177
|
'''
|
|
1142
1178
|
def _Pow4(p):
|
|
1143
1179
|
r = 0
|
|
1144
|
-
if
|
|
1180
|
+
if _isFsum_2Tuple(p):
|
|
1145
1181
|
s, r = p._fprs2
|
|
1146
1182
|
if r:
|
|
1147
1183
|
m = Fsum._pow
|
|
@@ -1158,7 +1194,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1158
1194
|
_Pow, p, s, r = _Pow4(power)
|
|
1159
1195
|
if p: # and xs:
|
|
1160
1196
|
op = which.__name__
|
|
1161
|
-
_FsT =
|
|
1197
|
+
_FsT = _Fsum_2Tuple_types
|
|
1162
1198
|
_pow = self._pow_2_3
|
|
1163
1199
|
|
|
1164
1200
|
def _P(X):
|
|
@@ -1172,24 +1208,32 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1172
1208
|
f *= _pow(x, r, power, op, **raiser_RESIDUAL)
|
|
1173
1209
|
return f
|
|
1174
1210
|
|
|
1175
|
-
f = self._facc(xs,
|
|
1211
|
+
f = self._facc(xs, _X=_P, _x=_p) # origin=1?
|
|
1176
1212
|
else:
|
|
1177
1213
|
f = self._facc_scalar_(float(len(xs))) # x**0 == 1
|
|
1178
1214
|
return f
|
|
1179
1215
|
|
|
1180
1216
|
def _facc_scalar(self, xs, **up):
|
|
1181
|
-
'''(INTERNAL) Accumulate all C{xs},
|
|
1217
|
+
'''(INTERNAL) Accumulate all C{xs}, each C{scalar}.
|
|
1182
1218
|
'''
|
|
1183
1219
|
if xs:
|
|
1184
|
-
|
|
1220
|
+
ps = self._ps
|
|
1221
|
+
ps[:] = self._ps_acc(list(ps), xs, **up)
|
|
1185
1222
|
return self
|
|
1186
1223
|
|
|
1187
1224
|
def _facc_scalar_(self, *xs, **up):
|
|
1188
|
-
'''(INTERNAL) Accumulate all positional C{xs},
|
|
1225
|
+
'''(INTERNAL) Accumulate all positional C{xs}, each C{scalar}.
|
|
1189
1226
|
'''
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1227
|
+
return self._facc_scalar(xs, **up)
|
|
1228
|
+
|
|
1229
|
+
def _facc_scalarf(self, xs, up=True, **origin_which):
|
|
1230
|
+
'''(INTERNAL) Accumulate all C{xs}, each C{scalar}, an L{Fsum} or
|
|
1231
|
+
L{Fsum2Tuple}, like function C{_xsum}.
|
|
1232
|
+
'''
|
|
1233
|
+
_C = self.__class__
|
|
1234
|
+
fs = _xs(xs, **_x_isfine(self.nonfinitesOK, _Cdot=_C,
|
|
1235
|
+
**origin_which)) # PYCHOK yield
|
|
1236
|
+
return self._facc_scalar(fs, up=up)
|
|
1193
1237
|
|
|
1194
1238
|
# def _facc_up(self, up=True):
|
|
1195
1239
|
# '''(INTERNAL) Update the C{partials}, by removing
|
|
@@ -1208,8 +1252,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1208
1252
|
def fadd(self, xs=()):
|
|
1209
1253
|
'''Add an iterable's items to this instance.
|
|
1210
1254
|
|
|
1211
|
-
@arg xs: Iterable of items to add (each C{scalar}
|
|
1212
|
-
|
|
1255
|
+
@arg xs: Iterable of items to add (each C{scalar},
|
|
1256
|
+
an L{Fsum} or L{Fsum2Tuple}).
|
|
1213
1257
|
|
|
1214
1258
|
@return: This instance (L{Fsum}).
|
|
1215
1259
|
|
|
@@ -1219,7 +1263,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1219
1263
|
|
|
1220
1264
|
@raise ValueError: Invalid or I{non-finite} B{C{xs}} value.
|
|
1221
1265
|
'''
|
|
1222
|
-
if
|
|
1266
|
+
if _isFsum_2Tuple(xs):
|
|
1223
1267
|
self._facc_scalar(xs._ps)
|
|
1224
1268
|
elif isscalar(xs): # for backward compatibility # PYCHOK no cover
|
|
1225
1269
|
x = _2float(x=xs, **self._isfine)
|
|
@@ -1231,26 +1275,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1231
1275
|
def fadd_(self, *xs):
|
|
1232
1276
|
'''Add all positional items to this instance.
|
|
1233
1277
|
|
|
1234
|
-
@arg xs: Values to add (each C{scalar}
|
|
1235
|
-
or L{Fsum2Tuple}
|
|
1278
|
+
@arg xs: Values to add (each C{scalar}, an L{Fsum}
|
|
1279
|
+
or L{Fsum2Tuple}), all positional.
|
|
1236
1280
|
|
|
1237
1281
|
@see: Method L{Fsum.fadd} for further details.
|
|
1238
1282
|
'''
|
|
1239
1283
|
return self._facc_args(xs)
|
|
1240
1284
|
|
|
1241
|
-
def _fadd(self, other, op, **up):
|
|
1285
|
+
def _fadd(self, other, op=_add_op_, **up):
|
|
1242
1286
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
1243
1287
|
'''
|
|
1244
|
-
if
|
|
1245
|
-
|
|
1246
|
-
self._facc_scalar(other._ps, **up)
|
|
1247
|
-
else:
|
|
1248
|
-
self._fset(other, op=op, **up)
|
|
1288
|
+
if _isFsum_2Tuple(other):
|
|
1289
|
+
self._facc_scalar(other._ps, **up)
|
|
1249
1290
|
elif self._scalar(other, op):
|
|
1250
|
-
|
|
1251
|
-
self._facc_scalar_(other, **up)
|
|
1252
|
-
else:
|
|
1253
|
-
self._fset(other, op=op, **up)
|
|
1291
|
+
self._facc_scalar_(other, **up)
|
|
1254
1292
|
return self
|
|
1255
1293
|
|
|
1256
1294
|
fcopy = copy # for backward compatibility
|
|
@@ -1276,25 +1314,27 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1276
1314
|
# raise self._Error(op, other, _AssertionError, txt__=signOf)
|
|
1277
1315
|
return DivMod2Tuple(q, self) # q is C{int} in Python 3+, but C{float} in Python 2-
|
|
1278
1316
|
|
|
1279
|
-
def _fhorner(self, x, cs,
|
|
1317
|
+
def _fhorner(self, x, cs, where, incx=True): # in .fmath
|
|
1280
1318
|
'''(INTERNAL) Add an L{Fhorner} evaluation of polynomial
|
|
1281
1319
|
C{sum(cs[i] * B{x}**i for i=0..len(cs)-1) if B{incx}
|
|
1282
1320
|
else sum(... i=len(cs)-1..0)}.
|
|
1283
1321
|
'''
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
else
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
if len(cs) > 1 and x:
|
|
1322
|
+
# assert _xiterablen(cs)
|
|
1323
|
+
try:
|
|
1324
|
+
n = len(cs)
|
|
1325
|
+
H = self._Fsum_as(name__=self._fhorner)
|
|
1326
|
+
_m = H._mul_Fsum if _isFsum_2Tuple(x) else \
|
|
1327
|
+
H._mul_scalar
|
|
1328
|
+
if _2finite(x, **self._isfine) and n > 1:
|
|
1292
1329
|
for c in (reversed(cs) if incx else cs):
|
|
1293
|
-
H.
|
|
1294
|
-
H._fadd(c,
|
|
1330
|
+
H._fset(_m(x, _mul_op_), up=False)
|
|
1331
|
+
H._fadd(c, up=False)
|
|
1295
1332
|
else: # x == 0
|
|
1296
|
-
H = cs[0] if
|
|
1297
|
-
self._fadd(H
|
|
1333
|
+
H = cs[0] if n else 0
|
|
1334
|
+
self._fadd(H)
|
|
1335
|
+
except Exception as X:
|
|
1336
|
+
t = unstr(where, x, *cs, _ELLIPSIS=4, incx=incx)
|
|
1337
|
+
raise self._ErrorX(X, _add_op_, t)
|
|
1298
1338
|
return self
|
|
1299
1339
|
|
|
1300
1340
|
def _finite(self, other, op=None):
|
|
@@ -1346,36 +1386,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1346
1386
|
def _fint2(self): # see ._fset
|
|
1347
1387
|
'''(INTERNAL) Get 2-tuple (C{int}, I{integer} residual).
|
|
1348
1388
|
'''
|
|
1349
|
-
s,
|
|
1350
|
-
|
|
1389
|
+
s, r = self._nfprs2
|
|
1390
|
+
if _isfinite(s):
|
|
1351
1391
|
i = int(s)
|
|
1352
1392
|
r = (self._ps_1sum(i) if len(self._ps) > 1 else
|
|
1353
1393
|
float(s - i)) or INT0
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1394
|
+
else: # INF, NAN, NINF
|
|
1395
|
+
i = float(s)
|
|
1396
|
+
# r = _NONFINITEr
|
|
1357
1397
|
return i, r # Fsum2Tuple?
|
|
1358
1398
|
|
|
1359
1399
|
@_fint2.setter_ # PYCHOK setter_UNDERscore!
|
|
1360
1400
|
def _fint2(self, s): # in _fset
|
|
1361
1401
|
'''(INTERNAL) Replace the C{_fint2} value.
|
|
1362
1402
|
'''
|
|
1363
|
-
|
|
1403
|
+
if _isfinite(s):
|
|
1364
1404
|
i = int(s)
|
|
1365
1405
|
r = (s - i) or INT0
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1406
|
+
else: # INF, NAN, NINF
|
|
1407
|
+
i = float(s)
|
|
1408
|
+
r = _NONFINITEr
|
|
1369
1409
|
return i, r # like _fint2.getter
|
|
1370
1410
|
|
|
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)
|
|
1378
|
-
|
|
1379
1411
|
@deprecated_property_RO
|
|
1380
1412
|
def float_int(self): # PYCHOK no cover
|
|
1381
1413
|
'''DEPRECATED, use method C{Fsum.int_float}.'''
|
|
@@ -1406,31 +1438,35 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1406
1438
|
q = self._ftruediv(other, op, **raiser_RESIDUAL) # == self
|
|
1407
1439
|
return self._fset(q.floor) # floor(q)
|
|
1408
1440
|
|
|
1409
|
-
def fma(self, other1, other2,
|
|
1441
|
+
def fma(self, other1, other2, **nonfinites): # in .fmath.fma
|
|
1410
1442
|
'''Fused-multiply-add C{self *= B{other1}; self += B{other2}}.
|
|
1411
1443
|
|
|
1412
1444
|
@arg other1: Multiplier (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
1413
1445
|
@arg other2: Addend (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
1414
|
-
@kwarg
|
|
1415
|
-
|
|
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}.
|
|
1446
|
+
@kwarg nonfinites: Use C{B{nonfinites}=True} or C{False}, to
|
|
1447
|
+
override L{nonfinites<Fsum.nonfinites>} and
|
|
1448
|
+
L{nonfiniterrors} default (C{bool}).
|
|
1419
1449
|
'''
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1450
|
+
op = self.fma.__name__
|
|
1451
|
+
_fs = self._ps_other
|
|
1452
|
+
try:
|
|
1453
|
+
s, r = self._fprs2
|
|
1454
|
+
if r:
|
|
1455
|
+
f = self._f2mul(self.fma, other1, **nonfinites)
|
|
1456
|
+
f += other2
|
|
1457
|
+
elif _residue(other1) or _residue(other2):
|
|
1458
|
+
fs = _2split3s(_fs(op, other1))
|
|
1459
|
+
fs = _2products(s, fs, *_fs(op, other2))
|
|
1460
|
+
f = _Psum(self._ps_acc([], fs, up=False), name=op)
|
|
1461
|
+
else:
|
|
1462
|
+
f = _fma(s, other1, other2)
|
|
1463
|
+
f = _2finite(f, **self._isfine)
|
|
1464
|
+
except TypeError as X:
|
|
1465
|
+
raise self._ErrorX(X, op, (other1, other2))
|
|
1466
|
+
except (OverflowError, ValueError) as X: # from math.fma
|
|
1467
|
+
f = self._mul_reduce(s, other1) # INF, NAN, NINF
|
|
1468
|
+
f += sum(_fs(op, other2))
|
|
1469
|
+
f = self._nonfiniteX(X, op, f, **nonfinites)
|
|
1434
1470
|
return self._fset(f)
|
|
1435
1471
|
|
|
1436
1472
|
fmul = __imul__
|
|
@@ -1438,11 +1474,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1438
1474
|
def _fmul(self, other, op):
|
|
1439
1475
|
'''(INTERNAL) Apply C{B{self} *= B{other}}.
|
|
1440
1476
|
'''
|
|
1441
|
-
if
|
|
1477
|
+
if _isFsum_2Tuple(other):
|
|
1442
1478
|
if len(self._ps) != 1:
|
|
1443
1479
|
f = self._mul_Fsum(other, op)
|
|
1444
1480
|
elif len(other._ps) != 1: # and len(self._ps) == 1
|
|
1445
|
-
f = self._ps_mul(op, *other._ps)
|
|
1481
|
+
f = self._ps_mul(op, *other._ps) if other._ps else _0_0
|
|
1446
1482
|
elif self._f2product: # len(other._ps) == 1
|
|
1447
1483
|
f = self._mul_scalar(other._ps[0], op)
|
|
1448
1484
|
else: # len(other._ps) == len(self._ps) == 1
|
|
@@ -1457,39 +1493,41 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1457
1493
|
'''DEPRECATED on 2024.09.13, use method L{f2mul_<Fsum.f2mul_>}.'''
|
|
1458
1494
|
return self._fset(self.f2mul_(*others, **raiser))
|
|
1459
1495
|
|
|
1460
|
-
def f2mul_(self, *others, **
|
|
1496
|
+
def f2mul_(self, *others, **nonfinites): # in .fmath.f2mul
|
|
1461
1497
|
'''Return C{B{self} * B{other} * B{other} ...} for all B{C{others}} using cascaded,
|
|
1462
1498
|
accurate multiplication like with L{f2product<Fsum.f2product>} set to C{True}.
|
|
1463
1499
|
|
|
1464
1500
|
@arg others: Multipliers (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
|
|
1465
1501
|
positional.
|
|
1466
|
-
@kwarg
|
|
1467
|
-
|
|
1502
|
+
@kwarg nonfinites: Use C{B{nonfinites}=True} or C{False}, to override both
|
|
1503
|
+
L{nonfinites<Fsum.nonfinites>} and the L{nonfiniterrors}
|
|
1504
|
+
default (C{bool}).
|
|
1468
1505
|
|
|
1469
1506
|
@return: The cascaded I{TwoProduct} (L{Fsum} or C{float}).
|
|
1470
1507
|
|
|
1471
1508
|
@see: U{Equations 2.3<https://www.TUHH.De/ti3/paper/rump/OzOgRuOi06.pdf>}
|
|
1472
1509
|
'''
|
|
1473
|
-
return self._f2mul(self.f2mul_, *others, **
|
|
1510
|
+
return self._f2mul(self.f2mul_, *others, **nonfinites)
|
|
1474
1511
|
|
|
1475
|
-
def _f2mul(self, where, *others, **
|
|
1512
|
+
def _f2mul(self, where, *others, **nonfinites_raiser):
|
|
1476
1513
|
'''(INTERNAL) See methods C{fma} and C{f2mul_}.
|
|
1477
1514
|
'''
|
|
1478
|
-
f
|
|
1479
|
-
|
|
1515
|
+
f = self._copy_2(where)
|
|
1516
|
+
ps = f._ps
|
|
1517
|
+
if ps and others:
|
|
1480
1518
|
op = where.__name__
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
for p in self._ps_other(op, *others):
|
|
1519
|
+
try:
|
|
1520
|
+
for other in others: # to pinpoint errors
|
|
1521
|
+
for p in self._ps_other(op, other):
|
|
1485
1522
|
pfs = _2products(p, _2split3s(ps))
|
|
1486
1523
|
ps[:] = f._ps_acc([], pfs, up=False)
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1524
|
+
f._update()
|
|
1525
|
+
except TypeError as X:
|
|
1526
|
+
raise self._ErrorX(X, op, other)
|
|
1527
|
+
except (OverflowError, ValueError) as X:
|
|
1528
|
+
r = self._mul_reduce(sum(ps), other) # INF, NAN, NINF
|
|
1529
|
+
r = self._nonfiniteX(X, op, r, **nonfinites_raiser)
|
|
1530
|
+
f._fset(r)
|
|
1493
1531
|
return f
|
|
1494
1532
|
|
|
1495
1533
|
def fover(self, over, **raiser_RESIDUAL):
|
|
@@ -1520,7 +1558,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1520
1558
|
elif self.is_integer():
|
|
1521
1559
|
# return an exact C{int} for C{int}**C{int}
|
|
1522
1560
|
i, _ = self._fint2 # assert _ == 0
|
|
1523
|
-
x, r =
|
|
1561
|
+
x, r = _2s_r(other) # C{int}, C{float} or other
|
|
1524
1562
|
f = self._Fsum_as(i)._pow_Fsum(other, op, **raiser_RESIDUAL) if r else \
|
|
1525
1563
|
self._pow_2_3(i, x, other, op, **raiser_RESIDUAL)
|
|
1526
1564
|
else: # mod[0] is None, power(self, other)
|
|
@@ -1531,8 +1569,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1531
1569
|
|
|
1532
1570
|
def f2product(self, *two):
|
|
1533
1571
|
'''Get and set accurate I{TwoProduct} multiplication for this
|
|
1534
|
-
L{Fsum},
|
|
1535
|
-
L{f2product<fsums.f2product>}.
|
|
1572
|
+
L{Fsum}, overriding the L{f2product} default.
|
|
1536
1573
|
|
|
1537
1574
|
@arg two: If omitted, leave the override unchanged, if C{True},
|
|
1538
1575
|
turn I{TwoProduct} on, if C{False} off, if C{None}e
|
|
@@ -1564,7 +1601,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1564
1601
|
s, _ = self._fprs2
|
|
1565
1602
|
return s # ._fprs2.fsum
|
|
1566
1603
|
|
|
1567
|
-
@_fprs.setter_ # PYCHOK
|
|
1604
|
+
@_fprs.setter_ # PYCHOK setter_UNDERscore!
|
|
1568
1605
|
def _fprs(self, s):
|
|
1569
1606
|
'''(INTERNAL) Replace the C{_fprs} value.
|
|
1570
1607
|
'''
|
|
@@ -1576,30 +1613,37 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1576
1613
|
running sum and residual (L{Fsum2Tuple}).
|
|
1577
1614
|
'''
|
|
1578
1615
|
ps = self._ps
|
|
1616
|
+
n = len(ps)
|
|
1579
1617
|
try:
|
|
1580
|
-
n
|
|
1581
|
-
if n > 0: # len(ps) > 2
|
|
1618
|
+
if n > 2:
|
|
1582
1619
|
s = _psum(ps, **self._isfine)
|
|
1583
|
-
|
|
1584
|
-
|
|
1620
|
+
if not _isfinite(s):
|
|
1621
|
+
ps[:] = s, # collapse ps
|
|
1622
|
+
return Fsum2Tuple(s, _NONFINITEr)
|
|
1623
|
+
n = len(ps)
|
|
1624
|
+
# Fsum._ps_max = max(Fsum._ps_max, n)
|
|
1625
|
+
if n > 2:
|
|
1585
1626
|
r = self._ps_1sum(s)
|
|
1586
1627
|
return Fsum2Tuple(*_s_r(s, r))
|
|
1587
|
-
if n
|
|
1628
|
+
if n > 1: # len(ps) == 2
|
|
1588
1629
|
s, r = _s_r(*_2sum(*ps, **self._isfine))
|
|
1589
1630
|
ps[:] = (r, s) if r else (s,)
|
|
1590
1631
|
elif ps: # len(ps) == 1
|
|
1591
|
-
s
|
|
1632
|
+
s = ps[0]
|
|
1633
|
+
r = INT0 if _isfinite(s) else _NONFINITEr
|
|
1592
1634
|
else: # len(ps) == 0
|
|
1593
|
-
s
|
|
1635
|
+
s = _0_0
|
|
1636
|
+
r = INT0 if _isfinite(s) else _NONFINITEr
|
|
1594
1637
|
ps[:] = s,
|
|
1595
1638
|
except (OverflowError, ValueError) as X:
|
|
1596
|
-
op =
|
|
1597
|
-
|
|
1598
|
-
|
|
1639
|
+
op = _fset_op_ # INF, NAN, NINF
|
|
1640
|
+
ps[:] = sum(ps), # collapse ps
|
|
1641
|
+
s = self._nonfiniteX(X, op, ps[0])
|
|
1642
|
+
r = _NONFINITEr
|
|
1599
1643
|
# assert self._ps is ps
|
|
1600
1644
|
return Fsum2Tuple(s, r)
|
|
1601
1645
|
|
|
1602
|
-
@_fprs2.setter_ # PYCHOK
|
|
1646
|
+
@_fprs2.setter_ # PYCHOK setter_UNDERscore!
|
|
1603
1647
|
def _fprs2(self, s_r):
|
|
1604
1648
|
'''(INTERNAL) Replace the C{_fprs2} value.
|
|
1605
1649
|
'''
|
|
@@ -1616,15 +1660,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1616
1660
|
|
|
1617
1661
|
@see: Method L{Fsum.fadd} for further details.
|
|
1618
1662
|
'''
|
|
1619
|
-
|
|
1620
|
-
|
|
1663
|
+
f = (xs[0] if xs else _0_0) if len(xs) < 2 else \
|
|
1664
|
+
Fsum(*xs, nonfinites=self.nonfinites()) # self._Fsum_as(*xs)
|
|
1665
|
+
return self._fset(f, op=_fset_op_)
|
|
1621
1666
|
|
|
1622
1667
|
def _fset(self, other, n=0, up=True, **op):
|
|
1623
1668
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
1624
1669
|
'''
|
|
1625
1670
|
if other is self:
|
|
1626
1671
|
pass # from ._fmul, ._ftruediv and ._pow_0_1
|
|
1627
|
-
elif
|
|
1672
|
+
elif _isFsum_2Tuple(other):
|
|
1673
|
+
if op: # and not self.nonfinitesOK:
|
|
1674
|
+
self._finite(other._fprs, **op)
|
|
1628
1675
|
self._ps[:] = other._ps
|
|
1629
1676
|
self._n = n or other._n
|
|
1630
1677
|
if up: # use or zap the C{Property_RO} values
|
|
@@ -1647,11 +1694,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1647
1694
|
raise self._Error(op, other, _TypeError)
|
|
1648
1695
|
return self
|
|
1649
1696
|
|
|
1650
|
-
def _fset_ps(self, other): # in .fmath._Fsum__init__
|
|
1651
|
-
'''(INTERNAL) Set partials from a known C{other}.
|
|
1652
|
-
'''
|
|
1653
|
-
return self._fset(other, up=False)
|
|
1654
|
-
|
|
1655
1697
|
def fsub(self, xs=()):
|
|
1656
1698
|
'''Subtract an iterable's items from this instance.
|
|
1657
1699
|
|
|
@@ -1664,13 +1706,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1664
1706
|
|
|
1665
1707
|
@see: Method L{Fsum.fadd_} for further details.
|
|
1666
1708
|
'''
|
|
1667
|
-
return self.
|
|
1668
|
-
self.
|
|
1709
|
+
return self._fsub(xs[0], _sub_op_) if len(xs) == 1 else \
|
|
1710
|
+
self._facc_neg(xs) # origin=1?
|
|
1669
1711
|
|
|
1670
1712
|
def _fsub(self, other, op):
|
|
1671
1713
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
1672
1714
|
'''
|
|
1673
|
-
if
|
|
1715
|
+
if _isFsum_2Tuple(other):
|
|
1674
1716
|
if other is self: # or other._fprs2 == self._fprs2:
|
|
1675
1717
|
self._fset(_0_0, n=len(self) * 2)
|
|
1676
1718
|
elif other._ps:
|
|
@@ -1680,11 +1722,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1680
1722
|
return self
|
|
1681
1723
|
|
|
1682
1724
|
def fsum(self, xs=()):
|
|
1683
|
-
'''Add an iterable's items, summate and return the
|
|
1684
|
-
|
|
1725
|
+
'''Add an iterable's items, summate and return the current
|
|
1726
|
+
precision running sum.
|
|
1685
1727
|
|
|
1686
|
-
@arg xs: Iterable of items to add (each item C{scalar}
|
|
1687
|
-
|
|
1728
|
+
@arg xs: Iterable of items to add (each item C{scalar},
|
|
1729
|
+
an L{Fsum} or L{Fsum2Tuple}).
|
|
1688
1730
|
|
|
1689
1731
|
@return: Precision running sum (C{float} or C{int}).
|
|
1690
1732
|
|
|
@@ -1695,11 +1737,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1695
1737
|
return self._facc(xs)._fprs
|
|
1696
1738
|
|
|
1697
1739
|
def fsum_(self, *xs):
|
|
1698
|
-
'''Add any positional items, summate and return the
|
|
1699
|
-
|
|
1740
|
+
'''Add any positional items, summate and return the current
|
|
1741
|
+
precision running sum.
|
|
1700
1742
|
|
|
1701
|
-
@arg xs: Items to add (each C{scalar}
|
|
1702
|
-
|
|
1743
|
+
@arg xs: Items to add (each C{scalar}, an L{Fsum} or
|
|
1744
|
+
L{Fsum2Tuple}), all positional.
|
|
1703
1745
|
|
|
1704
1746
|
@return: Precision running sum (C{float} or C{int}).
|
|
1705
1747
|
|
|
@@ -1723,10 +1765,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1723
1765
|
|
|
1724
1766
|
@return: Precision running sum (L{Fsum2Tuple}).
|
|
1725
1767
|
'''
|
|
1726
|
-
return Fsum2Tuple(self._facc_args(xs).
|
|
1768
|
+
return Fsum2Tuple(self._facc_args(xs)._nfprs2, **name)
|
|
1727
1769
|
|
|
1728
1770
|
@property_RO
|
|
1729
|
-
def _Fsum(self): # like L{Fsum2Tuple._Fsum},
|
|
1771
|
+
def _Fsum(self): # like L{Fsum2Tuple._Fsum}, in .fstats
|
|
1730
1772
|
return self # NOT @Property_RO, see .copy and ._copy_2
|
|
1731
1773
|
|
|
1732
1774
|
def _Fsum_as(self, *xs, **name_f2product_nonfinites_RESIDUAL):
|
|
@@ -1740,17 +1782,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1740
1782
|
RESIDUAL =self.RESIDUAL())
|
|
1741
1783
|
if name_f2product_nonfinites_RESIDUAL: # overwrites
|
|
1742
1784
|
kwds.update(name_f2product_nonfinites_RESIDUAL)
|
|
1743
|
-
|
|
1744
|
-
# assert all(v == self.__dict__[n] for n, v in
|
|
1745
|
-
return
|
|
1746
|
-
|
|
1785
|
+
f = Fsum(**kwds)
|
|
1786
|
+
# assert all(v == self.__dict__[n] for n, v in f.__dict__.items())
|
|
1787
|
+
return f._fset(xs[0], op=_fset_op_) if len(xs) == 1 else (
|
|
1788
|
+
f._facc(xs, up=False) if xs else f)
|
|
1747
1789
|
|
|
1748
1790
|
def fsum2(self, xs=(), **name):
|
|
1749
1791
|
'''Add an iterable's items, summate and return the
|
|
1750
1792
|
current precision running sum I{and} the C{residual}.
|
|
1751
1793
|
|
|
1752
|
-
@arg xs: Iterable of items to add (each item C{scalar}
|
|
1753
|
-
|
|
1794
|
+
@arg xs: Iterable of items to add (each item C{scalar},
|
|
1795
|
+
an L{Fsum} or L{Fsum2Tuple}).
|
|
1754
1796
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1755
1797
|
|
|
1756
1798
|
@return: L{Fsum2Tuple}C{(fsum, residual)} with C{fsum} the
|
|
@@ -1768,8 +1810,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1768
1810
|
'''Add any positional items, summate and return the current
|
|
1769
1811
|
precision running sum and the I{differential}.
|
|
1770
1812
|
|
|
1771
|
-
@arg xs: Values to add (each C{scalar}
|
|
1772
|
-
L{Fsum2Tuple}
|
|
1813
|
+
@arg xs: Values to add (each C{scalar}, an L{Fsum} or
|
|
1814
|
+
L{Fsum2Tuple}), all positional.
|
|
1773
1815
|
|
|
1774
1816
|
@return: 2Tuple C{(fsum, delta)} with the current, precision
|
|
1775
1817
|
running C{fsum} like method L{Fsum.fsum} and C{delta},
|
|
@@ -1779,33 +1821,36 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1779
1821
|
'''
|
|
1780
1822
|
return self._fsum2(xs, self._facc_args)
|
|
1781
1823
|
|
|
1782
|
-
def _fsum2(self, xs, _facc, **
|
|
1824
|
+
def _fsum2(self, xs, _facc, **facc_kwds):
|
|
1783
1825
|
'''(INTERNAL) Helper for L{Fsum.fsum2_} and L{Fsum.fsum2f_}.
|
|
1784
1826
|
'''
|
|
1785
1827
|
p, q = self._fprs2
|
|
1786
1828
|
if xs:
|
|
1787
|
-
s, r = _facc(xs, **
|
|
1829
|
+
s, r = _facc(xs, **facc_kwds)._fprs2
|
|
1788
1830
|
if _isfinite(s): # _fsum(_1primed((s, -p, r, -q))
|
|
1789
1831
|
d, r = _2sum(s - p, r - q, _isfine=_isOK)
|
|
1790
1832
|
r, _ = _s_r(d, r)
|
|
1791
|
-
return s, (r if _isfinite(r) else
|
|
1833
|
+
return s, (r if _isfinite(r) else _NONFINITEr)
|
|
1792
1834
|
else:
|
|
1793
1835
|
return p, _0_0
|
|
1794
1836
|
|
|
1795
1837
|
def fsumf_(self, *xs):
|
|
1796
|
-
'''Like method L{Fsum.fsum_} iff I{all} C{B{xs}}
|
|
1838
|
+
'''Like method L{Fsum.fsum_} iff I{all} C{B{xs}}, each I{known to be}
|
|
1839
|
+
C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
|
|
1797
1840
|
'''
|
|
1798
|
-
return self.
|
|
1841
|
+
return self._facc_scalarf(xs, which=self.fsumf_)._fprs # origin=1?
|
|
1799
1842
|
|
|
1800
1843
|
def Fsumf_(self, *xs):
|
|
1801
|
-
'''Like method L{Fsum.Fsum_} iff I{all} C{B{xs}}
|
|
1844
|
+
'''Like method L{Fsum.Fsum_} iff I{all} C{B{xs}}, each I{known to be}
|
|
1845
|
+
C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
|
|
1802
1846
|
'''
|
|
1803
|
-
return self.
|
|
1847
|
+
return self._facc_scalarf(xs, which=self.Fsumf_)._copy_2(self.Fsumf_) # origin=1?
|
|
1804
1848
|
|
|
1805
1849
|
def fsum2f_(self, *xs):
|
|
1806
|
-
'''Like method L{Fsum.fsum2_} iff I{all} C{B{xs}}
|
|
1850
|
+
'''Like method L{Fsum.fsum2_} iff I{all} C{B{xs}}, each I{known to be}
|
|
1851
|
+
C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
|
|
1807
1852
|
'''
|
|
1808
|
-
return self._fsum2(xs, self.
|
|
1853
|
+
return self._fsum2(xs, self._facc_scalarf, which=self.fsum2f_) # origin=1?
|
|
1809
1854
|
|
|
1810
1855
|
# ftruediv = __itruediv__ # for naming consistency?
|
|
1811
1856
|
|
|
@@ -1813,7 +1858,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1813
1858
|
'''(INTERNAL) Apply C{B{self} /= B{other}}.
|
|
1814
1859
|
'''
|
|
1815
1860
|
n = _1_0
|
|
1816
|
-
if
|
|
1861
|
+
if _isFsum_2Tuple(other):
|
|
1817
1862
|
if other is self or self == other:
|
|
1818
1863
|
return self._fset(n, n=len(self))
|
|
1819
1864
|
d, r = other._fprs2
|
|
@@ -1846,9 +1891,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1846
1891
|
L{ResidualError}s (C{bool}) and C{B{RESIDUAL}=scalar}
|
|
1847
1892
|
to override the current L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1848
1893
|
|
|
1849
|
-
@return: This C{
|
|
1850
|
-
otherwise
|
|
1851
|
-
zero or not significant.
|
|
1894
|
+
@return: This C{int} sum if this instance C{is_integer} and
|
|
1895
|
+
I{finite}, otherwise the C{float} sum if the residual
|
|
1896
|
+
is zero or not significant.
|
|
1852
1897
|
|
|
1853
1898
|
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1854
1899
|
B{C{RESIDUAL}}.
|
|
@@ -1878,7 +1923,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1878
1923
|
|
|
1879
1924
|
@see: Function L{isfinite<pygeodesy.isfinite>}.
|
|
1880
1925
|
'''
|
|
1881
|
-
return _isfinite(
|
|
1926
|
+
return _isfinite(sum(self._ps)) # == sum(self)
|
|
1882
1927
|
|
|
1883
1928
|
def is_integer(self):
|
|
1884
1929
|
'''Is this instance' running sum C{integer}? (C{bool}).
|
|
@@ -1895,7 +1940,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1895
1940
|
an C{fma} implementation as C{math.fma} or C{None}, a previous
|
|
1896
1941
|
C{PyGeodesy} implementation.
|
|
1897
1942
|
'''
|
|
1898
|
-
return (
|
|
1943
|
+
return (_2split3s is _passarg) or (False if _2n_d is None else None)
|
|
1899
1944
|
|
|
1900
1945
|
def is_math_fsum(self):
|
|
1901
1946
|
'''Are the summation functions L{fsum}, L{fsum_}, L{fsumf_}, L{fsum1},
|
|
@@ -1907,48 +1952,52 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1907
1952
|
return _sum is _fsum # _fsum.__module__ is fabs.__module__
|
|
1908
1953
|
|
|
1909
1954
|
def is_scalar(self, **raiser_RESIDUAL):
|
|
1910
|
-
'''Is this instance' running sum C{scalar}
|
|
1955
|
+
'''Is this instance' running sum C{scalar} with C{0} residual or with
|
|
1911
1956
|
a residual I{ratio} not exceeding the RESIDUAL threshold?
|
|
1912
1957
|
|
|
1913
1958
|
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
|
|
1914
1959
|
L{ResidualError}s (C{bool}) and C{B{RESIDUAL}=scalar}
|
|
1915
1960
|
to override the current L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1916
1961
|
|
|
1917
|
-
@return: C{True} if this instance'
|
|
1918
|
-
|
|
1962
|
+
@return: C{True} if this instance' residual is C{0} or C{insignificant},
|
|
1963
|
+
i.e. its residual C{ratio} doesn't exceed the L{RESIDUAL
|
|
1964
|
+
<Fsum.RESIDUAL>} threshold (C{bool}).
|
|
1919
1965
|
|
|
1920
1966
|
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1921
1967
|
B{C{RESIDUAL}}.
|
|
1922
1968
|
|
|
1923
|
-
@see:
|
|
1969
|
+
@see: Methods L{Fsum.RESIDUAL} and L{Fsum.is_integer} and property
|
|
1924
1970
|
L{Fsum.as_iscalar}.
|
|
1925
1971
|
'''
|
|
1926
1972
|
s, r = self._fprs2
|
|
1927
1973
|
return False if r and self._raiser(r, s, **raiser_RESIDUAL) else True
|
|
1928
1974
|
|
|
1929
|
-
def _mul_Fsum(self, other, op
|
|
1975
|
+
def _mul_Fsum(self, other, op):
|
|
1930
1976
|
'''(INTERNAL) Return C{B{self} * B{other}} as L{Fsum} or C{0}.
|
|
1931
1977
|
'''
|
|
1932
|
-
# assert
|
|
1978
|
+
# assert _isFsum_2Tuple(other)
|
|
1933
1979
|
if self._ps and other._ps:
|
|
1934
|
-
|
|
1980
|
+
try:
|
|
1981
|
+
f = self._ps_mul(op, *other._ps) # NO .as_iscalar!
|
|
1982
|
+
except Exception as X:
|
|
1983
|
+
raise self._ErrorX(X, op, other)
|
|
1935
1984
|
else:
|
|
1936
1985
|
f = _0_0
|
|
1937
1986
|
return f
|
|
1938
1987
|
|
|
1939
|
-
def _mul_reduce(self,
|
|
1940
|
-
'''(INTERNAL) Like fmath.
|
|
1941
|
-
for I{non-finite} C{start} and/or C{others}.
|
|
1988
|
+
def _mul_reduce(self, *others):
|
|
1989
|
+
'''(INTERNAL) Like fmath.fprod for I{non-finite} C{other}s.
|
|
1942
1990
|
'''
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1991
|
+
r = _1_0
|
|
1992
|
+
for f in others:
|
|
1993
|
+
r *= sum(f._ps) if _isFsum_2Tuple(f) else float(f)
|
|
1994
|
+
return r
|
|
1946
1995
|
|
|
1947
|
-
def _mul_scalar(self, factor, op):
|
|
1996
|
+
def _mul_scalar(self, factor, op):
|
|
1948
1997
|
'''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum}, C{0.0} or C{self}.
|
|
1949
1998
|
'''
|
|
1950
1999
|
# assert isscalar(factor)
|
|
1951
|
-
if self._ps and self._finite(factor, op):
|
|
2000
|
+
if self._ps and self._finite(factor, op=op):
|
|
1952
2001
|
f = self if factor == _1_0 else (
|
|
1953
2002
|
self._neg if factor == _N_1_0 else
|
|
1954
2003
|
self._ps_mul(op, factor).as_iscalar)
|
|
@@ -1967,11 +2016,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1967
2016
|
'''
|
|
1968
2017
|
return _Psum(self._ps_neg) if self._ps else NEG0
|
|
1969
2018
|
|
|
2019
|
+
@property_RO
|
|
2020
|
+
def _nfprs2(self):
|
|
2021
|
+
'''(INTERNAL) Handle I{non-finite} C{_fprs2}.
|
|
2022
|
+
'''
|
|
2023
|
+
try: # to handle nonfiniterrors, etc.
|
|
2024
|
+
t = self._fprs2
|
|
2025
|
+
except (OverflowError, ValueError):
|
|
2026
|
+
t = Fsum2Tuple(sum(self._ps), _NONFINITEr)
|
|
2027
|
+
return t
|
|
2028
|
+
|
|
1970
2029
|
def nonfinites(self, *OK):
|
|
1971
2030
|
'''Handle I{non-finite} C{float}s as C{inf}, C{INF}, C{NINF}, C{nan}
|
|
1972
2031
|
and C{NAN} for this L{Fsum} or throw C{OverflowError} respectively
|
|
1973
|
-
C{ValueError} exceptions,
|
|
1974
|
-
function L{nonfiniterrors<fsums.nonfiniterrors>}.
|
|
2032
|
+
C{ValueError} exceptions, overriding the L{nonfiniterrors} default.
|
|
1975
2033
|
|
|
1976
2034
|
@arg OK: If omitted, leave the override unchanged, if C{True},
|
|
1977
2035
|
I{non-finites} are C{OK}, if C{False} throw exceptions
|
|
@@ -1981,14 +2039,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1981
2039
|
|
|
1982
2040
|
@see: Function L{nonfiniterrors<fsums.nonfiniterrors>}.
|
|
1983
2041
|
|
|
1984
|
-
@note: Use
|
|
1985
|
-
whether
|
|
2042
|
+
@note: Use property L{nonfinitesOK<Fsum.nonfinitesOK>} to determine
|
|
2043
|
+
whether I{non-finites} are C{OK} for this L{Fsum} and by the
|
|
2044
|
+
L{nonfiniterrors} default.
|
|
1986
2045
|
'''
|
|
1987
2046
|
_ks = Fsum._nonfinites_isfine_kwds
|
|
1988
2047
|
if OK: # delattrof(self, _isfine=None)
|
|
1989
2048
|
k = _xkwds_pop(self.__dict__, _isfine=None)
|
|
1990
2049
|
if OK[0] is not None:
|
|
1991
2050
|
self._isfine = _ks[bool(OK[0])]
|
|
2051
|
+
self._update()
|
|
1992
2052
|
else: # getattrof(self, _isfine=None)
|
|
1993
2053
|
k = _xkwds_get(self.__dict__, _isfine=None)
|
|
1994
2054
|
# dict(map(reversed, _ks.items())).get(k, None)
|
|
@@ -1999,10 +2059,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1999
2059
|
_nonfinites_isfine_kwds = {True: dict(_isfine=_isOK),
|
|
2000
2060
|
False: dict(_isfine=_isfinite)}
|
|
2001
2061
|
|
|
2002
|
-
|
|
2062
|
+
@property_RO
|
|
2063
|
+
def nonfinitesOK(self):
|
|
2064
|
+
'''Are I{non-finites} C{OK} for this L{Fsum} or by default? (C{bool}).
|
|
2065
|
+
'''
|
|
2066
|
+
# nf = self.nonfinites()
|
|
2067
|
+
# if nf is None:
|
|
2068
|
+
# nf = not nonfiniterrors()
|
|
2069
|
+
return _isOK_or_finite(INF, **self._isfine)
|
|
2070
|
+
|
|
2071
|
+
def _nonfiniteX(self, X, op, f, nonfinites=None, raiser=None):
|
|
2003
2072
|
'''(INTERNAL) Handle a I{non-finite} exception.
|
|
2004
2073
|
'''
|
|
2005
|
-
if
|
|
2074
|
+
if nonfinites is None:
|
|
2075
|
+
nonfinites = _isOK_or_finite(f, **self._isfine) if raiser is None else (not raiser)
|
|
2076
|
+
if not nonfinites:
|
|
2006
2077
|
raise self._ErrorX(X, op, f)
|
|
2007
2078
|
return f
|
|
2008
2079
|
|
|
@@ -2063,10 +2134,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2063
2134
|
def _pow(self, other, unused, op, **raiser_RESIDUAL):
|
|
2064
2135
|
'''Return C{B{self} ** B{other}}.
|
|
2065
2136
|
'''
|
|
2066
|
-
if
|
|
2137
|
+
if _isFsum_2Tuple(other):
|
|
2067
2138
|
f = self._pow_Fsum(other, op, **raiser_RESIDUAL)
|
|
2068
2139
|
elif self._scalar(other, op):
|
|
2069
|
-
x = self._finite(other, op)
|
|
2140
|
+
x = self._finite(other, op=op)
|
|
2070
2141
|
f = self._pow_scalar(x, other, op, **raiser_RESIDUAL)
|
|
2071
2142
|
else:
|
|
2072
2143
|
f = self._pow_0_1(0, other)
|
|
@@ -2084,7 +2155,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2084
2155
|
|
|
2085
2156
|
if mod: # b, x, mod all C{int}, unless C{mod} is C{None}
|
|
2086
2157
|
m = mod[0]
|
|
2087
|
-
# assert
|
|
2158
|
+
# assert _isFsum_2Tuple(b)
|
|
2088
2159
|
|
|
2089
2160
|
def _s(s, r):
|
|
2090
2161
|
R = self._raiser(r, s, **raiser_RESIDUAL)
|
|
@@ -2093,7 +2164,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2093
2164
|
return s
|
|
2094
2165
|
|
|
2095
2166
|
b = _s(*(b._fprs2 if m is None else b._fint2))
|
|
2096
|
-
x = _s(*
|
|
2167
|
+
x = _s(*_2s_r(x))
|
|
2097
2168
|
|
|
2098
2169
|
try:
|
|
2099
2170
|
# 0**INF == 0.0, 1**INF == 1.0, -1**2.3 == -(1**2.3)
|
|
@@ -2101,14 +2172,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2101
2172
|
if iscomplex(s):
|
|
2102
2173
|
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
2103
2174
|
raise ValueError(_strcomplex(s, b, x, *mod))
|
|
2104
|
-
|
|
2175
|
+
_ = _2finite(s, **self._isfine) # ignore float
|
|
2176
|
+
return s
|
|
2105
2177
|
except Exception as X:
|
|
2106
2178
|
raise self._ErrorX(X, op, other, *mod)
|
|
2107
2179
|
|
|
2108
2180
|
def _pow_Fsum(self, other, op, **raiser_RESIDUAL):
|
|
2109
|
-
'''(INTERNAL) Return C{B{self} **= B{other}} for C{
|
|
2181
|
+
'''(INTERNAL) Return C{B{self} **= B{other}} for C{_isFsum_2Tuple(other)}.
|
|
2110
2182
|
'''
|
|
2111
|
-
# assert
|
|
2183
|
+
# assert _isFsum_2Tuple(other)
|
|
2112
2184
|
x, r = other._fprs2
|
|
2113
2185
|
f = self._pow_scalar(x, other, op, **raiser_RESIDUAL)
|
|
2114
2186
|
if f and r:
|
|
@@ -2202,13 +2274,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2202
2274
|
n += 1
|
|
2203
2275
|
if n:
|
|
2204
2276
|
self._n += n
|
|
2205
|
-
# if _fi: # collapse ps if non-finite
|
|
2206
|
-
# x = _sum(ps)
|
|
2207
|
-
# if not _isfinite(x):
|
|
2208
|
-
# ps[:] = x,
|
|
2209
2277
|
# Fsum._ps_max = max(Fsum._ps_max, len(ps))
|
|
2210
2278
|
if up:
|
|
2211
2279
|
self._update()
|
|
2280
|
+
# x = sum(ps)
|
|
2281
|
+
# if not _isOK_or_finite(x, **fi):
|
|
2282
|
+
# ps[:] = x, # collapse ps
|
|
2212
2283
|
return ps
|
|
2213
2284
|
|
|
2214
2285
|
def _ps_mul(self, op, *factors):
|
|
@@ -2219,19 +2290,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2219
2290
|
if len(ps) < len(fs):
|
|
2220
2291
|
ps, fs = fs, ps
|
|
2221
2292
|
if self._f2product:
|
|
2222
|
-
|
|
2223
|
-
|
|
2293
|
+
fs, p = _2split3s(fs), fs
|
|
2294
|
+
if len(ps) > 1 and fs is not p:
|
|
2295
|
+
fs = tuple(fs) # several ps
|
|
2296
|
+
_pfs = _2products
|
|
2224
2297
|
else:
|
|
2225
|
-
def
|
|
2226
|
-
return (
|
|
2298
|
+
def _pfs(p, fs):
|
|
2299
|
+
return (p * f for f in fs)
|
|
2227
2300
|
|
|
2228
|
-
for
|
|
2229
|
-
for
|
|
2230
|
-
yield
|
|
2301
|
+
for p in ps:
|
|
2302
|
+
for f in _pfs(p, fs):
|
|
2303
|
+
yield f if _isfine(f) else _nfError(f)
|
|
2231
2304
|
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
return
|
|
2305
|
+
fs = _psfs(self._ps, factors, **self._isfine)
|
|
2306
|
+
f = _Psum(self._ps_acc([], fs, up=False), name=op)
|
|
2307
|
+
return f
|
|
2235
2308
|
|
|
2236
2309
|
@property_RO
|
|
2237
2310
|
def _ps_neg(self):
|
|
@@ -2240,15 +2313,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2240
2313
|
for p in self._ps:
|
|
2241
2314
|
yield -p
|
|
2242
2315
|
|
|
2243
|
-
def _ps_other(self, op,
|
|
2244
|
-
'''(INTERNAL) Yield
|
|
2316
|
+
def _ps_other(self, op, other):
|
|
2317
|
+
'''(INTERNAL) Yield C{other} as C{scalar}s.
|
|
2245
2318
|
'''
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
yield self._scalar(other, op)
|
|
2319
|
+
if _isFsum_2Tuple(other):
|
|
2320
|
+
for p in other._ps:
|
|
2321
|
+
yield p
|
|
2322
|
+
else:
|
|
2323
|
+
yield self._scalar(other, op)
|
|
2252
2324
|
|
|
2253
2325
|
def _ps_1sum(self, *less):
|
|
2254
2326
|
'''(INTERNAL) Return the partials sum, 1-primed C{less} some scalars.
|
|
@@ -2345,7 +2417,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2345
2417
|
def root(self, root, **raiser_RESIDUAL):
|
|
2346
2418
|
'''Return C{B{self}**(1 / B{root})} as L{Fsum}.
|
|
2347
2419
|
|
|
2348
|
-
@arg root:
|
|
2420
|
+
@arg root: Non-zero order (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
2349
2421
|
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore any
|
|
2350
2422
|
L{ResidualError}s (C{bool}) or C{B{RESIDUAL}=scalar}
|
|
2351
2423
|
to override the current L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
@@ -2362,7 +2434,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2362
2434
|
return f._fpow(x, f.name, **raiser_RESIDUAL) # == pow(f, x)
|
|
2363
2435
|
|
|
2364
2436
|
def _scalar(self, other, op, **txt):
|
|
2365
|
-
'''(INTERNAL) Return scalar C{other}.
|
|
2437
|
+
'''(INTERNAL) Return scalar C{other} or throw a C{TypeError}.
|
|
2366
2438
|
'''
|
|
2367
2439
|
if isscalar(other):
|
|
2368
2440
|
return other
|
|
@@ -2371,12 +2443,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2371
2443
|
def signOf(self, res=True):
|
|
2372
2444
|
'''Determine the sign of this instance.
|
|
2373
2445
|
|
|
2374
|
-
@kwarg res: If C{True}, consider
|
|
2375
|
-
the
|
|
2446
|
+
@kwarg res: If C{True}, consider the residual,
|
|
2447
|
+
otherwise ignore the latter (C{bool}).
|
|
2376
2448
|
|
|
2377
2449
|
@return: The sign (C{int}, -1, 0 or +1).
|
|
2378
2450
|
'''
|
|
2379
|
-
s, r = self.
|
|
2451
|
+
s, r = self._nfprs2
|
|
2380
2452
|
r = (-r) if res else 0
|
|
2381
2453
|
return _signOf(s, r)
|
|
2382
2454
|
|
|
@@ -2404,7 +2476,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2404
2476
|
if lenc:
|
|
2405
2477
|
p = Fmt.SQUARE(p, len(self))
|
|
2406
2478
|
n = _enquote(self.name, white=_UNDER_)
|
|
2407
|
-
t = self.
|
|
2479
|
+
t = self._nfprs2.toStr(**prec_sep_fmt)
|
|
2408
2480
|
return NN(p, _SPACE_, n, t)
|
|
2409
2481
|
|
|
2410
2482
|
def _truediv(self, other, op, **raiser_RESIDUAL):
|
|
@@ -2427,7 +2499,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2427
2499
|
|
|
2428
2500
|
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK see Fsum._update
|
|
2429
2501
|
|
|
2430
|
-
if _NONFINITES: # PYCHOK no cover
|
|
2502
|
+
if _NONFINITES == _std_: # PYCHOK no cover
|
|
2431
2503
|
_ = nonfiniterrors(False)
|
|
2432
2504
|
|
|
2433
2505
|
|
|
@@ -2574,7 +2646,7 @@ class Fsum2Tuple(_NamedTuple): # in .fstats
|
|
|
2574
2646
|
'''
|
|
2575
2647
|
return Fmt.PAREN(fstr(self, fmt=fmt, strepr=str, force=False, **prec_sep))
|
|
2576
2648
|
|
|
2577
|
-
|
|
2649
|
+
_Fsum_2Tuple_types = Fsum, Fsum2Tuple # PYCHOK lines
|
|
2578
2650
|
|
|
2579
2651
|
|
|
2580
2652
|
class ResidualError(_ValueError):
|
|
@@ -2603,7 +2675,7 @@ except ImportError:
|
|
|
2603
2675
|
def _fsum(xs):
|
|
2604
2676
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
2605
2677
|
'''
|
|
2606
|
-
F = Fsum(name=_fsum.name, nonfinites=True)
|
|
2678
|
+
F = Fsum(name=_fsum.name, f2product=False, nonfinites=True)
|
|
2607
2679
|
return float(F._facc(xs, up=False))
|
|
2608
2680
|
|
|
2609
2681
|
|
|
@@ -2613,8 +2685,7 @@ def fsum(xs, nonfinites=None, **floats):
|
|
|
2613
2685
|
@arg xs: Iterable of items to add (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
2614
2686
|
@kwarg nonfinites: Use C{B{nonfinites}=True} if I{non-finites} are C{OK}, if
|
|
2615
2687
|
C{False} I{non-finites} raise an Overflow-/ValueError or if
|
|
2616
|
-
C{None},
|
|
2617
|
-
(C{bool} or C{None}).
|
|
2688
|
+
C{None}, L{nonfiniterrors} applies (C{bool} or C{None}).
|
|
2618
2689
|
@kwarg floats: DEPRECATED keyword argument C{B{floats}=False} (C{bool}), use
|
|
2619
2690
|
keyword argument C{B{nonfinites}=False} instead.
|
|
2620
2691
|
|
|
@@ -2640,7 +2711,7 @@ def fsum_(*xs, **nonfinites):
|
|
|
2640
2711
|
|
|
2641
2712
|
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2642
2713
|
'''
|
|
2643
|
-
return _xsum(fsum_, xs,
|
|
2714
|
+
return _xsum(fsum_, xs, **nonfinites) if xs else _0_0 # origin=1?
|
|
2644
2715
|
|
|
2645
2716
|
|
|
2646
2717
|
def fsumf_(*xs):
|
|
@@ -2651,7 +2722,7 @@ def fsumf_(*xs):
|
|
|
2651
2722
|
|
|
2652
2723
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2653
2724
|
'''
|
|
2654
|
-
return _xsum(fsumf_, xs, nonfinites=True
|
|
2725
|
+
return _xsum(fsumf_, xs, nonfinites=True) if xs else _0_0 # origin=1?
|
|
2655
2726
|
|
|
2656
2727
|
|
|
2657
2728
|
def fsum1(xs, **nonfinites):
|
|
@@ -2673,7 +2744,7 @@ def fsum1_(*xs, **nonfinites):
|
|
|
2673
2744
|
|
|
2674
2745
|
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2675
2746
|
'''
|
|
2676
|
-
return _xsum(fsum1_, xs,
|
|
2747
|
+
return _xsum(fsum1_, xs, primed=1, **nonfinites) if xs else _0_0 # origin=1?
|
|
2677
2748
|
|
|
2678
2749
|
|
|
2679
2750
|
def fsum1f_(*xs):
|
|
@@ -2685,45 +2756,50 @@ def fsum1f_(*xs):
|
|
|
2685
2756
|
return _xsum(fsum1f_, xs, nonfinites=True, primed=1) if xs else _0_0
|
|
2686
2757
|
|
|
2687
2758
|
|
|
2688
|
-
def
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
if _isFsumTuple(x):
|
|
2694
|
-
for p in map(_x, x._ps):
|
|
2695
|
-
yield p
|
|
2696
|
-
else:
|
|
2697
|
-
yield _x(x)
|
|
2759
|
+
def _x_isfine(nfOK, **kwds): # get the C{_x} and C{_isfine} handlers.
|
|
2760
|
+
_x_kwds = dict(_x= (_passarg if nfOK else _2finite),
|
|
2761
|
+
_isfine=(_isOK if nfOK else _isfinite)) # PYCHOK kwds
|
|
2762
|
+
_x_kwds.update(kwds)
|
|
2763
|
+
return _x_kwds
|
|
2698
2764
|
|
|
2699
2765
|
|
|
2700
|
-
def
|
|
2701
|
-
|
|
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))
|
|
2766
|
+
def _X_ps(X): # default C{_X} handler
|
|
2767
|
+
return X._ps # lambda X: X._ps
|
|
2706
2768
|
|
|
2707
2769
|
|
|
2708
|
-
def
|
|
2709
|
-
|
|
2770
|
+
def _xs(xs, _X=_X_ps, _x=float, _isfine=_isfinite, # defaults for Fsum._facc
|
|
2771
|
+
origin=0, which=None, **_Cdot):
|
|
2772
|
+
'''(INTERNAL) Yield each C{xs} item as 1 or more C{float}s.
|
|
2710
2773
|
'''
|
|
2711
|
-
|
|
2774
|
+
i, x = 0, xs
|
|
2712
2775
|
try:
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2776
|
+
for i, x in enumerate(_xiterable(xs)):
|
|
2777
|
+
if isinstance(x, _Fsum_2Tuple_types):
|
|
2778
|
+
for p in _X(x):
|
|
2779
|
+
yield p if _isfine(p) else _nfError(p)
|
|
2780
|
+
else:
|
|
2781
|
+
f = _x(x)
|
|
2782
|
+
yield f if _isfine(f) else _nfError(f)
|
|
2783
|
+
|
|
2719
2784
|
except (OverflowError, TypeError, ValueError) as X:
|
|
2720
|
-
i, x
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2785
|
+
t = _xsError(X, xs, i + origin, x)
|
|
2786
|
+
if which: # prefix invokation
|
|
2787
|
+
w = unstr(which, *xs, _ELLIPSIS=4, **_Cdot)
|
|
2788
|
+
t = _COMMASPACE_(w, t)
|
|
2724
2789
|
raise _xError(X, t, txt=None)
|
|
2725
2790
|
|
|
2726
2791
|
|
|
2792
|
+
def _xsum(which, xs, nonfinites=None, primed=0, **floats): # origin=0
|
|
2793
|
+
'''(INTERNAL) Precision summation of C{xs} with conditions.
|
|
2794
|
+
'''
|
|
2795
|
+
if floats: # for backward compatibility
|
|
2796
|
+
nonfinites = _xkwds_get1(floats, floats=nonfinites)
|
|
2797
|
+
elif nonfinites is None:
|
|
2798
|
+
nonfinites = not nonfiniterrors()
|
|
2799
|
+
fs = _xs(xs, **_x_isfine(nonfinites, which=which))
|
|
2800
|
+
return _fsum(_1primed(fs) if primed else fs)
|
|
2801
|
+
|
|
2802
|
+
|
|
2727
2803
|
# delete all decorators, etc.
|
|
2728
2804
|
del _allPropertiesOf_n, deprecated_method, deprecated_property_RO, \
|
|
2729
2805
|
Property, Property_RO, property_RO, _ALL_LAZY, _F2PRODUCT, \
|