@@ -5,35 +5,43 @@ use core::ffi::{c_int, c_uint};
55
66#[ cfg_attr( not( feature = "rand_r" ) , export_name = "tinyrlibc_RAND_MAX" ) ]
77#[ cfg_attr( feature = "rand_r" , no_mangle) ]
8- pub static RAND_MAX : c_int = 0x7FFF_FFFC as _ ;
8+ pub static RAND_MAX : c_int = c_int :: MAX ;
99
1010/// Rust implementation of C library function `rand_r`
1111///
1212/// Passing NULL (core::ptr::null()) gives undefined behaviour.
1313#[ cfg_attr( not( feature = "rand_r" ) , export_name = "tinyrlibc_rand_r" ) ]
1414#[ cfg_attr( feature = "rand_r" , no_mangle) ]
1515pub unsafe extern "C" fn rand_r ( seedp : * mut c_uint ) -> c_int {
16- // This algorithm is mentioned in the ISO C standard, here extended for 32 bits.
17- let mut next = * seedp;
18- let mut result: c_int ;
19-
20- next = next. wrapping_mul ( 1103515245 ) ;
21- next = next. wrapping_add ( 12345 ) ;
22- result = ( ( next / 65536 ) % 2048 ) as c_int ;
16+ let mut result;
2317
24- next = next . wrapping_mul ( 1103515245 ) ;
25- next = next . wrapping_add ( 12345 ) ;
26- result <<= 10 ;
27- result ^= ( ( next / 65536 ) % 1024 ) as c_int ;
18+ fn pump ( input : c_uint ) -> c_uint {
19+ // This algorithm is mentioned in the ISO C standard
20+ input . wrapping_mul ( 1103515245 ) . wrapping_add ( 12345 )
21+ }
2822
29- next = next . wrapping_mul ( 1103515245 ) ;
30- next = next . wrapping_add ( 12345 ) ;
31- result <<= 10 ;
32- result ^= ( ( next / 65536 ) % 1024 ) as c_int ;
23+ fn select_top ( state : c_uint , bits : usize ) -> c_uint {
24+ // ignore the lower 16 bits, as they are low quality
25+ ( state >> 16 ) & ( ( 1 << bits ) - 1 )
26+ }
3327
28+ let mut next = * seedp;
29+ if c_int:: MAX == 32767 {
30+ // pull 15 bits in one go
31+ next = pump ( next) ;
32+ result = select_top ( next, 15 ) ;
33+ } else {
34+ // pull 31 bits in three goes
35+ next = pump ( next) ;
36+ result = select_top ( next, 11 ) << 20 ;
37+ next = pump ( next) ;
38+ result |= select_top ( next, 10 ) << 10 ;
39+ next = pump ( next) ;
40+ result |= select_top ( next, 10 ) ;
41+ }
3442 * seedp = next;
3543
36- result - 1
44+ result as c_int
3745}
3846
3947#[ cfg( test) ]
@@ -43,10 +51,9 @@ mod test {
4351 fn test_rand_r ( ) {
4452 unsafe {
4553 let mut seed = 5 ;
46- // Values taken from glibc implementation
47- assert_eq ! ( rand_r( & mut seed) , 234104183 ) ;
48- assert_eq ! ( rand_r( & mut seed) , 1214203243 ) ;
49- assert_eq ! ( rand_r( & mut seed) , 1803669307 ) ;
54+ assert_eq ! ( rand_r( & mut seed) , 234104184 ) ;
55+ assert_eq ! ( rand_r( & mut seed) , 1214203244 ) ;
56+ assert_eq ! ( rand_r( & mut seed) , 1803669308 ) ;
5057 }
5158 }
5259}
0 commit comments