parity with delaunator#35
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 671aaa2..c7c8f72 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,6 +9,7 @@
option(WERROR "Add -Werror flag to build (turns warnings into errors)" ON)
option(BENCHMARK_BIG_O "Calculate Big O in benchmark" OFF)
option(BENCHMARK_100M "Run against 100M points" OFF)
+option(BENCHMARK_10M "Run against 100M points" OFF)
# configure optimization
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -54,11 +55,15 @@
add_executable(bench-tests ${BENCH_SOURCES})
if(BENCHMARK_BIG_O)
message("-- BENCHMARK_BIG_O=1")
- target_compile_definitions(bench-tests PRIVAT BENCHMARK_BIG_O=1)
+ target_compile_definitions(bench-tests PUBLIC BENCHMARK_BIG_O=1)
endif()
if(BENCHMARK_100M)
message("-- BENCHMARK_100M=1")
- target_compile_definitions(bench-tests PRIVAT BENCHMARK_100M=1)
+ target_compile_definitions(bench-tests PUBLIC BENCHMARK_100M=1)
+endif()
+if(BENCHMARK_10M)
+ message("-- BENCHMARK_10M=1")
+ target_compile_definitions(bench-tests PUBLIC BENCHMARK_10M=1)
endif()
#examples
diff --git a/bench/run.cpp b/bench/run.cpp
index 2c9c592..9b449b2 100644
--- a/bench/run.cpp
+++ b/bench/run.cpp
@@ -39,10 +39,13 @@
BENCHMARK(BM_uniform)->Arg(2000)->Arg(100000)->Arg(200000)->Arg(500000)->Arg(1000000)->Unit(benchmark::kMillisecond);
#if BENCHMARK_BIG_O
- BENCHMARK(BM_uniform)->RangeMultiplier(2)->Range(1<<12, 1<<22)->Unit(benchmark::kMillisecond)->Complexity();
+BENCHMARK(BM_uniform)->RangeMultiplier(2)->Range(1 << 12, 1 << 22)->Unit(benchmark::kMillisecond)->Complexity();
+#endif
+#if BENCHMARK_10M
+BENCHMARK(BM_uniform)->Arg(1000000 * 10)->Unit(benchmark::kMillisecond);
#endif
#if BENCHMARK_100M
- BENCHMARK(BM_uniform)->Arg(1000000 * 100)->Unit(benchmark::kMillisecond);
+BENCHMARK(BM_uniform)->Arg(1000000 * 100)->Unit(benchmark::kMillisecond);
#endif
BENCHMARK_MAIN()
diff --git a/include/delaunator.hpp b/include/delaunator.hpp
index e526e50..0acfed5 100644
--- a/include/delaunator.hpp
+++ b/include/delaunator.hpp
@@ -150,7 +150,7 @@
constexpr std::size_t INVALID_INDEX = std::numeric_limits<std::size_t>::max();
//@see https://stackoverflow.com/questions/30208196/maximum-recursive-function-calls-in-c-c-before-stack-is-full-and-gives-a-segme
-constexpr std::size_t LEGALIZE_STACK_SIZE = 1024;
+constexpr std::size_t EDGE_STACK_SIZE = 1024;
inline bool check_pts_equal(double x1, double y1, double x2, double y2) {
return std::fabs(x1 - x2) <= EPSILON &&
@@ -193,7 +193,7 @@
double m_center_x;
double m_center_y;
std::size_t m_hash_size;
- std::size_t m_legalize_stack[LEGALIZE_STACK_SIZE];
+ std::size_t m_edge_stack[EDGE_STACK_SIZE];
std::size_t legalize(std::size_t a);
std::size_t hash_key(double x, double y) const;
@@ -219,7 +219,7 @@
m_center_x(),
m_center_y(),
m_hash_size(),
- m_legalize_stack() {
+ m_edge_stack() {
std::size_t n = coords.size() >> 1;
double max_x = std::numeric_limits<double>::min();
@@ -440,21 +440,13 @@
return sum(hull_area);
}
-std::size_t Delaunator::legalize(std::size_t ia) {
- std::size_t b;
- std::size_t a0;
- std::size_t b0;
- std::size_t al;
- std::size_t ar;
- std::size_t bl;
+std::size_t Delaunator::legalize(std::size_t a) {
+ std::size_t i = 0;
+ std::size_t ar = 0;
- unsigned int i = 0;
- m_legalize_stack[i] = ia;
- size_t size = 1;
- while (i < size) {
-
- auto const a = m_legalize_stack[i];
- i++;
+ // recursion eliminated with a fixed-size stack
+ while (true) {
+ const size_t b = halfedges[a];
/* if the pair of triangles doesn't satisfy the Delaunay condition
* (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
@@ -471,26 +463,29 @@
* \||/ \ /
* pr pr
*/
-
- b = halfedges[a];
-
- //@see https://embeddedgurus.com/stack-overflow/2011/02/efficient-c-tip-13-use-the-modulus-operator-with-caution/
- a0 = 3 * (a / 3); //a - a % 3;
- b0 = 3 * (b / 3); //b - b % 3;
-
- al = a0 + (a + 1) % 3;
+ const size_t a0 = 3 * (a / 3);
ar = a0 + (a + 2) % 3;
- bl = b0 + (b + 2) % 3;
+
+ if (b == INVALID_INDEX) {
+ if (i > 0) {
+ i--;
+ a = m_edge_stack[i];
+ continue;
+ } else {
+ //i = INVALID_INDEX;
+ break;
+ }
+ }
+
+ const size_t b0 = 3 * (b / 3);
+ const size_t al = a0 + (a + 1) % 3;
+ const size_t bl = b0 + (b + 2) % 3;
const std::size_t p0 = triangles[ar];
const std::size_t pr = triangles[a];
const std::size_t pl = triangles[al];
const std::size_t p1 = triangles[bl];
- if (b == INVALID_INDEX) {
- continue;
- }
-
const bool illegal = in_circle(
coords[2 * p0],
coords[2 * p0 + 1],
@@ -521,23 +516,19 @@
link(a, hbl);
link(b, halfedges[ar]);
link(ar, bl);
-
std::size_t br = b0 + (b + 1) % 3;
- if (size + 2 >= (LEGALIZE_STACK_SIZE)) {
- throw std::runtime_error("Legalize stack overflow");
+ if (i + 1 < EDGE_STACK_SIZE) {
+ m_edge_stack[i++] = br;
}
-
- if (i < size) {
- //move elements down the stack
- for (auto mi = size - 1; mi >= i; mi--) {
- m_legalize_stack[mi + 2] = m_legalize_stack[mi];
- }
+ } else {
+ if (i > 0) {
+ i--;
+ a = m_edge_stack[i];
+ continue;
+ } else {
+ break;
}
-
- m_legalize_stack[i] = a;
- m_legalize_stack[i + 1] = br;
- size += 2;
}
}
return ar;