| 
									
										
										
										
											2010-10-14 12:54:38 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation,  | 
					
						
							|  |  |  |  * Atlanta, Georgia 30332-0415 | 
					
						
							|  |  |  |  * All Rights Reserved | 
					
						
							|  |  |  |  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * See LICENSE for the license information | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |  * DenseQRUtil.cpp | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  *   Created on: Jul 1, 2010 | 
					
						
							|  |  |  |  *       Author: nikai | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |  *  Description: the utility functions for DenseQR | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 17:17:43 +08:00
										 |  |  | #include <cstring>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <gtsam/base/timing.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | #include <gtsam/base/DenseQRUtil.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <boost/numeric/ublas/matrix.hpp>
 | 
					
						
							|  |  |  | #include <boost/numeric/ublas/matrix_proxy.hpp>
 | 
					
						
							|  |  |  | #include <boost/numeric/ublas/triangular.hpp>
 | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | namespace ublas = boost::numeric::ublas; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef GT_USE_LAPACK
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	long* MakeStairs(Matrix& A) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const long m = A.size1(); | 
					
						
							|  |  |  | 		const long n = A.size2(); | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 		long* Stair = new long[n]; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// record the starting pointer of each row
 | 
					
						
							|  |  |  | 		double* a[m]; | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 		list<int> remained; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		a[0] = A.data().begin(); | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 		for(int i=0; i<m-1; i++) { | 
					
						
							|  |  |  | 			a[i+1] = a[i] + n; | 
					
						
							|  |  |  | 			remained.push_back(i); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		remained.push_back(m-1); | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 		// reorder the rows
 | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		int j; | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 		vector<int> sorted; | 
					
						
							|  |  |  | 		list<int>::iterator itRemained; | 
					
						
							| 
									
										
										
										
											2010-07-20 14:12:10 +08:00
										 |  |  | 		for(j = 0; j < n; ) { | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 			// remove the non-zero rows in the current column
 | 
					
						
							|  |  |  | 			for(itRemained = remained.begin(); itRemained!=remained.end(); ) { | 
					
						
							|  |  |  | 				if (*(a[*itRemained]) != 0) { | 
					
						
							|  |  |  | 					sorted.push_back(*itRemained); | 
					
						
							|  |  |  | 					itRemained = remained.erase(itRemained); | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					a[*itRemained]++; | 
					
						
							|  |  |  | 					itRemained ++; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// record the stair number
 | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 			Stair[j++] = m - remained.size(); | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 			if(remained.empty()) break; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// all the remained columns have maximum stair
 | 
					
						
							|  |  |  | 		for (; j<n; j++) | 
					
						
							|  |  |  | 			Stair[j] = m; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-06 13:18:21 +08:00
										 |  |  | 		// copy the new row
 | 
					
						
							|  |  |  | 		Matrix A_new = zeros(m,n); | 
					
						
							|  |  |  | 		int offset[m]; | 
					
						
							|  |  |  | 		offset[0] = 0; | 
					
						
							|  |  |  | 		for(int i=1; i<m; i++) | 
					
						
							|  |  |  | 			offset[i] = offset[i-1] +n; | 
					
						
							|  |  |  | 		vector<int>::const_iterator itSorted; | 
					
						
							|  |  |  | 		double* ptr1 = A.data().begin(); | 
					
						
							|  |  |  | 		double* ptr2 = A_new.data().begin(); | 
					
						
							|  |  |  | 		int row = 0, sizeOfRow = n * sizeof(double); | 
					
						
							|  |  |  | 		for(itSorted=sorted.begin(); itSorted!=sorted.end(); itSorted++, row++) | 
					
						
							|  |  |  | 			memcpy(ptr2+offset[row], ptr1+offset[*itSorted], sizeOfRow); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		A = A_new; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		return Stair; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void printColumnMajor(const double* a, const long m, const long n) { | 
					
						
							|  |  |  | 		for(int i=0; i<m; i++) { | 
					
						
							|  |  |  | 			for(int j=0; j<n; j++) | 
					
						
							|  |  |  | 				cout << a[j*m+i] << "\t"; | 
					
						
							|  |  |  | 			cout << endl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | 	void householder_denseqr(Matrix &A, long* Stair) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | 	  tic("householder_denseqr"); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		long m = A.size1(); | 
					
						
							|  |  |  | 		long n = A.size2(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		bool allocedStair = false; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		if (Stair == NULL) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		  allocedStair = true; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 			Stair = new long[n]; | 
					
						
							|  |  |  | 			for(int j=0; j<n; j++) | 
					
						
							|  |  |  | 				Stair[j] = m; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | 		tic("householder_denseqr: row->col"); | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		// convert from row major to column major
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		ublas::matrix<double, ublas::column_major> Acolwise(A); | 
					
						
							|  |  |  | 		double *a = Acolwise.data().begin(); | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |     toc("householder_denseqr: row->col"); | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |     tic("householder_denseqr: denseqr_front"); | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		long npiv = min(m,n); | 
					
						
							|  |  |  | 		double tol = -1;	long ntol = -1; // no tolerance is used
 | 
					
						
							|  |  |  | 		long fchunk = m < 32 ? m : 32; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		char Rdead[npiv];  memset(Rdead, 0, sizeof(char)*npiv); | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		double Tau[n]; | 
					
						
							|  |  |  | 		long b = min(fchunk, min(n, m)); | 
					
						
							|  |  |  | 		double W[b*(n+b)]; | 
					
						
							|  |  |  | 		double wscale = 0; | 
					
						
							|  |  |  | 		double wssq = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		// todo: do something with the rank
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | 		long rank = DenseQR(m, n, npiv, tol, ntol, fchunk, | 
					
						
							|  |  |  | 				a, Stair, Rdead, Tau, W, &wscale, &wssq); | 
					
						
							|  |  |  |     toc("householder_denseqr: denseqr_front"); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 00:32:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		for(long j=0; j<npiv; ++j) | 
					
						
							|  |  |  | 		  if(Rdead[j]) { | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | 		    cout << "In householder_denseqr, aborting because some columns were found to be\n" | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		        "numerically linearly-dependent and we cannot handle this case yet." << endl; | 
					
						
							|  |  |  | 		    print(A, "The matrix being factored was\n"); | 
					
						
							|  |  |  | 		    ublas::matrix_range<ublas::matrix<double,ublas::column_major> > Acolsub( | 
					
						
							|  |  |  | 		        ublas::project(Acolwise, ublas::range(0, min(m,n)), ublas::range(0,n))); | 
					
						
							|  |  |  | 		    print(Matrix(ublas::triangular_adaptor<typeof(Acolsub), ublas::upper>(Acolsub)), "and the result was\n"); | 
					
						
							|  |  |  | 		    cout << "The following columns are \"dead\":"; | 
					
						
							|  |  |  | 		    for(long k=0; k<npiv; ++k) | 
					
						
							|  |  |  | 		      if(Rdead[k]) cout << " " << k; | 
					
						
							|  |  |  | 		    cout << endl; | 
					
						
							|  |  |  | 		    exit(1); | 
					
						
							|  |  |  | 		  } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |     tic("householder_denseqr: col->row"); | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		long k0 = 0; | 
					
						
							|  |  |  | 		long j0; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		int k; | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 		memset(A.data().begin(), 0, m*n*sizeof(double)); | 
					
						
							|  |  |  | 		for(long j=0; j<n; j++, k0+=m) { | 
					
						
							|  |  |  | 			k = k0; | 
					
						
							|  |  |  | 			j0 = min(j+1,m); | 
					
						
							|  |  |  | 			for(int i=0; i<j0; i++, k++) | 
					
						
							|  |  |  | 				A(i,j) = a[k]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 00:32:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |     toc("householder_denseqr: col->row"); | 
					
						
							| 
									
										
										
										
											2010-09-25 21:46:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 00:32:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(allocedStair) delete[] Stair; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | 		toc("householder_denseqr"); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  | 	void householder_denseqr_colmajor(ublas::matrix<double, ublas::column_major>& A, long *Stair) { | 
					
						
							|  |  |  |     tic("householder_denseqr"); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     long m = A.size1(); | 
					
						
							|  |  |  |     long n = A.size2(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(Stair != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |     tic("householder_denseqr: denseqr_front"); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     long npiv = min(m,n); | 
					
						
							|  |  |  |     double tol = -1;  long ntol = -1; // no tolerance is used
 | 
					
						
							|  |  |  |     long fchunk = m < 32 ? m : 32; | 
					
						
							|  |  |  |     char Rdead[npiv];  memset(Rdead, 0, sizeof(char)*npiv); | 
					
						
							|  |  |  |     double Tau[n]; | 
					
						
							|  |  |  |     long b = min(fchunk, min(n, m)); | 
					
						
							|  |  |  |     double W[b*(n+b)]; | 
					
						
							|  |  |  |     double wscale = 0; | 
					
						
							|  |  |  |     double wssq = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // todo: do something with the rank
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |     long rank = DenseQR(m, n, npiv, tol, ntol, fchunk, | 
					
						
							|  |  |  |         A.data().begin(), Stair, Rdead, Tau, W, &wscale, &wssq); | 
					
						
							|  |  |  |     toc("householder_denseqr: denseqr_front"); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for(long j=0; j<npiv; ++j) | 
					
						
							|  |  |  |       if(Rdead[j]) { | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |         cout << "In householder_denseqr, aborting because some columns were found to be\n" | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |             "numerically linearly-dependent and we cannot handle this case yet." << endl; | 
					
						
							|  |  |  |         print(A, "The matrix being factored was\n"); | 
					
						
							|  |  |  |         ublas::matrix_range<ublas::matrix<double,ublas::column_major> > Acolsub( | 
					
						
							|  |  |  |             ublas::project(A, ublas::range(0, min(m,n)), ublas::range(0,n))); | 
					
						
							|  |  |  |         print(Matrix(ublas::triangular_adaptor<typeof(Acolsub), ublas::upper>(Acolsub)), "and the result was\n"); | 
					
						
							|  |  |  |         cout << "The following columns are \"dead\":"; | 
					
						
							|  |  |  |         for(long k=0; k<npiv; ++k) | 
					
						
							|  |  |  |           if(Rdead[k]) cout << " " << k; | 
					
						
							|  |  |  |         cout << endl; | 
					
						
							|  |  |  |         exit(1); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 12:21:58 +08:00
										 |  |  |     toc("householder_denseqr"); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace gtsam
 | 
					
						
							|  |  |  | #endif
 |