Skip to content

Instantly share code, notes, and snippets.

@Sam-Belliveau
Last active April 29, 2019 02:41
Show Gist options
  • Select an option

  • Save Sam-Belliveau/bc58fdaa6b5e65ab44df95b6cd364a12 to your computer and use it in GitHub Desktop.

Select an option

Save Sam-Belliveau/bc58fdaa6b5e65ab44df95b6cd364a12 to your computer and use it in GitHub Desktop.
Simple C++ Fixed Point Number Library
#ifndef FIXED_POINT_NUMBERS_HPP
#define FIXED_POINT_NUMBERS_HPP 1
namespace Fixed
{
namespace FixedMath
{
template<class T>
constexpr T GCD(T a, T b) { return (b == 0) ? a : GCD(b, a % b); }
}
template<class T, T Exp>
class Number
{
public: // Static Variables
static const T Exponent = Exp;
private: // Variables
T val;
public: // Methods
/** Constructors **/
constexpr Number() : val{0} {}
constexpr Number(const Number& in) = default;
constexpr Number& operator=(const Number& in) = default;
constexpr Number(Number&& in) = default;
constexpr Number& operator=(Number&& in) = default;
constexpr Number(const T &in) : val{in * Exp} {}
template<T inExp>
constexpr Number(const Number<T, inExp> in)
{
// Get Compile Time GCD
constexpr T ExpGCD = FixedMath::GCD(Exp, inExp);
constexpr T ExpS = Exp / ExpGCD, inExpS = inExp / ExpGCD;
val = (in.getRawValue() * ExpS) / inExpS; // Convert Value
}
template<class inT>
constexpr Number(const inT in)
: val{static_cast<T>(in * static_cast<inT>(Exp))} {}
/** Casts **/
template<class outT>
explicit operator outT() const
{ return static_cast<outT>(val) / static_cast<outT>(Exp); }
/** Getters **/
constexpr const T& getRawValue() const { return val; }
/** Operators **/
// Increment
constexpr Number& operator++()
{ val += Exp; return *this; }
constexpr Number& operator++(int)
{ Number t(*this); val += Exp; return t; }
// Decrement
constexpr Number& operator--()
{ val -= Exp; return *this; }
constexpr Number& operator--(int)
{ Number t(*this); val -= Exp; return t; }
// Add
constexpr Number& operator+=(const Number &b)
{ val += b.val; return *this; }
// Sub
constexpr Number& operator-=(const Number &b)
{ val -= b.val; return *this; }
// Mul
constexpr Number& operator*=(const Number &b)
{ val = (val * b.val) / Exp; return *this; }
// Div
constexpr Number& operator/=(const Number &b)
{ val = (val * Exp) / b.val; return *this; }
// Mod
constexpr Number& operator%=(const Number &b)
{ val %= b.val; return *this; }
// Right Shift Operator
constexpr Number& operator>>=(const unsigned long long bits)
{ val >>= bits; return *this; }
// Left Shift Operator
constexpr Number& operator<<=(const unsigned long long bits)
{ val <<= bits; return *this; }
// And
constexpr Number& operator&=(const Number &b)
{ val &= b.val; return *this; }
// Or
constexpr Number& operator|=(const Number &b)
{ val |= b.val; return *this; }
// XOr
constexpr Number& operator^=(const Number &b)
{ val ^= b.val; return *this; }
// Less Than
constexpr bool operator==(const Number &b) const
{ return val == b.val; }
// Less Than
constexpr bool operator!=(const Number &b) const
{ return val != b.val; }
// Less Than
constexpr bool operator<(const Number &b) const
{ return val < b.val; }
// Less Than
constexpr bool operator>(const Number &b) const
{ return val > b.val; }
// Less Than
constexpr bool operator<=(const Number &b) const
{ return val <= b.val; }
// Less Than
constexpr bool operator>=(const Number &b) const
{ return val >= b.val; }
};
}
namespace Fixed // Implementation
{
/** Operators **/
// Add
template<class T, T Exp>
constexpr Number<T, Exp> operator+(Number<T, Exp> a, const Number<T, Exp> &b)
{ a += b; return a; }
// Sub
template<class T, T Exp>
constexpr Number<T, Exp> operator-(Number<T, Exp> a, const Number<T, Exp> &b)
{ a -= b; return a; }
// Mul
template<class T, T Exp>
constexpr Number<T, Exp> operator*(Number<T, Exp> a, const Number<T, Exp> &b)
{ a *= b; return a; }
// Div
template<class T, T Exp>
constexpr Number<T, Exp> operator/(Number<T, Exp> a, const Number<T, Exp> &b)
{ a /= b; return a; }
// Mod
template<class T, T Exp>
constexpr Number<T, Exp> operator%(Number<T, Exp> a, const Number<T, Exp> &b)
{ a %= b; return a; }
// Right Shift Operator
template<class T, T Exp>
constexpr Number<T, Exp> operator>>(Number<T, Exp> a, const unsigned long long bits)
{ a >>= bits; return a; }
// Left Shift Operator
template<class T, T Exp>
constexpr Number<T, Exp> operator<<(Number<T, Exp> a, const unsigned long long bits)
{ a <<= bits; return a; }
// And
template<class T, T Exp>
constexpr Number<T, Exp> operator&(Number<T, Exp> a, const Number<T, Exp> &b)
{ a &= b; return a; }
// Or
template<class T, T Exp>
constexpr Number<T, Exp> operator|(Number<T, Exp> a, const Number<T, Exp> &b)
{ a |= b; return a; }
// XOr
template<class T, T Exp>
constexpr Number<T, Exp> operator^(Number<T, Exp> a, const Number<T, Exp> &b)
{ a ^= b; return a; }
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment