sequential-integration 1.0.2

Lightweight library for sequential integration
Documentation
use fehler::throws;
use snafu::ensure;

use crate::{
    engine::{
        range_generator::{CalculationStep, RangeGenerator},
        Bounds,
    },
    errors::{self, Error},
};

pub struct SimpsonRangeGenerator {
    end: f64,
    h: f64,
    current_step: f64,
}

impl SimpsonRangeGenerator {
    #[throws]
    pub fn new(bounds: Bounds, h: f64) -> Option<Self> {
        if (bounds.end - bounds.begin).abs() == 0. {
            return None;
        }

        Some(Self {
            end: bounds.end,
            h,
            current_step: bounds.begin,
        })
    }
}

impl RangeGenerator for SimpsonRangeGenerator {
    #[throws]
    fn next(&mut self) -> CalculationStep {
        ensure!(
            self.current_step < self.end,
            errors::RangeGeneratorOutOfBounds {
                step: self.current_step,
                end: self.end
            }
        );

        let result = if self.current_step >= self.end - 2. * self.h {
            CalculationStep::Last(self.current_step)
        } else {
            CalculationStep::Common(self.current_step)
        };

        self.current_step += 2. * self.h;
        result
    }
}