root/software/fixed/fixed.h @ 835f4592
| 835f4592 | David Sorber | ||
#ifndef FIXED_H_
|
|||
#define FIXED_H_
|
|||
#include <cmath>
|
|||
#include <cstdint>
|
|||
#include <limits>
|
|||
#include <type_traits>
|
|||
template <typename IntegerType, typename FractionalType>
|
|||
class fixed
|
|||
{
|
|||
static_assert(std::is_integral<IntegerType>::value, "IntegerType must be an integral type");
|
|||
static_assert(std::is_integral<FractionalType>::value, "FractionalType must be an integral type");
|
|||
static_assert(std::is_signed<IntegerType>::value, "IntegerType must be a signed type");
|
|||
static_assert(std::is_unsigned<FractionalType>::value, "FractionalType must be an unsigned type");
|
|||
public:
|
|||
static constexpr size_t integer_bits = sizeof(IntegerType) * 8;
|
|||
static constexpr size_t fractional_bits = sizeof(FractionalType) * 8;
|
|||
static constexpr size_t integer_decimal_digits = std::floor(std::log10(std::numeric_limits<IntegerType>::max()));
|
|||
static constexpr size_t fractional_decimal_digits = std::floor(std::log10(std::numeric_limits<FractionalType>::max()));
|
|||
static constexpr size_t MAX_INTEGER_VALUE = (static_cast<uint64_t>(std::pow(10, integer_decimal_digits)) - 1);
|
|||
static constexpr size_t MIN_INTEGER_VALUE = 0;
|
|||
static constexpr size_t MAX_FRACTIONAL_VALUE = (static_cast<uint64_t>(std::pow(10, fractional_decimal_digits)) - 1);
|
|||
static constexpr size_t MIN_FRACTIONAL_VALUE = 0;
|
|||
fixed()
|
|||
: m_integer(0), m_fractional(0) {}
|
|||
fixed(IntegerType integerVal, FractionalType fractionalVal)
|
|||
: m_integer(integerVal), m_fractional(fractionalVal) {}
|
|||
// Default copy constructor, and assignment operator
|
|||
fixed(const fixed&) = default;
|
|||
fixed& operator=(const fixed&) = default;
|
|||
void parse(const char* input)
|
|||
{
|
|||
}
|
|||
constexpr inline fixed operator-() const noexcept = delete;
|
|||
inline fixed& operator+=(const fixed& y) noexcept = delete;
|
|||
inline fixed& operator-=(const fixed& y) noexcept = delete;
|
|||
inline fixed& operator*=(const fixed& y) noexcept = delete;
|
|||
inline fixed& operator/=(const fixed& y) noexcept = delete;
|
|||
// Comparison operators
|
|||
template <typename I, typename F>
|
|||
friend constexpr inline bool operator==(const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
|
|||
template <typename I, typename F>
|
|||
friend constexpr inline bool operator!=(const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
|
|||
template <typename I, typename F>
|
|||
friend constexpr inline bool operator<(const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
|
|||
template <typename I, typename F>
|
|||
friend constexpr inline bool operator>(const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
|
|||
template <typename I, typename F>
|
|||
friend constexpr inline bool operator<=(const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
|
|||
template <typename I, typename F>
|
|||
friend constexpr inline bool operator>=(const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
|
|||
private:
|
|||
IntegerType m_integer;
|
|||
FractionalType m_fractional;
|
|||
};
|
|||
using fixed_64_64 = fixed<int64_t, uint64_t>;
|
|||
template <typename I, typename F>
|
|||
constexpr inline bool operator==(const fixed<I, F>& x, const fixed<I, F>& y) noexcept
|
|||
{
|
|||
return (x.m_integer == y.m_integer && x.m_fractional == y.m_fractional);
|
|||
}
|
|||
template <typename I, typename F>
|
|||
constexpr inline bool operator!=(const fixed<I, F>& x, const fixed<I, F>& y) noexcept
|
|||
{
|
|||
return (! x == y);
|
|||
}
|
|||
template <typename I, typename F>
|
|||
constexpr inline bool operator<(const fixed<I, F>& x, const fixed<I, F>& y) noexcept
|
|||
{
|
|||
if (x.m_integer == y.m_integer)
|
|||
{
|
|||
return (x.m_fractional < y.m_fractional);
|
|||
}
|
|||
else
|
|||
{
|
|||
return (x.m_integer < y.m_integer);
|
|||
}
|
|||
return false;
|
|||
}
|
|||
template <typename I, typename F>
|
|||
constexpr inline bool operator>(const fixed<I, F>& x, const fixed<I, F>& y) noexcept
|
|||
{
|
|||
if (x.m_integer == y.m_integer)
|
|||
{
|
|||
return (x.m_fractional > y.m_fractional);
|
|||
}
|
|||
else
|
|||
{
|
|||
return (x.m_integer > y.m_integer);
|
|||
}
|
|||
return false;
|
|||
}
|
|||
template <typename I, typename F>
|
|||
constexpr inline bool operator<=(const fixed<I, F>& x, const fixed<I, F>& y) noexcept
|
|||
{
|
|||
if (x.m_integer == y.m_integer)
|
|||
{
|
|||
return (x.m_fractional <= y.m_fractional);
|
|||
}
|
|||
else
|
|||
{
|
|||
return (x.m_integer < y.m_integer);
|
|||
}
|
|||
return false;
|
|||
}
|
|||
template <typename I, typename F>
|
|||
constexpr inline bool operator>=(const fixed<I, F>& x, const fixed<I, F>& y) noexcept
|
|||
{
|
|||
if (x.m_integer == y.m_integer)
|
|||
{
|
|||
return (x.m_fractional > y.m_fractional);
|
|||
}
|
|||
else
|
|||
{
|
|||
return (x.m_integer > y.m_integer);
|
|||
}
|
|||
return false;
|
|||
}
|
|||
// Addition
|
|||
template <typename I, typename F>
|
|||
constexpr inline fixed<I, F> operator+(const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
|
|||
// Subtraction
|
|||
template <typename I, typename F>
|
|||
constexpr inline fixed<I, F> operator-(const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
|
|||
// Multiplication
|
|||
template <typename I, typename F>
|
|||
constexpr inline fixed<I, F> operator*(const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
|
|||
// Division
|
|||
template <typename I, typename F>
|
|||
constexpr inline fixed<I, F> operator/(const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
|
|||
#endif // FIXED_H_
|