diff --git a/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
index 62bb3afbe4..5820a8593e 100644
--- a/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
@@ -34,6 +34,9 @@
*/
public interface FloatingPointFormulaManager {
+ /** Creates a formula for the given floating point rounding mode. */
+ FloatingPointRoundingModeFormula makeRoundingMode(FloatingPointRoundingMode pRoundingMode);
+
/**
* Creates a floating point formula representing the given double value with the specified type.
*/
diff --git a/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java b/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java
index ead8fc04af..b9fb69fd73 100644
--- a/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java
+++ b/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java
@@ -11,8 +11,11 @@
import com.google.errorprone.annotations.Immutable;
/**
- * Formula representing a rounding mode for floating-point operations. This is currently unused by
- * the API but necessary for traversal of formulas with such terms.
+ * Formula representing a rounding mode for floating-point operations.
+ *
+ *
Rounding mode formulas are used by floating-point formulas to select the rounding mode for the
+ * operation. Use {@link FloatingPointFormulaManager#makeRoundingMode(FloatingPointRoundingMode)} to
+ * wrap a {@link org.sosy_lab.java_smt.api.FloatingPointRoundingMode} value inside a new formula.
*/
@Immutable
public interface FloatingPointRoundingModeFormula extends Formula {}
diff --git a/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java b/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
index a203fa1f2d..bb8a3929ba 100644
--- a/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
+++ b/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
@@ -252,21 +252,6 @@ public enum FunctionDeclarationKind {
/** Equal over floating points. */
FP_EQ,
- /** Rounding over floating points. */
- FP_ROUND_EVEN,
-
- /** Rounding over floating points. */
- FP_ROUND_AWAY,
-
- /** Rounding over floating points. */
- FP_ROUND_POSITIVE,
-
- /** Rounding over floating points. */
- FP_ROUND_NEGATIVE,
-
- /** Rounding over floating points. */
- FP_ROUND_ZERO,
-
/** Rounding over floating points. */
FP_ROUND_TO_INTEGRAL,
diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
index 47c847afe2..a653948bb3 100644
--- a/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
@@ -22,6 +22,7 @@
import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
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;
@@ -60,6 +61,12 @@ private TFormulaInfo getRoundingMode(FloatingPointRoundingMode pFloatingPointRou
return roundingModes.computeIfAbsent(pFloatingPointRoundingMode, this::getRoundingModeImpl);
}
+ @Override
+ public FloatingPointRoundingModeFormula makeRoundingMode(
+ FloatingPointRoundingMode pRoundingMode) {
+ return getFormulaCreator().encapsulateRoundingMode(getRoundingMode(pRoundingMode));
+ }
+
protected FloatingPointFormula wrap(TFormulaInfo pTerm) {
return getFormulaCreator().encapsulateFloatingPoint(pTerm);
}
diff --git a/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java b/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java
index 748fdd7b3b..cf383fde5a 100644
--- a/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java
@@ -160,6 +160,14 @@ protected FloatingPointFormula encapsulateFloatingPoint(TFormulaInfo pTerm) {
return new FloatingPointFormulaImpl<>(pTerm);
}
+ protected FloatingPointRoundingModeFormula encapsulateRoundingMode(TFormulaInfo pTerm) {
+ checkArgument(
+ getFormulaType(pTerm).isFloatingPointRoundingModeType(),
+ "Floatingpoint rounding mode formula has unexpected type: %s",
+ getFormulaType(pTerm));
+ return new FloatingPointRoundingModeFormulaImpl<>(pTerm);
+ }
+
protected ArrayFormula encapsulateArray(
TFormulaInfo pTerm, FormulaType pIndexType, FormulaType pElementType) {
checkArgument(
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..817fb05ff1 100644
--- a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
@@ -17,6 +17,7 @@
import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
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;
@@ -31,6 +32,15 @@ public class DebuggingFloatingPointFormulaManager implements FloatingPointFormul
debugging = pDebugging;
}
+ @Override
+ public FloatingPointRoundingModeFormula makeRoundingMode(
+ FloatingPointRoundingMode pRoundingMode) {
+ debugging.assertThreadLocal();
+ FloatingPointRoundingModeFormula result = delegate.makeRoundingMode(pRoundingMode);
+ debugging.addFormulaTerm(result);
+ return result;
+ }
+
@Override
public FloatingPointFormula makeNumber(double n, FloatingPointType type) {
debugging.assertThreadLocal();
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..f1669369c8 100644
--- a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
@@ -19,6 +19,7 @@
import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
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;
@@ -34,6 +35,13 @@ class StatisticsFloatingPointFormulaManager implements FloatingPointFormulaManag
stats = checkNotNull(pStats);
}
+ @Override
+ public FloatingPointRoundingModeFormula makeRoundingMode(
+ FloatingPointRoundingMode pRoundingMode) {
+ stats.fpOperations.getAndIncrement();
+ return delegate.makeRoundingMode(pRoundingMode);
+ }
+
@Override
public FloatingPointFormula makeNumber(double pN, FloatingPointType pType) {
stats.fpOperations.getAndIncrement();
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..f0e1049c75 100644
--- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
@@ -19,6 +19,7 @@
import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
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;
@@ -35,6 +36,14 @@ class SynchronizedFloatingPointFormulaManager implements FloatingPointFormulaMan
sync = checkNotNull(pSync);
}
+ @Override
+ public FloatingPointRoundingModeFormula makeRoundingMode(
+ FloatingPointRoundingMode pRoundingMode) {
+ synchronized (sync) {
+ return delegate.makeRoundingMode(pRoundingMode);
+ }
+ }
+
@Override
public FloatingPointFormula makeNumber(double pN, FloatingPointType pType) {
synchronized (sync) {
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..f9fa6e30e7 100644
--- a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
@@ -33,6 +33,8 @@
import org.sosy_lab.java_smt.api.BooleanFormula;
import org.sosy_lab.java_smt.api.FloatingPointFormula;
import org.sosy_lab.java_smt.api.FloatingPointNumber;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -131,6 +133,14 @@ assert getFormulaType(pTerm).isFloatingPointType()
return new BitwuzlaFloatingPointFormula(pTerm);
}
+ @Override
+ protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Term pTerm) {
+ assert getFormulaType(pTerm).isFloatingPointRoundingModeType()
+ : String.format(
+ "%s is no FP rounding mode, but %s (%s)", pTerm, pTerm.sort(), getFormulaType(pTerm));
+ return new BitwuzlaFloatingPointRoundingModeFormula(pTerm);
+ }
+
@Override
@SuppressWarnings("MethodTypeParameterName")
protected ArrayFormula encapsulateArray(
@@ -584,7 +594,19 @@ public Object convertValue(Term term) {
return term.to_bool();
}
if (sort.is_rm()) {
- return term.to_rm();
+ if (term.is_rm_value_rna()) {
+ return FloatingPointRoundingMode.NEAREST_TIES_AWAY;
+ } else if (term.is_rm_value_rne()) {
+ return FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN;
+ } else if (term.is_rm_value_rtn()) {
+ return FloatingPointRoundingMode.TOWARD_NEGATIVE;
+ } else if (term.is_rm_value_rtp()) {
+ return FloatingPointRoundingMode.TOWARD_POSITIVE;
+ } else if (term.is_rm_value_rtz()) {
+ return FloatingPointRoundingMode.TOWARD_ZERO;
+ } else {
+ throw new IllegalArgumentException(String.format("Unknown rounding mode: %s", term));
+ }
}
if (sort.is_bv()) {
return new BigInteger(term.to_bv(), 2);
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..875cce7bef 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
@@ -26,6 +26,7 @@
import edu.stanford.CVC4.Integer;
import edu.stanford.CVC4.Kind;
import edu.stanford.CVC4.Rational;
+import edu.stanford.CVC4.RoundingMode;
import edu.stanford.CVC4.Type;
import edu.stanford.CVC4.vectorExpr;
import edu.stanford.CVC4.vectorType;
@@ -41,6 +42,8 @@
import org.sosy_lab.java_smt.api.FloatingPointFormula;
import org.sosy_lab.java_smt.api.FloatingPointNumber;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -264,6 +267,15 @@ assert getFormulaType(pTerm).isFloatingPointType()
return new CVC4FloatingPointFormula(pTerm);
}
+ @Override
+ protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Expr pTerm) {
+ assert getFormulaType(pTerm).isFloatingPointRoundingModeType()
+ : String.format(
+ "%s is no FP rounding mode, but %s (%s)",
+ pTerm, pTerm.getType(), getFormulaType(pTerm));
+ return new CVC4FloatingPointRoundingModeFormula(pTerm);
+ }
+
@Override
@SuppressWarnings("MethodTypeParameterName")
protected ArrayFormula encapsulateArray(
@@ -323,8 +335,7 @@ public R visit(FormulaVisitor visitor, Formula formula, final Expr f) {
} else if (type.isFloatingPoint()) {
return visitor.visitConstant(formula, convertFloatingPoint(f));
} else if (type.isRoundingMode()) {
- // TODO is this correct?
- return visitor.visitConstant(formula, f.getConstRoundingMode());
+ return visitor.visitConstant(formula, convertRoundingMode(f));
} else if (type.isString()) {
return visitor.visitConstant(formula, f.getConstString());
} else if (type.isArray()) {
@@ -613,6 +624,9 @@ public Object convertValue(Expr expForType, Expr value) {
} else if (valueType.isFloatingPoint()) {
return convertFloatingPoint(value);
+ } else if (valueType.isRoundingMode()) {
+ return convertRoundingMode(value);
+
} else if (valueType.isString()) {
return unescapeUnicodeForSmtlib(value.getConstString().toString());
@@ -648,4 +662,21 @@ private FloatingPointNumber convertFloatingPoint(Expr fpExpr) {
expWidth,
mantWidth);
}
+
+ private FloatingPointRoundingMode convertRoundingMode(Expr pExpr) {
+ RoundingMode rm = pExpr.getConstRoundingMode();
+ if (rm.equals(RoundingMode.roundNearestTiesToAway)) {
+ return FloatingPointRoundingMode.NEAREST_TIES_AWAY;
+ } else if (rm.equals(RoundingMode.roundNearestTiesToEven)) {
+ return FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN;
+ } else if (rm.equals(RoundingMode.roundTowardNegative)) {
+ return FloatingPointRoundingMode.TOWARD_NEGATIVE;
+ } else if (rm.equals(RoundingMode.roundTowardPositive)) {
+ return FloatingPointRoundingMode.TOWARD_POSITIVE;
+ } else if (rm.equals(RoundingMode.roundTowardZero)) {
+ return FloatingPointRoundingMode.TOWARD_ZERO;
+ } else {
+ throw new IllegalArgumentException(String.format("Unknown rounding mode: %s", pExpr));
+ }
+ }
}
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..f326da1590 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
@@ -27,6 +27,7 @@
import io.github.cvc5.Kind;
import io.github.cvc5.Op;
import io.github.cvc5.Pair;
+import io.github.cvc5.RoundingMode;
import io.github.cvc5.Solver;
import io.github.cvc5.Sort;
import io.github.cvc5.Term;
@@ -44,6 +45,8 @@
import org.sosy_lab.java_smt.api.EnumerationFormula;
import org.sosy_lab.java_smt.api.FloatingPointFormula;
import org.sosy_lab.java_smt.api.FloatingPointNumber;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -315,6 +318,15 @@ assert getFormulaType(pTerm).isFloatingPointType()
return new CVC5FloatingPointFormula(pTerm);
}
+ @Override
+ protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Term pTerm) {
+ assert getFormulaType(pTerm).isFloatingPointRoundingModeType()
+ : String.format(
+ "%s is no FP rounding mode, but %s (%s)",
+ pTerm, pTerm.getSort(), getFormulaType(pTerm));
+ return new CVC5FloatingPointRoundingModeFormula(pTerm);
+ }
+
@Override
@SuppressWarnings("MethodTypeParameterName")
protected ArrayFormula encapsulateArray(
@@ -399,7 +411,7 @@ public R visit(FormulaVisitor visitor, Formula formula, final Term f) {
return visitor.visitConstant(formula, convertFloatingPoint(f));
} else if (f.isRoundingModeValue()) {
- return visitor.visitConstant(formula, f.getRoundingModeValue());
+ return visitor.visitConstant(formula, convertRoundingMode(f));
} else if (f.isConstArray()) {
Term constant = f.getConstArrayBase();
@@ -816,6 +828,9 @@ public Object convertValue(Term expForType, Term value) {
} else if (value.isFloatingPointValue()) {
return convertFloatingPoint(value);
+ } else if (value.isRoundingModeValue()) {
+ return convertRoundingMode(value);
+
} else if (value.isBooleanValue()) {
return value.getBooleanValue();
@@ -845,6 +860,23 @@ private FloatingPointNumber convertFloatingPoint(Term value) throws CVC5ApiExcep
return FloatingPointNumber.of(bits, expWidth, mantWidth);
}
+ private FloatingPointRoundingMode convertRoundingMode(Term pTerm) throws CVC5ApiException {
+ RoundingMode rm = pTerm.getRoundingModeValue();
+ if (rm.equals(RoundingMode.ROUND_NEAREST_TIES_TO_AWAY)) {
+ return FloatingPointRoundingMode.NEAREST_TIES_AWAY;
+ } else if (rm.equals(RoundingMode.ROUND_NEAREST_TIES_TO_EVEN)) {
+ return FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN;
+ } else if (rm.equals(RoundingMode.ROUND_TOWARD_NEGATIVE)) {
+ return FloatingPointRoundingMode.TOWARD_NEGATIVE;
+ } else if (rm.equals(RoundingMode.ROUND_TOWARD_POSITIVE)) {
+ return FloatingPointRoundingMode.TOWARD_POSITIVE;
+ } else if (rm.equals(RoundingMode.ROUND_TOWARD_ZERO)) {
+ return FloatingPointRoundingMode.TOWARD_ZERO;
+ } else {
+ throw new IllegalArgumentException(String.format("Unknown rounding mode: %s", pTerm));
+ }
+ }
+
private Term accessVariablesCache(String name, Sort sort) {
Term existingVar = variablesCache.get(name, sort.toString());
Preconditions.checkNotNull(
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..276cb236b8 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
@@ -71,7 +71,6 @@
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_OR;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_PLUS;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_TIMES;
-import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_UNKNOWN;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_arg_type;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_name;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_tag;
@@ -105,6 +104,10 @@
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_get_type;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_constant;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_false;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_minus_inf;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_nearest_even;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_plus_inf;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_zero;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_number;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_true;
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_uf;
@@ -127,6 +130,8 @@
import org.sosy_lab.java_smt.api.FloatingPointFormula;
import org.sosy_lab.java_smt.api.FloatingPointNumber;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -291,6 +296,12 @@ protected FloatingPointFormula encapsulateFloatingPoint(Long pTerm) {
return new Mathsat5FloatingPointFormula(pTerm);
}
+ @Override
+ protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Long pTerm) {
+ assert getFormulaType(pTerm).isFloatingPointRoundingModeType();
+ return new Mathsat5FloatingPointRoundingModeFormula(pTerm);
+ }
+
@Override
@SuppressWarnings("MethodTypeParameterName")
protected ArrayFormula encapsulateArray(
@@ -333,6 +344,19 @@ public R visit(FormulaVisitor visitor, Formula formula, final Long f) {
return visitor.visitConstant(formula, true);
} else if (msat_term_is_false(environment, f)) {
return visitor.visitConstant(formula, false);
+ } else if (msat_is_fp_roundingmode_type(environment, msat_term_get_type(f))) {
+ if (msat_term_is_fp_roundingmode_nearest_even(environment, f)) {
+ return visitor.visitConstant(formula, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN);
+ } else if (msat_term_is_fp_roundingmode_plus_inf(environment, f)) {
+ return visitor.visitConstant(formula, FloatingPointRoundingMode.TOWARD_POSITIVE);
+ } else if (msat_term_is_fp_roundingmode_minus_inf(environment, f)) {
+ return visitor.visitConstant(formula, FloatingPointRoundingMode.TOWARD_NEGATIVE);
+ } else if (msat_term_is_fp_roundingmode_zero(environment, f)) {
+ return visitor.visitConstant(formula, FloatingPointRoundingMode.TOWARD_ZERO);
+ } else {
+ throw new IllegalArgumentException(
+ "Unknown rounding mode " + msat_decl_get_name(msat_term_get_decl(f)));
+ }
} else if (msat_term_is_constant(environment, f)) {
return visitor.visitFreeVariable(formula, msat_term_repr(f));
} else if (msat_is_enum_type(environment, msat_term_get_type(f))) {
@@ -516,22 +540,6 @@ private FunctionDeclarationKind getDeclarationKind(long pF) {
return FunctionDeclarationKind.FP_IS_SUBNORMAL;
case MSAT_TAG_FP_ISNORMAL:
return FunctionDeclarationKind.FP_IS_NORMAL;
-
- case MSAT_TAG_UNKNOWN:
- switch (msat_decl_get_name(decl)) {
- case "`fprounding_even`":
- return FunctionDeclarationKind.FP_ROUND_EVEN;
- case "`fprounding_plus_inf`":
- return FunctionDeclarationKind.FP_ROUND_POSITIVE;
- case "`fprounding_minus_inf`":
- return FunctionDeclarationKind.FP_ROUND_NEGATIVE;
- case "`fprounding_zero`":
- return FunctionDeclarationKind.FP_ROUND_ZERO;
-
- default:
- return FunctionDeclarationKind.OTHER;
- }
-
case MSAT_TAG_FLOOR:
return FunctionDeclarationKind.FLOOR;
diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java
index f0862ddaf8..aa8556f983 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java
@@ -652,6 +652,14 @@ public static native long msat_simplify(
public static native boolean msat_term_is_bv_comp(long e, long t);
+ public static native boolean msat_term_is_fp_roundingmode_nearest_even(long e, long t);
+
+ public static native boolean msat_term_is_fp_roundingmode_zero(long e, long t);
+
+ public static native boolean msat_term_is_fp_roundingmode_plus_inf(long e, long t);
+
+ public static native boolean msat_term_is_fp_roundingmode_minus_inf(long e, long t);
+
public static native boolean msat_term_is_quantifier(long e, long t);
public static native boolean msat_term_is_forall(long e, long t);
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..f38c6837aa 100644
--- a/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
@@ -47,6 +47,7 @@
import org.sosy_lab.java_smt.api.FloatingPointNumber;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.FormulaType;
import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -366,6 +367,13 @@ protected FloatingPointFormula encapsulateFloatingPoint(Long pTerm) {
return storePhantomReference(new Z3FloatingPointFormula(getEnv(), pTerm), pTerm);
}
+ @Override
+ protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Long pTerm) {
+ assert getFormulaType(pTerm).isFloatingPointRoundingModeType();
+ cleanupReferences();
+ return storePhantomReference(new Z3FloatingPointRoundingModeFormula(getEnv(), pTerm), pTerm);
+ }
+
@Override
protected StringFormula encapsulateString(Long pTerm) {
assert getFormulaType(pTerm).isStringType()
@@ -791,16 +799,6 @@ private FunctionDeclarationKind getDeclarationKind(long f) {
return FunctionDeclarationKind.FP_GT;
case Z3_OP_FPA_EQ:
return FunctionDeclarationKind.FP_EQ;
- case Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN:
- return FunctionDeclarationKind.FP_ROUND_EVEN;
- case Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY:
- return FunctionDeclarationKind.FP_ROUND_AWAY;
- case Z3_OP_FPA_RM_TOWARD_POSITIVE:
- return FunctionDeclarationKind.FP_ROUND_POSITIVE;
- case Z3_OP_FPA_RM_TOWARD_NEGATIVE:
- return FunctionDeclarationKind.FP_ROUND_NEGATIVE;
- case Z3_OP_FPA_RM_TOWARD_ZERO:
- return FunctionDeclarationKind.FP_ROUND_ZERO;
case Z3_OP_FPA_ROUND_TO_INTEGRAL:
return FunctionDeclarationKind.FP_ROUND_TO_INTEGRAL;
case Z3_OP_FPA_TO_FP_UNSIGNED:
diff --git a/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java b/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
index 74390241cf..3f87193507 100644
--- a/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
+++ b/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
@@ -32,15 +32,21 @@
import org.sosy_lab.java_smt.api.FloatingPointNumber;
import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
+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.api.FunctionDeclaration;
+import org.sosy_lab.java_smt.api.FunctionDeclarationKind;
import org.sosy_lab.java_smt.api.InterpolatingProverEnvironment;
import org.sosy_lab.java_smt.api.Model;
import org.sosy_lab.java_smt.api.Model.ValueAssignment;
import org.sosy_lab.java_smt.api.NumeralFormula;
import org.sosy_lab.java_smt.api.ProverEnvironment;
+import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier;
import org.sosy_lab.java_smt.api.SolverContext.ProverOptions;
import org.sosy_lab.java_smt.api.SolverException;
+import org.sosy_lab.java_smt.api.visitors.FormulaVisitor;
public class FloatingPointFormulaManagerTest
extends SolverBasedTest0.ParameterizedSolverBasedTest0 {
@@ -87,6 +93,67 @@ public void floatingPointType() {
.isEqualTo(type.getMantissaSize());
}
+ @Test
+ public void roundingModeVisitor() {
+ FloatingPointFormula variable =
+ fpmgr.makeVariable("a", FormulaType.getSinglePrecisionFloatingPointType());
+ FloatingPointFormula original =
+ fpmgr.sqrt(variable, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN);
+
+ for (FloatingPointRoundingMode rm : FloatingPointRoundingMode.values()) {
+ if (solver == Solvers.MATHSAT5 && rm == FloatingPointRoundingMode.NEAREST_TIES_AWAY) {
+ // SKIP MathSAT does not support rounding mode "nearest-ties-away"
+ continue;
+ }
+ // Build a term with a different rounding mode, then replace it in the visitor
+ FloatingPointFormula substituted =
+ (FloatingPointFormula)
+ mgr.visit(
+ fpmgr.sqrt(variable, rm),
+ new FormulaVisitor() {
+ @Override
+ public Formula visitFreeVariable(Formula f, String name) {
+ return f;
+ }
+
+ @Override
+ public Formula visitConstant(Formula f, Object value) {
+ assertThat(f).isInstanceOf(FloatingPointRoundingModeFormula.class);
+ assertThat(value).isInstanceOf(FloatingPointRoundingMode.class);
+ assertThat(value).isEqualTo(rm);
+
+ // Return the default rounding mode
+ return fpmgr.makeRoundingMode(FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN);
+ }
+
+ @Override
+ public Formula visitFunction(
+ Formula f, List args, FunctionDeclaration> functionDeclaration) {
+ assertThat(functionDeclaration.getKind())
+ .isEqualTo(FunctionDeclarationKind.FP_SQRT);
+ assertThat(args).hasSize(2);
+ return mgr.makeApplication(
+ functionDeclaration,
+ mgr.visit(args.get(0), this),
+ mgr.visit(args.get(1), this));
+ }
+
+ @Override
+ public Formula visitQuantifier(
+ BooleanFormula f,
+ Quantifier quantifier,
+ List boundVariables,
+ BooleanFormula body) {
+ throw new IllegalArgumentException(
+ String.format("Unexpected quantifier %s", quantifier));
+ }
+ });
+
+ // Check that after the substitution the rounding mode is the default again
+ assertThat(original).isEqualTo(substituted);
+ }
+ }
+
@Test
public void negative() throws SolverException, InterruptedException {
for (double d : new double[] {-1, -2, -0.0, Double.NEGATIVE_INFINITY}) {