amath  1.8.5
Simple command line calculator
scalbn.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2014-2018 Carsten Sonne Larsen <cs@innolan.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * Project homepage:
26  * https://amath.innolan.net
27  *
28  * The original source code can be obtained from:
29  * http://www.netlib.org/fdlibm/s_scalbn.c
30  *
31  * =================================================================
32  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
33  *
34  * Developed at SunSoft, a Sun Microsystems, Inc. business.
35  * Permission to use, copy, modify, and distribute this
36  * software is freely granted, provided that this notice
37  * is preserved.
38  * =================================================================
39  */
40 
41 #include "prim.h"
42 
43 /*
44  * scalbn (double x, int n)
45  * scalbn(x,n) returns x* 2**n computed by exponent
46  * manipulation rather than by actually performing an
47  * exponentiation or a multiplication.
48  */
49 
50 static const double
51  two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
52  twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
53  huge = 1.0e+300,
54  tiny = 1.0e-300;
55 
56 double scalbn(double x, int32_t n)
57 {
58  int32_t k, hx, lx;
59  EXTRACT_WORDS(hx, lx, x);
60  k = (hx & 0x7ff00000) >> 20; /* extract exponent */
61  if (k == 0)
62  { /* 0 or subnormal x */
63  if ((lx | (hx & 0x7fffffff)) == 0)
64  return x; /* +-0 */
65  x *= two54;
66  GET_HIGH_WORD(hx, x);
67  k = ((hx & 0x7ff00000) >> 20) - 54;
68  if (n < -50000)
69  return tiny * x; /*underflow*/
70  }
71  if (k == 0x7ff)
72  return x + x; /* NaN or Inf */
73  k = k + n;
74  if (k > 0x7fe)
75  return huge * copysign(huge, x); /* overflow */
76  if (k > 0) /* normal result */
77  {
78  SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
79  return x;
80  }
81  if (k <= -54)
82  {
83  if (n > 50000) /* in case integer overflow in n+k */
84  return huge * copysign(huge, x); /*overflow*/
85  else
86  return tiny * copysign(tiny, x); /*underflow*/
87  }
88  k += 54; /* subnormal result */
89  SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
90  return x * twom54;
91 }
#define GET_HIGH_WORD(i, d)
Get the more significant 32 bit int from a double.
Definition: prim.h:167
double scalbn(double x, int32_t n)
Definition: scalbn.c:56
static const double two54
Definition: scalbn.c:51
static const double tiny
Definition: scalbn.c:54
#define EXTRACT_WORDS(ix0, ix1, d)
Get two 32 bit ints from a double.
Definition: prim.h:156
double copysign(double x, double y)
Returns a value with the magnitude of x and with the sign bit of y.
Definition: csign.c:47
static const double huge
Definition: scalbn.c:53
#define SET_HIGH_WORD(d, v)
Set the more significant 32 bits of a double from an int.
Definition: prim.h:198
static const double twom54
Definition: scalbn.c:52