1use crate::float_consts::{EXP_BIAS, EXP_BIT_MASK, SIGNIF_BIT_MASK, SIGNIFICAND_WIDTH, SIZE};
4
5#[must_use]
12pub const fn round_f32(value: f32) -> i32 {
13 let bits = value.to_bits() as i32;
14 let biased_exp = (bits & EXP_BIT_MASK) >> (SIGNIFICAND_WIDTH - 1);
15 let shift = (SIGNIFICAND_WIDTH - 2 + EXP_BIAS) - biased_exp;
16 if shift >= 0 && shift < SIZE {
18 let mut r = (bits & SIGNIF_BIT_MASK) | (SIGNIF_BIT_MASK + 1);
19 if bits < 0 {
20 r = -r;
21 }
22 ((r >> shift) + 1) >> 1
23 } else {
24 value as i32
25 }
26}
27
28#[cfg(test)]
29mod tests {
30 use super::round_f32;
31
32 #[test]
33 fn round_f32_matches_java_math_round_on_halves() {
34 assert_eq!(round_f32(2.5), 3);
35 assert_eq!(round_f32(-2.5), -2);
36 assert_eq!(round_f32(2.4), 2);
37 assert_eq!(round_f32(-2.6), -3);
38 assert_eq!(round_f32(0.499_999_97), 0);
39 assert_eq!(round_f32(f32::NAN), 0);
40 assert_eq!(round_f32(1.0e10), i32::MAX);
41 }
42}