Is there any way to get the high half of the multiplication of two long
s in Java? I.e. the part that vanishes due to overflow. (So the upper 64 bits of the 128-bit result)
I'm used to writing OpenCL code where the command mul_hi
does exactly this: http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/mul_hi.html
Since OpenCL can do it efficiently on my CPU, Java should be able to do so as well, but I can't find how I should do this (or even mimic its behaviour efficiently) in Java. Is this possible in Java, and if so, how?
If either x or y can be negative, you should use Hacker's Delight function (Henry S. Warren, Hacker's Delight, Addison-Wesley, 2nd edition, Fig. 8.2):
Let's say you have two longs,
x
andy
, andx = x_hi * 2^32 + x_lo
, andy = y_hi * 2^32 + y_lo
.Then
x * y == (x_hi * y_hi) * 2^64 + (x_hi * y_lo + x_lo * y_hi) * 2^32 + (x_lo * y_lo)
.The high 64 bits of that product can, therefore, be computed as follows:
Here is a code snippet from Java's
Math.multiplyHigh(long,long)
As from Java 9, this is included in java.lang.Math and probably direct call to it should be made. Posting the source just to show what is going on "under the hood".
The accepted solution is wrong most of the time (66%), though the error is bounded (it can be smaller than the exact result by at most 2 and it can never be bigger). This comes from
x_lo * y_lo
productx_hi * y_lo
andx_lo * y_hi
My solution seems to always work for non-negative operands.
Tested on a billion random operands. There should be a special test for corner cases and some analysis.
Dealing with negative operands would be more complicated as it'd prohibit using the unsigned shift and force us to handle intermediate result overflow.
In case speed doesn't matter much (and it rarely does), I'd go for
You should look at using a BigInteger.
Java 9 has Math.multiplyHigh, which according to the Javadocs "Returns as a long the most significant 64 bits of the 128-bit product of two 64-bit factors."