Back to index

glibc  2.9
s_ceill.c
Go to the documentation of this file.
00001 /* Ceil (round to +inf) 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 __ceill (long double x)
00030 #else
00031 long double
00032 __ceill (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       double orig_xh;
00046 
00047       /* Long double arithmetic, including the canonicalisation below,
00048         only works in round-to-nearest mode.  */
00049 
00050       /* Convert the high double to integer.  */
00051       orig_xh = xh;
00052       hi = ldbl_nearbyint (xh);
00053 
00054       /* Subtract integral high part from the value.  */
00055       xh -= hi;
00056       ldbl_canonicalize (&xh, &xl);
00057 
00058       /* Now convert the low double, adjusted for any remainder from the
00059          high double.  */
00060       lo = ldbl_nearbyint (xh);
00061 
00062       /* Adjust the result when the remainder is non-zero.  nearbyint
00063          rounds values to the nearest integer, and values halfway
00064          between integers to the nearest even integer.  ceill must
00065          round towards +Inf.  */
00066       xh -= lo;
00067       ldbl_canonicalize (&xh, &xl);
00068 
00069       if (xh > 0.0 || (xh == 0.0 && xl > 0.0))
00070        lo += 1.0;
00071 
00072       /* Ensure the final value is canonical.  In certain cases,
00073          rounding causes hi,lo calculated so far to be non-canonical.  */
00074       xh = hi;
00075       xl = lo;
00076       ldbl_canonicalize (&xh, &xl);
00077 
00078       /* Ensure we return -0 rather than +0 when appropriate.  */
00079       if (orig_xh < 0.0)
00080        xh = -__builtin_fabs (xh);
00081     }
00082 
00083   return ldbl_pack (xh, xl);
00084 }
00085 
00086 long_double_symbol (libm, __ceill, ceill);