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
40double
41scalbn (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