From f090cbc2eb79e5eaa0e51e8c3ba2ec32df6a8be4 Mon Sep 17 00:00:00 2001 From: Niklas Uhl Date: Thu, 4 Dec 2025 10:16:04 +0100 Subject: [PATCH 1/4] Clamp probabilities passed to binomial distribution to $[0.0, 1.0]$. When the probability is computed based on chunk and cell sizes which are equal, floating point inaccuracies may lead to probabilities greater than 1.0. --- kagen/generators/geometric/geometric_2d.h | 4 +++- kagen/generators/geometric/geometric_3d.h | 3 ++- kagen/generators/geometric/rgg/rgg_2d.cpp | 5 ++++- kagen/generators/geometric/rgg/rgg_3d.cpp | 5 ++++- kagen/generators/hyperbolic/hyperbolic.cpp | 6 ++++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/kagen/generators/geometric/geometric_2d.h b/kagen/generators/geometric/geometric_2d.h index 71222064..9a5a9349 100644 --- a/kagen/generators/geometric/geometric_2d.h +++ b/kagen/generators/geometric/geometric_2d.h @@ -19,6 +19,7 @@ #include "libmorton/morton2D.h" #include #include +#include namespace kagen { class Geometric2D : public virtual Generator, private EdgeListOnlyGenerator { @@ -206,7 +207,8 @@ class Geometric2D : public virtual Generator, private EdgeListOnlyGenerator { for (SInt i = 0; i < cells_per_chunk_; ++i) { seed = config_.seed + chunk_id * cells_per_chunk_ + i + total_chunks_ * cells_per_chunk_; SInt h = sampling::Spooky::hash(seed); - SInt cell_vertices = rng_.GenerateBinomial(h, n, cell_area / total_area); + // due to potential floating point inaccuracies clamp probability + SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(std::cell_area / total_area, 0.0, 1.0)); LPFloat cell_start_x = std::get<1>(chunk) + (i / cells_per_dim_) * cell_size_; LPFloat cell_start_y = std::get<2>(chunk) + (i % cells_per_dim_) * cell_size_; if (cell_vertices != 0) { diff --git a/kagen/generators/geometric/geometric_3d.h b/kagen/generators/geometric/geometric_3d.h index d85a7795..9ca9bbf9 100644 --- a/kagen/generators/geometric/geometric_3d.h +++ b/kagen/generators/geometric/geometric_3d.h @@ -19,6 +19,7 @@ #include "libmorton/morton3D.h" #include #include +#include namespace kagen { class Geometric3D : public virtual Generator, private EdgeListOnlyGenerator { @@ -247,7 +248,7 @@ class Geometric3D : public virtual Generator, private EdgeListOnlyGenerator { for (SInt i = 0; i < cells_per_chunk_; ++i) { seed = config_.seed + chunk_id * cells_per_chunk_ + i + total_chunks_ * cells_per_chunk_; SInt h = sampling::Spooky::hash(seed); - SInt cell_vertices = rng_.GenerateBinomial(h, n, cell_area / total_area); + SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(cell_area / total_area, 0.0, 1.0)); LPFloat cell_start_x = std::get<1>(chunk) + ((i / cells_per_dim_) % cells_per_dim_) * cell_size_; LPFloat cell_start_y = std::get<2>(chunk) + (i % cells_per_dim_) * cell_size_; LPFloat cell_start_z = std::get<3>(chunk) + (i / (cells_per_dim_ * cells_per_dim_)) * cell_size_; diff --git a/kagen/generators/geometric/rgg/rgg_2d.cpp b/kagen/generators/geometric/rgg/rgg_2d.cpp index c3c526d7..1c5e5df0 100644 --- a/kagen/generators/geometric/rgg/rgg_2d.cpp +++ b/kagen/generators/geometric/rgg/rgg_2d.cpp @@ -1,5 +1,7 @@ #include "kagen/generators/geometric/rgg/rgg_2d.h" +#include + #include "kagen/tools/geometry.h" namespace kagen { @@ -152,7 +154,8 @@ void RGG2D::GenerateCells(const SInt chunk_id) { for (SInt i = 0; i < cells_per_chunk_; ++i) { seed = config_.seed + chunk_id * cells_per_chunk_ + i + total_chunks_ * cells_per_chunk_; SInt h = sampling::Spooky::hash(seed); - SInt cell_vertices = rng_.GenerateBinomial(h, n, cell_area / total_area); + // due to potential floating point inaccuracies clamp probability + SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(cell_area / total_area, 0.0, 0.1)); LPFloat cell_start_x = std::get<1>(chunk) + (i / cells_per_dim_) * cell_size_; LPFloat cell_start_y = std::get<2>(chunk) + (i % cells_per_dim_) * cell_size_; diff --git a/kagen/generators/geometric/rgg/rgg_3d.cpp b/kagen/generators/geometric/rgg/rgg_3d.cpp index dd70e3b6..b4754e7b 100644 --- a/kagen/generators/geometric/rgg/rgg_3d.cpp +++ b/kagen/generators/geometric/rgg/rgg_3d.cpp @@ -1,5 +1,7 @@ #include "kagen/generators/geometric/rgg/rgg_3d.h" +#include + namespace kagen { RGG3D::RGG3D(const PGeneratorConfig& config, const PEID rank, const PEID size) : Geometric3D(config, rank, size) { // Chunk variables @@ -176,7 +178,8 @@ void RGG3D::GenerateCells(const SInt chunk_id) { for (SInt i = 0; i < cells_per_chunk_; ++i) { seed = config_.seed + chunk_id * cells_per_chunk_ + i + total_chunks_ * cells_per_chunk_; SInt h = sampling::Spooky::hash(seed); - SInt cell_vertices = rng_.GenerateBinomial(h, n, cell_area / total_area); + // due to potential floating point inaccuracies clamp probability + SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(cell_area / total_area, 0.0, 1.0)); LPFloat cell_start_x = std::get<1>(chunk) + ((i / cells_per_dim_) % cells_per_dim_) * cell_size_; LPFloat cell_start_y = std::get<2>(chunk) + (i % cells_per_dim_) * cell_size_; LPFloat cell_start_z = std::get<3>(chunk) + (i / (cells_per_dim_ * cells_per_dim_)) * cell_size_; diff --git a/kagen/generators/hyperbolic/hyperbolic.cpp b/kagen/generators/hyperbolic/hyperbolic.cpp index 991e62fc..606931bb 100644 --- a/kagen/generators/hyperbolic/hyperbolic.cpp +++ b/kagen/generators/hyperbolic/hyperbolic.cpp @@ -7,6 +7,7 @@ #include "kagen/tools/postprocessor.h" #include +#include namespace kagen { PGeneratorConfig @@ -188,7 +189,8 @@ void Hyperbolic::ComputeAnnuli(const SInt chunk_id) { // Variate SInt h = sampling::Spooky::hash(config_.seed + total_annuli_ * config_.k + chunk_id * total_annuli_ + i); - SInt n_annulus = rng_.GenerateBinomial(h, n, ring_area / total_area); + // due to potential floating point inaccuracies clamp probability + SInt n_annulus = rng_.GenerateBinomial(h, n, std::clamp(ring_area / total_area, 0.0, 1.0)); // Push annuli_ annuli_[ComputeGlobalChunkId(i - 1, chunk_id)] = std::make_tuple(n_annulus, min_r, max_r, false, offset); @@ -294,7 +296,7 @@ void Hyperbolic::GenerateCells(const SInt annulus_id, SInt chunk_id) { if (!clique) seed = config_.seed + annulus_id * config_.k + chunk_id + i + config_.n; SInt h = sampling::Spooky::hash(seed); - SInt n_cell = rng_.GenerateBinomial(h, n, grid_phi / total_phi); + SInt n_cell = rng_.GenerateBinomial(h, n, std::clamp(grid_phi / total_phi, 0.0, 1.0)); SInt global_cell_id = ComputeGlobalCellId(annulus_id, chunk_id, i); cells_[global_cell_id] = From 4fe2737e50da3b605fd16fd4d2367cb1195072d0 Mon Sep 17 00:00:00 2001 From: Niklas Uhl Date: Thu, 4 Dec 2025 10:26:59 +0100 Subject: [PATCH 2/4] Fix compilation. --- kagen/generators/geometric/geometric_2d.h | 2 +- kagen/generators/hyperbolic/hyperbolic.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kagen/generators/geometric/geometric_2d.h b/kagen/generators/geometric/geometric_2d.h index 9a5a9349..2d6a30dd 100644 --- a/kagen/generators/geometric/geometric_2d.h +++ b/kagen/generators/geometric/geometric_2d.h @@ -208,7 +208,7 @@ class Geometric2D : public virtual Generator, private EdgeListOnlyGenerator { seed = config_.seed + chunk_id * cells_per_chunk_ + i + total_chunks_ * cells_per_chunk_; SInt h = sampling::Spooky::hash(seed); // due to potential floating point inaccuracies clamp probability - SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(std::cell_area / total_area, 0.0, 1.0)); + SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(cell_area / total_area, 0.0, 1.0)); LPFloat cell_start_x = std::get<1>(chunk) + (i / cells_per_dim_) * cell_size_; LPFloat cell_start_y = std::get<2>(chunk) + (i % cells_per_dim_) * cell_size_; if (cell_vertices != 0) { diff --git a/kagen/generators/hyperbolic/hyperbolic.cpp b/kagen/generators/hyperbolic/hyperbolic.cpp index 606931bb..5aaeb338 100644 --- a/kagen/generators/hyperbolic/hyperbolic.cpp +++ b/kagen/generators/hyperbolic/hyperbolic.cpp @@ -190,7 +190,7 @@ void Hyperbolic::ComputeAnnuli(const SInt chunk_id) { // Variate SInt h = sampling::Spooky::hash(config_.seed + total_annuli_ * config_.k + chunk_id * total_annuli_ + i); // due to potential floating point inaccuracies clamp probability - SInt n_annulus = rng_.GenerateBinomial(h, n, std::clamp(ring_area / total_area, 0.0, 1.0)); + SInt n_annulus = rng_.GenerateBinomial(h, n, std::clamp(ring_area / total_area, Double {0.0}, Double{1.0})); // Push annuli_ annuli_[ComputeGlobalChunkId(i - 1, chunk_id)] = std::make_tuple(n_annulus, min_r, max_r, false, offset); @@ -296,7 +296,7 @@ void Hyperbolic::GenerateCells(const SInt annulus_id, SInt chunk_id) { if (!clique) seed = config_.seed + annulus_id * config_.k + chunk_id + i + config_.n; SInt h = sampling::Spooky::hash(seed); - SInt n_cell = rng_.GenerateBinomial(h, n, std::clamp(grid_phi / total_phi, 0.0, 1.0)); + SInt n_cell = rng_.GenerateBinomial(h, n, std::clamp(grid_phi / total_phi, Double{0.0}, Double{1.0})); SInt global_cell_id = ComputeGlobalCellId(annulus_id, chunk_id, i); cells_[global_cell_id] = From 28d0a736b792370d3e1b6e601d657b70037988f4 Mon Sep 17 00:00:00 2001 From: Niklas Uhl Date: Thu, 4 Dec 2025 10:28:21 +0100 Subject: [PATCH 3/4] Use spaces instead of tabs. --- kagen/generators/geometric/geometric_2d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kagen/generators/geometric/geometric_2d.h b/kagen/generators/geometric/geometric_2d.h index 2d6a30dd..30a285b3 100644 --- a/kagen/generators/geometric/geometric_2d.h +++ b/kagen/generators/geometric/geometric_2d.h @@ -207,7 +207,7 @@ class Geometric2D : public virtual Generator, private EdgeListOnlyGenerator { for (SInt i = 0; i < cells_per_chunk_; ++i) { seed = config_.seed + chunk_id * cells_per_chunk_ + i + total_chunks_ * cells_per_chunk_; SInt h = sampling::Spooky::hash(seed); - // due to potential floating point inaccuracies clamp probability + // due to potential floating point inaccuracies clamp probability SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(cell_area / total_area, 0.0, 1.0)); LPFloat cell_start_x = std::get<1>(chunk) + (i / cells_per_dim_) * cell_size_; LPFloat cell_start_y = std::get<2>(chunk) + (i % cells_per_dim_) * cell_size_; From 78dbf4a966ae0f91521f6ebaa6e99bd0ef6b95ce Mon Sep 17 00:00:00 2001 From: Niklas Uhl Date: Thu, 4 Dec 2025 10:29:09 +0100 Subject: [PATCH 4/4] Fix erroneous upper bound in one of the clamp calls. --- kagen/generators/geometric/rgg/rgg_2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kagen/generators/geometric/rgg/rgg_2d.cpp b/kagen/generators/geometric/rgg/rgg_2d.cpp index 1c5e5df0..09fb0e01 100644 --- a/kagen/generators/geometric/rgg/rgg_2d.cpp +++ b/kagen/generators/geometric/rgg/rgg_2d.cpp @@ -155,7 +155,7 @@ void RGG2D::GenerateCells(const SInt chunk_id) { seed = config_.seed + chunk_id * cells_per_chunk_ + i + total_chunks_ * cells_per_chunk_; SInt h = sampling::Spooky::hash(seed); // due to potential floating point inaccuracies clamp probability - SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(cell_area / total_area, 0.0, 0.1)); + SInt cell_vertices = rng_.GenerateBinomial(h, n, std::clamp(cell_area / total_area, 0.0, 1.0)); LPFloat cell_start_x = std::get<1>(chunk) + (i / cells_per_dim_) * cell_size_; LPFloat cell_start_y = std::get<2>(chunk) + (i % cells_per_dim_) * cell_size_;