summaryrefslogtreecommitdiff
path: root/src/theory/fp/fp_word_blaster.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/fp/fp_word_blaster.cpp')
-rw-r--r--src/theory/fp/fp_word_blaster.cpp1308
1 files changed, 1308 insertions, 0 deletions
diff --git a/src/theory/fp/fp_word_blaster.cpp b/src/theory/fp/fp_word_blaster.cpp
new file mode 100644
index 000000000..70d77abed
--- /dev/null
+++ b/src/theory/fp/fp_word_blaster.cpp
@@ -0,0 +1,1308 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Martin Brain, Mathias Preiner, Aina Niemetz
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Conversion of floating-point operations to bit-vectors using symfpu.
+ */
+
+#include "theory/fp/fp_word_blaster.h"
+
+#include <vector>
+
+#include "base/check.h"
+#include "expr/node_builder.h"
+#include "symfpu/core/add.h"
+#include "symfpu/core/classify.h"
+#include "symfpu/core/compare.h"
+#include "symfpu/core/convert.h"
+#include "symfpu/core/divide.h"
+#include "symfpu/core/fma.h"
+#include "symfpu/core/ite.h"
+#include "symfpu/core/multiply.h"
+#include "symfpu/core/packing.h"
+#include "symfpu/core/remainder.h"
+#include "symfpu/core/sign.h"
+#include "symfpu/core/sqrt.h"
+#include "symfpu/utils/numberOfRoundingModes.h"
+#include "symfpu/utils/properties.h"
+#include "theory/theory.h" // theory.h Only needed for the leaf test
+#include "util/floatingpoint.h"
+#include "util/floatingpoint_literal_symfpu.h"
+
+namespace symfpu {
+using namespace ::cvc5::theory::fp::symfpuSymbolic;
+
+#define CVC5_SYM_ITE_DFN(T) \
+ template <> \
+ struct ite<symbolicProposition, T> \
+ { \
+ static const T iteOp(const symbolicProposition& _cond, \
+ const T& _l, \
+ const T& _r) \
+ { \
+ ::cvc5::NodeManager* nm = ::cvc5::NodeManager::currentNM(); \
+ \
+ ::cvc5::Node cond = _cond; \
+ ::cvc5::Node l = _l; \
+ ::cvc5::Node r = _r; \
+ \
+ /* Handle some common symfpu idioms */ \
+ if (cond.isConst()) \
+ { \
+ return (cond == nm->mkConst(::cvc5::BitVector(1U, 1U))) ? l : r; \
+ } \
+ else \
+ { \
+ if (l.getKind() == ::cvc5::kind::BITVECTOR_ITE) \
+ { \
+ if (l[1] == r) \
+ { \
+ return nm->mkNode( \
+ ::cvc5::kind::BITVECTOR_ITE, \
+ nm->mkNode(::cvc5::kind::BITVECTOR_AND, \
+ cond, \
+ nm->mkNode(::cvc5::kind::BITVECTOR_NOT, l[0])), \
+ l[2], \
+ r); \
+ } \
+ else if (l[2] == r) \
+ { \
+ return nm->mkNode( \
+ ::cvc5::kind::BITVECTOR_ITE, \
+ nm->mkNode(::cvc5::kind::BITVECTOR_AND, cond, l[0]), \
+ l[1], \
+ r); \
+ } \
+ } \
+ else if (r.getKind() == ::cvc5::kind::BITVECTOR_ITE) \
+ { \
+ if (r[1] == l) \
+ { \
+ return nm->mkNode( \
+ ::cvc5::kind::BITVECTOR_ITE, \
+ nm->mkNode(::cvc5::kind::BITVECTOR_AND, \
+ nm->mkNode(::cvc5::kind::BITVECTOR_NOT, cond), \
+ nm->mkNode(::cvc5::kind::BITVECTOR_NOT, r[0])), \
+ r[2], \
+ l); \
+ } \
+ else if (r[2] == l) \
+ { \
+ return nm->mkNode( \
+ ::cvc5::kind::BITVECTOR_ITE, \
+ nm->mkNode(::cvc5::kind::BITVECTOR_AND, \
+ nm->mkNode(::cvc5::kind::BITVECTOR_NOT, cond), \
+ r[0]), \
+ r[1], \
+ l); \
+ } \
+ } \
+ } \
+ return T(nm->mkNode(::cvc5::kind::BITVECTOR_ITE, cond, l, r)); \
+ } \
+ }
+
+// Can (unsurprisingly) only ITE things which contain Nodes
+CVC5_SYM_ITE_DFN(traits::rm);
+CVC5_SYM_ITE_DFN(traits::prop);
+CVC5_SYM_ITE_DFN(traits::sbv);
+CVC5_SYM_ITE_DFN(traits::ubv);
+
+#undef CVC5_SYM_ITE_DFN
+
+template <>
+traits::ubv orderEncode<traits, traits::ubv>(const traits::ubv& b)
+{
+ return orderEncodeBitwise<traits, traits::ubv>(b);
+}
+
+template <>
+stickyRightShiftResult<traits> stickyRightShift(const traits::ubv& input,
+ const traits::ubv& shiftAmount)
+{
+ return stickyRightShiftBitwise<traits>(input, shiftAmount);
+}
+
+template <>
+void probabilityAnnotation<traits, traits::prop>(const traits::prop& p,
+ const probability& pr)
+{
+ // For now, do nothing...
+ return;
+}
+}; // namespace symfpu
+
+namespace cvc5 {
+namespace theory {
+namespace fp {
+namespace symfpuSymbolic {
+
+symbolicRoundingMode traits::RNE(void) { return symbolicRoundingMode(0x01); };
+symbolicRoundingMode traits::RNA(void) { return symbolicRoundingMode(0x02); };
+symbolicRoundingMode traits::RTP(void) { return symbolicRoundingMode(0x04); };
+symbolicRoundingMode traits::RTN(void) { return symbolicRoundingMode(0x08); };
+symbolicRoundingMode traits::RTZ(void) { return symbolicRoundingMode(0x10); };
+
+void traits::precondition(const bool b)
+{
+ Assert(b);
+ return;
+}
+void traits::postcondition(const bool b)
+{
+ Assert(b);
+ return;
+}
+void traits::invariant(const bool b)
+{
+ Assert(b);
+ return;
+}
+
+void traits::precondition(const prop& p) { return; }
+void traits::postcondition(const prop& p) { return; }
+void traits::invariant(const prop& p) { return; }
+// This allows us to use the symfpu literal / symbolic assertions in the
+// symbolic back-end
+typedef traits t;
+
+bool symbolicProposition::checkNodeType(const TNode node)
+{
+ TypeNode tn = node.getType(false);
+ return tn.isBitVector() && tn.getBitVectorSize() == 1;
+}
+
+symbolicProposition::symbolicProposition(const Node n) : nodeWrapper(n)
+{
+ Assert(checkNodeType(*this));
+} // Only used within this header so could be friend'd
+symbolicProposition::symbolicProposition(bool v)
+ : nodeWrapper(
+ NodeManager::currentNM()->mkConst(BitVector(1U, (v ? 1U : 0U))))
+{
+ Assert(checkNodeType(*this));
+}
+
+symbolicProposition::symbolicProposition(const symbolicProposition& old)
+ : nodeWrapper(old)
+{
+ Assert(checkNodeType(*this));
+}
+
+symbolicProposition symbolicProposition::operator!(void) const
+{
+ return symbolicProposition(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, *this));
+}
+
+symbolicProposition symbolicProposition::operator&&(
+ const symbolicProposition& op) const
+{
+ return symbolicProposition(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_AND, *this, op));
+}
+
+symbolicProposition symbolicProposition::operator||(
+ const symbolicProposition& op) const
+{
+ return symbolicProposition(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_OR, *this, op));
+}
+
+symbolicProposition symbolicProposition::operator==(
+ const symbolicProposition& op) const
+{
+ return symbolicProposition(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
+}
+
+symbolicProposition symbolicProposition::operator^(
+ const symbolicProposition& op) const
+{
+ return symbolicProposition(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_XOR, *this, op));
+}
+
+bool symbolicRoundingMode::checkNodeType(const TNode n)
+{
+ return n.getType(false).isBitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES);
+}
+
+symbolicRoundingMode::symbolicRoundingMode(const Node n) : nodeWrapper(n)
+{
+ Assert(checkNodeType(*this));
+}
+
+symbolicRoundingMode::symbolicRoundingMode(const unsigned v)
+ : nodeWrapper(NodeManager::currentNM()->mkConst(
+ BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, v)))
+{
+ Assert((v & (v - 1)) == 0 && v != 0); // Exactly one bit set
+ Assert(checkNodeType(*this));
+}
+
+symbolicRoundingMode::symbolicRoundingMode(const symbolicRoundingMode& old)
+ : nodeWrapper(old)
+{
+ Assert(checkNodeType(*this));
+}
+
+symbolicProposition symbolicRoundingMode::valid(void) const
+{
+ NodeManager* nm = NodeManager::currentNM();
+ Node zero(nm->mkConst(BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, 0u)));
+
+ // Is there a better encoding of this?
+ return symbolicProposition(nm->mkNode(
+ kind::BITVECTOR_AND,
+ nm->mkNode(
+ kind::BITVECTOR_COMP,
+ nm->mkNode(kind::BITVECTOR_AND,
+ *this,
+ nm->mkNode(kind::BITVECTOR_SUB,
+ *this,
+ nm->mkConst(BitVector(
+ SYMFPU_NUMBER_OF_ROUNDING_MODES, 1u)))),
+ zero),
+ nm->mkNode(kind::BITVECTOR_NOT,
+ nm->mkNode(kind::BITVECTOR_COMP, *this, zero))));
+}
+
+symbolicProposition symbolicRoundingMode::operator==(
+ const symbolicRoundingMode& op) const
+{
+ return symbolicProposition(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
+}
+
+template <bool isSigned>
+Node symbolicBitVector<isSigned>::boolNodeToBV(Node node) const
+{
+ Assert(node.getType().isBoolean());
+ NodeManager* nm = NodeManager::currentNM();
+ return nm->mkNode(kind::ITE,
+ node,
+ nm->mkConst(BitVector(1U, 1U)),
+ nm->mkConst(BitVector(1U, 0U)));
+}
+
+template <bool isSigned>
+Node symbolicBitVector<isSigned>::BVToBoolNode(Node node) const
+{
+ Assert(node.getType().isBitVector());
+ Assert(node.getType().getBitVectorSize() == 1);
+ NodeManager* nm = NodeManager::currentNM();
+ return nm->mkNode(kind::EQUAL, node, nm->mkConst(BitVector(1U, 1U)));
+}
+
+template <bool isSigned>
+Node symbolicBitVector<isSigned>::fromProposition(Node node) const
+{
+ return node;
+}
+template <bool isSigned>
+Node symbolicBitVector<isSigned>::toProposition(Node node) const
+{
+ return boolNodeToBV(node);
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned>::symbolicBitVector(const Node n) : nodeWrapper(n)
+{
+ Assert(checkNodeType(*this));
+}
+
+template <bool isSigned>
+bool symbolicBitVector<isSigned>::checkNodeType(const TNode n)
+{
+ return n.getType(false).isBitVector();
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned>::symbolicBitVector(const bwt w, const unsigned v)
+ : nodeWrapper(NodeManager::currentNM()->mkConst(BitVector(w, v)))
+{
+ Assert(checkNodeType(*this));
+}
+template <bool isSigned>
+symbolicBitVector<isSigned>::symbolicBitVector(const symbolicProposition& p)
+ : nodeWrapper(fromProposition(p))
+{
+}
+template <bool isSigned>
+symbolicBitVector<isSigned>::symbolicBitVector(
+ const symbolicBitVector<isSigned>& old)
+ : nodeWrapper(old)
+{
+ Assert(checkNodeType(*this));
+}
+template <bool isSigned>
+symbolicBitVector<isSigned>::symbolicBitVector(const BitVector& old)
+ : nodeWrapper(NodeManager::currentNM()->mkConst(old))
+{
+ Assert(checkNodeType(*this));
+}
+
+template <bool isSigned>
+bwt symbolicBitVector<isSigned>::getWidth(void) const
+{
+ return this->getType(false).getBitVectorSize();
+}
+
+/*** Constant creation and test ***/
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::one(const bwt& w)
+{
+ return symbolicBitVector<isSigned>(w, 1);
+}
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::zero(const bwt& w)
+{
+ return symbolicBitVector<isSigned>(w, 0);
+}
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::allOnes(const bwt& w)
+{
+ return symbolicBitVector<isSigned>(~zero(w));
+}
+
+template <bool isSigned>
+symbolicProposition symbolicBitVector<isSigned>::isAllOnes() const
+{
+ return (*this == symbolicBitVector<isSigned>::allOnes(this->getWidth()));
+}
+template <bool isSigned>
+symbolicProposition symbolicBitVector<isSigned>::isAllZeros() const
+{
+ return (*this == symbolicBitVector<isSigned>::zero(this->getWidth()));
+}
+
+template <>
+symbolicBitVector<true> symbolicBitVector<true>::maxValue(const bwt& w)
+{
+ symbolicBitVector<true> leadingZero(symbolicBitVector<true>::zero(1));
+ symbolicBitVector<true> base(symbolicBitVector<true>::allOnes(w - 1));
+
+ return symbolicBitVector<true>(::cvc5::NodeManager::currentNM()->mkNode(
+ ::cvc5::kind::BITVECTOR_CONCAT, leadingZero, base));
+}
+
+template <>
+symbolicBitVector<false> symbolicBitVector<false>::maxValue(const bwt& w)
+{
+ return symbolicBitVector<false>::allOnes(w);
+}
+
+template <>
+symbolicBitVector<true> symbolicBitVector<true>::minValue(const bwt& w)
+{
+ symbolicBitVector<true> leadingOne(symbolicBitVector<true>::one(1));
+ symbolicBitVector<true> base(symbolicBitVector<true>::zero(w - 1));
+
+ return symbolicBitVector<true>(::cvc5::NodeManager::currentNM()->mkNode(
+ ::cvc5::kind::BITVECTOR_CONCAT, leadingOne, base));
+}
+
+template <>
+symbolicBitVector<false> symbolicBitVector<false>::minValue(const bwt& w)
+{
+ return symbolicBitVector<false>::zero(w);
+}
+
+/*** Operators ***/
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator<<(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_SHL, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator>>(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
+ (isSigned) ? kind::BITVECTOR_ASHR : kind::BITVECTOR_LSHR, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator|(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_OR, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator&(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_AND, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator+(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_ADD, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator-(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_SUB, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator*(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_MULT, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator/(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
+ (isSigned) ? kind::BITVECTOR_SDIV : kind::BITVECTOR_UDIV, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator%(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
+ (isSigned) ? kind::BITVECTOR_SREM : kind::BITVECTOR_UREM, *this, op));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator-(void) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_NEG, *this));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::operator~(void) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, *this));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::increment() const
+{
+ return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
+ kind::BITVECTOR_ADD, *this, one(this->getWidth())));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::decrement() const
+{
+ return symbolicBitVector<isSigned>(NodeManager::currentNM()->mkNode(
+ kind::BITVECTOR_SUB, *this, one(this->getWidth())));
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::signExtendRightShift(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_ASHR, *this, op));
+}
+
+/*** Modular operations ***/
+// No overflow checking so these are the same as other operations
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularLeftShift(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return *this << op;
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularRightShift(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return *this >> op;
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularIncrement()
+ const
+{
+ return this->increment();
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularDecrement()
+ const
+{
+ return this->decrement();
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularAdd(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return *this + op;
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::modularNegate() const
+{
+ return -(*this);
+}
+
+/*** Comparisons ***/
+
+template <bool isSigned>
+symbolicProposition symbolicBitVector<isSigned>::operator==(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicProposition(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_COMP, *this, op));
+}
+
+template <bool isSigned>
+symbolicProposition symbolicBitVector<isSigned>::operator<=(
+ const symbolicBitVector<isSigned>& op) const
+{
+ // Consider adding kind::BITVECTOR_SLEBV and BITVECTOR_ULEBV
+ return (*this < op) || (*this == op);
+}
+
+template <bool isSigned>
+symbolicProposition symbolicBitVector<isSigned>::operator>=(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return (*this > op) || (*this == op);
+}
+
+template <bool isSigned>
+symbolicProposition symbolicBitVector<isSigned>::operator<(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicProposition(NodeManager::currentNM()->mkNode(
+ (isSigned) ? kind::BITVECTOR_SLTBV : kind::BITVECTOR_ULTBV, *this, op));
+}
+
+template <bool isSigned>
+symbolicProposition symbolicBitVector<isSigned>::operator>(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicProposition(NodeManager::currentNM()->mkNode(
+ (isSigned) ? kind::BITVECTOR_SLTBV : kind::BITVECTOR_ULTBV, op, *this));
+}
+
+/*** Type conversion ***/
+// cvc5 nodes make no distinction between signed and unsigned, thus ...
+template <bool isSigned>
+symbolicBitVector<true> symbolicBitVector<isSigned>::toSigned(void) const
+{
+ return symbolicBitVector<true>(*this);
+}
+template <bool isSigned>
+symbolicBitVector<false> symbolicBitVector<isSigned>::toUnsigned(void) const
+{
+ return symbolicBitVector<false>(*this);
+}
+
+/*** Bit hacks ***/
+template <>
+symbolicBitVector<true> symbolicBitVector<true>::extend(bwt extension) const
+{
+ NodeBuilder construct(kind::BITVECTOR_SIGN_EXTEND);
+ construct << NodeManager::currentNM()->mkConst<BitVectorSignExtend>(
+ BitVectorSignExtend(extension))
+ << *this;
+
+ return symbolicBitVector<true>(construct);
+}
+
+template <>
+symbolicBitVector<false> symbolicBitVector<false>::extend(bwt extension) const
+{
+ NodeBuilder construct(kind::BITVECTOR_ZERO_EXTEND);
+ construct << NodeManager::currentNM()->mkConst<BitVectorZeroExtend>(
+ BitVectorZeroExtend(extension))
+ << *this;
+
+ return symbolicBitVector<false>(construct);
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::contract(
+ bwt reduction) const
+{
+ Assert(this->getWidth() > reduction);
+
+ NodeBuilder construct(kind::BITVECTOR_EXTRACT);
+ construct << NodeManager::currentNM()->mkConst<BitVectorExtract>(
+ BitVectorExtract((this->getWidth() - 1) - reduction, 0))
+ << *this;
+
+ return symbolicBitVector<isSigned>(construct);
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::resize(
+ bwt newSize) const
+{
+ bwt width = this->getWidth();
+
+ if (newSize > width)
+ {
+ return this->extend(newSize - width);
+ }
+ else if (newSize < width)
+ {
+ return this->contract(width - newSize);
+ }
+ else
+ {
+ return *this;
+ }
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::matchWidth(
+ const symbolicBitVector<isSigned>& op) const
+{
+ Assert(this->getWidth() <= op.getWidth());
+ return this->extend(op.getWidth() - this->getWidth());
+}
+
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::append(
+ const symbolicBitVector<isSigned>& op) const
+{
+ return symbolicBitVector<isSigned>(
+ NodeManager::currentNM()->mkNode(kind::BITVECTOR_CONCAT, *this, op));
+}
+
+// Inclusive of end points, thus if the same, extracts just one bit
+template <bool isSigned>
+symbolicBitVector<isSigned> symbolicBitVector<isSigned>::extract(
+ bwt upper, bwt lower) const
+{
+ Assert(upper >= lower);
+
+ NodeBuilder construct(kind::BITVECTOR_EXTRACT);
+ construct << NodeManager::currentNM()->mkConst<BitVectorExtract>(
+ BitVectorExtract(upper, lower))
+ << *this;
+
+ return symbolicBitVector<isSigned>(construct);
+}
+
+floatingPointTypeInfo::floatingPointTypeInfo(const TypeNode type)
+ : FloatingPointSize(type.getConst<FloatingPointSize>())
+{
+ Assert(type.isFloatingPoint());
+}
+floatingPointTypeInfo::floatingPointTypeInfo(unsigned exp, unsigned sig)
+ : FloatingPointSize(exp, sig)
+{
+}
+floatingPointTypeInfo::floatingPointTypeInfo(const floatingPointTypeInfo& old)
+ : FloatingPointSize(old)
+{
+}
+
+TypeNode floatingPointTypeInfo::getTypeNode(void) const
+{
+ return NodeManager::currentNM()->mkFloatingPointType(*this);
+}
+} // namespace symfpuSymbolic
+
+FpWordBlaster::FpWordBlaster(context::UserContext* user)
+ : d_additionalAssertions(user),
+ d_fpMap(user),
+ d_rmMap(user),
+ d_boolMap(user),
+ d_ubvMap(user),
+ d_sbvMap(user)
+{
+}
+
+FpWordBlaster::~FpWordBlaster() {}
+
+Node FpWordBlaster::ufToNode(const fpt& format, const uf& u) const
+{
+ NodeManager* nm = NodeManager::currentNM();
+
+ FloatingPointSize fps(format.getTypeNode().getConst<FloatingPointSize>());
+
+ // This is not entirely obvious but it builds a float from components
+ // Particularly, if the components can be constant folded, it should
+ // build a Node containing a constant FloatingPoint number
+
+ ubv packed(symfpu::pack<traits>(format, u));
+ Node value =
+ nm->mkNode(nm->mkConst(FloatingPointToFPIEEEBitVector(fps)), packed);
+ return value;
+}
+
+Node FpWordBlaster::rmToNode(const rm& r) const
+{
+ NodeManager* nm = NodeManager::currentNM();
+
+ Node transVar = r;
+
+ Node RNE = traits::RNE();
+ Node RNA = traits::RNA();
+ Node RTP = traits::RTP();
+ Node RTN = traits::RTN();
+ Node RTZ = traits::RTZ();
+
+ Node value = nm->mkNode(
+ kind::ITE,
+ nm->mkNode(kind::EQUAL, transVar, RNE),
+ nm->mkConst(RoundingMode::ROUND_NEAREST_TIES_TO_EVEN),
+ nm->mkNode(
+ kind::ITE,
+ nm->mkNode(kind::EQUAL, transVar, RNA),
+ nm->mkConst(RoundingMode::ROUND_NEAREST_TIES_TO_AWAY),
+ nm->mkNode(
+ kind::ITE,
+ nm->mkNode(kind::EQUAL, transVar, RTP),
+ nm->mkConst(RoundingMode::ROUND_TOWARD_POSITIVE),
+ nm->mkNode(kind::ITE,
+ nm->mkNode(kind::EQUAL, transVar, RTN),
+ nm->mkConst(RoundingMode::ROUND_TOWARD_NEGATIVE),
+ nm->mkConst(RoundingMode::ROUND_TOWARD_ZERO)))));
+ return value;
+}
+
+Node FpWordBlaster::propToNode(const prop& p) const
+{
+ NodeManager* nm = NodeManager::currentNM();
+ Node value =
+ nm->mkNode(kind::EQUAL, p, nm->mkConst(::cvc5::BitVector(1U, 1U)));
+ return value;
+}
+Node FpWordBlaster::ubvToNode(const ubv& u) const { return u; }
+Node FpWordBlaster::sbvToNode(const sbv& s) const { return s; }
+// Creates the components constraint
+FpWordBlaster::uf FpWordBlaster::buildComponents(TNode current)
+{
+ Assert(Theory::isLeafOf(current, THEORY_FP)
+ || current.getKind() == kind::FLOATINGPOINT_TO_FP_REAL);
+
+ NodeManager* nm = NodeManager::currentNM();
+ uf tmp(nm->mkNode(kind::FLOATINGPOINT_COMPONENT_NAN, current),
+ nm->mkNode(kind::FLOATINGPOINT_COMPONENT_INF, current),
+ nm->mkNode(kind::FLOATINGPOINT_COMPONENT_ZERO, current),
+ nm->mkNode(kind::FLOATINGPOINT_COMPONENT_SIGN, current),
+ nm->mkNode(kind::FLOATINGPOINT_COMPONENT_EXPONENT, current),
+ nm->mkNode(kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND, current));
+
+ d_additionalAssertions.push_back(tmp.valid(fpt(current.getType())));
+
+ return tmp;
+}
+
+Node FpWordBlaster::wordBlast(TNode node)
+{
+ std::vector<TNode> visit;
+ std::unordered_map<TNode, bool> visited;
+ NodeManager* nm = NodeManager::currentNM();
+
+ visit.push_back(node);
+
+ while (!visit.empty())
+ {
+ TNode cur = visit.back();
+ visit.pop_back();
+ TypeNode t(cur.getType());
+
+ /* Already word-blasted, skip. */
+ if ((t.isBoolean() && d_boolMap.find(cur) != d_boolMap.end())
+ || (t.isRoundingMode() && d_rmMap.find(cur) != d_rmMap.end())
+ || (t.isBitVector()
+ && (d_sbvMap.find(cur) != d_sbvMap.end()
+ || d_ubvMap.find(cur) != d_ubvMap.end()))
+ || (t.isFloatingPoint() && d_fpMap.find(cur) != d_fpMap.end()))
+ {
+ continue;
+ }
+
+ Kind kind = cur.getKind();
+
+ if (t.isReal() && kind != kind::FLOATINGPOINT_TO_REAL_TOTAL)
+ {
+ // The only nodes with Real sort in Theory FP are of kind
+ // kind::FLOATINGPOINT_TO_REAL_TOTAL (kind::FLOATINGPOINT_TO_REAL is
+ // rewritten to kind::FLOATINGPOINT_TO_REAL_TOTAL).
+ // We don't need to do anything explicitly with them since they will be
+ // treated as an uninterpreted function by the Real theory and we don't
+ // need to bit-blast the float expression unless we need to say something
+ // about its value.
+ //
+ // We still have to word blast it's arguments, though.
+ //
+ // All other Real expressions can be skipped.
+ continue;
+ }
+
+ auto it = visited.find(cur);
+ if (it == visited.end())
+ {
+ visited.emplace(cur, 0);
+ visit.push_back(cur);
+ visit.insert(visit.end(), cur.begin(), cur.end());
+ }
+ else if (it->second == false)
+ {
+ it->second = true;
+
+ if (t.isRoundingMode())
+ {
+ /* ---- RoundingMode constants and variables -------------- */
+ Assert(Theory::isLeafOf(cur, THEORY_FP));
+ if (kind == kind::CONST_ROUNDINGMODE)
+ {
+ switch (cur.getConst<RoundingMode>())
+ {
+ case RoundingMode::ROUND_NEAREST_TIES_TO_EVEN:
+ d_rmMap.insert(cur, traits::RNE());
+ break;
+ case RoundingMode::ROUND_NEAREST_TIES_TO_AWAY:
+ d_rmMap.insert(cur, traits::RNA());
+ break;
+ case RoundingMode::ROUND_TOWARD_POSITIVE:
+ d_rmMap.insert(cur, traits::RTP());
+ break;
+ case RoundingMode::ROUND_TOWARD_NEGATIVE:
+ d_rmMap.insert(cur, traits::RTN());
+ break;
+ case RoundingMode::ROUND_TOWARD_ZERO:
+ d_rmMap.insert(cur, traits::RTZ());
+ break;
+ default: Unreachable() << "Unknown rounding mode"; break;
+ }
+ }
+ else
+ {
+ rm tmp(nm->mkNode(kind::ROUNDINGMODE_BITBLAST, cur));
+ d_rmMap.insert(cur, tmp);
+ d_additionalAssertions.push_back(tmp.valid());
+ }
+ }
+ else if (t.isFloatingPoint())
+ {
+ /* ---- FloatingPoint constants and variables ------------- */
+ if (Theory::isLeafOf(cur, THEORY_FP))
+ {
+ if (kind == kind::CONST_FLOATINGPOINT)
+ {
+ d_fpMap.insert(
+ cur,
+ symfpu::unpackedFloat<traits>(
+ cur.getConst<FloatingPoint>().getLiteral()->getSymUF()));
+ }
+ else
+ {
+ d_fpMap.insert(cur, buildComponents(cur));
+ }
+ }
+ else
+ {
+ /* ---- FloatingPoint operators --------------------------- */
+ Assert(kind != kind::CONST_FLOATINGPOINT);
+ Assert(kind != kind::VARIABLE);
+ Assert(kind != kind::BOUND_VARIABLE && kind != kind::SKOLEM);
+
+ switch (kind)
+ {
+ /* ---- Arithmetic operators ---- */
+ case kind::FLOATINGPOINT_ABS:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_fpMap.insert(cur,
+ symfpu::absolute<traits>(
+ fpt(t), (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_NEG:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_fpMap.insert(cur,
+ symfpu::negate<traits>(
+ fpt(t), (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_SQRT:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ d_fpMap.insert(
+ cur,
+ symfpu::sqrt<traits>(fpt(t),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second));
+ break;
+
+ case kind::FLOATINGPOINT_RTI:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ d_fpMap.insert(cur,
+ symfpu::roundToIntegral<traits>(
+ fpt(t),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second));
+ break;
+
+ case kind::FLOATINGPOINT_REM:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ d_fpMap.insert(
+ cur,
+ symfpu::remainder<traits>(fpt(t),
+ (*d_fpMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second));
+ break;
+
+ case kind::FLOATINGPOINT_MAX_TOTAL:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ Assert(cur[2].getType().isBitVector());
+ d_fpMap.insert(cur,
+ symfpu::max<traits>(fpt(t),
+ (*d_fpMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ prop(cur[2])));
+ break;
+
+ case kind::FLOATINGPOINT_MIN_TOTAL:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ Assert(cur[2].getType().isBitVector());
+ d_fpMap.insert(cur,
+ symfpu::min<traits>(fpt(t),
+ (*d_fpMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ prop(cur[2])));
+ break;
+
+ case kind::FLOATINGPOINT_ADD:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
+ d_fpMap.insert(cur,
+ symfpu::add<traits>(fpt(t),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ (*d_fpMap.find(cur[2])).second,
+ prop(true)));
+ break;
+
+ case kind::FLOATINGPOINT_MULT:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
+ d_fpMap.insert(
+ cur,
+ symfpu::multiply<traits>(fpt(t),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ (*d_fpMap.find(cur[2])).second));
+ break;
+
+ case kind::FLOATINGPOINT_DIV:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
+ d_fpMap.insert(
+ cur,
+ symfpu::divide<traits>(fpt(t),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ (*d_fpMap.find(cur[2])).second));
+ break;
+
+ case kind::FLOATINGPOINT_FMA:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[2]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[3]) != d_fpMap.end());
+
+ d_fpMap.insert(
+ cur,
+ symfpu::fma<traits>(fpt(t),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ (*d_fpMap.find(cur[2])).second,
+ (*d_fpMap.find(cur[3])).second));
+ break;
+
+ /* ---- Conversions ---- */
+ case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ d_fpMap.insert(cur,
+ symfpu::convertFloatToFloat<traits>(
+ fpt(cur[1].getType()),
+ fpt(t),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second));
+ break;
+
+ case kind::FLOATINGPOINT_FP:
+ {
+ Assert(cur[0].getType().isBitVector());
+ Assert(cur[1].getType().isBitVector());
+ Assert(cur[2].getType().isBitVector());
+
+ Node IEEEBV(
+ nm->mkNode(kind::BITVECTOR_CONCAT, cur[0], cur[1], cur[2]));
+ d_fpMap.insert(cur, symfpu::unpack<traits>(fpt(t), IEEEBV));
+ }
+ break;
+
+ case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
+ Assert(cur[0].getType().isBitVector());
+ d_fpMap.insert(cur, symfpu::unpack<traits>(fpt(t), ubv(cur[0])));
+ break;
+
+ case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ d_fpMap.insert(
+ cur,
+ symfpu::convertSBVToFloat<traits>(
+ fpt(t), (*d_rmMap.find(cur[0])).second, sbv(cur[1])));
+ break;
+
+ case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ d_fpMap.insert(
+ cur,
+ symfpu::convertUBVToFloat<traits>(
+ fpt(t), (*d_rmMap.find(cur[0])).second, ubv(cur[1])));
+ break;
+
+ case kind::FLOATINGPOINT_TO_FP_REAL:
+ d_fpMap.insert(cur, buildComponents(cur));
+ // Rely on the real theory and theory combination
+ // to handle the value
+ break;
+
+ default: Unreachable() << "Unhandled kind " << kind; break;
+ }
+ }
+ }
+ else if (t.isBoolean())
+ {
+ switch (kind)
+ {
+ /* ---- Comparisons --------------------------------------- */
+ case kind::EQUAL:
+ {
+ TypeNode childType(cur[0].getType());
+
+ if (childType.isFloatingPoint())
+ {
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::smtlibEqual<traits>(fpt(childType),
+ (*d_fpMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second));
+ }
+ else if (childType.isRoundingMode())
+ {
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_rmMap.find(cur[1]) != d_rmMap.end());
+ d_boolMap.insert(cur,
+ (*d_rmMap.find(cur[0])).second
+ == (*d_rmMap.find(cur[1])).second);
+ }
+ // else do nothing
+ }
+ break;
+
+ case kind::FLOATINGPOINT_LEQ:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ d_boolMap.insert(cur,
+ symfpu::lessThanOrEqual<traits>(
+ fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second));
+ break;
+
+ case kind::FLOATINGPOINT_LT:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::lessThan<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second));
+ break;
+
+ /* ---- Tester -------------------------------------------- */
+ case kind::FLOATINGPOINT_ISN:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::isNormal<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_ISSN:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::isSubnormal<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_ISZ:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::isZero<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_ISINF:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::isInfinite<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_ISNAN:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::isNaN<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_ISNEG:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::isNegative<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second));
+ break;
+
+ case kind::FLOATINGPOINT_ISPOS:
+ Assert(d_fpMap.find(cur[0]) != d_fpMap.end());
+ d_boolMap.insert(
+ cur,
+ symfpu::isPositive<traits>(fpt(cur[0].getType()),
+ (*d_fpMap.find(cur[0])).second));
+ break;
+
+ default:; // do nothing
+ }
+ }
+ else if (t.isBitVector())
+ {
+ /* ---- Conversions --------------------------------------- */
+ if (kind == kind::FLOATINGPOINT_TO_UBV_TOTAL)
+ {
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ FloatingPointToUBVTotal info =
+ cur.getOperator().getConst<FloatingPointToUBVTotal>();
+ d_ubvMap.insert(
+ cur,
+ symfpu::convertFloatToUBV<traits>(fpt(cur[1].getType()),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ info.d_bv_size,
+ ubv(cur[2])));
+ }
+ else if (kind == kind::FLOATINGPOINT_TO_SBV_TOTAL)
+ {
+ Assert(d_rmMap.find(cur[0]) != d_rmMap.end());
+ Assert(d_fpMap.find(cur[1]) != d_fpMap.end());
+ FloatingPointToSBVTotal info =
+ cur.getOperator().getConst<FloatingPointToSBVTotal>();
+
+ d_sbvMap.insert(
+ cur,
+ symfpu::convertFloatToSBV<traits>(fpt(cur[1].getType()),
+ (*d_rmMap.find(cur[0])).second,
+ (*d_fpMap.find(cur[1])).second,
+ info.d_bv_size,
+ sbv(cur[2])));
+ }
+ // else do nothing
+ }
+ }
+ else
+ {
+ Assert(visited.at(cur) == 1);
+ continue;
+ }
+ }
+
+ if (d_boolMap.find(node) != d_boolMap.end())
+ {
+ Assert(node.getType().isBoolean());
+ return (*d_boolMap.find(node)).second;
+ }
+ if (d_sbvMap.find(node) != d_sbvMap.end())
+ {
+ Assert(node.getKind() == kind::FLOATINGPOINT_TO_SBV_TOTAL);
+ return (*d_sbvMap.find(node)).second;
+ }
+ if (d_ubvMap.find(node) != d_ubvMap.end())
+ {
+ Assert(node.getKind() == kind::FLOATINGPOINT_TO_UBV_TOTAL);
+ return (*d_ubvMap.find(node)).second;
+ }
+ return node;
+}
+
+Node FpWordBlaster::getValue(Valuation& val, TNode var)
+{
+ Assert(Theory::isLeafOf(var, THEORY_FP));
+
+ TypeNode t(var.getType());
+
+ Assert(t.isRoundingMode() || t.isFloatingPoint())
+ << "Asking for the value of a type that is not managed by the "
+ "floating-point theory";
+
+ if (t.isRoundingMode())
+ {
+ rmMap::const_iterator i(d_rmMap.find(var));
+ if (i == d_rmMap.end())
+ {
+ return Node::null();
+ }
+ return rmToNode((*i).second);
+ }
+
+ fpMap::const_iterator i(d_fpMap.find(var));
+ if (i == d_fpMap.end())
+ {
+ return Node::null();
+ }
+ return ufToNode(fpt(t), (*i).second);
+}
+
+} // namespace fp
+} // namespace theory
+} // namespace cvc5
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback