LongRangeSet: fix for range[Long.MIN_VALUE..x] % point[Long.MIN_VALUE]

This commit is contained in:
Tagir Valeev
2017-12-04 10:07:00 +07:00
parent 670ce0d028
commit 20211e0084
2 changed files with 18 additions and 8 deletions
@@ -737,7 +737,9 @@ public abstract class LongRangeSet {
@Override
public LongRangeSet mod(LongRangeSet divisor) {
if (divisor.isEmpty() || divisor.equals(point(0))) return empty();
if (divisor instanceof Point && ((Point)divisor).myValue == Long.MIN_VALUE) return this;
if (divisor instanceof Point && ((Point)divisor).myValue == Long.MIN_VALUE) {
return this.contains(Long.MIN_VALUE) ? this.subtract(divisor).union(point(0)) : this;
}
if (divisor.contains(Long.MIN_VALUE)) {
return possibleMod();
}
@@ -23,6 +23,7 @@ import org.junit.Test;
import java.util.Random;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet.*;
import static org.junit.Assert.*;
@@ -321,16 +322,23 @@ public class LongRangeSetTest {
checkMod(range(0, 10).union(range(30, 50)), range(-20, -10).union(range(15, 25)), "{0..24}");
checkMod(point(10), point(0), "{}");
checkMod(range(0, 10), point(0), "{}");
checkMod(range(Long.MIN_VALUE, Long.MIN_VALUE + 3), point(Long.MIN_VALUE), "{-9223372036854775807..-9223372036854775805, 0}");
checkMod(range(Long.MAX_VALUE - 3, Long.MAX_VALUE), point(Long.MAX_VALUE), "{0..9223372036854775806}");
}
void checkMod(LongRangeSet dividentRange, LongRangeSet divisorRange, String expected) {
LongRangeSet result = dividentRange.mod(divisorRange);
void checkMod(LongRangeSet dividendRange, LongRangeSet divisorRange, String expected) {
LongRangeSet result = dividendRange.mod(divisorRange);
assertEquals(expected, result.toString());
assertTrue(
dividentRange.stream()
.mapToObj(divident -> divisorRange.stream()
.filter(divisor -> divisor != 0).map(divisor -> divident % divisor)).flatMapToLong(Function.identity())
.allMatch(result::contains));
String errors = dividendRange.stream()
.mapToObj(dividend -> divisorRange.stream()
.filter(divisor -> divisor != 0)
.filter(divisor -> !result.contains(dividend % divisor))
.mapToObj(divisor -> dividend + " % " + divisor + " = " + (dividend % divisor)))
.flatMap(Function.identity())
.collect(Collectors.joining("\n"));
if (!errors.isEmpty()) {
fail("Expected range " + expected + " is not satisfied:\n" + errors);
}
}
@Test