pygeodesy 24.4.4__py2.py3-none-any.whl → 24.4.18__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.4.dist-info → PyGeodesy-24.4.18.dist-info}/METADATA +6 -6
- {PyGeodesy-24.4.4.dist-info → PyGeodesy-24.4.18.dist-info}/RECORD +40 -40
- pygeodesy/__init__.py +1 -1
- pygeodesy/albers.py +20 -27
- pygeodesy/auxilats/auxLat.py +3 -3
- pygeodesy/azimuthal.py +9 -8
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +14 -1
- pygeodesy/ecef.py +4 -4
- pygeodesy/ellipsoidalBase.py +2 -3
- pygeodesy/ellipsoids.py +4 -4
- pygeodesy/elliptic.py +27 -26
- pygeodesy/errors.py +27 -28
- pygeodesy/etm.py +3 -3
- pygeodesy/fmath.py +64 -65
- pygeodesy/frechet.py +6 -6
- pygeodesy/fstats.py +3 -4
- pygeodesy/fsums.py +506 -396
- pygeodesy/geodesicw.py +2 -2
- pygeodesy/geodsolve.py +4 -3
- pygeodesy/geoids.py +4 -4
- pygeodesy/hausdorff.py +5 -5
- pygeodesy/heights.py +6 -6
- pygeodesy/latlonBase.py +6 -6
- pygeodesy/lazily.py +3 -3
- pygeodesy/ltp.py +11 -11
- pygeodesy/ltpTuples.py +3 -4
- pygeodesy/named.py +14 -3
- pygeodesy/nvectorBase.py +5 -5
- pygeodesy/osgr.py +24 -24
- pygeodesy/points.py +3 -3
- pygeodesy/resections.py +16 -24
- pygeodesy/rhumb/bases.py +24 -25
- pygeodesy/sphericalNvector.py +6 -6
- pygeodesy/sphericalTrigonometry.py +3 -4
- pygeodesy/triaxials.py +4 -4
- pygeodesy/utmupsBase.py +6 -6
- pygeodesy/vector2d.py +9 -8
- {PyGeodesy-24.4.4.dist-info → PyGeodesy-24.4.18.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.4.4.dist-info → PyGeodesy-24.4.18.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -17,25 +17,24 @@ C{-1.0} and C{+1.0}, including C{INT0} if considered to be I{exact}.
|
|
|
17
17
|
Set env variable C{PYGEODESY_FSUM_PARTIALS} to string C{"fsum"}) for summation
|
|
18
18
|
of L{Fsum} partials by Python function C{math.fsum}.
|
|
19
19
|
|
|
20
|
-
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
and L{Fsum.__itruediv__}.
|
|
20
|
+
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} in division or exponention
|
|
22
|
+
of an L{Fsum} instance with a I{relative} C{residual} exceeding the threshold,
|
|
23
|
+
see methods L{Fsum.RESIDUAL}, L{Fsum.pow}, L{Fsum.__ipow__} and L{Fsum.__itruediv__}.
|
|
25
24
|
'''
|
|
26
25
|
# make sure int/int division yields float quotient, see .basics
|
|
27
26
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
28
27
|
|
|
29
28
|
from pygeodesy.basics import iscomplex, isint, isscalar, itemsorted, \
|
|
30
29
|
signOf, _signOf
|
|
31
|
-
from pygeodesy.constants import INT0, _isfinite,
|
|
30
|
+
from pygeodesy.constants import INT0, _isfinite, NEG0, _pos_self, \
|
|
32
31
|
_0_0, _1_0, _N_1_0, Float, Int
|
|
33
32
|
from pygeodesy.errors import _OverflowError, _TypeError, _ValueError, _xError, \
|
|
34
33
|
_xError2, _xkwds_get, _ZeroDivisionError
|
|
35
34
|
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DASH_, _DOT_, _EQUAL_, \
|
|
36
35
|
_exceeds_, _from_, _iadd_op_, _LANGLE_, _negative_, \
|
|
37
|
-
_NOTEQUAL_, _not_finite_,
|
|
38
|
-
|
|
36
|
+
_NOTEQUAL_, _not_finite_, _PERCENT_, _PLUS_, _R_, \
|
|
37
|
+
_RANGLE_, _SLASH_, _SPACE_, _STAR_, _UNDER_
|
|
39
38
|
from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
|
|
40
39
|
from pygeodesy.named import _Named, _NamedTuple, _NotImplemented, Fmt, unstr
|
|
41
40
|
from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
@@ -46,7 +45,7 @@ from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
|
46
45
|
from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
|
|
47
46
|
|
|
48
47
|
__all__ = _ALL_LAZY.fsums
|
|
49
|
-
__version__ = '24.04.
|
|
48
|
+
__version__ = '24.04.18'
|
|
50
49
|
|
|
51
50
|
_add_op_ = _PLUS_ # in .auxilats.auxAngle
|
|
52
51
|
_eq_op_ = _EQUAL_ * 2 # _DEQUAL_
|
|
@@ -72,54 +71,94 @@ _divmod_op_ = _floordiv_op_ + _mod_op_
|
|
|
72
71
|
_isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle, .fsums
|
|
73
72
|
|
|
74
73
|
|
|
74
|
+
def _2delta(*ab):
|
|
75
|
+
'''(INTERNAL) Helper for C{Fsum._fsum2}.
|
|
76
|
+
'''
|
|
77
|
+
try:
|
|
78
|
+
a, b = _2sum(*ab)
|
|
79
|
+
except _OverflowError:
|
|
80
|
+
a, b = ab
|
|
81
|
+
return float(a if fabs(a) > fabs(b) else b)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _2error(unused):
|
|
85
|
+
'''(INTERNAL) Throw a C{not finite} exception.
|
|
86
|
+
'''
|
|
87
|
+
raise ValueError(_not_finite_)
|
|
88
|
+
|
|
89
|
+
|
|
75
90
|
def _2float(index=None, **name_value): # in .fmath, .fstats
|
|
76
91
|
'''(INTERNAL) Raise C{TypeError} or C{ValueError} if not scalar or infinite.
|
|
77
92
|
'''
|
|
78
93
|
n, v = name_value.popitem() # _xkwds_item2(name_value)
|
|
79
94
|
try:
|
|
80
95
|
v = float(v)
|
|
81
|
-
if _isfinite(v)
|
|
82
|
-
return v
|
|
83
|
-
raise ValueError(_not_finite_)
|
|
96
|
+
return v if _isfinite(v) else _2error(v)
|
|
84
97
|
except Exception as X:
|
|
85
98
|
raise _xError(X, Fmt.INDEX(n, index), v)
|
|
86
99
|
|
|
87
100
|
|
|
88
|
-
def
|
|
101
|
+
def _X_ps(X): # for _2floats only
|
|
102
|
+
return X._ps
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _2floats(xs, origin=0, _X=_X_ps, _x=float):
|
|
89
106
|
'''(INTERNAL) Yield each B{C{xs}} as a C{float}.
|
|
90
107
|
'''
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
try:
|
|
109
|
+
i, x = origin, None
|
|
110
|
+
_fin = _isfinite
|
|
111
|
+
_Fs = Fsum
|
|
112
|
+
for x in xs:
|
|
113
|
+
if isinstance(x, _Fs):
|
|
114
|
+
for p in _X(x):
|
|
115
|
+
yield p
|
|
116
|
+
else:
|
|
117
|
+
f = _x(x)
|
|
118
|
+
yield f if _fin(f) else _2error(f)
|
|
119
|
+
i += 1
|
|
120
|
+
except Exception as X:
|
|
121
|
+
raise _xError(X, Fmt.INDEX(xs=i), x)
|
|
94
122
|
|
|
95
|
-
def _x(x):
|
|
96
|
-
return -float(x)
|
|
97
|
-
else:
|
|
98
|
-
def _X(X): # PYCHOK re-def
|
|
99
|
-
return X._ps
|
|
100
123
|
|
|
101
|
-
|
|
124
|
+
def _Fsumf_(*xs): # floats=True, in .auxLat, ...
|
|
125
|
+
'''(INTERNAL) An C{Fsum} of I{known scalars}.
|
|
126
|
+
'''
|
|
127
|
+
return Fsum()._facc_scalar(xs, up=False)
|
|
128
|
+
|
|
102
129
|
|
|
103
|
-
|
|
130
|
+
def _Fsum1f_(*xs): # floats=True, in .albers, ...
|
|
131
|
+
'''(INTERNAL) An C{Fsum} of I{known scalars}, 1-primed.
|
|
132
|
+
'''
|
|
133
|
+
return Fsum()._facc_scalar(_1primed(xs), up=False)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _2halfeven(s, r, p):
|
|
137
|
+
'''(INTERNAL) Round half-even.
|
|
138
|
+
'''
|
|
139
|
+
if (p > 0 and r > 0) or \
|
|
140
|
+
(p < 0 and r < 0): # signs match
|
|
141
|
+
r *= 2
|
|
142
|
+
t = s + r
|
|
143
|
+
if r == (t - s):
|
|
144
|
+
s = t
|
|
145
|
+
return s
|
|
104
146
|
|
|
105
147
|
|
|
106
148
|
def _1primed(xs): # in .fmath
|
|
107
|
-
'''(INTERNAL) 1-
|
|
108
|
-
|
|
149
|
+
'''(INTERNAL) 1-Primed summation of iterable C{xs}
|
|
150
|
+
items, all I{known} to be C{finite float}.
|
|
109
151
|
'''
|
|
110
152
|
yield _1_0
|
|
111
153
|
for x in xs:
|
|
112
|
-
|
|
113
|
-
yield x
|
|
154
|
+
yield x
|
|
114
155
|
yield _N_1_0
|
|
115
156
|
|
|
116
157
|
|
|
117
158
|
def _2ps(s, r):
|
|
118
159
|
'''(INTERNAL) Return a C{s} and C{r} pair, I{ps-ordered}.
|
|
119
160
|
'''
|
|
120
|
-
if fabs(s) < fabs(r)
|
|
121
|
-
s, r = r, s
|
|
122
|
-
return ((r, s) if s else (r,)) if r else (s,)
|
|
161
|
+
return (s, r) if fabs(s) < fabs(r) else (r, s)
|
|
123
162
|
|
|
124
163
|
|
|
125
164
|
def _psum(ps): # PYCHOK used!
|
|
@@ -136,20 +175,33 @@ def _psum(ps): # PYCHOK used!
|
|
|
136
175
|
if s:
|
|
137
176
|
ps[i:] = r, s
|
|
138
177
|
if i > 0:
|
|
139
|
-
|
|
140
|
-
if (p > 0 and r > 0) or \
|
|
141
|
-
(p < 0 and r < 0): # signs match
|
|
142
|
-
r *= 2
|
|
143
|
-
t = s + r
|
|
144
|
-
if r == (t - s):
|
|
145
|
-
s = t
|
|
178
|
+
s = _2halfeven(s, r, ps[i-1])
|
|
146
179
|
break # return s
|
|
147
180
|
s = r # PYCHOK no cover
|
|
148
181
|
ps[i:] = s,
|
|
149
182
|
return s
|
|
150
183
|
|
|
151
184
|
|
|
152
|
-
def
|
|
185
|
+
def _Psum(ps, **name):
|
|
186
|
+
'''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
|
|
187
|
+
'''
|
|
188
|
+
F = Fsum(**name) if name else Fsum()
|
|
189
|
+
if ps:
|
|
190
|
+
F._ps[:] = ps
|
|
191
|
+
F._n = len(F._ps)
|
|
192
|
+
return F
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _Psum_1(p=_1_0, **name):
|
|
196
|
+
'''(INTERNAL) Return an C{Fsum} from a single partial C{p}.
|
|
197
|
+
'''
|
|
198
|
+
F = Fsum(**name) if name else Fsum()
|
|
199
|
+
F._ps[:] = p,
|
|
200
|
+
F._n = 1 # len(F._ps)
|
|
201
|
+
return F
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _2scalar(other, _raiser=None, **mod):
|
|
153
205
|
'''(INTERNAL) Return B{C{other}} as C{int}, C{float} or C{as-is}.
|
|
154
206
|
'''
|
|
155
207
|
if isinstance(other, Fsum):
|
|
@@ -158,7 +210,8 @@ def _2scalar(other, _raiser=None):
|
|
|
158
210
|
s, r = other._fprs2
|
|
159
211
|
if r: # PYCHOK no cover
|
|
160
212
|
if _raiser and _raiser(r, s):
|
|
161
|
-
|
|
213
|
+
t = _stresidual(_non_zero_, r, **mod)
|
|
214
|
+
raise ResidualError(t, txt=None)
|
|
162
215
|
s = other # L{Fsum} as-is
|
|
163
216
|
else:
|
|
164
217
|
s = other # C{type} as-is
|
|
@@ -192,35 +245,13 @@ def _2sum(a, b): # by .testFmath
|
|
|
192
245
|
'''(INTERNAL) Return C{a + b} as 2-tuple (sum, residual).
|
|
193
246
|
'''
|
|
194
247
|
s = a + b
|
|
195
|
-
if
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def _2yield(xs, i, _X_ps, _x):
|
|
205
|
-
'''(INTERNAL) Yield each B{C{xs}} as a C{float}.
|
|
206
|
-
'''
|
|
207
|
-
x = None
|
|
208
|
-
try:
|
|
209
|
-
_fin = _isfinite
|
|
210
|
-
_Fs = Fsum
|
|
211
|
-
for x in xs:
|
|
212
|
-
if isinstance(x, _Fs):
|
|
213
|
-
for p in _X_ps(x):
|
|
214
|
-
yield p
|
|
215
|
-
else:
|
|
216
|
-
f = _x(x)
|
|
217
|
-
if f:
|
|
218
|
-
if not _fin(f):
|
|
219
|
-
raise ValueError(_not_finite_)
|
|
220
|
-
yield f
|
|
221
|
-
i += 1
|
|
222
|
-
except Exception as X:
|
|
223
|
-
raise _xError(X, Fmt.INDEX(xs=i), x)
|
|
248
|
+
if _isfinite(s):
|
|
249
|
+
if fabs(a) < fabs(b):
|
|
250
|
+
b, a = a, b
|
|
251
|
+
return s, (b - (s - a))
|
|
252
|
+
u = unstr(_2sum, a, b)
|
|
253
|
+
t = Fmt.PARENSPACED(_not_finite_, s)
|
|
254
|
+
raise _OverflowError(u, txt=t)
|
|
224
255
|
|
|
225
256
|
|
|
226
257
|
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
@@ -246,8 +277,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
246
277
|
_math_fsum = None
|
|
247
278
|
_n = 0
|
|
248
279
|
# _ps = [] # partial sums
|
|
249
|
-
#
|
|
250
|
-
_ratio = None
|
|
280
|
+
# _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps))
|
|
281
|
+
_ratio = None # see method _raiser
|
|
282
|
+
_recursive = bool(_getenv('PYGEODESY_FSUM_RECURSIVE', NN))
|
|
251
283
|
_RESIDUAL = max(float(_getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)), _0_0)
|
|
252
284
|
|
|
253
285
|
def __init__(self, *xs, **name_RESIDUAL):
|
|
@@ -267,22 +299,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
267
299
|
r = _xkwds_get(name_RESIDUAL, RESIDUAL=None)
|
|
268
300
|
if r is not None:
|
|
269
301
|
self.RESIDUAL(r) # ... ResidualError
|
|
270
|
-
# self._n = 0
|
|
271
302
|
self._ps = [] # [_0_0], see L{Fsum._fprs}
|
|
272
|
-
if
|
|
273
|
-
self._facc(
|
|
274
|
-
elif xs: # len(xs) == 1
|
|
275
|
-
self._n = 1
|
|
276
|
-
self._ps[:] = _2float(x=xs[0]),
|
|
303
|
+
if xs:
|
|
304
|
+
self._facc(xs, origin=1, up=False)
|
|
277
305
|
|
|
278
306
|
def __abs__(self):
|
|
279
307
|
'''Return this instance' absolute value as an L{Fsum}.
|
|
280
308
|
'''
|
|
281
|
-
s = _fsum(self.
|
|
309
|
+
s = _fsum(self._ps_1primed()) # == self._cmp_0(0, ...)
|
|
282
310
|
return (-self) if s < 0 else self._copy_2(self.__abs__)
|
|
283
311
|
|
|
284
312
|
def __add__(self, other):
|
|
285
|
-
'''Return
|
|
313
|
+
'''Return C{B{self} + B{other}} as an L{Fsum}.
|
|
286
314
|
|
|
287
315
|
@arg other: An L{Fsum} or C{scalar}.
|
|
288
316
|
|
|
@@ -338,7 +366,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
338
366
|
return self._cmp_0(other, _eq_op_) == 0
|
|
339
367
|
|
|
340
368
|
def __float__(self):
|
|
341
|
-
'''Return this instance' current precision running sum as C{float}.
|
|
369
|
+
'''Return this instance' current, precision running sum as C{float}.
|
|
342
370
|
|
|
343
371
|
@see: Methods L{Fsum.fsum} and L{Fsum.int_float}.
|
|
344
372
|
'''
|
|
@@ -462,13 +490,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
462
490
|
# Luciano Ramalho, "Fluent Python", O'Reilly, 2nd Ed, 2022 p. 567
|
|
463
491
|
return _NotImplemented(self)
|
|
464
492
|
|
|
465
|
-
def __ipow__(self, other, *mod): # PYCHOK 2 vs 3 args
|
|
493
|
+
def __ipow__(self, other, *mod, **raiser): # PYCHOK 2 vs 3 args
|
|
466
494
|
'''Apply C{B{self} **= B{other}} to this instance.
|
|
467
495
|
|
|
468
496
|
@arg other: The exponent (L{Fsum} or C{scalar}).
|
|
469
497
|
@arg mod: Optional modulus (C{int} or C{None}) for the
|
|
470
498
|
3-argument C{pow(B{self}, B{other}, B{mod})}
|
|
471
499
|
version.
|
|
500
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
501
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
472
502
|
|
|
473
503
|
@return: This instance, updated (L{Fsum}).
|
|
474
504
|
|
|
@@ -497,7 +527,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
497
527
|
@see: CPython function U{float_pow<https://GitHub.com/
|
|
498
528
|
python/cpython/blob/main/Objects/floatobject.c>}.
|
|
499
529
|
'''
|
|
500
|
-
return self._fpow(other, _pow_op_ + _fset_op_, *mod)
|
|
530
|
+
return self._fpow(other, _pow_op_ + _fset_op_, *mod, **raiser)
|
|
501
531
|
|
|
502
532
|
def __isub__(self, other):
|
|
503
533
|
'''Apply C{B{self} -= B{other}} to this instance.
|
|
@@ -517,10 +547,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
517
547
|
'''
|
|
518
548
|
return iter(self.partials)
|
|
519
549
|
|
|
520
|
-
def __itruediv__(self, other):
|
|
550
|
+
def __itruediv__(self, other, **raiser):
|
|
521
551
|
'''Apply C{B{self} /= B{other}} to this instance.
|
|
522
552
|
|
|
523
553
|
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
554
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
555
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
524
556
|
|
|
525
557
|
@return: This instance, updated (L{Fsum}).
|
|
526
558
|
|
|
@@ -537,7 +569,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
537
569
|
|
|
538
570
|
@see: Method L{Fsum.__ifloordiv__}.
|
|
539
571
|
'''
|
|
540
|
-
return self._ftruediv(other, _truediv_op_ + _fset_op_)
|
|
572
|
+
return self._ftruediv(other, _truediv_op_ + _fset_op_, **raiser)
|
|
541
573
|
|
|
542
574
|
def __le__(self, other):
|
|
543
575
|
'''Compare this with an other instance or C{scalar}.
|
|
@@ -654,8 +686,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
654
686
|
@arg ndigits: Optional number of digits (C{int}).
|
|
655
687
|
'''
|
|
656
688
|
# <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
|
|
657
|
-
return
|
|
658
|
-
|
|
689
|
+
return _Psum_1(round(float(self), *ndigits), # can be C{int}
|
|
690
|
+
name=self.__round__.__name__)
|
|
659
691
|
|
|
660
692
|
def __rpow__(self, other, *mod):
|
|
661
693
|
'''Return C{B{other}**B{self}} as an L{Fsum}.
|
|
@@ -673,13 +705,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
673
705
|
f = self._copy_2r(other, self.__rsub__)
|
|
674
706
|
return f._fsub(self, _sub_op_)
|
|
675
707
|
|
|
676
|
-
def __rtruediv__(self, other):
|
|
708
|
+
def __rtruediv__(self, other, **raiser):
|
|
677
709
|
'''Return C{B{other} / B{self}} as an L{Fsum}.
|
|
678
710
|
|
|
679
711
|
@see: Method L{Fsum.__itruediv__}.
|
|
680
712
|
'''
|
|
681
713
|
f = self._copy_2r(other, self.__rtruediv__)
|
|
682
|
-
return f._ftruediv(self, _truediv_op_)
|
|
714
|
+
return f._ftruediv(self, _truediv_op_, **raiser)
|
|
683
715
|
|
|
684
716
|
def __str__(self):
|
|
685
717
|
'''Return the default C{str(self)}.
|
|
@@ -698,17 +730,19 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
698
730
|
f = self._copy_2(self.__sub__)
|
|
699
731
|
return f._fsub(other, _sub_op_)
|
|
700
732
|
|
|
701
|
-
def __truediv__(self, other):
|
|
733
|
+
def __truediv__(self, other, **raiser):
|
|
702
734
|
'''Return C{B{self} / B{other}} as an L{Fsum}.
|
|
703
735
|
|
|
704
736
|
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
737
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
738
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
705
739
|
|
|
706
740
|
@return: The quotient (L{Fsum}).
|
|
707
741
|
|
|
708
742
|
@see: Method L{Fsum.__itruediv__}.
|
|
709
743
|
'''
|
|
710
744
|
f = self._copy_2(self.__truediv__)
|
|
711
|
-
return f._ftruediv(other, _truediv_op_)
|
|
745
|
+
return f._ftruediv(other, _truediv_op_, **raiser)
|
|
712
746
|
|
|
713
747
|
__trunc__ = __int__
|
|
714
748
|
|
|
@@ -757,15 +791,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
757
791
|
'''(INTERNAL) Return C{scalar(self - B{other})} for 0-comparison.
|
|
758
792
|
'''
|
|
759
793
|
if isinstance(other, Fsum):
|
|
760
|
-
s = _fsum(self.
|
|
761
|
-
elif
|
|
762
|
-
|
|
763
|
-
s = _fsum(self._ps_1(other))
|
|
764
|
-
else:
|
|
765
|
-
s, r = self._fprs2
|
|
766
|
-
s = _signOf(s, -r)
|
|
794
|
+
s = _fsum(self._ps_1primed(*other._ps))
|
|
795
|
+
elif self._scalar(other, op):
|
|
796
|
+
s = _fsum(self._ps_1primed(other))
|
|
767
797
|
else:
|
|
768
|
-
|
|
798
|
+
s, r = self._fprs2
|
|
799
|
+
s = _signOf(s, -r)
|
|
769
800
|
return s
|
|
770
801
|
|
|
771
802
|
def copy(self, deep=False, name=NN):
|
|
@@ -774,8 +805,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
774
805
|
@return: The copy (L{Fsum}).
|
|
775
806
|
'''
|
|
776
807
|
f = _Named.copy(self, deep=deep, name=name)
|
|
777
|
-
f.
|
|
778
|
-
|
|
808
|
+
if f._ps is self._ps:
|
|
809
|
+
f._ps = list(self._ps) # separate list
|
|
810
|
+
if not deep:
|
|
811
|
+
f._n = 1
|
|
779
812
|
return f
|
|
780
813
|
|
|
781
814
|
def _copy_2(self, which, name=NN):
|
|
@@ -801,11 +834,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
801
834
|
# if R is not Fsum._RESIDUAL:
|
|
802
835
|
# self._RESIDUAL = R
|
|
803
836
|
|
|
804
|
-
def divmod(self, other):
|
|
837
|
+
def divmod(self, other, **raiser):
|
|
805
838
|
'''Return C{divmod(B{self}, B{other})} as 2-tuple C{(quotient,
|
|
806
839
|
remainder)}.
|
|
807
840
|
|
|
808
841
|
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
842
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
843
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
809
844
|
|
|
810
845
|
@return: A L{DivMod2Tuple}C{(div, mod)}, with quotient C{div}
|
|
811
846
|
an C{int} in Python 3+ or C{float} in Python 2- and
|
|
@@ -814,12 +849,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
814
849
|
@see: Method L{Fsum.__itruediv__}.
|
|
815
850
|
'''
|
|
816
851
|
f = self._copy_2(self.divmod)
|
|
817
|
-
return f._fdivmod2(other, _divmod_op_)
|
|
852
|
+
return f._fdivmod2(other, _divmod_op_, **raiser)
|
|
818
853
|
|
|
819
854
|
def _Error(self, op, other, Error, **txt_cause):
|
|
820
855
|
'''(INTERNAL) Format an B{C{Error}} for C{{self} B{op} B{other}}.
|
|
821
856
|
'''
|
|
822
|
-
return Error(_SPACE_(self.
|
|
857
|
+
return Error(_SPACE_(self.toStr(), op, other), **txt_cause)
|
|
823
858
|
|
|
824
859
|
def _ErrorX(self, X, op, other, *mod):
|
|
825
860
|
'''(INTERNAL) Format the caught exception C{X}.
|
|
@@ -836,64 +871,89 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
836
871
|
n = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
|
|
837
872
|
return E(n, txt=t, cause=X)
|
|
838
873
|
|
|
839
|
-
def _facc(self, xs, up=True):
|
|
840
|
-
'''(INTERNAL) Accumulate more
|
|
874
|
+
def _facc(self, xs, up=True, **origin_X_x):
|
|
875
|
+
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s.
|
|
841
876
|
'''
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
i = 0
|
|
847
|
-
for p in ps:
|
|
848
|
-
x, p = _2s(x, p)
|
|
849
|
-
if p:
|
|
850
|
-
ps[i] = p
|
|
851
|
-
i += 1
|
|
852
|
-
ps[i:] = (x,) if x else ()
|
|
853
|
-
n += 1
|
|
854
|
-
# assert self._ps is ps
|
|
855
|
-
if n:
|
|
856
|
-
self._n += n
|
|
857
|
-
# Fsum._px = max(Fsum._px, len(ps))
|
|
858
|
-
if up:
|
|
859
|
-
self._update()
|
|
877
|
+
if xs:
|
|
878
|
+
_x = _2floats(xs, **origin_X_x) # PYCHOK yield
|
|
879
|
+
ps = self._ps
|
|
880
|
+
ps[:] = self._ps_acc(list(ps), _x, up=up)
|
|
860
881
|
return self
|
|
861
882
|
|
|
862
|
-
def
|
|
863
|
-
'''(INTERNAL) Accumulate
|
|
883
|
+
def _facc_1(self, xs, **up):
|
|
884
|
+
'''(INTERNAL) Accumulate 0, 1 or more C{scalars} or L{Fsum}s,
|
|
885
|
+
all positional C{xs} in the caller of this method.
|
|
864
886
|
'''
|
|
865
|
-
|
|
887
|
+
# assert islistuple(xs)
|
|
888
|
+
return self._fadd(xs[0], _add_op_) if len(xs) == 1 else \
|
|
889
|
+
self._facc(xs, origin=1, **up)
|
|
890
|
+
|
|
891
|
+
def _facc_neg(self, xs, up=True, **origin):
|
|
892
|
+
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s, negated.
|
|
893
|
+
'''
|
|
894
|
+
if xs:
|
|
895
|
+
def _neg(x):
|
|
896
|
+
return -x
|
|
866
897
|
|
|
867
|
-
|
|
898
|
+
_x = _2floats(xs, **origin) # PYCHOK yield
|
|
899
|
+
ps = self._ps
|
|
900
|
+
ps[:] = self._ps_acc(list(ps), map(_neg, _x), up=up)
|
|
901
|
+
return self
|
|
902
|
+
|
|
903
|
+
def _facc_power(self, power, xs, which, **raiser): # in .fmath
|
|
868
904
|
'''(INTERNAL) Add each C{xs} as C{float(x**power)}.
|
|
869
905
|
'''
|
|
870
|
-
p
|
|
871
|
-
|
|
872
|
-
if p
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
906
|
+
def _Pow4(p):
|
|
907
|
+
r = 0
|
|
908
|
+
if isinstance(p, Fsum):
|
|
909
|
+
s, r = p._fprs2
|
|
910
|
+
if r:
|
|
911
|
+
return _Pow4(s)
|
|
912
|
+
m = Fsum._pow
|
|
913
|
+
elif isint(p, both=True) and int(p) >= 0:
|
|
914
|
+
p = s = int(p)
|
|
915
|
+
m = Fsum._pow_int
|
|
916
|
+
else:
|
|
917
|
+
p = s = _2float(power=p)
|
|
918
|
+
m = Fsum._pow_scalar
|
|
919
|
+
return m, p, s, r
|
|
879
920
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
921
|
+
_Pow, p, s, r = _Pow4(power)
|
|
922
|
+
if p: # and xs:
|
|
923
|
+
_pow = Fsum._pow_2_3
|
|
924
|
+
_Fs = Fsum
|
|
925
|
+
_Ps = _Psum_1()._fset_ps_
|
|
926
|
+
op = which.__name__
|
|
883
927
|
|
|
884
928
|
def _X(X):
|
|
885
|
-
f = _Pow(X, p, power, op)
|
|
886
|
-
|
|
887
|
-
return f._ps
|
|
888
|
-
except AttributeError: # scalar
|
|
889
|
-
return f,
|
|
929
|
+
f = _Pow(X, p, power, op, **raiser)
|
|
930
|
+
return f._ps if isinstance(f, _Fs) else (f,)
|
|
890
931
|
|
|
891
932
|
def _x(x):
|
|
892
|
-
|
|
933
|
+
x = float(x)
|
|
934
|
+
X = _Ps(x)
|
|
935
|
+
f = _pow(X, x, s, power, op, **raiser)
|
|
936
|
+
if r:
|
|
937
|
+
f *= _pow(X, x, r, power, op, **raiser)
|
|
938
|
+
return f
|
|
893
939
|
|
|
894
|
-
self._facc(
|
|
940
|
+
f = self._facc(xs, origin=1, _X=_X, _x=_x)
|
|
895
941
|
else:
|
|
896
|
-
self.
|
|
942
|
+
f = self._facc_scalar_(float(len(xs))) # x**0 == 1
|
|
943
|
+
return f
|
|
944
|
+
|
|
945
|
+
def _facc_scalar(self, xs, **up):
|
|
946
|
+
'''(INTERNAL) Accumulate all C{xs}, known to be scalar.
|
|
947
|
+
'''
|
|
948
|
+
if xs:
|
|
949
|
+
self._ps_acc(self._ps, xs, **up)
|
|
950
|
+
return self
|
|
951
|
+
|
|
952
|
+
def _facc_scalar_(self, *xs, **up):
|
|
953
|
+
'''(INTERNAL) Accumulate all positional C{xs}, known to be scalar.
|
|
954
|
+
'''
|
|
955
|
+
if xs:
|
|
956
|
+
self._ps_acc(self._ps, xs, **up)
|
|
897
957
|
return self
|
|
898
958
|
|
|
899
959
|
# def _facc_up(self, up=True):
|
|
@@ -904,7 +964,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
904
964
|
# p = self._ps.pop()
|
|
905
965
|
# if p:
|
|
906
966
|
# n = self._n
|
|
907
|
-
# self.
|
|
967
|
+
# self._facc_scalar_(p, up=False)
|
|
908
968
|
# self._n = n
|
|
909
969
|
# break
|
|
910
970
|
# return self._update() if up else self # ._fpsqz()
|
|
@@ -926,11 +986,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
926
986
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
927
987
|
'''
|
|
928
988
|
if isinstance(xs, Fsum):
|
|
929
|
-
self.
|
|
989
|
+
self._facc_scalar(xs._ps) # tuple
|
|
930
990
|
elif isscalar(xs): # for backward compatibility
|
|
931
|
-
self.
|
|
932
|
-
elif xs:
|
|
933
|
-
self._facc(
|
|
991
|
+
self._facc_scalar_(_2float(x=xs)) # PYCHOK no cover
|
|
992
|
+
elif xs: # assert isiterable(xs)
|
|
993
|
+
self._facc(xs)
|
|
934
994
|
return self
|
|
935
995
|
|
|
936
996
|
def fadd_(self, *xs):
|
|
@@ -949,33 +1009,29 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
949
1009
|
|
|
950
1010
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
951
1011
|
'''
|
|
952
|
-
return self.
|
|
1012
|
+
return self._facc_1(xs)
|
|
953
1013
|
|
|
954
1014
|
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
955
1015
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
956
1016
|
'''
|
|
957
1017
|
if isinstance(other, Fsum):
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
self._facc(other._ps, **up)
|
|
962
|
-
elif not isscalar(other):
|
|
963
|
-
raise self._TypeError(op, other) # txt=_invalid_
|
|
964
|
-
elif other:
|
|
965
|
-
self._facc_(other, **up)
|
|
1018
|
+
self._facc_scalar(other._ps, **up) # tuple
|
|
1019
|
+
elif self._scalar(other, op):
|
|
1020
|
+
self._facc_scalar_(other, **up)
|
|
966
1021
|
return self
|
|
967
1022
|
|
|
968
1023
|
fcopy = copy # for backward compatibility
|
|
969
1024
|
fdiv = __itruediv__ # for backward compatibility
|
|
970
1025
|
fdivmod = __divmod__ # for backward compatibility
|
|
971
1026
|
|
|
972
|
-
def _fdivmod2(self, other, op):
|
|
1027
|
+
def _fdivmod2(self, other, op, **raiser):
|
|
973
1028
|
'''(INTERNAL) Apply C{B{self} %= B{other}} and return a L{DivMod2Tuple}.
|
|
974
1029
|
'''
|
|
975
1030
|
# result mostly follows CPython function U{float_divmod
|
|
976
1031
|
# <https://GitHub.com/python/cpython/blob/main/Objects/floatobject.c>},
|
|
977
1032
|
# but at least divmod(-3, 2) equals Cpython's result (-2, 1).
|
|
978
|
-
|
|
1033
|
+
f = self._copy_2(self._fdivmod2)
|
|
1034
|
+
q = f._ftruediv(other, op, **raiser).floor
|
|
979
1035
|
if q: # == float // other == floor(float / other)
|
|
980
1036
|
self -= other * q
|
|
981
1037
|
|
|
@@ -999,8 +1055,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
999
1055
|
def fint(self, raiser=True, **name):
|
|
1000
1056
|
'''Return this instance' current running sum as C{integer}.
|
|
1001
1057
|
|
|
1002
|
-
@kwarg raiser:
|
|
1003
|
-
|
|
1058
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
1059
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
1004
1060
|
@kwarg name: Optional name (C{str}), overriding C{"fint"}.
|
|
1005
1061
|
|
|
1006
1062
|
@return: The C{integer} (L{Fsum}).
|
|
@@ -1034,8 +1090,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1034
1090
|
'''
|
|
1035
1091
|
s, r = self._fprs2
|
|
1036
1092
|
i = int(s)
|
|
1037
|
-
r = _fsum(self.
|
|
1038
|
-
return i, (r or INT0)
|
|
1093
|
+
r = _fsum(self._ps_1primed(i)) if r else float(s - i)
|
|
1094
|
+
return i, (r or INT0) # Fsum2Tuple?
|
|
1039
1095
|
|
|
1040
1096
|
@deprecated_property_RO
|
|
1041
1097
|
def float_int(self): # PYCHOK no cover
|
|
@@ -1060,10 +1116,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1060
1116
|
|
|
1061
1117
|
# floordiv = __floordiv__ # for naming consistency
|
|
1062
1118
|
|
|
1063
|
-
def _floordiv(self, other, op): # rather _ffloordiv?
|
|
1119
|
+
def _floordiv(self, other, op, **raiser): # rather _ffloordiv?
|
|
1064
1120
|
'''Apply C{B{self} //= B{other}}.
|
|
1065
1121
|
'''
|
|
1066
|
-
q = self._ftruediv(other, op) # == self
|
|
1122
|
+
q = self._ftruediv(other, op, **raiser) # == self
|
|
1067
1123
|
return self._fset(q.floor) # floor(q)
|
|
1068
1124
|
|
|
1069
1125
|
fmul = __imul__ # for backward compatibility
|
|
@@ -1078,41 +1134,42 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1078
1134
|
f = other._mul_scalar(self._ps[0], op)
|
|
1079
1135
|
else: # len(other._ps) == len(self._ps) == 1
|
|
1080
1136
|
f = self._finite(self._ps[0] * other._ps[0])
|
|
1081
|
-
elif isscalar(other):
|
|
1082
|
-
f = self._mul_scalar(other, op)
|
|
1083
1137
|
else:
|
|
1084
|
-
|
|
1138
|
+
s = self._scalar(other, op)
|
|
1139
|
+
f = self._mul_scalar(s, op)
|
|
1085
1140
|
return self._fset(f) # n=len(self) + 1
|
|
1086
1141
|
|
|
1087
|
-
def fover(self, over):
|
|
1142
|
+
def fover(self, over, **raiser):
|
|
1088
1143
|
'''Apply C{B{self} /= B{over}} and summate.
|
|
1089
1144
|
|
|
1090
1145
|
@arg over: An L{Fsum} or C{scalar} denominator.
|
|
1146
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
1147
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
1091
1148
|
|
|
1092
1149
|
@return: Precision running sum (C{float}).
|
|
1093
1150
|
|
|
1094
1151
|
@see: Methods L{Fsum.fsum} and L{Fsum.__itruediv__}.
|
|
1095
1152
|
'''
|
|
1096
|
-
return float(self.fdiv(over)._fprs)
|
|
1153
|
+
return float(self.fdiv(over, **raiser)._fprs)
|
|
1097
1154
|
|
|
1098
1155
|
fpow = __ipow__ # for backward compatibility
|
|
1099
1156
|
|
|
1100
|
-
def _fpow(self, other, op, *mod):
|
|
1157
|
+
def _fpow(self, other, op, *mod, **raiser):
|
|
1101
1158
|
'''Apply C{B{self} **= B{other}}, optional B{C{mod}} or C{None}.
|
|
1102
1159
|
'''
|
|
1103
1160
|
if mod:
|
|
1104
1161
|
if mod[0] is not None: # == 3-arg C{pow}
|
|
1105
|
-
f = self.
|
|
1162
|
+
f = self._pow_2_3(self, other, other, op, *mod, **raiser)
|
|
1106
1163
|
elif self.is_integer():
|
|
1107
1164
|
# return an exact C{int} for C{int}**C{int}
|
|
1165
|
+
i, _ = self._fint2 # assert _ == 0
|
|
1108
1166
|
x = _2scalar(other) # C{int}, C{float} or other
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
_Fsum_ps(i)._pow_any(x, other, op)
|
|
1167
|
+
f = self._pow_2_3(i, x, other, op, **raiser) if isscalar(x) else \
|
|
1168
|
+
_Psum_1(i)._pow( x, other, op, **raiser) # x is Fsum
|
|
1112
1169
|
else: # mod[0] is None, power(self, other)
|
|
1113
|
-
f = self.
|
|
1114
|
-
else: # pow(self, other)
|
|
1115
|
-
f = self.
|
|
1170
|
+
f = self._pow(other, other, op, **raiser)
|
|
1171
|
+
else: # pow(self, other)
|
|
1172
|
+
f = self._pow(other, other, op, **raiser)
|
|
1116
1173
|
return self._fset(f, asis=isint(f)) # n=max(len(self), 1)
|
|
1117
1174
|
|
|
1118
1175
|
@Property_RO
|
|
@@ -1134,8 +1191,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1134
1191
|
n = len(ps) - 2
|
|
1135
1192
|
if n > 0: # len(ps) > 2
|
|
1136
1193
|
s = _psum(ps)
|
|
1137
|
-
|
|
1138
|
-
|
|
1194
|
+
n = len(ps) - 2
|
|
1195
|
+
if n > 0:
|
|
1196
|
+
r = _fsum(self._ps_1primed(s)) or INT0
|
|
1197
|
+
return Fsum2Tuple(s, r)
|
|
1198
|
+
if n == 0: # len(ps) == 2
|
|
1139
1199
|
ps[:] = _2ps(*_2sum(*ps))
|
|
1140
1200
|
r, s = (INT0, ps[0]) if len(ps) != 2 else ps
|
|
1141
1201
|
elif ps: # len(ps) == 1
|
|
@@ -1150,7 +1210,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1150
1210
|
# '''(INTERNAL) Compress, squeeze the C{partials}.
|
|
1151
1211
|
# '''
|
|
1152
1212
|
# if len(self._ps) > 2:
|
|
1153
|
-
# _ = self.
|
|
1213
|
+
# _ = self._fprs2
|
|
1154
1214
|
# return self
|
|
1155
1215
|
|
|
1156
1216
|
def fset_(self, *xs):
|
|
@@ -1163,18 +1223,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1163
1223
|
|
|
1164
1224
|
@see: Method L{Fsum.fadd} for further details.
|
|
1165
1225
|
'''
|
|
1166
|
-
self._n = 0
|
|
1167
1226
|
self._ps[:] = 0,
|
|
1227
|
+
self._n = 0
|
|
1168
1228
|
return self.fadd(xs) if xs else self._update()
|
|
1169
1229
|
|
|
1170
1230
|
def _fset(self, other, asis=True, n=0):
|
|
1171
1231
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
1172
1232
|
'''
|
|
1173
1233
|
if other is self:
|
|
1174
|
-
pass # from ._fmul, ._ftruediv and .
|
|
1234
|
+
pass # from ._fmul, ._ftruediv and ._pow_0_1
|
|
1175
1235
|
elif isinstance(other, Fsum):
|
|
1176
|
-
self._n = n or other._n
|
|
1177
1236
|
self._ps[:] = other._ps
|
|
1237
|
+
self._n = n or other._n
|
|
1178
1238
|
# self._copy_RESIDUAL(other)
|
|
1179
1239
|
# use or zap the C{Property_RO} values
|
|
1180
1240
|
Fsum._fint2._update_from(self, other)
|
|
@@ -1184,24 +1244,32 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1184
1244
|
s = other if asis else float(other)
|
|
1185
1245
|
i = int(s) # see ._fint2
|
|
1186
1246
|
t = i, ((s - i) or INT0)
|
|
1187
|
-
self._n = n or 1
|
|
1188
1247
|
self._ps[:] = s,
|
|
1248
|
+
self._n = n or 1
|
|
1189
1249
|
# Property_ROs _fint2, _fprs and _fprs2 can't be a Property:
|
|
1190
1250
|
# Property's _fset zaps the value just set by the @setter
|
|
1191
1251
|
self.__dict__.update(_fint2=t, _fprs=s, _fprs2=Fsum2Tuple(s, INT0))
|
|
1192
1252
|
else: # PYCHOK no cover
|
|
1193
|
-
raise self._TypeError(_fset_op_, other) #
|
|
1253
|
+
raise self._TypeError(_fset_op_, other) # AssertionError
|
|
1194
1254
|
return self
|
|
1195
1255
|
|
|
1196
1256
|
def _fset_ps(self, other, n=0): # in .fmath
|
|
1197
|
-
'''(INTERNAL) Set a known C{Fsum} or C{scalar}.
|
|
1257
|
+
'''(INTERNAL) Set partials from a known C{Fsum} or C{scalar}.
|
|
1198
1258
|
'''
|
|
1199
1259
|
if isinstance(other, Fsum):
|
|
1200
|
-
self._n = n or other._n
|
|
1201
1260
|
self._ps[:] = other._ps
|
|
1261
|
+
self._n = n or other._n
|
|
1202
1262
|
else: # assert isscalar(other)
|
|
1203
|
-
self._n = n or 1
|
|
1204
1263
|
self._ps[:] = other,
|
|
1264
|
+
self._n = n or 1
|
|
1265
|
+
return self
|
|
1266
|
+
|
|
1267
|
+
def _fset_ps_(self, *xs):
|
|
1268
|
+
'''(INTERNAL) Set partials to all known scalar C{xs}.
|
|
1269
|
+
'''
|
|
1270
|
+
self._ps[:] = xs
|
|
1271
|
+
self.n = len(xs)
|
|
1272
|
+
return self
|
|
1205
1273
|
|
|
1206
1274
|
def fsub(self, xs=()):
|
|
1207
1275
|
'''Subtract an iterable of C{scalar} or L{Fsum} instances from
|
|
@@ -1214,7 +1282,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1214
1282
|
|
|
1215
1283
|
@see: Method L{Fsum.fadd}.
|
|
1216
1284
|
'''
|
|
1217
|
-
return self.
|
|
1285
|
+
return self._facc_neg(xs)
|
|
1218
1286
|
|
|
1219
1287
|
def fsub_(self, *xs):
|
|
1220
1288
|
'''Subtract all positional C{scalar} or L{Fsum} instances from
|
|
@@ -1227,7 +1295,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1227
1295
|
|
|
1228
1296
|
@see: Method L{Fsum.fadd}.
|
|
1229
1297
|
'''
|
|
1230
|
-
return self.
|
|
1298
|
+
return self._fsub(xs[0], _sub_op_) if len(xs) == 1 else \
|
|
1299
|
+
self._facc_neg(xs, origin=1)
|
|
1231
1300
|
|
|
1232
1301
|
def _fsub(self, other, op):
|
|
1233
1302
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
@@ -1236,11 +1305,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1236
1305
|
if other is self: # or other._fprs2 == self._fprs2:
|
|
1237
1306
|
self._fset(_0_0) # n=len(self) * 2, self -= self
|
|
1238
1307
|
elif other._ps:
|
|
1239
|
-
self.
|
|
1240
|
-
elif
|
|
1241
|
-
|
|
1242
|
-
elif self._finite(other, op):
|
|
1243
|
-
self._facc_(-other)
|
|
1308
|
+
self._facc_scalar(other._ps_neg)
|
|
1309
|
+
elif self._scalar(other, op):
|
|
1310
|
+
self._facc_scalar_(-self._finite(other, op))
|
|
1244
1311
|
return self
|
|
1245
1312
|
|
|
1246
1313
|
def fsum(self, xs=()):
|
|
@@ -1255,21 +1322,26 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1255
1322
|
|
|
1256
1323
|
@note: Accumulation can continue after summation.
|
|
1257
1324
|
'''
|
|
1258
|
-
|
|
1259
|
-
return f._fprs
|
|
1325
|
+
return self._facc(xs)._fprs
|
|
1260
1326
|
|
|
1261
1327
|
def fsum_(self, *xs):
|
|
1262
1328
|
'''Add all positional C{scalar} or L{Fsum} instances and summate.
|
|
1263
1329
|
|
|
1264
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1265
|
-
|
|
1330
|
+
@arg xs: Values to add (C{scalar} or L{Fsum} instances), all
|
|
1331
|
+
positional.
|
|
1266
1332
|
|
|
1267
1333
|
@return: Precision running sum (C{float} or C{int}).
|
|
1268
1334
|
|
|
1269
|
-
@see: Methods L{Fsum.fsum} and L{Fsum.fsumf_}.
|
|
1335
|
+
@see: Methods L{Fsum.fsum}, L{Fsum.Fsum_} and L{Fsum.fsumf_}.
|
|
1336
|
+
'''
|
|
1337
|
+
return self._facc_1(xs)._fprs
|
|
1338
|
+
|
|
1339
|
+
def Fsum_(self, *xs):
|
|
1340
|
+
'''Like method L{Fsum.fsum_} but returning an L{Fsum}.
|
|
1341
|
+
|
|
1342
|
+
@return: Current, precision running sum (L{Fsum}).
|
|
1270
1343
|
'''
|
|
1271
|
-
|
|
1272
|
-
return f._fprs
|
|
1344
|
+
return self._facc_1(xs)._copy_2(self.Fsum_)
|
|
1273
1345
|
|
|
1274
1346
|
def fsum2(self, xs=(), name=NN):
|
|
1275
1347
|
'''Add more C{scalar} or L{Fsum} instances and return the
|
|
@@ -1287,66 +1359,74 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1287
1359
|
|
|
1288
1360
|
@see: Methods L{Fsum.fint2}, L{Fsum.fsum} and L{Fsum.fsum2_}
|
|
1289
1361
|
'''
|
|
1290
|
-
|
|
1291
|
-
t
|
|
1292
|
-
if name:
|
|
1293
|
-
t = t.dup(name=name)
|
|
1294
|
-
return t
|
|
1362
|
+
t = self._facc(xs)._fprs2
|
|
1363
|
+
return t.dup(name=name) if name else t
|
|
1295
1364
|
|
|
1296
1365
|
def fsum2_(self, *xs):
|
|
1297
1366
|
'''Add any positional C{scalar} or L{Fsum} instances and return
|
|
1298
1367
|
the precision running sum and the C{differential}.
|
|
1299
1368
|
|
|
1300
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1301
|
-
|
|
1369
|
+
@arg xs: Values to add (C{scalar} or L{Fsum} instances), all
|
|
1370
|
+
positional.
|
|
1302
1371
|
|
|
1303
|
-
@return:
|
|
1304
|
-
running C{fsum} and C{delta},
|
|
1305
|
-
the previous running C{fsum}
|
|
1372
|
+
@return: 2Tuple C{(fsum, delta)} with the current, precision
|
|
1373
|
+
running C{fsum} like method L{Fsum.fsum} and C{delta},
|
|
1374
|
+
the difference with previous running C{fsum}, C{float}.
|
|
1306
1375
|
|
|
1307
1376
|
@see: Methods L{Fsum.fsum_} and L{Fsum.fsum}.
|
|
1308
1377
|
'''
|
|
1309
|
-
|
|
1378
|
+
return self._fsum2(xs, self._facc_1)
|
|
1379
|
+
|
|
1380
|
+
def _fsum2(self, xs, _f, **origin):
|
|
1381
|
+
'''(INTERNAL) Helper for L{Fsum.fsum2_} and L{Fsum.fsum2f_}.
|
|
1382
|
+
'''
|
|
1383
|
+
p, q = self._fprs2
|
|
1310
1384
|
if xs:
|
|
1311
|
-
s,
|
|
1312
|
-
return s,
|
|
1313
|
-
else:
|
|
1385
|
+
s, r = _f(xs, **origin)._fprs2
|
|
1386
|
+
return s, _2delta(s - p, r - q) # _fsum(_1primed((s, -p, r, -q))
|
|
1387
|
+
else:
|
|
1314
1388
|
return p, _0_0
|
|
1315
1389
|
|
|
1316
1390
|
def fsumf_(self, *xs):
|
|
1317
|
-
'''Like method L{Fsum.fsum_} but only for
|
|
1391
|
+
'''Like method L{Fsum.fsum_} but only for C{B{xs}}, I{known to be scalar}.
|
|
1392
|
+
'''
|
|
1393
|
+
return self._facc_scalar(xs)._fprs
|
|
1394
|
+
|
|
1395
|
+
def Fsumf_(self, *xs):
|
|
1396
|
+
'''Like method L{Fsum.Fsum_} but only for C{B{xs}}, I{known to be scalar}.
|
|
1397
|
+
'''
|
|
1398
|
+
return self._facc_scalar(xs)._copy_2(self.Fsumf_)
|
|
1399
|
+
|
|
1400
|
+
def fsum2f_(self, *xs):
|
|
1401
|
+
'''Like method L{Fsum.fsum2_} but only for C{B{xs}}, I{known to be scalar}.
|
|
1318
1402
|
'''
|
|
1319
|
-
|
|
1320
|
-
return f._fprs
|
|
1403
|
+
return self._fsum2(xs, self._facc_scalar, origin=1)
|
|
1321
1404
|
|
|
1322
|
-
# ftruediv = __itruediv__ # for naming consistency
|
|
1405
|
+
# ftruediv = __itruediv__ # for naming consistency?
|
|
1323
1406
|
|
|
1324
|
-
def _ftruediv(self, other, op):
|
|
1407
|
+
def _ftruediv(self, other, op, **raiser):
|
|
1325
1408
|
'''(INTERNAL) Apply C{B{self} /= B{other}}.
|
|
1326
1409
|
'''
|
|
1327
1410
|
n = _1_0
|
|
1328
1411
|
if isinstance(other, Fsum):
|
|
1329
1412
|
if other is self or other == self:
|
|
1330
|
-
return self._fset(
|
|
1413
|
+
return self._fset(n) # n=len(self)
|
|
1331
1414
|
d, r = other._fprs2
|
|
1332
1415
|
if r:
|
|
1333
1416
|
if d:
|
|
1334
|
-
if self._raiser(r, d):
|
|
1417
|
+
if self._raiser(r, d, **raiser):
|
|
1335
1418
|
raise self._ResidualError(op, other, r)
|
|
1336
1419
|
d, n = other.as_integer_ratio()
|
|
1337
1420
|
else: # PYCHOK no cover
|
|
1338
1421
|
d = r
|
|
1339
|
-
|
|
1340
|
-
d = other
|
|
1341
|
-
else: # PYCHOK no cover
|
|
1342
|
-
raise self._TypeError(op, other) # txt=_invalid_
|
|
1422
|
+
else:
|
|
1423
|
+
d = self._scalar(other, op)
|
|
1343
1424
|
try:
|
|
1344
|
-
s =
|
|
1345
|
-
d if isnan(d) else self._finite(n / d))
|
|
1425
|
+
s = n / d
|
|
1346
1426
|
except Exception as X:
|
|
1347
1427
|
raise self._ErrorX(X, op, other)
|
|
1348
|
-
f = self._mul_scalar(s, _mul_op_) # handles 0,
|
|
1349
|
-
return self._fset(f
|
|
1428
|
+
f = self._mul_scalar(s, _mul_op_) # handles 0, INF, NAN
|
|
1429
|
+
return self._fset(f) # asis=False
|
|
1350
1430
|
|
|
1351
1431
|
@property_RO
|
|
1352
1432
|
def imag(self):
|
|
@@ -1360,7 +1440,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1360
1440
|
'''Return this instance' current running sum as C{int} or C{float}.
|
|
1361
1441
|
|
|
1362
1442
|
@kwarg raiser: If C{True} throw a L{ResidualError} if the
|
|
1363
|
-
residual is non-zero.
|
|
1443
|
+
residual is non-zero (C{bool}).
|
|
1364
1444
|
|
|
1365
1445
|
@return: This C{integer} sum if this instance C{is_integer},
|
|
1366
1446
|
otherwise return the C{float} sum if the residual
|
|
@@ -1380,13 +1460,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1380
1460
|
return s
|
|
1381
1461
|
|
|
1382
1462
|
def is_exact(self):
|
|
1383
|
-
'''Is this instance'
|
|
1384
|
-
be exact? (C{bool}).
|
|
1463
|
+
'''Is this instance' running C{fsum} considered to be exact? (C{bool}).
|
|
1385
1464
|
'''
|
|
1386
1465
|
return self.residual is INT0
|
|
1387
1466
|
|
|
1388
1467
|
def is_integer(self):
|
|
1389
|
-
'''Is this instance'
|
|
1468
|
+
'''Is this instance' running sum C{integer}? (C{bool}).
|
|
1390
1469
|
|
|
1391
1470
|
@see: Methods L{Fsum.fint} and L{Fsum.fint2}.
|
|
1392
1471
|
'''
|
|
@@ -1412,7 +1491,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1412
1491
|
'''
|
|
1413
1492
|
# assert isinstance(other, Fsum)
|
|
1414
1493
|
if self._ps and other._ps:
|
|
1415
|
-
f =
|
|
1494
|
+
f = self._ps_mul(op, *other._ps) # NO ._2scalar
|
|
1416
1495
|
else:
|
|
1417
1496
|
f = _0_0
|
|
1418
1497
|
return f
|
|
@@ -1424,133 +1503,119 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1424
1503
|
if self._ps and self._finite(factor, op):
|
|
1425
1504
|
f = self if factor == _1_0 else (
|
|
1426
1505
|
self._neg if factor == _N_1_0 else
|
|
1427
|
-
|
|
1506
|
+
self._ps_mul(op, factor)._2scalar)
|
|
1428
1507
|
else:
|
|
1429
1508
|
f = _0_0
|
|
1430
1509
|
return f
|
|
1431
1510
|
|
|
1432
1511
|
@property_RO
|
|
1433
1512
|
def _neg(self):
|
|
1434
|
-
'''(INTERNAL) Return C{-self}.
|
|
1513
|
+
'''(INTERNAL) Return C{Fsum(-self)} or scalar C{NEG0}.
|
|
1435
1514
|
'''
|
|
1436
|
-
return
|
|
1515
|
+
return _Psum(self._ps_neg) if self._ps else NEG0
|
|
1437
1516
|
|
|
1438
1517
|
@property_RO
|
|
1439
1518
|
def partials(self):
|
|
1440
|
-
'''Get this instance' current partial sums (C{tuple} of C{float}s
|
|
1519
|
+
'''Get this instance' current, partial sums (C{tuple} of C{float}s).
|
|
1441
1520
|
'''
|
|
1442
1521
|
return tuple(self._ps)
|
|
1443
1522
|
|
|
1444
|
-
def pow(self, x, *mod):
|
|
1523
|
+
def pow(self, x, *mod, **raiser):
|
|
1445
1524
|
'''Return C{B{self}**B{x}} as L{Fsum}.
|
|
1446
1525
|
|
|
1447
1526
|
@arg x: The exponent (L{Fsum} or C{scalar}).
|
|
1448
1527
|
@arg mod: Optional modulus (C{int} or C{None}) for the 3-argument
|
|
1449
1528
|
C{pow(B{self}, B{other}, B{mod})} version.
|
|
1529
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
1530
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
1450
1531
|
|
|
1451
1532
|
@return: The C{pow(self, B{x})} or C{pow(self, B{x}, *B{mod})}
|
|
1452
1533
|
result (L{Fsum}).
|
|
1453
1534
|
|
|
1454
1535
|
@note: If B{C{mod}} is given as C{None}, the result will be an
|
|
1455
1536
|
C{integer} L{Fsum} provided this instance C{is_integer}
|
|
1456
|
-
or set to C{integer}
|
|
1537
|
+
or set to C{integer} by an L{Fsum.fint} call.
|
|
1457
1538
|
|
|
1458
|
-
@see: Methods L{Fsum.__ipow__}, L{Fsum.fint}
|
|
1539
|
+
@see: Methods L{Fsum.__ipow__}, L{Fsum.fint}, L{Fsum.is_integer}
|
|
1540
|
+
and L{Fsum.root}.
|
|
1459
1541
|
'''
|
|
1460
1542
|
f = self._copy_2(self.pow)
|
|
1461
|
-
return f._fpow(x, _pow_op_, *mod) # f = pow(f, x, *mod)
|
|
1543
|
+
return f._fpow(x, _pow_op_, *mod, **raiser) # f = pow(f, x, *mod)
|
|
1462
1544
|
|
|
1463
|
-
def
|
|
1464
|
-
'''(INTERNAL) Return B{C{self}**1} or C{B{self}**0 == 1.0}.
|
|
1465
|
-
'''
|
|
1466
|
-
return self if x else (1 if isint(other) and self.is_integer() else _1_0)
|
|
1467
|
-
|
|
1468
|
-
def _pow_2(self, b, x, other, op):
|
|
1469
|
-
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} embellishing errors.
|
|
1470
|
-
'''
|
|
1471
|
-
# assert isscalar(b) and isscalar(x)
|
|
1472
|
-
try: # type(s) == type(x) if x in (_1_0, 1)
|
|
1473
|
-
s = pow(b, x) # -1**2.3 == -(1**2.3)
|
|
1474
|
-
if not iscomplex(s):
|
|
1475
|
-
return self._finite(s) # 0**INF == 0.0, 1**INF==1.0
|
|
1476
|
-
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1477
|
-
raise ValueError(_strcomplex(s, b, x)) # PYCHOK no cover
|
|
1478
|
-
except Exception as X:
|
|
1479
|
-
raise self._ErrorX(X, op, other)
|
|
1480
|
-
|
|
1481
|
-
def _pow_3(self, other, mod, op):
|
|
1482
|
-
'''(INTERNAL) 3-arg C{pow(B{self}, B{other}, int B{mod} or C{None})}.
|
|
1483
|
-
'''
|
|
1484
|
-
b, r = self._fprs2 if mod is None else self._fint2
|
|
1485
|
-
if r and self._raiser(r, b):
|
|
1486
|
-
t = _non_zero_ if mod is None else _integer_
|
|
1487
|
-
t = _stresidual(t, r, mod=mod)
|
|
1488
|
-
raise self._Error(op, other, ResidualError, txt=t)
|
|
1489
|
-
|
|
1490
|
-
try: # b, other, mod all C{int}, unless C{mod} is C{None}
|
|
1491
|
-
x = _2scalar(other, _raiser=self._raiser)
|
|
1492
|
-
s = pow(b, x, mod)
|
|
1493
|
-
if not iscomplex(s):
|
|
1494
|
-
return self._finite(s)
|
|
1495
|
-
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1496
|
-
raise ValueError(_strcomplex(s, b, x, mod)) # PYCHOK no cover
|
|
1497
|
-
except Exception as X:
|
|
1498
|
-
raise self._ErrorX(X, op, other, mod)
|
|
1499
|
-
|
|
1500
|
-
def _pow_any(self, other, unused, op):
|
|
1545
|
+
def _pow(self, other, unused, op, **raiser):
|
|
1501
1546
|
'''Return C{B{self} ** B{other}}.
|
|
1502
1547
|
'''
|
|
1503
1548
|
if isinstance(other, Fsum):
|
|
1504
1549
|
x, r = other._fprs2
|
|
1505
|
-
|
|
1550
|
+
if r and self._raiser(r, x, **raiser):
|
|
1551
|
+
raise self._ResidualError(op, other, r)
|
|
1552
|
+
f = self._pow_scalar(x, other, op, **raiser)
|
|
1506
1553
|
if r:
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
s = self._pow_scalar(r, other, op)
|
|
1510
|
-
# s = _2scalar(s) # _raiser = None
|
|
1511
|
-
f *= s
|
|
1512
|
-
elif isscalar(other):
|
|
1554
|
+
f *= self._pow_scalar(r, other, op, **raiser)
|
|
1555
|
+
elif self._scalar(other, op):
|
|
1513
1556
|
x = self._finite(other, op)
|
|
1514
|
-
f = self._pow_scalar(x, other, op)
|
|
1557
|
+
f = self._pow_scalar(x, other, op, **raiser)
|
|
1515
1558
|
else:
|
|
1516
|
-
|
|
1559
|
+
f = self._pow_0_1(0, other)
|
|
1517
1560
|
return f
|
|
1518
1561
|
|
|
1519
|
-
def
|
|
1562
|
+
def _pow_0_1(self, x, other):
|
|
1563
|
+
'''(INTERNAL) Return B{C{self}**1} or C{B{self}**0 == 1.0}.
|
|
1564
|
+
'''
|
|
1565
|
+
return self if x else (1 if isint(other) and self.is_integer() else _1_0)
|
|
1566
|
+
|
|
1567
|
+
def _pow_2_3(self, b, x, other, op, *mod, **raiser):
|
|
1568
|
+
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} and 3-arg C{pow(B{b},
|
|
1569
|
+
B{x}, int B{mod} or C{None})}, embellishing errors.
|
|
1570
|
+
'''
|
|
1571
|
+
try:
|
|
1572
|
+
if mod: # b, x, mod all C{int}, unless C{mod} is C{None}
|
|
1573
|
+
m = mod[0]
|
|
1574
|
+
b, r = b._fprs2 if m is None else b._fint2
|
|
1575
|
+
if r and self._raiser(r, b, **raiser):
|
|
1576
|
+
t = _non_zero_ if m is None else _integer_
|
|
1577
|
+
raise ResidualError(_stresidual(t, r, mod=m), txt=None)
|
|
1578
|
+
x = _2scalar(x, _raiser=self._raiser, mod=m)
|
|
1579
|
+
# 0**INF == 0.0, 1**INF == 1.0, -1**2.3 == -(1**2.3)
|
|
1580
|
+
s = pow(b, x, *mod)
|
|
1581
|
+
if iscomplex(s):
|
|
1582
|
+
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1583
|
+
raise ValueError(_strcomplex(s, b, x, *mod))
|
|
1584
|
+
return self._finite(s)
|
|
1585
|
+
except Exception as X:
|
|
1586
|
+
raise self._ErrorX(X, op, other, *mod)
|
|
1587
|
+
|
|
1588
|
+
def _pow_int(self, x, other, op, **raiser):
|
|
1520
1589
|
'''(INTERNAL) Return C{B{self} **= B{x}} for C{int B{x} >= 0}.
|
|
1521
1590
|
'''
|
|
1522
1591
|
# assert isint(x) and x >= 0
|
|
1523
1592
|
ps = self._ps
|
|
1524
1593
|
if len(ps) > 1:
|
|
1525
|
-
|
|
1594
|
+
_mul_Fsum = Fsum._mul_Fsum
|
|
1526
1595
|
if x > 4:
|
|
1527
|
-
m = 1 # single-bit mask
|
|
1528
|
-
if (x & m):
|
|
1529
|
-
x -= m # x ^= m
|
|
1530
|
-
else:
|
|
1531
|
-
f = _Fsum_ps(_1_0)
|
|
1532
1596
|
p = self
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
f
|
|
1597
|
+
f = self if (x & 1) else _Psum_1()
|
|
1598
|
+
m = x >> 1 # // 2
|
|
1599
|
+
while m:
|
|
1600
|
+
p = _mul_Fsum(p, p, op) # p **= 2
|
|
1601
|
+
if (m & 1):
|
|
1602
|
+
f = _mul_Fsum(f, p, op) # f *= p
|
|
1603
|
+
m >>= 1 # //= 2
|
|
1539
1604
|
elif x > 1: # self**2, 3 or 4
|
|
1540
|
-
f =
|
|
1605
|
+
f = _mul_Fsum(self, self, op)
|
|
1541
1606
|
if x > 2: # self**3 or 4
|
|
1542
|
-
p =
|
|
1543
|
-
f =
|
|
1607
|
+
p = self if x < 4 else f
|
|
1608
|
+
f = _mul_Fsum(f, p, op)._2scalar
|
|
1544
1609
|
else: # self**1 or self**0 == 1 or _1_0
|
|
1545
|
-
f =
|
|
1610
|
+
f = self._pow_0_1(x, other)
|
|
1546
1611
|
elif ps: # self._ps[0]**x
|
|
1547
|
-
f = self.
|
|
1612
|
+
f = self._pow_2_3(ps[0], x, other, op, **raiser)
|
|
1548
1613
|
else: # PYCHOK no cover
|
|
1549
1614
|
# 0**pos_int == 0, but 0**0 == 1
|
|
1550
|
-
f = 0 if x else 1
|
|
1615
|
+
f = 0 if x else 1
|
|
1551
1616
|
return f
|
|
1552
1617
|
|
|
1553
|
-
def _pow_scalar(self, x, other, op):
|
|
1618
|
+
def _pow_scalar(self, x, other, op, **raiser):
|
|
1554
1619
|
'''(INTERNAL) Return C{self**B{x}} for C{scalar B{x}}.
|
|
1555
1620
|
'''
|
|
1556
1621
|
s, r = self._fprs2
|
|
@@ -1559,55 +1624,65 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1559
1624
|
y = abs(x)
|
|
1560
1625
|
if y > 1:
|
|
1561
1626
|
if r:
|
|
1562
|
-
f = self._pow_int(y, other, op)
|
|
1627
|
+
f = self._pow_int(y, other, op, **raiser)
|
|
1563
1628
|
if x > 0: # > 1
|
|
1564
1629
|
return f
|
|
1565
1630
|
# assert x < 0 # < -1
|
|
1566
1631
|
s, r = f._fprs2 if isinstance(f, Fsum) else (f, 0)
|
|
1567
1632
|
if r:
|
|
1568
|
-
return
|
|
1633
|
+
return _Psum_1()._ftruediv(f, op, **raiser)
|
|
1569
1634
|
# use **= -1 for the CPython float_pow
|
|
1570
1635
|
# error if s is zero, and not s = 1 / s
|
|
1571
1636
|
x = -1
|
|
1572
|
-
elif x < 0: # self
|
|
1637
|
+
elif x < 0: # == -1: self**(-1) == 1 / self
|
|
1573
1638
|
if r:
|
|
1574
|
-
return
|
|
1639
|
+
return _Psum_1()._ftruediv(self, op, **raiser)
|
|
1575
1640
|
else: # self**1 or self**0
|
|
1576
1641
|
return self._pow_0_1(x, other) # self, 1 or 1.0
|
|
1577
|
-
elif
|
|
1578
|
-
raise self._TypeError(op, other, txt=_not_scalar_)
|
|
1579
|
-
elif r and self._raiser(r, s): # non-zero residual**fractional
|
|
1642
|
+
elif r and self._raiser(r, s, **raiser): # non-zero residual**fractional
|
|
1580
1643
|
# raise self._ResidualError(op, other, r, fractional_power=x)
|
|
1581
1644
|
t = _stresidual(_non_zero_, r, fractional_power=x)
|
|
1582
1645
|
raise self._Error(op, other, ResidualError, txt=t)
|
|
1583
1646
|
# assert isscalar(s) and isscalar(x)
|
|
1584
|
-
return self.
|
|
1647
|
+
return self._pow_2_3(s, x, other, op, **raiser)
|
|
1585
1648
|
|
|
1586
|
-
def
|
|
1587
|
-
'''(INTERNAL)
|
|
1649
|
+
def _ps_acc(self, ps, xs, up=True, **unused):
|
|
1650
|
+
'''(INTERNAL) Accumulate all scalar C{xs} into C{ps}.
|
|
1588
1651
|
'''
|
|
1589
|
-
n
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1652
|
+
n = 0
|
|
1653
|
+
_2s = _2sum
|
|
1654
|
+
for x in (tuple(xs) if xs is ps else xs):
|
|
1655
|
+
# assert isscalar(x) and _isfinite(x)
|
|
1656
|
+
if x:
|
|
1657
|
+
i = 0
|
|
1658
|
+
for p in ps:
|
|
1659
|
+
x, p = _2s(x, p)
|
|
1660
|
+
if p:
|
|
1661
|
+
ps[i] = p
|
|
1662
|
+
i += 1
|
|
1663
|
+
ps[i:] = (x,) if x else ()
|
|
1664
|
+
n += 1
|
|
1665
|
+
if n:
|
|
1666
|
+
self._n += n
|
|
1667
|
+
# Fsum._ps_max = max(Fsum._ps_max, len(ps))
|
|
1668
|
+
if up:
|
|
1669
|
+
self._update()
|
|
1670
|
+
return ps
|
|
1671
|
+
|
|
1672
|
+
def _ps_mul(self, op, *factors):
|
|
1673
|
+
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1674
|
+
each of the scalar B{C{factors}} and accumulate.
|
|
1675
|
+
'''
|
|
1676
|
+
def _pfs(ps, fs):
|
|
1677
|
+
if len(ps) < len(fs):
|
|
1678
|
+
ps, fs = fs, ps
|
|
1679
|
+
_fin = _isfinite
|
|
1680
|
+
for f in fs:
|
|
1681
|
+
for p in ps:
|
|
1682
|
+
p *= f
|
|
1683
|
+
yield p if _fin(p) else self._finite(p, op)
|
|
1684
|
+
|
|
1685
|
+
return _Psum(self._ps_acc([], _pfs(self._ps, factors)))
|
|
1611
1686
|
|
|
1612
1687
|
@property_RO
|
|
1613
1688
|
def _ps_neg(self):
|
|
@@ -1616,6 +1691,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1616
1691
|
for p in self._ps:
|
|
1617
1692
|
yield -p
|
|
1618
1693
|
|
|
1694
|
+
def _ps_1primed(self, *less):
|
|
1695
|
+
'''(INTERNAL) Yield partials, 1-primed and subtract any C{less} scalars.
|
|
1696
|
+
'''
|
|
1697
|
+
yield _1_0
|
|
1698
|
+
for p in self._ps:
|
|
1699
|
+
yield p
|
|
1700
|
+
for p in less:
|
|
1701
|
+
yield -p
|
|
1702
|
+
yield _N_1_0
|
|
1703
|
+
|
|
1704
|
+
def _raiser(self, r, s, raiser=True):
|
|
1705
|
+
'''(INTERNAL) Does ratio C{r / s} exceed the RESIDUAL threshold?
|
|
1706
|
+
'''
|
|
1707
|
+
self._ratio = t = fabs(r / s) if s else 0 # _0_0
|
|
1708
|
+
return raiser and (t > self._RESIDUAL)
|
|
1709
|
+
|
|
1619
1710
|
@property_RO
|
|
1620
1711
|
def real(self):
|
|
1621
1712
|
'''Get the C{real} part of this instance (C{float}).
|
|
@@ -1638,12 +1729,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1638
1729
|
'''
|
|
1639
1730
|
return self._fprs2.residual
|
|
1640
1731
|
|
|
1641
|
-
def _raiser(self, r, s):
|
|
1642
|
-
'''(INTERNAL) Does ratio C{r / s} exceed threshold?
|
|
1643
|
-
'''
|
|
1644
|
-
self._ratio = t = fabs((r / s) if s else r)
|
|
1645
|
-
return t > self._RESIDUAL
|
|
1646
|
-
|
|
1647
1732
|
def RESIDUAL(self, *threshold):
|
|
1648
1733
|
'''Get and set this instance' I{ratio} for raising L{ResidualError}s,
|
|
1649
1734
|
overriding the default from env variable C{PYGEODESY_FSUM_RESIDUAL}.
|
|
@@ -1654,11 +1739,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1654
1739
|
C{PYGEODESY_FSUM_RESIDUAL} or if omitted, keep the
|
|
1655
1740
|
current setting.
|
|
1656
1741
|
|
|
1657
|
-
@return: The previous C{RESIDUAL} setting (C{float}), default C{0}.
|
|
1742
|
+
@return: The previous C{RESIDUAL} setting (C{float}), default C{0.}.
|
|
1658
1743
|
|
|
1659
1744
|
@raise ValueError: Negative B{C{threshold}}.
|
|
1660
1745
|
|
|
1661
|
-
@note:
|
|
1746
|
+
@note: L{ResidualError}s will be thrown if the non-zero I{ratio}
|
|
1662
1747
|
C{residual / fsum} exceeds the B{C{threshold}}.
|
|
1663
1748
|
'''
|
|
1664
1749
|
r = self._RESIDUAL
|
|
@@ -1681,6 +1766,44 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1681
1766
|
t = t.replace(_COMMASPACE_R_, _exceeds_R_)
|
|
1682
1767
|
return self._Error(op, other, ResidualError, txt=t)
|
|
1683
1768
|
|
|
1769
|
+
def root(self, root, **raiser):
|
|
1770
|
+
'''Return C{B{self}**(1 / B{root})} as L{Fsum}.
|
|
1771
|
+
|
|
1772
|
+
@arg root: The order (C{scalar} or C{Fsum}), non-zero.
|
|
1773
|
+
@kwarg raiser: Use C{B{raiser}=False} to ignore L{ResidualError}s
|
|
1774
|
+
(C{bool}), see also method L{RESIDUAL}.
|
|
1775
|
+
|
|
1776
|
+
@return: The C{self ** (1 / B{root})} result (L{Fsum}).
|
|
1777
|
+
|
|
1778
|
+
@see: Method L{Fsum.pow}.
|
|
1779
|
+
'''
|
|
1780
|
+
_root_ = self.root.__name__
|
|
1781
|
+
if isinstance(root, Fsum):
|
|
1782
|
+
x = root.__rtruediv__(_1_0, **raiser)
|
|
1783
|
+
else:
|
|
1784
|
+
try:
|
|
1785
|
+
x = _1_0 / _2float(root=root)
|
|
1786
|
+
except Exception as X:
|
|
1787
|
+
E, t = _xError2(X)
|
|
1788
|
+
n = _SPACE_(_1_0, _truediv_op_, _root_)
|
|
1789
|
+
raise E(n, root, txt=t, cause=X)
|
|
1790
|
+
f = self._copy_2(self.root)
|
|
1791
|
+
return f._fpow(x, _root_, **raiser) # == pow(f, x)
|
|
1792
|
+
|
|
1793
|
+
def _scalar(self, other, op, **txt):
|
|
1794
|
+
'''(INTERNAL) Return scalar C{other}.
|
|
1795
|
+
'''
|
|
1796
|
+
if isscalar(other):
|
|
1797
|
+
return other
|
|
1798
|
+
raise self._TypeError(op, other, **txt) # _invalid_
|
|
1799
|
+
|
|
1800
|
+
@property_RO
|
|
1801
|
+
def _2scalar(self):
|
|
1802
|
+
'''(INTERNAL) Get this instance as C{scalar} or C{as-is}.
|
|
1803
|
+
'''
|
|
1804
|
+
s, r = self._fprs2
|
|
1805
|
+
return self if r else s
|
|
1806
|
+
|
|
1684
1807
|
def signOf(self, res=True):
|
|
1685
1808
|
'''Determine the sign of this instance.
|
|
1686
1809
|
|
|
@@ -1689,8 +1812,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1689
1812
|
|
|
1690
1813
|
@return: The sign (C{int}, -1, 0 or +1).
|
|
1691
1814
|
'''
|
|
1692
|
-
s, r = self._fprs2
|
|
1693
|
-
return _signOf(s, -r)
|
|
1815
|
+
s, r = self._fprs2
|
|
1816
|
+
return _signOf(s, (-r) if res else 0)
|
|
1694
1817
|
|
|
1695
1818
|
def toRepr(self, **prec_sep_fmt_lenc): # PYCHOK signature
|
|
1696
1819
|
'''Return this C{Fsum} instance as representation.
|
|
@@ -1784,21 +1907,21 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
1784
1907
|
_Units_ = (_Float_Int, _Float_Int)
|
|
1785
1908
|
|
|
1786
1909
|
@Property_RO
|
|
1787
|
-
def
|
|
1788
|
-
'''Get this L{Fsum2Tuple} as an L{Fsum}.
|
|
1910
|
+
def _Fsum(self):
|
|
1911
|
+
'''(INTERNAL) Get this L{Fsum2Tuple} as an L{Fsum}.
|
|
1789
1912
|
'''
|
|
1790
1913
|
s, r = map(float, self)
|
|
1791
|
-
return
|
|
1914
|
+
return _Psum(_2ps(s, r), name=self.name)
|
|
1792
1915
|
|
|
1793
1916
|
def is_exact(self):
|
|
1794
1917
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
1795
1918
|
'''
|
|
1796
|
-
return self.
|
|
1919
|
+
return self._Fsum.is_exact()
|
|
1797
1920
|
|
|
1798
1921
|
def is_integer(self):
|
|
1799
1922
|
'''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
|
|
1800
1923
|
'''
|
|
1801
|
-
return self.
|
|
1924
|
+
return self._Fsum.is_integer()
|
|
1802
1925
|
|
|
1803
1926
|
|
|
1804
1927
|
class ResidualError(_ValueError):
|
|
@@ -1810,23 +1933,6 @@ class ResidualError(_ValueError):
|
|
|
1810
1933
|
pass
|
|
1811
1934
|
|
|
1812
1935
|
|
|
1813
|
-
def _Fsum_ps(*ps, **name):
|
|
1814
|
-
'''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
|
|
1815
|
-
'''
|
|
1816
|
-
f = Fsum(**name) if name else Fsum()
|
|
1817
|
-
if ps:
|
|
1818
|
-
f._n = len(ps)
|
|
1819
|
-
f._ps[:] = ps
|
|
1820
|
-
return f
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
def _Fsum_xs(xs, up=False, **name):
|
|
1824
|
-
'''(INTERNAL) Return an C{Fsum} from known floats C{xs}.
|
|
1825
|
-
'''
|
|
1826
|
-
f = Fsum(**name) if name else Fsum()
|
|
1827
|
-
return f._facc(xs, up=up)
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
1936
|
try:
|
|
1831
1937
|
from math import fsum as _fsum # precision IEEE-754 sum, Python 2.6+
|
|
1832
1938
|
|
|
@@ -1842,12 +1948,14 @@ try:
|
|
|
1842
1948
|
_psum = _fsum # PYCHOK re-def
|
|
1843
1949
|
|
|
1844
1950
|
except ImportError:
|
|
1845
|
-
_sum = sum # Fsum(NAN) exception fall-back
|
|
1951
|
+
_sum = sum # Fsum(NAN) exception fall-back, in .elliptic
|
|
1846
1952
|
|
|
1847
1953
|
def _fsum(xs):
|
|
1848
1954
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
1849
1955
|
'''
|
|
1850
|
-
|
|
1956
|
+
f = Fsum()
|
|
1957
|
+
f.name = _fsum.__name__
|
|
1958
|
+
return f.fsum(xs)
|
|
1851
1959
|
|
|
1852
1960
|
|
|
1853
1961
|
def fsum(xs, floats=False):
|
|
@@ -1855,8 +1963,8 @@ def fsum(xs, floats=False):
|
|
|
1855
1963
|
|
|
1856
1964
|
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1857
1965
|
instances).
|
|
1858
|
-
@kwarg floats:
|
|
1859
|
-
|
|
1966
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1967
|
+
to be C{float} scalars (C{bool}).
|
|
1860
1968
|
|
|
1861
1969
|
@return: Precision C{fsum} (C{float}).
|
|
1862
1970
|
|
|
@@ -1866,8 +1974,8 @@ def fsum(xs, floats=False):
|
|
|
1866
1974
|
|
|
1867
1975
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
1868
1976
|
|
|
1869
|
-
@note:
|
|
1870
|
-
|
|
1977
|
+
@note: Exception and I{non-finite} handling may differ if not based
|
|
1978
|
+
on Python's C{math.fsum}.
|
|
1871
1979
|
|
|
1872
1980
|
@see: Class L{Fsum} and methods L{Fsum.fsum} and L{Fsum.fadd}.
|
|
1873
1981
|
'''
|
|
@@ -1879,8 +1987,8 @@ def fsum_(*xs, **floats):
|
|
|
1879
1987
|
|
|
1880
1988
|
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1881
1989
|
positional.
|
|
1882
|
-
@kwarg floats:
|
|
1883
|
-
|
|
1990
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are I{known
|
|
1991
|
+
to be scalar} (C{bool}).
|
|
1884
1992
|
|
|
1885
1993
|
@return: Precision C{fsum} (C{float}).
|
|
1886
1994
|
|
|
@@ -1891,18 +1999,19 @@ def fsum_(*xs, **floats):
|
|
|
1891
1999
|
|
|
1892
2000
|
|
|
1893
2001
|
def fsumf_(*xs):
|
|
1894
|
-
'''Precision floating point summation L{fsum_}C{(*xs, floats=True)}
|
|
2002
|
+
'''Precision floating point summation, L{fsum_}C{(*B{xs}, floats=True)},
|
|
2003
|
+
but only for C{B{xs}} I{known to be scalar}.
|
|
1895
2004
|
'''
|
|
1896
2005
|
return _fsum(xs) if xs else _0_0
|
|
1897
2006
|
|
|
1898
2007
|
|
|
1899
2008
|
def fsum1(xs, floats=False):
|
|
1900
|
-
'''Precision floating point summation
|
|
2009
|
+
'''Precision floating point summation, 1-primed.
|
|
1901
2010
|
|
|
1902
2011
|
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1903
2012
|
instances).
|
|
1904
|
-
@kwarg floats:
|
|
1905
|
-
|
|
2013
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
2014
|
+
to be C{float}.
|
|
1906
2015
|
|
|
1907
2016
|
@return: Precision C{fsum} (C{float}).
|
|
1908
2017
|
|
|
@@ -1912,12 +2021,12 @@ def fsum1(xs, floats=False):
|
|
|
1912
2021
|
|
|
1913
2022
|
|
|
1914
2023
|
def fsum1_(*xs, **floats):
|
|
1915
|
-
'''Precision floating point summation
|
|
2024
|
+
'''Precision floating point summation, 1-primed.
|
|
1916
2025
|
|
|
1917
2026
|
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1918
2027
|
positional.
|
|
1919
|
-
@kwarg floats:
|
|
1920
|
-
|
|
2028
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are I{known
|
|
2029
|
+
to be scalar} (C{bool}).
|
|
1921
2030
|
|
|
1922
2031
|
@return: Precision C{fsum} (C{float}).
|
|
1923
2032
|
|
|
@@ -1928,7 +2037,8 @@ def fsum1_(*xs, **floats):
|
|
|
1928
2037
|
|
|
1929
2038
|
|
|
1930
2039
|
def fsum1f_(*xs):
|
|
1931
|
-
'''Precision floating point summation L{fsum1_}C{(*xs, floats=True)}
|
|
2040
|
+
'''Precision floating point summation, L{fsum1_}C{(*B{xs}, floats=True)},
|
|
2041
|
+
but only for C{B{xs}} I{known to be scalar}.
|
|
1932
2042
|
'''
|
|
1933
2043
|
return _fsum(_1primed(xs)) if xs else _0_0
|
|
1934
2044
|
|
|
@@ -1946,7 +2056,7 @@ if __name__ == '__main__':
|
|
|
1946
2056
|
printf(_psum.__name__, end=_COMMASPACE_)
|
|
1947
2057
|
|
|
1948
2058
|
F = Fsum()
|
|
1949
|
-
if F.is_math_fsum:
|
|
2059
|
+
if F.is_math_fsum():
|
|
1950
2060
|
c = (7, 1e100, -7, -1e100, -9e-20, 8e-20) * 10
|
|
1951
2061
|
for _ in range(n):
|
|
1952
2062
|
t = list(c)
|