sortix-mirror/libm/src/s_rint.c
Jonas 'Sortie' Termansen 5980be9b3c Add Sortix Math Library.
This work is based in part on code from NetBSD libm, libc and kernel.

The library is partly public domain and partly BSD-style licensed.
2013-12-17 14:30:39 +01:00

80 lines
1.9 KiB
C

/* @(#)s_rint.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#include <sys/cdefs.h>
#if defined(LIBM_SCCS) && !defined(lint)
__RCSID("$NetBSD: s_rint.c,v 1.12 2008/04/25 22:21:53 christos Exp $");
#endif
/*
* rint(x)
* Return x rounded to integral value according to the prevailing
* rounding mode.
* Method:
* Using floating addition.
* Exception:
* Inexact flag raised if x not equal to rint(x).
*/
#include "math.h"
#include "math_private.h"
static const double
TWO52[2]={
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
};
double
rint(double x)
{
int32_t i0,jj0,sx;
uint32_t i,i1;
double w,t;
EXTRACT_WORDS(i0,i1,x);
sx = (i0>>31)&1;
jj0 = ((i0>>20)&0x7ff)-0x3ff;
if(jj0<20) {
if(jj0<0) {
if(((i0&0x7fffffff)|i1)==0) return x;
i1 |= (i0&0x0fffff);
i0 &= 0xfffe0000;
i0 |= ((i1|-i1)>>12)&0x80000;
SET_HIGH_WORD(x,i0);
w = TWO52[sx]+x;
t = w-TWO52[sx];
GET_HIGH_WORD(i0,t);
SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
return t;
} else {
i = (0x000fffff)>>jj0;
if(((i0&i)|i1)==0) return x; /* x is integral */
i>>=1;
if(((i0&i)|i1)!=0) {
if(jj0==19) i1 = 0x40000000; else
i0 = (i0&(~i))|((0x20000)>>jj0);
}
}
} else if (jj0>51) {
if(jj0==0x400) return x+x; /* inf or NaN */
else return x; /* x is integral */
} else {
i = ((uint32_t)(0xffffffff))>>(jj0-20);
if((i1&i)==0) return x; /* x is integral */
i>>=1;
if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(jj0-20));
}
INSERT_WORDS(x,i0,i1);
w = TWO52[sx]+x;
return w-TWO52[sx];
}