| 449 | } |
| 450 | |
| 451 | expr FloatType::fromFloat(State &s, const expr &fp, const Type &from_type0, |
| 452 | unsigned nary, const expr &a, const expr &b, |
| 453 | const expr &c) const { |
| 454 | expr isnan = fp.isNaN(); |
| 455 | expr val = fp.float2BV(); |
| 456 | |
| 457 | if (isnan.isFalse()) |
| 458 | return val; |
| 459 | |
| 460 | unsigned fraction_bits = fractionBits(); |
| 461 | |
| 462 | // sign bit, exponent (-1), qnan bit (1) or snan (0), rest of fraction |
| 463 | expr var = s.getFreshNondetVar("#NaN", expr::mkUInt(0, 2)); |
| 464 | |
| 465 | ChoiceExpr<expr> exprs; |
| 466 | |
| 467 | // 1) preferred QNaN (1000..00) |
| 468 | exprs.add(expr::mkUInt(1, 1).concat_zeros(fraction_bits-1), expr(true)); |
| 469 | |
| 470 | // 2) input NaN |
| 471 | // 3) quieted input NaN |
| 472 | const FloatType *from_type = from_type0.getAsFloatType(); |
| 473 | |
| 474 | auto add_maybe_quiet = [&](const expr &e) { |
| 475 | // account for fpext/fptruc |
| 476 | auto orig_bw = from_type->fractionBits(); |
| 477 | expr fraction = e.trunc(orig_bw); |
| 478 | expr truncated_is_nan = true; |
| 479 | |
| 480 | if (orig_bw > fraction_bits) { |
| 481 | fraction = fraction.extract(orig_bw-1, orig_bw - fraction_bits); |
| 482 | truncated_is_nan = fraction != 0; |
| 483 | } else if (orig_bw < fraction_bits) { |
| 484 | fraction = fraction.concat_zeros(fraction_bits - fraction.bits()); |
| 485 | } |
| 486 | assert(!fraction.isValid() || fraction.bits() == fraction_bits); |
| 487 | |
| 488 | expr qnan = fraction.sign(); |
| 489 | expr quieted = var.extract(0, 0); |
| 490 | qnan = expr::mkIf(truncated_is_nan, qnan | quieted, expr::mkUInt(1, 1)); |
| 491 | exprs.add(qnan.concat(fraction.trunc(fraction_bits - 1)), |
| 492 | from_type->getFloat(e).isNaN()); |
| 493 | }; |
| 494 | if (nary >= 1) { |
| 495 | add_maybe_quiet(a); |
| 496 | if (nary >= 2) { |
| 497 | add_maybe_quiet(b); |
| 498 | if (nary >= 3) |
| 499 | add_maybe_quiet(c); |
| 500 | } |
| 501 | } |
| 502 | |
| 503 | // 4) target specific preferred QNaN (a set, possibly empty) |
| 504 | // approximated by adding just one more value |
| 505 | auto preferred_qnan_fraction |
| 506 | = expr::mkVar("#preferred_qnan", expr::mkUInt(0, fraction_bits - 1)); |
| 507 | exprs.add(expr::mkUInt(1, 1).concat(preferred_qnan_fraction), expr(true)); |
| 508 |
no test coverage detected