Three bugs in the def ref-counting infrastructure:
1. dec_ref() incremented (++) instead of decrementing (--) the ref count,
so objects were never freed.
2. def_ref lacked copy and move constructors, so the compiler-generated
default copy just copied the raw pointer without inc_ref. This caused
use-after-free when def_ref values were copied into vectors.
3. Compound def types (add_def, mul_def, div_def) lacked destructors to
dec_ref their children. Added virtual destructor to base def class
and child-releasing destructors to compound types.
Fixes the memory leak from #7027 (model_based_opt.cpp:81).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When check_nla returns FC_CONTINUE it means NLA found constraint
violations and added lemmas. The current LP value is a valid lower
bound, so the status should be FEASIBLE, not UNBOUNDED.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add checkpoint() call in gcd_prs() main loop so polynomial GCD
computation respects rlimit/timeout. Add cancellation callback to
HNF calculation so it can be interrupted when the solver is cancelled.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The arith rewriter now recognizes that x * (x + 1) >= 0 for all
integers, since no integer lies strictly between -1 and 0.
Two changes:
1. is_non_negative: detect products where unpaired factors are
consecutive integer expressions (differ by exactly 1), handling
both +1 and -1 offsets and n-ary additions
2. is_separated: return true for (>= non_negative_mul 0), restricted
to multiplication expressions to avoid disrupting other theories
Also adds regression tests for the new simplification.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add (set-option :model_validate true) to each SMT-LIB2 spec in
src/test/fpa.cpp, and add ENSURE checks that the output does not
contain the string "invalid".
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
Adds src/test/fpa.cpp with test_fp_to_real_denormal() exercising the
bug reported in the issue: denormal floating-point values in
(_ FloatingPoint 2 24) were getting wrong fp.to_real values because
mk_to_real was not subtracting the normalization shift lz from the
exponent.
Tests verify:
- The specific denormal from the bug report is NOT > 1.0
- Two other denormals have correct real values (0.5 and 0.125)
- A normal value is correctly identified as > 1.0
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
The mk_to_real function in fpa2bv_converter.cpp was missing the
normalization shift adjustment (lz) when computing the real-valued
exponent for denormal floating-point numbers.
When unpack(x, sgn, sig, exp, lz, normalize=true) normalizes a denormal
by shifting the significand left by lz positions, the returned exp does
not account for this shift. All other callers (mk_mul, mk_div, mk_fma)
correctly subtract lz from the exponent, but mk_to_real was missing this.
The fix subtracts zero-extended lz from the sign-extended exp to get the
true exponent, matching the convention used by other FP operations.
Fixes incorrect model with (_ FloatingPoint 2 24) and fp.to_real.
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>