All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cvc5-cvc5-1.2.0.src.theory.bv.bitblast.bitblast_utils.h Maven / Gradle / Ivy

The newest version!
/******************************************************************************
 * Top contributors (to current version):
 *   Liana Hadarean, Aina Niemetz, Dejan Jovanovic
 *
 * This file is part of the cvc5 project.
 *
 * Copyright (c) 2009-2024 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.
 * ****************************************************************************
 *
 * Various utility functions for bit-blasting.
 */

#include "cvc5_private.h"

#ifndef CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H
#define CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H

#include 
#include "expr/node.h"

namespace cvc5::internal {
namespace theory {
namespace bv {

template  class TBitblaster;

template  
std::string toString (const std::vector& bits);

template <> inline
std::string toString (const std::vector& bits) {
  std::ostringstream os;
  for (int i = bits.size() - 1; i >= 0; --i) {
    TNode bit = bits[i];
    if (bit.getKind() == Kind::CONST_BOOLEAN)
    {
      os << (bit.getConst() ? "1" : "0");
    }
    else
    {
      os << bit<< " ";
    }
  }
  os <<"\n";
  return os.str();
} 

template  T mkTrue(); 
template  T mkFalse(); 
template  T mkNot(T a);
template  T mkOr(T a, T b);
template  T mkOr(const std::vector& a);
template  T mkAnd(T a, T b);
template  T mkAnd(const std::vector& a);
template  T mkXor(T a, T b);
template  T mkIff(T a, T b);
template  T mkIte(T cond, T a, T b);


template <> inline
Node mkTrue() {
  return NodeManager::currentNM()->mkConst(true);
}

template <> inline
Node mkFalse() {
  return NodeManager::currentNM()->mkConst(false);
}

template <> inline
Node mkNot(Node a) {
  return NodeManager::currentNM()->mkNode(Kind::NOT, a);
}

template <> inline
Node mkOr(Node a, Node b) {
  return NodeManager::currentNM()->mkNode(Kind::OR, a, b);
}

template <> inline
Node mkOr(const std::vector& children) {
  Assert(children.size());
  if (children.size() == 1) return children[0];
  return NodeManager::currentNM()->mkNode(Kind::OR, children);
}


template <> inline
Node mkAnd(Node a, Node b) {
  return NodeManager::currentNM()->mkNode(Kind::AND, a, b);
}

template <> inline
Node mkAnd(const std::vector& children) {
  Assert(children.size());
  if (children.size() == 1) return children[0];
  return NodeManager::currentNM()->mkNode(Kind::AND, children);
}


template <> inline
Node mkXor(Node a, Node b) {
  return NodeManager::currentNM()->mkNode(Kind::XOR, a, b);
}

template <> inline
Node mkIff(Node a, Node b) {
  return NodeManager::currentNM()->mkNode(Kind::EQUAL, a, b);
}

template <> inline
Node mkIte(Node cond, Node a, Node b) {
  return NodeManager::currentNM()->mkNode(Kind::ITE, cond, a, b);
}

/*
 Various helper functions that get called by the bitblasting procedures
 */

template 
void inline extractBits(const std::vector& b, std::vector& dest, unsigned lo, unsigned hi) {
  Assert(lo < b.size() && hi < b.size() && lo <= hi);
  for (unsigned i = lo; i <= hi; ++i) {
    dest.push_back(b[i]); 
  }
}

template 
void inline negateBits(const std::vector& bits, std::vector& negated_bits) {
  for(unsigned i = 0; i < bits.size(); ++i) {
    negated_bits.push_back(mkNot(bits[i])); 
  }
}

template 
bool inline isZero(const std::vector& bits) {
  for(unsigned i = 0; i < bits.size(); ++i) {
    if(bits[i] != mkFalse()) {
      return false; 
    }
  }
  return true; 
}

template 
void inline rshift(std::vector& bits, unsigned amount) {
  for (unsigned i = 0; i < bits.size() - amount; ++i) {
    bits[i] = bits[i+amount]; 
  }
  for(unsigned i = bits.size() - amount; i < bits.size(); ++i) {
    bits[i] = mkFalse(); 
  }
}

template 
void inline lshift(std::vector& bits, unsigned amount) {
  for (int i = (int)bits.size() - 1; i >= (int)amount ; --i) {
    bits[i] = bits[i-amount]; 
  }
  for(unsigned i = 0; i < amount; ++i) {
    bits[i] = mkFalse(); 
  }
}

template 
void inline makeZero(std::vector& bits, unsigned width) {
  Assert(bits.size() == 0);
  for(unsigned i = 0; i < width; ++i) {
    bits.push_back(mkFalse()); 
  }
}


/** 
 * Constructs a simple ripple carry adder
 * 
 * @param a first term to be added
 * @param b second term to be added
 * @param res the result
 * @param carry the carry-in bit 
 * 
 * @return the carry-out
 */
template 
T inline rippleCarryAdder(const std::vector&a, const std::vector& b, std::vector& res, T carry) {
  Assert(a.size() == b.size() && res.size() == 0);

  for (unsigned i = 0 ; i < a.size(); ++i) {
    T sum = mkXor(mkXor(a[i], b[i]), carry);
    carry = mkOr( mkAnd(a[i], b[i]),
                  mkAnd( mkXor(a[i], b[i]),
                         carry));
    res.push_back(sum); 
  }

  return carry;
}

template 
inline void shiftAddMultiplier(const std::vector&a, const std::vector&b, std::vector& res) {
  
  for (unsigned i = 0; i < a.size(); ++i) {
    res.push_back(mkAnd(b[0], a[i])); 
  }
  
  for(unsigned k = 1; k < res.size(); ++k) {
  T carry_in = mkFalse();
  T carry_out;
    for(unsigned j = 0; j < res.size() -k; ++j) {
      T aj = mkAnd(b[k], a[j]);
      carry_out = mkOr(mkAnd(res[j+k], aj),
                       mkAnd( mkXor(res[j+k], aj), carry_in));
      res[j+k] = mkXor(mkXor(res[j+k], aj), carry_in);
      carry_in = carry_out; 
    }
  }
}

template 
T inline uLessThanBB(const std::vector&a, const std::vector& b, bool orEqual) {
  Assert(a.size() && b.size());

  T res = mkAnd(mkNot(a[0]), b[0]);
  
  if(orEqual) {
    res = mkOr(res, mkIff(a[0], b[0])); 
  }
  
  for (unsigned i = 1; i < a.size(); ++i) {
    // a < b iff ( a[i] <-> b[i] AND a[i-1:0] < b[i-1:0]) OR (~a[i] AND b[i]) 
    res = mkOr(mkAnd(mkIff(a[i], b[i]), res),
               mkAnd(mkNot(a[i]), b[i])); 
  }
  return res;
}

template 
T inline sLessThanBB(const std::vector&a, const std::vector& b, bool orEqual) {
  Assert(a.size() && b.size());
  if (a.size() == 1) {
    if(orEqual) {
      return  mkOr(mkIff(a[0], b[0]),
                   mkAnd(a[0], mkNot(b[0]))); 
    }

    return mkAnd(a[0], mkNot(b[0]));
  }
  unsigned n = a.size() - 1; 
  std::vector a1, b1;
  extractBits(a, a1, 0, n-1);
  extractBits(b, b1, 0, n-1);
  
  // unsigned comparison of the first n-1 bits
  T ures = uLessThanBB(a1, b1, orEqual);
  T res = mkOr(// a b have the same sign
               mkAnd(mkIff(a[n], b[n]),
                     ures),
               // a is negative and b positive
               mkAnd(a[n],
                     mkNot(b[n])));
  return res;
}

}  // namespace bv
}  // namespace theory
}  // namespace cvc5::internal

#endif  // CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H




© 2015 - 2024 Weber Informatics LLC | Privacy Policy