12116Sjkh/* e_rem_pio2f.c -- float version of e_rem_pio2.c 22116Sjkh * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 3152535Sbde * Debugged and optimized by Bruce D. Evans. 42116Sjkh */ 52116Sjkh 62116Sjkh/* 72116Sjkh * ==================================================== 82116Sjkh * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 92116Sjkh * 102116Sjkh * Developed at SunPro, a Sun Microsystems, Inc. business. 112116Sjkh * Permission to use, copy, modify, and distribute this 128870Srgrimes * software is freely granted, provided that this notice 132116Sjkh * is preserved. 142116Sjkh * ==================================================== 152116Sjkh */ 162116Sjkh 17176410Sbde#include <sys/cdefs.h> 18176410Sbde__FBSDID("$FreeBSD: releng/10.2/lib/msun/src/e_rem_pio2f.c 239195 2012-08-11 15:47:22Z dim $"); 192116Sjkh 202116Sjkh/* __ieee754_rem_pio2f(x,y) 218870Srgrimes * 22176552Sbde * return the remainder of x rem pi/2 in *y 23176552Sbde * use double precision for everything except passing x 24152535Sbde * use __kernel_rem_pio2() for large x 252116Sjkh */ 262116Sjkh 27176465Sbde#include <float.h> 28176465Sbde 292116Sjkh#include "math.h" 302116Sjkh#include "math_private.h" 312116Sjkh 322116Sjkh/* 33151864Sbde * invpio2: 53 bits of 2/pi 34239192Sdim * pio2_1: first 25 bits of pi/2 352116Sjkh * pio2_1t: pi/2 - pio2_1 362116Sjkh */ 372116Sjkh 38151855Sbdestatic const double 39151864Sbdeinvpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ 40176640Sbdepio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */ 41176640Sbdepio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */ 42151855Sbde 43239192Sdim#ifdef INLINE_REM_PIO2F 44239195Sdimstatic __inline __always_inline 45176569Sbde#endif 46239192Sdimint 47176552Sbde__ieee754_rem_pio2f(float x, double *y) 482116Sjkh{ 49176476Sbde double w,r,fn; 50176558Sbde double tx[1],ty[1]; 51152707Sbde float z; 52152707Sbde int32_t e0,n,ix,hx; 532116Sjkh 542116Sjkh GET_FLOAT_WORD(hx,x); 552116Sjkh ix = hx&0x7fffffff; 56152535Sbde /* 33+53 bit pi is good enough for medium size */ 57176640Sbde if(ix<0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */ 58176465Sbde /* Use a specialized rint() to get fn. Assume round-to-nearest. */ 59176476Sbde STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52); 60176465Sbde fn = fn-0x1.8p52; 61176467Sbde#ifdef HAVE_EFFICIENT_IRINT 62176465Sbde n = irint(fn); 63176465Sbde#else 64176467Sbde n = (int32_t)fn; 65176465Sbde#endif 66176476Sbde r = x-fn*pio2_1; 67151864Sbde w = fn*pio2_1t; 68176552Sbde *y = r-w; 69176476Sbde return n; 702116Sjkh } 718870Srgrimes /* 722116Sjkh * all other (large) arguments 732116Sjkh */ 742116Sjkh if(ix>=0x7f800000) { /* x is inf or NaN */ 75176552Sbde *y=x-x; return 0; 762116Sjkh } 77152707Sbde /* set z = scalbn(|x|,ilogb(|x|)-23) */ 78152707Sbde e0 = (ix>>23)-150; /* e0 = ilogb(|x|)-23; */ 79152707Sbde SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23))); 80152707Sbde tx[0] = z; 81176558Sbde n = __kernel_rem_pio2(tx,ty,e0,1,0); 82176558Sbde if(hx<0) {*y = -ty[0]; return -n;} 83176558Sbde *y = ty[0]; return n; 842116Sjkh} 85