pub mod asymptotics;
pub mod azeil;
pub mod boundary;
pub mod hyperterm;
pub mod modular;
pub mod qfield;
pub mod qzeil;
pub mod telescoping2d;
pub mod zeilberger;
pub use azeil::{
almkvist_zeilberger, dgosper, hyperexp_log_derivative, integral_boundary_status, AzOpts,
AzResult, DiffTelescopingError, HyperExpTerm, IntegralBoundaryStatus, IntegrationLimit,
PowerFactor,
};
pub use asymptotics::{
asymptotics_from_recurrence, CharacteristicAnalysis, CharacteristicRoot, ConnectionConstant,
PerronVerdict, RecurrenceAsymptotics,
};
pub use boundary::{
boundary_status, boundary_verdict, natural_limits, BoundaryStatus, BoundaryVerdict,
};
pub use hyperterm::{GammaFactor, ProperTerm};
pub use modular::{binomial_mod, ModularError, ModularEvaluation, ModularRecurrence};
pub use qfield::{PolyK, RatK, Rn};
pub use qzeil::{
cyclotomic_polynomial, q_boundary_status, q_specialize_at_root_of_unity, q_zeilberger,
CycloElem, CycloField, QBoundaryStatus, QCertificate, QHolonomicError, QProperTerm,
QRootOfUnitySpecialization, QRootOfUnityStatus, QZeilbergerOpts, QZeilbergerReport,
QZeilbergerResult,
};
pub use telescoping2d::{
boundary_status_2d, telescope2d, telescope2d_search, BoundaryStatus2d, Telescoping2dError,
Telescoping2dOpts, Telescoping2dResult,
};
pub use zeilberger::{
boundary_side_condition, boundary_term, zeilberger, zeilberger_search, OrderSearch,
ZeilbergerOpts, ZeilbergerResult, ZeilbergerSearchReport,
};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HolonomicError {
NotProperHypergeometric(String),
SearchExhausted(String),
CertificateVerificationFailed(String),
InvalidInput(String),
}
impl fmt::Display for HolonomicError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
HolonomicError::NotProperHypergeometric(s) => {
write!(f, "holonomic: not a proper hypergeometric term: {s}")
}
HolonomicError::SearchExhausted(s) => {
write!(f, "holonomic: search exhausted: {s}")
}
HolonomicError::CertificateVerificationFailed(s) => {
write!(f, "holonomic: certificate failed exact verification: {s}")
}
HolonomicError::InvalidInput(s) => {
write!(f, "holonomic: invalid input: {s}")
}
}
}
}
impl std::error::Error for HolonomicError {}
impl crate::errors::AlkahestError for HolonomicError {
fn code(&self) -> &'static str {
match self {
HolonomicError::NotProperHypergeometric(_) => "E-HOLO-001",
HolonomicError::SearchExhausted(_) => "E-HOLO-002",
HolonomicError::CertificateVerificationFailed(_) => "E-HOLO-003",
HolonomicError::InvalidInput(_) => "E-HOLO-004",
}
}
fn remediation(&self) -> Option<&'static str> {
Some(match self {
HolonomicError::NotProperHypergeometric(_) => {
"rewrite the term as R(n,k)*z**k*w**n*prod(gamma(a*n + b*k + c)**e) with \
integer a, b and rational c; supported function heads are gamma, factorial, \
binomial, pochhammer"
}
HolonomicError::SearchExhausted(_) => {
"raise max_order and/or max_degree in ZeilbergerOpts; if the term genuinely \
has no such recurrence within reach, Zeilberger's algorithm does not apply"
}
HolonomicError::CertificateVerificationFailed(_) => {
"internal: report the term as a minimal failing example"
}
HolonomicError::InvalidInput(_) => {
"n and k must be distinct symbols; max_order and max_degree must be positive"
}
})
}
}