Skip to content

Commit

Permalink
Fixes #1717 - overflow issues in LongInterval
Browse files Browse the repository at this point in the history
  • Loading branch information
vmzakharov committed Oct 14, 2024
1 parent 4bfa52e commit 1646c68
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -314,18 +314,19 @@ public void forEachWithIndex(LongIntProcedure procedure)
{
for (long i = this.from; i <= this.to; i += this.step)
{
procedure.value((int) i, index++);
procedure.value(i, index++);
}
}
else
{
for (long i = this.from; i >= this.to; i += this.step)
{
procedure.value((int) i, index++);
procedure.value(i, index++);
}
}
}

@Deprecated(forRemoval = true)
public void forEachWithLongIndex(LongLongProcedure procedure)
{
long index = 0;
Expand Down Expand Up @@ -360,14 +361,14 @@ public void each(LongProcedure procedure)
{
for (long i = this.from; i <= this.to; i += this.step)
{
procedure.value((int) i);
procedure.value(i);
}
}
else
{
for (long i = this.from; i >= this.to; i += this.step)
{
procedure.value((int) i);
procedure.value(i);
}
}
}
Expand Down Expand Up @@ -638,14 +639,14 @@ public <T> T injectInto(T injectedValue, ObjectLongToObjectFunction<? super T, ?
{
for (long i = this.from; i <= this.to; i += this.step)
{
result = function.valueOf(result, (int) i);
result = function.valueOf(result, i);
}
}
else
{
for (long i = this.from; i >= this.to; i += this.step)
{
result = function.valueOf(result, (int) i);
result = function.valueOf(result, i);
}
}
return result;
Expand All @@ -661,15 +662,15 @@ public <T> T injectIntoWithIndex(T injectedValue, ObjectLongIntToObjectFunction<
{
for (long i = this.from; i <= this.to; i += this.step)
{
result = function.valueOf(result, (int) i, index);
result = function.valueOf(result, i, index);
index++;
}
}
else
{
for (long i = this.from; i >= this.to; i += this.step)
{
result = function.valueOf(result, (int) i, index);
result = function.valueOf(result, i, index);
index++;
}
}
Expand All @@ -695,8 +696,8 @@ public RichIterable<LongIterable> chunk(int size)
MutableLongList batch = LongLists.mutable.empty();
for (long i = innerFrom; i <= this.to && batch.size() < size; i += this.step)
{
batch.add((int) i);
lastUpdated = (int) i;
batch.add(i);
lastUpdated = i;
}
result.add(batch);
innerFrom = lastUpdated + this.step;
Expand All @@ -709,8 +710,8 @@ public RichIterable<LongIterable> chunk(int size)
MutableLongList batch = LongLists.mutable.empty();
for (long i = innerFrom; i >= this.to && batch.size() < size; i += this.step)
{
batch.add((int) i);
lastUpdated = (int) i;
batch.add(i);
lastUpdated = i;
}
result.add(batch);
innerFrom = lastUpdated + this.step;
Expand Down Expand Up @@ -1003,7 +1004,7 @@ public long next()
{
if (this.hasNext())
{
long result = (int) this.current;
long result = this.current;
this.current += LongInterval.this.step;
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,66 @@ public void each()
assertEquals(list2, interval2);
}

@Test
public void eachForLargeValues()
{
var values1 = LongLists.mutable.empty();

LongInterval.zeroToBy(9_999_999_999L, 1_000_000_000L).forEach(values1::add);

assertEquals(
LongLists.immutable.of(
0, 1_000_000_000L, 2_000_000_000L, 3_000_000_000L, 4_000_000_000L,
5_000_000_000L, 6_000_000_000L, 7_000_000_000L, 8_000_000_000L, 9_000_000_000L),
values1);

var values2 = LongLists.mutable.empty();

LongInterval.zeroToBy(-9_999_999_999L, -1_000_000_000L).forEach(values2::add);

assertEquals(
LongLists.immutable.of(
0, -1_000_000_000L, -2_000_000_000L, -3_000_000_000L, -4_000_000_000L,
-5_000_000_000L, -6_000_000_000L, -7_000_000_000L, -8_000_000_000L, -9_000_000_000L),
values2);
}

@Test
public void forEachWithIndexForLargeValues()
{
var values1 = LongLists.mutable.empty();
var indices1 = LongLists.mutable.empty();

LongInterval.zeroToBy(9_999_999_999L, 1_000_000_000L)
.forEachWithIndex((each, index) -> {
values1.add(each + index);
indices1.add(index);
});

assertEquals(LongLists.immutable.of(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L), indices1);

assertEquals(
LongLists.immutable.of(0, 1_000_000_001L, 2_000_000_002L, 3_000_000_003L, 4_000_000_004L,
5_000_000_005L, 6_000_000_006L, 7_000_000_007L, 8_000_000_008L, 9_000_000_009L),
values1);

var values2 = LongLists.mutable.empty();
var indices2 = LongLists.mutable.empty();

LongInterval.zeroToBy(-9_999_999_999L, -1_000_000_000L)
.forEachWithIndex((each, index) -> {
values2.add(each - index);
indices2.add(index);
});

assertEquals(LongLists.immutable.of(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L), indices2);

assertEquals(
LongLists.immutable.of(0, -1_000_000_001L, -2_000_000_002L, -3_000_000_003L, -4_000_000_004L,
-5_000_000_005L, -6_000_000_006L, -7_000_000_007L, -8_000_000_008L, -9_000_000_009L),
values2);
}

@Test
public void injectInto()
{
Expand All @@ -273,6 +333,51 @@ public void injectIntoWithIndex()
assertEquals(new MutableLong(10), result2);
}

@Test
public void injectIntoForLargeValues()
{
long largeNumber = (long) Integer.MAX_VALUE * 2L;
LongInterval interval1 = LongInterval.fromTo(largeNumber, largeNumber + 10L);
MutableLong result1 = interval1.injectInto(new MutableLong(0), MutableLong::add);
long expected1 = 47244640289L; // largeNumber * 11 + 55;
assertEquals(new MutableLong(expected1), result1);

long largeNegativeNumber = (long) Integer.MIN_VALUE * 2L;
LongInterval interval2 = LongInterval.fromToBy(largeNegativeNumber, largeNegativeNumber - 10L, -1L);
MutableLong result2 = interval2.injectInto(new MutableLong(0), MutableLong::add);
long expected2 = -47244640311L; // (largeNegativeNumber * 11L) - 55L;
assertEquals(new MutableLong(expected2), result2);
}

@Test
public void injectIntoWithIndexForLargeValues()
{
long largeNumber = (long) Integer.MAX_VALUE * 2L;

LongInterval interval1 = LongInterval.fromTo(largeNumber, largeNumber + 3L);

MutableLong result1 = interval1.injectIntoWithIndex(
new MutableLong(0),
(object, value, index) -> {
assertEquals(interval1.get(index), value);
return object.add(value);
});

assertEquals(new MutableLong(17179869182L), result1);

long largeNegativeNumber = (long) Integer.MIN_VALUE * 2L;
LongInterval interval2 = LongInterval.fromToBy(largeNegativeNumber, largeNegativeNumber - 3L, -1L);

MutableLong result2 = interval2.injectIntoWithIndex(
new MutableLong(0),
(object, value, index) -> {
assertEquals(interval2.get(index), value);
return object.add(value);
});

assertEquals(new MutableLong(-17179869190L), result2);
}

@Test
public void injectIntoOnFromToBySameStartEndNegativeStepInterval()
{
Expand Down Expand Up @@ -355,6 +460,28 @@ public void chunk()
assertThrows(IllegalArgumentException.class, () -> interval12.chunk(-1));
}

@Test
public void chunkForLargeValues()
{
LongInterval interval1 = LongInterval.fromToBy(0, 9_999_999_999L, 1_000_000_000L);
MutableList<LongInterval> expected1 = Lists.mutable.with(
LongInterval.fromToBy(0, 2_000_000_000L, 1_000_000_000L),
LongInterval.fromToBy(3_000_000_000L, 5_000_000_000L, 1_000_000_000L),
LongInterval.fromToBy(6_000_000_000L, 8_000_000_000L, 1_000_000_000L),
LongInterval.fromToBy(9_000_000_000L, 9_000_000_000L, 1_000_000_000L));
assertEquals(expected1, interval1.chunk(3));

LongInterval interval2 = LongInterval.fromToBy(0, -9_999_999_999L, -1_000_000_000L);

MutableList<LongInterval> expected2 = Lists.mutable.with(
LongInterval.fromToBy(0, -2_000_000_000L, -1_000_000_000L),
LongInterval.fromToBy(-3_000_000_000L, -5_000_000_000L, -1_000_000_000L),
LongInterval.fromToBy(-6_000_000_000L, -8_000_000_000L, -1_000_000_000L),
LongInterval.fromToBy(-9_000_000_000L, -9_000_000_000L, -1_000_000_000L));

assertEquals(expected2, interval2.chunk(3));
}

@Test
public void size()
{
Expand Down Expand Up @@ -985,6 +1112,37 @@ public void intervalIterator()
assertThrows(NoSuchElementException.class, threeToNegativeThreeIterator::next);
}

@Test
public void intervalIteratorForLargeValues()
{
var values1 = LongLists.mutable.empty();
LongIterator iterator1 = LongInterval.zeroToBy(9_999_999_999L, 1_000_000_000L).longIterator();
while (iterator1.hasNext())
{
values1.add(iterator1.next());
}

assertEquals(
LongLists.immutable.of(
0, 1_000_000_000L, 2_000_000_000L, 3_000_000_000L, 4_000_000_000L,
5_000_000_000L, 6_000_000_000L, 7_000_000_000L, 8_000_000_000L, 9_000_000_000L),
values1);

var values2 = LongLists.mutable.empty();

LongIterator iterator2 = LongInterval.zeroToBy(-9_999_999_999L, -1_000_000_000L).longIterator();
while (iterator2.hasNext())
{
values2.add(iterator2.next());
}

assertEquals(
LongLists.immutable.of(
0, -1_000_000_000L, -2_000_000_000L, -3_000_000_000L, -4_000_000_000L,
-5_000_000_000L, -6_000_000_000L, -7_000_000_000L, -8_000_000_000L, -9_000_000_000L),
values2);
}

@Test
public void forEachWithIndex()
{
Expand Down

0 comments on commit 1646c68

Please sign in to comment.