Back to index

glibc  2.9
s_llrint.c
Go to the documentation of this file.
00001 /* Round argument to nearest integral value according to current rounding
00002    direction.
00003    Copyright (C) 1997, 2004, 2006 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #include <math.h>
00023 
00024 #include "math_private.h"
00025 
00026 static const double two52[2] =
00027 {
00028   4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
00029  -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
00030 };
00031 
00032 
00033 long long int
00034 __llrint (double x)
00035 {
00036   int32_t j0;
00037   u_int32_t i1, i0;
00038   long long int result;
00039   volatile double w;
00040   double t;
00041   int sx;
00042 
00043   EXTRACT_WORDS (i0, i1, x);
00044   j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
00045   sx = i0 >> 31;
00046   i0 &= 0xfffff;
00047   i0 |= 0x100000;
00048 
00049   if (j0 < 20)
00050     {
00051       w = two52[sx] + x;
00052       t = w - two52[sx];
00053       EXTRACT_WORDS (i0, i1, t);
00054       j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
00055       i0 &= 0xfffff;
00056       i0 |= 0x100000;
00057 
00058       result = (j0 < 0 ? 0 : i0 >> (20 - j0));
00059     }
00060   else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
00061     {
00062       if (j0 >= 52)
00063        result = (((long long int) i0 << 32) | i1) << (j0 - 52);
00064       else
00065        {
00066          w = two52[sx] + x;
00067          t = w - two52[sx];
00068          EXTRACT_WORDS (i0, i1, t);
00069          j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
00070          i0 &= 0xfffff;
00071          i0 |= 0x100000;
00072 
00073          if (j0 == 20)
00074            result = (long long int) i0;
00075          else
00076            result = ((long long int) i0 << (j0 - 20)) | (i1 >> (52 - j0));
00077        }
00078     }
00079   else
00080     {
00081       /* The number is too large.  It is left implementation defined
00082         what happens.  */
00083       return (long long int) x;
00084     }
00085 
00086   return sx ? -result : result;
00087 }
00088 
00089 weak_alias (__llrint, llrint)
00090 #ifdef NO_LONG_DOUBLE
00091 strong_alias (__llrint, __llrintl)
00092 weak_alias (__llrint, llrintl)
00093 #endif