use super::super::common::{Integrand, Range};
use super::super::qk::QKResult;
use super::super::util::{rescale_error, Array};
#[cfg(not(feature = "std"))]
use crate::float::Float;
pub unsafe fn qk<F, K, G>(
f: &mut F,
range: &Range,
xgk: &K,
wg: &G,
wgk: &K,
wck: f64,
buf: &mut [f64],
) -> QKResult
where
F: Integrand,
K: Array<Item = f64>,
G: Array<Item = f64>,
{
let xgk = xgk.as_slice();
let wg = wg.as_slice();
let wgk = wgk.as_slice();
debug_assert!(!xgk.is_empty());
debug_assert!(xgk.len() == wg.len() * 2);
debug_assert!(buf.len() > xgk.len() * 2);
let n = K::CAPACITY;
let center = 0.5 * (range.begin + range.end);
let half_length = 0.5 * (range.end - range.begin);
let abs_half_length = half_length.abs();
*buf.get_unchecked_mut(n << 1) = center;
for j in 0..n {
let abscissa = half_length * xgk.get_unchecked(j);
*buf.get_unchecked_mut(j) = center - abscissa;
*buf.get_unchecked_mut(j + n) = center + abscissa;
}
f.apply_to_slice(buf);
let f_center = buf.get_unchecked(n << 1);
let mut result_gauss = 0.;
let mut result_kronrod = f_center * wck;
let mut result_abs = result_kronrod.abs();
for j in 0..n {
let fval1 = *buf.get_unchecked(j);
let fval2 = *buf.get_unchecked(j + n);
let fsum = fval1 + fval2;
result_kronrod += wgk.get_unchecked(j) * fsum;
result_abs += wgk.get_unchecked(j) * (fval1.abs() + fval2.abs());
if j % 2 == 0 {
result_gauss += *wg.get_unchecked(j / 2) * fsum;
}
}
let mean = result_kronrod * 0.5;
let mut result_asc = wck * (f_center - mean).abs();
for j in 0..n {
result_asc += wgk.get_unchecked(j)
* ((buf.get_unchecked(j) - mean).abs() + (buf.get_unchecked(j + n) - mean).abs());
}
let err = (result_kronrod - result_gauss) * half_length;
result_kronrod *= half_length;
result_abs *= abs_half_length;
result_asc *= abs_half_length;
QKResult {
estimate: result_kronrod,
delta: rescale_error(err, result_abs, result_asc),
absvalue: result_abs,
asc: result_asc,
}
}