1 """geomath.py: transcription of GeographicLib::Math class."""
19 Additional math routines for GeographicLib.
21 This defines constants:
22 epsilon, difference between 1 and the next bigger number
23 digits, the number of digits in the fraction of a real number
24 minval, minimum normalized positive number
25 maxval, maximum finite number
31 epsilon = math.pow(2.0, 1-digits)
32 minval = math.pow(2.0, -1022)
33 maxval = math.pow(2.0, 1023) * (2 - epsilon)
34 inf =
float(
"inf")
if sys.version_info > (2, 6)
else 2 * maxval
35 nan =
float(
"nan")
if sys.version_info > (2, 6)
else inf - inf
44 """Real cube root of a number"""
46 y = math.pow(
abs(x), 1/3.0)
47 return y
if x >= 0
else -y
51 """log(1 + x) accurate for small x (missing from python 2.5.2)"""
53 if sys.version_info > (2, 6):
62 return x
if z == 0
else x * math.log(y) / z
66 """atanh(x) (missing from python 2.5.2)"""
68 if sys.version_info > (2, 6):
72 y = Math.log1p(2 * y/(1 - y))/2
73 return -y
if x < 0
else y
77 """return x with the sign of y (missing from python 2.5.2)"""
79 if sys.version_info > (2, 6):
80 return math.copysign(x, y)
82 return math.fabs(x) * (-1
if y < 0
or (y == 0
and 1/y < 0)
else 1)
86 """Private: Normalize a two-vector."""
92 """Error free transformation of a sum."""
107 """Evaluate a polynomial."""
108 y =
float(0
if N < 0
else p[s])
116 """Private: Round an angle so that small values underflow to zero."""
125 if y < z: y = z - (z - y)
126 return 0.0
if x == 0
else (-y
if x < 0
else y)
130 """reduce angle to (-180,180]"""
132 y = math.fmod(x, 360)
136 y = x
if x == 0
else y
137 return (y + 360
if y <= -180
else
138 (y
if y <= 180
else y - 360))
142 """replace angles outside [-90,90] by NaN"""
144 return Math.nan
if abs(x) > 90
else x
148 """compute y - x and reduce to [-180,180] accurately"""
150 d, t = Math.sum(Math.AngNormalize(-x), Math.AngNormalize(y))
151 d = Math.AngNormalize(d)
152 return Math.sum(-180
if d == 180
and t > 0
else d, t)
156 """Compute sine and cosine of x in degrees."""
158 r = math.fmod(x, 360)
159 q = Math.nan
if Math.isnan(r)
else int(math.floor(r / 90 + 0.5))
160 r -= 90 * q; r = math.radians(r)
161 s = math.sin(r); c = math.cos(r)
173 s, c = (x, c)
if x == 0
else (0.0+s, 0.0+c)
178 """compute atan2(y, x) with the result in degrees"""
186 ang = math.degrees(math.atan2(y, x))
188 ang = (180
if y >= 0
else -180) - ang
197 """Test for finiteness"""
199 return abs(x) <= Math.maxval
205 return math.isnan(x)
if sys.version_info > (2, 6)
else x != x