pygeodesy 24.3.24__py2.py3-none-any.whl → 24.4.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyGeodesy
3
- Version: 24.3.24
3
+ Version: 24.4.2
4
4
  Summary: Pure Python geodesy tools
5
5
  Home-page: https://GitHub.com/mrJean1/PyGeodesy
6
6
  Author: Jean M. Brouwers
@@ -158,7 +158,7 @@ and McCabe_ using Python 2.7.18 and with Flake8_ using Python 3.11.5, both in 64
158
158
 
159
159
  For a summary of all *Karney*-based functionality in ``pygeodesy``, see module karney_.
160
160
 
161
- *Last updated: March 24, 2024.*
161
+ *Last updated: April 02, 2024.*
162
162
 
163
163
  License
164
164
  =======
@@ -1,9 +1,9 @@
1
1
  pygeodesy/LICENSE,sha256=YfgAiyxOwY6P9Kkb1_5XN81nueTLrpb3Ffkv3EuPgFU,1144
2
- pygeodesy/__init__.py,sha256=kXxmGWvlmfYz8sCCrRv8aHmKa8_mPwPUKAEeNGOdq7Q,40824
2
+ pygeodesy/__init__.py,sha256=_3ZB1L61RzVekqZjnjG1Q-nWx4O6g6fbCUm9ygiBoQU,40824
3
3
  pygeodesy/__main__.py,sha256=qMFG3caY8ZXWu6uGiemzyT4OqTFZnsFtlxcGCAgkVJw,4637
4
4
  pygeodesy/albers.py,sha256=UpWNezHXFuA_kT5PhH_2V_gGFJjcmVLLogl5ScJloPU,31098
5
- pygeodesy/azimuthal.py,sha256=MU0PxHjyakqAp8XwGiG5hRg1ATa8RgGVUILtV-J4mOo,50121
6
- pygeodesy/basics.py,sha256=Akm_mffZPCr_m-10xnwG9VJIZNuNfCEoNbMobQoeyyM,27687
5
+ pygeodesy/azimuthal.py,sha256=e796vtU5ol5ZG2yBX3E5YBXsONJuCrhyEX60YzGzFi0,50115
6
+ pygeodesy/basics.py,sha256=tkHRN1-4wcZyniACBp9K5RJSrrFVIEmaVt9a0celNGk,27687
7
7
  pygeodesy/booleans.py,sha256=HZbwoL-S7Ww9d4C2D1BVqXfmcuqqVpEVSU9_S0uyUyo,74204
8
8
  pygeodesy/cartesianBase.py,sha256=I3q29mRdBB3NCDmPoJsJ0QOFfLzkdMWc8X9zG4IwJyA,47264
9
9
  pygeodesy/clipy.py,sha256=VU3ynQ1IZ0v5hJlicqD48oW0imRgiL5_ZzRPrIjpfPw,27683
@@ -25,11 +25,11 @@ pygeodesy/elliptic.py,sha256=n2R-3H1ruMnwBewEtn75ahjpgeEU93irzcvFxarCyPs,42393
25
25
  pygeodesy/epsg.py,sha256=ldHoLWqJWR4FUiBVnDTtrI_e7TNjjtr9OkxDlri1g5E,8165
26
26
  pygeodesy/errors.py,sha256=fRGrdnb81Y9KB4Y1ua1nvB9zuuiv8IL6c6YN_cb3kBo,27280
27
27
  pygeodesy/etm.py,sha256=ADIMY8zxVu3cAiP9rUGj3Mq3LyO2C5w3ejdW2YY1eJ8,44583
28
- pygeodesy/fmath.py,sha256=yxy5FVQjJek3VVB8hldPxm4BkWVA44E35uaHtcoN9pg,30328
28
+ pygeodesy/fmath.py,sha256=z0YBdZW92NaLM0VEyx6ItTIjuf3I6PhRce27OUl_RnM,30360
29
29
  pygeodesy/formy.py,sha256=Rces4Q5ecED0WVfuI9mQzeyHE54LDowYfI6faBHpyeA,74536
30
30
  pygeodesy/frechet.py,sha256=1tiLc6WZou8YVbizB0QisVhYH-VOP03pMZQ5GOAb9Dc,33527
31
31
  pygeodesy/fstats.py,sha256=X79Qd8pL4R-kUIYN0CZDuA7L1UArtBFvWqaFoHASNqs,25605
32
- pygeodesy/fsums.py,sha256=TNoLohoL1xuwxXg_nME7tDkpYfLG5PfUw2JDsTExMwc,66239
32
+ pygeodesy/fsums.py,sha256=3Fdnk0ZJmg05qoJmUSLH8ra4mQQKuDFDTdD5L4jio5U,67166
33
33
  pygeodesy/gars.py,sha256=fCiWBJ4kOJxPfNOxadX-OzBGDXj7C9g02NuGHiZa_88,11342
34
34
  pygeodesy/geodesicw.py,sha256=Rw1pmT8UabWsBKfecsd4VR5Ks3uMrhH8sufydJS_MMs,26901
35
35
  pygeodesy/geodsolve.py,sha256=J75l_bbPPsPr4NZXm1hCASl9TrXAS5DSeufXYkz2Qzs,21863
@@ -42,7 +42,7 @@ pygeodesy/iters.py,sha256=CfU365eE9F4oWZbBx0qTEvfodMhpa8rGOepLIv67xF8,20181
42
42
  pygeodesy/karney.py,sha256=lYdsSHis8xQJVS1V0F3cphx6Dhgd77xTlMOdVR8MN8I,34994
43
43
  pygeodesy/ktm.py,sha256=sCvbLvJItavlruilAyjeZ0sOZx2yJumzGe_UiIVbGi4,27315
44
44
  pygeodesy/latlonBase.py,sha256=oY7Trlw0pL_qAP8sdn68EfHDgaxM7JpL7AIynWkf1rk,77759
45
- pygeodesy/lazily.py,sha256=tNeOuVRO-qtIatYHTQzvrVENCxtEuN6RRWho8sKXZO8,48608
45
+ pygeodesy/lazily.py,sha256=JlMAXFraRha9SfwOADlFjLChtx6O9C9e0b_HWr6qtwM,48624
46
46
  pygeodesy/lcc.py,sha256=yNpmAdOwv3HNh2ZLopF5QtvDokeQYCmnxSc8UFUPHO4,25737
47
47
  pygeodesy/ltp.py,sha256=akINPlWAHDFefH5to5TAA0ZxaRepLKSZbKj12v23Dgs,48579
48
48
  pygeodesy/ltpTuples.py,sha256=o_bNxYpAZ-Kj5IOH3GAfkrwr3VdLlPD5k9Wn2NwOiQQ,55812
@@ -53,7 +53,7 @@ pygeodesy/nvectorBase.py,sha256=vpuGECs038I-8z_MDFJ9gZMY_6Een-EG2Y_llRLpl-o,2879
53
53
  pygeodesy/osgr.py,sha256=5JB6b_nvyZ6rFMlC7ZB45mvYtjc_aiLb4DPdeaui-KY,30995
54
54
  pygeodesy/points.py,sha256=8LiAH1dMiNN6mLmBZAisI0VsccD9PSy97XhDtJUfBuw,64441
55
55
  pygeodesy/props.py,sha256=ZnXRuSOkfkeJY3Of-iT06FNWZkTYgLZQBPBNF6aS0jE,21421
56
- pygeodesy/resections.py,sha256=jMT66w8mWfO-lck2r2W9nQ8EBkL1Xa3Dh8iLa83tnN4,43629
56
+ pygeodesy/resections.py,sha256=ILXfcWkHH-WP2eczhYw6p5HANZXH_sttfhdJBM22l-k,43586
57
57
  pygeodesy/simplify.py,sha256=FT3AzXiFjFfvwJ-X2q8iA9cQOUVdBT1vD_BIskM3gK8,25223
58
58
  pygeodesy/solveBase.py,sha256=cBe3QQWEaJlPWUlXoiYo1eFMh4z6GDZbQyt8ZiwMfos,16687
59
59
  pygeodesy/sphericalBase.py,sha256=sH2WwmY_RL0STyr1OhtCDKvGhO0Ks7o3V-MHLddpiHQ,31944
@@ -109,7 +109,7 @@ pygeodesy/rhumb/aux_.py,sha256=W4HkgoHAQz_aWaysfsmOA5010nCGvBfUs2Q-bymnHYU,16660
109
109
  pygeodesy/rhumb/bases.py,sha256=ZZ4Ba0Cl45tQdfEquyQPSQdH2vXgemF3tCw6UuzHphs,53893
110
110
  pygeodesy/rhumb/ekx.py,sha256=lF3tZ-ZY9fPJV8y1kgHW-7EOZCyb3gJr-kR-jj5Fbf8,23871
111
111
  pygeodesy/rhumb/solve.py,sha256=NZfwx7xv5UriQs7A0c7ZhoxxVUeAT15UwXK_jtwEXQw,27802
112
- PyGeodesy-24.3.24.dist-info/METADATA,sha256=lXN4ExMyvJ490O5Hcs-3xbq8_uR3_9aldw_49abcwAw,19366
113
- PyGeodesy-24.3.24.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
114
- PyGeodesy-24.3.24.dist-info/top_level.txt,sha256=cEQPatCXzKZqrivpULC5V5fuy9_V_bAwaP_gUGid7pQ,10
115
- PyGeodesy-24.3.24.dist-info/RECORD,,
112
+ PyGeodesy-24.4.2.dist-info/METADATA,sha256=hh9f4N7AItjpHOMK6dzULDBjunNb4dIoN4WIiVUxsDQ,19365
113
+ PyGeodesy-24.4.2.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
114
+ PyGeodesy-24.4.2.dist-info/top_level.txt,sha256=cEQPatCXzKZqrivpULC5V5fuy9_V_bAwaP_gUGid7pQ,10
115
+ PyGeodesy-24.4.2.dist-info/RECORD,,
pygeodesy/__init__.py CHANGED
@@ -586,7 +586,7 @@ else:
586
586
  _init__all__ = False
587
587
 
588
588
  from pygeodesy.interns import _DOT_, _version2 # PYCHOK import
589
- __version__ = '24.03.24'
589
+ __version__ = '24.04.02'
590
590
  # see setup.py for similar logic
591
591
  version = _DOT_(*_version2(__version__, n=3))
592
592
 
pygeodesy/azimuthal.py CHANGED
@@ -71,7 +71,7 @@ from pygeodesy.utily import asin1, atan1, atan2b, atan2d, sincos2, \
71
71
  from math import acos, atan2, degrees, fabs, sin, sqrt
72
72
 
73
73
  __all__ = _ALL_LAZY.azimuthal
74
- __version__ = '24.03.22'
74
+ __version__ = '24.04.02'
75
75
 
76
76
  _EPS_K = _EPStol * _0_1 # Karney's eps_ or _EPSmin * _0_1?
77
77
  _over_horizon_ = 'over horizon'
@@ -332,7 +332,7 @@ class Azimuthal7Tuple(_NamedTuple):
332
332
  @kwarg azimuth: Optional azimuth, overriding the current azimuth
333
333
  (C{compass degrees360}).
334
334
  '''
335
- a = _MODS.formy.antipode(self.lat, self.lon) # PYCHOK _namedTuple
335
+ a = _MODS.formy.antipode(self.lat, self.lon) # PYCHOK named
336
336
  z = self.azimuth if azimuth is None else Bearing(azimuth=azimuth) # PYCHOK named
337
337
  return _NamedTuple.dup(self, lat=a.lat, lon=a.lon, azimuth=z)
338
338
 
pygeodesy/basics.py CHANGED
@@ -28,7 +28,7 @@ from math import copysign as _copysign
28
28
  import inspect as _inspect
29
29
 
30
30
  __all__ = _ALL_LAZY.basics
31
- __version__ = '24.03.19'
31
+ __version__ = '24.04.01'
32
32
 
33
33
  _0_0 = 0.0 # in .constants
34
34
  _below_ = 'below'
pygeodesy/fmath.py CHANGED
@@ -10,11 +10,11 @@ from pygeodesy.basics import _copysign, copysign0, isint, len2
10
10
  from pygeodesy.constants import EPS0, EPS02, EPS1, NAN, PI, PI_2, PI_4, \
11
11
  _0_0, _0_125, _0_25, _0_5, _1_0, _N_1_0, \
12
12
  _1_3rd, _1_5, _1_6th, _2_0, _2_3rd, _3_0, \
13
- _isfinite, isnear0, isnear1, _over, remainder
13
+ _isfinite, isnear1, _over, remainder
14
14
  from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
15
15
  _xError, _xkwds_get, _xkwds_pop2
16
- from pygeodesy.fsums import _2float, _Powers, Fsum, _fsum, fsum, fsum1_, \
17
- _pow_op_, Fmt, unstr
16
+ from pygeodesy.fsums import _2float, Fsum, _fsum, fsum, fsum1_, _pow_op_, \
17
+ _1primed, Fmt, unstr
18
18
  from pygeodesy.interns import MISSING, _few_, _h_, _invokation_, _negative_, \
19
19
  _not_scalar_, _SPACE_, _too_
20
20
  from pygeodesy.lazily import _ALL_LAZY, _sys_version_info2
@@ -25,22 +25,24 @@ from math import fabs, sqrt # pow
25
25
  import operator as _operator # in .datums, .trf, .utm
26
26
 
27
27
  __all__ = _ALL_LAZY.fmath
28
- __version__ = '24.03.14'
28
+ __version__ = '24.03.31'
29
29
 
30
30
  # sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
31
- _0_4142 = 0.41421356237309504880 # ... sqrt(2) - 1
31
+ _0_4142 = 0.41421356237309504880 # ... sqrt(2) - 1
32
+ _h_lt_b_ = 'abs(h) < abs(b)'
32
33
 
33
34
 
34
35
  class Fdot(Fsum):
35
36
  '''Precision dot product.
36
37
  '''
37
- def __init__(self, a, *b, **name):
38
+ def __init__(self, a, *b, **name_RESIDUAL):
38
39
  '''New L{Fdot} precision dot product M{sum(a[i] * b[i]
39
- for i=0..len(a))}.
40
+ for i=0..len(a)-1)}.
40
41
 
41
42
  @arg a: Iterable, list, tuple, etc. (C{scalar}s).
42
43
  @arg b: Other values (C{scalar}s), all positional.
43
- @kwarg name: Optional name (C{str}).
44
+ @kwarg name_RESIDUAL: Optional C{B{name}=NN} and
45
+ C{B{RESIDUAL}=None}, see L{Fsum.__init__}.
44
46
 
45
47
  @raise OverflowError: Partial C{2sum} overflow.
46
48
 
@@ -48,21 +50,22 @@ class Fdot(Fsum):
48
50
 
49
51
  @see: Function L{fdot} and method L{Fsum.fadd}.
50
52
  '''
51
- Fsum.__init__(self, **name)
53
+ Fsum.__init__(self, **name_RESIDUAL)
52
54
  self.fadd(_map_mul(a, b, Fdot))
53
55
 
54
56
 
55
57
  class Fhorner(Fsum):
56
58
  '''Precision polynomial evaluation using the Horner form.
57
59
  '''
58
- def __init__(self, x, *cs, **name):
59
- '''New L{Fhorner} evaluation of the polynomial
60
- M{sum(cs[i] * x**i for i=0..len(cs))}.
60
+ def __init__(self, x, *cs, **name_RESIDUAL):
61
+ '''New L{Fhorner} evaluation of polynomial M{sum(cs[i] * x**i
62
+ for i=0..len(cs)-1)}.
61
63
 
62
- @arg x: Polynomial argument (C{scalar}).
64
+ @arg x: Polynomial argument (C{scalar} or C{Fsum} instance).
63
65
  @arg cs: Polynomial coeffients (C{scalar} or C{Fsum}
64
66
  instances), all positional.
65
- @kwarg name: Optional name (C{str}).
67
+ @kwarg name_RESIDUAL: Optional C{B{name}=NN} and
68
+ C{B{RESIDUAL}=None}, see L{Fsum.__init__}.
66
69
 
67
70
  @raise OverflowError: Partial C{2sum} overflow.
68
71
 
@@ -70,40 +73,49 @@ class Fhorner(Fsum):
70
73
 
71
74
  @raise ValueError: Non-finite B{C{x}}.
72
75
 
73
- @see: Function L{fhorner} and methods L{Fsum.fadd} and L{Fsum.fmul}.
76
+ @see: Function L{fhorner} and methods L{Fsum.fadd} and
77
+ L{Fsum.fmul}.
74
78
  '''
75
- Fsum.__init__(self, *cs[-1:], **name)
76
- if len(cs) > 1:
77
- x = _2float(x=x)
78
- _a = self._fadd # (other, op)
79
- _f = self._finite # (other, op)
80
- op = Fhorner.__name__
81
- ps = self._ps
82
- for c in reversed(cs[:-1]): # multiply-accumulate
83
- ps[:] = [_f(p * x, op) for p in ps]
84
- _a(c, op)
85
- # assert self._ps is ps
79
+ Fsum.__init__(self, **name_RESIDUAL)
80
+ if cs:
81
+ if isinstance(x, Fsum):
82
+ _mul = self._mul_Fsum
83
+ else:
84
+ _mul = self._mul_scalar
85
+ x = _2float(x=x)
86
+ op = Fhorner.__name__
87
+ if len(cs) > 1 and x:
88
+ for c in reversed(cs):
89
+ self._fset_ps(_mul(x, op))
90
+ self._fadd(c, op, up=False)
91
+ self._update()
92
+ else: # x == 0
93
+ self._fadd(cs[0], op)
94
+ else:
95
+ self._fset(_0_0)
86
96
 
87
97
 
88
98
  class Fhypot(Fsum):
89
- '''Precision hypotenuse of summation.
99
+ '''Precision summation and hypotenuse, default C{power=2}.
90
100
  '''
91
101
  def __init__(self, *xs, **power_name_RESIDUAL):
92
- '''New L{Fhypot} hypotenuse of (the I{power} of) several
93
- C{scalar} or C{Fsum} values.
102
+ '''New L{Fhypot} hypotenuse of (the I{power} of) several components.
94
103
 
95
- @arg xs: One or more values to include (each C{scalar}
96
- or an C{Fsum} instance).
97
- @kwarg power_name_RESIDUAL: Optional exponent and root
98
- order C{B{power}=2}, C{B{name}=NN} and
104
+ @arg xs: One or more components (each a C{scalar} or an C{Fsum}
105
+ instance).
106
+ @kwarg power_name_RESIDUAL: Optional, C{scalar} exponent and
107
+ root order C{B{power}=2}, a C{B{name}=NN} and
99
108
  C{B{RESIDUAL}=None}, see L{Fsum.__init__}.
100
109
  '''
101
110
  try:
102
111
  p, kwds = _xkwds_pop2(power_name_RESIDUAL, power=2)
103
112
  Fsum.__init__(self, **kwds)
104
113
  if xs:
105
- self._facc(_Powers(p, xs), up=False) # PYCHOK yield
106
- self._fset(self._fpow(_1_0 / p, _pow_op_), asis=True)
114
+ r = _1_0 / p
115
+ self._facc_power(p, xs, Fhypot)
116
+ self._fpow(r, _pow_op_)
117
+ else:
118
+ self._fset(_0_0)
107
119
  except Exception as X:
108
120
  raise self._ErrorX(X, xs, power=p)
109
121
 
@@ -111,14 +123,15 @@ class Fhypot(Fsum):
111
123
  class Fpolynomial(Fsum):
112
124
  '''Precision polynomial evaluation.
113
125
  '''
114
- def __init__(self, x, *cs, **name):
126
+ def __init__(self, x, *cs, **name_RESIDUAL):
115
127
  '''New L{Fpolynomial} evaluation of the polynomial
116
- M{sum(cs[i] * x**i for i=0..len(cs))}.
128
+ M{sum(cs[i] * x**i for i=0..len(cs)-1)}.
117
129
 
118
- @arg x: Polynomial argument (C{scalar}).
119
- @arg cs: Polynomial coeffients (C{scalar}s), all
120
- positional.
121
- @kwarg name: Optional name (C{str}).
130
+ @arg x: Polynomial argument (C{scalar} or L{Fsum}).
131
+ @arg cs: Polynomial coeffients (each a C{scalar} or
132
+ an L{Fsum} instance), all positional.
133
+ @kwarg name_RESIDUAL: Optional C{B{name}=NN} and
134
+ C{B{RESIDUAL}=None}, see L{Fsum.__init__}.
122
135
 
123
136
  @raise OverflowError: Partial C{2sum} overflow.
124
137
 
@@ -126,79 +139,81 @@ class Fpolynomial(Fsum):
126
139
 
127
140
  @raise ValueError: Non-finite B{C{x}}.
128
141
 
129
- @see: Function L{fpolynomial} and method L{Fsum.fadd}.
142
+ @see: Class L{Fhorner}, function L{fpolynomial} and
143
+ method L{Fsum.fadd}.
130
144
  '''
131
- Fsum.__init__(self, *cs[:1], **name)
145
+ Fsum.__init__(self, *cs[:1], **name_RESIDUAL)
132
146
  n = len(cs) - 1
133
147
  if n > 0:
134
- self.fadd(_map_mul(cs[1:], fpowers(x, n), Fpolynomial))
148
+ self.fadd(_1map_mul(cs[1:], _powers(x, n)))
149
+ elif n < 0:
150
+ self._fset(_0_0)
135
151
 
136
152
 
137
153
  class Fpowers(Fsum):
138
- '''Precision summation or powers, optimized for C{power=2}.
154
+ '''Precision summation of powers, optimized for C{power=2, 3 and 4}.
139
155
  '''
140
156
  def __init__(self, power, *xs, **name_RESIDUAL):
141
- '''New L{Fpowers} sum of (the I{power} of) several C{scalar}
142
- or C{Fsum} values.
143
-
144
- @arg power: The exponent (C{scalar} or C{Fsum}).
145
- @arg xs: One or more values to include (each C{scalar}
146
- or an C{Fsum} instance).
147
- @kwarg power_name_RESIDUAL: Optional exponent and root
148
- order C{B{power}=2}, C{B{name}=NN} and
149
- C{B{RESIDUAL}=None}, see L{Fsum.__init__}.
157
+ '''New L{Fpowers} sum of (the I{power} of) several values.
158
+
159
+ @arg power: The exponent (C{scalar} or L{Fsum}).
160
+ @arg xs: One or more values (each a C{scalar} or an
161
+ C{Fsum} instance).
162
+ @kwarg name_RESIDUAL: Optional C{B{name}=NN} and
163
+ C{B{RESIDUAL}=None}, see L{Fsum.__init__}.
150
164
  '''
151
165
  try:
152
166
  Fsum.__init__(self, **name_RESIDUAL)
153
167
  if xs:
154
- self._facc(_Powers(power, xs), up=False) # PYCHOK yield
155
- except Exception as X:
156
- raise self._ErrorX(X, xs, power=power)
168
+ self._facc_power(power, xs, Fpowers) # x**0 == 1
169
+ else:
170
+ self._fset(_0_0)
171
+ except Exception as x:
172
+ raise self._ErrorX(x, xs, power=power)
157
173
 
158
174
 
159
175
  class Fn_rt(Fsum):
160
- '''Precision n-th root of summation.
176
+ '''N-th root of a precision summation.
161
177
  '''
162
178
  def __init__(self, root, *xs, **name_RESIDUAL):
163
- '''New L{Fn_rt} root of the precision sum of several
164
- C{scalar} or C{Fsum} values.
179
+ '''New L{Fn_rt} root of a precision sum.
165
180
 
166
- @arg root: The order (C{scalar} or C{Fsum}).
167
- @arg xs: Values to include (each C{scalar} or an
168
- C{Fsum} instance).
181
+ @arg root: The order (C{scalar} or C{Fsum}),
182
+ non-zero.
183
+ @arg xs: Values to summate (each a C{scalar} or
184
+ an C{Fsum} instance).
169
185
  @kwarg name_RESIDUAL: See L{Fsum.__init__}.
170
186
  '''
171
187
  try:
172
- Fsum.__init__(self, *xs, **name_RESIDUAL)
173
- self._fset(self._fpow(_1_0 / root, _pow_op_), asis=True)
174
- except Exception as X:
175
- raise self._ErrorX(X, xs, root=root)
188
+ Fsum.__init__(self, **name_RESIDUAL)
189
+ if xs:
190
+ r = _1_0 / root
191
+ self. fadd(xs)
192
+ self._fpow(r, _pow_op_) # self **= r
193
+ else:
194
+ self._fset(_0_0)
195
+ except Exception as x:
196
+ raise self._ErrorX(x, xs, root=root)
176
197
 
177
198
 
178
199
  class Fcbrt(Fn_rt):
179
- '''Precision cubic root of summation.
200
+ '''Cubic root of a precision summation.
180
201
  '''
181
202
  def __init__(self, *xs, **name_RESIDUAL):
182
- '''New L{Fcbrt} cubic root of the precision sum of
183
- several C{scalar} or C{Fsum} values.
203
+ '''New L{Fcbrt} cubic root of a precision sum.
184
204
 
185
- @arg xs: Values to include (each C{scalar} or an
186
- C{Fsum} instance).
187
- @kwarg name_RESIDUAL: See L{Fsum.__init__}.
205
+ @see: Class L{Fn_rt} for further details.
188
206
  '''
189
207
  Fn_rt.__init__(self, _3_0, *xs, **name_RESIDUAL)
190
208
 
191
209
 
192
210
  class Fsqrt(Fn_rt):
193
- '''Precision square root of summation.
211
+ '''Square root of a precision summation.
194
212
  '''
195
213
  def __init__(self, *xs, **name_RESIDUAL):
196
- '''New L{Fsqrt} square root of the precision sum of
197
- several C{scalar} or C{Fsum} values.
214
+ '''New L{Fsqrt} square root of a precision sum.
198
215
 
199
- @arg xs: Values to include (each C{scalar} or an
200
- C{Fsum} instance).
201
- @kwarg name_RESIDUAL: See L{Fsum.__init__}.
216
+ @see: Class L{Fn_rt} for further details.
202
217
  '''
203
218
  Fn_rt.__init__(self, _2_0, *xs, **name_RESIDUAL)
204
219
 
@@ -355,12 +370,12 @@ def fatan2(y, x):
355
370
  master/Source/Shaders/Builtin/Functions/fastApproximateAtan.glsl>}
356
371
  and L{fatan1}.
357
372
  '''
358
- b, a = fabs(y), fabs(x)
359
- if a < b:
373
+ a, b = fabs(x), fabs(y)
374
+ if b > a:
360
375
  r = (PI_2 - fatan1(a / b)) if a else PI_2
361
- elif b < a:
376
+ elif a > b:
362
377
  r = fatan1(b / a) if b else _0_0
363
- elif a: # == b != 0
378
+ elif a: # a == b != 0
364
379
  r = PI_4
365
380
  else: # a == b == 0
366
381
  return _0_0
@@ -407,7 +422,7 @@ def fdot(a, *b):
407
422
 
408
423
  def fdot3(a, b, c, start=0):
409
424
  '''Return the precision dot product M{start +
410
- sum(a[i] * b[i] * c[i] for i=0..len(a))}.
425
+ sum(a[i] * b[i] * c[i] for i=0..len(a)-1)}.
411
426
 
412
427
  @arg a: Iterable, list, tuple, etc. (C{scalar}s).
413
428
  @arg b: Iterable, list, tuple, etc. (C{scalar}s).
@@ -424,7 +439,7 @@ def fdot3(a, b, c, start=0):
424
439
  def _mul3(a, b, c): # map function
425
440
  return a * b * c
426
441
 
427
- def _muly(a, b, c, start):
442
+ def _mul3_(a, b, c, start):
428
443
  yield start
429
444
  for abc in map(_mul3, a, b, c):
430
445
  yield abc
@@ -432,12 +447,12 @@ def fdot3(a, b, c, start=0):
432
447
  if not len(a) == len(b) == len(c):
433
448
  raise LenError(fdot3, a=len(a), b=len(b), c=len(c))
434
449
 
435
- return fsum(_muly(a, b, c, start) if start else map(_mul3, a, b, c))
450
+ return fsum(_mul3_(a, b, c, start) if start else map(_mul3, a, b, c))
436
451
 
437
452
 
438
453
  def fhorner(x, *cs):
439
454
  '''Evaluate the polynomial M{sum(cs[i] * x**i for
440
- i=0..len(cs))} using the Horner form.
455
+ i=0..len(cs)-1)} using the Horner form.
441
456
 
442
457
  @arg x: Polynomial argument (C{scalar}).
443
458
  @arg cs: Polynomial coeffients (C{scalar}s).
@@ -483,45 +498,37 @@ def fidw(xs, ds, beta=2):
483
498
  b = -Int_(beta=beta, low=0, high=3)
484
499
  if b < 0:
485
500
  ws = tuple(float(d)**b for d in ds)
486
- t = fsum(_map_mul1(xs, ws)) # fdot(xs, *ws)
501
+ t = fsum(_1map_mul(xs, ws)) # Fdot(xs, *ws)
487
502
  x = _over(t, fsum(ws, floats=True))
488
503
  else: # b == 0
489
504
  x = fsum(xs) / n # fmean(xs)
490
505
  elif d < 0: # PYCHOK no cover
491
- n = Fmt.INDEX(distance=ds.index(d))
506
+ n = Fmt.SQUARE(distance=ds.index(d))
492
507
  raise _ValueError(n, d, txt=_negative_)
493
508
  return x
494
509
 
495
510
 
496
511
  def fmean(xs):
497
- '''Compute the accurate mean M{sum(xs[i] for
498
- i=0..len(xs)) / len(xs)}.
512
+ '''Compute the accurate mean M{sum(xs) / len(xs)}.
499
513
 
500
514
  @arg xs: Values (C{scalar} or L{Fsum} instances).
501
515
 
502
516
  @return: Mean value (C{float}).
503
517
 
504
- @raise OverflowError: Partial C{2sum} overflow.
518
+ @raise LenError: No B{C{xs}} values.
505
519
 
506
- @raise ValueError: No B{C{xs}} values.
520
+ @raise OverflowError: Partial C{2sum} overflow.
507
521
  '''
508
522
  n, xs = len2(xs)
509
- if n > 0:
510
- return fsum(xs) / n # if n > 1 else _2float(index=0, xs=xs[0])
511
- raise _ValueError(xs=xs)
523
+ if n < 1:
524
+ raise LenError(fmean, xs=xs)
525
+ return Fsum(*xs).fover(n) if n > 1 else _2float(index=0, xs=xs[0])
512
526
 
513
527
 
514
528
  def fmean_(*xs):
515
- '''Compute the accurate mean M{sum(xs[i] for
516
- i=0..len(xs)) / len(xs)}.
529
+ '''Compute the accurate mean M{sum(xs) / len(xs)}.
517
530
 
518
- @arg xs: Values (C{scalar} or L{Fsum} instances).
519
-
520
- @return: Mean value (C{float}).
521
-
522
- @raise OverflowError: Partial C{2sum} overflow.
523
-
524
- @raise ValueError: No B{C{xs}} values.
531
+ @see: Function L{fmean} for further details.
525
532
  '''
526
533
  return fmean(xs)
527
534
 
@@ -533,7 +540,8 @@ def fpolynomial(x, *cs, **over):
533
540
  @arg x: Polynomial argument (C{scalar}).
534
541
  @arg cs: Polynomial coeffients (C{scalar}s), all
535
542
  positional.
536
- @kwarg over: Optional, final divisor (C{scalar}
543
+ @kwarg over: Optional final, I{non-zero} divisor
544
+ (C{scalar}).
537
545
 
538
546
  @return: Polynomial value (C{float}).
539
547
 
@@ -553,28 +561,24 @@ def fpolynomial(x, *cs, **over):
553
561
  def fpowers(x, n, alts=0):
554
562
  '''Return a series of powers M{[x**i for i=1..n]}.
555
563
 
556
- @arg x: Value (C{scalar}).
564
+ @arg x: Value (C{scalar} or L{Fsum}).
557
565
  @arg n: Highest exponent (C{int}).
558
- @kwarg alts: Only alternating powers, starting with
559
- this exponent (C{int}).
566
+ @kwarg alts: Only alternating powers, starting with this
567
+ exponent (C{int}).
560
568
 
561
- @return: Powers of B{C{x}} (C{float}s or C{int}s).
569
+ @return: Tuple of powers of B{C{x}} (C{type(B{x})}).
562
570
 
563
- @raise TypeError: Non-scalar B{C{x}} or B{C{n}} not C{int}.
571
+ @raise TypeError: Invalid B{C{x}} or B{C{n}} not C{int}.
564
572
 
565
- @raise ValueError: Non-finite B{C{x}} or non-positive B{C{n}}.
573
+ @raise ValueError: Non-finite B{C{x}} or invalid B{C{n}}.
566
574
  '''
567
575
  if not isint(n):
568
576
  raise _IsnotError(int.__name__, n=n)
569
577
  elif n < 1:
570
578
  raise _ValueError(n=n)
571
579
 
572
- p = t = x if isint(x) else _2float(x=x)
573
- ps = [p]
574
- _a = ps.append
575
- for _ in range(1, n):
576
- p *= t
577
- _a(p)
580
+ p = x if isint(x) or isinstance(x, Fsum) else _2float(x=x)
581
+ ps = tuple(_powers(p, n))
578
582
 
579
583
  if alts > 0: # x**2, x**4, ...
580
584
  # ps[alts-1::2] chokes PyChecker
@@ -618,7 +622,7 @@ def frange(start, number, step=1):
618
622
  if not isint(number):
619
623
  raise _IsnotError(int.__name__, number=number)
620
624
  for i in range(number):
621
- yield start + i * step
625
+ yield start + (step * i)
622
626
 
623
627
 
624
628
  try:
@@ -752,8 +756,10 @@ def _h_x2(xs):
752
756
  h = float(max(map(fabs, xs)))
753
757
  if h < EPS0:
754
758
  x2 = _0_0
755
- else: # math.fsum, see C{_hypot21_} below
756
- x2 = _fsum(_x2_h2(_1_0, xs, h, _N_1_0))
759
+ elif h in (_1_0, _N_1_0):
760
+ x2 = _fsum(_1primed(x**2 for x in xs))
761
+ else: # math.fsum
762
+ x2 = _fsum(_1primed((x / h)**2 for x in xs))
757
763
  return h, x2
758
764
 
759
765
  raise _ValueError(xs=xs, txt=_too_(_few_))
@@ -814,17 +820,13 @@ def _map_mul(a, b, where):
814
820
  n = len(b)
815
821
  if len(a) != n: # PYCHOK no cover
816
822
  raise LenError(where, a=len(a), b=n)
817
- return map(_operator.mul, a, b) if n > 3 else _map_mul1(a, b)
823
+ return map(_operator.mul, a, b) if n > 3 else _1map_mul(a, b)
818
824
 
819
825
 
820
- def _map_mul1(a, b):
826
+ def _1map_mul(a, b):
821
827
  '''(INTERNAL) Yield each B{C{a * b}}, 1-primed.
822
828
  '''
823
- yield _1_0
824
- for ab in map(_operator.mul, a, b):
825
- if ab:
826
- yield ab
827
- yield _N_1_0
829
+ return _1primed(map(_operator.mul, a, b))
828
830
 
829
831
 
830
832
  def norm2(x, y):
@@ -871,6 +873,15 @@ def norm_(*xs):
871
873
  yield _0_0
872
874
 
873
875
 
876
+ def _powers(x, n):
877
+ '''(INTERNAL) Yield C{x**i for i=1..n}.
878
+ '''
879
+ p = 1 # type(p) == type(x)
880
+ for _ in range(n):
881
+ p *= x
882
+ yield p
883
+
884
+
874
885
  def _root(x, p, where):
875
886
  '''(INTERNAL) Raise C{x} to power C{0 < p < 1}.
876
887
  '''
@@ -931,36 +942,22 @@ def sqrt_a(h, b):
931
942
  try:
932
943
  if not (_isHeight(h) and _isRadius(b)):
933
944
  raise TypeError(_not_scalar_)
934
- elif isnear0(h): # PYCHOK no cover
935
- c, b = fabs(h), fabs(b)
936
- d = c - b
937
- if d < 0:
938
- raise ValueError('abs(h) < abs(b)')
939
- a = copysign0(sqrt((c + b) * d), h) if d > 0 else _0_0
940
- else:
941
- c = float(h)
945
+ c = fabs(h)
946
+ if c > EPS0:
942
947
  s = _1_0 - (b / c)**2
943
948
  if s < 0:
944
- raise ValueError('abs(h) < abs(b)')
949
+ raise ValueError(_h_lt_b_)
945
950
  a = (sqrt(s) * c) if 0 < s < 1 else (c if s else _0_0)
951
+ else: # PYCHOK no cover
952
+ b = fabs(b)
953
+ d = c - b
954
+ if d < 0:
955
+ raise ValueError(_h_lt_b_)
956
+ d *= c + b
957
+ a = sqrt(d) if d else _0_0
946
958
  except Exception as x:
947
959
  raise _xError(x, h=h, b=b)
948
- return a
949
-
950
-
951
- def _x2_h2(s, xs, h, e):
952
- '''(INTERNAL) Yield M{(x / h)**2 for x in xs}.
953
- '''
954
- yield s
955
- if h in (_0_0, _1_0):
956
- for x in xs:
957
- if x:
958
- yield x**2
959
- else:
960
- for x in xs:
961
- if x:
962
- yield (x / h)**2
963
- yield e
960
+ return copysign0(a, h)
964
961
 
965
962
 
966
963
  def zcrt(x):