#![allow(clippy::unreadable_literal)]
#![forbid(unsafe_code)]
#[inline]
pub const fn lcg8(state: u8, mult: u8, inc: u8) -> u8 {
state.wrapping_mul(mult).wrapping_add(inc)
}
#[inline]
pub const fn lcg16(state: u16, mult: u16, inc: u16) -> u16 {
state.wrapping_mul(mult).wrapping_add(inc)
}
#[inline]
pub const fn lcg32(state: u32, mult: u32, inc: u32) -> u32 {
state.wrapping_mul(mult).wrapping_add(inc)
}
#[inline]
pub const fn lcg64(state: u64, mult: u64, inc: u64) -> u64 {
state.wrapping_mul(mult).wrapping_add(inc)
}
#[inline]
pub const fn lcg128(state: u128, mult: u128, inc: u128) -> u128 {
state.wrapping_mul(mult).wrapping_add(inc)
}
macro_rules! make_jump_lcgX {
($(#[$attr:meta])* $f:ident, $u:ty) => {
$(#[$attr])*
pub fn $f(mut delta: $u, state: $u, mult: $u, inc: $u) -> $u {
let mut cur_mult: $u = mult;
let mut cur_plus: $u = inc;
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
}
make_jump_lcgX! {
jump_lcg16, u16
}
make_jump_lcgX! {
jump_lcg32, u32
}
make_jump_lcgX! {
jump_lcg64, u64
}
make_jump_lcgX! {
jump_lcg128, u128
}
pub fn sm64(mut input: u16) -> u16 {
if input == 0x560A {
input = 0;
}
let mut s0: u16 = input << 8;
s0 ^= input;
input = s0.swap_bytes();
s0 = ((s0 & 0xFF) << 1) ^ input;
let s1 = (s0 >> 1) ^ 0xFF80;
if (s0 & 1) == 0 {
if s1 == 0xAA55 {
input = 0;
} else {
input = s1 ^ 0x1FF4;
}
} else {
input = s1 ^ 0x8180;
}
input
}
#[inline]
pub const fn pkmn_colosseum(state: u32) -> u32 {
lcg32(state, 0x000343FD, 0x00269EC3)
}
#[inline]
pub const fn pkmn_gen3gen4(state: u32) -> u32 {
lcg32(state, 0x41C64E6D, 0x00006073)
}
#[inline]
pub const fn pkmn_gen4alt(state: u32) -> u32 {
lcg32(state, 0x6C078965, 0x00000001)
}
#[inline]
pub const fn pkmn_gen5gen6(state: u64) -> u64 {
lcg64(state, 0x5D588B656C078965, 0x0000000000269EC3)
}
#[inline]
pub fn f32_half_open_right(u: u32) -> f32 {
f32::from_bits(0x3f80_0000 | (u & 0x7fffff)) - 1.0
}
#[inline]
pub fn f32_half_open_left(mut u: u32) -> f32 {
const TOTAL_BITS: u32 = 32;
const MANTISSA_SCALE: f32 = 1.0 / ((1 << core::f32::MANTISSA_DIGITS) as f32);
u >>= TOTAL_BITS - core::f32::MANTISSA_DIGITS;
u += 1;
u as f32 * MANTISSA_SCALE
}
#[inline]
pub fn f32_open(mut u: u32) -> f32 {
const TOTAL_BITS: u32 = 32;
const SMALL_MANTISSA: u32 = core::f32::MANTISSA_DIGITS - 1;
const ZERO_EXPONENT_BITS: u32 = 127 << SMALL_MANTISSA;
u >>= TOTAL_BITS - SMALL_MANTISSA;
f32::from_bits(u | ZERO_EXPONENT_BITS) - (1.0 - core::f32::EPSILON / 2.0)
}
#[inline]
pub fn f32_closed(u: u32) -> f32 {
const U32_MAX_AS_FLOAT: f32 = core::u32::MAX as f32;
u as f32 / U32_MAX_AS_FLOAT
}
#[inline]
pub fn f32_closed_neg_pos(u: u32) -> f32 {
const U32_MAX_AS_FLOAT: f32 = core::u32::MAX as f32;
((u as f32 / U32_MAX_AS_FLOAT) - 0.5) * 2.0
}
#[inline]
pub fn f64_half_open_right(u: u64) -> f64 {
f64::from_bits(0x3ff0000000000000 | (u & 0xFFFFFFFFFFFFF)) - 1.0
}
#[inline]
pub fn f64_half_open_left(mut u: u64) -> f64 {
const TOTAL_BITS: u32 = 64;
const MANTISSA_SCALE: f64 = 1.0 / ((1u64 << core::f64::MANTISSA_DIGITS) as f64);
u >>= TOTAL_BITS - core::f64::MANTISSA_DIGITS;
u += 1;
u as f64 * MANTISSA_SCALE
}
#[inline]
pub fn f64_open(mut u: u64) -> f64 {
const TOTAL_BITS: u32 = 64;
const SMALL_MANTISSA: u32 = core::f64::MANTISSA_DIGITS - 1;
const ZERO_EXPONENT_BITS: u64 = 1023 << SMALL_MANTISSA;
u >>= TOTAL_BITS - SMALL_MANTISSA;
f64::from_bits(u | ZERO_EXPONENT_BITS) - (1.0 - core::f64::EPSILON / 2.0)
}
#[inline]
pub fn f64_closed(u: u64) -> f64 {
const U64_MAX_AS_DOUBLE: f64 = core::u64::MAX as f64;
u as f64 / U64_MAX_AS_DOUBLE
}
#[inline]
pub fn f64_closed_neg_pos(u: u64) -> f64 {
const U64_MAX_AS_DOUBLE: f64 = core::u64::MAX as f64;
((u as f64 / U64_MAX_AS_DOUBLE) - 0.5) * 2.0
}
pub const PCG_MULTIPLIER_8: u8 = 141;
pub const PCG_MULTIPLIER_16: u16 = 12829;
pub const PCG_MULTIPLIER_32: u32 = 747796405;
pub const PCG_MULTIPLIER_64: u64 = 6364136223846793005;
pub const PCG_MULTIPLIER_128: u128 = 47026247687942121848144207491837523525;
pub const DEFAULT_PCG_SEED: u128 = 201526561274146932589719779721328219291;
pub const DEFAULT_PCG_INC: u128 = 34172814569070222299;
#[inline]
pub const fn pcg_core_state8(state: u8, inc: u8) -> u8 {
lcg8(state, PCG_MULTIPLIER_8, inc)
}
#[inline]
pub const fn pcg_core_state16(state: u16, inc: u16) -> u16 {
lcg16(state, PCG_MULTIPLIER_16, inc)
}
#[inline]
pub const fn pcg_core_state32(state: u32, inc: u32) -> u32 {
lcg32(state, PCG_MULTIPLIER_32, inc)
}
#[inline]
pub const fn pcg_core_state64(state: u64, inc: u64) -> u64 {
lcg64(state, PCG_MULTIPLIER_64, inc)
}
#[inline]
pub const fn pcg_core_state128(state: u128, inc: u128) -> u128 {
lcg128(state, PCG_MULTIPLIER_128, inc)
}
#[inline]
pub const fn xsh_rr_16_8(state: u16) -> u8 {
((((state >> 5) ^ state) >> 5) as u8).rotate_right((state >> 13) as u32)
}
#[inline]
pub const fn xsh_rr_32_16(state: u32) -> u16 {
((((state >> 10) ^ state) >> 12) as u16).rotate_right((state >> 28) as u32)
}
#[inline]
pub const fn xsh_rr_64_32(state: u64) -> u32 {
((((state >> 18) ^ state) >> 27) as u32).rotate_right((state >> 59) as u32)
}
#[inline]
pub const fn xsh_rr_128_64(state: u128) -> u64 {
((((state >> 29) ^ state) >> 58) as u64).rotate_right((state >> 122) as u32)
}
#[inline]
pub const fn xsh_rs_16_8(state: u16) -> u8 {
(((state >> 7) ^ state) >> ((state >> 14) + 3)) as u8
}
#[inline]
pub const fn xsh_rs_32_16(state: u32) -> u16 {
(((state >> 11) ^ state) >> ((state >> 30) + 11)) as u16
}
#[inline]
pub const fn xsh_rs_64_32(state: u64) -> u32 {
(((state >> 22) ^ state) >> ((state >> 61) + 22)) as u32
}
#[inline]
pub const fn xsh_rs_128_64(state: u128) -> u64 {
(((state >> 43) ^ state) >> ((state >> 124) + 45)) as u64
}
#[inline]
pub const fn rxs_m_xs_8_8(state: u8) -> u8 {
let w = (state >> ((state >> 6).wrapping_add(2)) ^ state).wrapping_mul(217);
w >> 6 ^ w
}
#[inline]
pub const fn rxs_m_xs_16_16(state: u16) -> u16 {
let w = (state >> ((state >> 13).wrapping_add(3)) ^ state).wrapping_mul(62169);
w >> 11 ^ w
}
#[inline]
pub const fn rxs_m_xs_32_32(state: u32) -> u32 {
let w = (state >> ((state >> 28).wrapping_add(4)) ^ state).wrapping_mul(277803737);
w >> 22 ^ w
}
#[inline]
pub const fn rxs_m_xs_64_64(state: u64) -> u64 {
let w = (state >> ((state >> 59).wrapping_add(5)) ^ state).wrapping_mul(12605985483714917081);
w >> 43 ^ w
}
#[inline]
pub const fn rxs_m_xs_128_128(state: u128) -> u128 {
let w = (state >> ((state >> 122).wrapping_add(6)) ^ state)
.wrapping_mul(327738287884841127335028083622016905945);
w >> 86 ^ w
}
#[inline]
pub const fn xsl_rr_64_32(state: u64) -> u32 {
((state >> 32) as u32 ^ (state as u32)).rotate_right((state >> 59) as u32)
}
#[inline]
pub const fn xsl_rr_128_64(state: u128) -> u64 {
((state >> 64) as u64 ^ (state as u64)).rotate_right((state >> 122) as u32)
}
#[inline]
pub const fn xsl_rr_rr_64_64(state: u64) -> u64 {
let rot1: u32 = (state >> 59) as u32;
let high: u32 = (state >> 32) as u32;
let low: u32 = state as u32;
let xor_d: u32 = high ^ low;
let new_low: u32 = xor_d.rotate_right(rot1);
let new_high: u32 = high.rotate_right(new_low & 31);
((new_high as u64) << 32) | new_low as u64
}
#[inline]
pub const fn xsl_rr_rr_128_128(state: u128) -> u128 {
let rot1: u32 = (state >> 122) as u32;
let high: u64 = (state >> 64) as u64;
let low: u64 = state as u64;
let xor_d: u64 = high ^ low;
let new_low: u64 = xor_d.rotate_right(rot1);
let new_high: u64 = high.rotate_right((new_low & 63) as u32);
((new_high as u128) << 64) | new_low as u128
}