| The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 1 | /* @(#)s_ceil.c 5.1 93/09/24 */ | 
|  | 2 | /* | 
|  | 3 | * ==================================================== | 
|  | 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. | 
|  | 5 | * | 
|  | 6 | * Developed at SunPro, a Sun Microsystems, Inc. business. | 
|  | 7 | * Permission to use, copy, modify, and distribute this | 
|  | 8 | * software is freely granted, provided that this notice | 
|  | 9 | * is preserved. | 
|  | 10 | * ==================================================== | 
|  | 11 | */ | 
|  | 12 |  | 
|  | 13 | #ifndef lint | 
|  | 14 | static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ceil.c,v 1.9 2003/07/23 04:53:46 peter Exp $"; | 
|  | 15 | #endif | 
|  | 16 |  | 
|  | 17 | /* | 
|  | 18 | * ceil(x) | 
|  | 19 | * Return x rounded toward -inf to integral value | 
|  | 20 | * Method: | 
|  | 21 | *	Bit twiddling. | 
|  | 22 | * Exception: | 
|  | 23 | *	Inexact flag raised if x not equal to ceil(x). | 
|  | 24 | */ | 
|  | 25 |  | 
|  | 26 | #include "math.h" | 
|  | 27 | #include "math_private.h" | 
|  | 28 |  | 
|  | 29 | static const double huge = 1.0e300; | 
|  | 30 |  | 
|  | 31 | double | 
|  | 32 | ceil(double x) | 
|  | 33 | { | 
|  | 34 | int32_t i0,i1,j0; | 
|  | 35 | u_int32_t i,j; | 
|  | 36 | EXTRACT_WORDS(i0,i1,x); | 
|  | 37 | j0 = ((i0>>20)&0x7ff)-0x3ff; | 
|  | 38 | if(j0<20) { | 
|  | 39 | if(j0<0) { 	/* raise inexact if x != 0 */ | 
|  | 40 | if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ | 
|  | 41 | if(i0<0) {i0=0x80000000;i1=0;} | 
|  | 42 | else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} | 
|  | 43 | } | 
|  | 44 | } else { | 
|  | 45 | i = (0x000fffff)>>j0; | 
|  | 46 | if(((i0&i)|i1)==0) return x; /* x is integral */ | 
|  | 47 | if(huge+x>0.0) {	/* raise inexact flag */ | 
|  | 48 | if(i0>0) i0 += (0x00100000)>>j0; | 
|  | 49 | i0 &= (~i); i1=0; | 
|  | 50 | } | 
|  | 51 | } | 
|  | 52 | } else if (j0>51) { | 
|  | 53 | if(j0==0x400) return x+x;	/* inf or NaN */ | 
|  | 54 | else return x;		/* x is integral */ | 
|  | 55 | } else { | 
|  | 56 | i = ((u_int32_t)(0xffffffff))>>(j0-20); | 
|  | 57 | if((i1&i)==0) return x;	/* x is integral */ | 
|  | 58 | if(huge+x>0.0) { 		/* raise inexact flag */ | 
|  | 59 | if(i0>0) { | 
|  | 60 | if(j0==20) i0+=1; | 
|  | 61 | else { | 
|  | 62 | j = i1 + (1<<(52-j0)); | 
|  | 63 | if(j<i1) i0+=1;	/* got a carry */ | 
|  | 64 | i1 = j; | 
|  | 65 | } | 
|  | 66 | } | 
|  | 67 | i1 &= (~i); | 
|  | 68 | } | 
|  | 69 | } | 
|  | 70 | INSERT_WORDS(x,i0,i1); | 
|  | 71 | return x; | 
|  | 72 | } |