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