gdsdiff 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. gdsdiff/__init__.py +148 -0
  2. gdsdiff/__main__.py +7 -0
  3. gdsdiff/_environment.py +12 -0
  4. gdsdiff/_version.py +34 -0
  5. gdsdiff/acceptance_evidence.py +530 -0
  6. gdsdiff/api.py +2955 -0
  7. gdsdiff/backends/__init__.py +26 -0
  8. gdsdiff/backends/base.py +77 -0
  9. gdsdiff/backends/boundary_loop_ctypes.py +191 -0
  10. gdsdiff/backends/cpu.py +20 -0
  11. gdsdiff/backends/cpu_ctypes.py +255 -0
  12. gdsdiff/backends/cuda.py +40 -0
  13. gdsdiff/backends/cuda_ctypes.py +1297 -0
  14. gdsdiff/backends/exact.py +424 -0
  15. gdsdiff/backends/geometry_ctypes.py +252 -0
  16. gdsdiff/backends/identity.py +53 -0
  17. gdsdiff/backends/metal.py +198 -0
  18. gdsdiff/backends/metal_ctypes.py +866 -0
  19. gdsdiff/backends/polygon_extract_ctypes.py +233 -0
  20. gdsdiff/backends/structural_ctypes.py +130 -0
  21. gdsdiff/boundary_loops.py +616 -0
  22. gdsdiff/cache.py +544 -0
  23. gdsdiff/canonicalize.py +176 -0
  24. gdsdiff/cli.py +352 -0
  25. gdsdiff/config.py +257 -0
  26. gdsdiff/cuda_setup.py +174 -0
  27. gdsdiff/design_history.py +65 -0
  28. gdsdiff/diagnostics.py +42 -0
  29. gdsdiff/diff_gds.py +66 -0
  30. gdsdiff/exact_diff_markdown.py +979 -0
  31. gdsdiff/exact_oracle.py +649 -0
  32. gdsdiff/extract.py +376 -0
  33. gdsdiff/gds_metadata.py +43 -0
  34. gdsdiff/geometry.py +112 -0
  35. gdsdiff/grid.py +143 -0
  36. gdsdiff/hierarchy.py +215 -0
  37. gdsdiff/hierarchy_extract.py +263 -0
  38. gdsdiff/inventory.py +153 -0
  39. gdsdiff/multiprocessing_support.py +39 -0
  40. gdsdiff/native.py +135 -0
  41. gdsdiff/native_cache.py +265 -0
  42. gdsdiff/native_src/cpu_prefilter.cpp +349 -0
  43. gdsdiff/native_src/gds_boundary_loops.cpp +505 -0
  44. gdsdiff/native_src/gds_geometry_scan.cpp +601 -0
  45. gdsdiff/native_src/gds_polygon_extract.cpp +594 -0
  46. gdsdiff/native_src/gds_structural_scan.cpp +335 -0
  47. gdsdiff/native_src/gdsdiff/CMakeLists.txt +74 -0
  48. gdsdiff/native_src/gdsdiff/core.cpp +191 -0
  49. gdsdiff/native_src/gdsdiff/core.hpp +96 -0
  50. gdsdiff/native_src/gdsdiff/cuda_assignment.cu +304 -0
  51. gdsdiff/native_src/gdsdiff/cuda_assignment.cuh +33 -0
  52. gdsdiff/native_src/gdsdiff/cuda_candidates.cu +133 -0
  53. gdsdiff/native_src/gdsdiff/cuda_candidates.cuh +17 -0
  54. gdsdiff/native_src/gdsdiff/cuda_ctypes.cu +4528 -0
  55. gdsdiff/native_src/gdsdiff/cuda_memory.cu +194 -0
  56. gdsdiff/native_src/gdsdiff/cuda_memory.cuh +34 -0
  57. gdsdiff/native_src/gdsdiff/metal_ctypes.mm +2791 -0
  58. gdsdiff/native_src/gdsdiff/python_bindings.cpp +21 -0
  59. gdsdiff/native_src/gdsdiff/test_core.cpp +93 -0
  60. gdsdiff/native_src/gdsdiff/test_cuda_assignment.cu +109 -0
  61. gdsdiff/native_src/gdsdiff/test_cuda_candidates.cu +94 -0
  62. gdsdiff/native_src/gdsdiff/test_cuda_memory.cu +97 -0
  63. gdsdiff/policy.py +305 -0
  64. gdsdiff/polygon_components.py +860 -0
  65. gdsdiff/profiles.py +152 -0
  66. gdsdiff/py.typed +1 -0
  67. gdsdiff/rect_coverage.py +384 -0
  68. gdsdiff/report.py +354 -0
  69. gdsdiff/schemas/gdsdiff_report-v1.schema.json +92 -0
  70. gdsdiff/semantics.py +75 -0
  71. gdsdiff/source_edge_diff.py +1120 -0
  72. gdsdiff/spatial.py +71 -0
  73. gdsdiff/structural_guard.py +161 -0
  74. gdsdiff/surplus_coverage.py +255 -0
  75. gdsdiff/synthetic_suite.py +1643 -0
  76. gdsdiff/templates.py +709 -0
  77. gdsdiff/tiling.py +153 -0
  78. gdsdiff/windowed_exact.py +270 -0
  79. gdsdiff/windows.py +184 -0
  80. gdsdiff-0.1.0.dist-info/METADATA +135 -0
  81. gdsdiff-0.1.0.dist-info/RECORD +85 -0
  82. gdsdiff-0.1.0.dist-info/WHEEL +5 -0
  83. gdsdiff-0.1.0.dist-info/entry_points.txt +4 -0
  84. gdsdiff-0.1.0.dist-info/licenses/LICENSE +674 -0
  85. gdsdiff-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ #include "core.hpp"
2
+
3
+ #include <pybind11/pybind11.h>
4
+
5
+ namespace py = pybind11;
6
+
7
+ PYBIND11_MODULE(_gds_compare_core, m) {
8
+ m.doc() = "Optional native core helpers for gdsdiff";
9
+ m.def("floor_div", &gdsdiff::floor_div, py::arg("value"), py::arg("divisor"));
10
+ m.def(
11
+ "bbox_tile_range",
12
+ [](std::int64_t x0, std::int64_t y0, std::int64_t x1, std::int64_t y1, std::int64_t tile_size) {
13
+ const auto bbox = gdsdiff::bbox_tile_range(gdsdiff::BBox{x0, y0, x1, y1}, tile_size);
14
+ return py::make_tuple(bbox.x0, bbox.y0, bbox.x1, bbox.y1);
15
+ },
16
+ py::arg("x0"),
17
+ py::arg("y0"),
18
+ py::arg("x1"),
19
+ py::arg("y1"),
20
+ py::arg("tile_size"));
21
+ }
@@ -0,0 +1,93 @@
1
+ #include "core.hpp"
2
+
3
+ #include <cassert>
4
+ #include <iostream>
5
+
6
+ using namespace gdsdiff;
7
+
8
+ namespace {
9
+
10
+ PolygonRecord rect(std::int64_t x0, std::int64_t y0, std::int64_t x1, std::int64_t y1, LayerSpec layer = {1, 0}) {
11
+ return PolygonRecord{
12
+ layer,
13
+ BBox{x0, y0, x1, y1},
14
+ std::vector<Point>{{x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}},
15
+ true,
16
+ };
17
+ }
18
+
19
+ } // namespace
20
+
21
+ int main() {
22
+ assert(floor_div(-1, 10) == -1);
23
+ assert(floor_div(-10, 10) == -1);
24
+ assert(floor_div(-11, 10) == -2);
25
+ assert((bbox_tile_range(BBox{-11, -1, 10, 20}, 10) == BBox{-2, -1, 1, 2}));
26
+
27
+ const auto a = rect(0, 0, 10, 10);
28
+ const PolygonRecord a_rotated{
29
+ a.layer,
30
+ a.bbox,
31
+ std::vector<Point>{{10, 10}, {0, 10}, {0, 0}, {10, 0}},
32
+ true,
33
+ };
34
+ assert(canonical_blob(a.points, true) == canonical_blob(a_rotated.points, true));
35
+ assert(canonical_blob(a.points, false) != canonical_blob(a_rotated.points, false));
36
+
37
+ const std::vector<std::string> blobs{
38
+ canonical_blob(a.points, true),
39
+ canonical_blob(a_rotated.points, true),
40
+ canonical_blob(rect(20, 0, 30, 10).points, true),
41
+ };
42
+ const auto ids = intern_canonical_blobs(blobs);
43
+ assert(ids.size() == 3);
44
+ assert(ids[0] == ids[1]);
45
+ assert(ids[0] != ids[2]);
46
+
47
+ const auto identical = run_tile_prefilter(
48
+ std::vector<PolygonRecord>{rect(0, 0, 9, 9)},
49
+ std::vector<std::uint64_t>{7},
50
+ std::vector<PolygonRecord>{rect(0, 0, 9, 9)},
51
+ std::vector<std::uint64_t>{7},
52
+ TileConfig{10, 4096});
53
+ assert(identical.candidate_tiles.empty());
54
+ assert(identical.assignment_count == 2);
55
+ assert(identical.collapsed_pair_count == 1);
56
+
57
+ const auto changed = run_tile_prefilter(
58
+ std::vector<PolygonRecord>{rect(0, 0, 9, 9)},
59
+ std::vector<std::uint64_t>{1},
60
+ std::vector<PolygonRecord>{rect(20, 0, 29, 9)},
61
+ std::vector<std::uint64_t>{2},
62
+ TileConfig{10, 4096});
63
+ assert(changed.candidate_tiles.size() == 2);
64
+ assert((changed.candidate_tiles[0] == TileKey{{1, 0}, 0, 0}));
65
+ assert((changed.candidate_tiles[1] == TileKey{{1, 0}, 2, 0}));
66
+
67
+ const auto oversized = run_tile_prefilter(
68
+ std::vector<PolygonRecord>{rect(0, 0, 100, 100)},
69
+ std::vector<std::uint64_t>{9},
70
+ std::vector<PolygonRecord>{},
71
+ std::vector<std::uint64_t>{},
72
+ TileConfig{10, 4});
73
+ assert(oversized.candidate_tiles.empty());
74
+ assert(oversized.oversized_candidates.size() == 1);
75
+ assert(oversized.oversized_candidates[0].side_mask == kOldSide);
76
+ assert((oversized.oversized_candidates[0].tile_bbox == BBox{0, 0, 10, 10}));
77
+
78
+ bool length_error = false;
79
+ try {
80
+ (void)run_tile_prefilter(
81
+ std::vector<PolygonRecord>{rect(0, 0, 1, 1)},
82
+ std::vector<std::uint64_t>{},
83
+ std::vector<PolygonRecord>{},
84
+ std::vector<std::uint64_t>{},
85
+ TileConfig{10, 4096});
86
+ } catch (const std::invalid_argument&) {
87
+ length_error = true;
88
+ }
89
+ assert(length_error);
90
+
91
+ std::cout << "cpp core tests passed\n";
92
+ return 0;
93
+ }
@@ -0,0 +1,109 @@
1
+ #include "cuda_assignment.cuh"
2
+
3
+ #include <algorithm>
4
+ #include <cassert>
5
+ #include <iostream>
6
+ #include <stdexcept>
7
+
8
+ using namespace gdsdiff;
9
+
10
+ namespace {
11
+
12
+ PolygonRecord rect(std::int64_t x0, std::int64_t y0, std::int64_t x1, std::int64_t y1, LayerSpec layer = {1, 0}) {
13
+ return PolygonRecord{
14
+ layer,
15
+ BBox{x0, y0, x1, y1},
16
+ std::vector<Point>{{x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}},
17
+ true,
18
+ };
19
+ }
20
+
21
+ std::vector<TileAssignment> cpu_assignments(
22
+ const std::vector<PolygonRecord>& polygons,
23
+ const std::vector<std::uint64_t>& ids,
24
+ std::uint8_t side,
25
+ const TileConfig& config,
26
+ std::vector<OversizedPolygon>* oversized) {
27
+ std::vector<TileAssignment> assignments;
28
+ for (std::size_t i = 0; i < polygons.size(); ++i) {
29
+ const auto range = bbox_tile_range(polygons[i].bbox, config.tile_size);
30
+ const std::uint64_t span_x = static_cast<std::uint64_t>(range.x1 - range.x0 + 1);
31
+ const std::uint64_t span_y = static_cast<std::uint64_t>(range.y1 - range.y0 + 1);
32
+ const std::uint64_t count = span_x * span_y;
33
+ if (count > config.max_tiles_per_polygon) {
34
+ oversized->push_back(OversizedPolygon{polygons[i].layer, ids[i], side, range});
35
+ continue;
36
+ }
37
+ for (std::int64_t tx = range.x0; tx <= range.x1; ++tx) {
38
+ for (std::int64_t ty = range.y0; ty <= range.y1; ++ty) {
39
+ assignments.push_back(TileAssignment{polygons[i].layer, tx, ty, ids[i], side});
40
+ }
41
+ }
42
+ }
43
+ return assignments;
44
+ }
45
+
46
+ void assert_matches_cpu(
47
+ const std::vector<PolygonRecord>& polygons,
48
+ const std::vector<std::uint64_t>& ids,
49
+ std::uint8_t side,
50
+ const TileConfig& config) {
51
+ std::vector<OversizedPolygon> expected_oversized;
52
+ auto expected = cpu_assignments(polygons, ids, side, config, &expected_oversized);
53
+ auto actual = run_cuda_assignment(polygons, ids, side, config);
54
+ std::sort(expected.begin(), expected.end());
55
+ std::sort(actual.assignments.begin(), actual.assignments.end());
56
+ std::sort(expected_oversized.begin(), expected_oversized.end());
57
+ std::sort(actual.oversized.begin(), actual.oversized.end());
58
+ assert(actual.assignments == expected);
59
+ assert(actual.oversized == expected_oversized);
60
+ assert(actual.total_assignment_count == expected.size());
61
+ }
62
+
63
+ } // namespace
64
+
65
+ int main() {
66
+ assert_matches_cpu({}, {}, kOldSide, TileConfig{10, 4096});
67
+ assert_matches_cpu(
68
+ std::vector<PolygonRecord>{rect(-11, -11, -1, -1)},
69
+ std::vector<std::uint64_t>{1},
70
+ kOldSide,
71
+ TileConfig{10, 4096});
72
+ assert_matches_cpu(
73
+ std::vector<PolygonRecord>{rect(0, 0, 10, 10)},
74
+ std::vector<std::uint64_t>{2},
75
+ kNewSide,
76
+ TileConfig{10, 4096});
77
+ assert_matches_cpu(
78
+ std::vector<PolygonRecord>{rect(0, 0, 100, 100)},
79
+ std::vector<std::uint64_t>{3},
80
+ kOldSide,
81
+ TileConfig{10, 4});
82
+
83
+ std::vector<PolygonRecord> many;
84
+ std::vector<std::uint64_t> ids;
85
+ for (int i = 0; i < 777; ++i) {
86
+ many.push_back(rect(i * 3, -i, i * 3 + 11, -i + 7, LayerSpec{i % 4, i % 2}));
87
+ ids.push_back(static_cast<std::uint64_t>(i % 9));
88
+ }
89
+ assert_matches_cpu(many, ids, kNewSide, TileConfig{10, 4096});
90
+
91
+ bool length_error = false;
92
+ try {
93
+ (void)run_cuda_assignment(std::vector<PolygonRecord>{rect(0, 0, 1, 1)}, {}, kOldSide, TileConfig{10, 4096});
94
+ } catch (const std::invalid_argument&) {
95
+ length_error = true;
96
+ }
97
+ assert(length_error);
98
+
99
+ bool config_error = false;
100
+ try {
101
+ (void)run_cuda_assignment(std::vector<PolygonRecord>{rect(0, 0, 1, 1)}, {1}, kOldSide, TileConfig{0, 4096});
102
+ } catch (const std::invalid_argument&) {
103
+ config_error = true;
104
+ }
105
+ assert(config_error);
106
+
107
+ std::cout << "cuda assignment tests passed\n";
108
+ return 0;
109
+ }
@@ -0,0 +1,94 @@
1
+ #include "cuda_candidates.cuh"
2
+
3
+ #include <algorithm>
4
+ #include <cassert>
5
+ #include <iostream>
6
+
7
+ using namespace gdsdiff;
8
+
9
+ namespace {
10
+
11
+ PolygonRecord rect(std::int64_t x0, std::int64_t y0, std::int64_t x1, std::int64_t y1, LayerSpec layer = {1, 0}) {
12
+ return PolygonRecord{
13
+ layer,
14
+ BBox{x0, y0, x1, y1},
15
+ std::vector<Point>{{x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}},
16
+ true,
17
+ };
18
+ }
19
+
20
+ void assert_same_result(
21
+ const std::vector<PolygonRecord>& old_polygons,
22
+ const std::vector<std::uint64_t>& old_ids,
23
+ const std::vector<PolygonRecord>& new_polygons,
24
+ const std::vector<std::uint64_t>& new_ids,
25
+ const TileConfig& config) {
26
+ auto cpu = run_tile_prefilter(old_polygons, old_ids, new_polygons, new_ids, config);
27
+ auto cuda = run_cuda_candidate_compaction(old_polygons, old_ids, new_polygons, new_ids, config);
28
+ std::sort(cpu.candidate_tiles.begin(), cpu.candidate_tiles.end());
29
+ std::sort(cuda.candidate_tiles.begin(), cuda.candidate_tiles.end());
30
+ std::sort(cpu.oversized_candidates.begin(), cpu.oversized_candidates.end());
31
+ std::sort(cuda.oversized_candidates.begin(), cuda.oversized_candidates.end());
32
+ assert(cuda.candidate_tiles == cpu.candidate_tiles);
33
+ assert(cuda.oversized_candidates == cpu.oversized_candidates);
34
+ assert(cuda.assignment_count == cpu.assignment_count);
35
+ assert(cuda.collapsed_pair_count == cpu.collapsed_pair_count);
36
+ assert(cuda.oversized_matched_count == cpu.oversized_matched_count);
37
+ }
38
+
39
+ } // namespace
40
+
41
+ int main() {
42
+ assert_same_result({}, {}, {}, {}, TileConfig{10, 4096});
43
+ assert_same_result(
44
+ {rect(0, 0, 9, 9)},
45
+ {1},
46
+ {rect(0, 0, 9, 9)},
47
+ {1},
48
+ TileConfig{10, 4096});
49
+ assert_same_result(
50
+ {rect(0, 0, 9, 9)},
51
+ {1},
52
+ {rect(20, 0, 29, 9)},
53
+ {2},
54
+ TileConfig{10, 4096});
55
+ assert_same_result(
56
+ {rect(0, 0, 9, 9), rect(0, 0, 9, 9)},
57
+ {5, 5},
58
+ {rect(0, 0, 9, 9)},
59
+ {5},
60
+ TileConfig{10, 4096});
61
+ assert_same_result(
62
+ {rect(-11, -11, -1, -1)},
63
+ {1},
64
+ {},
65
+ {},
66
+ TileConfig{10, 4096});
67
+ assert_same_result(
68
+ {rect(0, 0, 100, 100)},
69
+ {9},
70
+ {},
71
+ {},
72
+ TileConfig{10, 4});
73
+ assert_same_result(
74
+ {rect(0, 0, 100, 100)},
75
+ {9},
76
+ {rect(0, 0, 100, 100)},
77
+ {9},
78
+ TileConfig{10, 4});
79
+
80
+ std::vector<PolygonRecord> old_polygons;
81
+ std::vector<PolygonRecord> new_polygons;
82
+ std::vector<std::uint64_t> old_ids;
83
+ std::vector<std::uint64_t> new_ids;
84
+ for (int i = 0; i < 513; ++i) {
85
+ old_polygons.push_back(rect(i * 7 - 90, i % 17 - 40, i * 7 - 82, i % 17 - 31, LayerSpec{i % 5, i % 3}));
86
+ old_ids.push_back(static_cast<std::uint64_t>(i % 23));
87
+ new_polygons.push_back(rect(i * 7 - 88, i % 17 - 40, i * 7 - 80, i % 17 - 31, LayerSpec{i % 5, i % 3}));
88
+ new_ids.push_back(static_cast<std::uint64_t>((i + 1) % 23));
89
+ }
90
+ assert_same_result(old_polygons, old_ids, new_polygons, new_ids, TileConfig{16, 4096});
91
+
92
+ std::cout << "cuda candidate tests passed\n";
93
+ return 0;
94
+ }
@@ -0,0 +1,97 @@
1
+ #include "cuda_memory.cuh"
2
+ #include "cuda_candidates.cuh"
3
+
4
+ #include <algorithm>
5
+ #include <cassert>
6
+ #include <iostream>
7
+
8
+ using namespace gdsdiff;
9
+
10
+ namespace {
11
+
12
+ PolygonRecord rect(std::int64_t x0, std::int64_t y0, std::int64_t x1, std::int64_t y1, LayerSpec layer = {1, 0}) {
13
+ return PolygonRecord{
14
+ layer,
15
+ BBox{x0, y0, x1, y1},
16
+ std::vector<Point>{{x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}},
17
+ true,
18
+ };
19
+ }
20
+
21
+ void sort_result(TilePrefilterResult& result) {
22
+ std::sort(result.candidate_tiles.begin(), result.candidate_tiles.end());
23
+ std::sort(result.oversized_candidates.begin(), result.oversized_candidates.end());
24
+ }
25
+
26
+ void assert_chunked_matches(
27
+ const std::vector<PolygonRecord>& old_polygons,
28
+ const std::vector<std::uint64_t>& old_ids,
29
+ const std::vector<PolygonRecord>& new_polygons,
30
+ const std::vector<std::uint64_t>& new_ids,
31
+ const TileConfig& config,
32
+ const CudaMemoryBudget& budget,
33
+ bool expect_chunking) {
34
+ auto cpu = run_tile_prefilter(old_polygons, old_ids, new_polygons, new_ids, config);
35
+ auto whole_cuda = run_cuda_candidate_compaction(old_polygons, old_ids, new_polygons, new_ids, config);
36
+ auto chunked = run_cuda_candidate_compaction_chunked(old_polygons, old_ids, new_polygons, new_ids, config, budget);
37
+ sort_result(cpu);
38
+ sort_result(whole_cuda);
39
+ sort_result(chunked.prefilter);
40
+ assert(chunked.prefilter.candidate_tiles == cpu.candidate_tiles);
41
+ assert(chunked.prefilter.candidate_tiles == whole_cuda.candidate_tiles);
42
+ assert(chunked.prefilter.oversized_candidates == cpu.oversized_candidates);
43
+ assert(chunked.prefilter.oversized_candidates == whole_cuda.oversized_candidates);
44
+ assert(chunked.stats.chunk_count >= 1);
45
+ assert(chunked.stats.used_chunking == expect_chunking);
46
+ }
47
+
48
+ } // namespace
49
+
50
+ int main() {
51
+ assert_chunked_matches({}, {}, {}, {}, TileConfig{10, 4096}, CudaMemoryBudget{64, 64}, false);
52
+ assert_chunked_matches(
53
+ {rect(0, 0, 9, 45), rect(20, 0, 29, 9, LayerSpec{2, 0})},
54
+ {1, 2},
55
+ {rect(0, 10, 9, 55), rect(25, 0, 34, 9, LayerSpec{2, 0})},
56
+ {3, 4},
57
+ TileConfig{10, 4096},
58
+ CudaMemoryBudget{128, 64},
59
+ true);
60
+ assert_chunked_matches(
61
+ {rect(0, 0, 100, 100)},
62
+ {9},
63
+ {},
64
+ {},
65
+ TileConfig{10, 4},
66
+ CudaMemoryBudget{64, 64},
67
+ false);
68
+
69
+ std::vector<PolygonRecord> old_polygons;
70
+ std::vector<PolygonRecord> new_polygons;
71
+ std::vector<std::uint64_t> old_ids;
72
+ std::vector<std::uint64_t> new_ids;
73
+ for (int i = 0; i < 160; ++i) {
74
+ old_polygons.push_back(rect(i - 80, i * 5 - 300, i - 71, i * 5 - 276, LayerSpec{i % 3, i % 2}));
75
+ old_ids.push_back(static_cast<std::uint64_t>(i % 11));
76
+ new_polygons.push_back(rect(i - 78, i * 5 - 298, i - 69, i * 5 - 274, LayerSpec{i % 3, i % 2}));
77
+ new_ids.push_back(static_cast<std::uint64_t>((i + 3) % 11));
78
+ }
79
+ assert_chunked_matches(old_polygons, old_ids, new_polygons, new_ids, TileConfig{8, 4096}, CudaMemoryBudget{512, 64}, true);
80
+
81
+ bool config_error = false;
82
+ try {
83
+ (void)run_cuda_candidate_compaction_chunked(
84
+ {rect(0, 0, 1, 1)},
85
+ {1},
86
+ {},
87
+ {},
88
+ TileConfig{10, 4096},
89
+ CudaMemoryBudget{0, 64});
90
+ } catch (const std::invalid_argument&) {
91
+ config_error = true;
92
+ }
93
+ assert(config_error);
94
+
95
+ std::cout << "cuda memory tests passed\n";
96
+ return 0;
97
+ }