1use crate::support::{Float, FpResult, Round};
5
6#[inline]
9pub fn rint_round<F: Float>(x: F, _round: Round) -> FpResult<F> {
10 let toint = F::ONE / F::EPSILON;
11 let e = x.ex();
12 let positive = x.is_sign_positive();
13
14 let force = |x| {
17 if cfg!(x86_no_sse) && (F::BITS == 32 || F::BITS == 64) {
18 force_eval!(x)
19 } else {
20 x
21 }
22 };
23
24 let res = if e >= F::EXP_BIAS + F::SIG_BITS {
25 x
27 } else {
28 let y = if positive {
31 force(force(x) + toint) - toint
32 } else {
33 force(force(x) - toint) + toint
34 };
35
36 if y == F::ZERO {
37 if positive { F::ZERO } else { F::NEG_ZERO }
39 } else {
40 y
41 }
42 };
43
44 FpResult::ok(res)
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use crate::support::{Hexf, Status};
51
52 fn spec_test<F: Float>(cases: &[(F, F, Status)]) {
53 let roundtrip = [
54 F::ZERO,
55 F::ONE,
56 F::NEG_ONE,
57 F::NEG_ZERO,
58 F::INFINITY,
59 F::NEG_INFINITY,
60 ];
61
62 for x in roundtrip {
63 let FpResult { val, status } = rint_round(x, Round::Nearest);
64 assert_biteq!(val, x, "rint_round({})", Hexf(x));
65 assert_eq!(status, Status::OK, "{}", Hexf(x));
66 }
67
68 for &(x, res, res_stat) in cases {
69 let FpResult { val, status } = rint_round(x, Round::Nearest);
70 assert_biteq!(val, res, "rint_round({})", Hexf(x));
71 assert_eq!(status, res_stat, "{}", Hexf(x));
72 }
73 }
74
75 #[test]
76 #[cfg(f16_enabled)]
77 fn spec_tests_f16() {
78 let cases = [];
79 spec_test::<f16>(&cases);
80 }
81
82 #[test]
83 fn spec_tests_f32() {
84 let cases = [
85 (0.1, 0.0, Status::OK),
86 (-0.1, -0.0, Status::OK),
87 (0.5, 0.0, Status::OK),
88 (-0.5, -0.0, Status::OK),
89 (0.9, 1.0, Status::OK),
90 (-0.9, -1.0, Status::OK),
91 (1.1, 1.0, Status::OK),
92 (-1.1, -1.0, Status::OK),
93 (1.5, 2.0, Status::OK),
94 (-1.5, -2.0, Status::OK),
95 (1.9, 2.0, Status::OK),
96 (-1.9, -2.0, Status::OK),
97 (2.8, 3.0, Status::OK),
98 (-2.8, -3.0, Status::OK),
99 ];
100 spec_test::<f32>(&cases);
101 }
102
103 #[test]
104 fn spec_tests_f64() {
105 let cases = [
106 (0.1, 0.0, Status::OK),
107 (-0.1, -0.0, Status::OK),
108 (0.5, 0.0, Status::OK),
109 (-0.5, -0.0, Status::OK),
110 (0.9, 1.0, Status::OK),
111 (-0.9, -1.0, Status::OK),
112 (1.1, 1.0, Status::OK),
113 (-1.1, -1.0, Status::OK),
114 (1.5, 2.0, Status::OK),
115 (-1.5, -2.0, Status::OK),
116 (1.9, 2.0, Status::OK),
117 (-1.9, -2.0, Status::OK),
118 (2.8, 3.0, Status::OK),
119 (-2.8, -3.0, Status::OK),
120 ];
121 spec_test::<f64>(&cases);
122 }
123
124 #[test]
125 #[cfg(f128_enabled)]
126 fn spec_tests_f128() {
127 let cases = [];
128 spec_test::<f128>(&cases);
129 }
130}