13a8617a8SJordan K. Hubbard /* @(#)s_rint.c 5.1 93/09/24 */ 23a8617a8SJordan K. Hubbard /* 33a8617a8SJordan K. Hubbard * ==================================================== 43a8617a8SJordan K. Hubbard * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 53a8617a8SJordan K. Hubbard * 63a8617a8SJordan K. Hubbard * Developed at SunPro, a Sun Microsystems, Inc. business. 73a8617a8SJordan K. Hubbard * Permission to use, copy, modify, and distribute this 83a8617a8SJordan K. Hubbard * software is freely granted, provided that this notice 93a8617a8SJordan K. Hubbard * is preserved. 103a8617a8SJordan K. Hubbard * ==================================================== 113a8617a8SJordan K. Hubbard */ 123a8617a8SJordan K. Hubbard 133a8617a8SJordan K. Hubbard #ifndef lint 147f3dea24SPeter Wemm static char rcsid[] = "$FreeBSD$"; 153a8617a8SJordan K. Hubbard #endif 163a8617a8SJordan K. Hubbard 173a8617a8SJordan K. Hubbard /* 183a8617a8SJordan K. Hubbard * rint(x) 193a8617a8SJordan K. Hubbard * Return x rounded to integral value according to the prevailing 203a8617a8SJordan K. Hubbard * rounding mode. 213a8617a8SJordan K. Hubbard * Method: 223a8617a8SJordan K. Hubbard * Using floating addition. 233a8617a8SJordan K. Hubbard * Exception: 243a8617a8SJordan K. Hubbard * Inexact flag raised if x not equal to rint(x). 253a8617a8SJordan K. Hubbard */ 263a8617a8SJordan K. Hubbard 27d3f9671aSDavid Schultz #include <float.h> 28d3f9671aSDavid Schultz 293a8617a8SJordan K. Hubbard #include "math.h" 303a8617a8SJordan K. Hubbard #include "math_private.h" 313a8617a8SJordan K. Hubbard 323fc5a433SBruce Evans static const double 333a8617a8SJordan K. Hubbard TWO52[2]={ 343a8617a8SJordan K. Hubbard 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ 353a8617a8SJordan K. Hubbard -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ 363a8617a8SJordan K. Hubbard }; 373a8617a8SJordan K. Hubbard 3859b19ff1SAlfred Perlstein double 393819e840SPeter Wemm rint(double x) 403a8617a8SJordan K. Hubbard { 413a8617a8SJordan K. Hubbard int32_t i0,j0,sx; 423a8617a8SJordan K. Hubbard u_int32_t i,i1; 433a8617a8SJordan K. Hubbard double w,t; 443a8617a8SJordan K. Hubbard EXTRACT_WORDS(i0,i1,x); 453a8617a8SJordan K. Hubbard sx = (i0>>31)&1; 463a8617a8SJordan K. Hubbard j0 = ((i0>>20)&0x7ff)-0x3ff; 473a8617a8SJordan K. Hubbard if(j0<20) { 483a8617a8SJordan K. Hubbard if(j0<0) { 493a8617a8SJordan K. Hubbard if(((i0&0x7fffffff)|i1)==0) return x; 503a8617a8SJordan K. Hubbard i1 |= (i0&0x0fffff); 513a8617a8SJordan K. Hubbard i0 &= 0xfffe0000; 523a8617a8SJordan K. Hubbard i0 |= ((i1|-i1)>>12)&0x80000; 533a8617a8SJordan K. Hubbard SET_HIGH_WORD(x,i0); 546a876b92SBruce Evans STRICT_ASSIGN(double,w,TWO52[sx]+x); 553a8617a8SJordan K. Hubbard t = w-TWO52[sx]; 563a8617a8SJordan K. Hubbard GET_HIGH_WORD(i0,t); 573a8617a8SJordan K. Hubbard SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); 583a8617a8SJordan K. Hubbard return t; 593a8617a8SJordan K. Hubbard } else { 603a8617a8SJordan K. Hubbard i = (0x000fffff)>>j0; 613a8617a8SJordan K. Hubbard if(((i0&i)|i1)==0) return x; /* x is integral */ 623a8617a8SJordan K. Hubbard i>>=1; 633a8617a8SJordan K. Hubbard if(((i0&i)|i1)!=0) { 6474413775SBruce Evans /* 6574413775SBruce Evans * Some bit is set after the 0.5 bit. To avoid the 6674413775SBruce Evans * possibility of errors from double rounding in 6774413775SBruce Evans * w = TWO52[sx]+x, adjust the 0.25 bit to a lower 6874413775SBruce Evans * guard bit. We do this for all j0<=51. The 6974413775SBruce Evans * adjustment is trickiest for j0==18 and j0==19 7074413775SBruce Evans * since then it spans the word boundary. 7174413775SBruce Evans */ 723a8617a8SJordan K. Hubbard if(j0==19) i1 = 0x40000000; else 7374413775SBruce Evans if(j0==18) i1 = 0x80000000; else 743a8617a8SJordan K. Hubbard i0 = (i0&(~i))|((0x20000)>>j0); 753a8617a8SJordan K. Hubbard } 763a8617a8SJordan K. Hubbard } 773a8617a8SJordan K. Hubbard } else if (j0>51) { 783a8617a8SJordan K. Hubbard if(j0==0x400) return x+x; /* inf or NaN */ 793a8617a8SJordan K. Hubbard else return x; /* x is integral */ 803a8617a8SJordan K. Hubbard } else { 813a8617a8SJordan K. Hubbard i = ((u_int32_t)(0xffffffff))>>(j0-20); 823a8617a8SJordan K. Hubbard if((i1&i)==0) return x; /* x is integral */ 833a8617a8SJordan K. Hubbard i>>=1; 843a8617a8SJordan K. Hubbard if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); 853a8617a8SJordan K. Hubbard } 863a8617a8SJordan K. Hubbard INSERT_WORDS(x,i0,i1); 876a876b92SBruce Evans STRICT_ASSIGN(double,w,TWO52[sx]+x); 883a8617a8SJordan K. Hubbard return w-TWO52[sx]; 893a8617a8SJordan K. Hubbard } 90d3f9671aSDavid Schultz 91d3f9671aSDavid Schultz #if (LDBL_MANT_DIG == 53) 92d3f9671aSDavid Schultz __weak_reference(rint, rintl); 93d3f9671aSDavid Schultz #endif 94