Back to index

glibc  2.9
s_round.c
Go to the documentation of this file.
00001 /* Round double to integer away from zero.
00002    Copyright (C) 1997 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <math.h>
00022 
00023 #include "math_private.h"
00024 
00025 
00026 static const double huge = 1.0e300;
00027 
00028 
00029 double
00030 __round (double x)
00031 {
00032   int32_t i0, j0;
00033   u_int32_t i1;
00034 
00035   EXTRACT_WORDS (i0, i1, x);
00036   j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
00037   if (j0 < 20)
00038     {
00039       if (j0 < 0)
00040        {
00041          if (huge + x > 0.0)
00042            {
00043              i0 &= 0x80000000;
00044              if (j0 == -1)
00045               i0 |= 0x3ff00000;
00046              i1 = 0;
00047            }
00048        }
00049       else
00050        {
00051          u_int32_t i = 0x000fffff >> j0;
00052          if (((i0 & i) | i1) == 0)
00053            /* X is integral.  */
00054            return x;
00055          if (huge + x > 0.0)
00056            {
00057              /* Raise inexact if x != 0.  */
00058              i0 += 0x00080000 >> j0;
00059              i0 &= ~i;
00060              i1 = 0;
00061            }
00062        }
00063     }
00064   else if (j0 > 51)
00065     {
00066       if (j0 == 0x400)
00067        /* Inf or NaN.  */
00068        return x + x;
00069       else
00070        return x;
00071     }
00072   else
00073     {
00074       u_int32_t i = 0xffffffff >> (j0 - 20);
00075       if ((i1 & i) == 0)
00076        /* X is integral.  */
00077        return x;
00078 
00079       if (huge + x > 0.0)
00080        {
00081          /* Raise inexact if x != 0.  */
00082          u_int32_t j = i1 + (1 << (51 - j0));
00083          if (j < i1)
00084            i0 += 1;
00085          i1 = j;
00086        }
00087       i1 &= ~i;
00088     }
00089 
00090   INSERT_WORDS (x, i0, i1);
00091   return x;
00092 }
00093 weak_alias (__round, round)
00094 #ifdef NO_LONG_DOUBLE
00095 strong_alias (__round, __roundl)
00096 weak_alias (__round, roundl)
00097 #endif