2005-04-17 02:20:36 +04:00
/*
fp_trig . c : floating - point math routines for the Linux - m68k
floating point emulator .
Copyright ( c ) 1998 - 1999 David Huggins - Daines / Roman Zippel .
I hereby give permission , free of charge , to copy , modify , and
redistribute this software , in source or binary form , provided that
the above copyright notice and the following disclaimer are included
in all such copies .
THIS SOFTWARE IS PROVIDED " AS IS " , WITH ABSOLUTELY NO WARRANTY , REAL
OR IMPLIED .
*/
# include "fp_emu.h"
static const struct fp_ext fp_one =
{
. exp = 0x3fff ,
} ;
extern struct fp_ext * fp_fadd ( struct fp_ext * dest , const struct fp_ext * src ) ;
extern struct fp_ext * fp_fdiv ( struct fp_ext * dest , const struct fp_ext * src ) ;
struct fp_ext *
fp_fsqrt ( struct fp_ext * dest , struct fp_ext * src )
{
struct fp_ext tmp , src2 ;
int i , exp ;
dprint ( PINSTR , " fsqrt \n " ) ;
fp_monadic_check ( dest , src ) ;
if ( IS_ZERO ( dest ) )
return dest ;
if ( dest - > sign ) {
fp_set_nan ( dest ) ;
return dest ;
}
if ( IS_INF ( dest ) )
return dest ;
/*
* sqrt ( m ) * 2 ^ ( p ) , if e = 2 * p
* sqrt ( m * 2 ^ e ) =
* sqrt ( 2 * m ) * 2 ^ ( p ) , if e = 2 * p + 1
*
* So we use the last bit of the exponent to decide wether to
* use the m or 2 * m .
*
* Since only the fractional part of the mantissa is stored and
* the integer part is assumed to be one , we place a 1 or 2 into
* the fixed point representation .
*/
exp = dest - > exp ;
dest - > exp = 0x3FFF ;
if ( ! ( exp & 1 ) ) /* lowest bit of exponent is set */
dest - > exp + + ;
fp_copy_ext ( & src2 , dest ) ;
/*
2007-10-20 03:20:32 +04:00
* The taylor row around a for sqrt ( x ) is :
2005-04-17 02:20:36 +04:00
* sqrt ( x ) = sqrt ( a ) + 1 / ( 2 * sqrt ( a ) ) * ( x - a ) + R
* With a = 1 this gives :
* sqrt ( x ) = 1 + 1 / 2 * ( x - 1 )
* = 1 / 2 * ( 1 + x )
*/
fp_fadd ( dest , & fp_one ) ;
dest - > exp - - ; /* * 1/2 */
/*
* We now apply the newton rule to the function
* f ( x ) : = x ^ 2 - r
* which has a null point on x = sqrt ( r ) .
*
* It gives :
* x ' : = x - f ( x ) / f ' ( x )
* = x - ( x ^ 2 - r ) / ( 2 * x )
* = x - ( x - r / x ) / 2
* = ( 2 * x - x + r / x ) / 2
* = ( x + r / x ) / 2
*/
for ( i = 0 ; i < 9 ; i + + ) {
fp_copy_ext ( & tmp , & src2 ) ;
fp_fdiv ( & tmp , dest ) ;
fp_fadd ( dest , & tmp ) ;
dest - > exp - - ;
}
dest - > exp + = ( exp - 0x3FFF ) / 2 ;
return dest ;
}
struct fp_ext *
fp_fetoxm1 ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " fetoxm1 \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_fetox ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " fetox \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_ftwotox ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " ftwotox \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_ftentox ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " ftentox \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_flogn ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " flogn \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_flognp1 ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " flognp1 \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_flog10 ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " flog10 \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_flog2 ( struct fp_ext * dest , struct fp_ext * src )
{
uprint ( " flog2 \n " ) ;
fp_monadic_check ( dest , src ) ;
return dest ;
}
struct fp_ext *
fp_fgetexp ( struct fp_ext * dest , struct fp_ext * src )
{
dprint ( PINSTR , " fgetexp \n " ) ;
fp_monadic_check ( dest , src ) ;
if ( IS_INF ( dest ) ) {
fp_set_nan ( dest ) ;
return dest ;
}
if ( IS_ZERO ( dest ) )
return dest ;
fp_conv_long2ext ( dest , ( int ) dest - > exp - 0x3FFF ) ;
fp_normalize_ext ( dest ) ;
return dest ;
}
struct fp_ext *
fp_fgetman ( struct fp_ext * dest , struct fp_ext * src )
{
dprint ( PINSTR , " fgetman \n " ) ;
fp_monadic_check ( dest , src ) ;
if ( IS_ZERO ( dest ) )
return dest ;
if ( IS_INF ( dest ) )
return dest ;
dest - > exp = 0x3FFF ;
return dest ;
}