Skip to content

Commit ca4bea4

Browse files
author
Brian Burkhalter
committedJul 2, 2021
8188044: We need Math.unsignedMultiplyHigh
Reviewed-by: rriggs, aph, darcy
1 parent 3d84398 commit ca4bea4

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed
 

‎src/java.base/share/classes/java/lang/Math.java

+19
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,7 @@ public static long multiplyFull(int x, int y) {
11561156
* @param x the first value
11571157
* @param y the second value
11581158
* @return the result
1159+
* @see #unsignedMultiplyHigh
11591160
* @since 9
11601161
*/
11611162
@IntrinsicCandidate
@@ -1187,6 +1188,24 @@ public static long multiplyHigh(long x, long y) {
11871188
}
11881189
}
11891190

1191+
/**
1192+
* Returns as a {@code long} the most significant 64 bits of the unsigned
1193+
* 128-bit product of two unsigned 64-bit factors.
1194+
*
1195+
* @param x the first value
1196+
* @param y the second value
1197+
* @return the result
1198+
* @see #multiplyHigh
1199+
* @since 18
1200+
*/
1201+
public static long unsignedMultiplyHigh(long x, long y) {
1202+
// Compute via multiplyHigh() to leverage the intrinsic
1203+
long result = Math.multiplyHigh(x, y);
1204+
result += (y & (x >> 63)); // equivalent to `if (x < 0) result += y;`
1205+
result += (x & (y >> 63)); // equivalent to `if (y < 0) result += x;`
1206+
return result;
1207+
}
1208+
11901209
/**
11911210
* Returns the largest (closest to positive infinity)
11921211
* {@code int} value that is less than or equal to the algebraic quotient.

‎src/java.base/share/classes/java/lang/StrictMath.java

+16
Original file line numberDiff line numberDiff line change
@@ -982,13 +982,29 @@ public static long multiplyFull(int x, int y) {
982982
* @param x the first value
983983
* @param y the second value
984984
* @return the result
985+
* @see #unsignedMultiplyHigh
985986
* @see Math#multiplyHigh(long,long)
986987
* @since 9
987988
*/
988989
public static long multiplyHigh(long x, long y) {
989990
return Math.multiplyHigh(x, y);
990991
}
991992

993+
/**
994+
* Returns as a {@code long} the most significant 64 bits of the unsigned
995+
* 128-bit product of two unsigned 64-bit factors.
996+
*
997+
* @param x the first value
998+
* @param y the second value
999+
* @return the result
1000+
* @see #multiplyHigh
1001+
* @see Math#unsignedMultiplyHigh(long,long)
1002+
* @since 18
1003+
*/
1004+
public static long unsignedMultiplyHigh(long x, long y) {
1005+
return Math.unsignedMultiplyHigh(x, y);
1006+
}
1007+
9921008
/**
9931009
* Returns the largest (closest to positive infinity)
9941010
* {@code int} value that is less than or equal to the algebraic quotient.

‎test/jdk/java/lang/Math/MultiplicationTests.java

+46-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,13 @@
2626
* @library /test/lib
2727
* @build jdk.test.lib.RandomFactory
2828
* @run main MultiplicationTests
29-
* @bug 5100935
29+
* @bug 5100935 8188044
3030
* @summary Tests for multiplication methods (use -Dseed=X to set PRNG seed)
3131
* @key randomness
3232
*/
3333

3434
import java.math.BigInteger;
35+
import java.util.function.BiFunction;
3536
import jdk.test.lib.RandomFactory;
3637

3738
public class MultiplicationTests {
@@ -49,10 +50,25 @@ private static long multiplyHighBigInt(long x, long y) {
4950
.shiftRight(64).longValue();
5051
}
5152

52-
// Check Math.multiplyHigh(x,y) against multiplyHighBigInt(x,y)
53-
private static boolean check(long x, long y) {
54-
long p1 = multiplyHighBigInt(x, y);
55-
long p2 = Math.multiplyHigh(x, y);
53+
// Calculate high 64 bits of unsigned 128 product using signed multiply
54+
private static long unsignedMultiplyHigh(long x, long y) {
55+
long x0 = x & 0xffffffffL;
56+
long x1 = x >>> 32;
57+
long y0 = y & 0xffffffffL;
58+
long y1 = y >>> 32;
59+
60+
long t = x1 * y0 + ((x0 * y0) >>> 32);
61+
long z0 = x0 * y1 + (t & 0xffffffffL);
62+
long z1 = t >>> 32;
63+
64+
return x1 * y1 + z1 + (z0 >>> 32);
65+
}
66+
67+
// Compare results of two functions for a pair of values
68+
private static boolean check(BiFunction<Long,Long,Long> reference,
69+
BiFunction<Long,Long,Long> multiply, long x, long y) {
70+
long p1 = reference.apply(x, y);
71+
long p2 = multiply.apply(x, y);
5672
if (p1 != p2) {
5773
System.err.printf("Error - x:%d y:%d p1:%d p2:%d\n", x, y, p1, p2);
5874
return false;
@@ -61,7 +77,19 @@ private static boolean check(long x, long y) {
6177
}
6278
}
6379

64-
private static int testMultiplyHigh() {
80+
// Check Math.multiplyHigh(x,y) against multiplyHighBigInt(x,y)
81+
private static boolean checkSigned(long x, long y) {
82+
return check((a,b) -> multiplyHighBigInt(a,b),
83+
(a,b) -> Math.multiplyHigh(a, b), x, y);
84+
}
85+
86+
// Check Math.unsignedMultiplyHigh(x,y) against unsignedMultiplyHigh(x,y)
87+
private static boolean checkUnsigned(long x, long y) {
88+
return check((a,b) -> unsignedMultiplyHigh(a,b),
89+
(a,b) -> Math.unsignedMultiplyHigh(a, b), x, y);
90+
}
91+
92+
private static int test(BiFunction<Long,Long,Boolean> chk) {
6593
int failures = 0;
6694

6795
// check some boundary cases
@@ -84,23 +112,31 @@ private static int testMultiplyHigh() {
84112
};
85113

86114
for (long[] xy : v) {
87-
if(!check(xy[0], xy[1])) {
115+
if(!chk.apply(xy[0], xy[1])) {
88116
failures++;
89117
}
90118
}
91119

92120
// check some random values
93121
for (int i = 0; i < COUNT; i++) {
94-
if (!check(rnd.nextLong(), rnd.nextLong())) {
122+
if (!chk.apply(rnd.nextLong(), rnd.nextLong())) {
95123
failures++;
96124
}
97125
}
98126

99127
return failures;
100128
}
101129

130+
private static int testMultiplyHigh() {
131+
return test((x,y) -> checkSigned(x,y));
132+
}
133+
134+
private static int testUnsignedMultiplyHigh() {
135+
return test((x,y) -> checkUnsigned(x,y));
136+
}
137+
102138
public static void main(String argv[]) {
103-
int failures = testMultiplyHigh();
139+
int failures = testMultiplyHigh() + testUnsignedMultiplyHigh();
104140

105141
if (failures > 0) {
106142
System.err.println("Multiplication testing encountered "

0 commit comments

Comments
 (0)
Please sign in to comment.