Back to index

glibc  2.9
s_floorl.c
Go to the documentation of this file.
00001 /* Round to int long double floating-point values.
00002    IBM extended format long double version.
00003    Copyright (C) 2006, 2007 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
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 #include <math_ldbl_opt.h>
00023 #include <float.h>
00024 #include <ieee754.h>
00025 
00026 
00027 #ifdef __STDC__
00028 long double
00029 __floorl (long double x)
00030 #else
00031 long double
00032 __floorl (x)
00033      long double x;
00034 #endif
00035 {
00036   double xh, xl, hi, lo;
00037 
00038   ldbl_unpack (x, &xh, &xl);
00039 
00040   /* Return Inf, Nan, +/-0 unchanged.  */
00041   if (__builtin_expect (xh != 0.0
00042                      && __builtin_isless (__builtin_fabs (xh),
00043                                         __builtin_inf ()), 1))
00044     {
00045       /* Long double arithmetic, including the canonicalisation below,
00046         only works in round-to-nearest mode.  */
00047 
00048       /* Convert the high double to integer.  */
00049       hi = ldbl_nearbyint (xh);
00050 
00051       /* Subtract integral high part from the value.  */
00052       xh -= hi;
00053       ldbl_canonicalize (&xh, &xl);
00054 
00055       /* Now convert the low double, adjusted for any remainder from the
00056          high double.  */
00057       lo = ldbl_nearbyint (xh);
00058 
00059       /* Adjust the result when the remainder is non-zero.  nearbyint
00060          rounds values to the nearest integer, and values halfway
00061          between integers to the nearest even integer.  floorl must
00062          round towards -Inf.  */
00063       xh -= lo;
00064       ldbl_canonicalize (&xh, &xl);
00065 
00066       if (xh < 0.0 || (xh == 0.0 && xl < 0.0))
00067        lo += -1.0;
00068 
00069       /* Ensure the final value is canonical.  In certain cases,
00070          rounding causes hi,lo calculated so far to be non-canonical.  */
00071       xh = hi;
00072       xl = lo;
00073       ldbl_canonicalize (&xh, &xl);
00074     }
00075 
00076   return ldbl_pack (xh, xl);
00077 }
00078 
00079 long_double_symbol (libm, __floorl, floorl);