1818package org .apache .hadoop .ozone .client .checksum ;
1919
2020import java .util .Arrays ;
21+ import java .util .function .LongToIntFunction ;
2122import org .apache .hadoop .hdds .annotation .InterfaceAudience ;
2223import org .apache .hadoop .hdds .annotation .InterfaceStability ;
23- import org .apache .hadoop .util .DataChecksum ;
2424
2525/**
2626 * This class provides utilities for working with CRCs.
2929@ InterfaceStability .Unstable
3030public final class CrcUtil {
3131 public static final int MULTIPLICATIVE_IDENTITY = 0x80000000 ;
32- public static final int GZIP_POLYNOMIAL = 0xEDB88320 ;
33- public static final int CASTAGNOLI_POLYNOMIAL = 0x82F63B78 ;
32+ private static final long UNIT = 0x8000_0000_0000_0000L ;
3433
3534 /**
3635 * Hide default constructor for a static utils class.
@@ -39,22 +38,51 @@ private CrcUtil() {
3938 }
4039
4140 /**
42- * getCrcPolynomialForType.
43- *
44- * @param type type.
45- * @return the int representation of the polynomial associated with the
46- * CRC {@code type}, suitable for use with further CRC arithmetic.
41+ * @return a * b (mod p),
42+ * where mod p is computed by the given mod function.
4743 */
48- public static int getCrcPolynomialForType (DataChecksum .Type type ) {
49- switch (type ) {
50- case CRC32 :
51- return GZIP_POLYNOMIAL ;
52- case CRC32C :
53- return CASTAGNOLI_POLYNOMIAL ;
54- default :
55- throw new IllegalArgumentException (
56- "No CRC polynomial could be associated with type: " + type );
57- }
44+ static int multiplyMod (int a , int b , LongToIntFunction mod ) {
45+ final long left = ((long )a ) << 32 ;
46+ final long right = ((long )b ) << 32 ;
47+
48+ final long product
49+ = ((((((left & (UNIT /* */ )) == 0L ? 0L : right )
50+ ^ ((left & (UNIT >>> 1 )) == 0L ? 0L : right >>> 1 ))
51+ ^ (((left & (UNIT >>> 2 )) == 0L ? 0L : right >>> 2 )
52+ ^ ((left & (UNIT >>> 3 )) == 0L ? 0L : right >>> 3 )))
53+ ^ ((((left & (UNIT >>> 4 )) == 0L ? 0L : right >>> 4 )
54+ ^ ((left & (UNIT >>> 5 )) == 0L ? 0L : right >>> 5 ))
55+ ^ (((left & (UNIT >>> 6 )) == 0L ? 0L : right >>> 6 )
56+ ^ ((left & (UNIT >>> 7 )) == 0L ? 0L : right >>> 7 ))))
57+
58+ ^ (((((left & (UNIT >>> 8 )) == 0L ? 0L : right >>> 8 )
59+ ^ ((left & (UNIT >>> 9 )) == 0L ? 0L : right >>> 9 ))
60+ ^ (((left & (UNIT >>> 10 )) == 0L ? 0L : right >>> 10 )
61+ ^ ((left & (UNIT >>> 11 )) == 0L ? 0L : right >>> 11 )))
62+ ^ ((((left & (UNIT >>> 12 )) == 0L ? 0L : right >>> 12 )
63+ ^ ((left & (UNIT >>> 13 )) == 0L ? 0L : right >>> 13 ))
64+ ^ (((left & (UNIT >>> 14 )) == 0L ? 0L : right >>> 14 )
65+ ^ ((left & (UNIT >>> 15 )) == 0L ? 0L : right >>> 15 )))))
66+
67+ ^ ((((((left & (UNIT >>> 16 )) == 0L ? 0L : right >>> 16 )
68+ ^ ((left & (UNIT >>> 17 )) == 0L ? 0L : right >>> 17 ))
69+ ^ (((left & (UNIT >>> 18 )) == 0L ? 0L : right >>> 18 )
70+ ^ ((left & (UNIT >>> 19 )) == 0L ? 0L : right >>> 19 )))
71+ ^ ((((left & (UNIT >>> 20 )) == 0L ? 0L : right >>> 20 )
72+ ^ ((left & (UNIT >>> 21 )) == 0L ? 0L : right >>> 21 ))
73+ ^ (((left & (UNIT >>> 22 )) == 0L ? 0L : right >>> 22 )
74+ ^ ((left & (UNIT >>> 23 )) == 0L ? 0L : right >>> 23 ))))
75+
76+ ^ (((((left & (UNIT >>> 24 )) == 0L ? 0L : right >>> 24 )
77+ ^ ((left & (UNIT >>> 25 )) == 0L ? 0L : right >>> 25 ))
78+ ^ (((left & (UNIT >>> 26 )) == 0L ? 0L : right >>> 26 )
79+ ^ ((left & (UNIT >>> 27 )) == 0L ? 0L : right >>> 27 )))
80+ ^ ((((left & (UNIT >>> 28 )) == 0L ? 0L : right >>> 28 )
81+ ^ ((left & (UNIT >>> 29 )) == 0L ? 0L : right >>> 29 ))
82+ ^ (((left & (UNIT >>> 30 )) == 0L ? 0L : right >>> 30 )
83+ ^ ((left & (UNIT >>> 31 )) == 0L ? 0L : right >>> 31 )))));
84+
85+ return mod .applyAsInt (product );
5886 }
5987
6088 /**
@@ -66,7 +94,7 @@ public static int getCrcPolynomialForType(DataChecksum.Type type) {
6694 * @param mod mod.
6795 * @return monomial.
6896 */
69- public static int getMonomial (long lengthBytes , int mod ) {
97+ public static int getMonomial (long lengthBytes , LongToIntFunction mod ) {
7098 if (lengthBytes == 0 ) {
7199 return MULTIPLICATIVE_IDENTITY ;
72100 } else if (lengthBytes < 0 ) {
@@ -85,9 +113,9 @@ public static int getMonomial(long lengthBytes, int mod) {
85113 while (degree > 0 ) {
86114 if ((degree & 1 ) != 0 ) {
87115 product = (product == MULTIPLICATIVE_IDENTITY ) ? multiplier :
88- galoisFieldMultiply (product , multiplier , mod );
116+ multiplyMod (product , multiplier , mod );
89117 }
90- multiplier = galoisFieldMultiply (multiplier , multiplier , mod );
118+ multiplier = multiplyMod (multiplier , multiplier , mod );
91119 degree >>= 1 ;
92120 }
93121 return product ;
@@ -103,8 +131,8 @@ public static int getMonomial(long lengthBytes, int mod) {
103131 * @return compose with monomial.
104132 */
105133 public static int composeWithMonomial (
106- int crcA , int crcB , int monomial , int mod ) {
107- return galoisFieldMultiply (crcA , monomial , mod ) ^ crcB ;
134+ int crcA , int crcB , int monomial , LongToIntFunction mod ) {
135+ return multiplyMod (crcA , monomial , mod ) ^ crcB ;
108136 }
109137
110138 /**
@@ -116,7 +144,7 @@ public static int composeWithMonomial(
116144 * @param mod mod.
117145 * @return compose result.
118146 */
119- public static int compose (int crcA , int crcB , long lengthB , int mod ) {
147+ public static int compose (int crcA , int crcB , long lengthB , LongToIntFunction mod ) {
120148 int monomial = getMonomial (lengthB , mod );
121149 return composeWithMonomial (crcA , crcB , monomial , mod );
122150 }
@@ -216,41 +244,4 @@ public static String toMultiCrcString(final byte[] bytes) {
216244 sb .append (']' );
217245 return sb .toString ();
218246 }
219-
220- /**
221- * Galois field multiplication of {@code p} and {@code q} with the
222- * generator polynomial {@code m} as the modulus.
223- *
224- * @param m The little-endian polynomial to use as the modulus when
225- * multiplying p and q, with implicit "1" bit beyond the bottom bit.
226- */
227- private static int galoisFieldMultiply (int p , int q , int m ) {
228- int summation = 0 ;
229-
230- // Top bit is the x^0 place; each right-shift increments the degree of the
231- // current term.
232- int curTerm = MULTIPLICATIVE_IDENTITY ;
233-
234- // Iteratively multiply p by x mod m as we go to represent the q[i] term
235- // (of degree x^i) times p.
236- int px = p ;
237-
238- while (curTerm != 0 ) {
239- if ((q & curTerm ) != 0 ) {
240- summation ^= px ;
241- }
242-
243- // Bottom bit represents highest degree since we're little-endian; before
244- // we multiply by "x" for the next term, check bottom bit to know whether
245- // the resulting px will thus have a term matching the implicit "1" term
246- // of "m" and thus will need to subtract "m" after mutiplying by "x".
247- boolean hasMaxDegree = ((px & 1 ) != 0 );
248- px >>>= 1 ;
249- if (hasMaxDegree ) {
250- px ^= m ;
251- }
252- curTerm >>>= 1 ;
253- }
254- return summation ;
255- }
256247}
0 commit comments