Towards merging iand branch to master. This adds internal support for an "integer AND" operator.
util/divisible.h
util/gmp_util.h
util/hash.h
+ util/iand.h
util/integer_cln_imp.h
util/integer_gmp_imp.h
util/maybe.h
${CMAKE_CURRENT_BINARY_DIR}/FloatingPointType.java
${CMAKE_CURRENT_BINARY_DIR}/FunctionType.java
${CMAKE_CURRENT_BINARY_DIR}/InputLanguage.java
+ ${CMAKE_CURRENT_BINARY_DIR}/IntAnd.java
${CMAKE_CURRENT_BINARY_DIR}/IntToBitVector.java
${CMAKE_CURRENT_BINARY_DIR}/Integer.java
${CMAKE_CURRENT_BINARY_DIR}/IntegerHashFunction.java
#include "smt/command.h"
#include "util/bitvector.h"
#include "util/floatingpoint.h"
+#include "util/iand.h"
#include "util/integer.h"
#include "util/sexpr.h"
#include "util/unsafe_interrupt_exception.h"
%include "util/integer.i"
%include "util/rational.i"
%include "util/bitvector.i"
+%include "util/iand.i"
%include "util/floatingpoint.i"
// Tim: The remainder of util/.
#include "theory/arith/arith_utilities.h"
#include "theory/arith/normal_form.h"
#include "theory/theory.h"
+#include "util/iand.h"
namespace CVC4 {
namespace theory {
case kind::PLUS:
return preRewritePlus(t);
case kind::MULT:
- case kind::NONLINEAR_MULT:
- return preRewriteMult(t);
+ case kind::NONLINEAR_MULT: return preRewriteMult(t);
+ case kind::IAND: return RewriteResponse(REWRITE_DONE, t);
case kind::EXPONENTIAL:
case kind::SINE:
case kind::COSINE:
case kind::PLUS:
return postRewritePlus(t);
case kind::MULT:
- case kind::NONLINEAR_MULT:
- return postRewriteMult(t);
+ case kind::NONLINEAR_MULT: return postRewriteMult(t);
+ case kind::IAND: return postRewriteIAnd(t);
case kind::EXPONENTIAL:
case kind::SINE:
case kind::COSINE:
return RewriteResponse(REWRITE_DONE, res.getNode());
}
+RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
+{
+ Assert(t.getKind() == kind::IAND);
+ NodeManager* nm = NodeManager::currentNM();
+ // if constant, we eliminate
+ if (t[0].isConst() && t[1].isConst())
+ {
+ size_t bsize = t.getOperator().getConst<IntAnd>().d_size;
+ Node iToBvop = nm->mkConst(IntToBitVector(bsize));
+ Node arg1 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[0]);
+ Node arg2 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[1]);
+ Node bvand = nm->mkNode(kind::BITVECTOR_AND, arg1, arg2);
+ Node ret = nm->mkNode(kind::BITVECTOR_TO_NAT, bvand);
+ return RewriteResponse(REWRITE_AGAIN_FULL, ret);
+ }
+ else if (t[0] > t[1])
+ {
+ // ((_ iand k) x y) ---> ((_ iand k) y x) if x > y by node ordering
+ Node ret = nm->mkNode(kind::IAND, t.getOperator(), t[1], t[0]);
+ return RewriteResponse(REWRITE_AGAIN, ret);
+ }
+ else if (t[0] == t[1])
+ {
+ // ((_ iand k) x x) ---> x
+ return RewriteResponse(REWRITE_DONE, t[0]);
+ }
+ // simplifications involving constants
+ for (unsigned i = 0; i < 2; i++)
+ {
+ if (!t[i].isConst())
+ {
+ continue;
+ }
+ if (t[i].getConst<Rational>().sgn() == 0)
+ {
+ // ((_ iand k) 0 y) ---> 0
+ return RewriteResponse(REWRITE_DONE, t[i]);
+ }
+ }
+ return RewriteResponse(REWRITE_DONE, t);
+}
RewriteResponse ArithRewriter::preRewriteTranscendental(TNode t) {
return RewriteResponse(REWRITE_DONE, t);
static RewriteResponse preRewriteMult(TNode t);
static RewriteResponse postRewriteMult(TNode t);
-
+
+ static RewriteResponse postRewriteIAnd(TNode t);
+
static RewriteResponse preRewriteTranscendental(TNode t);
static RewriteResponse postRewriteTranscendental(TNode t);
d_ee.addFunctionKind(kind::NONLINEAR_MULT);
d_ee.addFunctionKind(kind::EXPONENTIAL);
d_ee.addFunctionKind(kind::SINE);
+ d_ee.addFunctionKind(kind::IAND);
}
ArithCongruenceManager::~ArithCongruenceManager() {}
typerule PI ::CVC4::theory::arith::RealNullaryOperatorTypeRule
+# Integer AND, which is parameterized by a (positive) bitwidth k.
+# ((_ iand k) i1 i2) is equivalent to:
+# (bv2int (bvand ((_ int2bv k) i1) ((_ int2bv k) i2)))
+# for all integers i1, i2.
+constant IAND_OP \
+ ::CVC4::IntAnd \
+ "::CVC4::UnsignedHashFunction< ::CVC4::IntAnd >" \
+ "util/iand.h" \
+ "operator for integer AND; payload is an instance of the CVC4::IntAnd class"
+parameterized IAND IAND_OP 2 "integer version of AND operator; first parameter is an IAND_OP, second and third are integer terms"
+
+typerule IAND_OP ::CVC4::theory::arith::IAndOpTypeRule
+typerule IAND ::CVC4::theory::arith::IAndTypeRule
+
endtheory
VarList::VarList(Node n) : NodeWrapper(n) { Assert(isSorted(begin(), end())); }
+bool Variable::isIAndMember(Node n)
+{
+ return n.getKind() == kind::IAND && Polynomial::isMember(n[0])
+ && Polynomial::isMember(n[1]);
+}
+
bool Variable::isDivMember(Node n){
switch(n.getKind()){
case kind::DIVISION:
case kind::INTS_DIVISION_TOTAL:
case kind::INTS_MODULUS_TOTAL:
case kind::DIVISION_TOTAL: return isDivMember(n);
+ case kind::IAND: return isIAndMember(n);
case kind::EXPONENTIAL:
case kind::SINE:
case kind::COSINE:
}
static bool isLeafMember(Node n);
+ static bool isIAndMember(Node n);
static bool isDivMember(Node n);
bool isDivLike() const{
return isDivMember(getNode());
getExtTheory()->addFunctionKind(kind::EXPONENTIAL);
getExtTheory()->addFunctionKind(kind::SINE);
getExtTheory()->addFunctionKind(kind::PI);
+ getExtTheory()->addFunctionKind(kind::IAND);
}
}
}
};/* class RealNullaryOperatorTypeRule */
+class IAndOpTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (n.getKind() != kind::IAND_OP)
+ {
+ InternalError() << "IAND_OP typerule invoked for IAND_OP kind";
+ }
+ TypeNode iType = nodeManager->integerType();
+ std::vector<TypeNode> argTypes;
+ argTypes.push_back(iType);
+ argTypes.push_back(iType);
+ return nodeManager->mkFunctionType(argTypes, iType);
+ }
+}; /* class IAndOpTypeRule */
+
+class IAndTypeRule
+{
+ public:
+ inline static TypeNode computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+ {
+ if (n.getKind() != kind::IAND)
+ {
+ InternalError() << "IAND typerule invoked for IAND kind";
+ }
+ if (check)
+ {
+ TypeNode arg1 = n[0].getType(check);
+ TypeNode arg2 = n[1].getType(check);
+ if (!arg1.isInteger() || !arg2.isInteger())
+ {
+ throw TypeCheckingExceptionPrivate(n, "expecting integer terms");
+ }
+ }
+ return nodeManager->integerType();
+ }
+}; /* class BitVectorConversionTypeRule */
+
}/* CVC4::theory::arith namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
floatingpoint.cpp
gmp_util.h
hash.h
+ iand.h
index.cpp
index.h
maybe.h
--- /dev/null
+/********************* */
+/*! \file iand.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Anrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2019 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.\endverbatim
+ **
+ ** \brief The integer AND operator.
+ **/
+
+#include "cvc4_public.h"
+
+#ifndef CVC4__IAND_H
+#define CVC4__IAND_H
+
+#include <cstdint>
+#include <iosfwd>
+
+#include "base/exception.h"
+#include "util/integer.h"
+
+namespace CVC4 {
+
+struct CVC4_PUBLIC IntAnd
+{
+ unsigned d_size;
+ IntAnd(unsigned size) : d_size(size) {}
+ operator unsigned() const { return d_size; }
+}; /* struct IntAnd */
+
+/* -----------------------------------------------------------------------
+ ** Output stream
+ * ----------------------------------------------------------------------- */
+
+inline std::ostream& operator<<(std::ostream& os, const IntAnd& ia) CVC4_PUBLIC;
+inline std::ostream& operator<<(std::ostream& os, const IntAnd& ia)
+{
+ return os << "[" << ia.d_size << "]";
+}
+
+} // namespace CVC4
+
+#endif /* CVC4__IAND_H */
--- /dev/null
+%{
+#include "util/iand.h"
+%}
+
+%rename(toUnsigned) CVC4::IntAnd::operator unsigned() const;
+
+%ignore CVC4::operator<<(std::ostream&, const IntAnd&);
+
+%include "util/iand.h"