const SMALLEST_PAIR_T: f32 = 1.0 / 1_048_576.0;
const ABSOLUTE_MARGIN: f32 = 2.3e-16;
const RELATIVE_MARGIN: f32 = 6.0e-14;
pub(super) fn edge_coverage(t: f32) -> f32 {
if t >= SMALLEST_PAIR_T
&& let Some(coverage) = pair_coverage(t)
{
return coverage;
}
f64_coverage(t)
}
#[cold]
#[inline(never)]
fn f64_coverage(t: f32) -> f32 {
let t = f64::from(t);
let smooth = t * t * (3.0 - 2.0 * t);
(1.0 - smooth) as f32
}
fn pair_coverage(t: f32) -> Option<f32> {
let (high, low) = if t >= 0.5 {
let u = 1.0 - t;
let (square, square_low) = two_product(u, u);
let (factor, factor_low) = two_sum(3.0, -2.0 * u);
let (product, product_low) = two_product(square, factor);
two_sum(
product,
product_low + (square * factor_low + square_low * factor),
)
} else {
let (square, square_low) = two_product(t, t);
let (factor, factor_low) = two_sum(3.0, -2.0 * t);
let (product, product_low) = two_product(square, factor);
let product_low = product_low + (square * factor_low + square_low * factor);
let (rest, rest_low) = two_sum(1.0, -product);
two_sum(rest, rest_low - product_low)
};
let nearest = high + low;
let (off, off_low) = two_sum(high - nearest, low);
let below = f32::from_bits(nearest.to_bits().checked_sub(1)?);
let half_step = (nearest - below) * 0.5;
let margin = ABSOLUTE_MARGIN + nearest * RELATIVE_MARGIN;
((off + off_low).abs() < half_step - margin).then_some(nearest)
}
fn split(a: f32) -> (f32, f32) {
let scaled = 4097.0 * a;
let high = scaled - (scaled - a);
(high, a - high)
}
fn two_product(a: f32, b: f32) -> (f32, f32) {
let product = a * b;
let (a_high, a_low) = split(a);
let (b_high, b_low) = split(b);
let error = ((a_high * b_high - product) + a_high * b_low + a_low * b_high) + a_low * b_low;
(product, error)
}
fn two_sum(a: f32, b: f32) -> (f32, f32) {
let sum = a + b;
let b_part = sum - a;
let error = (a - (sum - b_part)) + (b - b_part);
(sum, error)
}