Open AminMal opened 1 year ago
Good catch! There are a lot of edge cases in this code, and apparently you found one that was missed!
Looks like (N, Long.MinValue, -1L) always returns N. Also, separately, (Long.MinValue, 0L, 1L) returns 0 instead of an exception.
The latter one is caused by
// If the range crosses zero, it might overflow when subtracted
val startside = num.sign(start)
val endside = num.sign(end)
num.toInt{
if (num.gteq(num.times(startside, endside), zero)) {
not obeying (later on) the requirement that you can only count on being able to represent -a+1
if a
is negative, not -a
. This can be restored by making the following change
num.toInt{
// If the range crosses from negative to zero or positive,
// it might overflow when subtracted; otherwise we can compute directly
if (num.lt(start, zero) == num.lt(end, zero)) {
The second one is a bit more subtle. The first waypoint when traveling in the negative direction is 1, and then you go one step, and then you go to the endpoint. The problem is that if the step size is -1, the endpoint is 0, and 0 to MinValue won't fit in a 2's complement integer.
I am pretty sure, but not completely sure, that this will be fixed by replacing
val startlim = if (posStep) negone else one
by
val startlim = if (posStep) negone else zero
I also don't see how this line can be correct:
val waypointA = if (startq == zero) start else num.plus(start, num.times(startq, step))
I'm pretty sure this would have to be
val waypointA = if (startq == zero) startlim else num.plus(start, num.times(startq, step))
No, this was silly, I misread what startq
means. This is fine.
Reproduction steps
Scala version: 2.13.4, 2.13.8, 2.13.12, 2.13.13
Problem
Trying to get the length of a wide
Long
range, somehow 1 is returned, normally, I expected it to throw anIllegalArgumentException
much like wideInt
orBigInt
orBigDecimal
. The same exact values but withBigInt
is working fine though: