pub struct LayerGeometry {
pub t: usize,
pub digits: Vec<usize>,
pub q_powers: Vec<usize>,
}
impl LayerGeometry {
pub fn new(q: usize, t: usize, sub_chunk_no: usize) -> Self {
let mut q_powers = vec![1usize; t];
for i in 1..t {
q_powers[i] = q_powers[i - 1] * q;
}
let mut digits = vec![0usize; sub_chunk_no * t];
for z in 0..sub_chunk_no {
let mut remaining = z;
for i in 0..t {
digits[z * t + t - 1 - i] = remaining % q;
remaining /= q;
}
}
LayerGeometry {
t,
digits,
q_powers,
}
}
#[inline]
pub fn plane_digits(&self, z: usize) -> &[usize] {
&self.digits[z * self.t..(z + 1) * self.t]
}
#[inline]
pub fn companion_layer(&self, z: usize, x: usize, y: usize, z_y: usize) -> usize {
let place = self.q_powers[self.t - 1 - y];
z + x * place - z_y * place
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn plane_digits() {
let geometry = LayerGeometry::new(2, 2, 4);
assert_eq!(geometry.plane_digits(0), &[0, 0]);
assert_eq!(geometry.plane_digits(1), &[0, 1]);
assert_eq!(geometry.plane_digits(2), &[1, 0]);
assert_eq!(geometry.plane_digits(3), &[1, 1]);
let geometry = LayerGeometry::new(3, 2, 9);
assert_eq!(geometry.plane_digits(5), &[1, 2]);
}
#[test]
fn companion_layer() {
let geometry = LayerGeometry::new(3, 3, 27);
for z in 0..27 {
let digits = geometry.plane_digits(z).to_vec();
for y in 0..3 {
for x in 0..3 {
let z_sw = geometry.companion_layer(z, x, y, digits[y]);
assert!(z_sw < 27);
let sw_digits = geometry.plane_digits(z_sw);
assert_eq!(sw_digits[y], x);
for other in 0..3 {
if other != y {
assert_eq!(sw_digits[other], digits[other]);
}
}
}
}
}
}
}