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