diff --git a/libuavcan/include/uavcan/dynamic_memory.hpp b/libuavcan/include/uavcan/dynamic_memory.hpp index 927b8f392a..ff0ef2af14 100644 --- a/libuavcan/include/uavcan/dynamic_memory.hpp +++ b/libuavcan/include/uavcan/dynamic_memory.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -41,8 +40,8 @@ class UAVCAN_EXPORT PoolManager : public IPoolAllocator, Noncopyable { const IPoolAllocator* const a = *static_cast(raw_a); const IPoolAllocator* const b = *static_cast(raw_b); - const std::size_t a_size = a ? a->getBlockSize() : std::numeric_limits::max(); - const std::size_t b_size = b ? b->getBlockSize() : std::numeric_limits::max(); + const std::size_t a_size = a ? a->getBlockSize() : NumericTraits::max(); + const std::size_t b_size = b ? b->getBlockSize() : NumericTraits::max(); if (a_size != b_size) { return (a_size > b_size) ? 1 : -1; diff --git a/libuavcan/include/uavcan/marshal/float_spec.hpp b/libuavcan/include/uavcan/marshal/float_spec.hpp index 7c110f896f..ece754b39a 100644 --- a/libuavcan/include/uavcan/marshal/float_spec.hpp +++ b/libuavcan/include/uavcan/marshal/float_spec.hpp @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include @@ -18,6 +17,8 @@ #endif #if UAVCAN_CPP_VERSION < UAVCAN_CPP11 # include // Needed for isfinite() +#else +# include // Assuming that in C++11 mode all standard headers are available #endif namespace uavcan @@ -43,8 +44,10 @@ class UAVCAN_EXPORT IEEE754Converter IEEE754Converter(); public: +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 /// UAVCAN requires rounding to nearest for all float conversions static std::float_round_style roundstyle() { return std::round_to_nearest; } +#endif template static typename IntegerSpec::StorageType @@ -118,11 +121,17 @@ public: typedef typename NativeFloatSelector::Type StorageType; +#if UAVCAN_CPP_VERSION < UAVCAN_CPP11 + enum { IsExactRepresentation = (sizeof(StorageType) * 8 == BitLen) }; +#else enum { IsExactRepresentation = (sizeof(StorageType) * 8 == BitLen) && std::numeric_limits::is_iec559 }; +#endif using IEEE754Limits::max; using IEEE754Limits::epsilon; +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 static std::float_round_style roundstyle() { return IEEE754Converter::roundstyle(); } +#endif static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode) { @@ -180,11 +189,11 @@ private: { if (value > max()) { - value = std::numeric_limits::infinity(); + value = NumericTraits::infinity(); } else if (value < -max()) { - value = -std::numeric_limits::infinity(); + value = -NumericTraits::infinity(); } else { diff --git a/libuavcan/include/uavcan/marshal/integer_spec.hpp b/libuavcan/include/uavcan/marshal/integer_spec.hpp index a0a6e298e1..ab6ea98028 100644 --- a/libuavcan/include/uavcan/marshal/integer_spec.hpp +++ b/libuavcan/include/uavcan/marshal/integer_spec.hpp @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include @@ -93,9 +92,9 @@ private: { StaticAssert<(BitLen <= (sizeof(StorageType) * 8))>::check(); // coverity[result_independent_of_operands : FALSE] - assert(max() <= std::numeric_limits::max()); + assert(max() <= NumericTraits::max()); // coverity[result_independent_of_operands : FALSE] - assert(min() >= std::numeric_limits::min()); + assert(min() >= NumericTraits::min()); } public: diff --git a/libuavcan/include/uavcan/marshal/scalar_codec.hpp b/libuavcan/include/uavcan/marshal/scalar_codec.hpp index 2b7bceb0eb..be0aa373ba 100644 --- a/libuavcan/include/uavcan/marshal/scalar_codec.hpp +++ b/libuavcan/include/uavcan/marshal/scalar_codec.hpp @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include #include @@ -47,10 +46,10 @@ class UAVCAN_EXPORT ScalarCodec convertByteOrder(uint8_t (&)[Size]) { } template - static typename EnableIf::is_signed && ((sizeof(T) * 8) > BitLen)>::Type + static typename EnableIf(NumericTraits::IsSigned) && ((sizeof(T) * 8) > BitLen)>::Type fixTwosComplement(T& value) { - StaticAssert::is_integer>::check(); // Not applicable to floating point types + StaticAssert::IsInteger>::check(); // Not applicable to floating point types if (value & (T(1) << (BitLen - 1))) // The most significant bit is set --> negative { value |= 0xFFFFFFFFFFFFFFFF & ~((T(1) << BitLen) - 1); @@ -58,7 +57,7 @@ class UAVCAN_EXPORT ScalarCodec } template - static typename EnableIf::is_signed || ((sizeof(T) * 8) == BitLen)>::Type + static typename EnableIf(NumericTraits::IsSigned) || ((sizeof(T) * 8) == BitLen)>::Type fixTwosComplement(T&) { } template @@ -77,7 +76,7 @@ class UAVCAN_EXPORT ScalarCodec { StaticAssert<((sizeof(T) * 8) >= BitLen)>::check(); StaticAssert<(BitLen <= BitStream::MaxBitsPerRW)>::check(); - StaticAssert::is_signed ? (BitLen > 1) : 1>::check(); + StaticAssert(NumericTraits::IsSigned) ? (BitLen > 1) : true>::check(); } int encodeBytesImpl(uint8_t* bytes, unsigned bitlen); diff --git a/libuavcan/include/uavcan/time.hpp b/libuavcan/include/uavcan/time.hpp index 68c7b51286..3f25f3448e 100644 --- a/libuavcan/include/uavcan/time.hpp +++ b/libuavcan/include/uavcan/time.hpp @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include @@ -29,7 +28,7 @@ protected: } public: - static D getInfinite() { return fromUSec(std::numeric_limits::max()); } + static D getInfinite() { return fromUSec(NumericTraits::max()); } static D fromUSec(int64_t us) { @@ -106,7 +105,7 @@ protected: } public: - static T getMax() { return fromUSec(std::numeric_limits::max()); } + static T getMax() { return fromUSec(NumericTraits::max()); } static T fromUSec(uint64_t us) { @@ -142,7 +141,7 @@ public: { if (uint64_t(usec_ + r.toUSec()) < usec_) { - return fromUSec(std::numeric_limits::max()); + return fromUSec(NumericTraits::max()); } } return fromUSec(usec_ + r.toUSec()); diff --git a/libuavcan/include/uavcan/transport/transfer_buffer.hpp b/libuavcan/include/uavcan/transport/transfer_buffer.hpp index 7969338b82..db61104422 100644 --- a/libuavcan/include/uavcan/transport/transfer_buffer.hpp +++ b/libuavcan/include/uavcan/transport/transfer_buffer.hpp @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include diff --git a/libuavcan/include/uavcan/util/templates.hpp b/libuavcan/include/uavcan/util/templates.hpp index 438f426be3..eaf9aa354b 100644 --- a/libuavcan/include/uavcan/util/templates.hpp +++ b/libuavcan/include/uavcan/util/templates.hpp @@ -4,7 +4,19 @@ #pragma once +#include +#include #include +#include + +#ifndef UAVCAN_CPP_VERSION +# error UAVCAN_CPP_VERSION +#endif +#if UAVCAN_CPP_VERSION < UAVCAN_CPP11 +# include // cfloat may not be available +#else +# include // C++11 mode assumes that all standard headers are available +#endif namespace uavcan { @@ -241,4 +253,115 @@ bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) return true; } +/** + * Numeric traits, like std::numeric_limits<> + */ +template +struct UAVCAN_EXPORT NumericTraits; + +/// 8 bit +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 1 }; + enum { IsInteger = 1 }; + static int8_t max() { return 127; } + static int8_t min() { return -max() - 1; } +}; +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 0 }; + enum { IsInteger = 1 }; + static uint8_t max() { return 0xFFU; } + static uint8_t min() { return 0; } +}; + +/// 16 bit +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 1 }; + enum { IsInteger = 1 }; + static int16_t max() { return 32767; } + static int16_t min() { return -max() - 1; } +}; +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 0 }; + enum { IsInteger = 1 }; + static uint16_t max() { return 0xFFFFU; } + static uint16_t min() { return 0; } +}; + +/// 32 bit +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 1 }; + enum { IsInteger = 1 }; + static int32_t max() { return 2147483647L; } + static int32_t min() { return -max() - 1; } +}; +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 0 }; + enum { IsInteger = 1 }; + static uint32_t max() { return 0xFFFFFFFFUL; } + static uint32_t min() { return 0UL; } +}; + +/// 64 bit +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 1 }; + enum { IsInteger = 1 }; + static int64_t max() { return 9223372036854775807LL; } + static int64_t min() { return -max() - 1; } +}; +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 0 }; + enum { IsInteger = 1 }; + static uint64_t max() { return 0xFFFFFFFFFFFFFFFFULL; } + static uint64_t min() { return 0; } +}; + +/// float +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 1 }; + enum { IsInteger = 0 }; + static float max() { return FLT_MAX; } + static float min() { return FLT_MIN; } + static float infinity() { return INFINITY; } +}; + +/// double +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 1 }; + enum { IsInteger = 0 }; + static double max() { return DBL_MAX; } + static double min() { return DBL_MIN; } + static double infinity() { return static_cast(INFINITY) * static_cast(INFINITY); } +}; + +/// long double +template <> +struct UAVCAN_EXPORT NumericTraits +{ + enum { IsSigned = 1 }; + enum { IsInteger = 0 }; + static long double max() { return LDBL_MAX; } + static long double min() { return LDBL_MIN; } + static long double infinity() { return static_cast(INFINITY) * static_cast(INFINITY); } +}; + } diff --git a/libuavcan/src/marshal/uc_float_spec.cpp b/libuavcan/src/marshal/uc_float_spec.cpp index bc2a6921e5..644dd16f4f 100644 --- a/libuavcan/src/marshal/uc_float_spec.cpp +++ b/libuavcan/src/marshal/uc_float_spec.cpp @@ -10,6 +10,10 @@ # error UAVCAN_CPP_VERSION #endif +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 +# include +#endif + #undef signbit #undef isnan #undef isinf @@ -47,7 +51,7 @@ static inline bool isinf(T arg) #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 return std::isinf(arg); #else - return arg == std::numeric_limits::infinity() || arg == -std::numeric_limits::infinity(); + return arg == NumericTraits::infinity() || arg == -NumericTraits::infinity(); #endif } @@ -94,12 +98,20 @@ float IEEE754Converter::halfToNativeNonIeee(uint16_t value) unsigned abs = value & 0x7FFFU; if (abs > 0x7C00U) { +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 out = std::numeric_limits::has_quiet_NaN ? std::numeric_limits::quiet_NaN() : 0.0F; +#else + out = nanf(""); +#endif } else if (abs == 0x7C00U) { +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 out = std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : std::numeric_limits::max(); +#else + out = NumericTraits::infinity(); +#endif } else if (abs > 0x3FFU) { diff --git a/libuavcan/src/transport/uc_can_io.cpp b/libuavcan/src/transport/uc_can_io.cpp index 4df84247d2..e3cc4570cd 100644 --- a/libuavcan/src/transport/uc_can_io.cpp +++ b/libuavcan/src/transport/uc_can_io.cpp @@ -6,7 +6,6 @@ #include #include #include -#include namespace uavcan { @@ -100,7 +99,7 @@ CanTxQueue::~CanTxQueue() void CanTxQueue::registerRejectedFrame() { - if (rejected_frames_cnt_ < std::numeric_limits::max()) + if (rejected_frames_cnt_ < NumericTraits::max()) { rejected_frames_cnt_++; } diff --git a/libuavcan/test/marshal/float_spec.cpp b/libuavcan/test/marshal/float_spec.cpp index a6991c3afc..37dcd74f6a 100644 --- a/libuavcan/test/marshal/float_spec.cpp +++ b/libuavcan/test/marshal/float_spec.cpp @@ -3,6 +3,7 @@ */ #include +#include #include #include diff --git a/libuavcan/test/marshal/scalar_codec.cpp b/libuavcan/test/marshal/scalar_codec.cpp index 1525ce5281..ee816fdea4 100644 --- a/libuavcan/test/marshal/scalar_codec.cpp +++ b/libuavcan/test/marshal/scalar_codec.cpp @@ -3,6 +3,7 @@ */ #include +#include #include #include