// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2025 The Eigen Authors // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #include "main.h" template void verify_data(const Scalar* data_in, const Scalar* data_out, const Packet& a, Index begin, Index count) { constexpr int PacketSize = internal::unpacket_traits::size; bool ok = true; for (Index i = begin; i < begin + count; i++) { ok = ok && numext::equal_strict(data_in[i], data_out[i]); } if (!ok) { std::cout << "begin: " << begin << ", count: " << count << "\n"; std::cout << "Scalar type: " << type_name(Scalar()) << " x " << PacketSize << "\n"; std::cout << "data in: {"; for (Index i = 0; i < PacketSize; i++) { if (i > 0) std::cout << ","; if (i < begin || i >= begin + count) { std::cout << "MASK"; } else { std::cout << data_in[i]; } } std::cout << "}\n"; std::cout << "data out: {"; for (Index i = 0; i < PacketSize; i++) { if (i > 0) std::cout << ","; if (i < begin || i >= begin + count) { std::cout << "MASK"; } else { std::cout << data_out[i]; } } std::cout << "}\n"; std::cout << "packet: "; std::cout << internal::postream(a) << "\n"; } VERIFY(ok); } template ::value> struct packet_segment_test_impl { using Packet = typename internal::find_packet_by_size::type; static void test_unaligned() { // test loading a packet segment from unaligned memory that includes unallocated memory // | X X X X | * * * X | X X X X | // begin -> { X | * * * } <- begin + count VectorX data_in(PacketSize), data_out(PacketSize); data_in.setRandom(); data_out.setRandom(); Scalar* unaligned_data_in = data_in.data() - 1; Scalar* unaligned_data_out = data_out.data() - 1; Index begin = 1; Index count = PacketSize - 1; Packet a = internal::ploaduSegment(unaligned_data_in, begin, count); internal::pstoreuSegment(unaligned_data_out, a, begin, count); verify_data(unaligned_data_in, unaligned_data_out, a, begin, count); // test loading the entire packet data_in.setRandom(); data_out.setRandom(); unaligned_data_in = data_in.data(); unaligned_data_out = data_out.data(); begin = 0; count = PacketSize; Packet b = internal::ploaduSegment(unaligned_data_in, begin, count); internal::pstoreuSegment(unaligned_data_out, b, begin, count); verify_data(unaligned_data_in, unaligned_data_out, b, begin, count); // test loading an empty packet segment in unallocated memory count = 0; for (begin = 0; begin < PacketSize; begin++) { data_in.setRandom(); data_out = data_in; Packet c = internal::ploaduSegment(data_in.data(), begin, count); internal::pstoreuSegment(data_out.data(), c, begin, count); // verify that ploaduSegment / pstoreuSegment did nothing VERIFY_IS_CWISE_EQUAL(data_in, data_out); } } static void test_aligned() { // test loading a packet segment from aligned memory that includes unallocated memory // | X X X X | * * * X | X X X X | // begin -> { * * * X } <- begin + count VectorX data_in(PacketSize - 1), data_out(PacketSize - 1); data_in.setRandom(); data_out.setRandom(); Scalar* aligned_data_in = data_in.data(); Scalar* aligned_data_out = data_out.data(); Index begin = 0; Index count = PacketSize - 1; Packet b = internal::ploadSegment(aligned_data_in, begin, count); internal::pstoreSegment(aligned_data_out, b, begin, count); verify_data(aligned_data_in, aligned_data_out, b, begin, count); } static void run() { test_unaligned(); test_aligned(); } }; template struct packet_segment_test_impl { static void run() {} }; template struct packet_segment_test_driver { static void run() { packet_segment_test_impl::run(); packet_segment_test_driver::run(); } }; template struct packet_segment_test_driver { static void run() {} }; template void test_packet_segment() { packet_segment_test_driver::size>::run(); } EIGEN_DECLARE_TEST(packet_segment) { for (int i = 0; i < g_repeat; i++) { test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment(); test_packet_segment>(); test_packet_segment>(); } }