mirror of
https://github.com/ETLCPP/etl.git
synced 2026-11-09 14:49:53 +08:00
Added GCD and LCM algorithms
This commit is contained in:
parent
384c08f25b
commit
8528ed2b80
139
include/etl/gcd.h
Normal file
139
include/etl/gcd.h
Normal file
@ -0,0 +1,139 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2024 John Wellbelove
|
||||
|
||||
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.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_GDC_INCLUDED
|
||||
#define ETL_GDC_INCLUDED
|
||||
|
||||
#include "type_traits.h"
|
||||
#include "absolute.h"
|
||||
#include "static_assert.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
// Greatest Common Divisor.
|
||||
// For unsigned types.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_unsigned<T>::value, T>::type
|
||||
gcd(T a, T b) ETL_NOEXCEPT
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral type required");
|
||||
|
||||
while (b != 0)
|
||||
{
|
||||
T t = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
// Greatest Common Divisor.
|
||||
// For signed types.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_signed<T>::value, T>::type
|
||||
gcd(T a, T b) ETL_NOEXCEPT
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral type required");
|
||||
|
||||
typedef typename etl::make_unsigned<T>::type utype;
|
||||
|
||||
utype ua = etl::absolute_unsigned(a);
|
||||
utype ub = etl::absolute_unsigned(b);
|
||||
|
||||
return static_cast<T>(gcd(ua, ub));
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
//***************************************************************************
|
||||
// Greatest Common Divisor.
|
||||
// Non-recursive, using an initializer_list.
|
||||
// Top level variadic function.
|
||||
//***************************************************************************
|
||||
template<typename T, typename... TRest>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
T gcd(T first, TRest... rest) ETL_NOEXCEPT
|
||||
{
|
||||
T result = first;
|
||||
|
||||
for (T value : {rest...})
|
||||
{
|
||||
result = gcd(result, value);
|
||||
|
||||
if (result == 1)
|
||||
{
|
||||
// Early termination: if the GCD is one, it will remain one
|
||||
// no matter what other numbers are processed.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
//***************************************************************************
|
||||
// Greatest Common Divisor.
|
||||
// Recursive.
|
||||
// Top level variadic function.
|
||||
//***************************************************************************
|
||||
template<typename T, typename... TRest>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
T gcd(T a, T b, TRest... rest) ETL_NOEXCEPT
|
||||
{
|
||||
T gcd_ab = gcd(a, b);
|
||||
|
||||
if (gcd_ab == 1)
|
||||
{
|
||||
// Early termination: if the GCD is one, it will remain one
|
||||
// no matter what other numbers are processed.
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return gcd(gcd_ab, rest...);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
141
include/etl/lcm.h
Normal file
141
include/etl/lcm.h
Normal file
@ -0,0 +1,141 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2024 John Wellbelove
|
||||
|
||||
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.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_LCM_INCLUDED
|
||||
#define ETL_LCM_INCLUDED
|
||||
|
||||
#include "type_traits.h"
|
||||
#include "absolute.h"
|
||||
#include "static_assert.h"
|
||||
#include "gcd.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
// Least Common Multiple.
|
||||
// For unsigned types.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_unsigned<T>::value, T>::type
|
||||
lcm(T a, T b) ETL_NOEXCEPT
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral type required");
|
||||
|
||||
// Early termination: if either number is zero, the LCM is zero.
|
||||
if (a == 0 || b == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return a * (b / gcd(a, b));
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
// Least Common Multiple.
|
||||
// For signed types.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_signed<T>::value, T>::type
|
||||
lcm(T a, T b) ETL_NOEXCEPT
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral type required");
|
||||
|
||||
typedef typename etl::make_unsigned<T>::type utype;
|
||||
|
||||
utype ua = etl::absolute_unsigned(a);
|
||||
utype ub = etl::absolute_unsigned(b);
|
||||
|
||||
return static_cast<T>(lcm(ua, ub));
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
//***************************************************************************
|
||||
// Least Common Multiple.
|
||||
// Non-recursive, using an initializer_list.
|
||||
// Top level variadic function.
|
||||
//***************************************************************************
|
||||
template<typename T, typename... TRest>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
T lcm(T first, TRest... rest) ETL_NOEXCEPT
|
||||
{
|
||||
T result = first;
|
||||
|
||||
for (T value : {rest...})
|
||||
{
|
||||
result = lcm(result, value);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
// Early termination: if the LCM is zero, it will remain zero
|
||||
// no matter what other numbers are processed.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
//***************************************************************************
|
||||
// Least Common Multiple.
|
||||
// Recursive
|
||||
// Top level variadic function.
|
||||
//***************************************************************************
|
||||
template<typename T, typename... TRest>
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
T lcm(T a, T b, TRest... rest) ETL_NOEXCEPT
|
||||
{
|
||||
T lcm_ab = lcm(a, b);
|
||||
|
||||
if (lcm_ab == 0)
|
||||
{
|
||||
// Early termination: if the LCM is zero, it will remain zero
|
||||
// no matter what other numbers are processed.
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lcm(lcm_ab, rest...);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -35,6 +35,8 @@ SOFTWARE.
|
||||
#include "etl/sqrt.h"
|
||||
#include "etl/permutations.h"
|
||||
#include "etl/combinations.h"
|
||||
#include "etl/gcd.h"
|
||||
#include "etl/lcm.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -457,5 +459,45 @@ namespace
|
||||
CHECK_EQUAL((combinations(13, 9)), (actual = etl::combinations<13, 9>::value));
|
||||
CHECK_EQUAL((combinations(14, 10)), (actual = etl::combinations<14, 10>::value));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_gdc_for_positive_integers)
|
||||
{
|
||||
CHECK_EQUAL(1, etl::gcd( 3, 5, 7));
|
||||
CHECK_EQUAL(2, etl::gcd( 4, 6, 8));
|
||||
CHECK_EQUAL(3, etl::gcd( 9, 6, 3));
|
||||
CHECK_EQUAL(4, etl::gcd( 8, 4, 12));
|
||||
CHECK_EQUAL(5, etl::gcd(10, 5, 15));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_gdc_for_negative_integers)
|
||||
{
|
||||
CHECK_EQUAL(1, etl::gcd( -3, -5, -7));
|
||||
CHECK_EQUAL(2, etl::gcd( -4, -6, -8));
|
||||
CHECK_EQUAL(3, etl::gcd( -9, -6, -3));
|
||||
CHECK_EQUAL(4, etl::gcd( -8, -4, -12));
|
||||
CHECK_EQUAL(5, etl::gcd(-10, -5, -15));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_lcm_for_positive_integers)
|
||||
{
|
||||
CHECK_EQUAL(12, etl::lcm(3, 4, 6));
|
||||
CHECK_EQUAL(30, etl::lcm(3, 5, 10));
|
||||
CHECK_EQUAL(20, etl::lcm(2, 5, 4));
|
||||
CHECK_EQUAL(0, etl::lcm(0, 5, 7));
|
||||
CHECK_EQUAL(5, etl::lcm(5, 5, 5));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_lcm_for_negative_integers)
|
||||
{
|
||||
CHECK_EQUAL(12, etl::lcm(-3, -4, -6));
|
||||
CHECK_EQUAL(30, etl::lcm(-3, -5, -10));
|
||||
CHECK_EQUAL(20, etl::lcm(-2, -5, -4));
|
||||
CHECK_EQUAL(0, etl::lcm(-0, -5, -7));
|
||||
CHECK_EQUAL(5, etl::lcm(-5, -5, -5));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -3082,6 +3082,8 @@
|
||||
<ClInclude Include="..\..\include\etl\crc8_rohc.h" />
|
||||
<ClInclude Include="..\..\include\etl\crc8_wcdma.h" />
|
||||
<ClInclude Include="..\..\include\etl\expected.h" />
|
||||
<ClInclude Include="..\..\include\etl\gcd.h" />
|
||||
<ClInclude Include="..\..\include\etl\lcm.h" />
|
||||
<ClInclude Include="..\..\include\etl\math.h" />
|
||||
<ClInclude Include="..\..\include\etl\message_broker.h" />
|
||||
<ClInclude Include="..\..\include\etl\poly_span.h" />
|
||||
|
||||
@ -1395,6 +1395,12 @@
|
||||
<ClInclude Include="..\..\include\etl\crc8_j1850_zero.h">
|
||||
<Filter>ETL\Maths\CRC</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\gcd.h">
|
||||
<Filter>ETL\Maths</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\lcm.h">
|
||||
<Filter>ETL\Maths</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test_string_char.cpp">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user