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