crude overflow and underflow tests for exp(a). a_low <= a <= a_high */
| 4370 | |
| 4371 | /* crude overflow and underflow tests for exp(a). a_low <= a <= a_high */ |
| 4372 | static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r, |
| 4373 | const bf_t *a_low, const bf_t *a_high, |
| 4374 | limb_t prec, bf_flags_t flags) |
| 4375 | { |
| 4376 | bf_t T_s, *T = &T_s; |
| 4377 | bf_t log2_s, *log2 = &log2_s; |
| 4378 | slimb_t e_min, e_max; |
| 4379 | |
| 4380 | if (a_high->expn <= 0) |
| 4381 | return 0; |
| 4382 | |
| 4383 | e_max = (limb_t)1 << (bf_get_exp_bits(flags) - 1); |
| 4384 | e_min = -e_max + 3; |
| 4385 | if (flags & BF_FLAG_SUBNORMAL) |
| 4386 | e_min -= (prec - 1); |
| 4387 | |
| 4388 | bf_init(s, T); |
| 4389 | bf_init(s, log2); |
| 4390 | bf_const_log2(log2, LIMB_BITS, BF_RNDU); |
| 4391 | bf_mul_ui(T, log2, e_max, LIMB_BITS, BF_RNDU); |
| 4392 | /* a_low > e_max * log(2) implies exp(a) > e_max */ |
| 4393 | if (bf_cmp_lt(T, a_low) > 0) { |
| 4394 | /* overflow */ |
| 4395 | bf_delete(T); |
| 4396 | bf_delete(log2); |
| 4397 | return bf_set_overflow(r, 0, prec, flags); |
| 4398 | } |
| 4399 | /* a_high < (e_min - 2) * log(2) implies exp(a) < (e_min - 2) */ |
| 4400 | bf_const_log2(log2, LIMB_BITS, BF_RNDD); |
| 4401 | bf_mul_si(T, log2, e_min - 2, LIMB_BITS, BF_RNDD); |
| 4402 | if (bf_cmp_lt(a_high, T)) { |
| 4403 | int rnd_mode = flags & BF_RND_MASK; |
| 4404 | |
| 4405 | /* underflow */ |
| 4406 | bf_delete(T); |
| 4407 | bf_delete(log2); |
| 4408 | if (rnd_mode == BF_RNDU) { |
| 4409 | /* set the smallest value */ |
| 4410 | bf_set_ui(r, 1); |
| 4411 | r->expn = e_min; |
| 4412 | } else { |
| 4413 | bf_set_zero(r, 0); |
| 4414 | } |
| 4415 | return BF_ST_UNDERFLOW | BF_ST_INEXACT; |
| 4416 | } |
| 4417 | bf_delete(log2); |
| 4418 | bf_delete(T); |
| 4419 | return 0; |
| 4420 | } |
| 4421 | |
| 4422 | int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) |
| 4423 | { |
no test coverage detected