float FN_PROTOTYPE(exp2f)(float x) { static const float max_exp2_arg = 128.0F, /* 0x43000000 */ min_exp2_arg = -149.0F, /* 0xc3150000 */ log2 = 6.931471824645996e-01F, /* 0x3f317218 */ one_by_32_lead = 0.03125F; float y, z1, z2, z; int m; unsigned int ux, ax; /* Computation of exp2f(x). We compute the values m, z1, and z2 such that exp2f(x) = 2**m * (z1 + z2), where exp2f(x) is 2**x. Computations needed in order to obtain m, z1, and z2 involve three steps. First, we reduce the argument x to the form x = n/32 + remainder, where n has the value of an integer and |remainder| <= 1/64. The value of n = x * 32 rounded to the nearest integer and the remainder = x - n/32. Second, we approximate exp2f(r1 + r2) - 1 where r1 is the leading part of the remainder and r2 is the trailing part of the remainder. Third, we reconstruct exp2f(x) so that exp2f(x) = 2**m * (z1 + z2). */ GET_BITS_SP32(x, ux); ax = ux & (~SIGNBIT_SP32); if (ax >= 0x43000000) /* abs(x) >= 128.0 */ { if(ax >= 0x7f800000) { /* x is either NaN or infinity */ if (ux & MANTBITS_SP32) /* x is NaN */ return x + x; /* Raise invalid if it is a signalling NaN */ else if (ux & SIGNBIT_SP32) /* x is negative infinity; return 0.0 with no flags. */ return 0.0F; else /* x is positive infinity */ return x; } if (x > max_exp2_arg) /* Return +infinity with overflow flag */ return retval_errno_erange_overflow(x); else if (x < min_exp2_arg) /* x is negative. Return +zero with underflow and inexact flags */ return retval_errno_erange_underflow(x); } /* Handle small arguments separately */ if (ax < 0x3cb8aa3b) /* abs(x) < 1/(64*log2) */ { if (ax < 0x32800000) /* abs(x) < 2^(-26) */ return 1.0F + x; /* Raises inexact if x is non-zero */ else { y = log2*x; z = (((((((( 1.0F/40320)*y+ 1.0F/5040)*y+ 1.0F/720)*y+ 1.0F/120)*y+ 1.0F/24)*y+ 1.0F/6)*y+ 1.0F/2)*y+ 1.0F)*y + 1.0F; } } else { /* Find m, z1 and z2 such that exp2f(x) = 2**m * (z1 + z2) */ splitexpf(x, log2, 32.0F, one_by_32_lead, 0.0F, &m, &z1, &z2); /* Scale (z1 + z2) by 2.0**m */ if (m >= EMIN_SP32 && m <= EMAX_SP32) z = scaleFloat_1((float)(z1+z2),m); else z = scaleFloat_2((float)(z1+z2),m); } return z; }
float FN_PROTOTYPE(expf)(float x) { static const float max_exp_arg = 8.8722839355E+01F, /* 0x42B17218 */ min_exp_arg = -1.0327893066E+02F, /* 0xC2CE8ED0 */ thirtytwo_by_log2 = 4.6166240692E+01F, /* 0x4238AA3B */ log2_by_32_lead = 2.1659851074E-02F, /* 0x3CB17000 */ log2_by_32_tail = 9.9831822808E-07F; /* 0x3585FDF4 */ float z1, z2, z; int m; unsigned int ux, ax; /* Computation of exp(x). We compute the values m, z1, and z2 such that exp(x) = 2**m * (z1 + z2), where exp(x) is the natural exponential of x. Computations needed in order to obtain m, z1, and z2 involve three steps. First, we reduce the argument x to the form x = n * log2/32 + remainder, where n has the value of an integer and |remainder| <= log2/64. The value of n = x * 32/log2 rounded to the nearest integer and the remainder = x - n*log2/32. Second, we approximate exp(r1 + r2) - 1 where r1 is the leading part of the remainder and r2 is the trailing part of the remainder. Third, we reconstruct the exponential of x so that exp(x) = 2**m * (z1 + z2). */ GET_BITS_SP32(x, ux); ax = ux & (~SIGNBIT_SP32); if (ax >= 0x42B17218) /* abs(x) >= 88.7... */ { if(ax >= 0x7f800000) { /* x is either NaN or infinity */ if (ux & MANTBITS_SP32) /* x is NaN */ return x + x; /* Raise invalid if it is a signalling NaN */ else if (ux & SIGNBIT_SP32) /* x is negative infinity; return 0.0 with no flags */ return 0.0; else /* x is positive infinity */ return x; } if (x > max_exp_arg) /* Return +infinity with overflow flag */ return retval_errno_erange_overflow(x); else if (x < min_exp_arg) /* x is negative. Return +zero with underflow and inexact flags */ return retval_errno_erange_underflow(x); } /* Handle small arguments separately */ if (ax < 0x3c800000) /* abs(x) < 1/64 */ { if (ax < 0x32800000) /* abs(x) < 2^(-26) */ return 1.0F + x; /* Raises inexact if x is non-zero */ else z = ((((((( 1.0F/5040)*x+ 1.0F/720)*x+ 1.0F/120)*x+ 1.0F/24)*x+ 1.0F/6)*x+ 1.0F/2)*x+ 1.0F)*x + 1.0F; } else { /* Find m and z such that exp(x) = 2**m * (z1 + z2) */ splitexpf(x, 1.0F, thirtytwo_by_log2, log2_by_32_lead, log2_by_32_tail, &m, &z1, &z2); /* Scale (z1 + z2) by 2.0**m */ if (m >= EMIN_SP32 && m <= EMAX_SP32) z = scaleFloat_1((float)(z1+z2),m); else z = scaleFloat_2((float)(z1+z2),m); } return z; }
float FN_PROTOTYPE(exp10f)(float x) { static const float max_exp10_arg = 3.8531841278E+01F, /* 0x421A209B */ min_exp10_arg =-4.4853469848E+01F, /* 0xC23369F4 */ log10 = 2.3025850929E+00F, /* 0x40135D8E */ thirtytwo_by_log10of2 = 1.0630169677E+02F, /* 0x42D49A78 */ log10of2_by_32_lead = 9.4070434570E-03F, /* 0x3C1A2000 */ log10of2_by_32_tail = 1.4390730030E-07F; /* 0x341A84F0 */ float y, z1, z2, z; int m; unsigned int ux, ax; /* Computation of exp10f (x). We compute the values m, z1, and z2 such that exp10f(x) = 2**m * (z1 + z2), where exp10f(x) is 10**x. Computations needed in order to obtain m, z1, and z2 involve three steps. First, we reduce the argument x to the form x = n * log10of2/32 + remainder, where n has the value of an integer and |remainder| <= log10of2/64. The value of n = x * 32/log10of2 rounded to the nearest integer and the remainder = x - n*log10of2/32. Second, we approximate exp10f(r1 + r2) - 1 where r1 is the leading part of the remainder and r2 is the trailing part of the remainder. Third, we reconstruct exp10f(x) so that exp10f(x) = 2**m * (z1 + z2). */ GET_BITS_SP32(x, ux); ax = ux & (~SIGNBIT_SP32); if (ax >= 0x421A209B) /* abs(x) >= 38.5... */ { if(ax >= 0x7f800000) { /* x is either NaN or infinity */ if (ux & MANTBITS_SP32) /* x is NaN */ return x + x; /* Raise invalid if it is a signalling NaN */ else if (ux & SIGNBIT_SP32) /* x is negative infinity; return 0.0 with no flags. */ return 0.0F; else /* x is positive infinity */ return x; } if (x > max_exp10_arg) /* Return +infinity with overflow flag */ return retval_errno_erange_overflow(x); else if (x < min_exp10_arg) /* x is negative. Return +zero with underflow and inexact flags */ return retval_errno_erange_underflow(x); } /* Handle small arguments separately */ if (ax < 0x3bde5bd9) /* abs(x) < 1/(64*log10) */ { if (ax < 0x32800000) /* abs(x) < 2^(-26) */ return 1.0F + x; /* Raises inexact if x is non-zero */ else { y = log10*x; z = (((((((( 1.0F/40320)*x+ 1.0F/5040)*y+ 1.0F/720)*y+ 1.0F/120)*y+ 1.0F/24)*y+ 1.0F/6)*y+ 1.0F/2)*y+ 1.0F)*y + 1.0F; } } else { /* Find m, z1 and z2 such that exp10f(x) = 2**m * (z1 + z2) */ splitexpf(x, log10, thirtytwo_by_log10of2, log10of2_by_32_lead, log10of2_by_32_tail, &m, &z1, &z2); /* Scale (z1 + z2) by 2.0**m */ if (m >= EMIN_SP32 && m <= EMAX_SP32) z = scaleFloat_1((float)(z1+z2),m); else z = scaleFloat_2((float)(z1+z2),m); } return z; }