use crate::trit::{Trit, N, P, Z};
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Gen {
pub sig: Trit,
pub idx: u32,
}
impl Gen {
#[inline]
pub fn new(sig: Trit, idx: u32) -> Gen {
Gen { sig, idx }
}
#[inline]
pub fn imaginary(idx: u32) -> Gen {
Gen { sig: N, idx }
}
#[inline]
pub fn degenerate(idx: u32) -> Gen {
Gen { sig: Z, idx }
}
#[inline]
pub fn hyperbolic(idx: u32) -> Gen {
Gen { sig: P, idx }
}
pub fn is_valid(self) -> bool {
self.sig.is_valid()
}
pub fn signature(self) -> Trit {
self.sig
}
}
impl PartialOrd for Gen {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Gen {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.sig.0.cmp(&other.sig.0).then(self.idx.cmp(&other.idx))
}
}
impl std::fmt::Debug for Gen {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let type_char = match self.sig {
N => 'i',
Z => 'd',
P => 'h',
_ => '?',
};
write!(f, "e{}{}", self.idx + 1, type_char)
}
}
impl std::fmt::Display for Gen {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "e{}", self.idx + 1)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn imaginary_signature() {
assert_eq!(Gen::imaginary(0).signature(), N);
}
#[test]
fn degenerate_signature() {
assert_eq!(Gen::degenerate(0).signature(), Z);
}
#[test]
fn hyperbolic_signature() {
assert_eq!(Gen::hyperbolic(0).signature(), P);
}
#[test]
fn ordering_by_type_then_index() {
let d0 = Gen::degenerate(0);
let n0 = Gen::imaginary(0);
let p0 = Gen::hyperbolic(0);
assert!(d0 < n0);
assert!(n0 < p0);
assert!(Gen::imaginary(0) < Gen::imaginary(1));
}
#[test]
fn signature_is_one_field_access() {
let g = Gen::new(N, 3);
assert_eq!(g.signature(), g.sig); }
#[test]
fn relational_type() {
assert_ne!(Gen::imaginary(0), Gen::hyperbolic(0));
assert_ne!(
Gen::imaginary(0).signature(),
Gen::hyperbolic(0).signature()
);
}
}