use super::algorithm::*;
use super::common::{Integrand, IntegrationConfig, Points, Range};
use crate::{IntegrationResult, Tolerance};
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Integrator<F: Integrand, A: Algorithm<F>> {
integrand: F,
algorithm: A,
config: IntegrationConfig,
}
impl<F: Integrand> Integrator<F, AUTO> {
#[inline]
pub fn new(integrand: F) -> Integrator<F, AUTO> {
Self {
integrand,
algorithm: AUTO::new(),
config: IntegrationConfig::default(),
}
}
}
impl<F: Integrand, A: Algorithm<F>> Integrator<F, A> {
#[inline]
pub fn with_algorithm(integrand: F, algorithm: A) -> Integrator<F, A> {
Self {
integrand,
algorithm,
config: IntegrationConfig::default(),
}
}
#[inline]
pub fn tolerance(mut self, t: Tolerance) -> Self {
assert!(!t.contains_nan(), "Tolerance must not contain NAN.");
self.config.tolerance = t;
self
}
#[inline]
pub fn max_iters(mut self, max_iters: usize) -> Self {
self.config.max_iters = max_iters;
self
}
pub fn points(mut self, pts: &[f64]) -> Self {
assert!(
pts.iter().all(|&x| !x.is_nan()),
"cannot include NAN value in singular points: {:?}",
pts
);
self.config.points = Points::from(pts);
self
}
#[inline]
pub fn get_algorithm(&self) -> &A {
&self.algorithm
}
#[inline]
pub fn run<T: Into<Range>>(&mut self, range: T) -> IntegrationResult {
self.algorithm
.integrate(&mut self.integrand, &range.into(), &self.config)
}
}
impl<F: Integrand + Eq, A: Algorithm<F> + Eq> Eq for Integrator<F, A> {}
impl<F: Integrand> From<F> for Integrator<F, AUTO> {
#[inline]
fn from(integrand: F) -> Self {
Self::new(integrand)
}
}
impl<F: Integrand + Clone> From<&F> for Integrator<F, AUTO> {
#[inline]
fn from(integrand: &F) -> Self {
Self::new(integrand.clone())
}
}