38#define FT_TRIG_SCALE 0xDBD95B16UL
42#define FT_TRIG_SAFE_MSB 29
45#define FT_TRIG_MAX_ITERS 23
48 ft_trig_arctan_table[] =
50 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
51 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
52 57L, 29L, 14L, 7L, 4L, 2L, 1L
60 ft_trig_downscale( FT_Fixed val )
74 ( (FT_UInt64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 );
76 return s < 0 ? -val : val;
83 ft_trig_downscale( FT_Fixed val )
86 FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
95 lo1 = (FT_UInt32)val & 0x0000FFFFU;
96 hi1 = (FT_UInt32)val >> 16;
97 lo2 = FT_TRIG_SCALE & 0x0000FFFFU;
98 hi2 = FT_TRIG_SCALE >> 16;
107 hi += (FT_UInt32)( i1 < i2 ) << 16;
121 hi += ( lo < 0x40000000UL );
125 return s < 0 ? -val : val;
133 ft_trig_prenorm( FT_Vector* vec )
142 shift = FT_MSB( (FT_UInt32)( FT_ABS( x ) | FT_ABS( y ) ) );
144 if ( shift <= FT_TRIG_SAFE_MSB )
146 shift = FT_TRIG_SAFE_MSB - shift;
147 vec->x = (FT_Pos)( (FT_ULong)x << shift );
148 vec->y = (FT_Pos)( (FT_ULong)y << shift );
152 shift -= FT_TRIG_SAFE_MSB;
163 ft_trig_pseudo_rotate( FT_Vector* vec,
167 FT_Fixed x, y, xtemp, b;
168 const FT_Angle *arctanptr;
175 while ( theta < -FT_ANGLE_PI4 )
180 theta += FT_ANGLE_PI2;
183 while ( theta > FT_ANGLE_PI4 )
188 theta -= FT_ANGLE_PI2;
191 arctanptr = ft_trig_arctan_table;
194 for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
198 xtemp = x + ( ( y + b ) >> i );
199 y = y - ( ( x + b ) >> i );
201 theta += *arctanptr++;
205 xtemp = x - ( ( y + b ) >> i );
206 y = y + ( ( x + b ) >> i );
208 theta -= *arctanptr++;
218 ft_trig_pseudo_polarize( FT_Vector* vec )
222 FT_Fixed x, y, xtemp, b;
223 const FT_Angle *arctanptr;
234 theta = FT_ANGLE_PI2;
241 theta = y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI;
250 theta = -FT_ANGLE_PI2;
261 arctanptr = ft_trig_arctan_table;
264 for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
268 xtemp = x + ( ( y + b ) >> i );
269 y = y - ( ( x + b ) >> i );
271 theta += *arctanptr++;
275 xtemp = x - ( ( y + b ) >> i );
276 y = y + ( ( x + b ) >> i );
278 theta -= *arctanptr++;
285 theta = FT_PAD_ROUND( theta, 16 );
287 theta = -FT_PAD_ROUND( -theta, 16 );
296 FT_EXPORT_DEF( FT_Fixed )
297 FT_Cos( FT_Angle angle )
302 FT_Vector_Unit( &v, angle );
310 FT_EXPORT_DEF( FT_Fixed )
311 FT_Sin( FT_Angle angle )
316 FT_Vector_Unit( &v, angle );
324 FT_EXPORT_DEF( FT_Fixed )
325 FT_Tan( FT_Angle angle )
327 FT_Vector v = { 1 << 24, 0 };
330 ft_trig_pseudo_rotate( &v, angle );
332 return FT_DivFix( v.y, v.x );
338 FT_EXPORT_DEF( FT_Angle )
339 FT_Atan2( FT_Fixed dx,
345 if ( dx == 0 && dy == 0 )
350 ft_trig_prenorm( &v );
351 ft_trig_pseudo_polarize( &v );
359 FT_EXPORT_DEF(
void )
360 FT_Vector_Unit( FT_Vector* vec,
366 vec->x = FT_TRIG_SCALE >> 8;
368 ft_trig_pseudo_rotate( vec, angle );
369 vec->x = ( vec->x + 0x80L ) >> 8;
370 vec->y = ( vec->y + 0x80L ) >> 8;
376 FT_EXPORT_DEF(
void )
377 FT_Vector_Rotate( FT_Vector* vec,
384 if ( !vec || !angle )
389 if ( v.x == 0 && v.y == 0 )
392 shift = ft_trig_prenorm( &v );
393 ft_trig_pseudo_rotate( &v, angle );
394 v.x = ft_trig_downscale( v.x );
395 v.y = ft_trig_downscale( v.y );
399 FT_Int32 half = (FT_Int32)1L << ( shift - 1 );
402 vec->x = ( v.x + half - ( v.x < 0 ) ) >> shift;
403 vec->y = ( v.y + half - ( v.y < 0 ) ) >> shift;
408 vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
409 vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
416 FT_EXPORT_DEF( FT_Fixed )
417 FT_Vector_Length( FT_Vector* vec )
431 return FT_ABS( v.y );
435 return FT_ABS( v.x );
439 shift = ft_trig_prenorm( &v );
440 ft_trig_pseudo_polarize( &v );
442 v.x = ft_trig_downscale( v.x );
445 return ( v.x + ( 1L << ( shift - 1 ) ) ) >> shift;
447 return (FT_Fixed)( (FT_UInt32)v.x << -shift );
453 FT_EXPORT_DEF(
void )
454 FT_Vector_Polarize( FT_Vector* vec,
462 if ( !vec || !length || !angle )
467 if ( v.x == 0 && v.y == 0 )
470 shift = ft_trig_prenorm( &v );
471 ft_trig_pseudo_polarize( &v );
473 v.x = ft_trig_downscale( v.x );
475 *length = shift >= 0 ? ( v.x >> shift )
476 : (FT_Fixed)( (FT_UInt32)v.x << -shift );
483 FT_EXPORT_DEF(
void )
484 FT_Vector_From_Polar( FT_Vector* vec,
494 FT_Vector_Rotate( vec, angle );
500 FT_EXPORT_DEF( FT_Angle )
501 FT_Angle_Diff( FT_Angle angle1,
504 FT_Angle delta = angle2 - angle1;
507 while ( delta <= -FT_ANGLE_PI )
508 delta += FT_ANGLE_2PI;
510 while ( delta > FT_ANGLE_PI )
511 delta -= FT_ANGLE_2PI;