File tree Expand file tree Collapse file tree 3 files changed +51
-45
lines changed
Expand file tree Collapse file tree 3 files changed +51
-45
lines changed Original file line number Diff line number Diff line change @@ -97,4 +97,41 @@ u64 get_random_uniform_64(u64 max_bounds)
9797 return random_value % max_bounds;
9898}
9999
100+ XorShift128PlusRNG::XorShift128PlusRNG ()
101+ {
102+ // Splitmix64 is used as xorshift is sensitive to being seeded with all 0s
103+ u64 seed = get_random<u64 >();
104+ m_low = splitmix64 (seed);
105+ seed = get_random<u64 >();
106+ m_high = splitmix64 (seed);
107+ }
108+
109+ double XorShift128PlusRNG::get ()
110+ {
111+ u64 value = advance () & ((1ULL << 53 ) - 1 );
112+ return value * (1.0 / (1ULL << 53 ));
113+ }
114+
115+ u64 XorShift128PlusRNG::splitmix64 (u64 & state)
116+ {
117+ u64 z = (state += 0x9e3779b97f4a7c15ULL );
118+ z = (z ^ (z >> 30 )) * 0xbf58476d1ce4e5b9ULL ;
119+ z = (z ^ (z >> 27 )) * 0x94d049bb133111ebULL ;
120+ return z ^ (z >> 31 );
121+ }
122+
123+ // Apparently this set of constants is better: https://stackoverflow.com/a/34432126
124+ u64 XorShift128PlusRNG::advance ()
125+ {
126+ u64 s1 = m_low;
127+ u64 const s0 = m_high;
128+ u64 const result = s0 + s1;
129+ m_low = s0;
130+ s1 ^= s1 << 23 ;
131+ s1 ^= s1 >> 18 ;
132+ s1 ^= s0 ^ (s0 >> 5 );
133+ m_high = s1;
134+ return result + s1;
135+ }
136+
100137}
Original file line number Diff line number Diff line change @@ -31,6 +31,19 @@ inline T get_random()
3131u32 get_random_uniform (u32 max_bounds);
3232u64 get_random_uniform_64 (u64 max_bounds);
3333
34+ // http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
35+ class XorShift128PlusRNG {
36+ public:
37+ XorShift128PlusRNG ();
38+ double get ();
39+
40+ private:
41+ u64 splitmix64 (u64 & state);
42+ u64 advance ();
43+ u64 m_low { 0 };
44+ u64 m_high { 0 };
45+ };
46+
3447template <typename Collection>
3548inline void shuffle (Collection& collection)
3649{
@@ -48,4 +61,5 @@ using AK::fill_with_random;
4861using AK::get_random;
4962using AK::get_random_uniform;
5063using AK::shuffle;
64+ using AK::XorShift128PlusRNG;
5165#endif
Original file line number Diff line number Diff line change @@ -809,51 +809,6 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::pow)
809809 return pow_impl (vm, vm.argument (0 ), vm.argument (1 ));
810810}
811811
812- // http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
813- class XorShift128PlusRNG {
814- public:
815- XorShift128PlusRNG ()
816- {
817- // Splitmix64 is used as xorshift is sensitive to being seeded with all 0s
818- u64 seed = Crypto::get_secure_random<u64 >();
819- m_low = splitmix64 (seed);
820- seed = Crypto::get_secure_random<u64 >();
821- m_high = splitmix64 (seed);
822- }
823-
824- double get ()
825- {
826- u64 value = advance () & ((1ULL << 53 ) - 1 );
827- return value * (1.0 / (1ULL << 53 ));
828- }
829-
830- private:
831- u64 splitmix64 (u64 & state)
832- {
833- u64 z = (state += 0x9e3779b97f4a7c15ULL );
834- z = (z ^ (z >> 30 )) * 0xbf58476d1ce4e5b9ULL ;
835- z = (z ^ (z >> 27 )) * 0x94d049bb133111ebULL ;
836- return z ^ (z >> 31 );
837- }
838-
839- // Apparently this set of constants is better: https://stackoverflow.com/a/34432126
840- u64 advance ()
841- {
842- u64 s1 = m_low;
843- u64 const s0 = m_high;
844- u64 const result = s0 + s1;
845- m_low = s0;
846- s1 ^= s1 << 23 ;
847- s1 ^= s1 >> 18 ;
848- s1 ^= s0 ^ (s0 >> 5 );
849- m_high = s1;
850- return result + s1;
851- }
852-
853- u64 m_low { 0 };
854- u64 m_high { 0 };
855- };
856-
857812Value MathObject::random_impl ()
858813{
859814 // This function returns a Number value with positive sign, greater than or equal to +0𝔽 but strictly less than 1𝔽,
You can’t perform that action at this time.
0 commit comments