[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 
>


More information about the libre-riscv-dev mailing list