math: rewrite remainder functions (remainder, remquo, fmod, modf)
[musl] / src / math / floor.c
1 #include "libm.h"
2
3 double floor(double x)
4 {
5         union {double f; uint64_t i;} u = {x};
6         int e = u.i >> 52 & 0x7ff;
7         double_t y;
8
9         if (e >= 0x3ff+52 || x == 0)
10                 return x;
11         /* y = int(x) - x, where int(x) is an integer neighbor of x */
12         if (u.i >> 63)
13                 y = (double)(x - 0x1p52) + 0x1p52 - x;
14         else
15                 y = (double)(x + 0x1p52) - 0x1p52 - x;
16         /* special case because of non-nearest rounding modes */
17         if (e <= 0x3ff-1) {
18                 FORCE_EVAL(y);
19                 return u.i >> 63 ? -1 : 0;
20         }
21         if (y > 0)
22                 return x + y - 1;
23         return x + y;
24 }