pygeodesy 24.3.24__py2.py3-none-any.whl → 24.4.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyGeodesy-24.3.24.dist-info → PyGeodesy-24.4.2.dist-info}/METADATA +2 -2
- {PyGeodesy-24.3.24.dist-info → PyGeodesy-24.4.2.dist-info}/RECORD +11 -11
- pygeodesy/__init__.py +1 -1
- pygeodesy/azimuthal.py +2 -2
- pygeodesy/basics.py +1 -1
- pygeodesy/fmath.py +150 -153
- pygeodesy/fsums.py +369 -329
- pygeodesy/lazily.py +2 -2
- pygeodesy/resections.py +23 -24
- {PyGeodesy-24.3.24.dist-info → PyGeodesy-24.4.2.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.3.24.dist-info → PyGeodesy-24.4.2.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -27,11 +27,11 @@ and L{Fsum.__itruediv__}.
|
|
|
27
27
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
28
28
|
|
|
29
29
|
from pygeodesy.basics import iscomplex, isint, isscalar, itemsorted, \
|
|
30
|
-
signOf, _signOf
|
|
31
|
-
from pygeodesy.constants import INT0, _isfinite, isinf, isnan, _pos_self, \
|
|
30
|
+
signOf, _signOf
|
|
31
|
+
from pygeodesy.constants import INT0, _isfinite, isinf, isnan, NEG0, _pos_self, \
|
|
32
32
|
_0_0, _1_0, _N_1_0, Float, Int
|
|
33
|
-
from pygeodesy.errors import _OverflowError, _TypeError, _ValueError,
|
|
34
|
-
_xkwds_get, _ZeroDivisionError
|
|
33
|
+
from pygeodesy.errors import _OverflowError, _TypeError, _ValueError, _xError, \
|
|
34
|
+
_xError2, _xkwds_get, _ZeroDivisionError
|
|
35
35
|
from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DASH_, _DOT_, _EQUAL_, \
|
|
36
36
|
_exceeds_, _from_, _iadd_op_, _LANGLE_, _negative_, \
|
|
37
37
|
_NOTEQUAL_, _not_finite_, _not_scalar_, _PERCENT_, \
|
|
@@ -46,11 +46,12 @@ from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
|
|
|
46
46
|
from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
|
|
47
47
|
|
|
48
48
|
__all__ = _ALL_LAZY.fsums
|
|
49
|
-
__version__ = '24.
|
|
49
|
+
__version__ = '24.04.02'
|
|
50
50
|
|
|
51
51
|
_add_op_ = _PLUS_ # in .auxilats.auxAngle
|
|
52
52
|
_eq_op_ = _EQUAL_ * 2 # _DEQUAL_
|
|
53
53
|
_COMMASPACE_R_ = _COMMASPACE_ + _R_
|
|
54
|
+
_div_ = 'div'
|
|
54
55
|
_exceeds_R_ = _SPACE_ + _exceeds_(_R_)
|
|
55
56
|
_floordiv_op_ = _SLASH_ * 2 # _DSLASH_
|
|
56
57
|
_fset_op_ = _EQUAL_
|
|
@@ -59,6 +60,7 @@ _gt_op_ = _RANGLE_
|
|
|
59
60
|
_integer_ = 'integer'
|
|
60
61
|
_le_op_ = _LANGLE_ + _EQUAL_
|
|
61
62
|
_lt_op_ = _LANGLE_
|
|
63
|
+
_mod_ = 'mod'
|
|
62
64
|
_mod_op_ = _PERCENT_
|
|
63
65
|
_mul_op_ = _STAR_
|
|
64
66
|
_ne_op_ = _NOTEQUAL_
|
|
@@ -78,63 +80,30 @@ def _2float(index=None, **name_value): # in .fmath, .fstats
|
|
|
78
80
|
v = float(v)
|
|
79
81
|
if _isfinite(v):
|
|
80
82
|
return v
|
|
81
|
-
|
|
83
|
+
raise ValueError(_not_finite_)
|
|
82
84
|
except Exception as e:
|
|
83
|
-
|
|
84
|
-
raise E(Fmt.INDEX(n, index), v, txt=t)
|
|
85
|
+
raise _xError(e, Fmt.INDEX(n, index), v)
|
|
85
86
|
|
|
86
87
|
|
|
87
|
-
def _2floats(xs, origin=0,
|
|
88
|
+
def _2floats(xs, origin=0, neg=False):
|
|
88
89
|
'''(INTERNAL) Yield each B{C{xs}} as a C{float}.
|
|
89
90
|
'''
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
_Fsum = Fsum
|
|
94
|
-
for x in xs:
|
|
95
|
-
if isinstance(x, _Fsum):
|
|
96
|
-
for p in x._ps:
|
|
97
|
-
yield (-p) if sub else p
|
|
98
|
-
else:
|
|
99
|
-
f = float(x)
|
|
100
|
-
if not _fin(f):
|
|
101
|
-
raise ValueError(_not_finite_)
|
|
102
|
-
if f:
|
|
103
|
-
yield (-f) if sub else f
|
|
104
|
-
i += 1
|
|
105
|
-
except Exception as e:
|
|
106
|
-
E, t = _xError2(e)
|
|
107
|
-
n = Fmt.SQUARE(xs=i)
|
|
108
|
-
raise E(n, x, txt=t)
|
|
91
|
+
if neg:
|
|
92
|
+
def _X(X):
|
|
93
|
+
return X._ps_neg
|
|
109
94
|
|
|
95
|
+
def _x(x):
|
|
96
|
+
return -float(x)
|
|
97
|
+
else:
|
|
98
|
+
def _X(X): # PYCHOK re-def
|
|
99
|
+
return X._ps
|
|
110
100
|
|
|
111
|
-
|
|
112
|
-
'''(INTERNAL) Yield each C{xs} as C{float(x**power)}.
|
|
113
|
-
'''
|
|
114
|
-
_xisscalar(power=power)
|
|
115
|
-
try:
|
|
116
|
-
i, x = origin, None
|
|
117
|
-
_fin = _isfinite
|
|
118
|
-
_Fsum = Fsum
|
|
119
|
-
_pow = pow # XXX math.pow
|
|
120
|
-
for x in xs:
|
|
121
|
-
if isinstance(x, _Fsum):
|
|
122
|
-
P = x.pow(power)
|
|
123
|
-
for p in P._ps:
|
|
124
|
-
yield p
|
|
125
|
-
else:
|
|
126
|
-
p = _pow(float(x), power)
|
|
127
|
-
if not _fin(p):
|
|
128
|
-
raise ValueError(_not_finite_)
|
|
129
|
-
yield p
|
|
130
|
-
i += 1
|
|
131
|
-
except Exception as e:
|
|
132
|
-
E, t = _xError2(e)
|
|
133
|
-
n = Fmt.SQUARE(xs=i)
|
|
134
|
-
raise E(n, x, txt=t)
|
|
101
|
+
_x = float
|
|
135
102
|
|
|
103
|
+
return _2yield(xs, origin, _X, _x)
|
|
136
104
|
|
|
137
|
-
|
|
105
|
+
|
|
106
|
+
def _1primed(xs): # in .fmath
|
|
138
107
|
'''(INTERNAL) 1-Prime the summation of C{xs}
|
|
139
108
|
arguments I{known} to be C{finite float}.
|
|
140
109
|
'''
|
|
@@ -145,17 +114,28 @@ def _1primed(xs):
|
|
|
145
114
|
yield _N_1_0
|
|
146
115
|
|
|
147
116
|
|
|
117
|
+
def _2ps(s, r):
|
|
118
|
+
'''(INTERNAL) Return a C{s} and C{r} pair, I{ps-ordered}.
|
|
119
|
+
'''
|
|
120
|
+
if fabs(s) < fabs(r):
|
|
121
|
+
s, r = r, s
|
|
122
|
+
return ((r, s) if s else (r,)) if r else (s,)
|
|
123
|
+
|
|
124
|
+
|
|
148
125
|
def _psum(ps): # PYCHOK used!
|
|
149
126
|
'''(INTERNAL) Partials summation updating C{ps}, I{overridden below}.
|
|
150
127
|
'''
|
|
151
|
-
|
|
128
|
+
# assert isinstance(ps, list)
|
|
129
|
+
i = len(ps) - 1 # len(ps) > 2
|
|
130
|
+
if i < 0:
|
|
131
|
+
return _0_0
|
|
152
132
|
s = ps[i]
|
|
153
133
|
_2s = _2sum
|
|
154
134
|
while i > 0:
|
|
155
135
|
i -= 1
|
|
156
136
|
s, r = _2s(s, ps[i])
|
|
157
137
|
if r: # sum(ps) became inexact
|
|
158
|
-
ps[i:] =
|
|
138
|
+
ps[i:] = (s, r) if s else (r,)
|
|
159
139
|
if i > 0:
|
|
160
140
|
p = ps[i-1] # round half-even
|
|
161
141
|
if (p > 0 and r > 0) or \
|
|
@@ -165,7 +145,7 @@ def _psum(ps): # PYCHOK used!
|
|
|
165
145
|
if r == (t - s):
|
|
166
146
|
s = t
|
|
167
147
|
break
|
|
168
|
-
ps[i:] =
|
|
148
|
+
ps[i:] = s,
|
|
169
149
|
return s
|
|
170
150
|
|
|
171
151
|
|
|
@@ -221,16 +201,37 @@ def _2sum(a, b): # by .testFmath
|
|
|
221
201
|
return s, (b - (s - a))
|
|
222
202
|
|
|
223
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 e:
|
|
223
|
+
raise _xError(e, Fmt.INDEX(xs=i), x)
|
|
224
|
+
|
|
225
|
+
|
|
224
226
|
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
225
|
-
'''Precision floating point I{running} summation.
|
|
227
|
+
'''Precision floating point summation and I{running} summation.
|
|
226
228
|
|
|
227
229
|
Unlike Python's C{math.fsum}, this class accumulates values and provides intermediate,
|
|
228
|
-
I{running} precision floating point
|
|
230
|
+
I{running}, precision floating point summations. Accumulation may continue after any
|
|
229
231
|
intermediate, I{running} summuation.
|
|
230
232
|
|
|
231
|
-
@note: Accumulated values may be L{Fsum} or C{scalar} instances
|
|
232
|
-
|
|
233
|
-
method C{__float__}.
|
|
233
|
+
@note: Accumulated values may be L{Fsum} or C{scalar} instances, any C{type} having
|
|
234
|
+
method C{__float__} to convert the C{scalar} to a single C{float}.
|
|
234
235
|
|
|
235
236
|
@note: Handling of exceptions and C{inf}, C{INF}, C{nan} and C{NAN} differs from
|
|
236
237
|
Python's C{math.fsum}.
|
|
@@ -245,42 +246,40 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
245
246
|
_math_fsum = None
|
|
246
247
|
_n = 0
|
|
247
248
|
# _ps = [] # partial sums
|
|
248
|
-
# _px = 0
|
|
249
|
+
# _px = 0 # max(Fsum._px, len(Fsum._ps))
|
|
249
250
|
_ratio = None
|
|
250
251
|
_RESIDUAL = max(float(_getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)), _0_0)
|
|
251
252
|
|
|
252
253
|
def __init__(self, *xs, **name_RESIDUAL):
|
|
253
|
-
'''New L{Fsum} for precision floating point
|
|
254
|
+
'''New L{Fsum} for I{running} precision floating point summation.
|
|
254
255
|
|
|
255
|
-
@arg xs: No, one or more initial values (each C{scalar}
|
|
256
|
-
L{Fsum} instance).
|
|
257
|
-
@kwarg name_RESIDUAL: Optional C{B{name}=NN} for this L{Fsum}
|
|
258
|
-
|
|
259
|
-
L{ResidualError} threshold.
|
|
256
|
+
@arg xs: No, one or more initial values, all positional (each C{scalar}
|
|
257
|
+
or an L{Fsum} instance).
|
|
258
|
+
@kwarg name_RESIDUAL: Optional C{B{name}=NN} for this L{Fsum} and
|
|
259
|
+
C{B{RESIDUAL}=None} for the L{ResidualError} threshold.
|
|
260
260
|
|
|
261
261
|
@see: Methods L{Fsum.fadd} and L{Fsum.RESIDUAL}.
|
|
262
262
|
'''
|
|
263
263
|
if name_RESIDUAL:
|
|
264
264
|
n = _xkwds_get(name_RESIDUAL, name=NN)
|
|
265
|
-
if n: # set name ...
|
|
265
|
+
if n: # set name before ...
|
|
266
266
|
self.name = n
|
|
267
267
|
r = _xkwds_get(name_RESIDUAL, RESIDUAL=None)
|
|
268
268
|
if r is not None:
|
|
269
|
-
self.RESIDUAL(r) # ...
|
|
269
|
+
self.RESIDUAL(r) # ... ResidualError
|
|
270
270
|
# self._n = 0
|
|
271
271
|
self._ps = [] # [_0_0], see L{Fsum._fprs}
|
|
272
272
|
if len(xs) > 1:
|
|
273
273
|
self._facc(_2floats(xs, origin=1), up=False) # PYCHOK yield
|
|
274
274
|
elif xs: # len(xs) == 1
|
|
275
|
-
self.
|
|
276
|
-
self.
|
|
275
|
+
self._n = 1
|
|
276
|
+
self._ps[:] = _2float(x=xs[0]),
|
|
277
277
|
|
|
278
278
|
def __abs__(self):
|
|
279
279
|
'''Return this instance' absolute value as an L{Fsum}.
|
|
280
280
|
'''
|
|
281
281
|
s = _fsum(self._ps_1()) # == self._cmp_0(0, ...)
|
|
282
|
-
return
|
|
283
|
-
self._copy_2(self.__abs__)
|
|
282
|
+
return (-self) if s < 0 else self._copy_2(self.__abs__)
|
|
284
283
|
|
|
285
284
|
def __add__(self, other):
|
|
286
285
|
'''Return the C{Fsum(B{self}, B{other})}.
|
|
@@ -322,9 +321,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
322
321
|
cmp = __cmp__
|
|
323
322
|
|
|
324
323
|
def __divmod__(self, other):
|
|
325
|
-
'''Return C{divmod(B{self}, B{other})} as
|
|
326
|
-
|
|
327
|
-
and an L{Fsum}.
|
|
324
|
+
'''Return C{divmod(B{self}, B{other})} as a L{DivMod2Tuple}
|
|
325
|
+
with quotient C{div} an C{int} in Python 3+ or C{float}
|
|
326
|
+
in Python 2- and remainder C{mod} an L{Fsum}.
|
|
328
327
|
|
|
329
328
|
@arg other: An L{Fsum} or C{scalar} modulus.
|
|
330
329
|
|
|
@@ -431,8 +430,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
431
430
|
|
|
432
431
|
@see: Method L{Fsum.__divmod__}.
|
|
433
432
|
'''
|
|
434
|
-
self._fdivmod2(other, _mod_op_ + _fset_op_)
|
|
435
|
-
return self
|
|
433
|
+
return self._fdivmod2(other, _mod_op_ + _fset_op_).mod
|
|
436
434
|
|
|
437
435
|
def __imul__(self, other):
|
|
438
436
|
'''Apply C{B{self} *= B{other}} to this instance.
|
|
@@ -566,7 +564,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
566
564
|
@see: Method L{Fsum.__imod__}.
|
|
567
565
|
'''
|
|
568
566
|
f = self._copy_2(self.__mod__)
|
|
569
|
-
return f._fdivmod2(other, _mod_op_)
|
|
567
|
+
return f._fdivmod2(other, _mod_op_).mod
|
|
570
568
|
|
|
571
569
|
def __mul__(self, other):
|
|
572
570
|
'''Return C{B{self} * B{other}} as an L{Fsum}.
|
|
@@ -582,9 +580,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
582
580
|
return self._cmp_0(other, _ne_op_) != 0
|
|
583
581
|
|
|
584
582
|
def __neg__(self):
|
|
585
|
-
'''Return I{a copy of} this instance, negated.
|
|
583
|
+
'''Return I{a copy of} this instance, I{negated}.
|
|
586
584
|
'''
|
|
587
|
-
|
|
585
|
+
f = self._copy_2(self.__neg__)
|
|
586
|
+
return f._fset(self._neg)
|
|
588
587
|
|
|
589
588
|
def __pos__(self):
|
|
590
589
|
'''Return this instance I{as-is}, like C{float.__pos__()}.
|
|
@@ -604,7 +603,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
604
603
|
|
|
605
604
|
@see: Method L{Fsum.__iadd__}.
|
|
606
605
|
'''
|
|
607
|
-
f = self.
|
|
606
|
+
f = self._copy_2r(other, self.__radd__)
|
|
608
607
|
return f._fadd(self, _add_op_)
|
|
609
608
|
|
|
610
609
|
def __rdivmod__(self, other):
|
|
@@ -613,7 +612,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
613
612
|
|
|
614
613
|
@see: Method L{Fsum.__divmod__}.
|
|
615
614
|
'''
|
|
616
|
-
f = self.
|
|
615
|
+
f = self._copy_2r(other, self.__rdivmod__)
|
|
617
616
|
return f._fdivmod2(self, _divmod_op_)
|
|
618
617
|
|
|
619
618
|
# def __repr__(self):
|
|
@@ -626,7 +625,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
626
625
|
|
|
627
626
|
@see: Method L{Fsum.__ifloordiv__}.
|
|
628
627
|
'''
|
|
629
|
-
f = self.
|
|
628
|
+
f = self._copy_2r(other, self.__rfloordiv__)
|
|
630
629
|
return f._floordiv(self, _floordiv_op_)
|
|
631
630
|
|
|
632
631
|
def __rmatmul__(self, other): # PYCHOK no cover
|
|
@@ -638,15 +637,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
638
637
|
|
|
639
638
|
@see: Method L{Fsum.__imod__}.
|
|
640
639
|
'''
|
|
641
|
-
f = self.
|
|
642
|
-
return f._fdivmod2(self, _mod_op_)
|
|
640
|
+
f = self._copy_2r(other, self.__rmod__)
|
|
641
|
+
return f._fdivmod2(self, _mod_op_).mod
|
|
643
642
|
|
|
644
643
|
def __rmul__(self, other):
|
|
645
644
|
'''Return C{B{other} * B{self}} as an L{Fsum}.
|
|
646
645
|
|
|
647
646
|
@see: Method L{Fsum.__imul__}.
|
|
648
647
|
'''
|
|
649
|
-
f = self.
|
|
648
|
+
f = self._copy_2r(other, self.__rmul__)
|
|
650
649
|
return f._fmul(self, _mul_op_)
|
|
651
650
|
|
|
652
651
|
def __round__(self, *ndigits): # PYCHOK no cover
|
|
@@ -655,17 +654,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
655
654
|
@arg ndigits: Optional number of digits (C{int}).
|
|
656
655
|
'''
|
|
657
656
|
# <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
f._ps = [round(float(self), *ndigits)] # can be C{int}
|
|
661
|
-
return f
|
|
657
|
+
return _Fsum_ps(round(float(self), *ndigits), # can be C{int}
|
|
658
|
+
name=self.__round__.__name__)
|
|
662
659
|
|
|
663
660
|
def __rpow__(self, other, *mod):
|
|
664
661
|
'''Return C{B{other}**B{self}} as an L{Fsum}.
|
|
665
662
|
|
|
666
663
|
@see: Method L{Fsum.__ipow__}.
|
|
667
664
|
'''
|
|
668
|
-
f = self.
|
|
665
|
+
f = self._copy_2r(other, self.__rpow__)
|
|
669
666
|
return f._fpow(self, _pow_op_, *mod)
|
|
670
667
|
|
|
671
668
|
def __rsub__(self, other):
|
|
@@ -673,7 +670,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
673
670
|
|
|
674
671
|
@see: Method L{Fsum.__isub__}.
|
|
675
672
|
'''
|
|
676
|
-
f = self.
|
|
673
|
+
f = self._copy_2r(other, self.__rsub__)
|
|
677
674
|
return f._fsub(self, _sub_op_)
|
|
678
675
|
|
|
679
676
|
def __rtruediv__(self, other):
|
|
@@ -681,7 +678,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
681
678
|
|
|
682
679
|
@see: Method L{Fsum.__itruediv__}.
|
|
683
680
|
'''
|
|
684
|
-
f = self.
|
|
681
|
+
f = self._copy_2r(other, self.__rtruediv__)
|
|
685
682
|
return f._ftruediv(self, _truediv_op_)
|
|
686
683
|
|
|
687
684
|
def __str__(self):
|
|
@@ -781,57 +778,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
781
778
|
f._ps = list(self._ps) # separate list
|
|
782
779
|
return f
|
|
783
780
|
|
|
784
|
-
def
|
|
785
|
-
'''(INTERNAL) Copy with/-out overriding C{partials}.
|
|
786
|
-
'''
|
|
787
|
-
# for x in xs:
|
|
788
|
-
# assert isscalar(x)
|
|
789
|
-
f = self._Fsum(self._n + len(xs), *xs)
|
|
790
|
-
if self.name:
|
|
791
|
-
f._name = self.name # .rename calls _update_attrs
|
|
792
|
-
return f
|
|
793
|
-
|
|
794
|
-
def _copy_2(self, which):
|
|
781
|
+
def _copy_2(self, which, name=NN):
|
|
795
782
|
'''(INTERNAL) Copy for I{dyadic} operators.
|
|
796
783
|
'''
|
|
784
|
+
n = name or which.__name__
|
|
797
785
|
# NOT .classof due to .Fdot(a, *b) args, etc.
|
|
798
|
-
f = _Named.copy(self, deep=False, name=
|
|
786
|
+
f = _Named.copy(self, deep=False, name=n)
|
|
799
787
|
# assert f._n == self._n
|
|
800
788
|
f._ps = list(self._ps) # separate list
|
|
801
789
|
return f
|
|
802
790
|
|
|
803
|
-
def
|
|
804
|
-
'''(INTERNAL) Negated copy for I{monadic} C{__abs__} and C{__neg__}.
|
|
805
|
-
'''
|
|
806
|
-
if self._ps:
|
|
807
|
-
f = self._Fsum(self._n)
|
|
808
|
-
f._ps[:] = self._ps_n()
|
|
809
|
-
# f._facc_up(up=False)
|
|
810
|
-
else:
|
|
811
|
-
f = self._Fsum(self._n, _0_0)
|
|
812
|
-
f._name = which.__name__ # .rename calls _update_attrs
|
|
813
|
-
return f
|
|
814
|
-
|
|
815
|
-
def _copy_r2(self, other, which):
|
|
791
|
+
def _copy_2r(self, other, which):
|
|
816
792
|
'''(INTERNAL) Copy for I{reverse-dyadic} operators.
|
|
817
793
|
'''
|
|
818
794
|
return other._copy_2(which) if isinstance(other, Fsum) else \
|
|
819
|
-
Fsum(other, name=which.__name__)
|
|
795
|
+
Fsum(other, name=which.__name__)
|
|
820
796
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
def _copy_up(self, _fprs2=False):
|
|
829
|
-
'''(INTERNAL) Minimal, anonymous copy.
|
|
830
|
-
'''
|
|
831
|
-
f = self._Fsum(self._n, *self._ps)
|
|
832
|
-
if _fprs2: # only the ._fprs2 2-tuple
|
|
833
|
-
Fsum._fprs2._update_from(f, self)
|
|
834
|
-
return f
|
|
797
|
+
# def _copy_RESIDUAL(self, other):
|
|
798
|
+
# '''(INTERNAL) Copy C{other._RESIDUAL}.
|
|
799
|
+
# '''
|
|
800
|
+
# R = other._RESIDUAL
|
|
801
|
+
# if R is not Fsum._RESIDUAL:
|
|
802
|
+
# self._RESIDUAL = R
|
|
835
803
|
|
|
836
804
|
def divmod(self, other):
|
|
837
805
|
'''Return C{divmod(B{self}, B{other})} as 2-tuple C{(quotient,
|
|
@@ -839,9 +807,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
839
807
|
|
|
840
808
|
@arg other: An L{Fsum} or C{scalar} divisor.
|
|
841
809
|
|
|
842
|
-
@return:
|
|
843
|
-
an C{int} in Python 3+ or
|
|
844
|
-
|
|
810
|
+
@return: A L{DivMod2Tuple}C{(div, mod)}, with quotient C{div}
|
|
811
|
+
an C{int} in Python 3+ or C{float} in Python 2- and
|
|
812
|
+
remainder C{mod} an L{Fsum} instance.
|
|
845
813
|
|
|
846
814
|
@see: Method L{Fsum.__itruediv__}.
|
|
847
815
|
'''
|
|
@@ -872,7 +840,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
872
840
|
if p:
|
|
873
841
|
ps[i] = p
|
|
874
842
|
i += 1
|
|
875
|
-
ps[i:] =
|
|
843
|
+
ps[i:] = x,
|
|
876
844
|
n += 1
|
|
877
845
|
# assert self._ps is ps
|
|
878
846
|
if n:
|
|
@@ -887,6 +855,39 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
887
855
|
'''
|
|
888
856
|
return self._facc(xs, **up) if xs else self
|
|
889
857
|
|
|
858
|
+
def _facc_power(self, power, xs, which): # in .fmath
|
|
859
|
+
'''(INTERNAL) Add each C{xs} as C{float(x**power)}.
|
|
860
|
+
'''
|
|
861
|
+
if isinstance(power, Fsum):
|
|
862
|
+
if power.is_exact:
|
|
863
|
+
return self._facc_power(power._fprs, xs, which)
|
|
864
|
+
_Pow = Fsum._pow_any
|
|
865
|
+
elif isint(power, both=True) and power >= 0:
|
|
866
|
+
_Pow = Fsum._pow_int
|
|
867
|
+
power = int(power)
|
|
868
|
+
else:
|
|
869
|
+
_Pow = Fsum._pow_scalar
|
|
870
|
+
power = _2float(power=power)
|
|
871
|
+
|
|
872
|
+
if power:
|
|
873
|
+
from math import pow as _pow
|
|
874
|
+
op = which.__name__
|
|
875
|
+
|
|
876
|
+
def _X(X):
|
|
877
|
+
f = _Pow(X, power, power, op)
|
|
878
|
+
try: # isinstance(f, Fsum)
|
|
879
|
+
return f._ps
|
|
880
|
+
except AttributeError: # scalar
|
|
881
|
+
return f,
|
|
882
|
+
|
|
883
|
+
def _x(x):
|
|
884
|
+
return _pow(float(x), power)
|
|
885
|
+
|
|
886
|
+
self._facc(_2yield(xs, 1, _X, _x)) # PYCHOK yield
|
|
887
|
+
else:
|
|
888
|
+
self._facc_(float(len(xs))) # x**0 == 1
|
|
889
|
+
return self
|
|
890
|
+
|
|
890
891
|
# def _facc_up(self, up=True):
|
|
891
892
|
# '''(INTERNAL) Update the C{partials}, by removing
|
|
892
893
|
# and re-accumulating the final C{partial}.
|
|
@@ -942,18 +943,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
942
943
|
'''
|
|
943
944
|
return self._facc(_2floats(xs, origin=1)) # PYCHOK yield
|
|
944
945
|
|
|
945
|
-
def _fadd(self, other, op): # in .fmath.Fhorner
|
|
946
|
+
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
946
947
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
947
948
|
'''
|
|
948
949
|
if isinstance(other, Fsum):
|
|
949
950
|
if other is self:
|
|
950
|
-
self._facc_(*other._ps) # == ._facc(tuple(other._ps))
|
|
951
|
+
self._facc_(*other._ps, **up) # == ._facc(tuple(other._ps))
|
|
951
952
|
elif other._ps:
|
|
952
|
-
self._facc(other._ps)
|
|
953
|
+
self._facc(other._ps, **up)
|
|
953
954
|
elif not isscalar(other):
|
|
954
955
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
955
956
|
elif other:
|
|
956
|
-
self._facc_(other)
|
|
957
|
+
self._facc_(other, **up)
|
|
957
958
|
return self
|
|
958
959
|
|
|
959
960
|
fcopy = copy # for backward compatibility
|
|
@@ -961,13 +962,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
961
962
|
fdivmod = __divmod__ # for backward compatibility
|
|
962
963
|
|
|
963
964
|
def _fdivmod2(self, other, op):
|
|
964
|
-
'''(INTERNAL) C{
|
|
965
|
-
(C{int} or C{float}, remainder C{self}).
|
|
965
|
+
'''(INTERNAL) Apply C{B{self} %= B{other}} and return a L{DivMod2Tuple}.
|
|
966
966
|
'''
|
|
967
967
|
# result mostly follows CPython function U{float_divmod
|
|
968
968
|
# <https://GitHub.com/python/cpython/blob/main/Objects/floatobject.c>},
|
|
969
969
|
# but at least divmod(-3, 2) equals Cpython's result (-2, 1).
|
|
970
|
-
q = self.
|
|
970
|
+
q = self._copy_2(self._fdivmod2)._ftruediv(other, op).floor
|
|
971
971
|
if q: # == float // other == floor(float / other)
|
|
972
972
|
self -= other * q
|
|
973
973
|
|
|
@@ -975,12 +975,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
975
975
|
if s and self.signOf() == -s: # PYCHOK no cover
|
|
976
976
|
self += other
|
|
977
977
|
q -= 1
|
|
978
|
-
|
|
979
|
-
# t = self.signOf()
|
|
978
|
+
# t = self.signOf()
|
|
980
979
|
# if t and t != s:
|
|
981
|
-
# from pygeodesy.errors import _AssertionError
|
|
982
980
|
# raise self._Error(op, other, _AssertionError, txt=signOf.__name__)
|
|
983
|
-
return q, self # q is C{int} in Python 3+, but C{float} in Python 2-
|
|
981
|
+
return DivMod2Tuple(q, self) # q is C{int} in Python 3+, but C{float} in Python 2-
|
|
984
982
|
|
|
985
983
|
def _finite(self, other, op=None):
|
|
986
984
|
'''(INTERNAL) Return B{C{other}} if C{finite}.
|
|
@@ -990,7 +988,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
990
988
|
raise ValueError(_not_finite_) if not op else \
|
|
991
989
|
self._ValueError(op, other, txt=_not_finite_)
|
|
992
990
|
|
|
993
|
-
def fint(self, raiser=True, name
|
|
991
|
+
def fint(self, raiser=True, **name):
|
|
994
992
|
'''Return this instance' current running sum as C{integer}.
|
|
995
993
|
|
|
996
994
|
@kwarg raiser: If C{True} throw a L{ResidualError} if the
|
|
@@ -1007,8 +1005,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1007
1005
|
if r and raiser:
|
|
1008
1006
|
t = _stresidual(_integer_, r)
|
|
1009
1007
|
raise ResidualError(_integer_, i, txt=t)
|
|
1010
|
-
|
|
1011
|
-
return
|
|
1008
|
+
f = self._copy_2(self.fint, **name)
|
|
1009
|
+
return f._fset(i)
|
|
1012
1010
|
|
|
1013
1011
|
def fint2(self, **name):
|
|
1014
1012
|
'''Return this instance' current running sum as C{int} and
|
|
@@ -1026,9 +1024,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1026
1024
|
def _fint2(self): # see ._fset
|
|
1027
1025
|
'''(INTERNAL) Get 2-tuple (C{int}, I{integer} residual).
|
|
1028
1026
|
'''
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1027
|
+
s, r = self._fprs2
|
|
1028
|
+
i = int(s)
|
|
1029
|
+
r = _fsum(self._ps_1(i)) if r else float(s - i)
|
|
1032
1030
|
return i, (r or INT0)
|
|
1033
1031
|
|
|
1034
1032
|
@deprecated_property_RO
|
|
@@ -1048,7 +1046,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1048
1046
|
'''
|
|
1049
1047
|
s, r = self._fprs2
|
|
1050
1048
|
f = _floor(s) + _floor(r) + 1
|
|
1051
|
-
while
|
|
1049
|
+
while (f - s) > r: # f > (s + r)
|
|
1052
1050
|
f -= 1
|
|
1053
1051
|
return f
|
|
1054
1052
|
|
|
@@ -1058,25 +1056,25 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1058
1056
|
'''Apply C{B{self} //= B{other}}.
|
|
1059
1057
|
'''
|
|
1060
1058
|
q = self._ftruediv(other, op) # == self
|
|
1061
|
-
return self._fset(q.floor
|
|
1059
|
+
return self._fset(q.floor) # floor(q)
|
|
1062
1060
|
|
|
1063
1061
|
fmul = __imul__ # for backward compatibility
|
|
1064
1062
|
|
|
1065
1063
|
def _fmul(self, other, op):
|
|
1066
1064
|
'''(INTERNAL) Apply C{B{self} *= B{other}}.
|
|
1067
1065
|
'''
|
|
1068
|
-
if
|
|
1066
|
+
if isinstance(other, Fsum):
|
|
1067
|
+
if len(self._ps) != 1:
|
|
1068
|
+
f = self._mul_Fsum(other, op)
|
|
1069
|
+
elif len(other._ps) != 1: # and len(self._ps) == 1
|
|
1070
|
+
f = other._mul_scalar(self._ps[0], op)
|
|
1071
|
+
else: # len(other._ps) == len(self._ps) == 1
|
|
1072
|
+
f = self._finite(self._ps[0] * other._ps[0])
|
|
1073
|
+
elif isscalar(other):
|
|
1069
1074
|
f = self._mul_scalar(other, op)
|
|
1070
|
-
|
|
1075
|
+
else:
|
|
1071
1076
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
1072
|
-
|
|
1073
|
-
f = self._mul_Fsum(other, op)
|
|
1074
|
-
elif len(other._ps) != 1: # len(self._ps) == 1
|
|
1075
|
-
f = other._copy_up()._mul_scalar(self._ps[0], op)
|
|
1076
|
-
else: # len(other._ps) == len(self._ps) == 1
|
|
1077
|
-
s = self._finite(self._ps[0] * other._ps[0])
|
|
1078
|
-
return self._fset(s, asis=True, n=len(self) + 1)
|
|
1079
|
-
return self._fset(f)
|
|
1077
|
+
return self._fset(f) # n=len(self) + 1
|
|
1080
1078
|
|
|
1081
1079
|
def fover(self, over):
|
|
1082
1080
|
'''Apply C{B{self} /= B{over}} and summate.
|
|
@@ -1094,30 +1092,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1094
1092
|
def _fpow(self, other, op, *mod):
|
|
1095
1093
|
'''Apply C{B{self} **= B{other}}, optional B{C{mod}} or C{None}.
|
|
1096
1094
|
'''
|
|
1097
|
-
if mod
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1095
|
+
if mod:
|
|
1096
|
+
if mod[0] is not None: # == 3-arg C{pow}
|
|
1097
|
+
f = self._pow_3(other, mod[0], op)
|
|
1098
|
+
elif self.is_integer():
|
|
1099
|
+
# return an exact C{int} for C{int}**C{int}
|
|
1100
|
+
x = _2scalar(other) # C{int}, C{float} or other
|
|
1101
|
+
i = self._fint2[0] # assert _fint2[1] == 0
|
|
1102
|
+
f = self._pow_2(i, x, other, op) if isscalar(x) else \
|
|
1103
|
+
_Fsum_ps(i)._pow_any(x, other, op)
|
|
1104
|
+
else: # mod[0] is None, power(self, other)
|
|
1105
|
+
f = self._pow_any(other, other, op)
|
|
1104
1106
|
else: # pow(self, other) == pow(self, other, None)
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
x, r = other._fprs2
|
|
1108
|
-
if r:
|
|
1109
|
-
if self._raiser(r, x):
|
|
1110
|
-
raise self._ResidualError(op, other, r)
|
|
1111
|
-
p = self._pow_scalar(r, other, op)
|
|
1112
|
-
# p = _2scalar(p) # _raiser = None
|
|
1113
|
-
elif not isscalar(other):
|
|
1114
|
-
raise self._TypeError(op, other) # txt=_invalid_
|
|
1115
|
-
else:
|
|
1116
|
-
x = self._finite(other, op)
|
|
1117
|
-
s = self._pow_scalar(x, other, op)
|
|
1118
|
-
if p is not None:
|
|
1119
|
-
s *= p
|
|
1120
|
-
return self._fset(s, asis=isint(s), n=max(len(self), 1))
|
|
1107
|
+
f = self._pow_any(other, other, op)
|
|
1108
|
+
return self._fset(f, asis=isint(f)) # n=max(len(self), 1)
|
|
1121
1109
|
|
|
1122
1110
|
@Property_RO
|
|
1123
1111
|
def _fprs(self):
|
|
@@ -1127,30 +1115,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1127
1115
|
@note: The precision running C{fsum} after a C{//=} or
|
|
1128
1116
|
C{//} C{floor} division is C{int} in Python 3+.
|
|
1129
1117
|
'''
|
|
1130
|
-
|
|
1131
|
-
n = len(ps) - 1
|
|
1132
|
-
if n > 1:
|
|
1133
|
-
s = _psum(ps)
|
|
1134
|
-
elif n > 0: # len(ps) == 2
|
|
1135
|
-
s, p = _2sum(*ps) if ps[1] else ps
|
|
1136
|
-
ps[:] = ([p, s] if s else [p]) if p else [s]
|
|
1137
|
-
elif n < 0: # see L{Fsum.__init__}
|
|
1138
|
-
s = _0_0
|
|
1139
|
-
ps[:] = [s]
|
|
1140
|
-
else: # len(ps) == 1
|
|
1141
|
-
s = ps[0]
|
|
1142
|
-
# assert self._ps is ps
|
|
1143
|
-
# assert Fsum._fprs2.name not in self.__dict__
|
|
1144
|
-
return s
|
|
1118
|
+
return self._fprs2.fsum
|
|
1145
1119
|
|
|
1146
1120
|
@Property_RO
|
|
1147
1121
|
def _fprs2(self):
|
|
1148
1122
|
'''(INTERNAL) Get and cache this instance' precision
|
|
1149
1123
|
running sum and residual (L{Fsum2Tuple}).
|
|
1150
1124
|
'''
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1125
|
+
ps = self._ps
|
|
1126
|
+
n = len(ps)
|
|
1127
|
+
if n > 2: # len(ps) > 2
|
|
1128
|
+
s = _psum(ps)
|
|
1129
|
+
r = _fsum(self._ps_1(s)) or INT0
|
|
1130
|
+
elif n > 1: # len(ps) == 2
|
|
1131
|
+
ps[:] = _2ps(*_2sum(*ps))
|
|
1132
|
+
r, s = (INT0, ps[0]) if len(ps) != 2 else ps
|
|
1133
|
+
elif ps: # len(ps) == 1
|
|
1134
|
+
s, r = ps[0], INT0
|
|
1135
|
+
else: # len(ps) == 0
|
|
1136
|
+
s, r = _0_0, INT0
|
|
1137
|
+
ps[:] = s,
|
|
1138
|
+
# assert self._ps is ps
|
|
1139
|
+
return Fsum2Tuple(s, r)
|
|
1154
1140
|
|
|
1155
1141
|
# def _fpsqz(self):
|
|
1156
1142
|
# '''(INTERNAL) Compress, squeeze the C{partials}.
|
|
@@ -1159,15 +1145,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1159
1145
|
# _ = self._fprs
|
|
1160
1146
|
# return self
|
|
1161
1147
|
|
|
1162
|
-
def _fset(self, other, asis=
|
|
1148
|
+
def _fset(self, other, asis=True, n=0):
|
|
1163
1149
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
1164
1150
|
'''
|
|
1165
1151
|
if other is self:
|
|
1166
1152
|
pass # from ._fmul, ._ftruediv and ._pow_scalar
|
|
1167
1153
|
elif isinstance(other, Fsum):
|
|
1168
|
-
self._n = other._n
|
|
1154
|
+
self._n = n or other._n
|
|
1169
1155
|
self._ps[:] = other._ps
|
|
1170
|
-
|
|
1156
|
+
# self._copy_RESIDUAL(other)
|
|
1171
1157
|
# use or zap the C{Property_RO} values
|
|
1172
1158
|
Fsum._fint2._update_from(self, other)
|
|
1173
1159
|
Fsum._fprs ._update_from(self, other)
|
|
@@ -1176,65 +1162,65 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1176
1162
|
s = other if asis else float(other)
|
|
1177
1163
|
i = int(s) # see ._fint2
|
|
1178
1164
|
t = i, ((s - i) or INT0)
|
|
1179
|
-
self._n =
|
|
1180
|
-
self._ps[:] =
|
|
1181
|
-
#
|
|
1165
|
+
self._n = n or 1
|
|
1166
|
+
self._ps[:] = s,
|
|
1167
|
+
# Property_ROs _fint2, _fprs and _fprs2 can't be a Property:
|
|
1182
1168
|
# Property's _fset zaps the value just set by the @setter
|
|
1183
1169
|
self.__dict__.update(_fint2=t, _fprs=s, _fprs2=Fsum2Tuple(s, INT0))
|
|
1184
1170
|
else: # PYCHOK no cover
|
|
1185
1171
|
raise self._TypeError(_fset_op_, other) # txt=_invalid_
|
|
1186
1172
|
return self
|
|
1187
1173
|
|
|
1174
|
+
def _fset_ps(self, other, n=0): # in .fmath
|
|
1175
|
+
'''(INTERNAL) Set a known C{Fsum} or C{scalar}.
|
|
1176
|
+
'''
|
|
1177
|
+
if isinstance(other, Fsum):
|
|
1178
|
+
self._n = n or other._n
|
|
1179
|
+
self._ps[:] = other._ps
|
|
1180
|
+
else: # assert isscalar(other)
|
|
1181
|
+
self._n = n or 1
|
|
1182
|
+
self._ps[:] = other,
|
|
1183
|
+
|
|
1188
1184
|
def fsub(self, xs=()):
|
|
1189
|
-
'''Subtract an iterable of C{scalar} or L{Fsum} instances
|
|
1190
|
-
|
|
1185
|
+
'''Subtract an iterable of C{scalar} or L{Fsum} instances from
|
|
1186
|
+
this instance.
|
|
1191
1187
|
|
|
1192
|
-
@arg xs: Iterable, list, tuple. etc. (C{scalar}
|
|
1193
|
-
|
|
1188
|
+
@arg xs: Iterable, list, tuple. etc. (C{scalar} or L{Fsum}
|
|
1189
|
+
instances).
|
|
1194
1190
|
|
|
1195
1191
|
@return: This instance, updated (L{Fsum}).
|
|
1196
1192
|
|
|
1197
1193
|
@see: Method L{Fsum.fadd}.
|
|
1198
1194
|
'''
|
|
1199
|
-
return self._facc(_2floats(xs,
|
|
1195
|
+
return self._facc(_2floats(xs, neg=True)) if xs else self # PYCHOK yield
|
|
1200
1196
|
|
|
1201
1197
|
def fsub_(self, *xs):
|
|
1202
|
-
'''Subtract all positional C{scalar} or L{Fsum} instances
|
|
1203
|
-
|
|
1198
|
+
'''Subtract all positional C{scalar} or L{Fsum} instances from
|
|
1199
|
+
this instance.
|
|
1204
1200
|
|
|
1205
|
-
@arg xs: Values to subtract (C{scalar} or
|
|
1206
|
-
|
|
1201
|
+
@arg xs: Values to subtract (C{scalar} or L{Fsum} instances),
|
|
1202
|
+
all positional.
|
|
1207
1203
|
|
|
1208
1204
|
@return: This instance, updated (L{Fsum}).
|
|
1209
1205
|
|
|
1210
1206
|
@see: Method L{Fsum.fadd}.
|
|
1211
1207
|
'''
|
|
1212
|
-
return self._facc(_2floats(xs, origin=1,
|
|
1208
|
+
return self._facc(_2floats(xs, origin=1, neg=True)) if xs else self # PYCHOK yield
|
|
1213
1209
|
|
|
1214
1210
|
def _fsub(self, other, op):
|
|
1215
1211
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
1216
1212
|
'''
|
|
1217
1213
|
if isinstance(other, Fsum):
|
|
1218
1214
|
if other is self: # or other._fprs2 == self._fprs2:
|
|
1219
|
-
self._fset(_0_0
|
|
1215
|
+
self._fset(_0_0) # n=len(self) * 2, self -= self
|
|
1220
1216
|
elif other._ps:
|
|
1221
|
-
self._facc(other.
|
|
1217
|
+
self._facc(other._ps_neg)
|
|
1222
1218
|
elif not isscalar(other):
|
|
1223
1219
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
1224
1220
|
elif self._finite(other, op):
|
|
1225
1221
|
self._facc_(-other)
|
|
1226
1222
|
return self
|
|
1227
1223
|
|
|
1228
|
-
def _Fsum(self, n, *ps):
|
|
1229
|
-
'''(INTERNAL) New L{Fsum} instance.
|
|
1230
|
-
'''
|
|
1231
|
-
f = Fsum()
|
|
1232
|
-
f._n = n
|
|
1233
|
-
if ps:
|
|
1234
|
-
f._ps[:] = ps
|
|
1235
|
-
f._copy_RESIDUAL(self)
|
|
1236
|
-
return f
|
|
1237
|
-
|
|
1238
1224
|
def fsum(self, xs=()):
|
|
1239
1225
|
'''Add more C{scalar} or L{Fsum} instances and summate.
|
|
1240
1226
|
|
|
@@ -1267,8 +1253,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1267
1253
|
'''Add more C{scalar} or L{Fsum} instances and return the
|
|
1268
1254
|
current precision running sum and the C{residual}.
|
|
1269
1255
|
|
|
1270
|
-
@kwarg xs: Iterable, list, tuple, etc. (C{scalar} or
|
|
1271
|
-
|
|
1256
|
+
@kwarg xs: Iterable, list, tuple, etc. (C{scalar} or L{Fsum}
|
|
1257
|
+
instances).
|
|
1272
1258
|
@kwarg name: Optional name (C{str}).
|
|
1273
1259
|
|
|
1274
1260
|
@return: L{Fsum2Tuple}C{(fsum, residual)} with C{fsum} the
|
|
@@ -1282,7 +1268,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1282
1268
|
f = self._facc(_2floats(xs)) if xs else self # PYCHOK yield
|
|
1283
1269
|
t = f._fprs2
|
|
1284
1270
|
if name:
|
|
1285
|
-
|
|
1271
|
+
n = _xkwds_get(name, name=NN)
|
|
1272
|
+
if n:
|
|
1273
|
+
t = t.dup(name=n)
|
|
1286
1274
|
return t
|
|
1287
1275
|
|
|
1288
1276
|
def fsum2_(self, *xs):
|
|
@@ -1319,7 +1307,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1319
1307
|
n = _1_0
|
|
1320
1308
|
if isinstance(other, Fsum):
|
|
1321
1309
|
if other is self or other._fprs2 == self._fprs2:
|
|
1322
|
-
return self._fset(_1_0
|
|
1310
|
+
return self._fset(_1_0) # n=len(self)
|
|
1323
1311
|
d, r = other._fprs2
|
|
1324
1312
|
if r:
|
|
1325
1313
|
if not d: # PYCHOK no cover
|
|
@@ -1339,7 +1327,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1339
1327
|
E, t = _xError2(x)
|
|
1340
1328
|
raise self._Error(op, other, E, txt=t)
|
|
1341
1329
|
f = self._mul_scalar(s, _mul_op_) # handles 0, NAN, etc.
|
|
1342
|
-
return self._fset(f)
|
|
1330
|
+
return self._fset(f, asis=False)
|
|
1343
1331
|
|
|
1344
1332
|
@property_RO
|
|
1345
1333
|
def imag(self):
|
|
@@ -1387,9 +1375,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1387
1375
|
return False if r else True
|
|
1388
1376
|
|
|
1389
1377
|
def is_math_fsum(self):
|
|
1390
|
-
'''Return whether functions L{fsum}, L{fsum_}, L{fsum1}
|
|
1391
|
-
|
|
1392
|
-
|
|
1378
|
+
'''Return whether functions L{fsum}, L{fsum_}, L{fsum1} and
|
|
1379
|
+
L{fsum1_} plus partials summation are based on Python's
|
|
1380
|
+
C{math.fsum} or not.
|
|
1393
1381
|
|
|
1394
1382
|
@return: C{2} if all functions and partials summation
|
|
1395
1383
|
are based on C{math.fsum}, C{True} if only
|
|
@@ -1400,24 +1388,34 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1400
1388
|
f = Fsum._math_fsum
|
|
1401
1389
|
return 2 if _psum is f else bool(f)
|
|
1402
1390
|
|
|
1403
|
-
def _mul_Fsum(self, other, op=_mul_op_):
|
|
1404
|
-
'''(INTERNAL) Return C{B{self} * Fsum B{other}} as L{Fsum}.
|
|
1391
|
+
def _mul_Fsum(self, other, op=_mul_op_): # in .fmath.Fhorner
|
|
1392
|
+
'''(INTERNAL) Return C{B{self} * Fsum B{other}} as L{Fsum} or C{0}.
|
|
1405
1393
|
'''
|
|
1406
1394
|
# assert isinstance(other, Fsum)
|
|
1407
|
-
|
|
1395
|
+
if self._ps and other._ps:
|
|
1396
|
+
f = _Fsum_xs(self._ps_mul(op, *other._ps))
|
|
1397
|
+
else:
|
|
1398
|
+
f = _0_0
|
|
1399
|
+
return f
|
|
1408
1400
|
|
|
1409
|
-
def _mul_scalar(self, factor, op):
|
|
1410
|
-
'''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum} or C{
|
|
1401
|
+
def _mul_scalar(self, factor, op): # in .fmath.Fhorner
|
|
1402
|
+
'''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum}, C{0} or C{self}.
|
|
1411
1403
|
'''
|
|
1412
1404
|
# assert isscalar(factor)
|
|
1413
|
-
if self._finite(factor, op)
|
|
1414
|
-
if factor == _1_0
|
|
1415
|
-
|
|
1416
|
-
|
|
1405
|
+
if self._ps and self._finite(factor, op):
|
|
1406
|
+
f = self if factor == _1_0 else (
|
|
1407
|
+
self._neg if factor == _N_1_0 else
|
|
1408
|
+
_Fsum_xs(self._ps_mul(op, factor))) # PYCHOK indent
|
|
1417
1409
|
else:
|
|
1418
|
-
f =
|
|
1410
|
+
f = _0_0
|
|
1419
1411
|
return f
|
|
1420
1412
|
|
|
1413
|
+
@property_RO
|
|
1414
|
+
def _neg(self):
|
|
1415
|
+
'''(INTERNAL) Return C{-self}.
|
|
1416
|
+
'''
|
|
1417
|
+
return _Fsum_ps(*self._ps_neg) if self._ps else NEG0
|
|
1418
|
+
|
|
1421
1419
|
@property_RO
|
|
1422
1420
|
def partials(self):
|
|
1423
1421
|
'''Get this instance' current partial sums (C{tuple} of C{float}s and/or C{int}s).
|
|
@@ -1436,27 +1434,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1436
1434
|
|
|
1437
1435
|
@note: If B{C{mod}} is given as C{None}, the result will be an
|
|
1438
1436
|
C{integer} L{Fsum} provided this instance C{is_integer}
|
|
1439
|
-
or set C{integer} with L{Fsum.fint}.
|
|
1437
|
+
or set to C{integer} with L{Fsum.fint}.
|
|
1440
1438
|
|
|
1441
1439
|
@see: Methods L{Fsum.__ipow__}, L{Fsum.fint} and L{Fsum.is_integer}.
|
|
1442
1440
|
'''
|
|
1443
1441
|
f = self._copy_2(self.pow)
|
|
1444
|
-
|
|
1445
|
-
f._pow_int(x, x, _pow_op_) # f **= x
|
|
1446
|
-
else:
|
|
1447
|
-
f._fpow(x, _pow_op_, *mod) # f = pow(f, x, *mod)
|
|
1448
|
-
return f
|
|
1442
|
+
return f._fpow(x, _pow_op_, *mod) # f = pow(f, x, *mod)
|
|
1449
1443
|
|
|
1450
1444
|
def _pow_0_1(self, x, other):
|
|
1451
1445
|
'''(INTERNAL) Return B{C{self}**1} or C{B{self}**0 == 1.0}.
|
|
1452
1446
|
'''
|
|
1453
1447
|
return self if x else (1 if self.is_integer() and isint(other) else _1_0)
|
|
1454
1448
|
|
|
1455
|
-
def _pow_2(self, x, other, op):
|
|
1456
|
-
'''(INTERNAL) 2-arg C{pow(B{
|
|
1449
|
+
def _pow_2(self, b, x, other, op):
|
|
1450
|
+
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} embellishing errors.
|
|
1457
1451
|
'''
|
|
1458
|
-
# assert
|
|
1459
|
-
b = self._ps[0] # assert isscalar(b)
|
|
1452
|
+
# assert isscalar(b) and isscalar(x)
|
|
1460
1453
|
try: # type(s) == type(x) if x in (_1_0, 1)
|
|
1461
1454
|
s = pow(b, x) # -1**2.3 == -(1**2.3)
|
|
1462
1455
|
if not iscomplex(s):
|
|
@@ -1487,35 +1480,58 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1487
1480
|
t = _COMMASPACE_(Fmt.PARENSPACED(mod=mod), t)
|
|
1488
1481
|
raise self._Error(op, other, E, txt=t)
|
|
1489
1482
|
|
|
1483
|
+
def _pow_any(self, other, unused, op):
|
|
1484
|
+
'''Return C{B{self} ** B{other}}.
|
|
1485
|
+
'''
|
|
1486
|
+
if isinstance(other, Fsum):
|
|
1487
|
+
x, r = other._fprs2
|
|
1488
|
+
f = self._pow_scalar(x, other, op)
|
|
1489
|
+
if r:
|
|
1490
|
+
if self._raiser(r, x):
|
|
1491
|
+
raise self._ResidualError(op, other, r)
|
|
1492
|
+
s = self._pow_scalar(r, other, op)
|
|
1493
|
+
# s = _2scalar(s) # _raiser = None
|
|
1494
|
+
f *= s
|
|
1495
|
+
elif isscalar(other):
|
|
1496
|
+
x = self._finite(other, op)
|
|
1497
|
+
f = self._pow_scalar(x, other, op)
|
|
1498
|
+
else:
|
|
1499
|
+
raise self._TypeError(op, other) # txt=_invalid_
|
|
1500
|
+
return f
|
|
1501
|
+
|
|
1490
1502
|
def _pow_int(self, x, other, op):
|
|
1491
1503
|
'''(INTERNAL) Return C{B{self} **= B{x}} for C{int B{x} >= 0}.
|
|
1492
1504
|
'''
|
|
1493
1505
|
# assert isint(x) and x >= 0
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1506
|
+
ps = self._ps
|
|
1507
|
+
if len(ps) > 1:
|
|
1508
|
+
f = self
|
|
1509
|
+
if x > 4:
|
|
1497
1510
|
m = 1 # single-bit mask
|
|
1498
|
-
if x & m:
|
|
1511
|
+
if (x & m):
|
|
1499
1512
|
x -= m # x ^= m
|
|
1500
|
-
f = p._copy_up()
|
|
1501
1513
|
else:
|
|
1502
|
-
f =
|
|
1514
|
+
f = _Fsum_ps(_1_0)
|
|
1515
|
+
p = self
|
|
1503
1516
|
while x:
|
|
1504
1517
|
p = p._mul_Fsum(p, op) # p **= 2
|
|
1505
1518
|
m += m # m <<= 1
|
|
1506
|
-
if x & m:
|
|
1519
|
+
if (x & m):
|
|
1507
1520
|
x -= m # x ^= m
|
|
1508
1521
|
f = f._mul_Fsum(p, op) # f *= p
|
|
1509
|
-
elif x > 1: # self**2
|
|
1510
|
-
f =
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1522
|
+
elif x > 1: # self**2, 3 or 4
|
|
1523
|
+
f = f._mul_Fsum(f, op)
|
|
1524
|
+
if x > 2: # self**3 or 4
|
|
1525
|
+
p = self if x < 4 else f
|
|
1526
|
+
f = f._mul_Fsum(p, op)
|
|
1527
|
+
else: # self**1 or self**0 == 1 or _1_0
|
|
1528
|
+
f = f._pow_0_1(x, other)
|
|
1529
|
+
elif ps: # self._ps[0]**x
|
|
1530
|
+
f = self._pow_2(ps[0], x, other, op)
|
|
1515
1531
|
else: # PYCHOK no cover
|
|
1516
1532
|
# 0**pos_int == 0, but 0**0 == 1
|
|
1517
1533
|
f = 0 if x else 1 # like ._fprs
|
|
1518
|
-
return
|
|
1534
|
+
return f
|
|
1519
1535
|
|
|
1520
1536
|
def _pow_scalar(self, x, other, op):
|
|
1521
1537
|
'''(INTERNAL) Return C{self**B{x}} for C{scalar B{x}}.
|
|
@@ -1526,26 +1542,21 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1526
1542
|
y = abs(x)
|
|
1527
1543
|
if y > 1:
|
|
1528
1544
|
if r:
|
|
1529
|
-
f = self.
|
|
1545
|
+
f = self._pow_int(y, other, op)
|
|
1530
1546
|
if x > 0: # > 1
|
|
1531
1547
|
return f
|
|
1532
1548
|
# assert x < 0 # < -1
|
|
1533
|
-
s, r = f._fprs2
|
|
1549
|
+
s, r = f._fprs2 if isinstance(f, Fsum) else (f, 0)
|
|
1534
1550
|
if r:
|
|
1535
|
-
return
|
|
1551
|
+
return _Fsum_ps(_1_0)._ftruediv(f, op)
|
|
1536
1552
|
# use **= -1 for the CPython float_pow
|
|
1537
1553
|
# error if s is zero, and not s = 1 / s
|
|
1538
1554
|
x = -1
|
|
1539
|
-
# elif y > 1: # self**2 or self**-2
|
|
1540
|
-
# f = self._mul_Fsum(self, op)
|
|
1541
|
-
# if x < 0:
|
|
1542
|
-
# f = f._copy_0(_1_0)._ftruediv(f, op)
|
|
1543
|
-
# return f
|
|
1544
1555
|
elif x < 0: # self**-1 == 1 / self
|
|
1545
1556
|
if r:
|
|
1546
|
-
return
|
|
1557
|
+
return _Fsum_ps(_1_0)._ftruediv(self, op)
|
|
1547
1558
|
else: # self**1 or self**0
|
|
1548
|
-
return self._pow_0_1(x, other) # self or
|
|
1559
|
+
return self._pow_0_1(x, other) # self, 1 or 1.0
|
|
1549
1560
|
elif not isscalar(x): # assert ...
|
|
1550
1561
|
raise self._TypeError(op, other, txt=_not_scalar_)
|
|
1551
1562
|
elif r and self._raiser(r, s): # non-zero residual**fractional
|
|
@@ -1553,7 +1564,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1553
1564
|
t = _stresidual(_non_zero_, r, fractional_power=x)
|
|
1554
1565
|
raise self._Error(op, other, ResidualError, txt=t)
|
|
1555
1566
|
# assert isscalar(s) and isscalar(x)
|
|
1556
|
-
return self.
|
|
1567
|
+
return self._pow_2(s, x, other, op)
|
|
1557
1568
|
|
|
1558
1569
|
def _ps_1(self, *less):
|
|
1559
1570
|
'''(INTERNAL) Yield partials, 1-primed and subtract any C{less}.
|
|
@@ -1567,28 +1578,25 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1567
1578
|
yield -p
|
|
1568
1579
|
yield _N_1_0
|
|
1569
1580
|
|
|
1570
|
-
def
|
|
1571
|
-
'''(INTERNAL) Yield partials, negated.
|
|
1572
|
-
'''
|
|
1573
|
-
for p in self._ps:
|
|
1574
|
-
if p:
|
|
1575
|
-
yield -p
|
|
1576
|
-
|
|
1577
|
-
def _ps_x(self, op, *factors): # see .fmath.Fhorner
|
|
1581
|
+
def _ps_mul(self, op, *factors): # see .fmath.Fhorner
|
|
1578
1582
|
'''(INTERNAL) Yield all C{partials} times each B{C{factor}},
|
|
1579
1583
|
in total, up to C{len(partials) * len(factors)} items.
|
|
1580
1584
|
'''
|
|
1581
|
-
ps = self._ps
|
|
1585
|
+
ps = self._ps # tuple(self._ps)
|
|
1582
1586
|
if len(ps) < len(factors):
|
|
1583
1587
|
ps, factors = factors, ps
|
|
1584
1588
|
_f = _isfinite
|
|
1585
1589
|
for f in factors:
|
|
1586
1590
|
for p in ps:
|
|
1587
1591
|
p *= f
|
|
1588
|
-
if _f(p)
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
+
yield p if _f(p) else self._finite(p, op)
|
|
1593
|
+
|
|
1594
|
+
@property_RO
|
|
1595
|
+
def _ps_neg(self):
|
|
1596
|
+
'''(INTERNAL) Yield the partials, I{negated}.
|
|
1597
|
+
'''
|
|
1598
|
+
for p in self._ps:
|
|
1599
|
+
yield -p
|
|
1592
1600
|
|
|
1593
1601
|
@property_RO
|
|
1594
1602
|
def real(self):
|
|
@@ -1613,7 +1621,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1613
1621
|
return self._fprs2.residual
|
|
1614
1622
|
|
|
1615
1623
|
def _raiser(self, r, s):
|
|
1616
|
-
'''(INTERNAL) Does
|
|
1624
|
+
'''(INTERNAL) Does ratio C{r / s} exceed threshold?
|
|
1617
1625
|
'''
|
|
1618
1626
|
self._ratio = t = fabs((r / s) if s else r)
|
|
1619
1627
|
return t > self._RESIDUAL
|
|
@@ -1703,12 +1711,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1703
1711
|
'''
|
|
1704
1712
|
return self._Error(op, other, _TypeError, **txt)
|
|
1705
1713
|
|
|
1706
|
-
def _update(self): # see ._fset
|
|
1714
|
+
def _update(self, updated=True): # see ._fset
|
|
1707
1715
|
'''(INTERNAL) Zap all cached C{Property_RO} values.
|
|
1708
1716
|
'''
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1717
|
+
if updated:
|
|
1718
|
+
_pop = self.__dict__.pop
|
|
1719
|
+
for p in _ROs:
|
|
1720
|
+
_ = _pop(p, None)
|
|
1721
|
+
# Fsum._fint2._update(self)
|
|
1722
|
+
# Fsum._fprs ._update(self)
|
|
1723
|
+
# Fsum._fprs2._update(self)
|
|
1712
1724
|
return self
|
|
1713
1725
|
|
|
1714
1726
|
def _ValueError(self, op, other, **txt): # PYCHOK no cover
|
|
@@ -1721,7 +1733,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1721
1733
|
'''
|
|
1722
1734
|
return self._Error(op, other, _ZeroDivisionError, **txt)
|
|
1723
1735
|
|
|
1724
|
-
_allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK assert, see Fsum._fset, -._update
|
|
1736
|
+
_ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK assert, see Fsum._fset, -._update
|
|
1725
1737
|
|
|
1726
1738
|
|
|
1727
1739
|
def _Float_Int(arg, **name_Error):
|
|
@@ -1731,6 +1743,17 @@ def _Float_Int(arg, **name_Error):
|
|
|
1731
1743
|
return U(arg, **name_Error)
|
|
1732
1744
|
|
|
1733
1745
|
|
|
1746
|
+
class DivMod2Tuple(_NamedTuple):
|
|
1747
|
+
'''2-Tuple C{(div, mod)} with the quotient C{div} and remainder
|
|
1748
|
+
C{mod} results of a C{divmod} operation.
|
|
1749
|
+
|
|
1750
|
+
@note: Quotient C{div} an C{int} in Python 3+ or a C{float} in
|
|
1751
|
+
Python 2-. Remainder C{mod} an L{Fsum} instance.
|
|
1752
|
+
'''
|
|
1753
|
+
_Names_ = (_div_, _mod_)
|
|
1754
|
+
_Units_ = (_Float_Int, Fsum)
|
|
1755
|
+
|
|
1756
|
+
|
|
1734
1757
|
class Fsum2Tuple(_NamedTuple):
|
|
1735
1758
|
'''2-Tuple C{(fsum, residual)} with the precision running C{fsum}
|
|
1736
1759
|
and the C{residual}, the sum of the remaining partials. Each
|
|
@@ -1746,8 +1769,8 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
1746
1769
|
def Fsum(self):
|
|
1747
1770
|
'''Get this L{Fsum2Tuple} as an L{Fsum}.
|
|
1748
1771
|
'''
|
|
1749
|
-
|
|
1750
|
-
return
|
|
1772
|
+
s, r = map(float, self)
|
|
1773
|
+
return _Fsum_ps(*_2ps(s, r), name=self.name)
|
|
1751
1774
|
|
|
1752
1775
|
def is_exact(self):
|
|
1753
1776
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
@@ -1769,6 +1792,23 @@ class ResidualError(_ValueError):
|
|
|
1769
1792
|
pass
|
|
1770
1793
|
|
|
1771
1794
|
|
|
1795
|
+
def _Fsum_ps(*ps, **name):
|
|
1796
|
+
'''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
|
|
1797
|
+
'''
|
|
1798
|
+
f = Fsum(**name) if name else Fsum()
|
|
1799
|
+
if ps:
|
|
1800
|
+
f._n = len(ps)
|
|
1801
|
+
f._ps[:] = ps
|
|
1802
|
+
return f
|
|
1803
|
+
|
|
1804
|
+
|
|
1805
|
+
def _Fsum_xs(xs, up=False, **name):
|
|
1806
|
+
'''(INTERNAL) Return an C{Fsum} from known floats C{xs}.
|
|
1807
|
+
'''
|
|
1808
|
+
f = Fsum(**name) if name else Fsum()
|
|
1809
|
+
return f._facc(xs, up=up)
|
|
1810
|
+
|
|
1811
|
+
|
|
1772
1812
|
try:
|
|
1773
1813
|
from math import fsum as _fsum # precision IEEE-754 sum, Python 2.6+
|
|
1774
1814
|
|
|
@@ -1781,7 +1821,7 @@ try:
|
|
|
1781
1821
|
Fsum._math_fsum = _sum = _fsum # PYCHOK exported
|
|
1782
1822
|
|
|
1783
1823
|
if _getenv('PYGEODESY_FSUM_PARTIALS', _fsum.__name__) == _fsum.__name__:
|
|
1784
|
-
_psum = _fsum # PYCHOK
|
|
1824
|
+
_psum = _fsum # PYCHOK re-def
|
|
1785
1825
|
|
|
1786
1826
|
except ImportError:
|
|
1787
1827
|
_sum = sum # Fsum(NAN) exception fall-back
|
|
@@ -1789,16 +1829,16 @@ except ImportError:
|
|
|
1789
1829
|
def _fsum(xs):
|
|
1790
1830
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
1791
1831
|
'''
|
|
1792
|
-
return Fsum(name=_fsum.__name__).
|
|
1832
|
+
return Fsum(name=_fsum.__name__).fsum(xs) if xs else _0_0
|
|
1793
1833
|
|
|
1794
1834
|
|
|
1795
1835
|
def fsum(xs, floats=False):
|
|
1796
1836
|
'''Precision floating point summation based on or like Python's C{math.fsum}.
|
|
1797
1837
|
|
|
1798
|
-
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or
|
|
1799
|
-
|
|
1800
|
-
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all}
|
|
1801
|
-
|
|
1838
|
+
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1839
|
+
instances).
|
|
1840
|
+
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
|
|
1841
|
+
are known to be C{float}.
|
|
1802
1842
|
|
|
1803
1843
|
@return: Precision C{fsum} (C{float}).
|
|
1804
1844
|
|
|
@@ -1819,10 +1859,10 @@ def fsum(xs, floats=False):
|
|
|
1819
1859
|
def fsum_(*xs, **floats):
|
|
1820
1860
|
'''Precision floating point summation of all positional arguments.
|
|
1821
1861
|
|
|
1822
|
-
@arg xs: Values to be added (C{scalar} or L{Fsum} instances),
|
|
1823
|
-
|
|
1824
|
-
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all}
|
|
1825
|
-
|
|
1862
|
+
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1863
|
+
positional.
|
|
1864
|
+
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
|
|
1865
|
+
are known to be C{float}.
|
|
1826
1866
|
|
|
1827
1867
|
@return: Precision C{fsum} (C{float}).
|
|
1828
1868
|
|
|
@@ -1841,10 +1881,10 @@ def fsumf_(*xs):
|
|
|
1841
1881
|
def fsum1(xs, floats=False):
|
|
1842
1882
|
'''Precision floating point summation of a few arguments, 1-primed.
|
|
1843
1883
|
|
|
1844
|
-
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or
|
|
1845
|
-
|
|
1846
|
-
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all}
|
|
1847
|
-
|
|
1884
|
+
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1885
|
+
instances).
|
|
1886
|
+
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
|
|
1887
|
+
are known to be C{float}.
|
|
1848
1888
|
|
|
1849
1889
|
@return: Precision C{fsum} (C{float}).
|
|
1850
1890
|
|
|
@@ -1856,10 +1896,10 @@ def fsum1(xs, floats=False):
|
|
|
1856
1896
|
def fsum1_(*xs, **floats):
|
|
1857
1897
|
'''Precision floating point summation of a few arguments, 1-primed.
|
|
1858
1898
|
|
|
1859
|
-
@arg xs: Values to be added (C{scalar} or L{Fsum} instances),
|
|
1860
|
-
|
|
1861
|
-
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all}
|
|
1862
|
-
|
|
1899
|
+
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1900
|
+
positional.
|
|
1901
|
+
@kwarg floats: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
|
|
1902
|
+
are known to be C{float}.
|
|
1863
1903
|
|
|
1864
1904
|
@return: Precision C{fsum} (C{float}).
|
|
1865
1905
|
|