958abf5bd8c150c8121827bf8a8f3c97811561d2
[musl] / src / math / floorf.c
1 /* origin: FreeBSD /usr/src/lib/msun/src/s_floorf.c */
2 /*
3  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
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 /*
16  * floorf(x)
17  * Return x rounded toward -inf to integral value
18  * Method:
19  *      Bit twiddling.
20  * Exception:
21  *      Inexact flag raised if x not equal to floorf(x).
22  */
23
24 #include "libm.h"
25
26 static const float huge = 1.0e30;
27
28 float floorf(float x)
29 {
30         int32_t i0,j0;
31         uint32_t i;
32
33         GET_FLOAT_WORD(i0, x);
34         // FIXME: signed shift
35         j0 = ((i0>>23)&0xff) - 0x7f;
36         if (j0 < 23) {
37                 if (j0 < 0) {  /* |x| < 1 */
38                         /* raise inexact if x != 0 */
39                         if (huge+x > (float)0.0) {
40                                 if (i0 >= 0)  /* x >= 0 */
41                                         i0 = 0;
42                                 else if ((i0&0x7fffffff) != 0)
43                                         i0 = 0xbf800000;
44                         }
45                 } else {
46                         i = 0x007fffff>>j0;
47                         if ((i0&i) == 0)
48                                 return x; /* x is integral */
49                         /* raise inexact flag */
50                         if (huge+x > (float)0.0) {
51                                 if (i0 < 0)
52                                         i0 += 0x00800000>>j0;
53                                 i0 &= ~i;
54                         }
55                 }
56         } else {
57                 if (j0 == 0x80)  /* inf or NaN */
58                         return x+x;
59                 else
60                         return x;  /* x is integral */
61         }
62         SET_FLOAT_WORD(x, i0);
63         return x;
64 }