fixed: add integer logical operators
This commit is contained in:
parent
0997bbbaac
commit
b770e5f370
75
fixed.cpp
75
fixed.cpp
@ -22,21 +22,6 @@ using namespace util;
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructors
|
|
||||||
template <typename T, unsigned I, unsigned E>
|
|
||||||
fixed<T,I,E>::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 <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
double
|
double
|
||||||
fixed<T,I,E>::to_double (void) const
|
fixed<T,I,E>::to_double (void) const
|
||||||
@ -56,7 +41,7 @@ fixed<T,I,E>::to_float (void) const
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
typename fixed<T,I,E>::native_t
|
typename fixed<T,I,E>::integer_type
|
||||||
fixed<T,I,E>::to_integer (void) const
|
fixed<T,I,E>::to_integer (void) const
|
||||||
{
|
{
|
||||||
return m_value >> E;
|
return m_value >> E;
|
||||||
@ -65,7 +50,7 @@ fixed<T,I,E>::to_integer (void) const
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
typename fixed<T,I,E>::native_t
|
typename fixed<T,I,E>::native_type
|
||||||
fixed<T,I,E>::to_native (void) const
|
fixed<T,I,E>::to_native (void) const
|
||||||
{
|
{
|
||||||
return m_value;
|
return m_value;
|
||||||
@ -75,7 +60,7 @@ fixed<T,I,E>::to_native (void) const
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
fixed<T,I,E>
|
fixed<T,I,E>
|
||||||
fixed<T,I,E>::from_native (native_t i)
|
fixed<T,I,E>::from_native (native_type i)
|
||||||
{
|
{
|
||||||
fixed<T,I,E> v;
|
fixed<T,I,E> v;
|
||||||
v.m_value = i;
|
v.m_value = i;
|
||||||
@ -85,8 +70,22 @@ fixed<T,I,E>::from_native (native_t i)
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
typename fixed<T,I,E>::native_t
|
fixed<T,I,E>
|
||||||
fixed<T,I,E>::to_integer (native_t n)
|
fixed<T,I,E>::from_integer (integer_type val)
|
||||||
|
{
|
||||||
|
constexpr auto rshift = sizeof (val) * 8 - I;
|
||||||
|
constexpr auto lshift = E - rshift;
|
||||||
|
|
||||||
|
fixed<T,I,E> res;
|
||||||
|
res.m_value = static_cast<native_type> (val) << lshift;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T, unsigned I, unsigned E>
|
||||||
|
typename fixed<T,I,E>::integer_type
|
||||||
|
fixed<T,I,E>::to_integer (native_type n)
|
||||||
{
|
{
|
||||||
return n >> E;
|
return n >> E;
|
||||||
}
|
}
|
||||||
@ -123,13 +122,13 @@ SIMPLE_FIXED_LIT(+)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Integer operators
|
// Integer operators
|
||||||
#define SIMPLE_INTEGER_REF(OP) \
|
#define SIMPLE_INTEGER_REF(OP) \
|
||||||
template <typename T, unsigned I, unsigned E> \
|
template <typename T, unsigned I, unsigned E> \
|
||||||
fixed<T,I,E>& \
|
fixed<T,I,E>& \
|
||||||
fixed<T,I,E>::operator OP (native_t val) \
|
fixed<T,I,E>::operator OP (integer_type val) \
|
||||||
{ \
|
{ \
|
||||||
m_value OP val << E; \
|
m_value OP (static_cast<native_type> (val) << E); \
|
||||||
return *this; \
|
return *this; \
|
||||||
}
|
}
|
||||||
|
|
||||||
SIMPLE_INTEGER_REF(+=)
|
SIMPLE_INTEGER_REF(+=)
|
||||||
@ -139,10 +138,10 @@ SIMPLE_INTEGER_REF(/=)
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define SIMPLE_INTEGER_LIT(OP) \
|
#define SIMPLE_INTEGER_LIT(OP) \
|
||||||
template <typename T, unsigned I, unsigned E> \
|
template <typename T, unsigned I, unsigned E> \
|
||||||
fixed<T,I,E> \
|
fixed<T,I,E> \
|
||||||
fixed<T,I,E>::operator OP (native_t val) const \
|
fixed<T,I,E>::operator OP (integer_type val) const \
|
||||||
{ \
|
{ \
|
||||||
return fixed<T,I,E>::from_native (m_value OP val << E); \
|
return fixed<T,I,E>::from_native (m_value OP val << E); \
|
||||||
}
|
}
|
||||||
@ -163,6 +162,14 @@ util::operator OP (util::fixed<T,I,E> a, \
|
|||||||
util::fixed<T,I,E> b) \
|
util::fixed<T,I,E> b) \
|
||||||
{ \
|
{ \
|
||||||
return a.to_native () OP b.to_native (); \
|
return a.to_native () OP b.to_native (); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <typename T, unsigned I, unsigned E> \
|
||||||
|
bool \
|
||||||
|
util::operator OP (util::fixed<T,I,E> a, \
|
||||||
|
typename util::fixed<T,I,E>::integer_type b) \
|
||||||
|
{ \
|
||||||
|
return a OP util::fixed<T,I,E>::from_integer (b); \
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGIC_OP(==)
|
LOGIC_OP(==)
|
||||||
@ -172,6 +179,7 @@ LOGIC_OP(<=)
|
|||||||
LOGIC_OP(>)
|
LOGIC_OP(>)
|
||||||
LOGIC_OP(>=)
|
LOGIC_OP(>=)
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// iostream operators
|
// iostream operators
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
@ -193,10 +201,17 @@ template bool util::operator!= (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
|||||||
template bool util::operator< (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
template bool util::operator< (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
||||||
template bool util::operator<= (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
template bool util::operator<= (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
||||||
template bool util::operator> (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
template bool util::operator> (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
||||||
template bool util::operator>= (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
template bool util::operator>= (util::fixed<T,I,E>, util::fixed<T,I,E>); \
|
||||||
|
template bool util::operator== (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type); \
|
||||||
|
template bool util::operator!= (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type); \
|
||||||
|
template bool util::operator< (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type); \
|
||||||
|
template bool util::operator<= (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type); \
|
||||||
|
template bool util::operator> (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type); \
|
||||||
|
template bool util::operator>= (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type);
|
||||||
|
|
||||||
template class util::fixed<signed,8,8>;
|
template class util::fixed<signed,8,8>;
|
||||||
|
|
||||||
|
INSTANTIATE(signed, 2,14)
|
||||||
INSTANTIATE(signed,16,16)
|
INSTANTIATE(signed,16,16)
|
||||||
INSTANTIATE(signed,26, 6)
|
INSTANTIATE(signed,26, 6)
|
||||||
INSTANTIATE(signed,32,32)
|
INSTANTIATE(signed,32,32)
|
||||||
|
105
fixed.hpp
105
fixed.hpp
@ -17,69 +17,98 @@
|
|||||||
#ifndef __UTIL_FIXED_HPP
|
#ifndef __UTIL_FIXED_HPP
|
||||||
#define __UTIL_FIXED_HPP
|
#define __UTIL_FIXED_HPP
|
||||||
|
|
||||||
#include "types/bits.hpp"
|
#include "./types/bits.hpp"
|
||||||
|
#include "./maths.hpp"
|
||||||
|
#include "./endian.hpp"
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
class fixed {
|
class [[gnu::packed]] fixed {
|
||||||
public:
|
public:
|
||||||
typedef typename std::conditional<
|
static_assert (I > 0);
|
||||||
std::is_signed<T>::value,
|
static_assert (E > 0);
|
||||||
typename bits_type<I+E>::sint,
|
static_assert ((I + E) % 8 == 0);
|
||||||
typename bits_type<I+E>::uint
|
|
||||||
>::type native_t;
|
|
||||||
|
|
||||||
typedef native_t integer_t;
|
using sint_t = typename bits_type<I+E>::sint;
|
||||||
|
using uint_t = typename bits_type<I+E>::uint;
|
||||||
|
|
||||||
explicit fixed (double);
|
using native_type = typename std::conditional<
|
||||||
explicit fixed (float);
|
std::is_signed<T>::value,
|
||||||
explicit fixed (native_t);
|
sint_t, uint_t
|
||||||
|
>::type;
|
||||||
|
|
||||||
double to_double (void) const;
|
using integer_type = typename std::conditional<
|
||||||
float to_float (void) const;
|
std::is_signed<T>::value,
|
||||||
integer_t to_integer (void) const;
|
typename bits_type<divup (I, 8u) * 8u>::sint,
|
||||||
native_t to_native (void) const;
|
typename bits_type<divup (I, 8u) * 8u>::uint
|
||||||
|
>::type;
|
||||||
|
|
||||||
static fixed<T,I,E> from_native (native_t);
|
explicit fixed (double);
|
||||||
static integer_t to_integer (native_t);
|
explicit fixed (float);
|
||||||
|
|
||||||
fixed<T,I,E>& operator +=(const fixed<T,I,E>);
|
double to_double (void) const;
|
||||||
fixed<T,I,E>& operator -=(const fixed<T,I,E>);
|
float to_float (void) const;
|
||||||
fixed<T,I,E>& operator *=(const fixed<T,I,E>);
|
integer_type to_integer (void) const;
|
||||||
fixed<T,I,E>& operator /=(const fixed<T,I,E>);
|
native_type to_native (void) const;
|
||||||
|
|
||||||
fixed<T,I,E> operator +(const fixed<T,I,E>) const;
|
static fixed<T,I,E> from_native (native_type);
|
||||||
fixed<T,I,E> operator -(const fixed<T,I,E>) const;
|
static fixed<T,I,E> from_integer (integer_type);
|
||||||
fixed<T,I,E> operator *(const fixed<T,I,E>) const;
|
|
||||||
fixed<T,I,E> operator /(const fixed<T,I,E>) const;
|
|
||||||
|
|
||||||
fixed<T,I,E>& operator +=(integer_t);
|
static integer_type to_integer (native_type);
|
||||||
fixed<T,I,E>& operator -=(integer_t);
|
|
||||||
fixed<T,I,E>& operator *=(integer_t);
|
|
||||||
fixed<T,I,E>& operator /=(integer_t);
|
|
||||||
|
|
||||||
fixed<T,I,E> operator +(integer_t) const;
|
fixed<T,I,E>& operator +=(const fixed<T,I,E>);
|
||||||
fixed<T,I,E> operator -(integer_t) const;
|
fixed<T,I,E>& operator -=(const fixed<T,I,E>);
|
||||||
fixed<T,I,E> operator *(integer_t) const;
|
fixed<T,I,E>& operator *=(const fixed<T,I,E>);
|
||||||
fixed<T,I,E> operator /(integer_t) const;
|
fixed<T,I,E>& operator /=(const fixed<T,I,E>);
|
||||||
|
|
||||||
private:
|
fixed<T,I,E> operator +(const fixed<T,I,E>) const;
|
||||||
fixed () = default;
|
fixed<T,I,E> operator -(const fixed<T,I,E>) const;
|
||||||
|
fixed<T,I,E> operator *(const fixed<T,I,E>) const;
|
||||||
|
fixed<T,I,E> operator /(const fixed<T,I,E>) const;
|
||||||
|
|
||||||
native_t m_value;
|
fixed<T,I,E>& operator +=(integer_type);
|
||||||
|
fixed<T,I,E>& operator -=(integer_type);
|
||||||
|
fixed<T,I,E>& operator *=(integer_type);
|
||||||
|
fixed<T,I,E>& operator /=(integer_type);
|
||||||
|
|
||||||
|
fixed<T,I,E> operator +(integer_type) const;
|
||||||
|
fixed<T,I,E> operator -(integer_type) const;
|
||||||
|
fixed<T,I,E> operator *(integer_type) const;
|
||||||
|
fixed<T,I,E> operator /(integer_type) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
fixed () = default;
|
||||||
|
|
||||||
|
native_type m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, unsigned I, unsigned E>
|
||||||
|
constexpr
|
||||||
|
fixed<T,I,E>
|
||||||
|
bswap (fixed<T,I,E> val)
|
||||||
|
{
|
||||||
|
return fixed<T,I,E>::from_native (
|
||||||
|
bswap (val.to_native ())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T, unsigned I, unsigned E> bool operator== (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
template <typename T, unsigned I, unsigned E> bool operator== (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
||||||
template <typename T, unsigned I, unsigned E> bool operator!= (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
template <typename T, unsigned I, unsigned E> bool operator!= (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
||||||
|
|
||||||
template <typename T, unsigned I, unsigned E> bool operator< (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
template <typename T, unsigned I, unsigned E> bool operator< (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
||||||
template <typename T, unsigned I, unsigned E> bool operator<= (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
template <typename T, unsigned I, unsigned E> bool operator<= (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
||||||
template <typename T, unsigned I, unsigned E> bool operator> (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
template <typename T, unsigned I, unsigned E> bool operator> (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
||||||
template <typename T, unsigned I, unsigned E> bool operator>= (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
template <typename T, unsigned I, unsigned E> bool operator>= (util::fixed<T,I,E>, util::fixed<T,I,E>);
|
||||||
|
|
||||||
|
template <typename T, unsigned I, unsigned E> bool operator== (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type);
|
||||||
|
template <typename T, unsigned I, unsigned E> bool operator!= (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type);
|
||||||
|
template <typename T, unsigned I, unsigned E> bool operator< (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type);
|
||||||
|
template <typename T, unsigned I, unsigned E> bool operator<= (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type);
|
||||||
|
template <typename T, unsigned I, unsigned E> bool operator> (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type);
|
||||||
|
template <typename T, unsigned I, unsigned E> bool operator>= (util::fixed<T,I,E>, typename util::fixed<T,I,E>::integer_type);
|
||||||
|
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
std::ostream& operator<< (std::ostream&, fixed<T,I,E>);
|
std::ostream& operator<< (std::ostream&, fixed<T,I,E>);
|
||||||
|
@ -3,15 +3,17 @@
|
|||||||
|
|
||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
void
|
void
|
||||||
test_simple (util::TAP::logger &tap)
|
test_simple (util::TAP::logger &tap)
|
||||||
{
|
{
|
||||||
using fixed_t = util::fixed<T,I,E>;
|
using fixed = util::fixed<T,I,E>;
|
||||||
using integer_t = typename fixed_t::integer_t;
|
using integer = typename fixed::integer_type;
|
||||||
|
|
||||||
const fixed_t lo {integer_t{0}};
|
const auto lo = fixed::from_integer (integer {0});
|
||||||
const fixed_t hi {integer_t{1}};
|
const auto hi = fixed::from_integer (integer {1});
|
||||||
|
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "fixed<" << type_to_string<T> () << ',' << I << ',' << E << '>';
|
os << "fixed<" << type_to_string<T> () << ',' << I << ',' << E << '>';
|
||||||
@ -32,6 +34,7 @@ test_simple (util::TAP::logger &tap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
int
|
int
|
||||||
main (void)
|
main (void)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user