Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions core/libs/prx/libc/src/Math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,27 @@ int APS5_VABI __signbitf_nid_postfix(float x) { return std::signbit(x) ? 1 : 0;
static std::mutex g_randLock;
static std::uint32_t g_randState = 1;

int APS5_VABI rand_nid_postfix() {
std::lock_guard lock(g_randLock);
const std::int64_t x = static_cast<std::int64_t>(g_randState % 0x7ffffffeu) + 1;
static int NextRand_nid_no_patch(std::uint32_t& state) {
const std::int64_t x = static_cast<std::int64_t>(state % 0x7ffffffeu) + 1;
std::int64_t next = 16807 * (x % 127773) - 2836 * (x / 127773);
if (next < 0) next += 0x7fffffff;
g_randState = static_cast<std::uint32_t>(next - 1);
state = static_cast<std::uint32_t>(next - 1);
return static_cast<int>(next - 1);
}

int APS5_VABI rand_nid_postfix() {
std::lock_guard lock(g_randLock);
return NextRand_nid_no_patch(g_randState);
}

int APS5_VABI rand_r_nid_postfix(unsigned int* state) {
if (state == nullptr) throw std::invalid_argument("rand_r: null state");
std::uint32_t value = *state;
const int result = NextRand_nid_no_patch(value);
*state = value;
return result;
}

void APS5_VABI srand_nid_postfix(unsigned int seed) {
std::lock_guard lock(g_randLock);
g_randState = seed;
Expand Down
15 changes: 15 additions & 0 deletions core/libs/tests/GuestMath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ float APS5_VABI atan2f_nid_postfix(float, float);
float APS5_VABI hypotf_nid_postfix(float, float);
double APS5_VABI hypot_nid_postfix(double, double);
float APS5_VABI tanf_nid_postfix(float);
int APS5_VABI rand_nid_postfix();
void APS5_VABI srand_nid_postfix(unsigned int);
int APS5_VABI rand_r_nid_postfix(unsigned int*);
float APS5_VABI log10f_nid_postfix(float);
float APS5_VABI logbf_nid_postfix(float);
double APS5_VABI exp2_nid_postfix(double);
Expand Down Expand Up @@ -234,6 +237,18 @@ int main() {
Require(std::abs(acosf_nid_postfix(0.5f) - 1.0471976f) < 0.000001f);
Require(std::abs(atan2f_nid_postfix(1.f, -1.f) - 2.3561945f) < 0.000001f);
Require(tanf_nid_postfix(0.f) == 0.f);
unsigned int randomState = 1;
Require(rand_r_nid_postfix(&randomState) == 33613 && randomState == 33613u);
randomState = 0;
Require(rand_r_nid_postfix(&randomState) == 16806 && randomState == 16806u);
for (const unsigned int seed : {0u, 1u, 12345u, 0x7ffffffeu, 0xffffffffu}) {
srand_nid_postfix(seed);
randomState = seed;
for (int step = 0; step < 8; ++step) Require(rand_r_nid_postfix(&randomState) == rand_nid_postfix());
}
bool threw = false;
try { rand_r_nid_postfix(nullptr); } catch (...) { threw = true; }
Require(threw);
Require(hypot_nid_postfix(3.0, 4.0) == 5.0 && hypot_nid_postfix(-3.0, -4.0) == 5.0 && hypotf_nid_postfix(3.f, -4.f) == 5.f);
Require(std::abs(hypot_nid_postfix(1e308, 1e308) / 1.4142135623730951e308 - 1.0) < 1e-15);
Require(std::abs(hypotf_nid_postfix(2e38f, 2e38f) / 2.8284271e38f - 1.f) < 1e-6f);
Expand Down
Loading