1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
//
// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
//
/*!
# Quasi-Random Sequences
This chapter describes functions for generating quasi-random sequences in arbitrary dimensions. A quasi-random sequence progressively
covers a d-dimensional space with a set of points that are uniformly distributed. Quasi-random sequences are also known as low-discrepancy
sequences. The quasi-random sequence generators use an interface that is similar to the interface for random number generators, except
that seeding is not required—each generator produces a single sequence.
## References
The implementations of the quasi-random sequence routines are based on the algorithms described in the following paper,
P. Bratley and B.L. Fox and H. Niederreiter, “Algorithm 738: Programs to Generate Niederreiter’s Low-discrepancy Sequences”, ACM
Transactions on Mathematical Software, Vol. 20, No. 4, December, 1994, p. 494–495.
!*/
use crate::Value;
use ffi::FFI;
ffi_wrapper!(QRng, *mut sys::gsl_qrng, gsl_qrng_free);
impl QRng {
/// This function returns a pointer to a newly-created instance of a quasi-random sequence
/// generator of type T and dimension d. If there is insufficient memory to create the generator
/// then the function returns a null pointer and the error handler is invoked with an error code
/// of [`Value::NoMemory`].
#[doc(alias = "gsl_qrng_alloc")]
pub fn new(t: QRngType, d: u32) -> Option<Self> {
let tmp = unsafe { sys::gsl_qrng_alloc(t.unwrap_shared(), d) };
if tmp.is_null() {
None
} else {
Some(Self::wrap(tmp))
}
}
/// This function reinitializes the generator self to its starting point. Note that quasi-random
/// sequences do not use a seed and always produce the same set of values.
#[doc(alias = "gsl_qrng_init")]
pub fn init(&mut self) {
unsafe { sys::gsl_qrng_init(self.unwrap_unique()) }
}
/// This function stores the next point from the sequence generator self in the array x. The
/// space available for x must match the dimension of the generator. The point x will lie in the
/// range 0 < x_i < 1 for each x_i.
#[doc(alias = "gsl_qrng_get")]
pub fn get(&self, x: &mut [f64]) -> Value {
Value::from(unsafe { sys::gsl_qrng_get(self.unwrap_shared(), x.as_mut_ptr()) })
}
/// This function returns a pointer to the name of the generator.
#[doc(alias = "gsl_qrng_name")]
pub fn name(&self) -> Option<String> {
let tmp = unsafe { sys::gsl_qrng_name(self.unwrap_shared()) };
if tmp.is_null() {
None
} else {
unsafe {
Some(
String::from_utf8_lossy(::std::ffi::CStr::from_ptr(tmp).to_bytes()).to_string(),
)
}
}
}
/// These functions return a pointer to the state of generator r and its size.
#[doc(alias = "gsl_qrng_size")]
pub fn size(&self) -> usize {
unsafe { sys::gsl_qrng_size(self.unwrap_shared()) }
}
/// This function returns a pointer to the state of generator `self`.
#[doc(alias = "gsl_qrng_state")]
pub fn state(&mut self) -> Option<&[i8]> {
let tmp = unsafe { sys::gsl_qrng_state(self.unwrap_shared()) };
if tmp.is_null() {
None
} else {
Some(unsafe { ::std::slice::from_raw_parts(tmp as _, self.size()) })
}
}
/// This function returns a pointer to the state of generator `self`.
// checker:ignore
#[doc(alias = "gsl_qrng_state")]
pub fn state_mut(&mut self) -> Option<&mut [i8]> {
let tmp = unsafe { sys::gsl_qrng_state(self.unwrap_shared()) };
if tmp.is_null() {
None
} else {
Some(unsafe { ::std::slice::from_raw_parts_mut(tmp as _, self.size()) })
}
}
/// This function copies the quasi-random sequence generator src into the pre-existing generator
/// `dest`, making dest into an exact copy of `self`. The two generators must be of the same
/// type.
// checker:ignore
#[doc(alias = "gsl_qrng_memcpy")]
pub fn copy(&self, dest: &mut QRng) -> Value {
Value::from(unsafe { sys::gsl_qrng_memcpy(dest.unwrap_unique(), self.unwrap_shared()) })
}
}
impl Clone for QRng {
/// This function returns a pointer to a newly created generator which is an exact copy of the
/// generator `self`.
#[doc(alias = "gsl_qrng_clone")]
fn clone(&self) -> Self {
unsafe { Self::wrap(sys::gsl_qrng_clone(self.unwrap_shared())) }
}
}
ffi_wrapper!(QRngType, *const sys::gsl_qrng_type);
impl QRngType {
/// This generator uses the algorithm described in Bratley, Fox, Niederreiter, ACM Trans. Model.
/// Comp. Sim. 2, 195 (1992). It is valid up to 12 dimensions.
#[doc(alias = "gsl_qrng_niederreiter_2")]
pub fn niederreiter_2() -> QRngType {
ffi_wrap!(gsl_qrng_niederreiter_2)
}
/// This generator uses the Sobol sequence described in Antonov, Saleev, USSR Comput. Maths.
/// Math. Phys. 19, 252 (1980). It is valid up to 40 dimensions.
#[doc(alias = "gsl_qrng_sobol")]
pub fn sobol() -> QRngType {
ffi_wrap!(gsl_qrng_sobol)
}
/// These generators use the Halton and reverse Halton sequences described in J.H. Halton,
/// Numerische Mathematik 2, 84-90 (1960) and B. Vandewoestyne and R. Cools Computational and
/// Applied Mathematics 189, 1&2, 341-361 (2006). They are valid up to 1229 dimensions.
#[doc(alias = "gsl_qrng_halton")]
pub fn halton() -> QRngType {
ffi_wrap!(gsl_qrng_halton)
}
#[doc(alias = "gsl_qrng_reversehalton")]
pub fn reversehalton() -> QRngType {
ffi_wrap!(gsl_qrng_reversehalton)
}
}