1
2
3
4
5
6 """This provides useful general math tools.
7
8 Functions:
9 fcmp Compare two floating point numbers, up to a specified precision.
10 intd Represent a floating point number as an integer.
11 safe_log log, but returns an arbitrarily small number for log(0).
12 safe_exp exp, but returns a large or small number instead of overflows.
13
14 """
15 import math
16
17 -def fcmp(x, y, precision):
18 """fcmp(x, y, precision) -> -1, 0, or 1"""
19 if math.fabs(x-y) < precision:
20 return 0
21 elif x < y:
22 return -1
23 return 1
24
25 -def intd(x, digits_after_decimal=0):
26 """intd(x[, digits_after_decimal]) -> int x, rounded
27
28 Represent a floating point number with some digits after the
29 decimal point as an integer. This is useful when floating point
30 comparisons are failing due to precision problems. e.g.
31 intd(5.35, 1) -> 54.
32
33 """
34 precision = 10.**digits_after_decimal
35 if x >= 0:
36 x = int(x * precision + 0.5)
37 else:
38 x = int(x * precision - 0.5)
39 return x
40
42 """safe_log(n, zero=None, neg=None) -> log(n)
43
44 Calculate the log of n. If n is 0, returns the value of zero. If n is
45 negative, returns the value of neg.
46
47 """
48 if n < 0:
49 return neg
50 elif n < 1E-100:
51 return zero
52 return math.log(n)
53
54 LOG2 = math.log(2)
56 """safe_log2(n, zero=None, neg=None) -> log(n)
57
58 Calculate the log base 2 of n. If n is 0, returns the value of
59 zero. If n is negative, returns the value of neg.
60
61 """
62 l = safe_log(n, zero=zero, neg=neg)
63 if l is None:
64 return l
65 return l/LOG2
66
68 """safe_exp(n, under=None, over=None) -> e**n
69
70 Guaranteed not to overflow. Instead of overflowing, it returns
71 the values of 'under' for underflows or 'over' for overflows.
72
73 """
74 try:
75 return math.exp(n)
76 except OverflowError:
77 if n < 0:
78 return under
79 return over
80 raise "How did I get here?"
81
82
83
84 try:
85 from cmathfns import *
86 except ImportError:
87 pass
88