--- Final Solver (used for performance test) ---
from typing import Any
import os

import numpy as np


def _load_cython():
    """Import the compiled Cython projector, building it once if necessary.

    Building happens here (effectively __init__ time) and is excluded from the
    measured solve runtime.
    """
    import sys

    here = os.path.dirname(os.path.abspath(__file__))
    if here not in sys.path:
        sys.path.insert(0, here)
    try:
        import csolver  # type: ignore
        return csolver
    except Exception:
        pass
    try:
        import subprocess

        subprocess.run(
            [sys.executable, "setup_cython.py", "build_ext", "--inplace"],
            cwd=here,
            check=True,
            capture_output=True,
        )
        import importlib
        import csolver  # type: ignore
        importlib.reload(csolver)
        return csolver
    except Exception:
        return None


_CY = _load_cython()


def _numpy_project(y: np.ndarray) -> np.ndarray:
    """Pure-numpy O(n log n) fallback (used only if the Cython build fails)."""
    n = y.shape[0]
    if n == 1:
        return np.ones(1, dtype=np.float64)
    u = np.sort(y)[::-1]
    cssv = np.cumsum(u) - 1.0
    ind = np.arange(1, n + 1)
    rho = np.count_nonzero(u * ind > cssv)
    theta = cssv[rho - 1] / rho
    return np.maximum(y - theta, 0.0)


class Solver:
    def __init__(self):
        self._cy = _CY

    def solve(self, problem: dict[str, Any], **kwargs) -> Any:
        if self._cy is not None:
            return {"solution": self._cy.project(problem["y"])}

        y_in = problem["y"]
        y = np.asarray(y_in, dtype=np.float64).ravel()
        if y.shape[0] == 0:
            return {"solution": y}
        return {"solution": _numpy_project(y)}
--- End Solver ---
Running performance test...
============================= test session starts ==============================
platform linux -- Python 3.12.13, pytest-9.0.2, pluggy-1.6.0
rootdir: /tests
plugins: anyio-4.13.0, jaxtyping-0.3.9
collected 3 items

../tests/test_outputs.py .
--- Performance Summary ---
Validity: True
Total Baseline Time: 6.0888s
Total Solver Time:   5.9058s
Raw Speedup:         1.0310 x
Final Reward (Score): 1.0310
---------------------------
..

==================================== PASSES ====================================
=========================== short test summary info ============================
PASSED ../tests/test_outputs.py::test_solver_exists
PASSED ../tests/test_outputs.py::test_solver_validity
PASSED ../tests/test_outputs.py::test_solver_speedup
======================== 3 passed in 290.36s (0:04:50) =========================
