mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Make non STL builds independent of STL headers (#1621)
Fix etl::chrono floor/ceil/round/abs being declared in the wrong namespace The duration overloads of floor, ceil, round and abs were defined in namespace etl rather than etl::chrono, so qualified calls such as etl::chrono::floor<seconds>(ms) only found the time_point overload and failed to compile. Moved them into namespace chrono next to duration_cast and removed the old etl-scope definitions, which also fixes the unqualified calls made from time_point.h. Fix comment about rounding behavior Use cmath functions from std namespace GCC 16 doesn't support them in the global namespace anymore.
This commit is contained in:
parent
4903570496
commit
ebd9a7026f
@ -191,7 +191,7 @@ ETL_NOEXCEPT
|
||||
```
|
||||
**Description**
|
||||
Rounds a duration to the nearest precision.
|
||||
If the duration is exactly halfway, it rounds away from zero.
|
||||
If the duration is exactly halfway, it rounds to even.
|
||||
|
||||
## Casting
|
||||
```cpp
|
||||
|
||||
@ -64,6 +64,7 @@ These may be defined in the project settings or the user created `etl_profile.h`
|
||||
| `ETL_MESSAGES_ARE_VIRTUAL` | `ETL_MESSAGES_ARE_VIRTUAL` is deprecated and may be removed.<br/>Only valid before 19.4.1<br/>Messages are virtual, by default, from 19.4.1|
|
||||
| `ETL_USE_TYPE_TRAITS_BUILTINS` | Forces the ETL to use calls compiler built-ins.<br/>Sets all of them to be 1 if not already defined.<br/>If not defined `ETL_USE_BUILTIN_IS_ASSIGNABLE` then<br/>`ETL_USE_BUILTIN_IS_ASSIGNABLE = 1`<br/><br/>If not defined ETL_USE_BUILTIN_IS_CONSTRUCTIBLE then<br/>`ETL_USE_BUILTIN_IS_CONSTRUCTIBLE = 1`<br/><br/>If not `ETL_USE_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE` then<br/>`ETL_USE_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE = 1`<br/><br/>If not defined `ETL_USE_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE` then<br/>`ETL_USE_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE = 1`<br/><br/>If not defined `ETL_USE_BUILTIN_IS_TRIVIALLY_COPYABLE` then<br/>`ETL_USE_BUILTIN_IS_TRIVIALLY_COPYABLE = 1`<br/><br/>`ETL_TARGET_DEVICE_GENERIC`<br/>Only `ETL_TARGET_DEVICE_ARM_CORTEX_M0` and `ETL_TARGET_DEVICE_ARM` and `ETL_TARGET_DEVICE_ARM_CORTEX_M0_PLUS` are currently used in the ETL code to disable `etl::atomic`.|
|
||||
| `ETL_NO_LIBC_WCHAR_H` | Define if the libc++ used has not been compiled for `wchar_t` support.|
|
||||
| `ETL_FORCE_INCLUDE_MATH_H` | When `ETL_NO_STL` is defined and the compiler is GCC or clang, the ETL does not include `<math.h>`, but uses the equivalent compiler built-ins instead (GCC's `<math.h>` may drag in large parts of the C++ standard library).<br/>Define this to always include the environment's `<math.h>` instead.|
|
||||
|
||||
## ETL defined
|
||||
**Defined in platform.h**
|
||||
|
||||
@ -33,9 +33,9 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "functional.h"
|
||||
#include "math.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
@ -254,12 +254,12 @@ namespace etl
|
||||
|
||||
if (variance1 > 0)
|
||||
{
|
||||
stddev1 = sqrt(variance1);
|
||||
stddev1 = etl::private_math::sqrt(variance1);
|
||||
}
|
||||
|
||||
if (variance2 > 0)
|
||||
{
|
||||
stddev2 = sqrt(variance2);
|
||||
stddev2 = etl::private_math::sqrt(variance2);
|
||||
}
|
||||
|
||||
covariance_value = ((n * inner_product) - (sum1 * sum2)) * adjustment;
|
||||
|
||||
@ -1753,7 +1753,7 @@ namespace etl
|
||||
const size_t fractional_decimals = 6; // default
|
||||
|
||||
// Detect sign using signbit to correctly handle -0.0
|
||||
bool sign = signbit(value);
|
||||
bool sign = etl::private_math::sign_bit(value);
|
||||
T abs_value = sign ? -value : value;
|
||||
|
||||
// Use scientific notation for values that would overflow unsigned long long
|
||||
@ -1801,7 +1801,7 @@ namespace etl
|
||||
long long int exponent_int = 0;
|
||||
|
||||
// Detect sign using signbit to correctly handle -0.0
|
||||
bool sign = signbit(value);
|
||||
bool sign = etl::private_math::sign_bit(value);
|
||||
|
||||
T integral;
|
||||
T fractional = etl::math::modf(value, &integral);
|
||||
@ -1866,7 +1866,7 @@ namespace etl
|
||||
long long int exponent_int = 0;
|
||||
|
||||
// Detect sign using signbit to correctly handle -0.0
|
||||
bool sign = signbit(value);
|
||||
bool sign = etl::private_math::sign_bit(value);
|
||||
|
||||
T abs_value = sign ? -value : value;
|
||||
|
||||
@ -1930,7 +1930,7 @@ namespace etl
|
||||
const size_t fractional_decimals = 6; // default
|
||||
|
||||
// Detect sign using signbit to correctly handle -0.0
|
||||
bool sign = signbit(value);
|
||||
bool sign = etl::private_math::sign_bit(value);
|
||||
|
||||
T integral;
|
||||
T fractional = etl::math::modf(value, &integral);
|
||||
@ -2110,7 +2110,7 @@ namespace etl
|
||||
template <typename OutputIt, typename T>
|
||||
void format_floating(OutputIt& it, T value, const format_spec_t& spec)
|
||||
{
|
||||
if (isnan(value))
|
||||
if (etl::is_nan(value))
|
||||
{
|
||||
if (spec.type.has_value() && (is_uppercase(spec.type.value())))
|
||||
{
|
||||
@ -2121,7 +2121,7 @@ namespace etl
|
||||
format_sequence(it, "nan");
|
||||
}
|
||||
}
|
||||
else if (isinf(value))
|
||||
else if (etl::is_infinity(value))
|
||||
{
|
||||
if (spec.type.has_value() && (is_uppercase(spec.type.value())))
|
||||
{
|
||||
@ -2375,7 +2375,7 @@ namespace etl
|
||||
if (fmt_ctx.format_spec.zero && fmt_ctx.format_spec.align == spec_align_t::NONE)
|
||||
{
|
||||
// Output sign first, then zero-fill, then the unsigned part
|
||||
bool sign = signbit(arg);
|
||||
bool sign = etl::private_math::sign_bit(arg);
|
||||
if (sign || fmt_ctx.format_spec.sign != spec_sign_t::MINUS)
|
||||
{
|
||||
// Output the sign character
|
||||
|
||||
@ -33,10 +33,9 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "functional.h"
|
||||
#include "math.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
@ -64,7 +63,7 @@ namespace etl
|
||||
{
|
||||
// Calculate intermediate result because rounding + optimization
|
||||
// lead to wrong values when returning directly (test on i386)
|
||||
const double result = maximum * pow(double(value) / maximum, one_over_gamma);
|
||||
const double result = maximum * etl::math::pow(double(value) / maximum, one_over_gamma);
|
||||
|
||||
return TInput(result);
|
||||
}
|
||||
@ -100,7 +99,7 @@ namespace etl
|
||||
{
|
||||
// Calculate intermediate result because rounding + optimization
|
||||
// lead to wrong values when returning directly (test on i386)
|
||||
const double result = maximum * pow(double(value) / maximum, gamma);
|
||||
const double result = maximum * etl::math::pow(double(value) / maximum, gamma);
|
||||
return TInput(result);
|
||||
}
|
||||
|
||||
|
||||
@ -40,9 +40,23 @@ SOFTWARE.
|
||||
#define __USE_C99_MATH
|
||||
#endif
|
||||
|
||||
// GCC and clang supply the floating point infinity and NaN values as compiler builtins, so
|
||||
// <math.h> is not required at all.
|
||||
// This matters for ETL_NO_STL builds: libstdc++'s <math.h> (GCC 16) includes <cmath>, which in
|
||||
// turn drags in large parts of the standard library (<string> etc.), defeating the point of a
|
||||
// no-STL build. clang picks up the same <math.h> when using libstdc++.
|
||||
// Define ETL_FORCE_INCLUDE_MATH_H to opt out and use the environment's <math.h>.
|
||||
#if ETL_NOT_USING_STL && (defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_CLANG)) && !defined(ETL_FORCE_INCLUDE_MATH_H)
|
||||
#define ETL_LIMITS_USING_BUILTIN_FLOAT_VALUES 1
|
||||
#else
|
||||
#define ETL_LIMITS_USING_BUILTIN_FLOAT_VALUES 0
|
||||
#endif
|
||||
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#if !ETL_LIMITS_USING_BUILTIN_FLOAT_VALUES
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
|
||||
@ -68,6 +82,13 @@ SOFTWARE.
|
||||
#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
|
||||
#endif
|
||||
|
||||
#if ETL_LIMITS_USING_BUILTIN_FLOAT_VALUES
|
||||
// <math.h> was not included, so use the compiler builtins directly.
|
||||
// HUGE_VAL etc. are deliberately not defined, as they would clash with a <math.h> included later.
|
||||
#define ETL_HUGE_VALF (__builtin_huge_valf())
|
||||
#define ETL_HUGE_VAL (__builtin_huge_val())
|
||||
#define ETL_HUGE_VALL (__builtin_huge_vall())
|
||||
#else
|
||||
#if !defined(HUGE_VAL)
|
||||
// Looks like we don't have these macros defined.
|
||||
// They're compiler implementation dependent, so we'll make them the same as
|
||||
@ -77,7 +98,18 @@ SOFTWARE.
|
||||
#define HUGE_VALL LDBL_MAX
|
||||
#endif
|
||||
|
||||
#if defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
#define ETL_HUGE_VALF HUGE_VALF
|
||||
#define ETL_HUGE_VAL HUGE_VAL
|
||||
#define ETL_HUGE_VALL HUGE_VALL
|
||||
#endif
|
||||
|
||||
#if ETL_LIMITS_USING_BUILTIN_FLOAT_VALUES
|
||||
// The builtins need no library support, so ETL_NO_CPP_NAN_SUPPORT is irrelevant here.
|
||||
#define ETL_NANF __builtin_nanf("")
|
||||
#define ETL_NAN __builtin_nan("")
|
||||
#define ETL_NANL __builtin_nanl("")
|
||||
#define ETL_HAS_NAN true
|
||||
#elif defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
#if defined(NAN)
|
||||
#include "private/diagnostic_useless_cast_push.h"
|
||||
#define ETL_NANF NAN
|
||||
@ -87,9 +119,9 @@ SOFTWARE.
|
||||
#include "private/diagnostic_pop.h"
|
||||
#else
|
||||
#include "private/diagnostic_useless_cast_push.h"
|
||||
#define ETL_NANF HUGE_VALF
|
||||
#define ETL_NAN HUGE_VAL
|
||||
#define ETL_NANL HUGE_VALL
|
||||
#define ETL_NANF ETL_HUGE_VALF
|
||||
#define ETL_NAN ETL_HUGE_VAL
|
||||
#define ETL_NANL ETL_HUGE_VALL
|
||||
#define ETL_HAS_NAN false
|
||||
#include "private/diagnostic_pop.h"
|
||||
#endif
|
||||
@ -1570,7 +1602,7 @@ namespace etl
|
||||
}
|
||||
static ETL_CONSTEXPR float infinity()
|
||||
{
|
||||
return HUGE_VALF;
|
||||
return ETL_HUGE_VALF;
|
||||
}
|
||||
static float round_error()
|
||||
{
|
||||
@ -1617,7 +1649,7 @@ namespace etl
|
||||
}
|
||||
static ETL_CONSTEXPR double infinity()
|
||||
{
|
||||
return HUGE_VAL;
|
||||
return ETL_HUGE_VAL;
|
||||
}
|
||||
static double round_error()
|
||||
{
|
||||
@ -1664,7 +1696,7 @@ namespace etl
|
||||
}
|
||||
static ETL_CONSTEXPR long double infinity()
|
||||
{
|
||||
return HUGE_VALL;
|
||||
return ETL_HUGE_VALL;
|
||||
}
|
||||
static long double round_error()
|
||||
{
|
||||
|
||||
@ -38,8 +38,35 @@ SOFTWARE.
|
||||
#define __USE_C99_MATH
|
||||
#endif
|
||||
|
||||
// The ETL only needs floating point classification and a few elementary functions
|
||||
// (sqrt, pow, floor, ceil, round, log10, modf) from <math.h>.
|
||||
// GCC and clang provide all of them as compiler builtins, so <math.h> is not required at all.
|
||||
// This matters for ETL_NO_STL builds: libstdc++'s <math.h> (GCC 16) includes <cmath>, which in
|
||||
// turn drags in large parts of the standard library (<string> etc.), defeating the point of a
|
||||
// no-STL build. clang picks up the same <math.h> when using libstdc++.
|
||||
// Define ETL_FORCE_INCLUDE_MATH_H to opt out and use the environment's <math.h>.
|
||||
#if ETL_NOT_USING_STL && (defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_CLANG)) && !defined(ETL_FORCE_INCLUDE_MATH_H)
|
||||
#define ETL_MATH_USING_BUILTINS 1
|
||||
#else
|
||||
#define ETL_MATH_USING_BUILTINS 0
|
||||
#endif
|
||||
|
||||
// STL builds use <cmath>, which only guarantees the functions in namespace std.
|
||||
// C++03 <cmath> lacks round, signbit and fpclassify, so C++03 keeps using <math.h>.
|
||||
#if !ETL_MATH_USING_BUILTINS && ETL_USING_STL && ETL_USING_CPP11
|
||||
#define ETL_MATH_USING_STD_CMATH 1
|
||||
#else
|
||||
#define ETL_MATH_USING_STD_CMATH 0
|
||||
#endif
|
||||
|
||||
#include <float.h>
|
||||
// When using the builtins, <math.h> is not included and its macros (NAN, INFINITY, HUGE_VAL etc.)
|
||||
// are deliberately not defined here, as they would clash with a <math.h> included later.
|
||||
#if ETL_MATH_USING_STD_CMATH
|
||||
#include <cmath>
|
||||
#elif !ETL_MATH_USING_BUILTINS
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#include "limits.h"
|
||||
#include "type_traits.h"
|
||||
@ -49,11 +76,21 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// is_nan
|
||||
//***************************************************************************
|
||||
#if ETL_USING_CPP11 && !defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
#if ETL_MATH_USING_BUILTINS
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type is_nan(T value)
|
||||
{
|
||||
return __builtin_isnan(value);
|
||||
}
|
||||
#elif ETL_USING_CPP11 && !defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type is_nan(T value)
|
||||
{
|
||||
#if ETL_MATH_USING_STD_CMATH
|
||||
return std::fpclassify(value) == FP_NAN;
|
||||
#else
|
||||
return fpclassify(value) == FP_NAN;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#include "private/diagnostic_float_equal_push.h"
|
||||
@ -74,11 +111,21 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// is_infinity
|
||||
//***************************************************************************
|
||||
#if ETL_USING_CPP11 && !defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
#if ETL_MATH_USING_BUILTINS
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type is_infinity(T value)
|
||||
{
|
||||
return __builtin_isinf(value);
|
||||
}
|
||||
#elif ETL_USING_CPP11 && !defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type is_infinity(T value)
|
||||
{
|
||||
#if ETL_MATH_USING_STD_CMATH
|
||||
return std::fpclassify(value) == FP_INFINITE;
|
||||
#else
|
||||
return fpclassify(value) == FP_INFINITE;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#include "private/diagnostic_float_equal_push.h"
|
||||
@ -99,11 +146,24 @@ namespace etl
|
||||
//***************************************************************************
|
||||
// is_zero
|
||||
//***************************************************************************
|
||||
#if ETL_USING_CPP11 && !defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
#if ETL_MATH_USING_BUILTINS
|
||||
// FP_ZERO means 'exactly zero', which is precisely what '== 0' tests for.
|
||||
#include "private/diagnostic_float_equal_push.h"
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type is_zero(T value)
|
||||
{
|
||||
return value == 0;
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
#elif ETL_USING_CPP11 && !defined(ETL_NO_CPP_NAN_SUPPORT)
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type is_zero(T value)
|
||||
{
|
||||
#if ETL_MATH_USING_STD_CMATH
|
||||
return std::fpclassify(value) == FP_ZERO;
|
||||
#else
|
||||
return fpclassify(value) == FP_ZERO;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#include "private/diagnostic_float_equal_push.h"
|
||||
@ -132,12 +192,31 @@ namespace etl
|
||||
}
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
//***************************************************************************
|
||||
// Selects the implementation of a C math function for float, double and long double.
|
||||
// Either the compiler builtins, the overloads from <cmath> or the C functions from <math.h>.
|
||||
//***************************************************************************
|
||||
#if ETL_MATH_USING_BUILTINS
|
||||
#define ETL_MATH_FUNCTION_F(name) __builtin_##name##f
|
||||
#define ETL_MATH_FUNCTION_D(name) __builtin_##name
|
||||
#define ETL_MATH_FUNCTION_L(name) __builtin_##name##l
|
||||
#elif ETL_MATH_USING_STD_CMATH
|
||||
#define ETL_MATH_FUNCTION_F(name) std::name
|
||||
#define ETL_MATH_FUNCTION_D(name) std::name
|
||||
#define ETL_MATH_FUNCTION_L(name) std::name
|
||||
#else
|
||||
#define ETL_MATH_FUNCTION_F(name) ::name##f
|
||||
#define ETL_MATH_FUNCTION_D(name) ::name
|
||||
#define ETL_MATH_FUNCTION_L(name) ::name##l
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
// These functions wrap the C math.h functions.
|
||||
// The functions are overloaded for the different floating point types.
|
||||
// They provide a consistent interface for float, double and long double.
|
||||
// They are in the `math` namespace to avoid conflicts with the C library and ETL functions.
|
||||
// These take the place of std::floor, std::ceil etc which may not be available `No STL` environments.
|
||||
// For No-STL GCC/clang builds they use the compiler builtins, so <math.h> is not required.
|
||||
// Avoids unpredictable behaviour for global calls of ::floor, ::ceil etc when both <math.h> and <cmath> are included.
|
||||
//***************************************************************************
|
||||
namespace math
|
||||
@ -148,14 +227,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline float floor(float value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::floorf(value);
|
||||
return ETL_MATH_FUNCTION_F(floor)(value);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline double floor(double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::floor(value);
|
||||
return ETL_MATH_FUNCTION_D(floor)(value);
|
||||
}
|
||||
|
||||
#if ETL_USING_LONG_DOUBLE_MATH
|
||||
@ -163,14 +242,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline long double floor(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::floorl(value);
|
||||
return ETL_MATH_FUNCTION_L(floor)(value);
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline long double floor(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return static_cast<long double>(::floor(static_cast<double>(value)));
|
||||
return static_cast<long double>(ETL_MATH_FUNCTION_D(floor)(static_cast<double>(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -180,14 +259,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline float ceil(float value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::ceilf(value);
|
||||
return ETL_MATH_FUNCTION_F(ceil)(value);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline double ceil(double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::ceil(value);
|
||||
return ETL_MATH_FUNCTION_D(ceil)(value);
|
||||
}
|
||||
|
||||
#if ETL_USING_LONG_DOUBLE_MATH
|
||||
@ -195,14 +274,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline long double ceil(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::ceill(value);
|
||||
return ETL_MATH_FUNCTION_L(ceil)(value);
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline long double ceil(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return static_cast<long double>(::ceil(static_cast<double>(value)));
|
||||
return static_cast<long double>(ETL_MATH_FUNCTION_D(ceil)(static_cast<double>(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -212,14 +291,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline float log10(float value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::log10f(value);
|
||||
return ETL_MATH_FUNCTION_F(log10)(value);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline double log10(double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::log10(value);
|
||||
return ETL_MATH_FUNCTION_D(log10)(value);
|
||||
}
|
||||
|
||||
#if ETL_USING_LONG_DOUBLE_MATH
|
||||
@ -227,14 +306,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline long double log10(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::log10l(value);
|
||||
return ETL_MATH_FUNCTION_L(log10)(value);
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline long double log10(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return static_cast<long double>(::log10(static_cast<double>(value)));
|
||||
return static_cast<long double>(ETL_MATH_FUNCTION_D(log10)(static_cast<double>(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -244,14 +323,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline float round(float value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::roundf(value);
|
||||
return ETL_MATH_FUNCTION_F(round)(value);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline double round(double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::round(value);
|
||||
return ETL_MATH_FUNCTION_D(round)(value);
|
||||
}
|
||||
|
||||
#if ETL_USING_LONG_DOUBLE_MATH
|
||||
@ -259,14 +338,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline long double round(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return ::roundl(value);
|
||||
return ETL_MATH_FUNCTION_L(round)(value);
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline long double round(long double value) ETL_NOEXCEPT
|
||||
{
|
||||
return static_cast<long double>(::round(static_cast<double>(value)));
|
||||
return static_cast<long double>(ETL_MATH_FUNCTION_D(round)(static_cast<double>(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -276,14 +355,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline float pow(float base, float exponent) ETL_NOEXCEPT
|
||||
{
|
||||
return ::powf(base, exponent);
|
||||
return ETL_MATH_FUNCTION_F(pow)(base, exponent);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline double pow(double base, double exponent) ETL_NOEXCEPT
|
||||
{
|
||||
return ::pow(base, exponent);
|
||||
return ETL_MATH_FUNCTION_D(pow)(base, exponent);
|
||||
}
|
||||
|
||||
#if ETL_USING_LONG_DOUBLE_MATH
|
||||
@ -291,14 +370,14 @@ namespace etl
|
||||
ETL_NODISCARD
|
||||
inline long double pow(long double base, long double exponent) ETL_NOEXCEPT
|
||||
{
|
||||
return ::powl(base, exponent);
|
||||
return ETL_MATH_FUNCTION_L(pow)(base, exponent);
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
ETL_NODISCARD
|
||||
inline long double pow(long double base, long double exponent) ETL_NOEXCEPT
|
||||
{
|
||||
return static_cast<long double>(::pow(static_cast<double>(base), static_cast<double>(exponent)));
|
||||
return static_cast<long double>(ETL_MATH_FUNCTION_D(pow)(static_cast<double>(base), static_cast<double>(exponent)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -307,33 +386,81 @@ namespace etl
|
||||
//***************************************************************************
|
||||
inline float modf(float value, float* intpart) ETL_NOEXCEPT
|
||||
{
|
||||
return ::modff(value, intpart);
|
||||
return ETL_MATH_FUNCTION_F(modf)(value, intpart);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
inline double modf(double value, double* intpart) ETL_NOEXCEPT
|
||||
{
|
||||
return ::modf(value, intpart);
|
||||
return ETL_MATH_FUNCTION_D(modf)(value, intpart);
|
||||
}
|
||||
|
||||
#if ETL_USING_LONG_DOUBLE_MATH
|
||||
//*********************************
|
||||
inline long double modf(long double value, long double* intpart) ETL_NOEXCEPT
|
||||
{
|
||||
return ::modfl(value, intpart);
|
||||
return ETL_MATH_FUNCTION_L(modf)(value, intpart);
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
inline long double modf(long double value, long double* intpart) ETL_NOEXCEPT
|
||||
{
|
||||
double d_iptr;
|
||||
double result = ::modf(static_cast<double>(value), &d_iptr);
|
||||
double result = ETL_MATH_FUNCTION_D(modf)(static_cast<double>(value), &d_iptr);
|
||||
*intpart = static_cast<long double>(d_iptr);
|
||||
|
||||
return static_cast<long double>(result);
|
||||
}
|
||||
#endif
|
||||
} // namespace math
|
||||
|
||||
namespace private_math
|
||||
{
|
||||
//***************************************************************************
|
||||
// Functions used internally by the ETL.
|
||||
//***************************************************************************
|
||||
inline float sqrt(float value)
|
||||
{
|
||||
return ETL_MATH_FUNCTION_F(sqrt)(value);
|
||||
}
|
||||
|
||||
//*********************************
|
||||
inline double sqrt(double value)
|
||||
{
|
||||
return ETL_MATH_FUNCTION_D(sqrt)(value);
|
||||
}
|
||||
|
||||
#if ETL_USING_LONG_DOUBLE_MATH
|
||||
//*********************************
|
||||
inline long double sqrt(long double value)
|
||||
{
|
||||
return ETL_MATH_FUNCTION_L(sqrt)(value);
|
||||
}
|
||||
#else
|
||||
//*********************************
|
||||
inline long double sqrt(long double value)
|
||||
{
|
||||
return static_cast<long double>(ETL_MATH_FUNCTION_D(sqrt)(static_cast<double>(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************
|
||||
template <typename T>
|
||||
bool sign_bit(T value)
|
||||
{
|
||||
#if ETL_MATH_USING_BUILTINS
|
||||
return __builtin_signbit(value);
|
||||
#elif ETL_MATH_USING_STD_CMATH
|
||||
return std::signbit(value);
|
||||
#else
|
||||
return signbit(value);
|
||||
#endif
|
||||
}
|
||||
} // namespace private_math
|
||||
|
||||
#undef ETL_MATH_FUNCTION_F
|
||||
#undef ETL_MATH_FUNCTION_D
|
||||
#undef ETL_MATH_FUNCTION_L
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
|
||||
@ -32,6 +32,7 @@ SOFTWARE.
|
||||
#define ETL_NUMERIC_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "absolute.h"
|
||||
#include "iterator.h"
|
||||
#include "limits.h"
|
||||
#include "type_traits.h"
|
||||
@ -74,9 +75,9 @@ namespace etl
|
||||
T lo = etl::numeric_limits<T>::min() * T(2);
|
||||
T hi = etl::numeric_limits<T>::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)
|
||||
return ((etl::absolute(a) <= hi) && (etl::absolute(b) <= hi)) ? (a + b) / T(2)
|
||||
: (etl::absolute(a) < lo) ? a + (b / T(2))
|
||||
: (etl::absolute(b) < lo) ? ((a / T(2)) + b)
|
||||
: (a / T(2)) + (b / T(2));
|
||||
}
|
||||
|
||||
|
||||
@ -372,6 +372,79 @@ namespace etl
|
||||
return TToDuration(static_cast<to_rep>((ct_count * ct_num) / ct_den));
|
||||
}
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Rounds down a duration to the nearest lower precision.
|
||||
//***********************************************************************
|
||||
template <typename TToDuration, typename TRep, typename TPeriod>
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 typename etl::enable_if<etl::is_specialization<TToDuration, etl::chrono::duration>::value, TToDuration>::type
|
||||
floor(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
|
||||
{
|
||||
TToDuration result = etl::chrono::duration_cast<TToDuration>(d);
|
||||
|
||||
if (result > d)
|
||||
{
|
||||
--result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Rounds up a duration to the nearest higher precision.
|
||||
//***********************************************************************
|
||||
template <typename TToDuration, typename TRep, typename TPeriod>
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 typename etl::enable_if<etl::is_specialization<TToDuration, etl::chrono::duration>::value, TToDuration>::type
|
||||
ceil(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
|
||||
{
|
||||
TToDuration result = etl::chrono::duration_cast<TToDuration>(d);
|
||||
|
||||
if (result < d)
|
||||
{
|
||||
++result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Rounds a duration to the nearest precision.
|
||||
/// If the duration is exactly halfway, it rounds to even.
|
||||
//***********************************************************************
|
||||
template <typename TToDuration, typename TRep, typename TPeriod>
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 typename etl::enable_if<etl::is_specialization<TToDuration, etl::chrono::duration>::value, TToDuration>::type
|
||||
round(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
|
||||
{
|
||||
TToDuration lower = etl::chrono::floor<TToDuration>(d);
|
||||
|
||||
if (lower == d)
|
||||
{
|
||||
return lower;
|
||||
}
|
||||
|
||||
TToDuration upper = lower + TToDuration(1);
|
||||
|
||||
typename etl::common_type<TToDuration, etl::chrono::duration<TRep, TPeriod> >::type lower_diff = d - lower;
|
||||
typename etl::common_type<TToDuration, etl::chrono::duration<TRep, TPeriod> >::type upper_diff = upper - d;
|
||||
|
||||
if ((lower_diff < upper_diff) || ((lower_diff == upper_diff) && etl::is_even(lower.count())))
|
||||
{
|
||||
return lower;
|
||||
}
|
||||
else
|
||||
{
|
||||
return upper;
|
||||
}
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Returns the absolute value of a duration.
|
||||
//***********************************************************************
|
||||
template <typename TRep, typename TPeriod, typename = etl::enable_if_t<etl::numeric_limits<TRep>::is_signed> >
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::duration<TRep, TPeriod> abs(etl::chrono::duration<TRep, TPeriod> d) ETL_NOEXCEPT
|
||||
{
|
||||
return d.count() >= 0 ? +d : -d;
|
||||
}
|
||||
} // namespace chrono
|
||||
|
||||
//*************************************************************************
|
||||
@ -651,74 +724,6 @@ namespace etl
|
||||
|
||||
return common_duration(lhs_converted.count() % rhs_converted.count());
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Rounds down a duration to the nearest lower precision.
|
||||
//***********************************************************************
|
||||
template <typename TToDuration, typename TRep, typename TPeriod>
|
||||
ETL_CONSTEXPR14 typename etl::enable_if< etl::is_specialization<TToDuration, etl::chrono::duration>::value, TToDuration>::type
|
||||
floor(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
|
||||
{
|
||||
TToDuration result = etl::chrono::duration_cast<TToDuration>(d);
|
||||
|
||||
if (result > d)
|
||||
{
|
||||
--result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Rounds up a duration to the nearest higher precision.
|
||||
//***********************************************************************
|
||||
template <typename TToDuration, typename TRep, typename TPeriod>
|
||||
ETL_CONSTEXPR14 typename etl::enable_if< etl::is_specialization<TToDuration, etl::chrono::duration>::value, TToDuration>::type
|
||||
ceil(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
|
||||
{
|
||||
TToDuration result = etl::chrono::duration_cast<TToDuration>(d);
|
||||
|
||||
if (result < d)
|
||||
{
|
||||
++result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Rounds a duration to the nearest precision.
|
||||
/// If the duration is exactly halfway, it rounds away from zero.
|
||||
//***********************************************************************
|
||||
template <typename TToDuration, typename TRep, typename TPeriod>
|
||||
ETL_CONSTEXPR14 typename etl::enable_if< etl::is_specialization<TToDuration, etl::chrono::duration>::value, TToDuration>::type
|
||||
round(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
|
||||
{
|
||||
// Convert the input duration to the target duration type
|
||||
TToDuration lower = floor<TToDuration>(d);
|
||||
TToDuration upper = ceil<TToDuration>(lower + TToDuration(1));
|
||||
|
||||
auto lower_diff = d - lower;
|
||||
auto upper_diff = upper - d;
|
||||
|
||||
if ((lower_diff < upper_diff) || ((lower_diff == upper_diff) && etl::is_even(lower.count())))
|
||||
{
|
||||
return lower;
|
||||
}
|
||||
else
|
||||
{
|
||||
return upper;
|
||||
}
|
||||
}
|
||||
|
||||
//***********************************************************************
|
||||
/// Returns the absolute value of a duration.
|
||||
//***********************************************************************
|
||||
template <class TRep, class TPeriod, typename = etl::enable_if_t<etl::numeric_limits<TRep>::is_signed>>
|
||||
ETL_CONSTEXPR14 etl::chrono::duration<TRep, TPeriod> abs(etl::chrono::duration<TRep, TPeriod> d) ETL_NOEXCEPT
|
||||
{
|
||||
return d.count() >= 0 ? +d : -d;
|
||||
}
|
||||
} // namespace etl
|
||||
|
||||
#if ETL_HAS_CHRONO_LITERALS_DURATION
|
||||
|
||||
@ -224,7 +224,7 @@ namespace etl
|
||||
|
||||
//***********************************************************************
|
||||
/// Rounds a duration to the nearest precision.
|
||||
/// If the duration is exactly halfway, it rounds away from zero.
|
||||
/// If the duration is exactly halfway, it rounds to even.
|
||||
//***********************************************************************
|
||||
template <typename TToDuration, typename TClock, typename TDuration>
|
||||
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::time_point<TClock, TToDuration> round(const etl::chrono::time_point<TClock, TDuration>& tp)
|
||||
|
||||
@ -406,7 +406,7 @@ namespace etl
|
||||
uworkspace_t integral = static_cast<uworkspace_t>(f_integral);
|
||||
|
||||
// Find the fractional part of the floating point.
|
||||
uworkspace_t fractional = static_cast<uworkspace_t>(::round((etl::absolute(value) - f_integral) * multiplier));
|
||||
uworkspace_t fractional = static_cast<uworkspace_t>(etl::math::round((etl::absolute(value) - f_integral) * multiplier));
|
||||
|
||||
// Check for a rounding carry to the integral.
|
||||
if (fractional == multiplier)
|
||||
@ -434,9 +434,9 @@ namespace etl
|
||||
|
||||
iterator start = str.end();
|
||||
|
||||
if (isnan(value) || isinf(value))
|
||||
if (etl::is_nan(value) || etl::is_infinity(value))
|
||||
{
|
||||
etl::private_to_string::add_nan_inf(isnan(value), isinf(value), etl::is_negative(value), str, format);
|
||||
etl::private_to_string::add_nan_inf(etl::is_nan(value), etl::is_infinity(value), etl::is_negative(value), str, format);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -33,9 +33,9 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "functional.h"
|
||||
#include "math.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
@ -162,7 +162,7 @@ namespace etl
|
||||
|
||||
if (mean_of_squares > 0)
|
||||
{
|
||||
rms_value = sqrt(mean_of_squares);
|
||||
rms_value = etl::private_math::sqrt(mean_of_squares);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -33,9 +33,9 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
#include "functional.h"
|
||||
#include "math.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
@ -242,7 +242,7 @@ namespace etl
|
||||
|
||||
if (variance_value > 0)
|
||||
{
|
||||
standard_deviation_value = sqrt(variance_value);
|
||||
standard_deviation_value = etl::private_math::sqrt(variance_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -46,8 +46,6 @@ SOFTWARE.
|
||||
#include "string_view.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
@ -847,7 +845,7 @@ namespace etl
|
||||
TValue value = static_cast<TValue>(accumulator.value());
|
||||
int exponent = accumulator.exponent();
|
||||
|
||||
value *= pow(static_cast<TValue>(10.0), static_cast<TValue>(exponent));
|
||||
value *= etl::math::pow(static_cast<TValue>(10.0), static_cast<TValue>(exponent));
|
||||
|
||||
// Check that the result is a valid floating point number.
|
||||
if (etl::is_infinity(value))
|
||||
|
||||
@ -1100,11 +1100,11 @@ namespace
|
||||
TEST(test_floor)
|
||||
{
|
||||
Chrono::milliseconds ms(1234); // 1234 milliseconds
|
||||
Chrono::seconds s = floor<Chrono::seconds>(ms); // Floor to seconds
|
||||
Chrono::seconds s = Chrono::floor<Chrono::seconds>(ms); // Floor to seconds
|
||||
CHECK_EQUAL(1, s.count());
|
||||
|
||||
Chrono::milliseconds negative_ms(-1234); // -1234 milliseconds
|
||||
Chrono::seconds negative_s = floor<Chrono::seconds>(negative_ms); // Floor to seconds
|
||||
Chrono::seconds negative_s = Chrono::floor<Chrono::seconds>(negative_ms); // Floor to seconds
|
||||
CHECK_EQUAL(-2, negative_s.count());
|
||||
}
|
||||
|
||||
@ -1112,11 +1112,11 @@ namespace
|
||||
TEST(test_ceil)
|
||||
{
|
||||
Chrono::milliseconds ms(1234); // 1234 milliseconds
|
||||
Chrono::seconds s = ceil<Chrono::seconds>(ms); // Ceil to seconds
|
||||
Chrono::seconds s = Chrono::ceil<Chrono::seconds>(ms); // Ceil to seconds
|
||||
CHECK_EQUAL(2, s.count());
|
||||
|
||||
Chrono::milliseconds negative_ms(-1234); // -1234 milliseconds
|
||||
Chrono::seconds negative_s = ceil<Chrono::seconds>(negative_ms); // Ceil to seconds
|
||||
Chrono::seconds negative_s = Chrono::ceil<Chrono::seconds>(negative_ms); // Ceil to seconds
|
||||
CHECK_EQUAL(-1, negative_s.count());
|
||||
}
|
||||
|
||||
@ -1124,15 +1124,15 @@ namespace
|
||||
TEST(test_round)
|
||||
{
|
||||
Chrono::milliseconds ms(1500); // 1500 milliseconds
|
||||
Chrono::seconds s = round<Chrono::seconds>(ms); // Round to seconds
|
||||
Chrono::seconds s = Chrono::round<Chrono::seconds>(ms); // Round to seconds
|
||||
CHECK_EQUAL(2, s.count());
|
||||
|
||||
Chrono::milliseconds ms_halfway(2500); // 2500 milliseconds
|
||||
Chrono::seconds s_halfway = round<Chrono::seconds>(ms_halfway); // Round to seconds
|
||||
Chrono::seconds s_halfway = Chrono::round<Chrono::seconds>(ms_halfway); // Round to seconds
|
||||
CHECK_EQUAL(2, s_halfway.count());
|
||||
|
||||
Chrono::milliseconds negative_ms(-1500); // -1500 milliseconds
|
||||
Chrono::seconds negative_s = round<Chrono::seconds>(negative_ms); // Round to seconds
|
||||
Chrono::seconds negative_s = Chrono::round<Chrono::seconds>(negative_ms); // Round to seconds
|
||||
CHECK_EQUAL(-2, negative_s.count());
|
||||
}
|
||||
|
||||
|
||||
@ -399,11 +399,11 @@ namespace
|
||||
using TimePoint = Chrono::time_point<test_clock, Chrono::milliseconds>;
|
||||
|
||||
TimePoint tp(Chrono::milliseconds(1234)); // 1234 milliseconds
|
||||
auto floored_tp = floor<Chrono::seconds>(tp);
|
||||
auto floored_tp = Chrono::floor<Chrono::seconds>(tp);
|
||||
CHECK_EQUAL(1, floored_tp.time_since_epoch().count());
|
||||
|
||||
TimePoint negative_tp(Chrono::milliseconds(-1234)); // -1234 milliseconds
|
||||
auto floored_negative_tp = floor<Chrono::seconds>(negative_tp);
|
||||
auto floored_negative_tp = Chrono::floor<Chrono::seconds>(negative_tp);
|
||||
CHECK_EQUAL(-2, floored_negative_tp.time_since_epoch().count());
|
||||
}
|
||||
|
||||
@ -413,11 +413,11 @@ namespace
|
||||
using TimePoint = Chrono::time_point<test_clock, Chrono::milliseconds>;
|
||||
|
||||
TimePoint tp(Chrono::milliseconds(1234)); // 1234 milliseconds
|
||||
auto ceil_tp = ceil<Chrono::seconds>(tp);
|
||||
auto ceil_tp = Chrono::ceil<Chrono::seconds>(tp);
|
||||
CHECK_EQUAL(2, ceil_tp.time_since_epoch().count());
|
||||
|
||||
TimePoint negative_tp(Chrono::milliseconds(-1234)); // -1234 milliseconds
|
||||
auto ceil_negative_tp = ceil<Chrono::seconds>(negative_tp);
|
||||
auto ceil_negative_tp = Chrono::ceil<Chrono::seconds>(negative_tp);
|
||||
CHECK_EQUAL(-1, ceil_negative_tp.time_since_epoch().count());
|
||||
}
|
||||
|
||||
@ -427,15 +427,15 @@ namespace
|
||||
using TimePoint = Chrono::time_point<test_clock, Chrono::milliseconds>;
|
||||
|
||||
TimePoint tp1(Chrono::milliseconds(1500)); // 1500 milliseconds
|
||||
auto round1 = round<Chrono::seconds>(tp1); // Round to seconds
|
||||
auto round1 = Chrono::round<Chrono::seconds>(tp1); // Round to seconds
|
||||
CHECK_EQUAL(2, round1.time_since_epoch().count());
|
||||
|
||||
TimePoint tp2(Chrono::milliseconds(2500)); // 2500 milliseconds
|
||||
auto round2 = round<Chrono::seconds>(tp2); // Round to seconds
|
||||
auto round2 = Chrono::round<Chrono::seconds>(tp2); // Round to seconds
|
||||
CHECK_EQUAL(2, round2.time_since_epoch().count());
|
||||
|
||||
TimePoint tp3(Chrono::milliseconds(-1500)); // -1500 milliseconds
|
||||
auto round3 = round<Chrono::seconds>(tp3); // Round to seconds
|
||||
auto round3 = Chrono::round<Chrono::seconds>(tp3); // Round to seconds
|
||||
CHECK_EQUAL(-2, round3.time_since_epoch().count());
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +32,8 @@ SOFTWARE.
|
||||
|
||||
#include "etl/iterator.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
|
||||
namespace
|
||||
|
||||
@ -29,6 +29,7 @@ SOFTWARE.
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include "etl/limits.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace
|
||||
@ -675,6 +676,16 @@ namespace
|
||||
CHECK_EQUAL(STD_NL::min_exponent10, ETL_NL::min_exponent10);
|
||||
CHECK_EQUAL(STD_NL::radix, ETL_NL::radix);
|
||||
CHECK_EQUAL(STD_NL::round_error(), ETL_NL::round_error());
|
||||
CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity);
|
||||
CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN);
|
||||
CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN);
|
||||
CHECK_EQUAL(STD_NL::infinity(), ETL_NL::infinity());
|
||||
CHECK_EQUAL(-STD_NL::infinity(), -ETL_NL::infinity());
|
||||
CHECK_TRUE(ETL_NL::infinity() > ETL_NL::max());
|
||||
CHECK_TRUE(std::isinf(ETL_NL::infinity()));
|
||||
CHECK_FALSE(std::signbit(ETL_NL::infinity()));
|
||||
CHECK_TRUE(std::isnan(ETL_NL::quiet_NaN()));
|
||||
CHECK_TRUE(std::isnan(ETL_NL::signaling_NaN()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -702,6 +713,16 @@ namespace
|
||||
CHECK_EQUAL(STD_NL::min_exponent10, ETL_NL::min_exponent10);
|
||||
CHECK_EQUAL(STD_NL::radix, ETL_NL::radix);
|
||||
CHECK_EQUAL(STD_NL::round_error(), ETL_NL::round_error());
|
||||
CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity);
|
||||
CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN);
|
||||
CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN);
|
||||
CHECK_EQUAL(STD_NL::infinity(), ETL_NL::infinity());
|
||||
CHECK_EQUAL(-STD_NL::infinity(), -ETL_NL::infinity());
|
||||
CHECK_TRUE(ETL_NL::infinity() > ETL_NL::max());
|
||||
CHECK_TRUE(std::isinf(ETL_NL::infinity()));
|
||||
CHECK_FALSE(std::signbit(ETL_NL::infinity()));
|
||||
CHECK_TRUE(std::isnan(ETL_NL::quiet_NaN()));
|
||||
CHECK_TRUE(std::isnan(ETL_NL::signaling_NaN()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -729,6 +750,16 @@ namespace
|
||||
CHECK_EQUAL(STD_NL::min_exponent10, ETL_NL::min_exponent10);
|
||||
CHECK_EQUAL(STD_NL::radix, ETL_NL::radix);
|
||||
CHECK_EQUAL(STD_NL::round_error(), ETL_NL::round_error());
|
||||
CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity);
|
||||
CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN);
|
||||
CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN);
|
||||
CHECK_EQUAL(STD_NL::infinity(), ETL_NL::infinity());
|
||||
CHECK_EQUAL(-STD_NL::infinity(), -ETL_NL::infinity());
|
||||
CHECK_TRUE(ETL_NL::infinity() > ETL_NL::max());
|
||||
CHECK_TRUE(std::isinf(ETL_NL::infinity()));
|
||||
CHECK_FALSE(std::signbit(ETL_NL::infinity()));
|
||||
CHECK_TRUE(std::isnan(ETL_NL::quiet_NaN()));
|
||||
CHECK_TRUE(std::isnan(ETL_NL::signaling_NaN()));
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -30,11 +30,162 @@ SOFTWARE.
|
||||
|
||||
#include "etl/math.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace
|
||||
{
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
void check_classification_of_special_values()
|
||||
{
|
||||
typedef std::numeric_limits<T> STD_NL;
|
||||
|
||||
const T nan = STD_NL::quiet_NaN();
|
||||
const T negative_nan = std::copysign(STD_NL::quiet_NaN(), T(-1));
|
||||
const T inf = STD_NL::infinity();
|
||||
const T zero = T(0);
|
||||
const T negative_zero = -T(0);
|
||||
const T denorm = STD_NL::denorm_min();
|
||||
const T min_value = STD_NL::min();
|
||||
const T max_value = STD_NL::max();
|
||||
const T lowest_value = STD_NL::lowest();
|
||||
|
||||
// is_nan
|
||||
CHECK_TRUE(etl::is_nan(nan));
|
||||
CHECK_TRUE(etl::is_nan(negative_nan));
|
||||
CHECK_TRUE(etl::is_nan(STD_NL::signaling_NaN()));
|
||||
CHECK_FALSE(etl::is_nan(inf));
|
||||
CHECK_FALSE(etl::is_nan(-inf));
|
||||
CHECK_FALSE(etl::is_nan(zero));
|
||||
CHECK_FALSE(etl::is_nan(negative_zero));
|
||||
CHECK_FALSE(etl::is_nan(denorm));
|
||||
CHECK_FALSE(etl::is_nan(max_value));
|
||||
CHECK_FALSE(etl::is_nan(lowest_value));
|
||||
|
||||
// is_infinity
|
||||
CHECK_TRUE(etl::is_infinity(inf));
|
||||
CHECK_TRUE(etl::is_infinity(-inf));
|
||||
CHECK_FALSE(etl::is_infinity(nan));
|
||||
CHECK_FALSE(etl::is_infinity(negative_nan));
|
||||
CHECK_FALSE(etl::is_infinity(zero));
|
||||
CHECK_FALSE(etl::is_infinity(denorm));
|
||||
CHECK_FALSE(etl::is_infinity(max_value));
|
||||
CHECK_FALSE(etl::is_infinity(lowest_value));
|
||||
|
||||
// is_zero
|
||||
CHECK_TRUE(etl::is_zero(zero));
|
||||
CHECK_TRUE(etl::is_zero(negative_zero));
|
||||
CHECK_FALSE(etl::is_zero(denorm));
|
||||
CHECK_FALSE(etl::is_zero(-denorm));
|
||||
CHECK_FALSE(etl::is_zero(min_value));
|
||||
CHECK_FALSE(etl::is_zero(nan));
|
||||
CHECK_FALSE(etl::is_zero(inf));
|
||||
CHECK_FALSE(etl::is_zero(-inf));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
void check_math_functions()
|
||||
{
|
||||
typedef std::numeric_limits<T> STD_NL;
|
||||
|
||||
const T inf = STD_NL::infinity();
|
||||
const T tolerance = T(1e-5);
|
||||
|
||||
// The overload for the exact floating point type must be selected.
|
||||
CHECK_TRUE((std::is_same<T, decltype(etl::private_math::sqrt(T(1)))>::value));
|
||||
CHECK_TRUE((std::is_same<T, decltype(etl::math::pow(T(1), T(1)))>::value));
|
||||
CHECK_TRUE((std::is_same<T, decltype(etl::math::floor(T(1)))>::value));
|
||||
CHECK_TRUE((std::is_same<T, decltype(etl::math::ceil(T(1)))>::value));
|
||||
CHECK_TRUE((std::is_same<T, decltype(etl::math::round(T(1)))>::value));
|
||||
CHECK_TRUE((std::is_same<T, decltype(etl::math::log10(T(1)))>::value));
|
||||
CHECK_TRUE((std::is_same<T, decltype(etl::math::modf(T(1), static_cast<T*>(ETL_NULLPTR)))>::value));
|
||||
|
||||
// sqrt
|
||||
CHECK_EQUAL(T(2), etl::private_math::sqrt(T(4)));
|
||||
CHECK_CLOSE(T(1.41421356), etl::private_math::sqrt(T(2)), tolerance);
|
||||
CHECK_TRUE(etl::private_math::sign_bit(etl::private_math::sqrt(-T(0))));
|
||||
CHECK_TRUE(etl::is_nan(etl::private_math::sqrt(T(-1))));
|
||||
CHECK_TRUE(etl::is_infinity(etl::private_math::sqrt(inf)));
|
||||
|
||||
// pow
|
||||
CHECK_EQUAL(T(1024), etl::math::pow(T(2), T(10)));
|
||||
CHECK_EQUAL(T(1), etl::math::pow(T(123.456), T(0)));
|
||||
CHECK_CLOSE(T(0.01), etl::math::pow(T(10), T(-2)), tolerance);
|
||||
CHECK_CLOSE(T(2), etl::math::pow(T(4), T(0.5)), tolerance);
|
||||
|
||||
// floor
|
||||
CHECK_EQUAL(T(1), etl::math::floor(T(1.5)));
|
||||
CHECK_EQUAL(T(2), etl::math::floor(T(2)));
|
||||
CHECK_EQUAL(T(-2), etl::math::floor(T(-1.5)));
|
||||
CHECK_EQUAL(T(-1), etl::math::floor(T(-0.5)));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(etl::math::floor(-T(0))));
|
||||
|
||||
// round: halfway cases round away from zero.
|
||||
CHECK_EQUAL(T(3), etl::math::round(T(2.5)));
|
||||
CHECK_EQUAL(T(-3), etl::math::round(T(-2.5)));
|
||||
CHECK_EQUAL(T(1), etl::math::round(T(0.5)));
|
||||
CHECK_EQUAL(T(-1), etl::math::round(T(-0.5)));
|
||||
CHECK_EQUAL(T(1), etl::math::round(T(1.4999)));
|
||||
CHECK_TRUE(etl::is_zero(etl::math::round(T(-0.4))));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(etl::math::round(T(-0.4))));
|
||||
|
||||
// log10
|
||||
CHECK_EQUAL(T(0), etl::math::log10(T(1)));
|
||||
CHECK_CLOSE(T(3), etl::math::log10(T(1000)), tolerance);
|
||||
CHECK_CLOSE(T(-3), etl::math::log10(T(0.001)), tolerance);
|
||||
CHECK_TRUE(etl::is_infinity(etl::math::log10(T(0))));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(etl::math::log10(T(0))));
|
||||
CHECK_TRUE(etl::is_nan(etl::math::log10(T(-1))));
|
||||
|
||||
// modf
|
||||
T integral = T(0);
|
||||
T fractional = etl::math::modf(T(3.75), &integral);
|
||||
CHECK_EQUAL(T(3), integral);
|
||||
CHECK_EQUAL(T(0.75), fractional);
|
||||
|
||||
fractional = etl::math::modf(T(-1.25), &integral);
|
||||
CHECK_EQUAL(T(-1), integral);
|
||||
CHECK_EQUAL(T(-0.25), fractional);
|
||||
|
||||
fractional = etl::math::modf(T(5), &integral);
|
||||
CHECK_EQUAL(T(5), integral);
|
||||
CHECK_TRUE(etl::is_zero(fractional));
|
||||
CHECK_FALSE(etl::private_math::sign_bit(fractional));
|
||||
|
||||
fractional = etl::math::modf(-inf, &integral);
|
||||
CHECK_TRUE(etl::is_infinity(integral));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(integral));
|
||||
CHECK_TRUE(etl::is_zero(fractional));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(fractional));
|
||||
|
||||
// sign_bit
|
||||
CHECK_FALSE(etl::private_math::sign_bit(T(0)));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(-T(0)));
|
||||
CHECK_FALSE(etl::private_math::sign_bit(T(1)));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(T(-1)));
|
||||
CHECK_FALSE(etl::private_math::sign_bit(inf));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(-inf));
|
||||
CHECK_FALSE(etl::private_math::sign_bit(STD_NL::denorm_min()));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(-STD_NL::denorm_min()));
|
||||
CHECK_FALSE(etl::private_math::sign_bit(std::copysign(STD_NL::quiet_NaN(), T(1))));
|
||||
CHECK_TRUE(etl::private_math::sign_bit(std::copysign(STD_NL::quiet_NaN(), T(-1))));
|
||||
}
|
||||
|
||||
#if ETL_MATH_USING_BUILTINS
|
||||
// The builtin based classification functions must remain usable in constant expressions.
|
||||
static_assert(etl::is_nan(__builtin_nan("")), "is_nan must be constexpr");
|
||||
static_assert(!etl::is_nan(1.0), "is_nan must be constexpr");
|
||||
static_assert(etl::is_infinity(etl::numeric_limits<double>::infinity()), "is_infinity must be constexpr");
|
||||
static_assert(etl::is_infinity(-etl::numeric_limits<float>::infinity()), "is_infinity must be constexpr");
|
||||
static_assert(!etl::is_infinity(etl::numeric_limits<long double>::max()), "is_infinity must be constexpr");
|
||||
static_assert(etl::is_zero(-0.0), "is_zero must be constexpr");
|
||||
static_assert(!etl::is_zero(etl::numeric_limits<double>::min()), "is_zero must be constexpr");
|
||||
#endif
|
||||
|
||||
SUITE(test_math)
|
||||
{
|
||||
//*************************************************************************
|
||||
@ -245,5 +396,41 @@ namespace
|
||||
CHECK_CLOSE((double)3.0L, (double)ld_intpart, 0.0001);
|
||||
CHECK_CLOSE((double)0.75L, (double)ld_frac, 0.0001);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_classification_of_special_values_float)
|
||||
{
|
||||
check_classification_of_special_values<float>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_classification_of_special_values_double)
|
||||
{
|
||||
check_classification_of_special_values<double>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_classification_of_special_values_long_double)
|
||||
{
|
||||
check_classification_of_special_values<long double>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_math_functions_float)
|
||||
{
|
||||
check_math_functions<float>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_math_functions_double)
|
||||
{
|
||||
check_math_functions<double>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_math_functions_long_double)
|
||||
{
|
||||
check_math_functions<long double>();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user