pygeodesy 24.4.2__py2.py3-none-any.whl → 24.4.12__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.2.dist-info → PyGeodesy-24.4.12.dist-info}/METADATA +9 -9
- {PyGeodesy-24.4.2.dist-info → PyGeodesy-24.4.12.dist-info}/RECORD +36 -36
- pygeodesy/__init__.py +4 -4
- pygeodesy/albers.py +9 -9
- pygeodesy/azimuthal.py +9 -8
- pygeodesy/basics.py +16 -5
- pygeodesy/constants.py +2 -2
- pygeodesy/ecef.py +4 -4
- pygeodesy/ellipsoidalBase.py +2 -3
- pygeodesy/ellipsoids.py +2 -2
- pygeodesy/elliptic.py +19 -17
- pygeodesy/etm.py +3 -3
- pygeodesy/fmath.py +45 -49
- pygeodesy/frechet.py +6 -6
- pygeodesy/fstats.py +3 -4
- pygeodesy/fsums.py +418 -336
- 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 +1 -1
- pygeodesy/ltp.py +1 -1
- pygeodesy/ltpTuples.py +3 -4
- pygeodesy/named.py +14 -3
- pygeodesy/nvectorBase.py +5 -5
- pygeodesy/points.py +3 -3
- pygeodesy/resections.py +6 -5
- pygeodesy/rhumb/bases.py +24 -25
- pygeodesy/sphericalNvector.py +6 -6
- pygeodesy/sphericalTrigonometry.py +3 -4
- pygeodesy/utily.py +11 -10
- pygeodesy/utmupsBase.py +6 -6
- {PyGeodesy-24.4.2.dist-info → PyGeodesy-24.4.12.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.4.2.dist-info → PyGeodesy-24.4.12.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -14,14 +14,13 @@ L{Fsum.__rpow__} return a (very long) C{int} if invoked with optional argument
|
|
|
14
14
|
C{mod} set to C{None}. The C{residual} of an C{integer} L{Fsum} may be between
|
|
15
15
|
C{-1.0} and C{+1.0}, including C{INT0} if considered to be I{exact}.
|
|
16
16
|
|
|
17
|
-
Set env variable C{PYGEODESY_FSUM_PARTIALS} to
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
and L{Fsum.__itruediv__}.
|
|
17
|
+
Set env variable C{PYGEODESY_FSUM_PARTIALS} to string C{"fsum"}) for summation
|
|
18
|
+
of L{Fsum} partials by Python function C{math.fsum}.
|
|
19
|
+
|
|
20
|
+
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
|
|
@@ -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.09'
|
|
50
49
|
|
|
51
50
|
_add_op_ = _PLUS_ # in .auxilats.auxAngle
|
|
52
51
|
_eq_op_ = _EQUAL_ * 2 # _DEQUAL_
|
|
@@ -72,84 +71,125 @@ _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.fsum2f_}.
|
|
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
|
-
|
|
83
|
-
raise
|
|
84
|
-
|
|
85
|
-
raise _xError(e, Fmt.INDEX(n, index), v)
|
|
96
|
+
return v if _isfinite(v) else _2error(v)
|
|
97
|
+
except Exception as X:
|
|
98
|
+
raise _xError(X, Fmt.INDEX(n, index), v)
|
|
99
|
+
|
|
86
100
|
|
|
101
|
+
def _X_ps(X): # for _2floats only
|
|
102
|
+
return X._ps
|
|
87
103
|
|
|
88
|
-
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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)
|
|
100
122
|
|
|
101
|
-
_x = float
|
|
102
123
|
|
|
103
|
-
|
|
124
|
+
def _2halfeven(s, r, p):
|
|
125
|
+
'''(INTERNAL) Round half-even.
|
|
126
|
+
'''
|
|
127
|
+
if (p > 0 and r > 0) or \
|
|
128
|
+
(p < 0 and r < 0): # signs match
|
|
129
|
+
r *= 2
|
|
130
|
+
t = s + r
|
|
131
|
+
if r == (t - s):
|
|
132
|
+
s = t
|
|
133
|
+
return s
|
|
104
134
|
|
|
105
135
|
|
|
106
136
|
def _1primed(xs): # in .fmath
|
|
107
|
-
'''(INTERNAL) 1-
|
|
108
|
-
|
|
137
|
+
'''(INTERNAL) 1-Primed summation of iterable C{xs}
|
|
138
|
+
items, all I{known} to be C{finite float}.
|
|
109
139
|
'''
|
|
110
140
|
yield _1_0
|
|
111
141
|
for x in xs:
|
|
112
|
-
|
|
113
|
-
yield x
|
|
142
|
+
yield x
|
|
114
143
|
yield _N_1_0
|
|
115
144
|
|
|
116
145
|
|
|
117
146
|
def _2ps(s, r):
|
|
118
147
|
'''(INTERNAL) Return a C{s} and C{r} pair, I{ps-ordered}.
|
|
119
148
|
'''
|
|
120
|
-
if fabs(s) < fabs(r)
|
|
121
|
-
s, r = r, s
|
|
122
|
-
return ((r, s) if s else (r,)) if r else (s,)
|
|
149
|
+
return (s, r) if fabs(s) < fabs(r) else (r, s)
|
|
123
150
|
|
|
124
151
|
|
|
125
152
|
def _psum(ps): # PYCHOK used!
|
|
126
|
-
'''(INTERNAL) Partials
|
|
153
|
+
'''(INTERNAL) Partials sum, updating C{ps}, I{overridden below}.
|
|
127
154
|
'''
|
|
128
155
|
# assert isinstance(ps, list)
|
|
129
|
-
i
|
|
130
|
-
if i < 0
|
|
131
|
-
return _0_0
|
|
132
|
-
s = ps[i]
|
|
156
|
+
i = len(ps) - 1
|
|
157
|
+
s = _0_0 if i < 0 else ps[i]
|
|
133
158
|
_2s = _2sum
|
|
134
159
|
while i > 0:
|
|
135
160
|
i -= 1
|
|
136
161
|
s, r = _2s(s, ps[i])
|
|
137
162
|
if r: # sum(ps) became inexact
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
t = s + r
|
|
145
|
-
if r == (t - s):
|
|
146
|
-
s = t
|
|
147
|
-
break
|
|
163
|
+
if s:
|
|
164
|
+
ps[i:] = r, s
|
|
165
|
+
if i > 0:
|
|
166
|
+
s = _2halfeven(s, r, ps[i-1])
|
|
167
|
+
break # return s
|
|
168
|
+
s = r # PYCHOK no cover
|
|
148
169
|
ps[i:] = s,
|
|
149
170
|
return s
|
|
150
171
|
|
|
151
172
|
|
|
152
|
-
def
|
|
173
|
+
def _Psum(ps, **name):
|
|
174
|
+
'''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
|
|
175
|
+
'''
|
|
176
|
+
f = Fsum(**name) if name else Fsum()
|
|
177
|
+
if ps:
|
|
178
|
+
f._ps[:] = ps
|
|
179
|
+
f._n = len(f._ps)
|
|
180
|
+
return f
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _Psum_1(p=_1_0, **name):
|
|
184
|
+
'''(INTERNAL) Return an C{Fsum} from a single partial C{p}.
|
|
185
|
+
'''
|
|
186
|
+
f = Fsum(**name) if name else Fsum()
|
|
187
|
+
f._ps[:] = p,
|
|
188
|
+
f._n = 1 # len(f._ps)
|
|
189
|
+
return f
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _2scalar(other, _raiser=None, **mod):
|
|
153
193
|
'''(INTERNAL) Return B{C{other}} as C{int}, C{float} or C{as-is}.
|
|
154
194
|
'''
|
|
155
195
|
if isinstance(other, Fsum):
|
|
@@ -158,7 +198,8 @@ def _2scalar(other, _raiser=None):
|
|
|
158
198
|
s, r = other._fprs2
|
|
159
199
|
if r: # PYCHOK no cover
|
|
160
200
|
if _raiser and _raiser(r, s):
|
|
161
|
-
|
|
201
|
+
t = _stresidual(_non_zero_, r, **mod)
|
|
202
|
+
raise ResidualError(t, txt=None)
|
|
162
203
|
s = other # L{Fsum} as-is
|
|
163
204
|
else:
|
|
164
205
|
s = other # C{type} as-is
|
|
@@ -168,24 +209,24 @@ def _2scalar(other, _raiser=None):
|
|
|
168
209
|
|
|
169
210
|
|
|
170
211
|
def _strcomplex(s, *args):
|
|
171
|
-
'''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error C{str}.
|
|
212
|
+
'''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
|
|
172
213
|
'''
|
|
173
|
-
c =
|
|
214
|
+
c = _strcomplex.__name__[4:]
|
|
174
215
|
n = _DASH_(len(args), _arg_)
|
|
175
|
-
t =
|
|
176
|
-
return
|
|
216
|
+
t = unstr(pow, *args)
|
|
217
|
+
return _SPACE_(c, s, _from_, n, t)
|
|
177
218
|
|
|
178
219
|
|
|
179
220
|
def _stresidual(prefix, residual, **name_values):
|
|
180
|
-
'''(INTERNAL) Residual error C{str}.
|
|
221
|
+
'''(INTERNAL) Residual error as C{str}.
|
|
181
222
|
'''
|
|
182
|
-
p =
|
|
223
|
+
p = _stresidual.__name__[3:]
|
|
183
224
|
t = Fmt.PARENSPACED(p, Fmt(residual))
|
|
184
225
|
for n, v in itemsorted(name_values):
|
|
185
226
|
n = n.replace(_UNDER_, _SPACE_)
|
|
186
227
|
p = Fmt.PARENSPACED(n, Fmt(v))
|
|
187
228
|
t = _COMMASPACE_(t, p)
|
|
188
|
-
return t
|
|
229
|
+
return _SPACE_(prefix, t)
|
|
189
230
|
|
|
190
231
|
|
|
191
232
|
def _2sum(a, b): # by .testFmath
|
|
@@ -193,7 +234,7 @@ def _2sum(a, b): # by .testFmath
|
|
|
193
234
|
'''
|
|
194
235
|
s = a + b
|
|
195
236
|
if not _isfinite(s):
|
|
196
|
-
u = unstr(_2sum
|
|
237
|
+
u = unstr(_2sum, a, b)
|
|
197
238
|
t = Fmt.PARENSPACED(_not_finite_, s)
|
|
198
239
|
raise _OverflowError(u, txt=t)
|
|
199
240
|
if fabs(a) < fabs(b):
|
|
@@ -201,28 +242,6 @@ def _2sum(a, b): # by .testFmath
|
|
|
201
242
|
return s, (b - (s - a))
|
|
202
243
|
|
|
203
244
|
|
|
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
|
-
|
|
226
245
|
class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
227
246
|
'''Precision floating point summation and I{running} summation.
|
|
228
247
|
|
|
@@ -246,8 +265,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
246
265
|
_math_fsum = None
|
|
247
266
|
_n = 0
|
|
248
267
|
# _ps = [] # partial sums
|
|
249
|
-
#
|
|
268
|
+
# _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps))
|
|
250
269
|
_ratio = None
|
|
270
|
+
_recursive = bool(_getenv('PYGEODESY_FSUM_RECURSIVE', NN))
|
|
251
271
|
_RESIDUAL = max(float(_getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)), _0_0)
|
|
252
272
|
|
|
253
273
|
def __init__(self, *xs, **name_RESIDUAL):
|
|
@@ -267,13 +287,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
267
287
|
r = _xkwds_get(name_RESIDUAL, RESIDUAL=None)
|
|
268
288
|
if r is not None:
|
|
269
289
|
self.RESIDUAL(r) # ... ResidualError
|
|
270
|
-
# self._n = 0
|
|
271
290
|
self._ps = [] # [_0_0], see L{Fsum._fprs}
|
|
272
|
-
if
|
|
273
|
-
self.
|
|
274
|
-
elif xs: # len(xs) == 1
|
|
275
|
-
self._n = 1
|
|
276
|
-
self._ps[:] = _2float(x=xs[0]),
|
|
291
|
+
if xs:
|
|
292
|
+
self._facc_any(xs, origin=1, up=False)
|
|
277
293
|
|
|
278
294
|
def __abs__(self):
|
|
279
295
|
'''Return this instance' absolute value as an L{Fsum}.
|
|
@@ -282,7 +298,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
282
298
|
return (-self) if s < 0 else self._copy_2(self.__abs__)
|
|
283
299
|
|
|
284
300
|
def __add__(self, other):
|
|
285
|
-
'''Return
|
|
301
|
+
'''Return C{B{self} + B{other}} as an L{Fsum}.
|
|
286
302
|
|
|
287
303
|
@arg other: An L{Fsum} or C{scalar}.
|
|
288
304
|
|
|
@@ -338,7 +354,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
338
354
|
return self._cmp_0(other, _eq_op_) == 0
|
|
339
355
|
|
|
340
356
|
def __float__(self):
|
|
341
|
-
'''Return this instance' current precision running sum as C{float}.
|
|
357
|
+
'''Return this instance' current, precision running sum as C{float}.
|
|
342
358
|
|
|
343
359
|
@see: Methods L{Fsum.fsum} and L{Fsum.int_float}.
|
|
344
360
|
'''
|
|
@@ -654,8 +670,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
654
670
|
@arg ndigits: Optional number of digits (C{int}).
|
|
655
671
|
'''
|
|
656
672
|
# <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
|
|
657
|
-
return
|
|
658
|
-
|
|
673
|
+
return _Psum_1(round(float(self), *ndigits), # can be C{int}
|
|
674
|
+
name=self.__round__.__name__)
|
|
659
675
|
|
|
660
676
|
def __rpow__(self, other, *mod):
|
|
661
677
|
'''Return C{B{other}**B{self}} as an L{Fsum}.
|
|
@@ -756,14 +772,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
756
772
|
def _cmp_0(self, other, op):
|
|
757
773
|
'''(INTERNAL) Return C{scalar(self - B{other})} for 0-comparison.
|
|
758
774
|
'''
|
|
759
|
-
if
|
|
775
|
+
if isinstance(other, Fsum):
|
|
776
|
+
s = _fsum(self._ps_1(*other._ps))
|
|
777
|
+
elif isscalar(other):
|
|
760
778
|
if other:
|
|
761
779
|
s = _fsum(self._ps_1(other))
|
|
762
780
|
else:
|
|
763
781
|
s, r = self._fprs2
|
|
764
782
|
s = _signOf(s, -r)
|
|
765
|
-
elif isinstance(other, Fsum):
|
|
766
|
-
s = _fsum(self._ps_1(*other._ps))
|
|
767
783
|
else:
|
|
768
784
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
769
785
|
return s
|
|
@@ -774,8 +790,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
774
790
|
@return: The copy (L{Fsum}).
|
|
775
791
|
'''
|
|
776
792
|
f = _Named.copy(self, deep=deep, name=name)
|
|
777
|
-
f._n = self._n if deep else 1
|
|
778
793
|
f._ps = list(self._ps) # separate list
|
|
794
|
+
f._n = self._n if deep else 1
|
|
779
795
|
return f
|
|
780
796
|
|
|
781
797
|
def _copy_2(self, which, name=NN):
|
|
@@ -816,77 +832,85 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
816
832
|
f = self._copy_2(self.divmod)
|
|
817
833
|
return f._fdivmod2(other, _divmod_op_)
|
|
818
834
|
|
|
819
|
-
def _Error(self, op, other, Error, **
|
|
835
|
+
def _Error(self, op, other, Error, **txt_cause):
|
|
820
836
|
'''(INTERNAL) Format an B{C{Error}} for C{{self} B{op} B{other}}.
|
|
821
837
|
'''
|
|
822
|
-
return Error(_SPACE_(self.
|
|
838
|
+
return Error(_SPACE_(self.toStr(), op, other), **txt_cause)
|
|
839
|
+
|
|
840
|
+
def _ErrorX(self, X, op, other, *mod):
|
|
841
|
+
'''(INTERNAL) Format the caught exception C{X}.
|
|
842
|
+
'''
|
|
843
|
+
E, t = _xError2(X)
|
|
844
|
+
if mod:
|
|
845
|
+
t = _COMMASPACE_(Fmt.PARENSPACED(mod=mod[0]), t)
|
|
846
|
+
return self._Error(op, other, E, txt=t, cause=X)
|
|
823
847
|
|
|
824
|
-
def
|
|
825
|
-
'''(INTERNAL) Format
|
|
848
|
+
def _ErrorXs(self, X, xs, **kwds): # in .fmath
|
|
849
|
+
'''(INTERNAL) Format the caught exception C{X}.
|
|
826
850
|
'''
|
|
827
851
|
E, t = _xError2(X)
|
|
828
852
|
n = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
|
|
829
853
|
return E(n, txt=t, cause=X)
|
|
830
854
|
|
|
831
|
-
def _facc(self, xs, up
|
|
832
|
-
'''(INTERNAL) Accumulate
|
|
833
|
-
'''
|
|
834
|
-
|
|
835
|
-
for x in xs: # _iter()
|
|
836
|
-
# assert isscalar(x) and isfinite(x)
|
|
837
|
-
i = 0
|
|
838
|
-
for p in ps:
|
|
839
|
-
x, p = _2s(x, p)
|
|
840
|
-
if p:
|
|
841
|
-
ps[i] = p
|
|
842
|
-
i += 1
|
|
843
|
-
ps[i:] = x,
|
|
844
|
-
n += 1
|
|
845
|
-
# assert self._ps is ps
|
|
846
|
-
if n:
|
|
847
|
-
self._n += n
|
|
848
|
-
# Fsum._px = max(Fsum._px, len(ps))
|
|
849
|
-
if up:
|
|
850
|
-
self._update()
|
|
855
|
+
def _facc(self, xs, **up):
|
|
856
|
+
'''(INTERNAL) Accumulate all C{xs}, known to be scalar.
|
|
857
|
+
'''
|
|
858
|
+
self._ps_acc(self._ps, xs, **up)
|
|
851
859
|
return self
|
|
852
860
|
|
|
853
861
|
def _facc_(self, *xs, **up):
|
|
854
|
-
'''(INTERNAL) Accumulate all positional C{scalar
|
|
862
|
+
'''(INTERNAL) Accumulate all positional C{xs}, known to be scalar.
|
|
863
|
+
'''
|
|
864
|
+
if xs:
|
|
865
|
+
self._ps_acc(self._ps, xs, **up)
|
|
866
|
+
return self
|
|
867
|
+
|
|
868
|
+
def _facc_any(self, xs, up=True, **origin_X_x):
|
|
869
|
+
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s.
|
|
855
870
|
'''
|
|
856
|
-
|
|
871
|
+
self._ps[:] = self._ps_acc(list(self._ps),
|
|
872
|
+
_2floats(xs, **origin_X_x), up=up) # PYCHOK yield
|
|
873
|
+
return self
|
|
874
|
+
|
|
875
|
+
def _facc_any_neg(self, xs, up=True, **origin):
|
|
876
|
+
'''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s, negated.
|
|
877
|
+
'''
|
|
878
|
+
def _neg(x):
|
|
879
|
+
return -x
|
|
880
|
+
|
|
881
|
+
self._ps[:] = self._ps_acc(list(self._ps), map(_neg,
|
|
882
|
+
_2floats(xs, **origin)), up=up) # PYCHOK yield
|
|
883
|
+
return self
|
|
857
884
|
|
|
858
885
|
def _facc_power(self, power, xs, which): # in .fmath
|
|
859
886
|
'''(INTERNAL) Add each C{xs} as C{float(x**power)}.
|
|
860
887
|
'''
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
888
|
+
p = power
|
|
889
|
+
if isinstance(p, Fsum):
|
|
890
|
+
if p.is_exact:
|
|
891
|
+
return self._facc_power(p._fprs, xs, which)
|
|
864
892
|
_Pow = Fsum._pow_any
|
|
865
|
-
elif isint(
|
|
866
|
-
_Pow = Fsum._pow_int
|
|
867
|
-
power = int(power)
|
|
893
|
+
elif isint(p, both=True) and p >= 0:
|
|
894
|
+
_Pow, p = Fsum._pow_int, int(p)
|
|
868
895
|
else:
|
|
869
|
-
_Pow = Fsum._pow_scalar
|
|
870
|
-
power = _2float(power=power)
|
|
896
|
+
_Pow, p = Fsum._pow_scalar, _2float(power=p)
|
|
871
897
|
|
|
872
|
-
if
|
|
898
|
+
if p:
|
|
873
899
|
from math import pow as _pow
|
|
874
|
-
op
|
|
900
|
+
op = which.__name__
|
|
901
|
+
_Fs = Fsum
|
|
875
902
|
|
|
876
903
|
def _X(X):
|
|
877
|
-
f = _Pow(X,
|
|
878
|
-
|
|
879
|
-
return f._ps
|
|
880
|
-
except AttributeError: # scalar
|
|
881
|
-
return f,
|
|
904
|
+
f = _Pow(X, p, power, op)
|
|
905
|
+
return f._ps if isinstance(f, _Fs) else (f,)
|
|
882
906
|
|
|
883
907
|
def _x(x):
|
|
884
|
-
return _pow(float(x),
|
|
908
|
+
return _pow(float(x), p)
|
|
885
909
|
|
|
886
|
-
self.
|
|
910
|
+
f = self._facc_any(xs, origin=1, _X=_X, _x=_x)
|
|
887
911
|
else:
|
|
888
|
-
self._facc_(float(len(xs))) # x**0 == 1
|
|
889
|
-
return
|
|
912
|
+
f = self._facc_(float(len(xs))) # x**0 == 1
|
|
913
|
+
return f
|
|
890
914
|
|
|
891
915
|
# def _facc_up(self, up=True):
|
|
892
916
|
# '''(INTERNAL) Update the C{partials}, by removing
|
|
@@ -918,11 +942,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
918
942
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
919
943
|
'''
|
|
920
944
|
if isinstance(xs, Fsum):
|
|
921
|
-
self._facc(xs._ps)
|
|
945
|
+
self._facc(xs._ps) # tuple
|
|
922
946
|
elif isscalar(xs): # for backward compatibility
|
|
923
947
|
self._facc_(_2float(x=xs)) # PYCHOK no cover
|
|
924
948
|
elif xs:
|
|
925
|
-
self.
|
|
949
|
+
self._facc_any(xs)
|
|
926
950
|
return self
|
|
927
951
|
|
|
928
952
|
def fadd_(self, *xs):
|
|
@@ -941,16 +965,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
941
965
|
|
|
942
966
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
943
967
|
'''
|
|
944
|
-
return self.
|
|
968
|
+
return self._facc_any(xs, origin=1)
|
|
945
969
|
|
|
946
970
|
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
947
971
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
948
972
|
'''
|
|
949
973
|
if isinstance(other, Fsum):
|
|
950
|
-
|
|
951
|
-
self._facc_(*other._ps, **up) # == ._facc(tuple(other._ps))
|
|
952
|
-
elif other._ps:
|
|
953
|
-
self._facc(other._ps, **up)
|
|
974
|
+
self._facc(other._ps, **up) # tuple
|
|
954
975
|
elif not isscalar(other):
|
|
955
976
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
956
977
|
elif other:
|
|
@@ -985,14 +1006,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
985
1006
|
'''
|
|
986
1007
|
if _isfinite(other):
|
|
987
1008
|
return other
|
|
988
|
-
raise ValueError(_not_finite_) if
|
|
1009
|
+
raise ValueError(_not_finite_) if op is None else \
|
|
989
1010
|
self._ValueError(op, other, txt=_not_finite_)
|
|
990
1011
|
|
|
991
1012
|
def fint(self, raiser=True, **name):
|
|
992
1013
|
'''Return this instance' current running sum as C{integer}.
|
|
993
1014
|
|
|
994
1015
|
@kwarg raiser: If C{True} throw a L{ResidualError} if the
|
|
995
|
-
I{integer} residual is non-zero.
|
|
1016
|
+
I{integer} residual is non-zero (C{bool}).
|
|
996
1017
|
@kwarg name: Optional name (C{str}), overriding C{"fint"}.
|
|
997
1018
|
|
|
998
1019
|
@return: The C{integer} (L{Fsum}).
|
|
@@ -1027,7 +1048,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1027
1048
|
s, r = self._fprs2
|
|
1028
1049
|
i = int(s)
|
|
1029
1050
|
r = _fsum(self._ps_1(i)) if r else float(s - i)
|
|
1030
|
-
return i, (r or INT0)
|
|
1051
|
+
return i, (r or INT0) # Fsum2Tuple?
|
|
1031
1052
|
|
|
1032
1053
|
@deprecated_property_RO
|
|
1033
1054
|
def float_int(self): # PYCHOK no cover
|
|
@@ -1071,7 +1092,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1071
1092
|
else: # len(other._ps) == len(self._ps) == 1
|
|
1072
1093
|
f = self._finite(self._ps[0] * other._ps[0])
|
|
1073
1094
|
elif isscalar(other):
|
|
1074
|
-
f = self._mul_scalar(other, op)
|
|
1095
|
+
f = self._mul_scalar(other, op) if other != _1_0 else self
|
|
1075
1096
|
else:
|
|
1076
1097
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
1077
1098
|
return self._fset(f) # n=len(self) + 1
|
|
@@ -1094,13 +1115,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1094
1115
|
'''
|
|
1095
1116
|
if mod:
|
|
1096
1117
|
if mod[0] is not None: # == 3-arg C{pow}
|
|
1097
|
-
f = self.
|
|
1118
|
+
f = self._pow_2_3(self, other, other, op, *mod)
|
|
1098
1119
|
elif self.is_integer():
|
|
1099
1120
|
# return an exact C{int} for C{int}**C{int}
|
|
1121
|
+
i, _ = self._fint2 # assert _ == 0
|
|
1100
1122
|
x = _2scalar(other) # C{int}, C{float} or other
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
_Fsum_ps(i)._pow_any(x, other, op)
|
|
1123
|
+
f = self._pow_2_3(i, x, other, op) if isscalar(x) else \
|
|
1124
|
+
_Psum_1(i)._pow_any(x, other, op)
|
|
1104
1125
|
else: # mod[0] is None, power(self, other)
|
|
1105
1126
|
f = self._pow_any(other, other, op)
|
|
1106
1127
|
else: # pow(self, other) == pow(self, other, None)
|
|
@@ -1123,11 +1144,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1123
1144
|
running sum and residual (L{Fsum2Tuple}).
|
|
1124
1145
|
'''
|
|
1125
1146
|
ps = self._ps
|
|
1126
|
-
n = len(ps)
|
|
1127
|
-
if n >
|
|
1147
|
+
n = len(ps) - 2
|
|
1148
|
+
if n > 0: # len(ps) > 2
|
|
1128
1149
|
s = _psum(ps)
|
|
1129
|
-
|
|
1130
|
-
|
|
1150
|
+
n = len(ps) - 2
|
|
1151
|
+
if n > 0:
|
|
1152
|
+
r = _fsum(self._ps_1(s)) or INT0
|
|
1153
|
+
return Fsum2Tuple(s, r)
|
|
1154
|
+
if n == 0: # len(ps) == 2
|
|
1131
1155
|
ps[:] = _2ps(*_2sum(*ps))
|
|
1132
1156
|
r, s = (INT0, ps[0]) if len(ps) != 2 else ps
|
|
1133
1157
|
elif ps: # len(ps) == 1
|
|
@@ -1142,17 +1166,31 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1142
1166
|
# '''(INTERNAL) Compress, squeeze the C{partials}.
|
|
1143
1167
|
# '''
|
|
1144
1168
|
# if len(self._ps) > 2:
|
|
1145
|
-
# _ = self.
|
|
1169
|
+
# _ = self._fprs2
|
|
1146
1170
|
# return self
|
|
1147
1171
|
|
|
1172
|
+
def fset_(self, *xs):
|
|
1173
|
+
'''Replace this instance' value with C{xs}.
|
|
1174
|
+
|
|
1175
|
+
@arg xs: Optional, new values (C{scalar} or L{Fsum}
|
|
1176
|
+
instances), all positional.
|
|
1177
|
+
|
|
1178
|
+
@return: This instance (C{Fsum}).
|
|
1179
|
+
|
|
1180
|
+
@see: Method L{Fsum.fadd} for further details.
|
|
1181
|
+
'''
|
|
1182
|
+
self._ps[:] = 0,
|
|
1183
|
+
self._n = 0
|
|
1184
|
+
return self.fadd(xs) if xs else self._update()
|
|
1185
|
+
|
|
1148
1186
|
def _fset(self, other, asis=True, n=0):
|
|
1149
1187
|
'''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
|
|
1150
1188
|
'''
|
|
1151
1189
|
if other is self:
|
|
1152
1190
|
pass # from ._fmul, ._ftruediv and ._pow_scalar
|
|
1153
1191
|
elif isinstance(other, Fsum):
|
|
1154
|
-
self._n = n or other._n
|
|
1155
1192
|
self._ps[:] = other._ps
|
|
1193
|
+
self._n = n or other._n
|
|
1156
1194
|
# self._copy_RESIDUAL(other)
|
|
1157
1195
|
# use or zap the C{Property_RO} values
|
|
1158
1196
|
Fsum._fint2._update_from(self, other)
|
|
@@ -1162,8 +1200,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1162
1200
|
s = other if asis else float(other)
|
|
1163
1201
|
i = int(s) # see ._fint2
|
|
1164
1202
|
t = i, ((s - i) or INT0)
|
|
1165
|
-
self._n = n or 1
|
|
1166
1203
|
self._ps[:] = s,
|
|
1204
|
+
self._n = n or 1
|
|
1167
1205
|
# Property_ROs _fint2, _fprs and _fprs2 can't be a Property:
|
|
1168
1206
|
# Property's _fset zaps the value just set by the @setter
|
|
1169
1207
|
self.__dict__.update(_fint2=t, _fprs=s, _fprs2=Fsum2Tuple(s, INT0))
|
|
@@ -1172,14 +1210,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1172
1210
|
return self
|
|
1173
1211
|
|
|
1174
1212
|
def _fset_ps(self, other, n=0): # in .fmath
|
|
1175
|
-
'''(INTERNAL) Set a known C{Fsum} or C{scalar}.
|
|
1213
|
+
'''(INTERNAL) Set partials from a known C{Fsum} or C{scalar}.
|
|
1176
1214
|
'''
|
|
1177
1215
|
if isinstance(other, Fsum):
|
|
1178
|
-
self._n = n or other._n
|
|
1179
1216
|
self._ps[:] = other._ps
|
|
1217
|
+
self._n = n or other._n
|
|
1180
1218
|
else: # assert isscalar(other)
|
|
1181
|
-
self._n = n or 1
|
|
1182
1219
|
self._ps[:] = other,
|
|
1220
|
+
self._n = n or 1
|
|
1221
|
+
return self
|
|
1183
1222
|
|
|
1184
1223
|
def fsub(self, xs=()):
|
|
1185
1224
|
'''Subtract an iterable of C{scalar} or L{Fsum} instances from
|
|
@@ -1192,7 +1231,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1192
1231
|
|
|
1193
1232
|
@see: Method L{Fsum.fadd}.
|
|
1194
1233
|
'''
|
|
1195
|
-
return self.
|
|
1234
|
+
return self._facc_any_neg(xs) if xs else self
|
|
1196
1235
|
|
|
1197
1236
|
def fsub_(self, *xs):
|
|
1198
1237
|
'''Subtract all positional C{scalar} or L{Fsum} instances from
|
|
@@ -1205,7 +1244,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1205
1244
|
|
|
1206
1245
|
@see: Method L{Fsum.fadd}.
|
|
1207
1246
|
'''
|
|
1208
|
-
return self.
|
|
1247
|
+
return self._facc_any_neg(xs, origin=1) if xs else self
|
|
1209
1248
|
|
|
1210
1249
|
def _fsub(self, other, op):
|
|
1211
1250
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
@@ -1233,23 +1272,30 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1233
1272
|
|
|
1234
1273
|
@note: Accumulation can continue after summation.
|
|
1235
1274
|
'''
|
|
1236
|
-
f = self.
|
|
1275
|
+
f = self._facc_any(xs) if xs else self
|
|
1237
1276
|
return f._fprs
|
|
1238
1277
|
|
|
1239
1278
|
def fsum_(self, *xs):
|
|
1240
1279
|
'''Add all positional C{scalar} or L{Fsum} instances and summate.
|
|
1241
1280
|
|
|
1242
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1243
|
-
|
|
1281
|
+
@arg xs: Values to add (C{scalar} or L{Fsum} instances), all
|
|
1282
|
+
positional.
|
|
1244
1283
|
|
|
1245
1284
|
@return: Precision running sum (C{float} or C{int}).
|
|
1246
1285
|
|
|
1247
|
-
@see: Methods L{Fsum.fsum} and L{Fsum.fsumf_}.
|
|
1286
|
+
@see: Methods L{Fsum.fsum}, L{Fsum.Fsum_} and L{Fsum.fsumf_}.
|
|
1248
1287
|
'''
|
|
1249
|
-
f = self.
|
|
1288
|
+
f = self._facc_any(xs, origin=1) if xs else self
|
|
1250
1289
|
return f._fprs
|
|
1251
1290
|
|
|
1252
|
-
def
|
|
1291
|
+
def Fsum_(self, *xs):
|
|
1292
|
+
'''Like method L{Fsum.fsum_} but returning an L{Fsum}.
|
|
1293
|
+
|
|
1294
|
+
@return: Current, precision running sum (L{Fsum}).
|
|
1295
|
+
'''
|
|
1296
|
+
return self._facc_any(xs, origin=1)._copy_2(self.Fsum_)
|
|
1297
|
+
|
|
1298
|
+
def fsum2(self, xs=(), name=NN):
|
|
1253
1299
|
'''Add more C{scalar} or L{Fsum} instances and return the
|
|
1254
1300
|
current precision running sum and the C{residual}.
|
|
1255
1301
|
|
|
@@ -1265,57 +1311,70 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1265
1311
|
|
|
1266
1312
|
@see: Methods L{Fsum.fint2}, L{Fsum.fsum} and L{Fsum.fsum2_}
|
|
1267
1313
|
'''
|
|
1268
|
-
f = self.
|
|
1314
|
+
f = self._facc_any(xs) if xs else self
|
|
1269
1315
|
t = f._fprs2
|
|
1270
1316
|
if name:
|
|
1271
|
-
|
|
1272
|
-
if n:
|
|
1273
|
-
t = t.dup(name=n)
|
|
1317
|
+
t = t.dup(name=name)
|
|
1274
1318
|
return t
|
|
1275
1319
|
|
|
1276
1320
|
def fsum2_(self, *xs):
|
|
1277
1321
|
'''Add any positional C{scalar} or L{Fsum} instances and return
|
|
1278
1322
|
the precision running sum and the C{differential}.
|
|
1279
1323
|
|
|
1280
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1281
|
-
|
|
1324
|
+
@arg xs: Values to add (C{scalar} or L{Fsum} instances), all
|
|
1325
|
+
positional.
|
|
1282
1326
|
|
|
1283
|
-
@return:
|
|
1284
|
-
running C{fsum} and C{delta},
|
|
1285
|
-
the previous running C{fsum}
|
|
1327
|
+
@return: 2Tuple C{(fsum, delta)} with the current, precision
|
|
1328
|
+
running C{fsum} like method L{Fsum.fsum} and C{delta},
|
|
1329
|
+
the difference with previous running C{fsum}, C{float}.
|
|
1286
1330
|
|
|
1287
1331
|
@see: Methods L{Fsum.fsum_} and L{Fsum.fsum}.
|
|
1288
1332
|
'''
|
|
1289
|
-
|
|
1290
|
-
if xs:
|
|
1291
|
-
s, t = self._facc(_2floats(xs, origin=1))._fprs2 # PYCHOK yield
|
|
1292
|
-
return s, _fsum((s, -p, r, -t)) # ((s - p) + (r - t))
|
|
1293
|
-
else: # PYCHOK no cover
|
|
1294
|
-
return p, _0_0
|
|
1333
|
+
return self._fsum2f_any(xs, self._facc_any, origin=1)
|
|
1295
1334
|
|
|
1296
1335
|
def fsumf_(self, *xs):
|
|
1297
|
-
'''Like method L{Fsum.fsum_} but only for known C{float B{xs}}.
|
|
1336
|
+
'''Like method L{Fsum.fsum_} but only for I{known} C{float B{xs}}.
|
|
1298
1337
|
'''
|
|
1299
|
-
f = self._facc(xs) if xs else self
|
|
1338
|
+
f = self._facc(xs) if xs else self
|
|
1300
1339
|
return f._fprs
|
|
1301
1340
|
|
|
1302
|
-
|
|
1341
|
+
def Fsumf_(self, *xs):
|
|
1342
|
+
'''Like method L{Fsum.Fsum_} but only for I{known} C{float B{xs}}.
|
|
1343
|
+
'''
|
|
1344
|
+
return self._facc(xs)._copy_2(self.Fsumf_)
|
|
1345
|
+
|
|
1346
|
+
def fsum2f_(self, *xs):
|
|
1347
|
+
'''Like method L{Fsum.fsum2_} but only for I{known} C{float B{xs}}.
|
|
1348
|
+
'''
|
|
1349
|
+
return self._fsum2f_any(xs, self._facc)
|
|
1350
|
+
|
|
1351
|
+
def _fsum2f_any(self, xs, _facc, **origin):
|
|
1352
|
+
'''(INTERNAL) Helper for L{Fsum.fsum2_} and L{Fsum.fsum2f_}.
|
|
1353
|
+
'''
|
|
1354
|
+
p, q = self._fprs2
|
|
1355
|
+
if xs:
|
|
1356
|
+
s, r = _facc(xs, **origin)._fprs2
|
|
1357
|
+
return s, _2delta(s - p, r - q) # _fsum(_1primed((s, -p, r, -q))
|
|
1358
|
+
else:
|
|
1359
|
+
return p, _0_0
|
|
1360
|
+
|
|
1361
|
+
# ftruediv = __itruediv__ # for naming consistency?
|
|
1303
1362
|
|
|
1304
1363
|
def _ftruediv(self, other, op):
|
|
1305
1364
|
'''(INTERNAL) Apply C{B{self} /= B{other}}.
|
|
1306
1365
|
'''
|
|
1307
1366
|
n = _1_0
|
|
1308
1367
|
if isinstance(other, Fsum):
|
|
1309
|
-
if other is self or other
|
|
1368
|
+
if other is self or other == self:
|
|
1310
1369
|
return self._fset(_1_0) # n=len(self)
|
|
1311
1370
|
d, r = other._fprs2
|
|
1312
1371
|
if r:
|
|
1313
|
-
if
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
raise self._ResidualError(op, other, r)
|
|
1317
|
-
else:
|
|
1372
|
+
if d:
|
|
1373
|
+
if self._raiser(r, d):
|
|
1374
|
+
raise self._ResidualError(op, other, r)
|
|
1318
1375
|
d, n = other.as_integer_ratio()
|
|
1376
|
+
else: # PYCHOK no cover
|
|
1377
|
+
d = r
|
|
1319
1378
|
elif isscalar(other):
|
|
1320
1379
|
d = other
|
|
1321
1380
|
else: # PYCHOK no cover
|
|
@@ -1323,9 +1382,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1323
1382
|
try:
|
|
1324
1383
|
s = 0 if isinf(d) else (
|
|
1325
1384
|
d if isnan(d) else self._finite(n / d))
|
|
1326
|
-
except Exception as
|
|
1327
|
-
|
|
1328
|
-
raise self._Error(op, other, E, txt=t)
|
|
1385
|
+
except Exception as X:
|
|
1386
|
+
raise self._ErrorX(X, op, other)
|
|
1329
1387
|
f = self._mul_scalar(s, _mul_op_) # handles 0, NAN, etc.
|
|
1330
1388
|
return self._fset(f, asis=False)
|
|
1331
1389
|
|
|
@@ -1361,13 +1419,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1361
1419
|
return s
|
|
1362
1420
|
|
|
1363
1421
|
def is_exact(self):
|
|
1364
|
-
'''Is this instance'
|
|
1365
|
-
be exact? (C{bool}).
|
|
1422
|
+
'''Is this instance' running C{fsum} considered to be exact? (C{bool}).
|
|
1366
1423
|
'''
|
|
1367
1424
|
return self.residual is INT0
|
|
1368
1425
|
|
|
1369
1426
|
def is_integer(self):
|
|
1370
|
-
'''Is this instance'
|
|
1427
|
+
'''Is this instance' running sum C{integer}? (C{bool}).
|
|
1371
1428
|
|
|
1372
1429
|
@see: Methods L{Fsum.fint} and L{Fsum.fint2}.
|
|
1373
1430
|
'''
|
|
@@ -1393,7 +1450,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1393
1450
|
'''
|
|
1394
1451
|
# assert isinstance(other, Fsum)
|
|
1395
1452
|
if self._ps and other._ps:
|
|
1396
|
-
f =
|
|
1453
|
+
f = self._ps_mul(op, *other._ps) # NO ._2scalar
|
|
1397
1454
|
else:
|
|
1398
1455
|
f = _0_0
|
|
1399
1456
|
return f
|
|
@@ -1405,20 +1462,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1405
1462
|
if self._ps and self._finite(factor, op):
|
|
1406
1463
|
f = self if factor == _1_0 else (
|
|
1407
1464
|
self._neg if factor == _N_1_0 else
|
|
1408
|
-
|
|
1465
|
+
self._ps_mul(op, factor)._2scalar)
|
|
1409
1466
|
else:
|
|
1410
1467
|
f = _0_0
|
|
1411
1468
|
return f
|
|
1412
1469
|
|
|
1413
1470
|
@property_RO
|
|
1414
1471
|
def _neg(self):
|
|
1415
|
-
'''(INTERNAL) Return C{-self}.
|
|
1472
|
+
'''(INTERNAL) Return C{Fsum(-self)} or scalar C{NEG0}.
|
|
1416
1473
|
'''
|
|
1417
|
-
return
|
|
1474
|
+
return _Psum(self._ps_neg) if self._ps else NEG0
|
|
1418
1475
|
|
|
1419
1476
|
@property_RO
|
|
1420
1477
|
def partials(self):
|
|
1421
|
-
'''Get this instance' current partial sums (C{tuple} of C{float}s
|
|
1478
|
+
'''Get this instance' current, partial sums (C{tuple} of C{float}s).
|
|
1422
1479
|
'''
|
|
1423
1480
|
return tuple(self._ps)
|
|
1424
1481
|
|
|
@@ -1434,7 +1491,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1434
1491
|
|
|
1435
1492
|
@note: If B{C{mod}} is given as C{None}, the result will be an
|
|
1436
1493
|
C{integer} L{Fsum} provided this instance C{is_integer}
|
|
1437
|
-
or set to C{integer}
|
|
1494
|
+
or set to C{integer} by an L{Fsum.fint} call.
|
|
1438
1495
|
|
|
1439
1496
|
@see: Methods L{Fsum.__ipow__}, L{Fsum.fint} and L{Fsum.is_integer}.
|
|
1440
1497
|
'''
|
|
@@ -1444,54 +1501,39 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1444
1501
|
def _pow_0_1(self, x, other):
|
|
1445
1502
|
'''(INTERNAL) Return B{C{self}**1} or C{B{self}**0 == 1.0}.
|
|
1446
1503
|
'''
|
|
1447
|
-
return self if x else (1 if
|
|
1448
|
-
|
|
1449
|
-
def
|
|
1450
|
-
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
try:
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
'''(INTERNAL) 3-arg C{pow(B{self}, B{other}, int B{mod} or C{None})}.
|
|
1465
|
-
'''
|
|
1466
|
-
b, r = self._fprs2 if mod is None else self._fint2
|
|
1467
|
-
if r and self._raiser(r, b):
|
|
1468
|
-
t = _non_zero_ if mod is None else _integer_
|
|
1469
|
-
E, t = ResidualError, _stresidual(t, r, mod=mod)
|
|
1470
|
-
else:
|
|
1471
|
-
try: # b, other, mod all C{int}, unless C{mod} is C{None}
|
|
1472
|
-
x = _2scalar(other, _raiser=self._raiser)
|
|
1473
|
-
s = pow(b, x, mod)
|
|
1474
|
-
if not iscomplex(s):
|
|
1475
|
-
return self._finite(s)
|
|
1504
|
+
return self if x else (1 if isint(other) and self.is_integer() else _1_0)
|
|
1505
|
+
|
|
1506
|
+
def _pow_2_3(self, b, x, other, op, *mod):
|
|
1507
|
+
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} and 3-arg C{pow(B{b},
|
|
1508
|
+
B{x}, int B{mod} or C{None})}, embellishing errors.
|
|
1509
|
+
'''
|
|
1510
|
+
try:
|
|
1511
|
+
if mod: # b, x, mod all C{int}, unless C{mod} is C{None}
|
|
1512
|
+
m = mod[0]
|
|
1513
|
+
b, r = b._fprs2 if m is None else b._fint2
|
|
1514
|
+
if r and self._raiser(r, b):
|
|
1515
|
+
t = _non_zero_ if m is None else _integer_
|
|
1516
|
+
raise ResidualError(_stresidual(t, r, mod=m), txt=None)
|
|
1517
|
+
x = _2scalar(x, _raiser=self._raiser, mod=m)
|
|
1518
|
+
# 0**INF == 0.0, 1**INF == 1.0, -1**2.3 == -(1**2.3)
|
|
1519
|
+
s = pow(b, x, *mod)
|
|
1520
|
+
if iscomplex(s):
|
|
1476
1521
|
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
raise self._Error(op, other, E, txt=t)
|
|
1522
|
+
raise ValueError(_strcomplex(s, b, x, *mod))
|
|
1523
|
+
return self._finite(s)
|
|
1524
|
+
except Exception as X:
|
|
1525
|
+
raise self._ErrorX(X, op, other, *mod)
|
|
1482
1526
|
|
|
1483
1527
|
def _pow_any(self, other, unused, op):
|
|
1484
1528
|
'''Return C{B{self} ** B{other}}.
|
|
1485
1529
|
'''
|
|
1486
1530
|
if isinstance(other, Fsum):
|
|
1487
1531
|
x, r = other._fprs2
|
|
1532
|
+
if r and self._raiser(r, x):
|
|
1533
|
+
raise self._ResidualError(op, other, r)
|
|
1488
1534
|
f = self._pow_scalar(x, other, op)
|
|
1489
1535
|
if r:
|
|
1490
|
-
|
|
1491
|
-
raise self._ResidualError(op, other, r)
|
|
1492
|
-
s = self._pow_scalar(r, other, op)
|
|
1493
|
-
# s = _2scalar(s) # _raiser = None
|
|
1494
|
-
f *= s
|
|
1536
|
+
f *= self._pow_scalar(r, other, op)
|
|
1495
1537
|
elif isscalar(other):
|
|
1496
1538
|
x = self._finite(other, op)
|
|
1497
1539
|
f = self._pow_scalar(x, other, op)
|
|
@@ -1505,32 +1547,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1505
1547
|
# assert isint(x) and x >= 0
|
|
1506
1548
|
ps = self._ps
|
|
1507
1549
|
if len(ps) > 1:
|
|
1508
|
-
|
|
1550
|
+
_mul_Fsum = Fsum._mul_Fsum
|
|
1509
1551
|
if x > 4:
|
|
1510
|
-
m = 1 # single-bit mask
|
|
1511
|
-
if (x & m):
|
|
1512
|
-
x -= m # x ^= m
|
|
1513
|
-
else:
|
|
1514
|
-
f = _Fsum_ps(_1_0)
|
|
1515
1552
|
p = self
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
f
|
|
1553
|
+
f = self if (x & 1) else _Psum_1()
|
|
1554
|
+
m = x >> 1 # // 2
|
|
1555
|
+
while m:
|
|
1556
|
+
p = _mul_Fsum(p, p, op) # p **= 2
|
|
1557
|
+
if (m & 1):
|
|
1558
|
+
f = _mul_Fsum(f, p, op) # f *= p
|
|
1559
|
+
m >>= 1 # //= 2
|
|
1522
1560
|
elif x > 1: # self**2, 3 or 4
|
|
1523
|
-
f =
|
|
1561
|
+
f = _mul_Fsum(self, self, op)
|
|
1524
1562
|
if x > 2: # self**3 or 4
|
|
1525
|
-
p =
|
|
1526
|
-
f =
|
|
1563
|
+
p = self if x < 4 else f
|
|
1564
|
+
f = _mul_Fsum(f, p, op)._2scalar
|
|
1527
1565
|
else: # self**1 or self**0 == 1 or _1_0
|
|
1528
|
-
f =
|
|
1566
|
+
f = self._pow_0_1(x, other)
|
|
1529
1567
|
elif ps: # self._ps[0]**x
|
|
1530
|
-
f = self.
|
|
1568
|
+
f = self._pow_2_3(ps[0], x, other, op)
|
|
1531
1569
|
else: # PYCHOK no cover
|
|
1532
1570
|
# 0**pos_int == 0, but 0**0 == 1
|
|
1533
|
-
f = 0 if x else 1
|
|
1571
|
+
f = 0 if x else 1
|
|
1534
1572
|
return f
|
|
1535
1573
|
|
|
1536
1574
|
def _pow_scalar(self, x, other, op):
|
|
@@ -1548,13 +1586,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1548
1586
|
# assert x < 0 # < -1
|
|
1549
1587
|
s, r = f._fprs2 if isinstance(f, Fsum) else (f, 0)
|
|
1550
1588
|
if r:
|
|
1551
|
-
return
|
|
1589
|
+
return _Psum_1()._ftruediv(f, op)
|
|
1552
1590
|
# use **= -1 for the CPython float_pow
|
|
1553
1591
|
# error if s is zero, and not s = 1 / s
|
|
1554
1592
|
x = -1
|
|
1555
|
-
elif x < 0: # self
|
|
1593
|
+
elif x < 0: # == -1: self**(-1) == 1 / self
|
|
1556
1594
|
if r:
|
|
1557
|
-
return
|
|
1595
|
+
return _Psum_1()._ftruediv(self, op)
|
|
1558
1596
|
else: # self**1 or self**0
|
|
1559
1597
|
return self._pow_0_1(x, other) # self, 1 or 1.0
|
|
1560
1598
|
elif not isscalar(x): # assert ...
|
|
@@ -1564,32 +1602,55 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1564
1602
|
t = _stresidual(_non_zero_, r, fractional_power=x)
|
|
1565
1603
|
raise self._Error(op, other, ResidualError, txt=t)
|
|
1566
1604
|
# assert isscalar(s) and isscalar(x)
|
|
1567
|
-
return self.
|
|
1605
|
+
return self._pow_2_3(s, x, other, op)
|
|
1568
1606
|
|
|
1569
1607
|
def _ps_1(self, *less):
|
|
1570
1608
|
'''(INTERNAL) Yield partials, 1-primed and subtract any C{less}.
|
|
1571
1609
|
'''
|
|
1572
1610
|
yield _1_0
|
|
1573
1611
|
for p in self._ps:
|
|
1574
|
-
|
|
1575
|
-
yield p
|
|
1612
|
+
yield p
|
|
1576
1613
|
for p in less:
|
|
1577
|
-
|
|
1578
|
-
yield -p
|
|
1614
|
+
yield -p
|
|
1579
1615
|
yield _N_1_0
|
|
1580
1616
|
|
|
1581
|
-
def
|
|
1582
|
-
'''(INTERNAL)
|
|
1583
|
-
|
|
1617
|
+
def _ps_acc(self, ps, xs, up=True):
|
|
1618
|
+
'''(INTERNAL) Accumulate all scalar C{xs} into C{ps}.
|
|
1619
|
+
'''
|
|
1620
|
+
n = 0
|
|
1621
|
+
_2s = _2sum
|
|
1622
|
+
for x in (tuple(xs) if xs is ps else xs):
|
|
1623
|
+
# assert isscalar(x) and _isfinite(x)
|
|
1624
|
+
if x:
|
|
1625
|
+
i = 0
|
|
1626
|
+
for p in ps:
|
|
1627
|
+
x, p = _2s(x, p)
|
|
1628
|
+
if p:
|
|
1629
|
+
ps[i] = p
|
|
1630
|
+
i += 1
|
|
1631
|
+
ps[i:] = (x,) if x else ()
|
|
1632
|
+
n += 1
|
|
1633
|
+
if n:
|
|
1634
|
+
self._n += n
|
|
1635
|
+
# Fsum._ps_max = max(Fsum._ps_max, len(ps))
|
|
1636
|
+
if up:
|
|
1637
|
+
self._update()
|
|
1638
|
+
return ps
|
|
1639
|
+
|
|
1640
|
+
def _ps_mul(self, op, *factors):
|
|
1641
|
+
'''(INTERNAL) Multiply this instance' C{partials} with
|
|
1642
|
+
each of the B{C{factors}}, all known to be scalar.
|
|
1584
1643
|
'''
|
|
1585
|
-
ps
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1644
|
+
def _pfs(ps, fs):
|
|
1645
|
+
if len(ps) < len(fs):
|
|
1646
|
+
ps, fs = fs, ps
|
|
1647
|
+
_fin = _isfinite
|
|
1648
|
+
for f in fs:
|
|
1649
|
+
for p in ps:
|
|
1650
|
+
p *= f
|
|
1651
|
+
yield p if _fin(p) else self._finite(p, op)
|
|
1652
|
+
|
|
1653
|
+
return _Psum(self._ps_acc([], _pfs(self._ps, factors)))
|
|
1593
1654
|
|
|
1594
1655
|
@property_RO
|
|
1595
1656
|
def _ps_neg(self):
|
|
@@ -1598,6 +1659,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1598
1659
|
for p in self._ps:
|
|
1599
1660
|
yield -p
|
|
1600
1661
|
|
|
1662
|
+
def _raiser(self, r, s):
|
|
1663
|
+
'''(INTERNAL) Does ratio C{r / s} exceed threshold?
|
|
1664
|
+
'''
|
|
1665
|
+
self._ratio = t = fabs((r / s) if s else r)
|
|
1666
|
+
return t > self._RESIDUAL
|
|
1667
|
+
|
|
1601
1668
|
@property_RO
|
|
1602
1669
|
def real(self):
|
|
1603
1670
|
'''Get the C{real} part of this instance (C{float}).
|
|
@@ -1620,12 +1687,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1620
1687
|
'''
|
|
1621
1688
|
return self._fprs2.residual
|
|
1622
1689
|
|
|
1623
|
-
def _raiser(self, r, s):
|
|
1624
|
-
'''(INTERNAL) Does ratio C{r / s} exceed threshold?
|
|
1625
|
-
'''
|
|
1626
|
-
self._ratio = t = fabs((r / s) if s else r)
|
|
1627
|
-
return t > self._RESIDUAL
|
|
1628
|
-
|
|
1629
1690
|
def RESIDUAL(self, *threshold):
|
|
1630
1691
|
'''Get and set this instance' I{ratio} for raising L{ResidualError}s,
|
|
1631
1692
|
overriding the default from env variable C{PYGEODESY_FSUM_RESIDUAL}.
|
|
@@ -1636,12 +1697,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1636
1697
|
C{PYGEODESY_FSUM_RESIDUAL} or if omitted, keep the
|
|
1637
1698
|
current setting.
|
|
1638
1699
|
|
|
1639
|
-
@return: The previous C{RESIDUAL} setting (C{float}).
|
|
1700
|
+
@return: The previous C{RESIDUAL} setting (C{float}), default C{0}.
|
|
1640
1701
|
|
|
1641
1702
|
@raise ValueError: Negative B{C{threshold}}.
|
|
1642
1703
|
|
|
1643
|
-
@note:
|
|
1644
|
-
C{residual
|
|
1704
|
+
@note: L{ResidualError}s will be thrown if the non-zero I{ratio}
|
|
1705
|
+
C{residual / fsum} exceeds the B{C{threshold}}.
|
|
1645
1706
|
'''
|
|
1646
1707
|
r = self._RESIDUAL
|
|
1647
1708
|
if threshold:
|
|
@@ -1659,10 +1720,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1659
1720
|
'''(INTERNAL) Non-zero B{C{residual}} etc.
|
|
1660
1721
|
'''
|
|
1661
1722
|
t = _stresidual(_non_zero_, residual, ratio=self._ratio,
|
|
1662
|
-
|
|
1723
|
+
RESIDUAL=self._RESIDUAL)
|
|
1663
1724
|
t = t.replace(_COMMASPACE_R_, _exceeds_R_)
|
|
1664
1725
|
return self._Error(op, other, ResidualError, txt=t)
|
|
1665
1726
|
|
|
1727
|
+
@property_RO
|
|
1728
|
+
def _2scalar(self):
|
|
1729
|
+
'''(INTERNAL) Get this instance as C{scalar} or C{as-is}.
|
|
1730
|
+
'''
|
|
1731
|
+
s, r = self._fprs2
|
|
1732
|
+
return self if r else s
|
|
1733
|
+
|
|
1666
1734
|
def signOf(self, res=True):
|
|
1667
1735
|
'''Determine the sign of this instance.
|
|
1668
1736
|
|
|
@@ -1671,8 +1739,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1671
1739
|
|
|
1672
1740
|
@return: The sign (C{int}, -1, 0 or +1).
|
|
1673
1741
|
'''
|
|
1674
|
-
s, r = self._fprs2
|
|
1675
|
-
return _signOf(s, -r)
|
|
1742
|
+
s, r = self._fprs2
|
|
1743
|
+
return _signOf(s, (-r) if res else 0)
|
|
1676
1744
|
|
|
1677
1745
|
def toRepr(self, **prec_sep_fmt_lenc): # PYCHOK signature
|
|
1678
1746
|
'''Return this C{Fsum} instance as representation.
|
|
@@ -1721,7 +1789,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1721
1789
|
# Fsum._fint2._update(self)
|
|
1722
1790
|
# Fsum._fprs ._update(self)
|
|
1723
1791
|
# Fsum._fprs2._update(self)
|
|
1724
|
-
return self
|
|
1792
|
+
return self # for .fset_
|
|
1725
1793
|
|
|
1726
1794
|
def _ValueError(self, op, other, **txt): # PYCHOK no cover
|
|
1727
1795
|
'''(INTERNAL) Return a C{ValueError}.
|
|
@@ -1766,21 +1834,21 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
1766
1834
|
_Units_ = (_Float_Int, _Float_Int)
|
|
1767
1835
|
|
|
1768
1836
|
@Property_RO
|
|
1769
|
-
def
|
|
1770
|
-
'''Get this L{Fsum2Tuple} as an L{Fsum}.
|
|
1837
|
+
def _Fsum(self):
|
|
1838
|
+
'''(INTERNAL) Get this L{Fsum2Tuple} as an L{Fsum}.
|
|
1771
1839
|
'''
|
|
1772
1840
|
s, r = map(float, self)
|
|
1773
|
-
return
|
|
1841
|
+
return _Psum(_2ps(s, r), name=self.name)
|
|
1774
1842
|
|
|
1775
1843
|
def is_exact(self):
|
|
1776
1844
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
1777
1845
|
'''
|
|
1778
|
-
return self.
|
|
1846
|
+
return self._Fsum.is_exact()
|
|
1779
1847
|
|
|
1780
1848
|
def is_integer(self):
|
|
1781
1849
|
'''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
|
|
1782
1850
|
'''
|
|
1783
|
-
return self.
|
|
1851
|
+
return self._Fsum.is_integer()
|
|
1784
1852
|
|
|
1785
1853
|
|
|
1786
1854
|
class ResidualError(_ValueError):
|
|
@@ -1792,23 +1860,6 @@ class ResidualError(_ValueError):
|
|
|
1792
1860
|
pass
|
|
1793
1861
|
|
|
1794
1862
|
|
|
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
|
-
|
|
1812
1863
|
try:
|
|
1813
1864
|
from math import fsum as _fsum # precision IEEE-754 sum, Python 2.6+
|
|
1814
1865
|
|
|
@@ -1820,16 +1871,18 @@ try:
|
|
|
1820
1871
|
|
|
1821
1872
|
Fsum._math_fsum = _sum = _fsum # PYCHOK exported
|
|
1822
1873
|
|
|
1823
|
-
if _getenv('PYGEODESY_FSUM_PARTIALS',
|
|
1874
|
+
if _getenv('PYGEODESY_FSUM_PARTIALS', NN) == _fsum.__name__:
|
|
1824
1875
|
_psum = _fsum # PYCHOK re-def
|
|
1825
1876
|
|
|
1826
1877
|
except ImportError:
|
|
1827
|
-
_sum = sum # Fsum(NAN) exception fall-back
|
|
1878
|
+
_sum = sum # Fsum(NAN) exception fall-back, in .elliptic
|
|
1828
1879
|
|
|
1829
1880
|
def _fsum(xs):
|
|
1830
1881
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
1831
1882
|
'''
|
|
1832
|
-
|
|
1883
|
+
f = Fsum()
|
|
1884
|
+
f.name = _fsum.__name__
|
|
1885
|
+
return f.fsum(xs)
|
|
1833
1886
|
|
|
1834
1887
|
|
|
1835
1888
|
def fsum(xs, floats=False):
|
|
@@ -1837,8 +1890,8 @@ def fsum(xs, floats=False):
|
|
|
1837
1890
|
|
|
1838
1891
|
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1839
1892
|
instances).
|
|
1840
|
-
@kwarg floats:
|
|
1841
|
-
|
|
1893
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1894
|
+
to be C{float} scalars (C{bool}).
|
|
1842
1895
|
|
|
1843
1896
|
@return: Precision C{fsum} (C{float}).
|
|
1844
1897
|
|
|
@@ -1848,8 +1901,8 @@ def fsum(xs, floats=False):
|
|
|
1848
1901
|
|
|
1849
1902
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
1850
1903
|
|
|
1851
|
-
@note:
|
|
1852
|
-
|
|
1904
|
+
@note: Exception and I{non-finite} handling may differ if not based
|
|
1905
|
+
on Python's C{math.fsum}.
|
|
1853
1906
|
|
|
1854
1907
|
@see: Class L{Fsum} and methods L{Fsum.fsum} and L{Fsum.fadd}.
|
|
1855
1908
|
'''
|
|
@@ -1861,8 +1914,8 @@ def fsum_(*xs, **floats):
|
|
|
1861
1914
|
|
|
1862
1915
|
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1863
1916
|
positional.
|
|
1864
|
-
@kwarg floats:
|
|
1865
|
-
|
|
1917
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1918
|
+
to be C{float} scalars (C{bool}).
|
|
1866
1919
|
|
|
1867
1920
|
@return: Precision C{fsum} (C{float}).
|
|
1868
1921
|
|
|
@@ -1879,12 +1932,12 @@ def fsumf_(*xs):
|
|
|
1879
1932
|
|
|
1880
1933
|
|
|
1881
1934
|
def fsum1(xs, floats=False):
|
|
1882
|
-
'''Precision floating point summation
|
|
1935
|
+
'''Precision floating point summation, 1-primed.
|
|
1883
1936
|
|
|
1884
1937
|
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1885
1938
|
instances).
|
|
1886
|
-
@kwarg floats:
|
|
1887
|
-
|
|
1939
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1940
|
+
to be C{float}.
|
|
1888
1941
|
|
|
1889
1942
|
@return: Precision C{fsum} (C{float}).
|
|
1890
1943
|
|
|
@@ -1894,12 +1947,12 @@ def fsum1(xs, floats=False):
|
|
|
1894
1947
|
|
|
1895
1948
|
|
|
1896
1949
|
def fsum1_(*xs, **floats):
|
|
1897
|
-
'''Precision floating point summation
|
|
1950
|
+
'''Precision floating point summation, 1-primed.
|
|
1898
1951
|
|
|
1899
1952
|
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1900
1953
|
positional.
|
|
1901
|
-
@kwarg floats:
|
|
1902
|
-
|
|
1954
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1955
|
+
to be C{float} scalars (C{bool}).
|
|
1903
1956
|
|
|
1904
1957
|
@return: Precision C{fsum} (C{float}).
|
|
1905
1958
|
|
|
@@ -1910,11 +1963,40 @@ def fsum1_(*xs, **floats):
|
|
|
1910
1963
|
|
|
1911
1964
|
|
|
1912
1965
|
def fsum1f_(*xs):
|
|
1913
|
-
'''Precision floating point summation L{fsum1_}C{(*xs, floats=True)}.
|
|
1966
|
+
'''Precision floating point summation, L{fsum1_}C{(*xs, floats=True)}.
|
|
1914
1967
|
'''
|
|
1915
1968
|
return _fsum(_1primed(xs)) if xs else _0_0
|
|
1916
1969
|
|
|
1917
1970
|
|
|
1971
|
+
if __name__ == '__main__':
|
|
1972
|
+
|
|
1973
|
+
# usage: [env PYGEODESY_FSUM_PARTIALS=fsum] python3 -m pygeodesy.fsums
|
|
1974
|
+
|
|
1975
|
+
def _test(n):
|
|
1976
|
+
# copied from Hettinger, see L{Fsum} reference
|
|
1977
|
+
from pygeodesy import printf
|
|
1978
|
+
from random import gauss, random, shuffle
|
|
1979
|
+
|
|
1980
|
+
printf(_fsum.__name__, end=_COMMASPACE_)
|
|
1981
|
+
printf(_psum.__name__, end=_COMMASPACE_)
|
|
1982
|
+
|
|
1983
|
+
F = Fsum()
|
|
1984
|
+
if F.is_math_fsum():
|
|
1985
|
+
c = (7, 1e100, -7, -1e100, -9e-20, 8e-20) * 10
|
|
1986
|
+
for _ in range(n):
|
|
1987
|
+
t = list(c)
|
|
1988
|
+
s = 0
|
|
1989
|
+
for _ in range(n * 8):
|
|
1990
|
+
v = gauss(0, random())**7 - s
|
|
1991
|
+
t.append(v)
|
|
1992
|
+
s += v
|
|
1993
|
+
shuffle(t)
|
|
1994
|
+
assert float(F.fset_(*t)) == _fsum(t)
|
|
1995
|
+
printf(_DOT_, end=NN)
|
|
1996
|
+
printf(NN)
|
|
1997
|
+
|
|
1998
|
+
_test(128)
|
|
1999
|
+
|
|
1918
2000
|
# **) MIT License
|
|
1919
2001
|
#
|
|
1920
2002
|
# Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
|