beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / goo / FixedPoint.cc
blob26b2f0fe89011b2c4f1ea4ee1f8b32bb656bd1b6
1 //========================================================================
2 //
3 // FixedPoint.cc
4 //
5 // Fixed point type, with C++ operators.
6 //
7 // Copyright 2004 Glyph & Cog, LLC
8 //
9 //========================================================================
11 #include <config.h>
13 #if USE_FIXEDPOINT
15 #ifdef USE_GCC_PRAGMAS
16 #pragma implementation
17 #endif
19 #include "FixedPoint.h"
21 #define ln2 ((FixedPoint)0.69314718)
23 #define ln2 ((FixedPoint)0.69314718)
25 FixedPoint FixedPoint::sqrt(FixedPoint x) {
26 FixedPoint y0, y1, z;
28 if (x.val <= 0) {
29 y1.val = 0;
30 } else {
31 y1.val = x.val == 1 ? 2 : x.val >> 1;
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);
38 return y1;
41 FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
42 FixedPoint t, t2, lnx0, lnx, z0, z;
43 int d, n, i;
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))
62 n = floor(t / ln2);
63 t -= ln2 * n;
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));
75 if (n >= 0) {
76 z.val <<= n;
77 } else if (n < 0) {
78 z.val >>= -n;
81 return z;
84 int FixedPoint::mul(int x, int y) {
85 FixPtInt64 z;
87 z = ((FixPtInt64)x * y) >> fixptShift;
88 if (z > 0x7fffffffLL) {
89 return 0x7fffffff;
90 } else if (z < -0x80000000LL) {
91 return 0x80000000;
92 } else {
93 return (int)z;
97 int FixedPoint::div(int x, int y) {
98 FixPtInt64 z;
100 z = ((FixPtInt64)x << fixptShift) / y;
101 if (z > 0x7fffffffLL) {
102 return 0x7fffffff;
103 } else if (z < -0x80000000LL) {
104 return 0x80000000;
105 } else {
106 return (int)z;
110 GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
111 FixPtInt64 z;
113 z = ((FixPtInt64)x.val << fixptShift) / y.val;
114 if ((z == 0 && x != 0) ||
115 z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) {
116 return gFalse;
118 result->val = z;
119 return gTrue;
122 GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
123 FixedPoint m21, FixedPoint m22,
124 FixedPoint epsilon) {
125 FixPtInt64 det, e;
127 det = (FixPtInt64)m11.val * (FixPtInt64)m22.val
128 - (FixPtInt64)m12.val * (FixPtInt64)m21.val;
129 e = (FixPtInt64)epsilon.val << fixptShift;
130 // NB: this comparison has to be >= not > because epsilon can be
131 // truncated to zero as a fixed point value.
132 return det >= e || det <= -e;
135 #endif // USE_FIXEDPOINT