twos_complement.h

Back to Two’s complement

pastel/sys/bit/

// Description: Two's complement

#ifndef PASTELSYS_TWOS_COMPLEMENT_H
#define PASTELSYS_TWOS_COMPLEMENT_H

#include "pastel/sys/mytypes.h"
#include "pastel/sys/integer/finite_integer_concept.h"
#include "pastel/sys/integer/integer_concept.h"

#include <type_traits>

namespace Pastel
{

    //! Two's complement form from a signed integer
    /*!
   Preconditions:
   Integer is a signed native integer.

   The bit-presentation of a signed integer is implementation-defined,
   and so not portable. However, the bit-representation of an unsigned
   integer is well-defined. This function converts the signed integer,
   no matter what its bit-presentation, portably to its two's complement
   form, and stores it in the bits of the corresponding unsigned integer 
   type.
   */   
    template <typename Integer, Requires<std::is_signed<Integer>> = 0>
    typename std::make_unsigned<Integer>::type 
    signedToTwosComplement(const Integer& that);

    //! Signed integer from a two's complement form.
    /*!
   Preconditions:
   Finite_Integer is an unsigned native integer.
   that != 2^{n - 1})

   This is the inverse of signedToTwosComplement(), see its
   documentation. However, this function can not portably be 
   defined for the two's complement form 2^{n - 1}, where n is 
   the number of bits: in ones' complement and sign-magnitude
   representations the corresponding number -2^{n - 1} does 
   not exist.
   */   
    template <typename Finite_Integer, Requires<std::is_unsigned<Finite_Integer>> = 0>
    typename std::make_signed<Finite_Integer>::type
        twosComplementToSigned(const Finite_Integer& that);

    //! Returns whether 'that' represents a negative value.
    /*!
   A two's complement integer is negative if and only if
   its most-significant bit is 1.
   */
    template <typename Finite_Integer, Requires<std::is_unsigned<Finite_Integer>> = 0>
    bool twosComplementNegative(const Finite_Integer& that);

    //! Arithmetic right-shift for integers in two's complement form.
    /*!
   Preconditions:
   n >= 0
   Finite_Integer is an unsigned native integer.

   returns:
   floor(that / 2^n)
   where
   that is interpreted by its two's complement value.
   */
    template <typename Finite_Integer, Requires<std::is_unsigned<Finite_Integer>> = 0>
    Finite_Integer arithmeticShiftRight(
            const Finite_Integer& that, 
            integer n);

    //! Computes floor(that / 2^n).
    /*!
   Preconditions:
   n >= 0
   Finite_Integer is an unsigned native integer.
   */
    template <typename Finite_Integer, Requires<std::is_unsigned<Finite_Integer>> = 0>
    Finite_Integer shiftRight(
            const Finite_Integer& that, 
            integer n);

    //! Computes roundTowardsZero(that / 2^n).
    /*!
   Preconditions:
   n >= 0
   Finite_Integer is a signed native integer.
   */
    template <typename Finite_Integer, Requires<std::is_signed<Finite_Integer>> = 0>
    Finite_Integer shiftRight(
            const Finite_Integer& that, 
            integer n);

}

#include "pastel/sys/bit/twos_complement.hpp"

#endif