From b770e5f370640675e6a6553a86492e55a4b179cd Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 4 Jan 2017 22:38:41 +1100 Subject: [PATCH] fixed: add integer logical operators --- fixed.cpp | 75 +++++++++++++++++++++-------------- fixed.hpp | 105 +++++++++++++++++++++++++++++++------------------ test/fixed.cpp | 11 ++++-- 3 files changed, 119 insertions(+), 72 deletions(-) diff --git a/fixed.cpp b/fixed.cpp index e62e706e..de7058a3 100644 --- a/fixed.cpp +++ b/fixed.cpp @@ -22,21 +22,6 @@ using namespace util; /////////////////////////////////////////////////////////////////////////////// -// Constructors -template -fixed::fixed (native_t val): - m_value (val << E) -{ - static_assert (I > 0, "must use positive integer bits"); - static_assert (E > 0, "must use positive fractional bits"); - static_assert (I + E == sizeof (m_value) * 8, - "underlying storage must be exactly I+E sized"); -} - - -/////////////////////////////////////////////////////////////////////////////// -// Conversions - template double fixed::to_double (void) const @@ -56,7 +41,7 @@ fixed::to_float (void) const //----------------------------------------------------------------------------- template -typename fixed::native_t +typename fixed::integer_type fixed::to_integer (void) const { return m_value >> E; @@ -65,7 +50,7 @@ fixed::to_integer (void) const //----------------------------------------------------------------------------- template -typename fixed::native_t +typename fixed::native_type fixed::to_native (void) const { return m_value; @@ -75,7 +60,7 @@ fixed::to_native (void) const //----------------------------------------------------------------------------- template fixed -fixed::from_native (native_t i) +fixed::from_native (native_type i) { fixed v; v.m_value = i; @@ -85,8 +70,22 @@ fixed::from_native (native_t i) //----------------------------------------------------------------------------- template -typename fixed::native_t -fixed::to_integer (native_t n) +fixed +fixed::from_integer (integer_type val) +{ + constexpr auto rshift = sizeof (val) * 8 - I; + constexpr auto lshift = E - rshift; + + fixed res; + res.m_value = static_cast (val) << lshift; + return res; +} + + +//----------------------------------------------------------------------------- +template +typename fixed::integer_type +fixed::to_integer (native_type n) { return n >> E; } @@ -123,13 +122,13 @@ SIMPLE_FIXED_LIT(+) /////////////////////////////////////////////////////////////////////////////// // Integer operators -#define SIMPLE_INTEGER_REF(OP) \ -template \ -fixed& \ -fixed::operator OP (native_t val) \ -{ \ - m_value OP val << E; \ - return *this; \ +#define SIMPLE_INTEGER_REF(OP) \ +template \ +fixed& \ +fixed::operator OP (integer_type val) \ +{ \ + m_value OP (static_cast (val) << E); \ + return *this; \ } SIMPLE_INTEGER_REF(+=) @@ -139,10 +138,10 @@ SIMPLE_INTEGER_REF(/=) //----------------------------------------------------------------------------- -#define SIMPLE_INTEGER_LIT(OP) \ +#define SIMPLE_INTEGER_LIT(OP) \ template \ fixed \ -fixed::operator OP (native_t val) const \ +fixed::operator OP (integer_type val) const \ { \ return fixed::from_native (m_value OP val << E); \ } @@ -163,6 +162,14 @@ util::operator OP (util::fixed a, \ util::fixed b) \ { \ return a.to_native () OP b.to_native (); \ +} \ + \ +template \ +bool \ +util::operator OP (util::fixed a, \ + typename util::fixed::integer_type b) \ +{ \ + return a OP util::fixed::from_integer (b); \ } LOGIC_OP(==) @@ -172,6 +179,7 @@ LOGIC_OP(<=) LOGIC_OP(>) LOGIC_OP(>=) + /////////////////////////////////////////////////////////////////////////////// // iostream operators template @@ -193,10 +201,17 @@ template bool util::operator!= (util::fixed, util::fixed); \ template bool util::operator< (util::fixed, util::fixed); \ template bool util::operator<= (util::fixed, util::fixed); \ template bool util::operator> (util::fixed, util::fixed); \ -template bool util::operator>= (util::fixed, util::fixed); +template bool util::operator>= (util::fixed, util::fixed); \ +template bool util::operator== (util::fixed, typename util::fixed::integer_type); \ +template bool util::operator!= (util::fixed, typename util::fixed::integer_type); \ +template bool util::operator< (util::fixed, typename util::fixed::integer_type); \ +template bool util::operator<= (util::fixed, typename util::fixed::integer_type); \ +template bool util::operator> (util::fixed, typename util::fixed::integer_type); \ +template bool util::operator>= (util::fixed, typename util::fixed::integer_type); template class util::fixed; +INSTANTIATE(signed, 2,14) INSTANTIATE(signed,16,16) INSTANTIATE(signed,26, 6) INSTANTIATE(signed,32,32) diff --git a/fixed.hpp b/fixed.hpp index c38361bf..5f6d7fca 100644 --- a/fixed.hpp +++ b/fixed.hpp @@ -17,69 +17,98 @@ #ifndef __UTIL_FIXED_HPP #define __UTIL_FIXED_HPP -#include "types/bits.hpp" +#include "./types/bits.hpp" +#include "./maths.hpp" +#include "./endian.hpp" #include namespace util { template - class fixed { - public: - typedef typename std::conditional< - std::is_signed::value, - typename bits_type::sint, - typename bits_type::uint - >::type native_t; + class [[gnu::packed]] fixed { + public: + static_assert (I > 0); + static_assert (E > 0); + static_assert ((I + E) % 8 == 0); - typedef native_t integer_t; + using sint_t = typename bits_type::sint; + using uint_t = typename bits_type::uint; - explicit fixed (double); - explicit fixed (float); - explicit fixed (native_t); + using native_type = typename std::conditional< + std::is_signed::value, + sint_t, uint_t + >::type; - double to_double (void) const; - float to_float (void) const; - integer_t to_integer (void) const; - native_t to_native (void) const; + using integer_type = typename std::conditional< + std::is_signed::value, + typename bits_type::sint, + typename bits_type::uint + >::type; - static fixed from_native (native_t); - static integer_t to_integer (native_t); + explicit fixed (double); + explicit fixed (float); - fixed& operator +=(const fixed); - fixed& operator -=(const fixed); - fixed& operator *=(const fixed); - fixed& operator /=(const fixed); + double to_double (void) const; + float to_float (void) const; + integer_type to_integer (void) const; + native_type to_native (void) const; - fixed operator +(const fixed) const; - fixed operator -(const fixed) const; - fixed operator *(const fixed) const; - fixed operator /(const fixed) const; + static fixed from_native (native_type); + static fixed from_integer (integer_type); - fixed& operator +=(integer_t); - fixed& operator -=(integer_t); - fixed& operator *=(integer_t); - fixed& operator /=(integer_t); + static integer_type to_integer (native_type); - fixed operator +(integer_t) const; - fixed operator -(integer_t) const; - fixed operator *(integer_t) const; - fixed operator /(integer_t) const; + fixed& operator +=(const fixed); + fixed& operator -=(const fixed); + fixed& operator *=(const fixed); + fixed& operator /=(const fixed); - private: - fixed () = default; + fixed operator +(const fixed) const; + fixed operator -(const fixed) const; + fixed operator *(const fixed) const; + fixed operator /(const fixed) const; - native_t m_value; + fixed& operator +=(integer_type); + fixed& operator -=(integer_type); + fixed& operator *=(integer_type); + fixed& operator /=(integer_type); + + fixed operator +(integer_type) const; + fixed operator -(integer_type) const; + fixed operator *(integer_type) const; + fixed operator /(integer_type) const; + + private: + fixed () = default; + + native_type m_value; }; + template + constexpr + fixed + bswap (fixed val) + { + return fixed::from_native ( + bswap (val.to_native ()) + ); + } + + template bool operator== (util::fixed, util::fixed); template bool operator!= (util::fixed, util::fixed); - template bool operator< (util::fixed, util::fixed); template bool operator<= (util::fixed, util::fixed); template bool operator> (util::fixed, util::fixed); template bool operator>= (util::fixed, util::fixed); + template bool operator== (util::fixed, typename util::fixed::integer_type); + template bool operator!= (util::fixed, typename util::fixed::integer_type); + template bool operator< (util::fixed, typename util::fixed::integer_type); + template bool operator<= (util::fixed, typename util::fixed::integer_type); + template bool operator> (util::fixed, typename util::fixed::integer_type); + template bool operator>= (util::fixed, typename util::fixed::integer_type); template std::ostream& operator<< (std::ostream&, fixed); diff --git a/test/fixed.cpp b/test/fixed.cpp index 03db9675..249c9609 100644 --- a/test/fixed.cpp +++ b/test/fixed.cpp @@ -3,15 +3,17 @@ #include "tap.hpp" + +/////////////////////////////////////////////////////////////////////////////// template void test_simple (util::TAP::logger &tap) { - using fixed_t = util::fixed; - using integer_t = typename fixed_t::integer_t; + using fixed = util::fixed; + using integer = typename fixed::integer_type; - const fixed_t lo {integer_t{0}}; - const fixed_t hi {integer_t{1}}; + const auto lo = fixed::from_integer (integer {0}); + const auto hi = fixed::from_integer (integer {1}); std::ostringstream os; os << "fixed<" << type_to_string () << ',' << I << ',' << E << '>'; @@ -32,6 +34,7 @@ test_simple (util::TAP::logger &tap) } +/////////////////////////////////////////////////////////////////////////////// int main (void) {