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_nextafter.c 1.3 95/01/18
26 */
27
28#include "jerry-libm-internal.h"
29
30double
31nextafter (double x,
32           double y)
33{
34  int hx, hy, ix, iy;
35  unsigned lx, ly;
36  double_accessor ret;
37
38  hx = __HI (x); /* high word of x */
39  lx = __LO (x); /* low  word of x */
40  hy = __HI (y); /* high word of y */
41  ly = __LO (y); /* low  word of y */
42  ix = hx & 0x7fffffff; /* |x| */
43  iy = hy & 0x7fffffff; /* |y| */
44
45  if (((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0)     /* x is nan */
46      || ((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) /* y is nan */
47  {
48    return x + y;
49  }
50
51  if (x == y)
52  {
53    return x; /* x=y, return x */
54  }
55
56  if ((ix | lx) == 0)
57  { /* x == 0 */
58    ret.as_int.hi = hy & 0x80000000; /* return +-minsubnormal */
59    ret.as_int.lo = 1;
60    y = ret.dbl * ret.dbl;
61    if (y == ret.dbl)
62    {
63      return y;
64    }
65    else
66    {
67      return ret.dbl; /* raise underflow flag */
68    }
69  }
70
71  if (hx >= 0)
72  { /* x > 0 */
73    if (hx > hy || ((hx == hy) && (lx > ly)))
74    { /* x > y, x -= ulp */
75      if (lx == 0)
76      {
77        hx -= 1;
78      }
79
80      lx -= 1;
81    }
82    else
83    { /* x < y, x += ulp */
84      lx += 1;
85
86      if (lx == 0)
87      {
88        hx += 1;
89      }
90    }
91  }
92  else
93  { /* x < 0 */
94    if (hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)))
95    { /* x < y, x -= ulp */
96      if (lx == 0)
97      {
98        hx -= 1;
99      }
100
101      lx -= 1;
102    }
103    else
104    { /* x > y, x += ulp */
105      lx += 1;
106
107      if (lx == 0)
108      {
109        hx += 1;
110      }
111    }
112  }
113
114  hy = hx & 0x7ff00000;
115
116  if (hy >= 0x7ff00000)
117  {
118    return x + x; /* overflow */
119  }
120
121  if (hy < 0x00100000)
122  { /* underflow */
123    y = x * x;
124    if (y != x)
125    { /* raise underflow flag */
126      ret.as_int.hi = hx;
127      ret.as_int.lo = lx;
128      return ret.dbl;
129    }
130  }
131
132  ret.as_int.hi = hx;
133  ret.as_int.lo = lx;
134  return ret.dbl;
135} /* nextafter */
136