mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 13:04:42 +00:00 
			
		
		
		
	 92b1e8454d
			
		
	
	
		92b1e8454d
		
	
	
	
	
		
			
			The repo will soon have `libm` as a top-level crate, so make it clear that this is only the test crate for `compiler-builtins`.
		
			
				
	
	
		
			135 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use compiler_builtins::int::{HInt, MinInt, i256, u256};
 | |
| 
 | |
| const LOHI_SPLIT: u128 = 0xaaaaaaaaaaaaaaaaffffffffffffffff;
 | |
| 
 | |
| /// Print a `u256` as hex since we can't add format implementations
 | |
| fn hexu(v: u256) -> String {
 | |
|     format!(
 | |
|         "0x{:016x}{:016x}{:016x}{:016x}",
 | |
|         v.0[3], v.0[2], v.0[1], v.0[0]
 | |
|     )
 | |
| }
 | |
| 
 | |
| #[test]
 | |
| fn widen_u128() {
 | |
|     assert_eq!(u128::MAX.widen(), u256([u64::MAX, u64::MAX, 0, 0]));
 | |
|     assert_eq!(
 | |
|         LOHI_SPLIT.widen(),
 | |
|         u256([u64::MAX, 0xaaaaaaaaaaaaaaaa, 0, 0])
 | |
|     );
 | |
| }
 | |
| 
 | |
| #[test]
 | |
| fn widen_i128() {
 | |
|     assert_eq!((-1i128).widen(), u256::MAX.signed());
 | |
|     assert_eq!(
 | |
|         (LOHI_SPLIT as i128).widen(),
 | |
|         i256([u64::MAX, 0xaaaaaaaaaaaaaaaa, u64::MAX, u64::MAX])
 | |
|     );
 | |
|     assert_eq!((-1i128).zero_widen().unsigned(), (u128::MAX).widen());
 | |
| }
 | |
| 
 | |
| #[test]
 | |
| fn widen_mul_u128() {
 | |
|     let tests = [
 | |
|         (u128::MAX / 2, 2_u128, u256([u64::MAX - 1, u64::MAX, 0, 0])),
 | |
|         (u128::MAX, 2_u128, u256([u64::MAX - 1, u64::MAX, 1, 0])),
 | |
|         (u128::MAX, u128::MAX, u256([1, 0, u64::MAX - 1, u64::MAX])),
 | |
|         (u128::MIN, u128::MIN, u256::ZERO),
 | |
|         (1234, 0, u256::ZERO),
 | |
|         (0, 1234, u256::ZERO),
 | |
|     ];
 | |
| 
 | |
|     let mut errors = Vec::new();
 | |
|     for (i, (a, b, exp)) in tests.iter().copied().enumerate() {
 | |
|         let res = a.widen_mul(b);
 | |
|         let res_z = a.zero_widen_mul(b);
 | |
|         assert_eq!(res, res_z);
 | |
|         if res != exp {
 | |
|             errors.push((i, a, b, exp, res));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i, a, b, exp, res) in &errors {
 | |
|         eprintln!(
 | |
|             "FAILURE ({i}): {a:#034x} * {b:#034x} = {} got {}",
 | |
|             hexu(*exp),
 | |
|             hexu(*res)
 | |
|         );
 | |
|     }
 | |
|     assert!(errors.is_empty());
 | |
| }
 | |
| 
 | |
| #[test]
 | |
| fn not_u128() {
 | |
|     assert_eq!(!u256::ZERO, u256::MAX);
 | |
| }
 | |
| 
 | |
| #[test]
 | |
| fn shr_u128() {
 | |
|     let only_low = [
 | |
|         1,
 | |
|         u16::MAX.into(),
 | |
|         u32::MAX.into(),
 | |
|         u64::MAX.into(),
 | |
|         u128::MAX,
 | |
|     ];
 | |
| 
 | |
|     let mut errors = Vec::new();
 | |
| 
 | |
|     for a in only_low {
 | |
|         for perturb in 0..10 {
 | |
|             let a = a.saturating_add(perturb);
 | |
|             for shift in 0..128 {
 | |
|                 let res = a.widen() >> shift;
 | |
|                 let expected = (a >> shift).widen();
 | |
|                 if res != expected {
 | |
|                     errors.push((a.widen(), shift, res, expected));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     let check = [
 | |
|         (
 | |
|             u256::MAX,
 | |
|             1,
 | |
|             u256([u64::MAX, u64::MAX, u64::MAX, u64::MAX >> 1]),
 | |
|         ),
 | |
|         (
 | |
|             u256::MAX,
 | |
|             5,
 | |
|             u256([u64::MAX, u64::MAX, u64::MAX, u64::MAX >> 5]),
 | |
|         ),
 | |
|         (u256::MAX, 63, u256([u64::MAX, u64::MAX, u64::MAX, 1])),
 | |
|         (u256::MAX, 64, u256([u64::MAX, u64::MAX, u64::MAX, 0])),
 | |
|         (u256::MAX, 65, u256([u64::MAX, u64::MAX, u64::MAX >> 1, 0])),
 | |
|         (u256::MAX, 127, u256([u64::MAX, u64::MAX, 1, 0])),
 | |
|         (u256::MAX, 128, u256([u64::MAX, u64::MAX, 0, 0])),
 | |
|         (u256::MAX, 129, u256([u64::MAX, u64::MAX >> 1, 0, 0])),
 | |
|         (u256::MAX, 191, u256([u64::MAX, 1, 0, 0])),
 | |
|         (u256::MAX, 192, u256([u64::MAX, 0, 0, 0])),
 | |
|         (u256::MAX, 193, u256([u64::MAX >> 1, 0, 0, 0])),
 | |
|         (u256::MAX, 191, u256([u64::MAX, 1, 0, 0])),
 | |
|         (u256::MAX, 254, u256([0b11, 0, 0, 0])),
 | |
|         (u256::MAX, 255, u256([1, 0, 0, 0])),
 | |
|     ];
 | |
| 
 | |
|     for (input, shift, expected) in check {
 | |
|         let res = input >> shift;
 | |
|         if res != expected {
 | |
|             errors.push((input, shift, res, expected));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (a, b, res, expected) in &errors {
 | |
|         eprintln!(
 | |
|             "FAILURE: {} >> {b} = {} got {}",
 | |
|             hexu(*a),
 | |
|             hexu(*expected),
 | |
|             hexu(*res),
 | |
|         );
 | |
|     }
 | |
|     assert!(errors.is_empty());
 | |
| }
 |