mirror of
https://github.com/Z3Prover/z3
synced 2026-05-16 07:05:35 +00:00
`fpa2bv_converter::mk_to_real` computed `2^(1/|exp|)` instead of `1/(2^|exp|)` for floats with negative exponents, causing the NRA solver to reach contradictory conclusions and return spurious `unsat` for satisfiable QF_FPLRA formulas. ## Root Cause After the loop that evaluates `exp2 = |unbiased_exp|` as an integer, the code took `1/exp2` (reciprocal of the integer) before calling `mk_power`, yielding `2^(1/3)` instead of `2^(-3) = 1/8` for a float with exponent -3: ```cpp // Buggy one_div_exp2 = mk_div(one, exp2); // 1/|exp|, not 1/2^|exp| exp2 = mk_ite(exp_is_neg, one_div_exp2, exp2); two_exp2 = mk_power(two, exp2); // 2^(1/3) ≠ 1/8 for exp=-3 ``` ## Fix Compute the power of 2 first, then invert it: ```cpp // Fixed two_exp2 = mk_power(two, exp2); // 2^|exp| one_div_two_exp2 = mk_div(one, two_exp2); // 1/(2^|exp|) two_exp2 = mk_ite(exp_is_neg, one_div_two_exp2, two_exp2); // correct 2^exp ``` ## Impact - **QF_FPLRA**: `to_fp(RTZ, r)` with a symbolic real `r` constrained to an interval containing a float's exact rational value now correctly returns `sat`. - **fp.to_real**: Fixes incorrect real-valued encoding for all floats with negative exponents, including denormals (which adjust the exponent by subtracting leading-zero count). A regression test covering the reported case is added to `src/test/fpa.cpp`. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> |
||
|---|---|---|
| .. | ||
| ackermannization | ||
| api | ||
| ast | ||
| cmd_context | ||
| math | ||
| model | ||
| muz | ||
| nlsat | ||
| opt | ||
| params | ||
| parsers | ||
| qe | ||
| sat | ||
| shell | ||
| smt | ||
| solver | ||
| tactic | ||
| test | ||
| util | ||
| CMakeLists.txt | ||