use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FiniteFieldError {
NotPrime {
modulus: String,
},
ModulusTooLarge {
modulus: String,
},
DegreeOutOfRange {
degree: i64,
},
BadDefiningPolynomial {
reason: String,
},
MalformedElement {
got: usize,
degree: usize,
},
FieldMismatch {
lhs: String,
rhs: String,
},
DimensionMismatch {
op: &'static str,
lhs: (usize, usize),
rhs: (usize, usize),
},
NotSquare {
op: &'static str,
shape: (usize, usize),
},
Singular {
shape: (usize, usize),
},
Inconsistent,
IndexOutOfBounds {
i: usize,
j: usize,
rows: usize,
cols: usize,
},
DimensionTooLarge {
rows: usize,
cols: usize,
},
}
impl fmt::Display for FiniteFieldError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FiniteFieldError::NotPrime { modulus } => write!(
f,
"{modulus} is not prime: GF(q) requires a prime characteristic"
),
FiniteFieldError::ModulusTooLarge { modulus } => write!(
f,
"characteristic {modulus} does not fit in a 64-bit machine word"
),
FiniteFieldError::DegreeOutOfRange { degree } => write!(
f,
"extension degree {degree} is outside 1..={}",
super::MAX_EXTENSION_DEGREE
),
FiniteFieldError::BadDefiningPolynomial { reason } => {
write!(f, "unusable defining polynomial: {reason}")
}
FiniteFieldError::MalformedElement { got, degree } => write!(
f,
"element has {got} coefficients but the field has degree {degree}; \
an element of GF(p^k) is a polynomial of degree < k"
),
FiniteFieldError::FieldMismatch { lhs, rhs } => {
write!(f, "operands live over different fields: {lhs} and {rhs}")
}
FiniteFieldError::DimensionMismatch { op, lhs, rhs } => write!(
f,
"cannot {op} a {}x{} matrix with a {}x{} matrix",
lhs.0, lhs.1, rhs.0, rhs.1
),
FiniteFieldError::NotSquare { op, shape } => write!(
f,
"{op} requires a square matrix; this one is {}x{}",
shape.0, shape.1
),
FiniteFieldError::Singular { shape } => write!(
f,
"the {}x{} matrix is singular over this field and has no inverse",
shape.0, shape.1
),
FiniteFieldError::Inconsistent => write!(
f,
"the linear system has no solution: the right-hand side is outside \
the column space"
),
FiniteFieldError::IndexOutOfBounds { i, j, rows, cols } => {
write!(f, "index ({i}, {j}) is outside a {rows}x{cols} matrix")
}
FiniteFieldError::DimensionTooLarge { rows, cols } => write!(
f,
"a {rows}x{cols} matrix exceeds what the FLINT backend can address"
),
}
}
}
impl std::error::Error for FiniteFieldError {}
impl crate::errors::AlkahestError for FiniteFieldError {
fn code(&self) -> &'static str {
match self {
FiniteFieldError::NotPrime { .. } => "E-GFQ-001",
FiniteFieldError::ModulusTooLarge { .. } => "E-GFQ-002",
FiniteFieldError::DegreeOutOfRange { .. } => "E-GFQ-003",
FiniteFieldError::BadDefiningPolynomial { .. } => "E-GFQ-004",
FiniteFieldError::MalformedElement { .. } => "E-GFQ-005",
FiniteFieldError::FieldMismatch { .. } => "E-GFQ-006",
FiniteFieldError::DimensionMismatch { .. } => "E-GFQ-007",
FiniteFieldError::NotSquare { .. } => "E-GFQ-008",
FiniteFieldError::Singular { .. } => "E-GFQ-009",
FiniteFieldError::Inconsistent => "E-GFQ-010",
FiniteFieldError::IndexOutOfBounds { .. } => "E-GFQ-011",
FiniteFieldError::DimensionTooLarge { .. } => "E-GFQ-012",
}
}
fn remediation(&self) -> Option<&'static str> {
crate::errors::codes::REGISTRY
.iter()
.find(|spec| spec.code == crate::errors::AlkahestError::code(self))
.and_then(|spec| spec.remediation)
}
}