Coverage Report

Created: 2025-11-09 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glaze/include/glaze/api/xxh64.hpp
Line
Count
Source
1
// Glaze Library
2
// For the license information refer to glaze.hpp
3
4
// Copyright (c) 2015 Daniel Kirchner
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining a copy
7
// of this software and associated documentation files (the "Software"), to deal
8
// in the Software without restriction, including without limitation the rights
9
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
// copies of the Software, and to permit persons to whom the Software is
11
// furnished to do so, subject to the following conditions:
12
//
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
// THE SOFTWARE.
23
24
#pragma once
25
26
#include <cstdint>
27
28
// https://github.com/Cyan4973/xxHash
29
// http://cyan4973.github.io/xxHash/
30
31
struct xxh64
32
{
33
   static constexpr uint64_t hash(const char* p, uint64_t len, uint64_t seed)
34
0
   {
35
0
      return finalize((len >= 32 ? h32bytes(p, len, seed) : seed + PRIME5) + len, p + (len & ~0x1F), len & 0x1F);
36
0
   }
37
38
  private:
39
   static constexpr uint64_t PRIME1 = 11400714785074694791ULL;
40
   static constexpr uint64_t PRIME2 = 14029467366897019727ULL;
41
   static constexpr uint64_t PRIME3 = 1609587929392839161ULL;
42
   static constexpr uint64_t PRIME4 = 9650029242287828579ULL;
43
   static constexpr uint64_t PRIME5 = 2870177450012600261ULL;
44
45
0
   static constexpr uint64_t rotl(uint64_t x, int r) { return ((x << r) | (x >> (64 - r))); }
46
   static constexpr uint64_t mix1(const uint64_t h, const uint64_t prime, int rshift)
47
0
   {
48
0
      return (h ^ (h >> rshift)) * prime;
49
0
   }
50
0
   static constexpr uint64_t mix2(const uint64_t p, const uint64_t v = 0) { return rotl(v + p * PRIME2, 31) * PRIME1; }
51
0
   static constexpr uint64_t mix3(const uint64_t h, const uint64_t v) { return (h ^ mix2(v)) * PRIME1 + PRIME4; }
52
#ifdef XXH64_BIG_ENDIAN
53
   static constexpr uint32_t endian32(const char* v)
54
   {
55
      return uint32_t(uint8_t(v[3])) | (uint32_t(uint8_t(v[2])) << 8) | (uint32_t(uint8_t(v[1])) << 16) |
56
             (uint32_t(uint8_t(v[0])) << 24);
57
   }
58
   static constexpr uint64_t endian64(const char* v)
59
   {
60
      return uint64_t(uint8_t(v[7])) | (uint64_t(uint8_t(v[6])) << 8) | (uint64_t(uint8_t(v[5])) << 16) |
61
             (uint64_t(uint8_t(v[4])) << 24) | (uint64_t(uint8_t(v[3])) << 32) | (uint64_t(uint8_t(v[2])) << 40) |
62
             (uint64_t(uint8_t(v[1])) << 48) | (uint64_t(uint8_t(v[0])) << 56);
63
   }
64
#else
65
   static constexpr uint32_t endian32(const char* v)
66
0
   {
67
0
      return uint32_t(uint8_t(v[0])) | (uint32_t(uint8_t(v[1])) << 8) | (uint32_t(uint8_t(v[2])) << 16) |
68
0
             (uint32_t(uint8_t(v[3])) << 24);
69
0
   }
70
   static constexpr uint64_t endian64(const char* v)
71
0
   {
72
0
      return uint64_t(uint8_t(v[0])) | (uint64_t(uint8_t(v[1])) << 8) | (uint64_t(uint8_t(v[2])) << 16) |
73
0
             (uint64_t(uint8_t(v[3])) << 24) | (uint64_t(uint8_t(v[4])) << 32) | (uint64_t(uint8_t(v[5])) << 40) |
74
0
             (uint64_t(uint8_t(v[6])) << 48) | (uint64_t(uint8_t(v[7])) << 56);
75
0
   }
76
#endif
77
0
   static constexpr uint64_t fetch64(const char* p, const uint64_t v = 0) { return mix2(endian64(p), v); }
78
0
   static constexpr uint64_t fetch32(const char* p) { return uint64_t(endian32(p)) * PRIME1; }
79
0
   static constexpr uint64_t fetch8(const char* p) { return uint8_t(*p) * PRIME5; }
80
   static constexpr uint64_t finalize(const uint64_t h, const char* p, uint64_t len)
81
0
   {
82
0
      return (len >= 8) ? (finalize(rotl(h ^ fetch64(p), 27) * PRIME1 + PRIME4, p + 8, len - 8))
83
0
                        : ((len >= 4) ? (finalize(rotl(h ^ fetch32(p), 23) * PRIME2 + PRIME3, p + 4, len - 4))
84
0
                                      : ((len > 0) ? (finalize(rotl(h ^ fetch8(p), 11) * PRIME1, p + 1, len - 1))
85
0
                                                   : (mix1(mix1(mix1(h, PRIME2, 33), PRIME3, 29), 1, 32))));
86
0
   }
87
   static constexpr uint64_t h32bytes(const char* p, uint64_t len, const uint64_t v1, const uint64_t v2,
88
                                      const uint64_t v3, const uint64_t v4)
89
0
   {
90
0
      return (len >= 32)
91
0
                ? h32bytes(p + 32, len - 32, fetch64(p, v1), fetch64(p + 8, v2), fetch64(p + 16, v3),
92
0
                           fetch64(p + 24, v4))
93
0
                : mix3(mix3(mix3(mix3(rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18), v1), v2), v3), v4);
94
0
   }
95
   static constexpr uint64_t h32bytes(const char* p, uint64_t len, const uint64_t seed)
96
0
   {
97
0
      return h32bytes(p, len, seed + PRIME1 + PRIME2, seed + PRIME2, seed, seed - PRIME1);
98
0
   }
99
};