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 <aconf.h>
12
13 #if USE_FIXEDPOINT
14
15 #ifdef USE_GCC_PRAGMAS
16 #pragma implementation
17 #endif
18
19 #include "FixedPoint.h"
20
21 #define ln2 ((FixedPoint)0.69314718)
22
sqrt(FixedPoint x)23 FixedPoint FixedPoint::sqrt(FixedPoint x) {
24 FixedPoint y0, y1, z;
25
26 if (x.val <= 0) {
27 y1.val = 0;
28 } else {
29 y1.val = x.val == 1 ? 2 : x.val >> 1;
30 do {
31 y0.val = y1.val;
32 z = x / y0;
33 y1.val = (y0.val + z.val) >> 1;
34 } while (::abs(y0.val - y1.val) > 1);
35 }
36 return y1;
37 }
38
pow(FixedPoint x,FixedPoint y)39 FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
40 FixedPoint t, t2, lnx0, lnx, z0, z;
41 int d, n, i;
42
43 if (y.val <= 0) {
44 z.val = 0;
45 } else {
46 // y * ln(x)
47 t = (x - 1) / (x + 1);
48 t2 = t * t;
49 d = 1;
50 lnx = 0;
51 do {
52 lnx0 = lnx;
53 lnx += t / d;
54 t *= t2;
55 d += 2;
56 } while (::abs(lnx.val - lnx0.val) > 2);
57 lnx.val <<= 1;
58 t = y * lnx;
59 // exp(y * ln(x))
60 n = floor(t / ln2);
61 t -= ln2 * n;
62 t2 = t;
63 d = 1;
64 i = 1;
65 z = 1;
66 do {
67 z0 = z;
68 z += t2 / d;
69 t2 *= t;
70 ++i;
71 d *= i;
72 } while (::abs(z.val - z0.val) > 2 && d < (1 << fixptShift));
73 if (n >= 0) {
74 z.val <<= n;
75 } else if (n < 0) {
76 z.val >>= -n;
77 }
78 }
79 return z;
80 }
81
mul(int x,int y)82 int FixedPoint::mul(int x, int y) {
83 FixPtInt64 z;
84
85 z = ((FixPtInt64)x * y) >> fixptShift;
86 if (z > 0x7fffffffLL) {
87 return 0x7fffffff;
88 } else if (z < -0x80000000LL) {
89 return 0x80000000;
90 } else {
91 return (int)z;
92 }
93 }
94
div(int x,int y)95 int FixedPoint::div(int x, int y) {
96 FixPtInt64 z;
97
98 z = ((FixPtInt64)x << fixptShift) / y;
99 if (z > 0x7fffffffLL) {
100 return 0x7fffffff;
101 } else if (z < -0x80000000LL) {
102 return 0x80000000;
103 } else {
104 return (int)z;
105 }
106 }
107
divCheck(FixedPoint x,FixedPoint y,FixedPoint * result)108 GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
109 FixPtInt64 z;
110
111 z = ((FixPtInt64)x.val << fixptShift) / y.val;
112 if ((z == 0 && x != 0) ||
113 z >= ((FixPtInt64)1 << 31) || z < -((FixPtInt64)1 << 31)) {
114 return gFalse;
115 }
116 result->val = z;
117 return gTrue;
118 }
119
checkDet(FixedPoint m11,FixedPoint m12,FixedPoint m21,FixedPoint m22,FixedPoint epsilon)120 GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
121 FixedPoint m21, FixedPoint m22,
122 FixedPoint epsilon) {
123 FixPtInt64 det, e;
124
125 det = (FixPtInt64)m11.val * (FixPtInt64)m22.val
126 - (FixPtInt64)m12.val * (FixPtInt64)m21.val;
127 e = (FixPtInt64)epsilon.val << fixptShift;
128 // NB: this comparison has to be >= not > because epsilon can be
129 // truncated to zero as a fixed point value.
130 return det >= e || det <= -e;
131 }
132
133 #endif // USE_FIXEDPOINT
134