JPL Spatial
Sound spatialization and propagation library
Loading...
Searching...
No Matches
ScratchHashSet.h
Go to the documentation of this file.
1//
2// ██╗██████╗ ██╗ ██╗██████╗ ███████╗
3// ██║██╔══██╗ ██║ ██║██╔══██╗██╔════╝ ** JPLSpatial **
4// ██║██████╔╝ ██║ ██║██████╔╝███████╗
5// ██ ██║██╔═══╝ ██║ ██║██╔══██╗╚════██║ https://github.com/Jaytheway/JPLSpatial
6// ╚█████╔╝██║ ███████╗██║██████╔╝███████║
7// ╚════╝ ╚═╝ ╚══════╝╚═╝╚═════╝ ╚══════╝
8//
9// Copyright 2026 Jaroslav Pevno, JPLSpatial is offered under the terms of the ISC license:
10//
11// Permission to use, copy, modify, and/or distribute this software for any purpose with or
12// without fee is hereby granted, provided that the above copyright notice and this permission
13// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
14// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
16// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#pragma once
21
22#include <JPLSpatial/Core.h>
24
25#include <bit>
26#include <cstring>
27#include <cstddef>
28#include <functional>
29#include <limits>
30#include <type_traits>
31
32namespace JPL
33{
34 template<class T, class HashFunction, class Equals = std::equal_to<T>> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
35 class ScratchHashSet32;
36
37 // Set that expects already hashed keys as inputs
39
40 //==========================================================================
44 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
45 class ScratchHashSet32 // TODO: convert to a proper hash table
46 {
47 public:
48 ScratchHashSet32() = default;
49
51 std::size_t memoryBytes,
53 const HashFunction& hash = {},
54 const Equals& equals = {});
55
56 [[nodiscard]] static JPL_INLINE std::size_t GetRequiredMemorySize(uint32 expectedCount);
57
58 inline void Init(void* memory, std::size_t memoryBytes, uint32 expectedCount);
59
60 inline bool Insert(const T& key);
61
62 [[nodiscard]] inline bool Contains(const T& key) const;
63
64 // Does not deallocate memory, only clears the occupancy flags and size counter
65 JPL_INLINE void Clear();
66
67 [[nodiscard]] JPL_INLINE uint32 size() const { return mSize; }
68 [[nodiscard]] JPL_INLINE uint32 capacity() const { return mCapacity; }
69
70 private:
71 [[nodiscard]] static JPL_INLINE std::size_t GetCapacityForCount(uint32 expectedCount);
72
73 private:
74 [[no_unique_address]] HashFunction mHasher{};
75 [[no_unique_address]] Equals mEquals{};
76 uint32* mKeys = nullptr;
77 uint8* mOcupied = nullptr;
78 uint32 mCapacity = 0;
79 uint32 mMask = 0;
80 uint32 mSize = 0;
81 };
82} // namespace JPL
83
84//==============================================================================
85//
86// Code beyond this point is implementation detail...
87//
88//==============================================================================
89
90namespace JPL
91{
92 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
94 std::size_t memoryBytes,
96 const HashFunction& hash,
97 const Equals& equals)
98 : mHasher(hash)
99 , mEquals(equals)
100 {
102 }
103
104 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
106 {
107 const std::size_t capacity = GetCapacityForCount(expectedCount);
108 return capacity * sizeof(T) // keys
109 + capacity * sizeof(uint8); // flags
110 }
111
112 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
114 {
115 const std::size_t minCapacity = expectedCount > 0 ? expectedCount * 2llu : 2llu;
116 JPL_ASSERT(minCapacity <= std::numeric_limits<uint32>::max()); // sanity check
117 return std::bit_ceil(minCapacity);
118 }
119
120 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
122 {
123 mCapacity = static_cast<uint32>(GetCapacityForCount(expectedCount));
124 mMask = mCapacity - 1u;
125 mSize = 0;
126
127 const std::size_t slotsBytes = static_cast<std::size_t>(mCapacity) * sizeof(T);
128 const std::size_t flagsBytes = static_cast<std::size_t>(mCapacity) * sizeof(uint8);
129
131
132 std::byte* ptr = static_cast<std::byte*>(memory);
133 mKeys = reinterpret_cast<T*>(ptr);
134 mOcupied = reinterpret_cast<uint8*>(ptr + slotsBytes);
135
136 std::memset(mOcupied, 0, flagsBytes);
137 }
138
139 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
141 {
142 uint32 index = mHasher(key) & mMask;
143
144 for (uint32 probe = 0; probe < mCapacity; ++probe)
145 {
146 if (not mOcupied[index])
147 {
148 mOcupied[index] = 1;
149 mKeys[index] = key;
150 ++mSize;
151 return true;
152 }
153
154 if (mEquals(mKeys[index], key))
155 {
156 return false;
157 }
158
159 index = (index + 1u) & mMask;
160 }
161
162 JPL_ASSERT(false);
163 return false;
164 }
165
166 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
168 {
169 uint32 index = mHasher(key) & mMask;
170
171 for (uint32 probe = 0; probe < mCapacity; ++probe)
172 {
173 if (not mOcupied[index])
174 {
175 return false;
176 }
177
178 if (mEquals(mKeys[index], key))
179 {
180 return true;
181 }
182
183 index = (index + 1u) & mMask;
184 }
185
186 return false;
187 }
188
189 template<class T, class HashFunction, class Equals> requires(std::is_trivial<T>::value and std::is_copy_constructible_v<T>)
191 {
192 std::memset(mOcupied, 0, static_cast<std::size_t>(mCapacity) * sizeof(uint8));
193 mSize = 0;
194 }
195} // namespace JPL
196
#define JPL_ASSERT(inExpression,...)
Main assert macro, usage: JPL_ASSERT(condition, message) or JPL_ASSERT(condition)
Definition ErrorReporting.h:76
Definition ScratchHashSet.h:46
JPL_INLINE uint32 capacity() const
Definition ScratchHashSet.h:68
ScratchHashSet32()=default
JPL_INLINE uint32 size() const
Definition ScratchHashSet.h:67
Definition AcousticMaterial.h:36
std::uint32_t uint32
Definition Core.h:311
std::uint8_t uint8
Definition Core.h:309
JPL_INLINE simd min(const simd &a, const simd &b) noexcept
Element-wise min.
Definition SIMD.h:1813