| // SPDX-FileCopyrightText: The Eigen Authors | |
| // SPDX-License-Identifier: MPL-2.0 | |
| #include "packetmath_test_shared.h" | |
| #include <memory> | |
| namespace Eigen { | |
| namespace test { | |
| template <typename Scalar, typename Packet> | |
| struct runall<Scalar, Packet, false, false> { | |
| static void run() { | |
| constexpr int PacketSize = internal::unpacket_traits<Packet>::size; | |
| auto samples = special_values<Scalar>(); | |
| using Bits = typename numext::get_integer_by_size<sizeof(Scalar)>::unsigned_type; | |
| const Bits nan_payload = numext::bit_cast<Bits>(NumTraits<Scalar>::quiet_NaN()) | Bits(0x123); | |
| samples.push_back(numext::bit_cast<Scalar>(nan_payload)); | |
| Scalar actual[PacketSize], expected[PacketSize]; | |
| for (Index stride : {Index(-7), Index(-2), Index(-1), Index(0), Index(1), Index(2), Index(3), Index(7)}) { | |
| const Index span = (PacketSize - 1) * numext::abs(stride) + 1; | |
| for (Index offset = 0; offset < PacketSize; ++offset) { | |
| // Exact-size new[] lets sanitizers detect reads past the last gathered coefficient. | |
| std::unique_ptr<Scalar[]> storage(new Scalar[span + offset]); | |
| Scalar* data = storage.get() + offset; | |
| const Scalar* from = stride < 0 ? data + span - 1 : data; | |
| for (Index rotation = 0; rotation < Index(samples.size()); ++rotation) { | |
| for (Index i = 0; i < span; ++i) data[i] = samples[(i + rotation) % samples.size()]; | |
| for (Index i = 0; i < PacketSize; ++i) expected[i] = from[i * stride]; | |
| volatile Index runtime_stride = stride; | |
| internal::pstoreu(actual, internal::pgather<Scalar, Packet>(from, runtime_stride)); | |
| VERIFY(areEqualBits(expected, actual, PacketSize, false)); | |
| if (stride == 2) { | |
| internal::pstoreu(actual, internal::pgather<Scalar, Packet>(from, 2)); | |
| VERIFY(areEqualBits(expected, actual, PacketSize, false)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| } // namespace test | |
| } // namespace Eigen | |
| EIGEN_DECLARE_TEST(packetmath_gather) { | |
| CALL_SUBTEST_1(test::runner<float>::run()); | |
| CALL_SUBTEST_2(test::runner<double>::run()); | |
| } |