mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibJS/AK: Move XorShift128PlusRNG to AK
This will be useful for CSS random functions so it should be in a reusable place. This does require us to use `AK::get_random` instead of `Crypto::get_secure_random`, but this is fine since the latter is in the process of being removed (see #6564).
This commit is contained in:
parent
6d9f10ba36
commit
1f7fe97ac3
Notes:
github-actions[bot]
2025-12-01 11:02:26 +00:00
Author: https://github.com/Calme1709
Commit: 1f7fe97ac3
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6707
Reviewed-by: https://github.com/AtkinsSJ ✅
Reviewed-by: https://github.com/gmta
3 changed files with 51 additions and 45 deletions
|
|
@ -97,4 +97,41 @@ u64 get_random_uniform_64(u64 max_bounds)
|
|||
return random_value % max_bounds;
|
||||
}
|
||||
|
||||
XorShift128PlusRNG::XorShift128PlusRNG()
|
||||
{
|
||||
// Splitmix64 is used as xorshift is sensitive to being seeded with all 0s
|
||||
u64 seed = get_random<u64>();
|
||||
m_low = splitmix64(seed);
|
||||
seed = get_random<u64>();
|
||||
m_high = splitmix64(seed);
|
||||
}
|
||||
|
||||
double XorShift128PlusRNG::get()
|
||||
{
|
||||
u64 value = advance() & ((1ULL << 53) - 1);
|
||||
return value * (1.0 / (1ULL << 53));
|
||||
}
|
||||
|
||||
u64 XorShift128PlusRNG::splitmix64(u64& state)
|
||||
{
|
||||
u64 z = (state += 0x9e3779b97f4a7c15ULL);
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
|
||||
return z ^ (z >> 31);
|
||||
}
|
||||
|
||||
// Apparently this set of constants is better: https://stackoverflow.com/a/34432126
|
||||
u64 XorShift128PlusRNG::advance()
|
||||
{
|
||||
u64 s1 = m_low;
|
||||
u64 const s0 = m_high;
|
||||
u64 const result = s0 + s1;
|
||||
m_low = s0;
|
||||
s1 ^= s1 << 23;
|
||||
s1 ^= s1 >> 18;
|
||||
s1 ^= s0 ^ (s0 >> 5);
|
||||
m_high = s1;
|
||||
return result + s1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
14
AK/Random.h
14
AK/Random.h
|
|
@ -31,6 +31,19 @@ inline T get_random()
|
|||
u32 get_random_uniform(u32 max_bounds);
|
||||
u64 get_random_uniform_64(u64 max_bounds);
|
||||
|
||||
// http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
|
||||
class XorShift128PlusRNG {
|
||||
public:
|
||||
XorShift128PlusRNG();
|
||||
double get();
|
||||
|
||||
private:
|
||||
u64 splitmix64(u64& state);
|
||||
u64 advance();
|
||||
u64 m_low { 0 };
|
||||
u64 m_high { 0 };
|
||||
};
|
||||
|
||||
template<typename Collection>
|
||||
inline void shuffle(Collection& collection)
|
||||
{
|
||||
|
|
@ -48,4 +61,5 @@ using AK::fill_with_random;
|
|||
using AK::get_random;
|
||||
using AK::get_random_uniform;
|
||||
using AK::shuffle;
|
||||
using AK::XorShift128PlusRNG;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -809,51 +809,6 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::pow)
|
|||
return pow_impl(vm, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
|
||||
class XorShift128PlusRNG {
|
||||
public:
|
||||
XorShift128PlusRNG()
|
||||
{
|
||||
// Splitmix64 is used as xorshift is sensitive to being seeded with all 0s
|
||||
u64 seed = Crypto::get_secure_random<u64>();
|
||||
m_low = splitmix64(seed);
|
||||
seed = Crypto::get_secure_random<u64>();
|
||||
m_high = splitmix64(seed);
|
||||
}
|
||||
|
||||
double get()
|
||||
{
|
||||
u64 value = advance() & ((1ULL << 53) - 1);
|
||||
return value * (1.0 / (1ULL << 53));
|
||||
}
|
||||
|
||||
private:
|
||||
u64 splitmix64(u64& state)
|
||||
{
|
||||
u64 z = (state += 0x9e3779b97f4a7c15ULL);
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
|
||||
return z ^ (z >> 31);
|
||||
}
|
||||
|
||||
// Apparently this set of constants is better: https://stackoverflow.com/a/34432126
|
||||
u64 advance()
|
||||
{
|
||||
u64 s1 = m_low;
|
||||
u64 const s0 = m_high;
|
||||
u64 const result = s0 + s1;
|
||||
m_low = s0;
|
||||
s1 ^= s1 << 23;
|
||||
s1 ^= s1 >> 18;
|
||||
s1 ^= s0 ^ (s0 >> 5);
|
||||
m_high = s1;
|
||||
return result + s1;
|
||||
}
|
||||
|
||||
u64 m_low { 0 };
|
||||
u64 m_high { 0 };
|
||||
};
|
||||
|
||||
Value MathObject::random_impl()
|
||||
{
|
||||
// This function returns a Number value with positive sign, greater than or equal to +0𝔽 but strictly less than 1𝔽,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue