From fb59bd7cd560928b628815f57b20d415e403527a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 21:35:43 +0000 Subject: [PATCH 1/3] statsmodels: Add version 0.15.0 Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- docs/packages/statsmodels.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/packages/statsmodels.yaml b/docs/packages/statsmodels.yaml index 4d7733b3a9..90260ba840 100644 --- a/docs/packages/statsmodels.yaml +++ b/docs/packages/statsmodels.yaml @@ -12,3 +12,4 @@ versions: - filename: statsmodels-0.14.6-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl sha256: d19c3b8befc7037d9fa9136b12c32b696417a4ea3e93c86632ddd0acd36932c8 requires-python: '>=3.9' +- version: 0.15.0 From 4309eaa006ca9db16d4b83caf8d1a5f301092842 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 18 Sep 2026 06:38:33 +0000 Subject: [PATCH 2/3] statsmodels: Add 0.15.0 patches Only the knockoff eigh fix is carried: 0.15.0 already handles scipy 1.18's array_api_extra move itself. --- ...-the-symmetric-matrix-in-_design_kno.patch | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 patches/statsmodels/0.15.0/0001-BUG-use-eigh-for-the-symmetric-matrix-in-_design_kno.patch diff --git a/patches/statsmodels/0.15.0/0001-BUG-use-eigh-for-the-symmetric-matrix-in-_design_kno.patch b/patches/statsmodels/0.15.0/0001-BUG-use-eigh-for-the-symmetric-matrix-in-_design_kno.patch new file mode 100644 index 0000000000..20e656af02 --- /dev/null +++ b/patches/statsmodels/0.15.0/0001-BUG-use-eigh-for-the-symmetric-matrix-in-_design_kno.patch @@ -0,0 +1,41 @@ +From 31c88b884dc8121d00daf79518915788290cc607 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Fri, 18 Sep 2026 06:38:25 +0000 +Subject: [PATCH] BUG: use eigh for the symmetric matrix in + _design_knockoff_equi + +`xcov` is `exog.T @ exog`, so it is symmetric positive semi-definite and its +eigenvalues are real. `np.linalg.eig` calls LAPACK's general `dgeev`, which +returns a complex array whenever rounding leaves any imaginary part non-zero +-- what happens depends on the BLAS kernels, and OpenBLAS's riscv64_generic +ones do it for these matrices where the x86_64 and aarch64 ones do not. +`evmin` is then complex, `min(2 * evmin, 1)` picks it over the real 1, and +`_get_knmat` dies on the first in-place multiply: + + ash *= -np.outer(sl, sl) + numpy._core._exceptions._UFuncOutputCastingError: Cannot cast ufunc + 'multiply' output from dtype('complex128') to dtype('float64') with + casting rule 'same_kind' + +`eigh` uses `dsyevd`, is real by construction on every platform, and agrees +with `eig` to 3e-15 on the same inputs. This is 13 failures in +stats/tests/test_knockoff.py on riscv64 -- every `equi` parametrisation. + +Upstream-Status: To upstream [not yet submitted; pending review of the riscv64 port that found it] +--- + statsmodels/stats/_knockoff.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/statsmodels/stats/_knockoff.py b/statsmodels/stats/_knockoff.py +index cbbbe9f04..a2de99a2e 100644 +--- a/statsmodels/stats/_knockoff.py ++++ b/statsmodels/stats/_knockoff.py +@@ -238,7 +238,7 @@ def _design_knockoff_equi(exog, rng): + exog = exog / xnm + + xcov = np.dot(exog.T, exog) +- ev, _ = np.linalg.eig(xcov) ++ ev, _ = np.linalg.eigh(xcov) + + if np.iscomplexobj(ev): + if np.all(ev.imag == 0): From 81fe9cff1209d12b900852e9c450e74615d9cbcf Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 18 Sep 2026 17:07:52 +0000 Subject: [PATCH 3/3] statsmodels: fix setuptools_scm pretend-version env var statsmodels' meson.build calls setuptools_scm.get_version(root=ROOT) directly with no dist_name, so it only honors the unscoped SETUPTOOLS_SCM_PRETEND_VERSION, not the _FOR_STATSMODELS-suffixed variant. The wheels built with a dirty-tree dev version instead of 0.15.0, which the publish job's dry run correctly caught as undeclared in docs/packages/statsmodels.yaml. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_011RwtHNpuiuiCk4MstTLu8m --- .github/workflows/build-statsmodels.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-statsmodels.yml b/.github/workflows/build-statsmodels.yml index 4a34640650..633ca97126 100644 --- a/.github/workflows/build-statsmodels.yml +++ b/.github/workflows/build-statsmodels.yml @@ -82,9 +82,11 @@ jobs: CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} # PIP_ONLY_BINARY keeps numpy/scipy/pandas on our registry's riscv64 wheels # instead of source-building the newer releases PyPI offers; setuptools_scm - # is pinned because the shallow tag checkout carries no version history. + # is pinned because the patched tree is dirty at the tag. statsmodels' + # meson.build calls setuptools_scm.get_version() directly with no dist_name, + # so only the unscoped var (not _FOR_STATSMODELS) is honored. CIBW_ENVIRONMENT: >- - SETUPTOOLS_SCM_PRETEND_VERSION_FOR_STATSMODELS=${{ env.STATSMODELS_VERSION }} + SETUPTOOLS_SCM_PRETEND_VERSION=${{ env.STATSMODELS_VERSION }} PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ PIP_ONLY_BINARY=numpy,scipy,pandas MKL_NUM_THREADS=1