// Copyright © 2024 Mikhail Hogrefe // // This file is part of Malachite. // // Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU // Lesser General Public License (LGPL) as published by the Free Software Foundation; either version // 3 of the License, or (at your option) any later version. See . use malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::{ primitive_float_gen_var_12, unsigned_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_30, unsigned_signed_pair_gen_var_1, unsigned_signed_pair_gen_var_2, }; use std::cmp::Ordering::*; use std::panic::catch_unwind; #[test] pub fn test_integer_mantissa_and_exponent() { fn test_unsigned(x: T, mantissa: T, exponent: u64) { assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!(x.integer_mantissa_and_exponent(), (mantissa, exponent)); } test_unsigned::(1, 1, 0); test_unsigned::(2, 1, 1); test_unsigned::(3, 3, 0); test_unsigned::(100, 25, 2); test_unsigned::(65536, 1, 16); fn test_primitive_float(x: T, mantissa: u64, exponent: i64) { assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!(x.integer_mantissa_and_exponent(), (mantissa, exponent)); } test_primitive_float::(1.0, 1, 0); test_primitive_float::(core::f32::consts::PI, 13176795, -22); test_primitive_float::(0.1, 13421773, -27); test_primitive_float::(10.0, 5, 1); test_primitive_float::(f32::MIN_POSITIVE_SUBNORMAL, 1, -149); test_primitive_float::(f32::MAX_SUBNORMAL, 0x7fffff, -149); test_primitive_float::(f32::MIN_POSITIVE_NORMAL, 1, -126); test_primitive_float::(f32::MAX_FINITE, 0xffffff, 104); test_primitive_float::(1.0, 1, 0); test_primitive_float::(core::f64::consts::PI, 884279719003555, -48); test_primitive_float::(0.1, 3602879701896397, -55); test_primitive_float::(10.0, 5, 1); test_primitive_float::(f64::MIN_POSITIVE_SUBNORMAL, 1, -1074); test_primitive_float::(f64::MAX_SUBNORMAL, 0xfffffffffffff, -1074); test_primitive_float::(f64::MIN_POSITIVE_NORMAL, 1, -1022); test_primitive_float::(f64::MAX_FINITE, 0x1fffffffffffff, 971); } fn integer_mantissa_and_exponent_unsigned_fail_helper() { assert_panic!(T::ZERO.integer_mantissa_and_exponent()); } fn integer_mantissa_and_exponent_primitive_float_fail_helper() { assert_panic!(T::NAN.integer_mantissa_and_exponent()); assert_panic!(T::INFINITY.integer_mantissa_and_exponent()); assert_panic!(T::NEGATIVE_INFINITY.integer_mantissa_and_exponent()); assert_panic!(T::ZERO.integer_mantissa_and_exponent()); assert_panic!(T::NEGATIVE_ZERO.integer_mantissa_and_exponent()); } #[test] pub fn integer_mantissa_and_exponent_fail() { apply_fn_to_unsigneds!(integer_mantissa_and_exponent_unsigned_fail_helper); apply_fn_to_primitive_floats!(integer_mantissa_and_exponent_primitive_float_fail_helper); } #[test] pub fn test_from_integer_mantissa_and_exponent() { fn test_unsigned(mantissa: T, exponent: u64, x: Option) { assert_eq!(T::from_integer_mantissa_and_exponent(mantissa, exponent), x); } test_unsigned::(0, 0, Some(0)); test_unsigned::(1, 0, Some(1)); test_unsigned::(1, 1, Some(2)); test_unsigned::(3, 0, Some(3)); test_unsigned::(25, 2, Some(100)); test_unsigned::(1, 16, Some(65536)); test_unsigned::(1, 100, None); fn test_primitive_float(mantissa: u64, exponent: i64, x: Option) { assert_eq!( T::from_integer_mantissa_and_exponent(mantissa, exponent).map(NiceFloat), x.map(NiceFloat) ); } test_primitive_float::(0, 5, Some(0.0)); test_primitive_float::(1, 0, Some(1.0)); test_primitive_float::(4, -2, Some(1.0)); test_primitive_float::(13176795, -22, Some(core::f32::consts::PI)); test_primitive_float::(13421773, -27, Some(0.1)); test_primitive_float::(5, 1, Some(10.0)); test_primitive_float::(1, -149, Some(f32::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(4, -151, Some(f32::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(0x7fffff, -149, Some(f32::MAX_SUBNORMAL)); test_primitive_float::(1, -126, Some(f32::MIN_POSITIVE_NORMAL)); test_primitive_float::(0xffffff, 104, Some(f32::MAX_FINITE)); test_primitive_float::(1, 127, Some(1.7014118e38)); test_primitive_float::(5, 10000, None); test_primitive_float::(5, -10000, None); test_primitive_float::(u64::MAX, -32, None); // precision too high test_primitive_float::(3, -150, None); // precision too high test_primitive_float::(1, 128, None); // precision too high test_primitive_float::(0, 5, Some(0.0)); test_primitive_float::(1, 0, Some(1.0)); test_primitive_float::(4, -2, Some(1.0)); test_primitive_float::(884279719003555, -48, Some(core::f64::consts::PI)); test_primitive_float::(3602879701896397, -55, Some(0.1)); test_primitive_float::(5, 1, Some(10.0)); test_primitive_float::(1, -1074, Some(f64::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(4, -1076, Some(f64::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(0xfffffffffffff, -1074, Some(f64::MAX_SUBNORMAL)); test_primitive_float::(1, -1022, Some(f64::MIN_POSITIVE_NORMAL)); test_primitive_float::(0x1fffffffffffff, 971, Some(f64::MAX_FINITE)); test_primitive_float::(1, 1023, Some(8.98846567431158e307)); test_primitive_float::(5, 10000, None); test_primitive_float::(5, -10000, None); test_primitive_float::(u64::MAX, -64, None); // precision too high test_primitive_float::(3, -1075, None); // precision too high test_primitive_float::(1, 1024, None); // precision too high } fn integer_mantissa_and_exponent_properties_helper_unsigned() { unsigned_gen_var_1::().test_properties(|x| { let (mantissa, exponent) = x.integer_mantissa_and_exponent(); assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!( T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap(), x ); assert!(exponent < T::WIDTH); assert!(mantissa.odd()); }); } fn integer_mantissa_and_exponent_properties_helper_primitive_float() { primitive_float_gen_var_12::().test_properties(|x| { let (mantissa, exponent) = x.integer_mantissa_and_exponent(); assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!( NiceFloat(T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap()), NiceFloat(x.abs()) ); assert!(exponent >= T::MIN_EXPONENT); assert!(exponent <= T::MAX_EXPONENT); assert!(mantissa.significant_bits() <= T::MANTISSA_WIDTH + 1); assert!(mantissa.odd()); }); } #[test] fn integer_mantissa_and_exponent_properties() { apply_fn_to_unsigneds!(integer_mantissa_and_exponent_properties_helper_unsigned); apply_fn_to_primitive_floats!(integer_mantissa_and_exponent_properties_helper_primitive_float); } fn from_integer_mantissa_and_exponent_properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(mantissa, exponent)| { T::from_integer_mantissa_and_exponent(mantissa, exponent); }); unsigned_pair_gen_var_30::().test_properties(|(mantissa, exponent)| { let f = T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap(); if mantissa.odd() { assert_eq!(f.integer_mantissa_and_exponent(), (mantissa, exponent)); } }); } fn from_integer_mantissa_and_exponent_properties_helper_primitive_float() { unsigned_signed_pair_gen_var_1().test_properties(|(mantissa, exponent)| { T::from_integer_mantissa_and_exponent(mantissa, exponent); }); unsigned_signed_pair_gen_var_2::().test_properties(|(mantissa, exponent)| { let f = T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap(); assert!(!f.is_nan()); assert_eq!(f.sign(), Greater); if !f.is_nan() && mantissa.odd() { assert_eq!(f.integer_mantissa_and_exponent(), (mantissa, exponent)); } }); } #[test] fn from_integer_mantissa_and_exponent_properties() { apply_fn_to_unsigneds!(from_integer_mantissa_and_exponent_properties_helper_unsigned); apply_fn_to_primitive_floats!( from_integer_mantissa_and_exponent_properties_helper_primitive_float ); }