#[macro_export]
macro_rules! dispatch_ring {
($ring:expr, $body:expr) => {
$crate::dispatch_ring!(
$ring,
$body,
else panic!(
"dispatch_ring: invalid ring {} (expected one of \
4, 6, 8, 10, 12, 16, 20, 24, 32, 60)",
$ring
)
)
};
($ring:expr, $body:expr, else $fallback:expr) => {{
match $ring {
4 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ4;
#[allow(dead_code)] const PHI: usize = 2;
$body
}
6 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ6;
#[allow(dead_code)] const PHI: usize = 2;
$body
}
8 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ8;
#[allow(dead_code)] const PHI: usize = 4;
$body
}
10 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ10;
#[allow(dead_code)] const PHI: usize = 4;
$body
}
12 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ12;
#[allow(dead_code)] const PHI: usize = 4;
$body
}
14 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ14;
#[allow(dead_code)] const PHI: usize = 6;
$body
}
16 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ16;
#[allow(dead_code)] const PHI: usize = 8;
$body
}
18 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ18;
#[allow(dead_code)] const PHI: usize = 6;
$body
}
20 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ20;
#[allow(dead_code)] const PHI: usize = 8;
$body
}
24 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ24;
#[allow(dead_code)] const PHI: usize = 8;
$body
}
32 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ32;
#[allow(dead_code)] const PHI: usize = 16;
$body
}
60 => {
#[allow(dead_code)] type ZZ = $crate::cyclotomic::ZZ60;
#[allow(dead_code)] const PHI: usize = 16;
$body
}
_ => $fallback,
}
}};
}
pub const SUPPORTED_RINGS: [u8; 12] = [4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 32, 60];
#[cfg(test)]
mod tests {
use crate::cyclotomic::SymNum;
#[test]
fn phi_matches_per_ring_constant() {
for &ring in &super::SUPPORTED_RINGS {
let dispatched_phi: usize = crate::dispatch_ring!(ring, ZZ::PHI);
assert_eq!(
dispatched_phi,
expected_phi(ring),
"dispatch_ring PHI for ZZ{ring} disagrees with the table",
);
}
}
#[test]
fn one_is_one_for_every_ring() {
use num_traits::One;
for &ring in &super::SUPPORTED_RINGS {
let c64 = crate::dispatch_ring!(ring, <ZZ as One>::one().complex64());
assert!(
(c64.re - 1.0).abs() < 1e-12 && c64.im.abs() < 1e-12,
"ZZ{ring}::one().complex64() = {c64:?}",
);
}
}
fn expected_phi(ring: u8) -> usize {
match ring {
4 | 6 => 2,
8 | 10 | 12 => 4,
14 | 18 => 6,
16 | 20 | 24 => 8,
32 | 60 => 16,
_ => panic!("unreachable"),
}
}
}