[committed] libstdc++: Optimise GCD algorithms
Sidney Marshall
sidneym@frontiernet.net
Sat Sep 5 00:31:44 GMT 2020
Jonathan
I don't know if the following comments are useful or not but here goes:
>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.
>
>Tested powerpc64le-linux. Committed to trunk.
>
>-------------- next part --------------
>commit 3c219134152f645103f2fcd50735b177ccd76cde
>Author: Jonathan Wakely <jwakely@redhat.com>
>Date: Thu Sep 3 12:38:50 2020
>
> 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.
>
>diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
>index 1682263fd9f..0e2efb2522b 100644
>--- a/libstdc++-v3/include/std/chrono
>+++ b/libstdc++-v3/include/std/chrono
>@@ -428,8 +428,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> _S_gcd(intmax_t __m, intmax_t __n) noexcept
> {
> // Duration only allows positive periods so we don't need to
>- // support negative values here (unlike __static_gcd and std::gcd).
>+ // handle negative values here (unlike __static_gcd and std::gcd).
>+#if __cplusplus >= 201402L
>+ while (__m != 0 && __n != 0)
Why are you testing for both __m != 0 && __n != 0 in the loop. Only
__n can be zero. A test for __m == 0 can be made out side of the loop
to save a possible division. Or is there something special about
compile time execution?
>+ {
>+ intmax_t __rem = __m % __n;
>+ __m = __n;
>+ __n = __rem;
>+ }
>+ return __m + __n;
If __n is zero then why not just return __m? Or, again, is there
something special about compile time execution?
>+#else
>+ // C++11 doesn't allow loops in constexpr functions, but this
>+ // recursive version can be more expensive to evaluate.
> return (__m == 0) ? __n : (__n == 0) ? __m : _S_gcd(__n,
> __m % __n);
>+#endif
> }
>
>...
More information about the Libstdc++
mailing list