• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* @(#)s_scalbn.c 5.1 93/09/24 */
2  /*
3   * ====================================================
4   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5   *
6   * Developed at SunPro, a Sun Microsystems, Inc. business.
7   * Permission to use, copy, modify, and distribute this
8   * software is freely granted, provided that this notice
9   * is preserved.
10   * ====================================================
11   */
12  
13  #ifndef lint
14  static char rcsid[] = "$FreeBSD$";
15  #endif
16  
17  /*
18   * scalbnl (long double x, int n)
19   * scalbnl(x,n) returns x* 2**n  computed by  exponent
20   * manipulation rather than by actually performing an
21   * exponentiation or a multiplication.
22   */
23  
24  /*
25   * We assume that a long double has a 15-bit exponent.  On systems
26   * where long double is the same as double, scalbnl() is an alias
27   * for scalbn(), so we don't use this routine.
28   */
29  
30  #include <sys/cdefs.h>
31  #include <float.h>
32  #include <math.h>
33  
34  #include "fpmath.h"
35  
36  #if LDBL_MAX_EXP != 0x4000
37  #error "Unsupported long double format"
38  #endif
39  
40  static const long double
41  huge = 0x1p16000L,
42  tiny = 0x1p-16000L;
43  
44  long double
scalbnl(long double x,int n)45  scalbnl (long double x, int n)
46  {
47  	union IEEEl2bits u;
48  	int k;
49  	u.e = x;
50          k = u.bits.exp;				/* extract exponent */
51          if (k==0) {				/* 0 or subnormal x */
52              if ((u.bits.manh|u.bits.manl)==0) return x;	/* +-0 */
53  	    u.e *= 0x1p+128;
54  	    k = u.bits.exp - 128;
55              if (n< -50000) return tiny*x; 	/*underflow*/
56  	    }
57          if (k==0x7fff) return x+x;		/* NaN or Inf */
58          k = k+n;
59          if (k >= 0x7fff) return huge*copysignl(huge,x); /* overflow  */
60          if (k > 0) 				/* normal result */
61  	    {u.bits.exp = k; return u.e;}
62          if (k <= -128)
63              if (n > 50000) 	/* in case integer overflow in n+k */
64  		return huge*copysign(huge,x);	/*overflow*/
65  	    else return tiny*copysign(tiny,x); 	/*underflow*/
66          k += 128;				/* subnormal result */
67  	u.bits.exp = k;
68          return u.e*0x1p-128;
69  }
70  
71  __strong_reference(scalbnl, ldexpl);
72