Yalantis/uCrop · error · CImgInstanceException

eigen(): Eigenvalues computation of general matrices is limi

Error message

eigen(): Eigenvalues computation of general matrices is limited to 2x2 matrices.

What it means

CImg's eigen() computes eigenvalues/eigenvectors of a matrix treated as a general (non-symmetric) matrix, but the closed-form algorithm shipped in this header only implements the 2x2 case. For any other width the library throws CImgInstanceException rather than iterating numerically.

Source

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

          const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a + d;
          double f = e*e - 4*(a*d - b*c);
          if (f<0) cimg::warn(_cimg_instance
                              "eigen(): Complex eigenvalues found.",
                              cimg_instance);
          f = std::sqrt(f);
          const double
            l1 = 0.5*(e - f),
            l2 = 0.5*(e + f),
            b2 = b*b,
            norm1 = std::sqrt(cimg::sqr(l2 - a) + b2),
            norm2 = std::sqrt(cimg::sqr(l1 - a) + b2);
          val[0] = (t)l2;
          val[1] = (t)l1;
          if (norm1>0) { vec(0,0) = (t)(b/norm1); vec(0,1) = (t)((l2 - a)/norm1); } else { vec(0,0) = 1; vec(0,1) = 0; }
          if (norm2>0) { vec(1,0) = (t)(b/norm2); vec(1,1) = (t)((l1 - a)/norm2); } else { vec(1,0) = 1; vec(1,1) = 0; }
        } break;
        default :
          throw CImgInstanceException(_cimg_instance
                                      "eigen(): Eigenvalues computation of general matrices is limited "
                                      "to 2x2 matrices.",
                                      cimg_instance);
        }
      }
      return *this;
    }

    //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix.
    /**
       \return A list of two images <tt>[val; vec]</tt>, whose meaning is similar as in eigen(CImg<t>&,CImg<t>&) const.
    **/
    CImgList<Tfloat> get_eigen() const {
      CImgList<Tfloat> res(2);
      eigen(res[0],res[1]);
      return res;
    }

View on GitHub (pinned to f788b534b4)

Solutions

  1. Restrict general eigen() calls to 2x2 matrices, or reshape/decompose your problem into 2x2 blocks
  2. For symmetric matrices of any size, call symmetric_eigen(val, vec) instead, which supports NxN
  3. Implement an external eigensolver (e.g. Eigen, LAPACK via JNI) for general NxN matrices
  4. Guard the call: if (m.width() != 2) use an alternative solver before calling eigen()

Example fix

// before
CImg<float> A(3,3); CImg<float> val, vec;
A.eigen(val, vec); // throws
// after
CImg<float> val, vec;
if (A.width() == 2 && A.height() == 2) A.eigen(val, vec);
else A.symmetric_eigen(val, vec); // for symmetric NxN
Defensive patterns

Strategy: validation

Validate before calling

if (m.width() == 2 && m.height() == 2) { m.eigen(val, vec); } else { /* use symmetric_eigen or external solver */ }

Type guard

bool isGeneralEigenSupported(const CImg<T>& m) { return m.width() == 2 && m.height() == 2 && m.depth() == 1 && m.spectrum() == 1; }

Try / catch

try { m.eigen(val, vec); } catch (CImgInstanceException& e) { /* fall back to symmetric_eigen or external library */ }

Prevention

When it happens

Trigger: Calling CImg<T>::eigen()/get_eigen() (or symmetric_eigen dispatch path) on an instance whose _width is not 2 (e.g. a 3x3 or NxN general matrix).

Common situations: Using eigen() on a 3x3 covariance or rotation matrix expecting LAPACK-like behavior; confusing eigen() with symmetric_eigen(), which supports arbitrary square sizes; upgrading CImg versions where general-N eigen support is absent.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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