17faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This file is part of Eigen, a lightweight C++ template library
27faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// for linear algebra.
37faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez//
47faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This code initially comes from MINPACK whose original authors are:
57faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Copyright Jorge More - Argonne National Laboratory
67faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Copyright Burt Garbow - Argonne National Laboratory
77faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Copyright Ken Hillstrom - Argonne National Laboratory
87faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez//
97faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This Source Code Form is subject to the terms of the Minpack license
107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file.
117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifndef EIGEN_LMCOVAR_H
137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define EIGEN_LMCOVAR_H
147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace Eigen {
167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace internal {
187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate <typename Scalar>
207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid covar(
217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Matrix< Scalar, Dynamic, Dynamic > &r,
227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        const VectorXi& ipvt,
237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) )
247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    using std::abs;
267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    typedef DenseIndex Index;
277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* Local variables */
287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Index i, j, k, l, ii, jj;
297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    bool sing;
307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Scalar temp;
317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* Function Body */
337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    const Index n = r.cols();
347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    const Scalar tolr = tol * abs(r(0,0));
357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    Matrix< Scalar, Dynamic, 1 > wa(n);
367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    eigen_assert(ipvt.size()==n);
377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* form the inverse of r in the full upper triangle of r. */
397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    l = -1;
407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (k = 0; k < n; ++k)
417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if (abs(r(k,k)) > tolr) {
427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            r(k,k) = 1. / r(k,k);
437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            for (j = 0; j <= k-1; ++j) {
447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                temp = r(k,k) * r(j,k);
457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                r(j,k) = 0.;
467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                r.col(k).head(j+1) -= r.col(j).head(j+1) * temp;
477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            }
487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            l = k;
497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        }
507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* form the full upper triangle of the inverse of (r transpose)*r */
527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* in the full upper triangle of r. */
537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (k = 0; k <= l; ++k) {
547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for (j = 0; j <= k-1; ++j)
557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            r.col(j).head(j+1) += r.col(k).head(j+1) * r(j,k);
567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        r.col(k).head(k+1) *= r(k,k);
577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* form the full lower triangle of the covariance matrix */
607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* in the strict lower triangle of r and in wa. */
617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (j = 0; j < n; ++j) {
627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        jj = ipvt[j];
637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        sing = j > l;
647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        for (i = 0; i <= j; ++i) {
657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            if (sing)
667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                r(i,j) = 0.;
677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            ii = ipvt[i];
687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            if (ii > jj)
697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                r(ii,jj) = r(i,j);
707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez            if (ii < jj)
717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez                r(jj,ii) = r(i,j);
727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        }
737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        wa[jj] = r(j,j);
747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    /* symmetrize the covariance matrix in r. */
777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    r.topLeftCorner(n,n).template triangularView<StrictlyUpper>() = r.topLeftCorner(n,n).transpose();
787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    r.diagonal() = wa;
797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace internal
827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace Eigen
847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif // EIGEN_LMCOVAR_H
86