Yalantis/uCrop · warning

symmetric_eigen(): LAPACK library function dsyev_() returned

Error message

symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.

What it means

CImg::symmetric_eigen() computes eigenvalues/eigenvectors of a symmetric matrix via LAPACK dsyev_(); nonzero INFO means the eigen-decomposition failed to converge or received an invalid argument. CImg warns and leaves val/vec unset rather than throwing.

Source

Thrown at ucrop/src/main/jni/CImg.h:33233

        val[0] = (t)l2;
        val[1] = (t)l1;
        if (n>0) { vec[0] = (t)(b/n); vec[2] = (t)((l2 - a)/n); } else { vec[0] = 1; vec[2] = 0; }
        vec[1] = -vec[2];
        vec[3] = vec[0];
        return *this;
      }

#ifdef cimg_use_lapack
      char JOB = 'V', UPLO = 'U';
      int N = _width, LWORK = 4*N, INFO;
      Tfloat
        *const lapA = new Tfloat[N*N],
        *const lapW = new Tfloat[N],
        *const WORK = new Tfloat[LWORK];
      cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l));
      cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO);
      if (INFO)
        cimg::warn(_cimg_instance
                   "symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.",
                   cimg_instance,
                   INFO);
      if (!INFO) {
        cimg_forY(val,i) val(i) = (T)lapW[N - 1 -i];
        cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N - 1 - k)*N + l]);
      } else { val.fill(0); vec.fill(0); }
      delete[] lapA; delete[] lapW; delete[] WORK;

#else
      CImg<t> V(_width,_width);
      Tfloat M = 0, m = (Tfloat)min_max(M), maxabs = cimg::max((Tfloat)1,cimg::abs(m),cimg::abs(M));
      (CImg<Tfloat>(*this,false)/=maxabs).SVD(vec,val,V,false);
      if (maxabs!=1) val*=maxabs;

      bool is_ambiguous = false;
      float eig = 0;
      cimg_forY(val,p) { // Check for ambiguous cases

View on GitHub (pinned to f788b534b4)

Solutions

  1. Symmetrize the matrix explicitly before the call: A = (A + A.get_transpose())/2
  2. Check for NaN/Inf entries and sanitize the input matrix
  3. Verify the matrix is square and non-empty
  4. Use double precision and scale the matrix to improve convergence
  5. Provide a fallback (e.g. Jacobi eigen implementation) if dsyev_ keeps failing

Example fix

// before
CImg<float> val, vec;
A.symmetric_eigen(val, vec);
// after
CImg<float> S = (A + A.get_transpose())*0.5f;
if (S.isnan().sum() > 0) S.nanf(0); // or reject input
CImg<float> val, vec;
S.symmetric_eigen(val, vec);
Defensive patterns

Strategy: validation

Validate before calling

bool readyForEigen(const CImg<float>& A) {
  if (A.width() != A.height() || A.width() == 0) return false;
  for (int i = 0; i < A.width(); ++i)
    for (int j = 0; j < A.height(); ++j)
      if (std::isnan(A(i,j)) || std::isinf(A(i,j))) return false;
  return true;
}

Prevention

When it happens

Trigger: Calling symmetric_eigen() on a matrix that is not actually symmetric (dsyev only reads one triangle, garbage in the other can cause divergence), non-square input, or extremely ill-conditioned matrices.

Common situations: Building covariance matrices with asymmetric accumulation bugs; NaN/Inf entries in the matrix; NDK LAPACK builds with mismatched dsyev_ ABI.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/10fbe4080c504ff7. Report an issue: GitHub.