#pragma once /////////////////////////////////////////////////////////////// // Distributed under the Boost Software License, Version 1.0. // (See at http://www.boost.org/LICENSE_1_0.txt) /////////////////////////////////////////////////////////////// /* Divide and multiply * * * Copyright (c) 2008 * Evan Teran * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appears in all copies and that both the * copyright notice and this permission notice appear in supporting * documentation, and that the same name not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. We make no representations about the * suitability this software for any purpose. It is provided "as is" * without express or implied warranty. */ #include #include #include #include namespace wide { template class integer; } namespace std { template struct common_type, wide::integer>; template struct common_type, Arithmetic>; template struct common_type>; } namespace wide { /// Attrubute 'packed' does not make sense to this class itself /// but it is needed to allow to use this type in other structs with attribute packed. template class __attribute__((__packed__)) integer { public: using base_type = uint64_t; using signed_base_type = int64_t; // ctors constexpr integer() noexcept = default; template constexpr integer(T rhs) noexcept; template constexpr integer(std::initializer_list il) noexcept; // assignment template constexpr integer & operator=(const integer & rhs) noexcept; template constexpr integer & operator=(Arithmetic rhs) noexcept; template constexpr integer & operator*=(const Arithmetic & rhs); template constexpr integer & operator/=(const Arithmetic & rhs); template constexpr integer & operator+=(const Arithmetic & rhs) noexcept(std::is_same_v); template constexpr integer & operator-=(const Arithmetic & rhs) noexcept(std::is_same_v); template constexpr integer & operator%=(const Integral & rhs); template constexpr integer & operator&=(const Integral & rhs) noexcept; template constexpr integer & operator|=(const Integral & rhs) noexcept; template constexpr integer & operator^=(const Integral & rhs) noexcept; constexpr integer & operator<<=(int n) noexcept; constexpr integer & operator>>=(int n) noexcept; constexpr integer & operator++() noexcept(std::is_same_v); constexpr integer operator++(int) noexcept(std::is_same_v); constexpr integer & operator--() noexcept(std::is_same_v); constexpr integer operator--(int) noexcept(std::is_same_v); // observers constexpr explicit operator bool() const noexcept; template using _integral_not_wide_integer_class = typename std::enable_if::value, T>::type; template > constexpr operator T() const noexcept; constexpr operator long double() const noexcept; constexpr operator double() const noexcept; constexpr operator float() const noexcept; struct _impl; base_type items[_impl::item_count]; private: template friend class integer; friend class std::numeric_limits>; friend class std::numeric_limits>; }; template static constexpr bool ArithmeticConcept() noexcept; template using _only_arithmetic = typename std::enable_if() && ArithmeticConcept()>::type; template static constexpr bool IntegralConcept() noexcept; template using _only_integer = typename std::enable_if() && IntegralConcept()>::type; // Unary operators template constexpr integer operator~(const integer & lhs) noexcept; template constexpr integer operator-(const integer & lhs) noexcept(std::is_same_v); template constexpr integer operator+(const integer & lhs) noexcept(std::is_same_v); // Binary operators template std::common_type_t, integer> constexpr operator*(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator*(const Arithmetic & rhs, const Arithmetic2 & lhs); template std::common_type_t, integer> constexpr operator/(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator/(const Arithmetic & rhs, const Arithmetic2 & lhs); template std::common_type_t, integer> constexpr operator+(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator+(const Arithmetic & rhs, const Arithmetic2 & lhs); template std::common_type_t, integer> constexpr operator-(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator-(const Arithmetic & rhs, const Arithmetic2 & lhs); template std::common_type_t, integer> constexpr operator%(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator%(const Integral & rhs, const Integral2 & lhs); template std::common_type_t, integer> constexpr operator&(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator&(const Integral & rhs, const Integral2 & lhs); template std::common_type_t, integer> constexpr operator|(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator|(const Integral & rhs, const Integral2 & lhs); template std::common_type_t, integer> constexpr operator^(const integer & lhs, const integer & rhs); template > std::common_type_t constexpr operator^(const Integral & rhs, const Integral2 & lhs); // TODO: Integral template constexpr integer operator<<(const integer & lhs, int n) noexcept; template constexpr integer operator>>(const integer & lhs, int n) noexcept; template >> constexpr integer operator<<(const integer & lhs, Int n) noexcept { return lhs << int(n); } template >> constexpr integer operator>>(const integer & lhs, Int n) noexcept { return lhs >> int(n); } template constexpr bool operator<(const integer & lhs, const integer & rhs); template > constexpr bool operator<(const Arithmetic & rhs, const Arithmetic2 & lhs); template constexpr bool operator>(const integer & lhs, const integer & rhs); template > constexpr bool operator>(const Arithmetic & rhs, const Arithmetic2 & lhs); template constexpr bool operator<=(const integer & lhs, const integer & rhs); template > constexpr bool operator<=(const Arithmetic & rhs, const Arithmetic2 & lhs); template constexpr bool operator>=(const integer & lhs, const integer & rhs); template > constexpr bool operator>=(const Arithmetic & rhs, const Arithmetic2 & lhs); template constexpr bool operator==(const integer & lhs, const integer & rhs); template > constexpr bool operator==(const Arithmetic & rhs, const Arithmetic2 & lhs); template constexpr bool operator!=(const integer & lhs, const integer & rhs); template > constexpr bool operator!=(const Arithmetic & rhs, const Arithmetic2 & lhs); } namespace std { template struct hash>; } #include "wide_integer_impl.h"