| 
									
										
										
										
											2010-07-05 07:50:21 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * SPQRUtil.cpp | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   Created on: Jul 1, 2010 | 
					
						
							|  |  |  |  *       Author: nikai | 
					
						
							|  |  |  |  *  Description: the utility functions for SPQR | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <map>
 | 
					
						
							|  |  |  | #include "SPQRUtil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #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-05 07:50:21 +08:00
										 |  |  | 		for(j = 0; j < min(m,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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	void householder_spqr(Matrix &A, long* Stair) { | 
					
						
							|  |  |  | 		long m = A.size1(); | 
					
						
							|  |  |  | 		long n = A.size2(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (Stair == NULL) { | 
					
						
							|  |  |  | 			Stair = new long[n]; | 
					
						
							|  |  |  | 			for(int j=0; j<n; j++) | 
					
						
							|  |  |  | 				Stair[j] = m; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// convert from row major to column major
 | 
					
						
							|  |  |  | 		double a[m*n]; int k = 0; | 
					
						
							|  |  |  | 		for(int j=0; j<n; j++) | 
					
						
							|  |  |  | 			for(int i=0; i<m; i++, k++) | 
					
						
							|  |  |  | 				a[k] = A(i,j); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		long npiv = min(m,n); | 
					
						
							|  |  |  | 		double tol = -1;	long ntol = -1; // no tolerance is used
 | 
					
						
							|  |  |  | 		long fchunk = m < 32 ? m : 32; | 
					
						
							|  |  |  | 		char Rdead[npiv]; | 
					
						
							|  |  |  | 		double Tau[n]; | 
					
						
							|  |  |  | 		long b = min(fchunk, min(n, m)); | 
					
						
							|  |  |  | 		double W[b*(n+b)]; | 
					
						
							|  |  |  | 		double wscale = 0; | 
					
						
							|  |  |  | 		double wssq = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cholmod_common cc; | 
					
						
							|  |  |  | 		cholmod_l_start(&cc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		long rank = spqr_front<double>(m, n, npiv, tol, ntol, fchunk, | 
					
						
							|  |  |  | 				a, Stair, Rdead, Tau, W, &wscale, &wssq, &cc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		long k0 = 0; | 
					
						
							|  |  |  | 		long j0; | 
					
						
							|  |  |  | 		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]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		delete []Stair; | 
					
						
							|  |  |  | 		cholmod_l_finish(&cc); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace gtsam
 | 
					
						
							|  |  |  | #endif
 |