Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)

sparseqr/givensRotations.hh
Go to the documentation of this file.
00001 // Givens rotations
00002 
00003 #ifndef givensRotations_hh
00004 #define givensRotations_hh
00005 
00006 #include "sparseqr/sparseqr.hh"
00007 #include "operator/matrix.hh"
00008 
00009 namespace sparseqr {
00010 
00011   // ******************************************************* GivensRotations **
00012 
00027   template<typename F>
00028   class GivensRotations : public concepts::Operator<F> {
00029   public:
00030     template<class G>
00031     GivensRotations(const concepts::Space<G>& space,
00032                     const Qmatrix& q, bool transpose)
00033       : concepts::Operator<F>(space.dim(), space.dim())
00034       , q_(q), transpose_(transpose) {}
00035     GivensRotations(uint dim, const Qmatrix& q, bool transpose)
00036       : concepts::Operator<F>(dim, dim), q_(q), transpose_(transpose) {}
00037     virtual void operator()(const concepts::Function<F>& fncY,
00038                             concepts::Function<F>& fncX);
00042     void multiply(const concepts::Matrix<F>& fact,
00043                   concepts::Matrix<F>& dest) const;
00047     void multiplyFirst(const concepts::Matrix<F>& fact,
00048                        concepts::Matrix<F>& dest) const;
00049   protected:
00050     virtual std::ostream& info(std::ostream& os) const;
00051   private:
00053     const Qmatrix& q_;
00054     const bool transpose_;
00055   };
00056 
00057   template<typename F>
00058   void GivensRotations<F>::operator()
00059     (const concepts::Function<F>& fncY, concepts::Function<F>& fncX) {
00060     conceptsAssert(fncY.dim() == this->dimY(), concepts::Assertion());
00061     conceptsAssert(fncX.dim() == this->dimX(), concepts::Assertion());
00062     fncX = fncY;
00063     const J* j = q_.qend;
00064     if (transpose_) j = q_.qbegin;
00065     while (j != 0) {
00066       conceptsAssert((uint)j->row1 < this->dimY(), concepts::Assertion());
00067       conceptsAssert((uint)j->row2 < this->dimY(), concepts::Assertion());
00068       F t = fncX(j->row1);
00069       if (transpose_) {
00070         fncX(j->row1) = j->c*fncX(j->row1) + j->s*fncX(j->row2);
00071         fncX(j->row2) = j->c*fncX(j->row2) - j->s*t;
00072       } else {
00073         fncX(j->row1) = j->c*fncX(j->row1) - j->s*fncX(j->row2);
00074         fncX(j->row2) = j->c*fncX(j->row2) + j->s*t;
00075       }
00076       if (transpose_) j = j->next;
00077       else  j = j->previous;
00078     }
00079   }
00080 
00081   /* The following routine does the same for a matrix as operator() above
00082      does for a vector.
00083 
00084      It has to compute \c dest = \c fact times Given's rotations whereas
00085      operator() computes \c fncX = Given's rotations times \c fncY.
00086      \c dest^T = Given's^T times \c fact^T => each column of \c fact^T is
00087      treated the same way as \c fncY. A column of \c fact^T is a row
00088      of \c fact.
00089 
00090      The precondition of the routine is \c fact = \c dest, therefore, we
00091      can work on \c dest only.
00092   */
00093   template<typename F>
00094   void GivensRotations<F>::multiply
00095   (const concepts::Matrix<F>& fact, concepts::Matrix<F>& dest) const {
00096     // check sizes of the matrices
00097     conceptsAssert(fact.dimX() == dest.dimX(), concepts::Assertion());
00098     conceptsAssert(fact.dimY() == dest.dimY(), concepts::Assertion());
00099     conceptsAssert(fact.dimY() == this->dimX(), concepts::Assertion());
00100     // loop over rows of dest
00101     for (uint i = 0; i < dest.dimX(); ++i) {
00102       const J* j = q_.qbegin;
00103       if (transpose_) j = q_.qend;
00104       while (j != 0) { // loop over Given's rotations
00105         conceptsAssert((uint)j->row1 < this->dimX(), concepts::Assertion());
00106         conceptsAssert((uint)j->row2 < this->dimX(), concepts::Assertion());
00107         F t = dest(i, j->row1);
00108         if (transpose_) {
00109           dest(i, j->row1) = j->c*dest(i, j->row1) - j->s*dest(i, j->row2);
00110           dest(i, j->row2) = j->c*dest(i, j->row2) + j->s*t;
00111         } else {
00112           dest(i, j->row1) = j->c*dest(i, j->row1) + j->s*dest(i, j->row2);
00113           dest(i, j->row2) = j->c*dest(i, j->row2) - j->s*t;
00114         }
00115         if (transpose_) j = j->previous;
00116         else j = j->next;
00117       } // while j
00118     } // for i
00119   }
00120 
00121   template<typename F>
00122   void GivensRotations<F>::multiplyFirst
00123   (const concepts::Matrix<F>& fact, concepts::Matrix<F>& dest) const {
00124     // check sizes of the matrices
00125     conceptsAssert(fact.dimX() == dest.dimX(), concepts::Assertion());
00126     conceptsAssert(fact.dimY() == dest.dimY(), concepts::Assertion());
00127     conceptsAssert(fact.dimX() == this->dimX(),  concepts::Assertion());
00128     // loop over columns of dest
00129     for (uint i = 0; i < dest.dimY(); ++i) {
00130       const J* j = q_.qend;
00131       if (transpose_) j = q_.qbegin;
00132       while (j != 0) {
00133         conceptsAssert((uint)j->row1 < this->dimX(), concepts::Assertion());
00134         conceptsAssert((uint)j->row2 < this->dimX(), concepts::Assertion());
00135         F t = dest(j->row1, i);
00136         if (transpose_) {
00137           dest(j->row1, i) = j->c*dest(j->row1, i) + j->s*dest(j->row2, i);
00138           dest(j->row2, i) = j->c*dest(j->row2, i) - j->s*t;
00139         } else {
00140           dest(j->row1, i) = j->c*dest(j->row1, i) - j->s*dest(j->row2, i);
00141           dest(j->row2, i) = j->c*dest(j->row2, i) + j->s*t;
00142         }
00143         if (transpose_) j = j->next;
00144         else j = j->previous;
00145       }
00146     }
00147   }
00148 
00149   template<typename F>
00150   std::ostream& GivensRotations<F>::info(std::ostream& os) const {
00151     return os << "GivensRotations(" << this->dimX() << ", " << q_ << ')';
00152   }
00153 
00154 } // namespace sparseqr
00155 
00156 #endif // givensRotations_hh

Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)