You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
FixedPointsArduino/src/FixedPoints/Details.h

219 lines
5.9 KiB

#pragma once
#include <limits.h>
#include <stdint.h>
#if defined(FIXED_POINTS_USE_NAMESPACE)
#define FIXED_POINTS_NAMESPACE FixedPoints
#define FIXED_POINTS_BEGIN_NAMESPACE namespace FIXED_POINTS_NAMESPACE\
{
#define FIXED_POINTS_END_NAMESPACE }
#define FIXED_POINTS_DETAILS Details
#else
#define FIXED_POINTS_NAMESPACE
#define FIXED_POINTS_BEGIN_NAMESPACE
#define FIXED_POINTS_END_NAMESPACE
#define FIXED_POINTS_DETAILS FixedPointsDetails
#endif
// Pay no attention to the man behind the curtains
FIXED_POINTS_BEGIN_NAMESPACE
namespace FIXED_POINTS_DETAILS
{
template< typename T >
struct BitSize
{
BitSize(void) = delete;
constexpr static const auto Value = sizeof(T) * CHAR_BIT;
};
template< typename T, typename U = T >
constexpr auto Max(const T & left, const U & right) noexcept -> decltype((left > right) ? left : right)
{
return (left > right) ? left : right;
}
template< typename T, T Left, T Right >
constexpr auto Max(void) noexcept -> decltype((Left > Right) ? Left : Right)
{
return (Left > Right) ? Left : Right;
}
template< typename T, typename U = T >
constexpr auto Min(const T & left, const U & right) noexcept -> decltype((left < right) ? left : right)
{
return (left < right) ? left : right;
}
template< typename T, T Left, T Right >
constexpr auto Min(void) noexcept -> decltype((Left < Right) ? Left : Right)
{
return (Left < Right) ? Left : Right;
}
template< bool Condition, typename TTrue, typename TFalse >
struct Conditional;
template< typename TTrue, typename TFalse >
struct Conditional< true, TTrue, TFalse > { using Type = TTrue; };
template< typename TTrue, typename TFalse >
struct Conditional< false, TTrue, TFalse > { using Type = TFalse; };
template< bool Condition, typename TTrue, typename TFalse >
using ConditionalT = typename Conditional<Condition, TTrue, TFalse >::Type;
template< typename T, typename U >
using LargerType = ConditionalT<(BitSize<T>::Value > BitSize<U>::Value), T, U>;
template< typename T, typename U >
using StrictLargerType = ConditionalT< (BitSize<T>::Value > BitSize<U>::Value), T, ConditionalT< (BitSize<U>::Value > BitSize<T>::Value), U, void > >;
template< typename T, typename U >
using SmallerType = ConditionalT<(BitSize<T>::Value < BitSize<U>::Value), T, U>;
template< typename T, typename U >
using StrictSmallerType = ConditionalT< (BitSize<T>::Value < BitSize<U>::Value), T, ConditionalT< (BitSize<U>::Value < BitSize<T>::Value), U, void > >;
template< unsigned Bits, typename... Ts >
struct LeastTypeHelper;
template< unsigned Bits, typename T, typename... Ts >
struct LeastTypeHelper<Bits, T, Ts... >
{
LeastTypeHelper(void) = delete;
using Type = ConditionalT<(Bits <= BitSize<T>::Value), T, typename LeastTypeHelper<Bits, Ts...>::Type>;
};
template< unsigned Bits >
struct LeastTypeHelper<Bits>
{
LeastTypeHelper(void) = delete;
using Type = void;
};
template< unsigned Bits, typename... Ts >
using LeastType = typename LeastTypeHelper<Bits, Ts...>::Type;
template< unsigned Bits >
struct LeastUIntDef
{
static_assert(Bits <= BitSize<uintmax_t>::Value, "No type large enough");
LeastUIntDef(void) = delete;
using Type = LeastType<Bits, uint_least8_t, uint_least16_t, uint_least32_t, uint_least64_t, uintmax_t>;
};
template< unsigned Bits >
using LeastUInt = typename LeastUIntDef<Bits>::Type;
template< unsigned Bits >
struct LeastIntDef
{
static_assert(Bits <= BitSize<intmax_t>::Value, "No type large enough");
LeastIntDef(void) = delete;
using Type = LeastType<Bits, int_least8_t, int_least16_t, int_least32_t, int_least64_t, intmax_t>;
};
template< unsigned Bits >
using LeastInt = typename LeastIntDef<Bits>::Type;
template< unsigned Bits >
struct MsbMask
{
MsbMask(void) = delete;
constexpr const static LeastUInt<Bits> Value = (1ull << (Bits - 1));
};
template< unsigned Bits >
struct IdentityMask
{
IdentityMask(void) = delete;
constexpr const static LeastUInt<Bits> Value = 1 | (IdentityMask<Bits - 1>::Value << 1);
};
template<>
struct IdentityMask<0>
{
IdentityMask(void) = delete;
constexpr const static LeastUInt<0> Value = 0;
};
using IntegerLiteral = decltype(0);
using IntegerLiteralU = decltype(0U);
using IntegerLiteralL = decltype(0L);
using IntegerLiteralUL = decltype(0UL);
using IntegerLiteralLL = decltype(0LL);
using IntegerLiteralULL = decltype(0ULL);
using DecimalLiteral = decltype(0.0);
using DecimalLiteralF = decltype(0.0F);
using DecimalLiteralL = decltype(0.0L);
template< typename T >
struct RandomHelper;
template<>
struct RandomHelper<uint8_t>
{
static inline uint8_t Random() { return static_cast<uint8_t>(random()); }
};
template<>
struct RandomHelper<uint16_t>
{
static inline uint16_t Random() { return static_cast<uint16_t>(random()); }
};
template<>
struct RandomHelper<uint32_t>
{
static inline uint32_t Random() { return static_cast<uint32_t>(random()); }
};
template<>
struct RandomHelper<uint64_t>
{
static inline uint64_t Random() { return (static_cast<uint64_t>(random()) << 32) | static_cast<uint64_t>(random()); }
};
template<>
struct RandomHelper<int8_t>
{
static inline int8_t Random() { return static_cast<int8_t>(random()); }
};
template<>
struct RandomHelper<int16_t>
{
static inline int16_t Random() { return static_cast<int16_t>(random()); }
};
template<>
struct RandomHelper<int32_t>
{
static inline int32_t Random() { return static_cast<int32_t>(random()); }
};
template<>
struct RandomHelper<int64_t>
{
static inline int64_t Random() { return (static_cast<int64_t>(random()) << 32) | static_cast<int64_t>(random()); }
};
// Here be dragons!!
//
//
//
// /\___/\ ~
// ( O . O ) \\
// > ^ < //
// ( \ / )//
// u U U u
//
// Or cats?
// ~Mwrow~
}
FIXED_POINTS_END_NAMESPACE