Skip to content

Instantly share code, notes, and snippets.

@ThePhD
Created September 21, 2014 23:15
Show Gist options
  • Select an option

  • Save ThePhD/fdde7f1838efddcbf77d to your computer and use it in GitHub Desktop.

Select an option

Save ThePhD/fdde7f1838efddcbf77d to your computer and use it in GitHub Desktop.
q.h
#pragma once
#include <Furrovine++/integral_type.h>
#include <Furrovine++/direct.h>
namespace Furrovine {
namespace detail {
template <std::size_t n, std::size_t m>
struct t_pow {
static const std::size_t value = n * t_pow<n, m - 1>::value;
};
template <std::size_t n>
struct t_pow<n, 0> {
static const std::size_t value = 1;
};
}
template <typename T>
struct direct_q {
T res;
operator T ( ) const {
return res;
}
direct_q& operator= ( T r ) {
res = r;
return *this;
}
};
template <std::size_t n, std::size_t m, typename Signedness = signed>
struct q {
typedef std::conditional_t<std::is_signed<Signedness>::value, std::make_signed_t<integral_type_t< ( n + m ) / 8>>, std::make_unsigned_t<integral_type_t< ( n + m ) / 8>>> T;
static_assert( (n + m) <= (sizeof( T ) * CHAR_BIT), "type for T is not large enough to back this q<>" );
T res;
q( ) = default;
template <typename F, typename = typename std::enable_if<std::is_floating_point<F>::value>::type>
q( F f ) : res( static_cast<T>( f * detail::t_pow<2, m>::value ) ) {
}
template <typename I, typename P = I, typename = typename std::enable_if<std::is_integral<I>::value>::type>
q( I u ) : res( static_cast<T>( u << m ) ) {
}
template <typename R>
q( direct_q<R> rq ) : res( static_cast<T>( rq.res ) ) {
}
template <typename R>
q( direct_t, R res ) : res( static_cast<T>( res ) ) {
}
template <typename F, typename = typename std::enable_if<std::is_floating_point<F>::value>::type>
q& operator=( F f ) {
res = static_cast<T>( f * detail::t_pow<2, m>::value );
return *this;
}
template <typename I, typename P = I, typename = typename std::enable_if<std::is_integral<I>::value>::type>
q& operator=( I u ) {
res = static_cast<T>( u << m );
return *this;
}
template <typename F, typename = typename std::enable_if<std::is_floating_point<F>::value>::type>
explicit operator F( ) const {
F val = static_cast<F>( res );
val /= detail::t_pow<2, m>::value;
return val;
}
T bits( ) const {
return res;
}
};
template <std::size_t n, std::size_t m>
using uq = q<n, m, unsigned>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment