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_scalbn.c 1.3 95/01/18
26 */
27
28 #include "jerry-libm-internal.h"
29
30 /* scalbn(x,n) returns x* 2**n computed by exponent
31 * manipulation rather than by actually performing an
32 * exponentiation or a multiplication.
33 */
34
35 #define two54 1.80143985094819840000e+16 /* 0x43500000, 0x00000000 */
36 #define twom54 5.55111512312578270212e-17 /* 0x3C900000, 0x00000000 */
37 #define huge 1.0e+300
38 #define tiny 1.0e-300
39
40 double
scalbn(double x,int n)41 scalbn (double x, int n)
42 {
43 int k, hx, lx;
44
45 hx = __HI (x);
46 lx = __LO (x);
47 k = (hx & 0x7ff00000) >> 20; /* extract exponent */
48 if (k == 0) /* 0 or subnormal x */
49 {
50 if ((lx | (hx & 0x7fffffff)) == 0) /* +-0 */
51 {
52 return x;
53 }
54 x *= two54;
55 hx = __HI (x);
56 k = ((hx & 0x7ff00000) >> 20) - 54;
57 if (n < -50000) /*underflow */
58 {
59 return tiny * x;
60 }
61 }
62 if (k == 0x7ff) /* NaN or Inf */
63 {
64 return x + x;
65 }
66 k = k + n;
67 if (k > 0x7fe) /* overflow */
68 {
69 return huge * copysign (huge, x);
70 }
71 if (k > 0) /* normal result */
72 {
73 double_accessor ret;
74 ret.dbl = x;
75 ret.as_int.hi = (hx & 0x800fffff) | (k << 20);
76 return ret.dbl;
77 }
78 if (k <= -54)
79 {
80 if (n > 50000) /* in case integer overflow in n + k */
81 {
82 return huge * copysign (huge, x); /*overflow */
83 }
84 else
85 {
86 return tiny * copysign (tiny, x); /*underflow */
87 }
88 }
89 k += 54; /* subnormal result */
90 double_accessor ret;
91 ret.dbl = x;
92 ret.as_int.hi = (hx & 0x800fffff) | (k << 20);
93 return ret.dbl * twom54;
94 } /* scalbn */
95
96 #undef two54
97 #undef twom54
98 #undef huge
99 #undef tiny
100