Merge branch 'vendor/OPENPAM'
[dragonfly.git] / lib / libm / src / s_rintf.c
1 /* s_rintf.c -- float version of s_rint.c.
2  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3  */
4
5 /*
6  * ====================================================
7  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8  *
9  * Developed at SunPro, a Sun Microsystems, Inc. business.
10  * Permission to use, copy, modify, and distribute this
11  * software is freely granted, provided that this notice
12  * is preserved.
13  * ====================================================
14  *
15  * $NetBSD: s_rintf.c,v 1.9 2008/04/25 22:21:53 christos Exp $
16  */
17
18 #include <math.h>
19 #include "math_private.h"
20
21 static const float
22 TWO23[2]={
23   8.3886080000e+06, /* 0x4b000000 */
24  -8.3886080000e+06, /* 0xcb000000 */
25 };
26
27 float
28 rintf(float x)
29 {
30         int32_t i0,jj0,sx;
31         u_int32_t i,i1;
32 #ifdef __i386__ /* XXX gcc4 will omit the rounding otherwise */
33         volatile
34 #endif
35                 float w;
36         float t;
37         GET_FLOAT_WORD(i0,x);
38         sx = (i0>>31)&1;
39         jj0 = ((i0>>23)&0xff)-0x7f;
40         if(jj0<23) {
41             if(jj0<0) {
42                 if((i0&0x7fffffff)==0) return x;
43                 i1 = (i0&0x07fffff);
44                 i0 &= 0xfff00000;
45                 i0 |= ((i1|-i1)>>9)&0x400000;
46                 SET_FLOAT_WORD(x,i0);
47                 w = TWO23[sx]+x;
48                 t =  w-TWO23[sx];
49                 GET_FLOAT_WORD(i0,t);
50                 SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
51                 return t;
52             } else {
53                 i = (0x007fffff)>>jj0;
54                 if((i0&i)==0) return x; /* x is integral */
55                 i>>=1;
56                 if((i0&i)!=0) i0 = (i0&(~i))|((0x100000)>>jj0);
57             }
58         } else {
59             if(jj0==0x80) return x+x;   /* inf or NaN */
60             else return x;              /* x is integral */
61         }
62         SET_FLOAT_WORD(x,i0);
63         w = TWO23[sx]+x;
64         return w-TWO23[sx];
65 }