1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
extern crate libc;
extern crate num_traits;

mod f128_derive;
mod f128_t;
pub mod ffi;

pub use f128_derive::*;
pub use f128_t::*;

#[cfg(test)]
mod tests {

    use super::*;
    use num_traits::*;
    use std::num::FpCategory;

    #[test]
    fn test_minus() {
        let a = f128::from_f64(-4.).unwrap();
        assert_eq!(a.is_finite(), true);
        assert_eq!(a.is_infinite(), false);
        assert_eq!(a.is_sign_negative(), true);
        assert_eq!(a.is_sign_positive(), false);
        assert_eq!(a.signum(), -f128::ONE);

        let a = f128::from_f64(4.).unwrap();
        assert_eq!(a.is_finite(), true);
        assert_eq!(a.is_infinite(), false);
        assert_eq!(a.is_sign_negative(), false);
        assert_eq!(a.is_sign_positive(), true);
        assert_eq!(a.signum(), f128::ONE);
    }

    #[test]
    fn test_constants() {
        let pi = f128::parse("3.1415926535897932384626433832795028841971693993751058").unwrap();
        let e = f128::parse("2.7182818284590452353602874713526624977572").unwrap();
        let one = f128::parse("1.0").unwrap();
        let two = f128::parse("2.0").unwrap();

        // .0 because using actual float comparison won't work, and we're concerned about the bits
        assert!(pi.bitwise_eq(f128::PI));
        assert!(e.bitwise_eq(f128::E));
        assert!(one.bitwise_eq(f128::ONE));
        assert!(two.bitwise_eq(f128::TWO));

        assert!(f128::NAN.is_nan());
        assert!(!f128::NAN.is_finite());
        assert!(!f128::NAN.is_infinite());

        assert!(f128::INFINITY.is_infinite());
        assert!(!f128::INFINITY.is_finite());

        assert!(f128::NEG_INFINITY.is_infinite());
        assert!(!f128::NEG_INFINITY.is_finite());
    }

    #[test]
    fn test_classify() {
        let pi = f128::PI;
        let one = f128::ONE;
        let half = f128::parse("0.5").unwrap();
        let zero = f128::from_u8(0).unwrap();
        let min = f128::MIN_POSITIVE;

        assert_eq!(half.classify(), FpCategory::Normal);
        assert_eq!(one.classify(), FpCategory::Normal);
        assert_eq!(pi.classify(), FpCategory::Normal);
        assert_eq!(min.classify(), FpCategory::Subnormal);
        assert_eq!(f128::INFINITY.classify(), FpCategory::Infinite);
        assert_eq!(f128::NEG_INFINITY.classify(), FpCategory::Infinite);
        assert_eq!(f128::NAN.classify(), FpCategory::Nan);
    }

    #[test]
    fn test_f128_to_primitive() {
        let a = f128::parse("1003.0").unwrap();

        assert_eq!(1003i64, a.to_i64().unwrap());
        assert_eq!(1003u64, a.to_u64().unwrap());
        assert_eq!(1003i128, a.to_i128().unwrap());
        assert_eq!(1003u128, a.to_u128().unwrap());
    }

    #[test]
    fn test_conversions() {
        assert!(f128::from_u128(123456789)
            .unwrap()
            .bitwise_eq(f128::parse("123456789.0").unwrap()));
        assert!(f128::from_i128(5i128)
            .unwrap()
            .bitwise_eq(f128::parse("5.0").unwrap()));
        assert!(f128::from_i64(-64)
            .unwrap()
            .bitwise_eq(f128::parse("-64.0").unwrap()));
        assert!(f128::from_u64(10_000_000)
            .unwrap()
            .bitwise_eq(f128::parse("10000000.0").unwrap()));
        assert!(f128::from_i32(5i32)
            .unwrap()
            .bitwise_eq(f128::parse("5.0").unwrap()));
        assert!(f128::from_u32(0)
            .unwrap()
            .bitwise_eq(f128::parse("0.0").unwrap()));
        assert!(f128::from_u16(32000)
            .unwrap()
            .bitwise_eq(f128::parse("32000.0").unwrap()));
        assert!(f128::from_i16(-30000)
            .unwrap()
            .bitwise_eq(f128::parse("-30000.0").unwrap()));
        assert!(f128::from_i8(-100)
            .unwrap()
            .bitwise_eq(f128::parse("-100.0").unwrap()));
        assert!(f128::from_u8(255)
            .unwrap()
            .bitwise_eq(f128::parse("255.0").unwrap()));
    }

    #[test]
    fn test_to_string() {
        assert_eq!(f128::infinity().to_string().as_str(), "inf");
        assert_eq!(f128::neg_infinity().to_string().as_str(), "-inf");
        assert_eq!(f128::nan().to_string().as_str(), "nan");
        assert_eq!(f128::neg_zero().to_string().as_str(), "-0");
        assert_eq!(f128::zero().to_string().as_str(), "0");
    }

    macro_rules! assert_approx_eq {
        ($a:expr, $b:expr, $epsilon:expr) => {
            assert!(($a - $b).abs() < $epsilon)
        };
    }

    const EPSILON: f128 = f128::EPSILON;

    #[test]
    fn test_casts_to_f128() {
        let thirty = f128::parse("30").unwrap();
        let nthirty = f128::parse("-30").unwrap();
        let oneandhalf = f128::parse("1.5").unwrap();
        assert_approx_eq!(oneandhalf, f128::from_f64(1.5).unwrap(), EPSILON);
        assert_approx_eq!(oneandhalf, f128::from_f32(1.5).unwrap(), EPSILON);
        assert_approx_eq!(thirty, f128::from_u64(30).unwrap(), EPSILON);
        assert_approx_eq!(nthirty, f128::from_i64(-30).unwrap(), EPSILON);
        assert_approx_eq!(thirty, f128::from_u32(30).unwrap(), EPSILON);
        assert_approx_eq!(nthirty, f128::from_i32(-30).unwrap(), EPSILON);
        assert_approx_eq!(thirty, f128::from_u16(30).unwrap(), EPSILON);
        assert_approx_eq!(nthirty, f128::from_i16(-30).unwrap(), EPSILON);
        assert_approx_eq!(thirty, f128::from_u8(30).unwrap(), EPSILON);
        assert_approx_eq!(nthirty, f128::from_i8(-30).unwrap(), EPSILON);
    }

    #[test]
    fn test_casts_from_f128() {
        use std::{f32, f64};
        let oneandhalf = f128::parse("1.6").unwrap();
        assert_approx_eq!(1.6f64, oneandhalf.to_f64().unwrap(), f64::EPSILON);
        assert_approx_eq!(1.6f32, oneandhalf.to_f32().unwrap(), f32::EPSILON);
        assert_eq!(1i32, oneandhalf.to_i32().unwrap());
        assert_eq!(1u32, oneandhalf.to_u32().unwrap());
        assert_eq!(1i64, oneandhalf.to_i64().unwrap());
        assert_eq!(1u64, oneandhalf.to_u64().unwrap());
        assert_eq!(1i16, oneandhalf.to_i16().unwrap());
        assert_eq!(1u16, oneandhalf.to_u16().unwrap());
        assert_eq!(1i8, oneandhalf.to_i8().unwrap());
        assert_eq!(1u8, oneandhalf.to_u8().unwrap());
    }

    #[test]
    fn test_cmp() {
        let a = f128::parse("1.5").unwrap();
        let c = f128::parse("1.5").unwrap();
        let b = f128::parse("3.0").unwrap();
        assert!(a == c);
        assert!(a < b);
        assert!(a <= b);
        assert!(b > a);
        assert!(b >= a);
        assert!(a != b);
    }
}