00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef __OPENKN_MATH__RQ_DECOMPOSITION_HPP__
00027 #define __OPENKN_MATH__RQ_DECOMPOSITION_HPP__
00028
00029
00030
00031
00032
00033 #include <cmath>
00034
00035
00036
00037
00038 #include "MathException.hpp"
00039 #include "Matrix.hpp"
00040 #include "Matrix3x3.hpp"
00041
00042
00043
00044
00045
00046 namespace kn {
00047
00048
00057 template <class T>
00058 void qrDecomposition(const Matrix<T> &A, Matrix<T> &R, Matrix<T> &Q){
00059 if(A.rows() != A.columns()) throw MathException("the input matrix is not a square matrix");
00060 if(R.rows() != R.columns()) throw MathException("the 'R' matrix is not a square matrix");
00061 if(Q.rows() != Q.columns()) throw MathException("the 'Q' matrix is not a square matrix");
00062 if(A.rows() != R.rows() || A.rows() != Q.rows()) throw MathException("input matrix does not have the same size");
00063
00064 R=A;
00065 Q.setIdentity();
00066 Matrix<T> Qtmp(Q.rows());
00067
00068
00069 for(unsigned int i=0;i<A.columns()-1;i++){
00070
00071 Vector<T> v=R.getColumn(i).getSubVector(i,R.rows()-i);
00072
00073
00074 if(v.at(0)<0.0) {v.at(0) -= v.getNorm();}
00075 else {v.at(0) += v.getNorm();}
00076
00077 if(v.getNorm()<10e-30){
00078 throw MathException("Division by zero");
00079 }
00080 v.normalize();
00081
00082
00083 Matrix<T> Qn(v.size(),v.size());
00084 Qn.setIdentity();
00085
00086 for(unsigned int j=0;j<v.size();j++){
00087 for(unsigned int k=j;k<v.size();k++){
00088 Qn.at(j,k) -= 2*v.at(j)*v.at(k);
00089 Qn.at(k,j) = Qn.at(j,k);
00090 }
00091 }
00092 Qn=-Qn;
00093
00094
00095 Qtmp.setIdentity();
00096 Qtmp.setSubMatrix(i,i,Qn);
00097
00098 Q = Qtmp*Q;
00099
00100
00101 R = Q*A;
00102 R.roundZero(10e-10);
00103
00104 }
00105 Q.transpose();
00106 }
00107
00108
00116 template <class T>
00117 void rqDecomposition3x3(const Matrix<T> &A, Matrix<T> &R, Matrix<T> &Q){
00118 if(A.rows() != 3 || A.columns() != 3) throw MathException("the input matrix is not a 3x3 matrix");
00119 if(R.rows() != 3 || R.columns() != 3) throw MathException("the 'R' matrix is not a 3x3 matrix");
00120 if(Q.rows() != 3 || Q.columns() != 3) throw MathException("the 'Q' matrix is not a 3x3 matrix");
00121
00122 Matrix3x3<T> Qx;
00123 Matrix3x3<T> Qy;
00124 Matrix3x3<T> Qz;
00125
00126 Qx.setIdentity();
00127 Qy.setIdentity();
00128 Qz.setIdentity();
00129
00130
00132 R = A;
00133
00135 Qx[2][2] = -R[2][2]/sqrt(pow(R[2][1],2)+pow(R[2][2],2));
00136 Qx[1][1] = Qx[2][2];
00137 Qx[2][1] = R[2][1]/sqrt(pow(R[2][1],2)+pow(R[2][2],2));
00138 Qx[1][2] = -Qx[2][1];
00139
00140 R = R*Qx;
00141
00142
00143
00144
00146 Qy[2][2] = R[2][2]/sqrt(pow(R[2][0],2)+pow(R[2][2],2));
00147 Qy[0][0] = Qy[2][2];
00148 Qy[0][2] = R[2][0]/sqrt(pow(R[2][0],2)+pow(R[2][2],2));
00149 Qy[2][0] = -Qy[0][2];
00150
00151 R = R*Qy;
00152
00154 Qz[0][0] = R[1][1]/sqrt(pow(R[1][1],2)+pow(R[1][0],2));
00155 Qz[1][1] = Qz[0][0];
00156 Qz[1][0] = -R[1][0]/sqrt(pow(R[1][1],2)+pow(R[1][0],2));
00157 Qz[0][1] = -Qz[1][0];
00158
00159 R = R*Qz;
00160
00162 Qx.transpose();
00163 Qy.transpose();
00164 Qz.transpose();
00165 Q = Qz * Qy * Qx;
00166 }
00167
00168
00175 template <class T>
00176 void rq3x3MakePositiveDiagonal(Matrix<T> &R, Matrix<T> &Q){
00177 if(R.rows() != 3 || R.columns() != 3) throw MathException("the 'R' matrix is not a 3x3 matrix");
00178 if(Q.rows() != 3 || Q.columns() != 3) throw MathException("the 'Q' matrix is not a 3x3 matrix");
00179
00180
00181 if(R[1][1] < 0)
00182 {
00183 for(int i=0; i<3; i++) R[i][1] *= -1.0;
00184 for(int i=0; i<3; i++) Q[1][i] *= -1.0;
00185 }
00186
00187
00188 if(R[0][0] < 0)
00189 {
00190 for(int i=0; i<3; i++) R[i][0] *= -1.0;
00191 for(int i=0; i<3; i++) Q[0][i] *= -1.0;
00192 }
00193 }
00194
00195
00196
00197
00198 }
00199
00200
00201
00202
00203 #endif
00204
00205
00206
00207
00208
00209
00210