00001
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
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
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 template<typename F>
00094 void GivensRotations<F>::multiply
00095 (const concepts::Matrix<F>& fact, concepts::Matrix<F>& dest) const {
00096
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
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) {
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 }
00118 }
00119 }
00120
00121 template<typename F>
00122 void GivensRotations<F>::multiplyFirst
00123 (const concepts::Matrix<F>& fact, concepts::Matrix<F>& dest) const {
00124
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
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 }
00155
00156 #endif // givensRotations_hh