From: lkcl Date: Mon, 8 Aug 2022 18:55:57 +0000 (+0100) Subject: (no commit message) X-Git-Tag: opf_rfc_ls005_v1~896 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9c3bda50f561d578b997c410c5a580445e611148;p=libreriscv.git --- diff --git a/openpower/transcendentals/discussion.mdwn b/openpower/transcendentals/discussion.mdwn index b4c75abd4..7324801f0 100644 --- a/openpower/transcendentals/discussion.mdwn +++ b/openpower/transcendentals/discussion.mdwn @@ -168,3 +168,40 @@ And GPUs have been doing this almost since the dawn of 3D. This way the adds and subtracts from the constant are not in a precision precarious position. + +``` +double ATAN2( double y, double x ) +{ // IEEE 754-2008 quality ATAN2 + // deal with NaNs + if( ISNAN( x ) ) return x; + if( ISNAN( y ) ) return y; + // deal with infinities + if( x == +∞ && |y|== +∞ ) return copysign( π/4, y ); + if( x == +∞ ) return copysign( 0.0, y ); + if( x == -∞ && |y|== +∞ ) return copysign( 3π/4, y ); + if( x == -∞ ) return copysign( π, y ); + if( |y|== +∞ ) return copysign( π/2, y ); + // deal with signed zeros + if( x == 0.0 && y != 0.0 ) return copysign( π/2, y ); + if( x >=+0.0 && y == 0.0 ) return copysign( 0.0, y ); + if( x <=-0.0 && y == 0.0 ) return copysign( π, y ); + // + // calculate ATAN2 high performance style + // Note: at this point x != y + // + if( x > 0.0 ) + { + if( y < 0.0 && |y| < |x| ) return - π/2 - ATAN( x / y ); + if( y < 0.0 && |y| > |x| ) return + ATAN( y / x ); + if( y > 0.0 && |y| < |x| ) return + ATAN( y / x ); + if( y > 0.0 && |y| > |x| ) return + π/2 - ATAN( x / y ); + } + if( x < 0.0 ) + { + if( y < 0.0 && |y| < |x| ) return + π/2 + ATAN( x / y ); + if( y < 0.0 && |y| > |x| ) return + π - ATAN( y / x ); + if( y > 0.0 && |y| < |x| ) return + π - ATAN( y / x ); + if( y > 0.0 && |y| > |x| ) return +3π/2 + ATAN( x / y ); + } +} +```