mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-19 02:57:33 +00:00

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());
|
|
}
|