diff --git a/include/etl/experimental/bit_cast.h b/include/etl/experimental/bit_cast.h index 0add8d5e..7c38b875 100644 --- a/include/etl/experimental/bit_cast.h +++ b/include/etl/experimental/bit_cast.h @@ -1,20 +1,34 @@ #pragma once -template -etl::enable_if_t && etl::is_trivially_copyable_v, To> -//ETL_CONSTEXPR -bit_cast(const From& src) ETL_NOEXCEPT +#include "platform.h" + +template +ETL_CONSTEXPR +typename etl::enable_if<(sizeof(TDestination) == sizeof(TSource)) && + etl::is_trivially_copyable::value && + etl::is_trivially_copyable::value, TDestination>::type + bit_cast(const TSource& source) ETL_NOEXCEPT { - To dst; - memcpy(&dst, &src, sizeof(To)); + TDestination destination; - // __builtin_memcpy(&dst, &src, sizeof(To)); + memcpy(&destination, &source, sizeof(TDestination)); - return dst; + return destination; } -std::midpoint -// https://en.cppreference.com/w/cpp/numeric/midpoint +template +ETL_CONSTEXPR +typename etl::enable_if<(sizeof(TDestination) == sizeof(TSource)) && + etl::is_trivially_copyable::value && + etl::is_trivially_copyable::value, TDestination>::type + bit_cast(const TSource& source) ETL_NOEXCEPT +{ + TDestination destination; + + __builtin_memcpy(&destination, &source, sizeof(TDestination)); + + return destination; +} + + -std::lerp -// https://en.cppreference.com/w/cpp/numeric/lerp \ No newline at end of file diff --git a/include/etl/numeric.h b/include/etl/numeric.h index e30475bd..fde0876f 100644 --- a/include/etl/numeric.h +++ b/include/etl/numeric.h @@ -32,6 +32,7 @@ SOFTWARE. #define ETL_NUMERIC_INCLUDED #include "platform.h" +#include "type_traits.h" ///\defgroup numeric numeric ///\ingroup utilities @@ -54,7 +55,94 @@ namespace etl *first++ = value++; } } + + //*************************************************************************** + /// + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, T>::type + midpoint(T a, T b) ETL_NOEXCEPT + { + T lo = etl::numeric_limits::min() * T(2); + T hi = etl::numeric_limits::max() * T(2); + + return ((abs(a) <= hi) && (abs(b) <= hi)) ? + (a + b) / T(2) : + (abs(a) < lo) ? + a + (b / T(2)) : + (abs(b) < lo) ? + (a / T(2)) + b) : + (a / T(2)) + (b / T(2)); + } + + //*************************************************************************** + /// + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, T>::type + midpoint(T a, T b) ETL_NOEXCEPT + { + typedef typename etl::make_unsigned::type type; + + int sign; + type lo; + type hi; + + if (a > b) + { + sign = -1; + lo = type(b); + hi = type(a); + } + else + { + sign = 1; + lo = type(a); + hi = type(b); + } + + return a + sign * T(type(M - m) >> 1); + } + + //*************************************************************************** + /// + //*************************************************************************** + template + ETL_CONSTEXPR typename etl::enable_if::value, T>::type + midpoint(T a, T b) + { + return a + midpoint(ptrdiff_t{ 0 }, b - a); + } + + //*************************************************************************** + /// Linear interpolation + /// For floating point. + //*************************************************************************** + template + ETL_CONSTEXPR typename etl::enable_if::value, T>::type + lerp(T a, T b, T t) ETL_NOEXCEPT + { + return a + (t * (b ? a)); + } + + //*************************************************************************** + /// Linear interpolation + /// For when any parameter is not floating point. + //*************************************************************************** + template + ETL_CONSTEXPR typename etl::enable_if_t::value || + !etl::is_floating_point::value || + !etl::is_floating_point::value, typename etl::conditional::value || + etl::is_same::value || + etl::is_same::value, long double, double>::type> + lerp(TArithmetic1 a, TArithmetic2 b, TArithmetic3 t) ETL_NOEXCEPT + { + typename etl::conditional::value, double, TArithmetic1>::type typecast_a; + typename etl::conditional::value, double, TArithmetic2>::type typecast_b; + typename etl::conditional::value, double, TArithmetic3>::type typecast_t; + + return typecast_a(a) + (typecast_t(t) * (typecast_b(b) ? typecast_a(a)); + } } #endif -