From 360f503bcfdcb89f2a77ed09915d063f4840286d Mon Sep 17 00:00:00 2001 From: rolandreichweinbmw Date: Wed, 22 Jan 2025 18:15:53 +0100 Subject: [PATCH 1/3] Added missing rational arithmetic functions from (#1014) * Added ratio traits * Fix unused test suite in < C++14 case * Port to C++11 * Fix header includes --- include/etl/ratio.h | 155 +++++++++++++++++++++++++++++++++++++++++++- test/CMakeLists.txt | 1 + test/test_ratio.cpp | 144 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 test/test_ratio.cpp diff --git a/include/etl/ratio.h b/include/etl/ratio.h index 8c7fa81d..1035e774 100644 --- a/include/etl/ratio.h +++ b/include/etl/ratio.h @@ -33,6 +33,8 @@ SOFTWARE. #include "platform.h" +#include "type_traits.h" + #include #include @@ -41,17 +43,17 @@ SOFTWARE. namespace etl { - template + template struct ratio { static ETL_CONSTANT intmax_t num = NUM; static ETL_CONSTANT intmax_t den = DEN; }; - template + template ETL_CONSTANT intmax_t ratio::num; - template + template ETL_CONSTANT intmax_t ratio::den; #if INT_MAX > INT32_MAX @@ -97,6 +99,153 @@ namespace etl /// An approximation of e. typedef ratio<326, 120> ratio_e; + +#if ETL_USING_CPP11 + namespace private_ratio + { + // Primary template for GCD calculation + template + struct ratio_gcd; + + // Specialisation for the case when B is not zero + template + struct ratio_gcd + { + static constexpr T value = ratio_gcd::value; + }; + + // Specialisation for the case when B is zero + template + struct ratio_gcd + { + static constexpr T value = (A < 0) ? -A : A; + }; + + // Primary template for LCM calculation + template + struct ratio_lcm + { + private: + + static constexpr T product = ((A * B) < 0) ? -(A * B) : A * B; + + public: + + static constexpr T value = product / ratio_gcd::value; + }; + + template + struct ratio_reduce + { + private: + + static ETL_CONSTEXPR11 intmax_t gcd = etl::private_ratio::ratio_gcd::value; + + public: + + using value = ratio; + }; + + template + struct ratio_add + { + private: + + static ETL_CONSTEXPR11 intmax_t lcm = etl::private_ratio::ratio_lcm::value; + + public: + + using value = typename ratio_reduce>::value; + }; + + template + struct ratio_subtract + { + public: + using value = typename ratio_add>::value; + }; + + template + struct ratio_multiply + { + private: + static ETL_CONSTEXPR11 intmax_t gcd1 = etl::private_ratio::ratio_gcd::value; + static ETL_CONSTEXPR11 intmax_t gcd2 = etl::private_ratio::ratio_gcd::value; + + public: + using value = ratio<(R1::num / gcd1) * (R2::num / gcd2), (R1::den / gcd2) * (R2::den / gcd1)>; + }; + + template + struct ratio_divide + { + public: + using value = typename ratio_multiply>::value; + }; + } + + template + using ratio_add = typename private_ratio::ratio_add::value; + + template + using ratio_subtract = typename private_ratio::ratio_subtract::value; + + template + using ratio_multiply = typename private_ratio::ratio_multiply::value; + + template + using ratio_divide = typename private_ratio::ratio_divide::value; + + template + struct ratio_equal: etl::integral_constant + { + }; + + template + struct ratio_not_equal: etl::integral_constant + { + }; + + template + struct ratio_less: etl::integral_constant + { + }; + + template + struct ratio_less_equal: etl::integral_constant + { + }; + + template + struct ratio_greater: etl::integral_constant R2::num * R1::den)> + { + }; + + template + struct ratio_greater_equal: etl::integral_constant= R2::num * R1::den)> + { + }; + +#if ETL_USING_CPP14 + template + ETL_CONSTEXPR14 bool ratio_equal_v = ratio_equal::value; + + template + ETL_CONSTEXPR14 bool ratio_not_equal_v = ratio_not_equal::value; + + template + ETL_CONSTEXPR14 bool ratio_less_v = ratio_less::value; + + template + ETL_CONSTEXPR14 bool ratio_less_equal_v = ratio_less_equal::value; + + template + ETL_CONSTEXPR14 bool ratio_greater_v = ratio_greater::value; + + template + ETL_CONSTEXPR14 bool ratio_greater_equal_v = ratio_greater_equal::value; +#endif +#endif } #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ce9e2a66..725b6928 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -222,6 +222,7 @@ add_executable(etl_tests test_queue_spsc_locked.cpp test_queue_spsc_locked_small.cpp test_random.cpp + test_ratio.cpp test_reference_flat_map.cpp test_reference_flat_multimap.cpp test_reference_flat_multiset.cpp diff --git a/test/test_ratio.cpp b/test/test_ratio.cpp new file mode 100644 index 00000000..12a0b406 --- /dev/null +++ b/test/test_ratio.cpp @@ -0,0 +1,144 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/ratio.h" + +#if ETL_USING_CPP11 +namespace +{ + SUITE(test_ratio) + { + //************************************************************************* + TEST(test_ratio_add) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + using r3 = etl::ratio_add; + + CHECK((etl::ratio_equal>::value)); + CHECK((!etl::ratio_equal>::value)); + } + + //************************************************************************* + TEST(test_ratio_subtract) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + using r3 = etl::ratio_subtract; + + CHECK((etl::ratio_equal>::value)); + CHECK((!etl::ratio_equal>::value)); + } + + //************************************************************************* + TEST(test_ratio_multiply) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + using r3 = etl::ratio_multiply; + + CHECK((etl::ratio_equal>::value)); + CHECK((!etl::ratio_equal>::value)); + } + + //************************************************************************* + TEST(test_ratio_divide) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + using r3 = etl::ratio_divide; + + CHECK((!etl::ratio_not_equal>::value)); + CHECK((etl::ratio_not_equal>::value)); + } + + //************************************************************************* + TEST(test_ratio_equal) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + + CHECK((etl::ratio_equal::value)); + CHECK((!etl::ratio_equal::value)); + } + + //************************************************************************* + TEST(test_ratio_not_equal) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + + CHECK((!etl::ratio_not_equal::value)); + CHECK((etl::ratio_not_equal::value)); + } + + //************************************************************************* + TEST(test_ratio_less) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + + CHECK((etl::ratio_less::value)); + CHECK((!etl::ratio_less::value)); + } + + //************************************************************************* + TEST(test_ratio_less_equal) + { + using r1 = etl::ratio<1, 2>; + using r2 = etl::ratio<2, 3>; + + CHECK((etl::ratio_less_equal::value)); + CHECK((etl::ratio_less_equal::value)); + } + + //************************************************************************* + TEST(test_ratio_greater) + { + using r1 = etl::ratio<4, 3>; + using r2 = etl::ratio<2, 3>; + + CHECK((etl::ratio_greater::value)); + CHECK((!etl::ratio_greater::value)); + } + + //************************************************************************* + TEST(test_ratio_greater_equal) + { + using r1 = etl::ratio<4, 3>; + using r2 = etl::ratio<2, 3>; + + CHECK((etl::ratio_greater_equal::value)); + CHECK((etl::ratio_greater_equal::value)); + } + }; + +} +#endif From 44df80219b88ab4d76b1c094f89d99a7e4f3b168 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 23 Jan 2025 09:37:40 +0000 Subject: [PATCH 2/3] Changed 'value' to 'type' Added C++14 constant tests --- include/etl/ratio.h | 28 ++++++++++++++-------------- test/test_ratio.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/include/etl/ratio.h b/include/etl/ratio.h index 1035e774..738fdfb7 100644 --- a/include/etl/ratio.h +++ b/include/etl/ratio.h @@ -143,7 +143,7 @@ namespace etl public: - using value = ratio; + using type = ratio; }; template @@ -155,14 +155,14 @@ namespace etl public: - using value = typename ratio_reduce>::value; + using type = typename ratio_reduce>::type; }; template struct ratio_subtract { public: - using value = typename ratio_add>::value; + using type = typename ratio_add>::type; }; template @@ -173,51 +173,51 @@ namespace etl static ETL_CONSTEXPR11 intmax_t gcd2 = etl::private_ratio::ratio_gcd::value; public: - using value = ratio<(R1::num / gcd1) * (R2::num / gcd2), (R1::den / gcd2) * (R2::den / gcd1)>; + using type = ratio<(R1::num / gcd1) * (R2::num / gcd2), (R1::den / gcd2) * (R2::den / gcd1)>; }; template struct ratio_divide { public: - using value = typename ratio_multiply>::value; + using type = typename ratio_multiply>::type; }; } template - using ratio_add = typename private_ratio::ratio_add::value; + using ratio_add = typename private_ratio::ratio_add::type; template - using ratio_subtract = typename private_ratio::ratio_subtract::value; + using ratio_subtract = typename private_ratio::ratio_subtract::type; template - using ratio_multiply = typename private_ratio::ratio_multiply::value; + using ratio_multiply = typename private_ratio::ratio_multiply::type; template - using ratio_divide = typename private_ratio::ratio_divide::value; + using ratio_divide = typename private_ratio::ratio_divide::type; template - struct ratio_equal: etl::integral_constant + struct ratio_equal : etl::integral_constant { }; template - struct ratio_not_equal: etl::integral_constant + struct ratio_not_equal : etl::integral_constant { }; template - struct ratio_less: etl::integral_constant + struct ratio_less : etl::integral_constant { }; template - struct ratio_less_equal: etl::integral_constant + struct ratio_less_equal : etl::integral_constant { }; template - struct ratio_greater: etl::integral_constant R2::num * R1::den)> + struct ratio_greater : etl::integral_constant R2::num * R1::den)> { }; diff --git a/test/test_ratio.cpp b/test/test_ratio.cpp index 12a0b406..863bd5cd 100644 --- a/test/test_ratio.cpp +++ b/test/test_ratio.cpp @@ -87,6 +87,11 @@ namespace CHECK((etl::ratio_equal::value)); CHECK((!etl::ratio_equal::value)); + +#if ETL_USING_CPP14 + CHECK((etl::ratio_equal_v)); + CHECK((!etl::ratio_equal_v)); +#endif } //************************************************************************* @@ -97,6 +102,11 @@ namespace CHECK((!etl::ratio_not_equal::value)); CHECK((etl::ratio_not_equal::value)); + +#if ETL_USING_CPP14 + CHECK((!etl::ratio_not_equal_v)); + CHECK((etl::ratio_not_equal_v)); +#endif } //************************************************************************* @@ -107,6 +117,11 @@ namespace CHECK((etl::ratio_less::value)); CHECK((!etl::ratio_less::value)); + +#if ETL_USING_CPP14 + CHECK((etl::ratio_less_v)); + CHECK((!etl::ratio_less_v)); +#endif } //************************************************************************* @@ -117,6 +132,11 @@ namespace CHECK((etl::ratio_less_equal::value)); CHECK((etl::ratio_less_equal::value)); + +#if ETL_USING_CPP14 + CHECK((etl::ratio_less_equal_v)); + CHECK((etl::ratio_less_equal_v)); +#endif } //************************************************************************* @@ -127,6 +147,11 @@ namespace CHECK((etl::ratio_greater::value)); CHECK((!etl::ratio_greater::value)); + +#if ETL_USING_CPP14 + CHECK((etl::ratio_greater_v)); + CHECK((!etl::ratio_greater_v)); +#endif } //************************************************************************* @@ -137,6 +162,11 @@ namespace CHECK((etl::ratio_greater_equal::value)); CHECK((etl::ratio_greater_equal::value)); + +#if ETL_USING_CPP14 + CHECK((etl::ratio_greater_equal_v)); + CHECK((etl::ratio_greater_equal_v)); +#endif } }; From a8c6b116ab1c322adc83814073401145c9b6d267 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 23 Jan 2025 09:39:16 +0000 Subject: [PATCH 3/3] Added test_ratio to VS2022 project --- .gitignore | 1 + test/vs2022/etl.vcxproj | 1 + test/vs2022/etl.vcxproj.filters | 3 +++ 3 files changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 8f313ddb..6d624695 100644 --- a/.gitignore +++ b/.gitignore @@ -388,3 +388,4 @@ support/time remaining test.xlsx test/vs2022/Debug MSVC C++20 - Force C++03 test/vs2022/Release MSVC C++20 - No STL - Optimised -O2 - Sanitiser test/test_file_list.txt +test/etl_error_handler/assert_function/build-make diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 7506cfa1..24fa574c 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -8883,6 +8883,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 2da095b9..914bfa86 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3386,6 +3386,9 @@ Tests\Syntax Checks\Source + + Tests\Maths +