diff --git a/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
index 62bb3afbe4..91a9d7d6bc 100644
--- a/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
@@ -8,13 +8,15 @@
package org.sosy_lab.java_smt.api;
-import static org.sosy_lab.java_smt.api.FormulaType.getFloatingPointType;
+import static org.sosy_lab.java_smt.api.FormulaType.getFloatingPointTypeWithoutSignBit;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.Map;
import org.sosy_lab.common.rationals.Rational;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
+import org.sosy_lab.java_smt.basicimpl.AbstractFloatingPointFormulaManager.BitvectorFormulaAndBooleanFormula;
/**
* Floating point operations.
@@ -99,7 +101,8 @@ default FloatingPointFormula makeNumber(FloatingPointNumber number) {
number.getExponent(),
number.getMantissa(),
number.getMathSign(),
- getFloatingPointType(number.getExponentSize(), number.getMantissaSize()));
+ getFloatingPointTypeWithoutSignBit(
+ number.getExponentSize(), number.getMantissaSizeWithoutSignBit()));
}
/**
@@ -285,11 +288,70 @@ FloatingPointFormula castFrom(
/**
* Create a formula that produces a representation of the given floating-point value as a
- * bitvector conforming to the IEEE format. The size of the resulting bitvector is the sum of the
- * sizes of the exponent and mantissa of the input formula plus 1 (for the sign bit).
+ * bitvector conforming to the IEEE 754-2008 format. The size of the resulting bitvector is the
+ * sum of the sizes of the exponent and mantissa of the input formula plus 1 (for the sign bit).
*/
BitvectorFormula toIeeeBitvector(FloatingPointFormula number);
+ /**
+ * Create a formula that produces a representation of the given floating-point value as a
+ * bitvector conforming to the IEEE 754-2008 format. The size of the resulting bitvector is the
+ * sum of the sizes of the exponent and mantissa of the input formula plus 1 (for the sign bit).
+ * This implementation can be used independently of {@link
+ * #toIeeeBitvector(FloatingPointFormula)}, as it does not rely on an SMT solvers support for
+ * {@link #toIeeeBitvector(FloatingPointFormula)}. Behavior for special FP values (NaN, Inf, etc.)
+ * is not defined, and returned values are solver dependent. In case you want to define how to
+ * handle those values, please use {@link #toIeeeBitvector(FloatingPointFormula, String, Map)}.
+ * This method is based on a suggestion in the SMTLib2 standard ( source) implementation:
+ *
+ *
(declare-fun b () (_ BitVec m))
+ *
+ *
(assert (= ((_ to_fp eb sb) b) f))
+ *
+ * @param number the {@link FloatingPointFormula} to be converted into an IEEE bitvector.
+ * @param bitvectorConstantName the name of the returned {@link BitvectorFormula}.
+ * @return {@link BitvectorFormulaAndBooleanFormula} consisting of the transformed input
+ * floating-point as a {@link BitvectorFormula} and the additional constraint as {@link
+ * BooleanFormula}.
+ */
+ BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number, String bitvectorConstantName);
+
+ /**
+ * Create a formula that produces a representation of the given floating-point value as a
+ * bitvector conforming to the IEEE 754-2008 format. The size of the resulting bitvector is the
+ * sum of the sizes of the exponent and mantissa of the input formula plus 1 (for the sign bit).
+ * This implementation can be used independently of {@link
+ * #toIeeeBitvector(FloatingPointFormula)}, as it does not rely on an SMT solvers support for
+ * {@link #toIeeeBitvector(FloatingPointFormula)}. Behavior for special FP values (NaN, Inf, etc.)
+ * can be defined using the specialFPConstantHandling parameter. This method is based on a
+ * suggestion in the SMTLib2 standard ( source) implementation:
+ *
+ *
(declare-fun b () (_ BitVec m))
+ *
+ *
(assert (= ((_ to_fp eb sb) b) f))
+ *
+ * @param number the {@link FloatingPointFormula} to be converted into an IEEE bitvector.
+ * @param bitvectorConstantName the name of the returned {@link BitvectorFormula}.
+ * @param specialFPConstantHandling a {@link Map} defining the returned {@link BitvectorFormula}
+ * for special {@link FloatingPointFormula} constant numbers. You are only allowed to specify
+ * a mapping for special FP numbers with more than one well-defined bitvector representation,
+ * i.e. NaN and +/- Infinity. The width of the mapped bitvector values has to match the
+ * expected width of the bitvector return value. The {@link FloatingPointType}, i.e.
+ * precision, of the key FP numbers has to match the {@link FloatingPointType} of the
+ * parameter {@code number}. For an empty {@link Map}, or missing mappings, this method
+ * behaves like {@link #toIeeeBitvector(FloatingPointFormula, String)}.
+ * @return {@link BitvectorFormulaAndBooleanFormula} consisting of the transformed input
+ * floating-point as a {@link BitvectorFormula} and the additional constraint as {@link
+ * BooleanFormula}.
+ */
+ BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number,
+ String bitvectorConstantName,
+ Map specialFPConstantHandling);
+
FloatingPointFormula round(FloatingPointFormula formula, FloatingPointRoundingMode roundingMode);
// ----------------- Arithmetic relations, return type NumeralFormula -----------------
@@ -467,4 +529,13 @@ FloatingPointFormula multiply(
*
*/
BooleanFormula isNegative(FloatingPointFormula number);
+
+ /**
+ * Returns the size of the mantissa (also called a coefficient or significant), including the sign
+ * bit, for the given {@link FloatingPointFormula}.
+ */
+ int getMantissaSizeWithSignBit(FloatingPointFormula number);
+
+ /** Returns the size of the exponent for the given {@link FloatingPointFormula}. */
+ int getExponentSize(FloatingPointFormula number);
}
diff --git a/src/org/sosy_lab/java_smt/api/FloatingPointNumber.java b/src/org/sosy_lab/java_smt/api/FloatingPointNumber.java
index fe3c14b1ca..6c750e3701 100644
--- a/src/org/sosy_lab/java_smt/api/FloatingPointNumber.java
+++ b/src/org/sosy_lab/java_smt/api/FloatingPointNumber.java
@@ -23,6 +23,7 @@
@AutoValue
public abstract class FloatingPointNumber {
+ // Mantissas do not include the sign bit
public static final int SINGLE_PRECISION_EXPONENT_SIZE = 8;
public static final int SINGLE_PRECISION_MANTISSA_SIZE = 23;
public static final int DOUBLE_PRECISION_EXPONENT_SIZE = 11;
@@ -80,8 +81,29 @@ public final boolean getSign() {
public abstract int getExponentSize();
+ /**
+ * Returns the size of the mantissa (also called a coefficient or significant), excluding the sign
+ * bit.
+ */
+ // TODO: mark as soon to be deprecated
public abstract int getMantissaSize();
+ /**
+ * Returns the size of the mantissa (also called a coefficient or significant), excluding the sign
+ * bit.
+ */
+ public int getMantissaSizeWithoutSignBit() {
+ return getMantissaSize();
+ }
+
+ /**
+ * Returns the size of the mantissa (also called a coefficient or significant), including the sign
+ * bit.
+ */
+ public int getMantissaSizeWithSignBit() {
+ return getMantissaSize() + 1;
+ }
+
/**
* Get a floating-point number with the given sign, exponent, and mantissa.
*
@@ -92,7 +114,7 @@ public final boolean getSign() {
* @param mantissa the mantissa of the floating-point number, given as unsigned (not negative)
* number without hidden bit
* @param exponentSize the (maximum) size of the exponent in bits
- * @param mantissaSize the (maximum) size of the mantissa in bits
+ * @param mantissaSize the (maximum) size of the mantissa in bits (excluding the sign bit)
* @see #of(Sign, BigInteger, BigInteger, int, int)
*/
@Deprecated(
@@ -119,7 +141,7 @@ public static FloatingPointNumber of(
* @param mantissa the mantissa of the floating-point number, given as unsigned (not negative)
* number without hidden bit
* @param exponentSize the (maximum) size of the exponent in bits
- * @param mantissaSize the (maximum) size of the mantissa in bits
+ * @param mantissaSize the (maximum) size of the mantissa in bits (excluding the sign bit)
*/
public static FloatingPointNumber of(
Sign sign, BigInteger exponent, BigInteger mantissa, int exponentSize, int mantissaSize) {
@@ -136,7 +158,7 @@ public static FloatingPointNumber of(
* @param bits the bit-representation of the floating-point number, consisting of sign bit,
* exponent (without bias) and mantissa (without hidden bit) in this exact ordering
* @param exponentSize the size of the exponent in bits
- * @param mantissaSize the size of the mantissa in bits
+ * @param mantissaSize the size of the mantissa in bits (excluding the sign bit)
*/
public static FloatingPointNumber of(String bits, int exponentSize, int mantissaSize) {
Preconditions.checkArgument(0 < exponentSize);
@@ -159,24 +181,26 @@ public static FloatingPointNumber of(String bits, int exponentSize, int mantissa
/**
* Returns true if this floating-point number is an IEEE-754-2008 single precision type with 32
- * bits length consisting of an 8 bit exponent, a 23 bit mantissa and a single sign bit.
+ * bits length consisting of an 8 bit exponent, a 24 bit mantissa (including the sign bit).
*
* @return true for IEEE-754 single precision type, false otherwise.
*/
public boolean isIEEE754SinglePrecision() {
+ // Mantissa does not include the sign bit
return getExponentSize() == SINGLE_PRECISION_EXPONENT_SIZE
- && getMantissaSize() == SINGLE_PRECISION_MANTISSA_SIZE;
+ && getMantissaSizeWithoutSignBit() == SINGLE_PRECISION_MANTISSA_SIZE;
}
/**
* Returns true if this floating-point number is an IEEE-754-2008 double precision type with 64
- * bits length consisting of an 11 bit exponent, a 52 bit mantissa and a single sign bit.
+ * bits length consisting of an 11 bit exponent, a 53 bit mantissa (including the sign bit).
*
* @return true for IEEE-754 double precision type, false otherwise.
*/
public boolean isIEEE754DoublePrecision() {
+ // Mantissa does not include the sign bit
return getExponentSize() == DOUBLE_PRECISION_EXPONENT_SIZE
- && getMantissaSize() == DOUBLE_PRECISION_MANTISSA_SIZE;
+ && getMantissaSizeWithoutSignBit() == DOUBLE_PRECISION_MANTISSA_SIZE;
}
/** compute a representation as Java-based float value, if possible. */
@@ -204,18 +228,18 @@ public double doubleValue() {
}
private BitSet getBits() {
- var mantissaSize = getMantissaSize();
+ var mantissaSizeWithoutSign = getMantissaSizeWithoutSignBit();
var exponentSize = getExponentSize();
var mantissa = getMantissa();
var exponent = getExponent();
- var bits = new BitSet(1 + exponentSize + mantissaSize);
+ var bits = new BitSet(exponentSize + mantissaSizeWithoutSign + 1);
if (getMathSign().isNegative()) {
- bits.set(exponentSize + mantissaSize); // if negative, set first bit to 1
+ bits.set(exponentSize + mantissaSizeWithoutSign); // if negative, set first bit to 1
}
for (int i = 0; i < exponentSize; i++) {
- bits.set(mantissaSize + i, exponent.testBit(i));
+ bits.set(mantissaSizeWithoutSign + i, exponent.testBit(i));
}
- for (int i = 0; i < mantissaSize; i++) {
+ for (int i = 0; i < mantissaSizeWithoutSign; i++) {
bits.set(i, mantissa.testBit(i));
}
return bits;
@@ -227,7 +251,7 @@ private BitSet getBits() {
*/
@Override
public final String toString() {
- var length = 1 + getExponentSize() + getMantissaSize();
+ var length = getExponentSize() + getMantissaSizeWithSignBit();
var str = new StringBuilder(length);
var bits = getBits();
for (int i = 0; i < length; i++) {
diff --git a/src/org/sosy_lab/java_smt/api/FormulaType.java b/src/org/sosy_lab/java_smt/api/FormulaType.java
index d5beea79cc..da62759ba3 100644
--- a/src/org/sosy_lab/java_smt/api/FormulaType.java
+++ b/src/org/sosy_lab/java_smt/api/FormulaType.java
@@ -205,14 +205,61 @@ public String toSMTLIBString() {
}
}
- public static FloatingPointType getFloatingPointType(int exponentSize, int mantissaSize) {
- return new FloatingPointType(exponentSize, mantissaSize);
+ /**
+ * Constructs a new IEEE-754 {@link FloatingPointType} with the given exponent and mantissa sizes.
+ * The mantissa size is expected to not include the sign bit.
+ *
+ * @param exponentSize size of the exponent for the base of the floating-point
+ * @param mantissaSizeWithoutSignBit size of the mantissa (also called a coefficient or
+ * significant), excluding the sign bit.
+ * @return the newly constructed {@link FloatingPointType}.
+ */
+ // TODO: mark as soon to be deprecated
+ public static FloatingPointType getFloatingPointType(
+ int exponentSize, int mantissaSizeWithoutSignBit) {
+ return new FloatingPointType(exponentSize, mantissaSizeWithoutSignBit);
+ }
+
+ /**
+ * Constructs a new IEEE-754 {@link FloatingPointType} with the given exponent and mantissa sizes.
+ * The mantissa size is expected to not include the sign bit.
+ *
+ * @param exponentSize size of the exponent for the base of the floating-point
+ * @param mantissaSizeWithoutSignBit size of the mantissa (also called a coefficient or
+ * significant), excluding the sign bit.
+ * @return the newly constructed {@link FloatingPointType}.
+ */
+ public static FloatingPointType getFloatingPointTypeWithoutSignBit(
+ int exponentSize, int mantissaSizeWithoutSignBit) {
+ return new FloatingPointType(exponentSize, mantissaSizeWithoutSignBit);
+ }
+
+ /**
+ * Constructs a new IEEE-754 {@link FloatingPointType} with the given exponent and mantissa sizes.
+ * The mantissa size is expected to not include the sign bit.
+ *
+ * @param exponentSize size of the exponent for the base of the floating-point
+ * @param mantissaSizeWithSignBit size of the mantissa (also called a coefficient or significant),
+ * including the sign bit.
+ * @return the newly constructed {@link FloatingPointType}.
+ */
+ public static FloatingPointType getFloatingPointTypeWithSignBit(
+ int exponentSize, int mantissaSizeWithSignBit) {
+ return new FloatingPointType(exponentSize, mantissaSizeWithSignBit);
}
+ /**
+ * @return single precision {@link FloatingPointType} with exponent sized 8, and mantissa sized 24
+ * (including the sign bit).
+ */
public static FloatingPointType getSinglePrecisionFloatingPointType() {
return FloatingPointType.SINGLE_PRECISION_FP_TYPE;
}
+ /**
+ * @return double precision {@link FloatingPointType} with exponent sized 11, and mantissa sized
+ * 53 (including the sign bit).
+ */
public static FloatingPointType getDoublePrecisionFloatingPointType() {
return FloatingPointType.DOUBLE_PRECISION_FP_TYPE;
}
@@ -226,6 +273,8 @@ public static final class FloatingPointType extends FormulaType";
+ return "FloatingPoint";
}
@Override
public String toSMTLIBString() {
- return "(_ FloatingPoint " + exponentSize + " " + mantissaSize + ")";
+ return "(_ FloatingPoint " + exponentSize + " " + getMantissaSizeWithSignBit() + ")";
}
}
@@ -478,7 +552,7 @@ public static FormulaType> fromString(String t) {
} else if (t.startsWith("FloatingPoint<")) {
// FloatingPoint
List exman = Splitter.on(',').limit(2).splitToList(t.substring(14, t.length() - 1));
- return FormulaType.getFloatingPointType(
+ return FormulaType.getFloatingPointTypeWithoutSignBit(
Integer.parseInt(exman.get(0).substring(4)), Integer.parseInt(exman.get(1).substring(5)));
} else if (t.startsWith("Bitvector<")) {
// Bitvector<32>
diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
index 47c847afe2..2653558406 100644
--- a/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
@@ -8,13 +8,19 @@
package org.sosy_lab.java_smt.basicimpl;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.sosy_lab.java_smt.api.FormulaType.getFloatingPointType;
import static org.sosy_lab.java_smt.basicimpl.AbstractFormulaManager.checkVariableName;
-import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
import org.sosy_lab.common.rationals.Rational;
import org.sosy_lab.java_smt.api.BitvectorFormula;
import org.sosy_lab.java_smt.api.BooleanFormula;
@@ -45,10 +51,18 @@ public abstract class AbstractFloatingPointFormulaManager roundingModes;
+ private final AbstractBitvectorFormulaManager bvMgr;
+
+ private final AbstractBooleanFormulaManager bMgr;
+
protected AbstractFloatingPointFormulaManager(
- FormulaCreator pCreator) {
+ FormulaCreator pCreator,
+ AbstractBitvectorFormulaManager pBvMgr,
+ AbstractBooleanFormulaManager pBMgr) {
super(pCreator);
roundingModes = new HashMap<>();
+ bvMgr = pBvMgr;
+ bMgr = pBMgr;
}
protected abstract TFormulaInfo getDefaultRoundingMode();
@@ -145,7 +159,7 @@ protected abstract TFormulaInfo makeNumberImpl(
BigInteger exponent, BigInteger mantissa, Sign sign, FloatingPointType type);
protected static boolean isNegativeZero(Double pN) {
- Preconditions.checkNotNull(pN);
+ checkNotNull(pN);
return Double.valueOf("-0.0").equals(pN);
}
@@ -256,7 +270,95 @@ public BitvectorFormula toIeeeBitvector(FloatingPointFormula pNumber) {
return getFormulaCreator().encapsulateBitvector(toIeeeBitvectorImpl(extractInfo(pNumber)));
}
- protected abstract TFormulaInfo toIeeeBitvectorImpl(TFormulaInfo pNumber);
+ @SuppressWarnings("unused")
+ protected TFormulaInfo toIeeeBitvectorImpl(TFormulaInfo pNumber) {
+ throw new UnsupportedOperationException(
+ "The chosen solver does not support transforming "
+ + "FloatingPointFormula to IEEE bitvectors. Try using the fallback "
+ + "methods toIeeeBitvector"
+ + "(FloatingPointFormula, String) and/or "
+ + "toIeeeBitvector(FloatingPointFormula, String, Map)");
+ }
+
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula f, String bitvectorConstantName) {
+ return toIeeeBitvector(f, bitvectorConstantName, ImmutableMap.of());
+ }
+
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula f,
+ String bitvectorConstantName,
+ Map specialFPConstantHandling) {
+
+ FormulaType.FloatingPointType fpType =
+ (FloatingPointType) getFormulaCreator().getFormulaType(f);
+ int mantissaSizeWithSignBit = fpType.getMantissaSizeWithSignBit();
+ int exponentSize = fpType.getExponentSize();
+ BitvectorFormula bvFormula =
+ bvMgr.makeVariable(mantissaSizeWithSignBit + exponentSize, bitvectorConstantName);
+
+ // When building new Fp types, we don't include the sign bit
+ FloatingPointFormula fromIeeeBitvector =
+ fromIeeeBitvector(
+ bvFormula, getFloatingPointType(exponentSize, mantissaSizeWithSignBit - 1));
+
+ // assignment() allows a value to be NaN etc.
+ // Note: All fp.to_* functions are unspecified for NaN and infinity input values in the
+ // standard, what solvers return might be distinct.
+ BooleanFormula additionalConstraint = assignment(fromIeeeBitvector, f);
+
+ // Build special numbers so that we can compare them in the map
+ FloatingPointType precision = getFloatingPointType(exponentSize, mantissaSizeWithSignBit - 1);
+ Set specialNumbers =
+ ImmutableSet.of(
+ makeNaN(precision), makePlusInfinity(precision), makeMinusInfinity(precision));
+
+ BitvectorFormula toIeeeBv = bvFormula;
+ for (Entry entry :
+ specialFPConstantHandling.entrySet()) {
+ FloatingPointFormula fpConst = entry.getKey();
+
+ // We check that FP const special numbers are used (info from SMTLib2-standard)
+ // NaN has multiple possible definitions.
+ // +/- Infinity each has 2; e.g., +infinity for sort (_ FloatingPoint 2 3) is represented
+ // equivalently by (_ +oo 2 3) and (fp #b0 #b11 #b00).
+ // -0 only has one representation; i.e. (_ -zero 3 2) abbreviates (fp #b1 #b000 #b0), and
+ // is therefore disallowed.
+ // This automatically checks the correct precision as well!
+ checkArgument(
+ specialNumbers.contains(fpConst),
+ "You are only allowed to specify a mapping for special FP numbers with more than one"
+ + " well-defined bitvector representation, i.e. NaN and +/- Infinity. Their precision"
+ + " has to match the precision of the formula to be represented as bitvector.");
+
+ BitvectorFormula bvTerm = entry.getValue();
+ checkArgument(
+ bvMgr.getLength(bvTerm) == bvMgr.getLength(bvFormula),
+ "The size of the bitvector terms used as mapped values needs to be equal to the size of"
+ + " the bitvector returned by this method");
+
+ BooleanFormula assumption = assignment(fpConst, f);
+ toIeeeBv = bMgr.ifThenElse(assumption, bvTerm, toIeeeBv);
+ }
+
+ return BitvectorFormulaAndBooleanFormula.of(toIeeeBv, additionalConstraint);
+ }
+
+ @Override
+ public int getMantissaSizeWithSignBit(FloatingPointFormula f) {
+ return getMantissaSizeWithSignBitImpl(extractInfo(f));
+ }
+
+ protected abstract int getMantissaSizeWithSignBitImpl(TFormulaInfo f);
+
+ @Override
+ public int getExponentSize(FloatingPointFormula f) {
+ return getExponentSizeImpl(extractInfo(f));
+ }
+
+ protected abstract int getExponentSizeImpl(TFormulaInfo f);
@Override
public FloatingPointFormula negate(FloatingPointFormula pNumber) {
@@ -519,4 +621,28 @@ protected static String getBvRepresentation(BigInteger integer, int size) {
}
return String.copyValueOf(values);
}
+
+ public static final class BitvectorFormulaAndBooleanFormula {
+ private final BitvectorFormula bitvectorFormula;
+ private final BooleanFormula booleanFormula;
+
+ private BitvectorFormulaAndBooleanFormula(
+ BitvectorFormula pBitvectorFormula, BooleanFormula pBooleanFormula) {
+ bitvectorFormula = checkNotNull(pBitvectorFormula);
+ booleanFormula = checkNotNull(pBooleanFormula);
+ }
+
+ private static BitvectorFormulaAndBooleanFormula of(
+ BitvectorFormula pBitvectorFormula, BooleanFormula pBooleanFormula) {
+ return new BitvectorFormulaAndBooleanFormula(pBitvectorFormula, pBooleanFormula);
+ }
+
+ public BitvectorFormula getBitvectorFormula() {
+ return bitvectorFormula;
+ }
+
+ public BooleanFormula getBooleanFormula() {
+ return booleanFormula;
+ }
+ }
}
diff --git a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
index 74b1677375..cc0ca778a1 100644
--- a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
@@ -10,6 +10,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.Map;
import org.sosy_lab.common.rationals.Rational;
import org.sosy_lab.java_smt.api.BitvectorFormula;
import org.sosy_lab.java_smt.api.BooleanFormula;
@@ -20,6 +21,7 @@
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
+import org.sosy_lab.java_smt.basicimpl.AbstractFloatingPointFormulaManager.BitvectorFormulaAndBooleanFormula;
public class DebuggingFloatingPointFormulaManager implements FloatingPointFormulaManager {
private final FloatingPointFormulaManager delegate;
@@ -206,6 +208,36 @@ public BitvectorFormula toIeeeBitvector(FloatingPointFormula number) {
return result;
}
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number, String bitvectorConstantName) {
+ debugging.assertThreadLocal();
+ debugging.assertFormulaInContext(number);
+ BitvectorFormulaAndBooleanFormula res = delegate.toIeeeBitvector(number, bitvectorConstantName);
+ debugging.addFormulaTerm(res.getBitvectorFormula());
+ debugging.addFormulaTerm(res.getBooleanFormula());
+ return res;
+ }
+
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number,
+ String bitvectorConstantName,
+ Map specialFPConstantHandling) {
+ debugging.assertThreadLocal();
+ debugging.assertFormulaInContext(number);
+ specialFPConstantHandling.forEach(
+ (key, value) -> {
+ debugging.assertFormulaInContext(key);
+ debugging.assertFormulaInContext(value);
+ });
+ BitvectorFormulaAndBooleanFormula res =
+ delegate.toIeeeBitvector(number, bitvectorConstantName, specialFPConstantHandling);
+ debugging.addFormulaTerm(res.getBitvectorFormula());
+ debugging.addFormulaTerm(res.getBooleanFormula());
+ return res;
+ }
+
@Override
public FloatingPointFormula round(
FloatingPointFormula formula, FloatingPointRoundingMode roundingMode) {
@@ -491,4 +523,18 @@ public BooleanFormula isNegative(FloatingPointFormula number) {
debugging.addFormulaTerm(result);
return result;
}
+
+ @Override
+ public int getMantissaSizeWithSignBit(FloatingPointFormula number) {
+ debugging.assertThreadLocal();
+ debugging.assertFormulaInContext(number);
+ return delegate.getMantissaSizeWithSignBit(number);
+ }
+
+ @Override
+ public int getExponentSize(FloatingPointFormula number) {
+ debugging.assertThreadLocal();
+ debugging.assertFormulaInContext(number);
+ return delegate.getExponentSize(number);
+ }
}
diff --git a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
index 415b7cb00f..e0756d53f8 100644
--- a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
@@ -12,6 +12,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.Map;
import org.sosy_lab.common.rationals.Rational;
import org.sosy_lab.java_smt.api.BitvectorFormula;
import org.sosy_lab.java_smt.api.BooleanFormula;
@@ -22,6 +23,7 @@
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
+import org.sosy_lab.java_smt.basicimpl.AbstractFloatingPointFormulaManager.BitvectorFormulaAndBooleanFormula;
class StatisticsFloatingPointFormulaManager implements FloatingPointFormulaManager {
@@ -166,6 +168,21 @@ public BitvectorFormula toIeeeBitvector(FloatingPointFormula pNumber) {
return delegate.toIeeeBitvector(pNumber);
}
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number, String bitvectorConstantName) {
+ stats.fpOperations.getAndIncrement();
+ return delegate.toIeeeBitvector(number, bitvectorConstantName);
+ }
+
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number,
+ String bitvectorConstantName,
+ Map specialFPConstantHandling) {
+ return delegate.toIeeeBitvector(number, bitvectorConstantName, specialFPConstantHandling);
+ }
+
@Override
public FloatingPointFormula round(
FloatingPointFormula pFormula, FloatingPointRoundingMode pRoundingMode) {
@@ -352,4 +369,16 @@ public BooleanFormula isNegative(FloatingPointFormula pNumber) {
stats.fpOperations.getAndIncrement();
return delegate.isNegative(pNumber);
}
+
+ @Override
+ public int getMantissaSizeWithSignBit(FloatingPointFormula pNumber) {
+ stats.fpOperations.getAndIncrement();
+ return delegate.getMantissaSizeWithSignBit(pNumber);
+ }
+
+ @Override
+ public int getExponentSize(FloatingPointFormula pNumber) {
+ stats.fpOperations.getAndIncrement();
+ return delegate.getExponentSize(pNumber);
+ }
}
diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
index 3d922f71a8..4b7b7b3a63 100644
--- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
@@ -12,6 +12,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.Map;
import org.sosy_lab.common.rationals.Rational;
import org.sosy_lab.java_smt.api.BitvectorFormula;
import org.sosy_lab.java_smt.api.BooleanFormula;
@@ -23,6 +24,7 @@
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
import org.sosy_lab.java_smt.api.SolverContext;
+import org.sosy_lab.java_smt.basicimpl.AbstractFloatingPointFormulaManager.BitvectorFormulaAndBooleanFormula;
class SynchronizedFloatingPointFormulaManager implements FloatingPointFormulaManager {
@@ -186,6 +188,24 @@ public BitvectorFormula toIeeeBitvector(FloatingPointFormula pNumber) {
}
}
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number, String bitvectorConstantName) {
+ synchronized (sync) {
+ return delegate.toIeeeBitvector(number, bitvectorConstantName);
+ }
+ }
+
+ @Override
+ public BitvectorFormulaAndBooleanFormula toIeeeBitvector(
+ FloatingPointFormula number,
+ String bitvectorConstantName,
+ Map specialFPConstantHandling) {
+ synchronized (sync) {
+ return delegate.toIeeeBitvector(number, bitvectorConstantName, specialFPConstantHandling);
+ }
+ }
+
@Override
public FloatingPointFormula round(
FloatingPointFormula pFormula, FloatingPointRoundingMode pRoundingMode) {
@@ -400,4 +420,18 @@ public BooleanFormula isNegative(FloatingPointFormula pNumber) {
return delegate.isNegative(pNumber);
}
}
+
+ @Override
+ public int getMantissaSizeWithSignBit(FloatingPointFormula pNumber) {
+ synchronized (sync) {
+ return delegate.getMantissaSizeWithSignBit(pNumber);
+ }
+ }
+
+ @Override
+ public int getExponentSize(FloatingPointFormula pNumber) {
+ synchronized (sync) {
+ return delegate.getExponentSize(pNumber);
+ }
+ }
}
diff --git a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFloatingPointManager.java b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFloatingPointManager.java
index cb03e5aa6d..f5ee0f07f7 100644
--- a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFloatingPointManager.java
+++ b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFloatingPointManager.java
@@ -25,17 +25,16 @@
public class BitwuzlaFloatingPointManager
extends AbstractFloatingPointFormulaManager {
- private final BitwuzlaFormulaCreator bitwuzlaCreator;
+
private final TermManager termManager;
private final Term roundingMode;
- // Keeps track of the temporary variables that are created for fp-to-bv casts
- private static int counter = 0;
-
protected BitwuzlaFloatingPointManager(
- BitwuzlaFormulaCreator pCreator, FloatingPointRoundingMode pFloatingPointRoundingMode) {
- super(pCreator);
- bitwuzlaCreator = pCreator;
+ BitwuzlaFormulaCreator pCreator,
+ FloatingPointRoundingMode pFloatingPointRoundingMode,
+ BitwuzlaBitvectorFormulaManager pBvMgr,
+ BitwuzlaBooleanFormulaManager pBmgr) {
+ super(pCreator, pBvMgr, pBmgr);
termManager = pCreator.getTermManager();
roundingMode = getRoundingModeImpl(pFloatingPointRoundingMode);
}
@@ -84,7 +83,7 @@ protected Term makeNumberImpl(
Sort expSort = termManager.mk_bv_sort(type.getExponentSize());
Term expTerm = termManager.mk_bv_value(expSort, exponent.toString(2));
- Sort mantissaSort = termManager.mk_bv_sort(type.getMantissaSize());
+ Sort mantissaSort = termManager.mk_bv_sort(type.getMantissaSizeWithoutSignBit());
Term mantissaTerm = termManager.mk_bv_value(mantissaSort, mantissa.toString(2));
return termManager.mk_fp_value(signTerm, expTerm, mantissaTerm);
@@ -134,7 +133,7 @@ protected Term castToImpl(
pRoundingMode,
pNumber,
targetType.getExponentSize(),
- targetType.getMantissaSize() + 1);
+ targetType.getMantissaSizeWithSignBit());
} else if (pTargetType.isBitvectorType()) {
FormulaType.BitvectorType targetType = (FormulaType.BitvectorType) pTargetType;
if (pSigned) {
@@ -148,6 +147,16 @@ protected Term castToImpl(
}
}
+ @Override
+ protected int getMantissaSizeWithSignBitImpl(Term fp) {
+ return fp.sort().fp_sig_size();
+ }
+
+ @Override
+ protected int getExponentSizeImpl(Term fp) {
+ return fp.sort().fp_exp_size();
+ }
+
@Override
protected Term castFromImpl(
Term pNumber, boolean pSigned, FloatingPointType pTargetType, Term pRoundingMode) {
@@ -161,14 +170,14 @@ protected Term castFromImpl(
roundingMode,
pNumber,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize() + 1);
+ pTargetType.getMantissaSizeWithSignBit());
} else {
return termManager.mk_term(
Kind.FP_TO_FP_FROM_UBV,
roundingMode,
pNumber,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize() + 1);
+ pTargetType.getMantissaSizeWithSignBit());
}
} else {
@@ -183,49 +192,7 @@ protected Term fromIeeeBitvectorImpl(Term pNumber, FloatingPointType pTargetType
Kind.FP_TO_FP_FROM_BV,
pNumber,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize() + 1);
- }
-
- @Override
- protected Term toIeeeBitvectorImpl(Term pNumber) {
- int sizeExp = pNumber.sort().fp_exp_size();
- int sizeSig = pNumber.sort().fp_sig_size();
-
- Sort bvSort = termManager.mk_bv_sort(sizeExp + sizeSig);
-
- // The following code creates a new variable that is returned as result.
- // Additionally, we track constraints about the equality of the new variable and the FP number,
- // which is added onto the prover stack whenever the new variable is used as assertion.
-
- // TODO This internal implementation is a technical dept and should be removed.
- // The additional constraints are not transparent in all cases, e.g., when visiting a
- // formula, creating a model, or transferring the assertions onto another prover stack.
- // A better way would be a direct implementation of this in Bitwuzla, without interfering
- // with JavaSMT.
-
- // Note that NaN is handled as a special case in this method. This is not strictly necessary,
- // but if we just use "fpTerm = to_fp(bvVar)" the NaN will be given a random payload (and
- // sign). Since NaN payloads are not preserved here anyway we might as well pick a canonical
- // representation, e.g., which is "0 11111111 10000000000000000000000" for single precision.
- String nanRepr = "0" + "1".repeat(sizeExp + 1) + "0".repeat(sizeSig - 2);
- Term bvNaN = termManager.mk_bv_value(bvSort, nanRepr);
-
- // TODO creating our own utility variables might eb unexpected from the user.
- // We might need to exclude such variables in models and formula traversal.
- String newVariable = "__JAVASMT__CAST_FROM_BV_" + counter++;
- Term bvVar = termManager.mk_const(bvSort, newVariable);
- Term equal =
- termManager.mk_term(
- Kind.ITE,
- termManager.mk_term(Kind.FP_IS_NAN, pNumber),
- termManager.mk_term(Kind.EQUAL, bvVar, bvNaN),
- termManager.mk_term(
- Kind.EQUAL,
- termManager.mk_term(Kind.FP_TO_FP_FROM_BV, bvVar, sizeExp, sizeSig),
- pNumber));
-
- bitwuzlaCreator.addConstraintForVariable(newVariable, equal);
- return bvVar;
+ pTargetType.getMantissaSizeWithSignBit());
}
@Override
diff --git a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
index f946331319..fd5c82d284 100644
--- a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
@@ -102,7 +102,7 @@ assert getFormulaType(pTerm).isBitvectorType()
// system instead use bitwuzla_mk_fp_value_from_real somehow or convert myself
@Override
public Sort getFloatingPointType(FloatingPointType type) {
- return termManager.mk_fp_sort(type.getExponentSize(), type.getMantissaSize() + 1);
+ return termManager.mk_fp_sort(type.getExponentSize(), type.getMantissaSizeWithSignBit());
}
@Override
@@ -171,7 +171,7 @@ public FormulaType> bitwuzlaSortToType(Sort pSort) {
if (pSort.is_fp()) {
int exponent = pSort.fp_exp_size();
int mantissa = pSort.fp_sig_size() - 1;
- return FormulaType.getFloatingPointType(exponent, mantissa);
+ return FormulaType.getFloatingPointTypeWithoutSignBit(exponent, mantissa);
} else if (pSort.is_bv()) {
return FormulaType.getBitvectorTypeWithSize(pSort.bv_size());
} else if (pSort.is_array()) {
@@ -380,7 +380,7 @@ public FormulaType getFormulaType(T pFormula) {
}
int exp = sort.fp_exp_size();
int man = sort.fp_sig_size() - 1;
- return (FormulaType) FormulaType.getFloatingPointType(exp, man);
+ return (FormulaType) FormulaType.getFloatingPointTypeWithoutSignBit(exp, man);
} else if (sort.is_rm()) {
return (FormulaType) FormulaType.FloatingPointRoundingModeType;
}
diff --git a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaSolverContext.java b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaSolverContext.java
index 6ccc1c31ae..77110ba71e 100644
--- a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaSolverContext.java
+++ b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaSolverContext.java
@@ -172,7 +172,8 @@ public static BitwuzlaSolverContext create(
BitwuzlaQuantifiedFormulaManager quantifierTheory =
new BitwuzlaQuantifiedFormulaManager(creator);
BitwuzlaFloatingPointManager floatingPointTheory =
- new BitwuzlaFloatingPointManager(creator, pFloatingPointRoundingMode);
+ new BitwuzlaFloatingPointManager(
+ creator, pFloatingPointRoundingMode, bitvectorTheory, booleanTheory);
BitwuzlaArrayFormulaManager arrayTheory = new BitwuzlaArrayFormulaManager(creator);
BitwuzlaFormulaManager manager =
new BitwuzlaFormulaManager(
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FloatingPointFormulaManager.java
index 248f6a55a8..b62f959500 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FloatingPointFormulaManager.java
@@ -8,15 +8,17 @@
package org.sosy_lab.java_smt.solvers.cvc4;
+import static com.google.common.base.Preconditions.checkArgument;
+
import com.google.common.collect.ImmutableList;
import edu.stanford.CVC4.BitVector;
-import edu.stanford.CVC4.BitVectorExtract;
import edu.stanford.CVC4.Expr;
import edu.stanford.CVC4.ExprManager;
import edu.stanford.CVC4.FloatingPoint;
import edu.stanford.CVC4.FloatingPointConvertSort;
import edu.stanford.CVC4.FloatingPointSize;
import edu.stanford.CVC4.FloatingPointToFPFloatingPoint;
+import edu.stanford.CVC4.FloatingPointToFPIEEEBitVector;
import edu.stanford.CVC4.FloatingPointToFPSignedBitVector;
import edu.stanford.CVC4.FloatingPointToFPUnsignedBitVector;
import edu.stanford.CVC4.FloatingPointToSBV;
@@ -41,8 +43,11 @@ public class CVC4FloatingPointFormulaManager
private final Expr roundingMode;
protected CVC4FloatingPointFormulaManager(
- CVC4FormulaCreator pCreator, FloatingPointRoundingMode pFloatingPointRoundingMode) {
- super(pCreator);
+ CVC4FormulaCreator pCreator,
+ FloatingPointRoundingMode pFloatingPointRoundingMode,
+ CVC4BitvectorFormulaManager pBvFormulaManager,
+ CVC4BooleanFormulaManager pBoolFormulaManager) {
+ super(pCreator, pBvFormulaManager, pBoolFormulaManager);
exprManager = pCreator.getEnv();
roundingMode = getRoundingModeImpl(pFloatingPointRoundingMode);
}
@@ -52,8 +57,8 @@ protected CVC4FloatingPointFormulaManager(
private static FloatingPointSize getFPSize(FloatingPointType pType) {
long pExponentSize = pType.getExponentSize();
- long pMantissaSize = pType.getMantissaSize();
- return new FloatingPointSize(pExponentSize, pMantissaSize + 1); // plus sign bit
+ long pMantissaSize = pType.getMantissaSizeWithSignBit();
+ return new FloatingPointSize(pExponentSize, pMantissaSize);
}
@Override
@@ -89,11 +94,11 @@ protected Expr makeNumberImpl(
BigInteger exponent, BigInteger mantissa, Sign sign, FloatingPointType type) {
final String signStr = sign.isNegative() ? "1" : "0";
final String exponentStr = getBvRepresentation(exponent, type.getExponentSize());
- final String mantissaStr = getBvRepresentation(mantissa, type.getMantissaSize());
+ final String mantissaStr = getBvRepresentation(mantissa, type.getMantissaSizeWithoutSignBit());
final String bitvecStr = signStr + exponentStr + mantissaStr;
final BitVector bitVector = new BitVector(bitvecStr, 2);
final FloatingPoint fp =
- new FloatingPoint(type.getExponentSize(), type.getMantissaSize() + 1, bitVector);
+ new FloatingPoint(type.getExponentSize(), type.getMantissaSizeWithSignBit(), bitVector);
return exprManager.mkConst(fp);
}
@@ -109,7 +114,7 @@ protected Expr makeNumberAndRound(String pN, FloatingPointType pType, Expr pRoun
final Rational rat = toRational(pN);
final BigInteger upperBound =
- getBiggestNumberBeforeInf(pType.getMantissaSize(), pType.getExponentSize());
+ getBiggestNumberBeforeInf(pType.getMantissaSizeWithSignBit(), pType.getExponentSize());
if (rat.greater(Rational.fromDecimal(upperBound.negate().toString()))
&& rat.less(Rational.fromDecimal(upperBound.toString()))) {
@@ -218,8 +223,8 @@ protected Expr castFromImpl(
} else if (formulaType.isBitvectorType()) {
long pExponentSize = pTargetType.getExponentSize();
- long pMantissaSize = pTargetType.getMantissaSize();
- FloatingPointSize fpSize = new FloatingPointSize(pExponentSize, pMantissaSize + 1);
+ long pMantissaSize = pTargetType.getMantissaSizeWithSignBit();
+ FloatingPointSize fpSize = new FloatingPointSize(pExponentSize, pMantissaSize);
FloatingPointConvertSort fpConvert = new FloatingPointConvertSort(fpSize);
final Expr op;
if (pSigned) {
@@ -358,31 +363,30 @@ protected Expr isNegative(Expr pParam) {
@Override
protected Expr fromIeeeBitvectorImpl(Expr bitvector, FloatingPointType pTargetType) {
- int mantissaSize = pTargetType.getMantissaSize();
- int exponentSize = pTargetType.getExponentSize();
- int size = pTargetType.getTotalSize();
- assert size == mantissaSize + exponentSize + 1;
-
- Expr signExtract = exprManager.mkConst(new BitVectorExtract(size - 1, size - 1));
- Expr exponentExtract = exprManager.mkConst(new BitVectorExtract(size - 2, mantissaSize));
- Expr mantissaExtract = exprManager.mkConst(new BitVectorExtract(mantissaSize - 1, 0));
-
- Expr sign = exprManager.mkExpr(Kind.BITVECTOR_EXTRACT, signExtract, bitvector);
- Expr exponent = exprManager.mkExpr(Kind.BITVECTOR_EXTRACT, exponentExtract, bitvector);
- Expr mantissa = exprManager.mkExpr(Kind.BITVECTOR_EXTRACT, mantissaExtract, bitvector);
+ // This is just named weird, but the CVC4 doc say this is IEEE BV -> FP
+ FloatingPointConvertSort fpConvertSort = new FloatingPointConvertSort(getFPSize(pTargetType));
+ Expr op = exprManager.mkConst(new FloatingPointToFPIEEEBitVector(fpConvertSort));
+ return exprManager.mkExpr(op, bitvector);
+ }
- return exprManager.mkExpr(Kind.FLOATINGPOINT_FP, sign, exponent, mantissa);
+ @Override
+ protected Expr round(Expr pFormula, FloatingPointRoundingMode pRoundingMode) {
+ return exprManager.mkExpr(Kind.FLOATINGPOINT_RTI, getRoundingModeImpl(pRoundingMode), pFormula);
}
@Override
- protected Expr toIeeeBitvectorImpl(Expr pNumber) {
- // TODO possible work-around: use a tmp-variable "TMP" and add an
- // additional constraint "pNumer == fromIeeeBitvectorImpl(TMP)" for it in all use-cases.
- throw new UnsupportedOperationException("FP to IEEE-BV is not supported");
+ protected int getMantissaSizeWithSignBitImpl(Expr f) {
+ Type type = f.getType();
+ checkArgument(type.isFloatingPoint());
+ edu.stanford.CVC4.FloatingPointType fpType = new edu.stanford.CVC4.FloatingPointType(type);
+ return (int) fpType.getSignificandSize();
}
@Override
- protected Expr round(Expr pFormula, FloatingPointRoundingMode pRoundingMode) {
- return exprManager.mkExpr(Kind.FLOATINGPOINT_RTI, getRoundingModeImpl(pRoundingMode), pFormula);
+ protected int getExponentSizeImpl(Expr f) {
+ Type type = f.getType();
+ checkArgument(type.isFloatingPoint());
+ edu.stanford.CVC4.FloatingPointType fpType = new edu.stanford.CVC4.FloatingPointType(type);
+ return (int) fpType.getExponentSize();
}
}
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
index 23e7328956..1dac46d603 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
@@ -114,7 +114,7 @@ public Type getBitvectorType(int pBitwidth) {
@Override
public Type getFloatingPointType(FloatingPointType pType) {
return exprManager.mkFloatingPointType(
- pType.getExponentSize(), pType.getMantissaSize() + 1); // plus sign bit
+ pType.getExponentSize(), pType.getMantissaSizeWithSignBit());
}
@Override
@@ -154,7 +154,7 @@ public FormulaType getFormulaType(T pFormula) {
t.isFloatingPoint(), "FloatingPointFormula with actual type %s: %s", t, pFormula);
edu.stanford.CVC4.FloatingPointType fpType = new edu.stanford.CVC4.FloatingPointType(t);
return (FormulaType)
- FormulaType.getFloatingPointType(
+ FormulaType.getFloatingPointTypeWithoutSignBit(
(int) fpType.getExponentSize(),
(int) fpType.getSignificandSize() - 1); // without sign bit
@@ -182,7 +182,7 @@ private FormulaType> getFormulaTypeFromTermType(Type t) {
return FormulaType.getBitvectorTypeWithSize((int) new BitVectorType(t).getSize());
} else if (t.isFloatingPoint()) {
edu.stanford.CVC4.FloatingPointType fpType = new edu.stanford.CVC4.FloatingPointType(t);
- return FormulaType.getFloatingPointType(
+ return FormulaType.getFloatingPointTypeWithoutSignBit(
(int) fpType.getExponentSize(),
(int) fpType.getSignificandSize() - 1); // without sign bit
} else if (t.isRoundingMode()) {
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4SolverContext.java b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4SolverContext.java
index b5bd086812..6dff64284d 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4SolverContext.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4SolverContext.java
@@ -80,7 +80,9 @@ public static SolverContext create(
CVC4FloatingPointFormulaManager fpTheory;
if (Configuration.isBuiltWithSymFPU()) {
- fpTheory = new CVC4FloatingPointFormulaManager(creator, pFloatingPointRoundingMode);
+ fpTheory =
+ new CVC4FloatingPointFormulaManager(
+ creator, pFloatingPointRoundingMode, bitvectorTheory, booleanTheory);
} else {
fpTheory = null;
pLogger.log(Level.INFO, "CVC4 was built without support for FloatingPoint theory");
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FloatingPointFormulaManager.java
index 883a8a1f8a..ca4c2f339a 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FloatingPointFormulaManager.java
@@ -35,8 +35,11 @@ public class CVC5FloatingPointFormulaManager
private final Term roundingMode;
protected CVC5FloatingPointFormulaManager(
- CVC5FormulaCreator pCreator, FloatingPointRoundingMode pFloatingPointRoundingMode) {
- super(pCreator);
+ CVC5FormulaCreator pCreator,
+ FloatingPointRoundingMode pFloatingPointRoundingMode,
+ CVC5BitvectorFormulaManager pBvFormulaManager,
+ CVC5BooleanFormulaManager pBoolFormulaManager) {
+ super(pCreator, pBvFormulaManager, pBoolFormulaManager);
termManager = pCreator.getEnv();
solver = pCreator.getSolver();
roundingMode = getRoundingModeImpl(pFloatingPointRoundingMode);
@@ -78,7 +81,7 @@ protected Term makeNumberImpl(
return termManager.mkFloatingPoint(
termManager.mkBitVector(1, sign == Sign.NEGATIVE ? 1 : 0),
termManager.mkBitVector(type.getExponentSize(), exponent.toString(16), 16),
- termManager.mkBitVector(type.getMantissaSize(), mantissa.toString(16), 16));
+ termManager.mkBitVector(type.getMantissaSizeWithoutSignBit(), mantissa.toString(16), 16));
} catch (CVC5ApiException e) {
throw new IllegalArgumentException("You tried creating a invalid bitvector", e);
@@ -90,7 +93,7 @@ protected Term makeNumberAndRound(String pN, FloatingPointType pType, Term pRoun
try {
if (isNegativeZero(Double.valueOf(pN))) {
return termManager.mkFloatingPointNegZero(
- pType.getExponentSize(), pType.getMantissaSize() + 1);
+ pType.getExponentSize(), pType.getMantissaSizeWithSignBit());
}
} catch (CVC5ApiException | NumberFormatException e) {
// ignore and fallback to floating point from rational numbers
@@ -102,7 +105,7 @@ protected Term makeNumberAndRound(String pN, FloatingPointType pType, Term pRoun
termManager.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_REAL,
pType.getExponentSize(),
- pType.getMantissaSize() + 1);
+ pType.getMantissaSizeWithSignBit());
Term term =
termManager.mkTerm(realToFp, pRoundingMode, termManager.mkReal(rationalValue.toString()));
// simplification removes the cast from real to fp and return a bit-precise fp-number.
@@ -111,8 +114,8 @@ protected Term makeNumberAndRound(String pN, FloatingPointType pType, Term pRoun
throw new IllegalArgumentException(
"You tried creating a invalid floating point with exponent size "
+ pType.getExponentSize()
- + ", mantissa size "
- + pType.getMantissaSize()
+ + ", mantissa size (including sign bit)"
+ + pType.getMantissaSizeWithSignBit()
+ " and value "
+ pN
+ ".",
@@ -152,13 +155,13 @@ protected Term makeVariableImpl(String varName, FloatingPointType pType) {
protected Term makePlusInfinityImpl(FloatingPointType pType) {
try {
return termManager.mkFloatingPointPosInf(
- pType.getExponentSize(), pType.getMantissaSize() + 1);
+ pType.getExponentSize(), pType.getMantissaSizeWithSignBit());
} catch (CVC5ApiException e) {
throw new IllegalArgumentException(
"You tried creating a invalid positive floating point +infinity with exponent size "
+ pType.getExponentSize()
+ " and mantissa size "
- + pType.getMantissaSize()
+ + pType.getMantissaSizeWithSignBit()
+ ".",
e);
}
@@ -168,13 +171,13 @@ protected Term makePlusInfinityImpl(FloatingPointType pType) {
protected Term makeMinusInfinityImpl(FloatingPointType pType) {
try {
return termManager.mkFloatingPointNegInf(
- pType.getExponentSize(), pType.getMantissaSize() + 1);
+ pType.getExponentSize(), pType.getMantissaSizeWithSignBit());
} catch (CVC5ApiException e) {
throw new IllegalArgumentException(
"You tried creating a invalid negative floating point -infinity with exponent size "
+ pType.getExponentSize()
+ " and mantissa size "
- + pType.getMantissaSize()
+ + pType.getMantissaSizeWithSignBit()
+ ".",
e);
}
@@ -183,13 +186,14 @@ protected Term makeMinusInfinityImpl(FloatingPointType pType) {
@Override
protected Term makeNaNImpl(FloatingPointType pType) {
try {
- return termManager.mkFloatingPointNaN(pType.getExponentSize(), pType.getMantissaSize() + 1);
+ return termManager.mkFloatingPointNaN(
+ pType.getExponentSize(), pType.getMantissaSizeWithSignBit());
} catch (CVC5ApiException e) {
throw new IllegalArgumentException(
"You tried creating a invalid NaN with exponent size "
+ pType.getExponentSize()
+ " and mantissa size "
- + pType.getMantissaSize()
+ + pType.getMantissaSizeWithSignBit()
+ ".",
e);
}
@@ -205,7 +209,7 @@ protected Term castToImpl(
termManager.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_FP,
((FloatingPointType) pTargetType).getExponentSize(),
- ((FloatingPointType) pTargetType).getMantissaSize() + 1);
+ ((FloatingPointType) pTargetType).getMantissaSizeWithSignBit());
return termManager.mkTerm(fpToFp, pRoundingMode, pNumber);
} else if (pTargetType.isBitvectorType()) {
@@ -246,7 +250,7 @@ protected Term castFromImpl(
termManager.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_REAL,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize() + 1);
+ pTargetType.getMantissaSizeWithSignBit());
return termManager.mkTerm(realToFp, pRoundingMode, pNumber);
@@ -256,14 +260,14 @@ protected Term castFromImpl(
termManager.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_SBV,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize() + 1);
+ pTargetType.getMantissaSizeWithSignBit());
return termManager.mkTerm(realToSBv, pRoundingMode, pNumber);
} else {
Op realToUBv =
termManager.mkOp(
Kind.FLOATINGPOINT_TO_FP_FROM_UBV,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize() + 1);
+ pTargetType.getMantissaSizeWithSignBit());
return termManager.mkTerm(realToUBv, pRoundingMode, pNumber);
}
@@ -278,7 +282,7 @@ protected Term castFromImpl(
+ " into a FloatingPoint with exponent size "
+ pTargetType.getExponentSize()
+ " and mantissa size "
- + pTargetType.getMantissaSize()
+ + pTargetType.getMantissaSizeWithSignBit()
+ ".",
e);
}
@@ -408,41 +412,33 @@ protected Term isNegative(Term pParam) {
}
@Override
- protected Term fromIeeeBitvectorImpl(Term bitvector, FloatingPointType pTargetType) {
- int mantissaSize = pTargetType.getMantissaSize();
- int exponentSize = pTargetType.getExponentSize();
- int size = pTargetType.getTotalSize();
- assert size == mantissaSize + exponentSize + 1;
-
- Op signExtract;
- Op exponentExtract;
- Op mantissaExtract;
+ protected Term fromIeeeBitvectorImpl(Term pBitvector, FloatingPointType pTargetType) {
try {
- signExtract = termManager.mkOp(Kind.BITVECTOR_EXTRACT, size - 1, size - 1);
- exponentExtract = termManager.mkOp(Kind.BITVECTOR_EXTRACT, size - 2, mantissaSize);
- mantissaExtract = termManager.mkOp(Kind.BITVECTOR_EXTRACT, mantissaSize - 1, 0);
- } catch (CVC5ApiException e) {
- throw new IllegalArgumentException(
- "You tried creating a invalid bitvector extract in term " + bitvector + ".", e);
+ return termManager.mkTerm(
+ termManager.mkOp(
+ Kind.FLOATINGPOINT_TO_FP_FROM_IEEE_BV,
+ pTargetType.getExponentSize(),
+ pTargetType.getMantissaSizeWithSignBit()),
+ pBitvector);
+ } catch (CVC5ApiException pE) {
+ throw new RuntimeException(pE);
}
+ }
- Term sign = termManager.mkTerm(signExtract, bitvector);
- Term exponent = termManager.mkTerm(exponentExtract, bitvector);
- Term mantissa = termManager.mkTerm(mantissaExtract, bitvector);
-
- return termManager.mkTerm(Kind.FLOATINGPOINT_FP, sign, exponent, mantissa);
+ @Override
+ protected Term round(Term pFormula, FloatingPointRoundingMode pRoundingMode) {
+ return termManager.mkTerm(Kind.FLOATINGPOINT_RTI, getRoundingModeImpl(pRoundingMode), pFormula);
}
@Override
- protected Term toIeeeBitvectorImpl(Term pNumber) {
- // TODO possible work-around: use a tmp-variable "TMP" and add an
- // additional constraint "pNumer == fromIeeeBitvectorImpl(TMP)" for it in all use-cases.
- // --> This has to be done on user-side, not in JavaSMT.
- throw new UnsupportedOperationException("FP to IEEE-BV is not supported");
+ protected int getMantissaSizeWithSignBitImpl(Term f) {
+ Sort sort = f.getSort();
+ return sort.getFloatingPointSignificandSize();
}
@Override
- protected Term round(Term pFormula, FloatingPointRoundingMode pRoundingMode) {
- return termManager.mkTerm(Kind.FLOATINGPOINT_RTI, getRoundingModeImpl(pRoundingMode), pFormula);
+ protected int getExponentSizeImpl(Term f) {
+ Sort sort = f.getSort();
+ return sort.getFloatingPointExponentSize();
}
}
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
index 946b6be069..381daa2a29 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
@@ -142,14 +142,15 @@ public Sort getBitvectorType(int pBitwidth) {
public Sort getFloatingPointType(FloatingPointType pType) {
try {
// plus sign bit
- return termManager.mkFloatingPointSort(pType.getExponentSize(), pType.getMantissaSize() + 1);
+ return termManager.mkFloatingPointSort(
+ pType.getExponentSize(), pType.getMantissaSizeWithSignBit());
} catch (CVC5ApiException e) {
throw new IllegalArgumentException(
"Cannot create floatingpoint sort with exponent size "
+ pType.getExponentSize()
+ " and mantissa "
- + pType.getMantissaSize()
- + " (plus sign bit).",
+ + pType.getMantissaSizeWithSignBit()
+ + " (including sign bit).",
e);
}
}
@@ -223,7 +224,7 @@ private FormulaType> getFormulaTypeFromTermType(Sort sort) {
return FormulaType.getBitvectorTypeWithSize(sort.getBitVectorSize());
} else if (sort.isFloatingPoint()) {
// CVC5 wants the sign bit as part of the mantissa. We add that manually in creation.
- return FormulaType.getFloatingPointType(
+ return FormulaType.getFloatingPointTypeWithoutSignBit(
sort.getFloatingPointExponentSize(), sort.getFloatingPointSignificandSize() - 1);
} else if (sort.isRoundingMode()) {
return FormulaType.FloatingPointRoundingModeType;
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5SolverContext.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5SolverContext.java
index 97e0d269b2..696334c8ee 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5SolverContext.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5SolverContext.java
@@ -150,7 +150,8 @@ public static SolverContext create(
CVC5BitvectorFormulaManager bitvectorTheory =
new CVC5BitvectorFormulaManager(pCreator, booleanTheory);
CVC5FloatingPointFormulaManager fpTheory =
- new CVC5FloatingPointFormulaManager(pCreator, pFloatingPointRoundingMode);
+ new CVC5FloatingPointFormulaManager(
+ pCreator, pFloatingPointRoundingMode, bitvectorTheory, booleanTheory);
CVC5QuantifiedFormulaManager qfTheory = new CVC5QuantifiedFormulaManager(pCreator);
CVC5ArrayFormulaManager arrayTheory = new CVC5ArrayFormulaManager(pCreator);
CVC5SLFormulaManager slTheory = new CVC5SLFormulaManager(pCreator);
diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractNativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractNativeApiTest.java
index bd277cf91a..129b2669a8 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractNativeApiTest.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractNativeApiTest.java
@@ -35,6 +35,7 @@
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_repr;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_to_smtlib2_ext;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_to_smtlib2_term;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_type_equals;
import org.junit.After;
import org.junit.Ignore;
@@ -79,6 +80,44 @@ public void fpMantWidth() {
assertThat(msat_get_fp_type_mant_width(env, type)).isEqualTo(23);
}
+ /*
+ * MathSAT5, compared to all other solvers and the standard, does not expect the sign bit to be
+ * included in the mantissa!
+ */
+ @Test
+ public void fpMantissaDoesNotIncludeSignBit() {
+ int totalBVSize = 32;
+ long bvNumber = msat_make_bv_number(env, "42", totalBVSize, 10);
+ long bvType = msat_term_get_type(bvNumber);
+ assertThat(msat_get_bv_type_size(env, bvType)).isEqualTo(totalBVSize);
+ assertThat(msat_get_bv_type_size(env, msat_term_get_type(bvNumber))).isEqualTo(totalBVSize);
+
+ int exponent = 8;
+ int mantissaWithoutSign = 23; // excluding sign bit
+ long fpSinglePrecType = msat_get_fp_type(env, exponent, mantissaWithoutSign);
+ assertThat(msat_get_fp_type_mant_width(env, fpSinglePrecType)).isEqualTo(mantissaWithoutSign);
+ assertThat(msat_get_fp_type_exp_width(env, fpSinglePrecType)).isEqualTo(exponent);
+ // total size is exp + man + 1
+ assertThat(
+ msat_get_fp_type_mant_width(env, fpSinglePrecType)
+ + msat_get_fp_type_exp_width(env, fpSinglePrecType)
+ + 1)
+ .isEqualTo(totalBVSize);
+
+ long bvToFpSinglePrec =
+ Mathsat5NativeApi.msat_make_fp_from_ieeebv(env, exponent, mantissaWithoutSign, bvNumber);
+ assertThat(msat_type_equals(msat_term_get_type(bvToFpSinglePrec), fpSinglePrecType)).isTrue();
+ assertThat(msat_get_fp_type_mant_width(env, msat_term_get_type(bvToFpSinglePrec)))
+ .isEqualTo(mantissaWithoutSign);
+ assertThat(msat_get_fp_type_exp_width(env, msat_term_get_type(bvToFpSinglePrec)))
+ .isEqualTo(exponent);
+
+ long bvToFpSinglePrecToBv = Mathsat5NativeApi.msat_make_fp_as_ieeebv(env, bvToFpSinglePrec);
+ assertThat(msat_type_equals(msat_term_get_type(bvToFpSinglePrecToBv), bvType)).isTrue();
+ assertThat(msat_get_bv_type_size(env, msat_term_get_type(bvToFpSinglePrecToBv)))
+ .isEqualTo(totalBVSize);
+ }
+
@Test
public void fpExpWidthIllegal() {
long type = msat_get_integer_type(env);
diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FloatingPointFormulaManager.java
index d994620231..2eb6eb2750 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FloatingPointFormulaManager.java
@@ -8,6 +8,8 @@
package org.sosy_lab.java_smt.solvers.mathsat5;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_fp_type_exp_width;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_fp_type_mant_width;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_equal;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_fp_abs;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_fp_bits_number;
@@ -61,8 +63,11 @@ class Mathsat5FloatingPointFormulaManager
private final long roundingMode;
Mathsat5FloatingPointFormulaManager(
- Mathsat5FormulaCreator pCreator, FloatingPointRoundingMode pFloatingPointRoundingMode) {
- super(pCreator);
+ Mathsat5FormulaCreator pCreator,
+ FloatingPointRoundingMode pFloatingPointRoundingMode,
+ Mathsat5BitvectorFormulaManager pBvFormulaManager,
+ Mathsat5BooleanFormulaManager pBoolFormulaManager) {
+ super(pCreator, pBvFormulaManager, pBoolFormulaManager);
mathsatEnv = pCreator.getEnv();
roundingMode = getRoundingModeImpl(pFloatingPointRoundingMode);
@@ -102,27 +107,41 @@ protected Long makeNumberImpl(
BigInteger exponent, BigInteger mantissa, Sign sign, FloatingPointType type) {
final String signStr = sign.isNegative() ? "1" : "0";
final String exponentStr = getBvRepresentation(exponent, type.getExponentSize());
- final String mantissaStr = getBvRepresentation(mantissa, type.getMantissaSize());
+ // MathSAT5 expects the mantissa to not include the sign bit
+ final String mantissaStr = getBvRepresentation(mantissa, type.getMantissaSizeWithSignBit() - 1);
final String bitvecForm = signStr + exponentStr + mantissaStr;
final BigInteger bitvecValue = new BigInteger(bitvecForm, 2);
return msat_make_fp_bits_number(
- mathsatEnv, bitvecValue.toString(), type.getExponentSize(), type.getMantissaSize());
+ mathsatEnv,
+ bitvecValue.toString(),
+ type.getExponentSize(),
+ type.getMantissaSizeWithSignBit() - 1);
}
@Override
protected Long makeNumberAndRound(String pN, FloatingPointType pType, Long pRoundingMode) {
try {
if (isNegativeZero(Double.valueOf(pN))) {
+ // MathSAT5 expects the mantissa to not include the sign bit
return msat_make_fp_neg(
mathsatEnv,
msat_make_fp_rat_number(
- mathsatEnv, "0", pType.getExponentSize(), pType.getMantissaSize(), pRoundingMode));
+ mathsatEnv,
+ "0",
+ pType.getExponentSize(),
+ pType.getMantissaSizeWithSignBit() - 1,
+ pRoundingMode));
}
} catch (NumberFormatException e) {
// ignore and fallback to floating point from rational numbers
}
+ // MathSAT5 expects the mantissa to not include the sign bit
return msat_make_fp_rat_number(
- mathsatEnv, pN, pType.getExponentSize(), pType.getMantissaSize(), pRoundingMode);
+ mathsatEnv,
+ pN,
+ pType.getExponentSize(),
+ pType.getMantissaSizeWithoutSignBit(),
+ pRoundingMode);
}
@Override
@@ -132,17 +151,23 @@ protected Long makeVariableImpl(String var, FloatingPointType type) {
@Override
protected Long makePlusInfinityImpl(FloatingPointType type) {
- return msat_make_fp_plus_inf(mathsatEnv, type.getExponentSize(), type.getMantissaSize());
+ // MathSAT5 expects the mantissa to not include the sign bit
+ return msat_make_fp_plus_inf(
+ mathsatEnv, type.getExponentSize(), type.getMantissaSizeWithSignBit() - 1);
}
@Override
protected Long makeMinusInfinityImpl(FloatingPointType type) {
- return msat_make_fp_minus_inf(mathsatEnv, type.getExponentSize(), type.getMantissaSize());
+ // MathSAT5 expects the mantissa to not include the sign bit
+ return msat_make_fp_minus_inf(
+ mathsatEnv, type.getExponentSize(), type.getMantissaSizeWithSignBit() - 1);
}
@Override
protected Long makeNaNImpl(FloatingPointType type) {
- return msat_make_fp_nan(mathsatEnv, type.getExponentSize(), type.getMantissaSize());
+ // MathSAT5 expects the mantissa to not include the sign bit
+ return msat_make_fp_nan(
+ mathsatEnv, type.getExponentSize(), type.getMantissaSizeWithSignBit() - 1);
}
@Override
@@ -150,10 +175,11 @@ protected Long castToImpl(
Long pNumber, boolean pSigned, FormulaType> pTargetType, Long pRoundingMode) {
if (pTargetType.isFloatingPointType()) {
FormulaType.FloatingPointType targetType = (FormulaType.FloatingPointType) pTargetType;
+ // MathSAT5 expects the mantissa to not include the sign bit
return msat_make_fp_cast(
mathsatEnv,
targetType.getExponentSize(),
- targetType.getMantissaSize(),
+ targetType.getMantissaSizeWithSignBit() - 1,
pRoundingMode,
pNumber);
@@ -179,18 +205,19 @@ protected Long castFromImpl(
return castToImpl(pNumber, pSigned, pTargetType, pRoundingMode);
} else if (formulaType.isBitvectorType()) {
+ // MathSAT5 expects the mantissa to not include the sign bit
if (pSigned) {
return msat_make_fp_from_sbv(
mathsatEnv,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize(),
+ pTargetType.getMantissaSizeWithSignBit() - 1,
pRoundingMode,
pNumber);
} else {
return msat_make_fp_from_ubv(
mathsatEnv,
pTargetType.getExponentSize(),
- pTargetType.getMantissaSize(),
+ pTargetType.getMantissaSizeWithSignBit() - 1,
pRoundingMode,
pNumber);
}
@@ -214,8 +241,12 @@ private Long genericCast(Long pNumber, FormulaType> pTargetType) {
@Override
protected Long fromIeeeBitvectorImpl(Long pNumber, FloatingPointType pTargetType) {
+ // MathSAT5 expects the mantissa to not include the sign bit
return Mathsat5NativeApi.msat_make_fp_from_ieeebv(
- mathsatEnv, pTargetType.getExponentSize(), pTargetType.getMantissaSize(), pNumber);
+ mathsatEnv,
+ pTargetType.getExponentSize(),
+ pTargetType.getMantissaSizeWithSignBit() - 1,
+ pNumber);
}
@Override
@@ -223,6 +254,17 @@ protected Long toIeeeBitvectorImpl(Long pNumber) {
return Mathsat5NativeApi.msat_make_fp_as_ieeebv(mathsatEnv, pNumber);
}
+ @Override
+ protected int getMantissaSizeWithSignBitImpl(Long f) {
+ // The mantissa includes the sign bit according to the SMTLib2 standard, but MathSAT does not.
+ return msat_get_fp_type_mant_width(mathsatEnv, msat_term_get_type(f)) + 1;
+ }
+
+ @Override
+ protected int getExponentSizeImpl(Long f) {
+ return msat_get_fp_type_exp_width(mathsatEnv, msat_term_get_type(f));
+ }
+
@Override
protected Long negate(Long pNumber) {
return msat_make_fp_neg(mathsatEnv, pNumber);
diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
index ff35694c4a..d39b2f7d3b 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
@@ -213,7 +213,7 @@ private FormulaType> getFormulaTypeFromTermType(Long type) {
} else if (msat_is_bv_type(env, type)) {
return FormulaType.getBitvectorTypeWithSize(msat_get_bv_type_size(env, type));
} else if (msat_is_fp_type(env, type)) {
- return FormulaType.getFloatingPointType(
+ return FormulaType.getFloatingPointTypeWithoutSignBit(
msat_get_fp_type_exp_width(env, type), msat_get_fp_type_mant_width(env, type));
} else if (msat_is_fp_roundingmode_type(env, type)) {
return FormulaType.FloatingPointRoundingModeType;
@@ -241,7 +241,9 @@ public Long getBitvectorType(int pBitwidth) {
@Override
public Long getFloatingPointType(FloatingPointType pType) {
- return msat_get_fp_type(getEnv(), pType.getExponentSize(), pType.getMantissaSize());
+ // MathSAT5 automatically adds 1 to the mantissa, as it expects it to be without it.
+ return msat_get_fp_type(
+ getEnv(), pType.getExponentSize(), pType.getMantissaSizeWithSignBit() - 1);
}
@SuppressWarnings("unchecked")
@@ -575,13 +577,14 @@ private FloatingPointNumber parseFloatingPoint(String lTermRepresentation) {
BigInteger bits = new BigInteger(matcher.group(1));
int expWidth = Integer.parseInt(matcher.group(2));
- int mantWidth = Integer.parseInt(matcher.group(3));
+ // The term representation in MathSAT5 does not include the sign bit
+ int mantWidthWithoutSignBit = Integer.parseInt(matcher.group(3));
- Sign sign = Sign.of(bits.testBit(expWidth + mantWidth));
- BigInteger exponent = extractBitsFrom(bits, mantWidth, expWidth);
- BigInteger mantissa = extractBitsFrom(bits, 0, mantWidth);
+ Sign sign = Sign.of(bits.testBit(expWidth + mantWidthWithoutSignBit));
+ BigInteger exponent = extractBitsFrom(bits, mantWidthWithoutSignBit, expWidth);
+ BigInteger mantissa = extractBitsFrom(bits, 0, mantWidthWithoutSignBit);
- return FloatingPointNumber.of(sign, exponent, mantissa, expWidth, mantWidth);
+ return FloatingPointNumber.of(sign, exponent, mantissa, expWidth, mantWidthWithoutSignBit);
}
/**
diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5SolverContext.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5SolverContext.java
index 8ca17b8a2a..aaec8987bf 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5SolverContext.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5SolverContext.java
@@ -192,7 +192,8 @@ public static Mathsat5SolverContext create(
Mathsat5BitvectorFormulaManager bitvectorTheory =
new Mathsat5BitvectorFormulaManager(creator, booleanTheory);
Mathsat5FloatingPointFormulaManager floatingPointTheory =
- new Mathsat5FloatingPointFormulaManager(creator, pFloatingPointRoundingMode);
+ new Mathsat5FloatingPointFormulaManager(
+ creator, pFloatingPointRoundingMode, bitvectorTheory, booleanTheory);
Mathsat5ArrayFormulaManager arrayTheory = new Mathsat5ArrayFormulaManager(creator);
Mathsat5EnumerationFormulaManager enumerationTheory =
new Mathsat5EnumerationFormulaManager(creator);
diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3FloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3FloatingPointFormulaManager.java
index 84ed3dc559..d7714c401f 100644
--- a/src/org/sosy_lab/java_smt/solvers/z3/Z3FloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3FloatingPointFormulaManager.java
@@ -20,14 +20,18 @@
class Z3FloatingPointFormulaManager
extends AbstractFloatingPointFormulaManager {
- private static final FloatingPointType highPrec = FormulaType.getFloatingPointType(15, 112);
+ private static final FloatingPointType highPrec =
+ FormulaType.getFloatingPointTypeWithoutSignBit(15, 112);
private final long z3context;
private final long roundingMode;
Z3FloatingPointFormulaManager(
- Z3FormulaCreator creator, FloatingPointRoundingMode pFloatingPointRoundingMode) {
- super(creator);
+ Z3FormulaCreator creator,
+ FloatingPointRoundingMode pFloatingPointRoundingMode,
+ Z3BitvectorFormulaManager pBvFormulaManager,
+ Z3BooleanFormulaManager pBoolFormulaManager) {
+ super(creator, pBvFormulaManager, pBoolFormulaManager);
z3context = creator.getEnv();
roundingMode = getRoundingModeImpl(pFloatingPointRoundingMode);
}
@@ -78,7 +82,8 @@ protected Long makeNumberImpl(
final long signSort = getFormulaCreator().getBitvectorType(1);
final long expoSort = getFormulaCreator().getBitvectorType(type.getExponentSize());
- final long mantSort = getFormulaCreator().getBitvectorType(type.getMantissaSize());
+ final long mantSort =
+ getFormulaCreator().getBitvectorType(type.getMantissaSizeWithoutSignBit());
final long signBv = Native.mkNumeral(z3context, sign.isNegative() ? "1" : "0", signSort);
Native.incRef(z3context, signBv);
@@ -99,7 +104,7 @@ protected Long makeNumberAndRound(String pN, FloatingPointType pType, Long pRoun
// Z3 does not allow specifying a rounding mode for numerals,
// so we create it first with a high precision and then round it down explicitly.
if (pType.getExponentSize() <= highPrec.getExponentSize()
- || pType.getMantissaSize() <= highPrec.getMantissaSize()) {
+ || pType.getMantissaSizeWithSignBit() <= highPrec.getMantissaSizeWithSignBit()) {
long highPrecNumber = Native.mkNumeral(z3context, pN, mkFpaSort(highPrec));
Native.incRef(z3context, highPrecNumber);
long smallPrecNumber =
@@ -314,4 +319,14 @@ protected Long isNegative(Long pParam) {
protected Long round(Long pFormula, FloatingPointRoundingMode pRoundingMode) {
return Native.mkFpaRoundToIntegral(z3context, getRoundingModeImpl(pRoundingMode), pFormula);
}
+
+ @Override
+ protected int getMantissaSizeWithSignBitImpl(Long f) {
+ return Native.fpaGetEbits(z3context, Native.getSort(z3context, f));
+ }
+
+ @Override
+ protected int getExponentSizeImpl(Long f) {
+ return Native.fpaGetSbits(z3context, Native.getSort(z3context, f));
+ }
}
diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
index bde94b3e5f..890b5d8eac 100644
--- a/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
@@ -241,7 +241,7 @@ public FormulaType> getFormulaTypeFromSort(Long pSort) {
return FormulaType.getArrayType(
getFormulaTypeFromSort(domainSort), getFormulaTypeFromSort(rangeSort));
case Z3_FLOATING_POINT_SORT:
- return FormulaType.getFloatingPointType(
+ return FormulaType.getFloatingPointTypeWithoutSignBit(
Native.fpaGetEbits(z3context, pSort), Native.fpaGetSbits(z3context, pSort) - 1);
case Z3_ROUNDING_MODE_SORT:
return FormulaType.FloatingPointRoundingModeType;
@@ -420,7 +420,8 @@ public Long getBitvectorType(int pBitwidth) {
@Override
public Long getFloatingPointType(FormulaType.FloatingPointType type) {
- long fpSort = Native.mkFpaSort(getEnv(), type.getExponentSize(), type.getMantissaSize() + 1);
+ long fpSort =
+ Native.mkFpaSort(getEnv(), type.getExponentSize(), type.getMantissaSizeWithSignBit());
Native.incRef(getEnv(), Native.sortToAst(getEnv(), fpSort));
return fpSort;
}
@@ -967,7 +968,7 @@ private FloatingPointNumber convertFloatingPoint(FloatingPointType pType, Long p
expo,
mant,
pType.getExponentSize(),
- pType.getMantissaSize());
+ pType.getMantissaSizeWithSignBit());
} else if (Native.fpaIsNumeralInf(environment, pValue)) {
// Floating Point Inf uses:
@@ -976,9 +977,11 @@ private FloatingPointNumber convertFloatingPoint(FloatingPointType pType, Long p
// - "00..00" as mantissa.
String sign = getSign(pValue).isNegative() ? "1" : "0";
return FloatingPointNumber.of(
- sign + "1".repeat(pType.getExponentSize()) + "0".repeat(pType.getMantissaSize()),
+ sign
+ + "1".repeat(pType.getExponentSize())
+ + "0".repeat(pType.getMantissaSizeWithSignBit()),
pType.getExponentSize(),
- pType.getMantissaSize());
+ pType.getMantissaSizeWithSignBit());
} else if (Native.fpaIsNumeralNan(environment, pValue)) {
// TODO We are underspecified here and choose several bits on our own.
@@ -988,9 +991,11 @@ private FloatingPointNumber convertFloatingPoint(FloatingPointType pType, Long p
// - "11..11" as exponent,
// - an unspecified mantissa (we choose all "1").
return FloatingPointNumber.of(
- "0" + "1".repeat(pType.getExponentSize()) + "1".repeat(pType.getMantissaSize()),
+ "0"
+ + "1".repeat(pType.getExponentSize())
+ + "1".repeat(pType.getMantissaSizeWithSignBit()),
pType.getExponentSize(),
- pType.getMantissaSize());
+ pType.getMantissaSizeWithSignBit());
} else {
Sign sign = getSign(pValue);
@@ -1003,7 +1008,7 @@ private FloatingPointNumber convertFloatingPoint(FloatingPointType pType, Long p
new BigInteger(exponent),
new BigInteger(mantissa),
pType.getExponentSize(),
- pType.getMantissaSize());
+ pType.getMantissaSizeWithSignBit());
}
}
diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java
index 7d408faf11..80f9bd6904 100644
--- a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java
+++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java
@@ -186,7 +186,8 @@ public static synchronized Z3SolverContext create(
Z3BitvectorFormulaManager bitvectorTheory =
new Z3BitvectorFormulaManager(creator, booleanTheory);
Z3FloatingPointFormulaManager floatingPointTheory =
- new Z3FloatingPointFormulaManager(creator, pFloatingPointRoundingMode);
+ new Z3FloatingPointFormulaManager(
+ creator, pFloatingPointRoundingMode, bitvectorTheory, booleanTheory);
Z3QuantifiedFormulaManager quantifierManager = new Z3QuantifiedFormulaManager(creator);
Z3ArrayFormulaManager arrayManager = new Z3ArrayFormulaManager(creator);
Z3StringFormulaManager stringTheory = new Z3StringFormulaManager(creator);
diff --git a/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java b/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
index 74390241cf..00b1af6168 100644
--- a/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
+++ b/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
@@ -15,6 +15,7 @@
import static org.sosy_lab.java_smt.test.ProverEnvironmentSubject.assertThat;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import java.math.BigDecimal;
@@ -41,6 +42,7 @@
import org.sosy_lab.java_smt.api.ProverEnvironment;
import org.sosy_lab.java_smt.api.SolverContext.ProverOptions;
import org.sosy_lab.java_smt.api.SolverException;
+import org.sosy_lab.java_smt.basicimpl.AbstractFloatingPointFormulaManager.BitvectorFormulaAndBooleanFormula;
public class FloatingPointFormulaManagerTest
extends SolverBasedTest0.ParameterizedSolverBasedTest0 {
@@ -73,9 +75,35 @@ public void init() {
one = fpmgr.makeNumber(1.0, singlePrecType);
}
+ @Test
+ public void testSpecialNumberIdentity() {
+ assertThat(fpmgr.makeNaN(singlePrecType)).isEqualTo(nan);
+ assertThat(fpmgr.makePlusInfinity(singlePrecType)).isEqualTo(posInf);
+ assertThat(fpmgr.makeMinusInfinity(singlePrecType)).isEqualTo(negInf);
+ assertThat(fpmgr.makeNumber(0.0, singlePrecType)).isEqualTo(zero);
+ assertThat(fpmgr.makeNumber(-0.0, singlePrecType)).isEqualTo(negZero);
+
+ assertThat(fpmgr.makeNaN(doublePrecType)).isEqualTo(fpmgr.makeNaN(doublePrecType));
+ assertThat(fpmgr.makePlusInfinity(doublePrecType))
+ .isEqualTo(fpmgr.makePlusInfinity(doublePrecType));
+ assertThat(fpmgr.makeMinusInfinity(doublePrecType))
+ .isEqualTo(fpmgr.makeMinusInfinity(doublePrecType));
+ assertThat(fpmgr.makeNumber(0.0, doublePrecType))
+ .isEqualTo(fpmgr.makeNumber(0.0, doublePrecType));
+ assertThat(fpmgr.makeNumber(-0.0, doublePrecType))
+ .isEqualTo(fpmgr.makeNumber(-0.0, doublePrecType));
+
+ // Different precisions should not be equal
+ assertThat(fpmgr.makeNaN(doublePrecType)).isNotEqualTo(nan);
+ assertThat(fpmgr.makePlusInfinity(doublePrecType)).isNotEqualTo(posInf);
+ assertThat(fpmgr.makeMinusInfinity(doublePrecType)).isNotEqualTo(negInf);
+ assertThat(fpmgr.makeNumber(0.0, doublePrecType)).isNotEqualTo(zero);
+ assertThat(fpmgr.makeNumber(-0.0, doublePrecType)).isNotEqualTo(negZero);
+ }
+
@Test
public void floatingPointType() {
- FloatingPointType type = FormulaType.getFloatingPointType(23, 42);
+ FloatingPointType type = FormulaType.getFloatingPointTypeWithoutSignBit(23, 42);
FloatingPointFormula var = fpmgr.makeVariable("x", type);
FloatingPointType result = (FloatingPointType) mgr.getFormulaType(var);
@@ -83,8 +111,8 @@ public void floatingPointType() {
.that(result.getExponentSize())
.isEqualTo(type.getExponentSize());
assertWithMessage("mantissa size")
- .that(result.getMantissaSize())
- .isEqualTo(type.getMantissaSize());
+ .that(result.getMantissaSizeWithSignBit())
+ .isEqualTo(type.getMantissaSizeWithSignBit());
}
@Test
@@ -258,7 +286,7 @@ public void fpRemainderNormal() throws SolverException, InterruptedException {
for (FloatingPointType prec :
new FloatingPointType[] {
- singlePrecType, doublePrecType, FormulaType.getFloatingPointType(5, 6),
+ singlePrecType, doublePrecType, FormulaType.getFloatingPointTypeWithoutSignBit(5, 6),
}) {
final FloatingPointFormula numFive = fpmgr.makeNumber(5, prec);
@@ -282,7 +310,7 @@ public void fpRemainderSpecial() throws SolverException, InterruptedException {
for (FloatingPointType prec :
new FloatingPointType[] {
- singlePrecType, doublePrecType, FormulaType.getFloatingPointType(5, 6),
+ singlePrecType, doublePrecType, FormulaType.getFloatingPointTypeWithoutSignBit(5, 6),
}) {
final FloatingPointFormula num = fpmgr.makeNumber(42, prec);
@@ -408,7 +436,7 @@ public void specialValueFunctionsFrom64Bits() throws SolverException, Interrupte
@Test
public void specialValueFunctionsFrom32Bits2() throws SolverException, InterruptedException {
requireBitvectors();
- requireFPToBitvector();
+ requireNativeFPToBitvector();
final FloatingPointFormula x = fpmgr.makeVariable("x32", singlePrecType);
final BitvectorFormula signBit = bvmgr.extract(fpmgr.toIeeeBitvector(x), 31, 31);
@@ -453,7 +481,7 @@ public void specialValueFunctionsFrom32Bits2() throws SolverException, Interrupt
@Test
public void specialValueFunctionsFrom64Bits2() throws SolverException, InterruptedException {
requireBitvectors();
- requireFPToBitvector();
+ requireNativeFPToBitvector();
final FloatingPointFormula x = fpmgr.makeVariable("x64", doublePrecType);
final BitvectorFormula signBit = bvmgr.extract(fpmgr.toIeeeBitvector(x), 63, 63);
@@ -499,6 +527,346 @@ public void specialValueFunctionsFrom64Bits2() throws SolverException, Interrupt
bmgr.and(bmgr.not(fpmgr.isNaN(x)), bvmgr.equal(signBit, bvmgr.makeBitvector(1, 1))));
}
+ // Same as specialValueFunctionsFrom32Bits2, but with fallback toIeeeBitvector() implementation.
+ @Test
+ public void specialValueFunctionsFrom32Bits2ToIeeeFallback()
+ throws SolverException, InterruptedException {
+ requireBitvectors();
+
+ final FloatingPointFormula x = fpmgr.makeVariable("x32", singlePrecType);
+ BitvectorFormulaAndBooleanFormula xToIeeeAndAddConstraint =
+ fpmgr.toIeeeBitvector(x, "bvConst_x");
+ BitvectorFormula xToIeee = xToIeeeAndAddConstraint.getBitvectorFormula();
+ final BitvectorFormula signBit = bvmgr.extract(xToIeee, 31, 31);
+ final BitvectorFormula exponent = bvmgr.extract(xToIeee, 30, 23);
+ final BitvectorFormula mantissa = bvmgr.extract(xToIeee, 22, 0);
+ final BooleanFormula additionalConstraint = xToIeeeAndAddConstraint.getBooleanFormula();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isInfinity(x),
+ bmgr.or(
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(32, 0x7f80_0000L)),
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(32, 0xff80_0000L))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isZero(x),
+ bmgr.or(
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(32, 0x0000_0000)),
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(32, 0x8000_0000L))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isNormal(x),
+ bmgr.and(
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(8, 0))),
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(8, -1)))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isSubnormal(x),
+ bmgr.and(
+ bvmgr.equal(exponent, bvmgr.makeBitvector(8, 0)),
+ bmgr.not(bvmgr.equal(mantissa, bvmgr.makeBitvector(23, 0)))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isNaN(x),
+ bmgr.and(
+ bvmgr.equal(exponent, bvmgr.makeBitvector(8, -1)),
+ bmgr.not(bvmgr.equal(mantissa, bvmgr.makeBitvector(23, 0)))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isNegative(x),
+ bmgr.and(
+ bmgr.not(fpmgr.isNaN(x)),
+ bvmgr.equal(signBit, bvmgr.makeBitvector(1, 1))))))
+ .isTautological();
+ }
+
+ // Same as specialValueFunctionsFrom64Bits2, but with fallback toIeeeBitvector() implementation.
+ @Test
+ public void specialValueFunctionsFrom64Bits2ToIeeeFallback()
+ throws SolverException, InterruptedException {
+ requireBitvectors();
+
+ final FloatingPointFormula x = fpmgr.makeVariable("x64", doublePrecType);
+ BitvectorFormulaAndBooleanFormula xToIeeeAndAddConstraint =
+ fpmgr.toIeeeBitvector(x, "bvConst_x");
+ BitvectorFormula xToIeee = xToIeeeAndAddConstraint.getBitvectorFormula();
+ final BitvectorFormula signBit = bvmgr.extract(xToIeee, 63, 63);
+ final BitvectorFormula exponent = bvmgr.extract(xToIeee, 62, 52);
+ final BitvectorFormula mantissa = bvmgr.extract(xToIeee, 51, 0);
+ final BooleanFormula additionalConstraint = xToIeeeAndAddConstraint.getBooleanFormula();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isInfinity(x),
+ bmgr.or(
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(64, 0x7ff0_0000_0000_0000L)),
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(64, 0xfff0_0000_0000_0000L))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isZero(x),
+ bmgr.or(
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(64, 0x0000_0000_0000_0000L)),
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(64, 0x8000_0000_0000_0000L))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isNormal(x),
+ bmgr.and(
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(11, 0))),
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(11, -1)))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isSubnormal(x),
+ bmgr.and(
+ bvmgr.equal(exponent, bvmgr.makeBitvector(11, 0)),
+ bmgr.not(bvmgr.equal(mantissa, bvmgr.makeBitvector(52, 0)))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isNaN(x),
+ bmgr.and(
+ bvmgr.equal(exponent, bvmgr.makeBitvector(11, -1)),
+ bmgr.not(bvmgr.equal(mantissa, bvmgr.makeBitvector(52, 0)))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ additionalConstraint,
+ bmgr.equivalence(
+ fpmgr.isNegative(x),
+ bmgr.and(
+ bmgr.not(fpmgr.isNaN(x)),
+ bvmgr.equal(signBit, bvmgr.makeBitvector(1, 1))))))
+ .isTautological();
+ }
+
+ // Same as specialValueFunctionsFrom32Bits2, but with fallback toIeeeBitvector() implementation
+ // with mapped special numbers.
+ @Test
+ public void specialValueFunctionsFrom32Bits2ToIeeeFallbackAlternatives()
+ throws SolverException, InterruptedException {
+ requireBitvectors();
+
+ final FloatingPointFormula x = fpmgr.makeVariable("x32", singlePrecType);
+ var nanBv = bvmgr.makeBitvector(32, 0x0110_0000L);
+ var negInfBv = bvmgr.makeBitvector(32, 0x7f80_0000L);
+ var posInfBv = bvmgr.makeBitvector(32, 0xff80_0000L);
+ BitvectorFormulaAndBooleanFormula xToIeeeAndAddConstraint =
+ fpmgr.toIeeeBitvector(
+ x,
+ "bvConst_x",
+ ImmutableMap.of(
+ fpmgr.makePlusInfinity(singlePrecType),
+ posInfBv,
+ fpmgr.makeMinusInfinity(singlePrecType),
+ negInfBv,
+ fpmgr.makeNaN(singlePrecType),
+ nanBv));
+ BitvectorFormula xToIeee = xToIeeeAndAddConstraint.getBitvectorFormula();
+ final BitvectorFormula signBit = bvmgr.extract(xToIeee, 31, 31);
+ final BitvectorFormula exponent = bvmgr.extract(xToIeee, 30, 23);
+ final BitvectorFormula mantissa = bvmgr.extract(xToIeee, 22, 0);
+ final BooleanFormula additionalConstraint = xToIeeeAndAddConstraint.getBooleanFormula();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(additionalConstraint, bmgr.not(fpmgr.isNegative(x)), fpmgr.isInfinity(x)),
+ bvmgr.equal(xToIeee, posInfBv)))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNegative(x), fpmgr.isInfinity(x), additionalConstraint),
+ bvmgr.equal(xToIeee, negInfBv)))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNaN(x), additionalConstraint), bvmgr.equal(xToIeee, nanBv)))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isZero(x), additionalConstraint),
+ bmgr.or(
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(32, 0x0000_0000)),
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(32, 0x8000_0000L)))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNormal(x), additionalConstraint),
+ bmgr.and(
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(8, 0))),
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(8, -1))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isSubnormal(x), additionalConstraint),
+ bmgr.and(
+ bvmgr.equal(exponent, bvmgr.makeBitvector(8, 0)),
+ bmgr.not(bvmgr.equal(mantissa, bvmgr.makeBitvector(23, 0))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNegative(x), bmgr.not(fpmgr.isInfinity(x)), additionalConstraint),
+ bmgr.and(
+ bmgr.not(fpmgr.isNaN(x)), bvmgr.equal(signBit, bvmgr.makeBitvector(1, 1)))))
+ .isTautological();
+ }
+
+ // Same as specialValueFunctionsFrom64Bits2, but with fallback toIeeeBitvector() implementation
+ // with redefinitions for special values.
+ @Test
+ public void specialValueFunctionsFrom64Bits2ToIeeeFallbackAlternatives()
+ throws SolverException, InterruptedException {
+ requireBitvectors();
+
+ final FloatingPointFormula x = fpmgr.makeVariable("x64", doublePrecType);
+ var nanBv = bvmgr.makeBitvector(64, 0x0111_1000_0000_0000L);
+ var negInfBv = bvmgr.makeBitvector(64, 0x0000_0000_0000_0001L);
+ var posInfBv = bvmgr.makeBitvector(64, 0x0000_0000_0000_0000L);
+ BitvectorFormulaAndBooleanFormula xToIeeeAndAddConstraint =
+ fpmgr.toIeeeBitvector(
+ x,
+ "bvConst_x",
+ ImmutableMap.of(
+ fpmgr.makePlusInfinity(doublePrecType),
+ posInfBv,
+ fpmgr.makeMinusInfinity(doublePrecType),
+ negInfBv,
+ fpmgr.makeNaN(doublePrecType),
+ nanBv));
+ BitvectorFormula xToIeee = xToIeeeAndAddConstraint.getBitvectorFormula();
+ final BitvectorFormula signBit = bvmgr.extract(xToIeee, 63, 63);
+ final BitvectorFormula exponent = bvmgr.extract(xToIeee, 62, 52);
+ final BitvectorFormula mantissa = bvmgr.extract(xToIeee, 51, 0);
+ final BooleanFormula additionalConstraint = xToIeeeAndAddConstraint.getBooleanFormula();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(bmgr.not(fpmgr.isNegative(x)), fpmgr.isInfinity(x), additionalConstraint),
+ bvmgr.equal(xToIeee, posInfBv)))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNegative(x), fpmgr.isInfinity(x), additionalConstraint),
+ bvmgr.equal(xToIeee, negInfBv)))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNaN(x), additionalConstraint), bvmgr.equal(xToIeee, nanBv)))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isZero(x), additionalConstraint),
+ bmgr.or(
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(64, 0x0000_0000_0000_0000L)),
+ bvmgr.equal(xToIeee, bvmgr.makeBitvector(64, 0x8000_0000_0000_0000L)))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNormal(x), additionalConstraint),
+ bmgr.and(
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(11, 0))),
+ bmgr.not(bvmgr.equal(exponent, bvmgr.makeBitvector(11, -1))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isSubnormal(x), additionalConstraint),
+ bmgr.and(
+ bvmgr.equal(exponent, bvmgr.makeBitvector(11, 0)),
+ bmgr.not(bvmgr.equal(mantissa, bvmgr.makeBitvector(52, 0))))))
+ .isTautological();
+
+ assertThatFormula(
+ bmgr.implication(
+ bmgr.and(fpmgr.isNegative(x), bmgr.not(fpmgr.isInfinity(x)), additionalConstraint),
+ bmgr.and(
+ bmgr.not(fpmgr.isNaN(x)), bvmgr.equal(signBit, bvmgr.makeBitvector(1, 1)))))
+ .isTautological();
+ }
+
+ @Test
+ public void floatingPointSinglePrecisionSizeWithBvTransformationTest() {
+ requireBitvectors();
+ int fpSinglePrecSize = 32;
+ var bv32 = bvmgr.makeBitvector(fpSinglePrecSize, 0);
+ assertThat(bvmgr.getLength(bv32)).isEqualTo(fpSinglePrecSize);
+
+ requireFloats();
+ var singlePrec = FormulaType.getSinglePrecisionFloatingPointType();
+ var fpSinglePrec = fpmgr.makeNumber(0.0, singlePrec);
+ // Sizes of the type and the actual term should match
+ assertThat(fpmgr.getExponentSize(fpSinglePrec)).isEqualTo(8);
+ assertThat(fpmgr.getMantissaSizeWithSignBit(fpSinglePrec)).isEqualTo(24);
+ assertThat(singlePrec.getExponentSize()).isEqualTo(8);
+ assertThat(singlePrec.getMantissaSizeWithSignBit()).isEqualTo(24);
+ assertThat(singlePrec.getExponentSize() + singlePrec.getMantissaSizeWithSignBit())
+ .isEqualTo(fpSinglePrecSize);
+ assertThat(singlePrec.getTotalSize())
+ .isEqualTo(singlePrec.getExponentSize() + singlePrec.getMantissaSizeWithSignBit());
+
+ assertThat(bvmgr.getLength(fpmgr.toIeeeBitvector(fpSinglePrec, "dummy1").getBitvectorFormula()))
+ .isEqualTo(fpSinglePrecSize);
+ assertThat(
+ bvmgr.getLength(
+ fpmgr
+ .toIeeeBitvector(fpSinglePrec, "dummy2", ImmutableMap.of())
+ .getBitvectorFormula()))
+ .isEqualTo(fpSinglePrecSize);
+
+ if (solverSupportsNativeFPToBitvector()) {
+ assertThat(bvmgr.getLength(fpmgr.toIeeeBitvector(fpSinglePrec))).isEqualTo(fpSinglePrecSize);
+ }
+ }
+
@Test
public void specialDoubles() throws SolverException, InterruptedException {
assertThatFormula(fpmgr.assignment(fpmgr.makeNumber(Double.NaN, singlePrecType), nan))
@@ -536,7 +904,7 @@ public void numberConstants() throws SolverException, InterruptedException {
checkEqualityOfNumberConstantsFor(3.4028234663852886e+38, doublePrecType);
// check unequality for large types
- FloatingPointType nearDouble = FormulaType.getFloatingPointType(12, 52);
+ FloatingPointType nearDouble = FormulaType.getFloatingPointTypeWithoutSignBit(12, 52);
FloatingPointFormula h1 =
fpmgr.makeNumber(BigDecimal.TEN.pow(309).multiply(BigDecimal.valueOf(1.0001)), nearDouble);
FloatingPointFormula h2 =
@@ -544,7 +912,7 @@ public void numberConstants() throws SolverException, InterruptedException {
assertThatFormula(fpmgr.equalWithFPSemantics(h1, h2)).isUnsatisfiable();
// check equality for short types
- FloatingPointType smallType = FormulaType.getFloatingPointType(4, 4);
+ FloatingPointType smallType = FormulaType.getFloatingPointTypeWithoutSignBit(4, 4);
FloatingPointFormula i1 =
fpmgr.makeNumber(BigDecimal.TEN.pow(50).multiply(BigDecimal.valueOf(1.001)), smallType);
FloatingPointFormula i2 =
@@ -573,7 +941,7 @@ public void numberConstants() throws SolverException, InterruptedException {
assertThatFormula(fpmgr.isNegative(ni2)).isTautological();
// check equality for short types
- FloatingPointType smallType2 = FormulaType.getFloatingPointType(4, 4);
+ FloatingPointType smallType2 = FormulaType.getFloatingPointTypeWithoutSignBit(4, 4);
FloatingPointFormula j1 =
fpmgr.makeNumber(BigDecimal.TEN.pow(500).multiply(BigDecimal.valueOf(1.001)), smallType2);
FloatingPointFormula j2 =
@@ -604,7 +972,7 @@ public void numberConstants() throws SolverException, InterruptedException {
// Z3 supports at least FloatingPointType(15, 112). Larger types seem to be rounded.
if (!ImmutableSet.of(Solvers.Z3, Solvers.CVC4).contains(solver)) {
// check unequality for very large types
- FloatingPointType largeType = FormulaType.getFloatingPointType(100, 100);
+ FloatingPointType largeType = FormulaType.getFloatingPointTypeWithoutSignBit(100, 100);
FloatingPointFormula k1 =
fpmgr.makeNumber(BigDecimal.TEN.pow(200).multiply(BigDecimal.valueOf(1.001)), largeType);
FloatingPointFormula k2 =
@@ -641,7 +1009,7 @@ public void numberConstantsNearInf() throws SolverException, InterruptedExceptio
private void checkNearInf(int mantissa, int exponent, long value)
throws SolverException, InterruptedException {
- FloatingPointType type = FormulaType.getFloatingPointType(exponent, mantissa);
+ FloatingPointType type = FormulaType.getFloatingPointTypeWithoutSignBit(exponent, mantissa);
FloatingPointFormula fp1 = fpmgr.makeNumber(BigDecimal.valueOf(value), type);
assertThatFormula(fpmgr.isInfinity(fp1)).isTautological();
FloatingPointFormula fp2 = fpmgr.makeNumber(BigDecimal.valueOf(value - 1), type);
@@ -676,7 +1044,7 @@ public void numberConstantsNearMinusInf() throws SolverException, InterruptedExc
private void checkNearMinusInf(int mantissa, int exponent, long value)
throws SolverException, InterruptedException {
- FloatingPointType type = FormulaType.getFloatingPointType(exponent, mantissa);
+ FloatingPointType type = FormulaType.getFloatingPointTypeWithoutSignBit(exponent, mantissa);
FloatingPointFormula fp1 = fpmgr.makeNumber(BigDecimal.valueOf(value), type);
assertThatFormula(fpmgr.isInfinity(fp1)).isTautological();
FloatingPointFormula fp2 = fpmgr.makeNumber(BigDecimal.valueOf(value + 1), type);
@@ -956,7 +1324,7 @@ public void fpTraversalWithRoundingMode() {
@Test
public void fpIeeeConversionTypes() {
- requireFPToBitvector();
+ requireNativeFPToBitvector();
FloatingPointFormula var = fpmgr.makeVariable("var", singlePrecType);
assertThat(mgr.getFormulaType(fpmgr.toIeeeBitvector(var)))
@@ -965,7 +1333,7 @@ public void fpIeeeConversionTypes() {
@Test
public void fpIeeeConversion() throws SolverException, InterruptedException {
- requireFPToBitvector();
+ requireNativeFPToBitvector();
FloatingPointFormula var = fpmgr.makeVariable("var", singlePrecType);
assertThatFormula(
@@ -976,7 +1344,7 @@ public void fpIeeeConversion() throws SolverException, InterruptedException {
@Test
public void ieeeFpConversion() throws SolverException, InterruptedException {
- requireFPToBitvector();
+ requireNativeFPToBitvector();
BitvectorFormula var = bvmgr.makeBitvector(32, 123456789);
assertThatFormula(
@@ -1046,7 +1414,7 @@ public void checkIeeeBv2FpConversion64() throws SolverException, InterruptedExce
@Test
public void checkIeeeFp2BvConversion32() throws SolverException, InterruptedException {
- requireFPToBitvector();
+ requireNativeFPToBitvector();
proveForAll(
// makeBV(value.bits) == fromFP(makeFP(value.float))
@@ -1059,7 +1427,7 @@ public void checkIeeeFp2BvConversion32() throws SolverException, InterruptedExce
@Test
public void checkIeeeFp2BvConversion64() throws SolverException, InterruptedException {
- requireFPToBitvector();
+ requireNativeFPToBitvector();
proveForAll(
// makeBV(value.bits) == fromFP(makeFP(value.float))
@@ -1215,9 +1583,16 @@ public void fpModelValue() throws SolverException, InterruptedException {
Float.MIN_VALUE,
Float.MIN_NORMAL,
}) {
- FloatingPointNumber fiveValue = model.evaluate(fpmgr.makeNumber(f, singlePrecType));
- assertThat(fiveValue.floatValue()).isEqualTo(f);
- assertThat(fiveValue.doubleValue()).isEqualTo((double) f);
+ var constFpNum = fpmgr.makeNumber(f, singlePrecType);
+ assertThat(fpmgr.getMantissaSizeWithSignBit(constFpNum))
+ .isEqualTo(singlePrecType.getMantissaSizeWithSignBit());
+ FloatingPointNumber fpValue = model.evaluate(constFpNum);
+ assertThat(fpValue.getMantissaSizeWithSignBit())
+ .isEqualTo(singlePrecType.getMantissaSizeWithSignBit());
+ assertThat(fpValue.getMantissaSizeWithoutSignBit())
+ .isEqualTo(singlePrecType.getMantissaSizeWithSignBit() - 1);
+ assertThat(fpValue.floatValue()).isEqualTo(f);
+ assertThat(fpValue.doubleValue()).isEqualTo((double) f);
}
}
}
@@ -1266,16 +1641,28 @@ public void fpFrom32BitPattern() throws SolverException, InterruptedException {
final FloatingPointFormula fpFromBv =
fpmgr.makeNumber(
BigInteger.valueOf(exponent), BigInteger.valueOf(mantissa), sign, singlePrecType);
+ assertThat(fpmgr.getMantissaSizeWithSignBit(fpFromBv) + fpmgr.getExponentSize(fpFromBv))
+ .isEqualTo(singlePrecType.getTotalSize());
final FloatingPointNumber fpNumber =
FloatingPointNumber.of(
sign,
BigInteger.valueOf(exponent),
BigInteger.valueOf(mantissa),
singlePrecType.getExponentSize(),
- singlePrecType.getMantissaSize());
+ singlePrecType.getMantissaSizeWithoutSignBit());
+ assertThat(fpNumber.getMantissaSizeWithSignBit())
+ .isEqualTo(singlePrecType.getMantissaSizeWithSignBit());
+ assertThat(fpNumber.getMantissaSizeWithoutSignBit())
+ .isEqualTo(singlePrecType.getMantissaSizeWithSignBit() - 1);
final FloatingPointFormula fp1 = fpmgr.makeNumber(fpNumber);
+ assertThat(fpmgr.getMantissaSizeWithSignBit(fp1) + fpmgr.getExponentSize(fp1))
+ .isEqualTo(singlePrecType.getTotalSize());
final FloatingPointFormula fp2 = fpmgr.makeNumber(pFloat, singlePrecType);
- return bmgr.and(fpmgr.assignment(fpFromBv, fp1), fpmgr.assignment(fpFromBv, fp2));
+ assertThat(fpmgr.getMantissaSizeWithSignBit(fp2) + fpmgr.getExponentSize(fp2))
+ .isEqualTo(singlePrecType.getTotalSize());
+ final BooleanFormula assignment1 = fpmgr.assignment(fpFromBv, fp1);
+ final BooleanFormula assignment2 = fpmgr.assignment(fpFromBv, fp2);
+ return bmgr.and(assignment1, assignment2);
});
}
@@ -1292,16 +1679,28 @@ public void fpFrom64BitPattern() throws SolverException, InterruptedException {
final FloatingPointFormula fpFromBv =
fpmgr.makeNumber(
BigInteger.valueOf(exponent), BigInteger.valueOf(mantissa), sign, doublePrecType);
+ assertThat(fpmgr.getMantissaSizeWithSignBit(fpFromBv) + fpmgr.getExponentSize(fpFromBv))
+ .isEqualTo(doublePrecType.getTotalSize());
final FloatingPointNumber fpNumber =
FloatingPointNumber.of(
sign,
BigInteger.valueOf(exponent),
BigInteger.valueOf(mantissa),
doublePrecType.getExponentSize(),
- doublePrecType.getMantissaSize());
+ doublePrecType.getMantissaSizeWithoutSignBit());
+ assertThat(fpNumber.getMantissaSizeWithSignBit())
+ .isEqualTo(doublePrecType.getMantissaSizeWithSignBit());
+ assertThat(fpNumber.getMantissaSizeWithoutSignBit())
+ .isEqualTo(doublePrecType.getMantissaSizeWithSignBit() - 1);
final FloatingPointFormula fp1 = fpmgr.makeNumber(fpNumber);
+ assertThat(fpmgr.getMantissaSizeWithSignBit(fp1) + fpmgr.getExponentSize(fp1))
+ .isEqualTo(doublePrecType.getTotalSize());
final FloatingPointFormula fp2 = fpmgr.makeNumber(pDouble, doublePrecType);
- return bmgr.and(fpmgr.assignment(fpFromBv, fp1), fpmgr.assignment(fpFromBv, fp2));
+ assertThat(fpmgr.getMantissaSizeWithSignBit(fp2) + fpmgr.getExponentSize(fp2))
+ .isEqualTo(doublePrecType.getTotalSize());
+ final BooleanFormula assignment1 = fpmgr.assignment(fpFromBv, fp1);
+ final BooleanFormula assignment2 = fpmgr.assignment(fpFromBv, fp2);
+ return bmgr.and(assignment1, assignment2);
});
}
diff --git a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java
index e96c7b39f1..85cd1c1574 100644
--- a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java
+++ b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java
@@ -242,18 +242,34 @@ protected final void requireBitvectorToInt() {
}
@SuppressWarnings("CheckReturnValue")
- protected final void requireFPToBitvector() {
+ protected final void requireNativeFPToBitvector() {
requireFloats();
try {
fpmgr.toIeeeBitvector(fpmgr.makeNumber(0, getSinglePrecisionFloatingPointType()));
} catch (UnsupportedOperationException e) {
assume()
- .withMessage("Solver %s does not yet support FP-to-BV conversion", solverToUse())
+ .withMessage(
+ "Solver %s does not support FP-to-BV conversion, use the fallback methods "
+ + "FloatingPointFormulaManager#toIeeeBitvector(FloatingPointFormula, "
+ + "String, Map) and/or FloatingPointFormulaManager#toIeeeBitvector"
+ + "(FloatingPointFormula, String).",
+ solverToUse())
.that(solverToUse())
.isNull();
}
}
+ @SuppressWarnings("CheckReturnValue")
+ protected final boolean solverSupportsNativeFPToBitvector() {
+ requireFloats();
+ try {
+ fpmgr.toIeeeBitvector(fpmgr.makeNumber(0, getSinglePrecisionFloatingPointType()));
+ return true;
+ } catch (UnsupportedOperationException e) {
+ return false;
+ }
+ }
+
/** Skip test if the solver does not support quantifiers. */
protected final void requireQuantifiers() {
assume()
diff --git a/src/org/sosy_lab/java_smt/test/SolverVisitorTest.java b/src/org/sosy_lab/java_smt/test/SolverVisitorTest.java
index 56b0200874..bd072cd759 100644
--- a/src/org/sosy_lab/java_smt/test/SolverVisitorTest.java
+++ b/src/org/sosy_lab/java_smt/test/SolverVisitorTest.java
@@ -477,13 +477,14 @@ public void floatConstantVisit() {
Integer.toBinaryString(Float.floatToRawIntBits(entry.getKey().floatValue())),
32,
'0'));
- checkFloatConstant(FormulaType.getFloatingPointType(5, 10), entry.getKey(), entry.getValue());
+ checkFloatConstant(
+ FormulaType.getFloatingPointTypeWithoutSignBit(5, 10), entry.getKey(), entry.getValue());
}
}
private void checkFloatConstant(FloatingPointType prec, double value, String bits) {
FloatingPointNumber fp =
- FloatingPointNumber.of(bits, prec.getExponentSize(), prec.getMantissaSize());
+ FloatingPointNumber.of(bits, prec.getExponentSize(), prec.getMantissaSizeWithSignBit());
ConstantsVisitor visitor = new ConstantsVisitor();
mgr.visit(fpmgr.makeNumber(value, prec), visitor);
@@ -580,7 +581,7 @@ public void fpToBvTest() {
.that(solverToUse())
.isNoneOf(Solvers.CVC4, Solvers.CVC5);
- var fpType = FormulaType.getFloatingPointType(5, 10);
+ var fpType = FormulaType.getFloatingPointTypeWithoutSignBit(5, 10);
var visitor =
new DefaultFormulaVisitor() {
@Override