pub use crate::wide::Int4;
use crate::{NUM_DIMENSIONS, NUM_DIMENSION_SETS_4D, REV_VECTORS};
#[inline]
pub fn sobol_rev(sample_index_rev: u32, dimension: u32) -> u32 {
assert!(dimension < NUM_DIMENSIONS);
let dimension_set = (dimension >> 2) as usize;
let sub_dimension = (dimension & 0b11) as usize;
let vecs = &REV_VECTORS[dimension_set];
let mut sobol = 0u32;
let mut index = sample_index_rev & 0xffff0000; let mut i = 0;
while index != 0 {
let j = index.leading_zeros();
sobol ^= vecs[(i + j) as usize][sub_dimension];
i += j + 1;
index <<= j;
index <<= 1;
}
sobol
}
#[inline]
pub fn sobol_int4_rev(sample_index_rev: u32, dimension_set: u32) -> Int4 {
assert!(dimension_set < NUM_DIMENSION_SETS_4D);
let vecs = &REV_VECTORS[dimension_set as usize];
let mut sobol = Int4::zero();
let mut index = sample_index_rev & 0xffff0000; let mut i = 0;
while index != 0 {
let j = index.leading_zeros();
sobol ^= vecs[(i + j) as usize].into();
i += j + 1;
index <<= j;
index <<= 1;
}
sobol
}
#[inline(always)]
pub fn owen_scramble_rev(mut n_rev: u32, scramble: u32) -> u32 {
n_rev ^= n_rev.wrapping_mul(0x3d20adea);
n_rev = n_rev.wrapping_add(scramble);
n_rev = n_rev.wrapping_mul((scramble >> 16) | 1);
n_rev ^= n_rev.wrapping_mul(0x05526c56);
n_rev ^= n_rev.wrapping_mul(0x53a22864);
n_rev
}
#[inline(always)]
pub fn owen_scramble_int4_rev(mut n_rev: Int4, scramble: Int4) -> Int4 {
n_rev ^= n_rev * [0x3d20adea; 4].into();
n_rev += scramble;
n_rev *= (scramble >> 16) | [1; 4].into();
n_rev ^= n_rev * [0x05526c56; 4].into();
n_rev ^= n_rev * [0x53a22864; 4].into();
n_rev
}
#[inline(always)]
pub fn hash(mut n: u32) -> u32 {
n ^= 0xe6fe3beb;
n ^= n >> 16;
n = n.wrapping_mul(0x7feb352d);
n ^= n >> 15;
n = n.wrapping_mul(0x846ca68b);
n ^= n >> 16;
n
}
#[inline(always)]
pub fn hash_int4(mut n: Int4) -> Int4 {
n ^= [0xe6fe3beb; 4].into();
n ^= n >> 16;
n *= [0x7feb352d; 4].into();
n ^= n >> 15;
n *= [0x846ca68b; 4].into();
n ^= n >> 16;
n
}
#[inline(always)]
pub fn u32_to_f32_norm(n: u32) -> f32 {
f32::from_bits((n >> 9) | 0x3f800000) - 1.0
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
pub fn to_norm_f32() {
assert_eq!(u32_to_f32_norm(0), 0.0);
assert!(u32_to_f32_norm(core::u32::MAX) < 1.0);
}
}