// Copyright (C) 2020-2024 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 // . // expensive: * [1-9] * * #include "bits/main.h" using std::experimental::simd_cast; template auto gen(const F& fun) { if constexpr (ConstProp) return V(fun); else return make_value_unknown(V(fun)); } template void split_concat() { using T = typename V::value_type; if constexpr (V::size() * 3 <= std::experimental::simd_abi::max_fixed_size) { V a(0), b(1), c(2); auto x = concat(a, b, c); COMPARE(x.size(), a.size() * 3); std::size_t i = 0; for (; i < a.size(); ++i) { COMPARE(x[i], T(0)); } for (; i < 2 * a.size(); ++i) { COMPARE(x[i], T(1)); } for (; i < 3 * a.size(); ++i) { COMPARE(x[i], T(2)); } } if constexpr (V::size() >= 4) { const V a = gen([](auto i) -> T { return i; }); constexpr auto N0 = V::size() / 4u; constexpr auto N1 = V::size() - 2 * N0; using V0 = std::experimental::simd< T, std::experimental::simd_abi::deduce_t>; using V1 = std::experimental::simd< T, std::experimental::simd_abi::deduce_t>; { auto x = std::experimental::split(a); COMPARE(std::tuple_size::value, 3u); COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; })); COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N0; })); COMPARE(std::get<2>(x), V1([](auto i) -> T { return i + 2 * N0; })); auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x)); // a and b may have different types if a was fixed_size such that // another ABI tag exists with equal N, then b will have the // non-fixed-size ABI tag. COMPARE(a.size(), b.size()); COMPARE( b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); })); } { auto x = std::experimental::split(a); COMPARE(std::tuple_size::value, 3u); COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; })); COMPARE(std::get<1>(x), V1([](auto i) -> T { return i + N0; })); COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; })); auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x)); // a and b may have different types if a was fixed_size such that // another ABI tag exists with equal N, then b will have the // non-fixed-size ABI tag. COMPARE(a.size(), b.size()); COMPARE( b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); })); } { auto x = std::experimental::split(a); COMPARE(std::tuple_size::value, 3u); COMPARE(std::get<0>(x), V1([](auto i) -> T { return i; })); COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N1; })); COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; })); auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x)); // a and b may have different types if a was fixed_size such that // another ABI tag exists with equal N, then b will have the // non-fixed-size ABI tag. COMPARE(a.size(), b.size()); COMPARE( b, decltype(b)([](auto i) -> T { return (N1 + i) % V::size(); })); } } if constexpr (V::size() % 3 == 0) { const V a = gen([](auto i) -> T { return i; }); constexpr auto N0 = V::size() / 3; using V0 = std::experimental::simd< T, std::experimental::simd_abi::deduce_t>; using V1 = std::experimental::simd< T, std::experimental::simd_abi::deduce_t>; { auto [x, y, z] = std::experimental::split(a); COMPARE(x, V0([](auto i) -> T { return i; })); COMPARE(y, V0([](auto i) -> T { return i + N0; })); COMPARE(z, V0([](auto i) -> T { return i + N0 * 2; })); auto b = concat(x, y, z); COMPARE(a.size(), b.size()); COMPARE(b, simd_cast(a)); COMPARE(simd_cast(b), a); } { auto [x, y] = std::experimental::split(a); COMPARE(x, V0([](auto i) -> T { return i; })); COMPARE(y, V1([](auto i) -> T { return i + N0; })); auto b = concat(x, y); COMPARE(a.size(), b.size()); COMPARE(b, simd_cast(a)); COMPARE(simd_cast(b), a); } { auto [x, y] = std::experimental::split<2 * N0, N0>(a); COMPARE(x, V1([](auto i) -> T { return i; })); COMPARE(y, V0([](auto i) -> T { return i + 2 * N0; })); auto b = concat(x, y); COMPARE(a.size(), b.size()); COMPARE(b, simd_cast(a)); COMPARE(simd_cast(b), a); } } if constexpr ((V::size() & 1) == 0) { using std::experimental::simd; using std::experimental::simd_abi::deduce_t; using V0 = simd>; using V2 = simd>; using V3 = simd>; const V a = gen([](auto i) -> T { return i; }); std::array v2s = std::experimental::split(a); int offset = 0; for (V2 test : v2s) { COMPARE(test, V2([&](auto i) -> T { return i + offset; })); offset += 2; } COMPARE(concat(v2s), simd_cast(a)); std::array v3s = std::experimental::split(a); COMPARE(v3s[0], V3([](auto i) -> T { return i; })); COMPARE(v3s[1], V3([](auto i) -> T { return i + V3::size(); })); COMPARE(concat(v3s), simd_cast(a)); } } template void test() { split_concat(); split_concat(); }