[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