use symplex::prelude::*;
fn main() {
println!("=== Definite, Improper and Numeric Integration ===\n");
let ctx = Context::new();
symplex::syms!(ctx; x);
let zero = ctx.int(0);
let one = ctx.int(1);
let inf = ctx.infinity();
let neg_inf = ctx.neg_infinity();
println!("--- Proper definite integrals ---");
let poly = expr!(ctx, x ^ 3 - 3 * x ^ 2 + 2 * x);
println!(
"∫₀¹ ({poly}) dx = {}",
poly.integrate_definite(&x, &zero, &one)
);
println!(
"∫₀^π sin(x) dx = {}",
x.sin().integrate_definite(&x, &zero, &ctx.pi())
);
let two = ctx.int(2);
println!(
"∫₁² dx/x² = {}",
x.powi(-2).integrate_definite(&x, &one, &two)
);
println!("\n--- Divergence detection ---");
let neg_one = ctx.int(-1);
match x.powi(-2).try_integrate_definite(&x, &neg_one, &one) {
Err(SymplexError::Divergent { .. }) => {
println!("∫₋₁¹ dx/x² → Err(Divergent) (interior pole; F(1) − F(−1) would give −2)")
}
other => println!("unexpected: {other:?}"),
}
match (1 / &x).try_integrate_definite(&x, &one, &inf) {
Err(SymplexError::Divergent { .. }) => println!("∫₁^∞ dx/x → Err(Divergent)"),
other => println!("unexpected: {other:?}"),
}
let kept = x.powi(-2).integrate_definite(&x, &neg_one, &one);
println!(
"integrate_definite keeps it symbolic: {kept} (has_unevaluated = {})",
kept.has_unevaluated()
);
println!("\n--- Improper integrals ---");
let show = |label: &str, f: &Ex, lo: &Ex, hi: &Ex| {
println!("{label:<28} = {}", f.integrate_definite(&x, lo, hi));
};
show("∫₀^∞ e^(−x) dx", &(-&x).exp(), &zero, &inf);
show("∫₋∞^∞ e^(−x²) dx", &(-x.powi(2)).exp(), &neg_inf, &inf);
show("∫₀^∞ sin(x)/x dx", &(&x.sin() / &x), &zero, &inf);
show("∫₀^∞ dx/(1+x²)", &(1 / (&x.powi(2) + 1)), &zero, &inf);
show("∫₀¹ ln(x) dx", &x.ln(), &zero, &one);
show("∫₀¹ dx/√x", &(1 / &x.sqrt()), &zero, &one);
show(
"∫₀^∞ x³ e^(−x) dx",
&(&x.powi(3) * &(-&x).exp()),
&zero,
&inf,
);
show("∫₀^∞ x/(e^x − 1) dx", &(&x / (&x.exp() - 1)), &zero, &inf);
show("∫₀^∞ cos(x²) dx", &x.powi(2).cos(), &zero, &inf);
show(
"∫₋₁¹ √(1 − x²) dx",
&(1 - &x.powi(2)).sqrt(),
&neg_one,
&one,
);
let a = ctx.symbol_with("a", &[Assumption::Positive]);
let n = ctx.symbol_with("n", &[Assumption::Positive]);
show(
"∫₀^∞ e^(−a x) dx (a > 0)",
&(-(&a * &x)).exp(),
&zero,
&inf,
);
show(
"∫₋∞^∞ e^(−a x²) dx (a > 0)",
&(-(&a * &x.powi(2))).exp(),
&neg_inf,
&inf,
);
show(
"∫₀^∞ e^(−a x) sin(x) dx",
&(&x.sin() * &(-(&a * &x)).exp()),
&zero,
&inf,
);
show(
"∫₀^∞ x^(n−1) e^(−x) dx (n > 0)",
&(&x.pow(&(&n - 1)) * &(-&x).exp()),
&zero,
&inf,
);
println!("\n--- Abs / Heaviside / DiracDelta / Piecewise integrands ---");
let neg_two = ctx.int(-2);
let three = ctx.int(3);
println!(
"∫₋₂³ |x| dx = {}",
x.abs().integrate_definite(&x, &neg_two, &three)
);
println!(
"∫₋₁¹ H(x) dx = {}",
x.heaviside().integrate_definite(&x, &neg_one, &one)
);
println!(
"∫₋₁¹ δ(x) cos(x) dx = {}",
(&x.dirac_delta() * &x.cos()).integrate_definite(&x, &neg_one, &one)
);
let pw = Ex::piecewise(&[(&x.powi(2), &x.lt(&one)), (&(2 - &x), &x.ge(&one))]);
println!(
"∫₀² piecewise dx = {}",
pw.integrate_definite(&x, &zero, &two)
);
println!("\n--- Numeric quadrature ---");
let v = x.sin().integrate_numeric(&x, &zero, &ctx.pi()).unwrap();
println!("∫₀^π sin(x) dx ≈ {v:.15}");
let gauss = (-x.powi(2))
.exp()
.integrate_numeric(&x, &neg_inf, &inf)
.unwrap();
println!(
"∫₋∞^∞ e^(−x²) dx ≈ {gauss:.15} (√π = {:.15})",
std::f64::consts::PI.sqrt()
);
let no_closed_form = x.powi(2).exp();
println!(
"∫₀¹ e^(x²) dx symbolically = {}",
no_closed_form.integrate_definite(&x, &zero, &one)
);
let opts = QuadOpts {
rel_tol: 1e-12,
..QuadOpts::default()
};
let q = no_closed_form
.integrate_numeric_with(&x, &zero, &one, &opts)
.unwrap();
println!(
"∫₀¹ e^(x²) dx numerically ≈ {:.15} (error estimate {:.1e})",
q.value, q.error
);
match x.powi(-2).integrate_numeric(&x, &neg_one, &one) {
Err(e) => println!("integrate_numeric(1/x², −1, 1) → Err: {e}"),
Ok(v) => println!("unexpected value {v}"),
}
println!("\n--- Residues ---");
let z = ctx.symbol("z");
let f = &z.exp() / &z.powi(3); println!("Res_{{z=0}} e^z / z³ = {}", f.residue(&z, &zero));
let g = 1 / (&z.powi(2) + 1); let i = ctx.i_unit();
println!("Res_{{z=i}} 1/(z²+1) = {}", g.residue(&z, &i));
println!(
"Res_{{z=∞}} 1/(z²+1) = {}",
g.residue_at_infinity(&z)
);
let h = (&z + 2) / (&z * (&z - 1));
println!(
"Res_{{z=∞}} (z+2)/(z(z−1)) = {} (= −(Res₀ + Res₁) = −(−2 + 3))",
h.residue_at_infinity(&z)
);
println!("\n✓ Done!");
}