3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-04 06:16:09 +00:00
z3/src/ast/fpa
Copilot 2f7ff62173
Fix soundness bug in fpa2bv mk_to_real: wrong exponent power for negative exponents (#9513)
`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>
2026-05-13 06:11:36 -04:00
..
bv2fpa_converter.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
bv2fpa_converter.h model refactor (#4723) 2020-10-05 14:13:05 -07:00
CMakeLists.txt move fpa 2020-08-29 11:16:21 -07:00
fpa2bv_converter.cpp Fix soundness bug in fpa2bv mk_to_real: wrong exponent power for negative exponents (#9513) 2026-05-13 06:11:36 -04:00
fpa2bv_converter.h Assorted fixes for floats (#6968) 2023-10-29 17:29:42 -07:00
fpa2bv_rewriter.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
fpa2bv_rewriter.h remove default destructors 2024-10-02 22:20:12 +01:00