diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-10-03 18:01:10 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-10-03 18:01:10 +0100 |
commit | 606dda21c8bcd4c2574e5b28f8125f01e38955c6 (patch) | |
tree | fbbf846d1547d0889eb640b9c224bef9cb11882b /libstdc++-v3/include/std | |
parent | ec9d5ad13bf6a965007d727d0dcbc77155e8132a (diff) | |
download | gcc-606dda21c8bcd4c2574e5b28f8125f01e38955c6.zip gcc-606dda21c8bcd4c2574e5b28f8125f01e38955c6.tar.gz gcc-606dda21c8bcd4c2574e5b28f8125f01e38955c6.tar.bz2 |
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 <numeric>.
(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
Diffstat (limited to 'libstdc++-v3/include/std')
-rw-r--r-- | libstdc++-v3/include/std/numeric | 79 |
1 files changed, 79 insertions, 0 deletions
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 <type_traits> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __detail +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // std::abs is not constexpr and doesn't support unsigned integers. + template<typename _Tp> + constexpr + enable_if_t<__and_<is_integral<_Tp>, is_signed<_Tp>>::value, _Tp> + __abs_integral(_Tp __val) + { return __val < 0 ? -__val : __val; } + + template<typename _Tp> + constexpr + enable_if_t<__and_<is_integral<_Tp>, is_unsigned<_Tp>>::value, _Tp> + __abs_integral(_Tp __val) + { return __val; } + + template<typename _Mn, typename _Nn> + 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<typename _Mn, typename _Nn> + 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<typename _Mn, typename _Nn> + 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<typename _Mn, typename _Nn> + 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 */ |