mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Merge branch 'pull-request/#1014-Added-missing-rational-arithmetic-functions-from-ratio' into development
# Conflicts: # .gitignore # test/vs2022/etl.vcxproj.filters
This commit is contained in:
commit
c3d3a326f7
@ -33,6 +33,8 @@ SOFTWARE.
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -41,17 +43,17 @@ SOFTWARE.
|
||||
|
||||
namespace etl
|
||||
{
|
||||
template <size_t NUM, size_t DEN = 1UL>
|
||||
template <intmax_t NUM, intmax_t DEN = 1UL>
|
||||
struct ratio
|
||||
{
|
||||
static ETL_CONSTANT intmax_t num = NUM;
|
||||
static ETL_CONSTANT intmax_t den = DEN;
|
||||
};
|
||||
|
||||
template <size_t NUM, size_t DEN>
|
||||
template <intmax_t NUM, intmax_t DEN>
|
||||
ETL_CONSTANT intmax_t ratio<NUM, DEN>::num;
|
||||
|
||||
template <size_t NUM, size_t DEN>
|
||||
template <intmax_t NUM, intmax_t DEN>
|
||||
ETL_CONSTANT intmax_t ratio<NUM, DEN>::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 <typename T, T A, T B, bool = (B == 0)>
|
||||
struct ratio_gcd;
|
||||
|
||||
// Specialisation for the case when B is not zero
|
||||
template <typename T, T A, T B>
|
||||
struct ratio_gcd<T, A, B, false>
|
||||
{
|
||||
static constexpr T value = ratio_gcd<T, B, A % B>::value;
|
||||
};
|
||||
|
||||
// Specialisation for the case when B is zero
|
||||
template <typename T, T A, T B>
|
||||
struct ratio_gcd<T, A, B, true>
|
||||
{
|
||||
static constexpr T value = (A < 0) ? -A : A;
|
||||
};
|
||||
|
||||
// Primary template for LCM calculation
|
||||
template <typename T, T A, T B>
|
||||
struct ratio_lcm
|
||||
{
|
||||
private:
|
||||
|
||||
static constexpr T product = ((A * B) < 0) ? -(A * B) : A * B;
|
||||
|
||||
public:
|
||||
|
||||
static constexpr T value = product / ratio_gcd<T, A, B>::value;
|
||||
};
|
||||
|
||||
template<typename R1>
|
||||
struct ratio_reduce
|
||||
{
|
||||
private:
|
||||
|
||||
static ETL_CONSTEXPR11 intmax_t gcd = etl::private_ratio::ratio_gcd<intmax_t, R1::num, R1::den>::value;
|
||||
|
||||
public:
|
||||
|
||||
using type = ratio<R1::num / gcd, R1::den / gcd>;
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_add
|
||||
{
|
||||
private:
|
||||
|
||||
static ETL_CONSTEXPR11 intmax_t lcm = etl::private_ratio::ratio_lcm<intmax_t, R1::den, R2::den>::value;
|
||||
|
||||
public:
|
||||
|
||||
using type = typename ratio_reduce<ratio<R1::num * lcm / R1::den + R2::num * lcm / R2::den, lcm>>::type;
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_subtract
|
||||
{
|
||||
public:
|
||||
using type = typename ratio_add<R1, ratio<-R2::num, R2::den>>::type;
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_multiply
|
||||
{
|
||||
private:
|
||||
static ETL_CONSTEXPR11 intmax_t gcd1 = etl::private_ratio::ratio_gcd<intmax_t, R1::num, R2::den>::value;
|
||||
static ETL_CONSTEXPR11 intmax_t gcd2 = etl::private_ratio::ratio_gcd<intmax_t, R2::num, R1::den>::value;
|
||||
|
||||
public:
|
||||
using type = ratio<(R1::num / gcd1) * (R2::num / gcd2), (R1::den / gcd2) * (R2::den / gcd1)>;
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_divide
|
||||
{
|
||||
public:
|
||||
using type = typename ratio_multiply<R1, ratio<R2::den, R2::num>>::type;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename R1, typename R2>
|
||||
using ratio_add = typename private_ratio::ratio_add<R1, R2>::type;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
using ratio_subtract = typename private_ratio::ratio_subtract<R1, R2>::type;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
using ratio_multiply = typename private_ratio::ratio_multiply<R1, R2>::type;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
using ratio_divide = typename private_ratio::ratio_divide<R1, R2>::type;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_equal : etl::integral_constant<bool, (R1::num == R2::num && R1::den == R2::den)>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_not_equal : etl::integral_constant<bool, (R1::num != R2::num || R1::den != R2::den)>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_less : etl::integral_constant<bool, (R1::num * R2::den < R2::num * R1::den)>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_less_equal : etl::integral_constant<bool, (R1::num * R2::den <= R2::num * R1::den)>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_greater : etl::integral_constant<bool, (R1::num * R2::den > R2::num * R1::den)>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename R1, typename R2>
|
||||
struct ratio_greater_equal: etl::integral_constant<bool, (R1::num * R2::den >= R2::num * R1::den)>
|
||||
{
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
template<typename R1, typename R2>
|
||||
ETL_CONSTEXPR14 bool ratio_equal_v = ratio_equal<R1, R2>::value;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
ETL_CONSTEXPR14 bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
ETL_CONSTEXPR14 bool ratio_less_v = ratio_less<R1, R2>::value;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
ETL_CONSTEXPR14 bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
ETL_CONSTEXPR14 bool ratio_greater_v = ratio_greater<R1, R2>::value;
|
||||
|
||||
template<typename R1, typename R2>
|
||||
ETL_CONSTEXPR14 bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -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
|
||||
|
||||
174
test/test_ratio.cpp
Normal file
174
test/test_ratio.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/******************************************************************************
|
||||
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<r1, r2>;
|
||||
|
||||
CHECK((etl::ratio_equal<r3, etl::ratio<7, 6>>::value));
|
||||
CHECK((!etl::ratio_equal<r3, etl::ratio<1, 6>>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_subtract)
|
||||
{
|
||||
using r1 = etl::ratio<1, 2>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
using r3 = etl::ratio_subtract<r1, r2>;
|
||||
|
||||
CHECK((etl::ratio_equal<r3, etl::ratio<-1, 6>>::value));
|
||||
CHECK((!etl::ratio_equal<r3, etl::ratio<-2, 6>>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_multiply)
|
||||
{
|
||||
using r1 = etl::ratio<1, 2>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
using r3 = etl::ratio_multiply<r1, r2>;
|
||||
|
||||
CHECK((etl::ratio_equal<r3, etl::ratio<1, 3>>::value));
|
||||
CHECK((!etl::ratio_equal<r3, etl::ratio<1, 4>>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_divide)
|
||||
{
|
||||
using r1 = etl::ratio<1, 2>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
using r3 = etl::ratio_divide<r1, r2>;
|
||||
|
||||
CHECK((!etl::ratio_not_equal<r3, etl::ratio<3, 4>>::value));
|
||||
CHECK((etl::ratio_not_equal<r3, etl::ratio<4, 3>>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_equal)
|
||||
{
|
||||
using r1 = etl::ratio<1, 2>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
|
||||
CHECK((etl::ratio_equal<r1, r1>::value));
|
||||
CHECK((!etl::ratio_equal<r1, r2>::value));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
CHECK((etl::ratio_equal_v<r1, r1>));
|
||||
CHECK((!etl::ratio_equal_v<r1, r2>));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_not_equal)
|
||||
{
|
||||
using r1 = etl::ratio<1, 2>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
|
||||
CHECK((!etl::ratio_not_equal<r1, r1>::value));
|
||||
CHECK((etl::ratio_not_equal<r1, r2>::value));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
CHECK((!etl::ratio_not_equal_v<r1, r1>));
|
||||
CHECK((etl::ratio_not_equal_v<r1, r2>));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_less)
|
||||
{
|
||||
using r1 = etl::ratio<1, 2>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
|
||||
CHECK((etl::ratio_less<r1, r2>::value));
|
||||
CHECK((!etl::ratio_less<r2, r1>::value));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
CHECK((etl::ratio_less_v<r1, r2>));
|
||||
CHECK((!etl::ratio_less_v<r1, r1>));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_less_equal)
|
||||
{
|
||||
using r1 = etl::ratio<1, 2>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
|
||||
CHECK((etl::ratio_less_equal<r1, r1>::value));
|
||||
CHECK((etl::ratio_less_equal<r1, r2>::value));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
CHECK((etl::ratio_less_equal_v<r1, r1>));
|
||||
CHECK((etl::ratio_less_equal_v<r1, r1>));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_greater)
|
||||
{
|
||||
using r1 = etl::ratio<4, 3>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
|
||||
CHECK((etl::ratio_greater<r1, r2>::value));
|
||||
CHECK((!etl::ratio_greater<r2, r1>::value));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
CHECK((etl::ratio_greater_v<r1, r2>));
|
||||
CHECK((!etl::ratio_greater_v<r2, r1>));
|
||||
#endif
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_ratio_greater_equal)
|
||||
{
|
||||
using r1 = etl::ratio<4, 3>;
|
||||
using r2 = etl::ratio<2, 3>;
|
||||
|
||||
CHECK((etl::ratio_greater_equal<r1, r1>::value));
|
||||
CHECK((etl::ratio_greater_equal<r1, r2>::value));
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
CHECK((etl::ratio_greater_equal_v<r1, r1>));
|
||||
CHECK((etl::ratio_greater_equal_v<r1, r2>));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@ -8960,6 +8960,7 @@
|
||||
<ClCompile Include="..\test_quantize.cpp" />
|
||||
<ClCompile Include="..\test_queue_lockable.cpp" />
|
||||
<ClCompile Include="..\test_queue_lockable_small.cpp" />
|
||||
<ClCompile Include="..\test_ratio.cpp" />
|
||||
<ClCompile Include="..\test_rescale.cpp" />
|
||||
<ClCompile Include="..\test_result.cpp" />
|
||||
<ClCompile Include="..\test_rms.cpp" />
|
||||
|
||||
@ -3398,6 +3398,9 @@
|
||||
<ClCompile Include="..\syntax_check\stringify.h.t.cpp">
|
||||
<Filter>Tests\Syntax Checks\Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_ratio.cpp">
|
||||
<Filter>Tests\Maths</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_uncopyable.cpp">
|
||||
<Filter>Tests\Misc</Filter>
|
||||
</ClCompile>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user