pygeodesy 24.9.29__py2.py3-none-any.whl → 24.10.24__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.
Files changed (56) hide show
  1. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/METADATA +15 -15
  2. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/RECORD +56 -56
  3. pygeodesy/__init__.py +20 -19
  4. pygeodesy/__main__.py +5 -5
  5. pygeodesy/albers.py +12 -17
  6. pygeodesy/basics.py +38 -41
  7. pygeodesy/booleans.py +54 -46
  8. pygeodesy/cartesianBase.py +2 -2
  9. pygeodesy/constants.py +20 -16
  10. pygeodesy/datums.py +3 -3
  11. pygeodesy/dms.py +250 -270
  12. pygeodesy/ellipsoidalBase.py +2 -2
  13. pygeodesy/ellipsoidalBaseDI.py +10 -10
  14. pygeodesy/ellipsoidalNvector.py +4 -4
  15. pygeodesy/ellipsoidalVincenty.py +2 -2
  16. pygeodesy/ellipsoids.py +7 -48
  17. pygeodesy/elliptic.py +14 -14
  18. pygeodesy/errors.py +15 -10
  19. pygeodesy/etm.py +18 -2
  20. pygeodesy/fmath.py +188 -176
  21. pygeodesy/formy.py +4 -4
  22. pygeodesy/fstats.py +54 -56
  23. pygeodesy/fsums.py +304 -266
  24. pygeodesy/geodesici.py +43 -40
  25. pygeodesy/geodesicw.py +3 -3
  26. pygeodesy/geodesicx/gxarea.py +3 -2
  27. pygeodesy/geodsolve.py +73 -24
  28. pygeodesy/geohash.py +2 -2
  29. pygeodesy/geoids.py +28 -27
  30. pygeodesy/internals.py +156 -85
  31. pygeodesy/interns.py +23 -20
  32. pygeodesy/karney.py +61 -12
  33. pygeodesy/latlonBase.py +13 -15
  34. pygeodesy/lazily.py +206 -214
  35. pygeodesy/mgrs.py +13 -13
  36. pygeodesy/named.py +11 -10
  37. pygeodesy/nvectorBase.py +1 -1
  38. pygeodesy/points.py +2 -2
  39. pygeodesy/props.py +34 -13
  40. pygeodesy/rhumb/bases.py +5 -5
  41. pygeodesy/rhumb/solve.py +7 -8
  42. pygeodesy/solveBase.py +7 -25
  43. pygeodesy/sphericalBase.py +20 -23
  44. pygeodesy/sphericalNvector.py +24 -23
  45. pygeodesy/sphericalTrigonometry.py +9 -8
  46. pygeodesy/streprs.py +11 -8
  47. pygeodesy/trf.py +6 -4
  48. pygeodesy/triaxials.py +46 -9
  49. pygeodesy/units.py +4 -3
  50. pygeodesy/ups.py +6 -6
  51. pygeodesy/utily.py +2 -2
  52. pygeodesy/utm.py +2 -2
  53. pygeodesy/vector3d.py +5 -5
  54. pygeodesy/vector3dBase.py +4 -5
  55. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/WHEEL +0 -0
  56. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/top_level.txt +0 -0
pygeodesy/fsums.py CHANGED
@@ -40,21 +40,20 @@ results may differ from Python's C{math.fsum} results.
40
40
  from __future__ import division as _; del _ # PYCHOK semicolon
41
41
 
42
42
  from pygeodesy.basics import isbool, iscomplex, isint, isscalar, \
43
- _signOf, itemsorted, signOf, _xiterable, \
44
- _xiterablen
43
+ _signOf, itemsorted, signOf, _xiterable
45
44
  from pygeodesy.constants import INF, INT0, MANT_DIG, NEG0, NINF, _0_0, \
46
45
  _1_0, _N_1_0, _isfinite, _pos_self, \
47
46
  Float, Int
48
47
  from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
49
- _ValueError, _xError, _xError2, _xkwds_get, \
50
- _xkwds, _xkwds_get1, _xkwds_not, _xkwds_pop, \
51
- _xsError
52
- from pygeodesy.internals import _enquote, _passarg
48
+ _ValueError, _xError, _xError2, _xkwds, \
49
+ _xkwds_get, _xkwds_get1, _xkwds_not, \
50
+ _xkwds_pop, _xsError
51
+ from pygeodesy.internals import _enquote, _getPYGEODESY, _MODS, _passarg
53
52
  from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DOT_, _from_, \
54
53
  _not_finite_, _SPACE_, _std_, _UNDER_
55
- from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
54
+ # from pygeodesy.lazily import _ALL_LAZY # from .named
56
55
  from pygeodesy.named import _name__, _name2__, _Named, _NamedTuple, \
57
- _NotImplemented
56
+ _NotImplemented, _ALL_LAZY
58
57
  from pygeodesy.props import _allPropertiesOf_n, deprecated_method, \
59
58
  deprecated_property_RO, Property, \
60
59
  Property_RO, property_RO
@@ -65,7 +64,7 @@ from math import fabs, isinf, isnan, \
65
64
  ceil as _ceil, floor as _floor # PYCHOK used! .ltp
66
65
 
67
66
  __all__ = _ALL_LAZY.fsums
68
- __version__ = '24.09.29'
67
+ __version__ = '24.10.22'
69
68
 
70
69
  from pygeodesy.interns import (
71
70
  _PLUS_ as _add_op_, # in .auxilats.auxAngle
@@ -78,28 +77,25 @@ from pygeodesy.interns import (
78
77
  _DASH_ as _sub_op_, # in .auxilats.auxAngle
79
78
  _SLASH_ as _truediv_op_
80
79
  )
81
- _eq_op_ = _fset_op_ * 2 # _DEQUAL_
82
80
  _floordiv_op_ = _truediv_op_ * 2 # _DSLASH_
83
81
  _divmod_op_ = _floordiv_op_ + _mod_op_
84
- _F2PRODUCT = _getenv('PYGEODESY_FSUM_F2PRODUCT', NN)
85
- _ge_op_ = _gt_op_ + _fset_op_
82
+ _F2PRODUCT = _getPYGEODESY('FSUM_F2PRODUCT')
86
83
  _iadd_op_ = _add_op_ + _fset_op_ # in .auxilats.auxAngle, .fstats
87
84
  _integer_ = 'integer'
88
85
  _isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
89
- _le_op_ = _lt_op_ + _fset_op_
90
- _NONFINITEr = _0_0
91
- _NONFINITES = _getenv('PYGEODESY_FSUM_NONFINITES', NN)
86
+ _NONFINITEr = _0_0 # NOT INT0!
87
+ _NONFINITES = _getPYGEODESY('FSUM_NONFINITES')
92
88
  _non_zero_ = 'non-zero'
93
89
  _pow_op_ = _mul_op_ * 2 # _DSTAR_
94
- _RESIDUAL_0_0 = _getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)
90
+ _RESIDUAL_0_0 = _getPYGEODESY('FSUM_RESIDUAL', _0_0)
95
91
  _significant_ = 'significant'
96
92
  _threshold_ = 'threshold'
97
93
 
98
94
 
99
- def _2finite(x): # in .fstats
95
+ def _2finite(x, _isfine=_isfinite): # in .fstats
100
96
  '''(INTERNAL) return C{float(x)} if finite.
101
97
  '''
102
- return (float(x) if _isfinite(x) # and isscalar(x)
98
+ return (float(x) if _isfine(x) # and isscalar(x)
103
99
  else _nfError(x))
104
100
 
105
101
 
@@ -114,28 +110,6 @@ def _2float(index=None, _isfine=_isfinite, **name_x): # in .fmath, .fstats
114
110
  raise _xError(X, Fmt.INDEX(n, index), x)
115
111
 
116
112
 
117
- def _X_ps(X): # for _2floats only
118
- return X._ps
119
-
120
-
121
- def _2floats(xs, origin=0, _X=_X_ps, _x=float, _isfine=_isfinite):
122
- '''(INTERNAL) Yield each B{C{xs}} as a C{float}.
123
- '''
124
- try:
125
- i, x = origin, xs
126
- _FsT = _Fsum_2Tuple_types
127
- for x in _xiterable(xs):
128
- if isinstance(x, _FsT):
129
- for p in _X(x._Fsum):
130
- yield p
131
- else:
132
- f = _x(x)
133
- yield f if _isfine(f) else _nfError(f)
134
- i += 1
135
- except Exception as X:
136
- raise _xsError(X, xs, i, x)
137
-
138
-
139
113
  try: # MCCABE 26
140
114
  from math import fma as _fma
141
115
 
@@ -145,8 +119,9 @@ try: # MCCABE 26
145
119
  # <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
146
120
  for y in ys:
147
121
  f = x * y
148
- yield f
149
- yield _fma(x, y, -f)
122
+ yield f
123
+ if _isfinite(f):
124
+ yield _fma(x, y, -f)
150
125
  for z in zs:
151
126
  yield z
152
127
 
@@ -156,7 +131,7 @@ try: # MCCABE 26
156
131
  except ImportError: # PYCHOK DSPACE! Python 3.12-
157
132
 
158
133
  if _F2PRODUCT and _F2PRODUCT != _std_:
159
- # back to PyGeodesy 24.09.09, with _fmaX
134
+ # backward to PyGeodesy 24.09.09, with _fmaX
160
135
 
161
136
  def _fma(*a_b_c): # PYCHOK no cover
162
137
  # mimick C{math.fma} from Python 3.13+,
@@ -166,12 +141,13 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
166
141
  n += da * db * nc
167
142
  d = da * db * dc
168
143
  try:
169
- r = float(n / d)
144
+ n, d = _n_d2(n, d)
145
+ r = float(n / d)
170
146
  except OverflowError: # "integer division result too large ..."
171
147
  r = NINF if (_signOf(n, 0) * _signOf(d, 0)) < 0 else INF
172
148
  return r if _isfinite(r) else _fmaX(r, *a_b_c) # "overflow in fma"
173
149
 
174
- def _2n_d(x):
150
+ def _2n_d(x): # PYCHOK no cover
175
151
  try: # int.as_integer_ratio in 3.8+
176
152
  return x.as_integer_ratio()
177
153
  except (AttributeError, OverflowError, TypeError, ValueError):
@@ -188,18 +164,18 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
188
164
  _2n_d = None # redef
189
165
 
190
166
  def _fmaX(r, *a_b_c): # like Python 3.13+ I{Modules/mathmodule.c}:
191
- # raise a ValueError for a NAN result from non-NAN C{a_b_c}s or
192
- # OverflowError for a non-NAN result from all finite C{a_b_c}s.
167
+ # raise a ValueError for a NAN result from non-NAN C{a_b_c}s or an
168
+ # OverflowError for a non-NAN non-finite from all finite C{a_b_c}s.
193
169
  if isnan(r):
194
170
  def _x(x):
195
171
  return not isnan(x)
196
- else:
172
+ else: # non-NAN non-finite
197
173
  _x = _isfinite
198
174
  if all(map(_x, a_b_c)):
199
175
  raise _nfError(r, unstr(_fma, *a_b_c))
200
176
  return r
201
177
 
202
- def _2products(x, y3s, *zs): # PYCHOK in Fsum._f2mul
178
+ def _2products(x, y3s, *zs): # PYCHOK in _fma, ...
203
179
  # yield(x * y3 for y3 in y3s) + yield(z in zs)
204
180
  # TwoProduct U{Algorithm 3.3
205
181
  # <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>}
@@ -209,20 +185,16 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
209
185
  for y, c, d in y3s:
210
186
  y *= x
211
187
  yield y
212
- if False: # no cover
213
- yield b * d - (((y - a * c) - b * c) - a * d)
214
- # = b * d + (a * d - ((y - a * c) - b * c))
215
- # = b * d + (a * d + (b * c - (y - a * c)))
216
- # = b * d + (a * d + (b * c + (a * c - y)))
217
- elif a:
188
+ if _isfinite(y):
189
+ # yield b * d - (((y - a * c) - b * c) - a * d)
190
+ # = b * d + (a * d - ((y - a * c) - b * c))
191
+ # = b * d + (a * d + (b * c - (y - a * c)))
192
+ # = b * d + (a * d + (b * c + (a * c - y)))
218
193
  yield a * c - y
219
194
  yield b * c
220
195
  if d:
221
196
  yield a * d
222
197
  yield b * d
223
- else:
224
- yield b * c - y
225
- yield b * d
226
198
  for z in zs:
227
199
  yield z
228
200
 
@@ -268,10 +240,10 @@ def _Fsumf_(*xs): # in .auxLat, .ltp, ...
268
240
  def _Fsum1f_(*xs): # in .albers
269
241
  '''(INTERNAL) An C{Fsum(xs)}, all C{scalar}, an L{Fsum} or L{Fsum2Tuple}, 1-primed.
270
242
  '''
271
- return Fsum()._facc_scalarf(_1primed(xs), up=False)
243
+ return Fsum()._facc_scalarf(_1primed(xs), origin=-1, up=False)
272
244
 
273
245
 
274
- def _2halfeven(s, r, p):
246
+ def _halfeven(s, r, p):
275
247
  '''(INTERNAL) Round half-even.
276
248
  '''
277
249
  if (p > 0 and r > 0) or \
@@ -302,19 +274,31 @@ def _isOK(unused):
302
274
 
303
275
 
304
276
  def _isOK_or_finite(x, _isfine=_isfinite):
305
- '''(INTERNAL) Is C{x} finite or is I{non-finite} OK?.
277
+ '''(INTERNAL) Is C{x} finite or is I{non-finite} OK?
306
278
  '''
307
279
  # assert _isfine in (_isOK, _isfinite)
308
- return _isfine(x)
280
+ return _isfine(x) # C{bool}
309
281
 
310
282
 
311
- def _ixError(X, xs, i, x, origin=0, which=None):
312
- '''(INTERNAL) Error for C{xs} or C{x}, item C{xs[i]}.
313
- '''
314
- t = _xsError(X, xs, i + origin, x)
315
- if which:
316
- t = _COMMASPACE_(unstr(which, _Cdot=Fsum), t)
317
- return _xError(X, t, txt=None)
283
+ try:
284
+ from math import gcd as _gcd
285
+
286
+ def _n_d2(n, d):
287
+ '''(INTERNAL) Reduce C{n} and C{d} by C{gcd}.
288
+ '''
289
+ if n and d:
290
+ try:
291
+ c = _gcd(n, d)
292
+ if c > 1:
293
+ n, d = (n // c), (d // c)
294
+ except TypeError: # non-int float
295
+ pass
296
+ return n, d
297
+
298
+ except ImportError: # 3.4-
299
+
300
+ def _n_d2(*n_d): # PYCHOK redef
301
+ return n_d
318
302
 
319
303
 
320
304
  def _nfError(x, *args):
@@ -327,6 +311,13 @@ def _nfError(x, *args):
327
311
  raise E(t, txt=None)
328
312
 
329
313
 
314
+ def _NonfiniteError(x):
315
+ '''(INTERNAL) Return the Error class for C{x}, I{non-finite}.
316
+ '''
317
+ return _OverflowError if isinf(x) else (
318
+ _ValueError if isnan(x) else _AssertionError)
319
+
320
+
330
321
  def nonfiniterrors(*raiser):
331
322
  '''Throw C{OverflowError} and C{ValueError} exceptions for or
332
323
  handle I{non-finite} C{float}s as C{inf}, C{INF}, C{NINF},
@@ -344,14 +335,8 @@ def nonfiniterrors(*raiser):
344
335
  d = Fsum._isfine
345
336
  if raiser and raiser[0] is not None:
346
337
  Fsum._isfine = {} if bool(raiser[0]) else Fsum._nonfinites_isfine_kwds[True]
347
- return _xkwds_get1(d, _isfine=_isfinite) is _isfinite
348
-
349
-
350
- def _NonfiniteError(x):
351
- '''(INTERNAL) Return the Error class for C{x}, I{non-finite}.
352
- '''
353
- return _OverflowError if isinf(x) else (
354
- _ValueError if isnan(x) else _AssertionError)
338
+ return (False if d is Fsum._nonfinites_isfine_kwds[True] else
339
+ _xkwds_get1(d, _isfine=_isfinite) is _isfinite) if d else True
355
340
 
356
341
 
357
342
  def _1primed(xs): # in .fmath
@@ -377,7 +362,7 @@ def _psum(ps, **_isfine): # PYCHOK used!
377
362
  if s:
378
363
  ps[i:] = r, s
379
364
  if i > 0:
380
- s = _2halfeven(s, r, ps[i-1])
365
+ s = _halfeven(s, r, ps[i-1])
381
366
  break # return s
382
367
  s = r # PYCHOK no cover
383
368
  elif not _isfinite(s): # non-finite OK
@@ -404,14 +389,38 @@ def _Psum_(*ps, **name_f2product_nonfinites_RESIDUAL): # in .fmath
404
389
  return _Psum(ps, **name_f2product_nonfinites_RESIDUAL)
405
390
 
406
391
 
407
- def _2scalar2(other):
392
+ def _residue(other):
393
+ '''(INTERNAL) Return the C{residual} or C{None} for C{scalar}.
394
+ '''
395
+ try:
396
+ r = other.residual
397
+ except AttributeError:
398
+ r = None # float, int, other
399
+ return r
400
+
401
+
402
+ def _s_r(s, r):
403
+ '''(INTERNAL) Return C{(s, r)}, I{ordered}.
404
+ '''
405
+ if _isfinite(s):
406
+ if r:
407
+ if fabs(s) < fabs(r):
408
+ s, r = r, (s or INT0)
409
+ else:
410
+ r = INT0
411
+ else:
412
+ r = _NONFINITEr
413
+ return s, r
414
+
415
+
416
+ def _2s_r(other):
408
417
  '''(INTERNAL) Return 2-tuple C{(other, r)} with C{other} as C{int},
409
- C{float} or C{as-is} and C{r} the residual of C{as-is}.
418
+ C{float} or C{as-is} and C{r} the residual of C{as-is} or 0.
410
419
  '''
411
420
  if _isFsum_2Tuple(other):
412
421
  s, r = other._fint2
413
422
  if r:
414
- s, r = other._fprs2
423
+ s, r = other._nfprs2
415
424
  if r: # PYCHOK no cover
416
425
  s = other # L{Fsum} as-is
417
426
  else:
@@ -422,17 +431,6 @@ def _2scalar2(other):
422
431
  return s, r
423
432
 
424
433
 
425
- def _s_r(s, r):
426
- '''(INTERNAL) Return C{(s, r)}, I{ordered}.
427
- '''
428
- if r and _isfinite(s):
429
- if fabs(s) < fabs(r):
430
- s, r = r, (s or INT0)
431
- else:
432
- r = INT0
433
- return s, r
434
-
435
-
436
434
  def _strcomplex(s, *args):
437
435
  '''(INTERNAL) C{Complex} 2- or 3-arg C{pow} error as C{str}.
438
436
  '''
@@ -518,8 +516,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
518
516
  @see: Module L{fsums<pygeodesy.fsums>} for env variables C{PYGEODESY_FSUM_F2PRODUCT},
519
517
  C{PYGEODESY_FSUM_NONFINITES} and C{PYGEODESY_FSUM_RESIDUAL}.
520
518
  '''
521
- _f2product = _sys_version_info2 > (3, 12) or bool(_F2PRODUCT)
522
- _isfine = {} # == _isfinite
519
+ _f2product = _MODS.sys_version_info2 > (3, 12) or bool(_F2PRODUCT)
520
+ _isfine = {} # == _isfinite, see nonfiniterrors()
523
521
  _n = 0
524
522
  # _ps = [] # partial sums
525
523
  # _ps_max = 0 # max(Fsum._ps_max, len(Fsum._ps)) # 41
@@ -560,14 +558,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
560
558
  @see: Methods L{Fsum.fadd_} and L{Fsum.fadd}.
561
559
  '''
562
560
  f = self._copy_2(self.__add__)
563
- return f._fadd(other, _add_op_)
561
+ return f._fadd(other)
564
562
 
565
563
  def __bool__(self): # PYCHOK Python 3+
566
564
  '''Return C{bool(B{self})}, C{True} iff C{residual} is zero.
567
565
  '''
568
- s, r = self._fprs2
566
+ s, r = self._nfprs2
569
567
  return bool(s or r) and s != -r # == self != 0
570
568
 
569
+ def __call__(self, other, **up): # in .fmath
570
+ '''Reset this C{Fsum} to C{other}, default C{B{up}=True}.
571
+ '''
572
+ self._ps[:] = 0, # clear for errors
573
+ self._fset(other, op=_fset_op_, **up)
574
+ return self
575
+
576
+
571
577
  def __ceil__(self): # PYCHOK not special in Python 2-
572
578
  '''Return this instance' C{math.ceil} as C{int} or C{float}.
573
579
 
@@ -609,7 +615,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
609
615
  '''Return C{(B{self} == B{other})} as C{bool} where B{C{other}}
610
616
  is C{scalar}, an other L{Fsum} or L{Fsum2Tuple}.
611
617
  '''
612
- return self._cmp_0(other, _eq_op_) == 0
618
+ return self._cmp_0(other, _fset_op_ + _fset_op_) == 0
613
619
 
614
620
  def __float__(self):
615
621
  '''Return this instance' current, precision running sum as C{float}.
@@ -646,7 +652,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
646
652
  def __ge__(self, other):
647
653
  '''Return C{(B{self} >= B{other})}, see C{__eq__}.
648
654
  '''
649
- return self._cmp_0(other, _ge_op_) >= 0
655
+ return self._cmp_0(other, _gt_op_ + _fset_op_) >= 0
650
656
 
651
657
  def __gt__(self, other):
652
658
  '''Return C{(B{self} > B{other})}, see C{__eq__}.
@@ -674,7 +680,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
674
680
  @see: Methods L{Fsum.fadd_} and L{Fsum.fadd}.
675
681
  '''
676
682
  try:
677
- return self._fadd(other, _iadd_op_)
683
+ return self._fadd(other, op=_iadd_op_)
678
684
  except TypeError:
679
685
  pass
680
686
  _xiterable(other)
@@ -834,7 +840,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
834
840
  def __le__(self, other):
835
841
  '''Return C{(B{self} <= B{other})}, see C{__eq__}.
836
842
  '''
837
- return self._cmp_0(other, _le_op_) <= 0
843
+ return self._cmp_0(other, _lt_op_ + _fset_op_) <= 0
838
844
 
839
845
  def __len__(self):
840
846
  '''Return the number of values accumulated (C{int}).
@@ -896,7 +902,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
896
902
  @see: Method L{Fsum.__iadd__}.
897
903
  '''
898
904
  f = self._copy_2r(other, self.__radd__)
899
- return f._fadd(self, _add_op_)
905
+ return f._fadd(self)
900
906
 
901
907
  def __rdivmod__(self, other):
902
908
  '''Return C{divmod(B{other}, B{self})} as 2-tuple
@@ -907,6 +913,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
907
913
  f = self._copy_2r(other, self.__rdivmod__)
908
914
  return f._fdivmod2(self, _divmod_op_)
909
915
 
916
+ # turned off, called by _deepcopy and _copy
917
+ # def __reduce__(self): # Python 3.8+
918
+ # ''' Pickle, like std C{fractions.Fraction}, see U{__reduce__
919
+ # <https://docs.Python.org/3/library/pickle.html#object.__reduce__>}
920
+ # '''
921
+ # dict_ = self._Fsum_as().__dict__ # no __setstate__
922
+ # return (self.__class__, self.partials, dict_)
923
+
910
924
  # def __repr__(self):
911
925
  # '''Return the default C{repr(this)}.
912
926
  # '''
@@ -920,7 +934,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
920
934
  f = self._copy_2r(other, self.__rfloordiv__)
921
935
  return f._floordiv(self, _floordiv_op_)
922
936
 
923
- def __rmatmul__(self, other): # PYCHOK no cover
937
+ def __rmatmul__(self, other): # PYCHOK no coveS
924
938
  '''Not implemented.'''
925
939
  return _NotImplemented(self, other)
926
940
 
@@ -1009,7 +1023,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1009
1023
 
1010
1024
  __trunc__ = __int__
1011
1025
 
1012
- if _sys_version_info2 < (3, 0): # PYCHOK no cover
1026
+ if _MODS.sys_version_info2 < (3, 0): # PYCHOK no cover
1013
1027
  # <https://docs.Python.org/2/library/operator.html#mapping-operators-to-functions>
1014
1028
  __div__ = __truediv__
1015
1029
  __idiv__ = __itruediv__
@@ -1030,9 +1044,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1030
1044
  '''
1031
1045
  n, r = self._fint2
1032
1046
  if r:
1033
- i, d = float(r).as_integer_ratio()
1034
- n *= d
1035
- n += i
1047
+ i, d = float(r).as_integer_ratio()
1048
+ n, d = _n_d2(n * d + i, d)
1036
1049
  else: # PYCHOK no cover
1037
1050
  d = 1
1038
1051
  return n, d
@@ -1042,7 +1055,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1042
1055
  '''Get this instance I{as-is} (L{Fsum} with C{non-zero residual},
1043
1056
  C{scalar} or I{non-finite}).
1044
1057
  '''
1045
- s, r = self._fprs2
1058
+ s, r = self._nfprs2
1046
1059
  return self if r else s
1047
1060
 
1048
1061
  @property_RO
@@ -1089,18 +1102,22 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1089
1102
  f._n = 1
1090
1103
  # assert f._f2product == self._f2product
1091
1104
  # assert f._Fsum is f
1105
+ # assert f._isfine is self._isfine
1106
+ # assert f._RESIDUAL is self._RESIDUAL
1092
1107
  return f
1093
1108
 
1094
1109
  def _copy_2(self, which, name=NN):
1095
1110
  '''(INTERNAL) Copy for I{dyadic} operators.
1096
1111
  '''
1097
- n = name or which.__name__ # _dunder_nameof
1112
+ n = name or which.__name__ # _DUNDER_nameof
1098
1113
  # NOT .classof due to .Fdot(a, *b) args, etc.
1099
1114
  f = _Named.copy(self, deep=False, name=n)
1100
1115
  f._ps = list(self._ps) # separate list
1101
1116
  # assert f._n == self._n
1102
1117
  # assert f._f2product == self._f2product
1103
1118
  # assert f._Fsum is f
1119
+ # assert f._isfine is self._isfine
1120
+ # assert f._RESIDUAL is self._RESIDUAL
1104
1121
  return f
1105
1122
 
1106
1123
  def _copy_2r(self, other, which):
@@ -1130,25 +1147,29 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1130
1147
  '''(INTERNAL) Format the caught exception C{X}.
1131
1148
  '''
1132
1149
  E, t = _xError2(X)
1133
- u = unstr(self.named3, *xs[:3], _ELLIPSIS=len(xs) > 3, **kwds)
1150
+ u = unstr(self.named3, *xs, _ELLIPSIS=4, **kwds)
1134
1151
  return E(u, txt=t, cause=X)
1135
1152
 
1136
- def _facc(self, xs, up=True, **origin_X_x):
1137
- '''(INTERNAL) Accumulate more C{scalars} or L{Fsum}s.
1153
+ def _facc(self, xs, up=True, **_X_x_origin):
1154
+ '''(INTERNAL) Accumulate more C{scalar}s or L{Fsum}s.
1138
1155
  '''
1139
1156
  if xs:
1140
- kwds = _xkwds(self._isfine, **origin_X_x)
1141
- fs = _2floats(xs, **kwds) # PYCHOK yield
1157
+ kwds = self._isfine
1158
+ if _X_x_origin:
1159
+ kwds = _xkwds(_X_x_origin, **kwds)
1160
+ fs = _xs(xs, **kwds) # PYCHOK yield
1142
1161
  ps = self._ps
1143
1162
  ps[:] = self._ps_acc(list(ps), fs, up=up)
1163
+ # if len(ps) > 16:
1164
+ # _ = _psum(ps, **self._isfine)
1144
1165
  return self
1145
1166
 
1146
1167
  def _facc_args(self, xs, **up):
1147
1168
  '''(INTERNAL) Accumulate 0, 1 or more C{xs}, all positional
1148
1169
  arguments in the caller of this method.
1149
1170
  '''
1150
- return self._facc(xs, origin=1, **up) if len(xs) != 1 else \
1151
- self._fadd(xs[0], _add_op_, **up)
1171
+ return self._fadd(xs[0], **up) if len(xs) == 1 else \
1172
+ self._facc(xs, **up) # origin=1?
1152
1173
 
1153
1174
  def _facc_neg(self, xs, **up_origin):
1154
1175
  '''(INTERNAL) Accumulate more C{xs}, negated.
@@ -1197,7 +1218,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1197
1218
  f *= _pow(x, r, power, op, **raiser_RESIDUAL)
1198
1219
  return f
1199
1220
 
1200
- f = self._facc(xs, origin=1, _X=_P, _x=_p)
1221
+ f = self._facc(xs, _X=_P, _x=_p) # origin=1?
1201
1222
  else:
1202
1223
  f = self._facc_scalar_(float(len(xs))) # x**0 == 1
1203
1224
  return f
@@ -1206,7 +1227,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1206
1227
  '''(INTERNAL) Accumulate all C{xs}, each C{scalar}.
1207
1228
  '''
1208
1229
  if xs:
1209
- _ = self._ps_acc(self._ps, xs, **up)
1230
+ ps = self._ps
1231
+ ps[:] = self._ps_acc(list(ps), xs, **up)
1210
1232
  return self
1211
1233
 
1212
1234
  def _facc_scalar_(self, *xs, **up):
@@ -1214,16 +1236,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1214
1236
  '''
1215
1237
  return self._facc_scalar(xs, **up)
1216
1238
 
1217
- def _facc_scalarf(self, xs, **origin_which):
1239
+ def _facc_scalarf(self, xs, up=True, **origin_which):
1218
1240
  '''(INTERNAL) Accumulate all C{xs}, each C{scalar}, an L{Fsum} or
1219
1241
  L{Fsum2Tuple}, like function C{_xsum}.
1220
1242
  '''
1221
- i_x = [0, xs]
1222
- try:
1223
- nf = self.nonfinitesOK
1224
- return self._facc_scalar(_xs(xs, i_x, nf))
1225
- except (OverflowError, TypeError, ValueError) as X:
1226
- raise _ixError(X, xs, *i_x, **origin_which)
1243
+ _C = self.__class__
1244
+ fs = _xs(xs, **_x_isfine(self.nonfinitesOK, _Cdot=_C,
1245
+ **origin_which)) # PYCHOK yield
1246
+ return self._facc_scalar(fs, up=up)
1227
1247
 
1228
1248
  # def _facc_up(self, up=True):
1229
1249
  # '''(INTERNAL) Update the C{partials}, by removing
@@ -1242,8 +1262,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1242
1262
  def fadd(self, xs=()):
1243
1263
  '''Add an iterable's items to this instance.
1244
1264
 
1245
- @arg xs: Iterable of items to add (each C{scalar}
1246
- or an L{Fsum} or L{Fsum2Tuple} instance).
1265
+ @arg xs: Iterable of items to add (each C{scalar},
1266
+ an L{Fsum} or L{Fsum2Tuple}).
1247
1267
 
1248
1268
  @return: This instance (L{Fsum}).
1249
1269
 
@@ -1265,26 +1285,20 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1265
1285
  def fadd_(self, *xs):
1266
1286
  '''Add all positional items to this instance.
1267
1287
 
1268
- @arg xs: Values to add (each C{scalar} or an L{Fsum}
1269
- or L{Fsum2Tuple} instance), all positional.
1288
+ @arg xs: Values to add (each C{scalar}, an L{Fsum}
1289
+ or L{Fsum2Tuple}), all positional.
1270
1290
 
1271
1291
  @see: Method L{Fsum.fadd} for further details.
1272
1292
  '''
1273
1293
  return self._facc_args(xs)
1274
1294
 
1275
- def _fadd(self, other, op, **up): # in .fmath.Fhorner
1295
+ def _fadd(self, other, op=_add_op_, **up):
1276
1296
  '''(INTERNAL) Apply C{B{self} += B{other}}.
1277
1297
  '''
1278
1298
  if _isFsum_2Tuple(other):
1279
- if self._ps:
1280
- self._facc_scalar(other._ps, **up)
1281
- else:
1282
- self._fset(other, op=op, **up)
1299
+ self._facc_scalar(other._ps, **up)
1283
1300
  elif self._scalar(other, op):
1284
- if self._ps:
1285
- self._facc_scalar_(other, **up)
1286
- else:
1287
- self._fset(other, op=op, **up)
1301
+ self._facc_scalar_(other, **up)
1288
1302
  return self
1289
1303
 
1290
1304
  fcopy = copy # for backward compatibility
@@ -1310,25 +1324,27 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1310
1324
  # raise self._Error(op, other, _AssertionError, txt__=signOf)
1311
1325
  return DivMod2Tuple(q, self) # q is C{int} in Python 3+, but C{float} in Python 2-
1312
1326
 
1313
- def _fhorner(self, x, cs, op, incx=True): # in .fmath
1327
+ def _fhorner(self, x, cs, where, incx=True): # in .fmath
1314
1328
  '''(INTERNAL) Add an L{Fhorner} evaluation of polynomial
1315
1329
  C{sum(cs[i] * B{x}**i for i=0..len(cs)-1) if B{incx}
1316
1330
  else sum(... i=len(cs)-1..0)}.
1317
1331
  '''
1318
- if _xiterablen(cs):
1319
- H = self._Fsum_as(name__=self._fhorner)
1320
- if _isFsum_2Tuple(x):
1321
- _mul = H._mul_Fsum
1322
- else:
1323
- _mul = H._mul_scalar
1324
- x = _2float(x=x, **self._isfine)
1325
- if len(cs) > 1 and x:
1332
+ # assert _xiterablen(cs)
1333
+ try:
1334
+ n = len(cs)
1335
+ H = self._Fsum_as(name__=self._fhorner)
1336
+ _m = H._mul_Fsum if _isFsum_2Tuple(x) else \
1337
+ H._mul_scalar
1338
+ if _2finite(x, **self._isfine) and n > 1:
1326
1339
  for c in (reversed(cs) if incx else cs):
1327
- H._fset_ps(_mul(x, op))
1328
- H._fadd(c, op, up=False)
1340
+ H._fset(_m(x, _mul_op_), up=False)
1341
+ H._fadd(c, up=False)
1329
1342
  else: # x == 0
1330
- H = cs[0] if cs else _0_0
1331
- self._fadd(H, op)
1343
+ H = cs[0] if n else 0
1344
+ self._fadd(H)
1345
+ except Exception as X:
1346
+ t = unstr(where, x, *cs, _ELLIPSIS=4, incx=incx)
1347
+ raise self._ErrorX(X, _add_op_, t)
1332
1348
  return self
1333
1349
 
1334
1350
  def _finite(self, other, op=None):
@@ -1380,36 +1396,28 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1380
1396
  def _fint2(self): # see ._fset
1381
1397
  '''(INTERNAL) Get 2-tuple (C{int}, I{integer} residual).
1382
1398
  '''
1383
- s, _ = self._fprs2
1384
- try:
1399
+ s, r = self._nfprs2
1400
+ if _isfinite(s):
1385
1401
  i = int(s)
1386
1402
  r = (self._ps_1sum(i) if len(self._ps) > 1 else
1387
1403
  float(s - i)) or INT0
1388
- except (OverflowError, ValueError) as X:
1389
- r = _NONFINITEr # INF, NAN, NINF
1390
- i = self._fintX(X, sum(self._ps))
1404
+ else: # INF, NAN, NINF
1405
+ i = float(s)
1406
+ # r = _NONFINITEr
1391
1407
  return i, r # Fsum2Tuple?
1392
1408
 
1393
1409
  @_fint2.setter_ # PYCHOK setter_UNDERscore!
1394
1410
  def _fint2(self, s): # in _fset
1395
1411
  '''(INTERNAL) Replace the C{_fint2} value.
1396
1412
  '''
1397
- try:
1413
+ if _isfinite(s):
1398
1414
  i = int(s)
1399
1415
  r = (s - i) or INT0
1400
- except (OverflowError, ValueError) as X:
1401
- r = _NONFINITEr # INF, NAN, NINF
1402
- i = self._fintX(X, float(s))
1416
+ else: # INF, NAN, NINF
1417
+ i = float(s)
1418
+ r = _NONFINITEr
1403
1419
  return i, r # like _fint2.getter
1404
1420
 
1405
- def _fintX(self, X, i): # PYCHOK X
1406
- '''(INTERNAL) Handle I{non-finite} C{int}.
1407
- '''
1408
- # "cannot convert float infinity to integer"
1409
- return i # ignore such Overflow-/ValueErrors
1410
- # op = int.__name__
1411
- # return self._nonfiniteX(X, op, i)
1412
-
1413
1421
  @deprecated_property_RO
1414
1422
  def float_int(self): # PYCHOK no cover
1415
1423
  '''DEPRECATED, use method C{Fsum.int_float}.'''
@@ -1456,16 +1464,19 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1456
1464
  if r:
1457
1465
  f = self._f2mul(self.fma, other1, **nonfinites)
1458
1466
  f += other2
1459
- else:
1467
+ elif _residue(other1) or _residue(other2):
1460
1468
  fs = _2split3s(_fs(op, other1))
1461
1469
  fs = _2products(s, fs, *_fs(op, other2))
1462
1470
  f = _Psum(self._ps_acc([], fs, up=False), name=op)
1471
+ else:
1472
+ f = _fma(s, other1, other2)
1473
+ f = _2finite(f, **self._isfine)
1463
1474
  except TypeError as X:
1464
1475
  raise self._ErrorX(X, op, (other1, other2))
1465
1476
  except (OverflowError, ValueError) as X: # from math.fma
1466
- f = self._mul_reduce(op, s, other1) # INF, NAN, NINF
1467
- f = sum(_fs(op, f, other2))
1468
- f = self._nonfiniteX(X, op, f, **nonfinites)
1477
+ f = self._mul_reduce(s, other1) # INF, NAN, NINF
1478
+ f += sum(_fs(op, other2))
1479
+ f = self._nonfiniteX(X, op, f, **nonfinites)
1469
1480
  return self._fset(f)
1470
1481
 
1471
1482
  fmul = __imul__
@@ -1524,7 +1535,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1524
1535
  except TypeError as X:
1525
1536
  raise self._ErrorX(X, op, other)
1526
1537
  except (OverflowError, ValueError) as X:
1527
- r = self._mul_reduce(op, sum(ps), other) # INF, NAN, NINF
1538
+ r = self._mul_reduce(sum(ps), other) # INF, NAN, NINF
1528
1539
  r = self._nonfiniteX(X, op, r, **nonfinites_raiser)
1529
1540
  f._fset(r)
1530
1541
  return f
@@ -1557,7 +1568,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1557
1568
  elif self.is_integer():
1558
1569
  # return an exact C{int} for C{int}**C{int}
1559
1570
  i, _ = self._fint2 # assert _ == 0
1560
- x, r = _2scalar2(other) # C{int}, C{float} or other
1571
+ x, r = _2s_r(other) # C{int}, C{float} or other
1561
1572
  f = self._Fsum_as(i)._pow_Fsum(other, op, **raiser_RESIDUAL) if r else \
1562
1573
  self._pow_2_3(i, x, other, op, **raiser_RESIDUAL)
1563
1574
  else: # mod[0] is None, power(self, other)
@@ -1631,10 +1642,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1631
1642
  s = ps[0]
1632
1643
  r = INT0 if _isfinite(s) else _NONFINITEr
1633
1644
  else: # len(ps) == 0
1634
- s, r = _0_0, INT0
1645
+ s = _0_0
1646
+ r = INT0 if _isfinite(s) else _NONFINITEr
1635
1647
  ps[:] = s,
1636
1648
  except (OverflowError, ValueError) as X:
1637
- op = sum.__name__ # INF, NAN, NINF
1649
+ op = _fset_op_ # INF, NAN, NINF
1638
1650
  ps[:] = sum(ps), # collapse ps
1639
1651
  s = self._nonfiniteX(X, op, ps[0])
1640
1652
  r = _NONFINITEr
@@ -1658,8 +1670,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1658
1670
 
1659
1671
  @see: Method L{Fsum.fadd} for further details.
1660
1672
  '''
1661
- f = self._Fsum_as(*xs)
1662
- return self._fset(f, up=False, op=_fset_op_)
1673
+ f = (xs[0] if xs else _0_0) if len(xs) < 2 else \
1674
+ Fsum(*xs, nonfinites=self.nonfinites()) # self._Fsum_as(*xs)
1675
+ return self._fset(f, op=_fset_op_)
1663
1676
 
1664
1677
  def _fset(self, other, n=0, up=True, **op):
1665
1678
  '''(INTERNAL) Overwrite this instance with an other or a C{scalar}.
@@ -1667,6 +1680,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1667
1680
  if other is self:
1668
1681
  pass # from ._fmul, ._ftruediv and ._pow_0_1
1669
1682
  elif _isFsum_2Tuple(other):
1683
+ if op: # and not self.nonfinitesOK:
1684
+ self._finite(other._fprs, **op)
1670
1685
  self._ps[:] = other._ps
1671
1686
  self._n = n or other._n
1672
1687
  if up: # use or zap the C{Property_RO} values
@@ -1689,11 +1704,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1689
1704
  raise self._Error(op, other, _TypeError)
1690
1705
  return self
1691
1706
 
1692
- def _fset_ps(self, other): # in .fmath._Fsum__init__
1693
- '''(INTERNAL) Set partials from a known C{other}.
1694
- '''
1695
- return self._fset(other, up=False)
1696
-
1697
1707
  def fsub(self, xs=()):
1698
1708
  '''Subtract an iterable's items from this instance.
1699
1709
 
@@ -1706,8 +1716,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1706
1716
 
1707
1717
  @see: Method L{Fsum.fadd_} for further details.
1708
1718
  '''
1709
- return self._facc_neg(xs, origin=1) if len(xs) != 1 else \
1710
- self._fsub(xs[0], _sub_op_)
1719
+ return self._fsub(xs[0], _sub_op_) if len(xs) == 1 else \
1720
+ self._facc_neg(xs) # origin=1?
1711
1721
 
1712
1722
  def _fsub(self, other, op):
1713
1723
  '''(INTERNAL) Apply C{B{self} -= B{other}}.
@@ -1725,8 +1735,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1725
1735
  '''Add an iterable's items, summate and return the current
1726
1736
  precision running sum.
1727
1737
 
1728
- @arg xs: Iterable of items to add (each item C{scalar}
1729
- or an L{Fsum} or L{Fsum2Tuple} instance).
1738
+ @arg xs: Iterable of items to add (each item C{scalar},
1739
+ an L{Fsum} or L{Fsum2Tuple}).
1730
1740
 
1731
1741
  @return: Precision running sum (C{float} or C{int}).
1732
1742
 
@@ -1740,8 +1750,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1740
1750
  '''Add any positional items, summate and return the current
1741
1751
  precision running sum.
1742
1752
 
1743
- @arg xs: Items to add (each C{scalar} or an L{Fsum}
1744
- or L{Fsum2Tuple} instance), all positional.
1753
+ @arg xs: Items to add (each C{scalar}, an L{Fsum} or
1754
+ L{Fsum2Tuple}), all positional.
1745
1755
 
1746
1756
  @return: Precision running sum (C{float} or C{int}).
1747
1757
 
@@ -1765,10 +1775,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1765
1775
 
1766
1776
  @return: Precision running sum (L{Fsum2Tuple}).
1767
1777
  '''
1768
- return Fsum2Tuple(self._facc_args(xs)._fprs2, **name)
1778
+ return Fsum2Tuple(self._facc_args(xs)._nfprs2, **name)
1769
1779
 
1770
1780
  @property_RO
1771
- def _Fsum(self): # like L{Fsum2Tuple._Fsum}, for C{_2floats}, .fstats
1781
+ def _Fsum(self): # like L{Fsum2Tuple._Fsum}, in .fstats
1772
1782
  return self # NOT @Property_RO, see .copy and ._copy_2
1773
1783
 
1774
1784
  def _Fsum_as(self, *xs, **name_f2product_nonfinites_RESIDUAL):
@@ -1782,17 +1792,17 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1782
1792
  RESIDUAL =self.RESIDUAL())
1783
1793
  if name_f2product_nonfinites_RESIDUAL: # overwrites
1784
1794
  kwds.update(name_f2product_nonfinites_RESIDUAL)
1785
- F = Fsum(**kwds)
1786
- # assert all(v == self.__dict__[n] for n, v in F.__dict__.items())
1787
- return F._fset(xs[0], op=_fset_op_) if len(xs) == 1 else (
1788
- F._facc(xs, up=False) if xs else F)
1795
+ f = Fsum(**kwds)
1796
+ # assert all(v == self.__dict__[n] for n, v in f.__dict__.items())
1797
+ return f._fset(xs[0], op=_fset_op_) if len(xs) == 1 else (
1798
+ f._facc(xs, up=False) if xs else f)
1789
1799
 
1790
1800
  def fsum2(self, xs=(), **name):
1791
1801
  '''Add an iterable's items, summate and return the
1792
1802
  current precision running sum I{and} the C{residual}.
1793
1803
 
1794
- @arg xs: Iterable of items to add (each item C{scalar}
1795
- or an L{Fsum} or L{Fsum2Tuple} instance).
1804
+ @arg xs: Iterable of items to add (each item C{scalar},
1805
+ an L{Fsum} or L{Fsum2Tuple}).
1796
1806
  @kwarg name: Optional C{B{name}=NN} (C{str}).
1797
1807
 
1798
1808
  @return: L{Fsum2Tuple}C{(fsum, residual)} with C{fsum} the
@@ -1810,8 +1820,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1810
1820
  '''Add any positional items, summate and return the current
1811
1821
  precision running sum and the I{differential}.
1812
1822
 
1813
- @arg xs: Values to add (each C{scalar} or an L{Fsum} or
1814
- L{Fsum2Tuple} instance), all positional.
1823
+ @arg xs: Values to add (each C{scalar}, an L{Fsum} or
1824
+ L{Fsum2Tuple}), all positional.
1815
1825
 
1816
1826
  @return: 2Tuple C{(fsum, delta)} with the current, precision
1817
1827
  running C{fsum} like method L{Fsum.fsum} and C{delta},
@@ -1838,19 +1848,19 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1838
1848
  '''Like method L{Fsum.fsum_} iff I{all} C{B{xs}}, each I{known to be}
1839
1849
  C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
1840
1850
  '''
1841
- return self._facc_scalarf(xs, origin=1, which=self.fsumf_)._fprs
1851
+ return self._facc_scalarf(xs, which=self.fsumf_)._fprs # origin=1?
1842
1852
 
1843
1853
  def Fsumf_(self, *xs):
1844
1854
  '''Like method L{Fsum.Fsum_} iff I{all} C{B{xs}}, each I{known to be}
1845
1855
  C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
1846
1856
  '''
1847
- return self._facc_scalarf(xs, origin=1, which=self.Fsumf_)._copy_2(self.Fsumf_)
1857
+ return self._facc_scalarf(xs, which=self.Fsumf_)._copy_2(self.Fsumf_) # origin=1?
1848
1858
 
1849
1859
  def fsum2f_(self, *xs):
1850
1860
  '''Like method L{Fsum.fsum2_} iff I{all} C{B{xs}}, each I{known to be}
1851
1861
  C{scalar}, an L{Fsum} or L{Fsum2Tuple}.
1852
1862
  '''
1853
- return self._fsum2(xs, self._facc_scalarf, origin=1, which=self.fsum2f_)
1863
+ return self._fsum2(xs, self._facc_scalarf, which=self.fsum2f_) # origin=1?
1854
1864
 
1855
1865
  # ftruediv = __itruediv__ # for naming consistency?
1856
1866
 
@@ -1891,8 +1901,9 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1891
1901
  L{ResidualError}s (C{bool}) and C{B{RESIDUAL}=scalar}
1892
1902
  to override the current L{RESIDUAL<Fsum.RESIDUAL>}.
1893
1903
 
1894
- @return: This C{int} sum if this instance C{is_integer}, otherwise
1895
- the C{float} sum if the residual is zero or not significant.
1904
+ @return: This C{int} sum if this instance C{is_integer} and
1905
+ I{finite}, otherwise the C{float} sum if the residual
1906
+ is zero or not significant.
1896
1907
 
1897
1908
  @raise ResidualError: Non-zero, significant residual or invalid
1898
1909
  B{C{RESIDUAL}}.
@@ -1951,48 +1962,52 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1951
1962
  return _sum is _fsum # _fsum.__module__ is fabs.__module__
1952
1963
 
1953
1964
  def is_scalar(self, **raiser_RESIDUAL):
1954
- '''Is this instance' running sum C{scalar} without residual or with
1965
+ '''Is this instance' running sum C{scalar} with C{0} residual or with
1955
1966
  a residual I{ratio} not exceeding the RESIDUAL threshold?
1956
1967
 
1957
1968
  @kwarg raiser_RESIDUAL: Use C{B{raiser}=False} to ignore
1958
1969
  L{ResidualError}s (C{bool}) and C{B{RESIDUAL}=scalar}
1959
1970
  to override the current L{RESIDUAL<Fsum.RESIDUAL>}.
1960
1971
 
1961
- @return: C{True} if this instance' non-zero residual C{ratio} exceeds
1962
- the L{RESIDUAL<Fsum.RESIDUAL>} threshold (C{bool}).
1972
+ @return: C{True} if this instance' residual is C{0} or C{insignificant},
1973
+ i.e. its residual C{ratio} doesn't exceed the L{RESIDUAL
1974
+ <Fsum.RESIDUAL>} threshold (C{bool}).
1963
1975
 
1964
1976
  @raise ResidualError: Non-zero, significant residual or invalid
1965
1977
  B{C{RESIDUAL}}.
1966
1978
 
1967
- @see: Method L{Fsum.RESIDUAL}, L{Fsum.is_integer} and property
1979
+ @see: Methods L{Fsum.RESIDUAL} and L{Fsum.is_integer} and property
1968
1980
  L{Fsum.as_iscalar}.
1969
1981
  '''
1970
1982
  s, r = self._fprs2
1971
1983
  return False if r and self._raiser(r, s, **raiser_RESIDUAL) else True
1972
1984
 
1973
- def _mul_Fsum(self, other, op=_mul_op_): # in .fmath.Fhorner
1985
+ def _mul_Fsum(self, other, op):
1974
1986
  '''(INTERNAL) Return C{B{self} * B{other}} as L{Fsum} or C{0}.
1975
1987
  '''
1976
1988
  # assert _isFsum_2Tuple(other)
1977
1989
  if self._ps and other._ps:
1978
- f = self._ps_mul(op, *other._ps) # NO .as_iscalar!
1990
+ try:
1991
+ f = self._ps_mul(op, *other._ps) # NO .as_iscalar!
1992
+ except Exception as X:
1993
+ raise self._ErrorX(X, op, other)
1979
1994
  else:
1980
1995
  f = _0_0
1981
1996
  return f
1982
1997
 
1983
- def _mul_reduce(self, op, start, *others):
1984
- '''(INTERNAL) Like fmath.freduce(_operator.mul, ...)
1985
- for I{non-finite} C{start} and/or C{others}.
1998
+ def _mul_reduce(self, *others):
1999
+ '''(INTERNAL) Like fmath.fprod for I{non-finite} C{other}s.
1986
2000
  '''
1987
- for p in self._ps_other(op, *others):
1988
- start *= p
1989
- return start
2001
+ r = _1_0
2002
+ for f in others:
2003
+ r *= sum(f._ps) if _isFsum_2Tuple(f) else float(f)
2004
+ return r
1990
2005
 
1991
- def _mul_scalar(self, factor, op): # in .fmath.Fhorner
2006
+ def _mul_scalar(self, factor, op):
1992
2007
  '''(INTERNAL) Return C{B{self} * scalar B{factor}} as L{Fsum}, C{0.0} or C{self}.
1993
2008
  '''
1994
2009
  # assert isscalar(factor)
1995
- if self._ps and self._finite(factor, op):
2010
+ if self._ps and self._finite(factor, op=op):
1996
2011
  f = self if factor == _1_0 else (
1997
2012
  self._neg if factor == _N_1_0 else
1998
2013
  self._ps_mul(op, factor).as_iscalar)
@@ -2011,6 +2026,16 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2011
2026
  '''
2012
2027
  return _Psum(self._ps_neg) if self._ps else NEG0
2013
2028
 
2029
+ @property_RO
2030
+ def _nfprs2(self):
2031
+ '''(INTERNAL) Handle I{non-finite} C{_fprs2}.
2032
+ '''
2033
+ try: # to handle nonfiniterrors, etc.
2034
+ t = self._fprs2
2035
+ except (OverflowError, ValueError):
2036
+ t = Fsum2Tuple(sum(self._ps), _NONFINITEr)
2037
+ return t
2038
+
2014
2039
  def nonfinites(self, *OK):
2015
2040
  '''Handle I{non-finite} C{float}s as C{inf}, C{INF}, C{NINF}, C{nan}
2016
2041
  and C{NAN} for this L{Fsum} or throw C{OverflowError} respectively
@@ -2048,10 +2073,10 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2048
2073
  def nonfinitesOK(self):
2049
2074
  '''Are I{non-finites} C{OK} for this L{Fsum} or by default? (C{bool}).
2050
2075
  '''
2051
- nf = self.nonfinites()
2052
- if nf is None:
2053
- nf = not nonfiniterrors()
2054
- return nf
2076
+ # nf = self.nonfinites()
2077
+ # if nf is None:
2078
+ # nf = not nonfiniterrors()
2079
+ return _isOK_or_finite(INF, **self._isfine)
2055
2080
 
2056
2081
  def _nonfiniteX(self, X, op, f, nonfinites=None, raiser=None):
2057
2082
  '''(INTERNAL) Handle a I{non-finite} exception.
@@ -2122,7 +2147,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2122
2147
  if _isFsum_2Tuple(other):
2123
2148
  f = self._pow_Fsum(other, op, **raiser_RESIDUAL)
2124
2149
  elif self._scalar(other, op):
2125
- x = self._finite(other, op)
2150
+ x = self._finite(other, op=op)
2126
2151
  f = self._pow_scalar(x, other, op, **raiser_RESIDUAL)
2127
2152
  else:
2128
2153
  f = self._pow_0_1(0, other)
@@ -2149,7 +2174,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2149
2174
  return s
2150
2175
 
2151
2176
  b = _s(*(b._fprs2 if m is None else b._fint2))
2152
- x = _s(*_2scalar2(x))
2177
+ x = _s(*_2s_r(x))
2153
2178
 
2154
2179
  try:
2155
2180
  # 0**INF == 0.0, 1**INF == 1.0, -1**2.3 == -(1**2.3)
@@ -2157,7 +2182,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2157
2182
  if iscomplex(s):
2158
2183
  # neg**frac == complex in Python 3+, but ValueError in 2-
2159
2184
  raise ValueError(_strcomplex(s, b, x, *mod))
2160
- return self._finite(s)
2185
+ _ = _2finite(s, **self._isfine) # ignore float
2186
+ return s
2161
2187
  except Exception as X:
2162
2188
  raise self._ErrorX(X, op, other, *mod)
2163
2189
 
@@ -2258,13 +2284,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2258
2284
  n += 1
2259
2285
  if n:
2260
2286
  self._n += n
2261
- # if _fi: # collapse ps if non-finite
2262
- # x = sum(ps)
2263
- # if not _isfinite(x):
2264
- # ps[:] = x,
2265
2287
  # Fsum._ps_max = max(Fsum._ps_max, len(ps))
2266
2288
  if up:
2267
2289
  self._update()
2290
+ # x = sum(ps)
2291
+ # if not _isOK_or_finite(x, **fi):
2292
+ # ps[:] = x, # collapse ps
2268
2293
  return ps
2269
2294
 
2270
2295
  def _ps_mul(self, op, *factors):
@@ -2285,7 +2310,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2285
2310
 
2286
2311
  for p in ps:
2287
2312
  for f in _pfs(p, fs):
2288
- yield f if _isfine(f) else self._finite(f, op)
2313
+ yield f if _isfine(f) else _nfError(f)
2289
2314
 
2290
2315
  fs = _psfs(self._ps, factors, **self._isfine)
2291
2316
  f = _Psum(self._ps_acc([], fs, up=False), name=op)
@@ -2298,15 +2323,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2298
2323
  for p in self._ps:
2299
2324
  yield -p
2300
2325
 
2301
- def _ps_other(self, op, *others):
2302
- '''(INTERNAL) Yield all C{other}s as C{scalar}.
2326
+ def _ps_other(self, op, other):
2327
+ '''(INTERNAL) Yield C{other} as C{scalar}s.
2303
2328
  '''
2304
- for other in others:
2305
- if _isFsum_2Tuple(other):
2306
- for p in other._ps:
2307
- yield p
2308
- else:
2309
- yield self._scalar(other, op)
2329
+ if _isFsum_2Tuple(other):
2330
+ for p in other._ps:
2331
+ yield p
2332
+ else:
2333
+ yield self._scalar(other, op)
2310
2334
 
2311
2335
  def _ps_1sum(self, *less):
2312
2336
  '''(INTERNAL) Return the partials sum, 1-primed C{less} some scalars.
@@ -2434,7 +2458,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2434
2458
 
2435
2459
  @return: The sign (C{int}, -1, 0 or +1).
2436
2460
  '''
2437
- s, r = self._fprs2
2461
+ s, r = self._nfprs2
2438
2462
  r = (-r) if res else 0
2439
2463
  return _signOf(s, r)
2440
2464
 
@@ -2462,7 +2486,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
2462
2486
  if lenc:
2463
2487
  p = Fmt.SQUARE(p, len(self))
2464
2488
  n = _enquote(self.name, white=_UNDER_)
2465
- t = self._fprs2.toStr(**prec_sep_fmt)
2489
+ t = self._nfprs2.toStr(**prec_sep_fmt)
2466
2490
  return NN(p, _SPACE_, n, t)
2467
2491
 
2468
2492
  def _truediv(self, other, op, **raiser_RESIDUAL):
@@ -2697,7 +2721,7 @@ def fsum_(*xs, **nonfinites):
2697
2721
 
2698
2722
  @see: Function L{fsum<fsums.fsum>} for further details.
2699
2723
  '''
2700
- return _xsum(fsum_, xs, origin=1, **nonfinites) if xs else _0_0
2724
+ return _xsum(fsum_, xs, **nonfinites) if xs else _0_0 # origin=1?
2701
2725
 
2702
2726
 
2703
2727
  def fsumf_(*xs):
@@ -2708,7 +2732,7 @@ def fsumf_(*xs):
2708
2732
 
2709
2733
  @see: Function L{fsum_<fsums.fsum_>} for further details.
2710
2734
  '''
2711
- return _xsum(fsumf_, xs, nonfinites=True, origin=1) if xs else _0_0
2735
+ return _xsum(fsumf_, xs, nonfinites=True) if xs else _0_0 # origin=1?
2712
2736
 
2713
2737
 
2714
2738
  def fsum1(xs, **nonfinites):
@@ -2730,7 +2754,7 @@ def fsum1_(*xs, **nonfinites):
2730
2754
 
2731
2755
  @see: Function L{fsum_<fsums.fsum_>} for further details.
2732
2756
  '''
2733
- return _xsum(fsum1_, xs, origin=1, primed=1, **nonfinites) if xs else _0_0
2757
+ return _xsum(fsum1_, xs, primed=1, **nonfinites) if xs else _0_0 # origin=1?
2734
2758
 
2735
2759
 
2736
2760
  def fsum1f_(*xs):
@@ -2742,40 +2766,54 @@ def fsum1f_(*xs):
2742
2766
  return _xsum(fsum1f_, xs, nonfinites=True, primed=1) if xs else _0_0
2743
2767
 
2744
2768
 
2745
- def _xs(xs, i_x, nfOK): # in Fsum._facc_scalarf
2746
- '''(INTERNAL) Yield all C{xs} as C{scalar}.
2747
- '''
2748
- _x = _passarg if nfOK else _2finite
2749
- for i, x in enumerate(xs):
2750
- i_x[:] = i, x
2751
- if _isFsum_2Tuple(x):
2752
- for p in map(_x, x._ps):
2753
- yield p
2754
- else:
2755
- yield _x(x)
2769
+ def _x_isfine(nfOK, **kwds): # get the C{_x} and C{_isfine} handlers.
2770
+ _x_kwds = dict(_x= (_passarg if nfOK else _2finite),
2771
+ _isfine=(_isOK if nfOK else _isfinite)) # PYCHOK kwds
2772
+ _x_kwds.update(kwds)
2773
+ return _x_kwds
2756
2774
 
2757
2775
 
2758
- def _xsum(which, xs, nonfinites=None, origin=0, primed=0, **floats):
2759
- '''(INTERNAL) Precision summation of C{xs} with conditions.
2776
+ def _X_ps(X): # default C{_X} handler
2777
+ return X._ps # lambda X: X._ps
2778
+
2779
+
2780
+ def _xs(xs, _X=_X_ps, _x=float, _isfine=_isfinite, # defaults for Fsum._facc
2781
+ origin=0, which=None, **_Cdot):
2782
+ '''(INTERNAL) Yield each C{xs} item as 1 or more C{float}s.
2760
2783
  '''
2761
- i_x = [0, xs]
2784
+ i, x = 0, xs
2762
2785
  try:
2763
- if floats: # for backward compatibility
2764
- nonfinites = _xkwds_get1(floats, floats=nonfinites)
2765
- elif nonfinites is None:
2766
- nonfinites = not nonfiniterrors()
2767
- fs = _xs(xs, i_x, nonfinites)
2768
- return _fsum(_1primed(fs) if primed else fs)
2786
+ for i, x in enumerate(_xiterable(xs)):
2787
+ if isinstance(x, _Fsum_2Tuple_types):
2788
+ for p in _X(x):
2789
+ yield p if _isfine(p) else _nfError(p)
2790
+ else:
2791
+ f = _x(x)
2792
+ yield f if _isfine(f) else _nfError(f)
2793
+
2769
2794
  except (OverflowError, TypeError, ValueError) as X:
2770
- origin -= 1 if primed else 0
2771
- i_x += [origin, which]
2772
- raise _ixError(X, xs, *i_x)
2795
+ t = _xsError(X, xs, i + origin, x)
2796
+ if which: # prefix invokation
2797
+ w = unstr(which, *xs, _ELLIPSIS=4, **_Cdot)
2798
+ t = _COMMASPACE_(w, t)
2799
+ raise _xError(X, t, txt=None)
2800
+
2801
+
2802
+ def _xsum(which, xs, nonfinites=None, primed=0, **floats): # origin=0
2803
+ '''(INTERNAL) Precision summation of C{xs} with conditions.
2804
+ '''
2805
+ if floats: # for backward compatibility
2806
+ nonfinites = _xkwds_get1(floats, floats=nonfinites)
2807
+ elif nonfinites is None:
2808
+ nonfinites = not nonfiniterrors()
2809
+ fs = _xs(xs, **_x_isfine(nonfinites, which=which))
2810
+ return _fsum(_1primed(fs) if primed else fs)
2773
2811
 
2774
2812
 
2775
2813
  # delete all decorators, etc.
2776
2814
  del _allPropertiesOf_n, deprecated_method, deprecated_property_RO, \
2777
2815
  Property, Property_RO, property_RO, _ALL_LAZY, _F2PRODUCT, \
2778
- MANT_DIG, _NONFINITES, _RESIDUAL_0_0, _getenv, _std_
2816
+ MANT_DIG, _NONFINITES, _RESIDUAL_0_0, _getPYGEODESY, _std_
2779
2817
 
2780
2818
  if __name__ == '__main__':
2781
2819