High cost of failed Math.*Exact calls
John Rose
john.r.rose at oracle.com
Sat Jan 11 06:09:10 UTC 2025
On 13 Dec 2024, at 5:22, Raffaello Giulietti wrote:
> For your specific multiplication use case you might try with
>
> long high = Math.multiplyHigh(a, b);
> long low = a * b;
> if (high == 0) return low;
> return "the big integer consisting of high and low";
>
> It might be possible that the multiplyHigh() and * on the same operands, when appearing adjacent to each other, get optimized to just one instruction.
> And if not, they might be executed "in parallel" inside the CPU.
Here’s a relevant RFE, not yet implemented:
https://bugs.openjdk.org/browse/JDK-8285871
Math.multiplyHigh and multiply on same inputs can be computed faster if their computation is shared
And FWIW, a lambda-based API could be made generic in the lambda result, so that the full BigInteger (or whatever) could be returned immediately:
public static <R super Long>
R multiplyExact(long x, long y, BiFunction<Long,Long,R> recompute) {
if (<no overflow>) return x * y;
return recompute(x, y);
}
That lambda can also cover use cases with throwing and sigils and nulls.
To work efficiently it also needs some sort of box suppression, either by reliable inlining and EA, or by handling Long as a value class.
For completeness, if we get primitives over generics, then we could also spell it with lower-case “L”s:
public static <R super long>
R multiplyExact(long x, long y, BiFunction<long,long,R> recompute) {
if (<no overflow>) return x * y;
return recompute(x, y);
}
More information about the core-libs-dev
mailing list