Blame sysdeps/ieee754/flt-32/k_rem_pio2f.c

Packit Service 82fcde
/* k_rem_pio2f.c -- float version of k_rem_pio2.c
Packit Service 82fcde
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * ====================================================
Packit Service 82fcde
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Developed at SunPro, a Sun Microsystems, Inc. business.
Packit Service 82fcde
 * Permission to use, copy, modify, and distribute this
Packit Service 82fcde
 * software is freely granted, provided that this notice
Packit Service 82fcde
 * is preserved.
Packit Service 82fcde
 * ====================================================
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
#if defined(LIBM_SCCS) && !defined(lint)
Packit Service 82fcde
static char rcsid[] = "$NetBSD: k_rem_pio2f.c,v 1.4 1995/05/10 20:46:28 jtc Exp $";
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#include <math.h>
Packit Service 82fcde
#include <math-narrow-eval.h>
Packit Service 82fcde
#include <math_private.h>
Packit Service 82fcde
#include <libc-diag.h>
Packit Service 82fcde
Packit Service 82fcde
/* In the float version, the input parameter x contains 8 bit
Packit Service 82fcde
   integers, not 24 bit integers.  113 bit precision is not supported.  */
Packit Service 82fcde
Packit Service 82fcde
static const int init_jk[] = {4,7,9}; /* initial value for jk */
Packit Service 82fcde
Packit Service 82fcde
static const float PIo2[] = {
Packit Service 82fcde
  1.5703125000e+00, /* 0x3fc90000 */
Packit Service 82fcde
  4.5776367188e-04, /* 0x39f00000 */
Packit Service 82fcde
  2.5987625122e-05, /* 0x37da0000 */
Packit Service 82fcde
  7.5437128544e-08, /* 0x33a20000 */
Packit Service 82fcde
  6.0026650317e-11, /* 0x2e840000 */
Packit Service 82fcde
  7.3896444519e-13, /* 0x2b500000 */
Packit Service 82fcde
  5.3845816694e-15, /* 0x27c20000 */
Packit Service 82fcde
  5.6378512969e-18, /* 0x22d00000 */
Packit Service 82fcde
  8.3009228831e-20, /* 0x1fc40000 */
Packit Service 82fcde
  3.2756352257e-22, /* 0x1bc60000 */
Packit Service 82fcde
  6.3331015649e-25, /* 0x17440000 */
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static const float
Packit Service 82fcde
zero   = 0.0,
Packit Service 82fcde
one    = 1.0,
Packit Service 82fcde
two8   =  2.5600000000e+02, /* 0x43800000 */
Packit Service 82fcde
twon8  =  3.9062500000e-03; /* 0x3b800000 */
Packit Service 82fcde
Packit Service 82fcde
int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int32_t *ipio2)
Packit Service 82fcde
{
Packit Service 82fcde
	int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
Packit Service 82fcde
	float z,fw,f[20],fq[20],q[20];
Packit Service 82fcde
Packit Service 82fcde
    /* initialize jk*/
Packit Service 82fcde
	jk = init_jk[prec];
Packit Service 82fcde
	jp = jk;
Packit Service 82fcde
Packit Service 82fcde
    /* determine jx,jv,q0, note that 3>q0 */
Packit Service 82fcde
	jx =  nx-1;
Packit Service 82fcde
	jv = (e0-3)/8; if(jv<0) jv=0;
Packit Service 82fcde
	q0 =  e0-8*(jv+1);
Packit Service 82fcde
Packit Service 82fcde
    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
Packit Service 82fcde
	j = jv-jx; m = jx+jk;
Packit Service 82fcde
	for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
Packit Service 82fcde
Packit Service 82fcde
    /* compute q[0],q[1],...q[jk] */
Packit Service 82fcde
	for (i=0;i<=jk;i++) {
Packit Service 82fcde
	    for(j=0,fw=0.0;j<=jx;j++)
Packit Service 82fcde
		fw += x[j]*f[jx+i-j];
Packit Service 82fcde
	    q[i] = fw;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
	jz = jk;
Packit Service 82fcde
recompute:
Packit Service 82fcde
    /* distill q[] into iq[] reversingly */
Packit Service 82fcde
	for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
Packit Service 82fcde
	    fw    =  (float)((int32_t)(twon8* z));
Packit Service 82fcde
	    iq[i] =  (int32_t)(z-two8*fw);
Packit Service 82fcde
	    z     =  q[j-1]+fw;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
    /* compute n */
Packit Service 82fcde
	z  = __scalbnf(z,q0);		/* actual value of z */
Packit Service 82fcde
	z -= (float)8.0*__floorf(z*(float)0.125);	/* trim off integer >= 8 */
Packit Service 82fcde
	n  = (int32_t) z;
Packit Service 82fcde
	z -= (float)n;
Packit Service 82fcde
	ih = 0;
Packit Service 82fcde
	if(q0>0) {	/* need iq[jz-1] to determine n */
Packit Service 82fcde
	    i  = (iq[jz-1]>>(8-q0)); n += i;
Packit Service 82fcde
	    iq[jz-1] -= i<<(8-q0);
Packit Service 82fcde
	    ih = iq[jz-1]>>(7-q0);
Packit Service 82fcde
	}
Packit Service 82fcde
	else if(q0==0) ih = iq[jz-1]>>7;
Packit Service 82fcde
	else if(z>=(float)0.5) ih=2;
Packit Service 82fcde
Packit Service 82fcde
	if(ih>0) {	/* q > 0.5 */
Packit Service 82fcde
	    n += 1; carry = 0;
Packit Service 82fcde
	    for(i=0;i
Packit Service 82fcde
		j = iq[i];
Packit Service 82fcde
		if(carry==0) {
Packit Service 82fcde
		    if(j!=0) {
Packit Service 82fcde
			carry = 1; iq[i] = 0x100- j;
Packit Service 82fcde
		    }
Packit Service 82fcde
		} else  iq[i] = 0xff - j;
Packit Service 82fcde
	    }
Packit Service 82fcde
	    if(q0>0) {		/* rare case: chance is 1 in 12 */
Packit Service 82fcde
	        switch(q0) {
Packit Service 82fcde
	        case 1:
Packit Service 82fcde
		   iq[jz-1] &= 0x7f; break;
Packit Service 82fcde
		case 2:
Packit Service 82fcde
		   iq[jz-1] &= 0x3f; break;
Packit Service 82fcde
	        }
Packit Service 82fcde
	    }
Packit Service 82fcde
	    if(ih==2) {
Packit Service 82fcde
		z = one - z;
Packit Service 82fcde
		if(carry!=0) z -= __scalbnf(one,q0);
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
    /* check if recomputation is needed */
Packit Service 82fcde
	if(z==zero) {
Packit Service 82fcde
	    j = 0;
Packit Service 82fcde
	    for (i=jz-1;i>=jk;i--) j |= iq[i];
Packit Service 82fcde
	    if(j==0) { /* need recomputation */
Packit Service 82fcde
		/* On s390x gcc 6.1 -O3 produces the warning "array subscript is
Packit Service 82fcde
		   below array bounds [-Werror=array-bounds]".  Only
Packit Service 82fcde
		   __ieee754_rem_pio2f calls __kernel_rem_pio2f for normal
Packit Service 82fcde
		   numbers and |x| ~> 2^7*(pi/2).  Thus x can't be zero and
Packit Service 82fcde
		   ipio2 is not zero, too.  Thus not all iq[] values can't be
Packit Service 82fcde
		   zero.  */
Packit Service 82fcde
		DIAG_PUSH_NEEDS_COMMENT;
Packit Service 82fcde
		DIAG_IGNORE_NEEDS_COMMENT (6.1, "-Warray-bounds");
Packit Service 82fcde
		for(k=1;iq[jk-k]==0;k++);   /* k = no. of terms needed */
Packit Service 82fcde
		DIAG_POP_NEEDS_COMMENT;
Packit Service 82fcde
Packit Service 82fcde
		for(i=jz+1;i<=jz+k;i++) {   /* add q[jz+1] to q[jz+k] */
Packit Service 82fcde
		    f[jx+i] = (float) ipio2[jv+i];
Packit Service 82fcde
		    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
Packit Service 82fcde
		    q[i] = fw;
Packit Service 82fcde
		}
Packit Service 82fcde
		jz += k;
Packit Service 82fcde
		goto recompute;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
    /* chop off zero terms */
Packit Service 82fcde
	if(z==(float)0.0) {
Packit Service 82fcde
	    jz -= 1; q0 -= 8;
Packit Service 82fcde
	    while(iq[jz]==0) { jz--; q0-=8;}
Packit Service 82fcde
	} else { /* break z into 8-bit if necessary */
Packit Service 82fcde
	    z = __scalbnf(z,-q0);
Packit Service 82fcde
	    if(z>=two8) {
Packit Service 82fcde
		fw = (float)((int32_t)(twon8*z));
Packit Service 82fcde
		iq[jz] = (int32_t)(z-two8*fw);
Packit Service 82fcde
		jz += 1; q0 += 8;
Packit Service 82fcde
		iq[jz] = (int32_t) fw;
Packit Service 82fcde
	    } else iq[jz] = (int32_t) z ;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
    /* convert integer "bit" chunk to floating-point value */
Packit Service 82fcde
	fw = __scalbnf(one,q0);
Packit Service 82fcde
	for(i=jz;i>=0;i--) {
Packit Service 82fcde
	    q[i] = fw*(float)iq[i]; fw*=twon8;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
    /* compute PIo2[0,...,jp]*q[jz,...,0] */
Packit Service 82fcde
	for(i=jz;i>=0;i--) {
Packit Service 82fcde
	    for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
Packit Service 82fcde
	    fq[jz-i] = fw;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
    /* compress fq[] into y[] */
Packit Service 82fcde
	switch(prec) {
Packit Service 82fcde
	    case 0:
Packit Service 82fcde
		fw = 0.0;
Packit Service 82fcde
		for (i=jz;i>=0;i--) fw += fq[i];
Packit Service 82fcde
		y[0] = (ih==0)? fw: -fw;
Packit Service 82fcde
		break;
Packit Service 82fcde
	    case 1:
Packit Service 82fcde
	    case 2:;
Packit Service 82fcde
		float fv = 0.0;
Packit Service 82fcde
		for (i=jz;i>=0;i--) fv = math_narrow_eval (fv + fq[i]);
Packit Service 82fcde
		y[0] = (ih==0)? fv: -fv;
Packit Service 82fcde
		/* GCC mainline (to be GCC 9), as of 2018-05-22 on
Packit Service 82fcde
		   i686, warns that fq[0] may be used uninitialized.
Packit Service 82fcde
		   This is not possible because jz is always
Packit Service 82fcde
		   nonnegative when the above loop initializing fq is
Packit Service 82fcde
		   executed, because the result is never zero to full
Packit Service 82fcde
		   precision (this function is not called for zero
Packit Service 82fcde
		   arguments).  */
Packit Service 82fcde
		DIAG_PUSH_NEEDS_COMMENT;
Packit Service 82fcde
		DIAG_IGNORE_NEEDS_COMMENT (9, "-Wmaybe-uninitialized");
Packit Service 82fcde
		fv = math_narrow_eval (fq[0]-fv);
Packit Service 82fcde
		DIAG_POP_NEEDS_COMMENT;
Packit Service 82fcde
		for (i=1;i<=jz;i++) fv = math_narrow_eval (fv + fq[i]);
Packit Service 82fcde
		y[1] = (ih==0)? fv: -fv;
Packit Service 82fcde
		break;
Packit Service 82fcde
	    case 3:	/* painful */
Packit Service 82fcde
		for (i=jz;i>0;i--) {
Packit Service 82fcde
		    float fv = math_narrow_eval (fq[i-1]+fq[i]);
Packit Service 82fcde
		    fq[i]  += fq[i-1]-fv;
Packit Service 82fcde
		    fq[i-1] = fv;
Packit Service 82fcde
		}
Packit Service 82fcde
		for (i=jz;i>1;i--) {
Packit Service 82fcde
		    float fv = math_narrow_eval (fq[i-1]+fq[i]);
Packit Service 82fcde
		    fq[i]  += fq[i-1]-fv;
Packit Service 82fcde
		    fq[i-1] = fv;
Packit Service 82fcde
		}
Packit Service 82fcde
		for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
Packit Service 82fcde
		if(ih==0) {
Packit Service 82fcde
		    y[0] =  fq[0]; y[1] =  fq[1]; y[2] =  fw;
Packit Service 82fcde
		} else {
Packit Service 82fcde
		    y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
Packit Service 82fcde
		}
Packit Service 82fcde
	}
Packit Service 82fcde
	return n&7;
Packit Service 82fcde
}