pygeodesy 24.4.18__py2.py3-none-any.whl → 24.5.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyGeodesy-24.4.18.dist-info → PyGeodesy-24.5.2.dist-info}/METADATA +2 -2
- {PyGeodesy-24.4.18.dist-info → PyGeodesy-24.5.2.dist-info}/RECORD +15 -15
- pygeodesy/__init__.py +1 -2
- pygeodesy/auxilats/auxAngle.py +3 -3
- pygeodesy/basics.py +2 -2
- pygeodesy/constants.py +1 -2
- pygeodesy/fmath.py +150 -104
- pygeodesy/fstats.py +3 -3
- pygeodesy/fsums.py +609 -516
- pygeodesy/interns.py +0 -1
- pygeodesy/lazily.py +2 -2
- pygeodesy/streprs.py +3 -1
- pygeodesy/triaxials.py +5 -5
- {PyGeodesy-24.4.18.dist-info → PyGeodesy-24.5.2.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.4.18.dist-info → PyGeodesy-24.5.2.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -14,27 +14,26 @@ L{Fsum.__rpow__} return a (very long) C{int} if invoked with optional argument
|
|
|
14
14
|
C{mod} set to C{None}. The C{residual} of an C{integer} L{Fsum} may be between
|
|
15
15
|
C{-1.0} and C{+1.0}, including C{INT0} if considered to be I{exact}.
|
|
16
16
|
|
|
17
|
-
Set env variable C{PYGEODESY_FSUM_PARTIALS} to string C{"fsum"}) for summation
|
|
18
|
-
of L{Fsum} partials by Python function C{math.fsum}.
|
|
19
|
-
|
|
20
17
|
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater than
|
|
21
|
-
C{"0.0"} as the threshold to throw a L{ResidualError}
|
|
22
|
-
of an L{Fsum} instance with a
|
|
23
|
-
|
|
18
|
+
C{"0.0"} as the threshold to throw a L{ResidualError} for a division, power or
|
|
19
|
+
root operation of an L{Fsum} instance with a C{residual} I{ratio} exceeding
|
|
20
|
+
the threshold. See methods L{Fsum.RESIDUAL}, L{Fsum.pow}, L{Fsum.__ipow__}
|
|
21
|
+
and L{Fsum.__itruediv__}.
|
|
24
22
|
'''
|
|
25
23
|
# make sure int/int division yields float quotient, see .basics
|
|
26
24
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
27
25
|
|
|
28
|
-
from pygeodesy.basics import iscomplex, isint, isscalar, itemsorted, \
|
|
26
|
+
from pygeodesy.basics import isbool, iscomplex, isint, isscalar, itemsorted, \
|
|
29
27
|
signOf, _signOf
|
|
30
28
|
from pygeodesy.constants import INT0, _isfinite, NEG0, _pos_self, \
|
|
31
29
|
_0_0, _1_0, _N_1_0, Float, Int
|
|
32
|
-
from pygeodesy.errors import _OverflowError, _TypeError,
|
|
33
|
-
_xError2, _xkwds_get,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
|
|
31
|
+
_ValueError, _xError, _xError2, _xkwds_get, \
|
|
32
|
+
_ZeroDivisionError
|
|
33
|
+
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DASH_, _DOT_, \
|
|
34
|
+
_EQUAL_, _from_, _LANGLE_, _NOTEQUAL_, \
|
|
35
|
+
_not_finite_, _PERCENT_, _PLUS_, _RANGLE_, \
|
|
36
|
+
_SLASH_, _SPACE_, _STAR_, _UNDER_
|
|
38
37
|
from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
|
|
39
38
|
from pygeodesy.named import _Named, _NamedTuple, _NotImplemented, Fmt, unstr
|
|
40
39
|
from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
@@ -45,30 +44,32 @@ from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
|
45
44
|
from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
|
|
46
45
|
|
|
47
46
|
__all__ = _ALL_LAZY.fsums
|
|
48
|
-
__version__ = '24.
|
|
49
|
-
|
|
50
|
-
_add_op_
|
|
51
|
-
_eq_op_
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
_le_op_
|
|
61
|
-
_lt_op_
|
|
62
|
-
_mod_
|
|
63
|
-
_mod_op_
|
|
64
|
-
_mul_op_
|
|
65
|
-
_ne_op_
|
|
66
|
-
_non_zero_
|
|
67
|
-
_pow_op_
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
47
|
+
__version__ = '24.05.02'
|
|
48
|
+
|
|
49
|
+
_add_op_ = _PLUS_ # in .auxilats.auxAngle
|
|
50
|
+
_eq_op_ = _EQUAL_ * 2 # _DEQUAL_
|
|
51
|
+
_div_ = 'div'
|
|
52
|
+
_floordiv_op_ = _SLASH_ * 2 # _DSLASH_
|
|
53
|
+
_fset_op_ = _EQUAL_
|
|
54
|
+
_ge_op_ = _RANGLE_ + _EQUAL_
|
|
55
|
+
_gt_op_ = _RANGLE_
|
|
56
|
+
_iadd_op_ = _add_op_ + _EQUAL_ # in .auxilats.auxAngle, .fstats
|
|
57
|
+
_integer_ = 'integer'
|
|
58
|
+
_isinstance = isinstance
|
|
59
|
+
_le_op_ = _LANGLE_ + _EQUAL_
|
|
60
|
+
_lt_op_ = _LANGLE_
|
|
61
|
+
_mod_ = 'mod'
|
|
62
|
+
_mod_op_ = _PERCENT_
|
|
63
|
+
_mul_op_ = _STAR_
|
|
64
|
+
_ne_op_ = _NOTEQUAL_
|
|
65
|
+
_non_zero_ = 'non-zero'
|
|
66
|
+
_pow_op_ = _STAR_ * 2 # _DSTAR_
|
|
67
|
+
_significant_ = 'significant'
|
|
68
|
+
_sub_op_ = _DASH_ # in .auxilats.auxAngle
|
|
69
|
+
_threshold_ = 'threshold'
|
|
70
|
+
_truediv_op_ = _SLASH_
|
|
71
|
+
_divmod_op_ = _floordiv_op_ + _mod_op_
|
|
72
|
+
_isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
|
|
72
73
|
|
|
73
74
|
|
|
74
75
|
def _2delta(*ab):
|
|
@@ -82,7 +83,7 @@ def _2delta(*ab):
|
|
|
82
83
|
|
|
83
84
|
|
|
84
85
|
def _2error(unused):
|
|
85
|
-
'''(INTERNAL) Throw a C{not
|
|
86
|
+
'''(INTERNAL) Throw a C{not-finite} exception.
|
|
86
87
|
'''
|
|
87
88
|
raise ValueError(_not_finite_)
|
|
88
89
|
|
|
@@ -108,10 +109,11 @@ def _2floats(xs, origin=0, _X=_X_ps, _x=float):
|
|
|
108
109
|
try:
|
|
109
110
|
i, x = origin, None
|
|
110
111
|
_fin = _isfinite
|
|
111
|
-
|
|
112
|
+
_FsT = _Fsum_Fsum2Tuple_types
|
|
113
|
+
_is = _isinstance
|
|
112
114
|
for x in xs:
|
|
113
|
-
if
|
|
114
|
-
for p in _X(x):
|
|
115
|
+
if _is(x, _FsT):
|
|
116
|
+
for p in _X(x._Fsum):
|
|
115
117
|
yield p
|
|
116
118
|
else:
|
|
117
119
|
f = _x(x)
|
|
@@ -145,6 +147,24 @@ def _2halfeven(s, r, p):
|
|
|
145
147
|
return s
|
|
146
148
|
|
|
147
149
|
|
|
150
|
+
def _isFsum(x):
|
|
151
|
+
'''(INTERNAL) Is C{x} an C{Fsum} instance?
|
|
152
|
+
'''
|
|
153
|
+
return _isinstance(x, Fsum)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _isFsumTuple(x):
|
|
157
|
+
'''(INTERNAL) Is C{x} an C{Fsum} or C{Fsum2Tuple} instance?
|
|
158
|
+
'''
|
|
159
|
+
return _isinstance(x, _Fsum_Fsum2Tuple_types)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _1_Over(x, op, **raiser_RESIDUAL): # vs _1_over
|
|
163
|
+
'''(INTERNAL) Return C{Fsum(1) / B{x}}.
|
|
164
|
+
'''
|
|
165
|
+
return _Psum_(_1_0)._ftruediv(x, op, **raiser_RESIDUAL)
|
|
166
|
+
|
|
167
|
+
|
|
148
168
|
def _1primed(xs): # in .fmath
|
|
149
169
|
'''(INTERNAL) 1-Primed summation of iterable C{xs}
|
|
150
170
|
items, all I{known} to be C{finite float}.
|
|
@@ -155,16 +175,10 @@ def _1primed(xs): # in .fmath
|
|
|
155
175
|
yield _N_1_0
|
|
156
176
|
|
|
157
177
|
|
|
158
|
-
def _2ps(s, r):
|
|
159
|
-
'''(INTERNAL) Return a C{s} and C{r} pair, I{ps-ordered}.
|
|
160
|
-
'''
|
|
161
|
-
return (s, r) if fabs(s) < fabs(r) else (r, s)
|
|
162
|
-
|
|
163
|
-
|
|
164
178
|
def _psum(ps): # PYCHOK used!
|
|
165
|
-
'''(INTERNAL) Partials
|
|
179
|
+
'''(INTERNAL) Partials summation, updating C{ps}.
|
|
166
180
|
'''
|
|
167
|
-
# assert
|
|
181
|
+
# assert _isinstance(ps, list)
|
|
168
182
|
i = len(ps) - 1
|
|
169
183
|
s = _0_0 if i < 0 else ps[i]
|
|
170
184
|
_2s = _2sum
|
|
@@ -192,32 +206,39 @@ def _Psum(ps, **name):
|
|
|
192
206
|
return F
|
|
193
207
|
|
|
194
208
|
|
|
195
|
-
def
|
|
196
|
-
'''(INTERNAL) Return an C{Fsum} from
|
|
209
|
+
def _Psum_(*ps, **name):
|
|
210
|
+
'''(INTERNAL) Return an C{Fsum} from 1 or 2 known scalar(s) C{ps}.
|
|
197
211
|
'''
|
|
198
|
-
|
|
199
|
-
F._ps[:] = p,
|
|
200
|
-
F._n = 1 # len(F._ps)
|
|
201
|
-
return F
|
|
212
|
+
return _Psum(ps, **name)
|
|
202
213
|
|
|
203
214
|
|
|
204
|
-
def
|
|
205
|
-
'''(INTERNAL) Return
|
|
215
|
+
def _2scalar2(other):
|
|
216
|
+
'''(INTERNAL) Return 2-tuple C{(other, r)} with C{other} as C{int},
|
|
217
|
+
C{float} or C{as-is} and C{r} the residual of C{as-is}.
|
|
206
218
|
'''
|
|
207
|
-
if
|
|
219
|
+
if _isFsumTuple(other):
|
|
208
220
|
s, r = other._fint2
|
|
209
221
|
if r:
|
|
210
222
|
s, r = other._fprs2
|
|
211
223
|
if r: # PYCHOK no cover
|
|
212
|
-
if _raiser and _raiser(r, s):
|
|
213
|
-
t = _stresidual(_non_zero_, r, **mod)
|
|
214
|
-
raise ResidualError(t, txt=None)
|
|
215
224
|
s = other # L{Fsum} as-is
|
|
216
225
|
else:
|
|
226
|
+
r = 0
|
|
217
227
|
s = other # C{type} as-is
|
|
218
228
|
if isint(s, both=True):
|
|
219
229
|
s = int(s)
|
|
220
|
-
return s
|
|
230
|
+
return s, r
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _s_r(s, r):
|
|
234
|
+
'''(INTERNAL) Return C{(s, r)}, I{ordered}.
|
|
235
|
+
'''
|
|
236
|
+
if r:
|
|
237
|
+
if fabs(s) < fabs(r):
|
|
238
|
+
s, r = r, (s or INT0)
|
|
239
|
+
else:
|
|
240
|
+
r = INT0
|
|
241
|
+
return s, r
|
|
221
242
|
|
|
222
243
|
|
|
223
244
|
def _strcomplex(s, *args):
|
|
@@ -229,16 +250,15 @@ def _strcomplex(s, *args):
|
|
|
229
250
|
return _SPACE_(c, s, _from_, n, t)
|
|
230
251
|
|
|
231
252
|
|
|
232
|
-
def _stresidual(prefix, residual, **
|
|
233
|
-
'''(INTERNAL) Residual error
|
|
253
|
+
def _stresidual(prefix, residual, R=0, **mod_ratio):
|
|
254
|
+
'''(INTERNAL) Residual error txt C{str}.
|
|
234
255
|
'''
|
|
235
256
|
p = _stresidual.__name__[3:]
|
|
236
257
|
t = Fmt.PARENSPACED(p, Fmt(residual))
|
|
237
|
-
for n, v in itemsorted(
|
|
238
|
-
n = n.replace(_UNDER_, _SPACE_)
|
|
258
|
+
for n, v in itemsorted(mod_ratio):
|
|
239
259
|
p = Fmt.PARENSPACED(n, Fmt(v))
|
|
240
260
|
t = _COMMASPACE_(t, p)
|
|
241
|
-
return _SPACE_(prefix, t)
|
|
261
|
+
return _SPACE_(prefix, t, Fmt.exceeds_R(R), _threshold_)
|
|
242
262
|
|
|
243
263
|
|
|
244
264
|
def _2sum(a, b): # by .testFmath
|
|
@@ -254,6 +274,16 @@ def _2sum(a, b): # by .testFmath
|
|
|
254
274
|
raise _OverflowError(u, txt=t)
|
|
255
275
|
|
|
256
276
|
|
|
277
|
+
def _threshold(threshold):
|
|
278
|
+
'''(INTERNAL) Get the L{ResidualError}s threshold.
|
|
279
|
+
'''
|
|
280
|
+
try:
|
|
281
|
+
t = float(threshold) or _0_0
|
|
282
|
+
return t if _isfinite(t) else _2error(t) # PYCHOK None
|
|
283
|
+
except Exception as x:
|
|
284
|
+
raise ResidualError(threshold=threshold, cause=x)
|
|
285
|
+
|
|
286
|
+
|
|
257
287
|
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
258
288
|
'''Precision floating point summation and I{running} summation.
|
|
259
289
|
|
|
@@ -261,58 +291,61 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
261
291
|
I{running}, precision floating point summations. Accumulation may continue after any
|
|
262
292
|
intermediate, I{running} summuation.
|
|
263
293
|
|
|
264
|
-
@note:
|
|
265
|
-
method C{__float__} to convert the C{scalar} to a single
|
|
294
|
+
@note: Values may be L{Fsum}, L{Fsum2Tuple}, C{int}, C{float} or C{scalar} instances,
|
|
295
|
+
any C{type} having method C{__float__} to convert the C{scalar} to a single
|
|
296
|
+
C{float}, except C{complex}.
|
|
266
297
|
|
|
267
298
|
@note: Handling of exceptions and C{inf}, C{INF}, C{nan} and C{NAN} differs from
|
|
268
299
|
Python's C{math.fsum}.
|
|
269
300
|
|
|
270
|
-
@see: U{Hettinger<https://GitHub.com/ActiveState/code/
|
|
271
|
-
393090_Binary_floating_point_summatiaccurate_full/recipe-393090.py>},
|
|
272
|
-
<https://WikiPedia.org/wiki/Kahan_summation_algorithm>}, U{Klein
|
|
301
|
+
@see: U{Hettinger<https://GitHub.com/ActiveState/code/tree/master/recipes/Python/
|
|
302
|
+
393090_Binary_floating_point_summatiaccurate_full/recipe-393090.py>},
|
|
303
|
+
U{Kahan<https://WikiPedia.org/wiki/Kahan_summation_algorithm>}, U{Klein
|
|
273
304
|
<https://Link.Springer.com/article/10.1007/s00607-005-0139-x>}, Python 2.6+
|
|
274
305
|
file I{Modules/mathmodule.c} and the issue log U{Full precision summation
|
|
275
306
|
<https://Bugs.Python.org/issue2819>}.
|
|
276
307
|
'''
|
|
277
308
|
_math_fsum = None
|
|
278
|
-
_n =
|
|
309
|
+
_n = 0
|
|
279
310
|
# _ps = [] # partial sums
|
|
280
|
-
# _ps_max =
|
|
281
|
-
|
|
282
|
-
_recursive = bool(_getenv('PYGEODESY_FSUM_RECURSIVE', NN))
|
|
283
|
-
_RESIDUAL = max(float(_getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)), _0_0)
|
|
311
|
+
# _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps))
|
|
312
|
+
_RESIDUAL = _threshold(_getenv('PYGEODESY_FSUM_RESIDUAL', _0_0))
|
|
284
313
|
|
|
285
314
|
def __init__(self, *xs, **name_RESIDUAL):
|
|
286
315
|
'''New L{Fsum} for I{running} precision floating point summation.
|
|
287
316
|
|
|
288
|
-
@arg xs: No, one or more
|
|
289
|
-
or
|
|
317
|
+
@arg xs: No, one or more items to add (each C{scalar} or an L{Fsum}
|
|
318
|
+
or L{Fsum2Tuple} instance), all positional.
|
|
290
319
|
@kwarg name_RESIDUAL: Optional C{B{name}=NN} for this L{Fsum} and
|
|
291
|
-
C{B{RESIDUAL}=
|
|
320
|
+
the C{B{RESIDUAL}=0.0} threshold for L{ResidualError}s.
|
|
292
321
|
|
|
293
322
|
@see: Methods L{Fsum.fadd} and L{Fsum.RESIDUAL}.
|
|
294
323
|
'''
|
|
295
324
|
if name_RESIDUAL:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
325
|
+
|
|
326
|
+
def _n_r(name=NN, RESIDUAL=None):
|
|
327
|
+
return name, RESIDUAL
|
|
328
|
+
|
|
329
|
+
n, r = _n_r(**name_RESIDUAL)
|
|
300
330
|
if r is not None:
|
|
301
|
-
self.RESIDUAL(r)
|
|
331
|
+
self.RESIDUAL(r)
|
|
332
|
+
if n:
|
|
333
|
+
self.name = n
|
|
334
|
+
|
|
302
335
|
self._ps = [] # [_0_0], see L{Fsum._fprs}
|
|
303
336
|
if xs:
|
|
304
|
-
self.
|
|
337
|
+
self._facc_1(xs, up=False)
|
|
305
338
|
|
|
306
339
|
def __abs__(self):
|
|
307
340
|
'''Return this instance' absolute value as an L{Fsum}.
|
|
308
341
|
'''
|
|
309
|
-
s =
|
|
342
|
+
s = self.signOf() # == self._cmp_0(0)
|
|
310
343
|
return (-self) if s < 0 else self._copy_2(self.__abs__)
|
|
311
344
|
|
|
312
345
|
def __add__(self, other):
|
|
313
346
|
'''Return C{B{self} + B{other}} as an L{Fsum}.
|
|
314
347
|
|
|
315
|
-
@arg other: An L{Fsum} or C{scalar}.
|
|
348
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar}.
|
|
316
349
|
|
|
317
350
|
@return: The sum (L{Fsum}).
|
|
318
351
|
|
|
@@ -336,8 +369,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
336
369
|
'''
|
|
337
370
|
return self.ceil
|
|
338
371
|
|
|
339
|
-
def __cmp__(self, other): #
|
|
340
|
-
'''Compare this with an other instance or C{scalar}
|
|
372
|
+
def __cmp__(self, other): # PYCHOK no cover
|
|
373
|
+
'''Compare this with an other instance or C{scalar}, Python 2-.
|
|
341
374
|
|
|
342
375
|
@return: -1, 0 or +1 (C{int}).
|
|
343
376
|
|
|
@@ -346,19 +379,23 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
346
379
|
s = self._cmp_0(other, self.cmp.__name__)
|
|
347
380
|
return _signOf(s, 0)
|
|
348
381
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
def __divmod__(self, other):
|
|
382
|
+
def __divmod__(self, other, **raiser_RESIDUAL):
|
|
352
383
|
'''Return C{divmod(B{self}, B{other})} as a L{DivMod2Tuple}
|
|
353
384
|
with quotient C{div} an C{int} in Python 3+ or C{float}
|
|
354
|
-
in Python 2- and remainder C{mod} an L{Fsum}.
|
|
385
|
+
in Python 2- and remainder C{mod} an L{Fsum} instance.
|
|
386
|
+
|
|
387
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} modulus.
|
|
388
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
389
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
390
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
355
391
|
|
|
356
|
-
@
|
|
392
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
393
|
+
B{C{RESIDUAL}}.
|
|
357
394
|
|
|
358
395
|
@see: Method L{Fsum.__itruediv__}.
|
|
359
396
|
'''
|
|
360
397
|
f = self._copy_2(self.__divmod__)
|
|
361
|
-
return f._fdivmod2(other, _divmod_op_)
|
|
398
|
+
return f._fdivmod2(other, _divmod_op_, **raiser_RESIDUAL)
|
|
362
399
|
|
|
363
400
|
def __eq__(self, other):
|
|
364
401
|
'''Compare this with an other instance or C{scalar}.
|
|
@@ -384,7 +421,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
384
421
|
def __floordiv__(self, other):
|
|
385
422
|
'''Return C{B{self} // B{other}} as an L{Fsum}.
|
|
386
423
|
|
|
387
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
424
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} divisor.
|
|
388
425
|
|
|
389
426
|
@return: The C{floor} quotient (L{Fsum}).
|
|
390
427
|
|
|
@@ -415,7 +452,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
415
452
|
def __iadd__(self, other):
|
|
416
453
|
'''Apply C{B{self} += B{other}} to this instance.
|
|
417
454
|
|
|
418
|
-
@arg other: An L{Fsum} or C{scalar} instance.
|
|
455
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} instance.
|
|
419
456
|
|
|
420
457
|
@return: This instance, updated (L{Fsum}).
|
|
421
458
|
|
|
@@ -429,11 +466,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
429
466
|
def __ifloordiv__(self, other):
|
|
430
467
|
'''Apply C{B{self} //= B{other}} to this instance.
|
|
431
468
|
|
|
432
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
469
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} divisor.
|
|
433
470
|
|
|
434
471
|
@return: This instance, updated (L{Fsum}).
|
|
435
472
|
|
|
436
|
-
@raise ResidualError: Non-zero residual
|
|
473
|
+
@raise ResidualError: Non-zero, significant residual
|
|
474
|
+
in B{C{other}}.
|
|
437
475
|
|
|
438
476
|
@raise TypeError: Invalid B{C{other}} type.
|
|
439
477
|
|
|
@@ -452,7 +490,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
452
490
|
def __imod__(self, other):
|
|
453
491
|
'''Apply C{B{self} %= B{other}} to this instance.
|
|
454
492
|
|
|
455
|
-
@arg other: An L{Fsum} or C{scalar} modulus.
|
|
493
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} modulus.
|
|
456
494
|
|
|
457
495
|
@return: This instance, updated (L{Fsum}).
|
|
458
496
|
|
|
@@ -463,7 +501,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
463
501
|
def __imul__(self, other):
|
|
464
502
|
'''Apply C{B{self} *= B{other}} to this instance.
|
|
465
503
|
|
|
466
|
-
@arg other: An L{Fsum} or C{scalar} factor.
|
|
504
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} factor.
|
|
467
505
|
|
|
468
506
|
@return: This instance, updated (L{Fsum}).
|
|
469
507
|
|
|
@@ -490,49 +528,48 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
490
528
|
# Luciano Ramalho, "Fluent Python", O'Reilly, 2nd Ed, 2022 p. 567
|
|
491
529
|
return _NotImplemented(self)
|
|
492
530
|
|
|
493
|
-
def __ipow__(self, other, *mod, **
|
|
531
|
+
def __ipow__(self, other, *mod, **raiser_RESIDUAL): # PYCHOK 2 vs 3 args
|
|
494
532
|
'''Apply C{B{self} **= B{other}} to this instance.
|
|
495
533
|
|
|
496
|
-
@arg other: The exponent (L{Fsum} or
|
|
497
|
-
@arg mod: Optional modulus (C{int} or C{None}) for the
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
534
|
+
@arg other: The exponent (C{scalar}, L{Fsum} or L{Fsum2Tuple}).
|
|
535
|
+
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
536
|
+
C{pow(B{self}, B{other}, B{mod})} version.
|
|
537
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
538
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
539
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
502
540
|
|
|
503
541
|
@return: This instance, updated (L{Fsum}).
|
|
504
542
|
|
|
505
543
|
@note: If B{C{mod}} is given, the result will be an C{integer}
|
|
506
544
|
L{Fsum} in Python 3+ if this instance C{is_integer} or
|
|
507
|
-
set to C{as_integer}
|
|
545
|
+
set to C{as_integer} and B{C{mod}} is given as C{None}.
|
|
508
546
|
|
|
509
547
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
510
548
|
|
|
511
|
-
@raise ResidualError:
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
is a negative or fractional C{scalar}.
|
|
549
|
+
@raise ResidualError: Invalid B{C{RESIDUAL}} or the residual
|
|
550
|
+
is non-zero and significant and either
|
|
551
|
+
B{C{other}} is a fractional or negative
|
|
552
|
+
C{scalar} or B{C{mod}} is given and not
|
|
553
|
+
C{None}.
|
|
517
554
|
|
|
518
|
-
@raise TypeError: Invalid B{C{other}} type or 3-argument
|
|
519
|
-
|
|
555
|
+
@raise TypeError: Invalid B{C{other}} type or 3-argument C{pow}
|
|
556
|
+
invocation failed.
|
|
520
557
|
|
|
521
|
-
@raise ValueError: If B{C{other}} is a negative C{scalar}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
558
|
+
@raise ValueError: If B{C{other}} is a negative C{scalar} and this
|
|
559
|
+
instance is C{0} or B{C{other}} is a fractional
|
|
560
|
+
C{scalar} and this instance is negative or has a
|
|
561
|
+
non-zero and significant residual or B{C{mod}}
|
|
562
|
+
is given as C{0}.
|
|
526
563
|
|
|
527
564
|
@see: CPython function U{float_pow<https://GitHub.com/
|
|
528
565
|
python/cpython/blob/main/Objects/floatobject.c>}.
|
|
529
566
|
'''
|
|
530
|
-
return self._fpow(other, _pow_op_ + _fset_op_, *mod, **
|
|
567
|
+
return self._fpow(other, _pow_op_ + _fset_op_, *mod, **raiser_RESIDUAL)
|
|
531
568
|
|
|
532
569
|
def __isub__(self, other):
|
|
533
570
|
'''Apply C{B{self} -= B{other}} to this instance.
|
|
534
571
|
|
|
535
|
-
@arg other: An L{Fsum} or C{scalar}.
|
|
572
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar}.
|
|
536
573
|
|
|
537
574
|
@return: This instance, updated (L{Fsum}).
|
|
538
575
|
|
|
@@ -547,19 +584,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
547
584
|
'''
|
|
548
585
|
return iter(self.partials)
|
|
549
586
|
|
|
550
|
-
def __itruediv__(self, other, **
|
|
587
|
+
def __itruediv__(self, other, **raiser_RESIDUAL):
|
|
551
588
|
'''Apply C{B{self} /= B{other}} to this instance.
|
|
552
589
|
|
|
553
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
554
|
-
@kwarg
|
|
555
|
-
|
|
590
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} divisor.
|
|
591
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
592
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
593
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
556
594
|
|
|
557
595
|
@return: This instance, updated (L{Fsum}).
|
|
558
596
|
|
|
559
597
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
560
598
|
|
|
561
|
-
@raise ResidualError: Non-zero residual
|
|
562
|
-
|
|
599
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
600
|
+
B{C{RESIDUAL}}.
|
|
563
601
|
|
|
564
602
|
@raise TypeError: Invalid B{C{other}} type.
|
|
565
603
|
|
|
@@ -569,7 +607,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
569
607
|
|
|
570
608
|
@see: Method L{Fsum.__ifloordiv__}.
|
|
571
609
|
'''
|
|
572
|
-
return self._ftruediv(other, _truediv_op_ + _fset_op_, **
|
|
610
|
+
return self._ftruediv(other, _truediv_op_ + _fset_op_, **raiser_RESIDUAL)
|
|
573
611
|
|
|
574
612
|
def __le__(self, other):
|
|
575
613
|
'''Compare this with an other instance or C{scalar}.
|
|
@@ -639,8 +677,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
639
677
|
return f._fadd(self, _add_op_)
|
|
640
678
|
|
|
641
679
|
def __rdivmod__(self, other):
|
|
642
|
-
'''Return C{divmod(B{other}, B{self})} as 2-tuple
|
|
643
|
-
remainder)}.
|
|
680
|
+
'''Return C{divmod(B{other}, B{self})} as 2-tuple
|
|
681
|
+
C{(quotient, remainder)}.
|
|
644
682
|
|
|
645
683
|
@see: Method L{Fsum.__divmod__}.
|
|
646
684
|
'''
|
|
@@ -680,14 +718,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
680
718
|
f = self._copy_2r(other, self.__rmul__)
|
|
681
719
|
return f._fmul(self, _mul_op_)
|
|
682
720
|
|
|
683
|
-
def __round__(self, *ndigits): # PYCHOK
|
|
721
|
+
def __round__(self, *ndigits): # PYCHOK Python 3+
|
|
684
722
|
'''Return C{round(B{self}, *B{ndigits}} as an L{Fsum}.
|
|
685
723
|
|
|
686
724
|
@arg ndigits: Optional number of digits (C{int}).
|
|
687
725
|
'''
|
|
726
|
+
f = self._copy_2(self.__round__)
|
|
688
727
|
# <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
|
|
689
|
-
return
|
|
690
|
-
name=self.__round__.__name__)
|
|
728
|
+
return f._fset(round(float(self), *ndigits)) # can be C{int}
|
|
691
729
|
|
|
692
730
|
def __rpow__(self, other, *mod):
|
|
693
731
|
'''Return C{B{other}**B{self}} as an L{Fsum}.
|
|
@@ -705,13 +743,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
705
743
|
f = self._copy_2r(other, self.__rsub__)
|
|
706
744
|
return f._fsub(self, _sub_op_)
|
|
707
745
|
|
|
708
|
-
def __rtruediv__(self, other, **
|
|
746
|
+
def __rtruediv__(self, other, **raiser_RESIDUAL):
|
|
709
747
|
'''Return C{B{other} / B{self}} as an L{Fsum}.
|
|
710
748
|
|
|
711
749
|
@see: Method L{Fsum.__itruediv__}.
|
|
712
750
|
'''
|
|
713
751
|
f = self._copy_2r(other, self.__rtruediv__)
|
|
714
|
-
return f._ftruediv(self, _truediv_op_, **
|
|
752
|
+
return f._ftruediv(self, _truediv_op_, **raiser_RESIDUAL)
|
|
715
753
|
|
|
716
754
|
def __str__(self):
|
|
717
755
|
'''Return the default C{str(self)}.
|
|
@@ -721,7 +759,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
721
759
|
def __sub__(self, other):
|
|
722
760
|
'''Return C{B{self} - B{other}} as an L{Fsum}.
|
|
723
761
|
|
|
724
|
-
@arg other: An L{Fsum} or C{scalar}.
|
|
762
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar}.
|
|
725
763
|
|
|
726
764
|
@return: The difference (L{Fsum}).
|
|
727
765
|
|
|
@@ -730,19 +768,23 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
730
768
|
f = self._copy_2(self.__sub__)
|
|
731
769
|
return f._fsub(other, _sub_op_)
|
|
732
770
|
|
|
733
|
-
def __truediv__(self, other, **
|
|
771
|
+
def __truediv__(self, other, **raiser_RESIDUAL):
|
|
734
772
|
'''Return C{B{self} / B{other}} as an L{Fsum}.
|
|
735
773
|
|
|
736
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
737
|
-
@kwarg
|
|
738
|
-
|
|
774
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} divisor.
|
|
775
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
776
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
777
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
739
778
|
|
|
740
779
|
@return: The quotient (L{Fsum}).
|
|
741
780
|
|
|
781
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
782
|
+
B{C{RESIDUAL}}.
|
|
783
|
+
|
|
742
784
|
@see: Method L{Fsum.__itruediv__}.
|
|
743
785
|
'''
|
|
744
786
|
f = self._copy_2(self.__truediv__)
|
|
745
|
-
return f._ftruediv(other, _truediv_op_, **
|
|
787
|
+
return f._ftruediv(other, _truediv_op_, **raiser_RESIDUAL)
|
|
746
788
|
|
|
747
789
|
__trunc__ = __int__
|
|
748
790
|
|
|
@@ -764,13 +806,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
764
806
|
'''
|
|
765
807
|
n, r = self._fint2
|
|
766
808
|
if r:
|
|
767
|
-
i, d = r.as_integer_ratio()
|
|
809
|
+
i, d = float(r).as_integer_ratio()
|
|
768
810
|
n *= d
|
|
769
811
|
n += i
|
|
770
812
|
else: # PYCHOK no cover
|
|
771
813
|
d = 1
|
|
772
814
|
return n, d
|
|
773
815
|
|
|
816
|
+
@property_RO
|
|
817
|
+
def as_iscalar(self):
|
|
818
|
+
'''Get this instance I{as-is} (L{Fsum}) or as C{scalar} iff scalar.
|
|
819
|
+
'''
|
|
820
|
+
s, r = self._fprs2
|
|
821
|
+
return self if r else s
|
|
822
|
+
|
|
774
823
|
@property_RO
|
|
775
824
|
def ceil(self):
|
|
776
825
|
'''Get this instance' C{ceil} value (C{int} in Python 3+,
|
|
@@ -787,16 +836,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
787
836
|
c += 1
|
|
788
837
|
return c
|
|
789
838
|
|
|
839
|
+
cmp = __cmp__
|
|
840
|
+
|
|
790
841
|
def _cmp_0(self, other, op):
|
|
791
842
|
'''(INTERNAL) Return C{scalar(self - B{other})} for 0-comparison.
|
|
792
843
|
'''
|
|
793
|
-
if
|
|
844
|
+
if _isFsumTuple(other):
|
|
794
845
|
s = _fsum(self._ps_1primed(*other._ps))
|
|
795
846
|
elif self._scalar(other, op):
|
|
796
847
|
s = _fsum(self._ps_1primed(other))
|
|
797
848
|
else:
|
|
798
|
-
s
|
|
799
|
-
s = _signOf(s, -r)
|
|
849
|
+
s = self.signOf() # res=True
|
|
800
850
|
return s
|
|
801
851
|
|
|
802
852
|
def copy(self, deep=False, name=NN):
|
|
@@ -824,8 +874,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
824
874
|
def _copy_2r(self, other, which):
|
|
825
875
|
'''(INTERNAL) Copy for I{reverse-dyadic} operators.
|
|
826
876
|
'''
|
|
827
|
-
return other._copy_2(which) if
|
|
828
|
-
|
|
877
|
+
return other._copy_2(which) if _isFsum(other) else \
|
|
878
|
+
self._copy_2(which)._fset(other)
|
|
829
879
|
|
|
830
880
|
# def _copy_RESIDUAL(self, other):
|
|
831
881
|
# '''(INTERNAL) Copy C{other._RESIDUAL}.
|
|
@@ -834,27 +884,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
834
884
|
# if R is not Fsum._RESIDUAL:
|
|
835
885
|
# self._RESIDUAL = R
|
|
836
886
|
|
|
837
|
-
|
|
838
|
-
'''Return C{divmod(B{self}, B{other})} as 2-tuple C{(quotient,
|
|
839
|
-
remainder)}.
|
|
840
|
-
|
|
841
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
842
|
-
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
843
|
-
(C{bool}), see also method L{RESIDUAL}.
|
|
844
|
-
|
|
845
|
-
@return: A L{DivMod2Tuple}C{(div, mod)}, with quotient C{div}
|
|
846
|
-
an C{int} in Python 3+ or C{float} in Python 2- and
|
|
847
|
-
remainder C{mod} an L{Fsum} instance.
|
|
848
|
-
|
|
849
|
-
@see: Method L{Fsum.__itruediv__}.
|
|
850
|
-
'''
|
|
851
|
-
f = self._copy_2(self.divmod)
|
|
852
|
-
return f._fdivmod2(other, _divmod_op_, **raiser)
|
|
887
|
+
divmod = __divmod__
|
|
853
888
|
|
|
854
889
|
def _Error(self, op, other, Error, **txt_cause):
|
|
855
890
|
'''(INTERNAL) Format an B{C{Error}} for C{{self} B{op} B{other}}.
|
|
856
891
|
'''
|
|
857
|
-
return Error(_SPACE_(self.
|
|
892
|
+
return Error(_SPACE_(self.as_iscalar, op, other), **txt_cause)
|
|
858
893
|
|
|
859
894
|
def _ErrorX(self, X, op, other, *mod):
|
|
860
895
|
'''(INTERNAL) Format the caught exception C{X}.
|
|
@@ -868,48 +903,47 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
868
903
|
'''(INTERNAL) Format the caught exception C{X}.
|
|
869
904
|
'''
|
|
870
905
|
E, t = _xError2(X)
|
|
871
|
-
|
|
872
|
-
return E(
|
|
906
|
+
u = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
|
|
907
|
+
return E(u, txt=t, cause=X)
|
|
873
908
|
|
|
874
909
|
def _facc(self, xs, up=True, **origin_X_x):
|
|
875
910
|
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s.
|
|
876
911
|
'''
|
|
877
912
|
if xs:
|
|
878
|
-
|
|
879
|
-
ps
|
|
880
|
-
ps[:] =
|
|
913
|
+
_xs = _2floats(xs, **origin_X_x) # PYCHOK yield
|
|
914
|
+
ps = self._ps
|
|
915
|
+
ps[:] = self._ps_acc(list(ps), _xs, up=up)
|
|
881
916
|
return self
|
|
882
917
|
|
|
883
918
|
def _facc_1(self, xs, **up):
|
|
884
919
|
'''(INTERNAL) Accumulate 0, 1 or more C{scalars} or L{Fsum}s,
|
|
885
920
|
all positional C{xs} in the caller of this method.
|
|
886
921
|
'''
|
|
887
|
-
|
|
888
|
-
return self._fadd(xs[0], _add_op_) if len(xs) == 1 else \
|
|
922
|
+
return self._fadd(xs[0], _add_op_, **up) if len(xs) == 1 else \
|
|
889
923
|
self._facc(xs, origin=1, **up)
|
|
890
924
|
|
|
891
|
-
def _facc_neg(self, xs,
|
|
925
|
+
def _facc_neg(self, xs, **up_origin):
|
|
892
926
|
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s, negated.
|
|
893
927
|
'''
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
return -x
|
|
928
|
+
def _N(X):
|
|
929
|
+
return X._ps_neg
|
|
897
930
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
return self
|
|
931
|
+
def _n(x):
|
|
932
|
+
return -float(x)
|
|
933
|
+
|
|
934
|
+
return self._facc(xs, _X=_N, _x=_n, **up_origin)
|
|
902
935
|
|
|
903
|
-
def _facc_power(self, power, xs, which, **
|
|
936
|
+
def _facc_power(self, power, xs, which, **raiser_RESIDUAL): # in .fmath
|
|
904
937
|
'''(INTERNAL) Add each C{xs} as C{float(x**power)}.
|
|
905
938
|
'''
|
|
906
939
|
def _Pow4(p):
|
|
907
940
|
r = 0
|
|
908
|
-
if
|
|
941
|
+
if _isFsumTuple(p):
|
|
909
942
|
s, r = p._fprs2
|
|
910
943
|
if r:
|
|
944
|
+
m = Fsum._pow
|
|
945
|
+
else: # scalar
|
|
911
946
|
return _Pow4(s)
|
|
912
|
-
m = Fsum._pow
|
|
913
947
|
elif isint(p, both=True) and int(p) >= 0:
|
|
914
948
|
p = s = int(p)
|
|
915
949
|
m = Fsum._pow_int
|
|
@@ -920,24 +954,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
920
954
|
|
|
921
955
|
_Pow, p, s, r = _Pow4(power)
|
|
922
956
|
if p: # and xs:
|
|
923
|
-
_pow = Fsum._pow_2_3
|
|
924
|
-
_Fs = Fsum
|
|
925
|
-
_Ps = _Psum_1()._fset_ps_
|
|
926
957
|
op = which.__name__
|
|
958
|
+
_isF = _isFsum
|
|
959
|
+
_pow = self._pow_2_3
|
|
927
960
|
|
|
928
|
-
def
|
|
929
|
-
f = _Pow(X, p, power, op, **
|
|
930
|
-
return f._ps if
|
|
961
|
+
def _P(X):
|
|
962
|
+
f = _Pow(X, p, power, op, **raiser_RESIDUAL)
|
|
963
|
+
return f._ps if _isF(f) else (f,)
|
|
931
964
|
|
|
932
|
-
def
|
|
965
|
+
def _p(x):
|
|
933
966
|
x = float(x)
|
|
934
|
-
|
|
935
|
-
f
|
|
936
|
-
|
|
937
|
-
f *= _pow(X, x, r, power, op, **raiser)
|
|
967
|
+
f = _pow(x, s, power, op, **raiser_RESIDUAL)
|
|
968
|
+
if f and r:
|
|
969
|
+
f *= _pow(x, r, power, op, **raiser_RESIDUAL)
|
|
938
970
|
return f
|
|
939
971
|
|
|
940
|
-
f = self._facc(xs, origin=1, _X=
|
|
972
|
+
f = self._facc(xs, origin=1, _X=_P, _x=_p)
|
|
941
973
|
else:
|
|
942
974
|
f = self._facc_scalar_(float(len(xs))) # x**0 == 1
|
|
943
975
|
return f
|
|
@@ -946,47 +978,46 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
946
978
|
'''(INTERNAL) Accumulate all C{xs}, known to be scalar.
|
|
947
979
|
'''
|
|
948
980
|
if xs:
|
|
949
|
-
self._ps_acc(self._ps, xs, **up)
|
|
981
|
+
_ = self._ps_acc(self._ps, xs, **up)
|
|
950
982
|
return self
|
|
951
983
|
|
|
952
984
|
def _facc_scalar_(self, *xs, **up):
|
|
953
985
|
'''(INTERNAL) Accumulate all positional C{xs}, known to be scalar.
|
|
954
986
|
'''
|
|
955
987
|
if xs:
|
|
956
|
-
self._ps_acc(self._ps, xs, **up)
|
|
988
|
+
_ = self._ps_acc(self._ps, xs, **up)
|
|
957
989
|
return self
|
|
958
990
|
|
|
959
991
|
# def _facc_up(self, up=True):
|
|
960
992
|
# '''(INTERNAL) Update the C{partials}, by removing
|
|
961
993
|
# and re-accumulating the final C{partial}.
|
|
962
994
|
# '''
|
|
963
|
-
#
|
|
964
|
-
#
|
|
995
|
+
# ps = self._ps
|
|
996
|
+
# while len(ps) > 1:
|
|
997
|
+
# p = ps.pop()
|
|
965
998
|
# if p:
|
|
966
999
|
# n = self._n
|
|
967
|
-
# self.
|
|
1000
|
+
# _ = self._ps_acc(ps, (p,), up=False)
|
|
968
1001
|
# self._n = n
|
|
969
1002
|
# break
|
|
970
|
-
# return self._update() if up else self
|
|
1003
|
+
# return self._update() if up else self
|
|
971
1004
|
|
|
972
1005
|
def fadd(self, xs=()):
|
|
973
|
-
'''Add an iterable
|
|
974
|
-
to this instance.
|
|
1006
|
+
'''Add all items from an iterable to this instance.
|
|
975
1007
|
|
|
976
|
-
@arg xs: Iterable
|
|
977
|
-
L{Fsum}
|
|
1008
|
+
@arg xs: Iterable of items to add (each C{scalar}
|
|
1009
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
978
1010
|
|
|
979
1011
|
@return: This instance (L{Fsum}).
|
|
980
1012
|
|
|
981
1013
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
982
1014
|
|
|
983
|
-
@raise TypeError: An invalid B{C{xs}}
|
|
984
|
-
nor L{Fsum}.
|
|
1015
|
+
@raise TypeError: An invalid B{C{xs}} item.
|
|
985
1016
|
|
|
986
1017
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
987
1018
|
'''
|
|
988
|
-
if
|
|
989
|
-
self._facc_scalar(xs._ps) # tuple
|
|
1019
|
+
if _isFsumTuple(xs):
|
|
1020
|
+
self._facc_scalar(xs._ps) # tuple(xs._ps)
|
|
990
1021
|
elif isscalar(xs): # for backward compatibility
|
|
991
1022
|
self._facc_scalar_(_2float(x=xs)) # PYCHOK no cover
|
|
992
1023
|
elif xs: # assert isiterable(xs)
|
|
@@ -994,27 +1025,19 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
994
1025
|
return self
|
|
995
1026
|
|
|
996
1027
|
def fadd_(self, *xs):
|
|
997
|
-
'''Add all positional
|
|
998
|
-
to this instance.
|
|
999
|
-
|
|
1000
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1001
|
-
all positional.
|
|
1002
|
-
|
|
1003
|
-
@return: This instance (L{Fsum}).
|
|
1004
|
-
|
|
1005
|
-
@raise OverflowError: Partial C{2sum} overflow.
|
|
1028
|
+
'''Add all positional arguments to this instance.
|
|
1006
1029
|
|
|
1007
|
-
@
|
|
1008
|
-
|
|
1030
|
+
@arg xs: Values to add (each C{scalar} or an L{Fsum}
|
|
1031
|
+
or L{Fsum2Tuple} instance), all positional.
|
|
1009
1032
|
|
|
1010
|
-
@
|
|
1033
|
+
@see: Method L{Fsum.fadd} for further details.
|
|
1011
1034
|
'''
|
|
1012
1035
|
return self._facc_1(xs)
|
|
1013
1036
|
|
|
1014
1037
|
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
1015
1038
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
1016
1039
|
'''
|
|
1017
|
-
if
|
|
1040
|
+
if _isFsumTuple(other):
|
|
1018
1041
|
self._facc_scalar(other._ps, **up) # tuple
|
|
1019
1042
|
elif self._scalar(other, op):
|
|
1020
1043
|
self._facc_scalar_(other, **up)
|
|
@@ -1024,16 +1047,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1024
1047
|
fdiv = __itruediv__ # for backward compatibility
|
|
1025
1048
|
fdivmod = __divmod__ # for backward compatibility
|
|
1026
1049
|
|
|
1027
|
-
def _fdivmod2(self, other, op, **
|
|
1050
|
+
def _fdivmod2(self, other, op, **raiser_RESIDUAL):
|
|
1028
1051
|
'''(INTERNAL) Apply C{B{self} %= B{other}} and return a L{DivMod2Tuple}.
|
|
1029
1052
|
'''
|
|
1030
1053
|
# result mostly follows CPython function U{float_divmod
|
|
1031
1054
|
# <https://GitHub.com/python/cpython/blob/main/Objects/floatobject.c>},
|
|
1032
1055
|
# but at least divmod(-3, 2) equals Cpython's result (-2, 1).
|
|
1033
|
-
|
|
1034
|
-
q =
|
|
1056
|
+
q = self._copy_2(self._fdivmod2)
|
|
1057
|
+
q = q._ftruediv(other, op, **raiser_RESIDUAL).floor
|
|
1035
1058
|
if q: # == float // other == floor(float / other)
|
|
1036
|
-
self -= other * q
|
|
1059
|
+
self -= Fsum(other) * q # NO Fsum2Tuple.__mul__!
|
|
1037
1060
|
|
|
1038
1061
|
s = signOf(other) # make signOf(self) == signOf(other)
|
|
1039
1062
|
if s and self.signOf() == -s: # PYCHOK no cover
|
|
@@ -1052,29 +1075,34 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1052
1075
|
raise ValueError(_not_finite_) if op is None else \
|
|
1053
1076
|
self._ValueError(op, other, txt=_not_finite_)
|
|
1054
1077
|
|
|
1055
|
-
def fint(self,
|
|
1078
|
+
def fint(self, name=NN, **raiser_RESIDUAL):
|
|
1056
1079
|
'''Return this instance' current running sum as C{integer}.
|
|
1057
1080
|
|
|
1058
|
-
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
1059
|
-
(C{bool}), see also method L{RESIDUAL}.
|
|
1060
1081
|
@kwarg name: Optional name (C{str}), overriding C{"fint"}.
|
|
1082
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
1083
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
1084
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1061
1085
|
|
|
1062
|
-
@return: The C{integer} (L{Fsum})
|
|
1086
|
+
@return: The C{integer} sum (L{Fsum}) if this instance C{is_integer}
|
|
1087
|
+
with a zero or insignificant I{integer} residual.
|
|
1063
1088
|
|
|
1064
|
-
@raise ResidualError: Non-zero
|
|
1089
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1090
|
+
B{C{RESIDUAL}}.
|
|
1065
1091
|
|
|
1066
1092
|
@see: Methods L{Fsum.int_float} and L{Fsum.is_integer}.
|
|
1067
1093
|
'''
|
|
1068
1094
|
i, r = self._fint2
|
|
1069
|
-
if r
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1095
|
+
if r:
|
|
1096
|
+
R = self._raiser(r, i, **raiser_RESIDUAL)
|
|
1097
|
+
if R:
|
|
1098
|
+
t = _stresidual(_integer_, r, **R)
|
|
1099
|
+
raise ResidualError(_integer_, i, txt=t)
|
|
1100
|
+
f = self._copy_2(self.fint, name=name)
|
|
1073
1101
|
return f._fset(i)
|
|
1074
1102
|
|
|
1075
1103
|
def fint2(self, **name):
|
|
1076
|
-
'''Return this instance' current running sum as C{int} and
|
|
1077
|
-
|
|
1104
|
+
'''Return this instance' current running sum as C{int} and the
|
|
1105
|
+
I{integer} residual.
|
|
1078
1106
|
|
|
1079
1107
|
@kwarg name: Optional name (C{str}).
|
|
1080
1108
|
|
|
@@ -1116,10 +1144,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1116
1144
|
|
|
1117
1145
|
# floordiv = __floordiv__ # for naming consistency
|
|
1118
1146
|
|
|
1119
|
-
def _floordiv(self, other, op, **
|
|
1147
|
+
def _floordiv(self, other, op, **raiser_RESIDUAL): # rather _ffloordiv?
|
|
1120
1148
|
'''Apply C{B{self} //= B{other}}.
|
|
1121
1149
|
'''
|
|
1122
|
-
q = self._ftruediv(other, op, **
|
|
1150
|
+
q = self._ftruediv(other, op, **raiser_RESIDUAL) # == self
|
|
1123
1151
|
return self._fset(q.floor) # floor(q)
|
|
1124
1152
|
|
|
1125
1153
|
fmul = __imul__ # for backward compatibility
|
|
@@ -1127,7 +1155,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1127
1155
|
def _fmul(self, other, op):
|
|
1128
1156
|
'''(INTERNAL) Apply C{B{self} *= B{other}}.
|
|
1129
1157
|
'''
|
|
1130
|
-
if
|
|
1158
|
+
if _isFsumTuple(other):
|
|
1131
1159
|
if len(self._ps) != 1:
|
|
1132
1160
|
f = self._mul_Fsum(other, op)
|
|
1133
1161
|
elif len(other._ps) != 1: # and len(self._ps) == 1
|
|
@@ -1139,37 +1167,41 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1139
1167
|
f = self._mul_scalar(s, op)
|
|
1140
1168
|
return self._fset(f) # n=len(self) + 1
|
|
1141
1169
|
|
|
1142
|
-
def fover(self, over, **
|
|
1170
|
+
def fover(self, over, **raiser_RESIDUAL):
|
|
1143
1171
|
'''Apply C{B{self} /= B{over}} and summate.
|
|
1144
1172
|
|
|
1145
1173
|
@arg over: An L{Fsum} or C{scalar} denominator.
|
|
1146
|
-
@kwarg
|
|
1147
|
-
|
|
1174
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
1175
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
1176
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1148
1177
|
|
|
1149
1178
|
@return: Precision running sum (C{float}).
|
|
1150
1179
|
|
|
1180
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1181
|
+
B{C{RESIDUAL}}.
|
|
1182
|
+
|
|
1151
1183
|
@see: Methods L{Fsum.fsum} and L{Fsum.__itruediv__}.
|
|
1152
1184
|
'''
|
|
1153
|
-
return float(self.fdiv(over, **
|
|
1185
|
+
return float(self.fdiv(over, **raiser_RESIDUAL)._fprs)
|
|
1154
1186
|
|
|
1155
1187
|
fpow = __ipow__ # for backward compatibility
|
|
1156
1188
|
|
|
1157
|
-
def _fpow(self, other, op, *mod, **
|
|
1189
|
+
def _fpow(self, other, op, *mod, **raiser_RESIDUAL):
|
|
1158
1190
|
'''Apply C{B{self} **= B{other}}, optional B{C{mod}} or C{None}.
|
|
1159
1191
|
'''
|
|
1160
1192
|
if mod:
|
|
1161
1193
|
if mod[0] is not None: # == 3-arg C{pow}
|
|
1162
|
-
f = self._pow_2_3(self, other, other, op, *mod, **
|
|
1194
|
+
f = self._pow_2_3(self, other, other, op, *mod, **raiser_RESIDUAL)
|
|
1163
1195
|
elif self.is_integer():
|
|
1164
1196
|
# return an exact C{int} for C{int}**C{int}
|
|
1165
1197
|
i, _ = self._fint2 # assert _ == 0
|
|
1166
|
-
x =
|
|
1167
|
-
f =
|
|
1168
|
-
|
|
1198
|
+
x, r = _2scalar2(other) # C{int}, C{float} or other
|
|
1199
|
+
f = _Psum_(i)._pow_Fsum(other, op, **raiser_RESIDUAL) if r else \
|
|
1200
|
+
self._pow_2_3(i, x, other, op, **raiser_RESIDUAL)
|
|
1169
1201
|
else: # mod[0] is None, power(self, other)
|
|
1170
|
-
f = self._pow(other, other, op, **
|
|
1202
|
+
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1171
1203
|
else: # pow(self, other)
|
|
1172
|
-
f = self._pow(other, other, op, **
|
|
1204
|
+
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1173
1205
|
return self._fset(f, asis=isint(f)) # n=max(len(self), 1)
|
|
1174
1206
|
|
|
1175
1207
|
@Property_RO
|
|
@@ -1193,11 +1225,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1193
1225
|
s = _psum(ps)
|
|
1194
1226
|
n = len(ps) - 2
|
|
1195
1227
|
if n > 0:
|
|
1196
|
-
r = _fsum(self._ps_1primed(s))
|
|
1197
|
-
return Fsum2Tuple(s, r)
|
|
1228
|
+
r = _fsum(self._ps_1primed(s))
|
|
1229
|
+
return Fsum2Tuple(*_s_r(s, r))
|
|
1198
1230
|
if n == 0: # len(ps) == 2
|
|
1199
|
-
|
|
1200
|
-
|
|
1231
|
+
s, r = _s_r(*_2sum(*ps))
|
|
1232
|
+
ps[:] = (r, s) if r else (s,)
|
|
1201
1233
|
elif ps: # len(ps) == 1
|
|
1202
1234
|
s, r = ps[0], INT0
|
|
1203
1235
|
else: # len(ps) == 0
|
|
@@ -1206,33 +1238,26 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1206
1238
|
# assert self._ps is ps
|
|
1207
1239
|
return Fsum2Tuple(s, r)
|
|
1208
1240
|
|
|
1209
|
-
# def _fpsqz(self):
|
|
1210
|
-
# '''(INTERNAL) Compress, squeeze the C{partials}.
|
|
1211
|
-
# '''
|
|
1212
|
-
# if len(self._ps) > 2:
|
|
1213
|
-
# _ = self._fprs2
|
|
1214
|
-
# return self
|
|
1215
|
-
|
|
1216
1241
|
def fset_(self, *xs):
|
|
1217
1242
|
'''Replace this instance' value with C{xs}.
|
|
1218
1243
|
|
|
1219
|
-
@arg xs: Optional, new values (C{scalar} or
|
|
1220
|
-
|
|
1244
|
+
@arg xs: Optional, new values (each C{scalar} or
|
|
1245
|
+
an L{Fsum} or L{Fsum2Tuple} instance),
|
|
1246
|
+
all positional.
|
|
1221
1247
|
|
|
1222
1248
|
@return: This instance (C{Fsum}).
|
|
1223
1249
|
|
|
1224
1250
|
@see: Method L{Fsum.fadd} for further details.
|
|
1225
1251
|
'''
|
|
1226
|
-
|
|
1227
|
-
self.
|
|
1228
|
-
return self.fadd(xs) if xs else self._update()
|
|
1252
|
+
f = Fsum(*xs) if xs else _0_0
|
|
1253
|
+
return self._fset(f)
|
|
1229
1254
|
|
|
1230
1255
|
def _fset(self, other, asis=True, n=0):
|
|
1231
1256
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
1232
1257
|
'''
|
|
1233
1258
|
if other is self:
|
|
1234
1259
|
pass # from ._fmul, ._ftruediv and ._pow_0_1
|
|
1235
|
-
elif
|
|
1260
|
+
elif _isFsumTuple(other):
|
|
1236
1261
|
self._ps[:] = other._ps
|
|
1237
1262
|
self._n = n or other._n
|
|
1238
1263
|
# self._copy_RESIDUAL(other)
|
|
@@ -1250,13 +1275,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1250
1275
|
# Property's _fset zaps the value just set by the @setter
|
|
1251
1276
|
self.__dict__.update(_fint2=t, _fprs=s, _fprs2=Fsum2Tuple(s, INT0))
|
|
1252
1277
|
else: # PYCHOK no cover
|
|
1253
|
-
raise self.
|
|
1278
|
+
raise self._Error(_fset_op_, other, _AssertionError)
|
|
1254
1279
|
return self
|
|
1255
1280
|
|
|
1256
1281
|
def _fset_ps(self, other, n=0): # in .fmath
|
|
1257
|
-
'''(INTERNAL) Set partials from a known C{Fsum} or
|
|
1282
|
+
'''(INTERNAL) Set partials from a known C{scalar}, L{Fsum} or L{Fsum2Tuple}.
|
|
1258
1283
|
'''
|
|
1259
|
-
if
|
|
1284
|
+
if _isFsumTuple(other):
|
|
1260
1285
|
self._ps[:] = other._ps
|
|
1261
1286
|
self._n = n or other._n
|
|
1262
1287
|
else: # assert isscalar(other)
|
|
@@ -1264,36 +1289,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1264
1289
|
self._n = n or 1
|
|
1265
1290
|
return self
|
|
1266
1291
|
|
|
1267
|
-
def _fset_ps_(self, *xs):
|
|
1268
|
-
'''(INTERNAL) Set partials to all known scalar C{xs}.
|
|
1269
|
-
'''
|
|
1270
|
-
self._ps[:] = xs
|
|
1271
|
-
self.n = len(xs)
|
|
1272
|
-
return self
|
|
1273
|
-
|
|
1274
1292
|
def fsub(self, xs=()):
|
|
1275
|
-
'''Subtract
|
|
1276
|
-
this instance.
|
|
1277
|
-
|
|
1278
|
-
@arg xs: Iterable, list, tuple. etc. (C{scalar} or L{Fsum}
|
|
1279
|
-
instances).
|
|
1293
|
+
'''Subtract all items of an iterable from this instance.
|
|
1280
1294
|
|
|
1281
|
-
@
|
|
1282
|
-
|
|
1283
|
-
@see: Method L{Fsum.fadd}.
|
|
1295
|
+
@see: Method L{Fsum.fadd} for further details.
|
|
1284
1296
|
'''
|
|
1285
1297
|
return self._facc_neg(xs)
|
|
1286
1298
|
|
|
1287
1299
|
def fsub_(self, *xs):
|
|
1288
|
-
'''Subtract all positional
|
|
1289
|
-
this instance.
|
|
1290
|
-
|
|
1291
|
-
@arg xs: Values to subtract (C{scalar} or L{Fsum} instances),
|
|
1292
|
-
all positional.
|
|
1293
|
-
|
|
1294
|
-
@return: This instance, updated (L{Fsum}).
|
|
1300
|
+
'''Subtract all positional arguments from this instance.
|
|
1295
1301
|
|
|
1296
|
-
@see: Method L{Fsum.
|
|
1302
|
+
@see: Method L{Fsum.fadd_} for further details.
|
|
1297
1303
|
'''
|
|
1298
1304
|
return self._fsub(xs[0], _sub_op_) if len(xs) == 1 else \
|
|
1299
1305
|
self._facc_neg(xs, origin=1)
|
|
@@ -1301,20 +1307,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1301
1307
|
def _fsub(self, other, op):
|
|
1302
1308
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
1303
1309
|
'''
|
|
1304
|
-
if
|
|
1310
|
+
if _isFsumTuple(other):
|
|
1305
1311
|
if other is self: # or other._fprs2 == self._fprs2:
|
|
1306
|
-
self._fset(_0_0
|
|
1312
|
+
self._fset(_0_0, n=len(self) * 2)
|
|
1307
1313
|
elif other._ps:
|
|
1308
1314
|
self._facc_scalar(other._ps_neg)
|
|
1309
1315
|
elif self._scalar(other, op):
|
|
1310
|
-
self._facc_scalar_(-
|
|
1316
|
+
self._facc_scalar_(-other)
|
|
1311
1317
|
return self
|
|
1312
1318
|
|
|
1313
1319
|
def fsum(self, xs=()):
|
|
1314
|
-
'''Add more
|
|
1320
|
+
'''Add more items from an iterable, summate and return
|
|
1321
|
+
the current precision running sum.
|
|
1315
1322
|
|
|
1316
|
-
@
|
|
1317
|
-
|
|
1323
|
+
@arg xs: Iterable of items to add (each item C{scalar}
|
|
1324
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
1318
1325
|
|
|
1319
1326
|
@return: Precision running sum (C{float} or C{int}).
|
|
1320
1327
|
|
|
@@ -1325,10 +1332,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1325
1332
|
return self._facc(xs)._fprs
|
|
1326
1333
|
|
|
1327
1334
|
def fsum_(self, *xs):
|
|
1328
|
-
'''Add
|
|
1335
|
+
'''Add any positional arguments, summate and return the
|
|
1336
|
+
current precision running sum.
|
|
1329
1337
|
|
|
1330
|
-
@arg xs: Values to add (C{scalar} or L{Fsum}
|
|
1331
|
-
positional.
|
|
1338
|
+
@arg xs: Values to add (each C{scalar} or an L{Fsum}
|
|
1339
|
+
or L{Fsum2Tuple} instance), all positional.
|
|
1332
1340
|
|
|
1333
1341
|
@return: Precision running sum (C{float} or C{int}).
|
|
1334
1342
|
|
|
@@ -1336,19 +1344,36 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1336
1344
|
'''
|
|
1337
1345
|
return self._facc_1(xs)._fprs
|
|
1338
1346
|
|
|
1339
|
-
|
|
1340
|
-
|
|
1347
|
+
@property_RO
|
|
1348
|
+
def _Fsum(self):
|
|
1349
|
+
'''(INTERNAL) Like L{Fsum2Tuple._Fsum}, for C{_2floats}.
|
|
1350
|
+
'''
|
|
1351
|
+
return self
|
|
1352
|
+
|
|
1353
|
+
def Fsum_(self, *xs, **name):
|
|
1354
|
+
'''Like method L{Fsum.fsum_} but returning a named L{Fsum}.
|
|
1355
|
+
|
|
1356
|
+
@kwarg name: Optional name (C{str}).
|
|
1341
1357
|
|
|
1342
1358
|
@return: Current, precision running sum (L{Fsum}).
|
|
1343
1359
|
'''
|
|
1344
|
-
return self._facc_1(xs)._copy_2(self.Fsum_)
|
|
1360
|
+
return self._facc_1(xs)._copy_2(self.Fsum_, **name)
|
|
1361
|
+
|
|
1362
|
+
def Fsum2Tuple_(self, *xs, **name):
|
|
1363
|
+
'''Like method L{Fsum.fsum_} but returning a named L{Fsum2Tuple}.
|
|
1364
|
+
|
|
1365
|
+
@kwarg name: Optional name (C{str}).
|
|
1366
|
+
|
|
1367
|
+
@return: Current, precision running sum (L{Fsum2Tuple}).
|
|
1368
|
+
'''
|
|
1369
|
+
return Fsum2Tuple(self._facc_1(xs)._fprs2, **name)
|
|
1345
1370
|
|
|
1346
1371
|
def fsum2(self, xs=(), name=NN):
|
|
1347
|
-
'''Add more
|
|
1348
|
-
current precision running sum and the C{residual}.
|
|
1372
|
+
'''Add more items from an iterable, summate and return the
|
|
1373
|
+
current precision running sum I{and} the C{residual}.
|
|
1349
1374
|
|
|
1350
|
-
@
|
|
1351
|
-
|
|
1375
|
+
@arg xs: Iterable of items to add (each item C{scalar}
|
|
1376
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
1352
1377
|
@kwarg name: Optional name (C{str}).
|
|
1353
1378
|
|
|
1354
1379
|
@return: L{Fsum2Tuple}C{(fsum, residual)} with C{fsum} the
|
|
@@ -1363,11 +1388,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1363
1388
|
return t.dup(name=name) if name else t
|
|
1364
1389
|
|
|
1365
1390
|
def fsum2_(self, *xs):
|
|
1366
|
-
'''Add any positional
|
|
1367
|
-
|
|
1391
|
+
'''Add any positional arguments, summate and return the current
|
|
1392
|
+
precision running sum I{and} the C{differential}.
|
|
1368
1393
|
|
|
1369
|
-
@arg xs: Values to add (C{scalar} or L{Fsum}
|
|
1370
|
-
positional.
|
|
1394
|
+
@arg xs: Values to add (each C{scalar} or an L{Fsum} or
|
|
1395
|
+
L{Fsum2Tuple} instance), all positional.
|
|
1371
1396
|
|
|
1372
1397
|
@return: 2Tuple C{(fsum, delta)} with the current, precision
|
|
1373
1398
|
running C{fsum} like method L{Fsum.fsum} and C{delta},
|
|
@@ -1388,37 +1413,35 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1388
1413
|
return p, _0_0
|
|
1389
1414
|
|
|
1390
1415
|
def fsumf_(self, *xs):
|
|
1391
|
-
'''Like method L{Fsum.fsum_}
|
|
1416
|
+
'''Like method L{Fsum.fsum_} iff I{all} C{B{xs}} are I{known to be scalar}.
|
|
1392
1417
|
'''
|
|
1393
1418
|
return self._facc_scalar(xs)._fprs
|
|
1394
1419
|
|
|
1395
1420
|
def Fsumf_(self, *xs):
|
|
1396
|
-
'''Like method L{Fsum.Fsum_}
|
|
1421
|
+
'''Like method L{Fsum.Fsum_} iff I{all} C{B{xs}} are I{known to be scalar}.
|
|
1397
1422
|
'''
|
|
1398
1423
|
return self._facc_scalar(xs)._copy_2(self.Fsumf_)
|
|
1399
1424
|
|
|
1400
1425
|
def fsum2f_(self, *xs):
|
|
1401
|
-
'''Like method L{Fsum.fsum2_}
|
|
1426
|
+
'''Like method L{Fsum.fsum2_} iff I{all} C{B{xs}} are I{known to be scalar}.
|
|
1402
1427
|
'''
|
|
1403
1428
|
return self._fsum2(xs, self._facc_scalar, origin=1)
|
|
1404
1429
|
|
|
1405
1430
|
# ftruediv = __itruediv__ # for naming consistency?
|
|
1406
1431
|
|
|
1407
|
-
def _ftruediv(self, other, op, **
|
|
1432
|
+
def _ftruediv(self, other, op, **raiser_RESIDUAL):
|
|
1408
1433
|
'''(INTERNAL) Apply C{B{self} /= B{other}}.
|
|
1409
1434
|
'''
|
|
1410
1435
|
n = _1_0
|
|
1411
|
-
if
|
|
1412
|
-
if other is self or
|
|
1436
|
+
if _isFsumTuple(other):
|
|
1437
|
+
if other is self or self == other:
|
|
1413
1438
|
return self._fset(n) # n=len(self)
|
|
1414
1439
|
d, r = other._fprs2
|
|
1415
1440
|
if r:
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
else: # PYCHOK no cover
|
|
1421
|
-
d = r
|
|
1441
|
+
R = self._raiser(r, d, **raiser_RESIDUAL)
|
|
1442
|
+
if R:
|
|
1443
|
+
raise self._ResidualError(op, other, r, **R)
|
|
1444
|
+
d, n = other.as_integer_ratio()
|
|
1422
1445
|
else:
|
|
1423
1446
|
d = self._scalar(other, op)
|
|
1424
1447
|
try:
|
|
@@ -1436,26 +1459,31 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1436
1459
|
'''
|
|
1437
1460
|
return _0_0
|
|
1438
1461
|
|
|
1439
|
-
def int_float(self,
|
|
1462
|
+
def int_float(self, **raiser_RESIDUAL):
|
|
1440
1463
|
'''Return this instance' current running sum as C{int} or C{float}.
|
|
1441
1464
|
|
|
1442
|
-
@kwarg
|
|
1443
|
-
|
|
1465
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
1466
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
1467
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1444
1468
|
|
|
1445
1469
|
@return: This C{integer} sum if this instance C{is_integer},
|
|
1446
|
-
otherwise return the C{float} sum if the residual
|
|
1447
|
-
|
|
1470
|
+
otherwise return the C{float} sum if the residual is
|
|
1471
|
+
zero or not significant.
|
|
1448
1472
|
|
|
1449
|
-
@raise ResidualError: Non-zero residual
|
|
1473
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1474
|
+
B{C{RESIDUAL}}.
|
|
1450
1475
|
|
|
1451
|
-
@see: Methods L{Fsum.fint}
|
|
1476
|
+
@see: Methods L{Fsum.fint}, L{Fsum.fint2}, L{Fsum.RESIDUAL} and
|
|
1477
|
+
property L{Fsum.as_iscalar}.
|
|
1452
1478
|
'''
|
|
1453
1479
|
s, r = self._fint2
|
|
1454
1480
|
if r:
|
|
1455
1481
|
s, r = self._fprs2
|
|
1456
|
-
if r
|
|
1457
|
-
|
|
1458
|
-
|
|
1482
|
+
if r: # PYCHOK no cover
|
|
1483
|
+
R = self._raiser(r, s, **raiser_RESIDUAL)
|
|
1484
|
+
if R:
|
|
1485
|
+
t = _stresidual(_non_zero_, r, **R)
|
|
1486
|
+
raise ResidualError(int_float=s, txt=t)
|
|
1459
1487
|
s = float(s) # redundant
|
|
1460
1488
|
return s
|
|
1461
1489
|
|
|
@@ -1467,7 +1495,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1467
1495
|
def is_integer(self):
|
|
1468
1496
|
'''Is this instance' running sum C{integer}? (C{bool}).
|
|
1469
1497
|
|
|
1470
|
-
@see: Methods L{Fsum.fint} and L{Fsum.
|
|
1498
|
+
@see: Methods L{Fsum.fint}, L{Fsum.fint2} and L{Fsum.is_scalar}.
|
|
1471
1499
|
'''
|
|
1472
1500
|
_, r = self._fint2
|
|
1473
1501
|
return False if r else True
|
|
@@ -1486,12 +1514,30 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1486
1514
|
f = Fsum._math_fsum
|
|
1487
1515
|
return 2 if _psum is f else bool(f)
|
|
1488
1516
|
|
|
1517
|
+
def is_scalar(self, **raiser_RESIDUAL):
|
|
1518
|
+
'''Is this instance' running sum C{scalar} with an insignificant
|
|
1519
|
+
residual and the residual I{ratio} not exceeding the RESIDUAL
|
|
1520
|
+
threshold? (C{bool}).
|
|
1521
|
+
|
|
1522
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
1523
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
1524
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1525
|
+
|
|
1526
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1527
|
+
B{C{RESIDUAL}}.
|
|
1528
|
+
|
|
1529
|
+
@see: Method L{Fsum.RESIDUAL}, L{Fsum.is_integer} and property
|
|
1530
|
+
L{Fsum.as_iscalar}.
|
|
1531
|
+
'''
|
|
1532
|
+
s, r = self._fprs2
|
|
1533
|
+
return False if r and self._raiser(r, s, **raiser_RESIDUAL) else True
|
|
1534
|
+
|
|
1489
1535
|
def _mul_Fsum(self, other, op=_mul_op_): # in .fmath.Fhorner
|
|
1490
|
-
'''(INTERNAL) Return C{B{self} *
|
|
1536
|
+
'''(INTERNAL) Return C{B{self} * B{other}} as L{Fsum} or C{0}.
|
|
1491
1537
|
'''
|
|
1492
|
-
# assert
|
|
1538
|
+
# assert _isFsumTuple(other)
|
|
1493
1539
|
if self._ps and other._ps:
|
|
1494
|
-
f = self._ps_mul(op, *other._ps) # NO .
|
|
1540
|
+
f = self._ps_mul(op, *other._ps) # NO .as_iscalar
|
|
1495
1541
|
else:
|
|
1496
1542
|
f = _0_0
|
|
1497
1543
|
return f
|
|
@@ -1503,7 +1549,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1503
1549
|
if self._ps and self._finite(factor, op):
|
|
1504
1550
|
f = self if factor == _1_0 else (
|
|
1505
1551
|
self._neg if factor == _N_1_0 else
|
|
1506
|
-
self._ps_mul(op, factor).
|
|
1552
|
+
self._ps_mul(op, factor).as_iscalar)
|
|
1507
1553
|
else:
|
|
1508
1554
|
f = _0_0
|
|
1509
1555
|
return f
|
|
@@ -1520,18 +1566,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1520
1566
|
'''
|
|
1521
1567
|
return tuple(self._ps)
|
|
1522
1568
|
|
|
1523
|
-
def pow(self, x, *mod, **
|
|
1569
|
+
def pow(self, x, *mod, **raiser_RESIDUAL):
|
|
1524
1570
|
'''Return C{B{self}**B{x}} as L{Fsum}.
|
|
1525
1571
|
|
|
1526
|
-
@arg x: The exponent (
|
|
1572
|
+
@arg x: The exponent (C{scalar} or L{Fsum}).
|
|
1527
1573
|
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
1528
1574
|
C{pow(B{self}, B{other}, B{mod})} version.
|
|
1529
|
-
@kwarg
|
|
1530
|
-
|
|
1575
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
1576
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
1577
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1531
1578
|
|
|
1532
1579
|
@return: The C{pow(self, B{x})} or C{pow(self, B{x}, *B{mod})}
|
|
1533
1580
|
result (L{Fsum}).
|
|
1534
1581
|
|
|
1582
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1583
|
+
B{C{RESIDUAL}}.
|
|
1584
|
+
|
|
1535
1585
|
@note: If B{C{mod}} is given as C{None}, the result will be an
|
|
1536
1586
|
C{integer} L{Fsum} provided this instance C{is_integer}
|
|
1537
1587
|
or set to C{integer} by an L{Fsum.fint} call.
|
|
@@ -1540,21 +1590,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1540
1590
|
and L{Fsum.root}.
|
|
1541
1591
|
'''
|
|
1542
1592
|
f = self._copy_2(self.pow)
|
|
1543
|
-
return f._fpow(x, _pow_op_, *mod, **
|
|
1593
|
+
return f._fpow(x, _pow_op_, *mod, **raiser_RESIDUAL) # f = pow(f, x, *mod)
|
|
1544
1594
|
|
|
1545
|
-
def _pow(self, other, unused, op, **
|
|
1595
|
+
def _pow(self, other, unused, op, **raiser_RESIDUAL):
|
|
1546
1596
|
'''Return C{B{self} ** B{other}}.
|
|
1547
1597
|
'''
|
|
1548
|
-
if
|
|
1549
|
-
|
|
1550
|
-
if r and self._raiser(r, x, **raiser):
|
|
1551
|
-
raise self._ResidualError(op, other, r)
|
|
1552
|
-
f = self._pow_scalar(x, other, op, **raiser)
|
|
1553
|
-
if r:
|
|
1554
|
-
f *= self._pow_scalar(r, other, op, **raiser)
|
|
1598
|
+
if _isFsumTuple(other):
|
|
1599
|
+
f = self._pow_Fsum(other, op, **raiser_RESIDUAL)
|
|
1555
1600
|
elif self._scalar(other, op):
|
|
1556
1601
|
x = self._finite(other, op)
|
|
1557
|
-
f = self._pow_scalar(x, other, op, **
|
|
1602
|
+
f = self._pow_scalar(x, other, op, **raiser_RESIDUAL)
|
|
1558
1603
|
else:
|
|
1559
1604
|
f = self._pow_0_1(0, other)
|
|
1560
1605
|
return f
|
|
@@ -1564,18 +1609,25 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1564
1609
|
'''
|
|
1565
1610
|
return self if x else (1 if isint(other) and self.is_integer() else _1_0)
|
|
1566
1611
|
|
|
1567
|
-
def _pow_2_3(self, b, x, other, op, *mod, **
|
|
1612
|
+
def _pow_2_3(self, b, x, other, op, *mod, **raiser_RESIDUAL):
|
|
1568
1613
|
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} and 3-arg C{pow(B{b},
|
|
1569
1614
|
B{x}, int B{mod} or C{None})}, embellishing errors.
|
|
1570
1615
|
'''
|
|
1616
|
+
|
|
1617
|
+
if mod: # b, x, mod all C{int}, unless C{mod} is C{None}
|
|
1618
|
+
m = mod[0]
|
|
1619
|
+
# assert _isFsumTuple(b)
|
|
1620
|
+
|
|
1621
|
+
def _s(s, r):
|
|
1622
|
+
R = self._raiser(r, s, **raiser_RESIDUAL)
|
|
1623
|
+
if R:
|
|
1624
|
+
raise self._ResidualError(op, other, r, mod=m, **R)
|
|
1625
|
+
return s
|
|
1626
|
+
|
|
1627
|
+
b = _s(*(b._fprs2 if m is None else b._fint2))
|
|
1628
|
+
x = _s(*_2scalar2(x))
|
|
1629
|
+
|
|
1571
1630
|
try:
|
|
1572
|
-
if mod: # b, x, mod all C{int}, unless C{mod} is C{None}
|
|
1573
|
-
m = mod[0]
|
|
1574
|
-
b, r = b._fprs2 if m is None else b._fint2
|
|
1575
|
-
if r and self._raiser(r, b, **raiser):
|
|
1576
|
-
t = _non_zero_ if m is None else _integer_
|
|
1577
|
-
raise ResidualError(_stresidual(t, r, mod=m), txt=None)
|
|
1578
|
-
x = _2scalar(x, _raiser=self._raiser, mod=m)
|
|
1579
1631
|
# 0**INF == 0.0, 1**INF == 1.0, -1**2.3 == -(1**2.3)
|
|
1580
1632
|
s = pow(b, x, *mod)
|
|
1581
1633
|
if iscomplex(s):
|
|
@@ -1585,7 +1637,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1585
1637
|
except Exception as X:
|
|
1586
1638
|
raise self._ErrorX(X, op, other, *mod)
|
|
1587
1639
|
|
|
1588
|
-
def
|
|
1640
|
+
def _pow_Fsum(self, other, op, **raiser_RESIDUAL):
|
|
1641
|
+
'''(INTERNAL) Return C{B{self} **= B{other}} for C{_isFsumTuple(other)}.
|
|
1642
|
+
'''
|
|
1643
|
+
# assert _isFsumTuple(other)
|
|
1644
|
+
x, r = other._fprs2
|
|
1645
|
+
f = self._pow_scalar(x, other, op, **raiser_RESIDUAL)
|
|
1646
|
+
if f and r:
|
|
1647
|
+
f *= self._pow_scalar(r, other, op, **raiser_RESIDUAL)
|
|
1648
|
+
return f
|
|
1649
|
+
|
|
1650
|
+
def _pow_int(self, x, other, op, **raiser_RESIDUAL):
|
|
1589
1651
|
'''(INTERNAL) Return C{B{self} **= B{x}} for C{int B{x} >= 0}.
|
|
1590
1652
|
'''
|
|
1591
1653
|
# assert isint(x) and x >= 0
|
|
@@ -1594,7 +1656,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1594
1656
|
_mul_Fsum = Fsum._mul_Fsum
|
|
1595
1657
|
if x > 4:
|
|
1596
1658
|
p = self
|
|
1597
|
-
f = self if (x & 1) else
|
|
1659
|
+
f = self if (x & 1) else _Psum_(_1_0)
|
|
1598
1660
|
m = x >> 1 # // 2
|
|
1599
1661
|
while m:
|
|
1600
1662
|
p = _mul_Fsum(p, p, op) # p **= 2
|
|
@@ -1605,49 +1667,56 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1605
1667
|
f = _mul_Fsum(self, self, op)
|
|
1606
1668
|
if x > 2: # self**3 or 4
|
|
1607
1669
|
p = self if x < 4 else f
|
|
1608
|
-
f = _mul_Fsum(f, p, op).
|
|
1670
|
+
f = _mul_Fsum(f, p, op).as_iscalar
|
|
1609
1671
|
else: # self**1 or self**0 == 1 or _1_0
|
|
1610
1672
|
f = self._pow_0_1(x, other)
|
|
1611
1673
|
elif ps: # self._ps[0]**x
|
|
1612
|
-
f = self._pow_2_3(ps[0], x, other, op, **
|
|
1674
|
+
f = self._pow_2_3(ps[0], x, other, op, **raiser_RESIDUAL)
|
|
1613
1675
|
else: # PYCHOK no cover
|
|
1614
1676
|
# 0**pos_int == 0, but 0**0 == 1
|
|
1615
1677
|
f = 0 if x else 1
|
|
1616
1678
|
return f
|
|
1617
1679
|
|
|
1618
|
-
def _pow_scalar(self, x, other, op, **
|
|
1680
|
+
def _pow_scalar(self, x, other, op, **raiser_RESIDUAL):
|
|
1619
1681
|
'''(INTERNAL) Return C{self**B{x}} for C{scalar B{x}}.
|
|
1620
1682
|
'''
|
|
1621
1683
|
s, r = self._fprs2
|
|
1622
|
-
if
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
if
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1684
|
+
if r:
|
|
1685
|
+
# assert s != 0
|
|
1686
|
+
if isint(x, both=True): # self**int
|
|
1687
|
+
x = int(x)
|
|
1688
|
+
y = abs(x)
|
|
1689
|
+
if y > 1:
|
|
1690
|
+
f = self._pow_int(y, other, op, **raiser_RESIDUAL)
|
|
1691
|
+
if x > 0: # i.e. > 1
|
|
1692
|
+
return f # Fsum or scalar
|
|
1693
|
+
# assert x < 0 # i.e. < -1
|
|
1694
|
+
if _isFsum(f):
|
|
1695
|
+
s, r = f._fprs2
|
|
1696
|
+
if r:
|
|
1697
|
+
return _1_Over(f, op, **raiser_RESIDUAL)
|
|
1698
|
+
else: # scalar
|
|
1699
|
+
s = f
|
|
1700
|
+
# use s**(-1) to get the CPython
|
|
1701
|
+
# float_pow error iff s is zero
|
|
1636
1702
|
x = -1
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1703
|
+
elif x < 0: # self**(-1)
|
|
1704
|
+
return _1_Over(self, op, **raiser_RESIDUAL) # 1 / self
|
|
1705
|
+
else: # self**1 or self**0
|
|
1706
|
+
return self._pow_0_1(x, other) # self, 1 or 1.0
|
|
1707
|
+
else: # self**fractional
|
|
1708
|
+
R = self._raiser(r, s, **raiser_RESIDUAL)
|
|
1709
|
+
if R:
|
|
1710
|
+
raise self._ResidualError(op, other, r, **R)
|
|
1711
|
+
n, d = self.as_integer_ratio()
|
|
1712
|
+
if abs(n) > abs(d):
|
|
1713
|
+
n, d, x = d, n, (-x)
|
|
1714
|
+
s = n / d
|
|
1646
1715
|
# assert isscalar(s) and isscalar(x)
|
|
1647
|
-
return self._pow_2_3(s, x, other, op, **
|
|
1716
|
+
return self._pow_2_3(s, x, other, op, **raiser_RESIDUAL)
|
|
1648
1717
|
|
|
1649
1718
|
def _ps_acc(self, ps, xs, up=True, **unused):
|
|
1650
|
-
'''(INTERNAL) Accumulate all
|
|
1719
|
+
'''(INTERNAL) Accumulate all C{xs} scalars into list C{ps}.
|
|
1651
1720
|
'''
|
|
1652
1721
|
n = 0
|
|
1653
1722
|
_2s = _2sum
|
|
@@ -1670,8 +1739,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1670
1739
|
return ps
|
|
1671
1740
|
|
|
1672
1741
|
def _ps_mul(self, op, *factors):
|
|
1673
|
-
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1674
|
-
|
|
1742
|
+
'''(INTERNAL) Multiply this instance' C{partials} with each
|
|
1743
|
+
of the scalar B{C{factors}} and accumulate.
|
|
1675
1744
|
'''
|
|
1676
1745
|
def _pfs(ps, fs):
|
|
1677
1746
|
if len(ps) < len(fs):
|
|
@@ -1682,7 +1751,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1682
1751
|
p *= f
|
|
1683
1752
|
yield p if _fin(p) else self._finite(p, op)
|
|
1684
1753
|
|
|
1685
|
-
return _Psum(self._ps_acc([], _pfs(self._ps, factors)))
|
|
1754
|
+
return _Psum(self._ps_acc([], _pfs(self._ps, factors), up=False))
|
|
1686
1755
|
|
|
1687
1756
|
@property_RO
|
|
1688
1757
|
def _ps_neg(self):
|
|
@@ -1692,7 +1761,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1692
1761
|
yield -p
|
|
1693
1762
|
|
|
1694
1763
|
def _ps_1primed(self, *less):
|
|
1695
|
-
'''(INTERNAL) Yield partials, 1-primed
|
|
1764
|
+
'''(INTERNAL) Yield partials, 1-primed C{less} any scalars.
|
|
1696
1765
|
'''
|
|
1697
1766
|
yield _1_0
|
|
1698
1767
|
for p in self._ps:
|
|
@@ -1701,11 +1770,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1701
1770
|
yield -p
|
|
1702
1771
|
yield _N_1_0
|
|
1703
1772
|
|
|
1704
|
-
def _raiser(self, r, s, raiser=True):
|
|
1705
|
-
'''(INTERNAL) Does ratio C{r / s} exceed the RESIDUAL threshold
|
|
1773
|
+
def _raiser(self, r, s, raiser=True, **RESIDUAL):
|
|
1774
|
+
'''(INTERNAL) Does ratio C{r / s} exceed the RESIDUAL threshold
|
|
1775
|
+
I{and} is residual C{r} I{non-zero} or I{significant} (for a
|
|
1776
|
+
negative respectively positive C{RESIDUAL} threshold)?
|
|
1706
1777
|
'''
|
|
1707
|
-
|
|
1708
|
-
|
|
1778
|
+
if r and raiser:
|
|
1779
|
+
t = self._RESIDUAL
|
|
1780
|
+
if RESIDUAL:
|
|
1781
|
+
t = _threshold(_xkwds_get(RESIDUAL, RESIDUAL=t))
|
|
1782
|
+
if t < 0 or (s + r) != s:
|
|
1783
|
+
q = (r / s) if s else s # == 0.
|
|
1784
|
+
if fabs(q) > fabs(t):
|
|
1785
|
+
return dict(ratio=q, R=t)
|
|
1786
|
+
return {}
|
|
1709
1787
|
|
|
1710
1788
|
@property_RO
|
|
1711
1789
|
def real(self):
|
|
@@ -1719,10 +1797,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1719
1797
|
|
|
1720
1798
|
@property_RO
|
|
1721
1799
|
def residual(self):
|
|
1722
|
-
'''Get this instance' residual (C{float} or C{int})
|
|
1800
|
+
'''Get this instance' residual (C{float} or C{int}): the
|
|
1723
1801
|
C{sum(partials)} less the precision running sum C{fsum}.
|
|
1724
1802
|
|
|
1725
|
-
@note:
|
|
1803
|
+
@note: The C{residual is INT0} iff the precision running
|
|
1726
1804
|
C{fsum} is considered to be I{exact}.
|
|
1727
1805
|
|
|
1728
1806
|
@see: Methods L{Fsum.fsum}, L{Fsum.fsum2} and L{Fsum.is_exact}.
|
|
@@ -1739,56 +1817,54 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1739
1817
|
C{PYGEODESY_FSUM_RESIDUAL} or if omitted, keep the
|
|
1740
1818
|
current setting.
|
|
1741
1819
|
|
|
1742
|
-
@return: The previous C{RESIDUAL} setting (C{float}), default C{0.}.
|
|
1820
|
+
@return: The previous C{RESIDUAL} setting (C{float}), default C{0.0}.
|
|
1743
1821
|
|
|
1744
|
-
@raise
|
|
1822
|
+
@raise ResidualError: Invalid B{C{threshold}}.
|
|
1745
1823
|
|
|
1746
|
-
@note: L{ResidualError}s
|
|
1747
|
-
C{residual / fsum} exceeds the B{C{threshold}}
|
|
1824
|
+
@note: L{ResidualError}s may be thrown if the non-zero I{ratio}
|
|
1825
|
+
C{residual / fsum} exceeds the given B{C{threshold}} and
|
|
1826
|
+
if the C{residual} is non-zero and I{significant} vs the
|
|
1827
|
+
C{fsum}, i.e. C{(fsum + residual) != fsum} and if optional
|
|
1828
|
+
keyword argument C{raiser=False} is missing. Specify a
|
|
1829
|
+
negative B{C{threshold}} for only non-zero C{residual}
|
|
1830
|
+
testing without I{significant}.
|
|
1748
1831
|
'''
|
|
1749
1832
|
r = self._RESIDUAL
|
|
1750
1833
|
if threshold:
|
|
1751
1834
|
t = threshold[0]
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
if t < 0:
|
|
1756
|
-
u = _DOT_(self, unstr(self.RESIDUAL, *threshold))
|
|
1757
|
-
raise _ValueError(u, RESIDUAL=t, txt=_negative_)
|
|
1758
|
-
self._RESIDUAL = t
|
|
1835
|
+
self._RESIDUAL = Fsum._RESIDUAL if t is None else ( # for ...
|
|
1836
|
+
(_0_0 if t else _1_0) if isbool(t) else
|
|
1837
|
+
_threshold(t)) # ... backward compatibility
|
|
1759
1838
|
return r
|
|
1760
1839
|
|
|
1761
|
-
def _ResidualError(self, op, other, residual):
|
|
1840
|
+
def _ResidualError(self, op, other, residual, **mod_R):
|
|
1762
1841
|
'''(INTERNAL) Non-zero B{C{residual}} etc.
|
|
1763
1842
|
'''
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1843
|
+
def _p(mod=None, R=0, **unused): # ratio=0
|
|
1844
|
+
return (_non_zero_ if R < 0 else _significant_) \
|
|
1845
|
+
if mod is None else _integer_
|
|
1846
|
+
|
|
1847
|
+
t = _stresidual(_p(**mod_R), residual, **mod_R)
|
|
1767
1848
|
return self._Error(op, other, ResidualError, txt=t)
|
|
1768
1849
|
|
|
1769
|
-
def root(self, root, **
|
|
1850
|
+
def root(self, root, **raiser_RESIDUAL):
|
|
1770
1851
|
'''Return C{B{self}**(1 / B{root})} as L{Fsum}.
|
|
1771
1852
|
|
|
1772
|
-
@arg root: The order (C{scalar} or
|
|
1773
|
-
@kwarg
|
|
1774
|
-
|
|
1853
|
+
@arg root: The order (C{scalar} or L{Fsum}), non-zero.
|
|
1854
|
+
@kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
|
|
1855
|
+
ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
|
|
1856
|
+
to override the L{RESIDUAL<Fsum.RESIDUAL>}.
|
|
1775
1857
|
|
|
1776
1858
|
@return: The C{self ** (1 / B{root})} result (L{Fsum}).
|
|
1777
1859
|
|
|
1860
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1861
|
+
B{C{RESIDUAL}}.
|
|
1862
|
+
|
|
1778
1863
|
@see: Method L{Fsum.pow}.
|
|
1779
1864
|
'''
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
else:
|
|
1784
|
-
try:
|
|
1785
|
-
x = _1_0 / _2float(root=root)
|
|
1786
|
-
except Exception as X:
|
|
1787
|
-
E, t = _xError2(X)
|
|
1788
|
-
n = _SPACE_(_1_0, _truediv_op_, _root_)
|
|
1789
|
-
raise E(n, root, txt=t, cause=X)
|
|
1790
|
-
f = self._copy_2(self.root)
|
|
1791
|
-
return f._fpow(x, _root_, **raiser) # == pow(f, x)
|
|
1865
|
+
x = _1_Over(root, _truediv_op_, **raiser_RESIDUAL)
|
|
1866
|
+
f = self._copy_2(self.root)
|
|
1867
|
+
return f._fpow(x, f.name, **raiser_RESIDUAL) # == pow(f, x)
|
|
1792
1868
|
|
|
1793
1869
|
def _scalar(self, other, op, **txt):
|
|
1794
1870
|
'''(INTERNAL) Return scalar C{other}.
|
|
@@ -1797,13 +1873,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1797
1873
|
return other
|
|
1798
1874
|
raise self._TypeError(op, other, **txt) # _invalid_
|
|
1799
1875
|
|
|
1800
|
-
@property_RO
|
|
1801
|
-
def _2scalar(self):
|
|
1802
|
-
'''(INTERNAL) Get this instance as C{scalar} or C{as-is}.
|
|
1803
|
-
'''
|
|
1804
|
-
s, r = self._fprs2
|
|
1805
|
-
return self if r else s
|
|
1806
|
-
|
|
1807
1876
|
def signOf(self, res=True):
|
|
1808
1877
|
'''Determine the sign of this instance.
|
|
1809
1878
|
|
|
@@ -1813,7 +1882,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1813
1882
|
@return: The sign (C{int}, -1, 0 or +1).
|
|
1814
1883
|
'''
|
|
1815
1884
|
s, r = self._fprs2
|
|
1816
|
-
|
|
1885
|
+
r = (-r) if res else 0
|
|
1886
|
+
return _signOf(s, r)
|
|
1817
1887
|
|
|
1818
1888
|
def toRepr(self, **prec_sep_fmt_lenc): # PYCHOK signature
|
|
1819
1889
|
'''Return this C{Fsum} instance as representation.
|
|
@@ -1842,10 +1912,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1842
1912
|
def _toT(self, toT, fmt=Fmt.g, lenc=True, **kwds):
|
|
1843
1913
|
'''(INTERNAL) Helper for C{toRepr} and C{toStr}.
|
|
1844
1914
|
'''
|
|
1845
|
-
|
|
1915
|
+
p = self.classname
|
|
1846
1916
|
if lenc:
|
|
1847
|
-
|
|
1848
|
-
|
|
1917
|
+
p = Fmt.SQUARE(p, len(self))
|
|
1918
|
+
n = self.name
|
|
1919
|
+
if n:
|
|
1920
|
+
n = _UNDER_(*n.split())
|
|
1921
|
+
return NN(p, _SPACE_, n, toT(fmt=fmt, **kwds))
|
|
1849
1922
|
|
|
1850
1923
|
def _TypeError(self, op, other, **txt): # PYCHOK no cover
|
|
1851
1924
|
'''(INTERNAL) Return a C{TypeError}.
|
|
@@ -1874,7 +1947,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1874
1947
|
'''
|
|
1875
1948
|
return self._Error(op, other, _ZeroDivisionError, **txt)
|
|
1876
1949
|
|
|
1877
|
-
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK
|
|
1950
|
+
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK see Fsum._update
|
|
1878
1951
|
|
|
1879
1952
|
|
|
1880
1953
|
def _Float_Int(arg, **name_Error):
|
|
@@ -1888,8 +1961,8 @@ class DivMod2Tuple(_NamedTuple):
|
|
|
1888
1961
|
'''2-Tuple C{(div, mod)} with the quotient C{div} and remainder
|
|
1889
1962
|
C{mod} results of a C{divmod} operation.
|
|
1890
1963
|
|
|
1891
|
-
@note: Quotient C{div} an C{int} in Python 3+
|
|
1892
|
-
Python 2-. Remainder C{mod} an L{Fsum} instance.
|
|
1964
|
+
@note: Quotient C{div} an C{int} in Python 3+ but a C{float}
|
|
1965
|
+
in Python 2-. Remainder C{mod} an L{Fsum} instance.
|
|
1893
1966
|
'''
|
|
1894
1967
|
_Names_ = (_div_, _mod_)
|
|
1895
1968
|
_Units_ = (_Float_Int, Fsum)
|
|
@@ -1898,7 +1971,7 @@ class DivMod2Tuple(_NamedTuple):
|
|
|
1898
1971
|
class Fsum2Tuple(_NamedTuple):
|
|
1899
1972
|
'''2-Tuple C{(fsum, residual)} with the precision running C{fsum}
|
|
1900
1973
|
and the C{residual}, the sum of the remaining partials. Each
|
|
1901
|
-
item is
|
|
1974
|
+
item is C{float} or C{int}.
|
|
1902
1975
|
|
|
1903
1976
|
@note: If the C{residual is INT0}, the C{fsum} is considered
|
|
1904
1977
|
to be I{exact}, see method L{Fsum2Tuple.is_exact}.
|
|
@@ -1906,27 +1979,61 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
1906
1979
|
_Names_ = ( Fsum.fsum.__name__, Fsum.residual.name)
|
|
1907
1980
|
_Units_ = (_Float_Int, _Float_Int)
|
|
1908
1981
|
|
|
1982
|
+
def as_integer_ratio(self):
|
|
1983
|
+
'''Return this instance as the ratio of 2 integers.
|
|
1984
|
+
|
|
1985
|
+
@see: Method L{Fsum.as_integer_ratio} for further details.
|
|
1986
|
+
'''
|
|
1987
|
+
return self._Fsum.as_integer_ratio()
|
|
1988
|
+
|
|
1989
|
+
@property_RO
|
|
1990
|
+
def _fint2(self):
|
|
1991
|
+
return self._Fsum.fint2
|
|
1992
|
+
|
|
1993
|
+
@property_RO
|
|
1994
|
+
def _fprs2(self):
|
|
1995
|
+
return self._Fsum._fprs2
|
|
1996
|
+
|
|
1909
1997
|
@Property_RO
|
|
1910
1998
|
def _Fsum(self):
|
|
1911
|
-
|
|
1912
|
-
'''
|
|
1913
|
-
s, r = map(float, self)
|
|
1914
|
-
return _Psum(_2ps(s, r), name=self.name)
|
|
1999
|
+
return Fsum(*self)
|
|
1915
2000
|
|
|
1916
2001
|
def is_exact(self):
|
|
1917
2002
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
1918
2003
|
'''
|
|
1919
|
-
|
|
2004
|
+
_, r = _s_r(*self)
|
|
2005
|
+
return False if r else True
|
|
1920
2006
|
|
|
1921
2007
|
def is_integer(self):
|
|
1922
2008
|
'''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
|
|
1923
2009
|
'''
|
|
1924
|
-
|
|
2010
|
+
s, r = _s_r(*self)
|
|
2011
|
+
return False if r else isint(s, both=True)
|
|
2012
|
+
|
|
2013
|
+
@property_RO
|
|
2014
|
+
def _n(self):
|
|
2015
|
+
return self._Fsum._n
|
|
2016
|
+
|
|
2017
|
+
@property_RO
|
|
2018
|
+
def _ps(self):
|
|
2019
|
+
return self._Fsum._ps
|
|
2020
|
+
|
|
2021
|
+
@property_RO
|
|
2022
|
+
def _ps_neg(self):
|
|
2023
|
+
return self._Fsum._ps_neg
|
|
2024
|
+
|
|
2025
|
+
def signOf(self, **res):
|
|
2026
|
+
'''Like L{Fsum.signOf}.
|
|
2027
|
+
'''
|
|
2028
|
+
return self._Fsum.signOf(**res)
|
|
2029
|
+
|
|
2030
|
+
_Fsum_Fsum2Tuple_types = Fsum, Fsum2Tuple # PYCHOK line
|
|
1925
2031
|
|
|
1926
2032
|
|
|
1927
2033
|
class ResidualError(_ValueError):
|
|
1928
|
-
'''Error raised for
|
|
1929
|
-
instance with a
|
|
2034
|
+
'''Error raised for a division, power or root operation of
|
|
2035
|
+
an L{Fsum} instance with a C{residual} I{ratio} exceeding
|
|
2036
|
+
the L{RESIDUAL<Fsum.RESIDUAL>} threshold.
|
|
1930
2037
|
|
|
1931
2038
|
@see: Module L{pygeodesy.fsums} and method L{Fsum.RESIDUAL}.
|
|
1932
2039
|
'''
|
|
@@ -1943,64 +2050,59 @@ try:
|
|
|
1943
2050
|
raise ImportError # ... use _fsum below
|
|
1944
2051
|
|
|
1945
2052
|
Fsum._math_fsum = _sum = _fsum # PYCHOK exported
|
|
1946
|
-
|
|
1947
|
-
if _getenv('PYGEODESY_FSUM_PARTIALS', NN) == _fsum.__name__:
|
|
1948
|
-
_psum = _fsum # PYCHOK re-def
|
|
1949
|
-
|
|
1950
2053
|
except ImportError:
|
|
1951
2054
|
_sum = sum # Fsum(NAN) exception fall-back, in .elliptic
|
|
1952
2055
|
|
|
1953
2056
|
def _fsum(xs):
|
|
1954
2057
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
1955
2058
|
'''
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
return
|
|
2059
|
+
F = Fsum()
|
|
2060
|
+
F.name = _fsum.__name__
|
|
2061
|
+
return F._facc(xs, up=False)._fprs2.fsum
|
|
1959
2062
|
|
|
1960
2063
|
|
|
1961
2064
|
def fsum(xs, floats=False):
|
|
1962
|
-
'''Precision floating point summation based on
|
|
2065
|
+
'''Precision floating point summation based on/like Python's C{math.fsum}.
|
|
1963
2066
|
|
|
1964
|
-
@arg xs: Iterable
|
|
1965
|
-
|
|
1966
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
1967
|
-
to be
|
|
2067
|
+
@arg xs: Iterable of items to add (each C{scalar} or an L{Fsum} or
|
|
2068
|
+
L{Fsum2Tuple} instance).
|
|
2069
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
|
|
2070
|
+
I{known to be scalar} (C{bool}).
|
|
1968
2071
|
|
|
1969
2072
|
@return: Precision C{fsum} (C{float}).
|
|
1970
2073
|
|
|
1971
2074
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
1972
2075
|
|
|
1973
|
-
@raise TypeError: Non-scalar B{C{xs}}
|
|
2076
|
+
@raise TypeError: Non-scalar B{C{xs}} item.
|
|
1974
2077
|
|
|
1975
|
-
@raise ValueError: Invalid or non-finite B{C{xs}}
|
|
2078
|
+
@raise ValueError: Invalid or non-finite B{C{xs}} item.
|
|
1976
2079
|
|
|
1977
2080
|
@note: Exception and I{non-finite} handling may differ if not based
|
|
1978
2081
|
on Python's C{math.fsum}.
|
|
1979
2082
|
|
|
1980
2083
|
@see: Class L{Fsum} and methods L{Fsum.fsum} and L{Fsum.fadd}.
|
|
1981
2084
|
'''
|
|
1982
|
-
return _fsum(xs if floats else _2floats(xs)) if xs else _0_0 # PYCHOK yield
|
|
2085
|
+
return _fsum(xs if floats is True else _2floats(xs)) if xs else _0_0 # PYCHOK yield
|
|
1983
2086
|
|
|
1984
2087
|
|
|
1985
2088
|
def fsum_(*xs, **floats):
|
|
1986
2089
|
'''Precision floating point summation of all positional arguments.
|
|
1987
2090
|
|
|
1988
|
-
@arg xs:
|
|
1989
|
-
positional.
|
|
1990
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
1991
|
-
to be scalar} (C{bool}).
|
|
2091
|
+
@arg xs: Items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
2092
|
+
instance), all positional.
|
|
2093
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
|
|
2094
|
+
I{known to be scalar} (C{bool}).
|
|
1992
2095
|
|
|
1993
|
-
@
|
|
1994
|
-
|
|
1995
|
-
@see: Function C{fsum}.
|
|
2096
|
+
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
1996
2097
|
'''
|
|
1997
|
-
return _fsum(xs if _xkwds_get(floats, floats=False) else
|
|
2098
|
+
return _fsum(xs if _xkwds_get(floats, floats=False) is True else
|
|
1998
2099
|
_2floats(xs, origin=1)) if xs else _0_0 # PYCHOK yield
|
|
1999
2100
|
|
|
2000
2101
|
|
|
2001
2102
|
def fsumf_(*xs):
|
|
2002
|
-
'''Precision floating point summation
|
|
2003
|
-
|
|
2103
|
+
'''Precision floating point summation iff I{all} C{B{xs}} items are I{known to be scalar}.
|
|
2104
|
+
|
|
2105
|
+
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2004
2106
|
'''
|
|
2005
2107
|
return _fsum(xs) if xs else _0_0
|
|
2006
2108
|
|
|
@@ -2008,64 +2110,55 @@ def fsumf_(*xs):
|
|
|
2008
2110
|
def fsum1(xs, floats=False):
|
|
2009
2111
|
'''Precision floating point summation, 1-primed.
|
|
2010
2112
|
|
|
2011
|
-
@arg xs: Iterable
|
|
2012
|
-
|
|
2013
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
2014
|
-
to be C{
|
|
2113
|
+
@arg xs: Iterable of items to add (each C{scalar} or an L{Fsum} or
|
|
2114
|
+
L{Fsum2Tuple} instance).
|
|
2115
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
|
|
2116
|
+
I{known to be scalar} (C{bool}).
|
|
2015
2117
|
|
|
2016
|
-
@
|
|
2017
|
-
|
|
2018
|
-
@see: Function C{fsum}.
|
|
2118
|
+
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2019
2119
|
'''
|
|
2020
|
-
return _fsum(_1primed(xs if floats else _2floats(xs))) if xs else _0_0 # PYCHOK yield
|
|
2120
|
+
return _fsum(_1primed(xs if floats is True else _2floats(xs))) if xs else _0_0 # PYCHOK yield
|
|
2021
2121
|
|
|
2022
2122
|
|
|
2023
2123
|
def fsum1_(*xs, **floats):
|
|
2024
|
-
'''Precision floating point summation, 1-primed.
|
|
2124
|
+
'''Precision floating point summation, 1-primed of all positional arguments.
|
|
2025
2125
|
|
|
2026
|
-
@arg xs:
|
|
2027
|
-
positional.
|
|
2028
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
2029
|
-
to be scalar} (C{bool}).
|
|
2126
|
+
@arg xs: Items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
2127
|
+
instance), all positional.
|
|
2128
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
|
|
2129
|
+
I{known to be scalar} (C{bool}).
|
|
2030
2130
|
|
|
2031
|
-
@
|
|
2032
|
-
|
|
2033
|
-
@see: Function C{fsum}
|
|
2131
|
+
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2034
2132
|
'''
|
|
2035
|
-
return _fsum(_1primed(xs if _xkwds_get(floats, floats=False) else
|
|
2133
|
+
return _fsum(_1primed(xs if _xkwds_get(floats, floats=False) is True else
|
|
2036
2134
|
_2floats(xs, origin=1))) if xs else _0_0 # PYCHOK yield
|
|
2037
2135
|
|
|
2038
2136
|
|
|
2039
2137
|
def fsum1f_(*xs):
|
|
2040
|
-
'''Precision floating point summation
|
|
2041
|
-
|
|
2138
|
+
'''Precision floating point summation iff I{all} C{B{xs}} are I{known to be scalar}.
|
|
2139
|
+
|
|
2140
|
+
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2042
2141
|
'''
|
|
2043
2142
|
return _fsum(_1primed(xs)) if xs else _0_0
|
|
2044
2143
|
|
|
2045
2144
|
|
|
2046
2145
|
if __name__ == '__main__':
|
|
2047
2146
|
|
|
2048
|
-
# usage: [env
|
|
2147
|
+
# usage: [env _psum=fsum] python3 -m pygeodesy.fsums
|
|
2148
|
+
|
|
2149
|
+
if _getenv(_psum.__name__, NN) == _fsum.__name__:
|
|
2150
|
+
_psum = _fsum
|
|
2049
2151
|
|
|
2050
2152
|
def _test(n):
|
|
2051
2153
|
# copied from Hettinger, see L{Fsum} reference
|
|
2052
|
-
from pygeodesy import printf
|
|
2053
|
-
from random import gauss, random, shuffle
|
|
2154
|
+
from pygeodesy import frandoms, printf
|
|
2054
2155
|
|
|
2055
2156
|
printf(_fsum.__name__, end=_COMMASPACE_)
|
|
2056
2157
|
printf(_psum.__name__, end=_COMMASPACE_)
|
|
2057
2158
|
|
|
2058
2159
|
F = Fsum()
|
|
2059
2160
|
if F.is_math_fsum():
|
|
2060
|
-
|
|
2061
|
-
for _ in range(n):
|
|
2062
|
-
t = list(c)
|
|
2063
|
-
s = 0
|
|
2064
|
-
for _ in range(n * 8):
|
|
2065
|
-
v = gauss(0, random())**7 - s
|
|
2066
|
-
t.append(v)
|
|
2067
|
-
s += v
|
|
2068
|
-
shuffle(t)
|
|
2161
|
+
for t in frandoms(n, seeded=True):
|
|
2069
2162
|
assert float(F.fset_(*t)) == _fsum(t)
|
|
2070
2163
|
printf(_DOT_, end=NN)
|
|
2071
2164
|
printf(NN)
|