odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

checksumcrc32simdimpl_p.h (3465B)


      1 // This file is part of Blend2D project <https://blend2d.com>
      2 //
      3 // See blend2d.h or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 
      6 #ifndef BLEND2D_COMPRESSION_CHECKSUMCRC32SIMDIMPL_P_H_INCLUDED
      7 #define BLEND2D_COMPRESSION_CHECKSUMCRC32SIMDIMPL_P_H_INCLUDED
      8 
      9 #include "../api-internal_p.h"
     10 #include "../compression/checksum_p.h"
     11 #include "../simd/simd_p.h"
     12 
     13 //! \cond INTERNAL
     14 
     15 namespace bl::Compression::Checksum {
     16 namespace {
     17 
     18 static constexpr uint64_t kConstK1 = 0x0154442BD4u;
     19 static constexpr uint64_t kConstK2 = 0x01C6E41596u;
     20 static constexpr uint64_t kConstK3 = 0x01751997D0u;
     21 static constexpr uint64_t kConstK4 = 0x00CCAA009Eu;
     22 static constexpr uint64_t kConstK5 = 0x0163CD6124u;
     23 static constexpr uint64_t kConstP0 = 0x01DB710641u;
     24 static constexpr uint64_t kConstP1 = 0x01F7011641u;
     25 
     26 BL_INLINE uint32_t crc32_update_clmul128(uint32_t checksum, const uint8_t* data, size_t size) noexcept {
     27   using namespace SIMD;
     28 
     29   size_t n = bl_min<size_t>(IntOps::align_up_diff(uintptr_t(data), 16u), size);
     30   size -= n;
     31 
     32   BL_NOUNROLL
     33   while (n) {
     34     checksum = crc32_update_byte(checksum, *data++);
     35     n--;
     36   }
     37 
     38   // Process 64-byte chunks.
     39   if (size >= 64u) {
     40     Vec2xU64 x1 = loada_128<Vec2xU64>(data +  0u) ^ cast_from_u32<Vec2xU64>(checksum);
     41     Vec2xU64 x2 = loada_128<Vec2xU64>(data + 16u);
     42     Vec2xU64 x3 = loada_128<Vec2xU64>(data + 32u);
     43     Vec2xU64 x4 = loada_128<Vec2xU64>(data + 48u);
     44     Vec2xU64 k2k1 = make128_u64(kConstK2, kConstK1);
     45 
     46     data += 64u;
     47     size -= 64u;
     48 
     49     BL_NOUNROLL
     50     while (size >= 64u) {
     51       Vec2xU64 t1 = clmul_u128_ll(x1, k2k1);
     52       Vec2xU64 t2 = clmul_u128_ll(x2, k2k1);
     53       Vec2xU64 t3 = clmul_u128_ll(x3, k2k1);
     54       Vec2xU64 t4 = clmul_u128_ll(x4, k2k1);
     55 
     56       x1 = clmul_u128_hh(x1, k2k1) ^ t1;
     57       x2 = clmul_u128_hh(x2, k2k1) ^ t2;
     58       x3 = clmul_u128_hh(x3, k2k1) ^ t3;
     59       x4 = clmul_u128_hh(x4, k2k1) ^ t4;
     60 
     61       x1 ^= loada_128<Vec2xU64>(data +  0u);
     62       x2 ^= loada_128<Vec2xU64>(data + 16u);
     63       x3 ^= loada_128<Vec2xU64>(data + 32u);
     64       x4 ^= loada_128<Vec2xU64>(data + 48u);
     65 
     66       data += 64u;
     67       size -= 64u;
     68     }
     69 
     70     // Fold 4x128 bits into 128 bits.
     71     Vec2xU64 k4k3 = make128_u64(kConstK4, kConstK3);
     72     Vec2xU64 t1;
     73 
     74     t1 = clmul_u128_ll(x1, k4k3) ^ x2;
     75     x1 = clmul_u128_hh(x1, k4k3) ^ t1;
     76 
     77     t1 = clmul_u128_ll(x1, k4k3) ^ x3;
     78     x1 = clmul_u128_hh(x1, k4k3) ^ t1;
     79 
     80     t1 = clmul_u128_ll(x1, k4k3) ^ x4;
     81     x1 = clmul_u128_hh(x1, k4k3) ^ t1;
     82 
     83     // Process remaining 16-byte chunks.
     84     BL_NOUNROLL
     85     while (size >= 16u) {
     86       t1 = clmul_u128_ll(x1, k4k3);
     87       x1 = clmul_u128_hh(x1, k4k3) ^ t1;
     88       x1 ^= loada_128<Vec2xU64>(data);
     89 
     90       data += 16u;
     91       size -= 16u;
     92     }
     93 
     94     // Fold 128 bits to 64 bits.
     95     t1 = clmul_u128_lh(x1, k4k3);
     96     x1 = srlb_u128<8>(x1) ^ t1;
     97 
     98     Vec2xU64 k5 = make128_u64(kConstK5);
     99     Vec2xU64 lo32 = make128_u64(0x00000000FFFFFFFFu);
    100 
    101     t1 = srlb_u128<4>(x1);
    102     x1 = clmul_u128_ll(x1 & lo32, k5) ^ t1;
    103 
    104     // Reduce 64 bits to 32 bits.
    105     Vec2xU64 poly = make128_u64(kConstP1, kConstP0);
    106     t1 = clmul_u128_lh(x1 & lo32, poly);
    107     x1 ^= clmul_u128_ll(t1 & lo32, poly);
    108 
    109     checksum = extract_u32<1>(x1);
    110   }
    111 
    112   BL_NOUNROLL
    113   while (size) {
    114     checksum = crc32_update_byte(checksum, *data++);
    115     size--;
    116   }
    117 
    118   return checksum;
    119 }
    120 
    121 } // {anonymous}
    122 } // {bl::Compression::Checksum}
    123 
    124 //! \endcond
    125 
    126 #endif // BLEND2D_COMPRESSION_CHECKSUMCRC32SIMDIMPL_P_H_INCLUDED