Skip to content

Commit

Permalink
fix overflow bug where keys are close to overflow (fixes #16)
Browse files Browse the repository at this point in the history
  • Loading branch information
droundy committed Aug 10, 2022
1 parent e4a52c3 commit 70f49dd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 9 deletions.
15 changes: 12 additions & 3 deletions src/setu32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1717,7 +1717,10 @@ fn p_poverty(k: u32, idx: usize, n: usize) -> usize {
fn p_insert(k: u32, a: &mut [u32], offset: u32) -> usize {
let n = a.len();
for pov in 0..n {
let ii = ((k + pov as u32) % n as u32) as usize;
// The cast to u64 below avoids overflow issues when `k` is close
// to `u32::MAX`. It should cost nothing on 64-bit machines, and
// shouldn't be much worse than an extra `%` on 32-bit machines.
let ii = ((k as u64 + pov as u64) % n as u64) as usize;
let ki = a[ii] >> offset;
let pov_ki = p_poverty(ki, ii, n);
if a[ii] == 0 || ki == k {
Expand Down Expand Up @@ -1814,7 +1817,10 @@ impl LookedUp {
fn p_lookfor(k: u32, a: &[u32], offset: u32) -> LookedUp {
let n = a.len();
for pov in 0..n {
let ii = ((k + pov as u32) % n as u32) as usize;
// The cast to u64 below avoids overflow issues when `k` is close
// to `u32::MAX`. It should cost nothing on 64-bit machines, and
// shouldn't be much worse than an extra `%` on 32-bit machines.
let ii = ((k as u64 + pov as u64) % n as u64) as usize;
// println!("looking in spot ii = {} with pov={}", ii, pov);
if a[ii] == 0 {
// println!("got empty spot at {} for key {}", ii, k);
Expand Down Expand Up @@ -1843,7 +1849,10 @@ fn test_lookfor() {
fn p_remove(k: u32, a: &mut [u32], offset: u32) -> bool {
let n = a.len();
for i in 0..n {
let ii = ((k + i as u32) % n as u32) as usize;
// The cast to u64 below avoids overflow issues when `k` is close
// to `u32::MAX`. It should cost nothing on 64-bit machines, and
// shouldn't be much worse than an extra `%` on 32-bit machines.
let ii = ((k as u64 + i as u64) % n as u64) as usize;
// println!(" looking to remove at distance {} slot {}", i, ii);
if a[ii] == 0 {
return false;
Expand Down
6 changes: 3 additions & 3 deletions src/setu32b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,7 @@ fn p_insert_better(k: u32, a: &mut [(u32,u32)]) -> Inserted {
let n = a.len();
let poverty_limit = n;
for pov in 0..poverty_limit {
let ii = ((k + pov as u32) % n as u32) as usize;
let ii = ((k as u64 + pov as u64) % n as u64) as usize;
let ki = a[ii].0;
let pov_ki = p_poverty(ki, ii, n);
if a[ii] == (0,0) {
Expand Down Expand Up @@ -1261,7 +1261,7 @@ impl LookedUp {
fn p_lookfor(k: u32, a: &[(u32,u32)]) -> LookedUp {
let n = a.len();
for pov in 0..n {
let ii = ((k + pov as u32) % n as u32) as usize;
let ii = ((k as u64 + pov as u64) % n as u64) as usize;
if a[ii] == (0,0) {
// println!("got empty spot at {} for key {}", ii, k);
return LookedUp::EmptySpot(ii);
Expand Down Expand Up @@ -1289,7 +1289,7 @@ fn test_lookfor() {
fn p_remove(k: u32, a: &mut [(u32,u32)]) -> bool {
let n = a.len();
for i in 0..n {
let ii = ((k + i as u32) % n as u32) as usize;
let ii = ((k as u64 + i as u64) % n as u64) as usize;
// println!(" looking to remove at distance {} slot {}", i, ii);
if a[ii] == (0,0) {
return false;
Expand Down
6 changes: 3 additions & 3 deletions src/setu64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1723,7 +1723,7 @@ fn p_poverty(k: u64, idx: usize, n: usize) -> usize {
fn p_insert(k: u64, a: &mut [u64], offset: u64) -> usize {
let n = a.len();
for pov in 0..n {
let ii = ((k + pov as u64) % n as u64) as usize;
let ii = (((k % n as u64) + pov as u64) % n as u64) as usize;
let ki = a[ii] >> offset;
let pov_ki = p_poverty(ki, ii, n);
if a[ii] == 0 || ki == k {
Expand Down Expand Up @@ -1820,7 +1820,7 @@ impl LookedUp {
fn p_lookfor(k: u64, a: &[u64], offset: u64) -> LookedUp {
let n = a.len();
for pov in 0..n {
let ii = ((k + pov as u64) % n as u64) as usize;
let ii = (((k % n as u64) + pov as u64) % n as u64) as usize;
// println!("looking in spot ii = {} with pov={}", ii, pov);
if a[ii] == 0 {
// println!("got empty spot at {} for key {}", ii, k);
Expand Down Expand Up @@ -1849,7 +1849,7 @@ fn test_lookfor() {
fn p_remove(k: u64, a: &mut [u64], offset: u64) -> bool {
let n = a.len();
for i in 0..n {
let ii = ((k + i as u64) % n as u64) as usize;
let ii = (((k % n as u64) + i as u64) % n as u64) as usize;
// println!(" looking to remove at distance {} slot {}", i, ii);
if a[ii] == 0 {
return false;
Expand Down
20 changes: 20 additions & 0 deletions tests/add-with-overflow-issue-16.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use tinyset::Set64;

#[test]
fn issue_16() {
let mut a: Set64<u64> = Set64::new();
let mut b: Set64<u64> = Set64::new();
a.insert(u64::MAX);
a.insert(8589934592);
a.insert(8589934593);
a.insert(17179869184);
a.insert(17179869185);
a.insert(12884901889);
b.insert(17179869187);
b.insert(17179869188);
b.insert(12884901889);
b.insert(12884901890);
b.insert(12884901891);
b.insert(12884901892);
let _c = &a - &b;
}

0 comments on commit 70f49dd

Please sign in to comment.