pygeodesy 24.9.29__py2.py3-none-any.whl → 24.10.10__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/fmath.py CHANGED
@@ -10,11 +10,11 @@ from pygeodesy.basics import _copysign, copysign0, isbool, isint, isscalar, \
10
10
  len2, map1, _xiterable
11
11
  from pygeodesy.constants import EPS0, EPS02, EPS1, NAN, PI, PI_2, PI_4, \
12
12
  _0_0, _0_125, _1_6th, _0_25, _1_3rd, _0_5, _1_0, \
13
- _N_1_0, _1_5, _copysign_0_0, isfinite, remainder
13
+ _1_5, _copysign_0_0, isfinite, remainder
14
14
  from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
15
- _xError, _xkwds_get1, _xkwds_pop2, _xsError
16
- from pygeodesy.fsums import _2float, Fsum, fsum, fsum1_, _isFsum_2Tuple, \
17
- _1primed, _Psum_, Fmt, unstr
15
+ _xError, _xkwds_pop2, _xsError
16
+ from pygeodesy.fsums import _2float, Fsum, fsum, _isFsum_2Tuple, _1primed, \
17
+ Fmt, unstr
18
18
  from pygeodesy.interns import MISSING, _negative_, _not_scalar_
19
19
  from pygeodesy.lazily import _ALL_LAZY, _sys_version_info2
20
20
  # from pygeodesy.streprs import Fmt, unstr # from .fsums
@@ -24,7 +24,7 @@ from math import fabs, sqrt # pow
24
24
  import operator as _operator # in .datums, .trf, .utm
25
25
 
26
26
  __all__ = _ALL_LAZY.fmath
27
- __version__ = '24.09.29'
27
+ __version__ = '24.10.04'
28
28
 
29
29
  # sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
30
30
  _0_4142 = 0.41421356237309504880 # ... ~ 3730904090310553 / 9007199254740992
@@ -35,14 +35,15 @@ _h_lt_b_ = 'abs(h) < abs(b)'
35
35
  class Fdot(Fsum):
36
36
  '''Precision dot product.
37
37
  '''
38
- def __init__(self, a, *b, **name_RESIDUAL):
38
+ def __init__(self, a, *b, **start_name_f2product_nonfinites_RESIDUAL):
39
39
  '''New L{Fdot} precision dot product M{sum(a[i] * b[i] for i=0..len(a)-1)}.
40
40
 
41
41
  @arg a: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
42
- @arg b: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
43
- @kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
44
- threshold (C{scalar}) for raising L{ResidualError}s, see class
45
- L{Fsum<Fsum.__init__>}.
42
+ @arg b: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
43
+ positional.
44
+ @kwarg start_name_f2product_nonfinites_RESIDUAL: Optional bias C{B{start}=0}
45
+ (C{scalar}, an L{Fsum} or L{Fsum2Tuple}), C{B{name}=NN} (C{str})
46
+ and other settings, see class L{Fsum<Fsum.__init__>}.
46
47
 
47
48
  @raise LenError: Unequal C{len(B{a})} and C{len(B{b})}.
48
49
 
@@ -54,25 +55,37 @@ class Fdot(Fsum):
54
55
 
55
56
  @see: Function L{fdot} and method L{Fsum.fadd}.
56
57
  '''
57
- Fsum.__init__(self, **name_RESIDUAL)
58
- self.fadd(_map_mul(a, b, Fdot))
58
+ s, kwds = _xkwds_pop2(start_name_f2product_nonfinites_RESIDUAL, start=_0_0)
59
+ Fsum.__init__(self, **kwds)
60
+ self(s)
61
+
62
+ n = len(b)
63
+ if len(a) != n: # PYCHOK no cover
64
+ raise LenError(Fdot, a=len(a), b=n)
65
+ self._faddot(n, a, b, **kwds)
66
+
67
+ def _faddot(self, n, xs, ys, **kwds):
68
+ if n > 0:
69
+ _f = Fsum(**kwds)
70
+ r = (_f(x).fmul(y) for x, y in zip(xs, ys)) # PYCHOK attr?
71
+ self.fadd(_1primed(r) if n < 4 else r) # PYCHOK attr?
72
+ return self
59
73
 
60
74
 
61
75
  class Fhorner(Fsum):
62
76
  '''Precision polynomial evaluation using the Horner form.
63
77
  '''
64
- def __init__(self, x, *cs, **incx_name_RESIDUAL):
65
- '''New L{Fhorner} evaluation of polynomial M{sum(cs[i] * x**i for i=0..n)} if
66
- C{B{incx}=False} for decreasing exponent M{sum(... i=n..0)} where C{n =
67
- len(cs) - 1}.
78
+ def __init__(self, x, *cs, **incx_name_f2product_nonfinites_RESIDUAL):
79
+ '''New L{Fhorner} form evaluation of polynomial M{sum(cs[i] * x**i for
80
+ i=0..n)} with in- or decreasing exponent M{sum(... i=n..0)}, where C{n
81
+ = len(cs) - 1}.
68
82
 
69
83
  @arg x: Polynomial argument (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
70
84
  @arg cs: Polynomial coeffients (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}),
71
85
  all positional.
72
- @kwarg incx_name_RESIDUAL: Optional C{B{name}=NN} (C{str}), C{B{incx}=True}
73
- for in-/decreasing exponents (C{bool}) and the C{B{RESIDUAL}=0.0}
74
- threshold (C{scalar}) for raising L{ResidualError}s, see class
75
- L{Fsum<Fsum.__init__>}.
86
+ @kwarg incx_name_f2product_nonfinites_RESIDUAL: Optional C{B{name}=NN} (C{str}),
87
+ C{B{incx}=True} for in-/decreasing exponents (C{bool}) and other
88
+ settings, see class L{Fsum<Fsum.__init__>}.
76
89
 
77
90
  @raise OverflowError: Partial C{2sum} overflow.
78
91
 
@@ -82,54 +95,52 @@ class Fhorner(Fsum):
82
95
 
83
96
  @see: Function L{fhorner} and methods L{Fsum.fadd} and L{Fsum.fmul}.
84
97
  '''
85
- incx, name_RESIDUAL = _xkwds_pop2(incx_name_RESIDUAL, incx=True)
86
- Fsum.__init__(self, **name_RESIDUAL)
87
- if cs:
88
- self._fhorner(x, cs, Fhorner.__name__, incx=incx)
89
- else:
90
- self._fset_ps(_0_0)
98
+ incx, kwds = _xkwds_pop2(incx_name_f2product_nonfinites_RESIDUAL, incx=True)
99
+ Fsum.__init__(self, **kwds)
100
+ self._fhorner(x, cs, Fhorner, incx=incx)
91
101
 
92
102
 
93
103
  class Fhypot(Fsum):
94
104
  '''Precision summation and hypotenuse, default C{root=2}.
95
105
  '''
96
- def __init__(self, *xs, **root_name_RESIDUAL_raiser):
106
+ def __init__(self, *xs, **root_name_f2product_nonfinites_RESIDUAL_raiser):
97
107
  '''New L{Fhypot} hypotenuse of (the I{root} of) several components (raised
98
108
  to the power I{root}).
99
109
 
100
110
  @arg xs: Components (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
101
111
  positional.
102
- @kwarg root_name_RESIDUAL_raiser: Optional, exponent and C{B{root}=2} order
103
- (C{scalar}), C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
104
- threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for
105
- raising L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and
106
- method L{root<Fsum.root>}.
112
+ @kwarg root_name_f2product_nonfinites_RESIDUAL_raiser: Optional, exponent
113
+ and C{B{root}=2} order (C{scalar}), C{B{name}=NN} (C{str}),
114
+ C{B{raiser}=True} (C{bool}) for raising L{ResidualError}s and
115
+ other settings, see class L{Fsum<Fsum.__init__>} and method
116
+ L{root<Fsum.root>}.
107
117
  '''
108
118
  r = None # _xkwds_pop2 error
109
119
  try:
110
- r, kwds = _xkwds_pop2(root_name_RESIDUAL_raiser, root=2)
120
+ r, kwds = _xkwds_pop2(root_name_f2product_nonfinites_RESIDUAL_raiser, root=2)
111
121
  r, kwds = _xkwds_pop2(kwds, power=r) # for backward compatibility
112
- raiser = _Fsum__init__(self, **kwds)
122
+ t, kwds = _xkwds_pop2(kwds, raiser=True)
123
+ Fsum.__init__(self, **kwds)
124
+ self(_0_0)
113
125
  if xs:
114
- self._facc_power(r, xs, Fhypot, **raiser)
115
- self._fset(self.root(r, **raiser))
126
+ self._facc_power(r, xs, Fhypot, raiser=t)
127
+ self._fset(self.root(r, raiser=t))
116
128
  except Exception as X:
117
129
  raise self._ErrorXs(X, xs, root=r)
118
130
 
119
131
 
120
- class Fpolynomial(Fsum):
132
+ class Fpolynomial(Fdot):
121
133
  '''Precision polynomial evaluation.
122
134
  '''
123
- def __init__(self, x, *cs, **name_RESIDUAL):
135
+ def __init__(self, x, *cs, **name_f2product_nonfinites_RESIDUAL):
124
136
  '''New L{Fpolynomial} evaluation of the polynomial M{sum(cs[i] * x**i for
125
137
  i=0..len(cs)-1)}.
126
138
 
127
139
  @arg x: Polynomial argument (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
128
140
  @arg cs: Polynomial coeffients (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}),
129
141
  all positional.
130
- @kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
131
- threshold (C{scalar}) for raising L{ResidualError}s, see class
132
- L{Fsum<Fsum.__init__>}.
142
+ @kwarg name_f2product_nonfinites_RESIDUAL: Optional C{B{name}=NN} (C{str})
143
+ and other settings, see class L{Fsum<Fsum.__init__>}.
133
144
 
134
145
  @raise OverflowError: Partial C{2sum} overflow.
135
146
 
@@ -139,32 +150,34 @@ class Fpolynomial(Fsum):
139
150
 
140
151
  @see: Class L{Fhorner}, function L{fpolynomial} and method L{Fsum.fadd}.
141
152
  '''
142
- Fsum.__init__(self, *cs[:1], **name_RESIDUAL)
153
+ Fsum.__init__(self, *cs[:1], **name_f2product_nonfinites_RESIDUAL)
143
154
  n = len(cs) - 1
144
155
  if n > 0:
145
- self.fadd(_1map_mul(cs[1:], _powers(x, n)))
156
+ self._faddot(n, cs[1:], _powers(x, n), **name_f2product_nonfinites_RESIDUAL)
146
157
  elif n < 0:
147
- self._fset_ps(_0_0)
158
+ self(_0_0)
148
159
 
149
160
 
150
161
  class Fpowers(Fsum):
151
162
  '''Precision summation of powers, optimized for C{power=2, 3 and 4}.
152
163
  '''
153
- def __init__(self, power, *xs, **name_RESIDUAL_raiser):
164
+ def __init__(self, power, *xs, **name_f2product_nonfinites_RESIDUAL_raiser):
154
165
  '''New L{Fpowers} sum of (the I{power} of) several bases.
155
166
 
156
167
  @arg power: The exponent (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
157
168
  @arg xs: One or more bases (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
158
169
  positional.
159
- @kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
160
- threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for raising
161
- L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and method
170
+ @kwarg name_f2product_nonfinites_RESIDUAL_raiser: Optional C{B{name}=NN}
171
+ (C{str}), C{B{raiser}=True} (C{bool}) for raising L{ResidualError}s
172
+ and other settings, see class L{Fsum<Fsum.__init__>} and method
162
173
  L{fpow<Fsum.fpow>}.
163
174
  '''
164
175
  try:
165
- raiser = _Fsum__init__(self, **name_RESIDUAL_raiser)
176
+ t, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
177
+ Fsum.__init__(self, **kwds)
178
+ self(_0_0)
166
179
  if xs:
167
- self._facc_power(power, xs, Fpowers, **raiser) # x**0 == 1
180
+ self._facc_power(power, xs, Fpowers, raiser=t) # x**0 == 1
168
181
  except Exception as X:
169
182
  raise self._ErrorXs(X, xs, power=power)
170
183
 
@@ -172,22 +185,24 @@ class Fpowers(Fsum):
172
185
  class Froot(Fsum):
173
186
  '''The root of a precision summation.
174
187
  '''
175
- def __init__(self, root, *xs, **name_RESIDUAL_raiser):
188
+ def __init__(self, root, *xs, **name_f2product_nonfinites_RESIDUAL_raiser):
176
189
  '''New L{Froot} root of a precision sum.
177
190
 
178
191
  @arg root: The order (C{scalar}, an L{Fsum} or L{Fsum2Tuple}), non-zero.
179
192
  @arg xs: Items to summate (each a C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
180
193
  positional.
181
- @kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
182
- threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for raising
183
- L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and method
194
+ @kwarg name_f2product_nonfinites_RESIDUAL_raiser: Optional C{B{name}=NN}
195
+ (C{str}), C{B{raiser}=True} (C{bool}) for raising L{ResidualError}s
196
+ and other settings, see class L{Fsum<Fsum.__init__>} and method
184
197
  L{fpow<Fsum.fpow>}.
185
198
  '''
186
199
  try:
187
- raiser = _Fsum__init__(self, **name_RESIDUAL_raiser)
200
+ raiser, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
201
+ Fsum.__init__(self, **kwds)
202
+ self(_0_0)
188
203
  if xs:
189
204
  self.fadd(xs)
190
- self._fset(self.root(root, **raiser))
205
+ self(self.root(root, raiser=raiser))
191
206
  except Exception as X:
192
207
  raise self._ErrorXs(X, xs, root=root)
193
208
 
@@ -195,31 +210,23 @@ class Froot(Fsum):
195
210
  class Fcbrt(Froot):
196
211
  '''Cubic root of a precision summation.
197
212
  '''
198
- def __init__(self, *xs, **name_RESIDUAL_raiser):
213
+ def __init__(self, *xs, **name_f2product_nonfinites_RESIDUAL_raiser):
199
214
  '''New L{Fcbrt} cubic root of a precision sum.
200
215
 
201
- @see: Class L{Froot} for further details.
216
+ @see: Class L{Froot<Froot.__init__>} for further details.
202
217
  '''
203
- Froot.__init__(self, 3, *xs, **name_RESIDUAL_raiser)
218
+ Froot.__init__(self, 3, *xs, **name_f2product_nonfinites_RESIDUAL_raiser)
204
219
 
205
220
 
206
221
  class Fsqrt(Froot):
207
222
  '''Square root of a precision summation.
208
223
  '''
209
- def __init__(self, *xs, **name_RESIDUAL_raiser):
224
+ def __init__(self, *xs, **name_f2product_nonfinites_RESIDUAL_raiser):
210
225
  '''New L{Fsqrt} square root of a precision sum.
211
226
 
212
- @see: Class L{Froot} for further details.
227
+ @see: Class L{Froot<Froot.__init__>} for further details.
213
228
  '''
214
- Froot.__init__(self, 2, *xs, **name_RESIDUAL_raiser)
215
-
216
-
217
- def _Fsum__init__(inst, raiser=MISSING, **name_RESIDUAL):
218
- '''(INTERNAL) Init an C{F...} instance above.
219
- '''
220
- Fsum.__init__(inst, **name_RESIDUAL) # PYCHOK self
221
- inst._fset_ps(_0_0)
222
- return {} if raiser is MISSING else dict(raiser=raiser)
229
+ Froot.__init__(self, 2, *xs, **name_f2product_nonfinites_RESIDUAL_raiser)
223
230
 
224
231
 
225
232
  def bqrt(x):
@@ -297,7 +304,7 @@ def euclid(x, y):
297
304
  x, y = abs(x), abs(y) # NOT fabs!
298
305
  if y > x:
299
306
  x, y = y, x
300
- return x + y * _0_4142 # XXX * _0_5 before 20.10.02
307
+ return x + y * _0_4142 # * _0_5 before 20.10.02
301
308
 
302
309
 
303
310
  def euclid_(*xs):
@@ -322,7 +329,7 @@ def euclid_(*xs):
322
329
 
323
330
 
324
331
  def facos1(x):
325
- '''Fast approximation of L{pygeodesy.acos1}C{(B{x})}.
332
+ '''Fast approximation of L{pygeodesy.acos1}C{(B{x})}, scalar.
326
333
 
327
334
  @see: U{ShaderFastLibs.h<https://GitHub.com/michaldrobot/
328
335
  ShaderFastLibs/blob/master/ShaderFastMathLib.h>}.
@@ -331,9 +338,8 @@ def facos1(x):
331
338
  if a < EPS0:
332
339
  r = PI_2
333
340
  elif a < EPS1:
334
- H = Fhorner(-a, 1.5707288, 0.2121144, 0.0742610, 0.0187293)
335
- H *= Fsqrt(_1_0, -a)
336
- r = float(H)
341
+ r = _fast(-a, 1.5707288, 0.2121144, 0.0742610, 0.0187293)
342
+ r *= sqrt(_1_0 - a)
337
343
  if x < 0:
338
344
  r = PI - r
339
345
  else:
@@ -342,15 +348,24 @@ def facos1(x):
342
348
 
343
349
 
344
350
  def fasin1(x): # PYCHOK no cover
345
- '''Fast approximation of L{pygeodesy.asin1}C{(B{x})}.
351
+ '''Fast approximation of L{pygeodesy.asin1}C{(B{x})}, scalar.
346
352
 
347
353
  @see: L{facos1}.
348
354
  '''
349
355
  return PI_2 - facos1(x)
350
356
 
351
357
 
358
+ def _fast(x, *cs):
359
+ '''(INTERNAL) Horner form for C{facos1} and C{fatan1}.
360
+ '''
361
+ h = 0
362
+ for c in reversed(cs):
363
+ h = _fma(x, h, c) if h else c
364
+ return h
365
+
366
+
352
367
  def fatan(x):
353
- '''Fast approximation of C{atan(B{x})}.
368
+ '''Fast approximation of C{atan(B{x})}, scalar.
354
369
  '''
355
370
  a = fabs(x)
356
371
  if a < _1_0:
@@ -374,14 +389,13 @@ def fatan1(x):
374
389
  IEEE Signal Processing Magazine, 111, May 2006.
375
390
  '''
376
391
  # Eq (9): PI_4 * x - x * (abs(x) - 1) * (0.2447 + 0.0663 * abs(x)), for -1 < x < 1
377
- # PI_4 * x - (x**2 - x) * (0.2447 + 0.0663 * x), for 0 < x < 1
378
- # x * (1.0300981633974482 + x * (-0.1784 - x * 0.0663))
379
- H = Fhorner(x, _0_0, 1.0300981634, -0.1784, -0.0663)
380
- return float(H)
392
+ # == PI_4 * x - (x**2 - x) * (0.2447 + 0.0663 * x), for 0 < x < 1
393
+ # == x * (1.0300981633974482 + x * (-0.1784 - x * 0.0663))
394
+ return _fast(x, _0_0, 1.0300981634, -0.1784, -0.0663)
381
395
 
382
396
 
383
397
  def fatan2(y, x):
384
- '''Fast approximation of C{atan2(B{y}, B{x})}.
398
+ '''Fast approximation of C{atan2(B{y}, B{x})}, scalar.
385
399
 
386
400
  @see: U{fastApproximateAtan(x, y)<https://GitHub.com/CesiumGS/cesium/blob/
387
401
  master/Source/Shaders/Builtin/Functions/fastApproximateAtan.glsl>}
@@ -403,29 +417,28 @@ def fatan2(y, x):
403
417
  return r
404
418
 
405
419
 
406
- def favg(a, b, f=_0_5):
420
+ def favg(a, b, f=_0_5, nonfinites=True):
407
421
  '''Return the precise average of two values.
408
422
 
409
423
  @arg a: One (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
410
424
  @arg b: Other (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
411
425
  @kwarg f: Optional fraction (C{float}).
426
+ @kwarg nonfinites: Optional setting, see function L{fma}.
412
427
 
413
428
  @return: M{a + f * (b - a)} (C{float}).
414
429
  '''
415
- # @raise ValueError: Fraction out of range.
416
- # '''
417
- # if not 0 <= f <= 1: # XXX restrict fraction?
418
- # raise _ValueError(fraction=f)
419
- # a + f * (b - a) == a * (1 - f) + b * f
420
- return fsum1_(a, a * (-f), b * f)
430
+ F = fma(f, (b - a), a, nonfinites=nonfinites)
431
+ return float(F)
421
432
 
422
433
 
423
- def fdot(a, *b):
434
+ def fdot(a, *b, **start):
424
435
  '''Return the precision dot product M{sum(a[i] * b[i] for ni=0..len(a))}.
425
436
 
426
437
  @arg a: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
427
438
  @arg b: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
428
439
  positional.
440
+ @kwarg start: Optional bias C{B{start}=0} (C{scalar}, an L{Fsum} or
441
+ L{Fsum2Tuple}).
429
442
 
430
443
  @return: Dot product (C{float}).
431
444
 
@@ -435,7 +448,8 @@ def fdot(a, *b):
435
448
  <https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>} and function
436
449
  C{math.sumprod} in Python 3.12 and later.
437
450
  '''
438
- return fsum(_map_mul(a, b, fdot))
451
+ D = Fdot(a, nonfinites=True, *b, **start)
452
+ return float(D)
439
453
 
440
454
 
441
455
  def fdot3(xs, ys, zs, start=0):
@@ -450,34 +464,26 @@ def fdot3(xs, ys, zs, start=0):
450
464
  @return: Dot product (C{float}).
451
465
 
452
466
  @raise LenError: Unequal C{len(B{xs})}, C{len(B{ys})} and/or C{len(B{zs})}.
453
-
454
- @raise OverflowError: Partial C{2sum} overflow.
455
467
  '''
456
- def _mul3(xs, ys, zs, s, p):
457
- if s:
458
- yield s
459
- if p:
460
- yield _1_0
461
- for x, y, z in zip(xs, ys, zs):
462
- yield (Fsum(x) * y) * z
463
- if p:
464
- yield _N_1_0
465
-
466
468
  n = len(xs)
467
469
  if not n == len(ys) == len(zs):
468
470
  raise LenError(fdot3, xs=n, ys=len(ys), zs=len(zs))
469
471
 
470
- return fsum(_mul3(xs, ys, zs, start, n < 4))
472
+ D = Fdot((), nonfinites=True, start=start)
473
+ _f = Fsum(nonfinites=True) # f2product=True
474
+ r = (_f(x).f2mul_(y, z) for x, y, z in zip(xs, ys, zs))
475
+ D = D.fadd(_1primed(r) if n < 4 else r)
476
+ return float(D)
471
477
 
472
478
 
473
479
  def fhorner(x, *cs, **incx):
474
- '''Evaluate a polynomial using the Horner form M{sum(cs[i] * x**i
475
- for i=0..n)} or if C{B{incx}=False} for decreasing exponent
476
- M{sum(... i=n..0)} where C{n = len(cs) - 1}.
480
+ '''Horner form evaluation of polynomial M{sum(cs[i] * x**i for
481
+ i=0..n)} with in- or decreasing exponent M{sum(... i=n..0)},
482
+ where C{n = len(cs) - 1}.
477
483
 
478
484
  @return: Horner sum (C{float}).
479
485
 
480
- @see: Class L{Fhorner} for further details.
486
+ @see: Class L{Fhorner<Fhorner.__init__>} for further details.
481
487
  '''
482
488
  H = Fhorner(x, *cs, **incx)
483
489
  return float(H)
@@ -508,12 +514,10 @@ def fidw(xs, ds, beta=2):
508
514
  b = -Int_(beta=beta, low=0, high=3)
509
515
  if b < 0:
510
516
  try: # weighted
511
- _F = Fsum
512
- W = _F()
513
- X = _F()
517
+ _d, W, X = (Fsum() for _ in range(3))
514
518
  for i, d in enumerate(_xiterable(ds)):
515
- x = xs[i]
516
- D = _F(d)
519
+ x = xs[i]
520
+ D = _d(d)
517
521
  if D < EPS0:
518
522
  if D < 0:
519
523
  raise ValueError(_negative_)
@@ -530,7 +534,8 @@ def fidw(xs, ds, beta=2):
530
534
  i += 1 # len(xs) < i < len(ds)
531
535
  except Exception as X:
532
536
  _I = Fmt.INDEX
533
- raise _xError(X, _I(xs=i), x, _I(ds=i), d)
537
+ raise _xError(X, _I(xs=i), x,
538
+ _I(ds=i), d)
534
539
  else: # b == 0
535
540
  x = fsum(xs) / n # fmean(xs)
536
541
  i = n
@@ -545,20 +550,35 @@ def fidw(xs, ds, beta=2):
545
550
  return x
546
551
 
547
552
 
548
- def fma(x, y, z, **nonfinites):
553
+ try:
554
+ from math import fma as _fma
555
+ except ImportError: # PYCHOK DSPACE!
556
+
557
+ def _fma(x, y, z): # no need for accuracy
558
+ return x * y + z
559
+
560
+
561
+ def fma(x, y, z, **nonfinites): # **raiser
549
562
  '''Fused-multiply-add, using C{math.fma(x, y, z)} in Python 3.13+
550
563
  or an equivalent implementation.
551
564
 
552
565
  @arg x: Multiplicand (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
553
566
  @arg y: Multiplier (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
554
567
  @arg z: Addend (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
555
- @kwarg nonfinites: Use C{B{nonfinites}=True} or C{=False}, to
556
- override default L{nonfiniterrors} (C{bool}),
557
- see L{Fsum<Fsum.__init__>},
568
+ @kwarg nonfinites: Use C{B{nonfinites}=True} or C{=False},
569
+ to override default L{nonfiniterrors}
570
+ (C{bool}), see method L{Fsum.fma}.
558
571
 
559
- @return: C{(x * y) + z} (L{Fsum} or C{float}).
572
+ @return: C{(x * y) + z} (C{float} or L{Fsum}).
560
573
  '''
561
- return _Psum_(x).fma(y, z, **nonfinites).as_iscalar
574
+ F, raiser = _Fm2(x, **nonfinites)
575
+ return F.fma(y, z, **raiser).as_iscalar
576
+
577
+
578
+ def _Fm2(x, nonfinites=None, **raiser):
579
+ '''(INTERNAL) Handle C{fma} and C{f2mul} DEPRECATED C{raiser=False}.
580
+ '''
581
+ return Fsum(x, nonfinites=nonfinites), raiser
562
582
 
563
583
 
564
584
  def fmean(xs):
@@ -575,50 +595,51 @@ def fmean(xs):
575
595
  n, xs = len2(xs)
576
596
  if n < 1:
577
597
  raise LenError(fmean, xs=xs)
578
- return Fsum(*xs).fover(n) if n > 1 else _2float(index=0, xs=xs[0])
598
+ M = Fsum(*xs, nonfinites=True)
599
+ return M.fover(n) if n > 1 else float(M)
579
600
 
580
601
 
581
- def fmean_(*xs):
602
+ def fmean_(*xs, **nonfinites):
582
603
  '''Compute the accurate mean M{sum(xs) / len(xs)}.
583
604
 
584
605
  @see: Function L{fmean} for further details.
585
606
  '''
586
- return fmean(xs)
607
+ return fmean(xs, **nonfinites)
587
608
 
588
609
 
589
- def f2mul_(x, *ys, **nonfinites):
610
+ def f2mul_(x, *ys, **nonfinites): # **raiser
590
611
  '''Cascaded, accurate multiplication C{B{x} * B{y} * B{y} ...} for all B{C{ys}}.
591
612
 
592
613
  @arg x: Multiplicand (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
593
614
  @arg ys: Multipliers (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
594
615
  positional.
595
616
  @kwarg nonfinites: Use C{B{nonfinites}=True} or C{=False}, to override default
596
- L{nonfiniterrors} (C{bool}), see L{Fsum<Fsum.__init__>}.
617
+ L{nonfiniterrors} (C{bool}), see method L{Fsum.f2mul_}.
597
618
 
598
- @return: The cascaded I{TwoProduct} (L{Fsum}, C{float} or C{int}).
619
+ @return: The cascaded I{TwoProduct} (C{float}, C{int} or L{Fsum}).
599
620
 
600
621
  @see: U{Equations 2.3<https://www.TUHH.De/ti3/paper/rump/OzOgRuOi06.pdf>}
601
622
  '''
602
- return _Psum_(x).f2mul_(*ys, **nonfinites).as_iscalar
603
-
623
+ F, raiser = _Fm2(x, **nonfinites)
624
+ return F.f2mul_(*ys, **raiser).as_iscalar
604
625
 
605
- def fpolynomial(x, *cs, **over):
606
- '''Evaluate the polynomial M{sum(cs[i] * x**i for i=0..len(cs))
607
- [/ over]}.
608
626
 
609
- @kwarg over: Optional final, I{non-zero} divisor (C{scalar}).
627
+ def fpolynomial(x, *cs, **over_f2product_nonfinites):
628
+ '''Evaluate the polynomial M{sum(cs[i] * x**i for i=0..len(cs)) [/ over]}.
610
629
 
611
- @return: Polynomial value (C{float}).
630
+ @kwarg over_f2product_nonfinites: Optional final divisor C{B{over}=None}
631
+ (I{non-zero} C{scalar}) and other settings, see class
632
+ L{Fpolynomial<Fpolynomial.__init__>}.
612
633
 
613
- @see: Class L{Fpolynomial} for further details.
634
+ @return: Polynomial value (C{float} or L{Fpolynomial}).
614
635
  '''
615
- P = Fpolynomial(x, *cs)
616
- d = _xkwds_get1(over, over=0) if over else 0
636
+ d, kwds = _xkwds_pop2(over_f2product_nonfinites, over=0)
637
+ P = Fpolynomial(x, *cs, **kwds)
617
638
  return P.fover(d) if d else float(P)
618
639
 
619
640
 
620
641
  def fpowers(x, n, alts=0):
621
- '''Return a series of powers M{[x**i for i=1..n]}.
642
+ '''Return a series of powers M{[x**i for i=1..n]}, note I{1..!}
622
643
 
623
644
  @arg x: Value (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
624
645
  @arg n: Highest exponent (C{int}).
@@ -658,7 +679,7 @@ except ImportError:
658
679
  @kwarg start: Initial value, also the value returned
659
680
  for an empty B{C{xs}} (C{scalar}).
660
681
 
661
- @return: The product (C{float} or an L{Fsum}).
682
+ @return: The product (C{float} or L{Fsum}).
662
683
 
663
684
  @see: U{NumPy.prod<https://docs.SciPy.org/doc/
664
685
  numpy/reference/generated/numpy.prod.html>}.
@@ -808,7 +829,7 @@ if _sys_version_info2 < (3, 8): # PYCHOK no cover
808
829
  computed as M{hypot_(*((c1 - c2) for c1, c2 in zip(p1, p2)))},
809
830
  provided I{p1} and I{p2} have the same, non-zero length I{n}.
810
831
  '''
811
- return float(Fhypot(*xs, raiser=False))
832
+ return float(_Hypot(*xs))
812
833
 
813
834
  elif _sys_version_info2 < (3, 10):
814
835
  # In Python 3.8 and 3.9 C{math.hypot} is inaccurate, see
@@ -824,7 +845,7 @@ elif _sys_version_info2 < (3, 10):
824
845
 
825
846
  @return: C{sqrt(B{x}**2 + B{y}**2)} (C{float}).
826
847
  '''
827
- return float(Fhypot(x, y, raiser=False))
848
+ return float(_Hypot(x, y))
828
849
 
829
850
  from math import hypot as hypot_ # PYCHOK in Python 3.8 and 3.9
830
851
  else:
@@ -832,17 +853,26 @@ else:
832
853
  hypot_ = hypot
833
854
 
834
855
 
856
+ def _Hypot(*xs):
857
+ '''(INTERNAL) Substitute for inaccurate C{math.hypot}.
858
+ '''
859
+ return Fhypot(*xs, nonfinites=True, raiser=False) # f2product=True
860
+
861
+
835
862
  def hypot1(x):
836
863
  '''Compute the norm M{sqrt(1 + x**2)}.
837
864
 
838
865
  @arg x: Argument (C{scalar} or L{Fsum} or L{Fsum2Tuple}).
839
866
 
840
- @return: Norm (C{float}).
867
+ @return: Norm (C{float} or L{Fhypot}).
841
868
  '''
842
- if _isFsum_2Tuple(x):
843
- h = float(Fhypot(_1_0, x)) if x else _1_0
844
- else:
845
- h = hypot(_1_0, x) if x else _1_0
869
+ h = _1_0
870
+ if x:
871
+ if _isFsum_2Tuple(x):
872
+ h = _Hypot(h, x)
873
+ h = float(h)
874
+ else:
875
+ h = hypot(h, x)
846
876
  return h
847
877
 
848
878
 
@@ -857,14 +887,10 @@ def hypot2(x, y):
857
887
  x, y = map1(abs, x, y) # NOT fabs!
858
888
  if y > x:
859
889
  x, y = y, x
860
- if x:
861
- h2 = x**2
862
- if y:
863
- h2 *= (y / x)**2 + _1_0
864
- h2 = float(h2)
865
- else:
866
- h2 = _0_0
867
- return h2
890
+ h2 = x**2
891
+ if h2 and y:
892
+ h2 *= (y / x)**2 + _1_0
893
+ return float(h2)
868
894
 
869
895
 
870
896
  def hypot2_(*xs):
@@ -878,29 +904,14 @@ def hypot2_(*xs):
878
904
  @see: Class L{Fpowers} for further details.
879
905
  '''
880
906
  h2 = float(max(map(abs, xs))) if xs else _0_0
881
- if h2:
907
+ if h2: # and isfinite(h2)
882
908
  _h = _1_0 / h2
883
- h2 = Fpowers(2, *((x * _h) for x in xs))
884
- h2 = h2.fover(_h**2)
909
+ xs = ((x * _h) for x in xs)
910
+ H2 = Fpowers(2, *xs, nonfinites=True) # f2product=True
911
+ h2 = H2.fover(_h**2)
885
912
  return h2
886
913
 
887
914
 
888
- def _map_mul(xs, ys, where):
889
- '''(INTERNAL) Yield each B{C{x * y}}.
890
- '''
891
- n = len(ys)
892
- if len(xs) != n: # PYCHOK no cover
893
- raise LenError(where, xs=len(xs), ys=n)
894
- return _1map_mul(xs, ys) if n < 4 else map(
895
- _operator.mul, map(Fsum, xs), ys)
896
-
897
-
898
- def _1map_mul(xs, ys):
899
- '''(INTERNAL) Yield each B{C{x * y}}, 1-primed.
900
- '''
901
- return _1primed(map(_operator.mul, map(Fsum, xs), ys))
902
-
903
-
904
915
  def norm2(x, y):
905
916
  '''Normalize a 2-dimensional vector.
906
917
 
@@ -961,7 +972,8 @@ def _root(x, p, where):
961
972
  '''
962
973
  try:
963
974
  if x > 0:
964
- return Fsum(x).fpow(p).as_iscalar
975
+ r = Fsum(f2product=True, nonfinites=True)(x)
976
+ return r.fpow(p).as_iscalar
965
977
  elif x < 0:
966
978
  raise ValueError(_negative_)
967
979
  except Exception as X: