1132451Sroberto/* @(#)s_rint.c 5.1 93/09/24 */ 2132451Sroberto/* 3132451Sroberto * ==================================================== 4132451Sroberto * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5132451Sroberto * 6132451Sroberto * Developed at SunPro, a Sun Microsystems, Inc. business. 7132451Sroberto * Permission to use, copy, modify, and distribute this 8132451Sroberto * software is freely granted, provided that this notice 9132451Sroberto * is preserved. 10132451Sroberto * ==================================================== 11132451Sroberto */ 12132451Sroberto 13132451Sroberto/* 14132451Sroberto * rint(x) 15132451Sroberto * Return x rounded to integral value according to the prevailing 16132451Sroberto * rounding mode. 17132451Sroberto * Method: 18132451Sroberto * Using floating addition. 19132451Sroberto * Exception: 20132451Sroberto * Inexact flag raised if x not equal to rint(x). 21132451Sroberto */ 22132451Sroberto 23132451Sroberto#include <float.h> 24132451Sroberto#include <math.h> 25132451Sroberto 26132451Sroberto#include "math_private.h" 27132451Sroberto 28132451Srobertostatic const double 29132451SrobertoTWO52[2]={ 30132451Sroberto 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ 31132451Sroberto -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ 32132451Sroberto}; 33132451Sroberto 34132451Srobertodouble 35132451Srobertorint(double x) 36132451Sroberto{ 37132451Sroberto int32_t i0,jj0,sx; 38132451Sroberto u_int32_t i,i1; 39132451Sroberto double t; 40132451Sroberto volatile double w; /* clip extra precision */ 41132451Sroberto EXTRACT_WORDS(i0,i1,x); 42132451Sroberto sx = (i0>>31)&1; 43132451Sroberto jj0 = ((i0>>20)&0x7ff)-0x3ff; 44132451Sroberto if(jj0<20) { 45132451Sroberto if(jj0<0) { 46132451Sroberto if(((i0&0x7fffffff)|i1)==0) return x; 47132451Sroberto i1 |= (i0&0x0fffff); 48132451Sroberto i0 &= 0xfffe0000; 49132451Sroberto i0 |= ((i1|-i1)>>12)&0x80000; 50132451Sroberto SET_HIGH_WORD(x,i0); 51132451Sroberto w = TWO52[sx]+x; 52132451Sroberto t = w-TWO52[sx]; 53132451Sroberto GET_HIGH_WORD(i0,t); 54132451Sroberto SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); 55132451Sroberto return t; 56132451Sroberto } else { 57132451Sroberto i = (0x000fffff)>>jj0; 58132451Sroberto if(((i0&i)|i1)==0) return x; /* x is integral */ 59132451Sroberto i>>=1; 60132451Sroberto if(((i0&i)|i1)!=0) { 61132451Sroberto if(jj0==19) i1 = 0x40000000; else 62132451Sroberto i0 = (i0&(~i))|((0x20000)>>jj0); 63132451Sroberto } 64132451Sroberto } 65132451Sroberto } else if (jj0>51) { 66132451Sroberto if(jj0==0x400) return x+x; /* inf or NaN */ 67132451Sroberto else return x; /* x is integral */ 68132451Sroberto } else { 69132451Sroberto i = ((u_int32_t)(0xffffffff))>>(jj0-20); 70132451Sroberto if((i1&i)==0) return x; /* x is integral */ 71132451Sroberto i>>=1; 72132451Sroberto if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(jj0-20)); 73132451Sroberto } 74132451Sroberto INSERT_WORDS(x,i0,i1); 75132451Sroberto w = TWO52[sx]+x; 76132451Sroberto return w-TWO52[sx]; 77132451Sroberto} 78132451SrobertoDEF_STD(rint); 79132451SrobertoLDBL_MAYBE_NONSTD_CLONE(rint); 80132451Sroberto