Index: libcfa/src/stdlib.cfa
===================================================================
--- libcfa/src/stdlib.cfa	(revision 7a6ae53a7a7f1e5b82b3d0ce74a894019c2cc3d7)
+++ libcfa/src/stdlib.cfa	(revision aa8e24c3bb790e300fce0cb4b1a3a4a258671433)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:10:29 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Nov 12 07:46:09 2020
-// Update Count     : 503
+// Last Modified On : Wed Dec 29 15:32:44 2021
+// Update Count     : 512
 //
 
@@ -221,7 +221,34 @@
 //---------------------------------------
 
-bool threading_enabled(void) __attribute__((weak)) {
-	return false;
-}
+static uint32_t seed = 0;								// current seed
+static thread_local uint32_t state;						// random state
+
+void set_seed( uint32_t seed_ ) { state = seed = seed_; }
+uint32_t get_seed() { return seed; }
+
+#define GENERATOR LCG
+
+inline uint32_t MarsagliaXor( uint32_t & state ) {
+	if ( unlikely( seed == 0 ) ) set_seed( rdtscl() );
+	else if ( unlikely( state == 0 ) ) state = seed;
+	state ^= state << 6;
+	state ^= state >> 21;
+	state ^= state << 7;
+	return state;
+} // MarsagliaXor
+
+inline uint32_t LCG( uint32_t & state ) {				// linear congruential generator
+	if ( unlikely( seed == 0 ) ) set_seed( rdtscl() );
+	else if ( unlikely( state == 0 ) ) state = seed;
+	return state = 36973 * (state & 65535) + (state >> 16);
+} // LCG
+
+uint32_t prng( PRNG & prng ) with( prng ) { callcnt += 1; return GENERATOR( state ); }
+
+uint32_t prng( void ) { return GENERATOR( state ); }
+
+//---------------------------------------
+
+bool threading_enabled( void ) __attribute__(( weak )) { return false; }
 
 // Local Variables: //
Index: libcfa/src/stdlib.hfa
===================================================================
--- libcfa/src/stdlib.hfa	(revision 7a6ae53a7a7f1e5b82b3d0ce74a894019c2cc3d7)
+++ libcfa/src/stdlib.hfa	(revision aa8e24c3bb790e300fce0cb4b1a3a4a258671433)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:12:35 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 20 21:20:03 2021
-// Update Count     : 575
+// Last Modified On : Wed Dec 29 15:30:58 2021
+// Update Count     : 591
 //
 
@@ -363,9 +363,9 @@
 
 static inline {
-	long int random( long int l, long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l) + l; } // [l,u)
-	long int random( long int u ) { if ( u < 0 ) return random( u, 0 ); else return random( 0, u ); } // [0,u)
+	long int random( long int l, long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l + 1) + l; } // [l,u]
+	long int random( long int u ) { return random( 0, u - 1 ); } // [0,u)
 	unsigned long int random( void ) { return lrand48(); }
 	unsigned long int random( unsigned long int u ) { return lrand48() % u; } // [0,u)
-	unsigned long int random( unsigned long int l, unsigned long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l) + l; } // [l,u)
+	unsigned long int random( unsigned long int l, unsigned long int u ) { if ( u < l ) [u, l] = [l, u]; return lrand48() % (u - l + 1) + l; } // [l,u]
 
 	char random( void ) { return (unsigned long int)random(); }
@@ -388,4 +388,33 @@
 //---------------------------------------
 
+struct PRNG {
+	uint32_t callcnt;									// call count
+	uint32_t seed;										// current seed
+	uint32_t state;										// random state
+}; // PRNG
+
+extern uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )); // [0,UINT_MAX]
+static inline {
+	void set_seed( PRNG & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; } // set seed
+	void ?{}( PRNG & prng ) { set_seed( prng, rdtscl() ); }	// random seed
+	void ?{}( PRNG & prng, uint32_t seed ) { set_seed( prng, seed ); } // fixed seed
+	uint32_t get_seed( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed
+	uint32_t prng( PRNG & prng, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( prng ) % u; } // [0,u)
+	uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( prng, u - l + 1 ) + l; } // [l,u]
+	uint32_t calls( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return callcnt; }
+} // distribution
+
+extern void set_seed( uint32_t seed );					// set per thread seed
+extern uint32_t get_seed();								// get seed
+extern uint32_t prng( void ) __attribute__(( warn_unused_result )); // [0,UINT_MAX]
+static inline {
+	uint32_t prng( uint32_t u ) __attribute__(( warn_unused_result ));
+	uint32_t prng( uint32_t u ) { return prng() % u; }	// [0,u)
+	uint32_t prng( uint32_t l, uint32_t u ) __attribute__(( warn_unused_result ));
+	uint32_t prng( uint32_t l, uint32_t u ) { return prng( u - l + 1 ) + l; } // [l,u]
+} // distribution
+
+//---------------------------------------
+
 extern bool threading_enabled( void ) OPTIONAL_THREAD;
 
