1 /***************************************************************************/
5 /* Arithmetic computations (body). */
7 /* Copyright 1996-2001, 2002 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
18 /*************************************************************************/
20 /* Support for 1-complement arithmetic has been totally dropped in this */
21 /* release. You can still write your own code if you need it. */
23 /*************************************************************************/
25 /*************************************************************************/
27 /* Implementing basic computation routines. */
29 /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */
30 /* and FT_FloorFix() are declared in freetype.h. */
32 /*************************************************************************/
36 #include FT_INTERNAL_CALC_H
37 #include FT_INTERNAL_DEBUG_H
38 #include FT_INTERNAL_OBJECTS_H
41 /* we need to define a 64-bits data type here */
45 typedef FT_INT64 FT_Int64;
49 typedef struct FT_Int64_
56 #endif /* FT_LONG64 */
59 /*************************************************************************/
61 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
62 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
63 /* messages during execution. */
66 #define FT_COMPONENT trace_calc
69 /* The following three functions are available regardless of whether */
70 /* FT_LONG64 is defined. */
72 /* documentation is in freetype.h */
74 FT_EXPORT_DEF( FT_Fixed )
75 FT_RoundFix( FT_Fixed a )
77 return ( a >= 0 ) ? ( a + 0x8000L ) & -0x10000L
78 : -((-a + 0x8000L ) & -0x10000L );
82 /* documentation is in freetype.h */
84 FT_EXPORT_DEF( FT_Fixed )
85 FT_CeilFix( FT_Fixed a )
87 return ( a >= 0 ) ? ( a + 0xFFFFL ) & -0x10000L
88 : -((-a + 0xFFFFL ) & -0x10000L );
92 /* documentation is in freetype.h */
94 FT_EXPORT_DEF( FT_Fixed )
95 FT_FloorFix( FT_Fixed a )
97 return ( a >= 0 ) ? a & -0x10000L
98 : -((-a) & -0x10000L );
102 /* documentation is in ftcalc.h */
104 FT_EXPORT_DEF( FT_Int32 )
105 FT_Sqrt32( FT_Int32 x )
107 FT_ULong val, root, newroot, mask;
116 newroot = root + mask;
117 if ( newroot <= val )
120 root = newroot + mask;
126 } while ( mask != 0 );
135 /* documentation is in freetype.h */
137 FT_EXPORT_DEF( FT_Long )
138 FT_MulDiv( FT_Long a,
147 if ( a < 0 ) { a = -a; s = -1; }
148 if ( b < 0 ) { b = -b; s = -s; }
149 if ( c < 0 ) { c = -c; s = -s; }
151 d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
154 return ( s > 0 ) ? d : -d;
158 /* documentation is in freetype.h */
160 FT_EXPORT_DEF( FT_Long )
161 FT_MulFix( FT_Long a,
168 if ( a < 0 ) { a = -a; s = -1; }
169 if ( b < 0 ) { b = -b; s = -s; }
171 c = (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 );
172 return ( s > 0 ) ? c : -c ;
176 /* documentation is in freetype.h */
178 FT_EXPORT_DEF( FT_Long )
179 FT_DivFix( FT_Long a,
186 if ( a < 0 ) { a = -a; s = -1; }
187 if ( b < 0 ) { b = -b; s = -s; }
190 /* check for division by 0 */
193 /* compute result directly */
194 q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );
196 return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
200 #else /* FT_LONG64 */
204 ft_multo64( FT_UInt32 x,
208 FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
211 lo1 = x & 0x0000FFFFU; hi1 = x >> 16;
212 lo2 = y & 0x0000FFFFU; hi2 = y >> 16;
219 /* Check carry overflow of i1 + i2 */
221 hi += (FT_UInt32)( i1 < i2 ) << 16;
226 /* Check carry overflow of i1 + lo */
236 ft_div64by32( FT_UInt32 hi,
248 return (FT_UInt32)0x7FFFFFFFL;
257 if ( r >= (FT_UInt32)y )
269 /* documentation is in ftcalc.h */
271 FT_EXPORT_DEF( void )
272 FT_Add64( FT_Int64* x,
276 register FT_UInt32 lo, hi, max;
279 max = x->lo > y->lo ? x->lo : y->lo;
281 hi = x->hi + y->hi + ( lo < max );
288 /* documentation is in freetype.h */
290 FT_EXPORT_DEF( FT_Long )
291 FT_MulDiv( FT_Long a,
298 if ( a == 0 || b == c )
302 s ^= b; b = ABS( b );
303 s ^= c; c = ABS( c );
305 if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
307 a = ( a * b + ( c >> 1 ) ) / c;
311 FT_Int64 temp, temp2;
314 ft_multo64( a, b, &temp );
317 temp2.lo = (FT_UInt32)(c >> 1);
318 FT_Add64( &temp, &temp2, &temp );
319 a = ft_div64by32( temp.hi, temp.lo, c );
324 return ( s < 0 ? -a : a );
328 /* documentation is in freetype.h */
330 FT_EXPORT_DEF( FT_Long )
331 FT_MulFix( FT_Long a,
338 if ( a == 0 || b == 0x10000L )
347 if ( ua <= 2048 && ub <= 1048576L )
349 ua = ( ua * ub + 0x8000 ) >> 16;
353 FT_ULong al = ua & 0xFFFF;
356 ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
357 ( ( al * ( ub & 0xFFFF ) + 0x8000 ) >> 16 );
360 return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
364 /* documentation is in freetype.h */
366 FT_EXPORT_DEF( FT_Long )
367 FT_DivFix( FT_Long a,
379 /* check for division by 0 */
382 else if ( ( a >> 16 ) == 0 )
384 /* compute result directly */
385 q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b;
389 /* we need more bits; we have to do it by hand */
390 FT_Int64 temp, temp2;
392 temp.hi = (FT_Int32) (a >> 16);
393 temp.lo = (FT_UInt32)(a << 16);
395 temp2.lo = (FT_UInt32)( b >> 1 );
396 FT_Add64( &temp, &temp2, &temp );
397 q = ft_div64by32( temp.hi, temp.lo, b );
400 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
404 /* documentation is in ftcalc.h */
406 FT_EXPORT_DEF( void )
407 FT_MulTo64( FT_Int32 x,
415 s ^= y; y = ABS( y );
417 ft_multo64( x, y, z );
421 z->lo = (FT_UInt32)-(FT_Int32)z->lo;
422 z->hi = ~z->hi + !( z->lo );
427 /* documentation is in ftcalc.h */
429 /* apparently, the second version of this code is not compiled correctly */
430 /* on Mac machines with the MPW C compiler.. tsss, tsss, tss... */
434 FT_EXPORT_DEF( FT_Int32 )
435 FT_Div64by32( FT_Int64* x,
439 FT_UInt32 q, r, i, lo;
445 x->lo = (FT_UInt32)-(FT_Int32)x->lo;
446 x->hi = ~x->hi + !x->lo;
448 s ^= y; y = ABS( y );
458 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
464 if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
465 return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
466 /* Return Max/Min Int32 if division overflow. */
467 /* This includes division by zero! */
469 for ( i = 0; i < 32; i++ )
475 if ( r >= (FT_UInt32)y )
483 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
488 FT_EXPORT_DEF( FT_Int32 )
489 FT_Div64by32( FT_Int64* x,
499 x->lo = (FT_UInt32)-(FT_Int32)x->lo;
500 x->hi = ~x->hi + !x->lo;
502 s ^= y; y = ABS( y );
508 q = ( x->lo + ( y >> 1 ) ) / y;
512 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
515 q = ft_div64by32( x->hi, x->lo, y );
517 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
523 #endif /* FT_LONG64 */
526 /* a not-so-fast but working 16.16 fixed point square root function */
528 FT_EXPORT_DEF( FT_Int32 )
529 FT_SqrtFixed( FT_Int32 x )
531 FT_UInt32 root, rem_hi, rem_lo, test_div;
544 rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 );
547 test_div = ( root << 1 ) + 1;
549 if ( rem_hi >= test_div )
557 return (FT_Int32)root;