Blame sysdeps/ieee754/dbl-64/s_scalbn.c

Packit 6c4009
/*
Packit 6c4009
 * ====================================================
Packit 6c4009
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Packit 6c4009
 *
Packit 6c4009
 * Developed at SunPro, a Sun Microsystems, Inc. business.
Packit 6c4009
 * Permission to use, copy, modify, and distribute this
Packit 6c4009
 * software is freely granted, provided that this notice
Packit 6c4009
 * is preserved.
Packit 6c4009
 * ====================================================
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * scalbn (double x, int n)
Packit 6c4009
 * scalbn(x,n) returns x* 2**n  computed by  exponent
Packit 6c4009
 * manipulation rather than by actually performing an
Packit 6c4009
 * exponentiation or a multiplication.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
Packit 6c4009
static const double
Packit 6c4009
  two54 = 1.80143985094819840000e+16,  /* 0x43500000, 0x00000000 */
Packit 6c4009
  twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
Packit 6c4009
  huge = 1.0e+300,
Packit 6c4009
  tiny = 1.0e-300;
Packit 6c4009
Packit 6c4009
double
Packit 6c4009
__scalbn (double x, int n)
Packit 6c4009
{
Packit 6c4009
  int32_t k, hx, lx;
Packit 6c4009
  EXTRACT_WORDS (hx, lx, x);
Packit 6c4009
  k = (hx & 0x7ff00000) >> 20;                  /* extract exponent */
Packit 6c4009
  if (__glibc_unlikely (k == 0))                   /* 0 or subnormal x */
Packit 6c4009
    {
Packit 6c4009
      if ((lx | (hx & 0x7fffffff)) == 0)
Packit 6c4009
	return x;                                  /* +-0 */
Packit 6c4009
      x *= two54;
Packit 6c4009
      GET_HIGH_WORD (hx, x);
Packit 6c4009
      k = ((hx & 0x7ff00000) >> 20) - 54;
Packit 6c4009
    }
Packit 6c4009
  if (__glibc_unlikely (k == 0x7ff))
Packit 6c4009
    return x + x;                                       /* NaN or Inf */
Packit 6c4009
  if (__glibc_unlikely (n < -50000))
Packit 6c4009
    return tiny * __copysign (tiny, x);   /*underflow*/
Packit 6c4009
  if (__glibc_unlikely (n > 50000 || k + n > 0x7fe))
Packit 6c4009
    return huge * __copysign (huge, x);   /* overflow  */
Packit 6c4009
  /* Now k and n are bounded we know that k = k+n does not
Packit 6c4009
     overflow.  */
Packit 6c4009
  k = k + n;
Packit 6c4009
  if (__glibc_likely (k > 0))                    /* normal result */
Packit 6c4009
    {
Packit 6c4009
      SET_HIGH_WORD (x, (hx & 0x800fffff) | (k << 20)); return x;
Packit 6c4009
    }
Packit 6c4009
  if (k <= -54)
Packit 6c4009
    return tiny * __copysign (tiny, x);         /*underflow*/
Packit 6c4009
  k += 54;                                      /* subnormal result */
Packit 6c4009
  SET_HIGH_WORD (x, (hx & 0x800fffff) | (k << 20));
Packit 6c4009
  return x * twom54;
Packit 6c4009
}
Packit 6c4009
#ifdef NO_LONG_DOUBLE
Packit 6c4009
strong_alias (__scalbn, __scalbnl)
Packit 6c4009
#endif