pygeodesy 24.4.4__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.4.dist-info → PyGeodesy-24.4.12.dist-info}/METADATA +6 -6
- {PyGeodesy-24.4.4.dist-info → PyGeodesy-24.4.12.dist-info}/RECORD +31 -31
- pygeodesy/__init__.py +1 -1
- pygeodesy/albers.py +9 -9
- pygeodesy/azimuthal.py +9 -8
- 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/frechet.py +6 -6
- pygeodesy/fstats.py +3 -4
- pygeodesy/fsums.py +314 -279
- 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/rhumb/bases.py +24 -25
- pygeodesy/sphericalNvector.py +6 -6
- pygeodesy/sphericalTrigonometry.py +3 -4
- pygeodesy/utmupsBase.py +6 -6
- {PyGeodesy-24.4.4.dist-info → PyGeodesy-24.4.12.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.4.4.dist-info → PyGeodesy-24.4.12.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py
CHANGED
|
@@ -17,11 +17,10 @@ C{-1.0} and C{+1.0}, including C{INT0} if considered to be I{exact}.
|
|
|
17
17
|
Set env variable C{PYGEODESY_FSUM_PARTIALS} to string C{"fsum"}) for summation
|
|
18
18
|
of L{Fsum} partials by Python function C{math.fsum}.
|
|
19
19
|
|
|
20
|
-
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
and L{Fsum.__itruediv__}.
|
|
20
|
+
Set env variable C{PYGEODESY_FSUM_RESIDUAL} to a C{float} string greater than
|
|
21
|
+
C{"0.0"} as the threshold to throw a L{ResidualError} in division or exponention
|
|
22
|
+
of an L{Fsum} instance with a I{relative} C{residual} exceeding the threshold,
|
|
23
|
+
see methods L{Fsum.RESIDUAL}, L{Fsum.pow}, L{Fsum.__ipow__} and L{Fsum.__itruediv__}.
|
|
25
24
|
'''
|
|
26
25
|
# make sure int/int division yields float quotient, see .basics
|
|
27
26
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
@@ -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,54 +71,82 @@ _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
|
-
return v
|
|
83
|
-
raise ValueError(_not_finite_)
|
|
96
|
+
return v if _isfinite(v) else _2error(v)
|
|
84
97
|
except Exception as X:
|
|
85
98
|
raise _xError(X, Fmt.INDEX(n, index), v)
|
|
86
99
|
|
|
87
100
|
|
|
88
|
-
def
|
|
101
|
+
def _X_ps(X): # for _2floats only
|
|
102
|
+
return X._ps
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _2floats(xs, origin=0, _X=_X_ps, _x=float):
|
|
89
106
|
'''(INTERNAL) Yield each B{C{xs}} as a C{float}.
|
|
90
107
|
'''
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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!
|
|
@@ -136,20 +163,33 @@ def _psum(ps): # PYCHOK used!
|
|
|
136
163
|
if s:
|
|
137
164
|
ps[i:] = r, s
|
|
138
165
|
if i > 0:
|
|
139
|
-
|
|
140
|
-
if (p > 0 and r > 0) or \
|
|
141
|
-
(p < 0 and r < 0): # signs match
|
|
142
|
-
r *= 2
|
|
143
|
-
t = s + r
|
|
144
|
-
if r == (t - s):
|
|
145
|
-
s = t
|
|
166
|
+
s = _2halfeven(s, r, ps[i-1])
|
|
146
167
|
break # return s
|
|
147
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
|
|
@@ -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 X:
|
|
223
|
-
raise _xError(X, 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}.
|
|
@@ -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):
|
|
@@ -819,7 +835,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
819
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)
|
|
823
839
|
|
|
824
840
|
def _ErrorX(self, X, op, other, *mod):
|
|
825
841
|
'''(INTERNAL) Format the caught exception C{X}.
|
|
@@ -836,33 +852,35 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
836
852
|
n = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
|
|
837
853
|
return E(n, txt=t, cause=X)
|
|
838
854
|
|
|
839
|
-
def _facc(self, xs, up
|
|
840
|
-
'''(INTERNAL) Accumulate
|
|
855
|
+
def _facc(self, xs, **up):
|
|
856
|
+
'''(INTERNAL) Accumulate all C{xs}, known to be scalar.
|
|
841
857
|
'''
|
|
842
|
-
|
|
843
|
-
for x in xs: # _iter()
|
|
844
|
-
# assert isscalar(x) and isfinite(x)
|
|
845
|
-
if x:
|
|
846
|
-
i = 0
|
|
847
|
-
for p in ps:
|
|
848
|
-
x, p = _2s(x, p)
|
|
849
|
-
if p:
|
|
850
|
-
ps[i] = p
|
|
851
|
-
i += 1
|
|
852
|
-
ps[i:] = (x,) if x else ()
|
|
853
|
-
n += 1
|
|
854
|
-
# assert self._ps is ps
|
|
855
|
-
if n:
|
|
856
|
-
self._n += n
|
|
857
|
-
# Fsum._px = max(Fsum._px, len(ps))
|
|
858
|
-
if up:
|
|
859
|
-
self._update()
|
|
858
|
+
self._ps_acc(self._ps, xs, **up)
|
|
860
859
|
return self
|
|
861
860
|
|
|
862
861
|
def _facc_(self, *xs, **up):
|
|
863
|
-
'''(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.
|
|
864
870
|
'''
|
|
865
|
-
|
|
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
|
|
866
884
|
|
|
867
885
|
def _facc_power(self, power, xs, which): # in .fmath
|
|
868
886
|
'''(INTERNAL) Add each C{xs} as C{float(x**power)}.
|
|
@@ -879,22 +897,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
879
897
|
|
|
880
898
|
if p:
|
|
881
899
|
from math import pow as _pow
|
|
882
|
-
op
|
|
900
|
+
op = which.__name__
|
|
901
|
+
_Fs = Fsum
|
|
883
902
|
|
|
884
903
|
def _X(X):
|
|
885
904
|
f = _Pow(X, p, power, op)
|
|
886
|
-
|
|
887
|
-
return f._ps
|
|
888
|
-
except AttributeError: # scalar
|
|
889
|
-
return f,
|
|
905
|
+
return f._ps if isinstance(f, _Fs) else (f,)
|
|
890
906
|
|
|
891
907
|
def _x(x):
|
|
892
908
|
return _pow(float(x), p)
|
|
893
909
|
|
|
894
|
-
self.
|
|
910
|
+
f = self._facc_any(xs, origin=1, _X=_X, _x=_x)
|
|
895
911
|
else:
|
|
896
|
-
self._facc_(float(len(xs))) # x**0 == 1
|
|
897
|
-
return
|
|
912
|
+
f = self._facc_(float(len(xs))) # x**0 == 1
|
|
913
|
+
return f
|
|
898
914
|
|
|
899
915
|
# def _facc_up(self, up=True):
|
|
900
916
|
# '''(INTERNAL) Update the C{partials}, by removing
|
|
@@ -926,11 +942,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
926
942
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
927
943
|
'''
|
|
928
944
|
if isinstance(xs, Fsum):
|
|
929
|
-
self._facc(xs._ps)
|
|
945
|
+
self._facc(xs._ps) # tuple
|
|
930
946
|
elif isscalar(xs): # for backward compatibility
|
|
931
947
|
self._facc_(_2float(x=xs)) # PYCHOK no cover
|
|
932
948
|
elif xs:
|
|
933
|
-
self.
|
|
949
|
+
self._facc_any(xs)
|
|
934
950
|
return self
|
|
935
951
|
|
|
936
952
|
def fadd_(self, *xs):
|
|
@@ -949,16 +965,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
949
965
|
|
|
950
966
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
951
967
|
'''
|
|
952
|
-
return self.
|
|
968
|
+
return self._facc_any(xs, origin=1)
|
|
953
969
|
|
|
954
970
|
def _fadd(self, other, op, **up): # in .fmath.Fhorner
|
|
955
971
|
'''(INTERNAL) Apply C{B{self} += B{other}}.
|
|
956
972
|
'''
|
|
957
973
|
if isinstance(other, Fsum):
|
|
958
|
-
|
|
959
|
-
self._facc_(*other._ps, **up) # == ._facc(tuple(other._ps))
|
|
960
|
-
elif other._ps:
|
|
961
|
-
self._facc(other._ps, **up)
|
|
974
|
+
self._facc(other._ps, **up) # tuple
|
|
962
975
|
elif not isscalar(other):
|
|
963
976
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
964
977
|
elif other:
|
|
@@ -1000,7 +1013,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1000
1013
|
'''Return this instance' current running sum as C{integer}.
|
|
1001
1014
|
|
|
1002
1015
|
@kwarg raiser: If C{True} throw a L{ResidualError} if the
|
|
1003
|
-
I{integer} residual is non-zero.
|
|
1016
|
+
I{integer} residual is non-zero (C{bool}).
|
|
1004
1017
|
@kwarg name: Optional name (C{str}), overriding C{"fint"}.
|
|
1005
1018
|
|
|
1006
1019
|
@return: The C{integer} (L{Fsum}).
|
|
@@ -1035,7 +1048,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1035
1048
|
s, r = self._fprs2
|
|
1036
1049
|
i = int(s)
|
|
1037
1050
|
r = _fsum(self._ps_1(i)) if r else float(s - i)
|
|
1038
|
-
return i, (r or INT0)
|
|
1051
|
+
return i, (r or INT0) # Fsum2Tuple?
|
|
1039
1052
|
|
|
1040
1053
|
@deprecated_property_RO
|
|
1041
1054
|
def float_int(self): # PYCHOK no cover
|
|
@@ -1079,7 +1092,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1079
1092
|
else: # len(other._ps) == len(self._ps) == 1
|
|
1080
1093
|
f = self._finite(self._ps[0] * other._ps[0])
|
|
1081
1094
|
elif isscalar(other):
|
|
1082
|
-
f = self._mul_scalar(other, op)
|
|
1095
|
+
f = self._mul_scalar(other, op) if other != _1_0 else self
|
|
1083
1096
|
else:
|
|
1084
1097
|
raise self._TypeError(op, other) # txt=_invalid_
|
|
1085
1098
|
return self._fset(f) # n=len(self) + 1
|
|
@@ -1102,13 +1115,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1102
1115
|
'''
|
|
1103
1116
|
if mod:
|
|
1104
1117
|
if mod[0] is not None: # == 3-arg C{pow}
|
|
1105
|
-
f = self.
|
|
1118
|
+
f = self._pow_2_3(self, other, other, op, *mod)
|
|
1106
1119
|
elif self.is_integer():
|
|
1107
1120
|
# return an exact C{int} for C{int}**C{int}
|
|
1121
|
+
i, _ = self._fint2 # assert _ == 0
|
|
1108
1122
|
x = _2scalar(other) # C{int}, C{float} or other
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
_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)
|
|
1112
1125
|
else: # mod[0] is None, power(self, other)
|
|
1113
1126
|
f = self._pow_any(other, other, op)
|
|
1114
1127
|
else: # pow(self, other) == pow(self, other, None)
|
|
@@ -1134,8 +1147,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1134
1147
|
n = len(ps) - 2
|
|
1135
1148
|
if n > 0: # len(ps) > 2
|
|
1136
1149
|
s = _psum(ps)
|
|
1137
|
-
|
|
1138
|
-
|
|
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
|
|
1139
1155
|
ps[:] = _2ps(*_2sum(*ps))
|
|
1140
1156
|
r, s = (INT0, ps[0]) if len(ps) != 2 else ps
|
|
1141
1157
|
elif ps: # len(ps) == 1
|
|
@@ -1150,7 +1166,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1150
1166
|
# '''(INTERNAL) Compress, squeeze the C{partials}.
|
|
1151
1167
|
# '''
|
|
1152
1168
|
# if len(self._ps) > 2:
|
|
1153
|
-
# _ = self.
|
|
1169
|
+
# _ = self._fprs2
|
|
1154
1170
|
# return self
|
|
1155
1171
|
|
|
1156
1172
|
def fset_(self, *xs):
|
|
@@ -1163,8 +1179,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1163
1179
|
|
|
1164
1180
|
@see: Method L{Fsum.fadd} for further details.
|
|
1165
1181
|
'''
|
|
1166
|
-
self._n = 0
|
|
1167
1182
|
self._ps[:] = 0,
|
|
1183
|
+
self._n = 0
|
|
1168
1184
|
return self.fadd(xs) if xs else self._update()
|
|
1169
1185
|
|
|
1170
1186
|
def _fset(self, other, asis=True, n=0):
|
|
@@ -1173,8 +1189,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1173
1189
|
if other is self:
|
|
1174
1190
|
pass # from ._fmul, ._ftruediv and ._pow_scalar
|
|
1175
1191
|
elif isinstance(other, Fsum):
|
|
1176
|
-
self._n = n or other._n
|
|
1177
1192
|
self._ps[:] = other._ps
|
|
1193
|
+
self._n = n or other._n
|
|
1178
1194
|
# self._copy_RESIDUAL(other)
|
|
1179
1195
|
# use or zap the C{Property_RO} values
|
|
1180
1196
|
Fsum._fint2._update_from(self, other)
|
|
@@ -1184,8 +1200,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1184
1200
|
s = other if asis else float(other)
|
|
1185
1201
|
i = int(s) # see ._fint2
|
|
1186
1202
|
t = i, ((s - i) or INT0)
|
|
1187
|
-
self._n = n or 1
|
|
1188
1203
|
self._ps[:] = s,
|
|
1204
|
+
self._n = n or 1
|
|
1189
1205
|
# Property_ROs _fint2, _fprs and _fprs2 can't be a Property:
|
|
1190
1206
|
# Property's _fset zaps the value just set by the @setter
|
|
1191
1207
|
self.__dict__.update(_fint2=t, _fprs=s, _fprs2=Fsum2Tuple(s, INT0))
|
|
@@ -1194,14 +1210,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1194
1210
|
return self
|
|
1195
1211
|
|
|
1196
1212
|
def _fset_ps(self, other, n=0): # in .fmath
|
|
1197
|
-
'''(INTERNAL) Set a known C{Fsum} or C{scalar}.
|
|
1213
|
+
'''(INTERNAL) Set partials from a known C{Fsum} or C{scalar}.
|
|
1198
1214
|
'''
|
|
1199
1215
|
if isinstance(other, Fsum):
|
|
1200
|
-
self._n = n or other._n
|
|
1201
1216
|
self._ps[:] = other._ps
|
|
1217
|
+
self._n = n or other._n
|
|
1202
1218
|
else: # assert isscalar(other)
|
|
1203
|
-
self._n = n or 1
|
|
1204
1219
|
self._ps[:] = other,
|
|
1220
|
+
self._n = n or 1
|
|
1221
|
+
return self
|
|
1205
1222
|
|
|
1206
1223
|
def fsub(self, xs=()):
|
|
1207
1224
|
'''Subtract an iterable of C{scalar} or L{Fsum} instances from
|
|
@@ -1214,7 +1231,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1214
1231
|
|
|
1215
1232
|
@see: Method L{Fsum.fadd}.
|
|
1216
1233
|
'''
|
|
1217
|
-
return self.
|
|
1234
|
+
return self._facc_any_neg(xs) if xs else self
|
|
1218
1235
|
|
|
1219
1236
|
def fsub_(self, *xs):
|
|
1220
1237
|
'''Subtract all positional C{scalar} or L{Fsum} instances from
|
|
@@ -1227,7 +1244,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1227
1244
|
|
|
1228
1245
|
@see: Method L{Fsum.fadd}.
|
|
1229
1246
|
'''
|
|
1230
|
-
return self.
|
|
1247
|
+
return self._facc_any_neg(xs, origin=1) if xs else self
|
|
1231
1248
|
|
|
1232
1249
|
def _fsub(self, other, op):
|
|
1233
1250
|
'''(INTERNAL) Apply C{B{self} -= B{other}}.
|
|
@@ -1255,22 +1272,29 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1255
1272
|
|
|
1256
1273
|
@note: Accumulation can continue after summation.
|
|
1257
1274
|
'''
|
|
1258
|
-
f = self.
|
|
1275
|
+
f = self._facc_any(xs) if xs else self
|
|
1259
1276
|
return f._fprs
|
|
1260
1277
|
|
|
1261
1278
|
def fsum_(self, *xs):
|
|
1262
1279
|
'''Add all positional C{scalar} or L{Fsum} instances and summate.
|
|
1263
1280
|
|
|
1264
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1265
|
-
|
|
1281
|
+
@arg xs: Values to add (C{scalar} or L{Fsum} instances), all
|
|
1282
|
+
positional.
|
|
1266
1283
|
|
|
1267
1284
|
@return: Precision running sum (C{float} or C{int}).
|
|
1268
1285
|
|
|
1269
|
-
@see: Methods L{Fsum.fsum} and L{Fsum.fsumf_}.
|
|
1286
|
+
@see: Methods L{Fsum.fsum}, L{Fsum.Fsum_} and L{Fsum.fsumf_}.
|
|
1270
1287
|
'''
|
|
1271
|
-
f = self.
|
|
1288
|
+
f = self._facc_any(xs, origin=1) if xs else self
|
|
1272
1289
|
return f._fprs
|
|
1273
1290
|
|
|
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
|
+
|
|
1274
1298
|
def fsum2(self, xs=(), name=NN):
|
|
1275
1299
|
'''Add more C{scalar} or L{Fsum} instances and return the
|
|
1276
1300
|
current precision running sum and the C{residual}.
|
|
@@ -1287,7 +1311,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1287
1311
|
|
|
1288
1312
|
@see: Methods L{Fsum.fint2}, L{Fsum.fsum} and L{Fsum.fsum2_}
|
|
1289
1313
|
'''
|
|
1290
|
-
f = self.
|
|
1314
|
+
f = self._facc_any(xs) if xs else self
|
|
1291
1315
|
t = f._fprs2
|
|
1292
1316
|
if name:
|
|
1293
1317
|
t = t.dup(name=name)
|
|
@@ -1297,29 +1321,44 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1297
1321
|
'''Add any positional C{scalar} or L{Fsum} instances and return
|
|
1298
1322
|
the precision running sum and the C{differential}.
|
|
1299
1323
|
|
|
1300
|
-
@arg xs: Values to add (C{scalar} or L{Fsum} instances),
|
|
1301
|
-
|
|
1324
|
+
@arg xs: Values to add (C{scalar} or L{Fsum} instances), all
|
|
1325
|
+
positional.
|
|
1302
1326
|
|
|
1303
|
-
@return:
|
|
1304
|
-
running C{fsum} and C{delta},
|
|
1305
|
-
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}.
|
|
1306
1330
|
|
|
1307
1331
|
@see: Methods L{Fsum.fsum_} and L{Fsum.fsum}.
|
|
1308
1332
|
'''
|
|
1309
|
-
|
|
1310
|
-
if xs:
|
|
1311
|
-
s, t = self._facc(_2floats(xs, origin=1))._fprs2 # PYCHOK yield
|
|
1312
|
-
return s, _fsum((s, -p, r, -t)) # ((s - p) + (r - t))
|
|
1313
|
-
else: # PYCHOK no cover
|
|
1314
|
-
return p, _0_0
|
|
1333
|
+
return self._fsum2f_any(xs, self._facc_any, origin=1)
|
|
1315
1334
|
|
|
1316
1335
|
def fsumf_(self, *xs):
|
|
1317
|
-
'''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}}.
|
|
1318
1337
|
'''
|
|
1319
|
-
f = self._facc(xs) if xs else self
|
|
1338
|
+
f = self._facc(xs) if xs else self
|
|
1320
1339
|
return f._fprs
|
|
1321
1340
|
|
|
1322
|
-
|
|
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?
|
|
1323
1362
|
|
|
1324
1363
|
def _ftruediv(self, other, op):
|
|
1325
1364
|
'''(INTERNAL) Apply C{B{self} /= B{other}}.
|
|
@@ -1380,13 +1419,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1380
1419
|
return s
|
|
1381
1420
|
|
|
1382
1421
|
def is_exact(self):
|
|
1383
|
-
'''Is this instance'
|
|
1384
|
-
be exact? (C{bool}).
|
|
1422
|
+
'''Is this instance' running C{fsum} considered to be exact? (C{bool}).
|
|
1385
1423
|
'''
|
|
1386
1424
|
return self.residual is INT0
|
|
1387
1425
|
|
|
1388
1426
|
def is_integer(self):
|
|
1389
|
-
'''Is this instance'
|
|
1427
|
+
'''Is this instance' running sum C{integer}? (C{bool}).
|
|
1390
1428
|
|
|
1391
1429
|
@see: Methods L{Fsum.fint} and L{Fsum.fint2}.
|
|
1392
1430
|
'''
|
|
@@ -1412,7 +1450,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1412
1450
|
'''
|
|
1413
1451
|
# assert isinstance(other, Fsum)
|
|
1414
1452
|
if self._ps and other._ps:
|
|
1415
|
-
f =
|
|
1453
|
+
f = self._ps_mul(op, *other._ps) # NO ._2scalar
|
|
1416
1454
|
else:
|
|
1417
1455
|
f = _0_0
|
|
1418
1456
|
return f
|
|
@@ -1424,20 +1462,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1424
1462
|
if self._ps and self._finite(factor, op):
|
|
1425
1463
|
f = self if factor == _1_0 else (
|
|
1426
1464
|
self._neg if factor == _N_1_0 else
|
|
1427
|
-
|
|
1465
|
+
self._ps_mul(op, factor)._2scalar)
|
|
1428
1466
|
else:
|
|
1429
1467
|
f = _0_0
|
|
1430
1468
|
return f
|
|
1431
1469
|
|
|
1432
1470
|
@property_RO
|
|
1433
1471
|
def _neg(self):
|
|
1434
|
-
'''(INTERNAL) Return C{-self}.
|
|
1472
|
+
'''(INTERNAL) Return C{Fsum(-self)} or scalar C{NEG0}.
|
|
1435
1473
|
'''
|
|
1436
|
-
return
|
|
1474
|
+
return _Psum(self._ps_neg) if self._ps else NEG0
|
|
1437
1475
|
|
|
1438
1476
|
@property_RO
|
|
1439
1477
|
def partials(self):
|
|
1440
|
-
'''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).
|
|
1441
1479
|
'''
|
|
1442
1480
|
return tuple(self._ps)
|
|
1443
1481
|
|
|
@@ -1453,7 +1491,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1453
1491
|
|
|
1454
1492
|
@note: If B{C{mod}} is given as C{None}, the result will be an
|
|
1455
1493
|
C{integer} L{Fsum} provided this instance C{is_integer}
|
|
1456
|
-
or set to C{integer}
|
|
1494
|
+
or set to C{integer} by an L{Fsum.fint} call.
|
|
1457
1495
|
|
|
1458
1496
|
@see: Methods L{Fsum.__ipow__}, L{Fsum.fint} and L{Fsum.is_integer}.
|
|
1459
1497
|
'''
|
|
@@ -1465,50 +1503,37 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1465
1503
|
'''
|
|
1466
1504
|
return self if x else (1 if isint(other) and self.is_integer() else _1_0)
|
|
1467
1505
|
|
|
1468
|
-
def
|
|
1469
|
-
'''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})}
|
|
1470
|
-
|
|
1471
|
-
# assert isscalar(b) and isscalar(x)
|
|
1472
|
-
try: # type(s) == type(x) if x in (_1_0, 1)
|
|
1473
|
-
s = pow(b, x) # -1**2.3 == -(1**2.3)
|
|
1474
|
-
if not iscomplex(s):
|
|
1475
|
-
return self._finite(s) # 0**INF == 0.0, 1**INF==1.0
|
|
1476
|
-
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1477
|
-
raise ValueError(_strcomplex(s, b, x)) # PYCHOK no cover
|
|
1478
|
-
except Exception as X:
|
|
1479
|
-
raise self._ErrorX(X, op, other)
|
|
1480
|
-
|
|
1481
|
-
def _pow_3(self, other, mod, op):
|
|
1482
|
-
'''(INTERNAL) 3-arg C{pow(B{self}, B{other}, int B{mod} or C{None})}.
|
|
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.
|
|
1483
1509
|
'''
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
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):
|
|
1521
|
+
# neg**frac == complex in Python 3+, but ValueError in 2-
|
|
1522
|
+
raise ValueError(_strcomplex(s, b, x, *mod))
|
|
1523
|
+
return self._finite(s)
|
|
1497
1524
|
except Exception as X:
|
|
1498
|
-
raise self._ErrorX(X, op, other, mod)
|
|
1525
|
+
raise self._ErrorX(X, op, other, *mod)
|
|
1499
1526
|
|
|
1500
1527
|
def _pow_any(self, other, unused, op):
|
|
1501
1528
|
'''Return C{B{self} ** B{other}}.
|
|
1502
1529
|
'''
|
|
1503
1530
|
if isinstance(other, Fsum):
|
|
1504
1531
|
x, r = other._fprs2
|
|
1532
|
+
if r and self._raiser(r, x):
|
|
1533
|
+
raise self._ResidualError(op, other, r)
|
|
1505
1534
|
f = self._pow_scalar(x, other, op)
|
|
1506
1535
|
if r:
|
|
1507
|
-
|
|
1508
|
-
raise self._ResidualError(op, other, r)
|
|
1509
|
-
s = self._pow_scalar(r, other, op)
|
|
1510
|
-
# s = _2scalar(s) # _raiser = None
|
|
1511
|
-
f *= s
|
|
1536
|
+
f *= self._pow_scalar(r, other, op)
|
|
1512
1537
|
elif isscalar(other):
|
|
1513
1538
|
x = self._finite(other, op)
|
|
1514
1539
|
f = self._pow_scalar(x, other, op)
|
|
@@ -1522,32 +1547,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1522
1547
|
# assert isint(x) and x >= 0
|
|
1523
1548
|
ps = self._ps
|
|
1524
1549
|
if len(ps) > 1:
|
|
1525
|
-
|
|
1550
|
+
_mul_Fsum = Fsum._mul_Fsum
|
|
1526
1551
|
if x > 4:
|
|
1527
|
-
m = 1 # single-bit mask
|
|
1528
|
-
if (x & m):
|
|
1529
|
-
x -= m # x ^= m
|
|
1530
|
-
else:
|
|
1531
|
-
f = _Fsum_ps(_1_0)
|
|
1532
1552
|
p = self
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
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
|
|
1539
1560
|
elif x > 1: # self**2, 3 or 4
|
|
1540
|
-
f =
|
|
1561
|
+
f = _mul_Fsum(self, self, op)
|
|
1541
1562
|
if x > 2: # self**3 or 4
|
|
1542
|
-
p =
|
|
1543
|
-
f =
|
|
1563
|
+
p = self if x < 4 else f
|
|
1564
|
+
f = _mul_Fsum(f, p, op)._2scalar
|
|
1544
1565
|
else: # self**1 or self**0 == 1 or _1_0
|
|
1545
|
-
f =
|
|
1566
|
+
f = self._pow_0_1(x, other)
|
|
1546
1567
|
elif ps: # self._ps[0]**x
|
|
1547
|
-
f = self.
|
|
1568
|
+
f = self._pow_2_3(ps[0], x, other, op)
|
|
1548
1569
|
else: # PYCHOK no cover
|
|
1549
1570
|
# 0**pos_int == 0, but 0**0 == 1
|
|
1550
|
-
f = 0 if x else 1
|
|
1571
|
+
f = 0 if x else 1
|
|
1551
1572
|
return f
|
|
1552
1573
|
|
|
1553
1574
|
def _pow_scalar(self, x, other, op):
|
|
@@ -1565,13 +1586,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1565
1586
|
# assert x < 0 # < -1
|
|
1566
1587
|
s, r = f._fprs2 if isinstance(f, Fsum) else (f, 0)
|
|
1567
1588
|
if r:
|
|
1568
|
-
return
|
|
1589
|
+
return _Psum_1()._ftruediv(f, op)
|
|
1569
1590
|
# use **= -1 for the CPython float_pow
|
|
1570
1591
|
# error if s is zero, and not s = 1 / s
|
|
1571
1592
|
x = -1
|
|
1572
|
-
elif x < 0: # self
|
|
1593
|
+
elif x < 0: # == -1: self**(-1) == 1 / self
|
|
1573
1594
|
if r:
|
|
1574
|
-
return
|
|
1595
|
+
return _Psum_1()._ftruediv(self, op)
|
|
1575
1596
|
else: # self**1 or self**0
|
|
1576
1597
|
return self._pow_0_1(x, other) # self, 1 or 1.0
|
|
1577
1598
|
elif not isscalar(x): # assert ...
|
|
@@ -1581,33 +1602,55 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1581
1602
|
t = _stresidual(_non_zero_, r, fractional_power=x)
|
|
1582
1603
|
raise self._Error(op, other, ResidualError, txt=t)
|
|
1583
1604
|
# assert isscalar(s) and isscalar(x)
|
|
1584
|
-
return self.
|
|
1605
|
+
return self._pow_2_3(s, x, other, op)
|
|
1585
1606
|
|
|
1586
1607
|
def _ps_1(self, *less):
|
|
1587
1608
|
'''(INTERNAL) Yield partials, 1-primed and subtract any C{less}.
|
|
1588
1609
|
'''
|
|
1589
|
-
|
|
1590
|
-
if n < 0:
|
|
1591
|
-
yield _1_0
|
|
1610
|
+
yield _1_0
|
|
1592
1611
|
for p in self._ps:
|
|
1593
|
-
yield
|
|
1612
|
+
yield p
|
|
1594
1613
|
for p in less:
|
|
1595
1614
|
yield -p
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
'''
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1615
|
+
yield _N_1_0
|
|
1616
|
+
|
|
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.
|
|
1643
|
+
'''
|
|
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)))
|
|
1611
1654
|
|
|
1612
1655
|
@property_RO
|
|
1613
1656
|
def _ps_neg(self):
|
|
@@ -1616,6 +1659,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1616
1659
|
for p in self._ps:
|
|
1617
1660
|
yield -p
|
|
1618
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
|
+
|
|
1619
1668
|
@property_RO
|
|
1620
1669
|
def real(self):
|
|
1621
1670
|
'''Get the C{real} part of this instance (C{float}).
|
|
@@ -1638,12 +1687,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1638
1687
|
'''
|
|
1639
1688
|
return self._fprs2.residual
|
|
1640
1689
|
|
|
1641
|
-
def _raiser(self, r, s):
|
|
1642
|
-
'''(INTERNAL) Does ratio C{r / s} exceed threshold?
|
|
1643
|
-
'''
|
|
1644
|
-
self._ratio = t = fabs((r / s) if s else r)
|
|
1645
|
-
return t > self._RESIDUAL
|
|
1646
|
-
|
|
1647
1690
|
def RESIDUAL(self, *threshold):
|
|
1648
1691
|
'''Get and set this instance' I{ratio} for raising L{ResidualError}s,
|
|
1649
1692
|
overriding the default from env variable C{PYGEODESY_FSUM_RESIDUAL}.
|
|
@@ -1658,7 +1701,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1658
1701
|
|
|
1659
1702
|
@raise ValueError: Negative B{C{threshold}}.
|
|
1660
1703
|
|
|
1661
|
-
@note:
|
|
1704
|
+
@note: L{ResidualError}s will be thrown if the non-zero I{ratio}
|
|
1662
1705
|
C{residual / fsum} exceeds the B{C{threshold}}.
|
|
1663
1706
|
'''
|
|
1664
1707
|
r = self._RESIDUAL
|
|
@@ -1681,6 +1724,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1681
1724
|
t = t.replace(_COMMASPACE_R_, _exceeds_R_)
|
|
1682
1725
|
return self._Error(op, other, ResidualError, txt=t)
|
|
1683
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
|
+
|
|
1684
1734
|
def signOf(self, res=True):
|
|
1685
1735
|
'''Determine the sign of this instance.
|
|
1686
1736
|
|
|
@@ -1689,8 +1739,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
|
|
|
1689
1739
|
|
|
1690
1740
|
@return: The sign (C{int}, -1, 0 or +1).
|
|
1691
1741
|
'''
|
|
1692
|
-
s, r = self._fprs2
|
|
1693
|
-
return _signOf(s, -r)
|
|
1742
|
+
s, r = self._fprs2
|
|
1743
|
+
return _signOf(s, (-r) if res else 0)
|
|
1694
1744
|
|
|
1695
1745
|
def toRepr(self, **prec_sep_fmt_lenc): # PYCHOK signature
|
|
1696
1746
|
'''Return this C{Fsum} instance as representation.
|
|
@@ -1784,21 +1834,21 @@ class Fsum2Tuple(_NamedTuple):
|
|
|
1784
1834
|
_Units_ = (_Float_Int, _Float_Int)
|
|
1785
1835
|
|
|
1786
1836
|
@Property_RO
|
|
1787
|
-
def
|
|
1788
|
-
'''Get this L{Fsum2Tuple} as an L{Fsum}.
|
|
1837
|
+
def _Fsum(self):
|
|
1838
|
+
'''(INTERNAL) Get this L{Fsum2Tuple} as an L{Fsum}.
|
|
1789
1839
|
'''
|
|
1790
1840
|
s, r = map(float, self)
|
|
1791
|
-
return
|
|
1841
|
+
return _Psum(_2ps(s, r), name=self.name)
|
|
1792
1842
|
|
|
1793
1843
|
def is_exact(self):
|
|
1794
1844
|
'''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
|
|
1795
1845
|
'''
|
|
1796
|
-
return self.
|
|
1846
|
+
return self._Fsum.is_exact()
|
|
1797
1847
|
|
|
1798
1848
|
def is_integer(self):
|
|
1799
1849
|
'''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
|
|
1800
1850
|
'''
|
|
1801
|
-
return self.
|
|
1851
|
+
return self._Fsum.is_integer()
|
|
1802
1852
|
|
|
1803
1853
|
|
|
1804
1854
|
class ResidualError(_ValueError):
|
|
@@ -1810,23 +1860,6 @@ class ResidualError(_ValueError):
|
|
|
1810
1860
|
pass
|
|
1811
1861
|
|
|
1812
1862
|
|
|
1813
|
-
def _Fsum_ps(*ps, **name):
|
|
1814
|
-
'''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
|
|
1815
|
-
'''
|
|
1816
|
-
f = Fsum(**name) if name else Fsum()
|
|
1817
|
-
if ps:
|
|
1818
|
-
f._n = len(ps)
|
|
1819
|
-
f._ps[:] = ps
|
|
1820
|
-
return f
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
def _Fsum_xs(xs, up=False, **name):
|
|
1824
|
-
'''(INTERNAL) Return an C{Fsum} from known floats C{xs}.
|
|
1825
|
-
'''
|
|
1826
|
-
f = Fsum(**name) if name else Fsum()
|
|
1827
|
-
return f._facc(xs, up=up)
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
1863
|
try:
|
|
1831
1864
|
from math import fsum as _fsum # precision IEEE-754 sum, Python 2.6+
|
|
1832
1865
|
|
|
@@ -1842,12 +1875,14 @@ try:
|
|
|
1842
1875
|
_psum = _fsum # PYCHOK re-def
|
|
1843
1876
|
|
|
1844
1877
|
except ImportError:
|
|
1845
|
-
_sum = sum # Fsum(NAN) exception fall-back
|
|
1878
|
+
_sum = sum # Fsum(NAN) exception fall-back, in .elliptic
|
|
1846
1879
|
|
|
1847
1880
|
def _fsum(xs):
|
|
1848
1881
|
'''(INTERNAL) Precision summation, Python 2.5-.
|
|
1849
1882
|
'''
|
|
1850
|
-
|
|
1883
|
+
f = Fsum()
|
|
1884
|
+
f.name = _fsum.__name__
|
|
1885
|
+
return f.fsum(xs)
|
|
1851
1886
|
|
|
1852
1887
|
|
|
1853
1888
|
def fsum(xs, floats=False):
|
|
@@ -1855,8 +1890,8 @@ def fsum(xs, floats=False):
|
|
|
1855
1890
|
|
|
1856
1891
|
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1857
1892
|
instances).
|
|
1858
|
-
@kwarg floats:
|
|
1859
|
-
|
|
1893
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1894
|
+
to be C{float} scalars (C{bool}).
|
|
1860
1895
|
|
|
1861
1896
|
@return: Precision C{fsum} (C{float}).
|
|
1862
1897
|
|
|
@@ -1866,8 +1901,8 @@ def fsum(xs, floats=False):
|
|
|
1866
1901
|
|
|
1867
1902
|
@raise ValueError: Invalid or non-finite B{C{xs}} value.
|
|
1868
1903
|
|
|
1869
|
-
@note:
|
|
1870
|
-
|
|
1904
|
+
@note: Exception and I{non-finite} handling may differ if not based
|
|
1905
|
+
on Python's C{math.fsum}.
|
|
1871
1906
|
|
|
1872
1907
|
@see: Class L{Fsum} and methods L{Fsum.fsum} and L{Fsum.fadd}.
|
|
1873
1908
|
'''
|
|
@@ -1879,8 +1914,8 @@ def fsum_(*xs, **floats):
|
|
|
1879
1914
|
|
|
1880
1915
|
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1881
1916
|
positional.
|
|
1882
|
-
@kwarg floats:
|
|
1883
|
-
|
|
1917
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1918
|
+
to be C{float} scalars (C{bool}).
|
|
1884
1919
|
|
|
1885
1920
|
@return: Precision C{fsum} (C{float}).
|
|
1886
1921
|
|
|
@@ -1897,12 +1932,12 @@ def fsumf_(*xs):
|
|
|
1897
1932
|
|
|
1898
1933
|
|
|
1899
1934
|
def fsum1(xs, floats=False):
|
|
1900
|
-
'''Precision floating point summation
|
|
1935
|
+
'''Precision floating point summation, 1-primed.
|
|
1901
1936
|
|
|
1902
1937
|
@arg xs: Iterable, list, tuple, etc. of values (C{scalar} or L{Fsum}
|
|
1903
1938
|
instances).
|
|
1904
|
-
@kwarg floats:
|
|
1905
|
-
|
|
1939
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1940
|
+
to be C{float}.
|
|
1906
1941
|
|
|
1907
1942
|
@return: Precision C{fsum} (C{float}).
|
|
1908
1943
|
|
|
@@ -1912,12 +1947,12 @@ def fsum1(xs, floats=False):
|
|
|
1912
1947
|
|
|
1913
1948
|
|
|
1914
1949
|
def fsum1_(*xs, **floats):
|
|
1915
|
-
'''Precision floating point summation
|
|
1950
|
+
'''Precision floating point summation, 1-primed.
|
|
1916
1951
|
|
|
1917
1952
|
@arg xs: Values to be added (C{scalar} or L{Fsum} instances), all
|
|
1918
1953
|
positional.
|
|
1919
|
-
@kwarg floats:
|
|
1920
|
-
|
|
1954
|
+
@kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} are known
|
|
1955
|
+
to be C{float} scalars (C{bool}).
|
|
1921
1956
|
|
|
1922
1957
|
@return: Precision C{fsum} (C{float}).
|
|
1923
1958
|
|
|
@@ -1928,7 +1963,7 @@ def fsum1_(*xs, **floats):
|
|
|
1928
1963
|
|
|
1929
1964
|
|
|
1930
1965
|
def fsum1f_(*xs):
|
|
1931
|
-
'''Precision floating point summation L{fsum1_}C{(*xs, floats=True)}.
|
|
1966
|
+
'''Precision floating point summation, L{fsum1_}C{(*xs, floats=True)}.
|
|
1932
1967
|
'''
|
|
1933
1968
|
return _fsum(_1primed(xs)) if xs else _0_0
|
|
1934
1969
|
|
|
@@ -1946,7 +1981,7 @@ if __name__ == '__main__':
|
|
|
1946
1981
|
printf(_psum.__name__, end=_COMMASPACE_)
|
|
1947
1982
|
|
|
1948
1983
|
F = Fsum()
|
|
1949
|
-
if F.is_math_fsum:
|
|
1984
|
+
if F.is_math_fsum():
|
|
1950
1985
|
c = (7, 1e100, -7, -1e100, -9e-20, 8e-20) * 10
|
|
1951
1986
|
for _ in range(n):
|
|
1952
1987
|
t = list(c)
|