xref: /aosp_15_r20/external/abseil-cpp/absl/crc/internal/crc.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2022 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker 
15*9356374aSAndroid Build Coastguard Worker // Implementation of CRCs (aka Rabin Fingerprints).
16*9356374aSAndroid Build Coastguard Worker // Treats the input as a polynomial with coefficients in Z(2),
17*9356374aSAndroid Build Coastguard Worker // and finds the remainder when divided by an irreducible polynomial
18*9356374aSAndroid Build Coastguard Worker // of the appropriate length.
19*9356374aSAndroid Build Coastguard Worker // It handles all CRC sizes from 8 to 128 bits.
20*9356374aSAndroid Build Coastguard Worker // It's somewhat complicated by having separate implementations optimized for
21*9356374aSAndroid Build Coastguard Worker // CRC's <=32 bits, <= 64 bits, and <= 128 bits.
22*9356374aSAndroid Build Coastguard Worker // The input string is prefixed with a "1" bit, and has "degree" "0" bits
23*9356374aSAndroid Build Coastguard Worker // appended to it before the remainder is found.   This ensures that
24*9356374aSAndroid Build Coastguard Worker // short strings are scrambled somewhat and that strings consisting
25*9356374aSAndroid Build Coastguard Worker // of all nulls have a non-zero CRC.
26*9356374aSAndroid Build Coastguard Worker //
27*9356374aSAndroid Build Coastguard Worker // Uses the "interleaved word-by-word" method from
28*9356374aSAndroid Build Coastguard Worker // "Everything we know about CRC but afraid to forget" by Andrew Kadatch
29*9356374aSAndroid Build Coastguard Worker // and Bob Jenkins,
30*9356374aSAndroid Build Coastguard Worker // http://crcutil.googlecode.com/files/crc-doc.1.0.pdf
31*9356374aSAndroid Build Coastguard Worker //
32*9356374aSAndroid Build Coastguard Worker // The idea is to compute kStride CRCs simultaneously, allowing the
33*9356374aSAndroid Build Coastguard Worker // processor to more effectively use multiple execution units. Each of
34*9356374aSAndroid Build Coastguard Worker // the CRCs is calculated on one word of data followed by kStride - 1
35*9356374aSAndroid Build Coastguard Worker // words of zeroes; the CRC starting points are staggered by one word.
36*9356374aSAndroid Build Coastguard Worker // Assuming a stride of 4 with data words "ABCDABCDABCD", the first
37*9356374aSAndroid Build Coastguard Worker // CRC is over A000A000A, the second over 0B000B000B, and so on.
38*9356374aSAndroid Build Coastguard Worker // The CRC of the whole data is then calculated by properly aligning the
39*9356374aSAndroid Build Coastguard Worker // CRCs by appending zeroes until the data lengths agree then XORing
40*9356374aSAndroid Build Coastguard Worker // the CRCs.
41*9356374aSAndroid Build Coastguard Worker 
42*9356374aSAndroid Build Coastguard Worker #include "absl/crc/internal/crc.h"
43*9356374aSAndroid Build Coastguard Worker 
44*9356374aSAndroid Build Coastguard Worker #include <cstdint>
45*9356374aSAndroid Build Coastguard Worker 
46*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/endian.h"
47*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/raw_logging.h"
48*9356374aSAndroid Build Coastguard Worker #include "absl/base/prefetch.h"
49*9356374aSAndroid Build Coastguard Worker #include "absl/crc/internal/crc_internal.h"
50*9356374aSAndroid Build Coastguard Worker 
51*9356374aSAndroid Build Coastguard Worker namespace absl {
52*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
53*9356374aSAndroid Build Coastguard Worker namespace crc_internal {
54*9356374aSAndroid Build Coastguard Worker 
55*9356374aSAndroid Build Coastguard Worker namespace {
56*9356374aSAndroid Build Coastguard Worker 
57*9356374aSAndroid Build Coastguard Worker // Constants
58*9356374aSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
59*9356374aSAndroid Build Coastguard Worker constexpr bool kNeedAlignedLoads = false;
60*9356374aSAndroid Build Coastguard Worker #else
61*9356374aSAndroid Build Coastguard Worker constexpr bool kNeedAlignedLoads = true;
62*9356374aSAndroid Build Coastguard Worker #endif
63*9356374aSAndroid Build Coastguard Worker 
64*9356374aSAndroid Build Coastguard Worker // We express the number of zeroes as a number in base ZEROES_BASE. By
65*9356374aSAndroid Build Coastguard Worker // pre-computing the zero extensions for all possible components of such an
66*9356374aSAndroid Build Coastguard Worker // expression (numbers in a form a*ZEROES_BASE**b), we can calculate the
67*9356374aSAndroid Build Coastguard Worker // resulting extension by multiplying the extensions for individual components
68*9356374aSAndroid Build Coastguard Worker // using log_{ZEROES_BASE}(num_zeroes) polynomial multiplications. The tables of
69*9356374aSAndroid Build Coastguard Worker // zero extensions contain (ZEROES_BASE - 1) * (log_{ZEROES_BASE}(64)) entries.
70*9356374aSAndroid Build Coastguard Worker constexpr int ZEROES_BASE_LG = 4;                   // log_2(ZEROES_BASE)
71*9356374aSAndroid Build Coastguard Worker constexpr int ZEROES_BASE = (1 << ZEROES_BASE_LG);  // must be a power of 2
72*9356374aSAndroid Build Coastguard Worker 
73*9356374aSAndroid Build Coastguard Worker constexpr uint32_t kCrc32cPoly = 0x82f63b78;
74*9356374aSAndroid Build Coastguard Worker 
ReverseBits(uint32_t bits)75*9356374aSAndroid Build Coastguard Worker uint32_t ReverseBits(uint32_t bits) {
76*9356374aSAndroid Build Coastguard Worker   bits = (bits & 0xaaaaaaaau) >> 1 | (bits & 0x55555555u) << 1;
77*9356374aSAndroid Build Coastguard Worker   bits = (bits & 0xccccccccu) >> 2 | (bits & 0x33333333u) << 2;
78*9356374aSAndroid Build Coastguard Worker   bits = (bits & 0xf0f0f0f0u) >> 4 | (bits & 0x0f0f0f0fu) << 4;
79*9356374aSAndroid Build Coastguard Worker   return absl::gbswap_32(bits);
80*9356374aSAndroid Build Coastguard Worker }
81*9356374aSAndroid Build Coastguard Worker 
82*9356374aSAndroid Build Coastguard Worker // Polynomial long multiplication mod the polynomial of degree 32.
PolyMultiply(uint32_t * val,uint32_t m,uint32_t poly)83*9356374aSAndroid Build Coastguard Worker void PolyMultiply(uint32_t* val, uint32_t m, uint32_t poly) {
84*9356374aSAndroid Build Coastguard Worker   uint32_t l = *val;
85*9356374aSAndroid Build Coastguard Worker   uint32_t result = 0;
86*9356374aSAndroid Build Coastguard Worker   auto onebit = uint32_t{0x80000000u};
87*9356374aSAndroid Build Coastguard Worker   for (uint32_t one = onebit; one != 0; one >>= 1) {
88*9356374aSAndroid Build Coastguard Worker     if ((l & one) != 0) {
89*9356374aSAndroid Build Coastguard Worker       result ^= m;
90*9356374aSAndroid Build Coastguard Worker     }
91*9356374aSAndroid Build Coastguard Worker     if (m & 1) {
92*9356374aSAndroid Build Coastguard Worker       m = (m >> 1) ^ poly;
93*9356374aSAndroid Build Coastguard Worker     } else {
94*9356374aSAndroid Build Coastguard Worker       m >>= 1;
95*9356374aSAndroid Build Coastguard Worker     }
96*9356374aSAndroid Build Coastguard Worker   }
97*9356374aSAndroid Build Coastguard Worker   *val = result;
98*9356374aSAndroid Build Coastguard Worker }
99*9356374aSAndroid Build Coastguard Worker }  // namespace
100*9356374aSAndroid Build Coastguard Worker 
FillWordTable(uint32_t poly,uint32_t last,int word_size,Uint32By256 * t)101*9356374aSAndroid Build Coastguard Worker void CRCImpl::FillWordTable(uint32_t poly, uint32_t last, int word_size,
102*9356374aSAndroid Build Coastguard Worker                             Uint32By256* t) {
103*9356374aSAndroid Build Coastguard Worker   for (int j = 0; j != word_size; j++) {  // for each byte of extension....
104*9356374aSAndroid Build Coastguard Worker     t[j][0] = 0;                          // a zero has no effect
105*9356374aSAndroid Build Coastguard Worker     for (int i = 128; i != 0; i >>= 1) {  // fill in entries for powers of 2
106*9356374aSAndroid Build Coastguard Worker       if (j == 0 && i == 128) {
107*9356374aSAndroid Build Coastguard Worker         t[j][i] = last;  // top bit in last byte is given
108*9356374aSAndroid Build Coastguard Worker       } else {
109*9356374aSAndroid Build Coastguard Worker         // each successive power of two is derived from the previous
110*9356374aSAndroid Build Coastguard Worker         // one, either in this table, or the last table
111*9356374aSAndroid Build Coastguard Worker         uint32_t pred;
112*9356374aSAndroid Build Coastguard Worker         if (i == 128) {
113*9356374aSAndroid Build Coastguard Worker           pred = t[j - 1][1];
114*9356374aSAndroid Build Coastguard Worker         } else {
115*9356374aSAndroid Build Coastguard Worker           pred = t[j][i << 1];
116*9356374aSAndroid Build Coastguard Worker         }
117*9356374aSAndroid Build Coastguard Worker         // Advance the CRC by one bit (multiply by X, and take remainder
118*9356374aSAndroid Build Coastguard Worker         // through one step of polynomial long division)
119*9356374aSAndroid Build Coastguard Worker         if (pred & 1) {
120*9356374aSAndroid Build Coastguard Worker           t[j][i] = (pred >> 1) ^ poly;
121*9356374aSAndroid Build Coastguard Worker         } else {
122*9356374aSAndroid Build Coastguard Worker           t[j][i] = pred >> 1;
123*9356374aSAndroid Build Coastguard Worker         }
124*9356374aSAndroid Build Coastguard Worker       }
125*9356374aSAndroid Build Coastguard Worker     }
126*9356374aSAndroid Build Coastguard Worker     // CRCs have the property that CRC(a xor b) == CRC(a) xor CRC(b)
127*9356374aSAndroid Build Coastguard Worker     // so we can make all the tables for non-powers of two by
128*9356374aSAndroid Build Coastguard Worker     // xoring previously created entries.
129*9356374aSAndroid Build Coastguard Worker     for (int i = 2; i != 256; i <<= 1) {
130*9356374aSAndroid Build Coastguard Worker       for (int k = i + 1; k != (i << 1); k++) {
131*9356374aSAndroid Build Coastguard Worker         t[j][k] = t[j][i] ^ t[j][k - i];
132*9356374aSAndroid Build Coastguard Worker       }
133*9356374aSAndroid Build Coastguard Worker     }
134*9356374aSAndroid Build Coastguard Worker   }
135*9356374aSAndroid Build Coastguard Worker }
136*9356374aSAndroid Build Coastguard Worker 
FillZeroesTable(uint32_t poly,Uint32By256 * t)137*9356374aSAndroid Build Coastguard Worker int CRCImpl::FillZeroesTable(uint32_t poly, Uint32By256* t) {
138*9356374aSAndroid Build Coastguard Worker   uint32_t inc = 1;
139*9356374aSAndroid Build Coastguard Worker   inc <<= 31;
140*9356374aSAndroid Build Coastguard Worker 
141*9356374aSAndroid Build Coastguard Worker   // Extend by one zero bit. We know degree > 1 so (inc & 1) == 0.
142*9356374aSAndroid Build Coastguard Worker   inc >>= 1;
143*9356374aSAndroid Build Coastguard Worker 
144*9356374aSAndroid Build Coastguard Worker   // Now extend by 2, 4, and 8 bits, so now `inc` is extended by one zero byte.
145*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i < 3; ++i) {
146*9356374aSAndroid Build Coastguard Worker     PolyMultiply(&inc, inc, poly);
147*9356374aSAndroid Build Coastguard Worker   }
148*9356374aSAndroid Build Coastguard Worker 
149*9356374aSAndroid Build Coastguard Worker   int j = 0;
150*9356374aSAndroid Build Coastguard Worker   for (uint64_t inc_len = 1; inc_len != 0; inc_len <<= ZEROES_BASE_LG) {
151*9356374aSAndroid Build Coastguard Worker     // Every entry in the table adds an additional inc_len zeroes.
152*9356374aSAndroid Build Coastguard Worker     uint32_t v = inc;
153*9356374aSAndroid Build Coastguard Worker     for (int a = 1; a != ZEROES_BASE; a++) {
154*9356374aSAndroid Build Coastguard Worker       t[0][j] = v;
155*9356374aSAndroid Build Coastguard Worker       PolyMultiply(&v, inc, poly);
156*9356374aSAndroid Build Coastguard Worker       j++;
157*9356374aSAndroid Build Coastguard Worker     }
158*9356374aSAndroid Build Coastguard Worker     inc = v;
159*9356374aSAndroid Build Coastguard Worker   }
160*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(j <= 256, "");
161*9356374aSAndroid Build Coastguard Worker   return j;
162*9356374aSAndroid Build Coastguard Worker }
163*9356374aSAndroid Build Coastguard Worker 
164*9356374aSAndroid Build Coastguard Worker // Internal version of the "constructor".
NewInternal()165*9356374aSAndroid Build Coastguard Worker CRCImpl* CRCImpl::NewInternal() {
166*9356374aSAndroid Build Coastguard Worker   // Find an accelearated implementation first.
167*9356374aSAndroid Build Coastguard Worker   CRCImpl* result = TryNewCRC32AcceleratedX86ARMCombined();
168*9356374aSAndroid Build Coastguard Worker 
169*9356374aSAndroid Build Coastguard Worker   // Fall back to generic implementions if no acceleration is available.
170*9356374aSAndroid Build Coastguard Worker   if (result == nullptr) {
171*9356374aSAndroid Build Coastguard Worker     result = new CRC32();
172*9356374aSAndroid Build Coastguard Worker   }
173*9356374aSAndroid Build Coastguard Worker 
174*9356374aSAndroid Build Coastguard Worker   result->InitTables();
175*9356374aSAndroid Build Coastguard Worker 
176*9356374aSAndroid Build Coastguard Worker   return result;
177*9356374aSAndroid Build Coastguard Worker }
178*9356374aSAndroid Build Coastguard Worker 
179*9356374aSAndroid Build Coastguard Worker //  The 32-bit implementation
180*9356374aSAndroid Build Coastguard Worker 
InitTables()181*9356374aSAndroid Build Coastguard Worker void CRC32::InitTables() {
182*9356374aSAndroid Build Coastguard Worker   // Compute the table for extending a CRC by one byte.
183*9356374aSAndroid Build Coastguard Worker   Uint32By256* t = new Uint32By256[4];
184*9356374aSAndroid Build Coastguard Worker   FillWordTable(kCrc32cPoly, kCrc32cPoly, 1, t);
185*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i != 256; i++) {
186*9356374aSAndroid Build Coastguard Worker     this->table0_[i] = t[0][i];
187*9356374aSAndroid Build Coastguard Worker   }
188*9356374aSAndroid Build Coastguard Worker 
189*9356374aSAndroid Build Coastguard Worker   // Construct a table for updating the CRC by 4 bytes data followed by
190*9356374aSAndroid Build Coastguard Worker   // 12 bytes of zeroes.
191*9356374aSAndroid Build Coastguard Worker   //
192*9356374aSAndroid Build Coastguard Worker   // Note: the data word size could be larger than the CRC size; it might
193*9356374aSAndroid Build Coastguard Worker   // be slightly faster to use a 64-bit data word, but doing so doubles the
194*9356374aSAndroid Build Coastguard Worker   // table size.
195*9356374aSAndroid Build Coastguard Worker   uint32_t last = kCrc32cPoly;
196*9356374aSAndroid Build Coastguard Worker   const size_t size = 12;
197*9356374aSAndroid Build Coastguard Worker   for (size_t i = 0; i < size; ++i) {
198*9356374aSAndroid Build Coastguard Worker     last = (last >> 8) ^ this->table0_[last & 0xff];
199*9356374aSAndroid Build Coastguard Worker   }
200*9356374aSAndroid Build Coastguard Worker   FillWordTable(kCrc32cPoly, last, 4, t);
201*9356374aSAndroid Build Coastguard Worker   for (size_t b = 0; b < 4; ++b) {
202*9356374aSAndroid Build Coastguard Worker     for (int i = 0; i < 256; ++i) {
203*9356374aSAndroid Build Coastguard Worker       this->table_[b][i] = t[b][i];
204*9356374aSAndroid Build Coastguard Worker     }
205*9356374aSAndroid Build Coastguard Worker   }
206*9356374aSAndroid Build Coastguard Worker 
207*9356374aSAndroid Build Coastguard Worker   int j = FillZeroesTable(kCrc32cPoly, t);
208*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(j <= static_cast<int>(ABSL_ARRAYSIZE(this->zeroes_)), "");
209*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i < j; i++) {
210*9356374aSAndroid Build Coastguard Worker     this->zeroes_[i] = t[0][i];
211*9356374aSAndroid Build Coastguard Worker   }
212*9356374aSAndroid Build Coastguard Worker 
213*9356374aSAndroid Build Coastguard Worker   delete[] t;
214*9356374aSAndroid Build Coastguard Worker 
215*9356374aSAndroid Build Coastguard Worker   // Build up tables for _reversing_ the operation of doing CRC operations on
216*9356374aSAndroid Build Coastguard Worker   // zero bytes.
217*9356374aSAndroid Build Coastguard Worker 
218*9356374aSAndroid Build Coastguard Worker   // In C++, extending `crc` by a single zero bit is done by the following:
219*9356374aSAndroid Build Coastguard Worker   // (A)  bool low_bit_set = (crc & 1);
220*9356374aSAndroid Build Coastguard Worker   //      crc >>= 1;
221*9356374aSAndroid Build Coastguard Worker   //      if (low_bit_set) crc ^= kCrc32cPoly;
222*9356374aSAndroid Build Coastguard Worker   //
223*9356374aSAndroid Build Coastguard Worker   // In particular note that the high bit of `crc` after this operation will be
224*9356374aSAndroid Build Coastguard Worker   // set if and only if the low bit of `crc` was set before it.  This means that
225*9356374aSAndroid Build Coastguard Worker   // no information is lost, and the operation can be reversed, as follows:
226*9356374aSAndroid Build Coastguard Worker   // (B)  bool high_bit_set = (crc & 0x80000000u);
227*9356374aSAndroid Build Coastguard Worker   //      if (high_bit_set) crc ^= kCrc32cPoly;
228*9356374aSAndroid Build Coastguard Worker   //      crc <<= 1;
229*9356374aSAndroid Build Coastguard Worker   //      if (high_bit_set) crc ^= 1;
230*9356374aSAndroid Build Coastguard Worker   //
231*9356374aSAndroid Build Coastguard Worker   // Or, equivalently:
232*9356374aSAndroid Build Coastguard Worker   // (C)  bool high_bit_set = (crc & 0x80000000u);
233*9356374aSAndroid Build Coastguard Worker   //      crc <<= 1;
234*9356374aSAndroid Build Coastguard Worker   //      if (high_bit_set) crc ^= ((kCrc32cPoly << 1) ^ 1);
235*9356374aSAndroid Build Coastguard Worker   //
236*9356374aSAndroid Build Coastguard Worker   // The last observation is, if we store our checksums in variable `rcrc`,
237*9356374aSAndroid Build Coastguard Worker   // with order of the bits reversed, the inverse operation becomes:
238*9356374aSAndroid Build Coastguard Worker   // (D)  bool low_bit_set = (rcrc & 1);
239*9356374aSAndroid Build Coastguard Worker   //      rcrc >>= 1;
240*9356374aSAndroid Build Coastguard Worker   //      if (low_bit_set) rcrc ^= ReverseBits((kCrc32cPoly << 1) ^ 1)
241*9356374aSAndroid Build Coastguard Worker   //
242*9356374aSAndroid Build Coastguard Worker   // This is the same algorithm (A) that we started with, only with a different
243*9356374aSAndroid Build Coastguard Worker   // polynomial bit pattern.  This means that by building up our tables with
244*9356374aSAndroid Build Coastguard Worker   // this alternate polynomial, we can apply the CRC algorithms to a
245*9356374aSAndroid Build Coastguard Worker   // bit-reversed CRC checksum to perform inverse zero-extension.
246*9356374aSAndroid Build Coastguard Worker 
247*9356374aSAndroid Build Coastguard Worker   const uint32_t kCrc32cUnextendPoly =
248*9356374aSAndroid Build Coastguard Worker       ReverseBits(static_cast<uint32_t>((kCrc32cPoly << 1) ^ 1));
249*9356374aSAndroid Build Coastguard Worker   FillWordTable(kCrc32cUnextendPoly, kCrc32cUnextendPoly, 1, &reverse_table0_);
250*9356374aSAndroid Build Coastguard Worker 
251*9356374aSAndroid Build Coastguard Worker   j = FillZeroesTable(kCrc32cUnextendPoly, &reverse_zeroes_);
252*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(j <= static_cast<int>(ABSL_ARRAYSIZE(this->reverse_zeroes_)),
253*9356374aSAndroid Build Coastguard Worker                  "");
254*9356374aSAndroid Build Coastguard Worker }
255*9356374aSAndroid Build Coastguard Worker 
Extend(uint32_t * crc,const void * bytes,size_t length) const256*9356374aSAndroid Build Coastguard Worker void CRC32::Extend(uint32_t* crc, const void* bytes, size_t length) const {
257*9356374aSAndroid Build Coastguard Worker   const uint8_t* p = static_cast<const uint8_t*>(bytes);
258*9356374aSAndroid Build Coastguard Worker   const uint8_t* e = p + length;
259*9356374aSAndroid Build Coastguard Worker   uint32_t l = *crc;
260*9356374aSAndroid Build Coastguard Worker 
261*9356374aSAndroid Build Coastguard Worker   auto step_one_byte = [this, &p, &l]() {
262*9356374aSAndroid Build Coastguard Worker     int c = (l & 0xff) ^ *p++;
263*9356374aSAndroid Build Coastguard Worker     l = this->table0_[c] ^ (l >> 8);
264*9356374aSAndroid Build Coastguard Worker   };
265*9356374aSAndroid Build Coastguard Worker 
266*9356374aSAndroid Build Coastguard Worker   if (kNeedAlignedLoads) {
267*9356374aSAndroid Build Coastguard Worker     // point x at first 4-byte aligned byte in string. this might be past the
268*9356374aSAndroid Build Coastguard Worker     // end of the string.
269*9356374aSAndroid Build Coastguard Worker     const uint8_t* x = RoundUp<4>(p);
270*9356374aSAndroid Build Coastguard Worker     if (x <= e) {
271*9356374aSAndroid Build Coastguard Worker       // Process bytes until finished or p is 4-byte aligned
272*9356374aSAndroid Build Coastguard Worker       while (p != x) {
273*9356374aSAndroid Build Coastguard Worker         step_one_byte();
274*9356374aSAndroid Build Coastguard Worker       }
275*9356374aSAndroid Build Coastguard Worker     }
276*9356374aSAndroid Build Coastguard Worker   }
277*9356374aSAndroid Build Coastguard Worker 
278*9356374aSAndroid Build Coastguard Worker   const size_t kSwathSize = 16;
279*9356374aSAndroid Build Coastguard Worker   if (static_cast<size_t>(e - p) >= kSwathSize) {
280*9356374aSAndroid Build Coastguard Worker     // Load one swath of data into the operating buffers.
281*9356374aSAndroid Build Coastguard Worker     uint32_t buf0 = absl::little_endian::Load32(p) ^ l;
282*9356374aSAndroid Build Coastguard Worker     uint32_t buf1 = absl::little_endian::Load32(p + 4);
283*9356374aSAndroid Build Coastguard Worker     uint32_t buf2 = absl::little_endian::Load32(p + 8);
284*9356374aSAndroid Build Coastguard Worker     uint32_t buf3 = absl::little_endian::Load32(p + 12);
285*9356374aSAndroid Build Coastguard Worker     p += kSwathSize;
286*9356374aSAndroid Build Coastguard Worker 
287*9356374aSAndroid Build Coastguard Worker     // Increment a CRC value by a "swath"; this combines the four bytes
288*9356374aSAndroid Build Coastguard Worker     // starting at `ptr` and twelve zero bytes, so that four CRCs can be
289*9356374aSAndroid Build Coastguard Worker     // built incrementally and combined at the end.
290*9356374aSAndroid Build Coastguard Worker     const auto step_swath = [this](uint32_t crc_in, const std::uint8_t* ptr) {
291*9356374aSAndroid Build Coastguard Worker       return absl::little_endian::Load32(ptr) ^
292*9356374aSAndroid Build Coastguard Worker              this->table_[3][crc_in & 0xff] ^
293*9356374aSAndroid Build Coastguard Worker              this->table_[2][(crc_in >> 8) & 0xff] ^
294*9356374aSAndroid Build Coastguard Worker              this->table_[1][(crc_in >> 16) & 0xff] ^
295*9356374aSAndroid Build Coastguard Worker              this->table_[0][crc_in >> 24];
296*9356374aSAndroid Build Coastguard Worker     };
297*9356374aSAndroid Build Coastguard Worker 
298*9356374aSAndroid Build Coastguard Worker     // Run one CRC calculation step over all swaths in one 16-byte stride
299*9356374aSAndroid Build Coastguard Worker     const auto step_stride = [&]() {
300*9356374aSAndroid Build Coastguard Worker       buf0 = step_swath(buf0, p);
301*9356374aSAndroid Build Coastguard Worker       buf1 = step_swath(buf1, p + 4);
302*9356374aSAndroid Build Coastguard Worker       buf2 = step_swath(buf2, p + 8);
303*9356374aSAndroid Build Coastguard Worker       buf3 = step_swath(buf3, p + 12);
304*9356374aSAndroid Build Coastguard Worker       p += 16;
305*9356374aSAndroid Build Coastguard Worker     };
306*9356374aSAndroid Build Coastguard Worker 
307*9356374aSAndroid Build Coastguard Worker     // Process kStride interleaved swaths through the data in parallel.
308*9356374aSAndroid Build Coastguard Worker     while ((e - p) > kPrefetchHorizon) {
309*9356374aSAndroid Build Coastguard Worker       PrefetchToLocalCacheNta(
310*9356374aSAndroid Build Coastguard Worker           reinterpret_cast<const void*>(p + kPrefetchHorizon));
311*9356374aSAndroid Build Coastguard Worker       // Process 64 bytes at a time
312*9356374aSAndroid Build Coastguard Worker       step_stride();
313*9356374aSAndroid Build Coastguard Worker       step_stride();
314*9356374aSAndroid Build Coastguard Worker       step_stride();
315*9356374aSAndroid Build Coastguard Worker       step_stride();
316*9356374aSAndroid Build Coastguard Worker     }
317*9356374aSAndroid Build Coastguard Worker     while (static_cast<size_t>(e - p) >= kSwathSize) {
318*9356374aSAndroid Build Coastguard Worker       step_stride();
319*9356374aSAndroid Build Coastguard Worker     }
320*9356374aSAndroid Build Coastguard Worker 
321*9356374aSAndroid Build Coastguard Worker     // Now advance one word at a time as far as possible. This isn't worth
322*9356374aSAndroid Build Coastguard Worker     // doing if we have word-advance tables.
323*9356374aSAndroid Build Coastguard Worker     while (static_cast<size_t>(e - p) >= 4) {
324*9356374aSAndroid Build Coastguard Worker       buf0 = step_swath(buf0, p);
325*9356374aSAndroid Build Coastguard Worker       uint32_t tmp = buf0;
326*9356374aSAndroid Build Coastguard Worker       buf0 = buf1;
327*9356374aSAndroid Build Coastguard Worker       buf1 = buf2;
328*9356374aSAndroid Build Coastguard Worker       buf2 = buf3;
329*9356374aSAndroid Build Coastguard Worker       buf3 = tmp;
330*9356374aSAndroid Build Coastguard Worker       p += 4;
331*9356374aSAndroid Build Coastguard Worker     }
332*9356374aSAndroid Build Coastguard Worker 
333*9356374aSAndroid Build Coastguard Worker     // Combine the results from the different swaths. This is just a CRC
334*9356374aSAndroid Build Coastguard Worker     // on the data values in the bufX words.
335*9356374aSAndroid Build Coastguard Worker     auto combine_one_word = [this](uint32_t crc_in, uint32_t w) {
336*9356374aSAndroid Build Coastguard Worker       w ^= crc_in;
337*9356374aSAndroid Build Coastguard Worker       for (size_t i = 0; i < 4; ++i) {
338*9356374aSAndroid Build Coastguard Worker         w = (w >> 8) ^ this->table0_[w & 0xff];
339*9356374aSAndroid Build Coastguard Worker       }
340*9356374aSAndroid Build Coastguard Worker       return w;
341*9356374aSAndroid Build Coastguard Worker     };
342*9356374aSAndroid Build Coastguard Worker 
343*9356374aSAndroid Build Coastguard Worker     l = combine_one_word(0, buf0);
344*9356374aSAndroid Build Coastguard Worker     l = combine_one_word(l, buf1);
345*9356374aSAndroid Build Coastguard Worker     l = combine_one_word(l, buf2);
346*9356374aSAndroid Build Coastguard Worker     l = combine_one_word(l, buf3);
347*9356374aSAndroid Build Coastguard Worker   }
348*9356374aSAndroid Build Coastguard Worker 
349*9356374aSAndroid Build Coastguard Worker   // Process the last few bytes
350*9356374aSAndroid Build Coastguard Worker   while (p != e) {
351*9356374aSAndroid Build Coastguard Worker     step_one_byte();
352*9356374aSAndroid Build Coastguard Worker   }
353*9356374aSAndroid Build Coastguard Worker 
354*9356374aSAndroid Build Coastguard Worker   *crc = l;
355*9356374aSAndroid Build Coastguard Worker }
356*9356374aSAndroid Build Coastguard Worker 
ExtendByZeroesImpl(uint32_t * crc,size_t length,const uint32_t zeroes_table[256],const uint32_t poly_table[256])357*9356374aSAndroid Build Coastguard Worker void CRC32::ExtendByZeroesImpl(uint32_t* crc, size_t length,
358*9356374aSAndroid Build Coastguard Worker                                const uint32_t zeroes_table[256],
359*9356374aSAndroid Build Coastguard Worker                                const uint32_t poly_table[256]) {
360*9356374aSAndroid Build Coastguard Worker   if (length != 0) {
361*9356374aSAndroid Build Coastguard Worker     uint32_t l = *crc;
362*9356374aSAndroid Build Coastguard Worker     // For each ZEROES_BASE_LG bits in length
363*9356374aSAndroid Build Coastguard Worker     // (after the low-order bits have been removed)
364*9356374aSAndroid Build Coastguard Worker     // we lookup the appropriate polynomial in the zeroes_ array
365*9356374aSAndroid Build Coastguard Worker     // and do a polynomial long multiplication (mod the CRC polynomial)
366*9356374aSAndroid Build Coastguard Worker     // to extend the CRC by the appropriate number of bits.
367*9356374aSAndroid Build Coastguard Worker     for (int i = 0; length != 0;
368*9356374aSAndroid Build Coastguard Worker          i += ZEROES_BASE - 1, length >>= ZEROES_BASE_LG) {
369*9356374aSAndroid Build Coastguard Worker       int c = length & (ZEROES_BASE - 1);  // pick next ZEROES_BASE_LG bits
370*9356374aSAndroid Build Coastguard Worker       if (c != 0) {                        // if they are not zero,
371*9356374aSAndroid Build Coastguard Worker                                            // multiply by entry in table
372*9356374aSAndroid Build Coastguard Worker         // Build a table to aid in multiplying 2 bits at a time.
373*9356374aSAndroid Build Coastguard Worker         // It takes too long to build tables for more bits.
374*9356374aSAndroid Build Coastguard Worker         uint64_t m = zeroes_table[c + i - 1];
375*9356374aSAndroid Build Coastguard Worker         m <<= 1;
376*9356374aSAndroid Build Coastguard Worker         uint64_t m2 = m << 1;
377*9356374aSAndroid Build Coastguard Worker         uint64_t mtab[4] = {0, m, m2, m2 ^ m};
378*9356374aSAndroid Build Coastguard Worker 
379*9356374aSAndroid Build Coastguard Worker         // Do the multiply one byte at a time.
380*9356374aSAndroid Build Coastguard Worker         uint64_t result = 0;
381*9356374aSAndroid Build Coastguard Worker         for (int x = 0; x < 32; x += 8) {
382*9356374aSAndroid Build Coastguard Worker           // The carry-less multiply.
383*9356374aSAndroid Build Coastguard Worker           result ^= mtab[l & 3] ^ (mtab[(l >> 2) & 3] << 2) ^
384*9356374aSAndroid Build Coastguard Worker                     (mtab[(l >> 4) & 3] << 4) ^ (mtab[(l >> 6) & 3] << 6);
385*9356374aSAndroid Build Coastguard Worker           l >>= 8;
386*9356374aSAndroid Build Coastguard Worker 
387*9356374aSAndroid Build Coastguard Worker           // Reduce modulo the polynomial
388*9356374aSAndroid Build Coastguard Worker           result = (result >> 8) ^ poly_table[result & 0xff];
389*9356374aSAndroid Build Coastguard Worker         }
390*9356374aSAndroid Build Coastguard Worker         l = static_cast<uint32_t>(result);
391*9356374aSAndroid Build Coastguard Worker       }
392*9356374aSAndroid Build Coastguard Worker     }
393*9356374aSAndroid Build Coastguard Worker     *crc = l;
394*9356374aSAndroid Build Coastguard Worker   }
395*9356374aSAndroid Build Coastguard Worker }
396*9356374aSAndroid Build Coastguard Worker 
ExtendByZeroes(uint32_t * crc,size_t length) const397*9356374aSAndroid Build Coastguard Worker void CRC32::ExtendByZeroes(uint32_t* crc, size_t length) const {
398*9356374aSAndroid Build Coastguard Worker   return CRC32::ExtendByZeroesImpl(crc, length, zeroes_, table0_);
399*9356374aSAndroid Build Coastguard Worker }
400*9356374aSAndroid Build Coastguard Worker 
UnextendByZeroes(uint32_t * crc,size_t length) const401*9356374aSAndroid Build Coastguard Worker void CRC32::UnextendByZeroes(uint32_t* crc, size_t length) const {
402*9356374aSAndroid Build Coastguard Worker   // See the comment in CRC32::InitTables() for an explanation of the algorithm
403*9356374aSAndroid Build Coastguard Worker   // below.
404*9356374aSAndroid Build Coastguard Worker   *crc = ReverseBits(*crc);
405*9356374aSAndroid Build Coastguard Worker   ExtendByZeroesImpl(crc, length, reverse_zeroes_, reverse_table0_);
406*9356374aSAndroid Build Coastguard Worker   *crc = ReverseBits(*crc);
407*9356374aSAndroid Build Coastguard Worker }
408*9356374aSAndroid Build Coastguard Worker 
Scramble(uint32_t * crc) const409*9356374aSAndroid Build Coastguard Worker void CRC32::Scramble(uint32_t* crc) const {
410*9356374aSAndroid Build Coastguard Worker   // Rotate by near half the word size plus 1.  See the scramble comment in
411*9356374aSAndroid Build Coastguard Worker   // crc_internal.h for an explanation.
412*9356374aSAndroid Build Coastguard Worker   constexpr int scramble_rotate = (32 / 2) + 1;
413*9356374aSAndroid Build Coastguard Worker   *crc = RotateRight<uint32_t>(static_cast<unsigned int>(*crc + kScrambleLo),
414*9356374aSAndroid Build Coastguard Worker                                32, scramble_rotate) &
415*9356374aSAndroid Build Coastguard Worker          MaskOfLength<uint32_t>(32);
416*9356374aSAndroid Build Coastguard Worker }
417*9356374aSAndroid Build Coastguard Worker 
Unscramble(uint32_t * crc) const418*9356374aSAndroid Build Coastguard Worker void CRC32::Unscramble(uint32_t* crc) const {
419*9356374aSAndroid Build Coastguard Worker   constexpr int scramble_rotate = (32 / 2) + 1;
420*9356374aSAndroid Build Coastguard Worker   uint64_t rotated = RotateRight<uint32_t>(static_cast<unsigned int>(*crc), 32,
421*9356374aSAndroid Build Coastguard Worker                                            32 - scramble_rotate);
422*9356374aSAndroid Build Coastguard Worker   *crc = (rotated - kScrambleLo) & MaskOfLength<uint32_t>(32);
423*9356374aSAndroid Build Coastguard Worker }
424*9356374aSAndroid Build Coastguard Worker 
425*9356374aSAndroid Build Coastguard Worker // Constructor and destructor for base class CRC.
~CRC()426*9356374aSAndroid Build Coastguard Worker CRC::~CRC() {}
CRC()427*9356374aSAndroid Build Coastguard Worker CRC::CRC() {}
428*9356374aSAndroid Build Coastguard Worker 
429*9356374aSAndroid Build Coastguard Worker // The "constructor" for a CRC32C with a standard polynomial.
Crc32c()430*9356374aSAndroid Build Coastguard Worker CRC* CRC::Crc32c() {
431*9356374aSAndroid Build Coastguard Worker   static CRC* singleton = CRCImpl::NewInternal();
432*9356374aSAndroid Build Coastguard Worker   return singleton;
433*9356374aSAndroid Build Coastguard Worker }
434*9356374aSAndroid Build Coastguard Worker 
435*9356374aSAndroid Build Coastguard Worker }  // namespace crc_internal
436*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
437*9356374aSAndroid Build Coastguard Worker }  // namespace absl
438