mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
feat(libc): implement erand48, nrand48 and jrand48
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
24cb0d2412
commit
f85ae8d6f2
2 files changed
+62
No files matched your search
@@ -1,10 +1,12 @@
|
||||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -93,10 +95,35 @@ void SaveTypeWordLocked() {
|
||||
StoreWord(state.table, 0, static_cast<std::uint32_t>(word));
|
||||
}
|
||||
|
||||
std::uint64_t NextRand48(std::uint16_t* seed, const char* function) {
|
||||
if (seed == nullptr) throw std::invalid_argument(std::string(function) + ": null seed");
|
||||
constexpr std::uint64_t Multiplier = 0x5deece66dull;
|
||||
constexpr std::uint64_t Addend = 0xb;
|
||||
constexpr std::uint64_t Mask = (1ull << 48) - 1;
|
||||
std::uint64_t value = (static_cast<std::uint64_t>(seed[2]) << 32) | (static_cast<std::uint64_t>(seed[1]) << 16) | seed[0];
|
||||
value = (value * Multiplier + Addend) & Mask;
|
||||
seed[0] = static_cast<std::uint16_t>(value);
|
||||
seed[1] = static_cast<std::uint16_t>(value >> 16);
|
||||
seed[2] = static_cast<std::uint16_t>(value >> 32);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
double APS5_VABI erand48_nid_postfix(std::uint16_t* seed) {
|
||||
return std::ldexp(static_cast<double>(NextRand48(seed, __func__)), -48);
|
||||
}
|
||||
|
||||
std::int64_t APS5_VABI nrand48_nid_postfix(std::uint16_t* seed) {
|
||||
return static_cast<std::int64_t>(NextRand48(seed, __func__) >> 17);
|
||||
}
|
||||
|
||||
std::int64_t APS5_VABI jrand48_nid_postfix(std::uint16_t* seed) {
|
||||
return static_cast<std::int32_t>(static_cast<std::uint32_t>(NextRand48(seed, __func__) >> 16));
|
||||
}
|
||||
|
||||
std::int64_t APS5_VABI random_nid_postfix() {
|
||||
std::lock_guard lock(g_randomLock);
|
||||
return static_cast<std::int64_t>(NextLocked());
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
@@ -15,6 +16,9 @@ void APS5_VABI srandom_nid_postfix(std::uint64_t);
|
||||
char* APS5_VABI initstate_nid_postfix(std::uint64_t, char*, std::int64_t);
|
||||
char* APS5_VABI setstate_nid_postfix(char*);
|
||||
int* APS5_VABI __error_nid_postfix();
|
||||
double APS5_VABI erand48_nid_postfix(std::uint16_t*);
|
||||
std::int64_t APS5_VABI nrand48_nid_postfix(std::uint16_t*);
|
||||
std::int64_t APS5_VABI jrand48_nid_postfix(std::uint16_t*);
|
||||
}
|
||||
|
||||
static int failures = 0;
|
||||
@@ -40,7 +44,38 @@ static std::uint32_t Word(const char* table, std::size_t index) {
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool SeedIs(const std::uint16_t* seed, std::uint16_t low, std::uint16_t middle, std::uint16_t high) {
|
||||
return seed[0] == low && seed[1] == middle && seed[2] == high;
|
||||
}
|
||||
|
||||
static void CheckRand48() {
|
||||
std::uint16_t seed[3] = {0x330e, 0xabcd, 0x1234};
|
||||
Require(erand48_nid_postfix(seed) == 0x657eb7255101p-48 && SeedIs(seed, 0x5101, 0xb725, 0x657e), "erand48 first value");
|
||||
Require(nrand48_nid_postfix(seed) == 1804928587 && SeedIs(seed, 0x6378, 0x0c96, 0xd72a), "nrand48 second value");
|
||||
Require(jrand48_nid_postfix(seed) == 1517566982 && SeedIs(seed, 0x2a23, 0x3c06, 0x5a74), "jrand48 third value");
|
||||
Require(erand48_nid_postfix(seed) == 0x72534abf62f2p-48 && SeedIs(seed, 0x62f2, 0x4abf, 0x7253), "erand48 fourth value");
|
||||
Require(nrand48_nid_postfix(seed) == 684387517 && SeedIs(seed, 0x8d15, 0xd97a, 0x5195), "nrand48 fifth value");
|
||||
Require(jrand48_nid_postfix(seed) == -487786166 && SeedIs(seed, 0xeffc, 0xf94a, 0xe2ec), "jrand48 negative value");
|
||||
|
||||
std::uint16_t zero[3] = {};
|
||||
Require(nrand48_nid_postfix(zero) == 0 && SeedIs(zero, 0x000b, 0, 0), "rand48 zero seed adds the increment");
|
||||
std::uint16_t top[3] = {0xffff, 0xffff, 0xffff};
|
||||
const double value = erand48_nid_postfix(top);
|
||||
Require(value >= 0.0 && value < 1.0, "erand48 stays below 1");
|
||||
|
||||
#ifndef _WIN32
|
||||
std::uint16_t guest[3] = {0x1234, 0x5678, 0x9abc};
|
||||
unsigned short host[3] = {0x1234, 0x5678, 0x9abc};
|
||||
for (int round = 0; round < 64; ++round) {
|
||||
Require(erand48_nid_postfix(guest) == ::erand48(host), "erand48 matches the host");
|
||||
Require(nrand48_nid_postfix(guest) == ::nrand48(host), "nrand48 matches the host");
|
||||
Require(jrand48_nid_postfix(guest) == ::jrand48(host), "jrand48 matches the host");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main() {
|
||||
CheckRand48();
|
||||
constexpr Sequence seedOne {1408992891, 1638182910, 83848093, 145962118, 627851256};
|
||||
constexpr Sequence seed12345 {1052984060, 1639322404, 1971525204, 2097956667, 2012147915};
|
||||
constexpr std::array<Sequence, 5> seed42ByType {{
|
||||
|
||||
Reference in new issue
Block a user