xref: /third_party/jerryscript/jerry-libm/ceil.c (revision 425bb815)
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_ceil.c 1.3 95/01/18
26 */
27
28#include "jerry-libm-internal.h"
29
30/* ceil(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 ceil(x).
38 */
39
40#define huge 1.0e300
41
42double
43ceil (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 = 0x80000000;
60          i1 = 0;
61        }
62        else if ((i0 | i1) != 0)
63        {
64          i0 = 0x3ff00000;
65          i1 = 0;
66        }
67      }
68    }
69    else
70    {
71      i = (0x000fffff) >> j0;
72      if (((i0 & i) | i1) == 0) /* x is integral */
73      {
74        return x;
75      }
76      if (huge + x > 0.0) /* raise inexact flag */
77      {
78        if (i0 > 0)
79        {
80          i0 += (0x00100000) >> j0;
81        }
82        i0 &= (~i);
83        i1 = 0;
84      }
85    }
86  }
87  else if (j0 > 51)
88  {
89    if (j0 == 0x400) /* inf or NaN */
90    {
91      return x + x;
92    }
93    else /* x is integral */
94    {
95      return x;
96    }
97  }
98  else
99  {
100    i = ((unsigned) (0xffffffff)) >> (j0 - 20);
101    if ((i1 & i) == 0) /* x is integral */
102    {
103      return x;
104    }
105    if (huge + x > 0.0) /* raise inexact flag */
106    {
107      if (i0 > 0)
108      {
109        if (j0 == 20)
110        {
111          i0 += 1;
112        }
113        else
114        {
115          j = i1 + (1 << (52 - j0));
116          if (j < i1) /* got a carry */
117          {
118            i0 += 1;
119          }
120          i1 = j;
121        }
122      }
123      i1 &= (~i);
124    }
125  }
126
127  double_accessor ret;
128  ret.as_int.hi = i0;
129  ret.as_int.lo = i1;
130  return ret.dbl;
131} /* ceil */
132
133#undef huge
134