#[allow(dead_code)]
mod common;
use gsdesign::{DensityGrid, IntegrationError, gridpts, h1, hupdate};
use common::assert_close_slice;
#[test]
fn gridpts_supports_infinite_bounds() {
let grid = gridpts(3, 0.0, f64::NEG_INFINITY, f64::INFINITY).expect("gridpts infinite");
assert_eq!(grid.points.len(), grid.weights.len());
for (lhs, rhs) in grid.points.iter().zip(grid.points.iter().rev()) {
assert!((*lhs + *rhs).abs() < 1e-12);
}
assert!(grid.weights.iter().all(|w| *w > 0.0));
}
#[test]
fn gridpts_single_point_when_bounds_extreme() {
let grid = gridpts(3, 0.0, 100.0, 101.0).expect("gridpts extreme bounds");
assert_eq!(grid.points.len(), 1);
assert_eq!(grid.weights.len(), 1);
assert_close_slice(&grid.points, &[100.0]);
assert_close_slice(&grid.weights, &[1.0]);
}
#[test]
fn gridpts_requires_r_at_least_two() {
let err = gridpts(1, 0.0, -1.0, 1.0).expect_err("gridpts should fail");
assert!(matches!(err, IntegrationError::InvalidStencil { .. }));
}
#[test]
fn gridpts_requires_increasing_bounds() {
let err = gridpts(2, 0.0, 1.0, 1.0).expect_err("gridpts should fail");
assert!(matches!(err, IntegrationError::NonIncreasingBounds { .. }));
}
#[test]
fn h1_requires_positive_info() {
let err = h1(3, 0.0, 0.0, -1.0, 1.0).expect_err("h1 should fail");
assert!(matches!(
err,
IntegrationError::NonPositiveInformation { .. }
));
}
#[test]
fn h1_infinite_bounds_integrates_to_one() {
let grid = h1(3, 0.0, 1.0, f64::NEG_INFINITY, f64::INFINITY).expect("h1 infinite");
let total: f64 = grid.values.iter().sum();
assert!((total - 1.0).abs() < 1e-3);
}
#[test]
fn hupdate_requires_increasing_info() {
let gm1 = h1(3, 0.0, 1.0, -2.0, 2.0).expect("h1 previous");
let err = hupdate(3, 0.0, 1.0, -2.0, 2.0, 0.0, 1.0, &gm1).expect_err("hupdate should fail");
assert!(matches!(
err,
IntegrationError::NonIncreasingInformation { info_prev, info }
if (info_prev - 1.0).abs() < 1e-12 && (info - 1.0).abs() < 1e-12
));
}
#[test]
fn hupdate_requires_positive_previous_info() {
let gm1 = DensityGrid {
points: vec![0.0],
weights: vec![1.0],
values: vec![1.0],
};
let err = hupdate(3, 0.0, 2.0, -2.0, 2.0, 0.0, 0.0, &gm1).expect_err("hupdate should fail");
assert!(matches!(
err,
IntegrationError::NonPositivePreviousInformation { info_prev }
if info_prev == 0.0
));
}
#[test]
fn hupdate_rejects_shape_mismatch() {
let gm1 = DensityGrid {
points: vec![0.0, 1.0],
weights: vec![1.0, 1.0],
values: vec![1.0],
};
let err = hupdate(3, 0.0, 2.0, -2.0, 2.0, 0.0, 1.0, &gm1).expect_err("hupdate should fail");
assert!(matches!(
err,
IntegrationError::ShapeMismatch {
points,
weights,
values: Some(values),
}
if points == 2 && weights == 2 && values == 1
));
}
#[test]
fn hupdate_infinite_bounds_preserves_mass() {
let gm1 = h1(3, 0.0, 1.0, f64::NEG_INFINITY, f64::INFINITY).expect("h1 infinite");
let grid = hupdate(
3,
0.0,
2.0,
f64::NEG_INFINITY,
f64::INFINITY,
0.0,
1.0,
&gm1,
)
.expect("hupdate infinite");
let total: f64 = grid.values.iter().sum();
assert!((total - 1.0).abs() < 1e-3);
}