From 9e28a77462f81a9a2ab9064d768bd7c9484047e1 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 30 Sep 2016 14:43:37 +0100 Subject: [PATCH] Remove use of std::abs in experimental::{gcd,lcm} PR libstdc++/77801 * include/experimental/numeric: Include . (__abs): Define. (gcd, lcm): Use __abs instead of std::abs. * testsuite/experimental/numeric/77801.cc: New test. * testsuite/experimental/numeric/gcd.cc: Test unsigned inputs. * testsuite/experimental/numeric/lcm.cc: Likewise. From-SVN: r240656 --- libstdc++-v3/ChangeLog | 10 +++++++++ libstdc++-v3/include/experimental/numeric | 22 +++++++++++++++---- .../testsuite/experimental/numeric/77801.cc | 22 +++++++++++++++++++ .../testsuite/experimental/numeric/gcd.cc | 4 ++++ .../testsuite/experimental/numeric/lcm.cc | 3 +++ 5 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 libstdc++-v3/testsuite/experimental/numeric/77801.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 671c0db4e96..0bd62c549b8 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2016-09-30 Jonathan Wakely + + PR libstdc++/77801 + * include/experimental/numeric: Include . + (__abs): Define. + (gcd, lcm): Use __abs instead of std::abs. + * testsuite/experimental/numeric/77801.cc: New test. + * testsuite/experimental/numeric/gcd.cc: Test unsigned inputs. + * testsuite/experimental/numeric/lcm.cc: Likewise. + 2016-09-29 Ville Voutilainen Make optional::reset noexcept, make optional::value diff --git a/libstdc++-v3/include/experimental/numeric b/libstdc++-v3/include/experimental/numeric index 21878f3a910..50897722682 100644 --- a/libstdc++-v3/include/experimental/numeric +++ b/libstdc++-v3/include/experimental/numeric @@ -39,8 +39,8 @@ # include #else +#include #include -#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -52,6 +52,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define __cpp_lib_experimental_gcd_lcm 201411 + // std::abs is not constexpr and doesn't support unsigned integers. + template + constexpr + enable_if_t<__and_, is_signed<_Tp>>::value, _Tp> + __abs(_Tp __val) + { return __val < 0 ? -__val : __val; } + + template + constexpr + enable_if_t<__and_, is_unsigned<_Tp>>::value, _Tp> + __abs(_Tp __val) + { return __val; } + // Greatest common divisor template constexpr common_type_t<_Mn, _Nn> @@ -60,8 +73,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(is_integral<_Mn>::value, "arguments to gcd are integers"); static_assert(is_integral<_Nn>::value, "arguments to gcd are integers"); - return __m == 0 ? std::abs(__n) - : __n == 0 ? std::abs(__m) + return __m == 0 ? fundamentals_v2::__abs(__n) + : __n == 0 ? fundamentals_v2::__abs(__m) : fundamentals_v2::gcd(__n, __m % __n); } @@ -74,7 +87,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(is_integral<_Nn>::value, "arguments to lcm are integers"); return (__m != 0 && __n != 0) - ? (std::abs(__m) / fundamentals_v2::gcd(__m, __n)) * std::abs(__n) + ? (fundamentals_v2::__abs(__m) / fundamentals_v2::gcd(__m, __n)) + * fundamentals_v2::__abs(__n) : 0; } diff --git a/libstdc++-v3/testsuite/experimental/numeric/77801.cc b/libstdc++-v3/testsuite/experimental/numeric/77801.cc new file mode 100644 index 00000000000..c4c8bfbfa44 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/numeric/77801.cc @@ -0,0 +1,22 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do compile { target c++14 } } + +#include +#include +constexpr int i = std::experimental::gcd(4L, 5L); // PR libstdc++/77801 diff --git a/libstdc++-v3/testsuite/experimental/numeric/gcd.cc b/libstdc++-v3/testsuite/experimental/numeric/gcd.cc index 038f12d270c..b3345dc5e6d 100644 --- a/libstdc++-v3/testsuite/experimental/numeric/gcd.cc +++ b/libstdc++-v3/testsuite/experimental/numeric/gcd.cc @@ -25,3 +25,7 @@ static_assert(lcm(21, 6) == 42, ""); static_assert(lcm(41, 0) == 0, "LCD with zero is zero"); static_assert(lcm(0, 7) == 0, "LCD with zero is zero"); static_assert(lcm(0, 0) == 0, "no division by zero"); + +static_assert(lcm(1u, 2) == 2, "unsigned and signed"); +static_assert(lcm(3, 4u) == 12, "signed and unsigned"); +static_assert(lcm(5u, 6u) == 30, "unsigned and unsigned"); diff --git a/libstdc++-v3/testsuite/experimental/numeric/lcm.cc b/libstdc++-v3/testsuite/experimental/numeric/lcm.cc index 2c969b0afe5..d90c1527541 100644 --- a/libstdc++-v3/testsuite/experimental/numeric/lcm.cc +++ b/libstdc++-v3/testsuite/experimental/numeric/lcm.cc @@ -29,3 +29,6 @@ static_assert( gcd(0, 13) == 13, "GCD of any number and 0 is that number" ); static_assert( gcd(29, 0) == 29, "GCD of any number and 0 is that number" ); static_assert( gcd(0, 0) == 0, "" ); +static_assert(gcd(1u, 2) == 1, "unsigned and signed"); +static_assert(gcd(3, 4u) == 1, "signed and unsigned"); +static_assert(gcd(5u, 6u) == 1, "unsigned and unsigned"); -- 2.30.2