Back to index

glibc  2.9
s_floor.c
Go to the documentation of this file.
00001 /* @(#)s_floor.c 5.1 93/09/24 */
00002 /*
00003  * ====================================================
00004  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00005  *
00006  * Developed at SunPro, a Sun Microsystems, Inc. business.
00007  * Permission to use, copy, modify, and distribute this
00008  * software is freely granted, provided that this notice
00009  * is preserved.
00010  * ====================================================
00011  */
00012 
00013 #if defined(LIBM_SCCS) && !defined(lint)
00014 static char rcsid[] = "$NetBSD: s_floor.c,v 1.8 1995/05/10 20:47:20 jtc Exp $";
00015 #endif
00016 
00017 /*
00018  * floor(x)
00019  * Return x rounded toward -inf to integral value
00020  * Method:
00021  *     Bit twiddling.
00022  * Exception:
00023  *     Inexact flag raised if x not equal to floor(x).
00024  */
00025 
00026 #include "math.h"
00027 #include "math_private.h"
00028 
00029 #ifdef __STDC__
00030 static const double huge = 1.0e300;
00031 #else
00032 static double huge = 1.0e300;
00033 #endif
00034 
00035 #ifdef __STDC__
00036        double __floor(double x)
00037 #else
00038        double __floor(x)
00039        double x;
00040 #endif
00041 {
00042        int32_t i0,i1,j0;
00043        u_int32_t i,j;
00044        EXTRACT_WORDS(i0,i1,x);
00045        j0 = ((i0>>20)&0x7ff)-0x3ff;
00046        if(j0<20) {
00047            if(j0<0) {       /* raise inexact if x != 0 */
00048               if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
00049                   if(i0>=0) {i0=i1=0;}
00050                   else if(((i0&0x7fffffff)|i1)!=0)
00051                      { i0=0xbff00000;i1=0;}
00052               }
00053            } else {
00054               i = (0x000fffff)>>j0;
00055               if(((i0&i)|i1)==0) return x; /* x is integral */
00056               if(huge+x>0.0) {     /* raise inexact flag */
00057                   if(i0<0) i0 += (0x00100000)>>j0;
00058                   i0 &= (~i); i1=0;
00059               }
00060            }
00061        } else if (j0>51) {
00062            if(j0==0x400) return x+x;      /* inf or NaN */
00063            else return x;          /* x is integral */
00064        } else {
00065            i = ((u_int32_t)(0xffffffff))>>(j0-20);
00066            if((i1&i)==0) return x; /* x is integral */
00067            if(huge+x>0.0) {               /* raise inexact flag */
00068               if(i0<0) {
00069                   if(j0==20) i0+=1;
00070                   else {
00071                      j = i1+(1<<(52-j0));
00072                      if(j<i1) i0 +=1 ;    /* got a carry */
00073                      i1=j;
00074                   }
00075               }
00076               i1 &= (~i);
00077            }
00078        }
00079        INSERT_WORDS(x,i0,i1);
00080        return x;
00081 }
00082 weak_alias (__floor, floor)
00083 #ifdef NO_LONG_DOUBLE
00084 strong_alias (__floor, __floorl)
00085 weak_alias (__floor, floorl)
00086 #endif