Added more math wrappers.

Move wrappers to clib namespace
This commit is contained in:
John Wellbelove 2026-09-22 10:06:13 +01:00
parent f9c830a10c
commit 59204cf3a0
5 changed files with 527 additions and 39 deletions

View File

@ -49,10 +49,17 @@ ETL_CONSTEXPR bool is_exactly_equal(T value1, T value2)
## floor
Defined in the `etl::clib` namespace.
---
```cpp
ETL_NODISCARD
float floor(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::floorf`.
**Returns**
`::floorf(value)`
@ -62,6 +69,9 @@ float floor(float value) ETL_NOEXCEPT
ETL_NODISCARD
double floor(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::floor`.
**Returns**
`::floor(value)`
@ -71,15 +81,28 @@ double floor(double value) ETL_NOEXCEPT
ETL_NODISCARD
long double floor(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::floorl`.
**Returns**
`::floorl(value)`
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::floor` with casts to `double`.
otherwise
`::floorl(value)`
## ceil
Defined in the `etl::clib` namespace.
---
```cpp
ETL_NODISCARD
float ceil(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::ceilf`.
**Returns**
`::ceilf(value)`
@ -89,6 +112,9 @@ float ceil(float value) ETL_NOEXCEPT
ETL_NODISCARD
double ceil(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::ceil`.
**Returns**
`::ceil(value)`
@ -98,5 +124,183 @@ double ceil(double value) ETL_NOEXCEPT
ETL_NODISCARD
long double ceil(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::ceill`.
**Returns**
`::ceill(value)`
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::ceil` with casts to `double`.
otherwise
`::ceill(value)`
## log10
Defined in the `etl::clib` namespace.
---
```cpp
ETL_NODISCARD
float log10(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::log10f`.
**Returns**
`::log10f(value)`
---
```cpp
ETL_NODISCARD
double log10(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::log10`.
**Returns**
`::log10(value)`
---
```cpp
ETL_NODISCARD
long double log10(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::log10l`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::log10` with casts to `double`.
otherwise
`::log10l(value)`
## round
Defined in the `etl::clib` namespace.
---
```cpp
ETL_NODISCARD
float round(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::roundf`.
**Returns**
`::roundf(value)`
---
```cpp
ETL_NODISCARD
double round(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::round`.
**Returns**
`::round(value)`
---
```cpp
ETL_NODISCARD
long double round(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::roundl`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::round` with casts to `double`.
otherwise
`::roundl(value)`
## pow
Defined in the `etl::clib` namespace.
---
```cpp
ETL_NODISCARD
float pow(float base, float exponent) ETL_NOEXCEPT
```
**Description**
A wrapper around `::powf`.
**Returns**
`::powf(base, exponent)`
---
```cpp
ETL_NODISCARD
double pow(double base, double exponent) ETL_NOEXCEPT
```
**Description**
A wrapper around `::pow`.
**Returns**
`::pow(base, exponent)`
---
```cpp
ETL_NODISCARD
long double pow(long double base, long double exponent) ETL_NOEXCEPT
```
**Description**
A wrapper around `::powl`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::pow` with casts to `double`.
otherwise
`::powl(base, intpart)`
## modf
Defined in the `etl::clib` namespace.
---
```cpp
ETL_NODISCARD
float modf(float value, float* intpart) ETL_NOEXCEPT
```
**Description**
A wrapper around `::modff`.
**Returns**
`::modff(value, intpart)`
---
```cpp
ETL_NODISCARD
double modf(double value, double* intpart) ETL_NOEXCEPT
```
**Description**
A wrapper around `::modf`.
**Returns**
`::modf(value, intpart)`
---
```cpp
ETL_NODISCARD
long double modf(long double value, long double* intpart) ETL_NOEXCEPT
```
**Description**
A wrapper around `::modfl`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::modf` with casts to `double`.
otherwise
`::modfl(value, intpart)`

View File

@ -132,47 +132,215 @@ namespace etl
}
#include "private/diagnostic_pop.h"
//***************************************************************************
// floor
//***************************************************************************
ETL_NODISCARD
inline float floor(float value) ETL_NOEXCEPT
namespace clib
{
return ::floorf(value);
}
//***************************************************************************
// floor
//***************************************************************************
ETL_NODISCARD
inline float floor(float value) ETL_NOEXCEPT
{
return ::floorf(value);
}
ETL_NODISCARD
inline double floor(double value) ETL_NOEXCEPT
{
return ::floor(value);
}
ETL_NODISCARD
inline double floor(double value) ETL_NOEXCEPT
{
return ::floor(value);
}
ETL_NODISCARD
inline long double floor(long double value) ETL_NOEXCEPT
{
return ::floorl(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
ETL_NODISCARD
inline long double floor(long double value) ETL_NOEXCEPT
{
return ::floorl(value);
}
#else
ETL_NODISCARD
inline long double floor(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::floor(static_cast<double>(value)));
}
#endif
//***************************************************************************
// ceil
//***************************************************************************
ETL_NODISCARD
inline float ceil(float value) ETL_NOEXCEPT
{
return ::ceilf(value);
}
//***************************************************************************
// ceil
//***************************************************************************
ETL_NODISCARD
inline float ceil(float value) ETL_NOEXCEPT
{
return ::ceilf(value);
}
ETL_NODISCARD
inline double ceil(double value) ETL_NOEXCEPT
{
return ::ceil(value);
}
ETL_NODISCARD
inline double ceil(double value) ETL_NOEXCEPT
{
return ::ceil(value);
}
ETL_NODISCARD
inline long double ceil(long double value) ETL_NOEXCEPT
{
return ::ceill(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
ETL_NODISCARD
inline long double ceil(long double value) ETL_NOEXCEPT
{
return ::ceill(value);
}
#else
ETL_NODISCARD
inline long double ceil(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::ceil(static_cast<double>(value)));
}
#endif
//***************************************************************************
// log10
//***************************************************************************
ETL_NODISCARD
inline float log10(float value) ETL_NOEXCEPT
{
return ::log10f(value);
}
ETL_NODISCARD
inline double log10(double value) ETL_NOEXCEPT
{
return ::log10(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
ETL_NODISCARD
inline long double log10(long double value) ETL_NOEXCEPT
{
return ::log10l(value);
}
#else
ETL_NODISCARD
inline long double log10(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::log10(static_cast<double>(value)));
}
#endif
//***************************************************************************
// round
//***************************************************************************
ETL_NODISCARD
inline float round(float value) ETL_NOEXCEPT
{
return ::roundf(value);
}
ETL_NODISCARD
inline double round(double value) ETL_NOEXCEPT
{
return ::round(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
ETL_NODISCARD
inline long double round(long double value) ETL_NOEXCEPT
{
return ::roundl(value);
}
#else
ETL_NODISCARD
inline long double round(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::round(static_cast<double>(value)));
}
#endif
//***************************************************************************
// fabs
//***************************************************************************
ETL_NODISCARD
inline float fabs(float value) ETL_NOEXCEPT
{
return ::fabsf(value);
}
ETL_NODISCARD
inline double fabs(double value) ETL_NOEXCEPT
{
return ::fabs(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
ETL_NODISCARD
inline long double fabs(long double value) ETL_NOEXCEPT
{
return ::fabsl(value);
}
#else
ETL_NODISCARD
inline long double fabs(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::fabs(static_cast<double>(value)));
}
#endif
//***************************************************************************
// power
//***************************************************************************
ETL_NODISCARD
inline float pow(float base, float exponent) ETL_NOEXCEPT
{
return ::powf(base, exponent);
}
ETL_NODISCARD
inline double pow(double base, double exponent) ETL_NOEXCEPT
{
return ::pow(base, exponent);
}
#if ETL_USING_LONG_DOUBLE_MATH
ETL_NODISCARD
inline long double pow(long double base, long double exponent) ETL_NOEXCEPT
{
return ::powl(base, exponent);
}
#else
ETL_NODISCARD
inline long double power(long double base, long double exponent) ETL_NOEXCEPT
{
return static_cast<long double>(::pow(static_cast<double>(base), static_cast<double>(exponent)));
}
#endif
//***************************************************************************
// modf
//***************************************************************************
ETL_NODISCARD
inline float modf(float value, float* intpart) ETL_NOEXCEPT
{
return ::modff(value, intpart);
}
ETL_NODISCARD
inline double modf(double value, double* intpart) ETL_NOEXCEPT
{
return ::modf(value, intpart);
}
#if ETL_USING_LONG_DOUBLE_MATH
ETL_NODISCARD
inline long double modf(long double value, long double* intpart) ETL_NOEXCEPT
{
return ::modfl(value, intpart);
}
#else
ETL_NODISCARD
inline long double modf(long double value, long double* intpart) ETL_NOEXCEPT
{
double d_iptr;
double result = ::modf(static_cast<double>(value), &d_iptr);
*intpart = static_cast<long double>(d_iptr);
return static_cast<long double>(result);
}
#endif
} // namespace clib
} // namespace etl
#endif

View File

@ -187,6 +187,19 @@ SOFTWARE.
#define ETL_NOT_USING_FORMAT_LONG_DOUBLE_MATH 0
#endif
//*************************************
// Helper macro for ETL_NO_LONG_DOUBLE_MATH.
// Define ETL_NO_LONG_DOUBLE_MATH if the toolchain does not provide
// long double math functions (log10l, floorl, powl, modfl, roundl).
// When defined, long double arguments are cast to double for math operations.
#if defined(ETL_NO_LONG_DOUBLE_MATH)
#define ETL_USING_LONG_DOUBLE_MATH 0
#define ETL_NOT_USING_LONG_DOUBLE_MATH 1
#else
#define ETL_USING_LONG_DOUBLE_MATH 1
#define ETL_NOT_USING_LONG_DOUBLE_MATH 0
#endif
//*************************************
// Figure out things about the compiler, if haven't already done so in
// etl_profile.h

View File

@ -347,7 +347,7 @@ namespace etl
}
// Find the integral part of the floating point
T f_integral = etl::floor(scaled);
T f_integral = etl::clib::floor(scaled);
uworkspace_t integral = static_cast<uworkspace_t>(f_integral);
// Find the fractional part of the floating point.
@ -404,7 +404,7 @@ namespace etl
}
// Find the integral part of the floating point
T f_integral = etl::floor(etl::absolute(value));
T f_integral = etl::clib::floor(etl::absolute(value));
uworkspace_t integral = static_cast<uworkspace_t>(f_integral);
// Find the fractional part of the floating point.

View File

@ -130,5 +130,108 @@ namespace
CHECK_TRUE(etl::is_exactly_equal(i1, i1));
CHECK_FALSE(etl::is_exactly_equal(i1, i2));
}
//*************************************************************************
TEST(test_floor)
{
float f1 = 1.7f;
float f2 = -1.7f;
double d1 = 1.7;
double d2 = -1.7;
long double ld1 = 1.7L;
long double ld2 = -1.7L;
CHECK_CLOSE(1.0f, etl::clib::floor(f1), 0.0001f);
CHECK_CLOSE(-2.0f, etl::clib::floor(f2), 0.0001f);
CHECK_CLOSE(1.0, etl::clib::floor(d1), 0.0001);
CHECK_CLOSE(-2.0, etl::clib::floor(d2), 0.0001);
CHECK_CLOSE(1.0L, etl::clib::floor(ld1), 0.0001L);
CHECK_CLOSE(-2.0L, etl::clib::floor(ld2), 0.0001L);
}
//*************************************************************************
TEST(test_ceil)
{
float f1 = 1.2f;
float f2 = -1.2f;
double d1 = 1.2;
double d2 = -1.2;
long double ld1 = 1.2L;
long double ld2 = -1.2L;
CHECK_CLOSE(2.0f, etl::clib::ceil(f1), 0.0001f);
CHECK_CLOSE(-1.0f, etl::clib::ceil(f2), 0.0001f);
CHECK_CLOSE(2.0, etl::clib::ceil(d1), 0.0001);
CHECK_CLOSE(-1.0, etl::clib::ceil(d2), 0.0001);
CHECK_CLOSE(2.0L, etl::clib::ceil(ld1), 0.0001L);
CHECK_CLOSE(-1.0L, etl::clib::ceil(ld2), 0.0001L);
}
//*************************************************************************
TEST(test_log10)
{
float f1 = 100.0f;
double d1 = 1000.0;
long double ld1 = 10000.0L;
CHECK_CLOSE(2.0f, etl::clib::log10(f1), 0.0001f);
CHECK_CLOSE(3.0, etl::clib::log10(d1), 0.0001);
CHECK_CLOSE(4.0L, etl::clib::log10(ld1), 0.0001L);
}
//*************************************************************************
TEST(test_fabs)
{
float f1 = -1.5f;
float f2 = 1.5f;
double d1 = -2.5;
double d2 = 2.5;
long double ld1 = -3.5L;
long double ld2 = 3.5L;
CHECK_CLOSE(1.5f, etl::clib::fabs(f1), 0.0001f);
CHECK_CLOSE(1.5f, etl::clib::fabs(f2), 0.0001f);
CHECK_CLOSE(2.5, etl::clib::fabs(d1), 0.0001);
CHECK_CLOSE(2.5, etl::clib::fabs(d2), 0.0001);
CHECK_CLOSE(3.5L, etl::clib::fabs(ld1), 0.0001L);
CHECK_CLOSE(3.5L, etl::clib::fabs(ld2), 0.0001L);
}
//*************************************************************************
TEST(test_pow)
{
float fb = 2.0f;
float fe = 3.0f;
double db = 2.0;
double de = 10.0;
long double ldb = 2.0L;
long double lde = 4.0L;
CHECK_CLOSE(8.0f, etl::clib::pow(fb, fe), 0.0001f);
CHECK_CLOSE(1024.0, etl::clib::pow(db, de), 0.0001);
CHECK_CLOSE(16.0L, etl::clib::pow(ldb, lde), 0.0001L);
}
//*************************************************************************
TEST(test_modf)
{
float f1 = 3.75f;
float f_intpart = 0.0f;
double d1 = 3.75;
double d_intpart = 0.0;
long double ld1 = 3.75L;
long double ld_intpart = 0.0L;
float f_frac = etl::clib::modf(f1, &f_intpart);
double d_frac = etl::clib::modf(d1, &d_intpart);
long double ld_frac = etl::clib::modf(ld1, &ld_intpart);
CHECK_CLOSE(3.0f, f_intpart, 0.0001f);
CHECK_CLOSE(0.75f, f_frac, 0.0001f);
CHECK_CLOSE(3.0, d_intpart, 0.0001);
CHECK_CLOSE(0.75, d_frac, 0.0001);
CHECK_CLOSE((double)3.0L, (double)ld_intpart, 0.0001);
CHECK_CLOSE((double)0.75L, (double)ld_frac, 0.0001);
}
}
} // namespace