sequential-integration 1.0.2

Lightweight library for sequential integration
Documentation
use core::marker::PhantomData;
use fehler::throws;

use super::utils as integrator_utils;
use crate::{
    engine::{
        helper_equation_traits::{EquationOfThreeVariable, EquationOfTwoVariable},
        quadrature::GetQuadratureRange,
        Bounds, CalculationResult, CalculationStep,
    },
    errors::Error,
};

pub struct ThirdIntegrator<
    'a,
    G: GetQuadratureRange,
    E: EquationOfThreeVariable,
    F1: Fn(f64, f64) -> f64,
    F2: Fn(f64, f64) -> f64,
> {
    a_equation: F1,
    b_equation: F2,
    h: f64,
    equation: &'a E,
    _p: PhantomData<G>,
}

impl<
        'a,
        G: GetQuadratureRange,
        E: EquationOfThreeVariable,
        F1: Fn(f64, f64) -> f64,
        F2: Fn(f64, f64) -> f64,
    > ThirdIntegrator<'a, G, E, F1, F2>
{
    #[throws]
    pub fn new(a_equation: F1, b_equation: F2, h: f64, equation: &'a E) -> Self {
        Self {
            a_equation,
            b_equation,
            h,
            equation,
            _p: PhantomData,
        }
    }
}

impl<
        'a,
        G: GetQuadratureRange,
        E: EquationOfThreeVariable,
        F1: Fn(f64, f64) -> f64,
        F2: Fn(f64, f64) -> f64,
    > EquationOfTwoVariable for ThirdIntegrator<'a, G, E, F1, F2>
{
    #[throws]
    fn calculate(
        &self,
        x: CalculationStep,
        bounds_x: Bounds,
        y: CalculationStep,
        bounds_y: Bounds,
    ) -> CalculationResult {
        let a = (self.a_equation)(*x, *y);
        let b = (self.b_equation)(*x, *y);
        let borders_config = integrator_utils::BoundsConfigurator::configurate(a, b)?;

        let mut result = CalculationResult::new();
        let mut range = if let Some(range) = G::get_range_generator(borders_config.bounds, self.h)?
        {
            range
        } else {
            return result;
        };

        loop {
            let step = range.next()?;
            result +=
                self.equation
                    .calculate(x, bounds_x, y, bounds_y, step, borders_config.bounds)?
                    * borders_config.direction_coeff;

            if step.is_last() {
                break;
            }
        }

        result
    }
}