Skip to content

Conversation

baierd
Copy link
Contributor

@baierd baierd commented Sep 1, 2025

This PR adds 2 fallback methods for FloatingPointManager.toIeeeBitvector(FloatingPointFormula):

  • FloatingPointManager.toIeeeBitvector(FloatingPointFormula, String), returning the BV representation as a new variable with the given name. Special FP numbers are returned as the solver sees fit.
  • FloatingPointManager.toIeeeBitvector(FloatingPointFormula, String, Map<FloatingPointFormula, BitvectorFormula>), returning the BV representation as a new variable with the given name. Special FP numbers can be mapped to expected results, with the default behavior (if no mapping has been added) being like the previous method.

Both return a tuple BitvectorFormulaAndBooleanFormula, representing the bitvector of the input FP number, as well as the additional constraint needed as BooleanFormula. The constraint needs to be added to all assertion stacks that make use of the returned BitvectorFormula.

While implementing i found a problem in our implementation of FloatingPointType. Our returned significant precision is off by one. E.g. for single precision FP, we return significant size 23. But the standard defines exponent and significant as:

eb defines the number of bits in the exponent;
sb defines the number of bits in the significand, *including* the hidden bit.

Hence it should be 24.
As a consequence, we also return this wrongly for toSMTLIBString().

The solvers generally expect this to be the case, hence why we had 4 solvers with the code type.getMantissaSize() + 1, and only one solver without the + 1

Also, we don't communicate any information about our interpretation of FP precisions, hence the users might think that by building FormulaType.getFloatingPointType(8, 24) (first input is exponent, second is significant) they get a single precision FP-type, but in reality they get a total size of 33 bits currently. Our static implementation of the single/double precisions is fine however.

I added the capability to retrieve the precision from the solver directly, instead of using the JavaSMT type, as this was needed for this implementation. This addition is currently hidden from users, but could be exposed if needed. I exposed this API publicly, as it seems to fit well with getSize() for bitvectors, and offers a type-independent, solver based way of getting the FP sizes.

@baierd baierd self-assigned this Sep 1, 2025
@baierd
Copy link
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.

BaierD added 8 commits September 1, 2025 19:36
…he type/mantissa with/without sign bit and add sign bit to toString and toSMTLIBString representations
…a with/without sign bit and use those as far as possible to make the code unambiguous for mantissas
…n bit and add some assertions for mantissa/exponent
@baierd baierd requested a review from kfriedberger September 2, 2025 07:05
@baierd
Copy link
Contributor Author

baierd commented Sep 2, 2025

Do we want to document the typical returns of solvers for special FP numbers? There are multiple well defined return values for NaN as bitvector for example.

@baierd
Copy link
Contributor Author

baierd commented Sep 2, 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.

I mostly finished this as proposed. You can take a look. I feel like the API changes reduce the magic + 1 and - 1 by a large amount, increasing readability of the code. My guess is that users, especially new users, will benefit from that. The deprecation warning needs to be discussed/done.

…gnBitImpl() to reduce ambiguity + improve name of variable
@baierd
Copy link
Contributor Author

baierd commented Sep 2, 2025

I now split all changes in regard to FP mantissa into a dedicated PR here. We should first handle that PR, merge it, and then continue here.

Copy link
Member

@kfriedberger kfriedberger left a comment

Choose a reason for hiding this comment

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

I am unsure whether this special handling for FP2IEEEBV is really required. This feature looks errorprone and quite complex to understand. I would prefer that solvers provide their internal implementation for this, and JavaSMT just provides the wrapper/bindings instead of such parts. There might be potential, but also the burden for the developer, especially when using a method that returns additional constraints.

*/
public static FloatingPointType getFloatingPointTypeWithSignBit(
int exponentSize, int mantissaSizeWithSignBit) {
return new FloatingPointType(exponentSize, mantissaSizeWithSignBit);
Copy link
Member

Choose a reason for hiding this comment

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

Where is the difference in this method to the one before? Both methods create the same object with the same parameters, even if they are named differently.

* Returns the size of the mantissa (also called a coefficient or significant), excluding the sign
* bit.
*/
// TODO: mark as soon to be deprecated
Copy link
Member

Choose a reason for hiding this comment

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

Do we really want to remove this simple method? Is the documentation not sufficient?

Please provide a replacement code snippet for inlining deprecated code.

+ "methods toIeeeBitvector"
+ "(FloatingPointFormula, String) and/or "
+ "toIeeeBitvector(FloatingPointFormula, String, Map)");
}
Copy link
Member

Choose a reason for hiding this comment

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

This message is quite misleading: The message will be seen by a user of the application, not by the developer calling JavaSMT. How will the user of the application (e.g., CPAchecker) change that call? That might be impossible.

@@ -519,4 +621,28 @@ protected static String getBvRepresentation(BigInteger integer, int size) {
}
return String.copyValueOf(values);
}

public static final class BitvectorFormulaAndBooleanFormula {
Copy link
Member

Choose a reason for hiding this comment

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

Why not just use a Google-Auto-class? In the future this might be a record.

}

@Override
public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
Copy link
Member

Choose a reason for hiding this comment

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

This method is weird. Does is really handle NaN as expected?

int getMantissaSizeWithSignBit(FloatingPointFormula number);

/** Returns the size of the exponent for the given {@link FloatingPointFormula}. */
int getExponentSize(FloatingPointFormula number);
Copy link
Member

Choose a reason for hiding this comment

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

Do we really need these two methods?
The user already can access the FormulaType directly and extract exponentSize and mantissaSize from the returned FP-FormulaType.

protected int getExponentSizeImpl(Term fp) {
return fp.sort().fp_exp_size();
}

Copy link
Member

Choose a reason for hiding this comment

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

I doupt the requirement for these two methods.

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

Successfully merging this pull request may close these issues.

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