2525//! - 3D-5D: Higher-dimensional triangulations as documented in README.md
2626
2727use criterion:: { BenchmarkId , Criterion , Throughput , criterion_group, criterion_main} ;
28- use delaunay:: core:: delaunay_triangulation:: { ConstructionOptions , RetryPolicy } ;
2928use delaunay:: geometry:: util:: generate_random_points_seeded;
30- use delaunay:: prelude:: DelaunayTriangulation ;
29+ use delaunay:: prelude:: { ConstructionOptions , DelaunayTriangulation , RetryPolicy } ;
3130use delaunay:: vertex;
3231use std:: hint:: black_box;
3332use std:: num:: NonZeroUsize ;
@@ -70,6 +69,88 @@ macro_rules! benchmark_tds_new_dimension {
7069 ) ]
7170 fn $func_name( c: & mut Criterion ) {
7271 let counts = COUNTS ;
72+
73+ // Opt-in helper for discovering stable seeds without paying Criterion warmup/
74+ // measurement cost per seed.
75+ //
76+ // NOTE: This helper is intentionally per (dim, count) benchmark case.
77+ // It returns early on the first successful seed (and panics on failure),
78+ // so it is meant to be run with a Criterion filter that selects a single
79+ // case, for example:
80+ //
81+ // cargo bench --bench ci_performance_suite -- 'tds_new_3d/tds_new/50'
82+ //
83+ // Because the base seed is derived from `count`, a seed that works for one
84+ // count may still fail for a different count.
85+ //
86+ // We avoid `std::process::exit` here so that destructors run and Criterion
87+ // can clean up state on both success and failure.
88+ if bench_seed_search_enabled( ) {
89+ let bounds = ( -100.0 , 100.0 ) ;
90+ let filters: Vec <String > = std:: env:: args( )
91+ . skip( 1 )
92+ . filter( |arg| !arg. starts_with( '-' ) )
93+ . collect( ) ;
94+
95+ for & count in counts {
96+ let bench_id =
97+ format!( "tds_new_{}d/tds_new/{}" , stringify!( $dim) , count) ;
98+
99+ if !filters. is_empty( ) && !filters. iter( ) . any( |filter| bench_id. contains( filter) ) {
100+ continue ;
101+ }
102+
103+ let seed = ( $seed as u64 ) . wrapping_add( count as u64 ) ;
104+ let limit = bench_seed_search_limit( ) ;
105+
106+ for offset in 0 ..limit {
107+ let candidate_seed = seed. wrapping_add( offset as u64 ) ;
108+ let points = generate_random_points_seeded:: <f64 , $dim>(
109+ count,
110+ bounds,
111+ candidate_seed,
112+ )
113+ . expect( concat!(
114+ "generate_random_points_seeded failed for " ,
115+ stringify!( $dim) ,
116+ "D"
117+ ) ) ;
118+ let vertices = points. iter( ) . map( |p| vertex!( * p) ) . collect:: <Vec <_>>( ) ;
119+
120+ let options =
121+ ConstructionOptions :: default ( ) . with_retry_policy( RetryPolicy :: Shuffled {
122+ attempts: NonZeroUsize :: new( 6 )
123+ . expect( "retry attempts must be non-zero" ) ,
124+ base_seed: Some ( candidate_seed) ,
125+ } ) ;
126+
127+ if DelaunayTriangulation :: <_, ( ) , ( ) , $dim>:: new_with_options(
128+ & vertices,
129+ options,
130+ )
131+ . is_ok( )
132+ {
133+ println!(
134+ "seed_search_found dim={} count={} seed={}" ,
135+ $dim, count, candidate_seed
136+ ) ;
137+ return ;
138+ }
139+ }
140+
141+ panic!(
142+ "seed_search_failed dim={} count={} start_seed={} limit={}" ,
143+ $dim,
144+ count,
145+ seed,
146+ limit
147+ ) ;
148+ }
149+
150+ // No filter matched this benchmark function; do nothing.
151+ return ;
152+ }
153+
73154 let mut group = c. benchmark_group( concat!( "tds_new_" , stringify!( $dim) , "d" ) ) ;
74155
75156 // Set smaller sample sizes for higher dimensions to keep CI times reasonable
@@ -92,65 +173,6 @@ macro_rules! benchmark_tds_new_dimension {
92173 let bounds = ( -100.0 , 100.0 ) ;
93174 let seed = ( $seed as u64 ) . wrapping_add( count as u64 ) ;
94175
95- // Opt-in helper for discovering stable seeds without paying Criterion warmup/
96- // measurement cost per seed.
97- //
98- // NOTE: This helper is intentionally per (dim, count) benchmark case.
99- // It `exit(0)`s on the first successful seed (and `exit(1)`s on failure),
100- // so it is meant to be run with a Criterion filter that selects a single
101- // case, for example:
102- //
103- // cargo bench --bench ci_performance_suite -- 'tds_new_3d/tds_new/50'
104- //
105- // Because the base seed is derived from `count`, a seed that works for one
106- // count may still fail for a different count.
107- if bench_seed_search_enabled( ) {
108- let limit = bench_seed_search_limit( ) ;
109- for offset in 0 ..limit {
110- let candidate_seed = seed. wrapping_add( offset as u64 ) ;
111- let points = generate_random_points_seeded:: <f64 , $dim>(
112- count,
113- bounds,
114- candidate_seed,
115- )
116- . expect( concat!(
117- "generate_random_points_seeded failed for " ,
118- stringify!( $dim) ,
119- "D"
120- ) ) ;
121- let vertices = points. iter( ) . map( |p| vertex!( * p) ) . collect:: <Vec <_>>( ) ;
122-
123- let options =
124- ConstructionOptions :: default ( ) . with_retry_policy( RetryPolicy :: Shuffled {
125- attempts: NonZeroUsize :: new( 6 )
126- . expect( "retry attempts must be non-zero" ) ,
127- base_seed: Some ( candidate_seed) ,
128- } ) ;
129-
130- if DelaunayTriangulation :: <_, ( ) , ( ) , $dim>:: new_with_options(
131- & vertices,
132- options,
133- )
134- . is_ok( )
135- {
136- println!(
137- "seed_search_found dim={} count={} seed={}" ,
138- $dim, count, candidate_seed
139- ) ;
140- std:: process:: exit( 0 ) ;
141- }
142- }
143-
144- println!(
145- "seed_search_failed dim={} count={} start_seed={} limit={}" ,
146- $dim,
147- count,
148- seed,
149- limit
150- ) ;
151- std:: process:: exit( 1 ) ;
152- }
153-
154176 let points = generate_random_points_seeded:: <f64 , $dim>( count, bounds, seed)
155177 . expect( concat!(
156178 "generate_random_points_seeded failed for " ,
0 commit comments