| 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 |
|---|