162306a36Sopenharmony_ci/* SPDX-License-Identifier: LGPL-2.1
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * Based on Paul Hsieh's (LGPG 2.1) hash function
462306a36Sopenharmony_ci * From: http://www.azillionmonkeys.com/qed/hash.html
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define get16bits(d) (*((const __u16 *) (d)))
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistatic __always_inline
1062306a36Sopenharmony_ci__u32 SuperFastHash (const char *data, int len, __u32 initval) {
1162306a36Sopenharmony_ci	__u32 hash = initval;
1262306a36Sopenharmony_ci	__u32 tmp;
1362306a36Sopenharmony_ci	int rem;
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci	if (len <= 0 || data == NULL) return 0;
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci	rem = len & 3;
1862306a36Sopenharmony_ci	len >>= 2;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	/* Main loop */
2162306a36Sopenharmony_ci#pragma clang loop unroll(full)
2262306a36Sopenharmony_ci	for (;len > 0; len--) {
2362306a36Sopenharmony_ci		hash  += get16bits (data);
2462306a36Sopenharmony_ci		tmp    = (get16bits (data+2) << 11) ^ hash;
2562306a36Sopenharmony_ci		hash   = (hash << 16) ^ tmp;
2662306a36Sopenharmony_ci		data  += 2*sizeof (__u16);
2762306a36Sopenharmony_ci		hash  += hash >> 11;
2862306a36Sopenharmony_ci	}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	/* Handle end cases */
3162306a36Sopenharmony_ci	switch (rem) {
3262306a36Sopenharmony_ci        case 3: hash += get16bits (data);
3362306a36Sopenharmony_ci                hash ^= hash << 16;
3462306a36Sopenharmony_ci                hash ^= ((signed char)data[sizeof (__u16)]) << 18;
3562306a36Sopenharmony_ci                hash += hash >> 11;
3662306a36Sopenharmony_ci                break;
3762306a36Sopenharmony_ci        case 2: hash += get16bits (data);
3862306a36Sopenharmony_ci                hash ^= hash << 11;
3962306a36Sopenharmony_ci                hash += hash >> 17;
4062306a36Sopenharmony_ci                break;
4162306a36Sopenharmony_ci        case 1: hash += (signed char)*data;
4262306a36Sopenharmony_ci                hash ^= hash << 10;
4362306a36Sopenharmony_ci                hash += hash >> 1;
4462306a36Sopenharmony_ci	}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/* Force "avalanching" of final 127 bits */
4762306a36Sopenharmony_ci	hash ^= hash << 3;
4862306a36Sopenharmony_ci	hash += hash >> 5;
4962306a36Sopenharmony_ci	hash ^= hash << 4;
5062306a36Sopenharmony_ci	hash += hash >> 17;
5162306a36Sopenharmony_ci	hash ^= hash << 25;
5262306a36Sopenharmony_ci	hash += hash >> 6;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	return hash;
5562306a36Sopenharmony_ci}
56