Back to index

glibc  2.9
s_lrintl.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, 1999, 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 and
00006                 Jakub Jelinek <jj@ultra.linux.cz>, 1999.
00007 
00008    The GNU C Library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2.1 of the License, or (at your option) any later version.
00012 
00013    The GNU C Library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with the GNU C Library; if not, write to the Free
00020    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00021    02111-1307 USA.  */
00022 
00023 #include <math.h>
00024 
00025 #include "math_private.h"
00026 
00027 static const long double two112[2] =
00028 {
00029   5.19229685853482762853049632922009600E+33L, /* 0x406F000000000000, 0 */
00030  -5.19229685853482762853049632922009600E+33L  /* 0xC06F000000000000, 0 */
00031 };
00032 
00033 long int
00034 __lrintl (long double x)
00035 {
00036   int32_t j0;
00037   u_int64_t i0,i1;
00038   volatile long double w;
00039   long double t;
00040   long int result;
00041   int sx;
00042 
00043   GET_LDOUBLE_WORDS64 (i0, i1, x);
00044   j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
00045   sx = i0 >> 63;
00046   i0 &= 0x0000ffffffffffffLL;
00047   i0 |= 0x0001000000000000LL;
00048 
00049   if (j0 < 48)
00050     {
00051       w = two112[sx] + x;
00052       t = w - two112[sx];
00053       GET_LDOUBLE_WORDS64 (i0, i1, t);
00054       j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
00055       i0 &= 0x0000ffffffffffffLL;
00056       i0 |= 0x0001000000000000LL;
00057 
00058       result = (j0 < 0 ? 0 : i0 >> (48 - j0));
00059     }
00060   else if (j0 < (int32_t) (8 * sizeof (long int)) - 1)
00061     {
00062       if (j0 >= 112)
00063        result = ((long int) i0 << (j0 - 48)) | (i1 << (j0 - 112));
00064       else
00065        {
00066          w = two112[sx] + x;
00067          t = w - two112[sx];
00068          GET_LDOUBLE_WORDS64 (i0, i1, t);
00069          j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
00070          i0 &= 0x0000ffffffffffffLL;
00071          i0 |= 0x0001000000000000LL;
00072 
00073          if (j0 == 48)
00074            result = (long int) i0;
00075          else
00076            result = ((long int) i0 << (j0 - 48)) | (i1 >> (112 - j0));
00077        }
00078     }
00079   else
00080     {
00081       /* The number is too large.  It is left implementation defined
00082         what happens.  */
00083       return (long int) x;
00084     }
00085 
00086   return sx ? -result : result;
00087 }
00088 
00089 weak_alias (__lrintl, lrintl)