26#include <condition_variable>
29#include <unordered_map>
30#include <unordered_set>
32#ifdef ZLAYOUT_USE_CUDA
33#include <cuda_runtime.h>
34#include <device_launch_parameters.h>
37#ifdef ZLAYOUT_USE_OPENCL
51 alignas(T)
char data[
sizeof(T)];
55 std::vector<std::unique_ptr<Block[]>> chunks;
62 : chunk_size(chunk_size), free_list(nullptr) {
71 std::lock_guard<std::mutex> lock(mutex);
76 Block* block = free_list;
77 free_list = free_list->next;
78 return reinterpret_cast<T*
>(block);
82 std::lock_guard<std::mutex> lock(mutex);
83 Block* block =
reinterpret_cast<Block*
>(ptr);
84 block->next = free_list;
89 void allocate_chunk() {
90 auto chunk = std::make_unique<Block[]>(chunk_size);
91 for (
size_t i = 0; i < chunk_size - 1; ++i) {
92 chunk[i].next = &chunk[i + 1];
94 chunk[chunk_size - 1].next = free_list;
95 free_list = &chunk[0];
96 chunks.push_back(std::move(chunk));
110 std::vector<std::thread> workers;
111 mutable std::queue<std::function<void()>> tasks;
112 mutable std::mutex queue_mutex;
113 mutable std::condition_variable condition;
114 std::atomic<bool> stop;
117 explicit ThreadPool(
size_t threads = std::thread::hardware_concurrency());
120 template<
class F,
class... Args>
121 auto enqueue(F&& f, Args&&... args)
const
122 -> std::future<
typename std::result_of<F(Args...)>::type>;
142 return boundary.contains_rectangle(rect);
163 static uint64_t
encode(uint32_t x, uint32_t y) {
164 return interleave(x) | (interleave(y) << 1);
167 static std::pair<uint32_t, uint32_t>
decode(uint64_t z) {
168 return {deinterleave(z), deinterleave(z >> 1)};
173 uint32_t x =
static_cast<uint32_t
>((point.
x - bounds.
x) / bounds.
width * 0xFFFFFFFF);
174 uint32_t y =
static_cast<uint32_t
>((point.
y - bounds.
y) / bounds.
height * 0xFFFFFFFF);
179 static uint64_t interleave(uint32_t x) {
181 result = (result | (result << 16)) & 0x0000FFFF0000FFFF;
182 result = (result | (result << 8)) & 0x00FF00FF00FF00FF;
183 result = (result | (result << 4)) & 0x0F0F0F0F0F0F0F0F;
184 result = (result | (result << 2)) & 0x3333333333333333;
185 result = (result | (result << 1)) & 0x5555555555555555;
189 static uint32_t deinterleave(uint64_t x) {
190 x = x & 0x5555555555555555;
191 x = (x | (x >> 1)) & 0x3333333333333333;
192 x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
193 x = (x | (x >> 4)) & 0x00FF00FF00FF00FF;
194 x = (x | (x >> 8)) & 0x0000FFFF0000FFFF;
195 x = (x | (x >> 16)) & 0x00000000FFFFFFFF;
196 return static_cast<uint32_t
>(x);
206 std::vector<std::pair<T, geometry::Rectangle>>
entries;
207 std::vector<std::unique_ptr<RTreeNode<T>>>
children;
226 for (
size_t i = 1; i <
entries.size(); ++i) {
231 for (
size_t i = 1; i <
children.size(); ++i) {
244 std::unique_ptr<RTreeNode<T>> root;
249 root = std::make_unique<RTreeNode<T>>(
true);
257 size_t size()
const {
return object_count; }
258 bool empty()
const {
return object_count == 0; }
263 std::unique_ptr<RTreeNode<T>> split_node(
RTreeNode<T>* node);
274 std::unique_ptr<IPBlock> root_block;
275 std::unordered_map<std::string, std::unique_ptr<QuadTree<T>>> block_indices;
276 std::unordered_map<std::string, std::unique_ptr<RTree<T>>> rtree_indices;
277 std::unordered_map<uint64_t, std::vector<T>> zorder_buckets;
283 size_t max_objects_per_block;
284 size_t max_hierarchy_levels;
288 size_t max_objects_per_block = 1000000,
289 size_t max_hierarchy_levels = 8)
290 : world_bounds(world_bounds),
291 max_objects_per_block(max_objects_per_block),
292 max_hierarchy_levels(max_hierarchy_levels),
293 thread_pool(std::thread::hardware_concurrency()) {
295 root_block = std::make_unique<IPBlock>(
"root", world_bounds, 0);
299 void bulk_insert(
const std::vector<std::pair<T, geometry::Rectangle>>& objects);
307 const std::string& parent_name =
"root");
324 void create_block_index(
const std::string& block_name,
const geometry::Rectangle& boundary);
325 IPBlock* find_block(
const std::string& name)
const;
327 void partition_objects_by_zorder(
const std::vector<std::pair<T, geometry::Rectangle>>& objects);
329 std::vector<std::future<std::vector<T>>> dispatch_parallel_queries(
349 size_t expected_object_count,
353 size_t max_objects_per_block = 1000000;
354 size_t max_hierarchy_levels = 8;
356 if (expected_object_count > 100000000) {
357 max_objects_per_block = 10000000;
358 max_hierarchy_levels = 12;
359 }
else if (expected_object_count > 10000000) {
360 max_objects_per_block = 1000000;
361 max_hierarchy_levels = 10;
364 return std::make_unique<HierarchicalSpatialIndex<T>>(
365 world_bounds, max_objects_per_block, max_hierarchy_levels);
373 const std::vector<std::pair<T, geometry::Rectangle>>& objects) {
376 const std::vector<std::pair<T, geometry::Rectangle>>& sorted_objects = objects;
379 for (
const auto& [
object, bbox] : sorted_objects) {
381 std::string block_name = find_optimal_block(bbox);
384 if (block_indices.find(block_name) == block_indices.end()) {
385 create_block_index(block_name, bbox);
389 block_indices[block_name]->insert(
object);
395 const std::vector<std::pair<T, geometry::Rectangle>>& objects) {
397 const size_t num_threads = thread_pool.get_thread_count();
398 const size_t chunk_size = (objects.size() + num_threads - 1) / num_threads;
400 std::vector<std::future<void>> futures;
402 for (
size_t i = 0; i < num_threads; ++i) {
403 size_t start = i * chunk_size;
404 size_t end = std::min(start + chunk_size, objects.size());
406 if (start >= objects.size())
break;
408 auto future = thread_pool.enqueue([
this, &objects, start, end]() {
409 std::vector<std::pair<T, geometry::Rectangle>> chunk(
410 objects.begin() + start, objects.begin() + end);
414 futures.push_back(std::move(future));
418 for (
auto& future : futures) {
427 auto futures = dispatch_parallel_queries(range);
429 std::vector<T> result;
430 for (
auto& future : futures) {
431 auto partial_result = future.get();
432 result.insert(result.end(), partial_result.begin(), partial_result.end());
2D point with high-precision coordinates and utility methods
Axis-aligned rectangle for bounding boxes and simple EDA components.
double y
Y coordinate of bottom-left corner.
double height
Height of rectangle.
double x
X coordinate of bottom-left corner.
double width
Width of rectangle.
void create_ip_block(const std::string &name, const geometry::Rectangle &boundary, const std::string &parent_name="root")
void optimize_for_query_pattern(const std::vector< geometry::Rectangle > &query_patterns)
std::vector< std::pair< T, T > > parallel_find_intersections() const
HierarchicalSpatialIndex(const geometry::Rectangle &world_bounds, size_t max_objects_per_block=1000000, size_t max_hierarchy_levels=8)
Statistics get_statistics() const
void parallel_bulk_insert(const std::vector< std::pair< T, geometry::Rectangle > > &objects)
void bulk_insert(const std::vector< std::pair< T, geometry::Rectangle > > &objects)
void optimize_hierarchy()
std::vector< T > parallel_query_range(const geometry::Rectangle &range) const
Memory pool for efficient object allocation.
MemoryPool(size_t chunk_size=1024)
void insert(const T &object, const geometry::Rectangle &bbox)
std::vector< T > query_point(const geometry::Point &point) const
bool remove(const T &object, const geometry::Rectangle &bbox)
std::vector< T > query_range(const geometry::Rectangle &range) const
Ultra-high performance spatial index factory.
static std::unique_ptr< HierarchicalSpatialIndex< T > > create_optimized_index(const geometry::Rectangle &world_bounds, size_t expected_object_count, IndexType preferred_type=IndexType::HYBRID)
Thread pool for parallel processing.
auto enqueue(F &&f, Args &&... args) const -> std::future< typename std::result_of< F(Args...)>::type >
ThreadPool(size_t threads=std::thread::hardware_concurrency())
void wait_for_completion()
size_t get_thread_count() const
Z-order curve (Morton code) for spatial hashing.
static std::pair< uint32_t, uint32_t > decode(uint64_t z)
static uint64_t encode(uint32_t x, uint32_t y)
static uint64_t encode_point(const geometry::Point &point, const geometry::Rectangle &bounds)
Main namespace for ZLayout library.
2D Point class for geometric calculations
QuadTree spatial indexing for efficient geometric queries.
Axis-aligned rectangle class for bounding boxes and simple components.
double query_performance_ms
size_t avg_objects_per_block
IP Block represents a hierarchical design block.
geometry::Rectangle boundary
bool contains(const geometry::Rectangle &rect) const
std::vector< size_t > component_ids
bool intersects(const geometry::Rectangle &rect) const
void add_sub_block(std::unique_ptr< IPBlock > block)
std::vector< std::unique_ptr< IPBlock > > sub_blocks
IPBlock(const std::string &name, const geometry::Rectangle &boundary, size_t level=0)
void add_component(size_t component_id)
R-tree node for efficient rectangle indexing.
std::vector< std::pair< T, geometry::Rectangle > > entries
static const size_t MAX_ENTRIES
static const size_t MIN_ENTRIES
RTreeNode(bool leaf=true)
std::vector< std::unique_ptr< RTreeNode< T > > > children