Back to index

glibc  2.9
s_ceill.c
Go to the documentation of this file.
00001 /* s_ceill.c -- long double version of s_ceil.c.
00002  * Conversion to long double by Ulrich Drepper,
00003  * Cygnus Support, drepper@cygnus.com.
00004  */
00005 
00006 /*
00007  * ====================================================
00008  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00009  *
00010  * Developed at SunPro, a Sun Microsystems, Inc. business.
00011  * Permission to use, copy, modify, and distribute this
00012  * software is freely granted, provided that this notice
00013  * is preserved.
00014  * ====================================================
00015  */
00016 
00017 #if defined(LIBM_SCCS) && !defined(lint)
00018 static char rcsid[] = "$NetBSD: $";
00019 #endif
00020 
00021 /*
00022  * ceill(x)
00023  * Return x rounded toward -inf to integral value
00024  * Method:
00025  *     Bit twiddling.
00026  * Exception:
00027  *     Inexact flag raised if x not equal to ceil(x).
00028  */
00029 
00030 #include "math.h"
00031 #include "math_private.h"
00032 
00033 #ifdef __STDC__
00034 static const long double huge = 1.0e4930;
00035 #else
00036 static long double huge = 1.0e4930;
00037 #endif
00038 
00039 #ifdef __STDC__
00040        long double __ceill(long double x)
00041 #else
00042        long double __ceill(x)
00043        long double x;
00044 #endif
00045 {
00046        int32_t i1,j0;
00047        u_int32_t i,j,se,i0,sx;
00048        GET_LDOUBLE_WORDS(se,i0,i1,x);
00049        sx = (se>>15)&1;
00050        j0 = (se&0x7fff)-0x3fff;
00051        if(j0<31) {
00052            if(j0<0) {       /* raise inexact if x != 0 */
00053               if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
00054                   if(sx) {se=0x8000;i0=0;i1=0;}
00055                   else if((i0|i1)!=0) { se=0x3fff;i0=0;i1=0;}
00056               }
00057            } else {
00058               i = (0x7fffffff)>>j0;
00059               if(((i0&i)|i1)==0) return x; /* x is integral */
00060               if(huge+x>0.0) {     /* raise inexact flag */
00061                   if(sx==0) {
00062                      if (j0>0 && (i0+(0x80000000>>j0))>i0)
00063                        i0+=0x80000000>>j0;
00064                      else
00065                        {
00066                          i = 0x7fffffff;
00067                          ++se;
00068                        }
00069                   }
00070                   i0 &= (~i); i1=0;
00071               }
00072            }
00073        } else if (j0>62) {
00074            if(j0==0x4000) return x+x;     /* inf or NaN */
00075            else return x;          /* x is integral */
00076        } else {
00077            i = ((u_int32_t)(0xffffffff))>>(j0-31);
00078            if((i1&i)==0) return x; /* x is integral */
00079            if(huge+x>0.0) {               /* raise inexact flag */
00080               if(sx==0) {
00081                   if(j0==31) i0+=1;
00082                   else {
00083                      j = i1 + (1<<(63-j0));
00084                      if(j<i1) i0+=1;      /* got a carry */
00085                      i1 = j;
00086                   }
00087               }
00088               i1 &= (~i);
00089            }
00090        }
00091        SET_LDOUBLE_WORDS(x,se,i0,i1);
00092        return x;
00093 }
00094 weak_alias (__ceill, ceill)