xref: /inferno-os/libfreetype/ftcalc.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ftcalc.c                                                               */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    Arithmetic computations (body).                                      */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth   /*************************************************************************/
19*37da2899SCharles.Forsyth   /*                                                                       */
20*37da2899SCharles.Forsyth   /* Support for 1-complement arithmetic has been totally dropped in this  */
21*37da2899SCharles.Forsyth   /* release.  You can still write your own code if you need it.           */
22*37da2899SCharles.Forsyth   /*                                                                       */
23*37da2899SCharles.Forsyth   /*************************************************************************/
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth   /*************************************************************************/
26*37da2899SCharles.Forsyth   /*                                                                       */
27*37da2899SCharles.Forsyth   /* Implementing basic computation routines.                              */
28*37da2899SCharles.Forsyth   /*                                                                       */
29*37da2899SCharles.Forsyth   /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(),   */
30*37da2899SCharles.Forsyth   /* and FT_FloorFix() are declared in freetype.h.                         */
31*37da2899SCharles.Forsyth   /*                                                                       */
32*37da2899SCharles.Forsyth   /*************************************************************************/
33*37da2899SCharles.Forsyth 
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth #include <ft2build.h>
36*37da2899SCharles.Forsyth #include FT_INTERNAL_CALC_H
37*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
38*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth /* we need to define a 64-bits data type here */
42*37da2899SCharles.Forsyth 
43*37da2899SCharles.Forsyth #ifdef FT_LONG64
44*37da2899SCharles.Forsyth 
45*37da2899SCharles.Forsyth   typedef FT_INT64  FT_Int64;
46*37da2899SCharles.Forsyth 
47*37da2899SCharles.Forsyth #else
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth   typedef struct  FT_Int64_
50*37da2899SCharles.Forsyth   {
51*37da2899SCharles.Forsyth     FT_UInt32  lo;
52*37da2899SCharles.Forsyth     FT_UInt32  hi;
53*37da2899SCharles.Forsyth 
54*37da2899SCharles.Forsyth   } FT_Int64;
55*37da2899SCharles.Forsyth 
56*37da2899SCharles.Forsyth #endif /* FT_LONG64 */
57*37da2899SCharles.Forsyth 
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth   /*************************************************************************/
60*37da2899SCharles.Forsyth   /*                                                                       */
61*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
62*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
63*37da2899SCharles.Forsyth   /* messages during execution.                                            */
64*37da2899SCharles.Forsyth   /*                                                                       */
65*37da2899SCharles.Forsyth #undef  FT_COMPONENT
66*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_calc
67*37da2899SCharles.Forsyth 
68*37da2899SCharles.Forsyth 
69*37da2899SCharles.Forsyth   /* The following three functions are available regardless of whether */
70*37da2899SCharles.Forsyth   /* FT_LONG64 is defined.                                             */
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
73*37da2899SCharles.Forsyth 
74*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Fixed )
FT_RoundFix(FT_Fixed a)75*37da2899SCharles.Forsyth   FT_RoundFix( FT_Fixed  a )
76*37da2899SCharles.Forsyth   {
77*37da2899SCharles.Forsyth     return ( a >= 0 ) ?   ( a + 0x8000L ) & -0x10000L
78*37da2899SCharles.Forsyth                       : -((-a + 0x8000L ) & -0x10000L );
79*37da2899SCharles.Forsyth   }
80*37da2899SCharles.Forsyth 
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Fixed )
FT_CeilFix(FT_Fixed a)85*37da2899SCharles.Forsyth   FT_CeilFix( FT_Fixed  a )
86*37da2899SCharles.Forsyth   {
87*37da2899SCharles.Forsyth     return ( a >= 0 ) ?   ( a + 0xFFFFL ) & -0x10000L
88*37da2899SCharles.Forsyth                       : -((-a + 0xFFFFL ) & -0x10000L );
89*37da2899SCharles.Forsyth   }
90*37da2899SCharles.Forsyth 
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
93*37da2899SCharles.Forsyth 
94*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Fixed )
FT_FloorFix(FT_Fixed a)95*37da2899SCharles.Forsyth   FT_FloorFix( FT_Fixed  a )
96*37da2899SCharles.Forsyth   {
97*37da2899SCharles.Forsyth     return ( a >= 0 ) ?   a & -0x10000L
98*37da2899SCharles.Forsyth                       : -((-a) & -0x10000L );
99*37da2899SCharles.Forsyth   }
100*37da2899SCharles.Forsyth 
101*37da2899SCharles.Forsyth 
102*37da2899SCharles.Forsyth   /* documentation is in ftcalc.h */
103*37da2899SCharles.Forsyth 
104*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Int32 )
FT_Sqrt32(FT_Int32 x)105*37da2899SCharles.Forsyth   FT_Sqrt32( FT_Int32  x )
106*37da2899SCharles.Forsyth   {
107*37da2899SCharles.Forsyth     FT_ULong  val, root, newroot, mask;
108*37da2899SCharles.Forsyth 
109*37da2899SCharles.Forsyth 
110*37da2899SCharles.Forsyth     root = 0;
111*37da2899SCharles.Forsyth     mask = 0x40000000L;
112*37da2899SCharles.Forsyth     val  = (FT_ULong)x;
113*37da2899SCharles.Forsyth 
114*37da2899SCharles.Forsyth     do
115*37da2899SCharles.Forsyth     {
116*37da2899SCharles.Forsyth       newroot = root + mask;
117*37da2899SCharles.Forsyth       if ( newroot <= val )
118*37da2899SCharles.Forsyth       {
119*37da2899SCharles.Forsyth         val -= newroot;
120*37da2899SCharles.Forsyth         root = newroot + mask;
121*37da2899SCharles.Forsyth       }
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth       root >>= 1;
124*37da2899SCharles.Forsyth       mask >>= 2;
125*37da2899SCharles.Forsyth 
126*37da2899SCharles.Forsyth     } while ( mask != 0 );
127*37da2899SCharles.Forsyth 
128*37da2899SCharles.Forsyth     return root;
129*37da2899SCharles.Forsyth   }
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth #ifdef FT_LONG64
133*37da2899SCharles.Forsyth 
134*37da2899SCharles.Forsyth 
135*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Long )
FT_MulDiv(FT_Long a,FT_Long b,FT_Long c)138*37da2899SCharles.Forsyth   FT_MulDiv( FT_Long  a,
139*37da2899SCharles.Forsyth              FT_Long  b,
140*37da2899SCharles.Forsyth              FT_Long  c )
141*37da2899SCharles.Forsyth   {
142*37da2899SCharles.Forsyth     FT_Int   s;
143*37da2899SCharles.Forsyth     FT_Long  d;
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth     s = 1;
147*37da2899SCharles.Forsyth     if ( a < 0 ) { a = -a; s = -1; }
148*37da2899SCharles.Forsyth     if ( b < 0 ) { b = -b; s = -s; }
149*37da2899SCharles.Forsyth     if ( c < 0 ) { c = -c; s = -s; }
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth     d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
152*37da2899SCharles.Forsyth                          : 0x7FFFFFFFL );
153*37da2899SCharles.Forsyth 
154*37da2899SCharles.Forsyth     return ( s > 0 ) ? d : -d;
155*37da2899SCharles.Forsyth   }
156*37da2899SCharles.Forsyth 
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
159*37da2899SCharles.Forsyth 
160*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Long )
FT_MulFix(FT_Long a,FT_Long b)161*37da2899SCharles.Forsyth   FT_MulFix( FT_Long  a,
162*37da2899SCharles.Forsyth              FT_Long  b )
163*37da2899SCharles.Forsyth   {
164*37da2899SCharles.Forsyth     FT_Int   s = 1;
165*37da2899SCharles.Forsyth     FT_Long  c;
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth     if ( a < 0 ) { a = -a; s = -1; }
169*37da2899SCharles.Forsyth     if ( b < 0 ) { b = -b; s = -s; }
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth     c = (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 );
172*37da2899SCharles.Forsyth     return ( s > 0 ) ? c : -c ;
173*37da2899SCharles.Forsyth   }
174*37da2899SCharles.Forsyth 
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Long )
FT_DivFix(FT_Long a,FT_Long b)179*37da2899SCharles.Forsyth   FT_DivFix( FT_Long  a,
180*37da2899SCharles.Forsyth              FT_Long  b )
181*37da2899SCharles.Forsyth   {
182*37da2899SCharles.Forsyth     FT_Int32   s;
183*37da2899SCharles.Forsyth     FT_UInt32  q;
184*37da2899SCharles.Forsyth 
185*37da2899SCharles.Forsyth     s = 1;
186*37da2899SCharles.Forsyth     if ( a < 0 ) { a = -a; s = -1; }
187*37da2899SCharles.Forsyth     if ( b < 0 ) { b = -b; s = -s; }
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth     if ( b == 0 )
190*37da2899SCharles.Forsyth       /* check for division by 0 */
191*37da2899SCharles.Forsyth       q = 0x7FFFFFFFL;
192*37da2899SCharles.Forsyth     else
193*37da2899SCharles.Forsyth       /* compute result directly */
194*37da2899SCharles.Forsyth       q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );
195*37da2899SCharles.Forsyth 
196*37da2899SCharles.Forsyth     return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
197*37da2899SCharles.Forsyth   }
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth 
200*37da2899SCharles.Forsyth #else /* FT_LONG64 */
201*37da2899SCharles.Forsyth 
202*37da2899SCharles.Forsyth 
203*37da2899SCharles.Forsyth   static void
ft_multo64(FT_UInt32 x,FT_UInt32 y,FT_Int64 * z)204*37da2899SCharles.Forsyth   ft_multo64( FT_UInt32  x,
205*37da2899SCharles.Forsyth               FT_UInt32  y,
206*37da2899SCharles.Forsyth               FT_Int64  *z )
207*37da2899SCharles.Forsyth   {
208*37da2899SCharles.Forsyth     FT_UInt32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;
209*37da2899SCharles.Forsyth 
210*37da2899SCharles.Forsyth 
211*37da2899SCharles.Forsyth     lo1 = x & 0x0000FFFFU;  hi1 = x >> 16;
212*37da2899SCharles.Forsyth     lo2 = y & 0x0000FFFFU;  hi2 = y >> 16;
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth     lo = lo1 * lo2;
215*37da2899SCharles.Forsyth     i1 = lo1 * hi2;
216*37da2899SCharles.Forsyth     i2 = lo2 * hi1;
217*37da2899SCharles.Forsyth     hi = hi1 * hi2;
218*37da2899SCharles.Forsyth 
219*37da2899SCharles.Forsyth     /* Check carry overflow of i1 + i2 */
220*37da2899SCharles.Forsyth     i1 += i2;
221*37da2899SCharles.Forsyth     hi += (FT_UInt32)( i1 < i2 ) << 16;
222*37da2899SCharles.Forsyth 
223*37da2899SCharles.Forsyth     hi += i1 >> 16;
224*37da2899SCharles.Forsyth     i1  = i1 << 16;
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth     /* Check carry overflow of i1 + lo */
227*37da2899SCharles.Forsyth     lo += i1;
228*37da2899SCharles.Forsyth     hi += ( lo < i1 );
229*37da2899SCharles.Forsyth 
230*37da2899SCharles.Forsyth     z->lo = lo;
231*37da2899SCharles.Forsyth     z->hi = hi;
232*37da2899SCharles.Forsyth   }
233*37da2899SCharles.Forsyth 
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth   static FT_UInt32
ft_div64by32(FT_UInt32 hi,FT_UInt32 lo,FT_UInt32 y)236*37da2899SCharles.Forsyth   ft_div64by32( FT_UInt32  hi,
237*37da2899SCharles.Forsyth                 FT_UInt32  lo,
238*37da2899SCharles.Forsyth                 FT_UInt32  y )
239*37da2899SCharles.Forsyth   {
240*37da2899SCharles.Forsyth     FT_UInt32  r, q;
241*37da2899SCharles.Forsyth     FT_Int     i;
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth     q = 0;
245*37da2899SCharles.Forsyth     r = hi;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth     if ( r >= y )
248*37da2899SCharles.Forsyth       return (FT_UInt32)0x7FFFFFFFL;
249*37da2899SCharles.Forsyth 
250*37da2899SCharles.Forsyth     i = 32;
251*37da2899SCharles.Forsyth     do
252*37da2899SCharles.Forsyth     {
253*37da2899SCharles.Forsyth       r <<= 1;
254*37da2899SCharles.Forsyth       q <<= 1;
255*37da2899SCharles.Forsyth       r  |= lo >> 31;
256*37da2899SCharles.Forsyth 
257*37da2899SCharles.Forsyth       if ( r >= (FT_UInt32)y )
258*37da2899SCharles.Forsyth       {
259*37da2899SCharles.Forsyth         r -= y;
260*37da2899SCharles.Forsyth         q |= 1;
261*37da2899SCharles.Forsyth       }
262*37da2899SCharles.Forsyth       lo <<= 1;
263*37da2899SCharles.Forsyth     } while ( --i );
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth     return q;
266*37da2899SCharles.Forsyth   }
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth   /* documentation is in ftcalc.h */
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Add64(FT_Int64 * x,FT_Int64 * y,FT_Int64 * z)272*37da2899SCharles.Forsyth   FT_Add64( FT_Int64*  x,
273*37da2899SCharles.Forsyth             FT_Int64*  y,
274*37da2899SCharles.Forsyth             FT_Int64  *z )
275*37da2899SCharles.Forsyth   {
276*37da2899SCharles.Forsyth     register FT_UInt32  lo, hi, max;
277*37da2899SCharles.Forsyth 
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth     max = x->lo > y->lo ? x->lo : y->lo;
280*37da2899SCharles.Forsyth     lo  = x->lo + y->lo;
281*37da2899SCharles.Forsyth     hi  = x->hi + y->hi + ( lo < max );
282*37da2899SCharles.Forsyth 
283*37da2899SCharles.Forsyth     z->lo = lo;
284*37da2899SCharles.Forsyth     z->hi = hi;
285*37da2899SCharles.Forsyth   }
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Long )
FT_MulDiv(FT_Long a,FT_Long b,FT_Long c)291*37da2899SCharles.Forsyth   FT_MulDiv( FT_Long  a,
292*37da2899SCharles.Forsyth              FT_Long  b,
293*37da2899SCharles.Forsyth              FT_Long  c )
294*37da2899SCharles.Forsyth   {
295*37da2899SCharles.Forsyth     long  s;
296*37da2899SCharles.Forsyth 
297*37da2899SCharles.Forsyth 
298*37da2899SCharles.Forsyth     if ( a == 0 || b == c )
299*37da2899SCharles.Forsyth       return a;
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth     s  = a; a = ABS( a );
302*37da2899SCharles.Forsyth     s ^= b; b = ABS( b );
303*37da2899SCharles.Forsyth     s ^= c; c = ABS( c );
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth     if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
306*37da2899SCharles.Forsyth     {
307*37da2899SCharles.Forsyth       a = ( a * b + ( c >> 1 ) ) / c;
308*37da2899SCharles.Forsyth     }
309*37da2899SCharles.Forsyth     else if ( c > 0 )
310*37da2899SCharles.Forsyth     {
311*37da2899SCharles.Forsyth       FT_Int64  temp, temp2;
312*37da2899SCharles.Forsyth 
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth       ft_multo64( a, b, &temp );
315*37da2899SCharles.Forsyth 
316*37da2899SCharles.Forsyth       temp2.hi = 0;
317*37da2899SCharles.Forsyth       temp2.lo = (FT_UInt32)(c >> 1);
318*37da2899SCharles.Forsyth       FT_Add64( &temp, &temp2, &temp );
319*37da2899SCharles.Forsyth       a = ft_div64by32( temp.hi, temp.lo, c );
320*37da2899SCharles.Forsyth     }
321*37da2899SCharles.Forsyth     else
322*37da2899SCharles.Forsyth       a = 0x7FFFFFFFL;
323*37da2899SCharles.Forsyth 
324*37da2899SCharles.Forsyth     return ( s < 0 ? -a : a );
325*37da2899SCharles.Forsyth   }
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth 
328*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Long )
FT_MulFix(FT_Long a,FT_Long b)331*37da2899SCharles.Forsyth   FT_MulFix( FT_Long  a,
332*37da2899SCharles.Forsyth              FT_Long  b )
333*37da2899SCharles.Forsyth   {
334*37da2899SCharles.Forsyth     FT_Long   s;
335*37da2899SCharles.Forsyth     FT_ULong  ua, ub;
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth 
338*37da2899SCharles.Forsyth     if ( a == 0 || b == 0x10000L )
339*37da2899SCharles.Forsyth       return a;
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth     s  = a; a = ABS(a);
342*37da2899SCharles.Forsyth     s ^= b; b = ABS(b);
343*37da2899SCharles.Forsyth 
344*37da2899SCharles.Forsyth     ua = (FT_ULong)a;
345*37da2899SCharles.Forsyth     ub = (FT_ULong)b;
346*37da2899SCharles.Forsyth 
347*37da2899SCharles.Forsyth     if ( ua <= 2048 && ub <= 1048576L )
348*37da2899SCharles.Forsyth     {
349*37da2899SCharles.Forsyth       ua = ( ua * ub + 0x8000 ) >> 16;
350*37da2899SCharles.Forsyth     }
351*37da2899SCharles.Forsyth     else
352*37da2899SCharles.Forsyth     {
353*37da2899SCharles.Forsyth       FT_ULong  al = ua & 0xFFFF;
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth 
356*37da2899SCharles.Forsyth       ua = ( ua >> 16 ) * ub +  al * ( ub >> 16 ) +
357*37da2899SCharles.Forsyth            ( ( al * ( ub & 0xFFFF ) + 0x8000 ) >> 16 );
358*37da2899SCharles.Forsyth     }
359*37da2899SCharles.Forsyth 
360*37da2899SCharles.Forsyth     return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
361*37da2899SCharles.Forsyth   }
362*37da2899SCharles.Forsyth 
363*37da2899SCharles.Forsyth 
364*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Long )
FT_DivFix(FT_Long a,FT_Long b)367*37da2899SCharles.Forsyth   FT_DivFix( FT_Long  a,
368*37da2899SCharles.Forsyth              FT_Long  b )
369*37da2899SCharles.Forsyth   {
370*37da2899SCharles.Forsyth     FT_Int32   s;
371*37da2899SCharles.Forsyth     FT_UInt32  q;
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth 
374*37da2899SCharles.Forsyth     s  = a; a = ABS(a);
375*37da2899SCharles.Forsyth     s ^= b; b = ABS(b);
376*37da2899SCharles.Forsyth 
377*37da2899SCharles.Forsyth     if ( b == 0 )
378*37da2899SCharles.Forsyth     {
379*37da2899SCharles.Forsyth       /* check for division by 0 */
380*37da2899SCharles.Forsyth       q = 0x7FFFFFFFL;
381*37da2899SCharles.Forsyth     }
382*37da2899SCharles.Forsyth     else if ( ( a >> 16 ) == 0 )
383*37da2899SCharles.Forsyth     {
384*37da2899SCharles.Forsyth       /* compute result directly */
385*37da2899SCharles.Forsyth       q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b;
386*37da2899SCharles.Forsyth     }
387*37da2899SCharles.Forsyth     else
388*37da2899SCharles.Forsyth     {
389*37da2899SCharles.Forsyth       /* we need more bits; we have to do it by hand */
390*37da2899SCharles.Forsyth       FT_Int64  temp, temp2;
391*37da2899SCharles.Forsyth 
392*37da2899SCharles.Forsyth       temp.hi  = (FT_Int32) (a >> 16);
393*37da2899SCharles.Forsyth       temp.lo  = (FT_UInt32)(a << 16);
394*37da2899SCharles.Forsyth       temp2.hi = 0;
395*37da2899SCharles.Forsyth       temp2.lo = (FT_UInt32)( b >> 1 );
396*37da2899SCharles.Forsyth       FT_Add64( &temp, &temp2, &temp );
397*37da2899SCharles.Forsyth       q = ft_div64by32( temp.hi, temp.lo, b );
398*37da2899SCharles.Forsyth     }
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth     return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
401*37da2899SCharles.Forsyth   }
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth 
404*37da2899SCharles.Forsyth   /* documentation is in ftcalc.h */
405*37da2899SCharles.Forsyth 
406*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_MulTo64(FT_Int32 x,FT_Int32 y,FT_Int64 * z)407*37da2899SCharles.Forsyth   FT_MulTo64( FT_Int32   x,
408*37da2899SCharles.Forsyth               FT_Int32   y,
409*37da2899SCharles.Forsyth               FT_Int64  *z )
410*37da2899SCharles.Forsyth   {
411*37da2899SCharles.Forsyth     FT_Int32  s;
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth 
414*37da2899SCharles.Forsyth     s  = x; x = ABS( x );
415*37da2899SCharles.Forsyth     s ^= y; y = ABS( y );
416*37da2899SCharles.Forsyth 
417*37da2899SCharles.Forsyth     ft_multo64( x, y, z );
418*37da2899SCharles.Forsyth 
419*37da2899SCharles.Forsyth     if ( s < 0 )
420*37da2899SCharles.Forsyth     {
421*37da2899SCharles.Forsyth       z->lo = (FT_UInt32)-(FT_Int32)z->lo;
422*37da2899SCharles.Forsyth       z->hi = ~z->hi + !( z->lo );
423*37da2899SCharles.Forsyth     }
424*37da2899SCharles.Forsyth   }
425*37da2899SCharles.Forsyth 
426*37da2899SCharles.Forsyth 
427*37da2899SCharles.Forsyth   /* documentation is in ftcalc.h */
428*37da2899SCharles.Forsyth 
429*37da2899SCharles.Forsyth   /* apparently, the second version of this code is not compiled correctly */
430*37da2899SCharles.Forsyth   /* on Mac machines with the MPW C compiler..  tsss, tsss, tss...         */
431*37da2899SCharles.Forsyth 
432*37da2899SCharles.Forsyth #if 1
433*37da2899SCharles.Forsyth 
434*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Int32 )
FT_Div64by32(FT_Int64 * x,FT_Int32 y)435*37da2899SCharles.Forsyth   FT_Div64by32( FT_Int64*  x,
436*37da2899SCharles.Forsyth                 FT_Int32   y )
437*37da2899SCharles.Forsyth   {
438*37da2899SCharles.Forsyth     FT_Int32   s;
439*37da2899SCharles.Forsyth     FT_UInt32  q, r, i, lo;
440*37da2899SCharles.Forsyth 
441*37da2899SCharles.Forsyth 
442*37da2899SCharles.Forsyth     s  = x->hi;
443*37da2899SCharles.Forsyth     if ( s < 0 )
444*37da2899SCharles.Forsyth     {
445*37da2899SCharles.Forsyth       x->lo = (FT_UInt32)-(FT_Int32)x->lo;
446*37da2899SCharles.Forsyth       x->hi = ~x->hi + !x->lo;
447*37da2899SCharles.Forsyth     }
448*37da2899SCharles.Forsyth     s ^= y;  y = ABS( y );
449*37da2899SCharles.Forsyth 
450*37da2899SCharles.Forsyth     /* Shortcut */
451*37da2899SCharles.Forsyth     if ( x->hi == 0 )
452*37da2899SCharles.Forsyth     {
453*37da2899SCharles.Forsyth       if ( y > 0 )
454*37da2899SCharles.Forsyth         q = x->lo / y;
455*37da2899SCharles.Forsyth       else
456*37da2899SCharles.Forsyth         q = 0x7FFFFFFFL;
457*37da2899SCharles.Forsyth 
458*37da2899SCharles.Forsyth       return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
459*37da2899SCharles.Forsyth     }
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth     r  = x->hi;
462*37da2899SCharles.Forsyth     lo = x->lo;
463*37da2899SCharles.Forsyth 
464*37da2899SCharles.Forsyth     if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
465*37da2899SCharles.Forsyth       return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
466*37da2899SCharles.Forsyth                              /* Return Max/Min Int32 if division overflow. */
467*37da2899SCharles.Forsyth                              /* This includes division by zero! */
468*37da2899SCharles.Forsyth     q = 0;
469*37da2899SCharles.Forsyth     for ( i = 0; i < 32; i++ )
470*37da2899SCharles.Forsyth     {
471*37da2899SCharles.Forsyth       r <<= 1;
472*37da2899SCharles.Forsyth       q <<= 1;
473*37da2899SCharles.Forsyth       r  |= lo >> 31;
474*37da2899SCharles.Forsyth 
475*37da2899SCharles.Forsyth       if ( r >= (FT_UInt32)y )
476*37da2899SCharles.Forsyth       {
477*37da2899SCharles.Forsyth         r -= y;
478*37da2899SCharles.Forsyth         q |= 1;
479*37da2899SCharles.Forsyth       }
480*37da2899SCharles.Forsyth       lo <<= 1;
481*37da2899SCharles.Forsyth     }
482*37da2899SCharles.Forsyth 
483*37da2899SCharles.Forsyth     return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
484*37da2899SCharles.Forsyth   }
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth #else /* 0 */
487*37da2899SCharles.Forsyth 
488*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Int32 )
FT_Div64by32(FT_Int64 * x,FT_Int32 y)489*37da2899SCharles.Forsyth   FT_Div64by32( FT_Int64*  x,
490*37da2899SCharles.Forsyth                 FT_Int32   y )
491*37da2899SCharles.Forsyth   {
492*37da2899SCharles.Forsyth     FT_Int32   s;
493*37da2899SCharles.Forsyth     FT_UInt32  q;
494*37da2899SCharles.Forsyth 
495*37da2899SCharles.Forsyth 
496*37da2899SCharles.Forsyth     s  = x->hi;
497*37da2899SCharles.Forsyth     if ( s < 0 )
498*37da2899SCharles.Forsyth     {
499*37da2899SCharles.Forsyth       x->lo = (FT_UInt32)-(FT_Int32)x->lo;
500*37da2899SCharles.Forsyth       x->hi = ~x->hi + !x->lo;
501*37da2899SCharles.Forsyth     }
502*37da2899SCharles.Forsyth     s ^= y;  y = ABS( y );
503*37da2899SCharles.Forsyth 
504*37da2899SCharles.Forsyth     /* Shortcut */
505*37da2899SCharles.Forsyth     if ( x->hi == 0 )
506*37da2899SCharles.Forsyth     {
507*37da2899SCharles.Forsyth       if ( y > 0 )
508*37da2899SCharles.Forsyth         q = ( x->lo + ( y >> 1 ) ) / y;
509*37da2899SCharles.Forsyth       else
510*37da2899SCharles.Forsyth         q = 0x7FFFFFFFL;
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth       return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
513*37da2899SCharles.Forsyth     }
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth     q = ft_div64by32( x->hi, x->lo, y );
516*37da2899SCharles.Forsyth 
517*37da2899SCharles.Forsyth     return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
518*37da2899SCharles.Forsyth   }
519*37da2899SCharles.Forsyth 
520*37da2899SCharles.Forsyth #endif /* 0 */
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth 
523*37da2899SCharles.Forsyth #endif /* FT_LONG64 */
524*37da2899SCharles.Forsyth 
525*37da2899SCharles.Forsyth 
526*37da2899SCharles.Forsyth   /* a not-so-fast but working 16.16 fixed point square root function */
527*37da2899SCharles.Forsyth 
528*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Int32 )
FT_SqrtFixed(FT_Int32 x)529*37da2899SCharles.Forsyth   FT_SqrtFixed( FT_Int32  x )
530*37da2899SCharles.Forsyth   {
531*37da2899SCharles.Forsyth     FT_UInt32  root, rem_hi, rem_lo, test_div;
532*37da2899SCharles.Forsyth     FT_Int     count;
533*37da2899SCharles.Forsyth 
534*37da2899SCharles.Forsyth 
535*37da2899SCharles.Forsyth     root = 0;
536*37da2899SCharles.Forsyth 
537*37da2899SCharles.Forsyth     if ( x > 0 )
538*37da2899SCharles.Forsyth     {
539*37da2899SCharles.Forsyth       rem_hi = 0;
540*37da2899SCharles.Forsyth       rem_lo = x;
541*37da2899SCharles.Forsyth       count  = 24;
542*37da2899SCharles.Forsyth       do
543*37da2899SCharles.Forsyth       {
544*37da2899SCharles.Forsyth         rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
545*37da2899SCharles.Forsyth         rem_lo <<= 2;
546*37da2899SCharles.Forsyth         root   <<= 1;
547*37da2899SCharles.Forsyth         test_div = ( root << 1 ) + 1;
548*37da2899SCharles.Forsyth 
549*37da2899SCharles.Forsyth         if ( rem_hi >= test_div )
550*37da2899SCharles.Forsyth         {
551*37da2899SCharles.Forsyth           rem_hi -= test_div;
552*37da2899SCharles.Forsyth           root   += 1;
553*37da2899SCharles.Forsyth         }
554*37da2899SCharles.Forsyth       } while ( --count );
555*37da2899SCharles.Forsyth     }
556*37da2899SCharles.Forsyth 
557*37da2899SCharles.Forsyth     return (FT_Int32)root;
558*37da2899SCharles.Forsyth   }
559*37da2899SCharles.Forsyth 
560*37da2899SCharles.Forsyth 
561*37da2899SCharles.Forsyth /* END */
562