libstdc++: Optimise GCD algorithms
authorJonathan Wakely <jwakely@redhat.com>
Thu, 3 Sep 2020 11:38:50 +0000 (12:38 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 3 Sep 2020 11:46:13 +0000 (12:46 +0100)
commit3c219134152f645103f2fcd50735b177ccd76cde
treeddd487657c9d90fa34983735e3664ca056febc7f
parent3536ff2de8317c430546fd97574d44c5146cef2b
libstdc++: Optimise GCD algorithms

The current std::gcd and std::chrono::duration::_S_gcd algorithms are
both recursive. This is potentially expensive to evaluate in constant
expressions, because each level of recursion makes a new copy of the
function to evaluate. The maximum number of steps is bounded
(proportional to the number of decimal digits in the smaller value) and
so unlikely to exceed the limit for constexpr nesting, but the memory
usage is still suboptimal. By using an iterative algorithm we avoid
that compile-time cost. Because looping in constexpr functions is not
allowed until C++14, we need to keep the recursive implementation in
duration::_S_gcd for C++11 mode.

For std::gcd we can also optimise runtime performance by using the
binary GCD algorithm.

libstdc++-v3/ChangeLog:

* include/std/chrono (duration::_S_gcd): Use iterative algorithm
for C++14 and later.
* include/std/numeric (__detail::__gcd): Replace recursive
Euclidean algorithm with iterative version of binary GCD algorithm.
* testsuite/26_numerics/gcd/1.cc: Test additional inputs.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error lines.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/experimental/numeric/gcd.cc: Test additional inputs.
* testsuite/26_numerics/gcd/2.cc: New test.
libstdc++-v3/include/std/chrono
libstdc++-v3/include/std/numeric
libstdc++-v3/testsuite/26_numerics/gcd/1.cc
libstdc++-v3/testsuite/26_numerics/gcd/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc
libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc
libstdc++-v3/testsuite/experimental/numeric/gcd.cc