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