use super::*;
#[cfg_attr(feature = "python_stubgen", gen_stub_pyclass)]
#[pyclass(from_py_object, name = "Integer", module = "symbolica.core")]
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct PythonInteger {}
#[cfg_attr(feature = "python_stubgen", gen_stub_pymethods)]
#[cfg_attr(not(feature = "python_stubgen"), remove_gen_stub)]
#[pymethods]
impl PythonInteger {
#[pyo3(signature = (start = 1))]
#[classmethod]
fn prime_iter(_cls: &Bound<'_, PyType>, start: u64) -> PyResult<PythonPrimeIterator> {
Ok(PythonPrimeIterator {
cur: PrimeIteratorU64::new(start),
})
}
#[classmethod]
#[pyo3(signature = (n, k = 24))]
fn is_prime(_cls: &Bound<'_, PyType>, n: Integer, k: usize) -> bool {
n.is_prime(k)
}
#[classmethod]
fn factor(_cls: &Bound<'_, PyType>, n: Integer) -> Vec<(Integer, Integer)> {
n.factor()
}
#[classmethod]
fn totient(_cls: &Bound<'_, PyType>, n: Integer) -> Integer {
n.totient()
}
#[classmethod]
fn gcd(_cls: &Bound<'_, PyType>, n1: Integer, n2: Integer) -> Integer {
n1.gcd(&n2)
}
#[classmethod]
fn extended_gcd(
_cls: &Bound<'_, PyType>,
n1: Integer,
n2: Integer,
) -> (Integer, Integer, Integer) {
n1.extended_gcd(&n2)
}
#[classmethod]
fn chinese_remainder(
_cls: &Bound<'_, PyType>,
n1: Integer,
m1: Integer,
n2: Integer,
m2: Integer,
) -> Integer {
Integer::chinese_remainder(n1, n2, m1, m2)
}
#[classmethod]
fn lcm(_cls: &Bound<'_, PyType>, n1: Integer, n2: Integer) -> Integer {
n1.lcm(&n2)
}
#[pyo3(signature = (x, tolerance, max_iter = 1000, max_coeff = None, gamma = None))]
#[classmethod]
fn solve_integer_relation<'py>(
_cls: &Bound<'_, PyType>,
x: Vec<PythonMultiPrecisionFloat>,
tolerance: PythonMultiPrecisionFloat,
max_iter: usize,
max_coeff: Option<Integer>,
gamma: Option<PythonMultiPrecisionFloat>,
py: Python<'py>,
) -> PyResult<Vec<Bound<'py, PyInt>>> {
let x: Vec<_> = x.into_iter().map(|x| x.0).collect();
let res = Integer::solve_integer_relation(
&x,
tolerance.0,
max_iter,
max_coeff,
gamma.map(|x| x.0),
)
.map_err(|e| match e {
IntegerRelationError::CoefficientLimit => {
exceptions::PyValueError::new_err("Coefficient limit exceeded")
}
IntegerRelationError::IterationLimit(_) => {
exceptions::PyValueError::new_err("Iteration limit exceeded")
}
IntegerRelationError::PrecisionLimit => {
exceptions::PyValueError::new_err("Precision limit exceeded")
}
})?;
Ok(res
.into_iter()
.map(|x| x.into_pyobject(py).unwrap())
.collect())
}
}
#[cfg_attr(feature = "python_stubgen", gen_stub_pyclass)]
#[pyclass(from_py_object, name = "PrimeIterator", module = "symbolica.core")]
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct PythonPrimeIterator {
cur: PrimeIteratorU64,
}
#[cfg_attr(feature = "python_stubgen", gen_stub_pymethods)]
#[cfg_attr(not(feature = "python_stubgen"), remove_gen_stub)]
#[pymethods]
impl PythonPrimeIterator {
fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
slf
}
#[gen_stub(override_return_type(type_repr = "int"))]
fn __next__(&mut self) -> Option<u64> {
self.cur.next()
}
}
#[cfg(feature = "python_stubgen")]
pyo3_stub_gen::define_stub_info_gatherer!(stub_info);