use std::sync::atomic::{AtomicU64, Ordering};
const MAX_DIGITS: usize = 64;
#[derive(Debug)]
pub struct VdCorput {
base: u64,
count: AtomicU64,
factor_lst: Vec<u64>,
}
impl VdCorput {
pub fn new(base: u64, scale: u32) -> Self {
let mut factor = 1u64;
let n = (scale as usize).min(MAX_DIGITS);
let mut factor_lst = vec![0u64; MAX_DIGITS];
for i in 0..n {
factor_lst[n - 1 - i] = factor;
factor = factor.checked_mul(base).expect("scale too large");
}
Self {
base,
count: AtomicU64::new(0),
factor_lst,
}
}
pub fn pop(&mut self) -> u64 {
let count = self.count.fetch_add(1, Ordering::Relaxed) + 1;
let mut count = count;
let mut reslt = 0;
let mut idx = 0;
while count != 0 {
let remainder = count % self.base;
count /= self.base;
reslt += remainder * self.factor_lst[idx];
idx += 1;
}
reslt
}
pub fn peek(&self) -> u64 {
let mut count = self.count.load(Ordering::Relaxed) + 1;
let mut reslt = 0;
let mut idx = 0;
while count != 0 {
let remainder = count % self.base;
count /= self.base;
reslt += remainder * self.factor_lst[idx];
idx += 1;
}
reslt
}
pub fn advance(&self, n: u64) {
self.count.fetch_add(n, Ordering::Relaxed);
}
pub fn get_index(&self) -> u64 {
self.count.load(Ordering::Relaxed)
}
pub fn reseed(&mut self, seed: u64) {
self.count.store(seed, Ordering::Relaxed);
}
}
impl Default for VdCorput {
fn default() -> Self {
Self::new(2, 10)
}
}
impl Iterator for VdCorput {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
Some(self.pop())
}
}
pub struct Halton {
vdc0: VdCorput,
vdc1: VdCorput,
}
impl Halton {
pub fn new(base: [u64; 2], scale: [u32; 2]) -> Self {
Self {
vdc0: VdCorput::new(base[0], scale[0]),
vdc1: VdCorput::new(base[1], scale[1]),
}
}
pub fn pop(&mut self) -> [u64; 2] {
[self.vdc0.pop(), self.vdc1.pop()]
}
pub fn reseed(&mut self, seed: u64) {
self.vdc0.reseed(seed);
self.vdc1.reseed(seed);
}
}
impl Iterator for Halton {
type Item = [u64; 2];
fn next(&mut self) -> Option<Self::Item> {
Some(self.pop())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ilds_vdcorput_pop() {
let mut vdc = VdCorput::new(2, 10);
vdc.reseed(0);
assert_eq!(vdc.pop(), 512); assert_eq!(vdc.pop(), 256); assert_eq!(vdc.pop(), 768); assert_eq!(vdc.pop(), 128); }
#[test]
fn test_ilds_vdcorput_reseed() {
let mut vdc = VdCorput::new(2, 10);
vdc.reseed(5);
assert_eq!(vdc.pop(), 384); vdc.reseed(0);
assert_eq!(vdc.pop(), 512); }
#[test]
fn test_ilds_vdcorput_default() {
let mut vdc = VdCorput::default();
vdc.reseed(0);
assert_eq!(vdc.pop(), 512);
assert_eq!(vdc.pop(), 256);
}
#[test]
fn test_ilds_halton_pop() {
let mut hgen = Halton::new([2, 3], [11, 7]);
hgen.reseed(0);
let res = hgen.pop();
assert_eq!(res[0], 1024); assert_eq!(res[1], 729);
let res = hgen.pop();
assert_eq!(res[0], 512); assert_eq!(res[1], 1458); }
#[test]
fn test_ilds_vdcorput_different_bases() {
let mut vdc = VdCorput::new(3, 5);
vdc.reseed(0);
assert_eq!(vdc.pop(), 81); assert_eq!(vdc.pop(), 162);
let mut vdc = VdCorput::new(5, 3);
vdc.reseed(0);
assert_eq!(vdc.pop(), 25); assert_eq!(vdc.pop(), 50); }
#[test]
fn test_ilds_vdcorput_different_scales() {
let mut vdc1 = VdCorput::new(2, 5);
vdc1.reseed(0);
assert_eq!(vdc1.pop(), 16);
let mut vdc2 = VdCorput::new(2, 10);
vdc2.reseed(0);
assert_eq!(vdc2.pop(), 512);
let mut vdc3 = VdCorput::new(2, 15);
vdc3.reseed(0);
assert_eq!(vdc3.pop(), 16384); }
#[test]
fn test_ilds_vdcorput_large_values() {
let mut vdc = VdCorput::new(2, 20);
vdc.reseed(1000);
for _ in 0..10 {
let value = vdc.pop();
assert!(value < vdc.factor_lst[0] * vdc.base);
}
}
#[test]
fn test_ilds_halton_different_bases_and_scales() {
let mut hgen = Halton::new([3, 5], [5, 7]);
hgen.reseed(0);
let res = hgen.pop();
assert_eq!(res[0], 81); assert_eq!(res[1], 15625);
let mut hgen = Halton::new([5, 7], [3, 4]);
hgen.reseed(0);
let res = hgen.pop();
assert_eq!(res[0], 25); assert_eq!(res[1], 343); }
#[test]
fn test_ilds_halton_large_values() {
let mut hgen = Halton::new([2, 3], [15, 10]);
hgen.reseed(0);
for _ in 0..10 {
let res = hgen.pop();
assert!(res[0] < hgen.vdc0.factor_lst[0] * hgen.vdc0.base);
assert!(res[1] < hgen.vdc1.factor_lst[0] * hgen.vdc1.base);
}
}
#[test]
fn test_ilds_sequence_properties() {
let mut vdc = VdCorput::new(2, 10);
for _ in 0..100 {
let value = vdc.pop();
assert!(value < vdc.factor_lst[0] * vdc.base);
}
let mut hgen = Halton::new([2, 3], [10, 8]);
for _ in 0..100 {
let res = hgen.pop();
assert!(res[0] < hgen.vdc0.factor_lst[0] * hgen.vdc0.base);
assert!(res[1] < hgen.vdc1.factor_lst[0] * hgen.vdc1.base);
}
}
#[test]
fn test_ilds_reseed_consistency() {
let mut vdc = VdCorput::new(2, 10);
vdc.reseed(10);
let seq1: Vec<_> = (0..5).map(|_| vdc.pop()).collect();
vdc.reseed(10);
let seq2: Vec<_> = (0..5).map(|_| vdc.pop()).collect();
assert_eq!(seq1, seq2);
vdc.reseed(10);
let seq3: Vec<_> = (0..5).map(|_| vdc.pop()).collect();
vdc.reseed(20);
let seq4: Vec<_> = (0..5).map(|_| vdc.pop()).collect();
assert_ne!(seq3, seq4);
}
#[test]
fn test_ilds_default_implementation() {
let mut vdc = VdCorput::default();
vdc.reseed(0);
assert_eq!(vdc.pop(), 512);
let vdc_default = VdCorput::default();
assert_eq!(vdc_default.base, 2);
assert_eq!(vdc_default.factor_lst[0] * vdc_default.base, 1024);
}
#[test]
fn test_ilds_vdcorput_peek() {
let mut vdc = VdCorput::new(2, 10);
vdc.reseed(0);
let peeked = vdc.peek();
assert_eq!(peeked, 512);
let popped = vdc.pop();
assert_eq!(popped, 512); assert_eq!(vdc.peek(), 256);
}
#[test]
fn test_ilds_vdcorput_advance() {
let mut vdc = VdCorput::new(2, 10);
vdc.reseed(0);
vdc.advance(3);
assert_eq!(vdc.pop(), 128); vdc.reseed(0);
vdc.advance(4);
assert_eq!(vdc.pop(), 640);
}
#[test]
fn test_ilds_vdcorput_get_index() {
let mut vdc = VdCorput::new(2, 10);
assert_eq!(vdc.get_index(), 0);
vdc.pop();
assert_eq!(vdc.get_index(), 1);
vdc.pop();
assert_eq!(vdc.get_index(), 2);
vdc.reseed(5);
assert_eq!(vdc.get_index(), 5);
}
#[test]
fn test_ilds_halton_iterator() {
let mut hgen = Halton::new([2, 3], [11, 7]);
hgen.reseed(0);
let values: Vec<[u64; 2]> = hgen.take(3).collect();
assert_eq!(values.len(), 3);
assert_eq!(values[0][0], 1024);
assert_eq!(values[0][1], 729);
assert_eq!(values[1][0], 512);
assert_eq!(values[1][1], 1458);
}
}