e_rem_pio2f.c revision 302408
138716Smsmith/* e_rem_pio2f.c -- float version of e_rem_pio2.c
238716Smsmith * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
338716Smsmith * Debugged and optimized by Bruce D. Evans.
438716Smsmith */
538716Smsmith
638716Smsmith/*
738716Smsmith * ====================================================
838716Smsmith * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
938716Smsmith *
1038716Smsmith * Developed at SunPro, a Sun Microsystems, Inc. business.
1138716Smsmith * Permission to use, copy, modify, and distribute this
1238716Smsmith * software is freely granted, provided that this notice
1338716Smsmith * is preserved.
1444570Sdcs * ====================================================
1538716Smsmith */
1638716Smsmith
1738716Smsmith#include <sys/cdefs.h>
1838716Smsmith__FBSDID("$FreeBSD: stable/11/lib/msun/src/e_rem_pio2f.c 239195 2012-08-11 15:47:22Z dim $");
1938716Smsmith
2038716Smsmith/* __ieee754_rem_pio2f(x,y)
2138716Smsmith *
2238716Smsmith * return the remainder of x rem pi/2 in *y
2338716Smsmith * use double precision for everything except passing x
2438716Smsmith * use __kernel_rem_pio2() for large x
2538716Smsmith */
2638716Smsmith
2738716Smsmith#include <float.h>
2838716Smsmith
2938716Smsmith#include "math.h"
3038716Smsmith#include "math_private.h"
3138716Smsmith
3238716Smsmith/*
3338716Smsmith * invpio2:  53 bits of 2/pi
3438716Smsmith * pio2_1:   first 25 bits of pi/2
3538716Smsmith * pio2_1t:  pi/2 - pio2_1
3638716Smsmith */
3738716Smsmith
3838716Smsmithstatic const double
3938716Smsmithinvpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
4038716Smsmithpio2_1  =  1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
4138716Smsmithpio2_1t =  1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
4238716Smsmith
4338716Smsmith#ifdef INLINE_REM_PIO2F
4438716Smsmithstatic __inline __always_inline
4538716Smsmith#endif
4638716Smsmithint
4738716Smsmith__ieee754_rem_pio2f(float x, double *y)
4838716Smsmith{
4938716Smsmith	double w,r,fn;
5038716Smsmith	double tx[1],ty[1];
5138716Smsmith	float z;
5238716Smsmith	int32_t e0,n,ix,hx;
5338716Smsmith
5438716Smsmith	GET_FLOAT_WORD(hx,x);
5538716Smsmith	ix = hx&0x7fffffff;
5638716Smsmith    /* 33+53 bit pi is good enough for medium size */
5738716Smsmith	if(ix<0x4dc90fdb) {		/* |x| ~< 2^28*(pi/2), medium size */
5838716Smsmith	    /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
5938716Smsmith	    STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52);
6038716Smsmith	    fn = fn-0x1.8p52;
6138716Smsmith#ifdef HAVE_EFFICIENT_IRINT
6238716Smsmith	    n  = irint(fn);
6338716Smsmith#else
6438716Smsmith	    n  = (int32_t)fn;
6538716Smsmith#endif
6638716Smsmith	    r  = x-fn*pio2_1;
6738716Smsmith	    w  = fn*pio2_1t;
6838716Smsmith	    *y = r-w;
6938716Smsmith	    return n;
7038716Smsmith	}
7138716Smsmith    /*
7238716Smsmith     * all other (large) arguments
7338765Sjkh     */
7438765Sjkh	if(ix>=0x7f800000) {		/* x is inf or NaN */
7538765Sjkh	    *y=x-x; return 0;
7638765Sjkh	}
7738765Sjkh    /* set z = scalbn(|x|,ilogb(|x|)-23) */
7838765Sjkh	e0 = (ix>>23)-150;		/* e0 = ilogb(|x|)-23; */
7938716Smsmith	SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
8038716Smsmith	tx[0] = z;
8138716Smsmith	n  =  __kernel_rem_pio2(tx,ty,e0,1,0);
8238716Smsmith	if(hx<0) {*y = -ty[0]; return -n;}
8338716Smsmith	*y = ty[0]; return n;
8438716Smsmith}
8538765Sjkh