(no commit message)
authorlkcl <lkcl@web>
Mon, 8 Aug 2022 18:55:57 +0000 (19:55 +0100)
committerIkiWiki <ikiwiki.info>
Mon, 8 Aug 2022 18:55:57 +0000 (19:55 +0100)
openpower/transcendentals/discussion.mdwn

index b4c75abd4fc41d1dfdb87b21422783d07cc69c7c..7324801f0e143c7c18ce689e92f6cf6d53103142 100644 (file)
@@ -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 );
+    }
+}
+```