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
30 double
nextafter(double x,double y)31 nextafter (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