1use num_bigint::BigInt;
9use pyo3::exceptions::PyValueError;
10use pyo3::prelude::*;
11
12pub(crate) enum DomainKind {
15 Integer,
16 Rational,
17 FiniteField(BigInt),
18}
19
20impl DomainKind {
21 pub(crate) fn from_py(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
26 if let Ok(s) = obj.extract::<String>() {
27 match s.as_str() {
28 "integer" | "int" | "Z" => Ok(DomainKind::Integer),
29 "rational" | "rat" | "Q" => Ok(DomainKind::Rational),
30 other => Err(PyValueError::new_err(format!(
31 "unknown domain string: {other:?} (expected one of \
32 'integer'/'int'/'Z', 'rational'/'rat'/'Q', or a FiniteField)"
33 ))),
34 }
35 } else if let Ok(fq) = obj.extract::<PyRef<'_, PyFiniteField>>() {
36 Ok(DomainKind::FiniteField(fq.modulus.clone()))
37 } else {
38 Err(PyValueError::new_err(
39 "domain must be a string ('integer'/'rational') or a FiniteField instance",
40 ))
41 }
42 }
43}
44
45#[pyclass(name = "IntegerDomain", skip_from_py_object)]
53#[derive(Clone)]
54pub struct PyIntegerDomain;
55
56#[pymethods]
57impl PyIntegerDomain {
58 #[new]
59 fn new() -> Self {
60 PyIntegerDomain
61 }
62
63 fn __repr__(&self) -> String {
64 "IntegerDomain()".to_string()
65 }
66}
67
68#[pyclass(name = "RationalDomain", skip_from_py_object)]
75#[derive(Clone)]
76pub struct PyRationalDomain;
77
78#[pymethods]
79impl PyRationalDomain {
80 #[new]
81 fn new() -> Self {
82 PyRationalDomain
83 }
84
85 fn __repr__(&self) -> String {
86 "RationalDomain()".to_string()
87 }
88}
89
90#[pyclass(name = "FiniteField", from_py_object)]
98#[derive(Clone)]
99pub struct PyFiniteField {
100 pub(crate) modulus: BigInt,
101}
102
103#[pymethods]
104impl PyFiniteField {
105 #[new]
107 fn new(modulus: i64) -> PyResult<Self> {
108 if modulus < 2 {
109 return Err(PyValueError::new_err(format!(
110 "finite-field modulus must be a prime ≥ 2, got {modulus}"
111 )));
112 }
113 Ok(PyFiniteField {
114 modulus: BigInt::from(modulus),
115 })
116 }
117
118 #[getter]
120 fn modulus(&self) -> String {
121 self.modulus.to_string()
122 }
123
124 fn __repr__(&self) -> String {
125 format!("FiniteField({})", self.modulus)
126 }
127}