mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-28 23:04:18 +08:00
169 lines
5.4 KiB
C++
169 lines
5.4 KiB
C++
// 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 <typename Scalar, typename Packet>
|
|
void verify_data(const Scalar* data_in, const Scalar* data_out, const Packet& a, Index begin, Index count) {
|
|
constexpr int PacketSize = internal::unpacket_traits<Packet>::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 <typename Scalar, int PacketSize, bool Run = internal::find_packet_by_size<Scalar, PacketSize>::value>
|
|
struct packet_segment_test_impl {
|
|
using Packet = typename internal::find_packet_by_size<Scalar, PacketSize>::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<Scalar> 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<Packet>(unaligned_data_in, begin, count);
|
|
internal::pstoreuSegment<Scalar, Packet>(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<Packet>(unaligned_data_in, begin, count);
|
|
internal::pstoreuSegment<Scalar, Packet>(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<Packet>(data_in.data(), begin, count);
|
|
internal::pstoreuSegment<Scalar, Packet>(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<Scalar> 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<Packet>(aligned_data_in, begin, count);
|
|
internal::pstoreSegment<Scalar, Packet>(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 <typename Scalar, int PacketSize>
|
|
struct packet_segment_test_impl<Scalar, PacketSize, false> {
|
|
static void run() {}
|
|
};
|
|
|
|
template <typename Scalar, int PacketSize>
|
|
struct packet_segment_test_driver {
|
|
static void run() {
|
|
packet_segment_test_impl<Scalar, PacketSize>::run();
|
|
packet_segment_test_driver<Scalar, PacketSize / 2>::run();
|
|
}
|
|
};
|
|
|
|
template <typename Scalar>
|
|
struct packet_segment_test_driver<Scalar, 1> {
|
|
static void run() {}
|
|
};
|
|
|
|
template <typename Scalar>
|
|
void test_packet_segment() {
|
|
packet_segment_test_driver<Scalar, internal::packet_traits<Scalar>::size>::run();
|
|
}
|
|
|
|
EIGEN_DECLARE_TEST(packet_segment) {
|
|
for (int i = 0; i < g_repeat; i++) {
|
|
test_packet_segment<bool>();
|
|
test_packet_segment<int8_t>();
|
|
test_packet_segment<uint8_t>();
|
|
test_packet_segment<int16_t>();
|
|
test_packet_segment<uint16_t>();
|
|
test_packet_segment<int32_t>();
|
|
test_packet_segment<uint32_t>();
|
|
test_packet_segment<int64_t>();
|
|
test_packet_segment<uint64_t>();
|
|
test_packet_segment<bfloat16>();
|
|
test_packet_segment<half>();
|
|
test_packet_segment<float>();
|
|
test_packet_segment<double>();
|
|
test_packet_segment<std::complex<float>>();
|
|
test_packet_segment<std::complex<double>>();
|
|
}
|
|
}
|