Files
AnyPS5/core/libs/tests/GuestVectorAlgorithms.cpp
T
hypermistandClaude Opus 5.5 6103a3e0b9 feat(libc): implement the __std vectorized algorithm helpers
__std_find_trivial(_unsized), __std_count_trivial, __std_min/max/minmax_element,
__std_reverse_trivially_swappable, __std_reverse_copy_trivially_copyable and
__std_swap_ranges_trivially_swappable_noalias for 1-, 2-, 4- and 8-byte
elements, matching the libc.prx bundled with PPSA08427 including the rescan of
the first aligned block in the unsized find.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q8tinbP1MUpUaDsbNWnGnu
2026-10-16 01:15:23 +13:00

97 lines
4.7 KiB
C++

#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
struct MinMaxPointers {
const void* minimum;
const void* maximum;
};
extern "C" {
const void* APS5_VABI __std_find_trivial_2_nid_postfix(const void*, const void*, std::uint16_t);
const void* APS5_VABI __std_find_trivial_unsized_1_nid_postfix(const void*, std::uint8_t);
const void* APS5_VABI __std_find_trivial_unsized_4_nid_postfix(const void*, std::uint32_t);
std::size_t APS5_VABI __std_count_trivial_8_nid_postfix(const void*, const void*, std::uint64_t);
const void* APS5_VABI __std_min_element_1_nid_postfix(const void*, const void*, bool);
const void* APS5_VABI __std_max_element_4_nid_postfix(const void*, const void*, bool);
MinMaxPointers APS5_VABI __std_minmax_element_2_nid_postfix(const void*, const void*, bool);
MinMaxPointers APS5_VABI __std_minmax_element_8_nid_postfix(const void*, const void*, bool);
void APS5_VABI __std_reverse_trivially_swappable_2_nid_postfix(void*, void*);
void APS5_VABI __std_reverse_copy_trivially_copyable_8_nid_postfix(const void*, const void*, void*);
void APS5_VABI __std_swap_ranges_trivially_swappable_noalias_nid_postfix(void*, void*, void*);
}
static void Require(bool value) { if (!value) std::abort(); }
static void CheckFindAndCount() {
const std::uint16_t halves[] = {5, 7, 9, 7};
Require(__std_find_trivial_2_nid_postfix(halves, halves + 4, 7) == halves + 1);
Require(__std_find_trivial_2_nid_postfix(halves, halves + 4, 8) == halves + 4);
Require(__std_find_trivial_2_nid_postfix(halves, halves, 5) == halves);
const std::uint64_t wides[] = {1, 2, 1, 1};
Require(__std_count_trivial_8_nid_postfix(wides, wides + 4, 1) == 3 && __std_count_trivial_8_nid_postfix(wides, wides, 1) == 0);
alignas(32) std::uint32_t words[16] = {};
words[3] = 42;
words[12] = 42;
Require(__std_find_trivial_unsized_4_nid_postfix(words + 8, 42) == words + 12);
}
static void CheckUnsizedRescan() {
alignas(32) unsigned char bytes[96] = {};
bytes[3] = 'x';
bytes[70] = 'x';
Require(__std_find_trivial_unsized_1_nid_postfix(bytes + 8, 'x') == bytes + 3);
bytes[20] = 'x';
Require(__std_find_trivial_unsized_1_nid_postfix(bytes + 8, 'x') == bytes + 20);
bytes[3] = 0;
bytes[20] = 0;
Require(__std_find_trivial_unsized_1_nid_postfix(bytes + 8, 'x') == bytes + 70);
}
static void CheckMinMax() {
const unsigned char bytes[] = {3, 0x80, 1, 0x80, 1, 0xff};
Require(__std_min_element_1_nid_postfix(bytes, bytes + 6, false) == bytes + 2);
Require(__std_min_element_1_nid_postfix(bytes, bytes + 6, true) == bytes + 1);
Require(__std_min_element_1_nid_postfix(bytes, bytes, true) == bytes);
const std::uint32_t words[] = {7, 0xffffffffu, 9, 0xffffffffu, 9};
Require(__std_max_element_4_nid_postfix(words, words + 5, false) == words + 1);
Require(__std_max_element_4_nid_postfix(words, words + 5, true) == words + 2);
const std::int16_t halves[] = {4, -3, 8, -3, 8, 2};
const MinMaxPointers signedHalves = __std_minmax_element_2_nid_postfix(halves, halves + 6, true);
Require(signedHalves.minimum == halves + 1 && signedHalves.maximum == halves + 4);
const MinMaxPointers unsignedHalves = __std_minmax_element_2_nid_postfix(halves, halves + 6, false);
Require(unsignedHalves.minimum == halves + 5 && unsignedHalves.maximum == halves + 3);
const std::uint64_t wides[] = {5};
const MinMaxPointers single = __std_minmax_element_8_nid_postfix(wides, wides + 1, false);
Require(single.minimum == wides && single.maximum == wides);
const MinMaxPointers empty = __std_minmax_element_8_nid_postfix(wides, wides, false);
Require(empty.minimum == wides && empty.maximum == wides);
}
static void CheckReverseAndSwap() {
std::uint16_t halves[] = {1, 2, 3, 4, 5};
__std_reverse_trivially_swappable_2_nid_postfix(halves, halves + 5);
Require(halves[0] == 5 && halves[1] == 4 && halves[2] == 3 && halves[3] == 2 && halves[4] == 1);
const std::uint64_t wides[] = {1, 2, 3};
std::uint64_t reversed[4] = {9, 9, 9, 9};
__std_reverse_copy_trivially_copyable_8_nid_postfix(wides, wides + 3, reversed);
Require(reversed[0] == 3 && reversed[1] == 2 && reversed[2] == 1 && reversed[3] == 9);
unsigned char left[37], right[37];
for (int i = 0; i < 37; ++i) {
left[i] = static_cast<unsigned char>(i);
right[i] = static_cast<unsigned char>(100 + i);
}
__std_swap_ranges_trivially_swappable_noalias_nid_postfix(left, left + 37, right);
for (int i = 0; i < 37; ++i) Require(left[i] == 100 + i && right[i] == i);
}
int main() {
CheckFindAndCount();
CheckUnsizedRescan();
CheckMinMax();
CheckReverseAndSwap();
return 0;
}