Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/real-time-cpp-benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ jobs:
- name: benchmark_single-stm32f446
run: |
mkdir -p bin
arm-none-eabi-g++ -std=c++20 -Wall -Wextra -pedantic -O2 -g -gdwarf-2 -ffunction-sections -fdata-sections -x c++ -fno-rtti -fno-use-cxa-atexit -fno-exceptions -fno-nonansi-builtins -fno-threadsafe-statics -fno-enforce-eh-specs -ftemplate-depth=32 -mcpu=cortex-m4 -mtune=cortex-m4 -mthumb -mfloat-abi=soft -mno-unaligned-access -mno-long-calls -I./src/mcal/stm32f446 -I./src -DAPP_BENCHMARK_TYPE=APP_BENCHMARK_TYPE_CRC -DAPP_BENCHMARK_STANDALONE_MAIN ./src/app/benchmark/app_benchmark_crc.cpp ./target/micros/stm32f446/make/single/crt.cpp -nostartfiles -Wl,--gc-sections -Wl,-Map,./bin/app_benchmark_crc.map -T ./target/micros/stm32f446/make/stm32f446.ld -o ./bin/app_benchmark_crc.elf
arm-none-eabi-g++ -std=c++20 -Wall -Wextra -Wpedantic -O2 -g -gdwarf-2 -ffunction-sections -fdata-sections -x c++ -fno-rtti -fno-use-cxa-atexit -fno-exceptions -fno-nonansi-builtins -fno-threadsafe-statics -fno-enforce-eh-specs -ftemplate-depth=32 -mcpu=cortex-m4 -mtune=cortex-m4 -mthumb -mfloat-abi=soft -mno-unaligned-access -mno-long-calls -I./src/mcal/stm32f446 -I./src -DAPP_BENCHMARK_TYPE=APP_BENCHMARK_TYPE_CRC -DAPP_BENCHMARK_STANDALONE_MAIN ./src/app/benchmark/app_benchmark_crc.cpp ./target/micros/stm32f446/make/single/crt.cpp -nostartfiles -Wl,--gc-sections -Wl,-Map,./bin/app_benchmark_crc.map -T ./target/micros/stm32f446/make/stm32f446.ld -o ./bin/app_benchmark_crc.elf
arm-none-eabi-objcopy ./bin/app_benchmark_crc.elf -O ihex ./bin/app_benchmark_crc.hex
ls -la ./bin/app_benchmark_crc.elf ./bin/app_benchmark_crc.hex ./bin/app_benchmark_crc.map
working-directory: ./ref_app/
Expand Down
4 changes: 2 additions & 2 deletions ref_app/cmake/gcc-toolchain.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
##############################################################################
# Copyright Christopher Kormanyos 2021.
# Copyright Christopher Kormanyos 2021 - 2025.
# Distributed under the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt
# or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand Down Expand Up @@ -94,7 +94,7 @@ set(GCCFLAGS
-g
-Wall
-Wextra
-pedantic
-Wpedantic
-Wmain
-Wundef
-Wsign-conversion
Expand Down
67 changes: 36 additions & 31 deletions ref_app/src/app/benchmark/app_benchmark_trapezoid_integral.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2021 - 2024.
// Copyright Christopher Kormanyos 2021 - 2025.
// Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand Down Expand Up @@ -31,17 +31,17 @@
#if (defined(STDFLOAT_FLOAT64_NATIVE_TYPE) || (defined(__STDCPP_FLOAT64_T__) && (__STDCPP_FLOAT64_T__ == 1)))

using local_float_type = std::float64_t;
static_assert((std::numeric_limits<local_float_type>::digits >= 53), "Error: Incorrect my_float_type type definition");
static_assert((std::numeric_limits<local_float_type>::digits >= 53), "Error: Incorrect local_float_type type definition");

#elif (defined(STDFLOAT_FLOAT32_NATIVE_TYPE) || (defined(__STDCPP_FLOAT32_T__) && (__STDCPP_FLOAT32_T__ == 1)))

using local_float_type = std::float32_t;
static_assert((std::numeric_limits<local_float_type>::digits >= 24), "Error: Incorrect my_float_type type definition");
static_assert((std::numeric_limits<local_float_type>::digits >= 24), "Error: Incorrect local_float_type type definition");

#else

using local_float_type = double;
static_assert((std::numeric_limits<local_float_type>::digits >= 53), "Error: Incorrect my_float_type type definition");
static_assert((std::numeric_limits<local_float_type>::digits >= 53), "Error: Incorrect local_float_type type definition");

#endif

Expand All @@ -56,50 +56,55 @@ using my_float_type = ::local_float_type;
#include <math/calculus/integral.h>
#include <math/constants/constants.h>

namespace
namespace local
{
template<typename FloatingPointType>
auto cyl_bessel_j(const std::uint_fast8_t n, const FloatingPointType& x) -> FloatingPointType
{
using local_float_type = FloatingPointType;

constexpr auto epsilon = std::numeric_limits<local_float_type>::epsilon();

using std::sqrt;

const auto tol = sqrt(epsilon);

const auto integration_result =
math::integral(static_cast<local_float_type>(0),
math::constants::pi<local_float_type>(),
tol,
[&x, &n](const local_float_type& t) noexcept
{
using std::cos;
using std::sin;

return
static_cast<local_float_type>
(
cos(x * sin(t) - (t * static_cast<local_float_type>(n)))
);
});
const local_float_type tol { sqrt(std::numeric_limits<local_float_type>::epsilon()) };

const local_float_type
integration_result
{
math::integral
(
static_cast<local_float_type>(0),
math::constants::pi<local_float_type>(),
tol,
[&x, &n](const local_float_type& t) noexcept
{
using std::cos;
using std::sin;

return cos(static_cast<local_float_type>((x * sin(t)) - (t * static_cast<local_float_type>(n))));
}
)
};

return integration_result / math::constants::pi<local_float_type>();
}
}
} // namespace local

auto app::benchmark::run_trapezoid_integral() -> bool
{
constexpr auto app_benchmark_tolerance =
static_cast<my_float_type>
(
constexpr my_float_type
app_benchmark_tolerance
{
std::numeric_limits<my_float_type>::epsilon() * static_cast<my_float_type>(100.0L)
);
};

// Compute y = cyl_bessel_j(2, 1.23) = 0.16636938378681407351267852431513159437103348245333
// Test the value of a Bessel function.
// Here is a control value from Wolfram Alpha.
// N[BesselJ[2, 123/100], 50]
const auto j2 = cyl_bessel_j(static_cast<std::uint_fast8_t>(UINT8_C(2)), static_cast<my_float_type>(1.23L));
// 0.16636938378681407351267852431513159437103348245333

// Compute cyl_bessel_j(2, 1.23)

const my_float_type j2 { local::cyl_bessel_j(std::uint_fast8_t { UINT8_C(2) }, static_cast<my_float_type>(1.23L)) };

const bool app_benchmark_result_is_ok =
detail::is_close_fraction
Expand Down
85 changes: 44 additions & 41 deletions ref_app/src/math/calculus/integral.h
Original file line number Diff line number Diff line change
@@ -1,65 +1,68 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2007 - 2021.
// Copyright Christopher Kormanyos 2007 - 2025.
// Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef INTEGRAL_2012_01_09_H_
#define INTEGRAL_2012_01_09_H_
#ifndef INTEGRAL_2012_01_09_H
#define INTEGRAL_2012_01_09_H

#include <cmath>
#include <cmath>

namespace math
{
template<typename real_value_type,
typename real_function_type>
real_value_type integral(const real_value_type& a,
const real_value_type& b,
const real_value_type& tol,
real_function_type real_function)
{
std::uint_fast32_t n2(1);
namespace math
{
// Compute the numerical integral of a real function from a to b
// using a recursive trapezoid rule.

real_value_type step = ((b - a) / 2U);
template<typename real_value_type,
typename real_function_type>
real_value_type integral(const real_value_type& a,
const real_value_type& b,
const real_value_type& tol,
real_function_type real_function)
{
std::uint_fast32_t n2 { UINT8_C(1) };

real_value_type result = (real_function(a) + real_function(b)) * step;
real_value_type step { (b - a) / 2U };

const std::uint_fast8_t k_max = UINT8_C(32);
real_value_type result { (real_function(a) + real_function(b)) * step };

for(std::uint_fast8_t k = UINT8_C(0); k < k_max; ++k)
{
real_value_type sum(0);
constexpr std::uint_fast8_t k_max { UINT8_C(32) };

for(std::uint_fast32_t j(0U); j < n2; ++j)
{
const std::uint_fast32_t two_j_plus_one = (j * UINT32_C(2)) + UINT32_C(1);
for(std::uint_fast8_t k = UINT8_C(0); k < k_max; ++k)
{
real_value_type sum { 0 };

sum += real_function(a + real_value_type(step * real_value_type(two_j_plus_one)));
}
for(std::uint_fast32_t j { std::uint_fast32_t { UINT8_C(0) } }; j < n2; ++j)
{
const std::uint_fast32_t two_j_plus_one { (j * UINT32_C(2)) + UINT32_C(1) };

const real_value_type tmp = result;
sum += real_function(a + real_value_type(step * two_j_plus_one));
}

result = (result / 2U) + (step * sum);
const real_value_type tmp { result };

using std::fabs;
result = (result / 2U) + (step * sum);

const real_value_type ratio = fabs(tmp / result);
const real_value_type ratio { tmp / result };

const real_value_type delta = fabs(ratio - 1U);
using std::fabs;

if((k > UINT8_C(1)) && (delta < tol))
{
break;
}
const real_value_type delta = fabs(ratio - 1U);

n2 *= 2U;
if((k > std::uint_fast8_t { UINT8_C(1) }) && (delta < tol))
{
break;
}

step /= 2U;
}
n2 *= 2U;

return result;
}
}
step /= 2U;
}

#endif // INTEGRAL_2012_01_09_H_
return result;
}
}

#endif // INTEGRAL_2012_01_09_H
4 changes: 2 additions & 2 deletions ref_app/src/mcal/mcal_gcc_cxx_completion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ extern "C"
// and objects.

void abort () __attribute__((noreturn));
int atexit (void (*)()) noexcept;
int atexit (void (*)());
int at_quick_exit (void (*)());
void _Exit (int) __attribute__((noreturn));
void exit (int) __attribute__((noreturn));
Expand All @@ -111,7 +111,7 @@ extern "C"
// Implementations of patched functions.

void abort () { for(;;) { mcal::cpu::nop(); } }
int atexit (void (*)()) noexcept { return 0; }
int atexit (void (*)()) { return 0; }
int at_quick_exit (void (*)()) { return 0; }
void _Exit (int) { for(;;) { mcal::cpu::nop(); } }
void exit (int) { for(;;) { mcal::cpu::nop(); } }
Expand Down
4 changes: 2 additions & 2 deletions ref_app/src/sys/start/sys_start.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#if (defined(__XTENSA__) && !defined(CONFIG_IDF_TARGET_ESP32S3))
extern "C" ATTRIBUTE(used) auto app_main_loop() -> int;
#else
extern "C" ATTRIBUTE(used) auto main() -> int;
ATTRIBUTE(used) auto main() -> int;
#endif

#if (defined(__XTENSA__) && !defined(CONFIG_IDF_TARGET_ESP32S3))
Expand All @@ -29,7 +29,7 @@ auto main() -> int
// Initialize the microcontroller abstraction layer.
mcal::init();

// Start the multitasking scheduler. (This does not return.)
// Start the multitasking scheduler. This does not return.
// Handle an unexpected return from main() in the startup code.
os::start_os();

Expand Down
55 changes: 33 additions & 22 deletions ref_app/src/util/STL/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,25 @@
#define NAN (-(float)(INFINITY * 0.0F))
#endif

#define _DENORM (-2)
#define _FINITE (-1)
#define _INFCODE 1
#define _NANCODE 2

#define FP_INFINITE _INFCODE
#define FP_NAN _NANCODE
#define FP_NORMAL _FINITE
#define FP_SUBNORMAL _DENORM
#define FP_ZERO 0
#if !defined(FP_NAN)
#define FP_NAN 0
#endif
#if !defined(FP_INFINITE)
#define FP_INFINITE 1
#endif
#if !defined(FP_ZERO)
#define FP_ZERO 2
#endif
#if !defined(FP_SUBNORMAL)
#define FP_SUBNORMAL 3
#endif
#if !defined(FP_NORMAL)
#define FP_NORMAL 4
#endif

#define _C2 1 // 0 if not 2's complement
#define FP_ILOGB0 (-0x7fffffff - _C2)
#define FP_ILOGBNAN 0x7fffffff
#define _C2 1L // 0 if not 2's complement
#define FP_ILOGB0 (-0x7fffffffL - _C2)
#define FP_ILOGBNAN 0x7fffffffL

static_assert((__SIZEOF_LONG_DOUBLE__ > 0) && (__SIZEOF_LONG_DOUBLE__ >= __SIZEOF_DOUBLE__),
"Error: Configuration error regarding 64-bit double/long-double for AVR");
Expand Down Expand Up @@ -249,6 +254,9 @@

namespace std
{
using float_t = float;
using double_t = double;

inline bool isnan (float x) { return (__BUILTIN_ISNANF(x) == 1); }
inline bool isnan (double x) { return (__BUILTIN_ISNAN (x) == 1); }
inline bool isnan (long double x) { return (__BUILTIN_ISNANL(x) == 1); }
Expand Down Expand Up @@ -688,24 +696,27 @@
}
#endif

#if !defined(FP_INFINITE)
#define FP_INFINITE 1
#endif
#if !defined(FP_NAN)
#define FP_NAN 2
#define FP_NAN 0
#endif
#if !defined(FP_NORMAL)
#define FP_NORMAL (-1)
#if !defined(FP_INFINITE)
#define FP_INFINITE 1
#endif
#if !defined(FP_ZERO)
#define FP_ZERO 2
#endif
#if !defined(FP_SUBNORMAL)
#define FP_SUBNORMAL (-2)
#define FP_SUBNORMAL 3
#endif
#if !defined(FP_ZERO)
#define FP_ZERO 0
#if !defined(FP_NORMAL)
#define FP_NORMAL 4
#endif

namespace std
{
using float_t = float;
using double_t = double;

using ::isfinite;
using ::ilogb;

Expand Down
7 changes: 6 additions & 1 deletion ref_app/src/util/STL/stdfloat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2007 - 2024.
// Copyright Christopher Kormanyos 2007 - 2025.
// Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -12,6 +12,8 @@
#pragma GCC system_header
#endif

#include <limits>

namespace std
{
using float32_t = float;
Expand All @@ -32,4 +34,7 @@
#endif
}

static_assert((std::numeric_limits<std::float32_t>::digits == 24), "Error: Incorrect float32_t type definition");
static_assert((std::numeric_limits<std::float64_t>::digits == 53), "Error: Incorrect float64_t type definition");

#endif // STDFLOAT_2024_07_12
Loading