Yalantis/uCrop · warning

solve(): LAPACK library function sgels() returned error code

Error message

solve(): LAPACK library function sgels() returned error code %d.

What it means

CImg::solve() uses LAPACK sgels() for the least-squares/underdetermined path; nonzero INFO means sgels failed, either an invalid argument (bad dimensions/lwork) or the least-squares driver could not complete. CImg warns and falls back to (A.get_invert(use_LU)*X).

Source

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

        res.move_to(*this);
#endif
      } else { // Least-square solution for non-square systems

#ifdef cimg_use_lapack
        char TRANS = 'N';
        int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width;
        Ttfloat WORK_QUERY;
        Ttfloat
          * const lapA = new Ttfloat[M*N],
          * const lapB = new Ttfloat[M*NRHS];
        cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, &WORK_QUERY, LWORK, INFO);
        LWORK = (int) WORK_QUERY;
        Ttfloat *const WORK = new Ttfloat[LWORK];
        cimg_forXY(A,k,l) lapA[k*M + l] = (Ttfloat)(A(k,l));
        cimg_forXY(*this,k,l) lapB[k*M + l] = (Ttfloat)((*this)(k,l));
        cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, WORK, LWORK, INFO);
        if (INFO!=0)
          cimg::warn(_cimg_instance
                     "solve(): LAPACK library function sgels() returned error code %d.",
                     cimg_instance,
                     INFO);
        assign(NRHS, N);
        if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)lapB[k*M + l];
        else (A.get_invert(use_LU)*(*this)).move_to(*this);
        delete[] lapA; delete[] lapB; delete[] WORK;
#else
        (A.get_invert(use_LU)*(*this)).move_to(*this);
#endif
      }
      return *this;
    }

    //! Solve a system of linear equations \newinstance.
    template<typename t>
    CImg<_cimg_Ttfloat> get_solve(const CImg<t>& A, const bool use_LU=false) const {
      typedef _cimg_Ttfloat Ttfloat;

View on GitHub (pinned to f788b534b4)

Solutions

  1. Verify A and this (B) have consistent, expected dimensions before solve()
  2. Scale/normalize the data and use double precision to improve conditioning
  3. Check for rank deficiency in A and remove dependent columns/rows
  4. If the fallback (A^-1 * B) also fails, use a dedicated SVD-based pseudo-inverse
  5. Inspect that your LAPACK provides sgels with the expected signature

Example fix

// before
CImg<float> x = B.solve(A); // non-square A
// after
if (std::fabs(A.determinant()) < 1e-12f) {
  for (int i = 0; i < A.width(); ++i) A(i,i) += 1e-6f; // regularize before least-squares
}
CImg<float> x = B.solve(A);
Defensive patterns

Strategy: validation

Validate before calling

bool fitForLeastSquares(const CImg<float>& A, const CImg<float>& B) {
  return A.width() > 0 && A.height() > 0 && B.height() == A.height() &&
         !A.isnan().sum() && !B.isnan().sum();
}

Prevention

When it happens

Trigger: Calling solve() on non-square A (over/under-determined systems) when sgels receives inconsistent M/N/NRHS/LDA/LDB/LWORK values or the problem is numerically degenerate.

Common situations: Fitting models with rank-deficient design matrices; dimension typos when building A and B; single-precision (sgels) limitations with badly scaled data.

Related errors


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