#ifdef HAVE_CONFIG_H #include #endif #include #ifdef HAVE_CONFIG_H #include #endif #include #include "math_impl.h" /* * x * FLT_RADIX^n with FLT_RADIX 2 (C23 7.12.6.6), all three precisions * and both exponent-argument types. scalbn takes an int n, scalbln a long * n; otherwise the two families are semantically identical to ldexp (they * share the exact same scale cores and overflow-to-+-Inf-with-ERANGE * behavior, and subnormal inputs are handled exactly like subnormal * outputs). The scalbln functions clamp the long exponent to +-20000 * first: any magnitude beyond that saturates every result to +-Inf or +-0 * in all three formats, and clamping keeps the arithmetic inside int range * with no shift by a huge count. */ /* * As ldexp (see ldexp.c) for a double x and an int n. */ double scalbn(double x, int n) { int overflowed = 0; double r = vl_scale2_d(x, n, &overflowed); #ifdef HAVE_CONFIG_H if (overflowed) { errno = ERANGE; } #endif return r; } float scalbnf(float x, int n) { int overflowed = 0; float r = vl_scale2_f(x, n, &overflowed); #ifdef HAVE_CONFIG_H if (overflowed) { errno = ERANGE; } #endif return r; } long double scalbnl(long double x, int n) { int overflowed = 0; long double r = vl_scale2_ld(x, n, &overflowed); #ifdef HAVE_CONFIG_H if (overflowed) { errno = ERANGE; } #endif return r; } /* * The scalbln family: as scalbn with the exponent given as a long. * n is first clamped into [-20000, 20000]; anything beyond saturates every * precision's range (the largest meaningful long-double exponent is below * 16446 in magnitude), so no precision is lost by the clamp. */ double scalbln(double x, long n) { if (n > 20000) { n = 20000; } else if (n < -20000) { n = -20000; } return scalbn(x, (int)n); } float scalblnf(float x, long n) { if (n > 20000) { n = 20000; } else if (n < -20000) { n = -20000; } return scalbnf(x, (int)n); } long double scalblnl(long double x, long n) { if (n > 20000) { n = 20000; } else if (n < -20000) { n = -20000; } return scalbnl(x, (int)n); }