///|
/// Complete enumeration, or an error before traversal; never a truncated success.
pub fn Metric::reflections(
self : Metric,
d_min : Double,
max_candidates? : Int = 200000,
friedel_unique? : Bool = false,
) -> Result[Array[Hkl], Problem] {
if !finite(d_min) || d_min <= 0.0 {
return Err(Invalid("d_min must be finite positive"))
}
if max_candidates <= 0 || max_candidates > 2000000 {
return Err(Invalid("candidate budget outside [1,2000000]"))
}
// |h| <= a/d_min by Cauchy-Schwarz between direct and reciprocal vectors.
let bounds = [self.a / d_min, self.b / d_min, self.c / d_min]
if bounds.any(x => x > 999.0) {
return Err(Budget("Miller bound exceeds 999"))
}
// One guard shell handles rounding; q2 still controls membership.
let nh = bounds[0].to_int() + 1
let nk = bounds[1].to_int() + 1
let nl = bounds[2].to_int() + 1
let count = (2 * nh + 1).to_int64() *
(2 * nk + 1).to_int64() *
(2 * nl + 1).to_int64()
if count > max_candidates.to_int64() {
return Err(Budget("candidate box exceeds budget"))
}
let limit = 1.0 / (d_min * d_min)
let out = []
for h = -nh; h <= nh; h = h + 1 {
for k = -nk; k <= nk; k = k + 1 {
for l = -nl; l <= nl; l = l + 1 {
if h == 0 && k == 0 && l == 0 {
continue
}
let index = Hkl::{ h, k, l, }
if friedel_unique && index.canonical() != index {
continue
}
if self.q2(index) <= limit * (1.0 + 1.0e-12) {
out.push(index)
}
}
}
}
Ok(out)
}