1/* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 * This file is based on work under the following copyright and permission
16 * notice:
17 *
18 *     Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
19 *
20 *     Developed at SunSoft, a Sun Microsystems, Inc. business.
21 *     Permission to use, copy, modify, and distribute this
22 *     software is freely granted, provided that this notice
23 *     is preserved.
24 *
25 *     @(#)s_floor.c 1.3 95/01/18
26 */
27
28#include "jerry-libm-internal.h"
29
30/* floor(x)
31 * Return x rounded toward -inf to integral value
32 *
33 * Method:
34 *      Bit twiddling.
35 *
36 * Exception:
37 *      Inexact flag raised if x not equal to floor(x).
38 */
39
40#define huge 1.0e300
41
42double
43floor (double x)
44{
45  int i0, i1, j0;
46  unsigned i, j;
47
48  i0 = __HI (x);
49  i1 = __LO (x);
50  j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
51  if (j0 < 20)
52  {
53    if (j0 < 0) /* raise inexact if x != 0 */
54    {
55      if (huge + x > 0.0) /* return 0 * sign(x) if |x| < 1 */
56      {
57        if (i0 >= 0)
58        {
59          i0 = i1 = 0;
60        }
61        else if (((i0 & 0x7fffffff) | i1) != 0)
62        {
63          i0 = 0xbff00000;
64          i1 = 0;
65        }
66      }
67    }
68    else
69    {
70      i = (0x000fffff) >> j0;
71      if (((i0 & i) | i1) == 0) /* x is integral */
72      {
73        return x;
74      }
75      if (huge + x > 0.0) /* raise inexact flag */
76      {
77        if (i0 < 0)
78        {
79          i0 += (0x00100000) >> j0;
80        }
81        i0 &= (~i);
82        i1 = 0;
83      }
84    }
85  }
86  else if (j0 > 51)
87  {
88    if (j0 == 0x400) /* inf or NaN */
89    {
90      return x + x;
91    }
92    else /* x is integral */
93    {
94      return x;
95    }
96  }
97  else
98  {
99    i = ((unsigned) (0xffffffff)) >> (j0 - 20);
100    if ((i1 & i) == 0) /* x is integral */
101    {
102      return x;
103    }
104    if (huge + x > 0.0) /* raise inexact flag */
105    {
106      if (i0 < 0)
107      {
108        if (j0 == 20)
109        {
110          i0 += 1;
111        }
112        else
113        {
114          j = i1 + (1 << (52 - j0));
115          if (j < i1) /* got a carry */
116          {
117            i0 += 1;
118          }
119          i1 = j;
120        }
121      }
122      i1 &= (~i);
123    }
124  }
125
126  double_accessor ret;
127  ret.as_int.hi = i0;
128  ret.as_int.lo = i1;
129  return ret.dbl;
130} /* floor */
131
132#undef huge
133