Back to index

glibc  2.9
s_rint.c
Go to the documentation of this file.
00001 /* @(#)s_rint.c 5.1 93/09/24 */
00002 /*
00003  * ====================================================
00004  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00005  *
00006  * Developed at SunPro, a Sun Microsystems, Inc. business.
00007  * Permission to use, copy, modify, and distribute this
00008  * software is freely granted, provided that this notice
00009  * is preserved.
00010  * ====================================================
00011  */
00012 
00013 #if defined(LIBM_SCCS) && !defined(lint)
00014 static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $";
00015 #endif
00016 
00017 /*
00018  * rint(x)
00019  * Return x rounded to integral value according to the prevailing
00020  * rounding mode.
00021  * Method:
00022  *     Using floating addition.
00023  * Exception:
00024  *     Inexact flag raised if x not equal to rint(x).
00025  */
00026 
00027 #include "math.h"
00028 #include "math_private.h"
00029 
00030 #ifdef __STDC__
00031 static const double
00032 #else
00033 static double
00034 #endif
00035 TWO52[2]={
00036   4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
00037  -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
00038 };
00039 
00040 #ifdef __STDC__
00041        double __rint(double x)
00042 #else
00043        double __rint(x)
00044        double x;
00045 #endif
00046 {
00047        int32_t i0,j0,sx;
00048        u_int32_t i,i1;
00049        double w,t;
00050        EXTRACT_WORDS(i0,i1,x);
00051        sx = (i0>>31)&1;
00052        j0 = ((i0>>20)&0x7ff)-0x3ff;
00053        if(j0<20) {
00054            if(j0<0) {
00055               if(((i0&0x7fffffff)|i1)==0) return x;
00056               i1 |= (i0&0x0fffff);
00057               i0 &= 0xfffe0000;
00058               i0 |= ((i1|-i1)>>12)&0x80000;
00059               SET_HIGH_WORD(x,i0);
00060                w = TWO52[sx]+x;
00061                t =  w-TWO52[sx];
00062               GET_HIGH_WORD(i0,t);
00063               SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
00064                return t;
00065            } else {
00066               i = (0x000fffff)>>j0;
00067               if(((i0&i)|i1)==0) return x; /* x is integral */
00068               i>>=1;
00069               if(((i0&i)|i1)!=0) {
00070                   if (j0==19)
00071                     i1 = 0x40000000;
00072                   else if (j0<18)
00073                     i0 = (i0&(~i))|((0x20000)>>j0);
00074                   else
00075                     {
00076                      i0 &= ~i;
00077                      i1 = 0x80000000;
00078                     }
00079               }
00080            }
00081        } else if (j0>51) {
00082            if(j0==0x400) return x+x;      /* inf or NaN */
00083            else return x;          /* x is integral */
00084        } else {
00085            i = ((u_int32_t)(0xffffffff))>>(j0-20);
00086            if((i1&i)==0) return x; /* x is integral */
00087            i>>=1;
00088            if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
00089        }
00090        INSERT_WORDS(x,i0,i1);
00091        w = TWO52[sx]+x;
00092        return w-TWO52[sx];
00093 }
00094 weak_alias (__rint, rint)
00095 #ifdef NO_LONG_DOUBLE
00096 strong_alias (__rint, __rintl)
00097 weak_alias (__rint, rintl)
00098 #endif