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.
- {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/METADATA +15 -15
- {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/RECORD +56 -56
- pygeodesy/__init__.py +20 -19
- pygeodesy/__main__.py +5 -5
- pygeodesy/albers.py +12 -17
- pygeodesy/basics.py +38 -41
- pygeodesy/booleans.py +54 -46
- pygeodesy/cartesianBase.py +2 -2
- pygeodesy/constants.py +20 -16
- pygeodesy/datums.py +3 -3
- pygeodesy/dms.py +250 -270
- pygeodesy/ellipsoidalBase.py +2 -2
- pygeodesy/ellipsoidalBaseDI.py +10 -10
- pygeodesy/ellipsoidalNvector.py +4 -4
- pygeodesy/ellipsoidalVincenty.py +2 -2
- pygeodesy/ellipsoids.py +7 -48
- pygeodesy/elliptic.py +14 -14
- pygeodesy/errors.py +15 -10
- pygeodesy/etm.py +18 -2
- pygeodesy/fmath.py +188 -176
- pygeodesy/formy.py +4 -4
- pygeodesy/fstats.py +54 -56
- pygeodesy/fsums.py +304 -266
- pygeodesy/geodesici.py +43 -40
- pygeodesy/geodesicw.py +3 -3
- pygeodesy/geodesicx/gxarea.py +3 -2
- pygeodesy/geodsolve.py +73 -24
- pygeodesy/geohash.py +2 -2
- pygeodesy/geoids.py +28 -27
- pygeodesy/internals.py +156 -85
- pygeodesy/interns.py +23 -20
- pygeodesy/karney.py +61 -12
- pygeodesy/latlonBase.py +13 -15
- pygeodesy/lazily.py +206 -214
- pygeodesy/mgrs.py +13 -13
- pygeodesy/named.py +11 -10
- pygeodesy/nvectorBase.py +1 -1
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +34 -13
- pygeodesy/rhumb/bases.py +5 -5
- pygeodesy/rhumb/solve.py +7 -8
- pygeodesy/solveBase.py +7 -25
- pygeodesy/sphericalBase.py +20 -23
- pygeodesy/sphericalNvector.py +24 -23
- pygeodesy/sphericalTrigonometry.py +9 -8
- pygeodesy/streprs.py +11 -8
- pygeodesy/trf.py +6 -4
- pygeodesy/triaxials.py +46 -9
- pygeodesy/units.py +4 -3
- pygeodesy/ups.py +6 -6
- pygeodesy/utily.py +2 -2
- pygeodesy/utm.py +2 -2
- pygeodesy/vector3d.py +5 -5
- pygeodesy/vector3dBase.py +4 -5
- {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/top_level.txt +0 -0
pygeodesy/fmath.py
CHANGED
|
@@ -10,13 +10,13 @@ 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
|
-
|
|
13
|
+
_1_5, _copysign_0_0, isfinite, remainder
|
|
14
14
|
from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
|
|
15
|
-
_xError,
|
|
16
|
-
from pygeodesy.fsums import _2float, Fsum, fsum,
|
|
17
|
-
|
|
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
|
-
from pygeodesy.lazily import _ALL_LAZY,
|
|
19
|
+
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
20
20
|
# from pygeodesy.streprs import Fmt, unstr # from .fsums
|
|
21
21
|
from pygeodesy.units import Int_, _isHeight, _isRadius, Float_ # PYCHOK for .heights
|
|
22
22
|
|
|
@@ -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.
|
|
27
|
+
__version__ = '24.10.11'
|
|
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, **
|
|
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
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
58
|
-
|
|
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, **
|
|
65
|
-
'''New L{Fhorner} evaluation of polynomial M{sum(cs[i] * x**i for
|
|
66
|
-
|
|
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
|
|
73
|
-
for in-/decreasing exponents (C{bool}) and
|
|
74
|
-
|
|
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,
|
|
86
|
-
Fsum.__init__(self, **
|
|
87
|
-
|
|
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, **
|
|
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
|
|
103
|
-
(C{scalar}), C{B{name}=NN} (C{str}),
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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(
|
|
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
|
-
|
|
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,
|
|
115
|
-
self._fset(self.root(r,
|
|
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(
|
|
132
|
+
class Fpolynomial(Fdot):
|
|
121
133
|
'''Precision polynomial evaluation.
|
|
122
134
|
'''
|
|
123
|
-
def __init__(self, x, *cs, **
|
|
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
|
|
131
|
-
|
|
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], **
|
|
153
|
+
Fsum.__init__(self, *cs[:1], **name_f2product_nonfinites_RESIDUAL)
|
|
143
154
|
n = len(cs) - 1
|
|
144
155
|
if n > 0:
|
|
145
|
-
self.
|
|
156
|
+
self._faddot(n, cs[1:], _powers(x, n), **name_f2product_nonfinites_RESIDUAL)
|
|
146
157
|
elif n < 0:
|
|
147
|
-
self
|
|
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, **
|
|
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
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
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,
|
|
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, **
|
|
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
|
|
182
|
-
|
|
183
|
-
|
|
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 =
|
|
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
|
|
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, **
|
|
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, **
|
|
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, **
|
|
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, **
|
|
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 #
|
|
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
|
-
|
|
335
|
-
|
|
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
|
-
#
|
|
378
|
-
#
|
|
379
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
'''
|
|
475
|
-
|
|
476
|
-
|
|
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
|
-
|
|
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 =
|
|
516
|
-
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,
|
|
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
|
-
|
|
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},
|
|
556
|
-
override default L{nonfiniterrors}
|
|
557
|
-
see L{Fsum
|
|
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} (
|
|
572
|
+
@return: C{(x * y) + z} (C{float} or L{Fsum}).
|
|
560
573
|
'''
|
|
561
|
-
|
|
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
|
-
|
|
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
|
|
617
|
+
L{nonfiniterrors} (C{bool}), see method L{Fsum.f2mul_}.
|
|
597
618
|
|
|
598
|
-
@return: The cascaded I{TwoProduct} (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
@
|
|
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
|
-
@
|
|
634
|
+
@return: Polynomial value (C{float} or L{Fpolynomial}).
|
|
614
635
|
'''
|
|
615
|
-
|
|
616
|
-
|
|
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
|
|
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>}.
|
|
@@ -783,7 +804,7 @@ def fremainder(x, y):
|
|
|
783
804
|
return r
|
|
784
805
|
|
|
785
806
|
|
|
786
|
-
if
|
|
807
|
+
if _MODS.sys_version_info2 < (3, 8): # PYCHOK no cover
|
|
787
808
|
from math import hypot # OK in Python 3.7-
|
|
788
809
|
|
|
789
810
|
def hypot_(*xs):
|
|
@@ -808,9 +829,9 @@ 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(
|
|
832
|
+
return float(_Hypot(*xs))
|
|
812
833
|
|
|
813
|
-
elif
|
|
834
|
+
elif _MODS.sys_version_info2 < (3, 10):
|
|
814
835
|
# In Python 3.8 and 3.9 C{math.hypot} is inaccurate, see
|
|
815
836
|
# U{agdhruv<https://GitHub.com/geopy/geopy/issues/466>},
|
|
816
837
|
# U{cffk<https://Bugs.Python.org/issue43088>} and module
|
|
@@ -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(
|
|
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
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
-
|
|
884
|
-
|
|
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
|
-
|
|
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:
|