-
Notifications
You must be signed in to change notification settings - Fork 139
Expand file tree
/
Copy pathMaths.java
More file actions
85 lines (74 loc) · 3.12 KB
/
Copy pathMaths.java
File metadata and controls
85 lines (74 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
* Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0
*/
package net.openhft.hashing;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("Since15")
class Maths {
@NotNull
private static final Maths INSTANCE;
static {
boolean hasMultiplyHigh = true;
try {
// stubs in src/main/java-stub are used to allow this to compile in Java 8+
Math.multiplyHigh(0, 0);
} catch (final Throwable ignore) {
hasMultiplyHigh = false;
}
INSTANCE = hasMultiplyHigh ? new MathsJDK9() : new Maths();
}
public static long unsignedLongMulXorFold(final long lhs, final long rhs) {
return INSTANCE.unsignedLongMulXorFoldImp(lhs, rhs);
}
public static long unsignedLongMulHigh(final long lhs, final long rhs) {
return INSTANCE.unsignedLongMulHighImp(lhs, rhs);
}
long unsignedLongMulXorFoldImp(final long lhs, final long rhs) {
// The Grade School method of multiplication is a hair faster in Java, primarily used here
// because the implementation is simpler.
final long lhs_l = lhs & 0xFFFFFFFFL;
final long lhs_h = lhs >>> 32;
final long rhs_l = rhs & 0xFFFFFFFFL;
final long rhs_h = rhs >>> 32;
final long lo_lo = lhs_l * rhs_l;
final long hi_lo = lhs_h * rhs_l;
final long lo_hi = lhs_l * rhs_h;
final long hi_hi = lhs_h * rhs_h;
// Add the products together. This will never overflow.
final long cross = (lo_lo >>> 32) + (hi_lo & 0xFFFFFFFFL) + lo_hi;
final long upper = (hi_lo >>> 32) + (cross >>> 32) + hi_hi;
final long lower = (cross << 32) | (lo_lo & 0xFFFFFFFFL);
return lower ^ upper;
}
long unsignedLongMulHighImp(final long lhs, final long rhs) {
// The Grade School method of multiplication is a hair faster in Java, primarily used here
// because the implementation is simpler.
final long lhs_l = lhs & 0xFFFFFFFFL;
final long lhs_h = lhs >>> 32;
final long rhs_l = rhs & 0xFFFFFFFFL;
final long rhs_h = rhs >>> 32;
final long lo_lo = lhs_l * rhs_l;
final long hi_lo = lhs_h * rhs_l;
final long lo_hi = lhs_l * rhs_h;
final long hi_hi = lhs_h * rhs_h;
// Add the products together. This will never overflow.
final long cross = (lo_lo >>> 32) + (hi_lo & 0xFFFFFFFFL) + lo_hi;
final long upper = (hi_lo >>> 32) + (cross >>> 32) + hi_hi;
return upper;
}
}
@SuppressWarnings("Since15")
class MathsJDK9 extends Maths {
// Math.multiplyHigh() is intrinsified from JDK 10. But JDK 9 is out of life, we always prefer
// this version to the scalar one.
@Override
long unsignedLongMulXorFoldImp(final long lhs, final long rhs) {
final long upper = Math.multiplyHigh(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs);
final long lower = lhs * rhs;
return lower ^ upper;
}
@Override
long unsignedLongMulHighImp(final long lhs, final long rhs) {
return Math.multiplyHigh(lhs, rhs) + ((lhs >> 63) & rhs) + ((rhs >> 63) & lhs);
}
}