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 dual;
22pub mod eval;
23pub mod expression;
24pub mod matrix;
25pub mod ntheory;
26pub mod numeric;
27pub mod ode;
28pub mod polynomial;
29pub mod solve;
30pub mod tensor;
31
32pub use algebraic::{
33    PyAlgebraicElement, PyAlgebraicExtension, PyAlgebraicFactor, PyAlgebraicPolynomial,
34};
35pub use domain::{PyFiniteField, PyIntegerDomain, PyRationalDomain};
36pub use dual::{PyDualShape, PyHyperDual};
37pub use eval::PyExpressionEvaluator;
38pub use expression::Expression;
39pub use matrix::PyMatrix;
40pub use ntheory::{
41    py_crt, py_discrete_log, py_divisor_count, py_divisor_sigma, py_factorint, py_isprime,
42    py_isprime_u64, py_jacobi_symbol, py_liouville_lambda, py_mobius, py_nextprime, py_totient,
43};
44pub use numeric::{PyIntegrateResult, PyVegas, integrate_1d};
45pub use ode::{py_classify_ode, py_dsolve, py_dsolve_ivp};
46pub use polynomial::{PyPolynomial, PyPolynomialFactor};
47pub use solve::{
48    PyDiophantineSolution, py_solve_diophantine, py_solve_linear_integer, py_solve_linear_rational,
49};
50pub use tensor::{
51    PyTensor, canonicalize_tensors, contract_tensors, refresh_dummies, tensor_symmetrise_sign,
52    young_project,
53};
54
55/// The oCAS Python module entry point.
56///
57/// The function name `ocas` determines the exported symbol `PyInit_ocas`,
58/// which Python looks for when importing the module named `ocas`.
59#[pymodule]
60fn ocas(m: &Bound<'_, PyModule>) -> PyResult<()> {
61    m.add("__version__", env!("CARGO_PKG_VERSION"))?;
62
63    m.add_class::<Expression>()?;
64    m.add_class::<PyExpressionEvaluator>()?;
65    m.add_class::<PyDiophantineSolution>()?;
66    m.add_class::<PyPolynomial>()?;
67    m.add_class::<PyPolynomialFactor>()?;
68    m.add_class::<PyAlgebraicExtension>()?;
69    m.add_class::<PyAlgebraicElement>()?;
70    m.add_class::<PyAlgebraicPolynomial>()?;
71    m.add_class::<PyAlgebraicFactor>()?;
72    m.add_class::<PyMatrix>()?;
73    m.add_class::<PyIntegerDomain>()?;
74    m.add_class::<PyRationalDomain>()?;
75    m.add_class::<PyFiniteField>()?;
76    m.add_class::<PyVegas>()?;
77    m.add_class::<PyIntegrateResult>()?;
78    m.add_class::<PyTensor>()?;
79    m.add_class::<PyDualShape>()?;
80    m.add_class::<PyHyperDual>()?;
81
82    m.add_function(wrap_pyfunction!(py_solve_linear_rational, m)?)?;
83    m.add_function(wrap_pyfunction!(py_solve_linear_integer, m)?)?;
84    m.add_function(wrap_pyfunction!(py_solve_diophantine, m)?)?;
85    m.add_function(wrap_pyfunction!(integrate_1d, m)?)?;
86    m.add_function(wrap_pyfunction!(contract_tensors, m)?)?;
87    m.add_function(wrap_pyfunction!(tensor_symmetrise_sign, m)?)?;
88    m.add_function(wrap_pyfunction!(canonicalize_tensors, m)?)?;
89    m.add_function(wrap_pyfunction!(young_project, m)?)?;
90    m.add_function(wrap_pyfunction!(refresh_dummies, m)?)?;
91    m.add_function(wrap_pyfunction!(py_classify_ode, m)?)?;
92    m.add_function(wrap_pyfunction!(py_dsolve, m)?)?;
93    m.add_function(wrap_pyfunction!(py_dsolve_ivp, m)?)?;
94    m.add_function(wrap_pyfunction!(py_factorint, m)?)?;
95    m.add_function(wrap_pyfunction!(py_isprime, m)?)?;
96    m.add_function(wrap_pyfunction!(py_isprime_u64, m)?)?;
97    m.add_function(wrap_pyfunction!(py_nextprime, m)?)?;
98    m.add_function(wrap_pyfunction!(py_discrete_log, m)?)?;
99    m.add_function(wrap_pyfunction!(py_crt, m)?)?;
100    m.add_function(wrap_pyfunction!(py_jacobi_symbol, m)?)?;
101    m.add_function(wrap_pyfunction!(py_totient, m)?)?;
102    m.add_function(wrap_pyfunction!(py_mobius, m)?)?;
103    m.add_function(wrap_pyfunction!(py_divisor_count, m)?)?;
104    m.add_function(wrap_pyfunction!(py_divisor_sigma, m)?)?;
105    m.add_function(wrap_pyfunction!(py_liouville_lambda, m)?)?;
106
107    Ok(())
108}