Yalantis/uCrop · warning
eigen(): Complex eigenvalues found.
Error message
eigen(): Complex eigenvalues found.
What it means
CImg<T>::get_eigen()/eigen() computes eigenvalues/vectors of a symmetric matrix; for the 2x2 case it computes the discriminant f = e^2 - 4*(ad-bc). If f<0 the eigenvalues are complex and cannot be represented in the real output matrices, so cimg::warn() emits a non-fatal warning and the code proceeds with sqrt of a negative value clamped/behaving per std::sqrt (NaN), producing invalid results.
Source
Thrown at ucrop/src/main/jni/CImg.h:33158
\param[out] vec Matrix of the estimated eigenvectors, sorted by columns.
**/
template<typename t>
const CImg<T>& eigen(CImg<t>& val, CImg<t> &vec) const {
if (is_empty()) { val.assign(); vec.assign(); }
else {
if (_width!=_height || _depth>1 || _spectrum>1)
throw CImgInstanceException(_cimg_instance
"eigen(): Instance is not a square matrix.",
cimg_instance);
if (val.size()<(ulongT)_width) val.assign(1,_width);
if (vec.size()<(ulongT)_width*_width) vec.assign(_width,_width);
switch (_width) {
case 1 : { val[0] = (t)(*this)[0]; vec[0] = (t)1; } break;
case 2 : {
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.",View on GitHub (pinned to f788b534b4)
Solutions
- Symmetrize the input before calling: M = (M + M.get_transpose())/2
- Sanitize the matrix: replace NaN/Inf values and validate the data feeding the matrix
- If complex eigenvalues are legitimately possible, use a general (non-symmetric) eigensolver library (e.g. Eigen/LAPACK) instead of CImg's real-only eigen()
- Check for negative discriminant yourself before calling and handle the degenerate 2x2 case explicitly
Example fix
// before CImg<T> val, vec; M.eigen(val, vec); // warns if matrix not truly symmetric // after CImg<T> S = (M + M.get_transpose()) * 0.5; S.eigen(val, vec);
Defensive patterns
Strategy: validation
Validate before calling
bool symmetric_ok(const CImg<double>& M) {
if (M.width() != M.height()) return false;
for (unsigned i = 0; i < M.width(); ++i)
for (unsigned j = i + 1; j < M.width(); ++j)
if (M(i,j) != M(j,i) || !std::isfinite(M(i,j))) return false;
return true;
}
// then: CImg<double> S = (M + M.get_transpose()) * 0.5; S.eigen(val, vec); Type guard
bool is_finite_symmetric(const CImg<double>& M) {
if (M.width() != M.height()) return false;
for (unsigned i = 0; i < M.width(); ++i)
for (unsigned j = 0; j < M.width(); ++j)
if (!std::isfinite(M(i, j)) || M(i, j) != M(j, i)) return false;
return true;
} Prevention
- Symmetrize matrices ((M + M^T)/2) before eigen-decomposition
- Reject/repair NaN and Inf entries before numeric routines
- Use a general eigensolver (Eigen/LAPACK) when complex eigenvalues are possible
- Compute the discriminant yourself for 2x2 cases and branch explicitly
When it happens
Trigger: Calling eigen()/symmetric eigen-decomposition on a 2x2 (or larger, in general paths) matrix whose characteristic polynomial has negative discriminant — i.e. the input is not positive-definite / not a valid symmetric matrix with real spectrum, often due to floating-point asymmetry or garbage data.
Common situations: Running eigen() on nearly-symmetric matrices polluted by NaNs or noise, covariance/structure-tensor computations with degenerate input, passing a non-symmetric matrix where symmetry is assumed.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- eigen(): Instance is not a square matrix.
- eigen(): Eigenvalues computation of general matrices is limi
- operator*(): Invalid multiplication of instance by specified
- [cimg_appname_math_parser] CImg<%s>::%s: %s: Type of first a
- [cimg_appname_math_parser] CImg<%s>::%s: %s: Types of first
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/60f3a789658a380b.
Report an issue: GitHub.