00001 #ifndef LINALG_H
00002 #define LINALG_H
00003
00004 #include <vector>
00005 #include "tnt_array2d.h"
00006 #include "tnt_array2d_utils.h"
00007 #include "tnt_array1d_utils.h"
00008 #include "tnt_array1d.h"
00009 #include "jama_svd.h"
00010
00011
00012
00013
00014
00015
00016 using namespace std;
00017 using namespace TNT;
00018 using namespace JAMA;
00019
00020 #define EPSILON 1.0e-15
00021
00023 template <class T>
00024 Array1D<T> stl2tntVec(const vector<T>& v){
00025 int N=v.size();
00026 Array1D<T> a(N);
00027 for (int i=0;i<N;i++) a[i]=v[i];
00028 return a;
00029 }
00030
00032 template <class T>
00033 vector<T> tnt2stlVec(const Array1D<T>& v){
00034 int N=v.dim();
00035 vector<T> a;
00036 for (int i=0;i<N;i++) a.push_back(v[i]);
00037 return a;
00038 }
00039
00041 template <class T>
00042 vector< vector<T> > tnt2stlMat(const Array2D<T>& m){
00043 vector< vector<T> > tmp;
00044 for (int i=0;i<m.dim1();i++){
00045 vector<T> row;
00046 for (int j=0;j<m.dim2();j++) row.push_back(m[i][j]);
00047 tmp.push_back(row);
00048 }
00049 return tmp;
00050 }
00051
00053 template <class T>
00054 Array2D<T> stl2tntMat(const vector< vector<T> >& m){
00055 int ncol=0;
00056 for(int i=0;i<static_cast<int>(m.size());++i)
00057 {if (static_cast<int>(m[i].size())>ncol) ncol=m[i].size();}
00058
00059 Array2D<T> tmp(m.size(),ncol);
00060 for (int i=0;i<tmp.dim1();++i){
00061 for (int j=0;j<tmp.dim2();++j) {
00062 if (j<static_cast<int>(m[i].size())) {tmp[i][j]=m[i][j];} else {tmp[i][j]=static_cast<T>(0);}
00063 }
00064 }
00065 return tmp;
00066 }
00067
00069 template <class T>
00070 void copy(Array1D<T>& A, const vector<T>& v){
00071 int N=v.size();
00072 Array1D<T> a(N);
00073 for (int i=0;i<N;i++) a[i]=v[i];
00074 A=a;
00075 }
00076
00078 template <class T>
00079 void copy(vector<T>& A, const Array1D<T>& v){
00080 int N=v.dim();
00081 vector<T> a;
00082 for (int i=0;i<N;i++) a.push_back(v[i]);
00083 A=a;
00084 }
00085
00087 template <class T>
00088 void copy(vector< vector<T> >& A, const Array2D<T>& m){
00089 vector< vector<T> > tmp;
00090 for (int i=0;i<m.dim1();i++){
00091 vector<T> row(m.dim2());
00092 for (int j=0;j<m.dim2();j++) row[j]=m[i][j];
00093 tmp.push_back(row);
00094 }
00095 A=tmp;
00096 }
00097
00099 template <class T>
00100 void copy(Array2D<T>& A, const vector< vector<T> >& m){
00101 int ncol=0;
00102 for(int i=0;i<static_cast<int>(m.size());i++){if (static_cast<int>(m[i].size())>ncol) ncol=m[i].size();}
00103
00104 Array2D<T> tmp(m.size(),ncol);
00105 for (int i=0;i<tmp.dim1();i++){
00106 for (int j=0;j<tmp.dim2();j++) {
00107 if (j<ncol) {tmp[i][j]=m[i][j];} else {tmp[i][j]=static_cast<T>(0);}
00108 }
00109 }
00110 A=tmp;
00111 }
00112
00113
00115 template <class T>
00116 Array2D<T> transpose(const Array2D<T>& A){
00117 Array2D<T> B(A.dim2(),A.dim1());
00118 for (int i=0;i<A.dim1();i++){
00119 for (int j=0;j<A.dim2();j++){
00120 B[j][i]=A[i][j];
00121 }
00122 }
00123 return B;
00124 }
00125
00127 template <class T>
00128 Array1D<T> operator*(const Array2D<T>& A, const Array1D<T>& v){
00129 Array1D<T> x(A.dim1());
00130 for (int i=0;i<A.dim1();i++){
00131 x[i]=0.0;
00132 for (int j=0;j<A.dim2();j++){
00133 x[i]+=A[i][j]*v[j];
00134 }
00135 }
00136 return x;
00137 }
00138
00140 template <class T>
00141 T inner_prod(const Array1D<T>& A, const Array1D<T>& B){
00142 T ans=0;
00143 for (int i=0;i<A.dim1();i++){
00144 ans=ans+A[i]*B[i];
00145 }
00146 return ans;
00147 }
00148
00150 template <class T>
00151 Array1D<T> operator*(const T& x, const Array1D<T>& A){
00152 Array1D<T> B(A.dim1());
00153 for (int i=0;i<A.dim1();i++){
00154 B[i]=x*A[i];
00155 }
00156 return B;
00157 }
00158
00160 template <class T>
00161 Array2D<T> operator*(const T& x, const Array2D<T>& A){
00162 Array2D<T> B(A.dim1(),A.dim2());
00163 for (int i=0;i<A.dim1();i++){
00164 for (int j=0;j<A.dim2();j++){
00165 B[i][j]=x*A[i][j];
00166 }
00167 }
00168 return B;
00169 }
00170
00172 template <class T>
00173 Array2D<T> uplow_block(Array2D<T> U, Array2D<T> L){
00174 if (U.dim2() != L.dim2()) {
00175 cerr<<"In uplow_block: upper and lower matrices have different dim2!\n";
00176 exit(-1);
00177 }
00178 Array2D<T> M(U.dim1()+L.dim1(),U.dim2());
00179 for (int j=0;j<U.dim2();j++){
00180 int i=0;
00181 for (int k=0;k<U.dim1();k++){
00182 M[i][j]=U[k][j];i++;
00183 }
00184 for (int k=0;k<L.dim1();k++){
00185 M[i][j]=L[k][j];i++;
00186 }
00187 }
00188 return M;
00189 }
00190
00192 template <class T>
00193 Array2D<T> leftright_block(Array2D<T> L, Array2D<T> R){
00194 if (L.dim1() != R.dim1()) {
00195 cerr<<"In leftright_block: left and right matrices have different dim1!\n";
00196 exit(-1);
00197 }
00198 Array2D<T> M(L.dim1(),L.dim2()+R.dim2());
00199 for (int j=0;j<L.dim1();j++){
00200 int i=0;
00201 for (int k=0;k<L.dim2();k++){
00202 M[j][i]=L[j][k];i++;
00203 }
00204 for (int k=0;k<R.dim2();k++){
00205 M[j][i]=R[j][k];i++;
00206 }
00207 }
00208 return M;
00209 }
00210
00212 template <class T>
00213 Array1D<T> uplow_block(Array1D<T> U, Array1D<T> L){
00214 Array1D<T> V(U.dim1()+L.dim1());
00215 int i=0;
00216 for (int k=0;k<U.dim1();k++){
00217 V[i]=U[k];i++;
00218 }
00219 for (int k=0;k<L.dim1();k++){
00220 V[i]=L[k];i++;
00221 }
00222 return V;
00223 }
00224
00226 template <class T>
00227 Array2D<T> svdinvert(const Array2D<T>& A){
00228 Array2D<T> v,u;
00229 Array1D<T> w;
00230
00231
00232 SVD<T> decomp(A);
00233 decomp.getU(u);
00234 decomp.getV(v);
00235 decomp.getSingularValues(w);
00236
00237
00238 int r=0;
00239
00240 T cutoff_condition=1.0/(EPSILON*A.dim1());
00241 if (decomp.cond()>cutoff_condition) {
00242 cout << "svdinvert: Condition number = "<<decomp.cond();
00243 cout << ", failed condition number test, pruning singular values\n";
00244 cout << "svdinvert: Singular values are: ";
00245 for (int i=0;i<w.dim();i++) {cout << w[i] << " ";}cout <<endl;
00246 T minw=w[0]/cutoff_condition;
00247 for (int i=w.dim()-1;i >=0; i--){
00248 if (abs(w[i]) < minw) {w[i]=0.0;r++;}
00249 }
00250 }
00251 if (r!=0) cout << "svdinvert: Effective rank = "<<w.dim()-r<<endl;
00252
00253
00254 Array2D<T> winv(w.dim(),w.dim());
00255 winv=0.0;
00256 for (int i=0;i<w.dim();i++) {if (w[i]!=0.0) {winv[i][i]=1.0/w[i];}}
00257
00258
00259 return matmult(v,matmult(winv,transpose(u)));
00260 }
00261
00262
00263
00264
00265
00266 template <class T>
00267 Array1D<T> CovmtxToErrors(const Array2D<T>& M, const Array2D<T>& cov){
00268 if ((M.dim2() != cov.dim1())||(M.dim2() != cov.dim2())){
00269 cerr << "Incompatible dimensions in CovmtxToErrors!"<<endl;
00270 exit(-1);
00271 }
00272
00273 Array1D<T> ans(M.dim1(),0.0);
00274
00275 for (int i=0;i<M.dim1();i++){
00276 ans[i]=0.0;
00277 for (int j=0;j<M.dim2();j++){
00278 for (int k=0;k<M.dim2();k++){
00279 ans[i]+=M[i][j]*M[i][k]*cov[j][k];
00280 }
00281 }
00282 ans[i]=sqrt(ans[i]);
00283 }
00284 return ans;
00285 }
00286
00287 template <class T>
00288 Array2D<T> CovmtxToCovMtx(const Array2D<T>& M, const Array2D<T>& cov){
00289 if ((M.dim2() != cov.dim1())||(M.dim2() != cov.dim2())){
00290 cerr << "Incompatible dimensions in CovmtxToCovMtx!"<<endl;
00291 exit(-1);
00292 }
00293
00294 Array2D<T> ans(M.dim1(),M.dim1(),0.0);
00295
00296 for (int i=0;i<M.dim1();i++){
00297 for (int j=0;j<M.dim2();j++){
00298 ans[i][j]=0.0;
00299 for (int k=0;k<M.dim2();k++){
00300 for (int l=0;k<M.dim2();k++){
00301 ans[i][j]+=M[i][k]*M[j][l]*cov[k][l];
00302 }
00303 }
00304 }
00305 }
00306 return ans;
00307 }
00308
00309 template <class T>
00310 Array2D<T> ErrorsToCovmtx(const Array2D<T>& M, const Array1D<T>& err){
00311 if (M.dim2() != err.dim()){
00312 cerr << "Incompatible dimensions in ErrorsToCovmtx!"<<endl;
00313 exit(-1);
00314 }
00315 Array2D<T> ans(M.dim1(),M.dim1(),0.0);
00316
00317 for (int i=0;i<M.dim1();i++){
00318 for (int j=0;j<M.dim1();j++){
00319 ans[i][j]=0.0;
00320 for (int k=0;k<err.dim();k++){
00321 ans[i][j]+=M[i][k]*M[j][k]*err[k]*err[k];
00322 }
00323 }
00324 }
00325 return ans;
00326 }
00327
00328 template <class T>
00329 Array2D<T> makeDiag(const Array1D<T>& d){
00330 Array2D<T> ans(d.dim(),d.dim(),0.);
00331 for (int i=0;i<d.dim();i++){
00332 ans[i][i]=d[i];
00333 }
00334 return ans;
00335 }
00336
00337 template <class T>
00338 Array2D<T> makeDiagSquared(const Array1D<T>& d){
00339 Array2D<T> ans(d.dim(),d.dim(),0.);
00340 for (int i=0;i<d.dim();i++){
00341 ans[i][i]=d[i]*d[i];
00342 }
00343 return ans;
00344 }
00345
00346 #endif