Skip to content

Instantly share code, notes, and snippets.

@rofirrim
Created July 4, 2015 07:41
Show Gist options
  • Save rofirrim/ff94801715157d541199 to your computer and use it in GitHub Desktop.
Save rofirrim/ff94801715157d541199 to your computer and use it in GitHub Desktop.
#ifndef Q_NUMBERS_HPP
#define Q_NUMBERS_HPP
// Simple implementation of Q numbers
// There may be bugs. Use at your own risk
/*
See https://en.wikipedia.org/wiki/Q_%28number_format%29
*/
#include <limits.h>
template <bool B>
struct check_width;
template <>
struct check_width<true> { };
template <int M, int N>
struct Q : check_width<(M + N == sizeof(long)*CHAR_BIT)>
{
private:
long repr;
static Q Q_(long l) { Q q; q.repr = l; return q; }
public:
Q() : repr(0) { }
Q(int l);
Q(long l);
Q(float f);
Q(double d);
Q operator+(const Q& a) const;
Q operator-(const Q& a) const;
Q operator*(const Q& a) const;
Q operator/(const Q& a) const;
float to_float() const;
float to_double() const;
static Q max();
static Q min();
static Q epsilon();
};
template <int M, int N>
Q<M, N>::Q(int i)
{
this->repr = ((unsigned long)(i) << N);
}
template <int M, int N>
Q<M, N>::Q(long l)
{
this->repr = (l << N);
}
template <int M, int N>
Q<M, N>::Q(float f)
{
this->repr = (f * (1UL << N));
}
template <int M, int N>
Q<M, N>::Q(double d)
{
this->repr = (d * (1UL << N));
}
template <int M, int N>
Q<M,N> Q<M,N>::operator+(const Q& a) const
{
return Q_(this->repr + a.repr);
}
template <int M, int N>
Q<M,N> Q<M,N>::operator-(const Q& a) const
{
return Q_(this->repr - a.repr);
}
template <int M, int N>
Q<M,N> Q<M,N>::operator*(const Q& a) const
{
return Q_a((this->repr * a.repr) << N);
}
template <int M, int N>
Q<M,N> Q<M,N>::operator/(const Q& a) const
{
return Q_a((this->repr * a.repr) >> N);
}
template <int M, int N>
float Q<M,N>::to_float() const
{
return ((float)this->repr) / (1UL << N);
}
template <int M, int N>
float Q<M,N>::to_double() const
{
return ((double)this->repr) / (1UL << N);
}
template <int M, int N>
Q<M,N> Q<M,N>::max()
{
return Q_(LONG_MAX);
}
template <int M, int N>
Q<M,N> Q<M,N>::min()
{
return Q_(LONG_MIN);
}
template <int M, int N>
Q<M,N> Q<M,N>::epsilon()
{
return Q_(1);
}
#endif // Q_NUMBERS_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment