Index: libcfa/src/bits/random.hfa
===================================================================
--- libcfa/src/bits/random.hfa	(revision eac318afd8929f4e697581980c4ef80782c95d87)
+++ libcfa/src/bits/random.hfa	(revision 4c6ba5ad003f3f9296090ec36391b755cf9d6c45)
@@ -32,4 +32,5 @@
 	//#define XORSHIFT_6_21_7
 	#define XOSHIRO128PP
+    // #define SPLITMIX_32
 #else													// 32-bit architecture
 	// 64-bit generators
@@ -40,4 +41,5 @@
 	//#define XORSHIFT_6_21_7
 	#define XOSHIRO128PP
+    // #define SPLITMIX_32
 #endif // __x86_64__
 
@@ -77,4 +79,9 @@
 #define PRNG_STATE_32_T uint32_t
 #endif // XORSHIFT_6_21_7
+
+#ifdef SPLITMIX_32
+#define PRNG_NAME_32 splitmix
+#define PRNG_STATE_32_T uint32_t
+#endif // SPLITMIX32
 
 #ifdef XORSHIFT_12_25_27
@@ -119,74 +126,23 @@
 #ifdef __cforall										// don't include in C code (invoke.h)
 
-// https://prng.di.unimi.it/xoshiro256starstar.c
-//
-// This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.  It has excellent (sub-ns) speed, a state
-// (256 bits) that is large enough for any parallel application, and it passes all tests we are aware of.
-//
-// For generating just floating-point numbers, xoshiro256+ is even faster.
-//
-// The state must be seeded so that it is not everywhere zero. If you have a 64-bit seed, we suggest to seed a
-// splitmix64 generator and use its output to fill s.
-
-#ifndef XOSHIRO256PP
-typedef struct xoshiro256pp_t { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;
-#endif // ! XOSHIRO256PP
-
-static inline uint64_t xoshiro256pp( xoshiro256pp_t & rs ) with(rs) {
-	inline uint64_t rotl( const uint64_t x, int k ) {
-		return (x << k) | (x >> (64 - k));
-	} // rotl
-
-	const uint64_t result = rotl( s0 + s3, 23 ) + s0;
-	const uint64_t t = s1 << 17;
-
-	s2 ^= s0;
-	s3 ^= s1;
-	s1 ^= s2;
-	s0 ^= s3;
-	s2 ^= t;
-	s3 = rotl( s3, 45 );
-	return result;
-} // xoshiro256pp
-
-static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) {
-	state = (xoshiro256pp_t){ seed, seed, seed, seed };
-	xoshiro256pp( state );
-} // xoshiro256pp_set_seed
-
-// https://prng.di.unimi.it/xoshiro128plusplus.c
-//
-// This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid generators. It has excellent speed, a state size
-// (128 bits) that is large enough for mild parallelism, and it passes all tests we are aware of.
-//
-// For generating just single-precision (i.e., 32-bit) floating-point numbers, xoshiro128+ is even faster.
-//
-// The state must be seeded so that it is not everywhere zero.
-
-#ifndef XOSHIRO128PP
-typedef struct xoshiro128pp_t { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;
-#endif // ! XOSHIRO128PP
-
-static inline uint32_t xoshiro128pp( xoshiro128pp_t & rs ) with(rs) {
-	inline uint32_t rotl( const uint32_t x, int k ) {
-		return (x << k) | (x >> (32 - k));
-	} // rotl
-
-	const uint32_t result = rotl( s0 + s3, 7 ) + s0;
-	const uint32_t t = s1 << 9;
-
-	s2 ^= s0;
-	s3 ^= s1;
-	s1 ^= s2;
-	s0 ^= s3;
-	s2 ^= t;
-	s3 = rotl( s3, 11 );
-	return result;
-} // xoshiro128pp
-
-static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) {
-	state = (xoshiro128pp_t){ seed, seed, seed, seed };
-	xoshiro128pp( state );								// prime
-} // xoshiro128pp_set_seed
+// Splitmix32
+// https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32
+// Splitmix32 is not recommended for demanding random number requirements,
+// but is often used to calculate initial states for other more complex
+// pseudo-random number generators.
+// SplitMix32 is a 32 bit variant of Splitmix64
+
+static inline uint32_t splitmix32( uint32_t & state ) {
+    state += 0x9e3779b9;
+    uint64_t z = state;
+    z = (z ^ (z >> 15)) * 0x85ebca6b;
+    z = (z ^ (z >> 13)) * 0xc2b2ae35;
+    return z ^ (z >> 16);
+}
+
+static inline void splitmix32_set_seed( uint32_t & state , uint64_t seed ) {
+    state = seed;
+    splitmix32( state );								// prime
+} // splitmix32_set_seed
 
 #ifdef __SIZEOF_INT128__
@@ -222,4 +178,91 @@
 #endif // __SIZEOF_INT128__
 
+// https://prng.di.unimi.it/xoshiro256starstar.c
+//
+// This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.  It has excellent (sub-ns) speed, a state
+// (256 bits) that is large enough for any parallel application, and it passes all tests we are aware of.
+//
+// For generating just floating-point numbers, xoshiro256+ is even faster.
+//
+// The state must be seeded so that it is not everywhere zero. If you have a 64-bit seed, we suggest to seed a
+// splitmix64 generator and use its output to fill s.
+
+#ifndef XOSHIRO256PP
+typedef struct xoshiro256pp_t { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;
+#endif // ! XOSHIRO256PP
+
+static inline uint64_t xoshiro256pp( xoshiro256pp_t & rs ) with(rs) {
+	inline uint64_t rotl( const uint64_t x, int k ) {
+		return (x << k) | (x >> (64 - k));
+	} // rotl
+
+	const uint64_t result = rotl( s0 + s3, 23 ) + s0;
+	const uint64_t t = s1 << 17;
+
+	s2 ^= s0;
+	s3 ^= s1;
+	s1 ^= s2;
+	s0 ^= s3;
+	s2 ^= t;
+	s3 = rotl( s3, 45 );
+	return result;
+} // xoshiro256pp
+
+static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) {
+    uint64_t state;
+    wyhash64_set_seed( state, seed );
+    // these are done explicitly in this order to attain repeatable seeding.
+    // do not call splitmix32 directly in the state init since order of argument evaluation
+    // may not be consistent leading to irreproducible seeding
+    uint64_t seed1 = wyhash64( state );
+    uint64_t seed2 = wyhash64( state );
+    uint64_t seed3 = wyhash64( state );
+    uint64_t seed4 = wyhash64( state );
+	state = (xoshiro256pp_t){ seed1, seed2, seed3, seed4 };
+	xoshiro256pp( state );
+} // xoshiro256pp_set_seed
+
+// https://prng.di.unimi.it/xoshiro128plusplus.c
+//
+// This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid generators. It has excellent speed, a state size
+// (128 bits) that is large enough for mild parallelism, and it passes all tests we are aware of.
+//
+// For generating just single-precision (i.e., 32-bit) floating-point numbers, xoshiro128+ is even faster.
+//
+// The state must be seeded so that it is not everywhere zero.
+
+#ifndef XOSHIRO128PP
+typedef struct xoshiro128pp_t { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;
+#endif // ! XOSHIRO128PP
+
+static inline uint32_t xoshiro128pp( xoshiro128pp_t & rs ) with(rs) {
+	inline uint32_t rotl( const uint32_t x, int k ) {
+		return (x << k) | (x >> (32 - k));
+	} // rotl
+
+	const uint32_t result = rotl( s0 + s3, 7 ) + s0;
+	const uint32_t t = s1 << 9;
+
+	s2 ^= s0;
+	s3 ^= s1;
+	s1 ^= s2;
+	s0 ^= s3;
+	s2 ^= t;
+	s3 = rotl( s3, 11 );
+	return result;
+} // xoshiro128pp
+
+static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) {
+    // these are done explicitly in this order to attain repeatable seeding.
+    // do not call splitmix32 directly in the state init since order of argument evaluation
+    // may not be consistent leading to irreproducible seeding
+    uint32_t seed1 = splitmix32( seed );
+    uint32_t seed2 = splitmix32( seed );
+    uint32_t seed3 = splitmix32( seed );
+    uint32_t seed4 = splitmix32( seed );
+	state = (xoshiro128pp_t){ seed1, seed2, seed3, seed4 };
+	xoshiro128pp( state );								// prime
+} // xoshiro128pp_set_seed
+
 //--------------------------------------------------
 static inline uint64_t xorshift_13_7_17( uint64_t & state ) {
@@ -316,5 +359,12 @@
 
 static inline void xorwow_set_seed( xorwow_t & rs, uint32_t seed ) {
-	rs = (xorwow_t){ seed, seed, seed, seed, 0 };
+    // these are done explicitly in this order to attain repeatable seeding.
+    // do not call splitmix32 directly in the state init since order of argument evaluation
+    // may not be consistent leading to irreproducible seeding
+    uint32_t seed1 = splitmix32( seed );
+    uint32_t seed2 = splitmix32( seed );
+    uint32_t seed3 = splitmix32( seed );
+    uint32_t seed4 = splitmix32( seed );
+	rs = (xorwow_t){ seed1, seed2, seed3, seed4, 0 };
 	xorwow( rs );										// prime
 } // xorwow_set_seed
