pygeodesy 24.4.24__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.24.dist-info → PyGeodesy-24.5.2.dist-info}/METADATA +2 -2
- {PyGeodesy-24.4.24.dist-info → PyGeodesy-24.5.2.dist-info}/RECORD +12 -12
- pygeodesy/__init__.py +1 -2
- pygeodesy/auxilats/auxAngle.py +3 -3
- pygeodesy/basics.py +2 -2
- pygeodesy/fstats.py +3 -3
- pygeodesy/fsums.py +564 -488
- pygeodesy/interns.py +0 -1
- pygeodesy/streprs.py +3 -1
- pygeodesy/triaxials.py +5 -5
- {PyGeodesy-24.4.24.dist-info → PyGeodesy-24.5.2.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.4.24.dist-info → PyGeodesy-24.5.2.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -14,28 +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
30
|
from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
|
|
33
31
|
_ValueError, _xError, _xError2, _xkwds_get, \
|
|
34
32
|
_ZeroDivisionError
|
|
35
|
-
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DASH_, _DOT_,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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_
|
|
39
37
|
from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
|
|
40
38
|
from pygeodesy.named import _Named, _NamedTuple, _NotImplemented, Fmt, unstr
|
|
41
39
|
from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
@@ -46,30 +44,32 @@ from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
|
46
44
|
from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
|
|
47
45
|
|
|
48
46
|
__all__ = _ALL_LAZY.fsums
|
|
49
|
-
__version__ = '24.
|
|
50
|
-
|
|
51
|
-
_add_op_
|
|
52
|
-
_eq_op_
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
_le_op_
|
|
62
|
-
_lt_op_
|
|
63
|
-
_mod_
|
|
64
|
-
_mod_op_
|
|
65
|
-
_mul_op_
|
|
66
|
-
_ne_op_
|
|
67
|
-
_non_zero_
|
|
68
|
-
_pow_op_
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
def _2delta(*ab):
|
|
@@ -83,7 +83,7 @@ def _2delta(*ab):
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
def _2error(unused):
|
|
86
|
-
'''(INTERNAL) Throw a C{not
|
|
86
|
+
'''(INTERNAL) Throw a C{not-finite} exception.
|
|
87
87
|
'''
|
|
88
88
|
raise ValueError(_not_finite_)
|
|
89
89
|
|
|
@@ -109,10 +109,11 @@ def _2floats(xs, origin=0, _X=_X_ps, _x=float):
|
|
|
109
109
|
try:
|
|
110
110
|
i, x = origin, None
|
|
111
111
|
_fin = _isfinite
|
|
112
|
-
|
|
112
|
+
_FsT = _Fsum_Fsum2Tuple_types
|
|
113
|
+
_is = _isinstance
|
|
113
114
|
for x in xs:
|
|
114
|
-
if
|
|
115
|
-
for p in _X(x):
|
|
115
|
+
if _is(x, _FsT):
|
|
116
|
+
for p in _X(x._Fsum):
|
|
116
117
|
yield p
|
|
117
118
|
else:
|
|
118
119
|
f = _x(x)
|
|
@@ -146,10 +147,22 @@ def _2halfeven(s, r, p):
|
|
|
146
147
|
return s
|
|
147
148
|
|
|
148
149
|
|
|
149
|
-
def
|
|
150
|
-
'''(INTERNAL)
|
|
150
|
+
def _isFsum(x):
|
|
151
|
+
'''(INTERNAL) Is C{x} an C{Fsum} instance?
|
|
151
152
|
'''
|
|
152
|
-
return
|
|
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)
|
|
153
166
|
|
|
154
167
|
|
|
155
168
|
def _1primed(xs): # in .fmath
|
|
@@ -162,18 +175,10 @@ def _1primed(xs): # in .fmath
|
|
|
162
175
|
yield _N_1_0
|
|
163
176
|
|
|
164
177
|
|
|
165
|
-
def _2ps(s, r):
|
|
166
|
-
'''(INTERNAL) Return an C{s} and C{r} pair, I{ps-ordered}.
|
|
167
|
-
'''
|
|
168
|
-
if fabs(s) < fabs(r):
|
|
169
|
-
s, r = r, s
|
|
170
|
-
return (r, s) if r else (s,) # PYCHOK types
|
|
171
|
-
|
|
172
|
-
|
|
173
178
|
def _psum(ps): # PYCHOK used!
|
|
174
|
-
'''(INTERNAL) Partials
|
|
179
|
+
'''(INTERNAL) Partials summation, updating C{ps}.
|
|
175
180
|
'''
|
|
176
|
-
# assert
|
|
181
|
+
# assert _isinstance(ps, list)
|
|
177
182
|
i = len(ps) - 1
|
|
178
183
|
s = _0_0 if i < 0 else ps[i]
|
|
179
184
|
_2s = _2sum
|
|
@@ -207,23 +212,33 @@ def _Psum_(*ps, **name):
|
|
|
207
212
|
return _Psum(ps, **name)
|
|
208
213
|
|
|
209
214
|
|
|
210
|
-
def
|
|
211
|
-
'''(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}.
|
|
212
218
|
'''
|
|
213
|
-
if
|
|
219
|
+
if _isFsumTuple(other):
|
|
214
220
|
s, r = other._fint2
|
|
215
221
|
if r:
|
|
216
222
|
s, r = other._fprs2
|
|
217
223
|
if r: # PYCHOK no cover
|
|
218
|
-
if _raiser and _raiser(r, s):
|
|
219
|
-
t = _stresidual(_non_zero_, r, **mod)
|
|
220
|
-
raise ResidualError(t, txt=None)
|
|
221
224
|
s = other # L{Fsum} as-is
|
|
222
225
|
else:
|
|
226
|
+
r = 0
|
|
223
227
|
s = other # C{type} as-is
|
|
224
228
|
if isint(s, both=True):
|
|
225
229
|
s = int(s)
|
|
226
|
-
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
|
|
227
242
|
|
|
228
243
|
|
|
229
244
|
def _strcomplex(s, *args):
|
|
@@ -235,16 +250,15 @@ def _strcomplex(s, *args):
|
|
|
235
250
|
return _SPACE_(c, s, _from_, n, t)
|
|
236
251
|
|
|
237
252
|
|
|
238
|
-
def _stresidual(prefix, residual, **
|
|
239
|
-
'''(INTERNAL) Residual error
|
|
253
|
+
def _stresidual(prefix, residual, R=0, **mod_ratio):
|
|
254
|
+
'''(INTERNAL) Residual error txt C{str}.
|
|
240
255
|
'''
|
|
241
256
|
p = _stresidual.__name__[3:]
|
|
242
257
|
t = Fmt.PARENSPACED(p, Fmt(residual))
|
|
243
|
-
for n, v in itemsorted(
|
|
244
|
-
n = n.replace(_UNDER_, _SPACE_)
|
|
258
|
+
for n, v in itemsorted(mod_ratio):
|
|
245
259
|
p = Fmt.PARENSPACED(n, Fmt(v))
|
|
246
260
|
t = _COMMASPACE_(t, p)
|
|
247
|
-
return _SPACE_(prefix, t)
|
|
261
|
+
return _SPACE_(prefix, t, Fmt.exceeds_R(R), _threshold_)
|
|
248
262
|
|
|
249
263
|
|
|
250
264
|
def _2sum(a, b): # by .testFmath
|
|
@@ -260,6 +274,16 @@ def _2sum(a, b): # by .testFmath
|
|
|
260
274
|
raise _OverflowError(u, txt=t)
|
|
261
275
|
|
|
262
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
|
+
|
|
263
287
|
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
264
288
|
'''Precision floating point summation and I{running} summation.
|
|
265
289
|
|
|
@@ -267,8 +291,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
267
291
|
I{running}, precision floating point summations. Accumulation may continue after any
|
|
268
292
|
intermediate, I{running} summuation.
|
|
269
293
|
|
|
270
|
-
@note:
|
|
271
|
-
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}.
|
|
272
297
|
|
|
273
298
|
@note: Handling of exceptions and C{inf}, C{INF}, C{nan} and C{NAN} differs from
|
|
274
299
|
Python's C{math.fsum}.
|
|
@@ -281,44 +306,46 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
281
306
|
<https://Bugs.Python.org/issue2819>}.
|
|
282
307
|
'''
|
|
283
308
|
_math_fsum = None
|
|
284
|
-
_n =
|
|
309
|
+
_n = 0
|
|
285
310
|
# _ps = [] # partial sums
|
|
286
|
-
# _ps_max =
|
|
287
|
-
|
|
288
|
-
_recursive = bool(_getenv('PYGEODESY_FSUM_RECURSIVE', NN))
|
|
289
|
-
_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))
|
|
290
313
|
|
|
291
314
|
def __init__(self, *xs, **name_RESIDUAL):
|
|
292
315
|
'''New L{Fsum} for I{running} precision floating point summation.
|
|
293
316
|
|
|
294
|
-
@arg xs: No, one or more
|
|
295
|
-
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.
|
|
296
319
|
@kwarg name_RESIDUAL: Optional C{B{name}=NN} for this L{Fsum} and
|
|
297
|
-
C{B{RESIDUAL}=
|
|
320
|
+
the C{B{RESIDUAL}=0.0} threshold for L{ResidualError}s.
|
|
298
321
|
|
|
299
322
|
@see: Methods L{Fsum.fadd} and L{Fsum.RESIDUAL}.
|
|
300
323
|
'''
|
|
301
324
|
if name_RESIDUAL:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
325
|
+
|
|
326
|
+
def _n_r(name=NN, RESIDUAL=None):
|
|
327
|
+
return name, RESIDUAL
|
|
328
|
+
|
|
329
|
+
n, r = _n_r(**name_RESIDUAL)
|
|
306
330
|
if r is not None:
|
|
307
|
-
self.RESIDUAL(r)
|
|
331
|
+
self.RESIDUAL(r)
|
|
332
|
+
if n:
|
|
333
|
+
self.name = n
|
|
334
|
+
|
|
308
335
|
self._ps = [] # [_0_0], see L{Fsum._fprs}
|
|
309
336
|
if xs:
|
|
310
|
-
self.
|
|
337
|
+
self._facc_1(xs, up=False)
|
|
311
338
|
|
|
312
339
|
def __abs__(self):
|
|
313
340
|
'''Return this instance' absolute value as an L{Fsum}.
|
|
314
341
|
'''
|
|
315
|
-
s =
|
|
342
|
+
s = self.signOf() # == self._cmp_0(0)
|
|
316
343
|
return (-self) if s < 0 else self._copy_2(self.__abs__)
|
|
317
344
|
|
|
318
345
|
def __add__(self, other):
|
|
319
346
|
'''Return C{B{self} + B{other}} as an L{Fsum}.
|
|
320
347
|
|
|
321
|
-
@arg other: An L{Fsum} or C{scalar}.
|
|
348
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar}.
|
|
322
349
|
|
|
323
350
|
@return: The sum (L{Fsum}).
|
|
324
351
|
|
|
@@ -352,19 +379,23 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
352
379
|
s = self._cmp_0(other, self.cmp.__name__)
|
|
353
380
|
return _signOf(s, 0)
|
|
354
381
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
def __divmod__(self, other):
|
|
382
|
+
def __divmod__(self, other, **raiser_RESIDUAL):
|
|
358
383
|
'''Return C{divmod(B{self}, B{other})} as a L{DivMod2Tuple}
|
|
359
384
|
with quotient C{div} an C{int} in Python 3+ or C{float}
|
|
360
|
-
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>}.
|
|
361
391
|
|
|
362
|
-
@
|
|
392
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
393
|
+
B{C{RESIDUAL}}.
|
|
363
394
|
|
|
364
395
|
@see: Method L{Fsum.__itruediv__}.
|
|
365
396
|
'''
|
|
366
397
|
f = self._copy_2(self.__divmod__)
|
|
367
|
-
return f._fdivmod2(other, _divmod_op_)
|
|
398
|
+
return f._fdivmod2(other, _divmod_op_, **raiser_RESIDUAL)
|
|
368
399
|
|
|
369
400
|
def __eq__(self, other):
|
|
370
401
|
'''Compare this with an other instance or C{scalar}.
|
|
@@ -390,7 +421,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
390
421
|
def __floordiv__(self, other):
|
|
391
422
|
'''Return C{B{self} // B{other}} as an L{Fsum}.
|
|
392
423
|
|
|
393
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
424
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} divisor.
|
|
394
425
|
|
|
395
426
|
@return: The C{floor} quotient (L{Fsum}).
|
|
396
427
|
|
|
@@ -421,7 +452,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
421
452
|
def __iadd__(self, other):
|
|
422
453
|
'''Apply C{B{self} += B{other}} to this instance.
|
|
423
454
|
|
|
424
|
-
@arg other: An L{Fsum} or C{scalar} instance.
|
|
455
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} instance.
|
|
425
456
|
|
|
426
457
|
@return: This instance, updated (L{Fsum}).
|
|
427
458
|
|
|
@@ -435,11 +466,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
435
466
|
def __ifloordiv__(self, other):
|
|
436
467
|
'''Apply C{B{self} //= B{other}} to this instance.
|
|
437
468
|
|
|
438
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
469
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} divisor.
|
|
439
470
|
|
|
440
471
|
@return: This instance, updated (L{Fsum}).
|
|
441
472
|
|
|
442
|
-
@raise ResidualError: Non-zero residual
|
|
473
|
+
@raise ResidualError: Non-zero, significant residual
|
|
474
|
+
in B{C{other}}.
|
|
443
475
|
|
|
444
476
|
@raise TypeError: Invalid B{C{other}} type.
|
|
445
477
|
|
|
@@ -458,7 +490,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
458
490
|
def __imod__(self, other):
|
|
459
491
|
'''Apply C{B{self} %= B{other}} to this instance.
|
|
460
492
|
|
|
461
|
-
@arg other: An L{Fsum} or C{scalar} modulus.
|
|
493
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} modulus.
|
|
462
494
|
|
|
463
495
|
@return: This instance, updated (L{Fsum}).
|
|
464
496
|
|
|
@@ -469,7 +501,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
469
501
|
def __imul__(self, other):
|
|
470
502
|
'''Apply C{B{self} *= B{other}} to this instance.
|
|
471
503
|
|
|
472
|
-
@arg other: An L{Fsum} or C{scalar} factor.
|
|
504
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar} factor.
|
|
473
505
|
|
|
474
506
|
@return: This instance, updated (L{Fsum}).
|
|
475
507
|
|
|
@@ -496,49 +528,48 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
496
528
|
# Luciano Ramalho, "Fluent Python", O'Reilly, 2nd Ed, 2022 p. 567
|
|
497
529
|
return _NotImplemented(self)
|
|
498
530
|
|
|
499
|
-
def __ipow__(self, other, *mod, **
|
|
531
|
+
def __ipow__(self, other, *mod, **raiser_RESIDUAL): # PYCHOK 2 vs 3 args
|
|
500
532
|
'''Apply C{B{self} **= B{other}} to this instance.
|
|
501
533
|
|
|
502
|
-
@arg other: The exponent (L{Fsum} or
|
|
503
|
-
@arg mod: Optional modulus (C{int} or C{None}) for the
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
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>}.
|
|
508
540
|
|
|
509
541
|
@return: This instance, updated (L{Fsum}).
|
|
510
542
|
|
|
511
543
|
@note: If B{C{mod}} is given, the result will be an C{integer}
|
|
512
544
|
L{Fsum} in Python 3+ if this instance C{is_integer} or
|
|
513
|
-
set to C{as_integer}
|
|
545
|
+
set to C{as_integer} and B{C{mod}} is given as C{None}.
|
|
514
546
|
|
|
515
547
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
516
548
|
|
|
517
|
-
@raise ResidualError:
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
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}.
|
|
523
554
|
|
|
524
|
-
@raise TypeError: Invalid B{C{other}} type or 3-argument
|
|
525
|
-
|
|
555
|
+
@raise TypeError: Invalid B{C{other}} type or 3-argument C{pow}
|
|
556
|
+
invocation failed.
|
|
526
557
|
|
|
527
|
-
@raise ValueError: If B{C{other}} is a negative C{scalar}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
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}.
|
|
532
563
|
|
|
533
564
|
@see: CPython function U{float_pow<https://GitHub.com/
|
|
534
565
|
python/cpython/blob/main/Objects/floatobject.c>}.
|
|
535
566
|
'''
|
|
536
|
-
return self._fpow(other, _pow_op_ + _fset_op_, *mod, **
|
|
567
|
+
return self._fpow(other, _pow_op_ + _fset_op_, *mod, **raiser_RESIDUAL)
|
|
537
568
|
|
|
538
569
|
def __isub__(self, other):
|
|
539
570
|
'''Apply C{B{self} -= B{other}} to this instance.
|
|
540
571
|
|
|
541
|
-
@arg other: An L{Fsum} or C{scalar}.
|
|
572
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar}.
|
|
542
573
|
|
|
543
574
|
@return: This instance, updated (L{Fsum}).
|
|
544
575
|
|
|
@@ -553,19 +584,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
553
584
|
'''
|
|
554
585
|
return iter(self.partials)
|
|
555
586
|
|
|
556
|
-
def __itruediv__(self, other, **
|
|
587
|
+
def __itruediv__(self, other, **raiser_RESIDUAL):
|
|
557
588
|
'''Apply C{B{self} /= B{other}} to this instance.
|
|
558
589
|
|
|
559
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
560
|
-
@kwarg
|
|
561
|
-
|
|
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>}.
|
|
562
594
|
|
|
563
595
|
@return: This instance, updated (L{Fsum}).
|
|
564
596
|
|
|
565
597
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
566
598
|
|
|
567
|
-
@raise ResidualError: Non-zero residual
|
|
568
|
-
|
|
599
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
600
|
+
B{C{RESIDUAL}}.
|
|
569
601
|
|
|
570
602
|
@raise TypeError: Invalid B{C{other}} type.
|
|
571
603
|
|
|
@@ -575,7 +607,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
575
607
|
|
|
576
608
|
@see: Method L{Fsum.__ifloordiv__}.
|
|
577
609
|
'''
|
|
578
|
-
return self._ftruediv(other, _truediv_op_ + _fset_op_, **
|
|
610
|
+
return self._ftruediv(other, _truediv_op_ + _fset_op_, **raiser_RESIDUAL)
|
|
579
611
|
|
|
580
612
|
def __le__(self, other):
|
|
581
613
|
'''Compare this with an other instance or C{scalar}.
|
|
@@ -645,8 +677,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
645
677
|
return f._fadd(self, _add_op_)
|
|
646
678
|
|
|
647
679
|
def __rdivmod__(self, other):
|
|
648
|
-
'''Return C{divmod(B{other}, B{self})} as 2-tuple
|
|
649
|
-
remainder)}.
|
|
680
|
+
'''Return C{divmod(B{other}, B{self})} as 2-tuple
|
|
681
|
+
C{(quotient, remainder)}.
|
|
650
682
|
|
|
651
683
|
@see: Method L{Fsum.__divmod__}.
|
|
652
684
|
'''
|
|
@@ -686,14 +718,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
686
718
|
f = self._copy_2r(other, self.__rmul__)
|
|
687
719
|
return f._fmul(self, _mul_op_)
|
|
688
720
|
|
|
689
|
-
def __round__(self, *ndigits): # PYCHOK
|
|
721
|
+
def __round__(self, *ndigits): # PYCHOK Python 3+
|
|
690
722
|
'''Return C{round(B{self}, *B{ndigits}} as an L{Fsum}.
|
|
691
723
|
|
|
692
724
|
@arg ndigits: Optional number of digits (C{int}).
|
|
693
725
|
'''
|
|
726
|
+
f = self._copy_2(self.__round__)
|
|
694
727
|
# <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
|
|
695
|
-
return
|
|
696
|
-
name=self.__round__.__name__)
|
|
728
|
+
return f._fset(round(float(self), *ndigits)) # can be C{int}
|
|
697
729
|
|
|
698
730
|
def __rpow__(self, other, *mod):
|
|
699
731
|
'''Return C{B{other}**B{self}} as an L{Fsum}.
|
|
@@ -711,13 +743,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
711
743
|
f = self._copy_2r(other, self.__rsub__)
|
|
712
744
|
return f._fsub(self, _sub_op_)
|
|
713
745
|
|
|
714
|
-
def __rtruediv__(self, other, **
|
|
746
|
+
def __rtruediv__(self, other, **raiser_RESIDUAL):
|
|
715
747
|
'''Return C{B{other} / B{self}} as an L{Fsum}.
|
|
716
748
|
|
|
717
749
|
@see: Method L{Fsum.__itruediv__}.
|
|
718
750
|
'''
|
|
719
751
|
f = self._copy_2r(other, self.__rtruediv__)
|
|
720
|
-
return f._ftruediv(self, _truediv_op_, **
|
|
752
|
+
return f._ftruediv(self, _truediv_op_, **raiser_RESIDUAL)
|
|
721
753
|
|
|
722
754
|
def __str__(self):
|
|
723
755
|
'''Return the default C{str(self)}.
|
|
@@ -727,7 +759,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
727
759
|
def __sub__(self, other):
|
|
728
760
|
'''Return C{B{self} - B{other}} as an L{Fsum}.
|
|
729
761
|
|
|
730
|
-
@arg other: An L{Fsum} or C{scalar}.
|
|
762
|
+
@arg other: An L{Fsum}, L{Fsum2Tuple} or C{scalar}.
|
|
731
763
|
|
|
732
764
|
@return: The difference (L{Fsum}).
|
|
733
765
|
|
|
@@ -736,19 +768,23 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
736
768
|
f = self._copy_2(self.__sub__)
|
|
737
769
|
return f._fsub(other, _sub_op_)
|
|
738
770
|
|
|
739
|
-
def __truediv__(self, other, **
|
|
771
|
+
def __truediv__(self, other, **raiser_RESIDUAL):
|
|
740
772
|
'''Return C{B{self} / B{other}} as an L{Fsum}.
|
|
741
773
|
|
|
742
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
743
|
-
@kwarg
|
|
744
|
-
|
|
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>}.
|
|
745
778
|
|
|
746
779
|
@return: The quotient (L{Fsum}).
|
|
747
780
|
|
|
781
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
782
|
+
B{C{RESIDUAL}}.
|
|
783
|
+
|
|
748
784
|
@see: Method L{Fsum.__itruediv__}.
|
|
749
785
|
'''
|
|
750
786
|
f = self._copy_2(self.__truediv__)
|
|
751
|
-
return f._ftruediv(other, _truediv_op_, **
|
|
787
|
+
return f._ftruediv(other, _truediv_op_, **raiser_RESIDUAL)
|
|
752
788
|
|
|
753
789
|
__trunc__ = __int__
|
|
754
790
|
|
|
@@ -770,7 +806,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
770
806
|
'''
|
|
771
807
|
n, r = self._fint2
|
|
772
808
|
if r:
|
|
773
|
-
i, d = r.as_integer_ratio()
|
|
809
|
+
i, d = float(r).as_integer_ratio()
|
|
774
810
|
n *= d
|
|
775
811
|
n += i
|
|
776
812
|
else: # PYCHOK no cover
|
|
@@ -779,7 +815,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
779
815
|
|
|
780
816
|
@property_RO
|
|
781
817
|
def as_iscalar(self):
|
|
782
|
-
'''Get this instance I{as-is} (L{Fsum}) or C{scalar} iff scalar.
|
|
818
|
+
'''Get this instance I{as-is} (L{Fsum}) or as C{scalar} iff scalar.
|
|
783
819
|
'''
|
|
784
820
|
s, r = self._fprs2
|
|
785
821
|
return self if r else s
|
|
@@ -800,16 +836,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
800
836
|
c += 1
|
|
801
837
|
return c
|
|
802
838
|
|
|
839
|
+
cmp = __cmp__
|
|
840
|
+
|
|
803
841
|
def _cmp_0(self, other, op):
|
|
804
842
|
'''(INTERNAL) Return C{scalar(self - B{other})} for 0-comparison.
|
|
805
843
|
'''
|
|
806
|
-
if
|
|
844
|
+
if _isFsumTuple(other):
|
|
807
845
|
s = _fsum(self._ps_1primed(*other._ps))
|
|
808
846
|
elif self._scalar(other, op):
|
|
809
847
|
s = _fsum(self._ps_1primed(other))
|
|
810
848
|
else:
|
|
811
|
-
s
|
|
812
|
-
s = _signOf(s, -r)
|
|
849
|
+
s = self.signOf() # res=True
|
|
813
850
|
return s
|
|
814
851
|
|
|
815
852
|
def copy(self, deep=False, name=NN):
|
|
@@ -837,8 +874,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
837
874
|
def _copy_2r(self, other, which):
|
|
838
875
|
'''(INTERNAL) Copy for I{reverse-dyadic} operators.
|
|
839
876
|
'''
|
|
840
|
-
return other._copy_2(which) if
|
|
841
|
-
|
|
877
|
+
return other._copy_2(which) if _isFsum(other) else \
|
|
878
|
+
self._copy_2(which)._fset(other)
|
|
842
879
|
|
|
843
880
|
# def _copy_RESIDUAL(self, other):
|
|
844
881
|
# '''(INTERNAL) Copy C{other._RESIDUAL}.
|
|
@@ -847,22 +884,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
847
884
|
# if R is not Fsum._RESIDUAL:
|
|
848
885
|
# self._RESIDUAL = R
|
|
849
886
|
|
|
850
|
-
|
|
851
|
-
'''Return C{divmod(B{self}, B{other})} as 2-tuple C{(quotient,
|
|
852
|
-
remainder)}.
|
|
853
|
-
|
|
854
|
-
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
855
|
-
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
856
|
-
(C{bool}), see also method L{RESIDUAL}.
|
|
857
|
-
|
|
858
|
-
@return: A L{DivMod2Tuple}C{(div, mod)}, with quotient C{div}
|
|
859
|
-
an C{int} in Python 3+ or C{float} in Python 2- and
|
|
860
|
-
remainder C{mod} an L{Fsum} instance.
|
|
861
|
-
|
|
862
|
-
@see: Method L{Fsum.__itruediv__}.
|
|
863
|
-
'''
|
|
864
|
-
f = self._copy_2(self.divmod)
|
|
865
|
-
return f._fdivmod2(other, _divmod_op_, **raiser)
|
|
887
|
+
divmod = __divmod__
|
|
866
888
|
|
|
867
889
|
def _Error(self, op, other, Error, **txt_cause):
|
|
868
890
|
'''(INTERNAL) Format an B{C{Error}} for C{{self} B{op} B{other}}.
|
|
@@ -881,8 +903,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
881
903
|
'''(INTERNAL) Format the caught exception C{X}.
|
|
882
904
|
'''
|
|
883
905
|
E, t = _xError2(X)
|
|
884
|
-
|
|
885
|
-
return E(
|
|
906
|
+
u = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
|
|
907
|
+
return E(u, txt=t, cause=X)
|
|
886
908
|
|
|
887
909
|
def _facc(self, xs, up=True, **origin_X_x):
|
|
888
910
|
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s.
|
|
@@ -897,32 +919,31 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
897
919
|
'''(INTERNAL) Accumulate 0, 1 or more C{scalars} or L{Fsum}s,
|
|
898
920
|
all positional C{xs} in the caller of this method.
|
|
899
921
|
'''
|
|
900
|
-
|
|
901
|
-
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 \
|
|
902
923
|
self._facc(xs, origin=1, **up)
|
|
903
924
|
|
|
904
|
-
def _facc_neg(self, xs,
|
|
925
|
+
def _facc_neg(self, xs, **up_origin):
|
|
905
926
|
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s, negated.
|
|
906
927
|
'''
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
return -x
|
|
928
|
+
def _N(X):
|
|
929
|
+
return X._ps_neg
|
|
910
930
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
ps[:] = self._ps_acc(list(ps), map(_neg, _x), up=up)
|
|
914
|
-
return self
|
|
931
|
+
def _n(x):
|
|
932
|
+
return -float(x)
|
|
915
933
|
|
|
916
|
-
|
|
934
|
+
return self._facc(xs, _X=_N, _x=_n, **up_origin)
|
|
935
|
+
|
|
936
|
+
def _facc_power(self, power, xs, which, **raiser_RESIDUAL): # in .fmath
|
|
917
937
|
'''(INTERNAL) Add each C{xs} as C{float(x**power)}.
|
|
918
938
|
'''
|
|
919
939
|
def _Pow4(p):
|
|
920
940
|
r = 0
|
|
921
|
-
if
|
|
941
|
+
if _isFsumTuple(p):
|
|
922
942
|
s, r = p._fprs2
|
|
923
|
-
if r
|
|
943
|
+
if r:
|
|
944
|
+
m = Fsum._pow
|
|
945
|
+
else: # scalar
|
|
924
946
|
return _Pow4(s)
|
|
925
|
-
m = Fsum._pow
|
|
926
947
|
elif isint(p, both=True) and int(p) >= 0:
|
|
927
948
|
p = s = int(p)
|
|
928
949
|
m = Fsum._pow_int
|
|
@@ -933,24 +954,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
933
954
|
|
|
934
955
|
_Pow, p, s, r = _Pow4(power)
|
|
935
956
|
if p: # and xs:
|
|
936
|
-
_pow = Fsum._pow_2_3
|
|
937
|
-
_Fs = Fsum
|
|
938
|
-
_Ps = _Psum_ # ()._fset_ps_
|
|
939
957
|
op = which.__name__
|
|
958
|
+
_isF = _isFsum
|
|
959
|
+
_pow = self._pow_2_3
|
|
940
960
|
|
|
941
|
-
def
|
|
942
|
-
f = _Pow(X, p, power, op, **
|
|
943
|
-
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,)
|
|
944
964
|
|
|
945
|
-
def
|
|
965
|
+
def _p(x):
|
|
946
966
|
x = float(x)
|
|
947
|
-
|
|
948
|
-
f
|
|
949
|
-
|
|
950
|
-
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)
|
|
951
970
|
return f
|
|
952
971
|
|
|
953
|
-
f = self._facc(xs, origin=1, _X=
|
|
972
|
+
f = self._facc(xs, origin=1, _X=_P, _x=_p)
|
|
954
973
|
else:
|
|
955
974
|
f = self._facc_scalar_(float(len(xs))) # x**0 == 1
|
|
956
975
|
return f
|
|
@@ -959,47 +978,46 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
959
978
|
'''(INTERNAL) Accumulate all C{xs}, known to be scalar.
|
|
960
979
|
'''
|
|
961
980
|
if xs:
|
|
962
|
-
self._ps_acc(self._ps, xs, **up)
|
|
981
|
+
_ = self._ps_acc(self._ps, xs, **up)
|
|
963
982
|
return self
|
|
964
983
|
|
|
965
984
|
def _facc_scalar_(self, *xs, **up):
|
|
966
985
|
'''(INTERNAL) Accumulate all positional C{xs}, known to be scalar.
|
|
967
986
|
'''
|
|
968
987
|
if xs:
|
|
969
|
-
self._ps_acc(self._ps, xs, **up)
|
|
988
|
+
_ = self._ps_acc(self._ps, xs, **up)
|
|
970
989
|
return self
|
|
971
990
|
|
|
972
991
|
# def _facc_up(self, up=True):
|
|
973
992
|
# '''(INTERNAL) Update the C{partials}, by removing
|
|
974
993
|
# and re-accumulating the final C{partial}.
|
|
975
994
|
# '''
|
|
976
|
-
#
|
|
977
|
-
#
|
|
995
|
+
# ps = self._ps
|
|
996
|
+
# while len(ps) > 1:
|
|
997
|
+
# p = ps.pop()
|
|
978
998
|
# if p:
|
|
979
999
|
# n = self._n
|
|
980
|
-
# self.
|
|
1000
|
+
# _ = self._ps_acc(ps, (p,), up=False)
|
|
981
1001
|
# self._n = n
|
|
982
1002
|
# break
|
|
983
|
-
# return self._update() if up else self
|
|
1003
|
+
# return self._update() if up else self
|
|
984
1004
|
|
|
985
1005
|
def fadd(self, xs=()):
|
|
986
|
-
'''Add an iterable
|
|
987
|
-
to this instance.
|
|
1006
|
+
'''Add all items from an iterable to this instance.
|
|
988
1007
|
|
|
989
|
-
@arg xs: Iterable
|
|
990
|
-
L{Fsum}
|
|
1008
|
+
@arg xs: Iterable of items to add (each C{scalar}
|
|
1009
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
991
1010
|
|
|
992
1011
|
@return: This instance (L{Fsum}).
|
|
993
1012
|
|
|
994
1013
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
995
1014
|
|
|
996
|
-
@raise TypeError: An invalid B{C{xs}}
|
|
997
|
-
nor L{Fsum}.
|
|
1015
|
+
@raise TypeError: An invalid B{C{xs}} item.
|
|
998
1016
|
|
|
999
1017
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
1000
1018
|
'''
|
|
1001
|
-
if
|
|
1002
|
-
self._facc_scalar(xs._ps) # tuple
|
|
1019
|
+
if _isFsumTuple(xs):
|
|
1020
|
+
self._facc_scalar(xs._ps) # tuple(xs._ps)
|
|
1003
1021
|
elif isscalar(xs): # for backward compatibility
|
|
1004
1022
|
self._facc_scalar_(_2float(x=xs)) # PYCHOK no cover
|
|
1005
1023
|
elif xs: # assert isiterable(xs)
|
|
@@ -1007,27 +1025,19 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1007
1025
|
return self
|
|
1008
1026
|
|
|
1009
1027
|
def fadd_(self, *xs):
|
|
1010
|
-
'''Add all positional
|
|
1011
|
-
to this instance.
|
|
1012
|
-
|
|
1013
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1014
|
-
all positional.
|
|
1015
|
-
|
|
1016
|
-
@return: This instance (L{Fsum}).
|
|
1017
|
-
|
|
1018
|
-
@raise OverflowError: Partial C{2sum} overflow.
|
|
1028
|
+
'''Add all positional arguments to this instance.
|
|
1019
1029
|
|
|
1020
|
-
@
|
|
1021
|
-
|
|
1030
|
+
@arg xs: Values to add (each C{scalar} or an L{Fsum}
|
|
1031
|
+
or L{Fsum2Tuple} instance), all positional.
|
|
1022
1032
|
|
|
1023
|
-
@
|
|
1033
|
+
@see: Method L{Fsum.fadd} for further details.
|
|
1024
1034
|
'''
|
|
1025
1035
|
return self._facc_1(xs)
|
|
1026
1036
|
|
|
1027
1037
|
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
1028
1038
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
1029
1039
|
'''
|
|
1030
|
-
if
|
|
1040
|
+
if _isFsumTuple(other):
|
|
1031
1041
|
self._facc_scalar(other._ps, **up) # tuple
|
|
1032
1042
|
elif self._scalar(other, op):
|
|
1033
1043
|
self._facc_scalar_(other, **up)
|
|
@@ -1037,16 +1047,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1037
1047
|
fdiv = __itruediv__ # for backward compatibility
|
|
1038
1048
|
fdivmod = __divmod__ # for backward compatibility
|
|
1039
1049
|
|
|
1040
|
-
def _fdivmod2(self, other, op, **
|
|
1050
|
+
def _fdivmod2(self, other, op, **raiser_RESIDUAL):
|
|
1041
1051
|
'''(INTERNAL) Apply C{B{self} %= B{other}} and return a L{DivMod2Tuple}.
|
|
1042
1052
|
'''
|
|
1043
1053
|
# result mostly follows CPython function U{float_divmod
|
|
1044
1054
|
# <https://GitHub.com/python/cpython/blob/main/Objects/floatobject.c>},
|
|
1045
1055
|
# but at least divmod(-3, 2) equals Cpython's result (-2, 1).
|
|
1046
|
-
|
|
1047
|
-
q =
|
|
1056
|
+
q = self._copy_2(self._fdivmod2)
|
|
1057
|
+
q = q._ftruediv(other, op, **raiser_RESIDUAL).floor
|
|
1048
1058
|
if q: # == float // other == floor(float / other)
|
|
1049
|
-
self -= other * q
|
|
1059
|
+
self -= Fsum(other) * q # NO Fsum2Tuple.__mul__!
|
|
1050
1060
|
|
|
1051
1061
|
s = signOf(other) # make signOf(self) == signOf(other)
|
|
1052
1062
|
if s and self.signOf() == -s: # PYCHOK no cover
|
|
@@ -1065,33 +1075,34 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1065
1075
|
raise ValueError(_not_finite_) if op is None else \
|
|
1066
1076
|
self._ValueError(op, other, txt=_not_finite_)
|
|
1067
1077
|
|
|
1068
|
-
def fint(self,
|
|
1078
|
+
def fint(self, name=NN, **raiser_RESIDUAL):
|
|
1069
1079
|
'''Return this instance' current running sum as C{integer}.
|
|
1070
1080
|
|
|
1071
|
-
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
1072
|
-
(C{bool}), see also method L{RESIDUAL}.
|
|
1073
1081
|
@kwarg name: Optional name (C{str}), overriding C{"fint"}.
|
|
1074
|
-
@kwarg
|
|
1075
|
-
|
|
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>}.
|
|
1076
1085
|
|
|
1077
|
-
@return: The C{integer} sum (L{Fsum}) if this instance
|
|
1078
|
-
|
|
1079
|
-
insignificant or if C{B{raiser}=False}.
|
|
1086
|
+
@return: The C{integer} sum (L{Fsum}) if this instance C{is_integer}
|
|
1087
|
+
with a zero or insignificant I{integer} residual.
|
|
1080
1088
|
|
|
1081
|
-
@raise ResidualError: Non-zero
|
|
1089
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1090
|
+
B{C{RESIDUAL}}.
|
|
1082
1091
|
|
|
1083
1092
|
@see: Methods L{Fsum.int_float} and L{Fsum.is_integer}.
|
|
1084
1093
|
'''
|
|
1085
1094
|
i, r = self._fint2
|
|
1086
|
-
if r
|
|
1087
|
-
|
|
1088
|
-
|
|
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)
|
|
1089
1100
|
f = self._copy_2(self.fint, name=name)
|
|
1090
1101
|
return f._fset(i)
|
|
1091
1102
|
|
|
1092
1103
|
def fint2(self, **name):
|
|
1093
|
-
'''Return this instance' current running sum as C{int} and
|
|
1094
|
-
|
|
1104
|
+
'''Return this instance' current running sum as C{int} and the
|
|
1105
|
+
I{integer} residual.
|
|
1095
1106
|
|
|
1096
1107
|
@kwarg name: Optional name (C{str}).
|
|
1097
1108
|
|
|
@@ -1133,10 +1144,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1133
1144
|
|
|
1134
1145
|
# floordiv = __floordiv__ # for naming consistency
|
|
1135
1146
|
|
|
1136
|
-
def _floordiv(self, other, op, **
|
|
1147
|
+
def _floordiv(self, other, op, **raiser_RESIDUAL): # rather _ffloordiv?
|
|
1137
1148
|
'''Apply C{B{self} //= B{other}}.
|
|
1138
1149
|
'''
|
|
1139
|
-
q = self._ftruediv(other, op, **
|
|
1150
|
+
q = self._ftruediv(other, op, **raiser_RESIDUAL) # == self
|
|
1140
1151
|
return self._fset(q.floor) # floor(q)
|
|
1141
1152
|
|
|
1142
1153
|
fmul = __imul__ # for backward compatibility
|
|
@@ -1144,7 +1155,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1144
1155
|
def _fmul(self, other, op):
|
|
1145
1156
|
'''(INTERNAL) Apply C{B{self} *= B{other}}.
|
|
1146
1157
|
'''
|
|
1147
|
-
if
|
|
1158
|
+
if _isFsumTuple(other):
|
|
1148
1159
|
if len(self._ps) != 1:
|
|
1149
1160
|
f = self._mul_Fsum(other, op)
|
|
1150
1161
|
elif len(other._ps) != 1: # and len(self._ps) == 1
|
|
@@ -1156,37 +1167,41 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1156
1167
|
f = self._mul_scalar(s, op)
|
|
1157
1168
|
return self._fset(f) # n=len(self) + 1
|
|
1158
1169
|
|
|
1159
|
-
def fover(self, over, **
|
|
1170
|
+
def fover(self, over, **raiser_RESIDUAL):
|
|
1160
1171
|
'''Apply C{B{self} /= B{over}} and summate.
|
|
1161
1172
|
|
|
1162
1173
|
@arg over: An L{Fsum} or C{scalar} denominator.
|
|
1163
|
-
@kwarg
|
|
1164
|
-
|
|
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>}.
|
|
1165
1177
|
|
|
1166
1178
|
@return: Precision running sum (C{float}).
|
|
1167
1179
|
|
|
1180
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1181
|
+
B{C{RESIDUAL}}.
|
|
1182
|
+
|
|
1168
1183
|
@see: Methods L{Fsum.fsum} and L{Fsum.__itruediv__}.
|
|
1169
1184
|
'''
|
|
1170
|
-
return float(self.fdiv(over, **
|
|
1185
|
+
return float(self.fdiv(over, **raiser_RESIDUAL)._fprs)
|
|
1171
1186
|
|
|
1172
1187
|
fpow = __ipow__ # for backward compatibility
|
|
1173
1188
|
|
|
1174
|
-
def _fpow(self, other, op, *mod, **
|
|
1189
|
+
def _fpow(self, other, op, *mod, **raiser_RESIDUAL):
|
|
1175
1190
|
'''Apply C{B{self} **= B{other}}, optional B{C{mod}} or C{None}.
|
|
1176
1191
|
'''
|
|
1177
1192
|
if mod:
|
|
1178
1193
|
if mod[0] is not None: # == 3-arg C{pow}
|
|
1179
|
-
f = self._pow_2_3(self, other, other, op, *mod, **
|
|
1194
|
+
f = self._pow_2_3(self, other, other, op, *mod, **raiser_RESIDUAL)
|
|
1180
1195
|
elif self.is_integer():
|
|
1181
1196
|
# return an exact C{int} for C{int}**C{int}
|
|
1182
1197
|
i, _ = self._fint2 # assert _ == 0
|
|
1183
|
-
x =
|
|
1184
|
-
f =
|
|
1185
|
-
|
|
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)
|
|
1186
1201
|
else: # mod[0] is None, power(self, other)
|
|
1187
|
-
f = self._pow(other, other, op, **
|
|
1202
|
+
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1188
1203
|
else: # pow(self, other)
|
|
1189
|
-
f = self._pow(other, other, op, **
|
|
1204
|
+
f = self._pow(other, other, op, **raiser_RESIDUAL)
|
|
1190
1205
|
return self._fset(f, asis=isint(f)) # n=max(len(self), 1)
|
|
1191
1206
|
|
|
1192
1207
|
@Property_RO
|
|
@@ -1210,11 +1225,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1210
1225
|
s = _psum(ps)
|
|
1211
1226
|
n = len(ps) - 2
|
|
1212
1227
|
if n > 0:
|
|
1213
|
-
r = _fsum(self._ps_1primed(s))
|
|
1214
|
-
return Fsum2Tuple(s, r)
|
|
1228
|
+
r = _fsum(self._ps_1primed(s))
|
|
1229
|
+
return Fsum2Tuple(*_s_r(s, r))
|
|
1215
1230
|
if n == 0: # len(ps) == 2
|
|
1216
|
-
|
|
1217
|
-
|
|
1231
|
+
s, r = _s_r(*_2sum(*ps))
|
|
1232
|
+
ps[:] = (r, s) if r else (s,)
|
|
1218
1233
|
elif ps: # len(ps) == 1
|
|
1219
1234
|
s, r = ps[0], INT0
|
|
1220
1235
|
else: # len(ps) == 0
|
|
@@ -1223,33 +1238,26 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1223
1238
|
# assert self._ps is ps
|
|
1224
1239
|
return Fsum2Tuple(s, r)
|
|
1225
1240
|
|
|
1226
|
-
# def _fpsqz(self):
|
|
1227
|
-
# '''(INTERNAL) Compress, squeeze the C{partials}.
|
|
1228
|
-
# '''
|
|
1229
|
-
# if len(self._ps) > 2:
|
|
1230
|
-
# _ = self._fprs2
|
|
1231
|
-
# return self
|
|
1232
|
-
|
|
1233
1241
|
def fset_(self, *xs):
|
|
1234
1242
|
'''Replace this instance' value with C{xs}.
|
|
1235
1243
|
|
|
1236
|
-
@arg xs: Optional, new values (C{scalar} or
|
|
1237
|
-
|
|
1244
|
+
@arg xs: Optional, new values (each C{scalar} or
|
|
1245
|
+
an L{Fsum} or L{Fsum2Tuple} instance),
|
|
1246
|
+
all positional.
|
|
1238
1247
|
|
|
1239
1248
|
@return: This instance (C{Fsum}).
|
|
1240
1249
|
|
|
1241
1250
|
@see: Method L{Fsum.fadd} for further details.
|
|
1242
1251
|
'''
|
|
1243
|
-
|
|
1244
|
-
self.
|
|
1245
|
-
return self.fadd(xs) if xs else self._update()
|
|
1252
|
+
f = Fsum(*xs) if xs else _0_0
|
|
1253
|
+
return self._fset(f)
|
|
1246
1254
|
|
|
1247
1255
|
def _fset(self, other, asis=True, n=0):
|
|
1248
1256
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
1249
1257
|
'''
|
|
1250
1258
|
if other is self:
|
|
1251
1259
|
pass # from ._fmul, ._ftruediv and ._pow_0_1
|
|
1252
|
-
elif
|
|
1260
|
+
elif _isFsumTuple(other):
|
|
1253
1261
|
self._ps[:] = other._ps
|
|
1254
1262
|
self._n = n or other._n
|
|
1255
1263
|
# self._copy_RESIDUAL(other)
|
|
@@ -1271,9 +1279,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1271
1279
|
return self
|
|
1272
1280
|
|
|
1273
1281
|
def _fset_ps(self, other, n=0): # in .fmath
|
|
1274
|
-
'''(INTERNAL) Set partials from a known C{Fsum} or
|
|
1282
|
+
'''(INTERNAL) Set partials from a known C{scalar}, L{Fsum} or L{Fsum2Tuple}.
|
|
1275
1283
|
'''
|
|
1276
|
-
if
|
|
1284
|
+
if _isFsumTuple(other):
|
|
1277
1285
|
self._ps[:] = other._ps
|
|
1278
1286
|
self._n = n or other._n
|
|
1279
1287
|
else: # assert isscalar(other)
|
|
@@ -1281,36 +1289,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1281
1289
|
self._n = n or 1
|
|
1282
1290
|
return self
|
|
1283
1291
|
|
|
1284
|
-
# def _fset_ps_(self, *xs):
|
|
1285
|
-
# '''(INTERNAL) Set partials to all known scalar C{xs}.
|
|
1286
|
-
# '''
|
|
1287
|
-
# self._ps[:] = xs
|
|
1288
|
-
# self.n = len(xs)
|
|
1289
|
-
# return self
|
|
1290
|
-
|
|
1291
1292
|
def fsub(self, xs=()):
|
|
1292
|
-
'''Subtract
|
|
1293
|
-
this instance.
|
|
1293
|
+
'''Subtract all items of an iterable from this instance.
|
|
1294
1294
|
|
|
1295
|
-
@
|
|
1296
|
-
instances).
|
|
1297
|
-
|
|
1298
|
-
@return: This instance, updated (L{Fsum}).
|
|
1299
|
-
|
|
1300
|
-
@see: Method L{Fsum.fadd}.
|
|
1295
|
+
@see: Method L{Fsum.fadd} for further details.
|
|
1301
1296
|
'''
|
|
1302
1297
|
return self._facc_neg(xs)
|
|
1303
1298
|
|
|
1304
1299
|
def fsub_(self, *xs):
|
|
1305
|
-
'''Subtract all positional
|
|
1306
|
-
this instance.
|
|
1307
|
-
|
|
1308
|
-
@arg xs: Values to subtract (C{scalar} or L{Fsum} instances),
|
|
1309
|
-
all positional.
|
|
1310
|
-
|
|
1311
|
-
@return: This instance, updated (L{Fsum}).
|
|
1300
|
+
'''Subtract all positional arguments from this instance.
|
|
1312
1301
|
|
|
1313
|
-
@see: Method L{Fsum.
|
|
1302
|
+
@see: Method L{Fsum.fadd_} for further details.
|
|
1314
1303
|
'''
|
|
1315
1304
|
return self._fsub(xs[0], _sub_op_) if len(xs) == 1 else \
|
|
1316
1305
|
self._facc_neg(xs, origin=1)
|
|
@@ -1318,20 +1307,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1318
1307
|
def _fsub(self, other, op):
|
|
1319
1308
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
1320
1309
|
'''
|
|
1321
|
-
if
|
|
1310
|
+
if _isFsumTuple(other):
|
|
1322
1311
|
if other is self: # or other._fprs2 == self._fprs2:
|
|
1323
|
-
self._fset(_0_0
|
|
1312
|
+
self._fset(_0_0, n=len(self) * 2)
|
|
1324
1313
|
elif other._ps:
|
|
1325
1314
|
self._facc_scalar(other._ps_neg)
|
|
1326
1315
|
elif self._scalar(other, op):
|
|
1327
|
-
self._facc_scalar_(-
|
|
1316
|
+
self._facc_scalar_(-other)
|
|
1328
1317
|
return self
|
|
1329
1318
|
|
|
1330
1319
|
def fsum(self, xs=()):
|
|
1331
|
-
'''Add more
|
|
1320
|
+
'''Add more items from an iterable, summate and return
|
|
1321
|
+
the current precision running sum.
|
|
1332
1322
|
|
|
1333
|
-
@
|
|
1334
|
-
|
|
1323
|
+
@arg xs: Iterable of items to add (each item C{scalar}
|
|
1324
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
1335
1325
|
|
|
1336
1326
|
@return: Precision running sum (C{float} or C{int}).
|
|
1337
1327
|
|
|
@@ -1342,10 +1332,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1342
1332
|
return self._facc(xs)._fprs
|
|
1343
1333
|
|
|
1344
1334
|
def fsum_(self, *xs):
|
|
1345
|
-
'''Add
|
|
1335
|
+
'''Add any positional arguments, summate and return the
|
|
1336
|
+
current precision running sum.
|
|
1346
1337
|
|
|
1347
|
-
@arg xs: Values to add (C{scalar} or L{Fsum}
|
|
1348
|
-
positional.
|
|
1338
|
+
@arg xs: Values to add (each C{scalar} or an L{Fsum}
|
|
1339
|
+
or L{Fsum2Tuple} instance), all positional.
|
|
1349
1340
|
|
|
1350
1341
|
@return: Precision running sum (C{float} or C{int}).
|
|
1351
1342
|
|
|
@@ -1353,19 +1344,36 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1353
1344
|
'''
|
|
1354
1345
|
return self._facc_1(xs)._fprs
|
|
1355
1346
|
|
|
1356
|
-
|
|
1357
|
-
|
|
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}).
|
|
1358
1357
|
|
|
1359
1358
|
@return: Current, precision running sum (L{Fsum}).
|
|
1360
1359
|
'''
|
|
1361
|
-
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)
|
|
1362
1370
|
|
|
1363
1371
|
def fsum2(self, xs=(), name=NN):
|
|
1364
|
-
'''Add more
|
|
1365
|
-
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}.
|
|
1366
1374
|
|
|
1367
|
-
@
|
|
1368
|
-
|
|
1375
|
+
@arg xs: Iterable of items to add (each item C{scalar}
|
|
1376
|
+
or an L{Fsum} or L{Fsum2Tuple} instance).
|
|
1369
1377
|
@kwarg name: Optional name (C{str}).
|
|
1370
1378
|
|
|
1371
1379
|
@return: L{Fsum2Tuple}C{(fsum, residual)} with C{fsum} the
|
|
@@ -1380,11 +1388,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1380
1388
|
return t.dup(name=name) if name else t
|
|
1381
1389
|
|
|
1382
1390
|
def fsum2_(self, *xs):
|
|
1383
|
-
'''Add any positional
|
|
1384
|
-
|
|
1391
|
+
'''Add any positional arguments, summate and return the current
|
|
1392
|
+
precision running sum I{and} the C{differential}.
|
|
1385
1393
|
|
|
1386
|
-
@arg xs: Values to add (C{scalar} or L{Fsum}
|
|
1387
|
-
positional.
|
|
1394
|
+
@arg xs: Values to add (each C{scalar} or an L{Fsum} or
|
|
1395
|
+
L{Fsum2Tuple} instance), all positional.
|
|
1388
1396
|
|
|
1389
1397
|
@return: 2Tuple C{(fsum, delta)} with the current, precision
|
|
1390
1398
|
running C{fsum} like method L{Fsum.fsum} and C{delta},
|
|
@@ -1405,37 +1413,35 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1405
1413
|
return p, _0_0
|
|
1406
1414
|
|
|
1407
1415
|
def fsumf_(self, *xs):
|
|
1408
|
-
'''Like method L{Fsum.fsum_}
|
|
1416
|
+
'''Like method L{Fsum.fsum_} iff I{all} C{B{xs}} are I{known to be scalar}.
|
|
1409
1417
|
'''
|
|
1410
1418
|
return self._facc_scalar(xs)._fprs
|
|
1411
1419
|
|
|
1412
1420
|
def Fsumf_(self, *xs):
|
|
1413
|
-
'''Like method L{Fsum.Fsum_}
|
|
1421
|
+
'''Like method L{Fsum.Fsum_} iff I{all} C{B{xs}} are I{known to be scalar}.
|
|
1414
1422
|
'''
|
|
1415
1423
|
return self._facc_scalar(xs)._copy_2(self.Fsumf_)
|
|
1416
1424
|
|
|
1417
1425
|
def fsum2f_(self, *xs):
|
|
1418
|
-
'''Like method L{Fsum.fsum2_}
|
|
1426
|
+
'''Like method L{Fsum.fsum2_} iff I{all} C{B{xs}} are I{known to be scalar}.
|
|
1419
1427
|
'''
|
|
1420
1428
|
return self._fsum2(xs, self._facc_scalar, origin=1)
|
|
1421
1429
|
|
|
1422
1430
|
# ftruediv = __itruediv__ # for naming consistency?
|
|
1423
1431
|
|
|
1424
|
-
def _ftruediv(self, other, op, **
|
|
1432
|
+
def _ftruediv(self, other, op, **raiser_RESIDUAL):
|
|
1425
1433
|
'''(INTERNAL) Apply C{B{self} /= B{other}}.
|
|
1426
1434
|
'''
|
|
1427
1435
|
n = _1_0
|
|
1428
|
-
if
|
|
1429
|
-
if other is self or
|
|
1436
|
+
if _isFsumTuple(other):
|
|
1437
|
+
if other is self or self == other:
|
|
1430
1438
|
return self._fset(n) # n=len(self)
|
|
1431
1439
|
d, r = other._fprs2
|
|
1432
1440
|
if r:
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
else: # PYCHOK no cover
|
|
1438
|
-
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()
|
|
1439
1445
|
else:
|
|
1440
1446
|
d = self._scalar(other, op)
|
|
1441
1447
|
try:
|
|
@@ -1453,28 +1459,31 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1453
1459
|
'''
|
|
1454
1460
|
return _0_0
|
|
1455
1461
|
|
|
1456
|
-
def int_float(self,
|
|
1462
|
+
def int_float(self, **raiser_RESIDUAL):
|
|
1457
1463
|
'''Return this instance' current running sum as C{int} or C{float}.
|
|
1458
1464
|
|
|
1459
|
-
@kwarg
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
L{RESIDUAL<Fsum.RESIDUAL>} (C{scalar}).
|
|
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>}.
|
|
1463
1468
|
|
|
1464
1469
|
@return: This C{integer} sum if this instance C{is_integer},
|
|
1465
1470
|
otherwise return the C{float} sum if the residual is
|
|
1466
|
-
zero or
|
|
1471
|
+
zero or not significant.
|
|
1467
1472
|
|
|
1468
|
-
@raise ResidualError: Non-zero residual
|
|
1473
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1474
|
+
B{C{RESIDUAL}}.
|
|
1469
1475
|
|
|
1470
|
-
@see: Methods L{Fsum.fint}
|
|
1476
|
+
@see: Methods L{Fsum.fint}, L{Fsum.fint2}, L{Fsum.RESIDUAL} and
|
|
1477
|
+
property L{Fsum.as_iscalar}.
|
|
1471
1478
|
'''
|
|
1472
1479
|
s, r = self._fint2
|
|
1473
1480
|
if r:
|
|
1474
1481
|
s, r = self._fprs2
|
|
1475
|
-
if r
|
|
1476
|
-
|
|
1477
|
-
|
|
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)
|
|
1478
1487
|
s = float(s) # redundant
|
|
1479
1488
|
return s
|
|
1480
1489
|
|
|
@@ -1505,18 +1514,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1505
1514
|
f = Fsum._math_fsum
|
|
1506
1515
|
return 2 if _psum is f else bool(f)
|
|
1507
1516
|
|
|
1508
|
-
def is_scalar(self):
|
|
1509
|
-
'''Is this instance' running sum C{scalar}
|
|
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>}.
|
|
1510
1525
|
|
|
1511
|
-
@
|
|
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}.
|
|
1512
1531
|
'''
|
|
1513
|
-
s, r =
|
|
1514
|
-
return False if r and
|
|
1532
|
+
s, r = self._fprs2
|
|
1533
|
+
return False if r and self._raiser(r, s, **raiser_RESIDUAL) else True
|
|
1515
1534
|
|
|
1516
1535
|
def _mul_Fsum(self, other, op=_mul_op_): # in .fmath.Fhorner
|
|
1517
|
-
'''(INTERNAL) Return C{B{self} *
|
|
1536
|
+
'''(INTERNAL) Return C{B{self} * B{other}} as L{Fsum} or C{0}.
|
|
1518
1537
|
'''
|
|
1519
|
-
# assert
|
|
1538
|
+
# assert _isFsumTuple(other)
|
|
1520
1539
|
if self._ps and other._ps:
|
|
1521
1540
|
f = self._ps_mul(op, *other._ps) # NO .as_iscalar
|
|
1522
1541
|
else:
|
|
@@ -1547,18 +1566,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1547
1566
|
'''
|
|
1548
1567
|
return tuple(self._ps)
|
|
1549
1568
|
|
|
1550
|
-
def pow(self, x, *mod, **
|
|
1569
|
+
def pow(self, x, *mod, **raiser_RESIDUAL):
|
|
1551
1570
|
'''Return C{B{self}**B{x}} as L{Fsum}.
|
|
1552
1571
|
|
|
1553
|
-
@arg x: The exponent (
|
|
1572
|
+
@arg x: The exponent (C{scalar} or L{Fsum}).
|
|
1554
1573
|
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
1555
1574
|
C{pow(B{self}, B{other}, B{mod})} version.
|
|
1556
|
-
@kwarg
|
|
1557
|
-
|
|
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>}.
|
|
1558
1578
|
|
|
1559
1579
|
@return: The C{pow(self, B{x})} or C{pow(self, B{x}, *B{mod})}
|
|
1560
1580
|
result (L{Fsum}).
|
|
1561
1581
|
|
|
1582
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1583
|
+
B{C{RESIDUAL}}.
|
|
1584
|
+
|
|
1562
1585
|
@note: If B{C{mod}} is given as C{None}, the result will be an
|
|
1563
1586
|
C{integer} L{Fsum} provided this instance C{is_integer}
|
|
1564
1587
|
or set to C{integer} by an L{Fsum.fint} call.
|
|
@@ -1567,21 +1590,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1567
1590
|
and L{Fsum.root}.
|
|
1568
1591
|
'''
|
|
1569
1592
|
f = self._copy_2(self.pow)
|
|
1570
|
-
return f._fpow(x, _pow_op_, *mod, **
|
|
1593
|
+
return f._fpow(x, _pow_op_, *mod, **raiser_RESIDUAL) # f = pow(f, x, *mod)
|
|
1571
1594
|
|
|
1572
|
-
def _pow(self, other, unused, op, **
|
|
1595
|
+
def _pow(self, other, unused, op, **raiser_RESIDUAL):
|
|
1573
1596
|
'''Return C{B{self} ** B{other}}.
|
|
1574
1597
|
'''
|
|
1575
|
-
if
|
|
1576
|
-
|
|
1577
|
-
if r and self._raiser(r, x, **raiser):
|
|
1578
|
-
raise self._ResidualError(op, other, r)
|
|
1579
|
-
f = self._pow_scalar(x, other, op, **raiser)
|
|
1580
|
-
if r:
|
|
1581
|
-
f *= self._pow_scalar(r, other, op, **raiser)
|
|
1598
|
+
if _isFsumTuple(other):
|
|
1599
|
+
f = self._pow_Fsum(other, op, **raiser_RESIDUAL)
|
|
1582
1600
|
elif self._scalar(other, op):
|
|
1583
1601
|
x = self._finite(other, op)
|
|
1584
|
-
f = self._pow_scalar(x, other, op, **
|
|
1602
|
+
f = self._pow_scalar(x, other, op, **raiser_RESIDUAL)
|
|
1585
1603
|
else:
|
|
1586
1604
|
f = self._pow_0_1(0, other)
|
|
1587
1605
|
return f
|
|
@@ -1591,18 +1609,25 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1591
1609
|
'''
|
|
1592
1610
|
return self if x else (1 if isint(other) and self.is_integer() else _1_0)
|
|
1593
1611
|
|
|
1594
|
-
def _pow_2_3(self, b, x, other, op, *mod, **
|
|
1612
|
+
def _pow_2_3(self, b, x, other, op, *mod, **raiser_RESIDUAL):
|
|
1595
1613
|
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} and 3-arg C{pow(B{b},
|
|
1596
1614
|
B{x}, int B{mod} or C{None})}, embellishing errors.
|
|
1597
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
|
+
|
|
1598
1630
|
try:
|
|
1599
|
-
if mod: # b, x, mod all C{int}, unless C{mod} is C{None}
|
|
1600
|
-
m = mod[0]
|
|
1601
|
-
b, r = b._fprs2 if m is None else b._fint2
|
|
1602
|
-
if r and self._raiser(r, b, **raiser):
|
|
1603
|
-
t = _non_zero_ if m is None else _integer_
|
|
1604
|
-
raise ResidualError(_stresidual(t, r, mod=m), txt=None)
|
|
1605
|
-
x = _2scalar(x, _raiser=self._raiser, mod=m)
|
|
1606
1631
|
# 0**INF == 0.0, 1**INF == 1.0, -1**2.3 == -(1**2.3)
|
|
1607
1632
|
s = pow(b, x, *mod)
|
|
1608
1633
|
if iscomplex(s):
|
|
@@ -1612,7 +1637,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1612
1637
|
except Exception as X:
|
|
1613
1638
|
raise self._ErrorX(X, op, other, *mod)
|
|
1614
1639
|
|
|
1615
|
-
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):
|
|
1616
1651
|
'''(INTERNAL) Return C{B{self} **= B{x}} for C{int B{x} >= 0}.
|
|
1617
1652
|
'''
|
|
1618
1653
|
# assert isint(x) and x >= 0
|
|
@@ -1636,49 +1671,52 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1636
1671
|
else: # self**1 or self**0 == 1 or _1_0
|
|
1637
1672
|
f = self._pow_0_1(x, other)
|
|
1638
1673
|
elif ps: # self._ps[0]**x
|
|
1639
|
-
f = self._pow_2_3(ps[0], x, other, op, **
|
|
1674
|
+
f = self._pow_2_3(ps[0], x, other, op, **raiser_RESIDUAL)
|
|
1640
1675
|
else: # PYCHOK no cover
|
|
1641
1676
|
# 0**pos_int == 0, but 0**0 == 1
|
|
1642
1677
|
f = 0 if x else 1
|
|
1643
1678
|
return f
|
|
1644
1679
|
|
|
1645
|
-
def _pow_scalar(self, x, other, op, **
|
|
1680
|
+
def _pow_scalar(self, x, other, op, **raiser_RESIDUAL):
|
|
1646
1681
|
'''(INTERNAL) Return C{self**B{x}} for C{scalar B{x}}.
|
|
1647
1682
|
'''
|
|
1648
1683
|
s, r = self._fprs2
|
|
1649
|
-
if
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
if
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
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
|
|
1663
1702
|
x = -1
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
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)
|
|
1671
1711
|
n, d = self.as_integer_ratio()
|
|
1672
1712
|
if abs(n) > abs(d):
|
|
1673
1713
|
n, d, x = d, n, (-x)
|
|
1674
1714
|
s = n / d
|
|
1675
|
-
else:
|
|
1676
|
-
s = r
|
|
1677
1715
|
# assert isscalar(s) and isscalar(x)
|
|
1678
|
-
return self._pow_2_3(s, x, other, op, **
|
|
1716
|
+
return self._pow_2_3(s, x, other, op, **raiser_RESIDUAL)
|
|
1679
1717
|
|
|
1680
1718
|
def _ps_acc(self, ps, xs, up=True, **unused):
|
|
1681
|
-
'''(INTERNAL) Accumulate all
|
|
1719
|
+
'''(INTERNAL) Accumulate all C{xs} scalars into list C{ps}.
|
|
1682
1720
|
'''
|
|
1683
1721
|
n = 0
|
|
1684
1722
|
_2s = _2sum
|
|
@@ -1701,8 +1739,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1701
1739
|
return ps
|
|
1702
1740
|
|
|
1703
1741
|
def _ps_mul(self, op, *factors):
|
|
1704
|
-
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1705
|
-
|
|
1742
|
+
'''(INTERNAL) Multiply this instance' C{partials} with each
|
|
1743
|
+
of the scalar B{C{factors}} and accumulate.
|
|
1706
1744
|
'''
|
|
1707
1745
|
def _pfs(ps, fs):
|
|
1708
1746
|
if len(ps) < len(fs):
|
|
@@ -1713,7 +1751,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1713
1751
|
p *= f
|
|
1714
1752
|
yield p if _fin(p) else self._finite(p, op)
|
|
1715
1753
|
|
|
1716
|
-
return _Psum(self._ps_acc([], _pfs(self._ps, factors)))
|
|
1754
|
+
return _Psum(self._ps_acc([], _pfs(self._ps, factors), up=False))
|
|
1717
1755
|
|
|
1718
1756
|
@property_RO
|
|
1719
1757
|
def _ps_neg(self):
|
|
@@ -1723,7 +1761,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1723
1761
|
yield -p
|
|
1724
1762
|
|
|
1725
1763
|
def _ps_1primed(self, *less):
|
|
1726
|
-
'''(INTERNAL) Yield partials, 1-primed
|
|
1764
|
+
'''(INTERNAL) Yield partials, 1-primed C{less} any scalars.
|
|
1727
1765
|
'''
|
|
1728
1766
|
yield _1_0
|
|
1729
1767
|
for p in self._ps:
|
|
@@ -1733,21 +1771,19 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1733
1771
|
yield _N_1_0
|
|
1734
1772
|
|
|
1735
1773
|
def _raiser(self, r, s, raiser=True, **RESIDUAL):
|
|
1736
|
-
'''(INTERNAL) Does ratio C{r / s} exceed the RESIDUAL threshold
|
|
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)?
|
|
1737
1777
|
'''
|
|
1738
|
-
self._ratio = r = (r / s) if s else s # == 0.
|
|
1739
1778
|
if r and raiser:
|
|
1740
|
-
|
|
1779
|
+
t = self._RESIDUAL
|
|
1741
1780
|
if RESIDUAL:
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
I{and} is the residual B{C{r}} significant vs sum B{C{s}}?
|
|
1749
|
-
'''
|
|
1750
|
-
return self._raiser(r, s, **raiser_RESIDUAL) and _2sum(s, r) != (s, r)
|
|
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 {}
|
|
1751
1787
|
|
|
1752
1788
|
@property_RO
|
|
1753
1789
|
def real(self):
|
|
@@ -1761,10 +1797,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1761
1797
|
|
|
1762
1798
|
@property_RO
|
|
1763
1799
|
def residual(self):
|
|
1764
|
-
'''Get this instance' residual (C{float} or C{int})
|
|
1800
|
+
'''Get this instance' residual (C{float} or C{int}): the
|
|
1765
1801
|
C{sum(partials)} less the precision running sum C{fsum}.
|
|
1766
1802
|
|
|
1767
|
-
@note:
|
|
1803
|
+
@note: The C{residual is INT0} iff the precision running
|
|
1768
1804
|
C{fsum} is considered to be I{exact}.
|
|
1769
1805
|
|
|
1770
1806
|
@see: Methods L{Fsum.fsum}, L{Fsum.fsum2} and L{Fsum.is_exact}.
|
|
@@ -1783,45 +1819,52 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1783
1819
|
|
|
1784
1820
|
@return: The previous C{RESIDUAL} setting (C{float}), default C{0.0}.
|
|
1785
1821
|
|
|
1786
|
-
@raise
|
|
1822
|
+
@raise ResidualError: Invalid B{C{threshold}}.
|
|
1787
1823
|
|
|
1788
|
-
@note: L{ResidualError}s
|
|
1789
|
-
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}.
|
|
1790
1831
|
'''
|
|
1791
1832
|
r = self._RESIDUAL
|
|
1792
1833
|
if threshold:
|
|
1793
1834
|
t = threshold[0]
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
if t < 0:
|
|
1798
|
-
u = _DOT_(self, unstr(self.RESIDUAL, *threshold))
|
|
1799
|
-
raise _ValueError(u, RESIDUAL=t, txt=_negative_)
|
|
1800
|
-
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
|
|
1801
1838
|
return r
|
|
1802
1839
|
|
|
1803
|
-
def _ResidualError(self, op, other, residual):
|
|
1840
|
+
def _ResidualError(self, op, other, residual, **mod_R):
|
|
1804
1841
|
'''(INTERNAL) Non-zero B{C{residual}} etc.
|
|
1805
1842
|
'''
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
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)
|
|
1809
1848
|
return self._Error(op, other, ResidualError, txt=t)
|
|
1810
1849
|
|
|
1811
|
-
def root(self, root, **
|
|
1850
|
+
def root(self, root, **raiser_RESIDUAL):
|
|
1812
1851
|
'''Return C{B{self}**(1 / B{root})} as L{Fsum}.
|
|
1813
1852
|
|
|
1814
|
-
@arg root: The order (C{scalar} or
|
|
1815
|
-
@kwarg
|
|
1816
|
-
|
|
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>}.
|
|
1817
1857
|
|
|
1818
1858
|
@return: The C{self ** (1 / B{root})} result (L{Fsum}).
|
|
1819
1859
|
|
|
1860
|
+
@raise ResidualError: Non-zero, significant residual or invalid
|
|
1861
|
+
B{C{RESIDUAL}}.
|
|
1862
|
+
|
|
1820
1863
|
@see: Method L{Fsum.pow}.
|
|
1821
1864
|
'''
|
|
1822
|
-
x =
|
|
1865
|
+
x = _1_Over(root, _truediv_op_, **raiser_RESIDUAL)
|
|
1823
1866
|
f = self._copy_2(self.root)
|
|
1824
|
-
return f._fpow(x, f.name, **
|
|
1867
|
+
return f._fpow(x, f.name, **raiser_RESIDUAL) # == pow(f, x)
|
|
1825
1868
|
|
|
1826
1869
|
def _scalar(self, other, op, **txt):
|
|
1827
1870
|
'''(INTERNAL) Return scalar C{other}.
|
|
@@ -1839,7 +1882,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1839
1882
|
@return: The sign (C{int}, -1, 0 or +1).
|
|
1840
1883
|
'''
|
|
1841
1884
|
s, r = self._fprs2
|
|
1842
|
-
|
|
1885
|
+
r = (-r) if res else 0
|
|
1886
|
+
return _signOf(s, r)
|
|
1843
1887
|
|
|
1844
1888
|
def toRepr(self, **prec_sep_fmt_lenc): # PYCHOK signature
|
|
1845
1889
|
'''Return this C{Fsum} instance as representation.
|
|
@@ -1868,10 +1912,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1868
1912
|
def _toT(self, toT, fmt=Fmt.g, lenc=True, **kwds):
|
|
1869
1913
|
'''(INTERNAL) Helper for C{toRepr} and C{toStr}.
|
|
1870
1914
|
'''
|
|
1871
|
-
|
|
1915
|
+
p = self.classname
|
|
1872
1916
|
if lenc:
|
|
1873
|
-
|
|
1874
|
-
|
|
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))
|
|
1875
1922
|
|
|
1876
1923
|
def _TypeError(self, op, other, **txt): # PYCHOK no cover
|
|
1877
1924
|
'''(INTERNAL) Return a C{TypeError}.
|
|
@@ -1900,7 +1947,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1900
1947
|
'''
|
|
1901
1948
|
return self._Error(op, other, _ZeroDivisionError, **txt)
|
|
1902
1949
|
|
|
1903
|
-
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK
|
|
1950
|
+
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK see Fsum._update
|
|
1904
1951
|
|
|
1905
1952
|
|
|
1906
1953
|
def _Float_Int(arg, **name_Error):
|
|
@@ -1914,8 +1961,8 @@ class DivMod2Tuple(_NamedTuple):
|
|
|
1914
1961
|
'''2-Tuple C{(div, mod)} with the quotient C{div} and remainder
|
|
1915
1962
|
C{mod} results of a C{divmod} operation.
|
|
1916
1963
|
|
|
1917
|
-
@note: Quotient C{div} an C{int} in Python 3+
|
|
1918
|
-
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.
|
|
1919
1966
|
'''
|
|
1920
1967
|
_Names_ = (_div_, _mod_)
|
|
1921
1968
|
_Units_ = (_Float_Int, Fsum)
|
|
@@ -1924,7 +1971,7 @@ class DivMod2Tuple(_NamedTuple):
|
|
|
1924
1971
|
class Fsum2Tuple(_NamedTuple):
|
|
1925
1972
|
'''2-Tuple C{(fsum, residual)} with the precision running C{fsum}
|
|
1926
1973
|
and the C{residual}, the sum of the remaining partials. Each
|
|
1927
|
-
item is
|
|
1974
|
+
item is C{float} or C{int}.
|
|
1928
1975
|
|
|
1929
1976
|
@note: If the C{residual is INT0}, the C{fsum} is considered
|
|
1930
1977
|
to be I{exact}, see method L{Fsum2Tuple.is_exact}.
|
|
@@ -1932,27 +1979,61 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
1932
1979
|
_Names_ = ( Fsum.fsum.__name__, Fsum.residual.name)
|
|
1933
1980
|
_Units_ = (_Float_Int, _Float_Int)
|
|
1934
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
|
+
|
|
1935
1997
|
@Property_RO
|
|
1936
1998
|
def _Fsum(self):
|
|
1937
|
-
|
|
1938
|
-
'''
|
|
1939
|
-
s, r = map(float, self)
|
|
1940
|
-
return _Psum(_2ps(s, r), name=self.name)
|
|
1999
|
+
return Fsum(*self)
|
|
1941
2000
|
|
|
1942
2001
|
def is_exact(self):
|
|
1943
2002
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
1944
2003
|
'''
|
|
1945
|
-
|
|
2004
|
+
_, r = _s_r(*self)
|
|
2005
|
+
return False if r else True
|
|
1946
2006
|
|
|
1947
2007
|
def is_integer(self):
|
|
1948
2008
|
'''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
|
|
1949
2009
|
'''
|
|
1950
|
-
|
|
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
|
|
1951
2031
|
|
|
1952
2032
|
|
|
1953
2033
|
class ResidualError(_ValueError):
|
|
1954
|
-
'''Error raised for
|
|
1955
|
-
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.
|
|
1956
2037
|
|
|
1957
2038
|
@see: Module L{pygeodesy.fsums} and method L{Fsum.RESIDUAL}.
|
|
1958
2039
|
'''
|
|
@@ -1969,64 +2050,59 @@ try:
|
|
|
1969
2050
|
raise ImportError # ... use _fsum below
|
|
1970
2051
|
|
|
1971
2052
|
Fsum._math_fsum = _sum = _fsum # PYCHOK exported
|
|
1972
|
-
|
|
1973
|
-
if _getenv('PYGEODESY_FSUM_PARTIALS', NN) == _fsum.__name__:
|
|
1974
|
-
_psum = _fsum # PYCHOK re-def
|
|
1975
|
-
|
|
1976
2053
|
except ImportError:
|
|
1977
2054
|
_sum = sum # Fsum(NAN) exception fall-back, in .elliptic
|
|
1978
2055
|
|
|
1979
2056
|
def _fsum(xs):
|
|
1980
2057
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
1981
2058
|
'''
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
return
|
|
2059
|
+
F = Fsum()
|
|
2060
|
+
F.name = _fsum.__name__
|
|
2061
|
+
return F._facc(xs, up=False)._fprs2.fsum
|
|
1985
2062
|
|
|
1986
2063
|
|
|
1987
2064
|
def fsum(xs, floats=False):
|
|
1988
|
-
'''Precision floating point summation based on
|
|
2065
|
+
'''Precision floating point summation based on/like Python's C{math.fsum}.
|
|
1989
2066
|
|
|
1990
|
-
@arg xs: Iterable
|
|
1991
|
-
|
|
1992
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
1993
|
-
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}).
|
|
1994
2071
|
|
|
1995
2072
|
@return: Precision C{fsum} (C{float}).
|
|
1996
2073
|
|
|
1997
2074
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
1998
2075
|
|
|
1999
|
-
@raise TypeError: Non-scalar B{C{xs}}
|
|
2076
|
+
@raise TypeError: Non-scalar B{C{xs}} item.
|
|
2000
2077
|
|
|
2001
|
-
@raise ValueError: Invalid or non-finite B{C{xs}}
|
|
2078
|
+
@raise ValueError: Invalid or non-finite B{C{xs}} item.
|
|
2002
2079
|
|
|
2003
2080
|
@note: Exception and I{non-finite} handling may differ if not based
|
|
2004
2081
|
on Python's C{math.fsum}.
|
|
2005
2082
|
|
|
2006
2083
|
@see: Class L{Fsum} and methods L{Fsum.fsum} and L{Fsum.fadd}.
|
|
2007
2084
|
'''
|
|
2008
|
-
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
|
|
2009
2086
|
|
|
2010
2087
|
|
|
2011
2088
|
def fsum_(*xs, **floats):
|
|
2012
2089
|
'''Precision floating point summation of all positional arguments.
|
|
2013
2090
|
|
|
2014
|
-
@arg xs:
|
|
2015
|
-
positional.
|
|
2016
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
2017
|
-
to be scalar} (C{bool}).
|
|
2018
|
-
|
|
2019
|
-
@return: Precision C{fsum} (C{float}).
|
|
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}).
|
|
2020
2095
|
|
|
2021
|
-
@see: Function
|
|
2096
|
+
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2022
2097
|
'''
|
|
2023
|
-
return _fsum(xs if _xkwds_get(floats, floats=False) else
|
|
2098
|
+
return _fsum(xs if _xkwds_get(floats, floats=False) is True else
|
|
2024
2099
|
_2floats(xs, origin=1)) if xs else _0_0 # PYCHOK yield
|
|
2025
2100
|
|
|
2026
2101
|
|
|
2027
2102
|
def fsumf_(*xs):
|
|
2028
|
-
'''Precision floating point summation
|
|
2029
|
-
|
|
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.
|
|
2030
2106
|
'''
|
|
2031
2107
|
return _fsum(xs) if xs else _0_0
|
|
2032
2108
|
|
|
@@ -2034,44 +2110,44 @@ def fsumf_(*xs):
|
|
|
2034
2110
|
def fsum1(xs, floats=False):
|
|
2035
2111
|
'''Precision floating point summation, 1-primed.
|
|
2036
2112
|
|
|
2037
|
-
@arg xs: Iterable
|
|
2038
|
-
|
|
2039
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
2040
|
-
to be C{
|
|
2041
|
-
|
|
2042
|
-
@return: Precision C{fsum} (C{float}).
|
|
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}).
|
|
2043
2117
|
|
|
2044
|
-
@see: Function
|
|
2118
|
+
@see: Function L{fsum<fsums.fsum>} for further details.
|
|
2045
2119
|
'''
|
|
2046
|
-
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
|
|
2047
2121
|
|
|
2048
2122
|
|
|
2049
2123
|
def fsum1_(*xs, **floats):
|
|
2050
|
-
'''Precision floating point summation, 1-primed.
|
|
2124
|
+
'''Precision floating point summation, 1-primed of all positional arguments.
|
|
2051
2125
|
|
|
2052
|
-
@arg xs:
|
|
2053
|
-
positional.
|
|
2054
|
-
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are
|
|
2055
|
-
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}).
|
|
2056
2130
|
|
|
2057
|
-
@
|
|
2058
|
-
|
|
2059
|
-
@see: Function C{fsum}
|
|
2131
|
+
@see: Function L{fsum_<fsums.fsum_>} for further details.
|
|
2060
2132
|
'''
|
|
2061
|
-
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
|
|
2062
2134
|
_2floats(xs, origin=1))) if xs else _0_0 # PYCHOK yield
|
|
2063
2135
|
|
|
2064
2136
|
|
|
2065
2137
|
def fsum1f_(*xs):
|
|
2066
|
-
'''Precision floating point summation
|
|
2067
|
-
|
|
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.
|
|
2068
2141
|
'''
|
|
2069
2142
|
return _fsum(_1primed(xs)) if xs else _0_0
|
|
2070
2143
|
|
|
2071
2144
|
|
|
2072
2145
|
if __name__ == '__main__':
|
|
2073
2146
|
|
|
2074
|
-
# usage: [env
|
|
2147
|
+
# usage: [env _psum=fsum] python3 -m pygeodesy.fsums
|
|
2148
|
+
|
|
2149
|
+
if _getenv(_psum.__name__, NN) == _fsum.__name__:
|
|
2150
|
+
_psum = _fsum
|
|
2075
2151
|
|
|
2076
2152
|
def _test(n):
|
|
2077
2153
|
# copied from Hettinger, see L{Fsum} reference
|