Skip to main content

nanvm_lib/vm/number/
to_integer_or_infinity.rs

1use crate::vm::Number;
2
3impl Number {
4    /// `ToIntegerOrInfinity` (<https://tc39.es/ecma262/#sec-tointegerorinfinity>)
5    /// of a number: `NaN` and either zero are `0`, an infinity is itself,
6    /// and everything else is truncated toward zero. The specification's
7    /// answer is a mathematical value, so a `-0` never comes out of it:
8    /// `-0.5` truncates to `0`, not `-0`, and the addition below is what
9    /// folds the sign — `-0.0 + 0.0` is `0.0` in IEEE 754.
10    pub fn to_integer_or_infinity(self) -> Number {
11        let n = f64::from(self);
12        if n.is_nan() {
13            return Number::from(0.0);
14        }
15        Number::from(n.trunc() + 0.0)
16    }
17}
18
19#[cfg(test)]
20mod tests {
21    use crate::vm::Number;
22
23    fn bits(v: f64) -> u64 {
24        f64::from(Number::from(v).to_integer_or_infinity()).to_bits()
25    }
26
27    #[test]
28    fn nan_and_zeros_are_zero() {
29        for v in [f64::NAN, 0.0, -0.0] {
30            assert_eq!(bits(v), 0.0f64.to_bits());
31        }
32    }
33
34    #[test]
35    fn infinities_are_themselves() {
36        assert_eq!(bits(f64::INFINITY), f64::INFINITY.to_bits());
37        assert_eq!(bits(f64::NEG_INFINITY), f64::NEG_INFINITY.to_bits());
38    }
39
40    /// Truncation toward zero, and no `-0` for a negative fraction.
41    #[test]
42    fn truncates_toward_zero() {
43        assert_eq!(bits(1.7), 1.0f64.to_bits());
44        assert_eq!(bits(-1.7), (-1.0f64).to_bits());
45        assert_eq!(bits(-0.5), 0.0f64.to_bits());
46        assert_eq!(bits(4_294_967_296.5), 4_294_967_296.0f64.to_bits());
47    }
48}