305 eigen_assert(m_analysisIsok &&
"analyzePattern() should be called before this step");
306 Index m = mat.rows();
307 Index n = mat.cols();
308 IndexVector mark(m); mark.setConstant(-1);
309 IndexVector Ridx(n), Qidx(m);
310 Index nzcolR, nzcolQ;
311 ScalarVector tval(m);
317 for (
int i = 0; i < n; i++)
319 Index p = m_perm_c.
size() ? m_perm_c.
indices()(i) : i;
321 m_pmat.
innerNonZeroPtr()[p] = mat.outerIndexPtr()[i+1] - mat.outerIndexPtr()[i];
328 if(m_useDefaultThreshold)
330 RealScalar max2Norm = 0.0;
331 for (
int j = 0; j < n; j++) max2Norm = (max)(max2Norm, m_pmat.
col(j).norm());
332 m_threshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
338 Index nonzeroCol = 0;
341 for (Index col = 0; col < n; ++col)
343 mark.setConstant(-1);
346 mark(nonzeroCol) = col;
347 Qidx(0) = nonzeroCol;
348 nzcolR = 0; nzcolQ = 1;
356 for (
typename MatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
358 Index curIdx = nonzeroCol ;
359 if(itp) curIdx = itp.row();
360 if(curIdx == nonzeroCol) found_diag =
true;
363 Index st = m_firstRowElt(curIdx);
366 m_lastError =
"Empty row found during numerical factorization";
373 for (; mark(st) != col; st = m_etree(st))
381 Index nt = nzcolR-bi;
382 for(Index i = 0; i < nt/2; i++) std::swap(Ridx(bi+i), Ridx(nzcolR-i-1));
385 if(itp) tval(curIdx) = itp.value();
386 else tval(curIdx) = Scalar(0);
389 if(curIdx > nonzeroCol && mark(curIdx) != col )
391 Qidx(nzcolQ) = curIdx;
398 for (Index i = nzcolR-1; i >= 0; i--)
400 Index curIdx = m_pivotperm.
indices()(Ridx(i));
406 tdot = m_Q.
col(curIdx).dot(tval);
408 tdot *= m_hcoeffs(curIdx);
412 for (
typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
413 tval(itq.row()) -= itq.value() * tdot;
416 if(m_etree(Ridx(i)) == nonzeroCol)
418 for (
typename QRMatrixType::InnerIterator itq(m_Q, curIdx); itq; ++itq)
420 Index iQ = itq.row();
434 Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
437 RealScalar sqrNorm = 0.;
438 for (Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
440 if(sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0))
443 beta = numext::real(c0);
448 beta = std::sqrt(numext::abs2(c0) + sqrNorm);
449 if(numext::real(c0) >= RealScalar(0))
452 for (Index itq = 1; itq < nzcolQ; ++itq)
453 tval(Qidx(itq)) /= (c0 - beta);
454 tau = numext::conj((beta-c0) / beta);
459 for (Index i = nzcolR-1; i >= 0; i--)
461 Index curIdx = Ridx(i);
462 if(curIdx < nonzeroCol)
464 m_R.insertBackByOuterInnerUnordered(col, curIdx) = tval(curIdx);
465 tval(curIdx) = Scalar(0.);
469 if(abs(beta) >= m_threshold)
471 m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
474 m_hcoeffs(col) = tau;
476 for (Index itq = 0; itq < nzcolQ; ++itq)
478 Index iQ = Qidx(itq);
479 m_Q.insertBackByOuterInnerUnordered(col,iQ) = tval(iQ);
480 tval(iQ) = Scalar(0.);
486 m_hcoeffs(col) = Scalar(0);
487 for (Index j = nonzeroCol; j < n-1; j++)
502 m_nonzeropivots = nonzeroCol;
507 MatrixType tempR(m_R);
508 m_R = tempR * m_pivotperm;
511 m_outputPerm_c = m_outputPerm_c * m_pivotperm;
514 m_isInitialized =
true;
515 m_factorizationIsok =
true;
const Index * innerNonZeroPtr() const
const IndicesType & indices() const
const Index * outerIndexPtr() const
int coletree(const MatrixType &mat, IndexVector &parent, IndexVector &firstRowElt, typename MatrixType::Index *perm=0)