Multiplication overflow issues around Long/MIN_VALUE

Description

Long story short (ha!), there are several related issues where overflow checking doesn't work correctly with Long/MIN_VALUE. The cause of this missed check is that in Java, these both pass:

This causes the following results in Clojure that do not match their siblings where the order of operands is switched:

Mailing list discussion here: https://groups.google.com/d/msg/clojure-dev/o1QGR1QK70M/A1KykR9OQqwJ

Patch: min_value_multiplication.diff

Approach: Modifies BigInt.multiply() and multiply/multiplyP in Numbers to take into account Long.MIN_VALUE.

After:

Screened by: Alex Miller (should also include CLJ-1225, CLJ-1253, CLJ-1254)

Environment

None

Activity

Show:
Rich Hickey
November 22, 2013, 4:14 PM

missed the ' earlier

Colin Jones
November 22, 2013, 2:14 PM

Rich, can you clarify? My understanding is that *' is an auto-promoting operation. For instance, in 1.5.1, *' auto-promotes in the positive direction:

user=> (*' Long/MAX_VALUE Long/MAX_VALUE)
85070591730234615847396907784232501249N

and in the negative:

user=> (*' Long/MIN_VALUE -2)
18446744073709551616N

The only outlier is the one addressed in this ticket. Am I missing something? What should the result be here if not the one given by this patch?

Rich Hickey
November 22, 2013, 1:28 PM

user=> (*' Long/MIN_VALUE -1)
9223372036854775808N

Is wrong - there should be no coercion, this is an overflowing operation.

Andy Fingerhut
June 25, 2013, 5:06 PM

I have created for the corresponding issues with / and quot with these arguments. I think that Long/MIN_VALUE and -1 should be the only arguments that cause problems for multiplication overflow detection, too, since it is based upon division, and I give some reasons in why I believe these are the only arguments that give the numerically wrong answer for the Java division operator / on longs.

Colin Jones
June 21, 2013, 7:54 PM

I don't have a proof, just a half-hour or so of digging for an alternate case (found none), plus taking a look at what Guava does in checkedMultiply: https://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/math/LongMath.java#522

I didn't do the leading zeros optimization they're doing to avoid even the division in the overflow check we already have; that felt like a bigger change, and not one that impacts correctness.

Completed
Your pinned fields
Click on the next to a field label to start pinning.

Assignee

Unassigned

Reporter

Colin Jones

Labels

Approval

Ok

Patch

Code and Test

Priority

Minor

Fix versions