Created
September 21, 2014 23:15
-
-
Save ThePhD/fdde7f1838efddcbf77d to your computer and use it in GitHub Desktop.
q.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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