use std::sync::LazyLock;
use crate::errors::QlResult;
use crate::math::integrals::gaussianquadratures::GaussianQuadrature;
use crate::termstructures::credit::defaulttermstructure::DefaultProbabilityTermStructure;
use crate::types::{Probability, Time};
pub trait DefaultDensityStructure: DefaultProbabilityTermStructure {
fn survival_probability_from_default_density(&self, t: Time) -> QlResult<Probability> {
static QUADRATURE: LazyLock<QlResult<GaussianQuadrature>> =
LazyLock::new(|| GaussianQuadrature::chebyshev(48));
let quadrature = QUADRATURE.as_ref().map_err(Clone::clone)?;
let mut integral = 0.0;
for i in (0..quadrature.order()).rev() {
let time = (quadrature.abscissas()[i] + 1.0) * t / 2.0;
integral += quadrature.weights()[i] * self.default_density_impl(time)?;
}
let survival = 1.0 - integral * t / 2.0;
Ok(if survival < 0.0 { 0.0 } else { survival })
}
}