diff options
author | Luc Grosheintz <luc.grosheintz@gmail.com> | 2025-08-11 22:14:55 +0200 |
---|---|---|
committer | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-08-21 10:41:53 +0200 |
commit | 4959739d83c25c37abdc19c3fda7067a70a751f0 (patch) | |
tree | 4cb10bf82b9427fa84940f0484477d2ddd8c06ad | |
parent | d6ed0658f70144dbec0fe7c494cf7a2a11b05d2e (diff) | |
download | gcc-4959739d83c25c37abdc19c3fda7067a70a751f0.zip gcc-4959739d83c25c37abdc19c3fda7067a70a751f0.tar.gz gcc-4959739d83c25c37abdc19c3fda7067a70a751f0.tar.bz2 |
libstdc++: Simplify precomputed partial products in <mdspan>.
Prior to this commit, the partial products of static extents in <mdspan>
was done in a loop that calls a function that computes the partial
product. The complexity is quadratic in the rank.
This commit removes the quadratic complexity.
libstdc++-v3/ChangeLog:
* include/std/mdspan (__static_prod): Delete.
(__fwd_partial_prods): Compute at compile-time in O(rank), not
O(rank**2).
(__rev_partial_prods): Ditto.
(__size): Inline __static_prod.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
-rw-r--r-- | libstdc++-v3/include/std/mdspan | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 8f97425..4db4fd9 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -256,27 +256,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __static_extents() noexcept { return _Extents::_S_storage::_S_static_extents(); } - template<array _Extents> - consteval size_t - __static_prod(size_t __begin, size_t __end) - { - size_t __prod = 1; - for(size_t __i = __begin; __i < __end; ++__i) - { - auto __ext = _Extents[__i]; - __prod *= __ext == dynamic_extent ? size_t(1) : __ext; - } - return __prod; - } - // Pre-compute: \prod_{i = 0}^r _Extents[i], for r = 0,..., n (exclusive) template<array _Extents> constexpr auto __fwd_partial_prods = [] consteval { constexpr size_t __rank = _Extents.size(); std::array<size_t, __rank> __ret; - for(size_t __r = 0; __r < __rank; ++__r) - __ret[__r] = __static_prod<_Extents>(0, __r); + size_t __prod = 1; + for (size_t __r = 0; __r < __rank; ++__r) + { + __ret[__r] = __prod; + if (size_t __ext = _Extents[__r]; __ext != dynamic_extent) + __prod *= __ext; + } return __ret; }(); @@ -286,8 +278,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { constexpr size_t __rank = _Extents.size(); std::array<size_t, __rank> __ret; - for(size_t __r = 0; __r < __rank; ++__r) - __ret[__r] = __static_prod<_Extents>(__r + 1, __rank); + size_t __prod = 1; + for (size_t __r = __rank; __r > 0; --__r) + { + __ret[__r - 1] = __prod; + if (size_t __ext = _Extents[__r - 1]; __ext != dynamic_extent) + __prod *= __ext; + } return __ret; }(); @@ -517,10 +514,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr typename _Extents::index_type __size(const _Extents& __exts) noexcept { - constexpr auto& __sta_exts = __static_extents<_Extents>(); - constexpr size_t __rank = _Extents::rank(); - constexpr size_t __sta_prod = __static_prod<__sta_exts>(0, __rank); - return __extents_prod(__exts, __sta_prod, 0, __rank); + constexpr size_t __sta_prod = [] { + span<const size_t> __sta_exts = __static_extents<_Extents>(); + size_t __ret = 1; + for(auto __ext : __sta_exts) + if (__ext != dynamic_extent) + __ret *= __ext; + return __ret; + }(); + return __extents_prod(__exts, __sta_prod, 0, _Extents::rank()); } template<typename _IndexType, size_t... _Counts> |