1#![no_std]
2
3pub trait NextAfter {
56 #[must_use]
57 fn next_after(self, y: Self) -> Self;
58}
59
60macro_rules! impl_next_after {
61 ($float_type:ty, $module:ident, $minimum_non_zero:literal) => {
62 use super::NextAfter;
63
64 impl NextAfter for $float_type {
65 fn next_after(self, y: Self) -> Self {
66 if let Some(out) = short_circuit_operands(self, y) {
70 return out;
71 }
72
73 let return_value = if (y > self) == (self > 0.0) {
76 <$float_type>::from_bits(self.to_bits() + 1)
77 } else {
78 <$float_type>::from_bits(self.to_bits() - 1)
79 };
80
81 if return_value != 0.0 {
83 return return_value;
84 }
85
86 copy_sign(return_value, self)
89 }
90 }
91
92 #[inline]
93 fn short_circuit_operands(x: $float_type, y: $float_type) -> Option<$float_type> {
94 if y == x {
97 return Some(y);
100 }
101
102 if x.is_nan() || y.is_nan() {
104 return Some(core::$module::NAN);
105 }
106
107 if x.is_infinite() {
108 return Some(x);
109 }
110
111 if x == 0.0 {
115 return Some(copy_sign($minimum_non_zero, y));
116 }
117
118 None
119 }
120
121 #[inline]
122 fn copy_sign(x: $float_type, y: $float_type) -> $float_type {
123 if x.is_sign_positive() == y.is_sign_positive() {
124 x
125 } else {
126 -x
127 }
128 }
129 };
130}
131
132macro_rules! tests {
133 ($float_type:ty, $module:ident, $smallest_pos:expr, $largest_neg:expr, $next_before_one:expr, $sequential_large_numbers:expr) => {
134 #[cfg(test)]
135 mod tests {
136 use super::{copy_sign, NextAfter};
137
138 const POS_INFINITY: $float_type = core::$module::INFINITY;
139 const NEG_INFINITY: $float_type = core::$module::NEG_INFINITY;
140 const POS_ZERO: $float_type = 0.0;
141 const NEG_ZERO: $float_type = -0.0;
142
143 const SMALLEST_POS: $float_type = $smallest_pos;
145 const LARGEST_NEG: $float_type = $largest_neg;
146 const LARGEST_POS: $float_type = core::$module::MAX;
147 const SMALLEST_NEG: $float_type = core::$module::MIN;
148
149 const POS_ONE: $float_type = 1.0;
150 const NEG_ONE: $float_type = -1.0;
151 const NEXT_LARGER_THAN_ONE: $float_type = 1.0 + core::$module::EPSILON;
152 const NEXT_SMALLER_THAN_ONE: $float_type = $next_before_one;
153
154 const SEQUENTIAL_LARGE_NUMBERS: ($float_type, $float_type) = $sequential_large_numbers;
155
156 const NAN: $float_type = core::$module::NAN;
157
158 fn is_positive_zero(x: $float_type) -> bool {
159 x.to_bits() == POS_ZERO.to_bits()
160 }
161
162 fn is_negative_zero(x: $float_type) -> bool {
163 x.to_bits() == NEG_ZERO.to_bits()
164 }
165
166 #[test]
167 fn test_copy_sign() {
168 assert_eq!(copy_sign(POS_ONE, POS_ZERO), POS_ONE);
169 assert_eq!(copy_sign(NEG_ONE, POS_ZERO), POS_ONE);
170 assert_eq!(copy_sign(POS_ONE, NEG_ZERO), NEG_ONE);
171 assert_eq!(copy_sign(NEG_ONE, NEG_ZERO), NEG_ONE);
172 }
173
174 #[test]
175 fn verify_constants() {
176 assert_ne!(POS_ZERO.to_bits(), NEG_ZERO.to_bits());
177 assert!(SMALLEST_POS > POS_ZERO);
178 assert!(LARGEST_NEG < NEG_ZERO);
179 assert!(!SMALLEST_POS.is_normal());
180 assert!(!LARGEST_NEG.is_normal());
181 }
182
183 #[test]
184 fn next_larger_than_0() {
185 assert_eq!(POS_ZERO.next_after(POS_INFINITY), SMALLEST_POS);
186 assert_eq!(NEG_ZERO.next_after(POS_INFINITY), SMALLEST_POS);
187 }
188
189 #[test]
190 fn next_smaller_than_0() {
191 assert_eq!(POS_ZERO.next_after(NEG_INFINITY), LARGEST_NEG);
192 assert_eq!(NEG_ZERO.next_after(NEG_INFINITY), LARGEST_NEG);
193 }
194
195 #[test]
196 fn step_towards_zero() {
197 assert!(is_positive_zero(SMALLEST_POS.next_after(POS_ZERO)));
200 assert!(is_positive_zero(SMALLEST_POS.next_after(NEG_ZERO)));
201 assert!(is_positive_zero(SMALLEST_POS.next_after(NEG_INFINITY)));
202 assert!(is_negative_zero(LARGEST_NEG.next_after(NEG_ZERO)));
203 assert!(is_negative_zero(LARGEST_NEG.next_after(POS_ZERO)));
204 assert!(is_negative_zero(LARGEST_NEG.next_after(POS_INFINITY)));
205 }
206
207 #[test]
208 fn special_case_signed_zeros() {
209 assert!(is_negative_zero(POS_ZERO.next_after(NEG_ZERO)));
213 assert!(is_positive_zero(NEG_ZERO.next_after(POS_ZERO)));
214 }
215
216 #[test]
217 fn nextafter_around_one() {
218 assert_eq!(POS_ONE.next_after(POS_INFINITY), NEXT_LARGER_THAN_ONE);
219 assert_eq!(POS_ONE.next_after(NEG_INFINITY), NEXT_SMALLER_THAN_ONE);
220 assert_eq!(NEG_ONE.next_after(NEG_INFINITY), -NEXT_LARGER_THAN_ONE);
221 assert_eq!(NEG_ONE.next_after(POS_INFINITY), -NEXT_SMALLER_THAN_ONE);
222 }
223
224 #[test]
225 fn nextafter_for_big_positive_number() {
226 let (lo, hi) = SEQUENTIAL_LARGE_NUMBERS;
227 assert_eq!(lo.next_after(POS_INFINITY), hi);
228 assert_eq!(hi.next_after(NEG_INFINITY), lo);
229 assert_eq!(lo.next_after(hi), hi);
230 assert_eq!(hi.next_after(lo), lo);
231 }
232
233 #[test]
234 fn nextafter_for_small_negative_number() {
235 let (lo, hi) = SEQUENTIAL_LARGE_NUMBERS;
236 let (lo, hi) = (-lo, -hi);
237 assert_eq!(lo.next_after(NEG_INFINITY), hi);
238 assert_eq!(hi.next_after(POS_INFINITY), lo);
239 assert_eq!(lo.next_after(hi), hi);
240 assert_eq!(hi.next_after(lo), lo);
241 }
242
243 #[test]
244 fn step_to_largest_is_possible() {
245 let smaller = LARGEST_POS.next_after(NEG_INFINITY);
246 assert_eq!(smaller.next_after(POS_INFINITY), LARGEST_POS);
247 let smaller = SMALLEST_NEG.next_after(POS_INFINITY);
248 assert_eq!(smaller.next_after(NEG_INFINITY), SMALLEST_NEG);
249 }
250
251 #[test]
252 fn jump_to_infinity() {
253 assert_eq!(LARGEST_POS.next_after(POS_INFINITY), POS_INFINITY);
255 assert_eq!(SMALLEST_NEG.next_after(NEG_INFINITY), NEG_INFINITY);
256 }
257
258 #[test]
259 fn stays_at_infinity() {
260 assert_eq!(POS_INFINITY.next_after(NEG_INFINITY), POS_INFINITY);
262 assert_eq!(NEG_INFINITY.next_after(POS_INFINITY), NEG_INFINITY);
263 }
264
265 #[test]
266 fn returns_nan_for_any_nan_involved() {
267 assert!(NAN.next_after(POS_ONE).is_nan());
268 assert!(POS_ONE.next_after(NAN).is_nan());
269 assert!(NAN.next_after(NAN).is_nan());
270 }
271
272 #[test]
273 fn returns_identity_for_equal_dest() {
274 let values = [
275 POS_ZERO,
276 NEG_ZERO,
277 POS_ONE,
278 NEG_ONE,
279 SEQUENTIAL_LARGE_NUMBERS.0,
280 SEQUENTIAL_LARGE_NUMBERS.1,
281 POS_INFINITY,
282 NEG_INFINITY,
283 SMALLEST_POS,
284 LARGEST_NEG,
285 LARGEST_POS,
286 SMALLEST_NEG,
287 ];
288 for x in values.iter() {
289 assert_eq!(x.next_after(*x), *x);
290 }
291 }
292
293 #[test]
294 fn can_successfully_roundtrip() {
295 let values = [
296 POS_ONE,
297 NEG_ONE,
298 SEQUENTIAL_LARGE_NUMBERS.0,
299 SEQUENTIAL_LARGE_NUMBERS.1,
300 SMALLEST_POS,
301 LARGEST_NEG,
302 ];
303 for orig in values.to_vec() {
304 assert_eq!(orig.next_after(POS_INFINITY).next_after(NEG_INFINITY), orig);
305 assert_eq!(orig.next_after(NEG_INFINITY).next_after(POS_INFINITY), orig);
306
307 let upper = orig.next_after(POS_INFINITY);
308 let lower = orig.next_after(NEG_INFINITY);
309
310 assert_eq!(orig.next_after(upper).next_after(lower), orig);
311 assert_eq!(orig.next_after(lower).next_after(upper), orig);
312 }
313 }
314 }
315 };
316}
317
318mod f64 {
319 impl_next_after!(f64, f64, 5e-324);
320
321 tests!(
322 f64,
323 f64,
324 5e-324,
325 -5e-324,
326 0.999_999_999_999_999_9,
327 (16_237_485_966.000_004, 16_237_485_966.000_006)
328 );
329}
330
331mod f32 {
332 impl_next_after!(f32, f32, 1e-45);
333
334 tests!(
335 f32,
336 f32,
337 1e-45,
338 -1e-45,
339 0.999_999_94,
340 (1.230_000_1e34, 1.230_000_3e34)
341 );
342}