SelfAdjointEigenSolver: scalar argmin in eigenvalue sort (fixes ARM NEON sort)

libeigen/eigen!2505

Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
diff --git a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
index 65533d8..c89c2d1 100644
--- a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
+++ b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
@@ -626,11 +626,21 @@
   // TODO: make the sort optional and use a more efficient sorting algorithm.
   if (info == Success) {
     for (Index i = 0; i < n - 1; ++i) {
-      Index k;
-      diag.segment(i, n - i).minCoeff(&k);
-      if (k > 0) {
-        numext::swap(diag[i], diag[k + i]);
-        if (computeEigenvectors) eivec.col(i).swap(eivec.col(k + i));
+      // Scalar argmin: the vectorized minCoeff path can return the wrong
+      // index on targets whose SIMD reduction flushes subnormals (32-bit ARM
+      // NEON always treats subnormal inputs to vminq_f32 as zero), which
+      // corrupts ordering when eigenvalues span the subnormal range.
+      Index k = i;
+      RealScalar min_val = diag[i];
+      for (Index j = i + 1; j < n; ++j) {
+        if (diag[j] < min_val) {
+          min_val = diag[j];
+          k = j;
+        }
+      }
+      if (k != i) {
+        numext::swap(diag[i], diag[k]);
+        if (computeEigenvectors) eivec.col(i).swap(eivec.col(k));
       }
     }
   }