Skip to content

Commit

Permalink
Merge pull request #347 from tcoratger/overflowing_shr
Browse files Browse the repository at this point in the history
fix: modify `overflowing_shr` to fix overflow check
  • Loading branch information
prestwich authored Feb 27, 2024
2 parents 4f2b31d + 0e515e0 commit f81baa3
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Overflow check in `overflowing_shr` implementation ([#347])

[#347]: https://github.com/recmo/uint/pulls/347

## [1.11.1] - 2023-11-18

### Fixed
Expand Down
120 changes: 115 additions & 5 deletions src/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,7 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
}

// Check for overflow
let mut overflow = false;
for i in 0..limbs {
overflow |= self.limbs[i] != 0;
}
overflow |= self.limbs[limbs] >> bits != 0;
let overflow = self.limbs[LIMBS - limbs - 1] >> (bits - 1) & 1 != 0;

// Shift
for i in 0..(LIMBS - limbs - 1) {
Expand Down Expand Up @@ -855,4 +851,118 @@ mod tests {
});
});
}

#[test]
fn test_overflowing_shr() {
// Test: Single limb right shift from 40u64 by 1 bit.
// Expects resulting integer: 20 with no fractional part.
assert_eq!(
Uint::<64, 1>::from_limbs([40u64]).overflowing_shr(1),
(Uint::<64, 1>::from(20), false)
);

// Test: Single limb right shift from 41u64 by 1 bit.
// Expects resulting integer: 20 with a detected fractional part.
assert_eq!(
Uint::<64, 1>::from_limbs([41u64]).overflowing_shr(1),
(Uint::<64, 1>::from(20), true)
);

// Test: Two limbs right shift from 0x0010_0000_0000_0000 and 0 by 1 bit.
// Expects resulting limbs: [0x0080_0000_0000_000, 0] with no fractional part.
assert_eq!(
Uint::<65, 2>::from_limbs([0x0010_0000_0000_0000, 0]).overflowing_shr(1),
(Uint::<65, 2>::from_limbs([0x0080_0000_0000_000, 0]), false)
);

// Test: Shift beyond single limb capacity with MAX value.
// Expects the highest possible value in 256-bit representation with a detected
// fractional part.
assert_eq!(
Uint::<256, 4>::MAX.overflowing_shr(65),
(
Uint::<256, 4>::from_str_radix(
"7fffffffffffffffffffffffffffffffffffffffffffffff",
16
)
.unwrap(),
true
)
);
// Test: Large 4096-bit integer right shift by 34 bits.
// Expects a specific value with no fractional part.
assert_eq!(
Uint::<4096, 64>::from_str_radix("3ffffffffffffffffffffffffffffc00000000", 16,)
.unwrap()
.overflowing_shr(34),
(
Uint::<4096, 64>::from_str_radix("fffffffffffffffffffffffffffff", 16).unwrap(),
false
)
);
// Test: Extremely large 4096-bit integer right shift by 100 bits.
// Expects a specific value with no fractional part.
assert_eq!(
Uint::<4096, 64>::from_str_radix(
"fffffffffffffffffffffffffffff0000000000000000000000000",
16,
)
.unwrap()
.overflowing_shr(100),
(
Uint::<4096, 64>::from_str_radix("fffffffffffffffffffffffffffff", 16).unwrap(),
false
)
);
// Test: Complex 4096-bit integer right shift by 1 bit.
// Expects a specific value with no fractional part.
assert_eq!(
Uint::<4096, 64>::from_str_radix(
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0bdbfe",
16,
)
.unwrap()
.overflowing_shr(1),
(
Uint::<4096, 64>::from_str_radix(
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff85edff",
16
)
.unwrap(),
false
)
);
// Test: Large 4096-bit integer right shift by 1000 bits.
// Expects a specific value with no fractional part.
assert_eq!(
Uint::<4096, 64>::from_str_radix(
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
16,
)
.unwrap()
.overflowing_shr(1000),
(
Uint::<4096, 64>::from_str_radix(
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
16
)
.unwrap(),
false
)
);
// Test: MAX 4096-bit integer right shift by 34 bits.
// Expects a specific value with a detected fractional part.
assert_eq!(
Uint::<4096, 64>::MAX
.overflowing_shr(34),
(
Uint::<4096, 64>::from_str_radix(
"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
16
)
.unwrap(),
true
)
);
}
}

0 comments on commit f81baa3

Please sign in to comment.