/****************************************************************************** * Top contributors (to current version): * Aina Niemetz, Martin Brain, Andres Noetzli * * 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. * **************************************************************************** * * SymFPU glue code for floating-point values. * * !!! This header is only to be included in floating-point literal headers !!! * * This is a symfpu literal "back-end". It allows the library to be used as * an arbitrary precision floating-point implementation. This is effectively * the glue between symfpu's notion of "signed bit-vector" and cvc5's * BitVector. */ #include "cvc5_private.h" #ifndef CVC5__UTIL__FLOATINGPOINT_LITERAL_SYMFPU_TRAITS_H #define CVC5__UTIL__FLOATINGPOINT_LITERAL_SYMFPU_TRAITS_H // clang-format off #if @CVC5_USE_SYMFPU@ // clang-format on #include "util/bitvector.h" #include "util/floatingpoint_size.h" #include "util/roundingmode.h" #include /* -------------------------------------------------------------------------- */ namespace cvc5 { namespace symfpuLiteral { /** * Forward declaration of wrapper so that traits can be defined early and so * used in the implementation of wrappedBitVector. */ template class wrappedBitVector; using Cvc5BitWidth = uint32_t; using Cvc5Prop = bool; using Cvc5RM = ::cvc5::RoundingMode; using Cvc5FPSize = ::cvc5::FloatingPointSize; using Cvc5UnsignedBitVector = wrappedBitVector; using Cvc5SignedBitVector = wrappedBitVector; /** * This is the template parameter for symfpu's templates. */ class traits { public: /** The six key types that symfpu uses. */ using bwt = Cvc5BitWidth; // bit-width type using prop = Cvc5Prop; // boolean type using rm = Cvc5RM; // rounding-mode type using fpt = Cvc5FPSize; // floating-point format type using ubv = Cvc5UnsignedBitVector; // unsigned bit-vector type using sbv = Cvc5SignedBitVector; // signed bit-vector type /** Give concrete instances of each rounding mode, mainly for comparisons. */ static rm RNE(void); static rm RNA(void); static rm RTP(void); static rm RTN(void); static rm RTZ(void); /** The sympfu properties. */ static void precondition(const prop& p); static void postcondition(const prop& p); static void invariant(const prop& p); }; /** * Type function for mapping between types. */ template struct signedToLiteralType; template <> struct signedToLiteralType { using literalType = int32_t; }; template <> struct signedToLiteralType { using literalType = uint32_t; }; /** * This extends the interface for cvc5::BitVector for compatibility with symFPU. * The template parameter distinguishes signed and unsigned bit-vectors, a * distinction symfpu uses. */ template class wrappedBitVector : public BitVector { protected: using literalType = typename signedToLiteralType::literalType; friend wrappedBitVector; // To allow conversion between types friend ::symfpu::ite >; // For ITE public: /** Constructors. */ wrappedBitVector(const Cvc5BitWidth w, const uint32_t v) : BitVector(w, v) {} wrappedBitVector(const Cvc5Prop& p) : BitVector(1, p ? 1U : 0U) {} wrappedBitVector(const wrappedBitVector& old) : BitVector(old) {} wrappedBitVector(const BitVector& old) : BitVector(old) {} /** Get the bit-width of this wrapped bit-vector. */ Cvc5BitWidth getWidth(void) const { return getSize(); } /** Create a zero value of given bit-width 'w'. */ static wrappedBitVector one(const Cvc5BitWidth& w); /** Create a one value of given bit-width 'w'. */ static wrappedBitVector zero(const Cvc5BitWidth& w); /** Create a ones value (all bits 1) of given bit-width 'w'. */ static wrappedBitVector allOnes(const Cvc5BitWidth& w); /** Create a maximum signed/unsigned value of given bit-width 'w'. */ static wrappedBitVector maxValue(const Cvc5BitWidth& w); /** Create a minimum signed/unsigned value of given bit-width 'w'. */ static wrappedBitVector minValue(const Cvc5BitWidth& w); /** Return true if this a bit-vector representing a ones value. */ Cvc5Prop isAllOnes() const; /** Return true if this a bit-vector representing a zero value. */ Cvc5Prop isAllZeros() const; /** Left shift. */ wrappedBitVector operator<<( const wrappedBitVector& op) const; /** Logical (unsigned) and arithmetic (signed) right shift. */ wrappedBitVector operator>>( const wrappedBitVector& op) const; /** * Inherited but ... * *sigh* if we use the inherited version then it will return a * cvc5::BitVector which can be converted back to a * wrappedBitVector but isn't done automatically when working * out types for templates instantiation. ITE is a particular * problem as expressions and constants no longer derive the * same type. There aren't any good solutions in C++, we could * use CRTP but Liana wouldn't appreciate that, so the following * pointless wrapping functions are needed. */ /** Bit-wise or. */ wrappedBitVector operator|( const wrappedBitVector& op) const; /** Bit-wise and. */ wrappedBitVector operator&( const wrappedBitVector& op) const; /** Bit-vector addition. */ wrappedBitVector operator+( const wrappedBitVector& op) const; /** Bit-vector subtraction. */ wrappedBitVector operator-( const wrappedBitVector& op) const; /** Bit-vector multiplication. */ wrappedBitVector operator*( const wrappedBitVector& op) const; /** Bit-vector signed/unsigned division. */ wrappedBitVector operator/( const wrappedBitVector& op) const; /** Bit-vector signed/unsigned remainder. */ wrappedBitVector operator%( const wrappedBitVector& op) const; /** Bit-vector negation. */ wrappedBitVector operator-(void) const; /** Bit-wise not. */ wrappedBitVector operator~(void) const; /** Bit-vector increment. */ wrappedBitVector increment() const; /** Bit-vector decrement. */ wrappedBitVector decrement() const; /** * Bit-vector logical/arithmetic right shift where 'op' extended to the * bit-width of this wrapped bit-vector. */ wrappedBitVector signExtendRightShift( const wrappedBitVector& op) const; /** * Modular operations. * Note: No overflow checking so these are the same as other operations. */ wrappedBitVector modularLeftShift( const wrappedBitVector& op) const; wrappedBitVector modularRightShift( const wrappedBitVector& op) const; wrappedBitVector modularIncrement() const; wrappedBitVector modularDecrement() const; wrappedBitVector modularAdd( const wrappedBitVector& op) const; wrappedBitVector modularNegate() const; /** Bit-vector equality. */ Cvc5Prop operator==(const wrappedBitVector& op) const; /** Bit-vector signed/unsigned less or equal than. */ Cvc5Prop operator<=(const wrappedBitVector& op) const; /** Bit-vector sign/unsigned greater or equal than. */ Cvc5Prop operator>=(const wrappedBitVector& op) const; /** Bit-vector signed/unsigned less than. */ Cvc5Prop operator<(const wrappedBitVector& op) const; /** Bit-vector sign/unsigned greater or equal than. */ Cvc5Prop operator>(const wrappedBitVector& op) const; /** Convert this bit-vector to a signed bit-vector. */ wrappedBitVector toSigned(void) const; /** Convert this bit-vector to an unsigned bit-vector. */ wrappedBitVector toUnsigned(void) const; /** Bit-vector signed/unsigned (zero) extension. */ wrappedBitVector extend(Cvc5BitWidth extension) const; /** * Create a "contracted" bit-vector by cutting off the 'reduction' number of * most significant bits, i.e., by extracting the (bit-width - reduction) * least significant bits. */ wrappedBitVector contract(Cvc5BitWidth reduction) const; /** * Create a "resized" bit-vector of given size bei either extending (if new * size is larger) or contracting (if it is smaller) this wrapped bit-vector. */ wrappedBitVector resize(Cvc5BitWidth newSize) const; /** * Create an extension of this bit-vector that matches the bit-width of the * given bit-vector. * * Note: The size of the given bit-vector may not be larger than the size of * this bit-vector. */ wrappedBitVector matchWidth( const wrappedBitVector& op) const; /** Bit-vector concatenation. */ wrappedBitVector append(const wrappedBitVector& op) const; /** Inclusive of end points, thus if the same, extracts just one bit. */ wrappedBitVector extract(Cvc5BitWidth upper, Cvc5BitWidth lower) const; }; } // namespace symfpuLiteral } #endif #endif