use super::*;
pub const fn lcg8(state: u8, mult: u8, inc: NonZeroU8) -> u8 {
state.wrapping_mul(mult).wrapping_add(inc.get() | 1)
}
pub const fn lcg16(state: u16, mult: u16, inc: NonZeroU16) -> u16 {
state.wrapping_mul(mult).wrapping_add(inc.get() | 1)
}
pub const fn lcg32(state: u32, mult: u32, inc: NonZeroU32) -> u32 {
state.wrapping_mul(mult).wrapping_add(inc.get() | 1)
}
pub const fn lcg64(state: u64, mult: u64, inc: NonZeroU64) -> u64 {
state.wrapping_mul(mult).wrapping_add(inc.get() | 1)
}
pub const fn lcg128(state: u128, mult: u128, inc: NonZeroU128) -> u128 {
state.wrapping_mul(mult).wrapping_add(inc.get() | 1)
}
pub const fn lcg32_colosseum(state: u32) -> u32 {
lcg32(state, 0x000343FD, unsafe { NonZeroU32::new_unchecked(0x00269EC3) })
}
pub const fn lcg32_gen3gen4(state: u32) -> u32 {
lcg32(state, 0x41C64E6D, unsafe { NonZeroU32::new_unchecked(0x00006073) })
}
pub const fn lcg32_gen4alt(state: u32) -> u32 {
lcg32(state, 0x6C078965, unsafe { NonZeroU32::new_unchecked(0x00000001) })
}
pub const fn lcg64_gen5gen6(state: u64) -> u64 {
lcg64(state, 0x5D588B656C078965, unsafe { NonZeroU64::new_unchecked(0x0000000000269EC3) })
}
macro_rules! make_jump_lcgX {
($(#[$attr:meta])* $f:ident, $u:ty, $nzu:ty) => {
$(#[$attr])*
pub fn $f(mut delta: $u, state: $u, mult: $u, inc: $nzu) -> $u {
let mut cur_mult: $u = mult;
let mut cur_plus: $u = inc.get();
let mut acc_mult: $u = 1;
let mut acc_plus: $u = 0;
while delta > 0 {
if (delta & 1) > 0 {
acc_mult = acc_mult.wrapping_mul(cur_mult);
acc_plus = acc_plus.wrapping_mul(cur_mult).wrapping_add(cur_plus);
}
cur_plus = cur_mult.wrapping_add(1).wrapping_mul(cur_plus);
cur_mult = cur_mult.wrapping_mul(cur_mult);
delta /= 2;
}
acc_mult.wrapping_mul(state).wrapping_add(acc_plus)
}
};
}
make_jump_lcgX! {
jump_lcg8, u8, NonZeroU8
}
make_jump_lcgX! {
jump_lcg16, u16, NonZeroU16
}
make_jump_lcgX! {
jump_lcg32, u32, NonZeroU32
}
make_jump_lcgX! {
jump_lcg64, u64, NonZeroU64
}
make_jump_lcgX! {
jump_lcg128, u128, NonZeroU128
}