"""Gates for the logarithmic space mode โ€” checked BEFORE the ranking is consulted. PREREG_logarithmic_2026-09-20.md, amendment 1: G1 the transform is parameter-free: c and s come from the bracket and the caller (c = the end with the smaller |f|, s = xtol), never from a chosen constant. G2' on APS-154 the cost must not grow (measured by the sweep, not here); what IS checkable here is that the deviation from the x-space step is of SECOND order in the bracket width, i.e. it vanishes as the bracket collapses. Also pinned: the transform round-trips, u-space is rejected where it cannot be read (no silent fallback to a different scale), and the mode still solves. """ from __future__ import annotations import inspect import math import re import pytest from simroot import pure as P def _steps(width, space, fun=None): """The points probed on a NONLINEAR f from a bracket of the given width around 1. Nonlinear on purpose: on a linear f the two spaces coincide EXACTLY (deviation 0.0, measured 2026-09-20), because the derived scale makes the step the Newton step and that lands on the root in either space โ€” so a linear probe cannot see the deviation at all.""" calls = [] g = fun or (lambda t: t * t * t - 1.0) def f(x): calls.append(x) return g(x) P.pure_root(f, 1.0 - width, 1.0 + width, xtol=1e-14, maxfev=200, similarity="ratio", scale="derived", guard="none", space=space) return calls def test_G1_the_transform_carries_no_chosen_constant(): src = "".join(inspect.getsource(fn) for fn in (P._log_map, P._log_unmap, P._log_space_step)) literals = set(re.findall(r"(? i and len(xs_log) > i dev[width] = abs(xs_log[i] - xs_x[i]) / width # exact zero is a STRONGER pass than a shrinking deviation, so it is allowed assert dev[1e-3] <= dev[1e-2] / 3.0 or dev[1e-2] == 0.0, dev assert dev[1e-4] <= dev[1e-3] / 3.0 or dev[1e-3] == 0.0, dev def test_the_mode_is_rejected_where_it_cannot_be_read(): with pytest.raises(ValueError): P.pure_root(lambda x: x, -1.0, 1.0, 1e-10, 100, scale="bracket", space="log") with pytest.raises(ValueError): P.pure_root(lambda x: x, -1.0, 1.0, 1e-10, 100, space="nope") def test_the_mode_still_solves_both_a_narrow_and_a_wide_bracket(): for lo, hi in ((0.5, 1.5), (-1e12, 3.0)): x, nfev, ok = P.pure_root(lambda t: t - 1.0, lo, hi, xtol=1e-10, maxfev=500, similarity="ratio", scale="derived3", guard="credit", space="log") assert ok and abs(x - 1.0) < 1e-8, (lo, hi, x, nfev, ok) def test_x_space_is_untouched_by_the_new_parameter(): """The published configuration must be bit-identical with the default space.""" for lo, hi in ((0.5, 1.5), (0.5, 1e6)): # both brackets must straddle sqrt(2) a = P.pure_root(lambda t: t * t - 2.0, lo, hi, 1e-12, 300, similarity="ratio", scale="derived3", guard="credit") b = P.pure_root(lambda t: t * t - 2.0, lo, hi, 1e-12, 300, similarity="ratio", scale="derived3", guard="credit", space="x") assert a == b