POK
rint.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_rint.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 #ifdef POK_NEEDS_LIBMATH
30 
31 /*
32  * rint(x)
33  * Return x rounded to integral value according to the prevailing
34  * rounding mode.
35  * Method:
36  * Using floating addition.
37  * Exception:
38  * Inexact flag raised if x not equal to rint(x).
39  */
40 
41 #include <libm.h>
42 #include "math_private.h"
43 
44 static const double
45 TWO52[2]={
46  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
47  -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
48 };
49 
50 double
51 rint(double x)
52 {
53  int32_t i0,jj0,sx;
54  uint32_t i,i1;
55  double w,t;
56  EXTRACT_WORDS(i0,i1,x);
57  sx = (i0>>31)&1;
58  jj0 = ((i0>>20)&0x7ff)-0x3ff;
59  if(jj0<20) {
60  if(jj0<0) {
61  if(((i0&0x7fffffff)|i1)==0) return x;
62  i1 |= (i0&0x0fffff);
63  i0 &= 0xfffe0000;
64  i0 |= ((i1|-i1)>>12)&0x80000;
65  SET_HIGH_WORD(x,i0);
66  w = TWO52[sx]+x;
67  t = w-TWO52[sx];
68  GET_HIGH_WORD(i0,t);
69  SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
70  return t;
71  } else {
72  i = (0x000fffff)>>jj0;
73  if(((i0&i)|i1)==0) return x; /* x is integral */
74  i>>=1;
75  if(((i0&i)|i1)!=0) {
76  if(jj0==19) i1 = 0x40000000; else
77  i0 = (i0&(~i))|((0x20000)>>jj0);
78  }
79  }
80  } else if (jj0>51) {
81  if(jj0==0x400) return x+x; /* inf or NaN */
82  else return x; /* x is integral */
83  } else {
84  i = ((uint32_t)(0xffffffff))>>(jj0-20);
85  if((i1&i)==0) return x; /* x is integral */
86  i>>=1;
87  if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(jj0-20));
88  }
89  INSERT_WORDS(x,i0,i1);
90  w = TWO52[sx]+x;
91  return w-TWO52[sx];
92 }
93 
94 #endif
95