Add bit twiddling
This commit is contained in:
parent
bd68de89b5
commit
6973fd716b
2 changed files with 19 additions and 15 deletions
|
|
@ -857,7 +857,7 @@ impl f32 {
|
|||
let mut left = self.to_bits() as i32;
|
||||
let mut right = other.to_bits() as i32;
|
||||
|
||||
// In case of negatives, flip all the bits except the sign
|
||||
// In case of negatives, flip all the bits expect the sign
|
||||
// to achieve a similar layout as two's complement integers
|
||||
//
|
||||
// Why does this work? IEEE 754 floats consist of three fields:
|
||||
|
|
@ -872,13 +872,15 @@ impl f32 {
|
|||
// To easily compare the floats as signed integers, we need to
|
||||
// flip the exponent and mantissa bits in case of negative numbers.
|
||||
// We effectively convert the numbers to "two's complement" form.
|
||||
if left < 0 {
|
||||
// i32::MAX corresponds the bit pattern of "all ones except for the sign bit"
|
||||
left ^= i32::MAX
|
||||
};
|
||||
if right < 0 {
|
||||
right ^= i32::MAX
|
||||
};
|
||||
//
|
||||
// To do the flipping, we construct a mask and XOR against it.
|
||||
// We branchlessly calculate an "all-ones expect for the sign bit"
|
||||
// mask from negative-signed values: right shifting sign-extends
|
||||
// the integer, so we "fill" the mask with sign bits, and then
|
||||
// convert to unsigned to push one more zero bit.
|
||||
// On positive values, the mask is all zeros, so it's a no-op.
|
||||
left ^= (((left >> 31) as u32) >> 1) as i32;
|
||||
right ^= (((right >> 31) as u32) >> 1) as i32;
|
||||
|
||||
left.cmp(&right)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -886,13 +886,15 @@ impl f64 {
|
|||
// To easily compare the floats as signed integers, we need to
|
||||
// flip the exponent and mantissa bits in case of negative numbers.
|
||||
// We effectively convert the numbers to "two's complement" form.
|
||||
if left < 0 {
|
||||
// i64::MAX corresponds the bit pattern of "all ones expect for the sign bit"
|
||||
left ^= i64::MAX
|
||||
};
|
||||
if right < 0 {
|
||||
right ^= i64::MAX
|
||||
};
|
||||
//
|
||||
// To do the flipping, we construct a mask and XOR against it.
|
||||
// We branchlessly calculate an "all-ones expect for the sign bit"
|
||||
// mask from negative-signed values: right shifting sign-extends
|
||||
// the integer, so we "fill" the mask with sign bits, and then
|
||||
// convert to unsigned to push one more zero bit.
|
||||
// On positive values, the mask is all zeros, so it's a no-op.
|
||||
left ^= (((left >> 63) as u64) >> 1) as i64;
|
||||
right ^= (((right >> 63) as u64) >> 1) as i64;
|
||||
|
||||
left.cmp(&right)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue