xref: /inferno-os/libmath/fdlibm/s_scalbn.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 /* derived from /netlib/fdlibm */
2 
3 /* @(#)s_scalbn.c 1.3 95/01/18 */
4 /*
5  * ====================================================
6  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
7  *
8  * Developed at SunSoft, a Sun Microsystems, Inc. business.
9  * Permission to use, copy, modify, and distribute this
10  * software is freely granted, provided that this notice
11  * is preserved.
12  * ====================================================
13  */
14 
15 /*
16  * scalbn (double x, int n)
17  * scalbn(x,n) returns x* 2**n  computed by  exponent
18  * manipulation rather than by actually performing an
19  * exponentiation or a multiplication.
20  */
21 
22 #include "fdlibm.h"
23 
24 static const double
25 two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
26 twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
27 Huge   = 1.0e+300,
28 tiny   = 1.0e-300;
29 
scalbn(double x,int n)30 	double scalbn (double x, int n)
31 {
32 	int  k,hx,lx;
33 	hx = __HI(x);
34 	lx = __LO(x);
35         k = (hx&0x7ff00000)>>20;		/* extract exponent */
36         if (k==0) {				/* 0 or subnormal x */
37             if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
38 	    x *= two54;
39 	    hx = __HI(x);
40 	    k = ((hx&0x7ff00000)>>20) - 54;
41             if (n< -50000) return tiny*x; 	/*underflow*/
42 	    }
43         if (k==0x7ff) return x+x;		/* NaN or Inf */
44         k = k+n;
45         if (k >  0x7fe) return Huge*copysign(Huge,x); /* overflow  */
46         if (k > 0) 				/* normal result */
47 	    {__HI(x) = (hx&0x800fffff)|(k<<20); return x;}
48         if (k <= -54)
49             if (n > 50000) 	/* in case integer overflow in n+k */
50 		return Huge*copysign(Huge,x);	/*overflow*/
51 	    else return tiny*copysign(tiny,x); 	/*underflow*/
52         k += 54;				/* subnormal result */
53         __HI(x) = (hx&0x800fffff)|(k<<20);
54         return x*twom54;
55 }
56