use num_traits::Pow;
use std::ops::{Add, Mul};
use crate::cnfterm::CnfTerm;
use crate::error::{OrdinalError, Result};
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum Ordinal {
Finite(u32),
Transfinite(Vec<CnfTerm>),
}
impl Ordinal {
pub fn new_finite(n: u32) -> Self {
Ordinal::Finite(n)
}
pub fn new_transfinite(terms: &[CnfTerm]) -> Result<Self> {
Self::validate_cnf_terms(terms)?;
Ok(Ordinal::Transfinite(terms.to_vec()))
}
pub(crate) fn transfinite_unchecked(terms: Vec<CnfTerm>) -> Self {
debug_assert!(
Self::validate_cnf_terms(&terms).is_ok(),
"internal arithmetic produced invalid CNF: {terms:?}"
);
Ordinal::Transfinite(terms)
}
fn validate_cnf_terms(terms: &[CnfTerm]) -> Result<()> {
match terms.first() {
None => return Err(OrdinalError::TransfiniteConstructionError),
Some(term) if term.is_finite() => {
return Err(OrdinalError::TransfiniteConstructionError);
}
_ => {}
}
for pair in terms.windows(2) {
if pair[0].exponent_ref() <= pair[1].exponent_ref() {
return Err(OrdinalError::TransfiniteConstructionError);
}
}
Ok(())
}
pub fn is_limit(&self) -> bool {
match self {
Ordinal::Finite(0) => true,
Ordinal::Finite(_) => false,
Ordinal::Transfinite(terms) => terms
.last()
.expect("transfinite ordinals always have at least one CNF term")
.is_limit(),
}
}
pub fn is_successor(&self) -> bool {
!self.is_limit()
}
pub fn successor(&self) -> Self {
match self {
Ordinal::Finite(n) => Ordinal::new_finite(n.saturating_add(1)),
Ordinal::Transfinite(terms) => {
let mut new_terms = terms.clone();
if let Some(last_term) = new_terms.pop() {
if last_term.is_finite() {
new_terms.push(CnfTerm::new_finite(
last_term.multiplicity().saturating_add(1),
));
} else {
new_terms.push(last_term);
new_terms.push(CnfTerm::new_finite(1));
}
}
Ordinal::Transfinite(new_terms)
}
}
}
pub fn is_finite(&self) -> bool {
matches!(self, Ordinal::Finite(_))
}
pub fn is_transfinite(&self) -> bool {
matches!(self, Ordinal::Transfinite(_))
}
pub fn leading_cnf_term(&self) -> Option<CnfTerm> {
match self {
Ordinal::Finite(_) => None,
Ordinal::Transfinite(terms) => terms.first().cloned(),
}
}
pub fn trailing_cnf_term(&self) -> Option<CnfTerm> {
match self {
Ordinal::Finite(_) => None,
Ordinal::Transfinite(terms) => terms.last().cloned(),
}
}
pub fn cnf_terms(&self) -> Option<Vec<CnfTerm>> {
match self {
Ordinal::Finite(_) => None,
Ordinal::Transfinite(terms) => Some(terms.clone()),
}
}
pub fn zero() -> Self {
Ordinal::new_finite(0)
}
pub fn one() -> Self {
Ordinal::new_finite(1)
}
pub fn omega() -> Self {
Ordinal::Transfinite(vec![
CnfTerm::new(&Ordinal::one(), 1).expect("omega term has positive multiplicity")
])
}
pub fn builder() -> crate::OrdinalBuilder {
crate::OrdinalBuilder::new()
}
}
impl std::fmt::Display for Ordinal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Ordinal::Finite(n) => write!(f, "{n}"),
Ordinal::Transfinite(terms) => {
for (i, term) in terms.iter().enumerate() {
if i > 0 {
write!(f, " + ")?;
}
write!(f, "{term}")?;
}
Ok(())
}
}
}
}
impl From<u32> for Ordinal {
fn from(n: u32) -> Self {
Ordinal::new_finite(n)
}
}
impl PartialOrd for Ordinal {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Ordinal {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self, other) {
(Ordinal::Finite(m), Ordinal::Finite(n)) => m.cmp(n),
(Ordinal::Finite(_), Ordinal::Transfinite(_)) => std::cmp::Ordering::Less,
(Ordinal::Transfinite(_), Ordinal::Finite(_)) => std::cmp::Ordering::Greater,
(Ordinal::Transfinite(terms_lhs), Ordinal::Transfinite(terms_rhs)) => {
for (term_lhs, term_rhs) in terms_lhs.iter().zip(terms_rhs.iter()) {
let cmp = term_lhs.cmp(term_rhs);
if cmp != std::cmp::Ordering::Equal {
return cmp;
}
}
terms_lhs.len().cmp(&terms_rhs.len())
}
}
}
}
impl Add<Ordinal> for Ordinal {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Ordinal::Finite(m), Ordinal::Finite(n)) => Ordinal::new_finite(m.saturating_add(n)),
(Ordinal::Finite(_), rhs_transfinite) => rhs_transfinite,
(Ordinal::Transfinite(mut terms), Ordinal::Finite(n)) => {
if n == 0 {
return Ordinal::Transfinite(terms);
}
if let Some(last_term) = terms.last() {
if last_term.is_finite() {
let new_mult = last_term.multiplicity().saturating_add(n);
let last_idx = terms.len() - 1;
terms[last_idx] = CnfTerm::new_finite(new_mult);
} else {
terms.push(CnfTerm::new_finite(n));
}
}
Ordinal::Transfinite(terms) }
(Ordinal::Transfinite(terms_lhs), Ordinal::Transfinite(terms_rhs)) => {
let leading_exponent_rhs = terms_rhs[0].exponent();
let leading_mult_rhs = terms_rhs[0].multiplicity();
if terms_lhs[0].exponent_ref() < &leading_exponent_rhs {
Ordinal::Transfinite(terms_rhs)
} else {
let mut index_lhs = terms_lhs.len() - 1;
while index_lhs > 0
&& terms_lhs[index_lhs].exponent_ref() < &leading_exponent_rhs
{
index_lhs -= 1;
}
if terms_lhs[index_lhs].exponent_ref() == &leading_exponent_rhs {
let mut new_terms = terms_lhs[..index_lhs].to_vec();
new_terms.push(
CnfTerm::from_parts(
leading_exponent_rhs,
terms_lhs[index_lhs]
.multiplicity()
.saturating_add(leading_mult_rhs),
)
.expect("combined CNF term has positive multiplicity"),
);
new_terms.extend(terms_rhs.into_iter().skip(1));
Ordinal::transfinite_unchecked(new_terms)
} else {
let mut new_terms = terms_lhs[..index_lhs + 1].to_vec();
new_terms.extend(terms_rhs);
Ordinal::transfinite_unchecked(new_terms)
}
}
}
}
}
}
impl Add<&Ordinal> for Ordinal {
type Output = Self;
fn add(self, rhs: &Ordinal) -> Self::Output {
self + rhs.clone()
}
}
impl Add<Ordinal> for &Ordinal {
type Output = Ordinal;
fn add(self, rhs: Ordinal) -> Self::Output {
self.clone() + rhs
}
}
impl Add<&Ordinal> for &Ordinal {
type Output = Ordinal;
fn add(self, rhs: &Ordinal) -> Self::Output {
self.clone() + rhs.clone()
}
}
#[expect(clippy::suspicious_arithmetic_impl)]
impl Mul<Ordinal> for Ordinal {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Ordinal::Finite(0), _) | (_, Ordinal::Finite(0)) => Ordinal::zero(),
(Ordinal::Finite(m), Ordinal::Finite(n)) => Ordinal::new_finite(m.saturating_mul(n)),
(Ordinal::Finite(m), Ordinal::Transfinite(mut terms_rhs)) => {
let last_term_rhs = terms_rhs
.pop()
.expect("transfinite ordinals always have at least one CNF term");
if last_term_rhs.is_finite() {
terms_rhs.push(CnfTerm::new_finite(
last_term_rhs.multiplicity().saturating_mul(m),
));
} else {
terms_rhs.push(last_term_rhs);
}
Ordinal::transfinite_unchecked(terms_rhs)
}
(Ordinal::Transfinite(mut terms_lhs), Ordinal::Finite(n)) => {
terms_lhs[0] = CnfTerm::new(
terms_lhs[0].exponent_ref(),
terms_lhs[0].multiplicity().saturating_mul(n),
)
.expect("scaled multiplicity is positive when n > 0");
Ordinal::transfinite_unchecked(terms_lhs)
}
(Ordinal::Transfinite(terms_lhs), Ordinal::Transfinite(terms_rhs)) => {
let mut new_terms: Vec<CnfTerm> = Vec::new();
let leading_exp_lhs = terms_lhs[0].exponent();
let leading_mult_lhs = terms_lhs[0].multiplicity();
let trailing_rhs = terms_rhs
.last()
.expect("transfinite ordinals always have at least one CNF term");
let rhs_is_limit = trailing_rhs.is_limit();
let trailing_mult_rhs = trailing_rhs.multiplicity();
let rhs_len = terms_rhs.len();
if rhs_is_limit {
new_terms.extend(terms_rhs.into_iter().map(|term| {
let (exp, mult) = term.into_parts();
CnfTerm::from_parts(&leading_exp_lhs + exp, mult)
.expect("exponent addition and positive multiplicity yield valid term")
}));
} else {
new_terms.extend(terms_rhs.into_iter().take(rhs_len - 1).map(|term| {
let (exp, mult) = term.into_parts();
CnfTerm::from_parts(&leading_exp_lhs + exp, mult)
.expect("exponent addition and positive multiplicity yield valid term")
}));
new_terms.push(
CnfTerm::from_parts(
leading_exp_lhs,
leading_mult_lhs.saturating_mul(trailing_mult_rhs),
)
.expect("product of positive multiplicities is positive"),
);
new_terms.extend(terms_lhs.into_iter().skip(1));
}
Ordinal::transfinite_unchecked(new_terms)
}
}
}
}
impl Mul<&Ordinal> for Ordinal {
type Output = Self;
fn mul(self, rhs: &Ordinal) -> Self::Output {
self * rhs.clone()
}
}
impl Mul<Ordinal> for &Ordinal {
type Output = Ordinal;
fn mul(self, rhs: Ordinal) -> Self::Output {
self.clone() * rhs
}
}
impl Mul<&Ordinal> for &Ordinal {
type Output = Ordinal;
fn mul(self, rhs: &Ordinal) -> Self::Output {
self.clone() * rhs.clone()
}
}
impl Pow<Ordinal> for Ordinal {
type Output = Self;
fn pow(self, rhs: Self) -> Self::Output {
if matches!(rhs, Ordinal::Finite(0)) || matches!(self, Ordinal::Finite(1)) {
return Ordinal::one();
}
if matches!(rhs, Ordinal::Finite(1)) {
return self;
}
if matches!(self, Ordinal::Finite(0)) {
return Ordinal::zero();
}
match (self, rhs) {
(Ordinal::Finite(m), Ordinal::Finite(n)) => Ordinal::new_finite(m.saturating_pow(n)),
(lhs @ Ordinal::Transfinite(_), rhs) => {
if rhs.is_limit() {
let Ordinal::Transfinite(terms_lhs) = lhs else {
unreachable!()
};
let (leading_exp, _) = terms_lhs
.into_iter()
.next()
.expect("transfinite ordinal has a leading term")
.into_parts();
let new_exponent = leading_exp * rhs;
Ordinal::transfinite_unchecked(vec![
CnfTerm::from_parts(new_exponent, 1).expect("positive multiplicity")
])
} else if let Ordinal::Finite(n) = rhs {
binary_pow(lhs, n)
} else {
let Ordinal::Transfinite(terms_rhs) = rhs else {
unreachable!()
};
let mut distributed = Ordinal::one();
for term in terms_rhs {
if term.is_finite() {
distributed =
distributed * binary_pow(lhs.clone(), term.multiplicity());
} else {
distributed = distributed
* lhs.clone().pow(Ordinal::transfinite_unchecked(vec![term]));
}
}
distributed
}
}
(Ordinal::Finite(m), Ordinal::Transfinite(terms_rhs)) => {
let mut distributed = Ordinal::one();
for term in terms_rhs {
if term.is_finite() {
distributed = distributed
* Ordinal::new_finite(m.saturating_pow(term.multiplicity()));
} else {
let (e, k) = term.into_parts();
if e == Ordinal::one() {
distributed = distributed
* Ordinal::transfinite_unchecked(vec![CnfTerm::from_parts(
Ordinal::new_finite(k),
1,
)
.expect("positive multiplicity for omega power")]);
} else if let Ordinal::Finite(e_val) = e {
let inner_exp =
Ordinal::transfinite_unchecked(vec![CnfTerm::from_parts(
Ordinal::new_finite(e_val - 1),
k,
)
.expect("positive multiplicity for inner exponent")]);
distributed = distributed
* Ordinal::transfinite_unchecked(vec![CnfTerm::from_parts(
inner_exp, 1,
)
.expect("positive multiplicity for outer term")]);
} else {
todo!("finite base with transfinite tower exponent (e.g., 2^(ω^ω·3))")
}
}
}
distributed
}
}
}
}
fn binary_pow(base: Ordinal, exp: u32) -> Ordinal {
if exp == 0 {
return Ordinal::one();
}
if exp == 1 {
return base;
}
let mut base = base;
let mut exp = exp;
let mut result = Ordinal::one();
while exp > 1 {
if exp % 2 == 1 {
result = result * base.clone();
}
exp /= 2;
base = base.clone() * base;
}
result * base
}
impl Pow<&Ordinal> for Ordinal {
type Output = Self;
fn pow(self, rhs: &Ordinal) -> Self::Output {
self.pow(rhs.clone())
}
}
impl Pow<Ordinal> for &Ordinal {
type Output = Ordinal;
fn pow(self, rhs: Ordinal) -> Self::Output {
self.clone().pow(rhs)
}
}
impl Pow<&Ordinal> for &Ordinal {
type Output = Ordinal;
fn pow(self, rhs: &Ordinal) -> Self::Output {
self.clone().pow(rhs.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ordinal_constructor() {
let zero = Ordinal::zero();
assert_eq!(zero, Ordinal::new_finite(0));
let one = Ordinal::one();
assert_eq!(one, Ordinal::new_finite(1));
let omega = Ordinal::omega();
assert_eq!(
omega,
Ordinal::new_transfinite(&[CnfTerm::new(&Ordinal::one(), 1).unwrap()]).unwrap()
);
}
#[test]
fn test_ordinal_is_limit() {
let zero = Ordinal::zero();
assert!(zero.is_limit());
let one = Ordinal::one();
assert!(!one.is_limit());
let omega = Ordinal::omega();
assert!(omega.is_limit());
}
#[test]
fn test_ordinal_is_successor() {
let zero = Ordinal::zero();
assert!(!zero.is_successor());
let one = Ordinal::one();
assert!(one.is_successor());
let omega = Ordinal::omega();
assert!(!omega.is_successor());
}
#[test]
fn test_ordinal_successor() {
let zero = Ordinal::zero();
let one = Ordinal::one();
let omega = Ordinal::omega();
assert_eq!(zero.successor(), one);
assert_eq!(one.successor(), Ordinal::new_finite(2));
let omega_successor = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::one(), 1).unwrap(),
CnfTerm::new_finite(1),
])
.unwrap();
assert_eq!(omega.successor(), omega_successor);
}
#[test]
fn test_ordinal_is_finite() {
let zero = Ordinal::zero();
assert!(zero.is_finite());
let one = Ordinal::one();
assert!(one.is_finite());
let omega = Ordinal::omega();
assert!(!omega.is_finite());
}
#[test]
fn test_ordinal_eq() {
let zero = Ordinal::zero();
let another_zero = Ordinal::new_finite(0);
assert_eq!(zero, another_zero);
let one = Ordinal::one();
let another_one = Ordinal::new_finite(1);
assert_eq!(one, another_one);
let omega = Ordinal::omega();
let another_omega = Ordinal::builder().omega().build_unchecked();
assert_eq!(omega, another_omega);
}
#[test]
fn test_ordinal_pow() {
let two = Ordinal::new_finite(2);
let three = Ordinal::new_finite(3);
assert_eq!(two.clone().pow(three.clone()), Ordinal::new_finite(8));
assert_eq!(three.pow(two.clone()), Ordinal::new_finite(9));
let zero = Ordinal::zero();
let one = Ordinal::one();
assert_eq!(zero.clone().pow(one.clone()), Ordinal::zero());
assert_eq!(one.clone().pow(zero.clone()), Ordinal::one());
assert_eq!(one.clone().pow(one), Ordinal::one());
assert_eq!(two.clone().pow(zero), Ordinal::one());
let omega = Ordinal::omega();
let omega_squared = Ordinal::builder().omega_power(2).build_unchecked();
assert_eq!(omega.clone().pow(two.clone()), omega_squared);
let omega_omega = Ordinal::builder()
.omega_exp(omega.clone())
.build_unchecked();
assert_eq!(omega.clone().pow(omega.clone()), omega_omega);
assert_eq!(two.pow(omega.clone()), omega);
}
#[test]
fn test_binary_exponentiation_small_powers() {
let omega = Ordinal::omega();
let omega_squared = Ordinal::builder().omega_power(2).build_unchecked();
assert_eq!(omega.clone().pow(Ordinal::new_finite(2)), omega_squared);
let omega_cubed = Ordinal::builder().omega_power(3).build_unchecked();
assert_eq!(omega.clone().pow(Ordinal::new_finite(3)), omega_cubed);
let omega_fourth = Ordinal::builder().omega_power(4).build_unchecked();
assert_eq!(omega.pow(Ordinal::new_finite(4)), omega_fourth);
}
#[test]
fn test_binary_exponentiation_powers_of_two() {
let omega = Ordinal::omega();
let omega_8 = Ordinal::builder().omega_power(8).build_unchecked();
assert_eq!(omega.clone().pow(Ordinal::new_finite(8)), omega_8);
let omega_16 = Ordinal::builder().omega_power(16).build_unchecked();
assert_eq!(omega.clone().pow(Ordinal::new_finite(16)), omega_16);
let omega_32 = Ordinal::builder().omega_power(32).build_unchecked();
assert_eq!(omega.pow(Ordinal::new_finite(32)), omega_32);
}
#[test]
fn test_binary_exponentiation_large_exponents() {
let omega = Ordinal::omega();
let omega_100 = Ordinal::builder().omega_power(100).build_unchecked();
assert_eq!(omega.clone().pow(Ordinal::new_finite(100)), omega_100);
let omega_255 = Ordinal::builder().omega_power(255).build_unchecked();
assert_eq!(omega.pow(Ordinal::new_finite(255)), omega_255);
}
#[test]
fn test_binary_exponentiation_complex_base() {
let complex_base = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::new_finite(2), 1).unwrap(), CnfTerm::new(&Ordinal::one(), 1).unwrap(), CnfTerm::new_finite(1),
])
.unwrap();
let result = complex_base.pow(Ordinal::new_finite(4));
let leading_term = result.leading_cnf_term().unwrap();
assert_eq!(leading_term.exponent(), Ordinal::new_finite(8));
assert_eq!(leading_term.multiplicity(), 1);
assert!(result.is_transfinite());
}
#[test]
fn test_binary_exponentiation_edge_cases() {
let omega = Ordinal::omega();
assert_eq!(omega.clone().pow(Ordinal::zero()), Ordinal::one());
assert_eq!(omega.clone().pow(Ordinal::one()), omega);
let omega_5 = Ordinal::builder().omega_power(5).build_unchecked();
assert_eq!(omega.clone().pow(Ordinal::new_finite(5)), omega_5);
let omega_7 = Ordinal::builder().omega_power(7).build_unchecked();
assert_eq!(omega.pow(Ordinal::new_finite(7)), omega_7);
}
#[test]
fn test_ordinal_add() {
let two = Ordinal::new_finite(2);
let three = Ordinal::new_finite(3);
assert_eq!(two.clone() + three.clone(), Ordinal::new_finite(5));
assert_eq!(three + two.clone(), Ordinal::new_finite(5));
let zero = Ordinal::zero();
let one = Ordinal::one();
assert_eq!(zero.clone() + one.clone(), Ordinal::one());
assert_eq!(one.clone() + zero.clone(), Ordinal::one());
assert_eq!(zero.clone() + zero, Ordinal::zero());
let omega = Ordinal::omega();
let omega_plus_one = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::one(), 1).unwrap(),
CnfTerm::new_finite(1),
])
.unwrap();
assert_eq!(omega.clone() + one, omega_plus_one);
let two_omega = Ordinal::builder().omega_times(2).build_unchecked();
assert_eq!(omega.clone() + omega.clone(), two_omega);
let omega_plus_two = omega.successor().successor();
assert_eq!(two.clone() + omega.clone(), omega);
assert_eq!(omega + two, omega_plus_two);
}
#[test]
fn test_ordinal_mul() {
let two = Ordinal::new_finite(2);
let three = Ordinal::new_finite(3);
assert_eq!(two.clone() * three.clone(), Ordinal::new_finite(6));
assert_eq!(three * two.clone(), Ordinal::new_finite(6));
let zero = Ordinal::zero();
let one = Ordinal::one();
assert_eq!(zero.clone() * one.clone(), Ordinal::zero());
assert_eq!(one.clone() * zero, Ordinal::zero());
assert_eq!(one.clone() * one.clone(), Ordinal::one());
assert_eq!(two.clone() * one.clone(), Ordinal::new_finite(2));
assert_eq!(one * two.clone(), Ordinal::new_finite(2));
let omega = Ordinal::omega();
let omega_times_two = Ordinal::builder().omega_times(2).build_unchecked();
assert_eq!(omega.clone() * two.clone(), omega_times_two);
let omega_squared = Ordinal::builder().omega_power(2).build_unchecked();
assert_eq!(omega.clone() * omega.clone(), omega_squared);
let two_omega = Ordinal::builder().omega_times(2).build_unchecked();
assert_eq!(two.clone() * omega.clone(), omega);
assert_eq!(omega * two, two_omega);
}
#[test]
fn test_cnf_ordering_valid() {
let ordinal = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::new_finite(2), 1).unwrap(), CnfTerm::new(&Ordinal::one(), 1).unwrap(), CnfTerm::new_finite(1),
]);
assert!(ordinal.is_ok());
}
#[test]
fn test_cnf_ordering_invalid_equal_exponents() {
let ordinal = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::one(), 1).unwrap(), CnfTerm::new(&Ordinal::one(), 1).unwrap(),
]);
assert!(ordinal.is_err());
assert!(matches!(
ordinal.unwrap_err(),
OrdinalError::TransfiniteConstructionError
));
}
#[test]
fn test_cnf_ordering_invalid_increasing() {
let ordinal = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::one(), 1).unwrap(), CnfTerm::new(&Ordinal::new_finite(2), 1).unwrap(),
]);
assert!(ordinal.is_err());
assert!(matches!(
ordinal.unwrap_err(),
OrdinalError::TransfiniteConstructionError
));
}
#[test]
fn test_cnf_ordering_complex_valid() {
let omega = Ordinal::omega();
let ordinal = Ordinal::new_transfinite(&[
CnfTerm::new(&omega, 1).unwrap(), CnfTerm::new(&Ordinal::new_finite(2), 1).unwrap(), CnfTerm::new(&Ordinal::one(), 1).unwrap(), CnfTerm::new_finite(5),
]);
assert!(ordinal.is_ok());
}
#[test]
fn test_cnf_ordering_two_terms_valid() {
let ordinal = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::new_finite(2), 1).unwrap(), CnfTerm::new(&Ordinal::one(), 1).unwrap(),
]);
assert!(ordinal.is_ok());
}
#[test]
fn test_cnf_ordering_two_terms_invalid() {
let ordinal = Ordinal::new_transfinite(&[
CnfTerm::new(&Ordinal::one(), 1).unwrap(), CnfTerm::new(&Ordinal::new_finite(2), 1).unwrap(),
]);
assert!(ordinal.is_err());
}
#[test]
fn test_cnf_ordering_single_term_valid() {
let ordinal = Ordinal::new_transfinite(&[CnfTerm::new(&Ordinal::one(), 1).unwrap()]);
assert!(ordinal.is_ok());
}
#[test]
fn test_cnf_ordering_finite_leading_invalid() {
let ordinal = Ordinal::new_transfinite(&[CnfTerm::new_finite(42)]);
assert!(ordinal.is_err());
assert!(matches!(
ordinal.unwrap_err(),
OrdinalError::TransfiniteConstructionError
));
}
}