xref: /plan9-contrib/sys/src/cmd/gs/src/ttcalc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier /* Copyright (C) 2003 Aladdin Enterprises.  All rights reserved.
2*593dc095SDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
5*593dc095SDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
9*593dc095SDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15*593dc095SDavid du Colombier */
16*593dc095SDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: ttcalc.c,v 1.1 2003/10/01 13:44:56 igor Exp $ */
18*593dc095SDavid du Colombier 
19*593dc095SDavid du Colombier /* Changes after FreeType: cut out the TrueType instruction interpreter. */
20*593dc095SDavid du Colombier 
21*593dc095SDavid du Colombier /*******************************************************************
22*593dc095SDavid du Colombier  *
23*593dc095SDavid du Colombier  *  ttcalc.c
24*593dc095SDavid du Colombier  *
25*593dc095SDavid du Colombier  *    Arithmetic Computations (body).
26*593dc095SDavid du Colombier  *
27*593dc095SDavid du Colombier  *  Copyright 1996-1998 by
28*593dc095SDavid du Colombier  *  David Turner, Robert Wilhelm, and Werner Lemberg.
29*593dc095SDavid du Colombier  *
30*593dc095SDavid du Colombier  *  This file is part of the FreeType project, and may only be used
31*593dc095SDavid du Colombier  *  modified and distributed under the terms of the FreeType project
32*593dc095SDavid du Colombier  *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
33*593dc095SDavid du Colombier  *  this file you indicate that you have read the license and
34*593dc095SDavid du Colombier  *  understand and accept it fully.
35*593dc095SDavid du Colombier  *
36*593dc095SDavid du Colombier  ******************************************************************/
37*593dc095SDavid du Colombier 
38*593dc095SDavid du Colombier #include "ttmisc.h"
39*593dc095SDavid du Colombier 
40*593dc095SDavid du Colombier #include "ttcalc.h"
41*593dc095SDavid du Colombier 
42*593dc095SDavid du Colombier /* support for 1-complement arithmetic has been totally dropped in this */
43*593dc095SDavid du Colombier /* release. You can still write your own code if you need it..          */
44*593dc095SDavid du Colombier 
45*593dc095SDavid du Colombier   static const long  Roots[63] =
46*593dc095SDavid du Colombier   {
47*593dc095SDavid du Colombier        1,    1,    2,     3,     4,     5,     8,    11,
48*593dc095SDavid du Colombier       16,   22,   32,    45,    64,    90,   128,   181,
49*593dc095SDavid du Colombier      256,  362,  512,   724,  1024,  1448,  2048,  2896,
50*593dc095SDavid du Colombier     4096, 5892, 8192, 11585, 16384, 23170, 32768, 46340,
51*593dc095SDavid du Colombier 
52*593dc095SDavid du Colombier       65536,   92681,  131072,   185363,   262144,   370727,
53*593dc095SDavid du Colombier      524288,  741455, 1048576,  1482910,  2097152,  2965820,
54*593dc095SDavid du Colombier     4194304, 5931641, 8388608, 11863283, 16777216, 23726566,
55*593dc095SDavid du Colombier 
56*593dc095SDavid du Colombier       33554432,   47453132,   67108864,   94906265,
57*593dc095SDavid du Colombier      134217728,  189812531,  268435456,  379625062,
58*593dc095SDavid du Colombier      536870912,  759250125, 1073741824, 1518500250,
59*593dc095SDavid du Colombier     2147483647
60*593dc095SDavid du Colombier   };
61*593dc095SDavid du Colombier 
62*593dc095SDavid du Colombier 
63*593dc095SDavid du Colombier #ifdef LONG64
64*593dc095SDavid du Colombier 
MulDiv(Int32 a,Int32 b,Int32 c)65*593dc095SDavid du Colombier   Int32  MulDiv( Int32  a, Int32  b, Int32  c )
66*593dc095SDavid du Colombier   {
67*593dc095SDavid du Colombier     Int32  s;
68*593dc095SDavid du Colombier 
69*593dc095SDavid du Colombier     s  = a; a = ABS(a);
70*593dc095SDavid du Colombier     s ^= b; b = ABS(b);
71*593dc095SDavid du Colombier     s ^= c; c = ABS(c);
72*593dc095SDavid du Colombier 
73*593dc095SDavid du Colombier     a = (Int64)a * b / c;
74*593dc095SDavid du Colombier     return ((s < 0) ? -a : a);
75*593dc095SDavid du Colombier   }
76*593dc095SDavid du Colombier 
77*593dc095SDavid du Colombier 
MulDiv_Round(Int32 a,Int32 b,Int32 c)78*593dc095SDavid du Colombier   Int32  MulDiv_Round( Int32  a, Int32  b, Int32  c )
79*593dc095SDavid du Colombier   {
80*593dc095SDavid du Colombier     int  s;
81*593dc095SDavid du Colombier 
82*593dc095SDavid du Colombier     s  = a; a = ABS(a);
83*593dc095SDavid du Colombier     s ^= b; b = ABS(b);
84*593dc095SDavid du Colombier     s ^= c; c = ABS(c);
85*593dc095SDavid du Colombier 
86*593dc095SDavid du Colombier     a = ((Int64)a * b + c/2) / c;
87*593dc095SDavid du Colombier     return ((s < 0) ? -a : a);
88*593dc095SDavid du Colombier   }
89*593dc095SDavid du Colombier 
90*593dc095SDavid du Colombier 
Order64(Int64 z)91*593dc095SDavid du Colombier   Int  Order64( Int64  z )
92*593dc095SDavid du Colombier   {
93*593dc095SDavid du Colombier     int  j = 0;
94*593dc095SDavid du Colombier     while ( z )
95*593dc095SDavid du Colombier     {
96*593dc095SDavid du Colombier       z = (unsigned INT64)z >> 1;
97*593dc095SDavid du Colombier       j++;
98*593dc095SDavid du Colombier     }
99*593dc095SDavid du Colombier     return j - 1;
100*593dc095SDavid du Colombier   }
101*593dc095SDavid du Colombier 
102*593dc095SDavid du Colombier 
Sqrt64(Int64 l)103*593dc095SDavid du Colombier   Int32  Sqrt64( Int64  l )
104*593dc095SDavid du Colombier   {
105*593dc095SDavid du Colombier     Int64  r, s;
106*593dc095SDavid du Colombier 
107*593dc095SDavid du Colombier     if ( l <= 0 ) return 0;
108*593dc095SDavid du Colombier     if ( l == 1 ) return 1;
109*593dc095SDavid du Colombier 
110*593dc095SDavid du Colombier     r = Roots[Order64( l )];
111*593dc095SDavid du Colombier 
112*593dc095SDavid du Colombier     do
113*593dc095SDavid du Colombier     {
114*593dc095SDavid du Colombier       s = r;
115*593dc095SDavid du Colombier       r = ( r + l/r ) >> 1;
116*593dc095SDavid du Colombier     }
117*593dc095SDavid du Colombier     while ( r > s || r*r > l );
118*593dc095SDavid du Colombier 
119*593dc095SDavid du Colombier     return r;
120*593dc095SDavid du Colombier   }
121*593dc095SDavid du Colombier 
122*593dc095SDavid du Colombier #else /* LONG64 */
123*593dc095SDavid du Colombier 
MulDiv(Int32 a,Int32 b,Int32 c)124*593dc095SDavid du Colombier   Int32  MulDiv( Int32  a, Int32  b, Int32  c )
125*593dc095SDavid du Colombier   {
126*593dc095SDavid du Colombier     Int64  temp;
127*593dc095SDavid du Colombier     Int32  s;
128*593dc095SDavid du Colombier 
129*593dc095SDavid du Colombier     s  = a; a = ABS(a);
130*593dc095SDavid du Colombier     s ^= b; b = ABS(b);
131*593dc095SDavid du Colombier     s ^= c; c = ABS(c);
132*593dc095SDavid du Colombier 
133*593dc095SDavid du Colombier     MulTo64( a, b, &temp );
134*593dc095SDavid du Colombier     a = Div64by32( &temp, c );
135*593dc095SDavid du Colombier 
136*593dc095SDavid du Colombier     return ((s < 0) ? -a : a);
137*593dc095SDavid du Colombier   }
138*593dc095SDavid du Colombier 
139*593dc095SDavid du Colombier 
MulDiv_Round(Int32 a,Int32 b,Int32 c)140*593dc095SDavid du Colombier   Int32  MulDiv_Round( Int32  a, Int32  b, Int32  c )
141*593dc095SDavid du Colombier   {
142*593dc095SDavid du Colombier     Int64  temp, temp2;
143*593dc095SDavid du Colombier     Int32  s;
144*593dc095SDavid du Colombier 
145*593dc095SDavid du Colombier     s  = a; a = ABS(a);
146*593dc095SDavid du Colombier     s ^= b; b = ABS(b);
147*593dc095SDavid du Colombier     s ^= c; c = ABS(c);
148*593dc095SDavid du Colombier 
149*593dc095SDavid du Colombier     MulTo64( a, b, &temp );
150*593dc095SDavid du Colombier     temp2.hi = (Int32)(c >> 31);
151*593dc095SDavid du Colombier     temp2.lo = (Word32)(c / 2);
152*593dc095SDavid du Colombier     Add64( &temp, &temp2, &temp );
153*593dc095SDavid du Colombier     a = Div64by32( &temp, c );
154*593dc095SDavid du Colombier 
155*593dc095SDavid du Colombier     return ((s < 0) ? -a : a);
156*593dc095SDavid du Colombier   }
157*593dc095SDavid du Colombier 
158*593dc095SDavid du Colombier 
Neg64__(Int64 * x)159*593dc095SDavid du Colombier   static void  Neg64__( Int64*  x )
160*593dc095SDavid du Colombier   {
161*593dc095SDavid du Colombier     /* Remember that -(0x80000000) == 0x80000000 with 2-complement! */
162*593dc095SDavid du Colombier     /* We take care of that here.                                   */
163*593dc095SDavid du Colombier 
164*593dc095SDavid du Colombier     x->hi ^= 0xFFFFFFFF;
165*593dc095SDavid du Colombier     x->lo ^= 0xFFFFFFFF;
166*593dc095SDavid du Colombier     x->lo++;
167*593dc095SDavid du Colombier 
168*593dc095SDavid du Colombier     if ( !x->lo )
169*593dc095SDavid du Colombier     {
170*593dc095SDavid du Colombier       x->hi++;
171*593dc095SDavid du Colombier       if ( (Int32)x->hi == 0x80000000 )  /* Check -MaxInt32 - 1 */
172*593dc095SDavid du Colombier       {
173*593dc095SDavid du Colombier         x->lo--;
174*593dc095SDavid du Colombier         x->hi--;  /* We return 0x7FFFFFFF! */
175*593dc095SDavid du Colombier       }
176*593dc095SDavid du Colombier     }
177*593dc095SDavid du Colombier   }
178*593dc095SDavid du Colombier 
179*593dc095SDavid du Colombier 
Add64(Int64 * x,Int64 * y,Int64 * z)180*593dc095SDavid du Colombier   void  Add64( Int64*  x, Int64*  y, Int64*  z )
181*593dc095SDavid du Colombier   {
182*593dc095SDavid du Colombier     register Word32  lo, hi;
183*593dc095SDavid du Colombier 
184*593dc095SDavid du Colombier     hi = x->hi + y->hi;
185*593dc095SDavid du Colombier     lo = x->lo + y->lo;
186*593dc095SDavid du Colombier 
187*593dc095SDavid du Colombier     if ( y->lo )
188*593dc095SDavid du Colombier       if ( (Word32)x->lo >= (Word32)(-y->lo) ) hi++;
189*593dc095SDavid du Colombier 
190*593dc095SDavid du Colombier     z->lo = lo;
191*593dc095SDavid du Colombier     z->hi = hi;
192*593dc095SDavid du Colombier   }
193*593dc095SDavid du Colombier 
194*593dc095SDavid du Colombier 
Sub64(Int64 * x,Int64 * y,Int64 * z)195*593dc095SDavid du Colombier   void  Sub64( Int64*  x, Int64*  y, Int64*  z )
196*593dc095SDavid du Colombier   {
197*593dc095SDavid du Colombier     register Word32  lo, hi;
198*593dc095SDavid du Colombier 
199*593dc095SDavid du Colombier     hi = x->hi - y->hi;
200*593dc095SDavid du Colombier     lo = x->lo - y->lo;
201*593dc095SDavid du Colombier 
202*593dc095SDavid du Colombier     if ( x->lo < y->lo ) hi--;
203*593dc095SDavid du Colombier 
204*593dc095SDavid du Colombier     z->lo = lo;
205*593dc095SDavid du Colombier     z->hi = hi;
206*593dc095SDavid du Colombier   }
207*593dc095SDavid du Colombier 
208*593dc095SDavid du Colombier 
MulTo64(Int32 x,Int32 y,Int64 * z)209*593dc095SDavid du Colombier   void  MulTo64( Int32  x, Int32  y, Int64*  z )
210*593dc095SDavid du Colombier   {
211*593dc095SDavid du Colombier     Int32   s;
212*593dc095SDavid du Colombier     Word32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;
213*593dc095SDavid du Colombier 
214*593dc095SDavid du Colombier     s  = x; x = ABS(x);
215*593dc095SDavid du Colombier     s ^= y; y = ABS(y);
216*593dc095SDavid du Colombier 
217*593dc095SDavid du Colombier     lo1 = x & 0x0000FFFF;  hi1 = x >> 16;
218*593dc095SDavid du Colombier     lo2 = y & 0x0000FFFF;  hi2 = y >> 16;
219*593dc095SDavid du Colombier 
220*593dc095SDavid du Colombier     lo = lo1*lo2;
221*593dc095SDavid du Colombier     i1 = lo1*hi2;
222*593dc095SDavid du Colombier     i2 = lo2*hi1;
223*593dc095SDavid du Colombier     hi = hi1*hi2;
224*593dc095SDavid du Colombier 
225*593dc095SDavid du Colombier     /* Check carry overflow of i1 + i2 */
226*593dc095SDavid du Colombier 
227*593dc095SDavid du Colombier     if ( i2 )
228*593dc095SDavid du Colombier     {
229*593dc095SDavid du Colombier       if ( i1 >= (Word32)-i2 ) hi += 1 << 16;
230*593dc095SDavid du Colombier       i1 += i2;
231*593dc095SDavid du Colombier     }
232*593dc095SDavid du Colombier 
233*593dc095SDavid du Colombier     i2 = i1 >> 16;
234*593dc095SDavid du Colombier     i1 = i1 << 16;
235*593dc095SDavid du Colombier 
236*593dc095SDavid du Colombier     /* Check carry overflow of i1 + lo */
237*593dc095SDavid du Colombier     if ( i1 )
238*593dc095SDavid du Colombier     {
239*593dc095SDavid du Colombier       if ( lo >= (Word32)-i1 ) hi++;
240*593dc095SDavid du Colombier       lo += i1;
241*593dc095SDavid du Colombier     }
242*593dc095SDavid du Colombier 
243*593dc095SDavid du Colombier     hi += i2;
244*593dc095SDavid du Colombier 
245*593dc095SDavid du Colombier     z->lo = lo;
246*593dc095SDavid du Colombier     z->hi = hi;
247*593dc095SDavid du Colombier 
248*593dc095SDavid du Colombier     if (s < 0) Neg64__( z );
249*593dc095SDavid du Colombier   }
250*593dc095SDavid du Colombier 
251*593dc095SDavid du Colombier 
Div64by32(Int64 * x,Int32 y)252*593dc095SDavid du Colombier   Int32  Div64by32( Int64*  x, Int32  y )
253*593dc095SDavid du Colombier   {
254*593dc095SDavid du Colombier     Int32   s;
255*593dc095SDavid du Colombier     Word32  q, r, i, lo;
256*593dc095SDavid du Colombier 
257*593dc095SDavid du Colombier     s  = x->hi; if (s<0) Neg64__(x);
258*593dc095SDavid du Colombier     s ^= y;     y = ABS(y);
259*593dc095SDavid du Colombier 
260*593dc095SDavid du Colombier     /* Shortcut */
261*593dc095SDavid du Colombier     if ( x->hi == 0 )
262*593dc095SDavid du Colombier     {
263*593dc095SDavid du Colombier       q = x->lo / y;
264*593dc095SDavid du Colombier       return ((s<0) ? -q : q);
265*593dc095SDavid du Colombier     }
266*593dc095SDavid du Colombier 
267*593dc095SDavid du Colombier     r  = x->hi;
268*593dc095SDavid du Colombier     lo = x->lo;
269*593dc095SDavid du Colombier 
270*593dc095SDavid du Colombier     if ( r >= (Word32)y )   /* we know y is to be treated as unsigned here */
271*593dc095SDavid du Colombier       return ( (s<0) ? 0x80000001 : 0x7FFFFFFF );
272*593dc095SDavid du Colombier                             /* Return Max/Min Int32 if divide overflow */
273*593dc095SDavid du Colombier                             /* This includes division by zero!         */
274*593dc095SDavid du Colombier     q = 0;
275*593dc095SDavid du Colombier     for ( i = 0; i < 32; i++ )
276*593dc095SDavid du Colombier     {
277*593dc095SDavid du Colombier       r <<= 1;
278*593dc095SDavid du Colombier       q <<= 1;
279*593dc095SDavid du Colombier       r  |= lo >> 31;
280*593dc095SDavid du Colombier 
281*593dc095SDavid du Colombier       if ( r >= (Word32)y )
282*593dc095SDavid du Colombier       {
283*593dc095SDavid du Colombier         r -= y;
284*593dc095SDavid du Colombier         q |= 1;
285*593dc095SDavid du Colombier       }
286*593dc095SDavid du Colombier       lo <<= 1;
287*593dc095SDavid du Colombier     }
288*593dc095SDavid du Colombier 
289*593dc095SDavid du Colombier     return ( (s<0) ? -q : q );
290*593dc095SDavid du Colombier   }
291*593dc095SDavid du Colombier 
292*593dc095SDavid du Colombier 
Order64(Int64 * z)293*593dc095SDavid du Colombier   Int  Order64( Int64*  z )
294*593dc095SDavid du Colombier   {
295*593dc095SDavid du Colombier     Word32  i;
296*593dc095SDavid du Colombier     int     j;
297*593dc095SDavid du Colombier 
298*593dc095SDavid du Colombier     if ( z->hi )
299*593dc095SDavid du Colombier     {
300*593dc095SDavid du Colombier       i = z->hi;
301*593dc095SDavid du Colombier       j = 32;
302*593dc095SDavid du Colombier     }
303*593dc095SDavid du Colombier     else
304*593dc095SDavid du Colombier     {
305*593dc095SDavid du Colombier       i = z->lo;
306*593dc095SDavid du Colombier       j = 0;
307*593dc095SDavid du Colombier     }
308*593dc095SDavid du Colombier 
309*593dc095SDavid du Colombier     while ( i > 0 )
310*593dc095SDavid du Colombier     {
311*593dc095SDavid du Colombier       i >>= 1;
312*593dc095SDavid du Colombier       j++;
313*593dc095SDavid du Colombier     }
314*593dc095SDavid du Colombier     return j-1;
315*593dc095SDavid du Colombier   }
316*593dc095SDavid du Colombier 
317*593dc095SDavid du Colombier 
Sqrt64(Int64 * l)318*593dc095SDavid du Colombier   Int32  Sqrt64( Int64*  l )
319*593dc095SDavid du Colombier   {
320*593dc095SDavid du Colombier     Int64  l2;
321*593dc095SDavid du Colombier     Int32  r, s;
322*593dc095SDavid du Colombier 
323*593dc095SDavid du Colombier     if ( (Int32)l->hi < 0          ||
324*593dc095SDavid du Colombier         (l->hi == 0 && l->lo == 0) )  return 0;
325*593dc095SDavid du Colombier 
326*593dc095SDavid du Colombier     s = Order64( l );
327*593dc095SDavid du Colombier     if ( s == 0 ) return 1;
328*593dc095SDavid du Colombier 
329*593dc095SDavid du Colombier     r = Roots[s];
330*593dc095SDavid du Colombier     do
331*593dc095SDavid du Colombier     {
332*593dc095SDavid du Colombier       s = r;
333*593dc095SDavid du Colombier       r = ( r + Div64by32(l,r) ) >> 1;
334*593dc095SDavid du Colombier       MulTo64( r, r,   &l2 );
335*593dc095SDavid du Colombier       Sub64  ( l, &l2, &l2 );
336*593dc095SDavid du Colombier     }
337*593dc095SDavid du Colombier     while ( r > s || (Int32)l2.hi < 0 );
338*593dc095SDavid du Colombier 
339*593dc095SDavid du Colombier     return r;
340*593dc095SDavid du Colombier   }
341*593dc095SDavid du Colombier 
342*593dc095SDavid du Colombier #endif /* LONG64 */
343*593dc095SDavid du Colombier 
344*593dc095SDavid du Colombier #if 0  /* unused by the rest of the library */
345*593dc095SDavid du Colombier 
346*593dc095SDavid du Colombier   Int  Order32( Int32  z )
347*593dc095SDavid du Colombier   {
348*593dc095SDavid du Colombier     int j;
349*593dc095SDavid du Colombier 
350*593dc095SDavid du Colombier     j = 0;
351*593dc095SDavid du Colombier     while ( z )
352*593dc095SDavid du Colombier     {
353*593dc095SDavid du Colombier       z = (Word32)z >> 1;
354*593dc095SDavid du Colombier       j++;
355*593dc095SDavid du Colombier     }
356*593dc095SDavid du Colombier     return j - 1;
357*593dc095SDavid du Colombier   }
358*593dc095SDavid du Colombier 
359*593dc095SDavid du Colombier 
360*593dc095SDavid du Colombier   Int32  Sqrt32( Int32  l )
361*593dc095SDavid du Colombier   {
362*593dc095SDavid du Colombier     Int32  r, s;
363*593dc095SDavid du Colombier 
364*593dc095SDavid du Colombier     if ( l <= 0 ) return 0;
365*593dc095SDavid du Colombier     if ( l == 1 ) return 1;
366*593dc095SDavid du Colombier 
367*593dc095SDavid du Colombier     r = Roots[Order32( l )];
368*593dc095SDavid du Colombier     do
369*593dc095SDavid du Colombier     {
370*593dc095SDavid du Colombier       s = r;
371*593dc095SDavid du Colombier       r = ( r + l/r ) >> 1;
372*593dc095SDavid du Colombier     }
373*593dc095SDavid du Colombier     while ( r > s || r*r > l );
374*593dc095SDavid du Colombier     return r;
375*593dc095SDavid du Colombier   }
376*593dc095SDavid du Colombier 
377*593dc095SDavid du Colombier #endif
378*593dc095SDavid du Colombier 
379*593dc095SDavid du Colombier /* END */
380