[2] | 1 | //======================================================================== |
---|
| 2 | // |
---|
| 3 | // FixedPoint.cc |
---|
| 4 | // |
---|
| 5 | // Fixed point type, with C++ operators. |
---|
| 6 | // |
---|
| 7 | // Copyright 2004 Glyph & Cog, LLC |
---|
| 8 | // |
---|
| 9 | //======================================================================== |
---|
| 10 | |
---|
| 11 | #include <config.h> |
---|
| 12 | |
---|
| 13 | #if USE_FIXEDPOINT |
---|
| 14 | |
---|
| 15 | #ifdef USE_GCC_PRAGMAS |
---|
| 16 | #pragma implementation |
---|
| 17 | #endif |
---|
| 18 | |
---|
| 19 | #include "FixedPoint.h" |
---|
| 20 | |
---|
[250] | 21 | #define ln2 ((FixedPoint)0.69314718) |
---|
| 22 | |
---|
| 23 | #define ln2 ((FixedPoint)0.69314718) |
---|
| 24 | |
---|
[2] | 25 | FixedPoint FixedPoint::sqrt(FixedPoint x) { |
---|
| 26 | FixedPoint y0, y1, z; |
---|
| 27 | |
---|
| 28 | if (x.val <= 0) { |
---|
| 29 | y1.val = 0; |
---|
| 30 | } else { |
---|
[250] | 31 | y1.val = x.val == 1 ? 2 : x.val >> 1; |
---|
[2] | 32 | do { |
---|
| 33 | y0.val = y1.val; |
---|
| 34 | z = x / y0; |
---|
| 35 | y1.val = (y0.val + z.val) >> 1; |
---|
| 36 | } while (::abs(y0.val - y1.val) > 1); |
---|
| 37 | } |
---|
| 38 | return y1; |
---|
| 39 | } |
---|
| 40 | |
---|
| 41 | FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) { |
---|
| 42 | FixedPoint t, t2, lnx0, lnx, z0, z; |
---|
[250] | 43 | int d, n, i; |
---|
[2] | 44 | |
---|
| 45 | if (y.val <= 0) { |
---|
| 46 | z.val = 0; |
---|
| 47 | } else { |
---|
| 48 | // y * ln(x) |
---|
| 49 | t = (x - 1) / (x + 1); |
---|
| 50 | t2 = t * t; |
---|
| 51 | d = 1; |
---|
| 52 | lnx = 0; |
---|
| 53 | do { |
---|
| 54 | lnx0 = lnx; |
---|
| 55 | lnx += t / d; |
---|
| 56 | t *= t2; |
---|
| 57 | d += 2; |
---|
| 58 | } while (::abs(lnx.val - lnx0.val) > 2); |
---|
| 59 | lnx.val <<= 1; |
---|
| 60 | t = y * lnx; |
---|
| 61 | // exp(y * ln(x)) |
---|
[250] | 62 | n = floor(t / ln2); |
---|
| 63 | t -= ln2 * n; |
---|
[2] | 64 | t2 = t; |
---|
| 65 | d = 1; |
---|
| 66 | i = 1; |
---|
| 67 | z = 1; |
---|
| 68 | do { |
---|
| 69 | z0 = z; |
---|
| 70 | z += t2 / d; |
---|
| 71 | t2 *= t; |
---|
| 72 | ++i; |
---|
| 73 | d *= i; |
---|
| 74 | } while (::abs(z.val - z0.val) > 2 && d < (1 << fixptShift)); |
---|
[250] | 75 | if (n >= 0) { |
---|
| 76 | z.val <<= n; |
---|
| 77 | } else if (n < 0) { |
---|
| 78 | z.val >>= -n; |
---|
| 79 | } |
---|
[2] | 80 | } |
---|
| 81 | return z; |
---|
| 82 | } |
---|
| 83 | |
---|
| 84 | int FixedPoint::mul(int x, int y) { |
---|
| 85 | #if 1 //~tmp |
---|
| 86 | return ((FixPtInt64)x * y) >> fixptShift; |
---|
| 87 | #else |
---|
| 88 | int ah0, ah, bh, al, bl; |
---|
| 89 | ah0 = x & fixptMaskH; |
---|
| 90 | ah = x >> fixptShift; |
---|
| 91 | al = x - ah0; |
---|
| 92 | bh = y >> fixptShift; |
---|
| 93 | bl = y - (bh << fixptShift); |
---|
| 94 | return ah0 * bh + ah * bl + al * bh + ((al * bl) >> fixptShift); |
---|
| 95 | #endif |
---|
| 96 | } |
---|
| 97 | |
---|
| 98 | int FixedPoint::div(int x, int y) { |
---|
| 99 | #if 1 //~tmp |
---|
| 100 | return ((FixPtInt64)x << fixptShift) / y; |
---|
| 101 | #else |
---|
| 102 | #endif |
---|
| 103 | } |
---|
| 104 | |
---|
[250] | 105 | GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) { |
---|
| 106 | #if 1 //~tmp |
---|
| 107 | FixPtInt64 z; |
---|
| 108 | |
---|
| 109 | z = ((FixPtInt64)x.val << fixptShift) / y.val; |
---|
| 110 | if ((z == 0 && x != 0) || |
---|
| 111 | z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) { |
---|
| 112 | return gFalse; |
---|
| 113 | } |
---|
| 114 | result->val = z; |
---|
| 115 | return gTrue; |
---|
| 116 | #else |
---|
| 117 | #endif |
---|
| 118 | } |
---|
| 119 | |
---|
[2] | 120 | #endif // USE_FIXEDPOINT |
---|