1 | // IntMath.h: Header for doing fractional math with integers for speed. |
---|
2 | |
---|
3 | #ifndef IntMath_h |
---|
4 | #define IntMath_h |
---|
5 | |
---|
6 | typedef float BASETYPE; |
---|
7 | //typedef double BASETYPE; |
---|
8 | |
---|
9 | // Scaling factor used to store certain floating point |
---|
10 | // values as integers to a few significant figures. |
---|
11 | //const int INTSCALE = 1000; |
---|
12 | const int INTSCALE = 1; |
---|
13 | |
---|
14 | // Type for a probability in range 0.0 to 1.0. |
---|
15 | typedef BASETYPE PROB; |
---|
16 | |
---|
17 | // Type for an log-odds integer score. |
---|
18 | // Stored as log2(PROB)*INTSCALE. |
---|
19 | //typedef int SCORE; |
---|
20 | typedef BASETYPE SCORE; |
---|
21 | |
---|
22 | // Type for a weight. |
---|
23 | // Stored as w*INTSCALE where w is in range 0.0 to 1.0. |
---|
24 | //typedef unsigned WEIGHT; |
---|
25 | typedef BASETYPE WEIGHT; |
---|
26 | |
---|
27 | // Type for a fractional weighted count stored as n*WEIGHT/N |
---|
28 | // where n=measured count (integer >= 0) and N is total for |
---|
29 | // the distribution (e.g., n=number of residues of a given |
---|
30 | // type in a column, N=number of residues in the column). |
---|
31 | // Hence values in an FCOUNT variable range from 0..INTSCALE |
---|
32 | // as an integer, representing "true" values 0.0 to 1.0. |
---|
33 | //typedef unsigned FCOUNT; |
---|
34 | typedef BASETYPE FCOUNT; |
---|
35 | |
---|
36 | // Representation of -infinity. Value should |
---|
37 | // be large and negative, but not so large |
---|
38 | // that adding a few of them overflows. |
---|
39 | // TODO: Multiplied by 10 to work around bug |
---|
40 | // when aligning Bali 1ckaA in ref4, which is |
---|
41 | // so long that B->Mmax got to -infinity, causing |
---|
42 | // traceback to fail. |
---|
43 | //const int MINUS_INFINITY = -10000000; |
---|
44 | const BASETYPE MINUS_INFINITY = (BASETYPE) -1e37; |
---|
45 | const BASETYPE PLUS_INFINITY = (BASETYPE) 1e37; |
---|
46 | |
---|
47 | // Probability relative to a null model |
---|
48 | typedef double RPROB; |
---|
49 | |
---|
50 | PROB ScoreToProb(SCORE Score); |
---|
51 | SCORE ProbToScore(PROB Prob); |
---|
52 | SCORE DoubleToScore(double d); |
---|
53 | WEIGHT DoubleToWeight(double d); |
---|
54 | double WeightToDouble(WEIGHT w); |
---|
55 | SCORE MulScoreWeight(SCORE Score, WEIGHT Weight); |
---|
56 | bool ScoreEq(SCORE s1, SCORE s2); |
---|
57 | bool BTEq(double b1, double b2); |
---|
58 | |
---|
59 | static double ScoreToDouble(SCORE Score) |
---|
60 | { |
---|
61 | return (double) Score / (double) INTSCALE; |
---|
62 | } |
---|
63 | |
---|
64 | #if 0 |
---|
65 | // In-line assembler for Result = (x*y)/z |
---|
66 | // Note that imul and idiv will do 64-bit arithmetic |
---|
67 | // on 32-bit operands, so this shouldn't overflow |
---|
68 | // Can't write this efficiently in C/C++ (would |
---|
69 | // often overlow 32 bits). |
---|
70 | #define MulDivAssign(Result, x, y, z) \ |
---|
71 | { \ |
---|
72 | int X = (x); \ |
---|
73 | int Y = (y); \ |
---|
74 | int Z = (z); \ |
---|
75 | _asm mov eax,X \ |
---|
76 | _asm imul Y \ |
---|
77 | _asm mov ecx,Z \ |
---|
78 | _asm idiv ecx \ |
---|
79 | _asm mov Result,eax \ |
---|
80 | } |
---|
81 | #else |
---|
82 | #define MulDivAssign(Result, x, y, z) Result = (((x)*(y))/(z)) |
---|
83 | #endif |
---|
84 | |
---|
85 | #define MulScoreWeight(r, s, w) MulDivAssign(r, s, w, INTSCALE) |
---|
86 | #define MulWeightWCount(r, wt, wc) MulDivAssign(r, wt, wc, INTSCALE) |
---|
87 | #define MulFCountScore(r, fc, sc) MulDivAssign(r, fc, sc, INTSCALE) |
---|
88 | |
---|
89 | #if _DEBUG |
---|
90 | |
---|
91 | static inline SCORE Add2(SCORE a, SCORE b) |
---|
92 | { |
---|
93 | if (MINUS_INFINITY == a) |
---|
94 | return MINUS_INFINITY; |
---|
95 | if (MINUS_INFINITY == b) |
---|
96 | return MINUS_INFINITY; |
---|
97 | SCORE sum = a + b; |
---|
98 | if (sum < MINUS_INFINITY) |
---|
99 | return MINUS_INFINITY; |
---|
100 | // assert(sum < OVERFLOW_WARN); |
---|
101 | return sum; |
---|
102 | } |
---|
103 | |
---|
104 | static inline SCORE Add3(SCORE a, SCORE b, SCORE c) |
---|
105 | { |
---|
106 | return Add2(Add2(a, b), c); |
---|
107 | } |
---|
108 | |
---|
109 | static inline SCORE Add4(SCORE a, SCORE b, SCORE c, SCORE d) |
---|
110 | { |
---|
111 | return Add2(Add2(a, b), Add2(c, d)); |
---|
112 | } |
---|
113 | |
---|
114 | static inline SCORE Add5(SCORE a, SCORE b, SCORE c, SCORE d, SCORE e) |
---|
115 | { |
---|
116 | return Add3(Add2(a, b), Add2(c, d), e); |
---|
117 | } |
---|
118 | |
---|
119 | static inline SCORE Add6(SCORE a, SCORE b, SCORE c, SCORE d, SCORE e, SCORE f) |
---|
120 | { |
---|
121 | return Add3(Add2(a, b), Add2(c, d), Add2(e, f)); |
---|
122 | } |
---|
123 | |
---|
124 | static inline SCORE Add7(SCORE a, SCORE b, SCORE c, SCORE d, SCORE e, SCORE f, SCORE g) |
---|
125 | { |
---|
126 | return Add4(Add2(a, b), Add2(c, d), Add2(e, f), g); |
---|
127 | } |
---|
128 | |
---|
129 | static inline SCORE Mul2(SCORE a, SCORE b) |
---|
130 | { |
---|
131 | if (MINUS_INFINITY == a) |
---|
132 | return MINUS_INFINITY; |
---|
133 | if (MINUS_INFINITY == b) |
---|
134 | return MINUS_INFINITY; |
---|
135 | //__int64 prod = (__int64) a * (__int64) b; |
---|
136 | //assert((SCORE) prod == prod); |
---|
137 | //return (SCORE) prod; |
---|
138 | return a*b; |
---|
139 | } |
---|
140 | |
---|
141 | static inline SCORE Sub2(SCORE a, SCORE b) |
---|
142 | { |
---|
143 | if (MINUS_INFINITY == a) |
---|
144 | return MINUS_INFINITY; |
---|
145 | if (MINUS_INFINITY == b) |
---|
146 | return MINUS_INFINITY; |
---|
147 | SCORE diff = a - b; |
---|
148 | if (diff < MINUS_INFINITY) |
---|
149 | return MINUS_INFINITY; |
---|
150 | // assert(diff < OVERFLOW_WARN); |
---|
151 | return diff; |
---|
152 | } |
---|
153 | |
---|
154 | static inline SCORE Div2(SCORE a, int b) |
---|
155 | { |
---|
156 | if (MINUS_INFINITY == a) |
---|
157 | return MINUS_INFINITY; |
---|
158 | return a/b; |
---|
159 | } |
---|
160 | |
---|
161 | //static inline SCORE MulScoreWeight(SCORE s, WEIGHT w) |
---|
162 | // { |
---|
163 | // SCORE Prod = s*(SCORE) w; |
---|
164 | // assert(Prod < OVERFLOW_WARN); |
---|
165 | // extern void Log(const char Format[], ...); |
---|
166 | // if (Prod/(SCORE) w != s) |
---|
167 | // Log("**WARRNING MulScoreWeight Prod=%d w=%d Prod/w=%d s=%d\n", |
---|
168 | // Prod, |
---|
169 | // w, |
---|
170 | // Prod/(SCORE) w, |
---|
171 | // s); |
---|
172 | // assert(Prod/ (SCORE) w == s); |
---|
173 | // return Prod/INTSCALE; |
---|
174 | // } |
---|
175 | // |
---|
176 | //static inline WCOUNT MulWeightWCount(WEIGHT wt, WCOUNT wc) |
---|
177 | // { |
---|
178 | // return (wt*wc)/INTSCALE; |
---|
179 | // } |
---|
180 | |
---|
181 | #else |
---|
182 | #define Add2(a, b) ((a) + (b)) |
---|
183 | #define Sub2(a, b) ((MINUS_INFINITY == (a)) ? MINUS_INFINITY : ((a) - (b))) |
---|
184 | #define Div2(a, b) ((MINUS_INFINITY == (a)) ? MINUS_INFINITY : ((a) / (b))) |
---|
185 | #define Add3(a, b, c) ((a) + (b) + (c)) |
---|
186 | #define Add4(a, b, c, d) ((a) + (b) + (c) + (d)) |
---|
187 | #define Add5(a, b, c, d, e) ((a) + (b) + (c) + (d) + (e)) |
---|
188 | #define Add6(a, b, c, d, e, f) ((a) + (b) + (c) + (d) + (e) + (f)) |
---|
189 | #define Add7(a, b, c, d, e, f, g) ((a) + (b) + (c) + (d) + (e) + (f) + (g)) |
---|
190 | //#define MulScoreWeight(s, w) (((s)*(SCORE) (w))/INTSCALE) |
---|
191 | #define Mul2(a, b) ((a)*(b)) |
---|
192 | #endif |
---|
193 | |
---|
194 | //static inline SCORE MulFCountScore(FCOUNT fc, SCORE sc) |
---|
195 | // { |
---|
196 | //// Fast way to say "if (fc >= 2^15 || sc >= 2^15)": |
---|
197 | // if ((fc | sc) & 0xffff1000) |
---|
198 | // { |
---|
199 | // SCORE Score = ((fc+5)/10)*sc; |
---|
200 | // assert(Score < assert); |
---|
201 | // OVERFLOW_WARN(Score > MINUS_INFINITY); |
---|
202 | // return Score/(INTSCALE/10); |
---|
203 | // } |
---|
204 | // SCORE Score = fc*sc; |
---|
205 | // assert(Score < OVERFLOW_WARN); |
---|
206 | // assert(Score > MINUS_INFINITY); |
---|
207 | // return Score/INTSCALE; |
---|
208 | // } |
---|
209 | |
---|
210 | #endif // IntMath_h |
---|