Skip to main content

ocas_py/
lib.rs

1//! Python bindings for oCAS.
2//!
3//! The top-level Python module is named `ocas` (see `pyproject.toml`).
4//!
5//! # Quick start
6//!
7//! ```python
8//! import ocas
9//!
10//! e = ocas.Expression("x^2 + 2*x + 1")
11//! print(e.diff("x"))                 # derivative
12//! print(e.simplify())
13//!
14//! print(ocas.solve_diophantine(3, 5, 1))
15//! ```
16
17use pyo3::prelude::*;
18
19pub mod algebraic;
20pub mod domain;
21pub mod double_float;
22pub mod dual;
23pub mod eval;
24pub mod expression;
25pub mod groebner;
26pub mod matrix;
27pub mod ntheory;
28pub mod numeric;
29pub mod ode;
30pub mod polynomial;
31pub mod solve;
32pub mod tensor;
33
34pub use algebraic::{
35    PyAlgebraicElement, PyAlgebraicExtension, PyAlgebraicFactor, PyAlgebraicPolynomial,
36};
37pub use domain::{PyFiniteField, PyIntegerDomain, PyRationalDomain};
38pub use double_float::PyDoubleF64;
39pub use dual::{PyDualShape, PyHyperDual};
40pub use eval::PyExpressionEvaluator;
41pub use expression::Expression;
42pub use groebner::{
43    PyGroebnerBasis, PyHilbertSeries, PyMultivariatePolynomial, PyPolynomialSystemSolution,
44    PyPrimaryComponent, PyRealSolution, py_eliminate, py_groebner_basis, py_hilbert_series,
45    py_ideal_contains, py_ideal_radical, py_is_zero_dimensional, py_primary_decomposition,
46    py_solve_polynomial_system,
47};
48pub use matrix::PyMatrix;
49pub use ntheory::{
50    py_crt, py_discrete_log, py_divisor_count, py_divisor_sigma, py_factorint, py_isprime,
51    py_isprime_u64, py_jacobi_symbol, py_liouville_lambda, py_mobius, py_nextprime, py_totient,
52};
53pub use numeric::{PyIntegrateResult, PyVegas, integrate_1d};
54pub use ode::{py_classify_ode, py_dsolve, py_dsolve_ivp};
55pub use polynomial::{PyPolynomial, PyPolynomialFactor};
56pub use solve::{
57    PyDiophantineSolution, py_solve_diophantine, py_solve_linear_integer, py_solve_linear_rational,
58};
59pub use tensor::{
60    PyTensor, canonicalize_tensors, contract_tensors, refresh_dummies, tensor_symmetrise_sign,
61    young_project,
62};
63
64/// The oCAS Python module entry point.
65///
66/// The function name `ocas` determines the exported symbol `PyInit_ocas`,
67/// which Python looks for when importing the module named `ocas`.
68#[pymodule]
69fn ocas(m: &Bound<'_, PyModule>) -> PyResult<()> {
70    m.add("__version__", env!("CARGO_PKG_VERSION"))?;
71
72    m.add_class::<Expression>()?;
73    m.add_class::<PyExpressionEvaluator>()?;
74    m.add_class::<PyDiophantineSolution>()?;
75    m.add_class::<PyPolynomial>()?;
76    m.add_class::<PyPolynomialFactor>()?;
77    m.add_class::<PyAlgebraicExtension>()?;
78    m.add_class::<PyAlgebraicElement>()?;
79    m.add_class::<PyAlgebraicPolynomial>()?;
80    m.add_class::<PyAlgebraicFactor>()?;
81    m.add_class::<PyMatrix>()?;
82    m.add_class::<PyIntegerDomain>()?;
83    m.add_class::<PyRationalDomain>()?;
84    m.add_class::<PyFiniteField>()?;
85    m.add_class::<PyVegas>()?;
86    m.add_class::<PyIntegrateResult>()?;
87    m.add_class::<PyTensor>()?;
88    m.add_class::<PyDualShape>()?;
89    m.add_class::<PyHyperDual>()?;
90    m.add_class::<PyDoubleF64>()?;
91    m.add_class::<PyGroebnerBasis>()?;
92    m.add_class::<PyRealSolution>()?;
93    m.add_class::<PyPolynomialSystemSolution>()?;
94    m.add_class::<PyHilbertSeries>()?;
95    m.add_class::<PyPrimaryComponent>()?;
96    m.add_class::<PyMultivariatePolynomial>()?;
97
98    m.add_function(wrap_pyfunction!(py_solve_linear_rational, m)?)?;
99    m.add_function(wrap_pyfunction!(py_solve_linear_integer, m)?)?;
100    m.add_function(wrap_pyfunction!(py_solve_diophantine, m)?)?;
101    m.add_function(wrap_pyfunction!(integrate_1d, m)?)?;
102    m.add_function(wrap_pyfunction!(contract_tensors, m)?)?;
103    m.add_function(wrap_pyfunction!(tensor_symmetrise_sign, m)?)?;
104    m.add_function(wrap_pyfunction!(canonicalize_tensors, m)?)?;
105    m.add_function(wrap_pyfunction!(young_project, m)?)?;
106    m.add_function(wrap_pyfunction!(refresh_dummies, m)?)?;
107    m.add_function(wrap_pyfunction!(py_classify_ode, m)?)?;
108    m.add_function(wrap_pyfunction!(py_dsolve, m)?)?;
109    m.add_function(wrap_pyfunction!(py_dsolve_ivp, m)?)?;
110    m.add_function(wrap_pyfunction!(py_factorint, m)?)?;
111    m.add_function(wrap_pyfunction!(py_isprime, m)?)?;
112    m.add_function(wrap_pyfunction!(py_isprime_u64, m)?)?;
113    m.add_function(wrap_pyfunction!(py_nextprime, m)?)?;
114    m.add_function(wrap_pyfunction!(py_discrete_log, m)?)?;
115    m.add_function(wrap_pyfunction!(py_crt, m)?)?;
116    m.add_function(wrap_pyfunction!(py_jacobi_symbol, m)?)?;
117    m.add_function(wrap_pyfunction!(py_totient, m)?)?;
118    m.add_function(wrap_pyfunction!(py_mobius, m)?)?;
119    m.add_function(wrap_pyfunction!(py_divisor_count, m)?)?;
120    m.add_function(wrap_pyfunction!(py_divisor_sigma, m)?)?;
121    m.add_function(wrap_pyfunction!(py_liouville_lambda, m)?)?;
122    m.add_function(wrap_pyfunction!(py_groebner_basis, m)?)?;
123    m.add_function(wrap_pyfunction!(py_ideal_contains, m)?)?;
124    m.add_function(wrap_pyfunction!(py_solve_polynomial_system, m)?)?;
125    m.add_function(wrap_pyfunction!(py_hilbert_series, m)?)?;
126    m.add_function(wrap_pyfunction!(py_ideal_radical, m)?)?;
127    m.add_function(wrap_pyfunction!(py_primary_decomposition, m)?)?;
128    m.add_function(wrap_pyfunction!(py_is_zero_dimensional, m)?)?;
129    m.add_function(wrap_pyfunction!(py_eliminate, m)?)?;
130
131    Ok(())
132}