135 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|  * 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();
 | |
| 		long* Stair = new long[n];
 | |
| 
 | |
| 		// record the starting pointer of each row
 | |
| 		double* a[m];
 | |
| 		list<int> remained;
 | |
| 		a[0] = A.data().begin();
 | |
| 		for(int i=0; i<m-1; i++) {
 | |
| 			a[i+1] = a[i] + n;
 | |
| 			remained.push_back(i);
 | |
| 		}
 | |
| 		remained.push_back(m-1);
 | |
| 
 | |
| 		// reorder the rows
 | |
| 		int j;
 | |
| 		vector<int> sorted;
 | |
| 		list<int>::iterator itRemained;
 | |
| 		for(j = 0; j < min(m,n); ) {
 | |
| 			// 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 ++;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// record the stair number
 | |
| 			Stair[j++] = m - remained.size();
 | |
| 
 | |
| 			if(remained.empty()) break;
 | |
| 		}
 | |
| 
 | |
| 		// all the remained columns have maximum stair
 | |
| 		for (; j<n; j++)
 | |
| 			Stair[j] = m;
 | |
| 
 | |
| 		// 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;
 | |
| 
 | |
| 		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
 |