pygeodesy 24.5.2__py2.py3-none-any.whl → 24.5.8__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
@@ -27,36 +27,39 @@ from pygeodesy.basics import isbool, iscomplex, isint, isscalar, itemsorted, \
27
27
  signOf, _signOf
28
28
  from pygeodesy.constants import INT0, _isfinite, NEG0, _pos_self, \
29
29
  _0_0, _1_0, _N_1_0, Float, Int
30
- from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
31
- _ValueError, _xError, _xError2, _xkwds_get, \
32
- _ZeroDivisionError
30
+ from pygeodesy.errors import _OverflowError, _TypeError, _ValueError, \
31
+ _xError, _xError2, _xkwds_get
33
32
  from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DASH_, _DOT_, \
34
- _EQUAL_, _from_, _LANGLE_, _NOTEQUAL_, \
33
+ _enquote, _EQUAL_, _from_, _LANGLE_, _NOTEQUAL_, \
35
34
  _not_finite_, _PERCENT_, _PLUS_, _RANGLE_, \
36
35
  _SLASH_, _SPACE_, _STAR_, _UNDER_
37
36
  from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
38
- from pygeodesy.named import _Named, _NamedTuple, _NotImplemented, Fmt, unstr
37
+ from pygeodesy.named import _Named, _NamedTuple, _NotImplemented
39
38
  from pygeodesy.props import _allPropertiesOf_n, deprecated_property_RO, \
40
39
  Property_RO, property_RO
41
- # from pygeodesy.streprs import Fmt, unstr # from .named
40
+ from pygeodesy.streprs import Fmt, fstr, unstr
42
41
  # from pygeodesy.units import Float, Int # from .constants
43
42
 
44
43
  from math import ceil as _ceil, fabs, floor as _floor # PYCHOK used! .ltp
45
44
 
46
45
  __all__ = _ALL_LAZY.fsums
47
- __version__ = '24.05.02'
46
+ __version__ = '24.05.08'
48
47
 
48
+ _abs = abs
49
49
  _add_op_ = _PLUS_ # in .auxilats.auxAngle
50
50
  _eq_op_ = _EQUAL_ * 2 # _DEQUAL_
51
51
  _div_ = 'div'
52
+ _Float = float # in .fstats
52
53
  _floordiv_op_ = _SLASH_ * 2 # _DSLASH_
53
54
  _fset_op_ = _EQUAL_
54
55
  _ge_op_ = _RANGLE_ + _EQUAL_
55
56
  _gt_op_ = _RANGLE_
56
57
  _iadd_op_ = _add_op_ + _EQUAL_ # in .auxilats.auxAngle, .fstats
57
58
  _integer_ = 'integer'
58
- _isinstance = isinstance
59
+ _isAn = isinstance # in .fstats
59
60
  _le_op_ = _LANGLE_ + _EQUAL_
61
+ _len = len
62
+ _List = list
60
63
  _lt_op_ = _LANGLE_
61
64
  _mod_ = 'mod'
62
65
  _mod_op_ = _PERCENT_
@@ -68,6 +71,7 @@ _significant_ = 'significant'
68
71
  _sub_op_ = _DASH_ # in .auxilats.auxAngle
69
72
  _threshold_ = 'threshold'
70
73
  _truediv_op_ = _SLASH_
74
+ _Tuple = tuple # in .fstats
71
75
  _divmod_op_ = _floordiv_op_ + _mod_op_
72
76
  _isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
73
77
 
@@ -79,22 +83,28 @@ def _2delta(*ab):
79
83
  a, b = _2sum(*ab)
80
84
  except _OverflowError:
81
85
  a, b = ab
82
- return float(a if fabs(a) > fabs(b) else b)
86
+ return _Float(a if fabs(a) > fabs(b) else b)
83
87
 
84
88
 
85
- def _2error(unused):
89
+ def _2error(unused): # in .fstats
86
90
  '''(INTERNAL) Throw a C{not-finite} exception.
87
91
  '''
88
92
  raise ValueError(_not_finite_)
89
93
 
90
94
 
95
+ def _2finite(x):
96
+ '''(INTERNAL) return C{float(x)} if finite.
97
+ '''
98
+ x = _Float(x)
99
+ return x if _isfinite(x) else _2error(x)
100
+
101
+
91
102
  def _2float(index=None, **name_value): # in .fmath, .fstats
92
103
  '''(INTERNAL) Raise C{TypeError} or C{ValueError} if not scalar or infinite.
93
104
  '''
94
105
  n, v = name_value.popitem() # _xkwds_item2(name_value)
95
106
  try:
96
- v = float(v)
97
- return v if _isfinite(v) else _2error(v)
107
+ return _2finite(v)
98
108
  except Exception as X:
99
109
  raise _xError(X, Fmt.INDEX(n, index), v)
100
110
 
@@ -103,14 +113,14 @@ def _X_ps(X): # for _2floats only
103
113
  return X._ps
104
114
 
105
115
 
106
- def _2floats(xs, origin=0, _X=_X_ps, _x=float):
116
+ def _2floats(xs, origin=0, _X=_X_ps, _x=_Float):
107
117
  '''(INTERNAL) Yield each B{C{xs}} as a C{float}.
108
118
  '''
109
119
  try:
110
120
  i, x = origin, None
111
121
  _fin = _isfinite
112
122
  _FsT = _Fsum_Fsum2Tuple_types
113
- _is = _isinstance
123
+ _is = _isAn
114
124
  for x in xs:
115
125
  if _is(x, _FsT):
116
126
  for p in _X(x._Fsum):
@@ -147,16 +157,16 @@ def _2halfeven(s, r, p):
147
157
  return s
148
158
 
149
159
 
150
- def _isFsum(x):
160
+ def _isFsum(x): # in .fmath
151
161
  '''(INTERNAL) Is C{x} an C{Fsum} instance?
152
162
  '''
153
- return _isinstance(x, Fsum)
163
+ return _isAn(x, Fsum)
154
164
 
155
165
 
156
- def _isFsumTuple(x):
166
+ def _isFsumTuple(x): # in .fmath
157
167
  '''(INTERNAL) Is C{x} an C{Fsum} or C{Fsum2Tuple} instance?
158
168
  '''
159
- return _isinstance(x, _Fsum_Fsum2Tuple_types)
169
+ return _isAn(x, _Fsum_Fsum2Tuple_types)
160
170
 
161
171
 
162
172
  def _1_Over(x, op, **raiser_RESIDUAL): # vs _1_over
@@ -167,7 +177,7 @@ def _1_Over(x, op, **raiser_RESIDUAL): # vs _1_over
167
177
 
168
178
  def _1primed(xs): # in .fmath
169
179
  '''(INTERNAL) 1-Primed summation of iterable C{xs}
170
- items, all I{known} to be C{finite float}.
180
+ items, all I{known} to be C{scalar}.
171
181
  '''
172
182
  yield _1_0
173
183
  for x in xs:
@@ -178,8 +188,8 @@ def _1primed(xs): # in .fmath
178
188
  def _psum(ps): # PYCHOK used!
179
189
  '''(INTERNAL) Partials summation, updating C{ps}.
180
190
  '''
181
- # assert _isinstance(ps, list)
182
- i = len(ps) - 1
191
+ # assert _isAn(ps, _List)
192
+ i = _len(ps) - 1
183
193
  s = _0_0 if i < 0 else ps[i]
184
194
  _2s = _2sum
185
195
  while i > 0:
@@ -196,20 +206,20 @@ def _psum(ps): # PYCHOK used!
196
206
  return s
197
207
 
198
208
 
199
- def _Psum(ps, **name):
209
+ def _Psum(ps, **name_RESIDUAL):
200
210
  '''(INTERNAL) Return an C{Fsum} from I{ordered} partials C{ps}.
201
211
  '''
202
- F = Fsum(**name) if name else Fsum()
212
+ f = Fsum(**name_RESIDUAL) if name_RESIDUAL else Fsum()
203
213
  if ps:
204
- F._ps[:] = ps
205
- F._n = len(F._ps)
206
- return F
214
+ f._ps[:] = ps
215
+ f._n = _len(f._ps)
216
+ return f
207
217
 
208
218
 
209
- def _Psum_(*ps, **name):
219
+ def _Psum_(*ps, **name_RESIDUAL):
210
220
  '''(INTERNAL) Return an C{Fsum} from 1 or 2 known scalar(s) C{ps}.
211
221
  '''
212
- return _Psum(ps, **name)
222
+ return _Psum(ps, **name_RESIDUAL)
213
223
 
214
224
 
215
225
  def _2scalar2(other):
@@ -245,7 +255,7 @@ def _strcomplex(s, *args):
245
255
  '''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
246
256
  '''
247
257
  c = _strcomplex.__name__[4:]
248
- n = _DASH_(len(args), _arg_)
258
+ n = _DASH_(_len(args), _arg_)
249
259
  t = unstr(pow, *args)
250
260
  return _SPACE_(c, s, _from_, n, t)
251
261
 
@@ -278,7 +288,7 @@ def _threshold(threshold):
278
288
  '''(INTERNAL) Get the L{ResidualError}s threshold.
279
289
  '''
280
290
  try:
281
- t = float(threshold) or _0_0
291
+ t = _Float(threshold) or _0_0
282
292
  return t if _isfinite(t) else _2error(t) # PYCHOK None
283
293
  except Exception as x:
284
294
  raise ResidualError(threshold=threshold, cause=x)
@@ -305,10 +315,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
305
315
  file I{Modules/mathmodule.c} and the issue log U{Full precision summation
306
316
  <https://Bugs.Python.org/issue2819>}.
307
317
  '''
308
- _math_fsum = None
318
+ _math_fsum = None
309
319
  _n = 0
310
320
  # _ps = [] # partial sums
311
- # _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps))
321
+ # _ps_max = 0 # max(Fsum._ps_max, _len(Fsum._ps))
312
322
  _RESIDUAL = _threshold(_getenv('PYGEODESY_FSUM_RESIDUAL', _0_0))
313
323
 
314
324
  def __init__(self, *xs, **name_RESIDUAL):
@@ -323,12 +333,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
323
333
  '''
324
334
  if name_RESIDUAL:
325
335
 
326
- def _n_r(name=NN, RESIDUAL=None):
336
+ def _n_R(name=NN, RESIDUAL=None):
327
337
  return name, RESIDUAL
328
338
 
329
- n, r = _n_r(**name_RESIDUAL)
330
- if r is not None:
331
- self.RESIDUAL(r)
339
+ n, R = _n_R(**name_RESIDUAL)
340
+ if R is not None:
341
+ self.RESIDUAL(R)
332
342
  if n:
333
343
  self.name = n
334
344
 
@@ -349,12 +359,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
349
359
 
350
360
  @return: The sum (L{Fsum}).
351
361
 
352
- @see: Method L{Fsum.__iadd__}.
362
+ @see: Methods L{Fsum.fadd_} and L{Fsum.fadd}.
353
363
  '''
354
364
  f = self._copy_2(self.__add__)
355
365
  return f._fadd(other, _add_op_)
356
366
 
357
- def __bool__(self): # PYCHOK not special in Python 2-
367
+ def __bool__(self): # PYCHOK Python 3+
358
368
  '''Return C{True} if this instance is I{exactly} non-zero.
359
369
  '''
360
370
  s, r = self._fprs2
@@ -392,7 +402,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
392
402
  @raise ResidualError: Non-zero, significant residual or invalid
393
403
  B{C{RESIDUAL}}.
394
404
 
395
- @see: Method L{Fsum.__itruediv__}.
405
+ @see: Method L{Fsum.fdiv}.
396
406
  '''
397
407
  f = self._copy_2(self.__divmod__)
398
408
  return f._fdivmod2(other, _divmod_op_, **raiser_RESIDUAL)
@@ -407,7 +417,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
407
417
 
408
418
  @see: Methods L{Fsum.fsum} and L{Fsum.int_float}.
409
419
  '''
410
- return float(self._fprs)
420
+ return _Float(self._fprs)
411
421
 
412
422
  def __floor__(self): # PYCHOK not special in Python 2-
413
423
  '''Return this instance' C{math.floor} as C{int} or C{float}.
@@ -459,7 +469,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
459
469
  @raise TypeError: Invalid B{C{other}}, not
460
470
  C{scalar} nor L{Fsum}.
461
471
 
462
- @see: Methods L{Fsum.fadd} and L{Fsum.fadd_}.
472
+ @see: Methods L{Fsum.fadd_} and L{Fsum.fadd}.
463
473
  '''
464
474
  return self._fadd(other, _iadd_op_)
465
475
 
@@ -516,9 +526,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
516
526
  def __int__(self):
517
527
  '''Return this instance as an C{int}.
518
528
 
519
- @see: Methods L{Fsum.int_float}, L{Fsum.__ceil__}
520
- and L{Fsum.__floor__} and properties
521
- L{Fsum.ceil} and L{Fsum.floor}.
529
+ @see: Method L{Fsum.int_float} and properties L{Fsum.ceil}
530
+ and L{Fsum.floor}.
522
531
  '''
523
532
  i, _ = self._fint2
524
533
  return i
@@ -575,7 +584,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
575
584
 
576
585
  @raise TypeError: Invalid B{C{other}} type.
577
586
 
578
- @see: Method L{Fsum.fadd}.
587
+ @see: Methods L{Fsum.fsub_} and L{Fsum.fsub}.
579
588
  '''
580
589
  return self._fsub(other, _isub_op_)
581
590
 
@@ -725,7 +734,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
725
734
  '''
726
735
  f = self._copy_2(self.__round__)
727
736
  # <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
728
- return f._fset(round(float(self), *ndigits)) # can be C{int}
737
+ return f._fset(round(_Float(self), *ndigits)) # can be C{int}
729
738
 
730
739
  def __rpow__(self, other, *mod):
731
740
  '''Return C{B{other}**B{self}} as an L{Fsum}.
@@ -783,8 +792,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
783
792
 
784
793
  @see: Method L{Fsum.__itruediv__}.
785
794
  '''
786
- f = self._copy_2(self.__truediv__)
787
- return f._ftruediv(other, _truediv_op_, **raiser_RESIDUAL)
795
+ return self._truediv(other, _truediv_op_, **raiser_RESIDUAL)
788
796
 
789
797
  __trunc__ = __int__
790
798
 
@@ -799,14 +807,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
799
807
  def as_integer_ratio(self):
800
808
  '''Return this instance as the ratio of 2 integers.
801
809
 
802
- @return: 2-Tuple C{(numerator, denominator)} both
803
- C{int} and with positive C{denominator}.
810
+ @return: 2-Tuple C{(numerator, denominator)} both C{int}
811
+ with C{numerator} signed and C{denominator}
812
+ non-zero, positive.
804
813
 
805
- @see: Standard C{float.as_integer_ratio} in Python 3+.
814
+ @see: Standard C{float.as_integer_ratio} in Python 2.7+.
806
815
  '''
807
816
  n, r = self._fint2
808
817
  if r:
809
- i, d = float(r).as_integer_ratio()
818
+ i, d = _Float(r).as_integer_ratio()
810
819
  n *= d
811
820
  n += i
812
821
  else: # PYCHOK no cover
@@ -815,17 +824,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
815
824
 
816
825
  @property_RO
817
826
  def as_iscalar(self):
818
- '''Get this instance I{as-is} (L{Fsum}) or as C{scalar} iff scalar.
827
+ '''Get this instance I{as-is} (L{Fsum} or C{scalar}), the
828
+ latter only if the C{residual} equals C{zero}.
819
829
  '''
820
830
  s, r = self._fprs2
821
831
  return self if r else s
822
832
 
823
833
  @property_RO
824
834
  def ceil(self):
825
- '''Get this instance' C{ceil} value (C{int} in Python 3+,
826
- but C{float} in Python 2-).
835
+ '''Get this instance' C{ceil} value (C{int} in Python 3+, but
836
+ C{float} in Python 2-).
827
837
 
828
- @note: The C{ceil} takes the C{residual} into account.
838
+ @note: This C{ceil} takes the C{residual} into account.
829
839
 
830
840
  @see: Method L{Fsum.int_float} and properties L{Fsum.floor},
831
841
  L{Fsum.imag} and L{Fsum.real}.
@@ -834,7 +844,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
834
844
  c = _ceil(s) + int(r) - 1
835
845
  while r > (c - s): # (s + r) > c
836
846
  c += 1
837
- return c
847
+ return c # _ceil(self._n_d)
838
848
 
839
849
  cmp = __cmp__
840
850
 
@@ -842,11 +852,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
842
852
  '''(INTERNAL) Return C{scalar(self - B{other})} for 0-comparison.
843
853
  '''
844
854
  if _isFsumTuple(other):
845
- s = _fsum(self._ps_1primed(*other._ps))
855
+ s = self._ps_1sum(*other._ps)
846
856
  elif self._scalar(other, op):
847
- s = _fsum(self._ps_1primed(other))
857
+ s = self._ps_1sum(other)
848
858
  else:
849
- s = self.signOf() # res=True
859
+ s = self.signOf() # res=True
850
860
  return s
851
861
 
852
862
  def copy(self, deep=False, name=NN):
@@ -856,9 +866,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
856
866
  '''
857
867
  f = _Named.copy(self, deep=deep, name=name)
858
868
  if f._ps is self._ps:
859
- f._ps = list(self._ps) # separate list
869
+ f._ps = _List(self._ps) # separate list
860
870
  if not deep:
861
871
  f._n = 1
872
+ # assert f._Fsum is f
862
873
  return f
863
874
 
864
875
  def _copy_2(self, which, name=NN):
@@ -867,8 +878,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
867
878
  n = name or which.__name__
868
879
  # NOT .classof due to .Fdot(a, *b) args, etc.
869
880
  f = _Named.copy(self, deep=False, name=n)
881
+ f._ps = _List(self._ps) # separate list
870
882
  # assert f._n == self._n
871
- f._ps = list(self._ps) # separate list
883
+ # assert f._Fsum is f
872
884
  return f
873
885
 
874
886
  def _copy_2r(self, other, which):
@@ -903,7 +915,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
903
915
  '''(INTERNAL) Format the caught exception C{X}.
904
916
  '''
905
917
  E, t = _xError2(X)
906
- u = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
918
+ u = unstr(self.named3, *xs[:3], _ELLIPSIS=_len(xs) > 3, **kwds)
907
919
  return E(u, txt=t, cause=X)
908
920
 
909
921
  def _facc(self, xs, up=True, **origin_X_x):
@@ -912,14 +924,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
912
924
  if xs:
913
925
  _xs = _2floats(xs, **origin_X_x) # PYCHOK yield
914
926
  ps = self._ps
915
- ps[:] = self._ps_acc(list(ps), _xs, up=up)
927
+ ps[:] = self._ps_acc(_List(ps), _xs, up=up)
916
928
  return self
917
929
 
918
930
  def _facc_1(self, xs, **up):
919
931
  '''(INTERNAL) Accumulate 0, 1 or more C{scalars} or L{Fsum}s,
920
932
  all positional C{xs} in the caller of this method.
921
933
  '''
922
- return self._fadd(xs[0], _add_op_, **up) if len(xs) == 1 else \
934
+ return self._fadd(xs[0], _add_op_, **up) if _len(xs) == 1 else \
923
935
  self._facc(xs, origin=1, **up)
924
936
 
925
937
  def _facc_neg(self, xs, **up_origin):
@@ -929,7 +941,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
929
941
  return X._ps_neg
930
942
 
931
943
  def _n(x):
932
- return -float(x)
944
+ return -_Float(x)
933
945
 
934
946
  return self._facc(xs, _X=_N, _x=_n, **up_origin)
935
947
 
@@ -955,15 +967,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
955
967
  _Pow, p, s, r = _Pow4(power)
956
968
  if p: # and xs:
957
969
  op = which.__name__
958
- _isF = _isFsum
970
+ _Fs = Fsum
971
+ _is = _isAn
959
972
  _pow = self._pow_2_3
960
973
 
961
974
  def _P(X):
962
975
  f = _Pow(X, p, power, op, **raiser_RESIDUAL)
963
- return f._ps if _isF(f) else (f,)
976
+ return f._ps if _is(f, _Fs) else (f,)
964
977
 
965
978
  def _p(x):
966
- x = float(x)
979
+ x = _Float(x)
967
980
  f = _pow(x, s, power, op, **raiser_RESIDUAL)
968
981
  if f and r:
969
982
  f *= _pow(x, r, power, op, **raiser_RESIDUAL)
@@ -971,7 +984,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
971
984
 
972
985
  f = self._facc(xs, origin=1, _X=_P, _x=_p)
973
986
  else:
974
- f = self._facc_scalar_(float(len(xs))) # x**0 == 1
987
+ f = self._facc_scalar_(_Float(_len(xs))) # x**0 == 1
975
988
  return f
976
989
 
977
990
  def _facc_scalar(self, xs, **up):
@@ -993,7 +1006,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
993
1006
  # and re-accumulating the final C{partial}.
994
1007
  # '''
995
1008
  # ps = self._ps
996
- # while len(ps) > 1:
1009
+ # while _len(ps) > 1:
997
1010
  # p = ps.pop()
998
1011
  # if p:
999
1012
  # n = self._n
@@ -1003,7 +1016,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1003
1016
  # return self._update() if up else self
1004
1017
 
1005
1018
  def fadd(self, xs=()):
1006
- '''Add all items from an iterable to this instance.
1019
+ '''Add an iterable's items to this instance.
1007
1020
 
1008
1021
  @arg xs: Iterable of items to add (each C{scalar}
1009
1022
  or an L{Fsum} or L{Fsum2Tuple} instance).
@@ -1017,7 +1030,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1017
1030
  @raise ValueError: Invalid or non-finite B{C{xs}} value.
1018
1031
  '''
1019
1032
  if _isFsumTuple(xs):
1020
- self._facc_scalar(xs._ps) # tuple(xs._ps)
1033
+ self._facc_scalar(xs._ps) # _Tuple(xs._ps)
1021
1034
  elif isscalar(xs): # for backward compatibility
1022
1035
  self._facc_scalar_(_2float(x=xs)) # PYCHOK no cover
1023
1036
  elif xs: # assert isiterable(xs)
@@ -1025,7 +1038,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1025
1038
  return self
1026
1039
 
1027
1040
  def fadd_(self, *xs):
1028
- '''Add all positional arguments to this instance.
1041
+ '''Add all positional items to this instance.
1029
1042
 
1030
1043
  @arg xs: Values to add (each C{scalar} or an L{Fsum}
1031
1044
  or L{Fsum2Tuple} instance), all positional.
@@ -1037,15 +1050,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1037
1050
  def _fadd(self, other, op, **up): # in .fmath.Fhorner
1038
1051
  '''(INTERNAL) Apply C{B{self} += B{other}}.
1039
1052
  '''
1040
- if _isFsumTuple(other):
1041
- self._facc_scalar(other._ps, **up) # tuple
1053
+ if not self._ps: # new Fsum(x)
1054
+ self._fset(other, as_is=False, **up)
1055
+ elif _isFsumTuple(other):
1056
+ self._facc_scalar(other._ps, **up) # _Tuple
1042
1057
  elif self._scalar(other, op):
1043
1058
  self._facc_scalar_(other, **up)
1044
1059
  return self
1045
1060
 
1046
- fcopy = copy # for backward compatibility
1047
- fdiv = __itruediv__ # for backward compatibility
1048
- fdivmod = __divmod__ # for backward compatibility
1061
+ fcopy = copy # for backward compatibility
1062
+ fdiv = __itruediv__
1063
+ fdivmod = __divmod__
1049
1064
 
1050
1065
  def _fdivmod2(self, other, op, **raiser_RESIDUAL):
1051
1066
  '''(INTERNAL) Apply C{B{self} %= B{other}} and return a L{DivMod2Tuple}.
@@ -1053,10 +1068,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1053
1068
  # result mostly follows CPython function U{float_divmod
1054
1069
  # <https://GitHub.com/python/cpython/blob/main/Objects/floatobject.c>},
1055
1070
  # but at least divmod(-3, 2) equals Cpython's result (-2, 1).
1056
- q = self._copy_2(self._fdivmod2)
1057
- q = q._ftruediv(other, op, **raiser_RESIDUAL).floor
1071
+ q = self._truediv(other, op, **raiser_RESIDUAL).floor
1058
1072
  if q: # == float // other == floor(float / other)
1059
- self -= Fsum(other) * q # NO Fsum2Tuple.__mul__!
1073
+ self -= Fsum(q) * other # NOT other * q!
1060
1074
 
1061
1075
  s = signOf(other) # make signOf(self) == signOf(other)
1062
1076
  if s and self.signOf() == -s: # PYCHOK no cover
@@ -1073,7 +1087,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1073
1087
  if _isfinite(other):
1074
1088
  return other
1075
1089
  raise ValueError(_not_finite_) if op is None else \
1076
- self._ValueError(op, other, txt=_not_finite_)
1090
+ self._Error(op, other, _ValueError, txt=_not_finite_)
1077
1091
 
1078
1092
  def fint(self, name=NN, **raiser_RESIDUAL):
1079
1093
  '''Return this instance' current running sum as C{integer}.
@@ -1089,7 +1103,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1089
1103
  @raise ResidualError: Non-zero, significant residual or invalid
1090
1104
  B{C{RESIDUAL}}.
1091
1105
 
1092
- @see: Methods L{Fsum.int_float} and L{Fsum.is_integer}.
1106
+ @see: Methods L{Fsum.fint2}, L{Fsum.int_float} and L{Fsum.is_integer}.
1093
1107
  '''
1094
1108
  i, r = self._fint2
1095
1109
  if r:
@@ -1118,7 +1132,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1118
1132
  '''
1119
1133
  s, r = self._fprs2
1120
1134
  i = int(s)
1121
- r = _fsum(self._ps_1primed(i)) if r else float(s - i)
1135
+ n = _len(self._ps)
1136
+ r = self._ps_1sum(i) if r and n > 1 else _Float(s - i)
1122
1137
  return i, (r or INT0) # Fsum2Tuple?
1123
1138
 
1124
1139
  @deprecated_property_RO
@@ -1131,7 +1146,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1131
1146
  '''Get this instance' C{floor} (C{int} in Python 3+, but
1132
1147
  C{float} in Python 2-).
1133
1148
 
1134
- @note: The C{floor} takes the C{residual} into account.
1149
+ @note: This C{floor} takes the C{residual} into account.
1135
1150
 
1136
1151
  @see: Method L{Fsum.int_float} and properties L{Fsum.ceil},
1137
1152
  L{Fsum.imag} and L{Fsum.real}.
@@ -1140,9 +1155,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1140
1155
  f = _floor(s) + _floor(r) + 1
1141
1156
  while (f - s) > r: # f > (s + r)
1142
1157
  f -= 1
1143
- return f
1158
+ return f # _floor(self._n_d)
1144
1159
 
1145
- # floordiv = __floordiv__ # for naming consistency
1160
+ # ffloordiv = __ifloordiv__ # for naming consistency
1161
+ # floordiv = __floordiv__ # for naming consistency
1146
1162
 
1147
1163
  def _floordiv(self, other, op, **raiser_RESIDUAL): # rather _ffloordiv?
1148
1164
  '''Apply C{B{self} //= B{other}}.
@@ -1150,22 +1166,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1150
1166
  q = self._ftruediv(other, op, **raiser_RESIDUAL) # == self
1151
1167
  return self._fset(q.floor) # floor(q)
1152
1168
 
1153
- fmul = __imul__ # for backward compatibility
1169
+ fmul = __imul__
1154
1170
 
1155
1171
  def _fmul(self, other, op):
1156
1172
  '''(INTERNAL) Apply C{B{self} *= B{other}}.
1157
1173
  '''
1158
1174
  if _isFsumTuple(other):
1159
- if len(self._ps) != 1:
1175
+ if _len(self._ps) != 1:
1160
1176
  f = self._mul_Fsum(other, op)
1161
- elif len(other._ps) != 1: # and len(self._ps) == 1
1177
+ elif _len(other._ps) != 1: # and _len(self._ps) == 1
1162
1178
  f = other._mul_scalar(self._ps[0], op)
1163
- else: # len(other._ps) == len(self._ps) == 1
1179
+ else: # _len(other._ps) == _len(self._ps) == 1
1164
1180
  f = self._finite(self._ps[0] * other._ps[0])
1165
1181
  else:
1166
1182
  s = self._scalar(other, op)
1167
1183
  f = self._mul_scalar(s, op)
1168
- return self._fset(f) # n=len(self) + 1
1184
+ return self._fset(f) # n=_len(self) + 1
1169
1185
 
1170
1186
  def fover(self, over, **raiser_RESIDUAL):
1171
1187
  '''Apply C{B{self} /= B{over}} and summate.
@@ -1182,9 +1198,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1182
1198
 
1183
1199
  @see: Methods L{Fsum.fsum} and L{Fsum.__itruediv__}.
1184
1200
  '''
1185
- return float(self.fdiv(over, **raiser_RESIDUAL)._fprs)
1201
+ return _Float(self.fdiv(over, **raiser_RESIDUAL)._fprs)
1186
1202
 
1187
- fpow = __ipow__ # for backward compatibility
1203
+ fpow = __ipow__
1188
1204
 
1189
1205
  def _fpow(self, other, op, *mod, **raiser_RESIDUAL):
1190
1206
  '''Apply C{B{self} **= B{other}}, optional B{C{mod}} or C{None}.
@@ -1202,7 +1218,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1202
1218
  f = self._pow(other, other, op, **raiser_RESIDUAL)
1203
1219
  else: # pow(self, other)
1204
1220
  f = self._pow(other, other, op, **raiser_RESIDUAL)
1205
- return self._fset(f, asis=isint(f)) # n=max(len(self), 1)
1221
+ return self._fset(f, as_is=isint(f)) # n=max(_len(self), 1)
1206
1222
 
1207
1223
  @Property_RO
1208
1224
  def _fprs(self):
@@ -1212,47 +1228,49 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1212
1228
  @note: The precision running C{fsum} after a C{//=} or
1213
1229
  C{//} C{floor} division is C{int} in Python 3+.
1214
1230
  '''
1215
- return self._fprs2.fsum
1231
+ s, _ = self._fprs2
1232
+ return s # ._fprs2.fsum
1216
1233
 
1217
1234
  @Property_RO
1218
1235
  def _fprs2(self):
1219
1236
  '''(INTERNAL) Get and cache this instance' precision
1220
1237
  running sum and residual (L{Fsum2Tuple}).
1221
1238
  '''
1222
- ps = self._ps
1223
- n = len(ps) - 2
1224
- if n > 0: # len(ps) > 2
1239
+ ps = self._ps
1240
+ n = _len(ps) - 2
1241
+ if n > 0: # _len(ps) > 2
1225
1242
  s = _psum(ps)
1226
- n = len(ps) - 2
1243
+ n = _len(ps) - 2
1227
1244
  if n > 0:
1228
- r = _fsum(self._ps_1primed(s))
1245
+ r = self._ps_1sum(s)
1229
1246
  return Fsum2Tuple(*_s_r(s, r))
1230
- if n == 0: # len(ps) == 2
1247
+ if n == 0: # _len(ps) == 2
1231
1248
  s, r = _s_r(*_2sum(*ps))
1232
1249
  ps[:] = (r, s) if r else (s,)
1233
- elif ps: # len(ps) == 1
1250
+ elif ps: # _len(ps) == 1
1234
1251
  s, r = ps[0], INT0
1235
- else: # len(ps) == 0
1252
+ else: # _len(ps) == 0
1236
1253
  s, r = _0_0, INT0
1237
1254
  ps[:] = s,
1238
1255
  # assert self._ps is ps
1239
1256
  return Fsum2Tuple(s, r)
1240
1257
 
1241
1258
  def fset_(self, *xs):
1242
- '''Replace this instance' value with C{xs}.
1259
+ '''Replace this instance' value with all positional items.
1243
1260
 
1244
1261
  @arg xs: Optional, new values (each C{scalar} or
1245
1262
  an L{Fsum} or L{Fsum2Tuple} instance),
1246
1263
  all positional.
1247
1264
 
1248
- @return: This instance (C{Fsum}).
1265
+ @return: This instance, replaced (C{Fsum}).
1249
1266
 
1250
1267
  @see: Method L{Fsum.fadd} for further details.
1251
1268
  '''
1252
- f = Fsum(*xs) if xs else _0_0
1269
+ f = xs[0] if len(xs) == 1 else (
1270
+ Fsum(*xs) if xs else _0_0)
1253
1271
  return self._fset(f)
1254
1272
 
1255
- def _fset(self, other, asis=True, n=0):
1273
+ def _fset(self, other, as_is=True, n=0, up=True):
1256
1274
  '''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
1257
1275
  '''
1258
1276
  if other is self:
@@ -1261,21 +1279,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1261
1279
  self._ps[:] = other._ps
1262
1280
  self._n = n or other._n
1263
1281
  # self._copy_RESIDUAL(other)
1264
- # use or zap the C{Property_RO} values
1265
- Fsum._fint2._update_from(self, other)
1266
- Fsum._fprs ._update_from(self, other)
1267
- Fsum._fprs2._update_from(self, other)
1282
+ if up: # use or zap the C{Property_RO} values
1283
+ Fsum._fint2._update_from(self, other)
1284
+ Fsum._fprs ._update_from(self, other)
1285
+ Fsum._fprs2._update_from(self, other)
1268
1286
  elif isscalar(other):
1269
- s = other if asis else float(other)
1270
- i = int(s) # see ._fint2
1271
- t = i, ((s - i) or INT0)
1287
+ s = other if as_is else _Float(other)
1272
1288
  self._ps[:] = s,
1273
1289
  self._n = n or 1
1274
- # Property_ROs _fint2, _fprs and _fprs2 can't be a Property:
1275
- # Property's _fset zaps the value just set by the @setter
1276
- self.__dict__.update(_fint2=t, _fprs=s, _fprs2=Fsum2Tuple(s, INT0))
1290
+ if up:
1291
+ i = int(s) # see ._fint2
1292
+ t = i, ((s - i) or INT0)
1293
+ # Property_ROs _fint2, _fprs and _fprs2 can't be a Property:
1294
+ # Property's _fset zaps the value just set by the @setter
1295
+ self.__dict__.update(_fint2=t, _fprs=s, _fprs2=Fsum2Tuple(s, INT0))
1277
1296
  else: # PYCHOK no cover
1278
- raise self._Error(_fset_op_, other, _AssertionError)
1297
+ raise self._Error(_fset_op_, other, _TypeError)
1279
1298
  return self
1280
1299
 
1281
1300
  def _fset_ps(self, other, n=0): # in .fmath
@@ -1290,18 +1309,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1290
1309
  return self
1291
1310
 
1292
1311
  def fsub(self, xs=()):
1293
- '''Subtract all items of an iterable from this instance.
1312
+ '''Subtract an iterable's items from this instance.
1294
1313
 
1295
1314
  @see: Method L{Fsum.fadd} for further details.
1296
1315
  '''
1297
1316
  return self._facc_neg(xs)
1298
1317
 
1299
1318
  def fsub_(self, *xs):
1300
- '''Subtract all positional arguments from this instance.
1319
+ '''Subtract all positional items from this instance.
1301
1320
 
1302
1321
  @see: Method L{Fsum.fadd_} for further details.
1303
1322
  '''
1304
- return self._fsub(xs[0], _sub_op_) if len(xs) == 1 else \
1323
+ return self._fsub(xs[0], _sub_op_) if _len(xs) == 1 else \
1305
1324
  self._facc_neg(xs, origin=1)
1306
1325
 
1307
1326
  def _fsub(self, other, op):
@@ -1309,7 +1328,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1309
1328
  '''
1310
1329
  if _isFsumTuple(other):
1311
1330
  if other is self: # or other._fprs2 == self._fprs2:
1312
- self._fset(_0_0, n=len(self) * 2)
1331
+ self._fset(_0_0, n=_len(self) * 2)
1313
1332
  elif other._ps:
1314
1333
  self._facc_scalar(other._ps_neg)
1315
1334
  elif self._scalar(other, op):
@@ -1317,8 +1336,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1317
1336
  return self
1318
1337
 
1319
1338
  def fsum(self, xs=()):
1320
- '''Add more items from an iterable, summate and return
1321
- the current precision running sum.
1339
+ '''Add an iterable's items, summate and return the
1340
+ current precision running sum.
1322
1341
 
1323
1342
  @arg xs: Iterable of items to add (each item C{scalar}
1324
1343
  or an L{Fsum} or L{Fsum2Tuple} instance).
@@ -1332,10 +1351,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1332
1351
  return self._facc(xs)._fprs
1333
1352
 
1334
1353
  def fsum_(self, *xs):
1335
- '''Add any positional arguments, summate and return the
1354
+ '''Add any positional items, summate and return the
1336
1355
  current precision running sum.
1337
1356
 
1338
- @arg xs: Values to add (each C{scalar} or an L{Fsum}
1357
+ @arg xs: Items to add (each C{scalar} or an L{Fsum}
1339
1358
  or L{Fsum2Tuple} instance), all positional.
1340
1359
 
1341
1360
  @return: Precision running sum (C{float} or C{int}).
@@ -1345,17 +1364,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1345
1364
  return self._facc_1(xs)._fprs
1346
1365
 
1347
1366
  @property_RO
1348
- def _Fsum(self):
1349
- '''(INTERNAL) Like L{Fsum2Tuple._Fsum}, for C{_2floats}.
1350
- '''
1351
- return self
1367
+ def _Fsum(self): # like L{Fsum2Tuple._Fsum}, for C{_2floats}, .fstats
1368
+ return self # NOT @Property_RO, see .copy and ._copy_2
1352
1369
 
1353
1370
  def Fsum_(self, *xs, **name):
1354
1371
  '''Like method L{Fsum.fsum_} but returning a named L{Fsum}.
1355
1372
 
1356
1373
  @kwarg name: Optional name (C{str}).
1357
1374
 
1358
- @return: Current, precision running sum (L{Fsum}).
1375
+ @return: Copy of this updated instance (L{Fsum}).
1359
1376
  '''
1360
1377
  return self._facc_1(xs)._copy_2(self.Fsum_, **name)
1361
1378
 
@@ -1364,12 +1381,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1364
1381
 
1365
1382
  @kwarg name: Optional name (C{str}).
1366
1383
 
1367
- @return: Current, precision running sum (L{Fsum2Tuple}).
1384
+ @return: Precision running sum (L{Fsum2Tuple}).
1368
1385
  '''
1369
1386
  return Fsum2Tuple(self._facc_1(xs)._fprs2, **name)
1370
1387
 
1371
1388
  def fsum2(self, xs=(), name=NN):
1372
- '''Add more items from an iterable, summate and return the
1389
+ '''Add an iterable's items, summate and return the
1373
1390
  current precision running sum I{and} the C{residual}.
1374
1391
 
1375
1392
  @arg xs: Iterable of items to add (each item C{scalar}
@@ -1388,8 +1405,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1388
1405
  return t.dup(name=name) if name else t
1389
1406
 
1390
1407
  def fsum2_(self, *xs):
1391
- '''Add any positional arguments, summate and return the current
1392
- precision running sum I{and} the C{differential}.
1408
+ '''Add any positional items, summate and return the current
1409
+ precision running sum and the I{differential}.
1393
1410
 
1394
1411
  @arg xs: Values to add (each C{scalar} or an L{Fsum} or
1395
1412
  L{Fsum2Tuple} instance), all positional.
@@ -1435,7 +1452,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1435
1452
  n = _1_0
1436
1453
  if _isFsumTuple(other):
1437
1454
  if other is self or self == other:
1438
- return self._fset(n) # n=len(self)
1455
+ return self._fset(n) # n=_len(self)
1439
1456
  d, r = other._fprs2
1440
1457
  if r:
1441
1458
  R = self._raiser(r, d, **raiser_RESIDUAL)
@@ -1449,13 +1466,13 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1449
1466
  except Exception as X:
1450
1467
  raise self._ErrorX(X, op, other)
1451
1468
  f = self._mul_scalar(s, _mul_op_) # handles 0, INF, NAN
1452
- return self._fset(f) # asis=False
1469
+ return self._fset(f) # as_is=False
1453
1470
 
1454
1471
  @property_RO
1455
1472
  def imag(self):
1456
1473
  '''Get the C{imaginary} part of this instance (C{0.0}, always).
1457
1474
 
1458
- @see: Properties L{Fsum.ceil}, L{Fsum.floor} and L{Fsum.real}.
1475
+ @see: Property L{Fsum.real}.
1459
1476
  '''
1460
1477
  return _0_0
1461
1478
 
@@ -1484,11 +1501,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1484
1501
  if R:
1485
1502
  t = _stresidual(_non_zero_, r, **R)
1486
1503
  raise ResidualError(int_float=s, txt=t)
1487
- s = float(s) # redundant
1504
+ s = _Float(s) # redundant
1488
1505
  return s
1489
1506
 
1490
1507
  def is_exact(self):
1491
- '''Is this instance' running C{fsum} considered to be exact? (C{bool}).
1508
+ '''Is this instance' running C{fsum} considered to be exact?
1509
+ (C{bool}), C{True} only if the C{residual is }L{INT0}.
1492
1510
  '''
1493
1511
  return self.residual is INT0
1494
1512
 
@@ -1515,13 +1533,15 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1515
1533
  return 2 if _psum is f else bool(f)
1516
1534
 
1517
1535
  def is_scalar(self, **raiser_RESIDUAL):
1518
- '''Is this instance' running sum C{scalar} with an insignificant
1519
- residual and the residual I{ratio} not exceeding the RESIDUAL
1520
- threshold? (C{bool}).
1536
+ '''Is this instance' running sum C{scalar} without residual or with
1537
+ a residual I{ratio} not exceeding the RESIDUAL threshold?
1521
1538
 
1522
- @kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to
1523
- ignore L{ResidualError}s and C{B{RESIDUAL}=scalar}
1524
- to override the L{RESIDUAL<Fsum.RESIDUAL>}.
1539
+ @kwarg raiser_RESIDUAL: Use C{B{raiser}=False} (C{bool}) to ignore
1540
+ L{ResidualError}s and C{B{RESIDUAL}=scalar} to override
1541
+ the L{RESIDUAL<Fsum.RESIDUAL>} threshold.
1542
+
1543
+ @return: C{True} if this instance' non-zero residual C{ratio} exceeds
1544
+ the L{RESIDUAL<Fsum.RESIDUAL>} threshold (C{bool}).
1525
1545
 
1526
1546
  @raise ResidualError: Non-zero, significant residual or invalid
1527
1547
  B{C{RESIDUAL}}.
@@ -1537,23 +1557,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1537
1557
  '''
1538
1558
  # assert _isFsumTuple(other)
1539
1559
  if self._ps and other._ps:
1540
- f = self._ps_mul(op, *other._ps) # NO .as_iscalar
1560
+ f = self._ps_mul(op, *other._ps) # NO .as_iscalar!
1541
1561
  else:
1542
1562
  f = _0_0
1543
1563
  return f
1544
1564
 
1545
1565
  def _mul_scalar(self, factor, op): # in .fmath.Fhorner
1546
- '''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum}, C{0} or C{self}.
1566
+ '''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum}, C{0.0} or C{self}.
1547
1567
  '''
1548
1568
  # assert isscalar(factor)
1549
1569
  if self._ps and self._finite(factor, op):
1550
- f = self if factor == _1_0 else (
1570
+ f = self if factor == _1_0 else (
1551
1571
  self._neg if factor == _N_1_0 else
1552
1572
  self._ps_mul(op, factor).as_iscalar)
1553
1573
  else:
1554
1574
  f = _0_0
1555
1575
  return f
1556
1576
 
1577
+ # @property_RO
1578
+ # def _n_d(self):
1579
+ # n, d = self.as_integer_ratio()
1580
+ # return n / d
1581
+
1557
1582
  @property_RO
1558
1583
  def _neg(self):
1559
1584
  '''(INTERNAL) Return C{Fsum(-self)} or scalar C{NEG0}.
@@ -1564,7 +1589,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1564
1589
  def partials(self):
1565
1590
  '''Get this instance' current, partial sums (C{tuple} of C{float}s).
1566
1591
  '''
1567
- return tuple(self._ps)
1592
+ return _Tuple(self._ps)
1568
1593
 
1569
1594
  def pow(self, x, *mod, **raiser_RESIDUAL):
1570
1595
  '''Return C{B{self}**B{x}} as L{Fsum}.
@@ -1652,7 +1677,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1652
1677
  '''
1653
1678
  # assert isint(x) and x >= 0
1654
1679
  ps = self._ps
1655
- if len(ps) > 1:
1680
+ if _len(ps) > 1:
1656
1681
  _mul_Fsum = Fsum._mul_Fsum
1657
1682
  if x > 4:
1658
1683
  p = self
@@ -1663,11 +1688,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1663
1688
  if (m & 1):
1664
1689
  f = _mul_Fsum(f, p, op) # f *= p
1665
1690
  m >>= 1 # //= 2
1666
- elif x > 1: # self**2, 3 or 4
1691
+ elif x > 1: # self**2, 3, or 4
1667
1692
  f = _mul_Fsum(self, self, op)
1668
1693
  if x > 2: # self**3 or 4
1669
1694
  p = self if x < 4 else f
1670
- f = _mul_Fsum(f, p, op).as_iscalar
1695
+ f = _mul_Fsum(f, p, op)
1671
1696
  else: # self**1 or self**0 == 1 or _1_0
1672
1697
  f = self._pow_0_1(x, other)
1673
1698
  elif ps: # self._ps[0]**x
@@ -1684,8 +1709,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1684
1709
  if r:
1685
1710
  # assert s != 0
1686
1711
  if isint(x, both=True): # self**int
1687
- x = int(x)
1688
- y = abs(x)
1712
+ x = int(x)
1713
+ y = _abs(x)
1689
1714
  if y > 1:
1690
1715
  f = self._pow_int(y, other, op, **raiser_RESIDUAL)
1691
1716
  if x > 0: # i.e. > 1
@@ -1709,18 +1734,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1709
1734
  if R:
1710
1735
  raise self._ResidualError(op, other, r, **R)
1711
1736
  n, d = self.as_integer_ratio()
1712
- if abs(n) > abs(d):
1737
+ if _abs(n) > _abs(d):
1713
1738
  n, d, x = d, n, (-x)
1714
1739
  s = n / d
1715
1740
  # assert isscalar(s) and isscalar(x)
1716
1741
  return self._pow_2_3(s, x, other, op, **raiser_RESIDUAL)
1717
1742
 
1718
1743
  def _ps_acc(self, ps, xs, up=True, **unused):
1719
- '''(INTERNAL) Accumulate all C{xs} scalars into list C{ps}.
1744
+ '''(INTERNAL) Accumulate C{xs} scalars into list C{ps}.
1720
1745
  '''
1721
1746
  n = 0
1722
1747
  _2s = _2sum
1723
- for x in (tuple(xs) if xs is ps else xs):
1748
+ for x in (_Tuple(xs) if xs is ps else xs):
1724
1749
  # assert isscalar(x) and _isfinite(x)
1725
1750
  if x:
1726
1751
  i = 0
@@ -1733,17 +1758,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1733
1758
  n += 1
1734
1759
  if n:
1735
1760
  self._n += n
1736
- # Fsum._ps_max = max(Fsum._ps_max, len(ps))
1761
+ # Fsum._ps_max = max(Fsum._ps_max, _len(ps))
1737
1762
  if up:
1738
1763
  self._update()
1739
1764
  return ps
1740
1765
 
1741
1766
  def _ps_mul(self, op, *factors):
1742
- '''(INTERNAL) Multiply this instance' C{partials} with each
1743
- of the scalar B{C{factors}} and accumulate.
1767
+ '''(INTERNAL) Multiply this instance' C{partials} with
1768
+ each scalar C{factor} and accumulate into an C{Fsum}.
1744
1769
  '''
1745
1770
  def _pfs(ps, fs):
1746
- if len(ps) < len(fs):
1771
+ if _len(ps) < _len(fs):
1747
1772
  ps, fs = fs, ps
1748
1773
  _fin = _isfinite
1749
1774
  for f in fs:
@@ -1751,7 +1776,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1751
1776
  p *= f
1752
1777
  yield p if _fin(p) else self._finite(p, op)
1753
1778
 
1754
- return _Psum(self._ps_acc([], _pfs(self._ps, factors), up=False))
1779
+ return Fsum()._facc_scalar(_pfs(self._ps, factors), up=False)
1755
1780
 
1756
1781
  @property_RO
1757
1782
  def _ps_neg(self):
@@ -1760,15 +1785,18 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1760
1785
  for p in self._ps:
1761
1786
  yield -p
1762
1787
 
1763
- def _ps_1primed(self, *less):
1764
- '''(INTERNAL) Yield partials, 1-primed C{less} any scalars.
1788
+ def _ps_1sum(self, *less):
1789
+ '''(INTERNAL) Return the partials sum, 1-primed C{less} some scalars.
1765
1790
  '''
1766
- yield _1_0
1767
- for p in self._ps:
1768
- yield p
1769
- for p in less:
1770
- yield -p
1771
- yield _N_1_0
1791
+ def _1pls(ps, ls):
1792
+ yield _1_0
1793
+ for p in ps:
1794
+ yield p
1795
+ for p in ls:
1796
+ yield -p
1797
+ yield _N_1_0
1798
+
1799
+ return _fsum(_1pls(self._ps, less))
1772
1800
 
1773
1801
  def _raiser(self, r, s, raiser=True, **RESIDUAL):
1774
1802
  '''(INTERNAL) Does ratio C{r / s} exceed the RESIDUAL threshold
@@ -1785,6 +1813,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1785
1813
  return dict(ratio=q, R=t)
1786
1814
  return {}
1787
1815
 
1816
+ rdiv = __rtruediv__
1817
+
1788
1818
  @property_RO
1789
1819
  def real(self):
1790
1820
  '''Get the C{real} part of this instance (C{float}).
@@ -1793,7 +1823,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1793
1823
  and properties L{Fsum.ceil}, L{Fsum.floor},
1794
1824
  L{Fsum.imag} and L{Fsum.residual}.
1795
1825
  '''
1796
- return float(self._fprs)
1826
+ return _Float(self._fprs)
1797
1827
 
1798
1828
  @property_RO
1799
1829
  def residual(self):
@@ -1871,7 +1901,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1871
1901
  '''
1872
1902
  if isscalar(other):
1873
1903
  return other
1874
- raise self._TypeError(op, other, **txt) # _invalid_
1904
+ raise self._Error(op, other, _TypeError, **txt) # _invalid_
1875
1905
 
1876
1906
  def signOf(self, res=True):
1877
1907
  '''Determine the sign of this instance.
@@ -1885,45 +1915,38 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1885
1915
  r = (-r) if res else 0
1886
1916
  return _signOf(s, r)
1887
1917
 
1888
- def toRepr(self, **prec_sep_fmt_lenc): # PYCHOK signature
1918
+ def toRepr(self, **lenc_prec_sep_fmt): # PYCHOK signature
1889
1919
  '''Return this C{Fsum} instance as representation.
1890
1920
 
1891
- @kwarg prec_sep_fmt_lenc: Optional keyword arguments for
1892
- method L{Fsum2Tuple.toRepr} plus C{B{lenc}=True}
1893
- (C{bool}) to in-/exclude the current C{[len]}
1894
- of this L{Fsum} enclosed in I{[brackets]}.
1921
+ @kwarg lenc_prec_sep_fmt: Optional keyword arguments
1922
+ for method L{Fsum.toStr}.
1895
1923
 
1896
1924
  @return: This instance (C{repr}).
1897
1925
  '''
1898
- return self._toT(self._fprs2.toRepr, **prec_sep_fmt_lenc)
1926
+ return Fmt.repr_at(self, self.toStr(**lenc_prec_sep_fmt))
1899
1927
 
1900
- def toStr(self, **prec_sep_fmt_lenc): # PYCHOK signature
1928
+ def toStr(self, lenc=True, **prec_sep_fmt): # PYCHOK signature
1901
1929
  '''Return this C{Fsum} instance as string.
1902
1930
 
1903
- @kwarg prec_sep_fmt_lenc: Optional keyword arguments for
1904
- method L{Fsum2Tuple.toStr} plus C{B{lenc}=True}
1905
- (C{bool}) to in-/exclude the current C{[len]}
1906
- of this L{Fsum} enclosed in I{[brackets]}.
1931
+ @kwarg lenc: If C{True} include the current C{[len]} of this
1932
+ L{Fsum} enclosed in I{[brackets]} (C{bool}).
1933
+ @kwarg prec_sep_fmt: Optional keyword arguments for method
1934
+ L{Fsum2Tuple.toStr}.
1907
1935
 
1908
1936
  @return: This instance (C{str}).
1909
1937
  '''
1910
- return self._toT(self._fprs2.toStr, **prec_sep_fmt_lenc)
1911
-
1912
- def _toT(self, toT, fmt=Fmt.g, lenc=True, **kwds):
1913
- '''(INTERNAL) Helper for C{toRepr} and C{toStr}.
1914
- '''
1915
1938
  p = self.classname
1916
1939
  if lenc:
1917
- p = Fmt.SQUARE(p, len(self))
1918
- n = self.name
1919
- if n:
1920
- n = _UNDER_(*n.split())
1921
- return NN(p, _SPACE_, n, toT(fmt=fmt, **kwds))
1940
+ p = Fmt.SQUARE(p, _len(self))
1941
+ n = _enquote(self.name, white=_UNDER_)
1942
+ t = self._fprs2.toStr(**prec_sep_fmt)
1943
+ return NN(p, _SPACE_, n, t)
1922
1944
 
1923
- def _TypeError(self, op, other, **txt): # PYCHOK no cover
1924
- '''(INTERNAL) Return a C{TypeError}.
1945
+ def _truediv(self, other, op, **raiser_RESIDUAL):
1946
+ '''(INTERNAL) Return C{B{self} / B{other}} as an L{Fsum}.
1925
1947
  '''
1926
- return self._Error(op, other, _TypeError, **txt)
1948
+ f = self._copy_2(self.__truediv__)
1949
+ return f._ftruediv(other, op, **raiser_RESIDUAL)
1927
1950
 
1928
1951
  def _update(self, updated=True): # see ._fset
1929
1952
  '''(INTERNAL) Zap all cached C{Property_RO} values.
@@ -1937,16 +1960,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase
1937
1960
  # Fsum._fprs2._update(self)
1938
1961
  return self # for .fset_
1939
1962
 
1940
- def _ValueError(self, op, other, **txt): # PYCHOK no cover
1941
- '''(INTERNAL) Return a C{ValueError}.
1942
- '''
1943
- return self._Error(op, other, _ValueError, **txt)
1944
-
1945
- def _ZeroDivisionError(self, op, other, **txt): # PYCHOK no cover
1946
- '''(INTERNAL) Return a C{ZeroDivisionError}.
1947
- '''
1948
- return self._Error(op, other, _ZeroDivisionError, **txt)
1949
-
1950
1963
  _ROs = _allPropertiesOf_n(3, Fsum, Property_RO) # PYCHOK see Fsum._update
1951
1964
 
1952
1965
 
@@ -1968,7 +1981,7 @@ class DivMod2Tuple(_NamedTuple):
1968
1981
  _Units_ = (_Float_Int, Fsum)
1969
1982
 
1970
1983
 
1971
- class Fsum2Tuple(_NamedTuple):
1984
+ class Fsum2Tuple(_NamedTuple): # in .fstats
1972
1985
  '''2-Tuple C{(fsum, residual)} with the precision running C{fsum}
1973
1986
  and the C{residual}, the sum of the remaining partials. Each
1974
1987
  item is C{float} or C{int}.
@@ -1979,6 +1992,44 @@ class Fsum2Tuple(_NamedTuple):
1979
1992
  _Names_ = ( Fsum.fsum.__name__, Fsum.residual.name)
1980
1993
  _Units_ = (_Float_Int, _Float_Int)
1981
1994
 
1995
+ def __abs__(self): # in .fmath
1996
+ return self._Fsum.__abs__()
1997
+
1998
+ def __bool__(self): # PYCHOK Python 3+
1999
+ return bool(self._Fsum)
2000
+
2001
+ def __eq__(self, other):
2002
+ return self._other_op(other, self.__eq__)
2003
+
2004
+ def __float__(self):
2005
+ return self._Fsum.__float__()
2006
+
2007
+ def __ge__(self, other):
2008
+ return self._other_op(other, self.__ge__)
2009
+
2010
+ def __gt__(self, other):
2011
+ return self._other_op(other, self.__gt__)
2012
+
2013
+ def __le__(self, other):
2014
+ return self._other_op(other, self.__le__)
2015
+
2016
+ def __lt__(self, other):
2017
+ return self._other_op(other, self.__lt__)
2018
+
2019
+ def __int__(self):
2020
+ return self._Fsum.__int__()
2021
+
2022
+ def __ne__(self, other):
2023
+ return self._other_op(other, self.__ne__)
2024
+
2025
+ def __neg__(self):
2026
+ return self._Fsum.__neg__()
2027
+
2028
+ __nonzero__ = __bool__ # Python 2-
2029
+
2030
+ def __pos__(self):
2031
+ return self._Fsum.__pos__()
2032
+
1982
2033
  def as_integer_ratio(self):
1983
2034
  '''Return this instance as the ratio of 2 integers.
1984
2035
 
@@ -1988,32 +2039,45 @@ class Fsum2Tuple(_NamedTuple):
1988
2039
 
1989
2040
  @property_RO
1990
2041
  def _fint2(self):
1991
- return self._Fsum.fint2
2042
+ return self._Fsum._fint2
1992
2043
 
1993
2044
  @property_RO
1994
2045
  def _fprs2(self):
1995
2046
  return self._Fsum._fprs2
1996
2047
 
1997
2048
  @Property_RO
1998
- def _Fsum(self):
1999
- return Fsum(*self)
2049
+ def _Fsum(self): # this C{Fsum2Tuple} as L{Fsum}, in .fstats
2050
+ s, r = _s_r(*self)
2051
+ ps = (r, s) if r else (s,)
2052
+ return _Psum(ps, name=self.name)
2053
+
2054
+ def Fsum_(self, *xs, **name_RESIDUAL):
2055
+ '''Return this C{Fsum2Tuple} as an L{Fsum} plus some C{xs}.
2056
+ '''
2057
+ f = _Psum(self._Fsum._ps, **name_RESIDUAL)
2058
+ return f._facc_1(xs, up=False) if xs else f
2000
2059
 
2001
2060
  def is_exact(self):
2002
2061
  '''Is this L{Fsum2Tuple} considered to be exact? (C{bool}).
2003
2062
  '''
2004
- _, r = _s_r(*self)
2005
- return False if r else True
2063
+ return self._Fsum.is_exact()
2006
2064
 
2007
2065
  def is_integer(self):
2008
2066
  '''Is this L{Fsum2Tuple} C{integer}? (C{bool}).
2009
2067
  '''
2010
- s, r = _s_r(*self)
2011
- return False if r else isint(s, both=True)
2068
+ return self._Fsum.is_integer()
2069
+
2070
+ def _mul_scalar(self, other, op): # for Fsum._fmul
2071
+ return self._Fsum._mul_scalar(other, op)
2012
2072
 
2013
2073
  @property_RO
2014
2074
  def _n(self):
2015
2075
  return self._Fsum._n
2016
2076
 
2077
+ def _other_op(self, other, which):
2078
+ C, s = (_Tuple, self) if _isAn(other, _Tuple) else (Fsum, self._Fsum)
2079
+ return getattr(C, which.__name__)(s, other)
2080
+
2017
2081
  @property_RO
2018
2082
  def _ps(self):
2019
2083
  return self._Fsum._ps
@@ -2023,11 +2087,20 @@ class Fsum2Tuple(_NamedTuple):
2023
2087
  return self._Fsum._ps_neg
2024
2088
 
2025
2089
  def signOf(self, **res):
2026
- '''Like L{Fsum.signOf}.
2090
+ '''Like method L{Fsum.signOf}.
2027
2091
  '''
2028
2092
  return self._Fsum.signOf(**res)
2029
2093
 
2030
- _Fsum_Fsum2Tuple_types = Fsum, Fsum2Tuple # PYCHOK line
2094
+ def toStr(self, fmt=Fmt.g, **prec_sep): # PYCHOK signature
2095
+ '''Return this L{Fsum2Tuple} as string (C{str}).
2096
+
2097
+ @kwarg fmt: Optional C{float} format (C{letter}).
2098
+ @kwarg prec_sep: Optional keyword arguments for function
2099
+ L{fstr<streprs.fstr>}.
2100
+ '''
2101
+ return Fmt.PAREN(fstr(self, fmt=fmt, strepr=str, force=False, **prec_sep))
2102
+
2103
+ _Fsum_Fsum2Tuple_types = Fsum, Fsum2Tuple # PYCHOK lines
2031
2104
 
2032
2105
 
2033
2106
  class ResidualError(_ValueError):
@@ -2064,10 +2137,10 @@ except ImportError:
2064
2137
  def fsum(xs, floats=False):
2065
2138
  '''Precision floating point summation based on/like Python's C{math.fsum}.
2066
2139
 
2067
- @arg xs: Iterable of items to add (each C{scalar} or an L{Fsum} or
2068
- L{Fsum2Tuple} instance).
2069
- @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
2070
- I{known to be scalar} (C{bool}).
2140
+ @arg xs: Iterable of items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
2141
+ instance).
2142
+ @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
2143
+ be scalar} (C{bool}).
2071
2144
 
2072
2145
  @return: Precision C{fsum} (C{float}).
2073
2146
 
@@ -2086,12 +2159,12 @@ def fsum(xs, floats=False):
2086
2159
 
2087
2160
 
2088
2161
  def fsum_(*xs, **floats):
2089
- '''Precision floating point summation of all positional arguments.
2162
+ '''Precision floating point summation of all positional items.
2090
2163
 
2091
- @arg xs: Items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
2092
- instance), all positional.
2093
- @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
2094
- I{known to be scalar} (C{bool}).
2164
+ @arg xs: Items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
2165
+ all positional.
2166
+ @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
2167
+ be scalar} (C{bool}).
2095
2168
 
2096
2169
  @see: Function L{fsum<fsums.fsum>} for further details.
2097
2170
  '''
@@ -2110,10 +2183,10 @@ def fsumf_(*xs):
2110
2183
  def fsum1(xs, floats=False):
2111
2184
  '''Precision floating point summation, 1-primed.
2112
2185
 
2113
- @arg xs: Iterable of items to add (each C{scalar} or an L{Fsum} or
2114
- L{Fsum2Tuple} instance).
2115
- @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
2116
- I{known to be scalar} (C{bool}).
2186
+ @arg xs: Iterable of items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
2187
+ instance).
2188
+ @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
2189
+ be scalar} (C{bool}).
2117
2190
 
2118
2191
  @see: Function L{fsum<fsums.fsum>} for further details.
2119
2192
  '''
@@ -2121,12 +2194,12 @@ def fsum1(xs, floats=False):
2121
2194
 
2122
2195
 
2123
2196
  def fsum1_(*xs, **floats):
2124
- '''Precision floating point summation, 1-primed of all positional arguments.
2197
+ '''Precision floating point summation, 1-primed of all positional items.
2125
2198
 
2126
- @arg xs: Items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
2127
- instance), all positional.
2128
- @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are
2129
- I{known to be scalar} (C{bool}).
2199
+ @arg xs: Items to add (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
2200
+ all positional.
2201
+ @kwarg floats: Use C{B{floats}=True} iff I{all} B{C{xs}} items are I{known to
2202
+ be scalar} (C{bool}).
2130
2203
 
2131
2204
  @see: Function L{fsum_<fsums.fsum_>} for further details.
2132
2205
  '''
@@ -2135,7 +2208,7 @@ def fsum1_(*xs, **floats):
2135
2208
 
2136
2209
 
2137
2210
  def fsum1f_(*xs):
2138
- '''Precision floating point summation iff I{all} C{B{xs}} are I{known to be scalar}.
2211
+ '''Precision floating point summation iff I{all} C{B{xs}} items are I{known to be scalar}.
2139
2212
 
2140
2213
  @see: Function L{fsum_<fsums.fsum_>} for further details.
2141
2214
  '''
@@ -2159,7 +2232,7 @@ if __name__ == '__main__':
2159
2232
  F = Fsum()
2160
2233
  if F.is_math_fsum():
2161
2234
  for t in frandoms(n, seeded=True):
2162
- assert float(F.fset_(*t)) == _fsum(t)
2235
+ assert _Float(F.fset_(*t)) == _fsum(t)
2163
2236
  printf(_DOT_, end=NN)
2164
2237
  printf(NN)
2165
2238