Commit f1b88d9e by jD91mZM2

Merge branch 'lcg48' into 'master'

```Implement LCG pseudorandom number functions

See merge request !213```
parents 06ab5b7d 45860e92
Pipeline #4161 passed with stages
in 30 minutes and 28 seconds
 //! Helper functions for pseudorandom number generation using LCG, see http://pubs.opengroup.org/onlinepubs/7908799/xsh/drand48.html use platform::types::*; /* The current element of the linear congruential generator's sequence. Any * function that sets this variable must ensure that only the lower 48 bits get * set. */ pub static mut XI: u64 = 0; /* Multiplier and addend, which may be set through lcong48(). Default values as * specified in POSIX. */ pub static mut A: u64 = 0x5deece66d; pub static mut C: u16 = 0xb; /// Advances the linear congruential generator to the next element in its /// sequence. pub unsafe fn generator_step() { /* The recurrence relation of the linear congruential generator, * X_(n+1) = (a * X_n + c) % m, * with m = 2**48. The multiplication and addition can overflow a u64, but * we just let it wrap since we take mod 2**48 anyway. */ XI = A.wrapping_mul(XI).wrapping_add(u64::from(C)) & 0xffff_ffff_ffff; } /// Get a C `double` from a 48-bit integer (for `drand48()` and `erand48()`). pub fn x_to_float64(x: u64) -> c_double { /* We set the exponent to 0, and the 48-bit integer is copied into the high * 48 of the 52 significand bits. The value then lies in the range * [1.0, 2.0), from which we simply subtract 1.0. */ f64::from_bits(0x3ff0_0000_0000_0000_u64 | (x << 4)) - 1.0f64 } /// Get the high 31 bits of a 48-bit integer (for `lrand48()` and `nrand48()`). pub fn x_to_uint31(x: u64) -> c_long { (x >> 17) as c_long } /// Get the high 32 bits, signed, of a 48-bit integer (for `mrand48()` and /// `jrand48()`). pub fn x_to_int32(x: u64) -> c_long { // Cast via i32 to ensure we get the sign correct (x >> 16) as i32 as c_long }
 ... ... @@ -20,6 +20,7 @@ use platform; use platform::types::*; use platform::{Pal, Sys}; mod lcg48; mod sort; pub const EXIT_FAILURE: c_int = 1; ... ... @@ -227,9 +228,10 @@ pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t { } } // #[no_mangle] pub extern "C" fn drand48() -> c_double { unimplemented!(); #[no_mangle] pub unsafe extern "C" fn drand48() -> c_double { lcg48::generator_step(); lcg48::x_to_float64(lcg48::XI) } // #[no_mangle] ... ... @@ -410,9 +412,10 @@ pub extern "C" fn lldiv(numer: c_longlong, denom: c_longlong) -> lldiv_t { } } // #[no_mangle] pub extern "C" fn lrand48() -> c_long { unimplemented!(); #[no_mangle] pub unsafe extern "C" fn lrand48() -> c_long { lcg48::generator_step(); lcg48::x_to_uint31(lcg48::XI) } #[no_mangle] ... ... @@ -566,9 +569,10 @@ pub extern "C" fn mkstemps(name: *mut c_char, suffix_len: c_int) -> c_int { mkostemps(name, suffix_len, 0) } // #[no_mangle] pub extern "C" fn mrand48() -> c_long { unimplemented!(); #[no_mangle] pub unsafe extern "C" fn mrand48() -> c_long { lcg48::generator_step(); lcg48::x_to_int32(lcg48::XI) } // #[no_mangle] ... ... @@ -775,9 +779,12 @@ pub unsafe extern "C" fn srand(seed: c_uint) { RNG = Some(XorShiftRng::from_seed([seed as u8; 16])); } // #[no_mangle] pub extern "C" fn srand48(seed: c_long) { unimplemented!(); #[no_mangle] pub unsafe extern "C" fn srand48(seedval: c_long) { /* Set the high 32 bits of the 48-bit X_i value to the lower 32 bits * of the input argument, and the lower 16 bits to 0x330e, as * specified in POSIX. */ lcg48::XI = (((seedval & 0xffff_ffff) as u64) << 16) | 0x330e_u64; } // #[no_mangle] ... ...
 ... ... @@ -41,6 +41,7 @@ EXPECT_NAMES=\ stdlib/atoi \ stdlib/div \ stdlib/env \ stdlib/lcg48 \ stdlib/mkostemps \ stdlib/rand \ stdlib/strtod \ ... ...
 lrand48 (uninitialized): 0 2116118 89401895 379337186 782977366 196130996 198207689 1046291021 1131187612 975888346 drand48: 0.750266 0.607593 0.567593 0.799563 0.984984 0.205670 0.625922 0.794426 0.369416 0.854100 lrand48: 1611183183 1304796356 1218897288 1717049088 2115236938 441672110 1344158015 1706017430 793314380 1834165927 mrand48: -1072600929 -1685374584 -1857172720 -860869119 -64493420 883344220 -1606651266 -882932436 1586628760 -626635441
 #include #include #include "test_helpers.h" int main(void) { long x_l, x_m; double x_d; long seedval = 0xcafebeef; printf("lrand48 (uninitialized):"); for (int i = 0; i < 10; i++) { x_l = lrand48(); printf(" %ld", x_l); } printf("\n"); srand48(seedval); printf("drand48:"); for (int i = 0; i < 10; i++) { x_d = drand48(); printf(" %lf", x_d); } printf("\n"); srand48(seedval); printf("lrand48:"); for (int i = 0; i < 10; i++) { x_l = lrand48(); printf(" %ld", x_l); } printf("\n"); srand48(seedval); printf("mrand48:"); for (int i = 0; i < 10; i++) { x_m = mrand48(); printf(" %ld", x_m); } printf("\n"); }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!