Skip to main content

gam_math/
score_opt.rs

1//! Certified global optimization of one-dimensional scores on a bounded
2//! domain, together with the affine-pencil spectral profile shared by the
3//! Gaussian REML smoothing-parameter searches.
4//!
5//! Point samples alone cannot prove that a smooth function has no narrow
6//! stationary pair between them.  The search therefore requires two pieces of
7//! information from its caller:
8//!
9//! * a nearest-rounded point evaluation `(value, first derivative, second
10//!   derivative)`, used only as a representative and to propose refinements;
11//! * an OUTER enclosure of the exact score value and both exact derivatives
12//!   over every requested interval, accompanied by a certified forward-error
13//!   bound for the scalar score evaluator.
14//!
15//! A cell needs no stationary decomposition when its derivative enclosure
16//! excludes zero or its exact score upper bound is strictly below an attained
17//! point-score lower bound. A stationary point is refined only after the second-derivative
18//! enclosure excludes zero, proving that the first derivative is monotone and
19//! hence that certified endpoint derivative ranges of opposite sign contain
20//! exactly one root. Every other interval is subdivided unless the exact score
21//! maximum is indistinguishable from an evaluated representative at the score
22//! evaluator's certified forward-error floor. Such a region is returned
23//! explicitly as a [`ResolutionFlatRegion`]; it is never mislabeled as a
24//! stationary point. This includes both a value-flat cell and a strictly concave
25//! cell whose unique maximum is already closer to the representative than the
26//! evaluator can resolve. A
27//! cell whose exact score upper bound is below an already attained exact
28//! point-score lower bound is retained as a [`DominatedRegion`] and needs no
29//! stationary decomposition: none of its structure can affect the global
30//! maximum. If neither exclusion, isolation, score-value flatness, nor exact
31//! dominance is proved before the requested abscissa resolution, the result is
32//! a typed [`ScoreSearchError::Unresolved`] rather than a best-effort optimum.
33//!
34//! [`AffineRemlProfile`] supplies both the point jets and rigorous interval
35//! formulas for scores whose penalized Hessian has simultaneously diagonal
36//! affine modes `h_i(lambda) = g_i + lambda s_i`.  This covers an ordinary
37//! Demmler--Reinsch eigensystem (`g_i = 1`) and a reference-Hessian pencil
38//! (`g_i = 1 - lambda_0 mu_i`, `s_i = mu_i`) without any matrix dependency in
39//! this crate.
40//!
41//! # The enclosure has to COLLAPSE, not merely be correct
42//!
43//! Everything above is a statement about what the search does with an
44//! enclosure; none of it says how tight one has to be, and the difference
45//! decides whether a domain can be decomposed at all. Every terminal verdict —
46//! derivative exclusion, stationary isolation, score-value flatness, exact
47//! dominance — is a comparison between an enclosure and a fixed quantity, so an
48//! enclosure whose overestimation is FIRST ORDER in the cell width buys a
49//! constant factor of resolution per subdivision, and the search enumerates
50//! cells until its budget is gone.
51//!
52//! That is not hypothetical: [`AffineRemlProfile::enclose`] was a natural
53//! interval extension, and on a REML score — whose log-determinant and deviance
54//! blocks each move by `O(rank)` per unit of `log lambda` while their sum does
55//! not — it returned a value range of exactly `rank * width`, up to `7.4e5`
56//! times wider than the cell's own derivative enclosure permitted, and refused
57//! designs it could certify. It is now a centred (mean value) form intersected
58//! with the natural one, in all three channels; see that method for the
59//! identity, the measurements, and what the centring is anchored on.
60
61use std::fmt;
62use std::sync::OnceLock;
63
64/// Closed real interval `[lo, hi]`.
65///
66/// Search callbacks may use infinite endpoints for conservative bounds, but
67/// neither endpoint may be NaN and `lo <= hi` must hold.  The search validates
68/// every enclosure returned by a callback.
69#[derive(Clone, Copy, Debug, PartialEq)]
70pub struct ClosedInterval {
71    pub lo: f64,
72    pub hi: f64,
73}
74
75impl ClosedInterval {
76    #[inline]
77    pub const fn new(lo: f64, hi: f64) -> Self {
78        Self { lo, hi }
79    }
80
81    #[inline]
82    pub const fn point(value: f64) -> Self {
83        Self {
84            lo: value,
85            hi: value,
86        }
87    }
88
89    #[inline]
90    pub const fn entire() -> Self {
91        Self {
92            lo: f64::NEG_INFINITY,
93            hi: f64::INFINITY,
94        }
95    }
96
97    #[inline]
98    pub fn contains(self, value: f64) -> bool {
99        self.lo <= value && value <= self.hi
100    }
101
102    #[inline]
103    pub fn contains_zero(self) -> bool {
104        self.contains(0.0)
105    }
106
107    #[inline]
108    fn is_valid(self) -> bool {
109        !self.lo.is_nan() && !self.hi.is_nan() && self.lo <= self.hi
110    }
111
112    #[inline]
113    fn hull(self, other: Self) -> Self {
114        Self {
115            lo: self.lo.min(other.lo),
116            hi: self.hi.max(other.hi),
117        }
118    }
119
120    #[inline]
121    fn intersection(self, other: Self) -> Option<Self> {
122        let intersection = Self {
123            lo: self.lo.max(other.lo),
124            hi: self.hi.min(other.hi),
125        };
126        (intersection.lo <= intersection.hi).then_some(intersection)
127    }
128
129    #[inline]
130    fn max_abs(self) -> f64 {
131        self.lo.abs().max(self.hi.abs())
132    }
133
134    #[inline]
135    fn widen(self, radius: f64) -> Self {
136        if radius == 0.0 {
137            return self;
138        }
139        if radius == f64::INFINITY {
140            return Self::entire();
141        }
142        Self {
143            lo: next_down(self.lo - radius),
144            hi: next_up(self.hi + radius),
145        }
146    }
147
148    #[inline]
149    /// Directed outer enclosure of the exact sum of two intervals.
150    pub fn add(self, other: Self) -> Self {
151        Self {
152            lo: sum_down(self.lo, other.lo),
153            hi: sum_up(self.hi, other.hi),
154        }
155    }
156
157    #[inline]
158    /// Directed outer enclosure of the exact interval difference.
159    pub fn sub(self, other: Self) -> Self {
160        Self {
161            lo: sum_down(self.lo, -other.hi),
162            hi: sum_up(self.hi, -other.lo),
163        }
164    }
165
166    #[inline]
167    /// Exact sign reversal of the interval.
168    pub fn neg(self) -> Self {
169        Self {
170            lo: -self.hi,
171            hi: -self.lo,
172        }
173    }
174
175    /// Directed outer enclosure of the exact interval product.
176    pub fn mul(self, other: Self) -> Self {
177        let pairs = [
178            (self.lo, other.lo),
179            (self.lo, other.hi),
180            (self.hi, other.lo),
181            (self.hi, other.hi),
182        ];
183        let mut lo = f64::INFINITY;
184        let mut hi = f64::NEG_INFINITY;
185        for (left, right) in pairs {
186            lo = lo.min(product_down(left, right));
187            hi = hi.max(product_up(left, right));
188        }
189        Self { lo, hi }
190    }
191
192    #[inline]
193    /// Directed outer enclosure after multiplication by an exact binary64
194    /// scalar.
195    pub fn scale(self, value: f64) -> Self {
196        self.mul(Self::point(value))
197    }
198
199    fn square(self) -> Self {
200        if self.lo >= 0.0 {
201            Self {
202                lo: product_down(self.lo, self.lo).max(0.0),
203                hi: product_up(self.hi, self.hi),
204            }
205        } else if self.hi <= 0.0 {
206            Self {
207                lo: product_down(self.hi, self.hi).max(0.0),
208                hi: product_up(self.lo, self.lo),
209            }
210        } else {
211            Self {
212                lo: 0.0,
213                hi: product_up(self.lo, self.lo).max(product_up(self.hi, self.hi)),
214            }
215        }
216    }
217
218    /// Natural logarithm of an interval known to be strictly positive.
219    fn ln_positive(self) -> Self {
220        assert!(
221            self.lo > 0.0,
222            "ln_positive requires a strictly positive interval, got lo={}",
223            self.lo
224        );
225        let lo = certified_ln_positive(self.lo)
226            .expect("ln_positive lower endpoint is finite and positive");
227        let hi = certified_ln_positive(self.hi)
228            .expect("ln_positive upper endpoint is finite and positive");
229        Self::new(lo.lo, hi.hi)
230    }
231
232    /// Divide by an interval known to be strictly positive.
233    fn div_positive(self, denominator: Self) -> Self {
234        assert!(
235            denominator.lo > 0.0,
236            "div_positive requires a strictly positive denominator interval, got lo={}",
237            denominator.lo
238        );
239        let reciprocal = Self {
240            lo: quotient_down(1.0, denominator.hi).max(0.0),
241            hi: quotient_up(1.0, denominator.lo),
242        };
243        self.mul(reciprocal)
244    }
245
246    /// Divide by an interval that excludes zero.
247    fn div_nonzero(self, denominator: Self) -> Self {
248        if denominator.lo > 0.0 {
249            self.div_positive(denominator)
250        } else {
251            assert!(
252                denominator.hi < 0.0,
253                "div_nonzero requires a denominator interval excluding zero, got {denominator:?}"
254            );
255            self.div_positive(denominator.neg()).neg()
256        }
257    }
258
259    #[inline]
260    fn nonnegative(self) -> Self {
261        Self {
262            lo: self.lo.max(0.0),
263            hi: self.hi.max(0.0),
264        }
265    }
266}
267
268/// Nearest-rounded value and analytic derivatives at one abscissa.
269///
270/// `third` is carried alongside the first two because every endpoint-anchored
271/// [`DerivativeEnclosure`] in this workspace is built from the endpoint
272/// curvature and third derivative. Dropping it here used to force the enclosure
273/// oracle to RE-EVALUATE the criterion at both endpoints of every
274/// branch-and-bound cell — endpoints the search had already sampled — which
275/// tripled the number of criterion evaluations the search actually paid for.
276/// Oracles that have no third derivative to report set it to zero; enclosures
277/// that do not consult it are unaffected.
278#[derive(Clone, Copy, Debug, PartialEq)]
279pub struct ScoreJet {
280    pub value: f64,
281    pub derivative: f64,
282    pub curvature: f64,
283    pub third: f64,
284}
285
286/// A point evaluation augmented with its abscissa.
287#[derive(Clone, Copy, Debug, PartialEq)]
288pub struct ScoreSample {
289    pub x: f64,
290    pub value: f64,
291    pub derivative: f64,
292    pub curvature: f64,
293    pub third: f64,
294}
295
296/// Exact score-value range and the numerical resolution of point values.
297///
298/// `value` contains the exact-real score at every point of the cell.
299/// `evaluation_error` is an absolute forward-error bound for both endpoint
300/// values supplied with that cell:
301///
302/// `|endpoint.value - exact_score(endpoint.x)| <= evaluation_error`.
303///
304/// An interval-extension oracle may provide the stronger cell-uniform bound.
305/// The search needs only the endpoint statement: every representative it
306/// retains is an evaluated cell endpoint. The corresponding uncertainty of a
307/// comparison between the two endpoints is at most `2 * evaluation_error`.
308#[derive(Clone, Copy, Debug, PartialEq)]
309pub struct ScoreValueEnclosure {
310    pub value: ClosedInterval,
311    pub evaluation_error: f64,
312}
313
314/// Exact-real score and derivative ranges supplied to the certified search.
315///
316/// Scalar derivative estimates are proposals only. Exclusion, monotonicity,
317/// and root-sign decisions use these mathematical ranges directly, so
318/// derivative-evaluator roundoff never becomes part of a proof predicate.
319#[derive(Clone, Copy, Debug, PartialEq)]
320pub struct DerivativeEnclosure {
321    pub score: ScoreValueEnclosure,
322    pub derivative: ClosedInterval,
323    pub curvature: ClosedInterval,
324}
325
326/// A region whose exact maximum is indistinguishable from an evaluated
327/// representative at the representable resolution of its score.
328///
329/// `max_score_gap` bounds `max(score over bracket) - score(sample.x)` in exact
330/// score units. `score_resolution` is the certified forward-error scale at
331/// which that improvement is numerically immaterial. The search records this
332/// region only when `max_score_gap <= score_resolution`.
333#[derive(Clone, Copy, Debug, PartialEq)]
334pub struct ResolutionFlatRegion {
335    pub sample: ScoreSample,
336    pub bracket: ClosedInterval,
337    /// Exact score range over `bracket`.
338    pub score: ClosedInterval,
339    pub max_score_gap: f64,
340    pub score_resolution: f64,
341}
342
343/// One stationary point together with the final bracket that certifies its
344/// location.  The bracket width is no larger than the requested resolution,
345/// unless the point was represented exactly (a zero-width bracket).
346#[derive(Clone, Copy, Debug, PartialEq)]
347pub struct StationaryPoint {
348    pub sample: ScoreSample,
349    pub bracket: ClosedInterval,
350    /// Exact score range over `bracket` and endpoint evaluation resolution.
351    pub score: ScoreValueEnclosure,
352    /// Strict curvature enclosure that proved the derivative root unique.
353    ///
354    /// This may be tighter than a fresh enclosure on the final tiny bracket:
355    /// cancellation can erase a sign under subdivision even though the wider
356    /// parent certificate remains valid on every subset.
357    pub curvature: ClosedInterval,
358}
359
360/// Exact-value certificate for the representative selected by the rounded
361/// evaluator.
362#[derive(Clone, Copy, Debug, PartialEq)]
363pub struct GlobalScoreCertificate {
364    /// Exact score at the returned representative.
365    pub selected: ClosedInterval,
366    /// Outer range containing the exact global maximum.
367    pub maximum: ClosedInterval,
368    /// Outward bound on `global maximum - exact score(representative)`.
369    /// Repeated certificates of the same represented point contribute zero:
370    /// they name the same exact real value, rather than independent uncertain
371    /// quantities.
372    pub maximum_excess: f64,
373    /// Outward sum of the selected point evaluator's forward error and the
374    /// largest competing representative's forward error. Exact terminal
375    /// ranges remain separate in [`Self::maximum_excess`].
376    pub comparison_resolution: f64,
377}
378
379#[derive(Clone, Copy, Debug, PartialEq, Eq)]
380pub enum ScoreOptimumLocation {
381    LowerBoundary,
382    UpperBoundary,
383    Stationary(usize),
384    ResolutionFlat(usize),
385}
386
387/// A cell excluded from the global maximum by exact score ordering.
388///
389/// `score.hi < incumbent_lower` proves every exact score in `bracket` is below
390/// an exact score already attained at an evaluated point. Stationary structure
391/// inside the cell is therefore irrelevant to the global maximum, but the
392/// region is retained so that this branch-and-bound decision remains auditable.
393#[derive(Clone, Copy, Debug, PartialEq)]
394pub struct DominatedRegion {
395    pub bracket: ClosedInterval,
396    pub score: ScoreValueEnclosure,
397    pub incumbent_lower: f64,
398}
399
400/// Complete successful search result. Endpoints, isolated stationary points,
401/// resolution-flat regions, and exactly dominated regions are retained
402/// explicitly so every terminal proof is independently checkable by the
403/// caller.
404#[derive(Clone, Debug, PartialEq)]
405pub struct ScoreSearchResult {
406    pub optimum: ScoreSample,
407    pub location: ScoreOptimumLocation,
408    pub lower_boundary: ScoreSample,
409    pub upper_boundary: ScoreSample,
410    pub stationary_points: Vec<StationaryPoint>,
411    pub resolution_flat_regions: Vec<ResolutionFlatRegion>,
412    /// Pairwise-disjoint terminal cells. A binary tree with at most `B`
413    /// subdivisions has at most `B + 1` leaves, so this audit is bounded by
414    /// the same [`subdivision_budget`] as the traversal.
415    pub dominated_regions: Vec<DominatedRegion>,
416    pub value_certificate: GlobalScoreCertificate,
417}
418
419/// Failure of the generic certified search.
420#[derive(Debug)]
421pub enum ScoreSearchError<E> {
422    InvalidDomain {
423        lo: f64,
424        hi: f64,
425    },
426    InvalidResolution {
427        resolution: f64,
428    },
429    PointEvaluation {
430        x: f64,
431        source: E,
432    },
433    EnclosureEvaluation {
434        lo: f64,
435        hi: f64,
436        source: E,
437    },
438    NonFiniteSample {
439        sample: ScoreSample,
440    },
441    InvalidEnclosure {
442        lo: f64,
443        hi: f64,
444        enclosure: DerivativeEnclosure,
445    },
446    ScoreValueEnclosureMissesEndpoint {
447        lo: f64,
448        hi: f64,
449        endpoint: ScoreSample,
450        score: ScoreValueEnclosure,
451    },
452    DisjointEndpointEnclosure {
453        lo: f64,
454        hi: f64,
455        endpoint: ScoreSample,
456        endpoint_derivative: ClosedInterval,
457        enclosure: DerivativeEnclosure,
458    },
459    /// Independent interval-Newton images of a root that was already proved
460    /// unique have empty intersection. This is a contradiction between
461    /// certificates, not an unresolved search cell.
462    InconsistentRootEnclosure {
463        lo: f64,
464        hi: f64,
465        left_derivative: ClosedInterval,
466        right_derivative: ClosedInterval,
467        curvature: ClosedInterval,
468        left_newton: ClosedInterval,
469        right_newton: ClosedInterval,
470        point_newton: ClosedInterval,
471    },
472    /// Neither stationary exclusion/isolation nor score flatness could be
473    /// proved before the requested or floating-point abscissa-resolution
474    /// floor.
475    Unresolved {
476        lo: f64,
477        hi: f64,
478        requested_resolution: f64,
479        enclosure: DerivativeEnclosure,
480    },
481    /// The traversal asked for more cell subdivisions than
482    /// [`subdivision_budget`] allows for this domain and resolution. Reported
483    /// with the cell that was being split when the budget ran out, so the
484    /// caller can see WHERE the criterion stopped being decomposable, and with
485    /// that cell's enclosure, so the caller can see WHETHER a larger budget
486    /// could ever have helped: once the certified evaluation error reaches the
487    /// requested resolution, no amount of subdivision separates stationary
488    /// structure at that tolerance (#2614).
489    SubdivisionBudget {
490        lo: f64,
491        hi: f64,
492        cell_lo: f64,
493        cell_hi: f64,
494        requested_resolution: f64,
495        subdivisions: usize,
496        budget: usize,
497        depth_bound: u32,
498        enclosure: DerivativeEnclosure,
499    },
500}
501
502/// Total cell subdivisions a converging certified 1-D search may spend on
503/// `[lo, hi]` at `resolution`.
504///
505/// Two facts set the scale. First, no cell can be halved more than
506/// `D = ceil(log2((hi - lo) / resolution))` times before it is narrower than
507/// `resolution`, where the search already stops with
508/// [`ScoreSearchError::Unresolved`] — so `D` bounds the depth of the
509/// subdivision tree outright. Second, a search that is ISOLATING structure
510/// spends at most `D` subdivisions per cell it finally certifies, because each
511/// one halves the cell it is working in.
512///
513/// So the whole traversal costs at most `D` times the size of the certified
514/// decomposition, and the budget is that product with the decomposition
515/// allowed `2 D` cells — twice as many certified cells as the domain has
516/// resolvable binary levels. Measured on #2546's cascade: every terminating
517/// search on that surface spent 33–39 subdivisions at `D = 32`, i.e. about `D`,
518/// against a budget of `2 D² = 2048`; the non-terminating one passes 40 000
519/// with its bracket still halving cleanly at every node. The margin over the
520/// deepest currently-successful search is ~60x, so the budget is invisible to
521/// every search that converges and is reached in under a second by one that
522/// does not.
523///
524/// gam#2614 — that ~60x margin is NOT general, and the `2 D` cell allowance is
525/// the reason. The `D` factor is derived: no cell survives more than `D`
526/// halvings before it is narrower than `resolution`. The cell allowance is an
527/// assumption about how many cells a criterion's certified decomposition
528/// contains, which is exactly what the search cannot know in advance.
529///
530/// Read the calibration above again: spending about `D` subdivisions IN TOTAL,
531/// at `D` per certified cell, means that surface's decomposition was about ONE
532/// cell. The `2 D` allowance (64 cells at `D = 32`) was never exercised there,
533/// so the quoted margin is headroom over a single-cell case.
534///
535/// Measured since, at the same `D = 32`, which is why the multiplier below is 8
536/// and not 2. Bisected across the FULL `spline_scan` set:
537///
538/// ```text
539///   2 D² (  64 cells)  order_one_scan_matches_dense_random_walk_posterior refused
540///   4 D² ( 128 cells)  passes
541///   8 D² ( 256 cells)  passes          <- shipped
542/// 128 D² (4096 cells)  passes, and NO further test passes
543/// ```
544///
545/// That search is not going deeper than `D` per cell — the depth bound is a hard
546/// geometric fact. It isolates structure over a decomposition of 65–128 cells,
547/// wider than the `2 D` allowance anticipated, so against that surface the older
548/// "~60x margin" was negative. Nothing above `8 D²` buys another passing test.
549///
550/// A larger allowance does NOT repair the other scan refusals, and raising it
551/// past this point actively HIDES their cause. At `128 D²` the budget message
552/// disappears entirely and
553/// `state_snapshot_round_trips_predict_and_training_sample_size_bit_for_bit` —
554/// which exhausted the budget at both 2048 and 8192 — instead reports
555/// `OptimumResolutionFlat` on a bracket `2.15e-6` wide, about twice the endpoint
556/// `eval_err` of `~9.6e-7`. The budget was masking a score-RESOLUTION floor.
557/// Likewise `weighted_scan_dgp_2300_search_terminates_in_bounded_evaluations`
558/// fails identically at every multiplier tested, because its certificates carry
559/// `eval_err ~1e-6` while the search requests `resolution = 1.49e-8`.
560///
561/// So: three of the four `spline_scan` failures are evaluation-conditioning, not
562/// cell shortage, and no allowance reaches them. Do not raise this constant
563/// further expecting it to fix them — it converts a budget refusal into a
564/// resolution refusal and gains no coverage.
565///
566/// A degenerate domain still gets a budget of at least one subdivision: the
567/// bound is a backstop against unbounded breadth, never a refusal of the first
568/// split.
569///
570/// # The request, not the budget, is what actually binds (#2614, measured 0731)
571///
572/// Callers pass `f64::EPSILON.sqrt()` (`1.4901161193847656e-8`) as the requested
573/// resolution — a MACHINE constant. The achievable certified evaluation error is
574/// a property of the problem and varies by more than forty times between callers:
575///
576/// | caller | `evaluation_error` | `requested_resolution` | terminal bracket |
577/// |---|---|---|---|
578/// | `gam-solve` spline_scan | `9.741e-7` | `1.490e-8` | — |
579/// | `gam-predict` weighted scan | `2.302e-8` | `1.490e-8` | `~4.8e-8` ≈ 2 × eval_err |
580///
581/// In both the error EXCEEDS the request, and `gam-predict` terminates at almost
582/// exactly twice its own evaluation error — the floor you would predict, since
583/// inside that width the endpoint enclosures overlap and no comparison is
584/// decidable. In both the derivative enclosure straddles zero, so even the sign
585/// of the slope is undecidable there.
586///
587/// A fixed `sqrt(EPSILON)` request cannot be right for both. The resolution
588/// should be derived from the evaluator's certified error at the working point
589/// rather than pinned to a machine constant.
590///
591/// # That recommendation is NOT the repair for a budget refusal, measured
592///
593/// It was taken as one, and the discriminator says otherwise. On a rank-deficient
594/// cascade design (36 rows, 1725 columns, 33 modes on a 40.6-wide domain) that
595/// refused here at 8193/8192 subdivisions, the same search was run at four
596/// requested resolutions spanning five orders — `1.49e-8`, `1e-6`, `1e-4`,
597/// `1e-3` — and **every one refused**, the terminal cell merely walking down the
598/// domain (`-16.79`, `-18.51`, `-20.08`, `-20.59`) as the request coarsened.
599/// Matching the request to the evaluator's error bought nothing there.
600///
601/// What bound that search was the ENCLOSURE, one level down: the score's value
602/// range was a natural interval extension, first order in the cell width with
603/// constant `rank` (`33.0·w`, over six decades) against an exact `|f'|` of
604/// `1.15e-5`. `resolution_flat_region` reads that range, so no cell could be
605/// retired at any request. With the centred form in
606/// [`AffineRemlProfile::enclose`] the same design certifies in 0.4 s at every
607/// one of those four requests.
608///
609/// The two `spline_scan` refusals named above also both PASS now
610/// (`cargo test -p gam-solve --lib`, 1898 of 1901, and neither is among the
611/// three reds). So the table above stands as a measurement of a real
612/// mismatch — a machine constant is still the wrong source for a
613/// problem-dependent tolerance — but the failures it was written to explain are
614/// gone, and it should not be cited as the cause of a fresh one without a
615/// discriminator like the ladder above.
616pub fn subdivision_budget(lo: f64, hi: f64, resolution: f64) -> (usize, u32) {
617    let width = hi - lo;
618    if !(width.is_finite() && width > 0.0 && resolution.is_finite() && resolution > 0.0) {
619        return (1, 0);
620    }
621    let levels = (width / resolution).log2().ceil();
622    let depth_bound = if levels.is_finite() && levels >= 1.0 {
623        // `f64::MANTISSA_DIGITS`-scaled domains cannot exceed the exponent
624        // range, so the cast is saturating in practice and clamped in fact.
625        levels.min(u32::MAX as f64) as u32
626    } else {
627        1
628    };
629    let depth = depth_bound as usize;
630    (8 * depth * depth, depth_bound)
631}
632
633impl<E: fmt::Display> fmt::Display for ScoreSearchError<E> {
634    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635        match self {
636            Self::InvalidDomain { lo, hi } => {
637                write!(f, "score search: invalid domain [{lo}, {hi}]")
638            }
639            Self::InvalidResolution { resolution } => {
640                write!(f, "score search: invalid resolution {resolution}")
641            }
642            Self::PointEvaluation { x, source } => {
643                write!(f, "score search: evaluation failed at {x}: {source}")
644            }
645            Self::EnclosureEvaluation { lo, hi, source } => write!(
646                f,
647                "score search: score/derivative enclosure failed on [{lo}, {hi}]: {source}"
648            ),
649            Self::NonFiniteSample { sample } => write!(
650                f,
651                "score search: non-finite jet at {} (value {}, derivative {}, curvature {}, third {})",
652                sample.x, sample.value, sample.derivative, sample.curvature, sample.third
653            ),
654            Self::InvalidEnclosure { lo, hi, enclosure } => write!(
655                f,
656                "score search: invalid score/derivative enclosure on [{lo}, {hi}]: {enclosure:?}"
657            ),
658            Self::ScoreValueEnclosureMissesEndpoint {
659                lo,
660                hi,
661                endpoint,
662                score,
663            } => write!(
664                f,
665                "score search: exact score range {:?} plus evaluator error {} on [{lo}, {hi}] misses the rounded endpoint value {} at {}",
666                score.value, score.evaluation_error, endpoint.value, endpoint.x
667            ),
668            Self::DisjointEndpointEnclosure {
669                lo,
670                hi,
671                endpoint,
672                endpoint_derivative,
673                enclosure,
674            } => write!(
675                f,
676                "score search: derivative enclosures on [{lo}, {hi}] and its endpoint {} are disjoint: endpoint range {endpoint_derivative:?}, cell {enclosure:?}; point estimate {endpoint:?}",
677                endpoint.x
678            ),
679            Self::InconsistentRootEnclosure {
680                lo,
681                hi,
682                left_derivative,
683                right_derivative,
684                curvature,
685                left_newton,
686                right_newton,
687                point_newton,
688            } => write!(
689                f,
690                "score search: interval-Newton certificates for the unique root on [{lo}, {hi}] \
691                 are inconsistent: left derivative {left_derivative:?}, right derivative \
692                 {right_derivative:?}, curvature {curvature:?}, left image {left_newton:?}, \
693                 right image {right_newton:?}, point image {point_newton:?}"
694            ),
695            Self::Unresolved {
696                lo,
697                hi,
698                requested_resolution,
699                enclosure,
700            } => {
701                // The enclosure already carries both numbers, but a reader has
702                // to notice the comparison themselves. State it: when the
703                // certified evaluation error has reached the requested
704                // resolution, the request is the defect, not the search (#2614).
705                let evaluation_error = enclosure.score.evaluation_error;
706                let verdict = if evaluation_error >= *requested_resolution {
707                    " -- the REQUEST is unsatisfiable: the certified evaluation error at this cell \
708                     already reaches the requested resolution, so no bracket narrower than about \
709                     twice that error is decidable and no additional subdivision can close it"
710                } else {
711                    ""
712                };
713                write!(
714                    f,
715                    "score search: stationary structure unresolved on [{lo}, {hi}] at requested \
716                     resolution {requested_resolution} (certified evaluation error \
717                     {evaluation_error:e}){verdict}: {enclosure:?}"
718                )
719            }
720            Self::SubdivisionBudget {
721                lo,
722                hi,
723                cell_lo,
724                cell_hi,
725                requested_resolution,
726                subdivisions,
727                budget,
728                depth_bound,
729                enclosure,
730            } => {
731                // Which of these two numbers is larger decides whether a bigger
732                // budget is a fix or a distraction. Reporting the budget alone
733                // sends the reader to the wrong lever (#2614).
734                let evaluation_error = enclosure.score.evaluation_error;
735                let verdict = if evaluation_error >= *requested_resolution {
736                    "a LARGER BUDGET CANNOT HELP -- the certified evaluation error already reaches \
737                     the requested resolution, so no subdivision separates stationary structure at \
738                     this tolerance; the resolution asked for is finer than the evaluator delivers"
739                } else {
740                    "the evaluation error is below the requested resolution, so this cell was still \
741                     separable and a larger budget may resolve it"
742                };
743                write!(
744                    f,
745                    "score search: {subdivisions} cell subdivisions on [{lo}, {hi}] at requested \
746                     resolution {requested_resolution} exceed the budget {budget} derived from this \
747                     domain's subdivision depth bound {depth_bound}; the criterion is still \
748                     undecomposable at [{cell_lo}, {cell_hi}], so it neither excludes nor isolates \
749                     stationary structure over a region the search can only enumerate. Certified \
750                     evaluation error at this cell is {evaluation_error:e} against requested \
751                     resolution {requested_resolution:e}: {verdict}"
752                )
753            }
754        }
755    }
756}
757
758impl<E: std::error::Error + 'static> std::error::Error for ScoreSearchError<E> {}
759
760#[derive(Clone, Copy)]
761struct SearchSample {
762    sample: ScoreSample,
763    point_enclosure: Option<DerivativeEnclosure>,
764}
765
766#[derive(Clone, Copy)]
767struct SearchNode {
768    left: SearchSample,
769    right: SearchSample,
770}
771
772#[derive(Clone, Copy)]
773struct TerminalScoreCandidate {
774    score: ScoreValueEnclosure,
775    /// Forward error of the rounded representative used to compare this
776    /// candidate with the selected representative. For a region certificate
777    /// this is kept separate from the exact range: the range bounds the
778    /// terminal maximum, while the error belongs to an actually evaluated
779    /// point.
780    comparison_error: f64,
781    /// Present only when the terminal maximum is the exact score at this
782    /// represented point. Region certificates deliberately carry `None` so
783    /// their possible improvement over a representative is retained.
784    point_x: Option<f64>,
785}
786
787impl TerminalScoreCandidate {
788    #[inline]
789    fn point(x: f64, score: ScoreValueEnclosure) -> Self {
790        Self {
791            score,
792            comparison_error: score.evaluation_error,
793            point_x: Some(x),
794        }
795    }
796
797    #[inline]
798    fn region(score: ScoreValueEnclosure, comparison_error: f64) -> Self {
799        Self {
800            score,
801            comparison_error,
802            point_x: None,
803        }
804    }
805}
806
807fn evaluate_sample<E, F>(x: f64, evaluate: &mut F) -> Result<SearchSample, ScoreSearchError<E>>
808where
809    F: FnMut(f64) -> Result<ScoreJet, E>,
810{
811    let jet = evaluate(x).map_err(|source| ScoreSearchError::PointEvaluation { x, source })?;
812    let sample = ScoreSample {
813        x,
814        value: jet.value,
815        derivative: jet.derivative,
816        curvature: jet.curvature,
817        third: jet.third,
818    };
819    if sample.value.is_finite()
820        && sample.derivative.is_finite()
821        && sample.curvature.is_finite()
822        && sample.third.is_finite()
823    {
824        Ok(SearchSample {
825            sample,
826            point_enclosure: None,
827        })
828    } else {
829        Err(ScoreSearchError::NonFiniteSample { sample })
830    }
831}
832
833fn checked_enclosure<E, F>(
834    left: ScoreSample,
835    right: ScoreSample,
836    enclose: &mut F,
837) -> Result<DerivativeEnclosure, ScoreSearchError<E>>
838where
839    F: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
840{
841    let lo = left.x;
842    let hi = right.x;
843    // The cell's endpoints are handed to the oracle as the SAMPLES the search
844    // already paid for, not as bare abscissae. An endpoint-anchored enclosure
845    // needs the endpoint jets and nothing else, so this is what makes it free:
846    // the oracle reads `left`/`right` instead of re-evaluating the criterion at
847    // two points it has already evaluated.
848    let enclosure = enclose(left, right)
849        .map_err(|source| ScoreSearchError::EnclosureEvaluation { lo, hi, source })?;
850    if !(enclosure.derivative.is_valid()
851        && enclosure.curvature.is_valid()
852        && enclosure.score.value.is_valid()
853        && enclosure.score.evaluation_error.is_finite()
854        && enclosure.score.evaluation_error >= 0.0)
855    {
856        return Err(ScoreSearchError::InvalidEnclosure { lo, hi, enclosure });
857    }
858    let score = enclosure.score;
859    let resolved_score = score.value.widen(score.evaluation_error);
860    for endpoint in [left, right] {
861        if !resolved_score.contains(endpoint.value) {
862            return Err(ScoreSearchError::ScoreValueEnclosureMissesEndpoint {
863                lo,
864                hi,
865                endpoint,
866                score,
867            });
868        }
869    }
870    Ok(enclosure)
871}
872
873/// Attach the oracle's exact score/derivative ranges at one represented point.
874///
875/// A nearest-rounded scalar jet is not required to lie inside an exact-real
876/// interval extension.  Instead, proof decisions use this degenerate-cell
877/// enclosure.  Both the point range and its parent-cell range contain the same
878/// exact endpoint derivative, so disjointness remains a valid contract check.
879fn certify_point<E, F>(
880    point: &mut SearchSample,
881    enclose: &mut F,
882) -> Result<DerivativeEnclosure, ScoreSearchError<E>>
883where
884    F: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
885{
886    let enclosure = match point.point_enclosure {
887        Some(enclosure) => enclosure,
888        None => {
889            let enclosure = checked_enclosure(point.sample, point.sample, enclose)?;
890            point.point_enclosure = Some(enclosure);
891            enclosure
892        }
893    };
894    Ok(enclosure)
895}
896
897fn certify_endpoint_derivative<E, F>(
898    point: &mut SearchSample,
899    cell_lo: f64,
900    cell_hi: f64,
901    cell: DerivativeEnclosure,
902    enclose: &mut F,
903) -> Result<ClosedInterval, ScoreSearchError<E>>
904where
905    F: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
906{
907    let endpoint_derivative = certify_point(point, enclose)?.derivative;
908    endpoint_derivative.intersection(cell.derivative).ok_or(
909        ScoreSearchError::DisjointEndpointEnclosure {
910            lo: cell_lo,
911            hi: cell_hi,
912            endpoint: point.sample,
913            endpoint_derivative,
914            enclosure: cell,
915        },
916    )
917}
918
919#[derive(Clone, Copy, PartialEq, Eq)]
920enum StrictSign {
921    Negative,
922    Positive,
923}
924
925#[inline]
926fn strict_sign(interval: ClosedInterval) -> Option<StrictSign> {
927    if interval.hi < 0.0 {
928        Some(StrictSign::Negative)
929    } else if interval.lo > 0.0 {
930        Some(StrictSign::Positive)
931    } else {
932        None
933    }
934}
935
936#[inline]
937fn is_exact_zero(interval: ClosedInterval) -> bool {
938    interval.lo == 0.0 && interval.hi == 0.0
939}
940
941fn certify_bracket_score<E, Eval, Enclose>(
942    bracket: ClosedInterval,
943    representative: SearchSample,
944    evaluate: &mut Eval,
945    enclose: &mut Enclose,
946) -> Result<ScoreValueEnclosure, ScoreSearchError<E>>
947where
948    Eval: FnMut(f64) -> Result<ScoreJet, E>,
949    Enclose: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
950{
951    if bracket.lo == bracket.hi {
952        let mut representative = representative;
953        return Ok(certify_point(&mut representative, enclose)?.score);
954    }
955    let left = if representative.sample.x == bracket.lo {
956        representative
957    } else {
958        evaluate_sample(bracket.lo, evaluate)?
959    };
960    let right = if representative.sample.x == bracket.hi {
961        representative
962    } else {
963        evaluate_sample(bracket.hi, evaluate)?
964    };
965    Ok(checked_enclosure(left.sample, right.sample, enclose)?.score)
966}
967
968enum UniqueRootRefinement {
969    Stationary(StationaryPoint),
970    ResolutionFlat {
971        region: ResolutionFlatRegion,
972        maximum: ScoreValueEnclosure,
973    },
974}
975
976/// Refine a UNIQUE derivative root.  The caller has already proved uniqueness
977/// by a curvature enclosure that excludes zero and supplied endpoint
978/// derivative enclosures of opposite sign.
979fn refine_unique_root<E, Eval, Enclose>(
980    mut left: SearchSample,
981    mut right: SearchSample,
982    resolution: f64,
983    enclosure: DerivativeEnclosure,
984    evaluate: &mut Eval,
985    enclose: &mut Enclose,
986) -> Result<UniqueRootRefinement, ScoreSearchError<E>>
987where
988    Eval: FnMut(f64) -> Result<ScoreJet, E>,
989    Enclose: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
990{
991    let bracket_lo = left.sample.x;
992    let bracket_hi = right.sample.x;
993    let mut left_derivative =
994        certify_endpoint_derivative(&mut left, bracket_lo, bracket_hi, enclosure, enclose)?;
995    let mut right_derivative =
996        certify_endpoint_derivative(&mut right, bracket_lo, bracket_hi, enclosure, enclose)?;
997    let curvature_sign =
998        strict_sign(enclosure.curvature).ok_or(ScoreSearchError::InvalidEnclosure {
999            lo: left.sample.x,
1000            hi: right.sample.x,
1001            enclosure,
1002        })?;
1003    let increasing = curvature_sign == StrictSign::Positive;
1004    let expected_left_sign = if increasing {
1005        StrictSign::Negative
1006    } else {
1007        StrictSign::Positive
1008    };
1009    let expected_right_sign = if increasing {
1010        StrictSign::Positive
1011    } else {
1012        StrictSign::Negative
1013    };
1014    if strict_sign(left_derivative) != Some(expected_left_sign)
1015        || strict_sign(right_derivative) != Some(expected_right_sign)
1016    {
1017        return Err(ScoreSearchError::InvalidEnclosure {
1018            lo: left.sample.x,
1019            hi: right.sample.x,
1020            enclosure,
1021        });
1022    }
1023
1024    let mut force_midpoint = false;
1025    while right.sample.x - left.sample.x > resolution {
1026        let width = right.sample.x - left.sample.x;
1027        let midpoint = left.sample.x + 0.5 * width;
1028        if !(midpoint > left.sample.x && midpoint < right.sample.x) {
1029            return Err(ScoreSearchError::Unresolved {
1030                lo: left.sample.x,
1031                hi: right.sample.x,
1032                requested_resolution: resolution,
1033                enclosure,
1034            });
1035        }
1036
1037        // Newton is accepted only in the central half of the bracket.  Thus
1038        // every accepted point, Newton or midpoint, contracts the maintained
1039        // sign bracket by at least one quarter.  The loop has no iteration cap
1040        // because its geometric termination follows from this safeguard.
1041        // Point derivatives are refinement proposals, not proof currency. In
1042        // particular, a nonzero derivative can round to scalar zero. Rank the
1043        // Newton anchors by their certified point ranges so that false scalar
1044        // zeros cannot control either the refinement path or its eventual
1045        // endpoint representative.
1046        let base = if left_derivative.max_abs() <= right_derivative.max_abs() {
1047            left.sample
1048        } else {
1049            right.sample
1050        };
1051        let newton = if base.curvature != 0.0 {
1052            base.x - base.derivative / base.curvature
1053        } else {
1054            f64::NAN
1055        };
1056        let guard = 0.25 * width;
1057        let x = if !force_midpoint
1058            && newton.is_finite()
1059            && newton >= left.sample.x + guard
1060            && newton <= right.sample.x - guard
1061        {
1062            newton
1063        } else {
1064            midpoint
1065        };
1066        force_midpoint = false;
1067        if !(x > left.sample.x && x < right.sample.x) {
1068            return Err(ScoreSearchError::Unresolved {
1069                lo: left.sample.x,
1070                hi: right.sample.x,
1071                requested_resolution: resolution,
1072                enclosure,
1073            });
1074        }
1075        let mut sample = evaluate_sample(x, evaluate)?;
1076        let probe_x = sample.sample.x;
1077        let mut point_derivative = certify_endpoint_derivative(
1078            &mut sample,
1079            left.sample.x,
1080            right.sample.x,
1081            enclosure,
1082            enclose,
1083        )?;
1084        let mut root_curvature = enclosure.curvature;
1085        if !is_exact_zero(point_derivative) && strict_sign(point_derivative).is_none() {
1086            // A degenerate-cell derivative enclosure can remain wide when its
1087            // analytic formula contains cancellation. The two adjacent cell
1088            // extensions are independent exact evidence about their shared
1089            // endpoint. Intersect all three rather than discarding the cell
1090            // information after merely checking overlap.
1091            let left_cell = checked_enclosure(left.sample, sample.sample, enclose)?;
1092            let right_cell = checked_enclosure(sample.sample, right.sample, enclose)?;
1093            let left_probe_derivative = certify_endpoint_derivative(
1094                &mut sample,
1095                left.sample.x,
1096                probe_x,
1097                left_cell,
1098                enclose,
1099            )?;
1100            let right_probe_derivative = certify_endpoint_derivative(
1101                &mut sample,
1102                probe_x,
1103                right.sample.x,
1104                right_cell,
1105                enclose,
1106            )?;
1107            point_derivative = left_probe_derivative
1108                .intersection(right_probe_derivative)
1109                .ok_or(ScoreSearchError::DisjointEndpointEnclosure {
1110                    lo: left.sample.x,
1111                    hi: right.sample.x,
1112                    endpoint: sample.sample,
1113                    endpoint_derivative: left_probe_derivative,
1114                    enclosure: right_cell,
1115                })?;
1116            let child_curvature = left_cell.curvature.hull(right_cell.curvature);
1117            root_curvature = enclosure.curvature.intersection(child_curvature).ok_or(
1118                ScoreSearchError::InvalidEnclosure {
1119                    lo: left.sample.x,
1120                    hi: right.sample.x,
1121                    enclosure: right_cell,
1122                },
1123            )?;
1124        }
1125        if is_exact_zero(point_derivative) {
1126            let bracket = ClosedInterval::point(x);
1127            let score = certify_bracket_score(bracket, sample, evaluate, enclose)?;
1128            return Ok(UniqueRootRefinement::Stationary(StationaryPoint {
1129                sample: sample.sample,
1130                bracket,
1131                score,
1132                curvature: root_curvature,
1133            }));
1134        }
1135        if let Some(sign) = strict_sign(point_derivative) {
1136            match (increasing, sign) {
1137                (true, StrictSign::Negative) | (false, StrictSign::Positive) => {
1138                    left = sample;
1139                    left_derivative = point_derivative;
1140                }
1141                (true, StrictSign::Positive) | (false, StrictSign::Negative) => {
1142                    right = sample;
1143                    right_derivative = point_derivative;
1144                }
1145            }
1146            continue;
1147        }
1148
1149        // The point derivative is itself unresolved at f64 precision. The
1150        // mean-value theorem gives THREE independent interval-Newton images of
1151        // the same unique root: one from the point and one from each signed
1152        // endpoint. Intersect all three. Using only the cancellation-heavy
1153        // point image can leave the whole bracket unchanged even when the
1154        // endpoint images contract it decisively.
1155        //
1156        //   root = x₀ - f'(x₀) / f''(ξ),  ξ between x₀ and root.
1157        let bracket = ClosedInterval::new(left.sample.x, right.sample.x);
1158        let point_newton =
1159            ClosedInterval::point(x).sub(point_derivative.div_nonzero(root_curvature));
1160        let left_newton = ClosedInterval::point(left.sample.x)
1161            .sub(left_derivative.div_nonzero(enclosure.curvature));
1162        let right_newton = ClosedInterval::point(right.sample.x)
1163            .sub(right_derivative.div_nonzero(enclosure.curvature));
1164        let root = bracket
1165            .intersection(point_newton)
1166            .and_then(|root| root.intersection(left_newton))
1167            .and_then(|root| root.intersection(right_newton))
1168            .ok_or(ScoreSearchError::InconsistentRootEnclosure {
1169                lo: left.sample.x,
1170                hi: right.sample.x,
1171                left_derivative,
1172                right_derivative,
1173                curvature: enclosure.curvature,
1174                left_newton,
1175                right_newton,
1176                point_newton,
1177            })?;
1178        if root.hi - root.lo <= resolution {
1179            let score = certify_bracket_score(root, sample, evaluate, enclose)?;
1180            return Ok(UniqueRootRefinement::Stationary(StationaryPoint {
1181                sample: sample.sample,
1182                bracket: root,
1183                score,
1184                curvature: root_curvature,
1185            }));
1186        }
1187        // If the Newton image cannot certify the requested location, strict
1188        // concavity can still certify the score (#2790): for f'' <= -mu < 0,
1189        // f(x*) - f(x) <= f'(x)^2 / (2 mu). Evaluate this bound with directed
1190        // intervals against the score evaluator's own forward error.
1191        //
1192        // This value-only stopping rule must follow the root-width check:
1193        // callers that require KKT stationarity need the stronger certificate
1194        // whenever the same interval-Newton image already establishes it.
1195        let point_score = certify_point(&mut sample, enclose)?.score;
1196        if let Some((region, maximum)) = score_resolved_concave_maximum(
1197            SearchNode { left, right },
1198            enclosure,
1199            sample.sample,
1200            point_derivative,
1201            root_curvature,
1202            point_score,
1203        ) {
1204            return Ok(UniqueRootRefinement::ResolutionFlat { region, maximum });
1205        }
1206        if root.lo > left.sample.x || root.hi < right.sample.x {
1207            let mut new_left = if root.lo == sample.sample.x {
1208                sample
1209            } else {
1210                evaluate_sample(root.lo, evaluate)?
1211            };
1212            let mut new_right = if root.hi == sample.sample.x {
1213                sample
1214            } else {
1215                evaluate_sample(root.hi, evaluate)?
1216            };
1217            let contracted_enclosure =
1218                checked_enclosure(new_left.sample, new_right.sample, enclose)?;
1219            // The point certificate and the strict curvature range give a
1220            // second exact score extension over the contracted root image:
1221            //
1222            //   f(y) = f(x) + f'(x)(y-x) + 1/2 f''(ξ)(y-x)^2.
1223            //
1224            // Intersecting it with the endpoint-based cell extension removes
1225            // common cancellation noise from the score range. This does not
1226            // alter the evaluator error or invent a tolerance; it can only
1227            // reveal that the existing exact score diameter has reached that
1228            // existing comparison floor.
1229            let point_score = certify_point(&mut sample, enclose)?.score;
1230            let displacement = ClosedInterval::new(root.lo - x, root.hi - x);
1231            let taylor_score = point_score
1232                .value
1233                .add(point_derivative.mul(displacement))
1234                .add(root_curvature.mul(displacement.square()).scale(0.5));
1235            let tightened_score = contracted_enclosure
1236                .score
1237                .value
1238                .intersection(taylor_score)
1239                .ok_or(ScoreSearchError::InvalidEnclosure {
1240                    lo: root.lo,
1241                    hi: root.hi,
1242                    enclosure: contracted_enclosure,
1243                })?;
1244            let contracted_enclosure = DerivativeEnclosure {
1245                score: ScoreValueEnclosure {
1246                    value: tightened_score,
1247                    evaluation_error: contracted_enclosure.score.evaluation_error,
1248                },
1249                ..contracted_enclosure
1250            };
1251            if let Some(region) = resolution_flat_region(
1252                SearchNode {
1253                    left: new_left,
1254                    right: new_right,
1255                },
1256                contracted_enclosure,
1257            ) {
1258                return Ok(UniqueRootRefinement::ResolutionFlat {
1259                    region,
1260                    maximum: contracted_enclosure.score,
1261                });
1262            }
1263            let new_left_derivative = if new_left.sample.x == sample.sample.x {
1264                point_derivative
1265            } else {
1266                certify_endpoint_derivative(
1267                    &mut new_left,
1268                    root.lo,
1269                    root.hi,
1270                    contracted_enclosure,
1271                    enclose,
1272                )?
1273            };
1274            let new_right_derivative = if new_right.sample.x == sample.sample.x {
1275                point_derivative
1276            } else {
1277                certify_endpoint_derivative(
1278                    &mut new_right,
1279                    root.lo,
1280                    root.hi,
1281                    contracted_enclosure,
1282                    enclose,
1283                )?
1284            };
1285
1286            // A Newton image encloses the root; it does NOT prove that either
1287            // image boundary has a strict derivative sign. Retain each old
1288            // signed endpoint until its replacement independently certifies
1289            // the same oriented sign. This is the invariant that proves the
1290            // root unique on every subsequent iteration.
1291            let mut preserved_sign_contraction = false;
1292            if root.lo > left.sample.x {
1293                match strict_sign(new_left_derivative) {
1294                    Some(sign) if sign == expected_left_sign => {
1295                        left = new_left;
1296                        left_derivative = new_left_derivative;
1297                        preserved_sign_contraction = true;
1298                    }
1299                    Some(_) => {
1300                        return Err(ScoreSearchError::InvalidEnclosure {
1301                            lo: root.lo,
1302                            hi: root.hi,
1303                            enclosure: contracted_enclosure,
1304                        });
1305                    }
1306                    None => {}
1307                }
1308            }
1309            if root.hi < right.sample.x {
1310                match strict_sign(new_right_derivative) {
1311                    Some(sign) if sign == expected_right_sign => {
1312                        right = new_right;
1313                        right_derivative = new_right_derivative;
1314                        preserved_sign_contraction = true;
1315                    }
1316                    Some(_) => {
1317                        return Err(ScoreSearchError::InvalidEnclosure {
1318                            lo: root.lo,
1319                            hi: root.hi,
1320                            enclosure: contracted_enclosure,
1321                        });
1322                    }
1323                    None => {}
1324                }
1325            }
1326            if preserved_sign_contraction {
1327                continue;
1328            }
1329        }
1330        if x != midpoint {
1331            force_midpoint = true;
1332            continue;
1333        }
1334        return Err(ScoreSearchError::Unresolved {
1335            lo: left.sample.x,
1336            hi: right.sample.x,
1337            requested_resolution: resolution,
1338            enclosure,
1339        });
1340    }
1341
1342    let midpoint = left.sample.x + 0.5 * (right.sample.x - left.sample.x);
1343    let sample = if midpoint > left.sample.x && midpoint < right.sample.x {
1344        evaluate_sample(midpoint, evaluate)?.sample
1345    } else if left_derivative.max_abs() <= right_derivative.max_abs() {
1346        left.sample
1347    } else {
1348        right.sample
1349    };
1350    let bracket = ClosedInterval::new(left.sample.x, right.sample.x);
1351    let representative = SearchSample {
1352        sample,
1353        point_enclosure: None,
1354    };
1355    let score = certify_bracket_score(bracket, representative, evaluate, enclose)?;
1356    Ok(UniqueRootRefinement::Stationary(StationaryPoint {
1357        sample,
1358        bracket,
1359        score,
1360        curvature: enclosure.curvature,
1361    }))
1362}
1363
1364/// When subdivision lands exactly on a stationary abscissa, a rigorous point
1365/// interval can contain zero without proving the derivative is exactly zero.
1366/// Probe symmetrically within one requested-resolution bracket and accept the
1367/// shared endpoint only if those two certified derivative ranges have opposite
1368/// signs and the probe-cell curvature proves uniqueness.
1369fn isolate_shared_endpoint_root<E, Eval, Enclose>(
1370    endpoint: SearchSample,
1371    domain_lo: f64,
1372    domain_hi: f64,
1373    resolution: f64,
1374    evaluate: &mut Eval,
1375    enclose: &mut Enclose,
1376) -> Result<Option<StationaryPoint>, ScoreSearchError<E>>
1377where
1378    Eval: FnMut(f64) -> Result<ScoreJet, E>,
1379    Enclose: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
1380{
1381    let radius = 0.5 * resolution;
1382    let left_x = endpoint.sample.x - radius;
1383    let mut right_x = endpoint.sample.x + radius;
1384    if !(left_x >= domain_lo
1385        && right_x <= domain_hi
1386        && left_x < endpoint.sample.x
1387        && right_x > endpoint.sample.x)
1388    {
1389        return Ok(None);
1390    }
1391    while right_x - left_x > resolution {
1392        right_x = next_down(right_x);
1393    }
1394    if !(right_x > endpoint.sample.x && right_x - left_x <= resolution) {
1395        return Ok(None);
1396    }
1397
1398    let mut left = evaluate_sample(left_x, evaluate)?;
1399    let mut right = evaluate_sample(right_x, evaluate)?;
1400    let probe_enclosure = checked_enclosure(left.sample, right.sample, enclose)?;
1401    if probe_enclosure.curvature.contains_zero() {
1402        return Ok(None);
1403    }
1404    let left_derivative =
1405        certify_endpoint_derivative(&mut left, left_x, right_x, probe_enclosure, enclose)?;
1406    let right_derivative =
1407        certify_endpoint_derivative(&mut right, left_x, right_x, probe_enclosure, enclose)?;
1408    if strict_sign(left_derivative)
1409        .zip(strict_sign(right_derivative))
1410        .is_some_and(|(left_sign, right_sign)| left_sign != right_sign)
1411    {
1412        Ok(Some(StationaryPoint {
1413            sample: endpoint.sample,
1414            bracket: ClosedInterval::new(left_x, right_x),
1415            score: probe_enclosure.score,
1416            curvature: probe_enclosure.curvature,
1417        }))
1418    } else {
1419        Ok(None)
1420    }
1421}
1422
1423/// Prove that every score value in a cell is indistinguishable from one of its
1424/// endpoint samples at the point evaluator's certified f64 resolution.
1425///
1426/// If the exact score range is `[L, U]`, every pair of exact scores in the cell
1427/// differs by at most `U-L`. If each nearest-rounded point value has absolute
1428/// forward error at most `rho`, a comparison of two such values has uncertainty
1429/// at most `2 rho`. The cell is resolution-flat only when `U-L <= 2 rho`.
1430///
1431/// Both sides are expressed in score-value units and are invariant under
1432/// adding a constant to the objective. Derivative-evaluator error is
1433/// deliberately absent: integrating it would bound the error of a hypothetical
1434/// numerical quadrature, not the forward error of `ScoreJet::value`.
1435fn resolution_flat_region(
1436    node: SearchNode,
1437    enclosure: DerivativeEnclosure,
1438) -> Option<ResolutionFlatRegion> {
1439    let score = enclosure.score;
1440    let max_score_gap = if score.value.lo == score.value.hi {
1441        0.0
1442    } else {
1443        next_up(score.value.hi - score.value.lo)
1444    };
1445    let score_resolution = if score.evaluation_error == 0.0 {
1446        0.0
1447    } else {
1448        next_up(2.0 * score.evaluation_error)
1449    };
1450    if !(max_score_gap.is_finite() && score_resolution.is_finite()) {
1451        return None;
1452    }
1453    let sample = if node.right.sample.value > node.left.sample.value {
1454        node.right.sample
1455    } else {
1456        node.left.sample
1457    };
1458    (max_score_gap <= score_resolution).then_some(ResolutionFlatRegion {
1459        sample,
1460        bracket: ClosedInterval::new(node.left.sample.x, node.right.sample.x),
1461        score: score.value,
1462        max_score_gap,
1463        score_resolution,
1464    })
1465}
1466
1467/// Turn strict concavity plus an unresolved point derivative into a direct
1468/// score-optimality certificate.
1469///
1470/// `curvature.hi < 0` proves a unique maximum in the signed root bracket. The
1471/// strong-concavity inequality bounds how much that maximum can improve on the
1472/// represented point without requiring its location to be distinguishable.
1473/// Unlike [`resolution_flat_region`], this does not require every pair of scores
1474/// in the cell to be close; only the maximum and the returned representative
1475/// need to be numerically indistinguishable.
1476fn score_resolved_concave_maximum(
1477    node: SearchNode,
1478    enclosure: DerivativeEnclosure,
1479    sample: ScoreSample,
1480    point_derivative: ClosedInterval,
1481    curvature: ClosedInterval,
1482    point_score: ScoreValueEnclosure,
1483) -> Option<(ResolutionFlatRegion, ScoreValueEnclosure)> {
1484    if !(curvature.hi < 0.0 && sample.x >= node.left.sample.x && sample.x <= node.right.sample.x) {
1485        return None;
1486    }
1487
1488    // max |g|^2 / (2 mu), where mu = -max f''. Interval multiplication and
1489    // division are outward-rounded, including the factor 1/2.
1490    let maximum_excess = point_derivative
1491        .square()
1492        .scale(0.5)
1493        .div_positive(curvature.neg())
1494        .hi;
1495    let comparison_resolution = point_score.evaluation_error;
1496    if !(maximum_excess.is_finite()
1497        && maximum_excess >= 0.0
1498        && comparison_resolution.is_finite()
1499        && maximum_excess <= comparison_resolution)
1500    {
1501        return None;
1502    }
1503
1504    // Intersect the cell-wide score upper bound with the tighter
1505    // strong-concavity upper bound anchored at the represented point. The
1506    // maximum is at least the point score itself.
1507    let maximum = ClosedInterval::new(
1508        point_score.value.lo,
1509        enclosure
1510            .score
1511            .value
1512            .hi
1513            .min(sum_up(point_score.value.hi, maximum_excess)),
1514    );
1515    if !maximum.is_valid() {
1516        return None;
1517    }
1518    let region = ResolutionFlatRegion {
1519        sample,
1520        bracket: ClosedInterval::new(node.left.sample.x, node.right.sample.x),
1521        score: enclosure.score.value,
1522        max_score_gap: maximum_excess,
1523        score_resolution: comparison_resolution,
1524    };
1525    Some((
1526        region,
1527        ScoreValueEnclosure {
1528            value: maximum,
1529            evaluation_error: point_score
1530                .evaluation_error
1531                .max(enclosure.score.evaluation_error),
1532        },
1533    ))
1534}
1535
1536/// Select a domain boundary only when one proof cell covers the whole domain
1537/// and its derivative has one strict sign throughout.
1538///
1539/// Rounded endpoint values may tie even when their exact-real ordering is
1540/// strict. A whole-domain monotonicity certificate resolves that ordering
1541/// directly. A proper subcell cannot select the global representative because
1542/// its endpoint has not been compared with maxima in the other cells.
1543fn certified_domain_boundary(
1544    node: &SearchNode,
1545    derivative_sign: StrictSign,
1546    domain_lo: f64,
1547    domain_hi: f64,
1548) -> Option<(ScoreSample, ScoreOptimumLocation)> {
1549    if node.left.sample.x != domain_lo || node.right.sample.x != domain_hi {
1550        return None;
1551    }
1552    Some(match derivative_sign {
1553        StrictSign::Positive => (node.right.sample, ScoreOptimumLocation::UpperBoundary),
1554        StrictSign::Negative => (node.left.sample, ScoreOptimumLocation::LowerBoundary),
1555    })
1556}
1557
1558/// Globally maximize a smooth score on `[lo, hi]` by certified stationary
1559/// isolation.
1560///
1561/// `evaluate` returns a nearest-rounded score jet at a point. `enclose(a, b)`
1562/// receives the cell's two ENDPOINT SAMPLES — the jets the search already
1563/// obtained from `evaluate` — and must return OUTER ranges containing the exact
1564/// first and second derivative at every point of `[a.x, b.x]`.
1565///
1566/// Handing the samples in (rather than the bare abscissae) is what keeps an
1567/// endpoint-anchored enclosure free: such an oracle is a Taylor pad around the
1568/// endpoint jets, so with the jets in hand it performs no criterion evaluation
1569/// of its own. An oracle whose enclosure is a genuine interval extension may
1570/// ignore the jets and use `a.x`/`b.x`.
1571///
1572/// The scalar derivatives are never treated as proofs: when an endpoint sign
1573/// matters, the search asks `enclose(a, a)` for its exact derivative range.
1574/// The point and parent-cell ranges must overlap, but the exact-real parent
1575/// range is intentionally not required to contain a separately rounded scalar
1576/// estimate.
1577///
1578/// A successful return means every cell was derivative-excluded, stationary-
1579/// isolated to `resolution`, proved score-flat at the local representable value
1580/// resolution, or proved exactly dominated by an already attained point score.
1581/// Any cell that satisfies none of those conditions produces
1582/// [`ScoreSearchError::Unresolved`].
1583///
1584/// The traversal is bounded by [`subdivision_budget`]. The per-cell resolution
1585/// floor bounds the DEPTH of the subdivision and never its BREADTH, and those
1586/// are different failures. A criterion that certifies NOTHING bottoms out on the
1587/// floor after `D` subdivisions and is already typed
1588/// [`ScoreSearchError::Unresolved`]. The unbounded case is the one where cells
1589/// DO certify, at widths far above the floor, and there are simply too many of
1590/// them: a criterion whose derivative and curvature enclosures both straddle
1591/// zero over a wide region excludes no cell by a sign and isolates no root, so
1592/// every cell it reaches is split until its score range collapses under the
1593/// evaluator's own error — and the leaf count of that tree is exponential in the
1594/// depth, 2^32 cells on a 58-wide log-λ domain at `sqrt(eps)` resolution, which
1595/// is non-termination rather than slowness (#2546). Exceeding the budget is
1596/// [`ScoreSearchError::SubdivisionBudget`], a statement about the CRITERION and
1597/// not about the machine: the search was asked to certify more cells than a
1598/// converging 1-D decomposition at this resolution consists of.
1599pub fn maximize_score_1d<E, Eval, Enclose>(
1600    lo: f64,
1601    hi: f64,
1602    resolution: f64,
1603    mut evaluate: Eval,
1604    mut enclose: Enclose,
1605) -> Result<ScoreSearchResult, ScoreSearchError<E>>
1606where
1607    Eval: FnMut(f64) -> Result<ScoreJet, E>,
1608    Enclose: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
1609{
1610    if !(lo.is_finite() && hi.is_finite() && lo <= hi && (hi - lo).is_finite()) {
1611        return Err(ScoreSearchError::InvalidDomain { lo, hi });
1612    }
1613    if !(resolution.is_finite() && resolution > 0.0) {
1614        return Err(ScoreSearchError::InvalidResolution { resolution });
1615    }
1616
1617    let mut lower_boundary = evaluate_sample(lo, &mut evaluate)?;
1618    if lo == hi {
1619        let score =
1620            checked_enclosure(lower_boundary.sample, lower_boundary.sample, &mut enclose)?.score;
1621        return Ok(ScoreSearchResult {
1622            optimum: lower_boundary.sample,
1623            location: ScoreOptimumLocation::LowerBoundary,
1624            lower_boundary: lower_boundary.sample,
1625            upper_boundary: lower_boundary.sample,
1626            stationary_points: Vec::new(),
1627            resolution_flat_regions: Vec::new(),
1628            dominated_regions: Vec::new(),
1629            value_certificate: GlobalScoreCertificate {
1630                selected: score.value,
1631                maximum: score.value,
1632                maximum_excess: 0.0,
1633                comparison_resolution: 0.0,
1634            },
1635        });
1636    }
1637    let mut upper_boundary = evaluate_sample(hi, &mut evaluate)?;
1638    let lower_boundary_score = certify_point(&mut lower_boundary, &mut enclose)?.score;
1639    let upper_boundary_score = certify_point(&mut upper_boundary, &mut enclose)?.score;
1640    let mut incumbent_lower = lower_boundary_score
1641        .value
1642        .lo
1643        .max(upper_boundary_score.value.lo);
1644    let (mut optimum, mut location) = if upper_boundary.sample.value > lower_boundary.sample.value {
1645        (upper_boundary.sample, ScoreOptimumLocation::UpperBoundary)
1646    } else {
1647        (lower_boundary.sample, ScoreOptimumLocation::LowerBoundary)
1648    };
1649
1650    let (budget, depth_bound) = subdivision_budget(lo, hi, resolution);
1651    let mut subdivisions = 0usize;
1652    let mut stationary_points = Vec::<StationaryPoint>::new();
1653    let mut resolution_flat_regions = Vec::<ResolutionFlatRegion>::new();
1654    let mut dominated_regions = Vec::<DominatedRegion>::new();
1655    // Boundary points are unconditional feasible incumbents. Keeping both in
1656    // the terminal ledger makes every later dominance decision independent of
1657    // which rounded boundary value happened to initialize `optimum`.
1658    let mut terminal_maxima = vec![
1659        TerminalScoreCandidate::point(lower_boundary.sample.x, lower_boundary_score),
1660        TerminalScoreCandidate::point(upper_boundary.sample.x, upper_boundary_score),
1661    ];
1662    let mut stack = vec![SearchNode {
1663        left: lower_boundary,
1664        right: upper_boundary,
1665    }];
1666    while let Some(mut node) = stack.pop() {
1667        let mathematical_enclosure =
1668            checked_enclosure(node.left.sample, node.right.sample, &mut enclose)?;
1669        let enclosure = mathematical_enclosure;
1670        if enclosure.score.value.hi < incumbent_lower {
1671            dominated_regions.push(DominatedRegion {
1672                bracket: ClosedInterval::new(node.left.sample.x, node.right.sample.x),
1673                score: enclosure.score,
1674                incumbent_lower,
1675            });
1676            continue;
1677        }
1678        if !enclosure.derivative.contains_zero() {
1679            let derivative_sign = if enclosure.derivative.lo > 0.0 {
1680                StrictSign::Positive
1681            } else {
1682                StrictSign::Negative
1683            };
1684            if let Some((proven_optimum, proven_location)) =
1685                certified_domain_boundary(&node, derivative_sign, lo, hi)
1686            {
1687                optimum = proven_optimum;
1688                location = proven_location;
1689            }
1690            let endpoint = match derivative_sign {
1691                StrictSign::Positive => &mut node.right,
1692                StrictSign::Negative => &mut node.left,
1693            };
1694            let endpoint_score = certify_point(endpoint, &mut enclose)?.score;
1695            incumbent_lower = incumbent_lower.max(endpoint_score.value.lo);
1696            terminal_maxima.push(TerminalScoreCandidate::point(
1697                endpoint.sample.x,
1698                endpoint_score,
1699            ));
1700            continue;
1701        }
1702
1703        let monotone = !enclosure.curvature.contains_zero();
1704        if monotone {
1705            let node_lo = node.left.sample.x;
1706            let node_hi = node.right.sample.x;
1707            let left_derivative = certify_endpoint_derivative(
1708                &mut node.left,
1709                node_lo,
1710                node_hi,
1711                enclosure,
1712                &mut enclose,
1713            )?;
1714            let right_derivative = certify_endpoint_derivative(
1715                &mut node.right,
1716                node_lo,
1717                node_hi,
1718                enclosure,
1719                &mut enclose,
1720            )?;
1721            let left_sign = strict_sign(left_derivative);
1722            let right_sign = strict_sign(right_derivative);
1723            let mut root_flat = None;
1724            let stationary = if is_exact_zero(left_derivative) {
1725                let score = certify_point(&mut node.left, &mut enclose)?.score;
1726                Some(StationaryPoint {
1727                    sample: node.left.sample,
1728                    bracket: ClosedInterval::point(node.left.sample.x),
1729                    score,
1730                    curvature: enclosure.curvature,
1731                })
1732            } else if is_exact_zero(right_derivative) {
1733                let score = certify_point(&mut node.right, &mut enclose)?.score;
1734                Some(StationaryPoint {
1735                    sample: node.right.sample,
1736                    bracket: ClosedInterval::point(node.right.sample.x),
1737                    score,
1738                    curvature: enclosure.curvature,
1739                })
1740            } else if left_sign
1741                .zip(right_sign)
1742                .is_some_and(|(left_sign, right_sign)| left_sign != right_sign)
1743            {
1744                match refine_unique_root(
1745                    node.left,
1746                    node.right,
1747                    resolution,
1748                    enclosure,
1749                    &mut evaluate,
1750                    &mut enclose,
1751                )? {
1752                    UniqueRootRefinement::Stationary(stationary) => Some(stationary),
1753                    UniqueRootRefinement::ResolutionFlat { region, maximum } => {
1754                        root_flat = Some((region, maximum));
1755                        None
1756                    }
1757                }
1758            } else if left_sign.is_none() {
1759                isolate_shared_endpoint_root(
1760                    node.left,
1761                    lo,
1762                    hi,
1763                    resolution,
1764                    &mut evaluate,
1765                    &mut enclose,
1766                )?
1767            } else if right_sign.is_none() {
1768                isolate_shared_endpoint_root(
1769                    node.right,
1770                    lo,
1771                    hi,
1772                    resolution,
1773                    &mut evaluate,
1774                    &mut enclose,
1775                )?
1776            } else {
1777                None
1778            };
1779
1780            if let Some((flat, maximum)) = root_flat {
1781                let index = resolution_flat_regions.len();
1782                if flat.sample.value > optimum.value {
1783                    optimum = flat.sample;
1784                    location = ScoreOptimumLocation::ResolutionFlat(index);
1785                }
1786                let mut representative = SearchSample {
1787                    sample: flat.sample,
1788                    point_enclosure: None,
1789                };
1790                let representative_score = certify_point(&mut representative, &mut enclose)?.score;
1791                incumbent_lower = incumbent_lower.max(representative_score.value.lo);
1792                terminal_maxima.push(TerminalScoreCandidate::region(
1793                    maximum,
1794                    representative_score
1795                        .evaluation_error
1796                        .max(maximum.evaluation_error),
1797                ));
1798                resolution_flat_regions.push(flat);
1799                continue;
1800            }
1801
1802            if let Some(stationary) = stationary {
1803                let mut representative = SearchSample {
1804                    sample: stationary.sample,
1805                    point_enclosure: None,
1806                };
1807                let representative_score = certify_point(&mut representative, &mut enclose)?.score;
1808                incumbent_lower = incumbent_lower.max(representative_score.value.lo);
1809                // Two adjacent certified cells can report the same exact root
1810                // when it lies on their common boundary.  Preserve one copy.
1811                let duplicate = stationary_points
1812                    .last()
1813                    .is_some_and(|previous| previous.sample.x == stationary.sample.x);
1814                if !duplicate {
1815                    let index = stationary_points.len();
1816                    if stationary.sample.value > optimum.value {
1817                        optimum = stationary.sample;
1818                        location = ScoreOptimumLocation::Stationary(index);
1819                    }
1820                    stationary_points.push(stationary);
1821                }
1822                if enclosure.curvature.hi < 0.0 {
1823                    let score = stationary.score;
1824                    terminal_maxima.push(if stationary.bracket.lo == stationary.bracket.hi {
1825                        TerminalScoreCandidate::point(stationary.sample.x, score)
1826                    } else {
1827                        TerminalScoreCandidate::region(
1828                            score,
1829                            representative_score
1830                                .evaluation_error
1831                                .max(score.evaluation_error),
1832                        )
1833                    });
1834                } else {
1835                    let left_score = certify_point(&mut node.left, &mut enclose)?.score;
1836                    let right_score = certify_point(&mut node.right, &mut enclose)?.score;
1837                    incumbent_lower = incumbent_lower
1838                        .max(left_score.value.lo)
1839                        .max(right_score.value.lo);
1840                    terminal_maxima.push(TerminalScoreCandidate::point(
1841                        node.left.sample.x,
1842                        left_score,
1843                    ));
1844                    terminal_maxima.push(TerminalScoreCandidate::point(
1845                        node.right.sample.x,
1846                        right_score,
1847                    ));
1848                }
1849                continue;
1850            }
1851
1852            // Definite equal endpoint signs plus strict monotonicity exclude a
1853            // root.  An endpoint range that straddles zero is not silently
1854            // replaced by the rounded point sign; it proceeds to the value-flat
1855            // proof or subdivision below.
1856            if let Some((left_sign, right_sign)) = left_sign.zip(right_sign)
1857                && left_sign == right_sign
1858            {
1859                if let Some((proven_optimum, proven_location)) =
1860                    certified_domain_boundary(&node, left_sign, lo, hi)
1861                {
1862                    optimum = proven_optimum;
1863                    location = proven_location;
1864                }
1865                let endpoint = match left_sign {
1866                    StrictSign::Positive => &mut node.right,
1867                    StrictSign::Negative => &mut node.left,
1868                };
1869                let endpoint_score = certify_point(endpoint, &mut enclose)?.score;
1870                incumbent_lower = incumbent_lower.max(endpoint_score.value.lo);
1871                terminal_maxima.push(TerminalScoreCandidate::point(
1872                    endpoint.sample.x,
1873                    endpoint_score,
1874                ));
1875                continue;
1876            }
1877        }
1878
1879        if let Some(flat) = resolution_flat_region(node, mathematical_enclosure) {
1880            let index = resolution_flat_regions.len();
1881            if flat.sample.value > optimum.value {
1882                optimum = flat.sample;
1883                location = ScoreOptimumLocation::ResolutionFlat(index);
1884            }
1885            let mut representative = SearchSample {
1886                sample: flat.sample,
1887                point_enclosure: None,
1888            };
1889            let representative_score = certify_point(&mut representative, &mut enclose)?.score;
1890            incumbent_lower = incumbent_lower.max(representative_score.value.lo);
1891            terminal_maxima.push(TerminalScoreCandidate::region(
1892                enclosure.score,
1893                representative_score
1894                    .evaluation_error
1895                    .max(enclosure.score.evaluation_error),
1896            ));
1897            resolution_flat_regions.push(flat);
1898            continue;
1899        }
1900
1901        let width = node.right.sample.x - node.left.sample.x;
1902        let midpoint = node.left.sample.x + 0.5 * width;
1903        if width <= resolution || !(midpoint > node.left.sample.x && midpoint < node.right.sample.x)
1904        {
1905            return Err(ScoreSearchError::Unresolved {
1906                lo: node.left.sample.x,
1907                hi: node.right.sample.x,
1908                requested_resolution: resolution,
1909                enclosure,
1910            });
1911        }
1912        subdivisions += 1;
1913        if subdivisions > budget {
1914            return Err(ScoreSearchError::SubdivisionBudget {
1915                lo,
1916                hi,
1917                cell_lo: node.left.sample.x,
1918                cell_hi: node.right.sample.x,
1919                requested_resolution: resolution,
1920                subdivisions,
1921                budget,
1922                depth_bound,
1923                enclosure,
1924            });
1925        }
1926        let middle = evaluate_sample(midpoint, &mut evaluate)?;
1927        // Right first, then left: the LIFO traversal emits stationary points
1928        // in ascending x, which makes exact-boundary de-duplication stable.
1929        stack.push(SearchNode {
1930            left: middle,
1931            right: node.right,
1932        });
1933        stack.push(SearchNode {
1934            left: node.left,
1935            right: middle,
1936        });
1937    }
1938
1939    let mut selected_sample = SearchSample {
1940        sample: optimum,
1941        point_enclosure: None,
1942    };
1943    let selected_score = certify_point(&mut selected_sample, &mut enclose)?.score;
1944    let global_lower = terminal_maxima
1945        .iter()
1946        .map(|candidate| candidate.score.value.lo)
1947        .fold(selected_score.value.lo, f64::max);
1948    let global_upper = terminal_maxima
1949        .iter()
1950        .map(|candidate| candidate.score.value.hi)
1951        .fold(selected_score.value.hi, f64::max);
1952    let candidate_evaluation_error = terminal_maxima
1953        .iter()
1954        .filter(|candidate| candidate.point_x != Some(optimum.x))
1955        .map(|candidate| candidate.comparison_error)
1956        .fold(0.0_f64, f64::max);
1957    let maximum_excess = terminal_maxima
1958        .iter()
1959        .filter(|candidate| candidate.point_x != Some(optimum.x))
1960        .map(|candidate| {
1961            if candidate.score.value.hi <= selected_score.value.lo {
1962                0.0
1963            } else {
1964                next_up(candidate.score.value.hi - selected_score.value.lo)
1965            }
1966        })
1967        .fold(0.0_f64, f64::max);
1968    let comparison_resolution =
1969        add_nonnegative_upward(selected_score.evaluation_error, candidate_evaluation_error);
1970
1971    Ok(ScoreSearchResult {
1972        optimum,
1973        location,
1974        lower_boundary: lower_boundary.sample,
1975        upper_boundary: upper_boundary.sample,
1976        stationary_points,
1977        resolution_flat_regions,
1978        dominated_regions,
1979        value_certificate: GlobalScoreCertificate {
1980            selected: selected_score.value,
1981            maximum: ClosedInterval::new(global_lower, global_upper),
1982            maximum_excess,
1983            comparison_resolution,
1984        },
1985    })
1986}
1987
1988/// Repeat a certified global score search until its exact winning value is
1989/// orderable at the evaluator's certified comparison resolution.
1990///
1991/// Location resolution and value resolution are different proof currencies:
1992/// isolating every stationary point to `initial_resolution` can still leave
1993/// the winning candidate's exact score range wider than the point evaluator's
1994/// forward-error comparison permits. Each pass here independently rebuilds
1995/// the complete global certificate at a smaller location target. The observed
1996/// ratio between maximum excess and comparison resolution is only a refinement
1997/// strategy; it is never used as acceptance evidence.
1998///
1999/// There is no retry cap or acceptance fallback. Each retry contracts the
2000/// target by at least one binary subdivision. If the next target is no longer
2001/// representable, or the oracle cannot resolve stationary structure at that
2002/// finer target, or the finer traversal exceeds its [`subdivision_budget`], the
2003/// last complete certificate is returned unchanged so the caller can issue its
2004/// domain-specific typed refusal.
2005pub fn maximize_score_1d_value_ordered<E, Eval, Enclose>(
2006    lo: f64,
2007    hi: f64,
2008    initial_resolution: f64,
2009    mut evaluate: Eval,
2010    mut enclose: Enclose,
2011) -> Result<ScoreSearchResult, ScoreSearchError<E>>
2012where
2013    Eval: FnMut(f64) -> Result<ScoreJet, E>,
2014    Enclose: FnMut(ScoreSample, ScoreSample) -> Result<DerivativeEnclosure, E>,
2015{
2016    let mut resolution = initial_resolution;
2017    let mut search = maximize_score_1d(lo, hi, resolution, &mut evaluate, &mut enclose)?;
2018    loop {
2019        let certificate = search.value_certificate;
2020        if certificate.maximum_excess <= certificate.comparison_resolution {
2021            return Ok(search);
2022        }
2023        let binary_refinement = 0.5 * resolution;
2024        let value_directed_refinement = if certificate.comparison_resolution > 0.0 {
2025            resolution * (certificate.comparison_resolution / certificate.maximum_excess)
2026        } else {
2027            binary_refinement
2028        };
2029        let next_resolution = binary_refinement.min(value_directed_refinement);
2030        if !(next_resolution.is_finite() && next_resolution > 0.0 && next_resolution < resolution) {
2031            return Ok(search);
2032        }
2033        match maximize_score_1d(lo, hi, next_resolution, &mut evaluate, &mut enclose) {
2034            Ok(refined) => {
2035                search = refined;
2036                resolution = next_resolution;
2037            }
2038            // A finer requested location is optional proof strengthening.
2039            // Preserve the last complete global certificate when the oracle
2040            // cannot resolve stationary structure at that finer currency; the
2041            // caller will still reject it if its values remain unordered.
2042            //
2043            // A retry that exhausts its subdivision budget is the same kind of
2044            // outcome and ENDS the loop rather than contracting again: each
2045            // retry's budget grows as its target shrinks, so continuing past
2046            // one exhaustion would pay a whole traversal per halving down to
2047            // the denormal floor — a second unbounded axis (#2546).
2048            Err(
2049                ScoreSearchError::Unresolved { .. } | ScoreSearchError::SubdivisionBudget { .. },
2050            ) => return Ok(search),
2051            Err(error) => return Err(error),
2052        }
2053    }
2054}
2055
2056/// Static validation or evaluation failure for [`AffineRemlProfile`].
2057#[derive(Clone, Copy, Debug, PartialEq)]
2058pub enum AffineRemlError {
2059    EmptyModes,
2060    EmptyResponses,
2061    ShapeMismatch {
2062        gram_modes: usize,
2063        penalty_modes: usize,
2064        projected_rhs_squared: usize,
2065        responses: usize,
2066    },
2067    InvalidMode {
2068        index: usize,
2069        gram: f64,
2070        penalty: f64,
2071    },
2072    InvalidProjectedSquare {
2073        index: usize,
2074        value: f64,
2075    },
2076    InvalidResponseEnergy {
2077        output: usize,
2078        value: f64,
2079    },
2080    ZeroLambdaResidualUnavailable {
2081        output: usize,
2082    },
2083    InvalidResidualDof {
2084        value: f64,
2085    },
2086    InvalidLogdetConstant {
2087        value: f64,
2088    },
2089    RankMismatch {
2090        supplied: usize,
2091        inferred: usize,
2092    },
2093    InvalidLogLambda {
2094        value: f64,
2095    },
2096    InvalidLogLambdaInterval {
2097        lo: f64,
2098        hi: f64,
2099    },
2100    ElementaryEnclosureUnavailable {
2101        function: &'static str,
2102        lo: f64,
2103        hi: f64,
2104    },
2105    NonPositiveMode {
2106        index: usize,
2107        log_lambda: f64,
2108        value: f64,
2109    },
2110    NonPositiveResidual {
2111        output: usize,
2112        log_lambda: f64,
2113        value: f64,
2114    },
2115    NonPositiveResidualInterval {
2116        output: usize,
2117        lo: f64,
2118        hi: f64,
2119        lower_bound: f64,
2120    },
2121    InconsistentResidualEnclosures {
2122        output: usize,
2123        lo: f64,
2124        hi: f64,
2125        direct: ClosedInterval,
2126        complement: ClosedInterval,
2127    },
2128    UnboundedScoreEvaluationError {
2129        lo: f64,
2130        hi: f64,
2131        error: f64,
2132    },
2133}
2134
2135impl fmt::Display for AffineRemlError {
2136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2137        match self {
2138            Self::EmptyModes => write!(f, "affine REML profile has no modes"),
2139            Self::EmptyResponses => write!(f, "affine REML profile has no responses"),
2140            Self::ShapeMismatch {
2141                gram_modes,
2142                penalty_modes,
2143                projected_rhs_squared,
2144                responses,
2145            } => write!(
2146                f,
2147                "affine REML profile shape mismatch: gram {gram_modes}, penalty {penalty_modes}, projected squares {projected_rhs_squared}, responses {responses}"
2148            ),
2149            Self::InvalidMode {
2150                index,
2151                gram,
2152                penalty,
2153            } => write!(
2154                f,
2155                "affine REML mode {index} must have finite nonnegative (g,s), not both zero; got ({gram}, {penalty})"
2156            ),
2157            Self::InvalidProjectedSquare { index, value } => write!(
2158                f,
2159                "affine REML projected square {index} must be finite and nonnegative, got {value}"
2160            ),
2161            Self::InvalidResponseEnergy { output, value } => write!(
2162                f,
2163                "affine REML response energy {output} must be finite and nonnegative, got {value}"
2164            ),
2165            Self::ZeroLambdaResidualUnavailable { output } => write!(
2166                f,
2167                "affine REML could not certify the zero-smoothing residual for response {output}"
2168            ),
2169            Self::InvalidResidualDof { value } => {
2170                write!(
2171                    f,
2172                    "affine REML residual dof must be finite and positive, got {value}"
2173                )
2174            }
2175            Self::InvalidLogdetConstant { value } => write!(
2176                f,
2177                "affine REML log-determinant constant must be finite, got {value}"
2178            ),
2179            Self::RankMismatch { supplied, inferred } => write!(
2180                f,
2181                "affine REML determinant rank {supplied} disagrees with {inferred} positive penalty modes"
2182            ),
2183            Self::InvalidLogLambda { value } => {
2184                write!(f, "affine REML invalid log lambda {value}")
2185            }
2186            Self::InvalidLogLambdaInterval { lo, hi } => {
2187                write!(f, "affine REML invalid log-lambda interval [{lo}, {hi}]")
2188            }
2189            Self::ElementaryEnclosureUnavailable { function, lo, hi } => write!(
2190                f,
2191                "affine REML has no finite source-derived {function} enclosure on [{lo}, {hi}]"
2192            ),
2193            Self::NonPositiveMode {
2194                index,
2195                log_lambda,
2196                value,
2197            } => write!(
2198                f,
2199                "affine REML mode {index} is nonpositive at log lambda {log_lambda}: {value}"
2200            ),
2201            Self::NonPositiveResidual {
2202                output,
2203                log_lambda,
2204                value,
2205            } => write!(
2206                f,
2207                "affine REML residual {output} is nonpositive at log lambda {log_lambda}: {value}"
2208            ),
2209            Self::NonPositiveResidualInterval {
2210                output,
2211                lo,
2212                hi,
2213                lower_bound,
2214            } => write!(
2215                f,
2216                "affine REML residual {output} is not certified positive on [{lo}, {hi}] (lower bound {lower_bound})"
2217            ),
2218            Self::InconsistentResidualEnclosures {
2219                output,
2220                lo,
2221                hi,
2222                direct,
2223                complement,
2224            } => write!(
2225                f,
2226                "affine REML residual {output} has disjoint direct {direct:?} and zero-smoothing-complement {complement:?} enclosures on [{lo}, {hi}]"
2227            ),
2228            Self::UnboundedScoreEvaluationError { lo, hi, error } => write!(
2229                f,
2230                "affine REML score evaluator has no finite forward-error bound on [{lo}, {hi}] (bound {error})"
2231            ),
2232        }
2233    }
2234}
2235
2236impl std::error::Error for AffineRemlError {}
2237
2238/// Spectral REML/profile score with affine diagonal modes
2239/// `h_i(lambda) = g_i + lambda s_i`.
2240///
2241/// `projected_rhs_squared` is RESPONSE-MAJOR: entry `(d, i)` is stored at
2242/// `d * n_modes + i`.  The score is
2243///
2244/// `-1/2 { D [logdet_constant + sum log h_i - rank log(lambda)]
2245///          + residual_dof * sum_d log(R_d / residual_dof) }`,
2246///
2247/// where `R_d = response_energy[d] - sum_i q[d,i] / h_i`.
2248#[derive(Clone, Debug)]
2249pub struct AffineRemlProfile<'a> {
2250    gram_modes: &'a [f64],
2251    penalty_modes: &'a [f64],
2252    projected_rhs_squared: &'a [f64],
2253    response_energy: &'a [f64],
2254    /// Exact-real residuals on the finite part of the zero-smoothing face,
2255    ///
2256    /// `response_energy[d] - sum_{i:g_i>0} q[d,i] / g_i`.
2257    ///
2258    /// These invariants are computed once with an error-free leading sum and
2259    /// FMA-certified division corrections. Re-forming them independently in
2260    /// every interval evaluation loses the small Schur complement to the
2261    /// rounding scale of its O(energy) operands.
2262    zero_lambda_residual: Vec<ClosedInterval>,
2263    residual_dof: f64,
2264    logdet_constant: f64,
2265}
2266
2267/// O(n) exact-leading accumulator.
2268///
2269/// `leading + correction` encloses the exact sum of every value submitted so
2270/// far. `leading` follows the ordinary binary64 accumulation path. Knuth's
2271/// TwoSum identity moves each discarded low part into `correction`, whose
2272/// directed interval accumulation never again mixes it with an O(energy)
2273/// operand. This is the fixed-size analogue of a floating-point expansion:
2274/// exact proof information, without an O(n²) expansion walk or arbitrary
2275/// precision dependency.
2276struct CertifiedCompensatedSum {
2277    leading: f64,
2278    correction: ClosedInterval,
2279}
2280
2281impl CertifiedCompensatedSum {
2282    fn new(value: f64) -> Self {
2283        Self {
2284            leading: value,
2285            correction: ClosedInterval::point(0.0),
2286        }
2287    }
2288
2289    /// Add one exact binary64 value, retaining the exact TwoSum residual.
2290    fn add_exact(&mut self, value: f64) -> bool {
2291        let sum = self.leading + value;
2292        if !sum.is_finite() {
2293            return false;
2294        }
2295        let virtual_value = sum - self.leading;
2296        let virtual_leading = sum - virtual_value;
2297        let value_residual = value - virtual_value;
2298        let leading_residual = self.leading - virtual_leading;
2299        // Under round-to-nearest with gradual underflow, the two residuals and
2300        // their final sum are exact (Knuth/Møller TwoSum).
2301        let error = leading_residual + value_residual;
2302        self.leading = sum;
2303        self.correction = self.correction.add(ClosedInterval::point(error));
2304        self.correction.is_valid()
2305    }
2306
2307    fn subtract_interval(&mut self, value: ClosedInterval) -> bool {
2308        self.correction = self.correction.sub(value);
2309        self.correction.is_valid()
2310    }
2311
2312    fn enclosure(self) -> Option<ClosedInterval> {
2313        let enclosure = ClosedInterval::point(self.leading).add(self.correction);
2314        (enclosure.is_valid() && enclosure.lo.is_finite() && enclosure.hi.is_finite())
2315            .then_some(enclosure)
2316    }
2317}
2318
2319/// Split one exact-real positive quotient into a binary64 leading value and a
2320/// rigorous low correction:
2321///
2322/// `numerator / denominator ∈ leading + correction`.
2323///
2324/// The fused residual `numerator - leading*denominator` rounds only once.
2325/// Its two adjacent binary64 values therefore enclose the exact residual; a
2326/// directed division by the positive denominator transports that enclosure
2327/// into quotient units. The correction is normally O(u²) relative to the
2328/// quotient, rather than the O(u) width of independently directed division.
2329fn quotient_leading_and_correction(
2330    numerator: f64,
2331    denominator: f64,
2332) -> Option<(f64, ClosedInterval)> {
2333    if numerator == 0.0 {
2334        return Some((0.0, ClosedInterval::point(0.0)));
2335    }
2336    if !(numerator.is_finite() && numerator > 0.0 && denominator.is_finite() && denominator > 0.0) {
2337        return None;
2338    }
2339    let leading = numerator / denominator;
2340    if !(leading.is_finite() && leading >= 0.0) {
2341        return None;
2342    }
2343    if denominator == 1.0 {
2344        return Some((leading, ClosedInterval::point(0.0)));
2345    }
2346    let fused_residual = (-leading).mul_add(denominator, numerator);
2347    if !fused_residual.is_finite() {
2348        return None;
2349    }
2350    let exact_residual = ClosedInterval::new(next_down(fused_residual), next_up(fused_residual));
2351    let correction = exact_residual.div_positive(ClosedInterval::point(denominator));
2352    (correction.is_valid() && correction.lo.is_finite() && correction.hi.is_finite())
2353        .then_some((leading, correction))
2354}
2355
2356fn certified_zero_lambda_residual(
2357    energy: f64,
2358    gram_modes: &[f64],
2359    projected_squares: &[f64],
2360) -> Option<ClosedInterval> {
2361    let mut residual = CertifiedCompensatedSum::new(energy);
2362    for (&gram, &projected_square) in gram_modes.iter().zip(projected_squares) {
2363        if gram == 0.0 || projected_square == 0.0 {
2364            continue;
2365        }
2366        let (leading, correction) = quotient_leading_and_correction(projected_square, gram)?;
2367        if !(residual.add_exact(-leading) && residual.subtract_interval(correction)) {
2368            return None;
2369        }
2370    }
2371    residual.enclosure()
2372}
2373
2374// Operation counts in the scalar evaluator's per-mode accumulators.  They are
2375// kept beside the profile rather than written as anonymous roundoff factors:
2376// determinant value = at most exponential, multiply, divide, two logarithms,
2377// two additions/subtractions, and accumulator update;
2378// determinant first = fused h, the cancellation-free complement g/h, and sum;
2379// determinant second adds u and the product;
2380// residual value = at most two ratio divisions, scaling, and subtraction;
2381// residual first adds numerator product, division, and sum to the `u` path;
2382// residual second additionally forms `2u`, `1-2u`, and its product.
2383const DETERMINANT_VALUE_OPS_PER_MODE: usize = 8;
2384const RESIDUAL_VALUE_OPS_PER_MODE: usize = 4;
2385const RESIDUAL_LOG_OPS_PER_RESPONSE: usize = 3;
2386const SCORE_COMBINE_OPS: usize = 4;
2387
2388impl<'a> AffineRemlProfile<'a> {
2389    pub fn new(
2390        gram_modes: &'a [f64],
2391        penalty_modes: &'a [f64],
2392        projected_rhs_squared: &'a [f64],
2393        response_energy: &'a [f64],
2394        residual_dof: f64,
2395        determinant_rank: usize,
2396        logdet_constant: f64,
2397    ) -> Result<Self, AffineRemlError> {
2398        let modes = gram_modes.len();
2399        let responses = response_energy.len();
2400        if modes == 0 {
2401            return Err(AffineRemlError::EmptyModes);
2402        }
2403        if responses == 0 {
2404            return Err(AffineRemlError::EmptyResponses);
2405        }
2406        if penalty_modes.len() != modes
2407            || projected_rhs_squared.len() != modes.saturating_mul(responses)
2408        {
2409            return Err(AffineRemlError::ShapeMismatch {
2410                gram_modes: modes,
2411                penalty_modes: penalty_modes.len(),
2412                projected_rhs_squared: projected_rhs_squared.len(),
2413                responses,
2414            });
2415        }
2416        for (index, (&gram, &penalty)) in gram_modes.iter().zip(penalty_modes).enumerate() {
2417            if !(gram.is_finite()
2418                && penalty.is_finite()
2419                && gram >= 0.0
2420                && penalty >= 0.0
2421                && (gram > 0.0 || penalty > 0.0))
2422            {
2423                return Err(AffineRemlError::InvalidMode {
2424                    index,
2425                    gram,
2426                    penalty,
2427                });
2428            }
2429        }
2430        for (index, &value) in projected_rhs_squared.iter().enumerate() {
2431            if !(value.is_finite() && value >= 0.0) {
2432                return Err(AffineRemlError::InvalidProjectedSquare { index, value });
2433            }
2434        }
2435        for (output, &value) in response_energy.iter().enumerate() {
2436            if !(value.is_finite() && value >= 0.0) {
2437                return Err(AffineRemlError::InvalidResponseEnergy { output, value });
2438            }
2439        }
2440        if !(residual_dof.is_finite() && residual_dof > 0.0) {
2441            return Err(AffineRemlError::InvalidResidualDof {
2442                value: residual_dof,
2443            });
2444        }
2445        if !logdet_constant.is_finite() {
2446            return Err(AffineRemlError::InvalidLogdetConstant {
2447                value: logdet_constant,
2448            });
2449        }
2450        let inferred_rank = penalty_modes.iter().filter(|&&value| value > 0.0).count();
2451        if determinant_rank != inferred_rank {
2452            return Err(AffineRemlError::RankMismatch {
2453                supplied: determinant_rank,
2454                inferred: inferred_rank,
2455            });
2456        }
2457        let mut zero_lambda_residual = Vec::with_capacity(responses);
2458        for (output, &energy) in response_energy.iter().enumerate() {
2459            let start = output * modes;
2460            let end = start + modes;
2461            zero_lambda_residual.push(
2462                certified_zero_lambda_residual(
2463                    energy,
2464                    gram_modes,
2465                    &projected_rhs_squared[start..end],
2466                )
2467                .ok_or(AffineRemlError::ZeroLambdaResidualUnavailable { output })?,
2468            );
2469        }
2470        Ok(Self {
2471            gram_modes,
2472            penalty_modes,
2473            projected_rhs_squared,
2474            response_energy,
2475            zero_lambda_residual,
2476            residual_dof,
2477            logdet_constant,
2478        })
2479    }
2480
2481    #[inline]
2482    pub fn num_modes(&self) -> usize {
2483        self.gram_modes.len()
2484    }
2485
2486    #[inline]
2487    pub fn num_responses(&self) -> usize {
2488        self.response_energy.len()
2489    }
2490
2491    /// Nearest-rounded score value, first derivative, and second derivative in
2492    /// `log(lambda)`. [`Self::enclose`] supplies the proof-grade outer ranges.
2493    pub fn evaluate(&self, log_lambda: f64) -> Result<ScoreJet, AffineRemlError> {
2494        if !log_lambda.is_finite() {
2495            return Err(AffineRemlError::InvalidLogLambda { value: log_lambda });
2496        }
2497        let lambda = certified_exp_representative(log_lambda)
2498            .ok_or(AffineRemlError::InvalidLogLambda { value: log_lambda })?;
2499        if !(lambda.is_finite() && lambda > 0.0) {
2500            return Err(AffineRemlError::InvalidLogLambda { value: log_lambda });
2501        }
2502
2503        let mut normalized_logdet = self.logdet_constant;
2504        let mut determinant_derivative = 0.0;
2505        let mut determinant_curvature = 0.0;
2506        let exp_neg_log_lambda = if log_lambda >= 0.0 {
2507            certified_exp_representative(-log_lambda)
2508        } else {
2509            None
2510        };
2511        for (index, (&gram, &penalty)) in self.gram_modes.iter().zip(self.penalty_modes).enumerate()
2512        {
2513            // A gram-zero penalized mode is structurally
2514            //
2515            //   log(exp(rho) s) - rho = log(s),
2516            //
2517            // with first and second derivatives exactly zero. Do not form
2518            // `exp(rho) s`: its rounded product may be zero or infinity even
2519            // though every normalized determinant quantity is finite.
2520            if gram == 0.0 {
2521                normalized_logdet +=
2522                    certified_ln_value(penalty).ok_or(AffineRemlError::NonPositiveMode {
2523                        index,
2524                        log_lambda,
2525                        value: penalty,
2526                    })?;
2527                continue;
2528            }
2529            let h = lambda.mul_add(penalty, gram);
2530            if !(h.is_finite() && h > 0.0) {
2531                return Err(AffineRemlError::NonPositiveMode {
2532                    index,
2533                    log_lambda,
2534                    value: h,
2535                });
2536            }
2537            let u = lambda * penalty / h;
2538            // For a penalized mode,
2539            //
2540            //   d/d rho [log(g + exp(rho)s) - rho]
2541            //     = u - 1 = -g/h,
2542            //
2543            // and its second derivative is u*g/h. Accumulate in that
2544            // cancellation-free complement currency rather than adding u to a
2545            // separately rounded `-rank`; the latter loses the derivative's
2546            // sign when u rounds to one. An unpenalized mode has no `-rho`
2547            // normalization and contributes exactly zero.
2548            let determinant_complement = if penalty == 0.0 { 0.0 } else { gram / h };
2549            // Accumulate the determinant in the normalized per-mode form
2550            // instead of forming two O(rho) quantities and subtracting them
2551            // after the sum. Both branches keep their exponential in (0, 1]:
2552            //
2553            // log(g + exp(rho)s) - rho
2554            //   = log(s + g exp(-rho))                         rho >= 0
2555            //   = log(g) - rho + log1p(exp(rho)s/g)            g dominates
2556            //   = log(s) + log1p(g/(exp(rho)s))                s dominates.
2557            //
2558            // The selected log1p ratio is always in [0, 1], so neither tail
2559            // forms an overflowing exponential or divides by its small term.
2560            let normalized_mode = if penalty == 0.0 {
2561                certified_ln_value(gram)
2562            } else if log_lambda >= 0.0 {
2563                exp_neg_log_lambda
2564                    .and_then(|exp_neg_rho| certified_ln_value(penalty + gram * exp_neg_rho))
2565            } else if gram >= penalty * lambda {
2566                certified_ln_value(gram)
2567                    .zip(certified_ln_1p_value(penalty * lambda / gram))
2568                    .map(|(log_gram, correction)| log_gram - log_lambda + correction)
2569            } else {
2570                certified_ln_value(penalty)
2571                    .zip(certified_ln_1p_value(gram / (penalty * lambda)))
2572                    .map(|(log_penalty, correction)| log_penalty + correction)
2573            }
2574            .ok_or(AffineRemlError::NonPositiveMode {
2575                index,
2576                log_lambda,
2577                value: h,
2578            })?;
2579            normalized_logdet += normalized_mode;
2580            determinant_derivative -= determinant_complement;
2581            determinant_curvature += u * determinant_complement;
2582        }
2583
2584        let modes = self.num_modes();
2585        let mut residual_log_sum = 0.0;
2586        let mut residual_derivative_sum = 0.0;
2587        let mut residual_curvature_sum = 0.0;
2588        for (output, &energy) in self.response_energy.iter().enumerate() {
2589            let mut residual = energy;
2590            let mut first = 0.0;
2591            let mut second = 0.0;
2592            for i in 0..modes {
2593                let projected_square = self.projected_rhs_squared[output * modes + i];
2594                if projected_square == 0.0 {
2595                    continue;
2596                }
2597                if self.gram_modes[i] == 0.0 {
2598                    let fitted = positive_ratio_over_product(
2599                        projected_square,
2600                        self.penalty_modes[i],
2601                        lambda,
2602                    )
2603                    .ok_or(
2604                        AffineRemlError::ElementaryEnclosureUnavailable {
2605                            function: "gram-zero residual quotient",
2606                            lo: log_lambda,
2607                            hi: log_lambda,
2608                        },
2609                    )?;
2610                    residual -= fitted;
2611                    first += fitted;
2612                    second -= fitted;
2613                    continue;
2614                }
2615                let h = lambda.mul_add(self.penalty_modes[i], self.gram_modes[i]);
2616                let u = lambda * self.penalty_modes[i] / h;
2617                residual -= projected_square / h;
2618                first += projected_square * u / h;
2619                second += projected_square * u * (1.0 - 2.0 * u) / h;
2620            }
2621            if !(residual.is_finite() && residual > 0.0) {
2622                return Err(AffineRemlError::NonPositiveResidual {
2623                    output,
2624                    log_lambda,
2625                    value: residual,
2626                });
2627            }
2628            let log_derivative = first / residual;
2629            residual_log_sum += certified_ln_value(residual / self.residual_dof).ok_or(
2630                AffineRemlError::NonPositiveResidual {
2631                    output,
2632                    log_lambda,
2633                    value: residual,
2634                },
2635            )?;
2636            residual_derivative_sum += log_derivative;
2637            residual_curvature_sum += second / residual - log_derivative * log_derivative;
2638        }
2639
2640        let outputs = self.num_responses() as f64;
2641        Ok(ScoreJet {
2642            value: -0.5 * (outputs * normalized_logdet + self.residual_dof * residual_log_sum),
2643            derivative: -0.5
2644                * (outputs * determinant_derivative + self.residual_dof * residual_derivative_sum),
2645            curvature: -0.5
2646                * (outputs * determinant_curvature + self.residual_dof * residual_curvature_sum),
2647            // This profile's companion `enclose` builds its own ranges from the
2648            // mode kernels on an interval lambda and centres them on the cell
2649            // MIDPOINT, so it never reads an endpoint jet's third derivative --
2650            // the third derivative it centres the curvature on is an interval
2651            // one it accumulates itself. Nothing reads this field for this
2652            // profile, and a scalar third derivative of a score whose two blocks
2653            // cancel would be the least trustworthy number here, so it stays
2654            // exactly zero rather than being computed and quietly relied on.
2655            third: 0.0,
2656        })
2657    }
2658
2659    /// Outward enclosure of the score value and first two derivatives on a
2660    /// bounded log-lambda interval.
2661    ///
2662    /// # Two enclosures, intersected: the natural extension and the centred form
2663    ///
2664    /// `Self::enclose_direct` below is the NATURAL interval extension — each
2665    /// mode kernel evaluated on the interval lambda and summed. It is rigorous,
2666    /// and on the derivative and curvature it is also tight, because there the
2667    /// exact quantities are `O(1)` sums.
2668    ///
2669    /// On the score VALUE it is neither, and the reason is structural rather
2670    /// than incidental. The value is
2671    ///
2672    /// ```text
2673    ///     -0.5 * (D * normalized_logdet + residual_dof * sum_d log(R_d/dof))
2674    /// ```
2675    ///
2676    /// and near a REML optimum those two brackets cancel: each block's `d/drho`
2677    /// is `O(rank)` while their sum is not. Interval addition cannot see that
2678    /// the two variations are the same quantity with opposite signs, so the
2679    /// natural extension carries `rank * width` of slack the exact function does
2680    /// not have. Measured on a 33-mode profile over six decades of cell width,
2681    /// the value range came out at `33.0 * width` EXACTLY while the cell's own
2682    /// derivative enclosure bounded the score's variation across it by up to
2683    /// `7.4e5` times less — and the ratio DIVERGES as the cell shrinks, because
2684    /// one side is `O(w)` and the other `O(w^2)`.
2685    ///
2686    /// That is not a cosmetic loss. `maximize_score_1d` retires a cell as
2687    /// resolution-flat when its score range fits inside `2 * evaluation_error`;
2688    /// against an `O(w)` range that test needs a cell `rank/|f'|` times narrower
2689    /// than the function requires, so cells that ARE flat get subdivided, and a
2690    /// search that should finish in a handful of cells exhausts its subdivision
2691    /// budget and refuses a design it can certify.
2692    ///
2693    /// The cure is the standard one and needs nothing this routine does not
2694    /// already compute. For every `x` in `[a, b]` and `m` the midpoint, the mean
2695    /// value theorem gives
2696    ///
2697    /// ```text
2698    ///     f(x)  in  F({m})  + F'([a,b]) * [a-m, b-m]
2699    ///     f'(x) in  F'({m}) + F''([a,b]) * [a-m, b-m]
2700    /// ```
2701    ///
2702    /// with `F({m})` obtained by calling the SAME natural extension on the
2703    /// degenerate interval `[m, m]`. Both forms are outer enclosures of the same
2704    /// exact range, so their INTERSECTION is an outer enclosure too — this can
2705    /// only ever tighten, never widen, and it is never an acceptance tolerance.
2706    /// The centred form's overestimation is second order in the cell width,
2707    /// which is what makes the branch-and-bound converge.
2708    ///
2709    /// All three channels are centred, including the curvature: the profile's
2710    /// mode kernels are analytic, so `enclose_direct` also accumulates the exact
2711    /// third-derivative range (`t(1-4t+t^2)/(1+t)^4` per mode for the residual,
2712    /// `t(1-t)/(1+t)^3` for the determinant), and the curvature is centred on
2713    /// that. It matters: stationary isolation reads the curvature DIRECTLY and
2714    /// needs its sign, so a first-order-loose curvature is what stops a root
2715    /// being isolated rather than merely making a range wide.
2716    ///
2717    /// The `evaluation_error` is a property of the POINT evaluator over the
2718    /// cell, not of which enclosure form was tighter, so it is carried across
2719    /// unchanged from the whole-cell reading (the conservative one — the
2720    /// midpoint reading is taken over a degenerate interval and is never wider).
2721    ///
2722    /// # One consequence worth naming, because it points the other way
2723    ///
2724    /// `resolution_flat_region` retires a cell when its score range fits inside
2725    /// `2 * evaluation_error`, so a TIGHTER value range makes that verdict
2726    /// easier to reach — and a caller whose optimum lands in such a region gets
2727    /// a refusal (`ResidualCascadeError::RemlOptimumResolutionFlat`) rather than
2728    /// a fit. Tightening could in principle trade a subdivision-budget refusal
2729    /// for a resolution-flat one.
2730    ///
2731    /// It does not, because the flat test is the LAST thing a cell is offered:
2732    /// dominance, derivative exclusion and stationary isolation are all tried
2733    /// first, and centring strengthens each of them by more than it strengthens
2734    /// the flat test — the derivative and curvature ranges are what decide those
2735    /// three, and both are now centred too. Measured on the cascade design this
2736    /// was built for: the search returns `Stationary(0)` at every requested
2737    /// resolution from `1.49e-8` to `1e-3`, never `ResolutionFlat`, and
2738    /// `auto_reml_certifies_a_design_the_data_cannot_identify` asserts exactly
2739    /// that so the trade cannot creep in unnoticed.
2740    pub fn enclose(&self, lo: f64, hi: f64) -> Result<DerivativeEnclosure, AffineRemlError> {
2741        let (direct, direct_third) = self.enclose_direct(lo, hi)?;
2742        if lo == hi {
2743            return Ok(direct);
2744        }
2745        // Any point of the cell is a valid expansion centre; the midpoint
2746        // minimizes the worst-case `|x - m|` and so the width of the remainder
2747        // term. Clamped because `0.5*(lo+hi)` may round outside a cell whose
2748        // endpoints are adjacent floats, and a centre outside the cell would
2749        // make the mean value theorem inapplicable.
2750        let centre_point = (0.5 * (lo + hi)).clamp(lo, hi);
2751        let (centre, _) = self.enclose_direct(centre_point, centre_point)?;
2752        // `[a-m, b-m]`, rounded OUTWARD. Both subtractions are exact by
2753        // Sterbenz whenever the endpoints are within a factor of two of the
2754        // centre, which is the usual case; the directed widening costs one ulp
2755        // and removes the need to prove it.
2756        let offset = ClosedInterval::new(
2757            next_down(lo - centre_point).min(0.0),
2758            next_up(hi - centre_point).max(0.0),
2759        );
2760        // The three channels are centred in DERIVATIVE ORDER, each on the result
2761        // of the one above, because a mean value remainder is only as tight as
2762        // the range fed into it: the curvature's remainder is `F'''*offset`, the
2763        // derivative's is `F''*offset`, and the value's is `F'*offset`. Feeding
2764        // each the natural extension's range instead of the centred one leaves a
2765        // constant factor on the floor at every level — measured at 3.3x on the
2766        // value alone — and it is this cascade that makes
2767        // `width(F) <= width(F({m})) + max|F'| * w` hold BY CONSTRUCTION against
2768        // the ranges this function actually returns.
2769        let curvature = centred_or(direct.curvature, centre.curvature, direct_third, offset);
2770        let derivative = centred_or(direct.derivative, centre.derivative, curvature, offset);
2771        let value = centred_or(direct.score.value, centre.score.value, derivative, offset);
2772        Ok(DerivativeEnclosure {
2773            score: ScoreValueEnclosure {
2774                value,
2775                evaluation_error: direct.score.evaluation_error,
2776            },
2777            derivative,
2778            curvature,
2779        })
2780    }
2781
2782    /// The natural (direct) interval extension: every mode kernel evaluated on
2783    /// the interval lambda and accumulated.
2784    ///
2785    /// The interval kernels enclose the exact-real ranges. The score value uses
2786    /// the same cancellation-free normalized determinant identity as
2787    /// [`Self::evaluate`]. Its separate `evaluation_error` charges each
2788    /// source-derived elementary-function interval, error propagation through
2789    /// `log(residual)`, and Wilkinson `gamma_k * sum |term|` bounds for the
2790    /// actual sequential accumulators.
2791    ///
2792    /// [`Self::enclose`] is what callers want: this form alone is first-order
2793    /// loose on the value, for the reason documented there.
2794    fn enclose_direct(
2795        &self,
2796        lo: f64,
2797        hi: f64,
2798    ) -> Result<(DerivativeEnclosure, ClosedInterval), AffineRemlError> {
2799        if !(lo.is_finite() && hi.is_finite() && lo <= hi) {
2800            return Err(AffineRemlError::InvalidLogLambdaInterval { lo, hi });
2801        }
2802        let lambda = exp_interval(lo, hi)?;
2803        if !(lambda.lo.is_finite() && lambda.lo > 0.0 && lambda.hi.is_finite()) {
2804            return Err(AffineRemlError::InvalidLogLambdaInterval { lo, hi });
2805        }
2806        // Exp's range-reduction, arithmetic, and truncation errors are
2807        // multiplicative and must remain in relative currency across a wide
2808        // interval. Only gradual underflow is additive and is charged against
2809        // the certified positive lower endpoint. This avoids coupling an
2810        // upper-endpoint absolute error to the lower-endpoint scale.
2811        let lambda_relative_error =
2812            certified_exp_relative_forward_error(ClosedInterval::new(lo, hi), lambda);
2813        if !lambda_relative_error.is_finite() {
2814            return Err(AffineRemlError::UnboundedScoreEvaluationError {
2815                lo,
2816                hi,
2817                error: lambda_relative_error,
2818            });
2819        }
2820
2821        let mut normalized_logdet = ClosedInterval::point(self.logdet_constant);
2822        let mut normalized_logdet_magnitude = self.logdet_constant.abs();
2823        let mut normalized_logdet_error = 0.0;
2824        let mut determinant_first = ClosedInterval::point(0.0);
2825        let mut determinant_second = ClosedInterval::point(0.0);
2826        let mut determinant_third = ClosedInterval::point(0.0);
2827        for i in 0..self.num_modes() {
2828            let (normalized_mode, normalized_mode_error) =
2829                normalized_log_mode_enclosure(self.gram_modes[i], self.penalty_modes[i], lo, hi)?;
2830            normalized_logdet = normalized_logdet.add(normalized_mode);
2831            normalized_logdet_magnitude = add_nonnegative_upward(
2832                normalized_logdet_magnitude,
2833                add_nonnegative_upward(normalized_mode.max_abs(), normalized_mode_error),
2834            );
2835            normalized_logdet_error =
2836                add_nonnegative_upward(normalized_logdet_error, normalized_mode_error);
2837
2838            let ranges = mode_ranges(self.gram_modes[i], self.penalty_modes[i], 0.0, lambda)?;
2839            determinant_first = determinant_first.sub(ranges.c);
2840            determinant_second = determinant_second.add(ranges.w);
2841            determinant_third = determinant_third.add(ranges.determinant_third);
2842        }
2843
2844        let mut residual_first_sum = ClosedInterval::point(0.0);
2845        let mut residual_second_sum = ClosedInterval::point(0.0);
2846        let mut residual_third_sum = ClosedInterval::point(0.0);
2847        let mut residual_log_sum = ClosedInterval::point(0.0);
2848        let mut residual_log_magnitude = 0.0;
2849        let mut residual_log_error = 0.0;
2850        let modes = self.num_modes();
2851        for (output, &energy) in self.response_energy.iter().enumerate() {
2852            let mut fitted_quadratic = ClosedInterval::point(0.0);
2853            let mut smoothing_increment = ClosedInterval::point(0.0);
2854            let mut singular_fitted = ClosedInterval::point(0.0);
2855            let mut first = ClosedInterval::point(0.0);
2856            let mut second = ClosedInterval::point(0.0);
2857            let mut third = ClosedInterval::point(0.0);
2858            let mut fitted_magnitude = energy;
2859            for i in 0..modes {
2860                let ranges = mode_ranges(
2861                    self.gram_modes[i],
2862                    self.penalty_modes[i],
2863                    self.projected_rhs_squared[output * modes + i],
2864                    lambda,
2865                )?;
2866                fitted_quadratic = fitted_quadratic.add(ranges.v);
2867                smoothing_increment = smoothing_increment.add(ranges.smoothing_increment);
2868                singular_fitted = singular_fitted.add(ranges.singular_fitted);
2869                first = first.add(ranges.p);
2870                second = second.add(ranges.q);
2871                third = third.add(ranges.residual_third);
2872                fitted_magnitude = add_nonnegative_upward(fitted_magnitude, ranges.v.max_abs());
2873            }
2874            // Two exact identities describe the same residual:
2875            //
2876            //   R = E - sum_i q_i/(g_i + lambda*s_i)
2877            //
2878            // and, for every positive-Gram mode,
2879            //
2880            //   q_i/(g_i + lambda*s_i)
2881            //     = q_i/g_i - (q_i/g_i) * lambda*s_i/(g_i + lambda*s_i).
2882            //
2883            // The direct form is well-conditioned away from interpolation.
2884            // Near the zero-smoothing face it subtracts many independently
2885            // rounded near-one fitted fractions from `E`, even though their
2886            // deviations from one are perfectly correlated with lambda.  The
2887            // complement form carries that correlation explicitly as a
2888            // fixed zero-smoothing residual plus nonnegative smoothing
2889            // increments.  Both are rigorous outer enclosures, so their
2890            // intersection is rigorous and never an acceptance tolerance.
2891            let direct_residual = ClosedInterval::point(energy).sub(fitted_quadratic);
2892            let complement_residual = self.zero_lambda_residual[output]
2893                .add(smoothing_increment)
2894                .sub(singular_fitted);
2895            let residual = direct_residual.intersection(complement_residual).ok_or(
2896                AffineRemlError::InconsistentResidualEnclosures {
2897                    output,
2898                    lo,
2899                    hi,
2900                    direct: direct_residual,
2901                    complement: complement_residual,
2902                },
2903            )?;
2904            if !(residual.lo > 0.0 && residual.is_valid()) {
2905                return Err(AffineRemlError::NonPositiveResidualInterval {
2906                    output,
2907                    lo,
2908                    hi,
2909                    lower_bound: residual.lo,
2910                });
2911            }
2912            let first_ratio = first.div_positive(residual).nonnegative();
2913            let second_ratio = second.div_positive(residual);
2914            let third_ratio = third.div_positive(residual);
2915            residual_first_sum = residual_first_sum.add(first_ratio);
2916            residual_second_sum = residual_second_sum.add(second_ratio.sub(first_ratio.square()));
2917            // The third derivative of `log R`, from the same three ratios:
2918            //   (log R)''' = R'''/R - 3 (R''/R)(R'/R) + 2 (R'/R)^3.
2919            residual_third_sum = residual_third_sum.add(
2920                third_ratio
2921                    .sub(second_ratio.mul(first_ratio).scale(3.0))
2922                    .add(first_ratio.square().mul(first_ratio).scale(2.0)),
2923            );
2924
2925            let fitted_arithmetic_error = wilkinson_roundoff(
2926                fitted_magnitude,
2927                modes.saturating_mul(RESIDUAL_VALUE_OPS_PER_MODE),
2928            );
2929            // `first = d fitted/d rho`, so the MVT propagates the exp error in
2930            // rho-space without a condition-number guess.
2931            let fitted_exp_error = next_up(first.max_abs() * lambda_relative_error);
2932            let resolved_fitted_quadratic = fitted_quadratic.widen(add_nonnegative_upward(
2933                fitted_arithmetic_error,
2934                fitted_exp_error,
2935            ));
2936            let resolved_residual = ClosedInterval::point(energy).sub(resolved_fitted_quadratic);
2937            if !(resolved_residual.lo > 0.0 && resolved_residual.is_valid()) {
2938                return Err(AffineRemlError::NonPositiveResidualInterval {
2939                    output,
2940                    lo,
2941                    hi,
2942                    lower_bound: resolved_residual.lo,
2943                });
2944            }
2945            let residual_over_dof = residual.div_positive(ClosedInterval::point(self.residual_dof));
2946            if !(residual_over_dof.lo > 0.0 && residual_over_dof.hi.is_finite()) {
2947                return Err(AffineRemlError::ElementaryEnclosureUnavailable {
2948                    function: "ln",
2949                    lo: residual_over_dof.lo,
2950                    hi: residual_over_dof.hi,
2951                });
2952            }
2953            let residual_log = residual_over_dof.ln_positive();
2954            residual_log_sum = residual_log_sum.add(residual_log);
2955
2956            // `evaluate` first forms the residual and then takes
2957            // `ln(residual/dof)`. The residual forward error is already
2958            // represented by `resolved_residual`. On the strictly positive
2959            // resolved range, the mean-value theorem bounds its propagation
2960            // through log by `delta_R / min(R)`. The division and logarithm
2961            // each add one directed basic-operation contribution; the
2962            // source-derived logarithm error is absolute, so it remains valid
2963            // when the logarithm's result is near zero.
2964            let residual_error = enclosure_excess(residual, resolved_residual);
2965            let propagated_residual_error = next_up(residual_error / resolved_residual.lo);
2966            let elementary_error = certified_log_forward_error(
2967                residual.div_positive(ClosedInterval::point(self.residual_dof)),
2968            );
2969            let local_log_error = add_nonnegative_upward(
2970                propagated_residual_error,
2971                add_nonnegative_upward(
2972                    elementary_error,
2973                    wilkinson_roundoff(
2974                        add_nonnegative_upward(1.0, residual_log.max_abs()),
2975                        RESIDUAL_LOG_OPS_PER_RESPONSE,
2976                    ),
2977                ),
2978            );
2979            residual_log_error = add_nonnegative_upward(residual_log_error, local_log_error);
2980            residual_log_magnitude = add_nonnegative_upward(
2981                residual_log_magnitude,
2982                add_nonnegative_upward(residual_log.max_abs(), local_log_error),
2983            );
2984        }
2985
2986        let outputs = self.num_responses() as f64;
2987        let first_bracket = determinant_first
2988            .scale(outputs)
2989            .add(residual_first_sum.scale(self.residual_dof));
2990        let second_bracket = determinant_second
2991            .scale(outputs)
2992            .add(residual_second_sum.scale(self.residual_dof));
2993        let third_bracket = determinant_third
2994            .scale(outputs)
2995            .add(residual_third_sum.scale(self.residual_dof));
2996        let derivative = first_bracket.scale(-0.5);
2997        let curvature = second_bracket.scale(-0.5);
2998        let third = third_bracket.scale(-0.5);
2999        let score_value = normalized_logdet
3000            .scale(outputs)
3001            .add(residual_log_sum.scale(self.residual_dof))
3002            .scale(-0.5);
3003        let score_magnitude = add_nonnegative_upward(
3004            next_up(outputs * normalized_logdet_magnitude),
3005            next_up(self.residual_dof * residual_log_magnitude),
3006        );
3007        normalized_logdet_error = add_nonnegative_upward(
3008            normalized_logdet_error,
3009            wilkinson_roundoff(normalized_logdet_magnitude, self.num_modes()),
3010        );
3011        residual_log_error = add_nonnegative_upward(
3012            residual_log_error,
3013            wilkinson_roundoff(residual_log_magnitude, self.num_responses()),
3014        );
3015        let final_arithmetic_error = wilkinson_roundoff(score_magnitude, SCORE_COMBINE_OPS);
3016        let weighted_component_error = add_nonnegative_upward(
3017            next_up(outputs * normalized_logdet_error),
3018            next_up(self.residual_dof * residual_log_error),
3019        );
3020        let value_evaluation_error =
3021            next_up(0.5 * add_nonnegative_upward(weighted_component_error, final_arithmetic_error));
3022        if !(score_value.is_valid() && value_evaluation_error.is_finite()) {
3023            return Err(AffineRemlError::UnboundedScoreEvaluationError {
3024                lo,
3025                hi,
3026                error: value_evaluation_error,
3027            });
3028        }
3029        let score = ScoreValueEnclosure {
3030            value: score_value,
3031            evaluation_error: value_evaluation_error,
3032        };
3033        Ok((
3034            DerivativeEnclosure {
3035                score,
3036                derivative,
3037                curvature,
3038            },
3039            third,
3040        ))
3041    }
3042
3043    /// Isolate every finite stationary candidate and tighten location
3044    /// resolution until the selected exact score is globally orderable at the
3045    /// point evaluator's certified comparison resolution.
3046    ///
3047    /// The first pass honors the caller's requested location resolution.  A
3048    /// successful root isolation can still leave a wider exact score range
3049    /// than the rounded point comparison can distinguish, because location and
3050    /// value are different currencies.  In that case this repeats the same
3051    /// exact search with a smaller location target.  The observed ratio between
3052    /// comparison resolution and maximum excess is only an iteration strategy,
3053    /// never proof currency; every pass independently rebuilds the complete
3054    /// global certificate and the loop exits only on its verdict.
3055    ///
3056    /// There is no retry cap or acceptance fallback.  Each retry contracts the
3057    /// target by at least one binary subdivision.  If the target can no longer
3058    /// be represented, or the oracle cannot resolve structure at that finer
3059    /// target, the last complete certificate is returned unchanged for the
3060    /// caller's existing typed refusal.
3061    pub fn maximize_value_ordered(
3062        &self,
3063        lo: f64,
3064        hi: f64,
3065        initial_resolution: f64,
3066    ) -> Result<ScoreSearchResult, ScoreSearchError<AffineRemlError>> {
3067        maximize_score_1d_value_ordered(
3068            lo,
3069            hi,
3070            initial_resolution,
3071            |x| self.evaluate(x),
3072            |a, b| self.enclose(a.x, b.x),
3073        )
3074    }
3075}
3076
3077#[derive(Clone, Copy)]
3078struct ModeRanges {
3079    /// Cancellation-free determinant complement `c = g/h` for a penalized
3080    /// mode. An unpenalized mode contributes exactly zero because its
3081    /// normalized log determinant has no `-rho` term.
3082    c: ClosedInterval,
3083    /// `u(1-u)`.
3084    w: ClosedInterval,
3085    /// `projected_square / h`.
3086    v: ClosedInterval,
3087    /// The nonnegative loss of fitted energy caused by smoothing,
3088    /// `(projected_square / gram) * lambda*penalty / h`, for a positive Gram
3089    /// mode.
3090    smoothing_increment: ClosedInterval,
3091    /// The complete fitted contribution of a Gram-zero mode. Such a mode
3092    /// cannot participate in the zero-smoothing complement identity.
3093    singular_fitted: ClosedInterval,
3094    /// First derivative of the residual contribution:
3095    /// `projected_square * lambda s / h^2`.
3096    p: ClosedInterval,
3097    /// Second derivative of the residual contribution:
3098    /// `projected_square * lambda s (g-lambda s) / h^3`.
3099    q: ClosedInterval,
3100    /// Third `rho`-derivative of this mode's normalized log determinant,
3101    /// `u(1-u)(1-2u) = t(1-t)/(1+t)^3`. Exactly the `k` kernel: the
3102    /// determinant's second derivative is `w` and its third is `k`, which is
3103    /// also the fitted fraction's second. Zero for an unpenalized mode (no
3104    /// `-rho` term) and for a Gram-zero mode (whose normalized determinant is
3105    /// exactly constant).
3106    determinant_third: ClosedInterval,
3107    /// Third derivative of the residual contribution.
3108    residual_third: ClosedInterval,
3109}
3110
3111/// Exact-real range and a uniform forward-error bound for the normalized
3112/// determinant contribution of one affine mode.
3113///
3114/// The exact function is monotone, so outward endpoint evaluation gives its
3115/// range. [`AffineRemlProfile::evaluate`] uses algebraically equivalent stable
3116/// sign/dominance branches whose exponential or `ln_1p` argument is in
3117/// `[0, 1]`. The elementary-function bounds come from the source-derived
3118/// range-reduced series above, not a platform-libm accuracy assumption;
3119/// Wilkinson's bound charges the surrounding IEEE basic operations and the
3120/// elementary input perturbation. The leading `1` is the analytic sensitivity
3121/// bound: the mode's rho derivative lies in `[-1, 0]`.
3122fn normalized_log_mode_enclosure(
3123    gram: f64,
3124    penalty: f64,
3125    lo: f64,
3126    hi: f64,
3127) -> Result<(ClosedInterval, f64), AffineRemlError> {
3128    if penalty == 0.0 {
3129        let range = ClosedInterval::point(gram).ln_positive();
3130        return Ok((
3131            range,
3132            certified_log_forward_error(ClosedInterval::point(gram)),
3133        ));
3134    }
3135    if gram == 0.0 {
3136        let range = ClosedInterval::point(penalty).ln_positive();
3137        return Ok((
3138            range,
3139            certified_log_forward_error(ClosedInterval::point(penalty)),
3140        ));
3141    }
3142
3143    let at_lo = normalized_log_mode_at(gram, penalty, lo)?;
3144    let at_hi = normalized_log_mode_at(gram, penalty, hi)?;
3145    // The normalized contribution has derivative `u - 1` in [-1, 0].
3146    let range = ClosedInterval::new(at_hi.lo, at_lo.hi);
3147    // In the negative branch the final subtraction can cancel `log(h)` and
3148    // `rho`; charge both pre-cancellation operands. Since
3149    // `log(h) = normalized_mode + rho`, `|mode| + 2|rho|` bounds their absolute
3150    // sum without evaluating a second logarithm.
3151    let negative_rho_abs = if lo < 0.0 { -lo } else { 0.0 };
3152    let arithmetic_scale = add_nonnegative_upward(
3153        add_nonnegative_upward(1.0, range.max_abs()),
3154        next_up(2.0 * negative_rho_abs),
3155    );
3156    let arithmetic_error = wilkinson_roundoff(arithmetic_scale, DETERMINANT_VALUE_OPS_PER_MODE);
3157    let mut exp_input_error = 0.0_f64;
3158    if hi >= 0.0 {
3159        let positive_lo = lo.max(0.0);
3160        let exp_neg_rho = exp_interval(-hi, -positive_lo)?;
3161        let argument_lo = ClosedInterval::point(penalty)
3162            .add(ClosedInterval::point(gram).mul(exp_neg_rho))
3163            .lo;
3164        if argument_lo > 0.0 {
3165            exp_input_error = exp_input_error.max(next_up(
3166                gram * certified_exp_forward_error(
3167                    ClosedInterval::new(-hi, -positive_lo),
3168                    exp_neg_rho,
3169                ) / argument_lo,
3170            ));
3171        } else {
3172            exp_input_error = f64::INFINITY;
3173        }
3174    }
3175    if lo < 0.0 {
3176        let negative_hi = hi.min(0.0);
3177        let exp_rho = exp_interval(lo, negative_hi)?;
3178        if exp_rho.lo > 0.0 {
3179            // The two stable negative-rho branches have log-lambda
3180            // sensitivities `u` and `1-u`, respectively. Both are at most one,
3181            // so the scale-safe relative exp error is a uniform bound even if
3182            // the dominance branch changes.
3183            exp_input_error = exp_input_error.max(certified_exp_relative_forward_error(
3184                ClosedInterval::new(lo, negative_hi),
3185                exp_rho,
3186            ));
3187        } else {
3188            exp_input_error = f64::INFINITY;
3189        }
3190    }
3191    let log_output_error =
3192        certified_log_error_from_output(at_lo).max(certified_log_error_from_output(at_hi));
3193    let log_gram_error = certified_log_forward_error(ClosedInterval::point(gram));
3194    let log_penalty_error = certified_log_forward_error(ClosedInterval::point(penalty));
3195    let log1p_error = certified_ln1p_forward_error();
3196    let elementary_error = add_nonnegative_upward(
3197        exp_input_error,
3198        add_nonnegative_upward(
3199            log_output_error,
3200            add_nonnegative_upward(
3201                log_gram_error,
3202                add_nonnegative_upward(log_penalty_error, log1p_error),
3203            ),
3204        ),
3205    );
3206    Ok((
3207        range,
3208        add_nonnegative_upward(arithmetic_error, elementary_error),
3209    ))
3210}
3211
3212fn normalized_log_mode_at(
3213    gram: f64,
3214    penalty: f64,
3215    rho: f64,
3216) -> Result<ClosedInterval, AffineRemlError> {
3217    if rho >= 0.0 {
3218        let exp_neg_rho = exp_interval(-rho, -rho)?;
3219        let argument =
3220            ClosedInterval::point(penalty).add(ClosedInterval::point(gram).mul(exp_neg_rho));
3221        if !(argument.lo > 0.0 && argument.hi.is_finite()) {
3222            return Err(AffineRemlError::ElementaryEnclosureUnavailable {
3223                function: "ln",
3224                lo: argument.lo,
3225                hi: argument.hi,
3226            });
3227        }
3228        Ok(argument.ln_positive())
3229    } else {
3230        let exp_rho = exp_interval(rho, rho)?;
3231        let argument = ClosedInterval::point(gram).add(ClosedInterval::point(penalty).mul(exp_rho));
3232        if !(argument.lo > 0.0 && argument.hi.is_finite()) {
3233            return Err(AffineRemlError::ElementaryEnclosureUnavailable {
3234                function: "ln",
3235                lo: argument.lo,
3236                hi: argument.hi,
3237            });
3238        }
3239        Ok(argument.ln_positive().sub(ClosedInterval::point(rho)))
3240    }
3241}
3242
3243fn exp_interval(lo: f64, hi: f64) -> Result<ClosedInterval, AffineRemlError> {
3244    let unavailable = || AffineRemlError::ElementaryEnclosureUnavailable {
3245        function: "exp",
3246        lo,
3247        hi,
3248    };
3249    if !(lo.is_finite() && hi.is_finite() && lo <= hi) {
3250        return Err(unavailable());
3251    }
3252    let lower = certified_exp(lo).ok_or_else(unavailable)?;
3253    let upper = certified_exp(hi).ok_or_else(unavailable)?;
3254    let enclosure = ClosedInterval::new(lower.lo.max(0.0), upper.hi).nonnegative();
3255    if !enclosure.is_valid() {
3256        return Err(unavailable());
3257    }
3258    Ok(enclosure)
3259}
3260
3261/// Directed division for a nonnegative numerator and a strictly positive
3262/// denominator without first materializing the reciprocal.
3263///
3264/// Forming `1 / denominator.lo` can overflow even when the final quotient is
3265/// finite because a correspondingly tiny numerator cancels that scale. Direct
3266/// endpoint quotients preserve that finite result. Invalid preconditions and a
3267/// nonfinite upper bound are typed refusals rather than assertions.
3268fn finite_nonnegative_quotient(
3269    numerator: ClosedInterval,
3270    denominator: ClosedInterval,
3271    function: &'static str,
3272) -> Result<ClosedInterval, AffineRemlError> {
3273    if !(numerator.is_valid()
3274        && numerator.lo >= 0.0
3275        && denominator.is_valid()
3276        && denominator.lo > 0.0)
3277    {
3278        return Err(AffineRemlError::ElementaryEnclosureUnavailable {
3279            function,
3280            lo: denominator.lo,
3281            hi: denominator.hi,
3282        });
3283    }
3284    let quotient = ClosedInterval::new(
3285        quotient_down(numerator.lo, denominator.hi).max(0.0),
3286        quotient_up(numerator.hi, denominator.lo),
3287    );
3288    if !(quotient.is_valid() && quotient.hi.is_finite()) {
3289        return Err(AffineRemlError::ElementaryEnclosureUnavailable {
3290            function,
3291            lo: quotient.lo,
3292            hi: quotient.hi,
3293        });
3294    }
3295    Ok(quotient.nonnegative())
3296}
3297
3298/// One channel of the centred (mean value) enclosure, intersected with the
3299/// natural extension — and never trusted over it when the remainder is not a
3300/// finite interval.
3301///
3302/// `f(x) in point + slope * offset` for every `x` in the cell, by the mean value
3303/// theorem, when `point` encloses `f` (or `f'`, or `f''`) at the expansion
3304/// centre and `slope` encloses the NEXT derivative over the whole cell. Both
3305/// forms are outer enclosures of one exact range, so the intersection is an
3306/// outer enclosure too: this can only tighten.
3307///
3308/// # What the finiteness guard is for, measured
3309///
3310/// `ClosedInterval::mul` reduces four endpoint products with `f64::min` and
3311/// `f64::max`, which IGNORE a NaN operand, so a NaN product drops out of the
3312/// reduction and the surviving endpoints describe a range strictly INSIDE the
3313/// true one — an unsound certificate, in the one direction that matters, with no
3314/// signal at all.
3315///
3316/// The obvious way in is `inf * 0`, and that way is already shut:
3317/// `product_down`/`product_up` treat a zero operand as exact and map the NaN to
3318/// `0.0`, and a sweep over every endpoint shape finds no narrowing from a
3319/// singly-infinite slope. The way that is NOT shut is a NaN arriving from
3320/// anywhere else — `[NaN, 1.0] * [-0.5, 0.5]` reduces to `[-0.5, 0.5]`, two
3321/// corners silently gone — because `enclose_direct` does not prove every
3322/// accumulator finite and `checked_enclosure` validates only the enclosure the
3323/// search receives, after this narrowing would already have happened.
3324///
3325/// So the guard excludes a non-finite slope and a non-finite remainder, and
3326/// keeps the natural extension, which is rigorous unconditionally. See
3327/// `the_centred_form_keeps_the_natural_extension_when_the_remainder_is_not_finite`
3328/// for both halves as assertions.
3329fn centred_or(
3330    direct: ClosedInterval,
3331    point: ClosedInterval,
3332    slope: ClosedInterval,
3333    offset: ClosedInterval,
3334) -> ClosedInterval {
3335    if !(slope.is_valid() && slope.lo.is_finite() && slope.hi.is_finite()) {
3336        return direct;
3337    }
3338    let remainder = slope.mul(offset);
3339    if !(remainder.is_valid() && remainder.lo.is_finite() && remainder.hi.is_finite()) {
3340        return direct;
3341    }
3342    let centred = point.add(remainder);
3343    if !centred.is_valid() {
3344        return direct;
3345    }
3346    // Two rigorous outer enclosures of the same nonempty exact range cannot be
3347    // disjoint, so this fallback is unreachable; it is written in the sound
3348    // direction rather than as a panic, because a refusal here would convert a
3349    // tightening into a failure.
3350    direct.intersection(centred).unwrap_or(direct)
3351}
3352
3353fn mode_ranges(
3354    gram: f64,
3355    penalty: f64,
3356    projected_square: f64,
3357    lambda: ClosedInterval,
3358) -> Result<ModeRanges, AffineRemlError> {
3359    if penalty == 0.0 {
3360        let v = ClosedInterval::point(projected_square)
3361            .div_positive(ClosedInterval::point(gram))
3362            .nonnegative();
3363        return Ok(ModeRanges {
3364            c: ClosedInterval::point(0.0),
3365            w: ClosedInterval::point(0.0),
3366            v,
3367            smoothing_increment: ClosedInterval::point(0.0),
3368            singular_fitted: ClosedInterval::point(0.0),
3369            p: ClosedInterval::point(0.0),
3370            q: ClosedInterval::point(0.0),
3371            determinant_third: ClosedInterval::point(0.0),
3372            residual_third: ClosedInterval::point(0.0),
3373        });
3374    }
3375    if gram == 0.0 {
3376        let zero = ClosedInterval::point(0.0);
3377        if projected_square == 0.0 {
3378            return Ok(ModeRanges {
3379                c: zero,
3380                w: zero,
3381                v: zero,
3382                smoothing_increment: zero,
3383                singular_fitted: zero,
3384                p: zero,
3385                q: zero,
3386                determinant_third: zero,
3387                residual_third: zero,
3388            });
3389        }
3390
3391        // The normalized determinant is exactly constant for g=0. For the
3392        // residual, v = A/(lambda*s). Use the direct product only when its
3393        // outward lower bound is strictly positive. If that lower bound rounds
3394        // to zero, cancel the exact scalar penalty first and divide the
3395        // resulting nonnegative interval directly by lambda. This preserves a
3396        // finite quotient such as min_subnormal/(0.01*lambda) without ever
3397        // asking `div_positive` to accept a denominator containing zero.
3398        let h = lambda.mul(ClosedInterval::point(penalty)).nonnegative();
3399        let projected = ClosedInterval::point(projected_square);
3400        let v = if h.lo > 0.0 {
3401            finite_nonnegative_quotient(projected, h, "gram-zero residual quotient")?
3402        } else {
3403            let scaled = finite_nonnegative_quotient(
3404                projected,
3405                ClosedInterval::point(penalty),
3406                "gram-zero residual quotient",
3407            )?;
3408            finite_nonnegative_quotient(scaled, lambda, "gram-zero residual quotient")?
3409        };
3410        return Ok(ModeRanges {
3411            c: ClosedInterval::point(0.0),
3412            w: ClosedInterval::point(0.0),
3413            v,
3414            smoothing_increment: zero,
3415            singular_fitted: v,
3416            p: v,
3417            q: v.neg(),
3418            // A Gram-zero mode's fitted fraction is `A/(lambda s)`, whose
3419            // rho-derivative is its own negative, so the residual's successive
3420            // derivatives alternate in sign at constant magnitude.
3421            determinant_third: zero,
3422            residual_third: v,
3423        });
3424    }
3425
3426    // Normalize by g: h = g(1+t), t = lambda*s/g.  The four kernels below
3427    // have known global critical points, so endpoint evaluation plus any
3428    // critical point contained by the t-window gives an exact real range;
3429    // interval arithmetic rounds every primitive outward.
3430    let t = lambda
3431        .mul(ClosedInterval::point(penalty))
3432        .div_positive(ClosedInterval::point(gram))
3433        .nonnegative();
3434    let scale = ClosedInterval::point(projected_square)
3435        .div_positive(ClosedInterval::point(gram))
3436        .nonnegative();
3437    let kernels = kernel_ranges(t);
3438    Ok(ModeRanges {
3439        c: kernels.v,
3440        w: kernels.w,
3441        v: scale.mul(kernels.v).nonnegative(),
3442        smoothing_increment: scale.mul(kernels.u).nonnegative(),
3443        singular_fitted: ClosedInterval::point(0.0),
3444        p: scale.mul(kernels.w).nonnegative(),
3445        q: scale.mul(kernels.k),
3446        determinant_third: kernels.k,
3447        residual_third: scale.mul(kernels.third),
3448    })
3449}
3450
3451#[derive(Clone, Copy)]
3452struct KernelRanges {
3453    /// `1/(1+t)`.
3454    v: ClosedInterval,
3455    /// `t/(1+t)`.
3456    u: ClosedInterval,
3457    /// `t/(1+t)^2`.
3458    w: ClosedInterval,
3459    /// `t(1-t)/(1+t)^3`.
3460    k: ClosedInterval,
3461    /// `t(1 - 4t + t^2)/(1+t)^4`, the rho-derivative of `k`.
3462    ///
3463    /// With `dt/drho = t`, differentiating `k` once more gives
3464    /// `t * dk/dt`, and `dk/dt = (1 - 4t + t^2)/(1+t)^4` because
3465    /// `k = (t - t^2)(1+t)^-3`. It is the third rho-derivative of a mode's
3466    /// fitted fraction (up to the scale `A/g`), which is what the residual
3467    /// block's `(log R)'''` is built from.
3468    ///
3469    /// Checked against finite differences of `q/(g + e^rho s)` in rho at
3470    /// `rho = -2, -0.5, 0.3, 1.7`: agreement to five significant figures at
3471    /// `h = 1e-2`, which is that FD's own `O(h^2)` truncation. The determinant's
3472    /// third derivative needed no new kernel at all — `u(1-u)(1-2u)` is
3473    /// `t(1-t)/(1+t)^3`, exactly `k` — and was checked the same way.
3474    third: ClosedInterval,
3475}
3476
3477fn kernel_at(t: ClosedInterval) -> KernelRanges {
3478    let one = ClosedInterval::point(1.0);
3479    let denom = one.add(t);
3480    let v = one.div_positive(denom).nonnegative();
3481    let u = t.mul(v).nonnegative();
3482    let w = u.mul(v).nonnegative();
3483    let k = w.mul(one.sub(t)).div_positive(denom);
3484    // `t(1 - 4t + t^2)/(1+t)^4 = w * (1 - 4t + t^2)/(1+t)^2`. The numerator is
3485    // signed, which `mul` handles; the denominator is a square of a strictly
3486    // positive interval.
3487    let third = w
3488        .mul(one.sub(t.scale(4.0)).add(t.square()))
3489        .div_positive(denom.square());
3490    KernelRanges { v, u, w, k, third }
3491}
3492
3493fn kernel_ranges(t: ClosedInterval) -> KernelRanges {
3494    let left = kernel_at(ClosedInterval::point(t.lo));
3495    let right = kernel_at(ClosedInterval::point(t.hi));
3496    let mut v = ClosedInterval::new(right.v.lo, left.v.hi).nonnegative();
3497    let u = ClosedInterval::new(left.u.lo, right.u.hi).nonnegative();
3498    let mut w = left.w.hull(right.w).nonnegative();
3499    let mut k = left.k.hull(right.k);
3500    let mut third = left.third.hull(right.third);
3501
3502    if t.contains(1.0) {
3503        let critical = kernel_at(ClosedInterval::point(1.0));
3504        w = w.hull(critical.w).nonnegative();
3505        // `d/dt [t(1-4t+t^2)/(1+t)^4] = (1 - 11t + 11t^2 - t^3)/(1+t)^5`, and
3506        // `t^3 - 11t^2 + 11t - 1 = (t-1)(t^2 - 10t + 1)`, so `t = 1` is one of
3507        // this kernel's three critical points as well.
3508        third = third.hull(critical.third);
3509    }
3510
3511    // k'(t) has its only positive roots at 2 +/- sqrt(3).  Enclose sqrt(3)
3512    // itself before subtraction/addition so the exact irrational critical
3513    // points are not lost to nearest-rounded scalar arithmetic.
3514    let sqrt_three =
3515        certified_sqrt_positive(3.0).expect("three is a finite positive square-root argument");
3516    let critical_points = [
3517        ClosedInterval::point(2.0).sub(sqrt_three),
3518        ClosedInterval::point(2.0).add(sqrt_three),
3519    ];
3520    for critical in critical_points {
3521        if critical.hi >= t.lo && critical.lo <= t.hi {
3522            k = k.hull(kernel_at(critical).k);
3523        }
3524    }
3525
3526    // The remaining two roots of `t^2 - 10t + 1` are `5 +/- 2 sqrt(6)`,
3527    // enclosed before the addition so the exact irrationals survive.
3528    let sqrt_six =
3529        certified_sqrt_positive(6.0).expect("six is a finite positive square-root argument");
3530    let two_sqrt_six = sqrt_six.scale(2.0);
3531    for critical in [
3532        ClosedInterval::point(5.0).sub(two_sqrt_six),
3533        ClosedInterval::point(5.0).add(two_sqrt_six),
3534    ] {
3535        if critical.hi >= t.lo && critical.lo <= t.hi {
3536            third = third.hull(kernel_at(critical).third);
3537        }
3538    }
3539
3540    // Monotonicity gives tighter endpoint ranges than a dependency-heavy
3541    // interval evaluation, but retain outward endpoint arithmetic.
3542    v.lo = v.lo.max(0.0);
3543    v.hi = v.hi.min(next_up(1.0));
3544    KernelRanges {
3545        v,
3546        u,
3547        w,
3548        k,
3549        third,
3550    }
3551}
3552
3553const LOG_SERIES_TERMS: usize = 18;
3554const EXP_SERIES_TERMS: usize = 18;
3555const EXP_RANGE_SQUARINGS: usize = 6;
3556
3557fn certified_sqrt_positive(value: f64) -> Option<ClosedInterval> {
3558    if !(value.is_finite() && value > 0.0) {
3559        return None;
3560    }
3561    // `sqrt` supplies only a starting guess. Directed squaring proves and, if
3562    // necessary, expands the two sides, so no platform sqrt accuracy contract
3563    // is a premise of the returned interval.
3564    let guess = value.sqrt();
3565    if !(guess.is_finite() && guess > 0.0) {
3566        return None;
3567    }
3568    let mut lo = next_down(guess);
3569    for _ in 0..8 {
3570        if ClosedInterval::point(lo).square().hi <= value {
3571            break;
3572        }
3573        lo = next_down(lo);
3574    }
3575    let mut hi = next_up(guess);
3576    for _ in 0..8 {
3577        if ClosedInterval::point(hi).square().lo >= value {
3578            break;
3579        }
3580        hi = next_up(hi);
3581    }
3582    (ClosedInterval::point(lo).square().hi <= value
3583        && ClosedInterval::point(hi).square().lo >= value)
3584        .then(|| ClosedInterval::new(lo, hi))
3585}
3586
3587/// `2·atanh(z)` by its positive odd-power series, with the omitted tail
3588/// bounded geometrically. The caller supplies `|z| <= 1/3`.
3589fn certified_log_from_atanh(z: ClosedInterval) -> ClosedInterval {
3590    let z_abs = z.max_abs();
3591    assert!(z_abs <= 1.0 / 3.0 + f64::EPSILON);
3592    let z2 = z.square();
3593    let mut power = z;
3594    let mut sum = z;
3595    for term in 1..LOG_SERIES_TERMS {
3596        power = power.mul(z2);
3597        sum = sum.add(power.div_positive(ClosedInterval::point((2 * term + 1) as f64)));
3598    }
3599    let next_power = power.mul(z2).max_abs();
3600    let first_denominator = (2 * LOG_SERIES_TERMS + 1) as f64;
3601    let geometric_denominator = next_down(1.0 - next_up(z_abs * z_abs));
3602    let tail = if geometric_denominator > 0.0 {
3603        next_up(next_up(2.0 * next_power) / next_down(first_denominator * geometric_denominator))
3604    } else {
3605        f64::INFINITY
3606    };
3607    sum.scale(2.0).widen(tail)
3608}
3609
3610fn certified_ln_two() -> ClosedInterval {
3611    static LN_TWO: OnceLock<ClosedInterval> = OnceLock::new();
3612    *LN_TWO.get_or_init(|| {
3613        // ln(2) = 2 atanh(1/3). Both the rational 1/3 and the series are
3614        // evaluated with directed IEEE basic operations; no platform libm
3615        // result participates in this constant.
3616        let third = ClosedInterval::point(1.0).div_positive(ClosedInterval::point(3.0));
3617        certified_log_from_atanh(third)
3618    })
3619}
3620
3621/// Exact decomposition `value = mantissa * 2^exponent` with
3622/// `mantissa in [1, 2)` for every positive finite binary64 value.
3623fn positive_binary64_parts(value: f64) -> Option<(f64, i32)> {
3624    if !(value.is_finite() && value > 0.0) {
3625        return None;
3626    }
3627    let bits = value.to_bits();
3628    let exponent_bits = ((bits >> 52) & 0x7ff) as i32;
3629    let fraction = bits & ((1_u64 << 52) - 1);
3630    if exponent_bits == 0 {
3631        // value = fraction*2^-1074. Normalize the integer significand into
3632        // [2^52,2^53), then install it under exponent zero.
3633        let highest = 63_i32 - fraction.leading_zeros() as i32;
3634        let normalized = fraction << (52 - highest);
3635        let mantissa_bits = (1023_u64 << 52) | (normalized - (1_u64 << 52));
3636        Some((f64::from_bits(mantissa_bits), highest - 1074))
3637    } else {
3638        let mantissa_bits = (1023_u64 << 52) | fraction;
3639        Some((f64::from_bits(mantissa_bits), exponent_bits - 1023))
3640    }
3641}
3642
3643/// Rigorous exact-real enclosure of `ln(value)` for every finite positive
3644/// binary64 input, including subnormals.
3645///
3646/// Bit decomposition writes `value = m·2^k` exactly with `m in [1,2)`.
3647/// `ln(m) = 2·atanh((m-1)/(m+1))` then has `z in [0,1/3]`, so the fixed
3648/// positive series above has a closed geometric remainder. Only directed
3649/// binary64 basic operations are used.
3650pub fn certified_ln_positive(value: f64) -> Option<ClosedInterval> {
3651    if !(value.is_finite() && value > 0.0) {
3652        return None;
3653    }
3654    if value == 1.0 {
3655        return Some(ClosedInterval::point(0.0));
3656    }
3657    let (mantissa, exponent) = positive_binary64_parts(value)?;
3658    let m = ClosedInterval::point(mantissa);
3659    let z = m
3660        .sub(ClosedInterval::point(1.0))
3661        .div_positive(m.add(ClosedInterval::point(1.0)));
3662    Some(certified_log_from_atanh(z).add(certified_ln_two().scale(exponent as f64)))
3663}
3664
3665/// Rigorous exact-real enclosure of `ln(1+value)`.
3666///
3667/// The nonnegative lane used by the affine score evaluates
3668/// `2·atanh(value/(2+value))` directly when `value <= 1`, preserving tiny
3669/// `value` without the rounded `1+value` cancellation. For larger values the
3670/// exact identity `ln(1+x) = ln(x) + ln(1+1/x)` keeps the atanh argument below
3671/// `1/3` and avoids overflow in `1+x`. Negative valid inputs route through the
3672/// certified positive logarithm of an outward `1+value` interval.
3673pub fn certified_ln_1p(value: f64) -> Option<ClosedInterval> {
3674    if !(value.is_finite() && value > -1.0) {
3675        return None;
3676    }
3677    if value == 0.0 {
3678        return Some(ClosedInterval::point(0.0));
3679    }
3680    if (0.0..=1.0).contains(&value) {
3681        let x = ClosedInterval::point(value);
3682        let z = x.div_positive(ClosedInterval::point(2.0).add(x));
3683        return Some(certified_log_from_atanh(z));
3684    }
3685    if value > 1.0 {
3686        let reciprocal = ClosedInterval::point(1.0)
3687            .div_positive(ClosedInterval::point(value))
3688            .nonnegative();
3689        let z = reciprocal
3690            .div_positive(ClosedInterval::point(2.0).add(reciprocal))
3691            .nonnegative();
3692        return Some(certified_ln_positive(value)?.add(certified_log_from_atanh(z)));
3693    }
3694    let argument = ClosedInterval::point(1.0).add(ClosedInterval::point(value));
3695    if !(argument.lo > 0.0) {
3696        return None;
3697    }
3698    let lo = certified_ln_positive(argument.lo)?;
3699    let hi = certified_ln_positive(argument.hi)?;
3700    Some(ClosedInterval::new(lo.lo, hi.hi))
3701}
3702
3703fn exact_power_of_two(exponent: i32) -> Option<f64> {
3704    match exponent {
3705        -1074..=-1023 => {
3706            let bit = (exponent + 1074) as u32;
3707            Some(f64::from_bits(1_u64 << bit))
3708        }
3709        -1022..=1023 => Some(f64::from_bits(((exponent + 1023) as u64) << 52)),
3710        _ => None,
3711    }
3712}
3713
3714/// Stable rounded representative of `numerator/(first*second)`.
3715///
3716/// Exact binary exponent extraction prevents the denominator product from
3717/// underflowing or overflowing before its scale cancels against the numerator.
3718/// Only two mantissa divisions and the final binary scaling round.
3719fn positive_ratio_over_product(
3720    numerator: f64,
3721    first_denominator: f64,
3722    second_denominator: f64,
3723) -> Option<f64> {
3724    if numerator == 0.0 {
3725        return Some(0.0);
3726    }
3727    let (numerator_mantissa, numerator_exponent) = positive_binary64_parts(numerator)?;
3728    let (first_mantissa, first_exponent) = positive_binary64_parts(first_denominator)?;
3729    let (second_mantissa, second_exponent) = positive_binary64_parts(second_denominator)?;
3730    let mut mantissa = numerator_mantissa / first_mantissa / second_mantissa;
3731    let mut exponent = numerator_exponent - first_exponent - second_exponent;
3732    if !(mantissa.is_finite() && mantissa > 0.0) {
3733        return None;
3734    }
3735    while mantissa < 1.0 {
3736        mantissa *= 2.0;
3737        exponent -= 1;
3738    }
3739    while mantissa >= 2.0 {
3740        mantissa *= 0.5;
3741        exponent += 1;
3742    }
3743    if exponent < -1075 {
3744        return Some(0.0);
3745    }
3746    if exponent > 1023 {
3747        return None;
3748    }
3749    let value = if exponent == -1075 {
3750        (0.5 * mantissa) * exact_power_of_two(-1074)?
3751    } else {
3752        mantissa * exact_power_of_two(exponent)?
3753    };
3754    (value.is_finite() && value >= 0.0).then_some(value)
3755}
3756
3757/// Rigorous exact-real enclosure of `exp(value)` for a finite binary64 input.
3758///
3759/// Range reduction uses the independently certified `ln(2)` interval:
3760/// `value = k ln(2) + r`. After six exact halvings, `|r/64| < 1/16`; a fixed
3761/// Taylor polynomial encloses `exp(r/64)` and a geometric bound encloses its
3762/// positive tail. Six interval squarings and multiplication by the exact
3763/// binary power `2^k` restore the result. Subnormal outputs remain intervals
3764/// with an absolute (possibly zero) lower endpoint instead of being forced
3765/// through an invalid relative-error model.
3766pub fn certified_exp(value: f64) -> Option<ClosedInterval> {
3767    if !value.is_finite() {
3768        return None;
3769    }
3770    if value == 0.0 {
3771        return Some(ClosedInterval::point(1.0));
3772    }
3773    // This quotient merely chooses an integer identity; its accuracy is not a
3774    // proof premise because `r = value-k·ln(2)` is subsequently enclosed using
3775    // the certified ln(2) interval and validated below.
3776    let mut exponent = (value / std::f64::consts::LN_2).round() as i32;
3777    exponent = exponent.clamp(-1074, 1023);
3778    let remainder = ClosedInterval::point(value).sub(certified_ln_two().scale(exponent as f64));
3779    if !(remainder.is_valid() && remainder.max_abs() < 4.0) {
3780        return None;
3781    }
3782    let reduction = (1_u64 << EXP_RANGE_SQUARINGS) as f64;
3783    let reduced = remainder.scale(1.0 / reduction);
3784    if !(reduced.max_abs() < 1.0 / 16.0) {
3785        return None;
3786    }
3787    let mut term = ClosedInterval::point(1.0);
3788    let mut sum = term;
3789    for degree in 1..=EXP_SERIES_TERMS {
3790        term = term
3791            .mul(reduced)
3792            .div_positive(ClosedInterval::point(degree as f64));
3793        sum = sum.add(term);
3794    }
3795    let z = reduced.max_abs();
3796    let first_omitted = next_up(term.max_abs() * z / (EXP_SERIES_TERMS + 1) as f64);
3797    // Every later term ratio is at most z, so a geometric majorant is valid.
3798    let tail = next_up(first_omitted / next_down(1.0 - z));
3799    let mut result = sum.widen(tail);
3800    for _ in 0..EXP_RANGE_SQUARINGS {
3801        result = result.square();
3802    }
3803    result = result.mul(ClosedInterval::point(exact_power_of_two(exponent)?));
3804    Some(result.nonnegative())
3805}
3806
3807#[inline]
3808fn certified_midpoint(interval: ClosedInterval) -> f64 {
3809    let midpoint = interval.lo + 0.5 * (interval.hi - interval.lo);
3810    midpoint.max(interval.lo).min(interval.hi)
3811}
3812
3813/// Deterministic representative of [`certified_exp`].
3814///
3815/// This midpoint is for downstream floating-point evaluation only; callers
3816/// needing a proof must retain the full enclosure returned by
3817/// [`certified_exp`].
3818#[inline]
3819pub fn certified_exp_representative(value: f64) -> Option<f64> {
3820    certified_exp(value).map(certified_midpoint)
3821}
3822
3823#[inline]
3824fn certified_ln_value(value: f64) -> Option<f64> {
3825    certified_ln_positive(value).map(certified_midpoint)
3826}
3827
3828#[inline]
3829fn certified_ln_1p_value(value: f64) -> Option<f64> {
3830    certified_ln_1p(value).map(certified_midpoint)
3831}
3832
3833fn interval_diameter(interval: ClosedInterval) -> f64 {
3834    if interval.lo == interval.hi {
3835        0.0
3836    } else {
3837        next_up(interval.hi - interval.lo)
3838    }
3839}
3840
3841fn log_series_tail_max() -> f64 {
3842    let z = next_up(1.0 / 3.0);
3843    let z2 = next_up(z * z);
3844    let mut power = z;
3845    for _ in 1..LOG_SERIES_TERMS {
3846        power = next_up(power * z2);
3847    }
3848    power = next_up(power * z2);
3849    let denominator = next_down((2 * LOG_SERIES_TERMS + 1) as f64 * next_down(1.0 - z2));
3850    next_up(next_up(2.0 * power) / denominator)
3851}
3852
3853/// Uniform absolute remainder of the reduced exponential Taylor series on
3854/// `[-1/16, 1/16]`, propagated through the six restoring squarings as a
3855/// relative error. This is computed only with outward basic arithmetic.
3856fn exp_series_relative_tail_max() -> f64 {
3857    let z = next_up(1.0 / 16.0);
3858    let mut term = 1.0;
3859    for degree in 1..=EXP_SERIES_TERMS {
3860        term = next_up(next_up(term * z) / degree as f64);
3861    }
3862    let first_omitted = next_up(next_up(term * z) / (EXP_SERIES_TERMS + 1) as f64);
3863    let absolute_tail = next_up(first_omitted / next_down(1.0 - z));
3864    // exp(reduced) >= exp(-1/16) > 1/2, hence its relative error is at most
3865    // twice the absolute Taylor tail. Raising the reduced result to 64 raises
3866    // the multiplicative error factor to the same power.
3867    let mut factor =
3868        ClosedInterval::point(1.0).add(ClosedInterval::point(next_up(2.0 * absolute_tail)));
3869    for _ in 0..EXP_RANGE_SQUARINGS {
3870        factor = factor.square();
3871    }
3872    next_up(factor.hi - 1.0).max(0.0)
3873}
3874
3875/// Uniform forward-error bound for the midpoint returned by
3876/// [`certified_ln_value`] over a positive input interval.
3877fn certified_log_forward_error(input: ClosedInterval) -> f64 {
3878    if !(input.lo > 0.0 && input.hi.is_finite()) {
3879        return f64::INFINITY;
3880    }
3881    let exponent_abs = [input.lo, input.hi]
3882        .into_iter()
3883        .map(|value| {
3884            let bits = value.to_bits();
3885            let exponent_bits = ((bits >> 52) & 0x7ff) as i32;
3886            if exponent_bits == 0 {
3887                let fraction = bits & ((1_u64 << 52) - 1);
3888                let highest = 63_i32 - fraction.leading_zeros() as i32;
3889                (highest - 1074).unsigned_abs() as f64
3890            } else {
3891                (exponent_bits - 1023).unsigned_abs() as f64
3892            }
3893        })
3894        .fold(0.0_f64, f64::max);
3895    let ln_two_uncertainty = next_up(exponent_abs * interval_diameter(certified_ln_two()));
3896    // Per term: power multiply, division, and accumulation, with two directed
3897    // endpoints; the remainder and range-combination path add 32 operations.
3898    let mantissa_ops = 6 * LOG_SERIES_TERMS + 32;
3899    let mantissa_error =
3900        add_nonnegative_upward(wilkinson_roundoff(1.0, mantissa_ops), log_series_tail_max());
3901    add_nonnegative_upward(ln_two_uncertainty, mantissa_error)
3902}
3903
3904fn certified_log_error_from_output(output: ClosedInterval) -> f64 {
3905    if !output.is_valid() {
3906        return f64::INFINITY;
3907    }
3908    // |ln(input)|/ln(2) bounds the binary exponent to one neighboring bin.
3909    let exponent_abs = next_up(output.max_abs() / certified_ln_two().lo.abs()).ceil() + 1.0;
3910    let ln_two_uncertainty = next_up(exponent_abs * interval_diameter(certified_ln_two()));
3911    let mantissa_ops = 6 * LOG_SERIES_TERMS + 32;
3912    add_nonnegative_upward(
3913        ln_two_uncertainty,
3914        add_nonnegative_upward(wilkinson_roundoff(1.0, mantissa_ops), log_series_tail_max()),
3915    )
3916}
3917
3918fn certified_ln1p_forward_error() -> f64 {
3919    let operations = 6 * LOG_SERIES_TERMS + 36;
3920    add_nonnegative_upward(wilkinson_roundoff(1.0, operations), log_series_tail_max())
3921}
3922
3923/// Uniform absolute forward-error bound for [`certified_exp_representative`] on an
3924/// input interval, including range-reduction uncertainty and gradual
3925/// underflow.
3926fn certified_exp_forward_error(input: ClosedInterval, output: ClosedInterval) -> f64 {
3927    if !(input.is_valid() && output.is_valid() && output.lo >= 0.0) {
3928        return f64::INFINITY;
3929    }
3930    let exponent_abs = next_up(input.max_abs() / certified_ln_two().lo).ceil() + 1.0;
3931    let reduction_error = next_up(exponent_abs * interval_diameter(certified_ln_two()));
3932    if !(reduction_error < 1.0) {
3933        return f64::INFINITY;
3934    }
3935    // exp(delta)-1 <= delta/(1-delta) for 0 <= delta < 1.
3936    let propagated_reduction =
3937        next_up(output.max_abs() * reduction_error / next_down(1.0 - reduction_error));
3938    // Taylor recurrence, remainder, six squarings, and final binary scaling;
3939    // count both directed endpoints of each basic operation.
3940    let operations = 6 * EXP_SERIES_TERMS + 4 * EXP_RANGE_SQUARINGS + 40;
3941    let arithmetic = wilkinson_roundoff(output.max_abs(), operations);
3942    let truncation = next_up(output.max_abs() * exp_series_relative_tail_max());
3943    add_nonnegative_upward(
3944        propagated_reduction,
3945        add_nonnegative_upward(arithmetic, truncation),
3946    )
3947}
3948
3949/// Uniform relative forward-error bound for
3950/// [`certified_exp_representative`] on an input interval whose exponential is
3951/// certified strictly positive.
3952///
3953/// The absolute bound above scales every multiplicative contribution by the
3954/// largest output in the interval. Dividing that result by the smallest output
3955/// couples opposite endpoints and can overflow on a wide interval even though
3956/// exp has a finite scale-independent relative error. Keep the range-reduction,
3957/// arithmetic, and truncation terms in relative currency instead. Only gradual
3958/// underflow is genuinely additive, so only that allowance is divided by the
3959/// certified positive lower output.
3960fn certified_exp_relative_forward_error(input: ClosedInterval, output: ClosedInterval) -> f64 {
3961    if !(input.is_valid() && output.is_valid() && output.lo > 0.0 && output.hi.is_finite()) {
3962        return f64::INFINITY;
3963    }
3964    let exponent_abs = next_up(input.max_abs() / certified_ln_two().lo).ceil() + 1.0;
3965    let reduction_error = next_up(exponent_abs * interval_diameter(certified_ln_two()));
3966    if !(reduction_error < 1.0) {
3967        return f64::INFINITY;
3968    }
3969    let relative_reduction = next_up(reduction_error / next_down(1.0 - reduction_error));
3970    let operations = 6 * EXP_SERIES_TERMS + 4 * EXP_RANGE_SQUARINGS + 40;
3971    let relative_arithmetic = wilkinson_roundoff(1.0, operations);
3972    let relative_underflow = next_up(wilkinson_roundoff(0.0, operations) / output.lo);
3973    add_nonnegative_upward(
3974        relative_reduction,
3975        add_nonnegative_upward(
3976            relative_arithmetic,
3977            add_nonnegative_upward(exp_series_relative_tail_max(), relative_underflow),
3978        ),
3979    )
3980}
3981
3982/// Upward-rounded accumulation of a nonnegative magnitude bound.
3983fn add_nonnegative_upward(accumulator: f64, term: f64) -> f64 {
3984    if accumulator == f64::INFINITY || term == f64::INFINITY {
3985        f64::INFINITY
3986    } else if term == 0.0 {
3987        accumulator
3988    } else {
3989        next_up(accumulator + term)
3990    }
3991}
3992
3993/// Symmetric absolute radius needed to widen `mathematical` until it contains
3994/// the already-computed `resolved` interval.
3995fn enclosure_excess(mathematical: ClosedInterval, resolved: ClosedInterval) -> f64 {
3996    let lower = if mathematical.lo == resolved.lo {
3997        0.0
3998    } else {
3999        next_up(mathematical.lo - resolved.lo)
4000    };
4001    let upper = if mathematical.hi == resolved.hi {
4002        0.0
4003    } else {
4004        next_up(resolved.hi - mathematical.hi)
4005    };
4006    lower.max(upper).max(0.0)
4007}
4008
4009/// Wilkinson forward-error bound for `k` round-to-nearest binary64
4010/// operations. The normal-range `gamma_k * magnitude` term is accompanied by
4011/// `k` minimum-subnormal units, covering gradual-underflow roundoff where a
4012/// purely relative model is invalid.
4013fn wilkinson_roundoff(magnitude: f64, operations: usize) -> f64 {
4014    if operations == 0 {
4015        return 0.0;
4016    }
4017    if !(magnitude.is_finite() && magnitude >= 0.0) {
4018        return f64::INFINITY;
4019    }
4020    // Convert the integer count upward before either product. For counts above
4021    // 2^53, `as f64` can round down; charging only one ulp after multiplication
4022    // would then combine two rounding steps into an unjustified one-step
4023    // bound.
4024    let operation_count = next_up(operations as f64);
4025    let underflow = next_up(operation_count * f64::from_bits(1));
4026    if magnitude == 0.0 {
4027        return underflow;
4028    }
4029    // IEEE-754 binary64 unit roundoff under round-to-nearest.
4030    let unit_roundoff = 0.5 * f64::EPSILON;
4031    let ku = next_up(operation_count * unit_roundoff);
4032    if !(ku < 1.0) {
4033        return f64::INFINITY;
4034    }
4035    let denominator = next_down(1.0 - ku);
4036    if !(denominator > 0.0) {
4037        return f64::INFINITY;
4038    }
4039    let gamma = next_up(ku / denominator);
4040    add_nonnegative_upward(next_up(gamma * magnitude), underflow)
4041}
4042
4043#[inline]
4044fn sum_down(left: f64, right: f64) -> f64 {
4045    let value = left + right;
4046    if sum_is_exact(left, right, value) {
4047        value
4048    } else {
4049        next_down(value)
4050    }
4051}
4052
4053#[inline]
4054fn sum_up(left: f64, right: f64) -> f64 {
4055    let value = left + right;
4056    if sum_is_exact(left, right, value) {
4057        value
4058    } else {
4059        next_up(value)
4060    }
4061}
4062
4063/// Whether binary64 addition produced the exact-real sum.
4064///
4065/// Knuth's `TwoSum` residual is itself exact under IEEE round-to-nearest with
4066/// gradual underflow. Besides avoiding needless interval inflation, retaining
4067/// exact cancellation is semantically important: structural zeros in diffuse
4068/// covariance recurrences must remain `[0, 0]`, not become artificial
4069/// minimum-subnormal uncertainty.
4070#[inline]
4071fn sum_is_exact(left: f64, right: f64, value: f64) -> bool {
4072    if left == 0.0 || right == 0.0 {
4073        return true;
4074    }
4075    if !(left.is_finite() && right.is_finite() && value.is_finite()) {
4076        return value == left || value == right;
4077    }
4078    let virtual_right = value - left;
4079    let virtual_left = value - virtual_right;
4080    let right_residual = right - virtual_right;
4081    let left_residual = left - virtual_left;
4082    left_residual + right_residual == 0.0
4083}
4084
4085#[inline]
4086fn product_is_exact(left: f64, right: f64) -> bool {
4087    left == 0.0 || right == 0.0 || left.abs() == 1.0 || right.abs() == 1.0
4088}
4089
4090#[inline]
4091fn product_down(left: f64, right: f64) -> f64 {
4092    let value = left * right;
4093    if product_is_exact(left, right) {
4094        if value.is_nan() { 0.0 } else { value }
4095    } else {
4096        next_down(value)
4097    }
4098}
4099
4100#[inline]
4101fn product_up(left: f64, right: f64) -> f64 {
4102    let value = left * right;
4103    if product_is_exact(left, right) {
4104        if value.is_nan() { 0.0 } else { value }
4105    } else {
4106        next_up(value)
4107    }
4108}
4109
4110#[inline]
4111fn quotient_down(numerator: f64, denominator: f64) -> f64 {
4112    let value = numerator / denominator;
4113    if numerator == 0.0 || denominator.abs() == 1.0 {
4114        value
4115    } else {
4116        next_down(value)
4117    }
4118}
4119
4120#[inline]
4121fn quotient_up(numerator: f64, denominator: f64) -> f64 {
4122    let value = numerator / denominator;
4123    if numerator == 0.0 || denominator.abs() == 1.0 {
4124        value
4125    } else {
4126        next_up(value)
4127    }
4128}
4129
4130/// Next representable number below `value`, used for directed outward
4131/// rounding of interval lower bounds.
4132fn next_down(value: f64) -> f64 {
4133    if value.is_nan() || value == f64::NEG_INFINITY {
4134        return value;
4135    }
4136    if value == 0.0 {
4137        return -f64::from_bits(1);
4138    }
4139    let bits = value.to_bits();
4140    f64::from_bits(if value > 0.0 { bits - 1 } else { bits + 1 })
4141}
4142
4143/// Next representable number above `value`, used for directed outward
4144/// rounding of interval upper bounds.
4145fn next_up(value: f64) -> f64 {
4146    if value.is_nan() || value == f64::INFINITY {
4147        return value;
4148    }
4149    if value == 0.0 {
4150        return f64::from_bits(1);
4151    }
4152    let bits = value.to_bits();
4153    f64::from_bits(if value > 0.0 { bits + 1 } else { bits - 1 })
4154}
4155
4156#[cfg(test)]
4157mod tests {
4158    use super::*;
4159
4160    fn polynomial_hidden_bump_jet(x: f64) -> ScoreJet {
4161        let p = x * (x - 0.5) * (x - 1.0);
4162        let dp = 3.0 * x * x - 3.0 * x + 0.5;
4163        let ddp = 6.0 * x - 3.0;
4164        ScoreJet {
4165            value: x + 1000.0 * p * p,
4166            derivative: 1.0 + 2000.0 * p * dp,
4167            curvature: 2000.0 * (dp * dp + p * ddp),
4168            third: 2000.0 * (3.0 * dp * ddp + p * 6.0),
4169        }
4170    }
4171
4172    fn polynomial_hidden_bump_enclosure(lo: f64, hi: f64) -> DerivativeEnclosure {
4173        let x = ClosedInterval::new(lo, hi);
4174        let p = x
4175            .mul(x.sub(ClosedInterval::point(0.5)))
4176            .mul(x.sub(ClosedInterval::point(1.0)));
4177        let dp = x
4178            .square()
4179            .scale(3.0)
4180            .sub(x.scale(3.0))
4181            .add(ClosedInterval::point(0.5));
4182        let ddp = x.scale(6.0).sub(ClosedInterval::point(3.0));
4183        let value = x.add(p.square().scale(1000.0));
4184        DerivativeEnclosure {
4185            score: ScoreValueEnclosure {
4186                value,
4187                evaluation_error: wilkinson_roundoff(value.max_abs(), 7),
4188            },
4189            derivative: ClosedInterval::point(1.0).add(p.mul(dp).scale(2000.0)),
4190            curvature: dp.square().add(p.mul(ddp)).scale(2000.0),
4191        }
4192    }
4193
4194    #[test]
4195    fn hidden_between_endpoint_and_midpoint_samples_is_found() {
4196        let result = maximize_score_1d(
4197            0.0,
4198            1.0,
4199            1.0e-9,
4200            |x| -> Result<_, String> { Ok(polynomial_hidden_bump_jet(x)) },
4201            |lo, hi| -> Result<_, String> { Ok(polynomial_hidden_bump_enclosure(lo.x, hi.x)) },
4202        )
4203        .expect("certified search");
4204
4205        // At x=0, 1/2, 1 both value and derivative agree exactly with f=x;
4206        // the former midpoint/Hermite heuristic therefore returned x=1.
4207        assert_eq!(polynomial_hidden_bump_jet(0.0).derivative, 1.0);
4208        assert_eq!(polynomial_hidden_bump_jet(0.5).derivative, 1.0);
4209        assert_eq!(polynomial_hidden_bump_jet(1.0).derivative, 1.0);
4210        assert!(result.optimum.x > 0.5 && result.optimum.x < 1.0);
4211        assert!(result.optimum.value > 2.9);
4212        assert!(
4213            result
4214                .stationary_points
4215                .iter()
4216                .any(|point| point.bracket.contains(result.optimum.x)),
4217            "the hidden global maximizer must have a retained root certificate"
4218        );
4219        assert!(
4220            result
4221                .dominated_regions
4222                .iter()
4223                .all(|region| region.score.value.hi < region.incumbent_lower),
4224            "every skipped stationary branch must carry a strict exact dominance proof"
4225        );
4226    }
4227
4228    fn quartic_jet(x: f64) -> ScoreJet {
4229        ScoreJet {
4230            value: -(x * x - 1.0).powi(2),
4231            derivative: 4.0 * x - 4.0 * x * x * x,
4232            curvature: 4.0 - 12.0 * x * x,
4233            third: -24.0 * x,
4234        }
4235    }
4236
4237    fn quartic_enclosure(lo: f64, hi: f64) -> DerivativeEnclosure {
4238        let x = ClosedInterval::new(lo, hi);
4239        let shifted_square = x.square().sub(ClosedInterval::point(1.0));
4240        let value = shifted_square.square().neg();
4241        if lo == hi && (lo == -1.0 || lo == 0.0 || lo == 1.0) {
4242            return DerivativeEnclosure {
4243                score: ScoreValueEnclosure {
4244                    value,
4245                    evaluation_error: wilkinson_roundoff(value.max_abs(), 4),
4246                },
4247                derivative: ClosedInterval::point(0.0),
4248                curvature: ClosedInterval::point(quartic_jet(lo).curvature),
4249            };
4250        }
4251        DerivativeEnclosure {
4252            score: ScoreValueEnclosure {
4253                value,
4254                evaluation_error: wilkinson_roundoff(value.max_abs(), 4),
4255            },
4256            derivative: x.scale(4.0).sub(x.mul(x).mul(x).scale(4.0)),
4257            curvature: ClosedInterval::point(4.0).sub(x.square().scale(12.0)),
4258        }
4259    }
4260
4261    #[test]
4262    fn globally_relevant_roots_are_isolated_and_dominated_structure_is_audited() {
4263        let result = maximize_score_1d(
4264            -2.0,
4265            2.0,
4266            1.0e-10,
4267            |x| -> Result<_, String> { Ok(quartic_jet(x)) },
4268            |lo, hi| -> Result<_, String> { Ok(quartic_enclosure(lo.x, hi.x)) },
4269        )
4270        .expect("certified search");
4271        assert_eq!(
4272            result.stationary_points.len(),
4273            2,
4274            "both equal global maxima must survive strict dominance"
4275        );
4276        for expected in [-1.0_f64, 1.0] {
4277            let point = result
4278                .stationary_points
4279                .iter()
4280                .find(|point| (point.sample.x - expected).abs() <= 1.0e-9)
4281                .unwrap_or_else(|| panic!("missing global maximum at {expected}"));
4282            assert!(point.bracket.hi - point.bracket.lo <= 1.0e-10);
4283        }
4284        assert!(
4285            result
4286                .dominated_regions
4287                .iter()
4288                .any(|region| region.bracket.contains(0.0)),
4289            "the strictly inferior stationary minimum must remain auditable as dominated"
4290        );
4291        assert!((result.optimum.x.abs() - 1.0).abs() <= 1.0e-9);
4292    }
4293
4294    #[test]
4295    fn exact_dominance_prunes_an_uninformative_saturated_tail() {
4296        let mut evaluations = 0_usize;
4297        let result = maximize_score_1d(
4298            -1.0,
4299            10.0,
4300            1.0e-9,
4301            |x| -> Result<_, String> {
4302                evaluations += 1;
4303                Ok(ScoreJet {
4304                    value: 1.0 - x * x,
4305                    derivative: -2.0 * x,
4306                    curvature: -2.0,
4307                    third: 0.0,
4308                })
4309            },
4310            |left, right| -> Result<_, String> {
4311                let x = ClosedInterval::new(left.x, right.x);
4312                let value = ClosedInterval::point(1.0).sub(x.square());
4313                let root_side_cell = right.x <= 1.0;
4314                Ok(DerivativeEnclosure {
4315                    score: ScoreValueEnclosure {
4316                        value,
4317                        evaluation_error: 1.0e-12,
4318                    },
4319                    derivative: if root_side_cell || left.x == right.x {
4320                        x.scale(-2.0)
4321                    } else {
4322                        // This deliberately dependency-heavy extension carries
4323                        // no stationary information in the low-score tail.
4324                        ClosedInterval::new(-100.0, 100.0)
4325                    },
4326                    curvature: if root_side_cell || left.x == right.x {
4327                        ClosedInterval::point(-2.0)
4328                    } else {
4329                        ClosedInterval::new(-100.0, 100.0)
4330                    },
4331                })
4332            },
4333        )
4334        .expect("the exact score incumbent must dominate the uninformative tail");
4335
4336        assert_eq!(result.optimum.x, 0.0);
4337        assert!(result.value_certificate.maximum.contains(1.0));
4338        assert!(
4339            !result.dominated_regions.is_empty(),
4340            "the fixture's saturated tail must be terminated by exact dominance"
4341        );
4342        assert!(
4343            result
4344                .dominated_regions
4345                .iter()
4346                .all(|region| region.score.value.hi < region.incumbent_lower),
4347            "every retained dominance decision must expose its strict exact ordering"
4348        );
4349        assert!(
4350            evaluations < 16,
4351            "the low-score tail was enumerated instead of pruned ({evaluations} evaluations)"
4352        );
4353    }
4354
4355    /// The abscissa at which this fixture's point oracle reports a derivative
4356    /// of exactly zero while the exact derivative is two.
4357    const ROUNDED_ZERO_ABSCISSA: f64 = 1.5;
4358
4359    /// A point derivative that rounds to zero cannot close its parent cell.
4360    ///
4361    /// The exact score is the concave quadratic `1 - (x - 2.5)^2` on `[0, 3]`.
4362    /// Its only stationary point and maximum is exactly representable at
4363    /// `x=2.5`.
4364    /// The point oracle deliberately loses the nonzero derivative at the
4365    /// safeguarded midpoint `x=1.5`, while the exact-real enclosure reports the
4366    /// true derivative range through interval arithmetic. The initial Newton
4367    /// proposal at `x=3` is `2.5`, outside the central-half guard, so the
4368    /// midpoint is exercised deterministically. Treating its rounded scalar
4369    /// zero as a root closes the left half, discards the real maximum, and
4370    /// leaves the rounded-value selection at boundary `x=3`, whose score is
4371    /// `0.75`. The point enclosure introduced by the exact-real repair
4372    /// distinguishes that false zero from the quadratic's exact zero at
4373    /// `x=2.5`.
4374    #[test]
4375    fn a_rounded_zero_at_a_cell_endpoint_does_not_close_the_cell() {
4376        let mut rounded_zeros = 0_usize;
4377        let result = maximize_score_1d(
4378            0.0,
4379            3.0,
4380            1.0e-9,
4381            |x| -> Result<_, String> {
4382                let shifted = x - 2.5;
4383                let derivative = if x == ROUNDED_ZERO_ABSCISSA {
4384                    rounded_zeros += 1;
4385                    0.0
4386                } else {
4387                    -2.0 * shifted
4388                };
4389                Ok(ScoreJet {
4390                    value: 1.0 - shifted * shifted,
4391                    derivative,
4392                    curvature: -2.0,
4393                    third: 0.0,
4394                })
4395            },
4396            |left, right| -> Result<_, String> {
4397                let x = ClosedInterval::new(left.x, right.x);
4398                let shifted = x.sub(ClosedInterval::point(2.5));
4399                let value = ClosedInterval::point(1.0).sub(shifted.square());
4400                Ok(DerivativeEnclosure {
4401                    score: ScoreValueEnclosure {
4402                        value,
4403                        evaluation_error: wilkinson_roundoff(value.max_abs(), 3),
4404                    },
4405                    // Preserve the quadratic's structural zero at x=2.5 instead
4406                    // of manufacturing cancellation through `5 - 2x`.
4407                    derivative: shifted.scale(-2.0),
4408                    curvature: ClosedInterval::point(-2.0),
4409                })
4410            },
4411        )
4412        .expect("certified search");
4413
4414        assert!(
4415            rounded_zeros > 0,
4416            "fixture premise unmet: the search never evaluated x = {ROUNDED_ZERO_ABSCISSA}"
4417        );
4418        assert!(
4419            (result.optimum.x - 2.5).abs() <= 1.0e-9,
4420            "reported the maximum at x={} (value {}) instead of x=2.5",
4421            result.optimum.x,
4422            result.optimum.value,
4423        );
4424        assert!(
4425            result.value_certificate.maximum.contains(1.0),
4426            "the exact maximum escaped the global score certificate: {:?}",
4427            result.value_certificate,
4428        );
4429        assert!(
4430            result
4431                .stationary_points
4432                .iter()
4433                .all(|point| point.sample.x != ROUNDED_ZERO_ABSCISSA),
4434            "a derivative that rounded to zero was reported as a stationary point",
4435        );
4436        let root = result
4437            .stationary_points
4438            .iter()
4439            .find(|point| point.bracket.contains(2.5))
4440            .expect("the exact quadratic root must be isolated");
4441        assert_eq!(
4442            root.bracket,
4443            ClosedInterval::point(2.5),
4444            "the cancellation-free point enclosure must preserve the exact dyadic root"
4445        );
4446    }
4447
4448    #[test]
4449    fn adjacent_cell_evidence_is_retained_when_point_derivative_is_uninformative() {
4450        let planted = 0.7_f64;
4451        let result = maximize_score_1d(
4452            0.0,
4453            1.0,
4454            1.0e-9,
4455            |x| -> Result<_, String> {
4456                let shifted = x - planted;
4457                Ok(ScoreJet {
4458                    value: 1.0 - shifted * shifted,
4459                    derivative: -2.0 * shifted,
4460                    curvature: -2.0,
4461                    third: 0.0,
4462                })
4463            },
4464            |left, right| -> Result<_, String> {
4465                let x = ClosedInterval::new(left.x, right.x);
4466                let shifted = x.sub(ClosedInterval::point(planted));
4467                let value = ClosedInterval::point(1.0).sub(shifted.square());
4468                let interior_point = left.x == right.x && left.x > 0.0 && left.x < 1.0;
4469                Ok(DerivativeEnclosure {
4470                    score: ScoreValueEnclosure {
4471                        value,
4472                        evaluation_error: wilkinson_roundoff(value.max_abs(), 3),
4473                    },
4474                    // Model a cancellation-heavy degenerate-cell formula: by
4475                    // itself it carries no sign. Each adjacent nondegenerate
4476                    // interval remains a tight exact extension, and their
4477                    // intersection at the shared endpoint isolates the root.
4478                    derivative: if interior_point {
4479                        ClosedInterval::new(-2.0, 2.0)
4480                    } else {
4481                        shifted.scale(-2.0)
4482                    },
4483                    curvature: ClosedInterval::point(-2.0),
4484                })
4485            },
4486        )
4487        .expect("adjacent exact cell evidence must isolate the unique root");
4488
4489        assert!(
4490            (result.optimum.x - planted).abs() <= 1.0e-9,
4491            "selected {}, expected {planted}",
4492            result.optimum.x
4493        );
4494        let stationary = result
4495            .stationary_points
4496            .iter()
4497            .find(|point| point.bracket.contains(planted))
4498            .expect("the planted stationary point must be certified");
4499        assert!(stationary.bracket.hi - stationary.bracket.lo <= 1.0e-9);
4500    }
4501
4502    #[test]
4503    fn interval_newton_stationarity_is_not_preempted_by_a_resolved_score_gap() {
4504        let planted = 0.25;
4505        let resolution = 1.0e-9;
4506        let mut unresolved_root_probes = 0;
4507        let result = maximize_score_1d(
4508            -1.0,
4509            1.0,
4510            resolution,
4511            |x| -> Result<_, String> {
4512                let shifted = x - planted;
4513                Ok(ScoreJet {
4514                    value: 1.0 - shifted * shifted,
4515                    derivative: -2.0 * shifted,
4516                    curvature: -2.0,
4517                    third: 0.0,
4518                })
4519            },
4520            |left, right| -> Result<_, String> {
4521                let shifted = ClosedInterval::new(left.x, right.x)
4522                    .sub(ClosedInterval::point(planted));
4523                let value = ClosedInterval::point(1.0).sub(shifted.square());
4524                // Certified roundoff leaves the derivative's sign unresolved
4525                // at the root, while the interval-Newton image can still pin
4526                // its location much more tightly than the requested width.
4527                let derivative = shifted
4528                    .scale(-2.0)
4529                    .add(ClosedInterval::new(-1.0e-12, 1.0e-12));
4530                if left.x == planted && right.x == planted {
4531                    unresolved_root_probes += 1;
4532                    assert!(derivative.contains_zero());
4533                    assert!(derivative.lo < derivative.hi);
4534                }
4535                Ok(DerivativeEnclosure {
4536                    score: ScoreValueEnclosure {
4537                        value,
4538                        evaluation_error: 1.0e-12,
4539                    },
4540                    derivative,
4541                    curvature: ClosedInterval::point(-2.0),
4542                })
4543            },
4544        )
4545        .expect("the certified Newton image must retain the stationarity proof");
4546        assert!(unresolved_root_probes > 0, "the ambiguous root must be probed");
4547        let ScoreOptimumLocation::Stationary(index) = result.location else {
4548            panic!(
4549                "a resolved Newton root lost its stationarity proof: {:?}",
4550                result.location
4551            );
4552        };
4553        let point = result.stationary_points[index];
4554        assert!(point.bracket.contains(planted));
4555        assert!(point.bracket.hi - point.bracket.lo <= resolution);
4556        assert!(point.curvature.hi < 0.0);
4557        assert!(result.resolution_flat_regions.is_empty());
4558    }
4559
4560    #[test]
4561    fn signed_endpoint_newton_reaches_the_existing_score_resolution_floor() {
4562        let planted = 0.8_f64;
4563        let ambiguous_probe = 0.5_f64;
4564        let mut ambiguous_probe_calls = 0_usize;
4565        let result = maximize_score_1d(
4566            0.0,
4567            1.0,
4568            1.0e-9,
4569            |x| -> Result<_, String> {
4570                let shifted = x - planted;
4571                Ok(ScoreJet {
4572                    value: 1.0 - shifted * shifted,
4573                    derivative: -2.0 * shifted,
4574                    curvature: -2.0,
4575                    third: 0.0,
4576                })
4577            },
4578            |left, right| -> Result<_, String> {
4579                let x = ClosedInterval::new(left.x, right.x);
4580                let shifted = x.sub(ClosedInterval::point(planted));
4581                let value = ClosedInterval::point(1.0).sub(shifted.square());
4582                let derivative = if left.x == right.x {
4583                    if left.x == ambiguous_probe {
4584                        ambiguous_probe_calls += 1;
4585                        ClosedInterval::new(-2.0, 2.0)
4586                    } else {
4587                        ClosedInterval::point(-2.0 * (left.x - planted))
4588                    }
4589                } else {
4590                    // A deliberately dependency-heavy cell extension. It is
4591                    // valid, but neither it nor the ambiguous point image can
4592                    // contract the first midpoint probe.
4593                    ClosedInterval::new(-2.0, 2.0)
4594                };
4595                Ok(DerivativeEnclosure {
4596                    score: ScoreValueEnclosure {
4597                        value,
4598                        // The exact score motion on the first endpoint-Newton
4599                        // image is 0.04. A valid 0.021 point forward-error bound
4600                        // makes that information floor 0.042, while the initial
4601                        // domain's 0.64 score motion remains visibly nonflat.
4602                        evaluation_error: 0.021,
4603                    },
4604                    derivative,
4605                    // Strictly oriented but deliberately wider than the exact
4606                    // constant curvature -2.
4607                    curvature: ClosedInterval::new(-4.0, -1.0),
4608                })
4609            },
4610        )
4611        .expect("signed endpoint Newton images must reach a typed score-resolution proof");
4612
4613        assert!(
4614            ambiguous_probe_calls > 0,
4615            "fixture premise unmet: the cancellation-heavy midpoint was never certified"
4616        );
4617        let ScoreOptimumLocation::ResolutionFlat(index) = result.location else {
4618            panic!(
4619                "the unique root's location is below the declared information floor: {:?}",
4620                result.location
4621            );
4622        };
4623        let flat = result.resolution_flat_regions[index];
4624        assert!(
4625            flat.bracket.contains(planted),
4626            "contracted flat bracket {:?} lost the unique root",
4627            flat.bracket
4628        );
4629        assert!(
4630            flat.max_score_gap <= flat.score_resolution,
4631            "typed flat proof exceeded its existing evaluator floor: {flat:?}"
4632        );
4633        assert!(result.stationary_points.is_empty());
4634    }
4635
4636    #[test]
4637    fn strict_concavity_certifies_the_quintic_scan_optimum_at_score_resolution() {
4638        // The terminal certificate from #2790, seed 0 at n=100. Its score
4639        // range is deliberately wider than pairwise evaluator error, so a
4640        // value-flat test cannot close this cell. Strict concavity says much
4641        // more: despite cancellation in the derivative enclosure, the maximum
4642        // can improve on the represented point by only g^2/(2 mu).
4643        let left = SearchSample {
4644            sample: ScoreSample {
4645                x: -12.105_374_438_144_967,
4646                value: 134.053_351_995_058_96,
4647                derivative: 1.0e-3,
4648                curvature: -1.0,
4649                third: 0.0,
4650            },
4651            point_enclosure: None,
4652        };
4653        let right = SearchSample {
4654            sample: ScoreSample {
4655                x: -12.104_760_848_454_575,
4656                value: 134.054_279_259_553_65,
4657                derivative: -1.0e-3,
4658                curvature: -1.0,
4659                third: 0.0,
4660            },
4661            point_enclosure: None,
4662        };
4663        let sample = ScoreSample {
4664            x: left.sample.x + 0.5 * (right.sample.x - left.sample.x),
4665            value: 134.053_9,
4666            derivative: 0.0,
4667            curvature: -1.0,
4668            third: 0.0,
4669        };
4670        let evaluation_error = 3.966_754_013_333_685e-4;
4671        let point_score = ScoreValueEnclosure {
4672            value: ClosedInterval::point(sample.value),
4673            evaluation_error,
4674        };
4675        let enclosure = DerivativeEnclosure {
4676            score: ScoreValueEnclosure {
4677                value: ClosedInterval::new(134.053_351_995_058_96, 134.054_279_259_553_65),
4678                evaluation_error,
4679            },
4680            derivative: ClosedInterval::new(-1.8562e-3, 1.6607e-3),
4681            curvature: ClosedInterval::new(-2.2666, -0.2358),
4682        };
4683
4684        assert!(
4685            resolution_flat_region(SearchNode { left, right }, enclosure).is_none(),
4686            "fixture premise: the full score diameter exceeds pairwise evaluation error"
4687        );
4688        let (flat, maximum) = score_resolved_concave_maximum(
4689            SearchNode { left, right },
4690            enclosure,
4691            sample,
4692            enclosure.derivative,
4693            enclosure.curvature,
4694            point_score,
4695        )
4696        .expect("strict concavity must close the already score-resolved optimum");
4697        assert!(flat.bracket.contains(sample.x));
4698        assert!(flat.max_score_gap < 7.4e-6);
4699        assert!(flat.max_score_gap <= flat.score_resolution);
4700        assert!(
4701            maximum.value.hi < enclosure.score.value.hi,
4702            "the strong-concavity maximum bound must remove the loose cell-wide score tail"
4703        );
4704    }
4705
4706    #[test]
4707    fn monotone_score_selects_exact_boundary() {
4708        let result = maximize_score_1d(
4709            -4.0,
4710            9.0,
4711            1.0e-9,
4712            |x| -> Result<_, String> {
4713                Ok(ScoreJet {
4714                    value: 0.3 * x,
4715                    derivative: 0.3,
4716                    curvature: 0.0,
4717                    third: 0.0,
4718                })
4719            },
4720            |left, right| -> Result<_, String> {
4721                let value = ClosedInterval::new(left.x, right.x).scale(0.3);
4722                Ok(DerivativeEnclosure {
4723                    score: ScoreValueEnclosure {
4724                        value,
4725                        evaluation_error: wilkinson_roundoff(value.max_abs(), 1),
4726                    },
4727                    derivative: ClosedInterval::point(0.3),
4728                    curvature: ClosedInterval::point(0.0),
4729                })
4730            },
4731        )
4732        .expect("certified search");
4733        assert_eq!(result.location, ScoreOptimumLocation::UpperBoundary);
4734        assert_eq!(result.optimum.x, 9.0);
4735        assert!(result.stationary_points.is_empty());
4736        assert_eq!(
4737            result.value_certificate.maximum_excess, 0.0,
4738            "the exact same terminal point is not a competing uncertain value"
4739        );
4740    }
4741
4742    #[test]
4743    fn certified_increase_selects_upper_boundary_when_rounded_values_tie() {
4744        let result = maximize_score_1d(
4745            -1.0,
4746            1.0,
4747            1.0e-9,
4748            |_| -> Result<_, String> {
4749                Ok(ScoreJet {
4750                    value: 0.0,
4751                    derivative: 1.0,
4752                    curvature: 0.0,
4753                    third: 0.0,
4754                })
4755            },
4756            |left, right| -> Result<_, String> {
4757                Ok(DerivativeEnclosure {
4758                    score: ScoreValueEnclosure {
4759                        value: ClosedInterval::new(left.x, right.x),
4760                        evaluation_error: 1.0,
4761                    },
4762                    derivative: ClosedInterval::point(1.0),
4763                    curvature: ClosedInterval::point(0.0),
4764                })
4765            },
4766        )
4767        .expect("a whole-domain positive derivative orders tied rounded endpoints");
4768        assert_eq!(result.lower_boundary.value, result.upper_boundary.value);
4769        assert_eq!(result.location, ScoreOptimumLocation::UpperBoundary);
4770        assert_eq!(result.optimum.x, 1.0);
4771        assert_eq!(result.value_certificate.maximum_excess, 0.0);
4772    }
4773
4774    #[test]
4775    fn certified_decrease_selects_lower_boundary_when_rounded_values_tie() {
4776        let result = maximize_score_1d(
4777            -1.0,
4778            1.0,
4779            1.0e-9,
4780            |_| -> Result<_, String> {
4781                Ok(ScoreJet {
4782                    value: 0.0,
4783                    derivative: -1.0,
4784                    curvature: 0.0,
4785                    third: 0.0,
4786                })
4787            },
4788            |left, right| -> Result<_, String> {
4789                Ok(DerivativeEnclosure {
4790                    score: ScoreValueEnclosure {
4791                        value: ClosedInterval::new(-right.x, -left.x),
4792                        evaluation_error: 1.0,
4793                    },
4794                    derivative: ClosedInterval::point(-1.0),
4795                    curvature: ClosedInterval::point(0.0),
4796                })
4797            },
4798        )
4799        .expect("a whole-domain negative derivative orders tied rounded endpoints");
4800        assert_eq!(result.lower_boundary.value, result.upper_boundary.value);
4801        assert_eq!(result.location, ScoreOptimumLocation::LowerBoundary);
4802        assert_eq!(result.optimum.x, -1.0);
4803        assert_eq!(result.value_certificate.maximum_excess, 0.0);
4804    }
4805
4806    #[test]
4807    fn tangential_nonmaximum_structure_is_closed_by_exact_dominance() {
4808        let result = maximize_score_1d(
4809            -1.0,
4810            1.0,
4811            1.0e-8,
4812            |x| -> Result<_, String> {
4813                Ok(ScoreJet {
4814                    value: x * x * x,
4815                    derivative: 3.0 * x * x,
4816                    curvature: 6.0 * x,
4817                    third: 6.0,
4818                })
4819            },
4820            |lo, hi| -> Result<_, String> {
4821                let x = ClosedInterval::new(lo.x, hi.x);
4822                Ok(DerivativeEnclosure {
4823                    score: ScoreValueEnclosure {
4824                        value: x.mul(x).mul(x),
4825                        evaluation_error: f64::EPSILON,
4826                    },
4827                    derivative: x.square().scale(3.0),
4828                    curvature: x.scale(6.0),
4829                })
4830            },
4831        )
4832        .expect("the inferior inflection is immaterial by exact score ordering");
4833        assert_eq!(result.location, ScoreOptimumLocation::UpperBoundary);
4834        assert!(
4835            !result.dominated_regions.is_empty(),
4836            "the search must record the exact dominance proof instead of silently dropping the cell"
4837        );
4838        for region in result.dominated_regions {
4839            assert!(region.score.value.hi < region.incumbent_lower);
4840        }
4841    }
4842
4843    #[test]
4844    fn unresolved_nonflat_cell_remains_typed() {
4845        let error = maximize_score_1d(
4846            0.0,
4847            1.0e-8,
4848            1.0e-8,
4849            |x| -> Result<_, String> {
4850                Ok(ScoreJet {
4851                    value: x,
4852                    derivative: 0.0,
4853                    curvature: 0.0,
4854                    third: 0.0,
4855                })
4856            },
4857            |lo, hi| -> Result<_, String> {
4858                Ok(DerivativeEnclosure {
4859                    score: ScoreValueEnclosure {
4860                        value: ClosedInterval::new(lo.x, hi.x),
4861                        evaluation_error: 0.0,
4862                    },
4863                    derivative: ClosedInterval::new(-1.0, 1.0),
4864                    curvature: ClosedInterval::new(-1.0, 1.0),
4865                })
4866            },
4867        )
4868        .expect_err("a derivative enclosure admitting visible score motion is not flat");
4869        assert!(matches!(error, ScoreSearchError::Unresolved { .. }));
4870    }
4871
4872    /// BREADTH exhaustion, which is a different failure from the per-cell depth
4873    /// floor and was #2546's non-termination.
4874    ///
4875    /// The oracle's derivative and curvature enclosures always straddle zero, so
4876    /// no cell is ever excluded by a sign or isolated as a root; but its score
4877    /// range collapses with the cell against a FIXED evaluation error, so every
4878    /// cell does terminate — as resolution-flat — once it is narrower than
4879    /// `2 * evaluation_error`. That is the regime the cascade is in: cells
4880    /// certify, at widths far above `resolution`, and the traversal simply needs
4881    /// too many of them. The flat width here is 1e-3 of a 32-wide domain, so the
4882    /// decomposition is ~2^15 = 32 768 cells and no cell ever reaches the
4883    /// resolution floor — `ScoreSearchError::Unresolved` cannot fire, and
4884    /// without a breadth budget nothing else can either.
4885    ///
4886    /// Contrast `unresolved_nonflat_cell_remains_typed`, whose oracle certifies
4887    /// NOTHING at any width: that one bottoms out on the depth floor after `D`
4888    /// subdivisions and is already typed. The two are not interchangeable.
4889    #[test]
4890    fn undecomposable_criterion_exhausts_the_budget_instead_of_enumerating_the_domain() {
4891        let lo = 0.0;
4892        let hi = 32.0;
4893        let resolution = f64::EPSILON.sqrt();
4894        let flat_error = 5.0e-4;
4895        let (budget, depth_bound) = subdivision_budget(lo, hi, resolution);
4896        assert_eq!(depth_bound, 31, "log2(32 / sqrt(eps)) rounds up to 31");
4897        // Pins the shipped coefficient in `subdivision_budget`, whose doc
4898        // explains why it is 8 and why raising it further only converts a
4899        // budget refusal into a resolution refusal (#2614). This assertion is
4900        // deliberately a change-detector: if the constant moves, update BOTH,
4901        // and read that doc before deciding the move is a fix.
4902        assert_eq!(
4903            budget,
4904            8 * 31 * 31,
4905            "budget must track the 8 D^2 coefficient in subdivision_budget"
4906        );
4907        let error = maximize_score_1d(
4908            lo,
4909            hi,
4910            resolution,
4911            |_| -> Result<_, String> {
4912                Ok(ScoreJet {
4913                    value: 0.0,
4914                    derivative: 0.0,
4915                    curvature: 0.0,
4916                    third: 0.0,
4917                })
4918            },
4919            |left, right| -> Result<_, String> {
4920                let half_width = 0.5 * (right.x - left.x);
4921                Ok(DerivativeEnclosure {
4922                    score: ScoreValueEnclosure {
4923                        value: ClosedInterval::new(-half_width, half_width),
4924                        evaluation_error: flat_error,
4925                    },
4926                    derivative: ClosedInterval::new(-1.0, 1.0),
4927                    curvature: ClosedInterval::new(-1.0, 1.0),
4928                })
4929            },
4930        )
4931        .expect_err("a decomposition this large must refuse, not enumerate");
4932        let ScoreSearchError::SubdivisionBudget {
4933            subdivisions,
4934            budget: reported_budget,
4935            depth_bound: reported_depth,
4936            cell_lo,
4937            cell_hi,
4938            ..
4939        } = error
4940        else {
4941            panic!("expected a subdivision-budget refusal, got {error}");
4942        };
4943        assert_eq!(
4944            subdivisions,
4945            budget + 1,
4946            "the budget stops the split that exceeds it"
4947        );
4948        assert_eq!(reported_budget, budget);
4949        assert_eq!(reported_depth, depth_bound);
4950        assert!(
4951            cell_hi - cell_lo > 2.0 * flat_error,
4952            "the reported cell must be one the search could still have split and \
4953             had not yet certified ({cell_lo}, {cell_hi}); a narrower cell would \
4954             mean the depth floor, not the breadth budget, was binding"
4955        );
4956    }
4957
4958    /// The same budget must be invisible to a search that converges. A strictly
4959    /// concave criterion over the same wide domain isolates its stationary point
4960    /// in subdivisions proportional to the DEPTH, so the number of criterion
4961    /// evaluations stays far below a budget scaled by the depth SQUARED.
4962    #[test]
4963    fn a_converging_search_stays_far_under_the_subdivision_budget() {
4964        let lo = 0.0;
4965        let hi = 32.0;
4966        let resolution = f64::EPSILON.sqrt();
4967        let (budget, depth_bound) = subdivision_budget(lo, hi, resolution);
4968        let evaluations = std::cell::Cell::new(0usize);
4969        let result = maximize_score_1d(
4970            lo,
4971            hi,
4972            resolution,
4973            |x| -> Result<_, String> {
4974                evaluations.set(evaluations.get() + 1);
4975                let shifted = x - 7.0;
4976                Ok(ScoreJet {
4977                    value: -shifted * shifted,
4978                    derivative: -2.0 * shifted,
4979                    curvature: -2.0,
4980                    third: 0.0,
4981                })
4982            },
4983            |left, right| -> Result<_, String> {
4984                let x = ClosedInterval::new(left.x, right.x);
4985                let shifted = x.sub(ClosedInterval::point(7.0));
4986                Ok(DerivativeEnclosure {
4987                    score: ScoreValueEnclosure {
4988                        value: shifted.square().scale(-1.0),
4989                        evaluation_error: f64::EPSILON * 1024.0,
4990                    },
4991                    derivative: shifted.scale(-2.0),
4992                    curvature: ClosedInterval::point(-2.0),
4993                })
4994            },
4995        )
4996        .expect("a strictly concave criterion is decomposable");
4997        let ScoreOptimumLocation::Stationary(index) = result.location else {
4998            panic!("expected the interior maximum, got {:?}", result.location);
4999        };
5000        let bracket = result.stationary_points[index].bracket;
5001        assert!(
5002            bracket.lo <= 7.0 && bracket.hi >= 7.0,
5003            "certified bracket {bracket:?} must contain the planted maximum"
5004        );
5005        // Every subdivision costs one midpoint evaluation, so the evaluation
5006        // count bounds the subdivisions from above.
5007        assert!(
5008            evaluations.get() < budget / 8,
5009            "a converging search used {} evaluations against budget {budget} at depth \
5010             bound {depth_bound}; a budget within 8x of a converging search is a \
5011             tuning parameter, not a backstop",
5012            evaluations.get()
5013        );
5014    }
5015
5016    #[test]
5017    fn resolution_flatness_is_exactly_value_diameter_vs_pairwise_error() {
5018        let sample = SearchSample {
5019            sample: ScoreSample {
5020                x: 0.0,
5021                value: 7.0,
5022                derivative: 0.0,
5023                curvature: 0.0,
5024                third: 0.0,
5025            },
5026            point_enclosure: None,
5027        };
5028        let node = SearchNode {
5029            left: sample,
5030            right: SearchSample {
5031                sample: ScoreSample {
5032                    x: 1.0,
5033                    ..sample.sample
5034                },
5035                point_enclosure: None,
5036            },
5037        };
5038        let error = 0.125;
5039        for (upper, expected) in [(1024.25, true), (next_up(1024.25), false)] {
5040            let enclosure = DerivativeEnclosure {
5041                score: ScoreValueEnclosure {
5042                    // Translation by a large exactly represented constant must
5043                    // not change either side of the flatness comparison.
5044                    value: ClosedInterval::new(1024.0, upper),
5045                    evaluation_error: error,
5046                },
5047                derivative: ClosedInterval::new(-1.0, 1.0),
5048                curvature: ClosedInterval::new(-1.0, 1.0),
5049            };
5050            assert_eq!(
5051                resolution_flat_region(node, enclosure).is_some(),
5052                expected,
5053                "flatness must be equivalent to outward diameter <= outward 2*value error"
5054            );
5055        }
5056    }
5057
5058    #[test]
5059    fn resolution_flat_cells_remain_regions_instead_of_fake_points() {
5060        let resolution = 0.25;
5061        let result = maximize_score_1d(
5062            0.0,
5063            1.0,
5064            resolution,
5065            |_| -> Result<_, String> {
5066                Ok(ScoreJet {
5067                    value: 3.0,
5068                    derivative: 0.0,
5069                    curvature: 0.0,
5070                    third: 0.0,
5071                })
5072            },
5073            |_, _| -> Result<_, String> {
5074                Ok(DerivativeEnclosure {
5075                    score: ScoreValueEnclosure {
5076                        value: ClosedInterval::point(3.0),
5077                        evaluation_error: 0.0,
5078                    },
5079                    derivative: ClosedInterval::new(-1.0, 1.0),
5080                    curvature: ClosedInterval::new(-1.0, 1.0),
5081                })
5082            },
5083        )
5084        .expect("an exactly constant score is resolution-flat");
5085        assert_eq!(result.resolution_flat_regions.len(), 1);
5086        assert!(
5087            result.resolution_flat_regions[0].bracket.hi
5088                - result.resolution_flat_regions[0].bracket.lo
5089                > resolution,
5090            "value resolution may close a wide cell, so callers must not reinterpret it \
5091             as an abscissa-resolved stationary point"
5092        );
5093    }
5094
5095    #[test]
5096    fn directed_arithmetic_preserves_cancellation_and_subnormal_error() {
5097        assert_eq!(
5098            ClosedInterval::point(1.0).sub(ClosedInterval::point(1.0)),
5099            ClosedInterval::point(0.0),
5100            "an exact structural zero must not acquire artificial uncertainty"
5101        );
5102        let minimum_subnormal = f64::from_bits(1);
5103        let underflowing_product =
5104            ClosedInterval::point(minimum_subnormal).mul(ClosedInterval::point(0.5));
5105        assert!(
5106            underflowing_product.lo <= 0.5 * minimum_subnormal
5107                && underflowing_product.hi >= 0.5 * minimum_subnormal
5108                && underflowing_product.lo < 0.0
5109                && underflowing_product.hi > 0.0,
5110            "a nonzero exact product that rounds to zero needs additive subnormal width"
5111        );
5112        assert!(
5113            wilkinson_roundoff(0.0, 1) >= minimum_subnormal,
5114            "a zero-magnitude relative model must still charge additive underflow"
5115        );
5116    }
5117
5118    #[test]
5119    fn certified_elementary_intervals_cover_normal_and_subnormal_lanes() {
5120        for value in [
5121            f64::from_bits(1),
5122            f64::MIN_POSITIVE,
5123            0.5,
5124            1.0,
5125            2.0,
5126            f64::MAX,
5127        ] {
5128            let enclosure = certified_ln_positive(value).expect("certified positive log");
5129            assert!(enclosure.is_valid() && enclosure.lo.is_finite() && enclosure.hi.is_finite());
5130            assert!(
5131                enclosure.contains(value.ln()),
5132                "independent platform log sanity value {} escaped {:?}",
5133                value.ln(),
5134                enclosure
5135            );
5136        }
5137        for value in [-744.0_f64, -708.0, -1.0, 0.0, 1.0, 709.0] {
5138            let enclosure = certified_exp(value).expect("certified exponential");
5139            assert!(enclosure.is_valid() && enclosure.lo >= 0.0);
5140            assert!(
5141                enclosure.contains(value.exp()),
5142                "independent platform exp sanity value {} escaped {:?}",
5143                value.exp(),
5144                enclosure
5145            );
5146        }
5147        for value in [f64::from_bits(1), 1.0e-12, 0.25, 1.0] {
5148            let enclosure = certified_ln_1p(value).expect("certified log1p");
5149            assert!(
5150                enclosure.contains(value.ln_1p()),
5151                "independent platform log1p sanity value {} escaped {:?}",
5152                value.ln_1p(),
5153                enclosure
5154            );
5155        }
5156    }
5157
5158    #[test]
5159    fn exact_range_is_not_compared_to_a_separately_rounded_curvature() {
5160        let denormal = f64::from_bits(1);
5161        let result = maximize_score_1d(
5162            0.0,
5163            1.0,
5164            1.0e-8,
5165            |x| -> Result<_, String> {
5166                Ok(ScoreJet {
5167                    value: x,
5168                    derivative: 1.0,
5169                    // A real negative denormal rounds to signed zero in the
5170                    // point-jet arithmetic represented by this fixture.
5171                    curvature: -0.0,
5172                    third: 0.0,
5173                })
5174            },
5175            |left, right| -> Result<_, String> {
5176                Ok(DerivativeEnclosure {
5177                    score: ScoreValueEnclosure {
5178                        value: ClosedInterval::new(left.x, right.x),
5179                        evaluation_error: 0.0,
5180                    },
5181                    derivative: ClosedInterval::point(1.0),
5182                    curvature: ClosedInterval::point(-denormal),
5183                })
5184            },
5185        )
5186        .expect("an exact-real enclosure need not contain a separately rounded scalar jet");
5187        assert_eq!(result.location, ScoreOptimumLocation::UpperBoundary);
5188    }
5189
5190    fn affine_fixture() -> AffineRemlProfile<'static> {
5191        const G: &[f64] = &[2.0, 0.5, 0.0, 3.0];
5192        const S: &[f64] = &[1.0, 0.0, 2.0, 0.25];
5193        const Q: &[f64] = &[
5194            0.6, 0.1, 0.02, 0.3, // response 0
5195            0.2, 0.4, 0.01, 0.5, // response 1
5196        ];
5197        const Y2: &[f64] = &[8.0, 10.0];
5198        AffineRemlProfile::new(G, S, Q, Y2, 12.0, 3, 0.7).expect("valid fixture")
5199    }
5200
5201    #[test]
5202    fn affine_reml_jet_matches_test_only_differences() {
5203        let profile = affine_fixture();
5204        for x in [-2.0_f64, -0.4, 0.7, 2.0] {
5205            let h = 1.0e-5;
5206            let center = profile.evaluate(x).unwrap();
5207            let left = profile.evaluate(x - h).unwrap();
5208            let right = profile.evaluate(x + h).unwrap();
5209            let derivative = (right.value - left.value) / (2.0 * h);
5210            let curvature = (right.derivative - left.derivative) / (2.0 * h);
5211            assert!(
5212                (center.derivative - derivative).abs() <= 2.0e-8 * (1.0 + derivative.abs()),
5213                "first derivative mismatch at {x}: analytic {}, difference {derivative}",
5214                center.derivative
5215            );
5216            assert!(
5217                (center.curvature - curvature).abs() <= 2.0e-8 * (1.0 + curvature.abs()),
5218                "curvature mismatch at {x}: analytic {}, difference {curvature}",
5219                center.curvature
5220            );
5221        }
5222    }
5223
5224    #[test]
5225    fn affine_reml_enclosure_contains_value_jets() {
5226        let profile = affine_fixture();
5227        let enclosure = profile.enclose(-2.5, 1.75).expect("enclosure");
5228        let score = enclosure.score;
5229        let resolved_score = score.value.widen(score.evaluation_error);
5230        for x in [-2.5_f64, -1.7, -0.3, 0.0, 0.9, 1.75] {
5231            let jet = profile.evaluate(x).unwrap();
5232            let point = profile.enclose(x, x).expect("point enclosure");
5233            assert!(
5234                resolved_score.contains(jet.value),
5235                "score {} at {x} outside {:?} ± {}",
5236                jet.value,
5237                score.value,
5238                score.evaluation_error
5239            );
5240            assert!(
5241                enclosure
5242                    .derivative
5243                    .intersection(point.derivative)
5244                    .is_some(),
5245                "exact point gradient {:?} at {x} is disjoint from {:?}",
5246                point.derivative,
5247                enclosure.derivative
5248            );
5249            assert!(
5250                enclosure.curvature.intersection(point.curvature).is_some(),
5251                "exact point curvature {:?} at {x} is disjoint from {:?}",
5252                point.curvature,
5253                enclosure.curvature
5254            );
5255        }
5256    }
5257
5258    #[test]
5259    fn affine_reml_zero_smoothing_complement_retains_residual_correlation() {
5260        // With E = sum(q/g), the zero-smoothing residual is exactly zero and
5261        //
5262        //   R(lambda) = sum_i (q_i/g_i) * lambda/(1 + lambda).
5263        //
5264        // The determinant and profiled-residual derivatives then cancel
5265        // identically when residual_dof equals the mode count, so the exact
5266        // score derivative is zero. Forming R as
5267        // `E - sum q/(g + lambda*s)` loses the shared near-one factor once per
5268        // mode: at lambda=1e-10 its interval width is large enough to fabricate
5269        // a material derivative range even though every term has the same
5270        // analytic complement. The zero-smoothing form carries that
5271        // correlation explicitly.
5272        const MODES: usize = 64;
5273        let grams = [1.0; MODES];
5274        let penalties = [1.0; MODES];
5275        let projected = [1.0; MODES];
5276        let energies = [MODES as f64];
5277        let profile = AffineRemlProfile::new(
5278            &grams,
5279            &penalties,
5280            &projected,
5281            &energies,
5282            MODES as f64,
5283            MODES,
5284            0.0,
5285        )
5286        .expect("valid cancellation fixture");
5287        let rho = -23.025850929940457_f64; // nearest binary64 to ln(1e-10)
5288        let enclosure = profile
5289            .enclose(rho, rho)
5290            .expect("equivalent residual forms must retain their intersection");
5291
5292        assert!(
5293            enclosure.derivative.contains_zero(),
5294            "the analytically constant profile must contain zero derivative: {:?}",
5295            enclosure.derivative
5296        );
5297        assert!(
5298            enclosure.derivative.hi - enclosure.derivative.lo < 1.0e-6,
5299            "the residual complement must remove the independent near-one dependency: {:?}",
5300            enclosure.derivative
5301        );
5302    }
5303
5304    /// The score VALUE enclosure may never be looser than the bound its own
5305    /// DERIVATIVE enclosure certifies for the same cell.
5306    ///
5307    /// Both are enclosures of one function, so the mean value theorem ties
5308    /// them: across a cell of width `w` the score cannot move by more than
5309    /// `max|f'| * w`, hence
5310    ///
5311    /// ```text
5312    ///     width(F([a,b]))  <=  width(F({m}))  +  max|F'([a,b])| * w
5313    /// ```
5314    ///
5315    /// This is the invariant the natural interval extension broke, and it broke
5316    /// it in the regime the search lives in. The score is
5317    /// `-0.5 * (D*logdet_block + dof*deviance_block)` and near a REML optimum
5318    /// those two blocks cancel — each moves by `O(rank)` per unit of `rho`
5319    /// while their sum does not. Interval addition cannot see that the two
5320    /// movements are the same quantity with opposite signs, so the natural
5321    /// extension returned a range of width `rank * w` where the exact function
5322    /// has `|f'| * w`. Measured on a 33-mode cascade profile, that was a factor
5323    /// of `7.4e5` at `w = 2e-6`, and the factor DIVERGED as the cell shrank
5324    /// (`O(w)` against `O(w^2)`).
5325    ///
5326    /// `resolution_flat_region` reads the value range, so the consequence was
5327    /// not a loose number but a search that could retire no cell and refused
5328    /// designs it could certify. The centred form in [`AffineRemlProfile::enclose`]
5329    /// restores the invariant by construction; this gate is what stops the
5330    /// natural extension coming back.
5331    ///
5332    /// The fixture is built to CANCEL: `g_i = s_i = q_i = 1` with
5333    /// `E = modes = dof = rank`, whose analytic score is exactly constant in
5334    /// `rho`, so `|f'|` is zero to roundoff and any first-order slack in the
5335    /// value range shows up immediately.
5336    #[test]
5337    fn the_value_enclosure_never_exceeds_the_bound_its_own_derivative_certifies() {
5338        const MODES: usize = 33;
5339        let grams = [1.0; MODES];
5340        let penalties = [1.0; MODES];
5341        let projected = [1.0; MODES];
5342        let energies = [MODES as f64];
5343        let profile = AffineRemlProfile::new(
5344            &grams,
5345            &penalties,
5346            &projected,
5347            &energies,
5348            MODES as f64,
5349            MODES,
5350            0.0,
5351        )
5352        .expect("valid cancellation fixture");
5353
5354        let centre = -12.0_f64;
5355        let mut previous_width = f64::INFINITY;
5356        for exponent in [-1_i32, -2, -3, -4, -5, -6] {
5357            let half = 10.0_f64.powi(exponent);
5358            let (a, b) = (centre - half, centre + half);
5359            let width = b - a;
5360            let cell = profile.enclose(a, b).expect("cell enclosure");
5361            let point = profile.enclose(centre, centre).expect("point enclosure");
5362
5363            // Soundness first: the cell's ranges must CONTAIN the degenerate
5364            // cell's, which is what `certify_endpoint_derivative` relies on and
5365            // what an intersection of two enclosures could otherwise break.
5366            assert!(
5367                cell.score.value.lo <= point.score.value.lo
5368                    && point.score.value.hi <= cell.score.value.hi,
5369                "w={width:e}: the midpoint value range {:?} escaped the cell range {:?}",
5370                point.score.value,
5371                cell.score.value
5372            );
5373            assert!(
5374                cell.derivative.lo <= point.derivative.lo
5375                    && point.derivative.hi <= cell.derivative.hi,
5376                "w={width:e}: the midpoint derivative range {:?} escaped the cell range {:?}",
5377                point.derivative,
5378                cell.derivative
5379            );
5380
5381            let value_width = cell.score.value.hi - cell.score.value.lo;
5382            let point_width = point.score.value.hi - point.score.value.lo;
5383            let derivative_bound = cell.derivative.hi.abs().max(cell.derivative.lo.abs());
5384            let mean_value_bound = point_width + derivative_bound * width;
5385            assert!(
5386                value_width <= mean_value_bound * (1.0 + 1.0e-9),
5387                "w={width:e}: the value range is {value_width:e} wide but this cell's own \
5388                 derivative enclosure {:?} bounds the score's movement across it by \
5389                 {mean_value_bound:e} — the natural extension is back",
5390                cell.derivative
5391            );
5392
5393            println!(
5394                "[GATE] w={width:e} value_width={value_width:e} point_width={point_width:e} \
5395                 mvt={mean_value_bound:e} D={derivative_bound:e}"
5396            );
5397            // And it must actually CONVERGE. A first-order range falls by 10
5398            // per decade of cell width; this one falls by ~1000, because the
5399            // remainder is `max|F'| * w` and `max|F'|` is itself centred. The
5400            // gate asks for better than 50 per decade — enough to separate
5401            // `O(w)` from anything above it without pinning a rate — until the
5402            // range reaches the floor every enclosure has, the width of the
5403            // DEGENERATE-cell reading, below which there is nothing left to
5404            // win. Measured floor here: 8.98e-12 on a score of magnitude ~30.
5405            assert!(
5406                value_width <= previous_width / 50.0 || value_width <= 2.0 * point_width,
5407                "w={width:e}: the value range fell only {previous_width:e} -> \
5408                 {value_width:e}, and it is not at the point-enclosure floor \
5409                 {point_width:e} — that is first-order behaviour"
5410            );
5411            previous_width = value_width;
5412        }
5413    }
5414
5415    /// The centred form's degenerate and extreme cells.
5416    ///
5417    /// Centring introduces a second evaluation and an arithmetic that can
5418    /// produce an empty intersection or a non-finite remainder where the
5419    /// natural extension could not, so the cases where those are reachable are
5420    /// pinned rather than argued:
5421    ///
5422    /// * a POINT cell must return the natural extension untouched — the centred
5423    ///   form's remainder is exactly zero there and re-deriving it would only
5424    ///   add rounding;
5425    /// * a cell whose endpoints are ADJACENT binary64 values must still centre
5426    ///   at a point inside itself (`0.5*(lo+hi)` can round to either endpoint,
5427    ///   and a centre outside the cell would make the mean value theorem
5428    ///   inapplicable);
5429    /// * cells at the far ends of the representable `log lambda` domain, where
5430    ///   `lambda` is denormal at one end and near overflow at the other, must
5431    ///   stay sound: the centred range must contain the point range, and it may
5432    ///   never be wider than the natural extension it intersects.
5433    #[test]
5434    fn the_centred_enclosure_holds_on_degenerate_adjacent_and_extreme_cells() {
5435        let grams = [1.0, 4.0, 1.0e-9, 2.5e7];
5436        let penalties = [1.0, 1.0, 1.0, 1.0];
5437        let projected = [0.5, 0.25, 1.0e-3, 3.0];
5438        let energies = [8.0];
5439        let profile =
5440            AffineRemlProfile::new(&grams, &penalties, &projected, &energies, 6.0, 4, 0.25)
5441                .expect("valid fixture");
5442
5443        for &x in &[-600.0_f64, -37.5, -1.0, 0.0, 2.75, 600.0] {
5444            let Ok((direct, _)) = profile.enclose_direct(x, x) else {
5445                continue;
5446            };
5447            let centred = profile.enclose(x, x).expect("a point cell must enclose");
5448            assert_eq!(
5449                centred, direct,
5450                "a point cell must return the natural extension untouched at x={x}"
5451            );
5452
5453            // Adjacent binary64 endpoints: the tightest non-degenerate cell.
5454            let up = next_up(x);
5455            let Ok(cell) = profile.enclose(x, up) else {
5456                continue;
5457            };
5458            let point = profile.enclose(x, x).expect("point cell");
5459            assert!(
5460                cell.score.value.lo <= point.score.value.lo
5461                    && point.score.value.hi <= cell.score.value.hi,
5462                "adjacent-float cell at {x}: point value range {:?} escaped {:?}",
5463                point.score.value,
5464                cell.score.value
5465            );
5466            assert!(
5467                cell.derivative.lo <= point.derivative.lo
5468                    && point.derivative.hi <= cell.derivative.hi,
5469                "adjacent-float cell at {x}: point derivative range {:?} escaped {:?}",
5470                point.derivative,
5471                cell.derivative
5472            );
5473            assert!(
5474                cell.score.value.is_valid() && cell.derivative.is_valid(),
5475                "adjacent-float cell at {x} produced an invalid enclosure: {cell:?}"
5476            );
5477
5478            // Intersecting can only tighten: never wider than the natural form.
5479            let (wide, _) = profile.enclose_direct(x, up).expect("direct adjacent cell");
5480            assert!(
5481                cell.score.value.lo >= wide.score.value.lo
5482                    && cell.score.value.hi <= wide.score.value.hi,
5483                "the centred value range {:?} is not inside the natural extension {:?} at {x}",
5484                cell.score.value,
5485                wide.score.value
5486            );
5487            assert!(
5488                cell.derivative.lo >= wide.derivative.lo
5489                    && cell.derivative.hi <= wide.derivative.hi,
5490                "the centred derivative range {:?} is not inside the natural extension {:?} at {x}",
5491                cell.derivative,
5492                wide.derivative
5493            );
5494        }
5495    }
5496
5497    /// The 33 kept Schur modes and response energies of the cascade design in
5498    /// `gam_solve::residual_cascade`'s
5499    /// `auto_reml_certifies_a_design_the_data_cannot_identify` — 36 rows against
5500    /// 1725 columns — printed by that crate's `zz_probe_rank_deficient_` probe and
5501    /// carried here as literals so these gates need no design build and no
5502    /// dependency on gam-solve.
5503    ///
5504    /// A synthetic stand-in was tried first, twice, and neither reproduced the
5505    /// defect: it needs BOTH the multiscale spectrum and the near-interpolating
5506    /// response that makes the two score blocks cancel, and hand-built profiles
5507    /// kept landing on a monotone score the natural extension excludes by sign in
5508    /// a handful of cells. That is why these gates carry data rather than a
5509    /// formula.
5510    ///
5511    /// Returns `(gram_modes, penalty_modes, projected_rhs_squared, response_energy)`;
5512    /// the profile also takes `residual_dof = 33`, `determinant_rank = 33` and
5513    /// `logdet_constant = 9.226276711274537`, and its certified log-lambda domain
5514    /// is `[-21.860900258111, 18.75853229939662]`.
5515    fn cascade_profile_parts() -> (Vec<f64>, Vec<f64>, Vec<f64>, Vec<f64>) {
5516        let grams = vec![
5517            0.021513523027428847, 0.023421509558465926, 0.024477791743994424,
5518            0.03028760364561828, 0.03510108223379587, 0.040671848915996144,
5519            0.042394860646972565, 0.044208976267946384, 0.046980397477518414,
5520            0.051041787441650194, 0.053417305918114666, 0.05575657456312382,
5521            0.056982691606415704, 0.059623191536431024, 0.06072593823762461,
5522            0.061603808142128846, 0.0626306391548814, 0.06415989316153273, 0.06612727525342801,
5523            0.07201682707299777, 0.10499606046436369, 0.12037535776467499, 0.1486138626340859,
5524            0.1762399329554861, 0.19315924476245142, 0.26688703253550705, 0.2848266927054469,
5525            0.33232244706214037, 0.6015439556821448, 1.1406886269841172, 1.3973782387809837,
5526            1.8043547873076875, 2.0890420358314765,
5527        ];
5528        let penalties = vec![1.0_f64; 33];
5529        let projected = vec![
5530            0.0008447602450715568, 0.004744115853417025, 0.0013711877079256205,
5531            0.000556576229807026, 0.00032950514304538826, 0.00015869074743770514,
5532            0.004035749350652998, 0.002408288703125203, 0.0002161132863778849,
5533            0.0024599052556113317, 0.00028155268264135145, 9.068039769807838e-7,
5534            0.0004390033211936947, 0.004642257342083, 5.722227645019854e-6,
5535            0.003702111930202603, 0.003943553329808974, 0.0011808139994261783,
5536            1.490921408482301e-5, 0.001728436851442388, 0.00040290378245105683,
5537            0.0006710268119971442, 0.0032383572156905664, 0.00013742753101732549,
5538            6.681227329297447e-5, 0.054339495839186305, 0.018972176651153957,
5539            0.04535732957447296, 0.1129209190002305, 0.05428138627351111, 1.5501891913959478,
5540            0.14151749008562448, 0.11704548115908926,
5541        ];
5542        let energies = vec![2.7067510572921663_f64];
5543        (grams, penalties, projected, energies)
5544    }
5545
5546    /// The centred form's guard, and an honest account of what it is for.
5547    ///
5548    /// I wrote this guard for a hazard that turned out not to exist on the live
5549    /// path, so here is what is actually true, measured rather than argued.
5550    ///
5551    /// **The `inf * 0` story is closed already.** `ClosedInterval::mul` reduces
5552    /// four endpoint products with `f64::min`/`f64::max`, which IGNORE a NaN
5553    /// operand — so an `inf * 0` product would drop out of the reduction
5554    /// silently and leave a range strictly INSIDE the true one. But
5555    /// `product_down`/`product_up` treat a zero operand as exact and map the
5556    /// resulting NaN to `0.0`, so no NaN is ever produced that way, and
5557    /// `[-inf, -inf] * [-1, 0]` reduces to `[0, inf]` — correct. Enumerating
5558    /// every endpoint shape over `{-inf, -3, -1, 0, 1, 3, inf}` against a
5559    /// sampled product set finds no narrowing from any singly-infinite slope.
5560    ///
5561    /// **What is still open is a NaN arriving from elsewhere.** `product_is_exact`
5562    /// is false for a NaN against a non-unit, non-zero operand, so
5563    /// `[NaN, 1.0] * [-0.5, 0.5]` reduces to `[-0.5, 0.5]`: two of the four
5564    /// corners are dropped and a finite-looking, too-narrow range comes back with
5565    /// no signal at all. `enclose_direct` does not prove every accumulator finite,
5566    /// and `checked_enclosure` only validates the enclosure the search RECEIVES —
5567    /// by which point a NaN slope has already been used to narrow the value.
5568    ///
5569    /// So the guard excludes a non-finite slope and a non-finite remainder and
5570    /// keeps the natural extension, which is rigorous unconditionally. It is
5571    /// cheap, and it means a certified range does not rest on a case analysis of
5572    /// a rounding primitive three modules away that the next person to touch
5573    /// `mode_ranges` will not re-derive.
5574    #[test]
5575    fn the_centred_form_keeps_the_natural_extension_when_the_remainder_is_not_finite() {
5576        let direct = ClosedInterval::new(-10.0, 10.0);
5577        let point = ClosedInterval::new(-1.0, 1.0);
5578        let touching_zero = ClosedInterval::new(-0.5, 0.0);
5579        let straddling_zero = ClosedInterval::new(-0.5, 0.5);
5580
5581        // The hazard, on the record as a fact rather than as a worry: a NaN
5582        // endpoint reduces to a finite-looking range narrower than the truth.
5583        let narrowed = ClosedInterval::new(f64::NAN, 1.0).mul(straddling_zero);
5584        assert!(
5585            narrowed.lo.is_finite() && narrowed.hi.is_finite(),
5586            "premise: a NaN endpoint must reduce to a finite-LOOKING range ({narrowed:?}); if \
5587             `mul` stops dropping it this gate is about nothing"
5588        );
5589        // And the `inf * 0` path, which is NOT a hazard, asserted so a change to
5590        // `product_down`'s zero handling shows up here rather than silently.
5591        let infinite = ClosedInterval::new(f64::NEG_INFINITY, f64::NEG_INFINITY)
5592            .mul(ClosedInterval::new(-1.0, 0.0));
5593        assert!(
5594            infinite.lo <= 0.0 && infinite.hi.is_infinite(),
5595            "`inf * 0` must stay sound through `product_down`'s exact-zero mapping, got \
5596             {infinite:?}"
5597        );
5598
5599        for slope in [
5600            ClosedInterval::new(f64::NEG_INFINITY, 3.0),
5601            ClosedInterval::new(-3.0, f64::INFINITY),
5602            ClosedInterval::new(f64::NEG_INFINITY, f64::INFINITY),
5603            ClosedInterval::new(f64::NEG_INFINITY, f64::NEG_INFINITY),
5604            ClosedInterval::new(f64::NAN, 1.0),
5605            ClosedInterval::new(1.0, f64::NAN),
5606        ] {
5607            for offset in [touching_zero, straddling_zero, ClosedInterval::new(0.0, 0.5)] {
5608                assert_eq!(
5609                    centred_or(direct, point, slope, offset),
5610                    direct,
5611                    "a non-finite slope {slope:?} over offset {offset:?} must leave the natural \
5612                     extension in place"
5613                );
5614            }
5615        }
5616
5617        // And it still tightens when the remainder IS finite, so the guard has
5618        // not simply disabled the centred form.
5619        let tightened = centred_or(
5620            direct,
5621            point,
5622            ClosedInterval::new(-2.0, 2.0),
5623            straddling_zero,
5624        );
5625        assert!(
5626            tightened.lo > direct.lo && tightened.hi < direct.hi,
5627            "a finite remainder must still tighten: {tightened:?} against {direct:?}"
5628        );
5629    }
5630
5631    /// The centred ranges contain the function at EVERY interior point, not just
5632    /// at the centre they were expanded about.
5633    ///
5634    /// This is the gate on the riskiest thing centring introduces. Each channel
5635    /// is now a mean value form anchored on the one above it — the curvature on
5636    /// an interval THIRD derivative, the derivative on the curvature, the value
5637    /// on the derivative — so an error in the third-derivative kernel does not
5638    /// make a range wide, it makes it NARROW, and a narrow certified range is an
5639    /// unsound proof rather than a slow one.
5640    ///
5641    /// The check needs no finite differences and no reference implementation.
5642    /// `enclose(x, x)` is the natural extension on a degenerate cell, which
5643    /// encloses the exact value, derivative and curvature AT `x`; so for every
5644    /// `x` in `[a, b]` the cell's ranges must contain the point's. Sampling `x`
5645    /// away from the midpoint is what exercises the remainder terms: at the
5646    /// centre they vanish identically and prove nothing.
5647    ///
5648    /// Sampled across four decades of cell width so the remainder is the
5649    /// dominant term at the wide end and roundoff dominates at the narrow one.
5650    #[test]
5651    fn the_centred_ranges_contain_the_function_at_every_interior_point() {
5652        let (grams, penalties, projected, energies) = cascade_profile_parts();
5653        let profile = AffineRemlProfile::new(
5654            &grams,
5655            &penalties,
5656            &projected,
5657            &energies,
5658            33.0,
5659            33,
5660            9.226276711274537,
5661        )
5662        .expect("valid cascade profile");
5663
5664        // A containment check is only evidence if the range it checks was
5665        // actually NARROWED by the thing under test: if the intersection with
5666        // the natural extension were a no-op, every assertion below would hold
5667        // for any third-derivative kernel at all, including a wrong one.
5668        let mut curvature_tightened = false;
5669        // Spread over the design's own domain, including both saturated tails.
5670        for centre in [-20.0_f64, -12.5, -6.0, -1.679, 3.0, 11.0, 17.5] {
5671            for exponent in [0_i32, -1, -2, -3, -4] {
5672                let half = 10.0_f64.powi(exponent);
5673                let (a, b) = (centre - half, centre + half);
5674                let cell = profile.enclose(a, b).expect("cell enclosure");
5675                let (natural, _) = profile.enclose_direct(a, b).expect("natural extension");
5676                assert!(
5677                    cell.curvature.lo >= natural.curvature.lo
5678                        && cell.curvature.hi <= natural.curvature.hi,
5679                    "cell [{a}, {b}]: the centred curvature {:?} is not inside the natural \
5680                     extension {:?}",
5681                    cell.curvature,
5682                    natural.curvature
5683                );
5684                if cell.curvature.hi - cell.curvature.lo
5685                    < 0.5 * (natural.curvature.hi - natural.curvature.lo)
5686                {
5687                    curvature_tightened = true;
5688                }
5689                for step in 0..=8 {
5690                    let x = a + (b - a) * (step as f64 / 8.0);
5691                    let point = profile.enclose(x, x).expect("point enclosure");
5692                    assert!(
5693                        cell.score.value.lo <= point.score.value.lo
5694                            && point.score.value.hi <= cell.score.value.hi,
5695                        "cell [{a}, {b}] value range {:?} does not contain the exact value at \
5696                         x={x}, {:?}",
5697                        cell.score.value,
5698                        point.score.value
5699                    );
5700                    assert!(
5701                        cell.derivative.lo <= point.derivative.lo
5702                            && point.derivative.hi <= cell.derivative.hi,
5703                        "cell [{a}, {b}] derivative range {:?} does not contain the exact \
5704                         derivative at x={x}, {:?}",
5705                        cell.derivative,
5706                        point.derivative
5707                    );
5708                    assert!(
5709                        cell.curvature.lo <= point.curvature.lo
5710                            && point.curvature.hi <= cell.curvature.hi,
5711                        "cell [{a}, {b}] curvature range {:?} does not contain the exact \
5712                         curvature at x={x}, {:?} — the third-derivative kernel the curvature \
5713                         is centred on is wrong",
5714                        cell.curvature,
5715                        point.curvature
5716                    );
5717                }
5718            }
5719        }
5720        assert!(
5721            curvature_tightened,
5722            "the centred curvature never halved the natural extension's range anywhere in this \
5723             sweep, so the containment checks above would pass for a WRONG third-derivative \
5724             kernel too — this gate has gone vacuous"
5725        );
5726    }
5727
5728    /// The located optimum is the SAME under both enclosure forms, and it is
5729    /// accurate to the search's location contract and no better.
5730    ///
5731    /// Two claims, and the second is the one that catches misuse.
5732    ///
5733    /// Tightening an enclosure changes which cells the search visits, so it
5734    /// could in principle move the point it returns. On the profile
5735    /// `gam_sae::identifiability::ridge_reml_select_weight` builds for its
5736    /// one-eigendirection closed-form fixture it does not: both oracles return
5737    /// the same abscissa to the last bit, from the same stationary bracket. That
5738    /// is worth pinning, because a caller comparing the returned `lambda` to a
5739    /// closed form cannot tell "the enclosure moved the answer" from "the
5740    /// enclosure was always allowed to".
5741    ///
5742    /// And it was always allowed to. The search certifies a stationary point's
5743    /// LOCATION to the requested resolution in `rho`, and returns an evaluated
5744    /// SAMPLE from that bracket rather than the bracket's midpoint or a
5745    /// polished root. So `|rho_hat - rho*|` is bounded by the resolution and by
5746    /// nothing smaller — measured here at `4.17e-9` against a requested
5747    /// `1.49e-8`, from a bracket `1.13e-8` wide. A caller wanting more than that
5748    /// has to polish the root itself; the fixture's exact `lambda = 1.2` is
5749    /// reproduced to `2.5e-9`, which is inside the contract and outside a `1e-9`
5750    /// tolerance that no version of this search has ever guaranteed.
5751    #[test]
5752    fn the_located_optimum_is_enclosure_independent_and_accurate_to_the_contract() {
5753        // eigvals=[2.0], signal=[8.0], aux_norm_sq=10.0, n_obs=5, n_responses=3
5754        // => pairs = [(1.0, 4.0)] in u = lambda/gamma_max, repeated once per
5755        // response, with residual_dof = n_obs*n_responses = 15.
5756        let grams = [1.0_f64; 3];
5757        let penalties = [1.0_f64; 3];
5758        let projected = [4.0 / 3.0; 3];
5759        let energies = [10.0_f64];
5760        let profile =
5761            AffineRemlProfile::new(&grams, &penalties, &projected, &energies, 15.0, 3, 0.0)
5762                .expect("valid ridge profile");
5763        let lo = certified_ln_positive(f64::MIN_POSITIVE).expect("lo").lo;
5764        let hi = certified_ln_positive(f64::MAX / 2.0).expect("hi").hi;
5765        let resolution = f64::EPSILON.sqrt();
5766        // The closed-form stationary point: lambda_hat = 1.2, and the profile is
5767        // built in u = lambda/gamma_max with gamma_max = 2.
5768        let truth = 0.6_f64;
5769
5770        let natural = maximize_score_1d(
5771            lo,
5772            hi,
5773            resolution,
5774            |x| profile.evaluate(x),
5775            |a, b| profile.enclose_direct(a.x, b.x).map(|(e, _)| e),
5776        )
5777        .expect("the natural extension decomposes this domain");
5778        let centred = maximize_score_1d(lo, hi, resolution, |x| profile.evaluate(x), |a, b| {
5779            profile.enclose(a.x, b.x)
5780        })
5781        .expect("the centred form decomposes this domain");
5782
5783        assert_eq!(
5784            natural.optimum.x, centred.optimum.x,
5785            "the two enclosure forms located different optima ({} against {}); tightening may \
5786             change which cells are visited but must not move the certified root",
5787            natural.optimum.x, centred.optimum.x
5788        );
5789        for (label, search) in [("natural", &natural), ("centred", &centred)] {
5790            assert!(
5791                matches!(search.location, ScoreOptimumLocation::Stationary(_)),
5792                "{label}: this fixture has an interior stationary optimum, got {:?}",
5793                search.location
5794            );
5795            let offset = (search.optimum.x - truth.ln()).abs();
5796            assert!(
5797                offset <= resolution,
5798                "{label}: the located root is {offset:e} from the closed form in rho, outside \
5799                 the requested resolution {resolution:e} — that is a location-contract failure"
5800            );
5801            // And no better, which is the half a caller must not assume: the
5802            // returned point is a sample from the bracket, not a polished root.
5803            assert!(
5804                offset > 0.0,
5805                "{label}: an exactly-attained root would mean this gate has stopped measuring \
5806                 what it claims"
5807            );
5808        }
5809    }
5810
5811    /// COST. Centring doubles the per-cell work (one extra degenerate-cell
5812    /// evaluation), so the net is only a win if it removes more cells than that.
5813    /// This measures both oracles on the same searches and prints the ratio.
5814    ///
5815    /// Two shapes, because they pull in opposite directions: the cascade profile
5816    /// on its own 40.6-wide domain, where the natural extension cannot finish at
5817    /// all, and a well-conditioned profile on the FULL representable log-lambda
5818    /// domain (`ln(MIN_POSITIVE)` to `ln(MAX/2)`, 1417 wide) — which is what
5819    /// `gam_sae::identifiability::ridge_reml_select_weight` searches, and the
5820    /// case where a search that already succeeded cheaply could only get slower.
5821    #[test]
5822    fn zz_measure_centred_enclosure_search_cost() {
5823        let (grams, penalties, projected, energies) = cascade_profile_parts();
5824        let cascade = AffineRemlProfile::new(
5825            &grams,
5826            &penalties,
5827            &projected,
5828            &energies,
5829            33.0,
5830            33,
5831            9.226276711274537,
5832        )
5833        .expect("valid cascade profile");
5834
5835        let full_lo = certified_ln_positive(f64::MIN_POSITIVE).expect("domain lo").lo;
5836        let full_hi = certified_ln_positive(f64::MAX / 2.0).expect("domain hi").hi;
5837        let cases: [(&str, f64, f64); 3] = [
5838            // The domain the design declares, where the natural extension
5839            // cannot finish at all.
5840            ("cascade/40.6-wide", -21.860900258111, 18.75853229939662),
5841            // A narrow window around the optimum (-1.679), where the natural
5842            // extension already succeeds in a handful of cells. This is the
5843            // case centring could only make SLOWER, since there are no cells
5844            // left for it to remove.
5845            ("cascade/narrow-around-the-optimum", -3.0, 0.0),
5846            // The full representable log-lambda domain, 1417 wide, which is what
5847            // `gam_sae::identifiability::ridge_reml_select_weight` searches.
5848            ("cascade/full-representable-domain", full_lo, full_hi),
5849        ];
5850
5851        for (label, lo, hi) in cases {
5852            let profile = &cascade;
5853            let resolution = f64::EPSILON.sqrt();
5854            let started = std::time::Instant::now();
5855            let natural = maximize_score_1d(
5856                lo,
5857                hi,
5858                resolution,
5859                |x| profile.evaluate(x),
5860                |a, b| profile.enclose_direct(a.x, b.x).map(|(e, _)| e),
5861            );
5862            let natural_seconds = started.elapsed().as_secs_f64();
5863            let started = std::time::Instant::now();
5864            let centred = maximize_score_1d(
5865                lo,
5866                hi,
5867                resolution,
5868                |x| profile.evaluate(x),
5869                |a, b| profile.enclose(a.x, b.x),
5870            );
5871            let centred_seconds = started.elapsed().as_secs_f64();
5872            println!(
5873                "#COST {label}: natural {:.4}s ({}) centred {:.4}s ({}) speedup {:.2}x",
5874                natural_seconds,
5875                natural.as_ref().map_or("REFUSED", |_| "ok"),
5876                centred_seconds,
5877                centred.as_ref().map_or("REFUSED", |_| "ok"),
5878                natural_seconds / centred_seconds.max(f64::MIN_POSITIVE),
5879            );
5880            // A refusal is a legitimate outcome for some domains (the full
5881            // representable one reaches lambda values where the profiled
5882            // residual is not evaluable at all); what must never happen is the
5883            // centred oracle refusing where the natural one succeeds.
5884            assert!(
5885                centred.is_ok() || natural.is_err(),
5886                "{label}: the centred oracle refused ({centred:?}) where the natural extension \
5887                 succeeded — an intersection can only tighten, so this is impossible unless the \
5888                 centred form is unsound"
5889            );
5890            // The per-cell cost is at most 2x, so a search that certifies under
5891            // BOTH oracles must not lose more than that. A wider loss means the
5892            // centred form is provoking work rather than removing it.
5893            if natural.is_ok() {
5894                assert!(
5895                    centred_seconds <= natural_seconds * 2.5 + 1.0e-3,
5896                    "{label}: centring cost {centred_seconds:.4}s against the natural \
5897                     extension's {natural_seconds:.4}s — more than the doubled per-cell work \
5898                     can explain"
5899                );
5900            }
5901        }
5902    }
5903
5904    /// The capability the centred form buys, pinned by running the SAME search
5905    /// twice on the same profile with the two enclosure forms.
5906    ///
5907    /// Every other gate here measures a width. This one measures the only thing
5908    /// a width is for: whether the certified search can decompose the domain at
5909    /// all. The natural extension is not removed by the fix — it is still what
5910    /// the centred form is built from and intersected with — so it stays
5911    /// callable, and that makes the before/after a controlled comparison inside
5912    /// one test rather than a claim about a previous commit.
5913    ///
5914    /// The fixture is the cascade's shape rather than its data: modes spread
5915    /// over nine decades (what a multilevel frame's Schur complement looks
5916    /// like), response energy split across them, and `dof = rank = modes`, so
5917    /// the log-determinant and deviance blocks each move by `O(rank)` per unit
5918    /// of `rho` while the score does not — the cancellation that the natural
5919    /// extension cannot see.
5920    #[test]
5921    fn the_natural_extension_cannot_decompose_a_domain_the_centred_form_certifies() {
5922        let (grams, penalties, projected, energies) = cascade_profile_parts();
5923        let profile = AffineRemlProfile::new(
5924            &grams,
5925            &penalties,
5926            &projected,
5927            &energies,
5928            33.0,
5929            33,
5930            9.226276711274537,
5931        )
5932        .expect("valid cascade profile");
5933
5934        // The design's own certified log-lambda domain, 40.6 wide.
5935        let (lo, hi) = (-21.860900258111_f64, 18.75853229939662);
5936        let resolution = f64::EPSILON.sqrt();
5937
5938        let natural = maximize_score_1d(
5939            lo,
5940            hi,
5941            resolution,
5942            |x| profile.evaluate(x),
5943            |a, b| profile.enclose_direct(a.x, b.x).map(|(enclosure, _)| enclosure),
5944        );
5945        let centred = maximize_score_1d(
5946            lo,
5947            hi,
5948            resolution,
5949            |x| profile.evaluate(x),
5950            |a, b| profile.enclose(a.x, b.x),
5951        );
5952
5953        let centred = centred.unwrap_or_else(|error| {
5954            panic!(
5955                "the centred enclosure must decompose this 33-mode cascade domain: {error}"
5956            )
5957        });
5958        assert!(
5959            matches!(
5960                natural,
5961                Err(ScoreSearchError::SubdivisionBudget { .. } | ScoreSearchError::Unresolved { .. })
5962            ),
5963            "PREMISE LOST: the natural extension now decomposes this domain \
5964             ({natural:?}), so this fixture no longer exercises the defect and the \
5965             comparison below proves nothing — widen the mode spread or the domain \
5966             until it refuses again",
5967        );
5968
5969        // And the answer it reaches is a real one, not a shrug: a decided
5970        // location whose global value ordering closed.
5971        assert!(
5972            !matches!(centred.location, ScoreOptimumLocation::ResolutionFlat(_)),
5973            "the centred search must decide a location, got {:?}",
5974            centred.location
5975        );
5976        assert!(
5977            centred.value_certificate.maximum_excess
5978                <= centred.value_certificate.comparison_resolution,
5979            "the centred search's value ordering must close: excess {} against {}",
5980            centred.value_certificate.maximum_excess,
5981            centred.value_certificate.comparison_resolution
5982        );
5983        assert!(
5984            centred.optimum.x >= lo && centred.optimum.x <= hi && centred.optimum.x.is_finite(),
5985            "the selected log lambda must lie in the domain, got {}",
5986            centred.optimum.x
5987        );
5988    }
5989
5990    #[test]
5991    fn affine_reml_zero_smoothing_schur_residual_keeps_division_low_parts() {
5992        // Three exact-real quotients 1/3 sum to one, although no individual
5993        // quotient is representable in binary64. A directed interval around
5994        // each independently rounded quotient leaves an O(u) uncertainty in
5995        // `1 - 3*(1/3)`, larger than this profile's residual at lambda=1e-10.
5996        // The one-time TwoSum/FMA construction retains the division low parts,
5997        // so the exact zero Schur residual remains resolved near O(u²).
5998        let grams = [3.0; 3];
5999        let penalties = [1.0; 3];
6000        let projected = [1.0; 3];
6001        let energies = [1.0];
6002        let profile =
6003            AffineRemlProfile::new(&grams, &penalties, &projected, &energies, 3.0, 3, 0.0)
6004                .expect("valid nonrepresentable-quotient fixture");
6005
6006        let zero_residual = profile.zero_lambda_residual[0];
6007        assert!(
6008            zero_residual.contains_zero(),
6009            "the exact identity 1 - 3*(1/3) = 0 must be retained: {zero_residual:?}"
6010        );
6011        assert!(
6012            zero_residual.hi - zero_residual.lo < 1.0e-28,
6013            "division corrections must live below ordinary binary64 cancellation scale: \
6014             {zero_residual:?}"
6015        );
6016
6017        let rho = -23.025850929940457_f64;
6018        let enclosure = profile
6019            .enclose(rho, rho)
6020            .expect("the small positive smoothing residual must remain resolved");
6021        assert!(
6022            enclosure.derivative.contains_zero(),
6023            "determinant and residual derivatives cancel analytically: {:?}",
6024            enclosure.derivative
6025        );
6026        assert!(
6027            enclosure.derivative.hi - enclosure.derivative.lo < 1.0e-6,
6028            "the exact Schur residual must control the profiled derivative: {:?}",
6029            enclosure.derivative
6030        );
6031    }
6032
6033    #[test]
6034    fn affine_reml_saturated_tail_preserves_complement_signs() {
6035        let profile = AffineRemlProfile::new(&[1.0], &[1.0], &[0.0], &[1.0], 4.0, 1, 0.0)
6036            .expect("valid saturated-tail fixture");
6037        let log_lambda = 700.0;
6038        let jet = profile.evaluate(log_lambda).expect("point jet");
6039        let enclosure = profile
6040            .enclose(log_lambda, log_lambda)
6041            .expect("point enclosure");
6042
6043        assert!(
6044            jet.derivative > 0.0,
6045            "the point derivative must preserve +0.5/(1+exp(rho)), got {}",
6046            jet.derivative
6047        );
6048        assert!(
6049            jet.curvature < 0.0,
6050            "the point curvature must preserve its negative u*c sign, got {}",
6051            jet.curvature
6052        );
6053        assert!(
6054            enclosure.curvature.hi <= 0.0,
6055            "the exact saturated curvature remains nonpositive: {:?}",
6056            enclosure.curvature
6057        );
6058        assert!(
6059            enclosure.derivative.lo >= 0.0,
6060            "the exact saturated derivative remains nonnegative: {:?}",
6061            enclosure.derivative
6062        );
6063        let score = enclosure.score;
6064        assert!(score.evaluation_error.is_finite());
6065        assert!(
6066            score
6067                .value
6068                .widen(score.evaluation_error)
6069                .contains(jet.value),
6070            "the stable score evaluator must lie inside its exact value range plus forward error"
6071        );
6072    }
6073
6074    #[test]
6075    fn affine_reml_extreme_domain_one_direction_encloses_and_maximizes_repeatably() {
6076        // The normalized one-direction ridge profile behind the gam-sae
6077        // regressions has
6078        //
6079        //   R(lambda) = 10 - 4/(1 + lambda),
6080        //
6081        // so its exact residual stays in [6, 10] over the complete finite
6082        // lambda domain. Repeating the direction three times reproduces the
6083        // response multiplicity of that caller and plants the stationary point
6084        // at lambda/gamma_max = 0.6.
6085        let gram_modes = [1.0, 1.0, 1.0];
6086        let penalty_modes = [1.0, 1.0, 1.0];
6087        let projected_rhs_squared = [4.0 / 3.0, 4.0 / 3.0, 4.0 / 3.0];
6088        let response_energy = [10.0];
6089        let profile = AffineRemlProfile::new(
6090            &gram_modes,
6091            &penalty_modes,
6092            &projected_rhs_squared,
6093            &response_energy,
6094            15.0,
6095            3,
6096            0.0,
6097        )
6098        .expect("valid normalized one-direction ridge profile");
6099        let rho_lo = certified_ln_positive(f64::MIN_POSITIVE)
6100            .expect("finite-domain lower log bound")
6101            .lo;
6102        let rho_hi = certified_ln_positive(f64::MAX / 2.0)
6103            .expect("finite-domain upper log bound")
6104            .hi;
6105
6106        let whole_domain = profile
6107            .enclose(rho_lo, rho_hi)
6108            .expect("scale-safe relative exp error keeps the full-domain residual finite");
6109        assert!(
6110            whole_domain.score.value.is_valid()
6111                && whole_domain.score.value.lo.is_finite()
6112                && whole_domain.score.value.hi.is_finite()
6113        );
6114        assert!(whole_domain.score.evaluation_error.is_finite());
6115        assert!(whole_domain.derivative.contains_zero());
6116
6117        let resolution = f64::EPSILON.sqrt();
6118        let first = profile
6119            .maximize_value_ordered(rho_lo, rho_hi, resolution)
6120            .expect("finite subdivision must certify the planted stationary optimum");
6121        let repeated = profile
6122            .maximize_value_ordered(rho_lo, rho_hi, resolution)
6123            .expect("the same exact search must be repeatable");
6124        assert_eq!(first, repeated);
6125        let ScoreOptimumLocation::Stationary(index) = first.location else {
6126            panic!(
6127                "the planted one-direction optimum must be stationary, got {:?}",
6128                first.location
6129            );
6130        };
6131        let stationary = first
6132            .stationary_points
6133            .get(index)
6134            .expect("stationary result index");
6135        let expected = certified_ln_positive(0.6).expect("analytic stationary log");
6136        assert!(
6137            stationary.bracket.lo <= expected.lo && stationary.bracket.hi >= expected.hi,
6138            "certified bracket {:?} must contain analytic log(0.6) {:?}",
6139            stationary.bracket,
6140            expected
6141        );
6142        assert!(
6143            first.value_certificate.maximum_excess <= first.value_certificate.comparison_resolution,
6144            "an isolated stationary root is not yet a globally ordered score candidate: \
6145             maximum excess {}, comparison resolution {}, bracket {:?}",
6146            first.value_certificate.maximum_excess,
6147            first.value_certificate.comparison_resolution,
6148            stationary.bracket,
6149        );
6150    }
6151
6152    #[test]
6153    fn affine_reml_gram_zero_subnormal_zero_projection_is_structural() {
6154        let minimum_subnormal = f64::from_bits(1);
6155        let log_lambda = -740.0;
6156        let lambda = exp_interval(log_lambda, log_lambda)
6157            .expect("the fixture needs a certified subnormal lambda");
6158        assert!(lambda.lo > 0.0 && lambda.hi < f64::MIN_POSITIVE);
6159        let raw_h = lambda.mul(ClosedInterval::point(minimum_subnormal));
6160        assert!(
6161            raw_h.lo < 0.0 && raw_h.hi > 0.0,
6162            "the raw outward product must cross rounded zero: {raw_h:?}"
6163        );
6164        let h = raw_h.nonnegative();
6165        assert_eq!(
6166            h.lo, 0.0,
6167            "known nonnegative product must clamp its outward lower bound to zero"
6168        );
6169
6170        let ranges = mode_ranges(0.0, minimum_subnormal, 0.0, lambda)
6171            .expect("the zero projection cancels before any residual division");
6172        assert_eq!(ranges.c, ClosedInterval::point(0.0));
6173        assert_eq!(ranges.w, ClosedInterval::point(0.0));
6174        assert_eq!(ranges.v, ClosedInterval::point(0.0));
6175        assert_eq!(ranges.p, ClosedInterval::point(0.0));
6176        assert_eq!(ranges.q, ClosedInterval::point(0.0));
6177
6178        let gram_modes = [0.0];
6179        let penalty_modes = [minimum_subnormal];
6180        let projected_rhs_squared = [0.0];
6181        let response_energy = [1.0];
6182        let profile = AffineRemlProfile::new(
6183            &gram_modes,
6184            &penalty_modes,
6185            &projected_rhs_squared,
6186            &response_energy,
6187            1.0,
6188            1,
6189            0.0,
6190        )
6191        .expect("valid gram-zero structural fixture");
6192        let jet = profile
6193            .evaluate(log_lambda)
6194            .expect("normalized determinant and zero residual projection stay finite");
6195        let enclosure = profile
6196            .enclose(log_lambda, log_lambda)
6197            .expect("the proof path must not divide by a zero-containing h interval");
6198        assert_eq!(jet.derivative, 0.0);
6199        assert_eq!(jet.curvature, 0.0);
6200        assert!(is_exact_zero(enclosure.derivative));
6201        assert!(is_exact_zero(enclosure.curvature));
6202        assert!(
6203            enclosure
6204                .score
6205                .value
6206                .widen(enclosure.score.evaluation_error)
6207                .contains(jet.value)
6208        );
6209    }
6210
6211    #[test]
6212    fn affine_reml_gram_zero_subnormal_nonzero_projection_stays_finite() {
6213        let minimum_subnormal = f64::from_bits(1);
6214        let log_lambda = -740.0;
6215        let lambda = exp_interval(log_lambda, log_lambda)
6216            .expect("the fixture needs a certified subnormal lambda");
6217        let penalty = 0.01;
6218        let h = lambda.mul(ClosedInterval::point(penalty)).nonnegative();
6219        assert_eq!(
6220            h.lo, 0.0,
6221            "the fixture must enter the structural quotient path"
6222        );
6223
6224        let ranges = mode_ranges(0.0, penalty, minimum_subnormal, lambda)
6225            .expect("the scaled quotient has a finite representable range");
6226        assert_eq!(ranges.c, ClosedInterval::point(0.0));
6227        assert_eq!(ranges.w, ClosedInterval::point(0.0));
6228        assert!(ranges.v.lo > 0.0 && ranges.v.hi.is_finite());
6229        assert_eq!(ranges.p, ranges.v);
6230        assert_eq!(ranges.q, ranges.v.neg());
6231
6232        let gram_modes = [0.0];
6233        let penalty_modes = [penalty];
6234        let projected_rhs_squared = [minimum_subnormal];
6235        let response_energy = [10.0];
6236        let profile = AffineRemlProfile::new(
6237            &gram_modes,
6238            &penalty_modes,
6239            &projected_rhs_squared,
6240            &response_energy,
6241            1.0,
6242            1,
6243            0.0,
6244        )
6245        .expect("valid gram-zero finite-ratio fixture");
6246        let jet = profile
6247            .evaluate(log_lambda)
6248            .expect("the point ratio must avoid the underflowing product");
6249        let enclosure = profile
6250            .enclose(log_lambda, log_lambda)
6251            .expect("the interval ratio must remain finite without a reciprocal overflow");
6252        assert!(
6253            enclosure
6254                .score
6255                .value
6256                .widen(enclosure.score.evaluation_error)
6257                .contains(jet.value)
6258        );
6259    }
6260
6261    #[test]
6262    fn affine_reml_gram_zero_unrepresentable_projection_is_typed() {
6263        let minimum_subnormal = f64::from_bits(1);
6264        let log_lambda = -740.0;
6265        let gram_modes = [0.0];
6266        let penalty_modes = [minimum_subnormal];
6267        let projected_rhs_squared = [1.0];
6268        let response_energy = [10.0];
6269        let profile = AffineRemlProfile::new(
6270            &gram_modes,
6271            &penalty_modes,
6272            &projected_rhs_squared,
6273            &response_energy,
6274            1.0,
6275            1,
6276            0.0,
6277        )
6278        .expect("valid gram-zero refusal fixture");
6279        assert!(matches!(
6280            profile.evaluate(log_lambda),
6281            Err(AffineRemlError::ElementaryEnclosureUnavailable {
6282                function: "gram-zero residual quotient",
6283                ..
6284            })
6285        ));
6286        assert!(matches!(
6287            profile.enclose(log_lambda, log_lambda),
6288            Err(AffineRemlError::ElementaryEnclosureUnavailable {
6289                function: "gram-zero residual quotient",
6290                ..
6291            })
6292        ));
6293    }
6294
6295    #[test]
6296    fn affine_reml_rejects_nonpositive_profile_residual() {
6297        let profile = AffineRemlProfile::new(&[1.0], &[1.0], &[2.0], &[1.0], 4.0, 1, 0.0)
6298            .expect("statically valid");
6299        assert!(matches!(
6300            profile.evaluate(-2.0),
6301            Err(AffineRemlError::NonPositiveResidual { .. })
6302        ));
6303    }
6304}