POK
ceil.c
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Fri Jan 30 14:41:34 2009
15  */
16 
17 /* @(#)s_ceil.c 5.1 93/09/24 */
18 /*
19  * ====================================================
20  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
21  *
22  * Developed at SunPro, a Sun Microsystems, Inc. business.
23  * Permission to use, copy, modify, and distribute this
24  * software is freely granted, provided that this notice
25  * is preserved.
26  * ====================================================
27  */
28 
29 
30 /*
31  * ceil(x)
32  * Return x rounded toward -inf to integral value
33  * Method:
34  * Bit twiddling.
35  * Exception:
36  * Inexact flag raised if x not equal to ceil(x).
37  */
38 
39 #ifdef POK_NEEDS_LIBMATH
40 
41 #include <libm.h>
42 #include "math_private.h"
43 
44 static const double huge = 1.0e300;
45 
46 double
47 ceil(double x)
48 {
49  int32_t i0,i1,jj0;
50  uint32_t i,j;
51  EXTRACT_WORDS(i0,i1,x);
52  jj0 = ((i0>>20)&0x7ff)-0x3ff;
53  if(jj0<20) {
54  if(jj0<0) { /* raise inexact if x != 0 */
55  if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
56  if(i0<0) {i0=0x80000000;i1=0;}
57  else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
58  }
59  } else {
60  i = (0x000fffff)>>jj0;
61  if(((i0&i)|i1)==0) return x; /* x is integral */
62  if(huge+x>0.0) { /* raise inexact flag */
63  if(i0>0) i0 += (0x00100000)>>jj0;
64  i0 &= (~i); i1=0;
65  }
66  }
67  } else if (jj0>51) {
68  if(jj0==0x400) return x+x; /* inf or NaN */
69  else return x; /* x is integral */
70  } else {
71  i = ((uint32_t)(0xffffffff))>>(jj0-20);
72  if((i1&i)==0) return x; /* x is integral */
73  if(huge+x>0.0) { /* raise inexact flag */
74  if(i0>0) {
75  if(jj0==20) i0+=1;
76  else {
77  j = i1 + (1<<(52-jj0));
78  if(j<(uint32_t)i1) i0+=1; /* got a carry */
79  i1 = j;
80  }
81  }
82  i1 &= (~i);
83  }
84  }
85  INSERT_WORDS(x,i0,i1);
86  return x;
87 }
88 
89 #endif