#!/usr/bin/env cargo
use delaunay::prelude::query::*;
use std::hint::black_box;
use std::time::Instant;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=================================================================");
println!("Zero-Allocation Iterator Demo");
println!("=================================================================\n");
let dt: delaunay::core::delaunay_triangulation::DelaunayTriangulation<_, (), (), 4> =
generate_random_triangulation(
12, (-1.0, 1.0), None, Some(777), )?;
let Some(cell) = dt.tds().cells().map(|(_, cell)| cell).next() else {
eprintln!("No cells in triangulation; nothing to demo.");
return Ok(());
};
println!(
"Using a 4D cell with {} vertices from triangulation\n",
cell.number_of_vertices()
);
println!("Functional Equivalence Test:");
println!("===========================");
let vec_uuids = cell.vertex_uuids(dt.tds())?;
let iter_uuids: Vec<_> = cell
.vertex_uuid_iter(dt.tds())
.collect::<Result<Vec<_>, _>>()?;
println!(" vertex_uuids() returned {} UUIDs", vec_uuids.len());
println!(
" vertex_uuid_iter().collect() returned {} UUIDs",
iter_uuids.len()
);
println!(
" Results are identical: {}",
vec_uuids.as_slice() == iter_uuids.as_slice()
);
println!();
println!("Performance Comparison:");
println!("======================");
let iterations = 10_000;
let start = Instant::now();
let mut total_count = 0;
for _ in 0..iterations {
if let Ok(uuids) = cell.vertex_uuids(dt.tds()) {
total_count += black_box(uuids.len()); }
}
let vec_duration = start.elapsed();
let start = Instant::now();
let mut total_count_iter = 0;
for _ in 0..iterations {
let count = cell.vertex_uuid_iter(dt.tds()).count(); total_count_iter += black_box(count);
}
let iter_duration = start.elapsed();
println!(" Method 1 (vertex_uuids): {vec_duration:>8.2?} ({iterations} iterations)");
println!(" Method 2 (vertex_uuid_iter): {iter_duration:>8.2?} ({iterations} iterations)");
if iter_duration.as_nanos() < 1000 || vec_duration.as_nanos() < 1000 {
println!(" Speedup: N/A (iteration time too small to measure reliably)");
} else {
let speedup = vec_duration.as_secs_f64() / iter_duration.as_secs_f64();
println!(" Speedup: {speedup:.2}x faster");
}
println!(" Counts match: {}", total_count == total_count_iter);
println!();
println!("Iterator Capabilities:");
println!("=====================");
let iter = cell.vertex_uuid_iter(dt.tds());
println!(" Length via ExactSizeIterator: {}", iter.len());
let mut count = 0;
for uuid in cell.vertex_uuid_iter(dt.tds()).flatten() {
if !uuid.is_nil() {
count += 1;
}
}
println!(" Non-nil UUIDs via for loop: {count}");
let valid_uuid_count = cell
.vertex_uuid_iter(dt.tds())
.filter_map(Result::ok)
.filter(|uuid| !uuid.is_nil())
.count();
println!(" Valid UUIDs via iterator chain: {valid_uuid_count}");
let first_few_count = cell.vertex_uuid_iter(dt.tds()).take(3).count();
println!(" First 3 UUIDs: {first_few_count} collected");
println!("\n=================================================================");
println!("Key Benefits of vertex_uuid_iter():");
println!("- Zero heap allocations (no Vec created)");
println!("- Implements ExactSizeIterator (O(1) len())");
println!("- Full iterator trait support (map, filter, etc.)");
println!("- Lazy evaluation (only compute what you need)");
println!("- Better performance for iteration-only use cases");
println!("=================================================================");
Ok(())
}