Coverage Report

Created: 2025-07-11 06:05

/src/alembic/lib/Alembic/Util/Murmur3.cpp
Line
Count
Source (jump to first uncovered line)
1
//-*****************************************************************************
2
//
3
// Copyright (c) 2009-2012,
4
//  Sony Pictures Imageworks Inc. and
5
//  Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6
//
7
// All rights reserved.
8
//
9
// Redistribution and use in source and binary forms, with or without
10
// modification, are permitted provided that the following conditions are
11
// met:
12
// *       Redistributions of source code must retain the above copyright
13
// notice, this list of conditions and the following disclaimer.
14
// *       Redistributions in binary form must reproduce the above
15
// copyright notice, this list of conditions and the following disclaimer
16
// in the documentation and/or other materials provided with the
17
// distribution.
18
// *       Neither the name of Industrial Light & Magic nor the names of
19
// its contributors may be used to endorse or promote products derived
20
// from this software without specific prior written permission.
21
//
22
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
//
34
//-*****************************************************************************
35
36
// MurmurHash3 was written by Austin Appleby, and is placed in the public
37
// domain. The author hereby disclaims copyright to this source code.
38
39
#include <Alembic/Util/Murmur3.h>
40
#include <Alembic/Util/PlainOldDataType.h>
41
42
#if defined(__APPLE__) || defined(__FreeBSD__)
43
#include <machine/endian.h>
44
#elif !defined(_MSC_VER) && !defined(__MINGW32__)
45
#include <endian.h>
46
#endif
47
48
namespace Alembic {
49
namespace Util {
50
namespace ALEMBIC_VERSION_NS {
51
52
//-*****************************************************************************
53
void MurmurHash3_x64_128 ( const void * key, const size_t len,
54
                           const size_t podSize, void * out )
55
0
{
56
0
    const uint8_t * data = (const uint8_t*)key;
57
0
    const size_t nblocks = len / 16;
58
59
0
    uint64_t h1 = 0;
60
0
    uint64_t h2 = 0;
61
62
63
#ifdef _MSC_VER
64
    uint64_t c1 = 0x87c37b91114253d5LL;
65
    uint64_t c2 = 0x4cf5ad432745937fLL;
66
#else
67
0
    uint64_t c1 = 0x87c37b91114253d5ULL;
68
0
    uint64_t c2 = 0x4cf5ad432745937fULL;
69
0
#endif
70
71
    //----------
72
    // body
73
74
0
    const uint64_t * blocks = (const uint64_t *)(data);
75
76
0
    for(size_t i = 0; i < nblocks; i++)
77
0
    {
78
79
0
        uint64_t k1 = blocks[i*2];
80
0
        uint64_t k2 = blocks[i*2+1];
81
82
83
#if (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN)
84
        if (podSize == 8)
85
        {
86
            k1 = (k1>>56) |
87
                ((k1<<40) & 0x00FF000000000000ULL) |
88
                ((k1<<24) & 0x0000FF0000000000ULL) |
89
                ((k1<<8)  & 0x000000FF00000000ULL) |
90
                ((k1>>8)  & 0x00000000FF000000ULL) |
91
                ((k1>>24) & 0x0000000000FF0000ULL) |
92
                ((k1>>40) & 0x000000000000FF00ULL) |
93
                (k1<<56);
94
95
            k2 = (k2>>56) |
96
                ((k2<<40) & 0x00FF000000000000ULL) |
97
                ((k2<<24) & 0x0000FF0000000000ULL) |
98
                ((k2<<8)  & 0x000000FF00000000ULL) |
99
                ((k2>>8)  & 0x00000000FF000000ULL) |
100
                ((k2>>24) & 0x0000000000FF0000ULL) |
101
                ((k2>>40) & 0x000000000000FF00ULL) |
102
                 (k2<<56);
103
        }
104
        else if (podSize == 4)
105
        {
106
            k1 =((k1<<24) & 0xFF00000000000000ULL) |
107
                ((k1<<8)  & 0x00FF000000000000ULL) |
108
                ((k1>>8)  & 0x0000FF0000000000ULL) |
109
                ((k1>>24) & 0x000000FF00000000ULL) |
110
                ((k1<<24) & 0x00000000FF000000ULL) |
111
                ((k1<<8)  & 0x0000000000FF0000ULL) |
112
                ((k1>>8)  & 0x000000000000FF00ULL) |
113
                ((k1>>24) & 0x00000000000000FFULL);
114
115
            k2 =((k2<<24) & 0xFF00000000000000ULL) |
116
                ((k2<<8)  & 0x00FF000000000000ULL) |
117
                ((k2>>8)  & 0x0000FF0000000000ULL) |
118
                ((k2>>24) & 0x000000FF00000000ULL) |
119
                ((k2<<24) & 0x00000000FF000000ULL) |
120
                ((k2<<8)  & 0x0000000000FF0000ULL) |
121
                ((k2>>8)  & 0x000000000000FF00ULL) |
122
                ((k2>>24) & 0x00000000000000FFULL);
123
        }
124
        else if (podSize == 2)
125
        {
126
            k1 =((k1<<8) & 0xFF00000000000000ULL) |
127
                ((k1>>8) & 0x00FF000000000000ULL) |
128
                ((k1<<8) & 0x0000FF0000000000ULL) |
129
                ((k1>>8) & 0x000000FF00000000ULL) |
130
                ((k1<<8) & 0x00000000FF000000ULL) |
131
                ((k1>>8) & 0x0000000000FF0000ULL) |
132
                ((k1<<8) & 0x000000000000FF00ULL) |
133
                ((k1>>8) & 0x00000000000000FFULL);
134
135
            k2 =((k2<<8) & 0xFF00000000000000ULL) |
136
                ((k2>>8) & 0x00FF000000000000ULL) |
137
                ((k2<<8) & 0x0000FF0000000000ULL) |
138
                ((k2>>8) & 0x000000FF00000000ULL) |
139
                ((k2<<8) & 0x00000000FF000000ULL) |
140
                ((k2>>8) & 0x0000000000FF0000ULL) |
141
                ((k2<<8) & 0x000000000000FF00ULL) |
142
                ((k2>>8) & 0x00000000000000FFULL);
143
        }
144
#endif
145
146
0
        k1 *= c1;
147
0
        k1  = (k1 << 31) | (k1 >> 33);
148
0
        k1 *= c2;
149
0
        h1 ^= k1;
150
151
0
        h1 = (h1 << 27) | (h1 >> 37);
152
0
        h1 += h2;
153
0
        h1 = h1*5+0x52dce729;
154
155
0
        k2 *= c2;
156
0
        k2  = (k2 << 33) | (k2 >> 31);
157
0
        k2 *= c1;
158
0
        h2 ^= k2;
159
160
0
        h2 = (h2 << 31) | (h2 >> 33);
161
0
        h2 += h1;
162
0
        h2 = h2*5+0x38495ab5;
163
0
    }
164
165
    //----------
166
    // tail
167
168
#if (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN)
169
    const uint8_t * unswappedTail = (const uint8_t*)(data + nblocks*16);
170
    uint8_t tail[16];
171
    size_t tailSize = len & 15;
172
173
    // no swapping needed
174
    if (podSize == 1)
175
    {
176
        memcpy(tail, unswappedTail, tailSize);
177
    }
178
    else
179
    {
180
        for (size_t j = 0; j < tailSize; ++j)
181
        {
182
            tail[j] = unswappedTail[j^(podSize-1)];
183
        }
184
    }
185
#else
186
0
    const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
187
0
#endif
188
189
0
    uint64_t k1 = 0;
190
0
    uint64_t k2 = 0;
191
192
0
    switch(len & 15)
193
0
    {
194
0
        case 15: k2 ^= uint64_t(tail[14]) << 48;
195
0
        case 14: k2 ^= uint64_t(tail[13]) << 40;
196
0
        case 13: k2 ^= uint64_t(tail[12]) << 32;
197
0
        case 12: k2 ^= uint64_t(tail[11]) << 24;
198
0
        case 11: k2 ^= uint64_t(tail[10]) << 16;
199
0
        case 10: k2 ^= uint64_t(tail[ 9]) << 8;
200
0
        case  9: k2 ^= uint64_t(tail[ 8]) << 0;
201
0
        {
202
0
            k2 *= c2;
203
0
            k2  = (k2 << 33) | (k2 >> 31);
204
0
            k2 *= c1;
205
0
            h2 ^= k2;
206
0
        }
207
208
0
        case  8: k1 ^= uint64_t(tail[ 7]) << 56;
209
0
        case  7: k1 ^= uint64_t(tail[ 6]) << 48;
210
0
        case  6: k1 ^= uint64_t(tail[ 5]) << 40;
211
0
        case  5: k1 ^= uint64_t(tail[ 4]) << 32;
212
0
        case  4: k1 ^= uint64_t(tail[ 3]) << 24;
213
0
        case  3: k1 ^= uint64_t(tail[ 2]) << 16;
214
0
        case  2: k1 ^= uint64_t(tail[ 1]) << 8;
215
0
        case  1: k1 ^= uint64_t(tail[ 0]) << 0;
216
0
        {
217
0
            k1 *= c1;
218
0
            k1  = (k1 << 31) | (k1 >> 33);
219
0
            k1 *= c2;
220
0
            h1 ^= k1;
221
0
        }
222
0
    };
223
224
    //----------
225
    // finalization
226
227
0
    h1 ^= len;
228
0
    h2 ^= len;
229
230
0
    h1 += h2;
231
0
    h2 += h1;
232
233
#ifdef _MSC_VER
234
    h1 ^= h1 >> 33;
235
    h1 *= 0xff51afd7ed558ccdLL;
236
    h1 ^= h1 >> 33;
237
    h1 *= 0xc4ceb9fe1a85ec53LL;
238
    h1 ^= h1 >> 33;
239
240
    h2 ^= h2 >> 33;
241
    h2 *= 0xff51afd7ed558ccdLL;
242
    h2 ^= h2 >> 33;
243
    h2 *= 0xc4ceb9fe1a85ec53LL;
244
    h2 ^= h2 >> 33;
245
#else
246
0
    h1 ^= h1 >> 33;
247
0
    h1 *= 0xff51afd7ed558ccdLLU;
248
0
    h1 ^= h1 >> 33;
249
0
    h1 *= 0xc4ceb9fe1a85ec53LLU;
250
0
    h1 ^= h1 >> 33;
251
252
0
    h2 ^= h2 >> 33;
253
0
    h2 *= 0xff51afd7ed558ccdLLU;
254
0
    h2 ^= h2 >> 33;
255
0
    h2 *= 0xc4ceb9fe1a85ec53LLU;
256
0
    h2 ^= h2 >> 33;
257
0
#endif
258
0
    h1 += h2;
259
0
    h2 += h1;
260
261
0
    ((uint64_t*)out)[0] = h1;
262
0
    ((uint64_t*)out)[1] = h2;
263
0
}
264
265
} // End namespace ALEMBIC_VERSION_NS
266
} // End namespace Util
267
} // End namespace Alembic