From a0c4f21d55ad370c494e39519ce47129e030b9b5 Mon Sep 17 00:00:00 2001 From: metab0t Date: Sat, 4 Jun 2022 18:02:32 +0800 Subject: [PATCH 1/3] Fix union!(s::BitSet, r::AbstractUnitRange{<:Integer}) when two ranges do not overlap. Resizing of BitSet should be filled with 0 by default. --- base/bitset.jl | 4 ++-- test/bitset.jl | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/base/bitset.jl b/base/bitset.jl index 0abd9d4b782d2..b4da9f1f7f022 100644 --- a/base/bitset.jl +++ b/base/bitset.jl @@ -137,7 +137,7 @@ function union!(s::BitSet, r::AbstractUnitRange{<:Integer}) # grow s.bits as necessary if diffb >= len - _growend!(s.bits, diffb - len + 1) + _growend0!(s.bits, diffb - len + 1) # we set only some values to CHK0, those which will not be # fully overwritten (i.e. only or'ed with `|`) s.bits[end] = CHK0 # end == diffb + 1 @@ -146,7 +146,7 @@ function union!(s::BitSet, r::AbstractUnitRange{<:Integer}) end end if diffa < 0 - _growbeg!(s.bits, -diffa) + _growbeg0!(s.bits, -diffa) s.bits[1] = CHK0 if diffb < 0 s.bits[diffb - diffa + 1] = CHK0 diff --git a/test/bitset.jl b/test/bitset.jl index 1919da4f3702a..399a5b979a42b 100644 --- a/test/bitset.jl +++ b/test/bitset.jl @@ -351,3 +351,12 @@ end # union! with an empty range doesn't modify the BitSet @test union!(x, b:a) == y end + +@testset "union!(::BitSet, ::AbstractUnitRange) when two ranges do not overlap" begin + # see #45574 + a, b = minmax(rand(-1000:1000, 2)...) + c, d = minmax(rand(2000:3000, 2)...) + @test length(union!(BitSet(a:b), c:d)) == length(a:b) + length(c:d) + c, d = minmax(rand(-3000:-2000, 2)...) + @test length(union!(BitSet(a:b), c:d)) == length(a:b) + length(c:d) +end From 5a40cbaedaf1df0ca85199335c8d6825a8402d95 Mon Sep 17 00:00:00 2001 From: metab0t Date: Sat, 4 Jun 2022 18:49:12 +0800 Subject: [PATCH 2/3] Remove old code because the new section is filled with 0. --- base/bitset.jl | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/base/bitset.jl b/base/bitset.jl index b4da9f1f7f022..22ff177695349 100644 --- a/base/bitset.jl +++ b/base/bitset.jl @@ -138,19 +138,9 @@ function union!(s::BitSet, r::AbstractUnitRange{<:Integer}) # grow s.bits as necessary if diffb >= len _growend0!(s.bits, diffb - len + 1) - # we set only some values to CHK0, those which will not be - # fully overwritten (i.e. only or'ed with `|`) - s.bits[end] = CHK0 # end == diffb + 1 - if diffa >= len - s.bits[diffa + 1] = CHK0 - end end if diffa < 0 _growbeg0!(s.bits, -diffa) - s.bits[1] = CHK0 - if diffb < 0 - s.bits[diffb - diffa + 1] = CHK0 - end s.offset = cidxa # s.offset += diffa diffb -= diffa diffa = 0 From a7ec078fd76a76c0ff074fd6ec71b143da66b5a6 Mon Sep 17 00:00:00 2001 From: metab0t Date: Mon, 6 Jun 2022 20:35:49 +0800 Subject: [PATCH 3/3] Make test more challenging and trigger failure. --- test/bitset.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/bitset.jl b/test/bitset.jl index 399a5b979a42b..6c7947ebc37af 100644 --- a/test/bitset.jl +++ b/test/bitset.jl @@ -354,9 +354,9 @@ end @testset "union!(::BitSet, ::AbstractUnitRange) when two ranges do not overlap" begin # see #45574 - a, b = minmax(rand(-1000:1000, 2)...) - c, d = minmax(rand(2000:3000, 2)...) + a, b = rand(-10000:-5000), rand(5000:10000) + c, d = minmax(rand(20000:30000, 2)...) @test length(union!(BitSet(a:b), c:d)) == length(a:b) + length(c:d) - c, d = minmax(rand(-3000:-2000, 2)...) + c, d = minmax(rand(-30000:-20000, 2)...) @test length(union!(BitSet(a:b), c:d)) == length(a:b) + length(c:d) end