crow

Utility library


Project maintained by CaptainCrowbar Hosted on GitHub Pages — Theme by mattgraham

Fixed-Size Binary Numbers

Crow Library by Ross Smith

#include "crow/fixed-binary.hpp"
namespace Crow;

Fixed binary classes

template <size_t N> class SmallBinary;
template <size_t N> class LargeBinary;
template <size_t N> using Binary
    = [SmallBinary if N<=64, otherwise LargeBinary];

All of these classes represent unsigned integers with N bits. SmallBinary stores its value in a single native integer of an appropriate size, LargeBinary in an array of integers, in little endian order. Normally you should just use the Binary alias; nearly all of the functions described below are common to both templates (except that, where a function is documented as taking a Binary argument by value, usually the LargeBinary version actually takes its argument by reference).

using Uint128 = Binary<128>;
using Uint256 = Binary<256>;
using Uint512 = Binary<512>;
using Uint1024 = Binary<1024>;

Defined for convenience

static constexpr size_t Binary::bits = N;
static constexpr size_t Binary::bytes = [total bytes in representation];
static constexpr size_t Binary::hex_digits
    = [maximum number of hex digits in value];

Member constants.

constexpr Binary::Binary() noexcept;

The default constructor sets the value to zero.

constexpr Binary::Binary(uint64_t x) noexcept;

Constructor from a primitive unsigned integer.

template <size_t M> constexpr explicit
    SmallBinary::SmallBinary(SmallBinary<M> x) noexcept;
template <size_t M> constexpr explicit
    LargeBinary::LargeBinary(SmallBinary<M> x) noexcept;
template <size_t M> constexpr explicit
    LargeBinary::LargeBinary(const LargeBinary<M>& x) noexcept;

Constructor from another Binary object.

constexpr Binary::Binary(std::initializer_list<uint64_t> init) noexcept;

Constructor from a list of 64-bit integers, in big-endian order. Any excess bits are discarded.

explicit Binary::Binary(std::string_view str);

The string constructor calls parse() and follows the same rules.

constexpr Binary::Binary(const Binary& x) noexcept;
constexpr Binary::Binary(Binary&& x) noexcept;
constexpr Binary::~Binary() noexcept;
constexpr Binary& Binary::operator=(const Binary& x) noexcept;
constexpr Binary& Binary::operator=(Binary&& x) noexcept;

Other life cycle operations.

std::string Binary::bin() const;
std::string Binary::dec() const;
std::string Binary::hex() const;
std::string to_string(Binary x);
std::ostream& operator<<(std::ostream& out, Binary x);

String formatting functions. The output operator and to_string() function call dec(). The bin() and hex() functions always return the same number of digits (equal to bits and hex_digits respectively); dec() writes only the number of digits needed, with no leading zeroes (unless the value is zero).

constexpr void Binary::clear() noexcept;

Sets the value to zero.

constexpr uint8_t* Binary::data() noexcept;
constexpr const uint8_t* Binary::data() const noexcept;

Pointers to the internal representation, which will consist of a number of bytes equal to the bytes constant, in little endian order.

template <ArithmeticType T> constexpr bool Binary::fits_in() const noexcept;

True if the current value of the Binary will fit in a T without loss of information.

constexpr size_t Binary::hash() const noexcept;
struct std::hash<Binary<T>>;

Hash function.

constexpr size_t Binary::significant_bits() const noexcept;

Returns the number of significant bits in the value.

constexpr explicit Binary::operator bool() const noexcept;

True if the value is not zero.

template <ArithmeticType T> constexpr explicit
    Binary::operator T() const noexcept;
template <size_t M> constexpr explicit
    LargeBinary::operator SmallBinary<M>() const noexcept;

Converts a fixed binary number into a standard integer or floating point type, or another fixed binary type. The usual arithmetic overflow rules apply if the value is out of range for the result type. Behaviour is undefined if T is a signed integer and fits_in<T>() is false.

SmallBinary Binary::operator+() const noexcept;
Binary Binary::operator-() const noexcept;
Binary& Binary::operator++() noexcept;
Binary Binary::operator++(int) noexcept;
Binary& Binary::operator--() noexcept;
Binary Binary::operator--(int) noexcept;
Binary& Binary::operator+=(Binary y) noexcept;
Binary& Binary::operator-=(Binary y) noexcept;
Binary& Binary::operator*=(Binary y) noexcept;
Binary& Binary::operator/=(Binary y) noexcept;
Binary& Binary::operator%=(Binary y) noexcept;
Binary operator+(Binary x, Binary y) noexcept;
Binary operator-(Binary x, Binary y) noexcept;
Binary operator*(Binary x, Binary y) noexcept;
Binary operator/(Binary x, Binary y) noexcept;
Binary operator%(Binary x, Binary y) noexcept;

Arithmetic operations. Most of these just have the obvious semantics, with the usual wraparound behaviour on overflow or underflow. For all of the division and remainder operations, behaviour is undefined if the divisor is zero.

Binary Binary::operator~() const noexcept;
Binary& Binary::operator&=(Binary y) noexcept;
Binary& Binary::operator|=(Binary y) noexcept;
Binary& Binary::operator^=(Binary y) noexcept;
Binary& Binary::operator<<=(int y) noexcept;
Binary& Binary::operator>>=(int y) noexcept;
Binary operator&(Binary x, Binary y) noexcept;
Binary operator|(Binary x, Binary y) noexcept;
Binary operator^(Binary x, Binary y) noexcept;
Binary operator<<(Binary x, int y) noexcept;
Binary operator>>(Binary x, int y) noexcept;
Binary rotl(Binary x, int y) noexcept;
Binary rotr(Binary x, int y) noexcept;

Bitwise operations. These have their usual semantics. The bit count argument to the shift and rotate operations can be any value, including out of range or negative values; a negative shift or rotate is interpreted as a positive one in the opposite direction.

static void Binary::divide(Binary x, Binary y, Binary& q, Binary& r) noexcept;

Calculates the quotient and remainder of x/y. Behaviour is undefined if y==0.

static Binary Binary::from_double(double x) noexcept;

Conversion from a double yields the equivalent of converting the significand exactly and then shifting by a number of bits based on the exponent. Behaviour is undefined if the argument is negative.

static Binary Binary::max() noexcept;

Returns the maximum value of the type (the complement of zero).

static Binary Binary::parse(std::string_view str);
static Binary Binary::parse_bin(std::string_view str);
static Binary Binary::parse_dec(std::string_view str);
static Binary Binary::parse_hex(std::string_view str);
static bool Binary::try_parse(std::string_view str, Binary& x) noexcept;
static bool Binary::try_parse_bin(std::string_view str, Binary& x) noexcept;
static bool Binary::try_parse_dec(std::string_view str, Binary& x) noexcept;
static bool Binary::try_parse_hex(std::string_view str, Binary& x) noexcept;

These attempt to parse a string as an unsigned integer, in base 2, 10, or 16. The plain parse() version recognises the "0b" and "0x" prefixes. Apostrophe delimiters are allowed. The parse*() functions return the parsed value, and throw std::invalid_argument on failure; the try_parse*() functions modify the supplied reference and return true on success, false on failure.

std::strong_ordering operator<=>(const Binary& a, const Binary& b) noexcept;
bool operator==(Binary x, Binary y) noexcept;
bool operator!=(Binary x, Binary y) noexcept;
bool operator<(Binary x, Binary y) noexcept;
bool operator>(Binary x, Binary y) noexcept;
bool operator<=(Binary x, Binary y) noexcept;
bool operator>=(Binary x, Binary y) noexcept;

Comparison operators.

namespace Literals {
    Uint128 operator""_u128(const char* p);
    Uint256 operator""_u256(const char* p);
    Uint512 operator""_u512(const char* p);
    Uint1024 operator""_u1024(const char* p);
}

Custom literals. These perform the same parsing as the parse() methods.

template <size_t N> class std::numeric_limits<Crow::SmallBinary<N>>;
template <size_t N> class std::numeric_limits<Crow::LargeBinary<N>>;

Numeric limits specializations.