Coverage Report

Created: 2025-06-23 13:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/cargo-vendor-dir/libm-0.2.15/src/math/generic/fma_wide.rs
Line
Count
Source
1
use crate::support::{
2
    CastFrom, CastInto, DFloat, Float, FpResult, HFloat, IntTy, MinInt, Round, Status,
3
};
4
5
/// Fma implementation when a hardware-backed larger float type is available. For `f32` and `f64`,
6
/// `f64` has enough precision to represent the `f32` in its entirety, except for double rounding.
7
#[inline]
8
0
pub fn fma_wide_round<F, B>(x: F, y: F, z: F, round: Round) -> FpResult<F>
9
0
where
10
0
    F: Float + HFloat<D = B>,
11
0
    B: Float + DFloat<H = F>,
12
0
    B::Int: CastInto<i32>,
13
0
    i32: CastFrom<i32>,
14
0
{
15
0
    let one = IntTy::<B>::ONE;
16
0
17
0
    let xy: B = x.widen() * y.widen();
18
0
    let mut result: B = xy + z.widen();
19
0
    let mut ui: B::Int = result.to_bits();
20
0
    let re = result.ex();
21
0
    let zb: B = z.widen();
22
0
23
0
    let prec_diff = B::SIG_BITS - F::SIG_BITS;
24
0
    let excess_prec = ui & ((one << prec_diff) - one);
25
0
    let halfway = one << (prec_diff - 1);
26
0
27
0
    // Common case: the larger precision is fine if...
28
0
    // This is not a halfway case
29
0
    if excess_prec != halfway
30
        // Or the result is NaN
31
0
        || re == B::EXP_SAT
32
        // Or the result is exact
33
0
        || (result - xy == zb && result - zb == xy)
34
        // Or the mode is something other than round to nearest
35
0
        || round != Round::Nearest
36
    {
37
0
        let min_inexact_exp = (B::EXP_BIAS as i32 + F::EXP_MIN_SUBNORM) as u32;
38
0
        let max_inexact_exp = (B::EXP_BIAS as i32 + F::EXP_MIN) as u32;
39
0
40
0
        let mut status = Status::OK;
41
0
42
0
        if (min_inexact_exp..max_inexact_exp).contains(&re) && status.inexact() {
43
            // This branch is never hit; requires previous operations to set a status
44
0
            status.set_inexact(false);
45
0
46
0
            result = xy + z.widen();
47
0
            if status.inexact() {
48
0
                status.set_underflow(true);
49
0
            } else {
50
0
                status.set_inexact(true);
51
0
            }
52
0
        }
53
54
0
        return FpResult {
55
0
            val: result.narrow(),
56
0
            status,
57
0
        };
58
0
    }
59
0
60
0
    let neg = ui >> (B::BITS - 1) != IntTy::<B>::ZERO;
61
0
    let err = if neg == (zb > xy) {
62
0
        xy - result + zb
63
    } else {
64
0
        zb - result + xy
65
    };
66
0
    if neg == (err < B::ZERO) {
67
0
        ui += one;
68
0
    } else {
69
0
        ui -= one;
70
0
    }
71
72
0
    FpResult::ok(B::from_bits(ui).narrow())
73
0
}