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