|
@@ -5,11 +5,11 @@ use crate::platform::types::*;
|
|
/* The default element buffer for the linear congruential generator's
|
|
/* The default element buffer for the linear congruential generator's
|
|
* sequence. Implemented using a c_ushort array for consistency between
|
|
* sequence. Implemented using a c_ushort array for consistency between
|
|
* the drand48()/lrand48()/mrand48() and erand48()/nrand48()/jrand48()
|
|
* the drand48()/lrand48()/mrand48() and erand48()/nrand48()/jrand48()
|
|
- * functions, and with STASHED_XI (see below). */
|
|
|
|
-pub static mut DEFAULT_XI: [c_ushort; 3] = [0; 3];
|
|
|
|
|
|
+ * functions, and with SEED48_XSUBI (see below). */
|
|
|
|
+pub static mut DEFAULT_XSUBI: [c_ushort; 3] = [0; 3];
|
|
|
|
|
|
// Used by seed48() (returns a pointer to this array).
|
|
// Used by seed48() (returns a pointer to this array).
|
|
-pub static mut STASHED_XI: [c_ushort; 3] = [0; 3];
|
|
|
|
|
|
+pub static mut SEED48_XSUBI: [c_ushort; 3] = [0; 3];
|
|
|
|
|
|
/* Multiplier and addend, which may be set through lcong48(). Default
|
|
/* Multiplier and addend, which may be set through lcong48(). Default
|
|
* values as specified in POSIX. */
|
|
* values as specified in POSIX. */
|
|
@@ -27,60 +27,64 @@ pub unsafe fn reset_a_and_c() {
|
|
|
|
|
|
/// Build a 48-bit integer from a size-3 array of unsigned short.
|
|
/// Build a 48-bit integer from a size-3 array of unsigned short.
|
|
///
|
|
///
|
|
-/// Takes a pointer argument due to the inappropriate C function
|
|
|
|
-/// signatures generated from Rust's sized arrays, see
|
|
|
|
|
|
+/// Pointers to c_ushort can be converted to &[c_ushort; 3] by taking
|
|
|
|
+/// &*(YOUR_C_USHORT_POINTER as *const [c_ushort; 3])
|
|
|
|
+///
|
|
|
|
+/// See also this cbindgen issue for why the stdlib functions can't just
|
|
|
|
+/// have an xsubi: *mut [c_ushort; 3] parameter:
|
|
/// https://github.com/eqrion/cbindgen/issues/171
|
|
/// https://github.com/eqrion/cbindgen/issues/171
|
|
-pub unsafe fn uint48_from_ushort_arr3(arr_ptr: *const c_ushort) -> u64 {
|
|
|
|
- let arr = [*arr_ptr.offset(0), *arr_ptr.offset(1), *arr_ptr.offset(2)];
|
|
|
|
-
|
|
|
|
|
|
+pub fn u48_from_ushort_arr3(arr: &[c_ushort; 3]) -> u64 {
|
|
/* Cast via u16 to ensure we get only the lower 16 bits of each
|
|
/* Cast via u16 to ensure we get only the lower 16 bits of each
|
|
* element, as specified by POSIX. */
|
|
* element, as specified by POSIX. */
|
|
u64::from(arr[0] as u16) | (u64::from(arr[1] as u16) << 16) | (u64::from(arr[2] as u16) << 32)
|
|
u64::from(arr[0] as u16) | (u64::from(arr[1] as u16) << 16) | (u64::from(arr[2] as u16) << 32)
|
|
}
|
|
}
|
|
|
|
|
|
-/// Set a size-3 array of unsigned short from a 48-bit integer.
|
|
|
|
-pub unsafe fn set_ushort_arr3_from_uint48(arr_ptr: *mut c_ushort, value: u64) {
|
|
|
|
- *arr_ptr.offset(0) = c_ushort::from(value as u16);
|
|
|
|
- *arr_ptr.offset(1) = c_ushort::from((value >> 16) as u16);
|
|
|
|
- *arr_ptr.offset(2) = c_ushort::from((value >> 32) as u16);
|
|
|
|
|
|
+/// Make a size-3 array of unsigned short from a 48-bit integer.
|
|
|
|
+pub fn ushort_arr3_from_u48(value: u64) -> [c_ushort; 3] {
|
|
|
|
+ [
|
|
|
|
+ c_ushort::from(value as u16),
|
|
|
|
+ c_ushort::from((value >> 16) as u16),
|
|
|
|
+ c_ushort::from((value >> 32) as u16),
|
|
|
|
+ ]
|
|
}
|
|
}
|
|
|
|
|
|
/// Advances the buffer from the input argument to the next element in
|
|
/// Advances the buffer from the input argument to the next element in
|
|
/// the linear congruential generator's sequence.
|
|
/// the linear congruential generator's sequence.
|
|
///
|
|
///
|
|
/// Modifies the passed argument in-place and returns the new value as a
|
|
/// Modifies the passed argument in-place and returns the new value as a
|
|
-/// u64. The input argument must be a size-3 array.
|
|
|
|
-pub unsafe fn generator_step(xi_arr_ptr: *mut c_ushort) -> u64 {
|
|
|
|
- let old_xi: u64 = uint48_from_ushort_arr3(xi_arr_ptr);
|
|
|
|
|
|
+/// u64.
|
|
|
|
+pub unsafe fn generator_step(xsubi: &mut [c_ushort; 3]) -> u64 {
|
|
|
|
+ let old_xsubi_value: u64 = u48_from_ushort_arr3(xsubi);
|
|
|
|
|
|
/* The recurrence relation of the linear congruential generator,
|
|
/* The recurrence relation of the linear congruential generator,
|
|
* X_(n+1) = (a * X_n + c) % m,
|
|
* X_(n+1) = (a * X_n + c) % m,
|
|
* with m = 2**48. The multiplication and addition can overflow a
|
|
* 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. */
|
|
* u64, but we just let it wrap since we take mod 2**48 anyway. */
|
|
- let new_xi: u64 = A.wrapping_mul(old_xi).wrapping_add(u64::from(C)) & 0xffff_ffff_ffff;
|
|
|
|
|
|
+ let new_xsubi_value: u64 =
|
|
|
|
+ A.wrapping_mul(old_xsubi_value).wrapping_add(u64::from(C)) & 0xffff_ffff_ffff;
|
|
|
|
|
|
- set_ushort_arr3_from_uint48(xi_arr_ptr, new_xi);
|
|
|
|
- new_xi
|
|
|
|
|
|
+ *xsubi = ushort_arr3_from_u48(new_xsubi_value);
|
|
|
|
+ new_xsubi_value
|
|
}
|
|
}
|
|
|
|
|
|
/// Get a C `double` from a 48-bit integer (for `drand48()` and
|
|
/// Get a C `double` from a 48-bit integer (for `drand48()` and
|
|
/// `erand48()`).
|
|
/// `erand48()`).
|
|
-pub fn float64_from_x(x: u64) -> c_double {
|
|
|
|
|
|
+pub fn f64_from_x(x: u64) -> c_double {
|
|
/* We set the exponent to 0, and the 48-bit integer is copied into the high
|
|
/* 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
|
|
* 48 of the 52 significand bits. The value then lies in the range
|
|
* [1.0, 2.0), from which we simply subtract 1.0. */
|
|
* [1.0, 2.0), from which we simply subtract 1.0. */
|
|
- f64::from_bits(0x3ff0_0000_0000_0000_u64 | (x << 4)) - 1.0f64
|
|
|
|
|
|
+ f64::from_bits(0x3ff0_0000_0000_0000_u64 | (x << 4)) - 1.0
|
|
}
|
|
}
|
|
|
|
|
|
/// Get the high 31 bits of a 48-bit integer (for `lrand48()` and
|
|
/// Get the high 31 bits of a 48-bit integer (for `lrand48()` and
|
|
/// `nrand48()`).
|
|
/// `nrand48()`).
|
|
-pub fn uint31_from_x(x: u64) -> c_long {
|
|
|
|
|
|
+pub fn u31_from_x(x: u64) -> c_long {
|
|
(x >> 17) as c_long
|
|
(x >> 17) as c_long
|
|
}
|
|
}
|
|
|
|
|
|
/// Get the high 32 bits, signed, of a 48-bit integer (for `mrand48()`
|
|
/// Get the high 32 bits, signed, of a 48-bit integer (for `mrand48()`
|
|
/// and `jrand48()`).
|
|
/// and `jrand48()`).
|
|
-pub fn int32_from_x(x: u64) -> c_long {
|
|
|
|
|
|
+pub fn i32_from_x(x: u64) -> c_long {
|
|
// Cast via i32 to ensure we get the sign correct
|
|
// Cast via i32 to ensure we get the sign correct
|
|
c_long::from((x >> 16) as i32)
|
|
c_long::from((x >> 16) as i32)
|
|
}
|
|
}
|