# [libre-riscv-dev] [isa-dev] Re: FP transcendentals (trigonometry, root/exp/log) proposal

MitchAlsup MitchAlsup at aol.com
Tue Aug 13 16:40:38 BST 2019

```
On Monday, August 12, 2019 at 10:00:59 PM UTC-5, Jacob Lifshay wrote:
>
> On Mon, Aug 12, 2019 at 10:52 AM 'MitchAlsup' via RISC-V ISA Dev
> <isa... at groups.riscv.org <javascript:>> wrote:
> > 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 textbook style
> >
> >     if( x  > 0.0               ) return     ATAN( |y / x| );
> >
> >     if( x  < 0.0               ) return π - ATAN( |y / x| );
> >
> > }
> >
> >
> > Yet the proposed encoding makes ATAN2 the primitive and has ATAN invent
> a constant and then call/use ATAN2.
> >
> > When one considers an implementation of ATAN, one must consider several
> ranges of evaluation::
> >
> >      x Î [  -∞, -1.0]:: ATAN( x ) = -π/2 + ATAN( 1/x );
> >
> >      x Î (-1.0, +1.0]:: ATAN( x ) =      + ATAN(   x );
> >
> >      x Î [ 1.0,   +∞]:: ATAN( x ) = +π/2 - ATAN( 1/x );
>
> Notice how the ATAN implementation has a division before the
> polynomial (or whatever implements the function in (-1.0, +1.0] ),
> that division can be merged with the ATAN2 division to end up with
> ATAN2 taking the same time as ATAN (assuming all the special cases can
> be handled in parallel to the division). For the case of ATAN2(1.0, x)
> with -1.0 < x <= +1.0, the division can be skipped if the pipeline is
> designed to be able to forward operations to a later than normal
> stage. So, in the case that reciprocal is the same speed as division
> (which it is in our current division pipeline) ATAN2 is not more
> expensive than ATAN except for the special cases which don't take up
> that many gates to decode them.
>

My actual implementation folds ATAN into ATAN2 and changes the last 2 lines
into::

// 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 );

}

This way the adds and subtracts from the constant are not in a precision
precarious position.

>
> Jacob Lifshay
>
```