22
22
import org .apache .hadoop .classification .InterfaceStability ;
23
23
24
24
import java .util .Arrays ;
25
+ import java .util .function .ToIntFunction ;
25
26
26
27
/**
27
28
* This class provides utilities for working with CRCs.
@@ -32,6 +33,55 @@ public final class CrcUtil {
32
33
public static final int MULTIPLICATIVE_IDENTITY = 0x80000000 ;
33
34
public static final int GZIP_POLYNOMIAL = 0xEDB88320 ;
34
35
public static final int CASTAGNOLI_POLYNOMIAL = 0x82F63B78 ;
36
+ private static final long UNIT = 0x8000_0000_0000_0000L ;
37
+
38
+ /**
39
+ * @return a * b (mod p),
40
+ * where mod p is computed by the given mod function.
41
+ */
42
+ static int multiplyMod (int a , int b , ToIntFunction <Long > mod ) {
43
+ final long left = ((long )a ) << 32 ;
44
+ final long right = ((long )b ) << 32 ;
45
+
46
+ final long product
47
+ = ((((((left & (UNIT /* */ )) == 0L ? 0L : right )
48
+ ^ ((left & (UNIT >>> 1 )) == 0L ? 0L : right >>> 1 ))
49
+ ^ (((left & (UNIT >>> 2 )) == 0L ? 0L : right >>> 2 )
50
+ ^ ((left & (UNIT >>> 3 )) == 0L ? 0L : right >>> 3 )))
51
+ ^ ((((left & (UNIT >>> 4 )) == 0L ? 0L : right >>> 4 )
52
+ ^ ((left & (UNIT >>> 5 )) == 0L ? 0L : right >>> 5 ))
53
+ ^ (((left & (UNIT >>> 6 )) == 0L ? 0L : right >>> 6 )
54
+ ^ ((left & (UNIT >>> 7 )) == 0L ? 0L : right >>> 7 ))))
55
+
56
+ ^ (((((left & (UNIT >>> 8 )) == 0L ? 0L : right >>> 8 )
57
+ ^ ((left & (UNIT >>> 9 )) == 0L ? 0L : right >>> 9 ))
58
+ ^ (((left & (UNIT >>> 10 )) == 0L ? 0L : right >>> 10 )
59
+ ^ ((left & (UNIT >>> 11 )) == 0L ? 0L : right >>> 11 )))
60
+ ^ ((((left & (UNIT >>> 12 )) == 0L ? 0L : right >>> 12 )
61
+ ^ ((left & (UNIT >>> 13 )) == 0L ? 0L : right >>> 13 ))
62
+ ^ (((left & (UNIT >>> 14 )) == 0L ? 0L : right >>> 14 )
63
+ ^ ((left & (UNIT >>> 15 )) == 0L ? 0L : right >>> 15 )))))
64
+
65
+ ^ ((((((left & (UNIT >>> 16 )) == 0L ? 0L : right >>> 16 )
66
+ ^ ((left & (UNIT >>> 17 )) == 0L ? 0L : right >>> 17 ))
67
+ ^ (((left & (UNIT >>> 18 )) == 0L ? 0L : right >>> 18 )
68
+ ^ ((left & (UNIT >>> 19 )) == 0L ? 0L : right >>> 19 )))
69
+ ^ ((((left & (UNIT >>> 20 )) == 0L ? 0L : right >>> 20 )
70
+ ^ ((left & (UNIT >>> 21 )) == 0L ? 0L : right >>> 21 ))
71
+ ^ (((left & (UNIT >>> 22 )) == 0L ? 0L : right >>> 22 )
72
+ ^ ((left & (UNIT >>> 23 )) == 0L ? 0L : right >>> 23 ))))
73
+
74
+ ^ (((((left & (UNIT >>> 24 )) == 0L ? 0L : right >>> 24 )
75
+ ^ ((left & (UNIT >>> 25 )) == 0L ? 0L : right >>> 25 ))
76
+ ^ (((left & (UNIT >>> 26 )) == 0L ? 0L : right >>> 26 )
77
+ ^ ((left & (UNIT >>> 27 )) == 0L ? 0L : right >>> 27 )))
78
+ ^ ((((left & (UNIT >>> 28 )) == 0L ? 0L : right >>> 28 )
79
+ ^ ((left & (UNIT >>> 29 )) == 0L ? 0L : right >>> 29 ))
80
+ ^ (((left & (UNIT >>> 30 )) == 0L ? 0L : right >>> 30 )
81
+ ^ ((left & (UNIT >>> 31 )) == 0L ? 0L : right >>> 31 )))));
82
+
83
+ return mod .applyAsInt (product );
84
+ }
35
85
36
86
/**
37
87
* Hide default constructor for a static utils class.
@@ -48,7 +98,7 @@ private CrcUtil() {
48
98
* @param mod mod.
49
99
* @return monomial.
50
100
*/
51
- public static int getMonomial (long lengthBytes , int mod ) {
101
+ public static int getMonomial (long lengthBytes , ToIntFunction < Long > mod ) {
52
102
if (lengthBytes == 0 ) {
53
103
return MULTIPLICATIVE_IDENTITY ;
54
104
} else if (lengthBytes < 0 ) {
@@ -67,9 +117,9 @@ public static int getMonomial(long lengthBytes, int mod) {
67
117
while (degree > 0 ) {
68
118
if ((degree & 1 ) != 0 ) {
69
119
product = (product == MULTIPLICATIVE_IDENTITY ) ? multiplier :
70
- galoisFieldMultiply (product , multiplier , mod );
120
+ multiplyMod (product , multiplier , mod );
71
121
}
72
- multiplier = galoisFieldMultiply (multiplier , multiplier , mod );
122
+ multiplier = multiplyMod (multiplier , multiplier , mod );
73
123
degree >>= 1 ;
74
124
}
75
125
return product ;
@@ -85,8 +135,8 @@ public static int getMonomial(long lengthBytes, int mod) {
85
135
* @return compose with monomial.
86
136
*/
87
137
public static int composeWithMonomial (
88
- int crcA , int crcB , int monomial , int mod ) {
89
- return galoisFieldMultiply (crcA , monomial , mod ) ^ crcB ;
138
+ int crcA , int crcB , int monomial , ToIntFunction < Long > mod ) {
139
+ return multiplyMod (crcA , monomial , mod ) ^ crcB ;
90
140
}
91
141
92
142
/**
@@ -98,7 +148,7 @@ public static int composeWithMonomial(
98
148
* @param mod mod.
99
149
* @return compose result.
100
150
*/
101
- public static int compose (int crcA , int crcB , long lengthB , int mod ) {
151
+ public static int compose (int crcA , int crcB , long lengthB , ToIntFunction < Long > mod ) {
102
152
int monomial = getMonomial (lengthB , mod );
103
153
return composeWithMonomial (crcA , crcB , monomial , mod );
104
154
}
@@ -199,40 +249,5 @@ public static String toMultiCrcString(final byte[] bytes) {
199
249
return sb .toString ();
200
250
}
201
251
202
- /**
203
- * Galois field multiplication of {@code p} and {@code q} with the
204
- * generator polynomial {@code m} as the modulus.
205
- *
206
- * @param m The little-endian polynomial to use as the modulus when
207
- * multiplying p and q, with implicit "1" bit beyond the bottom bit.
208
- */
209
- private static int galoisFieldMultiply (int p , int q , int m ) {
210
- int summation = 0 ;
211
-
212
- // Top bit is the x^0 place; each right-shift increments the degree of the
213
- // current term.
214
- int curTerm = MULTIPLICATIVE_IDENTITY ;
215
-
216
- // Iteratively multiply p by x mod m as we go to represent the q[i] term
217
- // (of degree x^i) times p.
218
- int px = p ;
219
-
220
- while (curTerm != 0 ) {
221
- if ((q & curTerm ) != 0 ) {
222
- summation ^= px ;
223
- }
224
252
225
- // Bottom bit represents highest degree since we're little-endian; before
226
- // we multiply by "x" for the next term, check bottom bit to know whether
227
- // the resulting px will thus have a term matching the implicit "1" term
228
- // of "m" and thus will need to subtract "m" after mutiplying by "x".
229
- boolean hasMaxDegree = ((px & 1 ) != 0 );
230
- px >>>= 1 ;
231
- if (hasMaxDegree ) {
232
- px ^= m ;
233
- }
234
- curTerm >>>= 1 ;
235
- }
236
- return summation ;
237
- }
238
253
}
0 commit comments