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/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
- than C{"0.0"} as the threshold to throw a L{ResidualError} in division or
22
- exponention of an L{Fsum} instance with a I{relative} C{residual} exceeding
23
- the threshold, see methods L{Fsum.RESIDUAL}, L{Fsum.pow}, L{Fsum.__ipow__}
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.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 _2floats(xs, origin=0, neg=False):
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
- if neg:
92
- def _X(X):
93
- return X._ps_neg
94
-
95
- def _x(x):
96
- return -float(x)
97
- else:
98
- def _X(X): # PYCHOK re-def
99
- return X._ps
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
- return _2yield(xs, origin, _X, _x)
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-Prime the summation of C{xs}
108
- arguments I{known} to be C{finite float}.
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
- if x:
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
- p = ps[i-1] # round half-even
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 _2scalar(other, _raiser=None):
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
- raise ValueError(_stresidual(_non_zero_, r))
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.__name__, a, b)
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
- # _px = 0 # max(Fsum._px, len(Fsum._ps))
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 len(xs) > 1:
273
- self._facc(_2floats(xs, origin=1), up=False) # PYCHOK yield
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 the C{Fsum(B{self}, B{other})}.
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 _Fsum_ps(round(float(self), *ndigits), # can be C{int}
658
- name=self.__round__.__name__)
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.toRepr(), op, repr(other)), **txt_cause)
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=True): # from .elliptic._Defer.Fsum
840
- '''(INTERNAL) Accumulate more known C{scalar}s.
855
+ def _facc(self, xs, **up):
856
+ '''(INTERNAL) Accumulate all C{xs}, known to be scalar.
841
857
  '''
842
- n, ps, _2s = 0, self._ps, _2sum
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}s.
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
- return self._facc(xs, **up) if xs else self
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 = which.__name__
900
+ op = which.__name__
901
+ _Fs = Fsum
883
902
 
884
903
  def _X(X):
885
904
  f = _Pow(X, p, power, op)
886
- try: # isinstance(f, Fsum)
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._facc(_2yield(xs, 1, _X, _x)) # PYCHOK yield
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 self
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._facc(_2floats(xs)) # PYCHOK yield
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._facc(_2floats(xs, origin=1)) # PYCHOK yield
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
- if other is self:
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._pow_3(other, mod[0], op)
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
- i = self._fint2[0] # assert _fint2[1] == 0
1110
- f = self._pow_2(i, x, other, op) if isscalar(x) else \
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
- r = _fsum(self._ps_1(s)) or INT0
1138
- elif n == 0: # len(ps) == 2
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._fprs
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._facc(_2floats(xs, neg=True)) if xs else self # PYCHOK yield
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._facc(_2floats(xs, origin=1, neg=True)) if xs else self # PYCHOK yield
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._facc(_2floats(xs)) if xs else self # PYCHOK yield
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
- all positional.
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._facc(_2floats(xs, origin=1)) if xs else self # PYCHOK yield
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._facc(_2floats(xs)) if xs else self # PYCHOK yield
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
- all positional.
1324
+ @arg xs: Values to add (C{scalar} or L{Fsum} instances), all
1325
+ positional.
1302
1326
 
1303
- @return: 2-Tuple C{(fsum, delta)} with the current precision
1304
- running C{fsum} and C{delta}, the difference with
1305
- the previous running C{fsum} (C{float}s).
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
- p, r = self._fprs2
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 # PYCHOK yield
1338
+ f = self._facc(xs) if xs else self
1320
1339
  return f._fprs
1321
1340
 
1322
- # ftruediv = __itruediv__ # for naming consistency
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' current running C{fsum} considered to
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' current running sum C{integer}? (C{bool}).
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 = _Fsum_xs(self._ps_mul(op, *other._ps))
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
- _Fsum_xs(self._ps_mul(op, factor))) # PYCHOK indent
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 _Fsum_ps(*self._ps_neg) if self._ps else NEG0
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 and/or C{int}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} with L{Fsum.fint}.
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 _pow_2(self, b, x, other, op):
1469
- '''(INTERNAL) 2-arg C{pow(B{b}, scalar B{x})} embellishing errors.
1470
- '''
1471
- # assert isscalar(b) and isscalar(x)
1472
- try: # type(s) == type(x) if x in (_1_0, 1)
1473
- s = pow(b, x) # -1**2.3 == -(1**2.3)
1474
- if not iscomplex(s):
1475
- return self._finite(s) # 0**INF == 0.0, 1**INF==1.0
1476
- # neg**frac == complex in Python 3+, but ValueError in 2-
1477
- raise ValueError(_strcomplex(s, b, x)) # PYCHOK no cover
1478
- except Exception as X:
1479
- raise self._ErrorX(X, op, other)
1480
-
1481
- def _pow_3(self, other, mod, op):
1482
- '''(INTERNAL) 3-arg C{pow(B{self}, B{other}, int B{mod} or C{None})}.
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
- b, r = self._fprs2 if mod is None else self._fint2
1485
- if r and self._raiser(r, b):
1486
- t = _non_zero_ if mod is None else _integer_
1487
- t = _stresidual(t, r, mod=mod)
1488
- raise self._Error(op, other, ResidualError, txt=t)
1489
-
1490
- try: # b, other, mod all C{int}, unless C{mod} is C{None}
1491
- x = _2scalar(other, _raiser=self._raiser)
1492
- s = pow(b, x, mod)
1493
- if not iscomplex(s):
1494
- return self._finite(s)
1495
- # neg**frac == complex in Python 3+, but ValueError in 2-
1496
- raise ValueError(_strcomplex(s, b, x, mod)) # PYCHOK no cover
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
- if self._raiser(r, x):
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
- f = self
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
- while x:
1534
- p = p._mul_Fsum(p, op) # p **= 2
1535
- m += m # m <<= 1
1536
- if (x & m):
1537
- x -= m # x ^= m
1538
- f = f._mul_Fsum(p, op) # f *= p
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 = f._mul_Fsum(f, op)
1561
+ f = _mul_Fsum(self, self, op)
1541
1562
  if x > 2: # self**3 or 4
1542
- p = self if x < 4 else f
1543
- f = f._mul_Fsum(p, op)
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 = f._pow_0_1(x, other)
1566
+ f = self._pow_0_1(x, other)
1546
1567
  elif ps: # self._ps[0]**x
1547
- f = self._pow_2(ps[0], x, other, op)
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 # like ._fprs
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 _Fsum_ps(_1_0)._ftruediv(f, op)
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**-1 == 1 / self
1593
+ elif x < 0: # == -1: self**(-1) == 1 / self
1573
1594
  if r:
1574
- return _Fsum_ps(_1_0)._ftruediv(self, op)
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._pow_2(s, x, other, op)
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
- n = len(self._ps) + len(less) - 4
1590
- if n < 0:
1591
- yield _1_0
1610
+ yield _1_0
1592
1611
  for p in self._ps:
1593
- yield p
1612
+ yield p
1594
1613
  for p in less:
1595
1614
  yield -p
1596
- if n < 0:
1597
- yield _N_1_0
1598
-
1599
- def _ps_mul(self, op, *factors): # see .fmath.Fhorner
1600
- '''(INTERNAL) Yield all C{partials} times each B{C{factor}},
1601
- in total, up to C{len(partials) * len(factors)} items.
1602
- '''
1603
- ps = self._ps # tuple(self._ps)
1604
- if len(ps) < len(factors):
1605
- ps, factors = factors, ps
1606
- _f = _isfinite
1607
- for f in factors:
1608
- for p in ps:
1609
- p *= f
1610
- yield p if _f(p) else self._finite(p, op)
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: A L{ResidualError} is thrown if the non-zero I{ratio}
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 if res else (self._fprs, 0)
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 Fsum(self):
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 _Fsum_ps(*_2ps(s, r), name=self.name)
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.Fsum.is_exact()
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.Fsum.is_integer()
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
- return Fsum(name=_fsum.__name__).fsum(xs) if xs else _0_0
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: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
1859
- are known to be C{float}.
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: Exceptions and I{non-finite} handling may differ if not
1870
- based on Python's C{math.fsum}.
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: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
1883
- are known to be C{float}.
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 of a few arguments, 1-primed.
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: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
1905
- are known to be C{float}.
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 of a few arguments, 1-primed.
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: Optionally, use C{B{floats}=True} iff I{all} B{C{xs}}
1920
- are known to be C{float}.
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)