Skip to content

Commit bfdced4

Browse files
authored
Merge pull request #643 from ckormanyos/syntax_and_bench
Improve syntax and math benchmark
2 parents 16c357a + a12e37d commit bfdced4

15 files changed

Lines changed: 156 additions & 130 deletions

File tree

.github/workflows/real-time-cpp-benchmarks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ jobs:
172172
- name: benchmark_single-stm32f446
173173
run: |
174174
mkdir -p bin
175-
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
175+
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
176176
arm-none-eabi-objcopy ./bin/app_benchmark_crc.elf -O ihex ./bin/app_benchmark_crc.hex
177177
ls -la ./bin/app_benchmark_crc.elf ./bin/app_benchmark_crc.hex ./bin/app_benchmark_crc.map
178178
working-directory: ./ref_app/

ref_app/cmake/gcc-toolchain.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
##############################################################################
2-
# Copyright Christopher Kormanyos 2021.
2+
# Copyright Christopher Kormanyos 2021 - 2025.
33
# Distributed under the Boost Software License,
44
# Version 1.0. (See accompanying file LICENSE_1_0.txt
55
# or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -94,7 +94,7 @@ set(GCCFLAGS
9494
-g
9595
-Wall
9696
-Wextra
97-
-pedantic
97+
-Wpedantic
9898
-Wmain
9999
-Wundef
100100
-Wsign-conversion

ref_app/src/app/benchmark/app_benchmark_trapezoid_integral.cpp

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
///////////////////////////////////////////////////////////////////////////////
2-
// Copyright Christopher Kormanyos 2021 - 2024.
2+
// Copyright Christopher Kormanyos 2021 - 2025.
33
// Distributed under the Boost Software License,
44
// Version 1.0. (See accompanying file LICENSE_1_0.txt
55
// or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -31,17 +31,17 @@
3131
#if (defined(STDFLOAT_FLOAT64_NATIVE_TYPE) || (defined(__STDCPP_FLOAT64_T__) && (__STDCPP_FLOAT64_T__ == 1)))
3232

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

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

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

4141
#else
4242

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

4646
#endif
4747

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

59-
namespace
59+
namespace local
6060
{
6161
template<typename FloatingPointType>
6262
auto cyl_bessel_j(const std::uint_fast8_t n, const FloatingPointType& x) -> FloatingPointType
6363
{
6464
using local_float_type = FloatingPointType;
6565

66-
constexpr auto epsilon = std::numeric_limits<local_float_type>::epsilon();
67-
6866
using std::sqrt;
6967

70-
const auto tol = sqrt(epsilon);
71-
72-
const auto integration_result =
73-
math::integral(static_cast<local_float_type>(0),
74-
math::constants::pi<local_float_type>(),
75-
tol,
76-
[&x, &n](const local_float_type& t) noexcept
77-
{
78-
using std::cos;
79-
using std::sin;
80-
81-
return
82-
static_cast<local_float_type>
83-
(
84-
cos(x * sin(t) - (t * static_cast<local_float_type>(n)))
85-
);
86-
});
68+
const local_float_type tol { sqrt(std::numeric_limits<local_float_type>::epsilon()) };
69+
70+
const local_float_type
71+
integration_result
72+
{
73+
math::integral
74+
(
75+
static_cast<local_float_type>(0),
76+
math::constants::pi<local_float_type>(),
77+
tol,
78+
[&x, &n](const local_float_type& t) noexcept
79+
{
80+
using std::cos;
81+
using std::sin;
82+
83+
return cos(static_cast<local_float_type>((x * sin(t)) - (t * static_cast<local_float_type>(n))));
84+
}
85+
)
86+
};
8787

8888
return integration_result / math::constants::pi<local_float_type>();
8989
}
90-
}
90+
} // namespace local
9191

9292
auto app::benchmark::run_trapezoid_integral() -> bool
9393
{
94-
constexpr auto app_benchmark_tolerance =
95-
static_cast<my_float_type>
96-
(
94+
constexpr my_float_type
95+
app_benchmark_tolerance
96+
{
9797
std::numeric_limits<my_float_type>::epsilon() * static_cast<my_float_type>(100.0L)
98-
);
98+
};
9999

100-
// Compute y = cyl_bessel_j(2, 1.23) = 0.16636938378681407351267852431513159437103348245333
100+
// Test the value of a Bessel function.
101+
// Here is a control value from Wolfram Alpha.
101102
// N[BesselJ[2, 123/100], 50]
102-
const auto j2 = cyl_bessel_j(static_cast<std::uint_fast8_t>(UINT8_C(2)), static_cast<my_float_type>(1.23L));
103+
// 0.16636938378681407351267852431513159437103348245333
104+
105+
// Compute cyl_bessel_j(2, 1.23)
106+
107+
const my_float_type j2 { local::cyl_bessel_j(std::uint_fast8_t { UINT8_C(2) }, static_cast<my_float_type>(1.23L)) };
103108

104109
const bool app_benchmark_result_is_ok =
105110
detail::is_close_fraction
Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,68 @@
11
///////////////////////////////////////////////////////////////////////////////
2-
// Copyright Christopher Kormanyos 2007 - 2021.
2+
// Copyright Christopher Kormanyos 2007 - 2025.
33
// Distributed under the Boost Software License,
44
// Version 1.0. (See accompanying file LICENSE_1_0.txt
55
// or copy at http://www.boost.org/LICENSE_1_0.txt)
66
//
77

8-
#ifndef INTEGRAL_2012_01_09_H_
9-
#define INTEGRAL_2012_01_09_H_
8+
#ifndef INTEGRAL_2012_01_09_H
9+
#define INTEGRAL_2012_01_09_H
1010

11-
#include <cmath>
11+
#include <cmath>
1212

13-
namespace math
14-
{
15-
template<typename real_value_type,
16-
typename real_function_type>
17-
real_value_type integral(const real_value_type& a,
18-
const real_value_type& b,
19-
const real_value_type& tol,
20-
real_function_type real_function)
21-
{
22-
std::uint_fast32_t n2(1);
13+
namespace math
14+
{
15+
// Compute the numerical integral of a real function from a to b
16+
// using a recursive trapezoid rule.
2317

24-
real_value_type step = ((b - a) / 2U);
18+
template<typename real_value_type,
19+
typename real_function_type>
20+
real_value_type integral(const real_value_type& a,
21+
const real_value_type& b,
22+
const real_value_type& tol,
23+
real_function_type real_function)
24+
{
25+
std::uint_fast32_t n2 { UINT8_C(1) };
2526

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

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

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

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

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

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

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

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

47-
const real_value_type ratio = fabs(tmp / result);
48+
const real_value_type ratio { tmp / result };
4849

49-
const real_value_type delta = fabs(ratio - 1U);
50+
using std::fabs;
5051

51-
if((k > UINT8_C(1)) && (delta < tol))
52-
{
53-
break;
54-
}
52+
const real_value_type delta = fabs(ratio - 1U);
5553

56-
n2 *= 2U;
54+
if((k > std::uint_fast8_t { UINT8_C(1) }) && (delta < tol))
55+
{
56+
break;
57+
}
5758

58-
step /= 2U;
59-
}
59+
n2 *= 2U;
6060

61-
return result;
62-
}
63-
}
61+
step /= 2U;
62+
}
6463

65-
#endif // INTEGRAL_2012_01_09_H_
64+
return result;
65+
}
66+
}
67+
68+
#endif // INTEGRAL_2012_01_09_H

ref_app/src/mcal/mcal_gcc_cxx_completion.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ extern "C"
8989
// and objects.
9090

9191
void abort () __attribute__((noreturn));
92-
int atexit (void (*)()) noexcept;
92+
int atexit (void (*)());
9393
int at_quick_exit (void (*)());
9494
void _Exit (int) __attribute__((noreturn));
9595
void exit (int) __attribute__((noreturn));
@@ -111,7 +111,7 @@ extern "C"
111111
// Implementations of patched functions.
112112

113113
void abort () { for(;;) { mcal::cpu::nop(); } }
114-
int atexit (void (*)()) noexcept { return 0; }
114+
int atexit (void (*)()) { return 0; }
115115
int at_quick_exit (void (*)()) { return 0; }
116116
void _Exit (int) { for(;;) { mcal::cpu::nop(); } }
117117
void exit (int) { for(;;) { mcal::cpu::nop(); } }

ref_app/src/sys/start/sys_start.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#if (defined(__XTENSA__) && !defined(CONFIG_IDF_TARGET_ESP32S3))
1818
extern "C" ATTRIBUTE(used) auto app_main_loop() -> int;
1919
#else
20-
extern "C" ATTRIBUTE(used) auto main() -> int;
20+
ATTRIBUTE(used) auto main() -> int;
2121
#endif
2222

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

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

ref_app/src/util/STL/cmath

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,25 @@
4141
#define NAN (-(float)(INFINITY * 0.0F))
4242
#endif
4343

44-
#define _DENORM (-2)
45-
#define _FINITE (-1)
46-
#define _INFCODE 1
47-
#define _NANCODE 2
48-
49-
#define FP_INFINITE _INFCODE
50-
#define FP_NAN _NANCODE
51-
#define FP_NORMAL _FINITE
52-
#define FP_SUBNORMAL _DENORM
53-
#define FP_ZERO 0
44+
#if !defined(FP_NAN)
45+
#define FP_NAN 0
46+
#endif
47+
#if !defined(FP_INFINITE)
48+
#define FP_INFINITE 1
49+
#endif
50+
#if !defined(FP_ZERO)
51+
#define FP_ZERO 2
52+
#endif
53+
#if !defined(FP_SUBNORMAL)
54+
#define FP_SUBNORMAL 3
55+
#endif
56+
#if !defined(FP_NORMAL)
57+
#define FP_NORMAL 4
58+
#endif
5459

55-
#define _C2 1 // 0 if not 2's complement
56-
#define FP_ILOGB0 (-0x7fffffff - _C2)
57-
#define FP_ILOGBNAN 0x7fffffff
60+
#define _C2 1L // 0 if not 2's complement
61+
#define FP_ILOGB0 (-0x7fffffffL - _C2)
62+
#define FP_ILOGBNAN 0x7fffffffL
5863

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

250255
namespace std
251256
{
257+
using float_t = float;
258+
using double_t = double;
259+
252260
inline bool isnan (float x) { return (__BUILTIN_ISNANF(x) == 1); }
253261
inline bool isnan (double x) { return (__BUILTIN_ISNAN (x) == 1); }
254262
inline bool isnan (long double x) { return (__BUILTIN_ISNANL(x) == 1); }
@@ -688,24 +696,27 @@
688696
}
689697
#endif
690698

691-
#if !defined(FP_INFINITE)
692-
#define FP_INFINITE 1
693-
#endif
694699
#if !defined(FP_NAN)
695-
#define FP_NAN 2
700+
#define FP_NAN 0
696701
#endif
697-
#if !defined(FP_NORMAL)
698-
#define FP_NORMAL (-1)
702+
#if !defined(FP_INFINITE)
703+
#define FP_INFINITE 1
704+
#endif
705+
#if !defined(FP_ZERO)
706+
#define FP_ZERO 2
699707
#endif
700708
#if !defined(FP_SUBNORMAL)
701-
#define FP_SUBNORMAL (-2)
709+
#define FP_SUBNORMAL 3
702710
#endif
703-
#if !defined(FP_ZERO)
704-
#define FP_ZERO 0
711+
#if !defined(FP_NORMAL)
712+
#define FP_NORMAL 4
705713
#endif
706714

707715
namespace std
708716
{
717+
using float_t = float;
718+
using double_t = double;
719+
709720
using ::isfinite;
710721
using ::ilogb;
711722

ref_app/src/util/STL/stdfloat

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
///////////////////////////////////////////////////////////////////////////////
2-
// Copyright Christopher Kormanyos 2007 - 2024.
2+
// Copyright Christopher Kormanyos 2007 - 2025.
33
// Distributed under the Boost Software License,
44
// Version 1.0. (See accompanying file LICENSE_1_0.txt
55
// or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -12,6 +12,8 @@
1212
#pragma GCC system_header
1313
#endif
1414

15+
#include <limits>
16+
1517
namespace std
1618
{
1719
using float32_t = float;
@@ -32,4 +34,7 @@
3234
#endif
3335
}
3436

37+
static_assert((std::numeric_limits<std::float32_t>::digits == 24), "Error: Incorrect float32_t type definition");
38+
static_assert((std::numeric_limits<std::float64_t>::digits == 53), "Error: Incorrect float64_t type definition");
39+
3540
#endif // STDFLOAT_2024_07_12

0 commit comments

Comments
 (0)