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 
21 #define ln2 ((FixedPoint)0.69314718)
22 
23 #define ln2 ((FixedPoint)0.69314718)
24 
sqrt(FixedPoint x)25 FixedPoint FixedPoint::sqrt(FixedPoint x) {
26   FixedPoint y0, y1, z;
27 
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);
37   }
38   return y1;
39 }
40 
pow(FixedPoint x,FixedPoint y)41 FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
42   FixedPoint t, t2, lnx0, lnx, z0, z;
43   int d, n, i;
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))
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;
79     }
80   }
81   return z;
82 }
83 
mul(int x,int y)84 int FixedPoint::mul(int x, int y) {
85   FixPtInt64 z;
86 
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;
94   }
95 }
96 
div(int x,int y)97 int FixedPoint::div(int x, int y) {
98   FixPtInt64 z;
99 
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;
107   }
108 }
109 
divCheck(FixedPoint x,FixedPoint y,FixedPoint * result)110 GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
111   FixPtInt64 z;
112 
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;
117   }
118   result->val = z;
119   return gTrue;
120 }
121 
checkDet(FixedPoint m11,FixedPoint m12,FixedPoint m21,FixedPoint m22,FixedPoint epsilon)122 GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
123                           FixedPoint m21, FixedPoint m22,
124                           FixedPoint epsilon) {
125   FixPtInt64 det, e;
126 
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;
133 }
134 
135 #endif // USE_FIXEDPOINT
136