Skip to content

Commit a7acc89

Browse files
committed
Add support for float fast hash when there are no zero or NaN values
1 parent 3800fb3 commit a7acc89

30 files changed

+928
-86
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// This file is auto-generated. Do not edit manually.
2+
// Structure: HashSet (HashSetChain)
3+
#pragma once
4+
#include <array>
5+
#include <cstdint>
6+
#include <limits>
7+
#include <string_view>
8+
9+
class HashSetChainStructure_Double_5_HashZeroOrNaN final
10+
{
11+
struct e
12+
{
13+
uint64_t hash_code;
14+
int8_t next;
15+
double value;
16+
17+
e(const uint64_t hash_code, const int8_t next, const double value)
18+
: hash_code(hash_code), next(next), value(value) {}
19+
};
20+
21+
static constexpr std::array<int8_t, 5> buckets = {
22+
4, 0, 3, 1, 5
23+
};
24+
25+
inline static const std::array<e, 5> entries = {
26+
e(4607182418800017408, -1, 1.0), e(4611686018427387904, -1, 2.0), e(4613937818241073152, -1, 3.0), e(4616189618054758400, -1, 4.0), e(4617315517961601024, 1, 5.0)
27+
};
28+
29+
static uint64_t get_hash(const double value) noexcept
30+
{
31+
uint64_t bits;
32+
std::memcpy(&bits, &value, sizeof(bits));
33+
return bits;
34+
}
35+
36+
public:
37+
[[nodiscard]]
38+
static bool contains(const double value) noexcept
39+
{
40+
if (value < 1.0 || value > 5.0)
41+
return false;
42+
43+
const uint64_t hash = get_hash(value);
44+
const size_t index = hash % 5;
45+
int8_t i = buckets[index] - 1;
46+
47+
while (i >= 0)
48+
{
49+
const auto& [hash_code, next, value1] = entries[i];
50+
51+
if (hash_code == hash && value1 == value)
52+
return true;
53+
54+
i = next;
55+
}
56+
57+
return false;
58+
}
59+
60+
static constexpr size_t item_count = 5;
61+
static constexpr double min_value = 1.0;
62+
static constexpr double max_value = 5.0;
63+
64+
public:
65+
HashSetChainStructure_Double_5_HashZeroOrNaN() = delete;
66+
HashSetChainStructure_Double_5_HashZeroOrNaN(const HashSetChainStructure_Double_5_HashZeroOrNaN&) = delete;
67+
HashSetChainStructure_Double_5_HashZeroOrNaN& operator=(const HashSetChainStructure_Double_5_HashZeroOrNaN&) = delete;
68+
HashSetChainStructure_Double_5_HashZeroOrNaN(HashSetChainStructure_Double_5_HashZeroOrNaN&&) = delete;
69+
HashSetChainStructure_Double_5_HashZeroOrNaN& operator=(HashSetChainStructure_Double_5_HashZeroOrNaN&&) = delete;
70+
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// This file is auto-generated. Do not edit manually.
2+
// Structure: HashSet (HashSetChain)
3+
#pragma once
4+
#include <array>
5+
#include <cstdint>
6+
#include <limits>
7+
#include <string_view>
8+
9+
class HashSetChainStructure_Single_5_HashZeroOrNaN final
10+
{
11+
struct e
12+
{
13+
uint64_t hash_code;
14+
int8_t next;
15+
float value;
16+
17+
e(const uint64_t hash_code, const int8_t next, const float value)
18+
: hash_code(hash_code), next(next), value(value) {}
19+
};
20+
21+
static constexpr std::array<int8_t, 5> buckets = {
22+
0, 1, 4, 3, 5
23+
};
24+
25+
inline static const std::array<e, 5> entries = {
26+
e(1065353216, -1, 1.0f), e(1073741824, -1, 2.0f), e(1077936128, -1, 3.0f), e(1082130432, -1, 4.0f), e(1084227584, 1, 5.0f)
27+
};
28+
29+
static uint64_t get_hash(const float value) noexcept
30+
{
31+
uint32_t bits;
32+
std::memcpy(&bits, &value, sizeof(bits));
33+
return bits;
34+
}
35+
36+
public:
37+
[[nodiscard]]
38+
static bool contains(const float value) noexcept
39+
{
40+
if (value < 1.0f || value > 5.0f)
41+
return false;
42+
43+
const uint64_t hash = get_hash(value);
44+
const size_t index = hash % 5;
45+
int8_t i = buckets[index] - 1;
46+
47+
while (i >= 0)
48+
{
49+
const auto& [hash_code, next, value1] = entries[i];
50+
51+
if (hash_code == hash && value1 == value)
52+
return true;
53+
54+
i = next;
55+
}
56+
57+
return false;
58+
}
59+
60+
static constexpr size_t item_count = 5;
61+
static constexpr float min_value = 1.0f;
62+
static constexpr float max_value = 5.0f;
63+
64+
public:
65+
HashSetChainStructure_Single_5_HashZeroOrNaN() = delete;
66+
HashSetChainStructure_Single_5_HashZeroOrNaN(const HashSetChainStructure_Single_5_HashZeroOrNaN&) = delete;
67+
HashSetChainStructure_Single_5_HashZeroOrNaN& operator=(const HashSetChainStructure_Single_5_HashZeroOrNaN&) = delete;
68+
HashSetChainStructure_Single_5_HashZeroOrNaN(HashSetChainStructure_Single_5_HashZeroOrNaN&&) = delete;
69+
HashSetChainStructure_Single_5_HashZeroOrNaN& operator=(HashSetChainStructure_Single_5_HashZeroOrNaN&&) = delete;
70+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// This file is auto-generated. Do not edit manually.
2+
// Structure: HashSet (HashSetLinear)
3+
#pragma once
4+
#include <array>
5+
#include <cstdint>
6+
#include <limits>
7+
#include <string_view>
8+
9+
class HashSetLinearStructure_Double_5_HashZeroOrNaN final
10+
{
11+
struct b
12+
{
13+
uint8_t start_index;
14+
uint8_t end_index;
15+
16+
b(const uint8_t start_index, const uint8_t end_index)
17+
: start_index(start_index), end_index(end_index) { }
18+
};
19+
20+
inline static const std::array<b, 11> buckets = {
21+
b(0, 0), b(0, 0), b(0, 0), b(0, 0), b(1, 1), b(0, 0), b(2, 2), b(0, 0), b(3, 3), b(4, 4),
22+
b(0, 0)
23+
};
24+
25+
static constexpr std::array<double, 5> items = {
26+
1.0, 2.0, 3.0, 4.0, 5.0
27+
};
28+
29+
static constexpr std::array<uint64_t, 5> hash_codes = {
30+
4607182418800017408, 4611686018427387904, 4613937818241073152, 4616189618054758400, 4617315517961601024
31+
};
32+
33+
static uint64_t get_hash(const double value) noexcept
34+
{
35+
uint64_t bits;
36+
std::memcpy(&bits, &value, sizeof(bits));
37+
return bits;
38+
}
39+
40+
public:
41+
[[nodiscard]]
42+
static bool contains(const double value) noexcept
43+
{
44+
if (value < 1.0 || value > 5.0)
45+
return false;
46+
47+
const uint64_t hash = get_hash(value);
48+
const auto& [start_index, end_index]= buckets[hash % 11];
49+
50+
uint8_t index = start_index;
51+
52+
while (index <= end_index)
53+
{
54+
if (hash_codes[index] == hash && items[index] == value)
55+
return true;
56+
57+
index++;
58+
}
59+
60+
return false;
61+
}
62+
63+
static constexpr size_t item_count = 5;
64+
static constexpr double min_value = 1.0;
65+
static constexpr double max_value = 5.0;
66+
67+
public:
68+
HashSetLinearStructure_Double_5_HashZeroOrNaN() = delete;
69+
HashSetLinearStructure_Double_5_HashZeroOrNaN(const HashSetLinearStructure_Double_5_HashZeroOrNaN&) = delete;
70+
HashSetLinearStructure_Double_5_HashZeroOrNaN& operator=(const HashSetLinearStructure_Double_5_HashZeroOrNaN&) = delete;
71+
HashSetLinearStructure_Double_5_HashZeroOrNaN(HashSetLinearStructure_Double_5_HashZeroOrNaN&&) = delete;
72+
HashSetLinearStructure_Double_5_HashZeroOrNaN& operator=(HashSetLinearStructure_Double_5_HashZeroOrNaN&&) = delete;
73+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// This file is auto-generated. Do not edit manually.
2+
// Structure: HashSet (HashSetLinear)
3+
#pragma once
4+
#include <array>
5+
#include <cstdint>
6+
#include <limits>
7+
#include <string_view>
8+
9+
class HashSetLinearStructure_Single_5_HashZeroOrNaN final
10+
{
11+
struct b
12+
{
13+
uint8_t start_index;
14+
uint8_t end_index;
15+
16+
b(const uint8_t start_index, const uint8_t end_index)
17+
: start_index(start_index), end_index(end_index) { }
18+
};
19+
20+
inline static const std::array<b, 11> buckets = {
21+
b(0, 0), b(1, 1), b(0, 0), b(0, 0), b(2, 2), b(3, 3), b(0, 0), b(0, 0), b(0, 0), b(4, 4),
22+
b(0, 0)
23+
};
24+
25+
static constexpr std::array<float, 5> items = {
26+
5.0f, 2.0f, 1.0f, 3.0f, 4.0f
27+
};
28+
29+
static constexpr std::array<uint64_t, 5> hash_codes = {
30+
1084227584, 1073741824, 1065353216, 1077936128, 1082130432
31+
};
32+
33+
static uint64_t get_hash(const float value) noexcept
34+
{
35+
uint32_t bits;
36+
std::memcpy(&bits, &value, sizeof(bits));
37+
return bits;
38+
}
39+
40+
public:
41+
[[nodiscard]]
42+
static bool contains(const float value) noexcept
43+
{
44+
if (value < 1.0f || value > 5.0f)
45+
return false;
46+
47+
const uint64_t hash = get_hash(value);
48+
const auto& [start_index, end_index]= buckets[hash % 11];
49+
50+
uint8_t index = start_index;
51+
52+
while (index <= end_index)
53+
{
54+
if (hash_codes[index] == hash && items[index] == value)
55+
return true;
56+
57+
index++;
58+
}
59+
60+
return false;
61+
}
62+
63+
static constexpr size_t item_count = 5;
64+
static constexpr float min_value = 1.0f;
65+
static constexpr float max_value = 5.0f;
66+
67+
public:
68+
HashSetLinearStructure_Single_5_HashZeroOrNaN() = delete;
69+
HashSetLinearStructure_Single_5_HashZeroOrNaN(const HashSetLinearStructure_Single_5_HashZeroOrNaN&) = delete;
70+
HashSetLinearStructure_Single_5_HashZeroOrNaN& operator=(const HashSetLinearStructure_Single_5_HashZeroOrNaN&) = delete;
71+
HashSetLinearStructure_Single_5_HashZeroOrNaN(HashSetLinearStructure_Single_5_HashZeroOrNaN&&) = delete;
72+
HashSetLinearStructure_Single_5_HashZeroOrNaN& operator=(HashSetLinearStructure_Single_5_HashZeroOrNaN&&) = delete;
73+
};

Src/FastData.Generator.CPlusPlus/Internal/Framework/CPlusPlusHashDef.cs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
using Genbox.FastData.Generator.Framework.Interfaces;
2+
using Genbox.FastData.Generators;
23
using Genbox.FastData.Generators.Extensions;
34

45
namespace Genbox.FastData.Generator.CPlusPlus.Internal.Framework;
56

67
internal class CPlusPlusHashDef : IHashDef
78
{
8-
public string GetHashSource(DataType dataType, string typeName)
9+
public string GetHashSource(DataType dataType, string typeName, HashInfo info)
910
{
1011
bool notConst = dataType is DataType.Single or DataType.Double or DataType.Int64 or DataType.UInt64;
1112

1213
return $$"""
1314
static{{(notConst ? " " : " constexpr ")}}uint64_t get_hash(const {{typeName}} value) noexcept
1415
{
15-
{{GetHash(dataType)}}
16+
{{GetHash(dataType, info)}}
1617
}
1718
""";
1819
}
1920

20-
private static string GetHash(DataType dataType)
21+
private static string GetHash(DataType dataType, HashInfo info)
2122
{
2223
if (dataType == DataType.String)
2324
{
@@ -41,24 +42,37 @@ private static string GetHash(DataType dataType)
4142

4243
if (dataType == DataType.Single)
4344
{
44-
return """
45-
uint32_t bits;
46-
std::memcpy(&bits, &value, sizeof(bits));
47-
if (((bits - 1) & ~0x80000000u) >= 0x7F800000u)
48-
bits &= 0x7F800000u;
49-
return bits;
50-
""";
45+
return info.HasZeroOrNaN
46+
? """
47+
uint32_t bits;
48+
std::memcpy(&bits, &value, sizeof(bits));
49+
if (((bits - 1) & ~0x80000000u) >= 0x7F800000u)
50+
bits &= 0x7F800000u;
51+
return bits;
52+
"""
53+
: """
54+
uint32_t bits;
55+
std::memcpy(&bits, &value, sizeof(bits));
56+
return bits;
57+
""";
58+
5159
}
5260

5361
if (dataType == DataType.Double)
5462
{
55-
return """
56-
uint64_t bits;
57-
std::memcpy(&bits, &value, sizeof(bits));
58-
if (((bits - 1) & ~0x8000000000000000ull) >= 0x7FF0000000000000ull)
59-
bits &= 0x7FF0000000000000ull;
60-
return bits;
61-
""";
63+
return info.HasZeroOrNaN
64+
? """
65+
uint64_t bits;
66+
std::memcpy(&bits, &value, sizeof(bits));
67+
if (((bits - 1) & ~0x8000000000000000ull) >= 0x7FF0000000000000ull)
68+
bits &= 0x7FF0000000000000ull;
69+
return bits;
70+
"""
71+
: """
72+
uint64_t bits;
73+
std::memcpy(&bits, &value, sizeof(bits));
74+
return bits;
75+
""";
6276
}
6377

6478
throw new InvalidOperationException("Unsupported data type: " + dataType);

0 commit comments

Comments
 (0)