use crate::lds::VdCorput;
/// The HaltonN struct is a generator for the Halton(n) sequence.
///
/// Properties:
///
/// * `vdcs`: A vector of VdCorput objects.
#[derive(Debug)]
pub struct HaltonN {
vdcs: Vec<VdCorput>,
}
/// Halton(n) sequence generator
///
/// The [`HaltonN`] class is a sequence generator that generates points in a
/// N-dimensional space using the Halton sequence. The Halton sequence is a
/// low-discrepancy sequence that is commonly used in quasi-Monte Carlo methods.
/// It is generated by iterating over two different bases and calculating the
/// fractional parts of the numbers in those bases. The [`HaltonN`] class keeps
/// track of the current count and bases, and provides a `pop()` method that
/// returns the next point in the sequence as a `std::vector<double>`.
///
/// # Examples
///
/// ```
/// use lds_rs::HaltonN;
/// use approx_eq::assert_approx_eq;
///
/// let mut hgen = HaltonN::new(&[2, 3, 5, 7, 11]);
/// hgen.reseed(10);
/// for _i in 0..10 {
/// println!("{:?}", hgen.pop_vec());
/// }
/// let res = hgen.pop_vec();
///
/// assert_approx_eq!(res[0], 0.65625);
/// ```
impl HaltonN {
/// Creates a new [`HaltonN`].
///
/// The `new` function creates a new `HaltonN` struct with a specified number of `VdCorput`
/// instances.
///
/// Arguments:
///
/// * `base`: The `base` parameter is a slice of `usize` values. It represents the base values for
/// each dimension of the Halton sequence. Each dimension of the Halton sequence uses a different
/// base value to generate the sequence.
///
/// Returns:
///
/// The `new` function returns a new instance of the `HaltonN` struct.
pub fn new(base: &[usize]) -> Self {
HaltonN {
vdcs: base.iter().map(|b| VdCorput::new(*b)).collect(),
// vdcs: (0..n).map(|i| VdCorput::new(base[i])).collect(),
}
}
/// Returns the pop vec of this [`HaltonN`].
///
/// The `pop()` function is used to generate the next value in the sequence.
/// For example, in the [`VdCorput`] class, `pop()` increments the count and
/// calculates the Van der Corput sequence value for that count and base. In
/// the [`Halton`] class, `pop()` returns the next point in the Halton sequence
/// as a `[f64; 2]`. Similarly, in the [`Circle`] class, `pop()`
/// returns the next point on the unit circle as a `[f64; 2]`. In
/// the [`Sphere`] class, `pop()` returns the next point on the unit sphere as a
/// `[f64; 3]`. And in the [`Sphere3Hopf`] class, `pop()` returns
/// the next point on the 3-sphere using the Hopf fibration as a `[f64; 4]`.
pub fn pop_vec(&mut self) -> Vec<f64> {
self.vdcs.iter_mut().map(|vdc| vdc.pop()).collect()
}
/// The below code is a Rust function called `reseed` that is used to reset the state of a sequence
/// generator to a specific seed value. This allows the sequence generator to start generating the
/// sequence from the beginning or from a specific point in the sequence, depending on the value of the
/// seed.
pub fn reseed(&mut self, seed: usize) {
for vdc in self.vdcs.iter_mut() {
vdc.reseed(seed);
}
}
}