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