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
Approach: Modifies BigInt.multiply() and multiply/multiplyP in Numbers to take into account Long.MIN_VALUE.
Screened by: Alex Miller (should also include CLJ-1225, CLJ-1253, CLJ-1254)
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.
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.
user=> (*' Long/MIN_VALUE -1)
Is wrong - there should be no coercion, this is an overflowing operation.
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)
and in the negative:
user=> (*' Long/MIN_VALUE -2)
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?
missed the ' earlier