Skip to content

Add IEEE-754 Floating Point to Bitvector Conversion Fallback#512

Open
baierd wants to merge 92 commits into
masterfrom
504-ieee-floating-point-to-bitvector-conversion-not-supported-in-all-solvers
Open

Add IEEE-754 Floating Point to Bitvector Conversion Fallback#512
baierd wants to merge 92 commits into
masterfrom
504-ieee-floating-point-to-bitvector-conversion-not-supported-in-all-solvers

Conversation

@baierd
Copy link
Copy Markdown
Contributor

@baierd baierd commented Sep 1, 2025

This PR adds a fallback method for FloatingPointManager.toIeeeBitvector(FloatingPointFormula):

  • FloatingPointManager.toIeeeBitvector(FloatingPointFormula, BitvectorFormula), returns a BooleanFormula that is the result of the equality of the FP input with the BV input (BV is equal to the floating-points bit representation according to the IEEE 754-2008 floating-point format). Special FP numbers are returned as the solver sees fit.

Tests for this method have been added. This includes the SMTLIB2 output of it, and the native toIeeeBitvector() method, showing us what solver can parse what output.

Furthermore, i added common FP type checks in the wrapping function of AbstractFloatingPointFormulaManager

@baierd baierd self-assigned this Sep 1, 2025
@baierd
Copy link
Copy Markdown
Contributor Author

baierd commented Sep 1, 2025

@kfriedberger the SMTLIB2 standard defines the size of an FP as mantissa + exponent with the mantissa including the sign bit. Our current implementation excludes it, and we do not document this properly in all cases, especially the FP type constructor.

This is problematic, as the standard defines the size of a BV representation of a FP as mantissa + exponent, which is off by 1 in our returned values (this is how i noticed btw.).

My proposal (already WIP):

  • Fix FP type etc. to include the sign bit, and switch to what the standard defines in our internal implementation. Only MathSAT5 expects the mantissa to not include the sign bit.
  • Announce the FP type constructor to be deprecated in the near future due to this.
  • Add new constructors for FP type that specify the inclusion in the method name.
  • Add methods to get the sizes of mantissa and exponent to FloatingPointFormulaManager based on the solvers terms instead of our types (similar to what we do for BV width), allowing assertions and checking the solvers interpretation for our type.

I don't want to change the current FP-Type constructor, as users expect this to not change behavior.

What do you think? I am happy about thoughts/ideas.

Edit: it would probably be a good idea to also update the API for getMantissaSize() to getMantissaSizeWithSignBit() and getMantissaSizeWithoutSignBit() and deprecate the old method.

+ " operation by utilizing the 'to_fp' operation.";
throw new IllegalArgumentException(
illegalArgumentException.getMessage() + additionalMessage, illegalArgumentException);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4x getMessage --> maybe use a variable for that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Thanks for noticing!

I also extracted it into a method and moved the call due to how parsing was changed in parseAll().

* only used to verify the exponent and mantissa sizes of pTerm.
* @return input term pTerm in a {@link FloatingPointFormula}.
*/
protected FloatingPointFormula wrapFloatingPointAndAssertType(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just keep the name wrap and make it so complex?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more detailed assertions were helpful when developing the BV-FP conversion, as the solvers handle things distinctly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check(s) are now assertions

return getFormulaCreator().encapsulateFloatingPoint(pTerm);
}

protected FloatingPointFormula wrapFloatingPoint(TFormulaInfo pTerm) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this second method really needed? Why not just name it wrap in this context?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed both and simplified/combined them. This can of course also be done in a distinct way, but this implementation guarantees that we will always check the correct assertion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this second method really needed?

It makes it easier to understand. The assertions were helpful when developing the BV-FP conversion, but are not strictly necessary. We can also use a single method that uses wrap(term, null) or so if you want.

termManager.mk_term(Kind.FP_TO_FP_FROM_BV, bvVar, sizeExp, sizeSig),
pNumber));

bitwuzlaCreator.addConstraintForVariable(newVariable, equal);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this piece of code will remove the reason for BitwuzlaFormulaCreator::constraintsForVariables. Please clean up the unused code there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot, thanks! I removed it.

@kfriedberger
Copy link
Copy Markdown
Member

The idea of this PR is quite similar to the implementation of IntegerFormulaManager::modularCongruence, i.e., a left and right operand are combined and a boolean result is returned.

Some request from my side:

  • the naming is not optimal: toIEEEBitvector(fp, bv) should be renamed to equal/bitsEqual/bitwiseEqual(fp, bv), because this is the exact meaning: assignment/equality of bits and a symmetrical nature. The parameter name is ugly, too.
  • cleaning up special logic for basic contraints in solvers.

Overall, the idea is good. If it works for special cases like NaN, Inf, Subnormal, etc, then fine for me.

baierd added 16 commits March 26, 2026 17:03
…rsion-not-supported-in-all-solvers

# Conflicts:
#	src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFloatingPointManager.java
#	src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FloatingPointFormulaManager.java
#	src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FloatingPointFormulaManager.java
…in Bitwuzla needed for old bv to fp workaround impl
…or messages to a method and the invocation into parseAllImpl() as this is called for all parsing operations
…pected to throw, as if requireParser() fails, the test would fail with a weird error
…rsion-not-supported-in-all-solvers

# Conflicts:
#	src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
#	src/org/sosy_lab/java_smt/basicimpl/AbstractFormulaManager.java
#	src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
#	src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
#	src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
…rsion-not-supported-in-all-solvers

# Conflicts:
#	src/org/sosy_lab/java_smt/basicimpl/AbstractFormulaManager.java
…nsive check and make the cheap checks message lazy
@baierd
Copy link
Copy Markdown
Contributor Author

baierd commented May 22, 2026

the naming is not optimal: toIEEEBitvector(fp, bv) should be renamed to equal/bitsEqual/bitwiseEqual(fp, bv), because this is the exact meaning: assignment/equality of bits and a symmetrical nature. The parameter name is ugly, too.

I chose toIEEEBitvector(fp, bv) as the SMTLIB2 standard defines this new implementation as the canonical way of implementing the functionality that we offer with the method toIEEEBitvector(fp). I would argue that changing the name could lead to users not understanding that this offers the same functionality.

Note: It returns a BooleanFormula only because the standard defines it that way. We could theoretically switch the bitvector and bool, such that a BitvectorFormula is returned, and a BooleanFormula is needed as argument. Alternativly: we can always just return a tuple of <BitvectorFormula, BooleanFormula>.

If it works for special cases like NaN, Inf, Subnormal, etc, then fine for me.

It works due to SMTLIB(2) only defining each special FP number only once. Hence "all" bitvector NaN representations return the "same" NaN (as defined by SMTLIB2). If translated back, the original bitvector is returned. I added tests for all special FP numbers that check this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

IEEE Floating-point to Bitvector Conversion Not Supported in All Solvers

3 participants