JDK-6535058 : Inconvenient to detect overflow while multiplying two long values
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 7
  • Priority: P5
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-03-15
  • Updated: 2010-04-04
  • Resolved: 2007-03-16
Related Reports
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
The Java language does not allow to detect overflow while the following code:

    long a = 7000000000L, b = 5000000000L;
    long c = a*b; // OVERFLOW!

Sometimes it leads to serious problems. Let's consider the following example:

public static SomeMyMatrix createMatrix(long width, long height) {
    long size = width * height; // ERROR! Overflow possible for illegal width and height.
    // then we create a file with the calculated number of bytes and use it for storing the matrix width*height
    ...
}

Here we tries to create a matrix that can contain more than 2^31 bytes. There are many ways to do this; for example, such a matrix can be stored in a large mapped file. The important thing is that both matrix width and height may be, theoretically, greater than 2^31 and cannot be described by "int" type.

How, in this situation, to calculate the matrix size: the product width*height? Of course, when we passes correct argument to this method, the width*height value will not be too high. Today it can be several gigabytes; tomorrow, maybe, it will be several terabytes. But how can I detect ILLEGAL width and height arguments?

For example, if I'll pass width=2^32 and height=2^32, the calculated size will be zero! The corresponding matrix will be probably created successfully, but will not work, because it's size!=width*height.

If width and height are "int" values, the solution is very simple: I should check (long)a*(long)b. For "long" type, this technique does not work. If I'll try to use "double" type - (double)a*(double)b - the result may be incorrect because the precision of double values is less than 64 bits. Namely, if I'll write

   if ((double)width*(double)height>Long.MAX_VALUE)
       throw new IllegalArgumentException(...)

this check may "skip" (not detect) some illegal (too high) width and height because of rounding. Another possible solution is using BigDecimal, but it seems too slow and "hard" method for such simple problem.

I've created a simple function "longMul(long a, long b)", that allows to resolve this issue. Please see the attached source code. In a case of overflow, it returns the "signal" result Long.MIN_VALUE.

Could you include this or equivalent function in your standard Math class?

JUSTIFICATION :
  Too complex code allowing to detect overflow while "long" multiplication.

Comments
EVALUATION The platform does not have a method to detect long overflow but it is certainly possible. For example, the BigInteger could be constructed from the long values and the result of the BigInteger multiply compared to Long.{MIN_VALUE, MAX_VALUE}. The book "Hacker's Delight" gives various clever algorithms to detect these sort of integer overflow cases without a larger data format. This sort of test would be eased by a method which gave the high word of a product; see bug 5100935. Closing as not a bug.
16-03-2007