From 606dda21c8bcd4c2574e5b28f8125f01e38955c6 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 3 Oct 2016 18:01:10 +0100 Subject: Define std::gcd and std::lcm for C++17 * doc/xml/manual/status_cxx2017.xml: Update gcd/lcm status. * doc/html/*: Regenerate. * include/experimental/numeric (__abs): Move to . (gcd, lcm): Use __detail::gcd and __detail::lcm. * include/std/numeric (__detail::__abs_integral) (__detail::__gcd, __detail::__lcm): Define. (gcd, lcm): Define for C++17. * testsuite/26_numerics/gcd/1.cc: New test. * testsuite/26_numerics/lcm/1.cc: New test. * testsuite/experimental/numeric/gcd.cc: Swap contents with ... * testsuite/experimental/numeric/lcd.cc: ... this. From-SVN: r240723 --- libstdc++-v3/include/std/numeric | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'libstdc++-v3/include/std/numeric') diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric index 47a7cb8..7b1ab98 100644 --- a/libstdc++-v3/include/std/numeric +++ b/libstdc++-v3/include/std/numeric @@ -74,4 +74,83 @@ * math functions. */ +#if __cplusplus >= 201402L +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __detail +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // std::abs is not constexpr and doesn't support unsigned integers. + template + constexpr + enable_if_t<__and_, is_signed<_Tp>>::value, _Tp> + __abs_integral(_Tp __val) + { return __val < 0 ? -__val : __val; } + + template + constexpr + enable_if_t<__and_, is_unsigned<_Tp>>::value, _Tp> + __abs_integral(_Tp __val) + { return __val; } + + template + constexpr common_type_t<_Mn, _Nn> + __gcd(_Mn __m, _Nn __n) + { + return __m == 0 ? __detail::__abs_integral(__n) + : __n == 0 ? __detail::__abs_integral(__m) + : __detail::__gcd(__n, __m % __n); + } + + /// Least common multiple + template + constexpr common_type_t<_Mn, _Nn> + __lcm(_Mn __m, _Nn __n) + { + return (__m != 0 && __n != 0) + ? (__detail::__abs_integral(__m) / __detail::__gcd(__m, __n)) + * __detail::__abs_integral(__n) + : 0; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} + +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus > 201402L + +#define __cpp_lib_gcd 201606 + /// Greatest common divisor + template + constexpr common_type_t<_Mn, _Nn> + gcd(_Mn __m, _Nn __n) + { + static_assert(is_integral<_Mn>::value, "arguments to gcd are integers"); + static_assert(is_integral<_Nn>::value, "arguments to gcd are integers"); + return __detail::__gcd(__m, __n); + } + +#define __cpp_lib_lcm 201606 + /// Least common multiple + template + constexpr common_type_t<_Mn, _Nn> + lcm(_Mn __m, _Nn __n) + { + static_assert(is_integral<_Mn>::value, "arguments to lcm are integers"); + static_assert(is_integral<_Nn>::value, "arguments to lcm are integers"); + return __detail::__lcm(__m, __n); + } + +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + + #endif /* _GLIBCXX_NUMERIC */ -- cgit v1.1