فهرست منبع

remvoed obsolete sparse example

Former-commit-id: d903a4d3a2583b885982cfdb57535b031a7011aa
jalec 13 سال پیش
والد
کامیت
da823d77c2

+ 0 - 17
examples/sparse/3x3.obj

@@ -1,17 +0,0 @@
-v 40.000000 40.000000 0.000000
-v 40.000000 200.000000 0.000000
-v 40.000000 360.000000 0.000000
-v 200.000000 40.000000 0.000000
-v 200.000000 200.000000 0.000000
-v 200.000000 360.000000 0.000000
-v 360.000000 40.000000 0.000000
-v 360.000000 200.000000 0.000000
-v 360.000000 360.000000 0.000000
-f 1 4 2
-f 4 5 2
-f 2 5 3
-f 5 6 3
-f 4 7 5
-f 7 8 5
-f 5 8 6
-f 8 9 6

+ 0 - 40
examples/sparse/IJV.h

@@ -1,40 +0,0 @@
-// Templates: 
-template <typename I,typename V>
-struct IJV
-{
-  // Subscripts
-  I i,j;
-  // Value
-  V v;
-  IJV(int i, int j, double v)
-  {
-    this->i = i;
-    this->j = j;
-    this->v = v;
-  }
-  // Compare based on i then j
-  bool operator<(const IJV & B) const
-  {
-    if(this->i < B.i)
-    {
-      return true;
-    }else if(this->i > B.i)
-    {
-      return false;
-    }else
-    {
-      if(this->j < B.j)
-      {
-        return true;
-      }else if(this->j > B.j)
-      {
-        return false;
-      }else
-      {
-        // i and j are equal
-        return false;
-      }
-    }
-    return false;
-  }
-};

+ 0 - 24
examples/sparse/Makefile

@@ -1,24 +0,0 @@
-
-.PHONY: all
-
-all: example
-
-.PHONY: example
-
-igl_lib=-I../../
-eigen=-I/usr/local/include/eigen3 -I/usr/local/include/eigen3/unsupported
-
-#CFLAGS=-g
-CFLAGS=-Os -DNDEBUG
-inc=$(igl_lib) $(eigen)
-lib=
-
-example: example.o
-	g++ $(CFLAGS) -o example example.o $(lib)
-	rm example.o
-
-example.o: example.cpp SparseSolver.h
-	g++ $(CFLAGS) -c example.cpp -o example.o $(inc)
-clean:
-	rm -f example.o
-	rm -f example

+ 0 - 2
examples/sparse/README

@@ -1,2 +0,0 @@
-This is a simple example comparing different methods of building a sparse
-cotangent matrix for a given mesh using Eigen.

+ 0 - 1601
examples/sparse/SparseSolver.h

@@ -1,1601 +0,0 @@
-#define NO_TAUCS
-
-#ifdef NO_TAUCS
-  typedef double taucsType;
-#  include <vector>
-#  include <map>
-#else
-#  include "taucsaddon.h"
-#endif
-
-class SparseSolver {
-protected:
-	// is set to true iff m_A is symmetric positive definite
-	bool  m_SPD;
-        
-#ifndef NO_TAUCS
-	taucs_ccs_matrix * m_A;
-	taucs_ccs_matrix * m_AT;
-	taucs_ccs_matrix * m_ATA;
-#endif
-
-#ifndef NO_TAUCS
-	void * m_factorATA;
-	void * m_factorA;
-	void * m_etree; // for the factor update
-#endif
-	
-	// placeholder, so that we don't need to allocate space every time
-	// the space is allocated when a factor for ATA is created
-	std::vector<taucsType> m_ATb;
-
-	// helper map to create A
-	std::vector< std::map<int,taucsType> > m_colsA;
-
-	// the dimensions of the A matrix
-	int m_numRows;
-	int m_numCols; 
-
-public:
-
-	SparseSolver(const int numRows = 0, const int numCols = 0, const bool isSPD = false) 
-		: 
-		m_SPD(isSPD)
-                ,
-#ifndef NO_TAUCS
-                  m_A(NULL)
-		, m_AT(NULL)
-		, m_ATA(NULL)
-		, m_factorATA(NULL)
-		, m_factorA(NULL)
-		, m_etree(NULL)
-		, m_ATb(NULL)
-		, 
-#endif
-		  m_colsA(numCols)
-                , m_numRows(numRows)
-		, m_numCols(numCols)
-	{};
-
-	~SparseSolver() { ClearObject();}
-
-//Operators
-public:
-	/** Copies the matrix.
-
-		However, factorizations are not copied.
-		This is because the factorizations are actually owned by taucs
-		and we have to call taucs to release them.
-		If we would release them from two different objects,
-		we would run into trouble.
-	*/
-	SparseSolver& operator=(const SparseSolver& other)
-	{
-		//Reset ourselves
-		Reset(other.GetNumRows(), other.GetNumColumns());
-
-		//Copy the sparse matrix
-		m_colsA = other.m_colsA;
-		m_SPD = other.m_SPD;
-		m_numRows = other.m_numRows;
-		m_numCols = other.m_numCols;
-
-		return *this;
-	}
-
-//Methods
-public:
-
-	///Resets all internal data structures and sets the new size of this matrix
-	void Reset(const int numRows, const int numCols);
-
-	///Returns the number of rows of the \c A matrix.
-	inline int GetNumRows() const {return m_numRows;}
-
-	///Returns the number of columns of the \c A matrix.
-	inline int GetNumColumns() const {return m_numCols;}
-
-	///Returns the dimensions of the \c A matrix.
-	inline void GetAMatrixSize(int & numRows, int & numCols) const
-	{
-		numRows = m_numRows;
-		numCols = m_numCols;
-	}
-
-	///Returns true if no rows or columns are in the matrix.
-	inline bool IsEmpty() const {return m_numRows == 0 || m_numCols == 0;}
-
-	///Clears all data structures.
-	void ClearObject();
-
-	// adds a new entry to the sparse matrix A
-	// i and j are 0-based
-	// if the A^T A matrix had been factored, this will destroy the factor
-	void AddIJV(const int i, const int j, const taucsType v);
-
-	// updates the entry in A by adding the value v to the current value
-	// i and j are 0-based
-	// if the A^T A matrix had been factored, this will destroy the factor
-	void AddToIJV(const int i, const int j, const taucsType v);
-
-        // updates the entries in A by adding the values v in B to the current
-        // Value
-	// if the A^T A matrix had been factored, this will destroy the factor
-	void AddMatrix(SparseSolver & B);
-        // updates the entries in A by adding the values v in B to the current
-        // Value in A offset by (i,j)
-        // like matlab's A[i:m,j:n] = B, where [m,n] = size(B);
-        // i and j are 0-based
-	// if the A^T A matrix had been factored, this will destroy the factor
-	void AddMatrix(const int i, const int j, SparseSolver & B);
-
-	///Removes all entries from the given row.
-	///If the A^T A matrix had been factored, this will destroy the factor.
-	inline bool ClearRow(const int iRow)
-	{
-		if (iRow >= 0 && iRow < m_numRows)
-		{
-#ifndef NO_TAUCS
-			ClearFactorATA();
-			ClearFactorA();
-			ClearMatricesATA();
-			ClearMatricesA();
-#endif
-
-			//Go over all columns, try to find the respective row and delete it
-			for(std::vector< std::map<int,taucsType> >::iterator itCol=m_colsA.begin();itCol!=m_colsA.end();itCol++)
-			{
-				//Find the row
-				std::map<int,taucsType>::iterator itRow = itCol->find(iRow);
-				if (itRow != itCol->end())
-				{
-					itCol->erase(itRow);
-				}
-			}
-
-			return true;
-		}
-
-		return false;
-	}
-
-	///Removes all entries from the given column.
-	///If the A^T A matrix had been factored, this will destroy the factor.
-	inline bool ClearColumn(const int iColumn)
-	{
-		if (iColumn >= 0 && iColumn < m_numCols)
-		{
-#ifndef NO_TAUCS
-			ClearFactorATA();
-			ClearFactorA();
-			ClearMatricesATA();
-			ClearMatricesA();
-#endif
-
-			m_colsA[iColumn].clear();
-			return true;
-		}
-
-		return false;
-	}
-
-	// Sets the status of a matrix - whether SPD or not
-	void SetSPD(bool isSPD) {m_SPD = isSPD;}
-        // Return true only if symmetric, automatically true if isSPD flag is
-        // set to true, otherwise actually determine if matrix is symmetric
-        bool IsSymmetric();
-
-#ifndef NO_TAUCS
-	// allows to add an anchored vertex without destroying the factor, if there was one
-	// i is the anchor's number (i.e. the index of the mesh vertex that is anchored is i)
-	// w is the weight of the anchor in the original Ax=b system. HAS TO BE POSITIVE!!
-	// if there was no factor for A^T A, this will simply add an anchor row to the Ax=b system
-	// if there was a factor, the factor will be updated, approximately at the cost of
-	// a single solve.
-	void AddAnchor(const int i, const taucsType w);
-
-	// Will create A^T A and its factorization, as well as store A^T
-	// returns true on success, false otherwise
-	bool FactorATA();
-
-	// Will create A and its factorization. If A is spd then Cholesky factor, otherwise LU
-	// returns true on success, false otherwise
-	// Assumes A is square and invertible
-	bool FactorA();
-	// Will create *symbolic* factorization of ATA and return it; returns NULL on failure
-	void * SymbolicFactorATA();
-
-	taucs_ccs_matrix * GetATA_Copy();
-
-	// Will create the actual numerical factorization of the present ATA matrix
-	// with the same non-zero pattern as created by SymbolicFactorATA()
-	bool FactorATA_UseSymbolic(void * symbFactor,
-	  taucs_ccs_matrix ** PAP,
-	  int * perm,
-	  int * invperm);
-
-	// Solves the normal equations for Ax = b, namely A^T A x = A^T b
-	// it is assumed that enough space is allocated in x
-	// Uses the factorization provided in factor
-	// numRhs should be the the number of right-hand sides stored in b (and respectively,
-	// there should be enough space allocated in the solution vector x)
-	// returns true on success, false otherwise
-	bool SolveATA_UseFactor(void * factor, 
-							taucs_ccs_matrix * PAP,
-							int * perm,
-							int * invperm,
-							const taucsType * b, taucsType * x, const int numRhs);
-
-	// Solves the normal equations for Ax = b, namely A^T A x = A^T b
-	// it is assumed that enough space is allocated in x
-	// If a factorization of A^T A exists, it will be used, otherwise it will be created
-	// numRhs should be the the number of right-hand sides stored in b (and respectively,
-	// there should be enough space allocated in the solution vector x)
-	// returns true on success, false otherwise
-	bool SolveATA(const taucsType * b, taucsType * x, const int numRhs); 
-
-	// Same as SolveATA only that this solves the actual system Ax = b
-	// It is assumed that A is rectangular and invertible
-	bool SolveA(const taucsType * b, taucsType * x, const int numRhs); 
-
-	// The version of SolveATA with 3 right-hand sides
-	// returns true on success, false otherwise
-	bool SolveATA3(const taucsType * bx, const taucsType * by, const taucsType * bz,
-						 taucsType * x,        taucsType * y,        taucsType * z);
-
-	// The version of SolveATA with 2 right-hand sides
-	// returns true on success, false otherwise
-	bool SolveATA2(const taucsType * bx, const taucsType * by,
-						 taucsType * x,        taucsType * y);
-#endif
-
-// Matrix utility routines
-
-	// Stores the result of Matrix*v in result.
-	// v can have numCols columns; then the result is stored column-wise as well
-	// It is assumed space is allocaed in result!
-	// v cannot be the same pointer as result
-	void MultiplyMatrixVector(const taucsType * v, taucsType * result, const int numCols) const;
-
-	// Multiplies the matrix by diagonal matrix D from the left, stores the result
-	// in the columns of res
-	void MultiplyDiagMatrixMatrix(const taucsType * D, SparseSolver & res) const;
-
-	// Multiplies the matrix by the given matrix B from the right
-	// and stores the result in the columns of res
-	// isSPD tells us whether the result should be SPD or not
-	// retuns false if the dimensions didn't match (in such case res is unaltered), otherwise true
-	bool MultiplyMatrixRight(const SparseSolver & B, SparseSolver & res,const bool isSPD) const;
-
-	// Transposes the matrix 
-	// and stores the result in the columns of res
-	bool Transpose(SparseSolver & res) const;
-
-	// will remove the rows startInd-endInd (including ends, zero-based) from the matrix
-	// will discard any factors	
-	bool DeleteRowRange(const int startInd, const int endInd);
-
-	// will remove the columns startInd-endInd (including ends, zero-based) from the matrix
-	// will discard any factors	
-	bool DeleteColumnRange(const int startInd, const int endInd);
-
-	// copies columns startInd through endInd (including, zero-based) from the matrix to res matrix
-	// previous data in res, including factors, is erased.
-	bool CopyColumnRange(const int startInd, const int endInd, SparseSolver & res) const;
-
-	// copies rows startInd through endInd (including, zero-based) from the matrix to res matrix
-	// previous data in res, including factors, is erased.
-	bool CopyRowRange(const int startInd, const int endInd, SparseSolver & res) const;
-
-	///Multiplies the given range of rows (zero-based, including startInd and endInd) with the given scalar.
-	bool MultiplyRows(const int startInd, const int endInd, const taucsType val);
-
-	///Multiplies all entries of the matrix with the given scalar. Will discard any factors.
-	void MultiplyMatrixScalar(const taucsType val);
-
-	/** Computes IdentityMatrix minus this matrix in-place. Will discard any factors.
-
-		If an entry on the diagonal is missing, it will be created.
-	*/
-	void IdentityMinusMatrix();
-
-	/** Computes IdentityMatrix plus this matrix in-place. Will discard any factors.
-
-		If an entry on the diagonal is missing, it will be created.
-	*/
-	void IdentityPlusMatrix();
-
-        // Alec:
-        // Note on splice methods:
-        // The following splice methods act like matlabs splicing and
-        // reordering via index lists and the operator()
-        // Both SpliceColumns and SpliceRows are ignorant of SPD, meaning that
-        // they will not give "correct" splices for SPD matrices: splices of
-        // This only matters if you are not setting all
-        // SPD matrices are just splices of the lower triangle
-        //
-        // This only matters if you are not setting the upper half of the
-        // matrix. To get correct splices you need to set both upper and lower
-        // triangles before splicing.
-
-        // Alec:
-        // Copies certain cols in any order to a new matrix res
-        // Like in Matlab B = A(:,column_indices)
-        // Previous data in res is erased.
-        // Returns false on error. As in column_indices are invalid
-        // Result is always NOT SPD
-        //
-        // WARNING: If your matrix is only the lower half of an SPD matrix
-        // then the result will only be a copy of the lower half of the 
-        // spliced columns. See note above (Note on splice methods)
-        bool SpliceColumns(
-            const std::vector<size_t> column_indices, 
-            SparseSolver & res) const;
-
-        // Alec:
-        // Copies certain rows in any order to a new matrix res
-        // Like in Matlab B = A(:,row_indices)
-        // Previous data in res is erased.
-        // Returns false on error. As in row_indices are invalid
-        // Result is always NOT SPD
-        //
-        // WARNING: If your matrix is only the lower half of an SPD matrix
-        // then the result will only be a copy of the lower half of the 
-        // spliced rows. See note above (Note on splice methods)
-        bool SpliceRows(
-            const std::vector<size_t> row_indices, 
-            SparseSolver & res) const;
-
-        // Wrapper than calls 
-        //   SpliceColumns(column_indices, temp) 
-        //   then 
-        //   temp.SpliceRows(row_indices, res);
-        bool SpliceColumnsThenRows(
-            const std::vector<size_t> column_indices, 
-            const std::vector<size_t> row_indices, 
-            SparseSolver & res) const;
-
-        // Vertical concatenation, works like matlab:
-        // C = [A ; B];
-        // If this matrix is A in the above the result is the concatenation of
-        // this matrix on top of the supplied other matrix into the result
-        // number of columns in A must equal number of columns in B
-        //
-        bool VerticalConcatenation(
-            SparseSolver & other,
-            SparseSolver & res);
-        // Convert the matrix to IJV aka Coordinate format,
-        // Outputs:
-        //   vals             non-zero values, in no particular order
-        //   row_indices      row indices corresponding to vals
-        //   column_indices   column indices corresponding to vals
-        //
-        // All indices are 0-based
-        void ConvertToIJV(
-          std::vector<int> & row_indices,
-          std::vector<int> & column_indices,
-          std::vector<taucsType> & vals);
-
-        // Convert lower triangle (including diagonal) of the matrix to IJV aka
-        // Coordinate format,
-        // Outputs:
-        //   vals             non-zero values, in no particular order
-        //   row_indices      row indices corresponding to vals
-        //   column_indices   column indices corresponding to vals
-        //
-        // All indices are 0-based
-        void ConvertLowerTriangleToIJV(
-          std::vector<int> & row_indices,
-          std::vector<int> & column_indices,
-          std::vector<taucsType> & vals);
-
-        // Convert the matrix to Compressed sparse column (CSC or CCS) format,
-        // also known as Harwell Boeing format. As described:
-        // http://netlib.org/linalg/html_templates/node92.html
-        // or
-        // http://en.wikipedia.org/wiki/Sparse_matrix
-        //   #Compressed_sparse_column_.28CSC_or_CCS.29
-        // Outputs:
-        //   nnz              number of non zero entries
-        //   num_rows         number of rows
-        //   num_cols         number of cols
-        //   vals             non-zero values, row indices running fastest,
-        //                    size(vals) = nnz 
-        //   row_indices      row indices corresponding to vals, 
-        //                    size(row_indices) = nnz
-        //   column_pointers  index in vals of first entry in each column, 
-        //                    size(column_pointers) = num_cols+1
-        //
-        // All indices and pointers are 0-based
-        void ConvertToHarwellBoeing(
-          int & nnz,
-          int & num_rows,
-          int & num_cols,
-          std::vector<taucsType> & vals,
-          std::vector<int> & row_indices,
-          std::vector<int> & column_pointers);
-
-#ifdef PRINTMODE
-        // Print the matrix in IJV form
-        void PrintIJV();
-#endif
-
-protected:
-#ifndef NO_TAUCS
-	// Will create ATA matrix and AT matrix (in ccs format).
-	void CreateATA();
-	// Will create A matrix (in ccs format)
-	void CreateA();
-
-	void ClearFactorATA();
-	void ClearFactorA();
-	void ClearMatricesATA(); // clears m_A, m_ATA, m_AT
-	void ClearMatricesA(); // clears the m_A matrix
-#endif
-};
-
-
-#ifdef PRINTMODE
-#include <cstdio>
-inline void SparseSolver::PrintIJV(){
-  std::map<int,taucsType>::iterator it;
-  for (int c = 0; c < m_numCols; ++c) 
-  {
-    it = m_colsA[c].begin();
-    while (it != m_colsA[c].end())
-    {
-      printf("%d %d %g\n",it->first,c, it->second);
-      ++it;
-    }
-  }
-}
-#endif
-
-
-inline void SparseSolver::ClearObject() {
-#ifndef NO_TAUCS
-	ClearFactorATA();
-	ClearFactorA();
-	ClearMatricesATA();
-	ClearMatricesA();
-
-	m_ATb.clear();
-	m_etree = NULL;
-#endif
-	m_numCols = 0;
-	m_numRows = 0;
-	m_colsA.clear();
-}
-
-// adds a new entry to the sparse matrix A
-// i and j are 0-based
-// if the A^T A matrix had been factored, this will destroy the factor
-inline void SparseSolver::AddIJV(const int i, const int j, const taucsType v) {
-#ifndef NO_TAUCS
-	ClearFactorATA();
-	ClearFactorA();
-	ClearMatricesATA();
-	ClearMatricesA();
-#endif
-
-	m_colsA[j][i] = v;
-
-	// update number of rows
-	if ((i+1) > m_numRows)
-		m_numRows = i+1;
-}
-
-// updates the entry in A by adding the value v to the current value
-// i and j are 0-based
-// if the A^T A matrix had been factored, this will destroy the factor
-inline void SparseSolver::AddToIJV(const int i, const int j, const taucsType v) {
-#ifndef NO_TAUCS
-	ClearFactorATA();
-	ClearFactorA();
-	ClearMatricesATA();
-	ClearMatricesA();
-#endif
-
-	// if no such entry existed
-	if (m_colsA[j].find(i) == m_colsA[j].end())
-		m_colsA[j][i] = 0;
-
-	m_colsA[j][i] += v;
-
-	// update number of rows
-	if ((i+1) > m_numRows)
-		m_numRows = i+1;
-}
-
-#ifndef NO_TAUCS
-inline taucs_ccs_matrix * SparseSolver::GetATA_Copy() {
-	if (! m_ATA) {
-		CreateATA();
-	}
-
-	return MatrixCopy(m_ATA);
-}
-#endif
-
-// Implementation
-#define PRINTMODE
-
-#ifndef NO_TAUCS
-extern "C" {
-    void chol_update(void *vF, int index, double val,void**vetree);
-}
-#endif
-
-void SparseSolver::Reset(const int numRows, const int numCols)
-{
-	ClearObject();
-	m_numRows = numRows;
-	m_numCols = numCols;
-	m_colsA.resize(m_numCols);
-}
-
-
-#ifndef NO_TAUCS
-// Will create A^T A and its factorization, as well as store A^T
-// returns true on success, false otherwise
-bool SparseSolver::FactorATA() {
-	if (m_SPD)
-		return FactorA();
-
-	ClearFactorATA();
-	if (m_ATA == NULL)
-		CreateATA();
-
-	// factorization
-	int	rc = taucs_linsolve(m_ATA, &m_factorATA,0,NULL,NULL,SIVANfactor,SIVANopt_arg);
-	if (rc != TAUCS_SUCCESS) 
-		return false;
-
-	return true;
-}
-
-
-// Will create ATA matrix and AT matrix.
-// returns true on success, false otherwise
-void SparseSolver::CreateATA() {
-	if (m_A == NULL)
-		CreateA();
-
-	ClearMatricesATA();
-
-	if (m_SPD) {
-		// don't need to multiply because m_A is invertible and symmetric
-		return;
-	}
-	else {
-		m_AT = MatrixTranspose(m_A);
-		// Multiply to get ATA:
-		m_ATA = Mul2NonSymmMatSymmResult(m_AT, m_A);
-	}
-}
-
-// Will create A matrix (in ccs format)
-void SparseSolver::CreateA() {
-	ClearMatricesA();
-
-	if (m_SPD) 
-		m_A = CreateTaucsMatrixFromColumns(m_colsA, m_numRows, TAUCS_DOUBLE|TAUCS_SYMMETRIC|TAUCS_LOWER);
-	else
-		m_A = CreateTaucsMatrixFromColumns(m_colsA, m_numRows, TAUCS_DOUBLE);
-}
-
-
-// Will create *symbolic* factorization of ATA and return it; returns NULL on failure
-void * SparseSolver::SymbolicFactorATA() {
-	if (m_SPD) {
-		if (m_A == NULL)
-			CreateA();
-
-		return taucs_ccs_factor_llt_symbolic(m_A);
-	}
-	else {
-		if (m_ATA == NULL)
-			CreateATA();
-
-		return taucs_ccs_factor_llt_symbolic(m_ATA);
-	}
-}
-// Will create the actual numerical factorization of the present ATA matrix
-// with the same non-zero pattern as created by SymbolicFactorATA()
-bool SparseSolver::FactorATA_UseSymbolic(void * symbFactor,
-										 taucs_ccs_matrix ** PAP,
-										 int * perm,
-										 int * invperm) 
-{	
-	if (m_SPD) {
-		if (m_A == NULL)
-			CreateA();
-
-		*PAP = taucs_ccs_permute_symmetrically(m_A, perm, invperm);
-	}
-	else {
-		if (m_ATA == NULL)
-			CreateATA();
-
-		*PAP = taucs_ccs_permute_symmetrically(m_ATA, perm, invperm);
-	}
-
-	// compute numerical factorization
-	if (taucs_ccs_factor_llt_numeric(*PAP, symbFactor) != 0)	{
-		return false;
-	}
-	else {
-		return true;	
-	}
-}
-
-// Will create A and its factorization. If A is spd Cholesky factor, otherwise LU
-// returns true on success, false otherwise
-// Assumes A is square and invertible
-bool SparseSolver::FactorA() {
-	ClearFactorA();
-
-	if (m_A == NULL)
-		CreateA();
-
-	// factorization
-	int	rc;
-	if (m_SPD)
-		rc = taucs_linsolve(m_A, &m_factorA,0,NULL,NULL,SIVANfactor,SIVANopt_arg);
-	else
-		rc = taucs_linsolve(m_A, &m_factorA,0,NULL,NULL,SIVANfactorLU,SIVANopt_arg);
-
-	if (rc != TAUCS_SUCCESS) 
-		return false;
-
-	return true;
-}
-
-// Solves the normal equations for Ax = b, namely A^T A x = A^T b
-// it is assumed that enough space is allocated in x
-// Uses the factorization provided in factor
-// numRhs should be the the number of right-hand sides stored in b (and respectively,
-// there should be enough space allocated in the solution vector x)
-// returns true on success, false otherwise
-bool SparseSolver::SolveATA_UseFactor(void * factor, 
-									  taucs_ccs_matrix * PAP,
-									  int * perm,
-									  int * invperm,
-									  const taucsType * b, taucsType * x, const int numRhs) {
-	if (factor == NULL) {
-		return false;
-	}
-
-	if (! m_SPD) {
-		// prepare right-hand side
-		if ((int)m_ATb.size() != m_numCols*numRhs)
-			m_ATb.resize(m_numCols*numRhs);
-
-		// multiply right-hand side
-		for (int i = 0; i < numRhs; ++i) {
-			MulMatrixVector(m_AT, b + i*m_numRows, (taucsType *)&(m_ATb.front()) + i*m_numCols);
-		}
-	}
-
-	//	 solve the system:
-	std::vector<taucsType>  PB(m_numCols*numRhs), PX(m_numCols*numRhs);
-
-	// permute rhs
-	for (int c = 0; c < numRhs; ++c) {
-		taucsType * curPB = &PB[0] + c*m_numCols;
-		const taucsType * curB = (m_SPD)? (b + c*m_numCols) : (&(m_ATb.front()) + c*m_numCols);
-
-		for (int i=0; i<m_numCols; ++i)
-			curPB[i] = curB[perm[i]];
-	}
-
-	// solve by back-substitution
-	int rc;
-	for (int c = 0; c < numRhs; ++c) {
-		rc = taucs_supernodal_solve_llt(factor, &PX[0] + c*m_numCols, &PB[0] + c*m_numCols); 
-		if (rc != TAUCS_SUCCESS) {
-			return false;
-		}
-	}
-
-	// re-permute x
-	for (int c = 0; c < numRhs; ++c) {
-		taucsType * curX = x + c*m_numCols;
-		taucsType * curPX = &PX[0] + c*m_numCols;
-
-		for (int i=0; i<m_numCols; ++i)
-			curX[i] = curPX[invperm[i]];
-	}
-
-	return true;
-}
-
-
-// Solves the normal equations for Ax = b, namely A^T A x = A^T b
-// it is assumed that enough space is allocated in x
-// If a factorization of A^T A exists, it will be used, otherwise it will be created
-// numRhs should be the the number of right-hand sides stored in b (and respectively,
-// there should be enough space allocated in the solution vector x)
-// returns true on success, false otherwise
-bool SparseSolver::SolveATA(const taucsType * b, taucsType * x, const int numRhs) {
-	if (m_SPD) {
-		return SolveA(b, x, numRhs);
-	}
-	else {
-		if (m_factorATA == NULL) {
-			bool rc = FactorATA();
-			if (!rc)
-				return false;
-		}
-	}
-
-	// prepare right-hand side
-	if ((int)m_ATb.size() != m_numCols*numRhs)
-		m_ATb.resize(m_numCols*numRhs);
-
-	// multiply right-hand side
-	for (int i = 0; i < numRhs; ++i) {
-		MulMatrixVector(m_AT, b + i*m_numRows, (taucsType *)&(m_ATb.front()) + i*m_numCols);
-	}
-
-	int rc;
-	// solve the system
-	rc = taucs_linsolve(m_ATA,
-						&m_factorATA,
-						numRhs,
-						x,
-						(taucsType *)&(m_ATb.front()),
-						SIVANsolve,
-						SIVANopt_arg);
-	return (rc == TAUCS_SUCCESS); 
-}
-
-// Same as SolveATA only that this solves the actual system Ax = b
-// It is assumed that A is rectangular and invertible
-bool SparseSolver::SolveA(const taucsType * b, taucsType * x, const int numRhs) {
-	if (m_factorA == NULL) 
-		if (!FactorA())
-			return false;
-
-	// solve the system
-	int	rc = taucs_linsolve(m_A,
-							&m_factorA,
-							numRhs,
-							x,
-							(void *)b,
-							SIVANsolve,
-							SIVANopt_arg);
-
-	return (rc == TAUCS_SUCCESS);
-}
-
-// The version of SolveATA with 3 right-hand sides
-// returns true on success, false otherwise
-bool SparseSolver::SolveATA3(const taucsType * bx, const taucsType * by, const taucsType * bz,
-							       taucsType * x,        taucsType * y,        taucsType * z) 
-{
-	if (m_factorATA == NULL) {
-		bool rc = FactorATA();
-		if (!rc)
-			return false;
-	}
-
-	// prepare right-hand side
-	if ((int)m_ATb.size() != m_numCols*3)
-		m_ATb.resize(m_numCols*3);
-
-	// multiply right-hand side
-	MulMatrixVector(m_AT, bx, (taucsType *)&(m_ATb.front()));
-	MulMatrixVector(m_AT, by, (taucsType *)&(m_ATb.front()) + m_numCols);
-	MulMatrixVector(m_AT, bz, (taucsType *)&(m_ATb.front()) + 2*m_numCols);
-	
-
-	// solve the system
-	int	rc = taucs_linsolve(m_ATA,
-							&m_factorATA,
-							1,
-							x,
-							(taucsType *)&(m_ATb.front()),
-							SIVANsolve,
-							SIVANopt_arg);
-
-	if (rc != TAUCS_SUCCESS)
-		return false;
-
-	rc = taucs_linsolve(m_ATA,
-							&m_factorATA,
-							1,
-							y,
-							(taucsType *)&(m_ATb.front()) + m_numCols,
-							SIVANsolve,
-							SIVANopt_arg);
-
-	if (rc != TAUCS_SUCCESS)
-		return false;
-
-	rc = taucs_linsolve(m_ATA,
-							&m_factorATA,
-							1,
-							z,
-							(taucsType *)&(m_ATb.front()) +  2*m_numCols,
-							SIVANsolve,
-							SIVANopt_arg);
-
-	return (rc == TAUCS_SUCCESS);
-}
-
-// The version of SolveATA with 2 right-hand sides
-// returns true on success, false otherwise
-bool SparseSolver::SolveATA2(const taucsType * bx, const taucsType * by,
-								   taucsType * x,        taucsType * y)
-{
-	if (m_factorATA == NULL) {
-		bool rc = FactorATA();
-		if (!rc)
-			return false;
-	}
-
-	// prepare right-hand side
-	if ((int)m_ATb.size() != m_numCols*2)
-		m_ATb.resize(m_numCols*2);
-
-	// multiply right-hand side
-	MulMatrixVector(m_AT, bx, (taucsType *)&(m_ATb.front()));
-	MulMatrixVector(m_AT, by, (taucsType *)&(m_ATb.front()) + m_numCols);
-	
-
-	// solve the system
-	int	rc = taucs_linsolve(m_ATA,
-							&m_factorATA,
-							1,
-							x,
-							(taucsType *)&(m_ATb.front()),
-							SIVANsolve,
-							SIVANopt_arg);
-
-	if (rc != TAUCS_SUCCESS)
-		return false;
-
-	rc = taucs_linsolve(m_ATA,
-							&m_factorATA,
-							1,
-							y,
-							(taucsType *)&(m_ATb.front()) + m_numCols,
-							SIVANsolve,
-							SIVANopt_arg);
-
-	return (rc == TAUCS_SUCCESS);
-}
-
-void SparseSolver::ClearFactorATA() {
-	// release the factor
-	taucs_linsolve(NULL,&m_factorATA,0, NULL,NULL,SIVANfactor,SIVANopt_arg);
-	m_factorATA = NULL;
-	m_etree = NULL;
-}
-
-void SparseSolver::ClearFactorA() {
-	// release the factor
-	if (m_SPD)
-		taucs_linsolve(NULL,&m_factorA,0, NULL,NULL,SIVANfactor,SIVANopt_arg);
-	else
-		taucs_linsolve(NULL,&m_factorA,0, NULL,NULL,SIVANfactorLU,SIVANopt_arg);
-	m_factorA = NULL;
-
-}
-
-void SparseSolver::ClearMatricesATA() {
-	// free the matrices
-	taucs_free(m_AT);
-	m_AT = NULL;
-	taucs_free(m_ATA);
-	m_ATA = NULL;
-}
-
-void SparseSolver::ClearMatricesA() {
-	// free the matrices
-	taucs_free(m_A);
-	m_A = NULL;
-}
-#endif
-
-void SparseSolver::AddMatrix(SparseSolver & B)
-{
-  AddMatrix(0,0,B);
-}
-
-void SparseSolver::AddMatrix(const int i, const int j, SparseSolver & B)
-{
-  std::map<int,taucsType>::iterator it;
-  for (int c = 0; c < B.m_numCols; ++c) 
-  {
-    it = B.m_colsA[c].begin();
-    while (it != B.m_colsA[c].end())
-    {
-      // because AddToIJV is not O(1), this algorithm is O(Bnnz * Amaxrows),
-      // ideally it would be O(Bnnz)
-      AddToIJV(i+it->first,j+c,it->second);
-      ++it;
-    }
-  }
-}
-
-bool SparseSolver::IsSymmetric()
-{
-  if(m_SPD)
-  {
-    return true;
-  }
-
-  if(GetNumColumns() != GetNumRows())
-  {
-    return false;
-  }
-
-  // Cheapskate way to test if symmetric
-  SparseSolver AT;
-  if(!Transpose(AT))
-  {
-    return false;
-  }
-  // loop over columns
-  std::map<int,taucsType>::iterator it;
-  std::map<int,taucsType>::iterator ATit;
-  for (int c = 0; c < m_numCols; ++c) 
-  {
-    it = m_colsA[c].begin();
-    ATit = AT.m_colsA[c].begin();
-    while (it != m_colsA[c].end() && ATit !=AT.m_colsA[c].end())
-    {
-      if( it->first != ATit->first || it->second != ATit->second)
-      {
-        return false;
-      }
-      ++it;
-      ++ATit;
-    }
-  }
-  return true;
-
-}
-
-#ifndef NO_TAUCS
-// allows to add an anchored vertex without destroying the factor, if there was one
-// i is the anchor's number (i.e. the index of the mesh vertex that is anchored is i)
-// w is the weight of the anchor in the original Ax=b system. HAS TO BE POSITIVE!!
-// if there was no factor for A^T A, this will simply add an anchor row to the Ax=b system
-// if there was a factor, the factor will be updated, approximately at the cost of
-// a single solve.
-void SparseSolver::AddAnchor(const int i, const taucsType w) {
-	if (m_SPD) {
-		// update the columns
-		if (m_colsA[i].find(i) == m_colsA[i].end())
-			m_colsA[i][i] = w*w;
-		else
-			m_colsA[i][i] += w*w;
-
-		if (m_factorA != NULL) {
-			// the matrix is SPD so we update the factor of A
-			chol_update(m_factorA, i, w, &m_etree);
-			// update the matrix
-			m_A->taucs_values[ m_A->colptr[i] ] += w*w;
-		}
-	}
-	else {
-		m_colsA[i][m_numRows] = w;
-		m_numRows++;
-
-		if (m_factorATA != NULL) {
-			// update the ATA factor
-			chol_update(m_factorATA, i, w, &m_etree);
-			// update ATA
-			m_ATA->taucs_values[ m_ATA->colptr[i] ] += w*w;
-			// update A and AT (for multiplying rhs)
-			CreateA();
-			taucs_free(m_AT);
-            m_AT = MatrixTranspose(m_A);
-		}
-	}	 
-}
-#endif
-
-void SparseSolver::MultiplyMatrixVector(const taucsType * v, taucsType * result, const int numCols) const {
-	// make result all zero
-	memset(result, 0, m_numRows * numCols * sizeof(taucsType));
-
-	std::map<int,taucsType>::const_iterator iter;
-	int  offset_v;
-	int  offset_r;
-
-	if (m_SPD) { // the matrix is symmetric
-		for (int c = 0; c < numCols; ++c) {
-			offset_v = m_numCols*c;
-			for (int col = 0; col < m_numCols; ++col) {
-				// going over column col of the matrix, multiplying
-				// it by v[col] and setting the appropriate values
-				// of vector result; also mirroring the other triangle
-				for (iter = m_colsA[col].begin(); iter->first < col; ++iter) {
-					result[iter->first + offset_v]	+= v[col + offset_v]*(iter->second);
-					// mirroring
-					result[col + offset_v]			+= v[iter->first + offset_v]*(iter->second);
-				}
-				if (iter->first == col)
-					result[iter->first + offset_v]	+= v[col + offset_v]*(iter->second);
-			}
-		}
-	}
-	else {
-		for (int c = 0; c < numCols; ++c) {
-			offset_v = m_numCols*c;
-			offset_r = m_numRows*c;
-			for (int col = 0; col < m_numCols; ++col) {
-				// going over column col of the matrix, multiplying
-				// it by v[col] and setting the appropriate values
-				// of vector result
-				for (iter = m_colsA[col].begin(); iter != m_colsA[col].end(); ++iter) {
-					result[iter->first + offset_r] += v[col + offset_v]*(iter->second);
-				}
-			}
-		}
-	}
-}
-
-// Multiplies the matrix by diagonal matrix D from the left, stores the result
-// in the columns of res
-void SparseSolver::MultiplyDiagMatrixMatrix(const taucsType * D, SparseSolver & res) const {
-	res = SparseSolver(m_numRows, m_numCols, false);
-
-	std::map<int,taucsType>::const_iterator iterA;
-	std::map<int,taucsType>::iterator		iterRes;
-
-	res.m_colsA = m_colsA;
-	if (m_SPD) {
-		for (int col = 0; col < m_numCols; ++col) {
-			iterA = m_colsA[col].begin();
-			iterRes = res.m_colsA[col].begin();
-			for ( ; iterA != m_colsA[col].end() && iterA->first <= col; ++iterA, ++iterRes) {
-				iterRes->second = (iterA->second) * D[iterA->first];
-				// mirroring
-				res.m_colsA[iterA->first][col] = (iterA->second) * D[col];
-			}
-		}
-	}
-	else {
-		for (int col = 0; col < m_numCols; ++col) {
-			iterA	= m_colsA[col].begin();
-			iterRes = res.m_colsA[col].begin();
-			for ( ; iterA != m_colsA[col].end(); ++iterA, ++iterRes) {
-				iterRes->second = (iterA->second) * D[iterA->first];
-			}
-		}
-	}
-}
-
-// Multiplies the matrix by the given matrix B from the right
-// and stores the result in the columns of res
-// isSPD tells us whether the result should be SPD or not
-// retuns false if the dimensions didn't match (in such case res is unaltered), otherwise true
-bool SparseSolver::MultiplyMatrixRight(const SparseSolver & B, SparseSolver & res,const bool isSPD) const {
-	// for now ignore the option that one of the involved matrices is symmetric and doesn't have
-	// stored under-diagonal values in m_colsA
-	// we assume both matrices have all the values in m_colsA
-
-	// (m x n) * (n x k)
-	int m = m_numRows;
-	int n = m_numCols;
-	int k = B.m_numCols;
-
-	if (B.m_numRows != n)
-		return false;
-
-	std::map<int,taucsType>::const_iterator iterBi, iterA;
-	std::map<int,taucsType>::iterator iterRes;
-
-	int			rowInd;
-	taucsType	BiVal;
-
-	res = SparseSolver(m, k, isSPD);
-	for (int i = 0; i < k; ++i) { // go over the columns of res; res(i) = A*B(i)
-		for (iterBi = B.m_colsA[i].begin(); iterBi != B.m_colsA[i].end(); ++iterBi) { // go over column B(i)
-			// iterBi->second multiplies column A(iterBi->first)
-			BiVal = iterBi->second;
-			rowInd = iterBi->first;
-
-			for (iterA = m_colsA[rowInd].begin(); iterA != m_colsA[rowInd].end(); ++iterA) { // go over column of A
-				iterRes = res.m_colsA[i].find(iterA->first);
-				if (iterRes == res.m_colsA[i].end()) // first occurence of this row number
-					res.m_colsA[i][iterA->first] = (iterA->second)*BiVal;
-				else
-					iterRes->second += (iterA->second)*BiVal;
-			}
-		}
-	}
-
-	return true;
-}
-
-// Transposes the matrix 
-// and stores the result in the columns of res
-bool SparseSolver::Transpose(SparseSolver & res) const {
-	res = SparseSolver(m_numCols, m_numRows, m_SPD);
-	// if the matrix was symmetric to begin with, just copy the columns
-	if (m_SPD) {
-		res.m_colsA = m_colsA;
-		return true;
-	}
-	// else need to transpose
-	std::map<int,taucsType>::const_iterator iterA;
-	for (int i=0; i < m_numCols; ++i) {
-		for (iterA = m_colsA[i].begin(); iterA != m_colsA[i].end(); ++iterA) {
-			res.m_colsA[iterA->first][i] = iterA->second;
-		}
-	}
-	return true;
-}
-
-// will remove the rows startInd-endInd (including ends, zero-based) from the matrix
-// will discard any factors	
-bool SparseSolver::DeleteRowRange(const int startInd, const int endInd) {
-	if (startInd < 0 || endInd >= m_numRows || startInd > endInd)
-		return false;
-
-#ifndef NO_TAUCS
-	ClearFactorATA();
-	ClearFactorA();
-	ClearMatricesATA();
-	ClearMatricesA();
-#endif
-
-	std::map<int,taucsType>::iterator it;
-	std::map<int,taucsType>::iterator tempIt;
-	int diff = endInd - startInd + 1;
-
-	for (int c = 0; c < m_numCols; ++c) {
-		it = m_colsA[c].begin();
-		while (it != m_colsA[c].end()) {
-			if (it->first >= startInd && it->first <= endInd) { // row that should be erased
-				m_colsA[c].erase(it++);
-                        } else {
-				if (it->first > endInd) {// row number must be updated
-					m_colsA[c][it->first - diff] = it->second;
-					m_colsA[c].erase(it++);
-				}
-				else
-                    ++it;
-			}
-		}
-	}
-
-	m_numRows -= diff;
-	m_SPD = false;
-	
-	return true;
-}
-
-bool SparseSolver::MultiplyRows(const int startInd, const int endInd, const taucsType val)
-{
-    if (startInd < 0 || endInd >= m_numRows || startInd > endInd) return false;
-
-#ifndef NO_TAUCS
-    ClearFactorATA();
-    ClearFactorA();
-    ClearMatricesATA();
-    ClearMatricesA();
-#endif
-
-    std::map<int,taucsType>::iterator it;
-
-    for (int c = 0; c < m_numCols; ++c)
-    {
-        it = m_colsA[c].begin();
-        while (it != m_colsA[c].end())
-        {
-            if (it->first >= startInd && it->first <= endInd) // row that should be multiplied
-			{
-                it->second *= val;
-			}
-            it++;
-        }
-    }
-
-    return true;
-}
-
-
-// will remove the columns startInd-endInd (including ends, zero-based) from the matrix
-// will discard any factors	
-bool SparseSolver::DeleteColumnRange(const int startInd, const int endInd) {
-	if (startInd < 0 || endInd >= m_numCols || startInd > endInd)
-		return false;
-
-#ifndef NO_TAUCS
-	ClearFactorATA();
-	ClearFactorA();
-	ClearMatricesATA();
-	ClearMatricesA();
-#endif
-
-	m_colsA.erase(m_colsA.begin() + startInd, m_colsA.begin() + (endInd+1));
-
-	m_numCols -= (endInd - startInd + 1);
-
-	return true;
-}
-
-// copies columns startInd through endInd (including, zero-based) from the matrix to res matrix
-// previous data in res, including factors, is erased.
-bool SparseSolver::CopyColumnRange(const int startInd, const int endInd, SparseSolver & res) const {
-	if (startInd < 0 || endInd >= m_numCols || startInd > endInd)
-		return false;
-
-	int k = endInd - startInd + 1;
-
-	res = SparseSolver(m_numRows, k, false);
-	for (int c = startInd; c <= endInd; ++c)
-		res.m_colsA[c - startInd] = m_colsA[c];
-
-	return true;
-}
-
-// copies rows startInd through endInd (including, zero-based) from the matrix to res matrix
-// previous data in res, including factors, is erased.
-bool SparseSolver::CopyRowRange(const int startInd, const int endInd, SparseSolver & res) const {
-	if (startInd < 0 || endInd >= m_numRows || startInd > endInd)
-		return false;
-
-	res.m_colsA = m_colsA;
-	for (int c = 0; c < m_numCols; ++c) {
-		std::map<int,taucsType>::iterator it = res.m_colsA[c].begin();
-		std::map<int,taucsType>::iterator tempIt;
-		for ( ; it != res.m_colsA[c].end(); ++it) {
-			if (it->first < startInd || it->first > endInd) {
-				tempIt = it;
-				it++;
-				res.m_colsA[c].erase(tempIt);
-				continue;
-			}
-		}
-	}
-
-	return true;
-}
-
-
-void SparseSolver::MultiplyMatrixScalar(const taucsType val)
-{
-#ifndef NO_TAUCS
-    ClearFactorATA();
-    ClearFactorA();
-    ClearMatricesATA();
-    ClearMatricesA();
-#endif
-
-	//Over all entries
-    for (int c=0;c<m_numCols;c++)
-    {
-		for(std::map< int, taucsType >::iterator it=m_colsA[c].begin();it!=m_colsA[c].end();it++)
-        {
-			it->second *= val; //Multiply
-        }
-    }
-}
-
-void SparseSolver::IdentityMinusMatrix()
-{
-#ifndef NO_TAUCS
-    ClearFactorATA();
-    ClearFactorA();
-    ClearMatricesATA();
-    ClearMatricesA();
-#endif
-
-	//Over the diagonal
-    for (int c=0;c<m_numCols;c++)
-    {
-		std::map< int, taucsType >::iterator it = m_colsA[c].find(c);
-		if (it != m_colsA[c].end())
-		{
-			it->second = 1.0 - it->second;
-		}
-		else
-		{
-			AddIJV(c, c, 1.0);
-		}
-    }
-}
-
-
-void SparseSolver::IdentityPlusMatrix()
-{
-#ifndef NO_TAUCS
-    ClearFactorATA();
-    ClearFactorA();
-    ClearMatricesATA();
-    ClearMatricesA();
-#endif
-
-	//Over the diagonal
-    for (int c=0;c<m_numCols;c++)
-    {
-		std::map< int, taucsType >::iterator it = m_colsA[c].find(c);
-		if (it != m_colsA[c].end())
-		{
-			it->second += 1.0;
-		}
-		else
-		{
-			AddIJV(c, c, 1.0);
-		}
-    }
-}
-
-//
-// Memory: 1*spliced = 1*O(column_indices.size * numRows)
-// Runtime: O(size of spliced) = O(column_indices.size * numRows)
-bool SparseSolver::SpliceColumns(
-    const std::vector<size_t> column_indices,
-    SparseSolver & res) const
-{
-  // Check that all indices in column_indices are valid
-  for(
-      std::vector<size_t>::const_iterator old_index = column_indices.begin();
-      old_index != column_indices.end();
-      old_index++)
-  {
-    if((*old_index) >= (size_t)m_numCols)
-    {
-      return false;
-    }
-  }
-
-  // create result
-  res = SparseSolver(m_numRows,column_indices.size(),false);
-
-  // splice (and reorder) columns
-  size_t new_index = 0;
-  for(
-      std::vector<size_t>::const_iterator old_index = column_indices.begin();
-      old_index != column_indices.end();
-      old_index++,new_index++)
-  {
-    res.m_colsA[new_index] = m_colsA[(*old_index)];
-  }
-
-  return true;
-}
-
-// Cheating way of handling SpliceRows. 
-// SpliceRows = Transpose -> SpliceColumns -> Transpose
-// 
-// Sparse (not dense), but not perfect implementation:
-// Memory: 1*original + 2*spliced
-// Runtime: O(
-//   transpose of original + 
-//   splicecolumns of original + 
-//   transpose of spliced)
-//   = O(
-//   size of original + 
-//   size of spliced
-//   size of spliced)
-//   = O( size of original )
-//
-// A good implementation should be:
-// Memory: 1*spliced = 1*O(row_indices.size * numCols)
-// Runtime: O(size of spliced) = O(row_indices.size * numCols)
-bool SparseSolver::SpliceRows(
-  const std::vector<size_t> row_indices,
-  SparseSolver & res) const 
-{
-  // Check that all indices in row_indices are valid
-  for(
-      std::vector<size_t>::const_iterator old_index = row_indices.begin();
-      old_index != row_indices.end();
-      old_index++)
-  {
-    if((*old_index) >= (size_t)m_numRows)
-    {
-      return false;
-    }
-  }
-
-  // transpose (now columns are rows, rows are columns)
-  SparseSolver transpose;
-  if(!Transpose(transpose))
-  {
-    return false;
-  }
-
-  // Splice columns of transpose
-  SparseSolver spliced_transpose;
-  if(!transpose.SpliceColumns(row_indices, spliced_transpose))
-  {
-    return false;
-  }
-
-  // Transpose again (rows back to rows, columns back to columns)
-  if(!spliced_transpose.Transpose(res))
-  {
-    return false;
-  }
-
-  return true;
-}
-
-bool SparseSolver::SpliceColumnsThenRows(
-  const std::vector<size_t> column_indices, 
-  const std::vector<size_t> row_indices, 
-  SparseSolver & res) const 
-{
-  SparseSolver temp;
-  if(!SpliceColumns(column_indices,temp))
-  {
-    return false;
-  }
-  if(!temp.SpliceRows(row_indices,res))
-  {
-    return false;
-  }
-  return true;
-}
-    
-
-bool SparseSolver::VerticalConcatenation(
-    SparseSolver & other,
-    SparseSolver & res)
-{
-  // if other if skinnier than we'll padd with zeros
-  if(other.GetNumColumns() > m_numCols)
-  {
-    return false;
-  }
-  res = SparseSolver(m_numRows+other.GetNumRows(), m_numCols,false);
-  // copy all columns from this matrix to result
-  res.m_colsA = m_colsA;
-  // copy all entries in other to result with rows offset by "m_numRows"
-  std::map<int,taucsType>::iterator it;
-  for (int c = 0; c < other.m_numCols; ++c)
-  {
-    it = other.m_colsA[c].begin();
-    while (it != other.m_colsA[c].end())
-    {
-      res.AddIJV(it->first+m_numRows,c,it->second);
-      ++it;
-    }
-  }
-
-  return true;
-}
-
-void SparseSolver::ConvertToIJV(
-  std::vector<int> & row_indices,
-  std::vector<int> & column_indices,
-  std::vector<taucsType> & vals)
-{
-  // Get number of non-zeros
-  size_t nnz = 0;
-  // loop over columns
-  for (int c = 0; c < m_numCols; ++c) 
-  {
-    // add up the number of non-zeros in each column
-    nnz += m_colsA[c].size();
-  }
-  // allocate space in outputs
-  vals.resize(nnz);
-  row_indices.resize(nnz);
-  column_indices.resize(nnz);
-
-  size_t index = 0;
-  
-  std::map<int,taucsType>::iterator it;
-  // loop over columns
-  for (int c = 0; c < m_numCols; ++c) 
-  {
-    // loop over rows
-    it = m_colsA[c].begin();
-    while (it != m_colsA[c].end())
-    {
-      row_indices[index] = it->first;
-      column_indices[index] = c;
-      vals[index] = it->second;
-      // increment index
-      index++;
-      
-      ++it;
-    }
-  }
-}
-
-
-void SparseSolver::ConvertLowerTriangleToIJV(
-  std::vector<int> & row_indices,
-  std::vector<int> & column_indices,
-  std::vector<taucsType> & vals)
-{
-  // Get number of ALL non-zeros
-  size_t nnz = 0;
-  // loop over columns
-  for (int c = 0; c < m_numCols; ++c) 
-  {
-    // add up the number of non-zeros in each column
-    nnz += m_colsA[c].size();
-  }
-  // allocate (too much) space in outputs
-  vals.resize(nnz);
-  row_indices.resize(nnz);
-  column_indices.resize(nnz);
-
-  size_t index = 0;
-  
-  std::map<int,taucsType>::iterator it;
-  // loop over columns
-  for (int c = 0; c < m_numCols; ++c) 
-  {
-    // loop over rows
-    it = m_colsA[c].begin();
-    while (it != m_colsA[c].end())
-    {
-      // if row is less than or equal to column then we're in the lower
-      // triangle
-      if(it->first>= c)
-      {
-        row_indices[index] = it->first;
-        column_indices[index] = c;
-        vals[index] = it->second;
-        // increment index
-        index++;
-      }
-      
-      ++it;
-    }
-  }
-  // resize to actually number of non-zeros in lower triangle
-  vals.resize(index);
-  row_indices.resize(index);
-  column_indices.resize(index);
-
-}
-
-void SparseSolver::ConvertToHarwellBoeing(
-  int & nnz,
-  int & num_rows,
-  int & num_cols,
-  std::vector<taucsType> & vals,
-  std::vector<int> & row_indices,
-  std::vector<int> & column_pointers)
-{
-  num_rows = m_numRows;
-  num_cols = m_numCols;
-  nnz = 0;
-  // loop over columns
-  for (int c = 0; c < m_numCols; ++c) 
-  {
-    // add up the number of non-zeros in each column
-    nnz += m_colsA[c].size();
-  }
-
-  vals.resize(nnz);
-  row_indices.resize(nnz);
-  column_pointers.resize(num_cols+1);
-
-  // loop over columns
-  int column_pointer = 0;
-  int val_index = 0;
-  std::map<int,taucsType>::iterator it;
-  int c;
-  for (c = 0; c < m_numCols; ++c) 
-  {
-    column_pointers[c] = column_pointer;
-    column_pointer += m_colsA[c].size();
-    // over rows in this column
-    it = m_colsA[c].begin();
-    while (it != m_colsA[c].end())
-    {
-      vals[val_index] = it->second;
-      row_indices[val_index] = it->first;
-      val_index++;
-      ++it;
-    }
-  }
-  // by convention column_pointers[num_cols] = nnz
-  column_pointers[c] = column_pointer;
-}

+ 0 - 312
examples/sparse/example.cpp

@@ -1,312 +0,0 @@
-#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
-#define EIGEN_IM_MAD_AS_HELL_AND_IM_NOT_GOING_TO_TAKE_IT_ANYMORE
-#include <Eigen/Sparse>
-#include <Eigen/SparseExtra>
-using namespace Eigen;
-
-#include <cstdio>
-#include <iostream>
-using namespace std;
-
-#include "readOBJ.h"
-#include "print_ijv.h"
-#include "cotmatrix.h"
-#include "get_seconds.h"
-#include "EPS.h"
-using namespace igl;
-
-#include "SparseSolver.h"
-#include "IJV.h"
-
-// Build cotangent matrix by looping over triangles filling in eigen's dynamic
-// sparse matrix then casting to sparse matrix
-inline void cotmatrix_dyncast(
-  const Eigen::MatrixXd & V, 
-  const Eigen::MatrixXi & F, 
-  Eigen::SparseMatrix<double>& L)
-{
-  // Assumes vertices are 3D or 2D
-  assert((V.cols() == 3) || (V.cols() == 2));
-  int dim = V.cols();
-  // Assumes faces are triangles
-  assert(F.cols() == 3);
-
-  Eigen::DynamicSparseMatrix<double, Eigen::RowMajor> dyn_L (V.rows(), V.rows());
-
-  // THIS MAKES A HUGE DIFFERENCE 2x
-  dyn_L.reserve(7*V.rows());
-  
-  // Loop over triangles
-  for (unsigned i = 0; i < F.rows(); i++)
-  {
-    // Corner indices of this triangle
-    int vi1 = F(i,0);
-    int vi2 = F(i,1);
-    int vi3 = F(i,2);
-    // Grab corner positions of this triangle
-    Eigen::Vector3d v1(V(vi1,0), V(vi1,1), V(vi1,2));
-    Eigen::Vector3d v2(V(vi2,0), V(vi2,1), V(vi2,2));
-    Eigen::Vector3d v3(V(vi3,0), V(vi3,1), V(vi3,2));
-    // Compute cotangent of angles at each corner
-    double cot1, cot2, cot3;
-    computeCotWeights(v1, v2, v3, cot1, cot2, cot3);
-    // Throw each corner's cotangent at opposite edge (in both directions)
-    dyn_L.coeffRef(vi1, vi2) += cot3;
-    dyn_L.coeffRef(vi2, vi1) += cot3;
-    dyn_L.coeffRef(vi2, vi3) += cot1;
-    dyn_L.coeffRef(vi3, vi2) += cot1;
-    dyn_L.coeffRef(vi3, vi1) += cot2;
-    dyn_L.coeffRef(vi1, vi3) += cot2;
-    //dyn_L.coeffRef(vi1, vi1) -= cot3;
-    //dyn_L.coeffRef(vi2, vi2) -= cot3;
-    //dyn_L.coeffRef(vi2, vi2) -= cot1;
-    //dyn_L.coeffRef(vi3, vi3) -= cot1;
-    //dyn_L.coeffRef(vi3, vi3) -= cot2;
-    //dyn_L.coeffRef(vi1, vi1) -= cot2;
-  }
-
-  for (int k=0; k < dyn_L.outerSize(); ++k)
-  {
-    double tmp = 0.0f;
-    for(Eigen::DynamicSparseMatrix<double, Eigen::RowMajor>::InnerIterator it (dyn_L, k); it; ++it)
-    {
-      tmp += it.value();
-    }
-    dyn_L.coeffRef(k,k) = -tmp;
-  }
-  L = Eigen::SparseMatrix<double>(dyn_L);
-}
-
-inline bool safe_AddToIJV(SparseSolver & S, int i, int j, double v)
-{
-  // Only add if not within double precision of zero
-  if( v>DOUBLE_EPS|| v< -DOUBLE_EPS)
-  {
-    S.AddToIJV(i,j,v);
-    return true;
-  }
-  //else
-  return false;
-}
-
-inline void cotmatrix_sparsesolver(
-  const Eigen::MatrixXd & V, 
-  const Eigen::MatrixXi & F, 
-  Eigen::SparseMatrix<double>& L)
-{
-  SparseSolver ssL(V.rows(),V.rows());
-
-  // loop over triangles
-  // Loop over triangles
-  for (int i = 0; i < F.rows(); i++)
-  {
-    // Corner indices of this triangle
-    int vi1 = F(i,0);
-    int vi2 = F(i,1);
-    int vi3 = F(i,2);
-    // Grab corner positions of this triangle
-    Eigen::Vector3d v1(V(vi1,0), V(vi1,1), V(vi1,2));
-    Eigen::Vector3d v2(V(vi2,0), V(vi2,1), V(vi2,2));
-    Eigen::Vector3d v3(V(vi3,0), V(vi3,1), V(vi3,2));
-    // Compute cotangent of angles at each corner
-    double cot1, cot2, cot3;
-    computeCotWeights(v1, v2, v3, cot1, cot2, cot3);
-    // Throw each corner's cotangent at opposite edge (in both directions)
-    safe_AddToIJV(ssL,vi1,vi2,cot3);
-    safe_AddToIJV(ssL,vi2,vi1,cot3);
-    safe_AddToIJV(ssL,vi2,vi3,cot1);
-    safe_AddToIJV(ssL,vi3,vi2,cot1);
-    safe_AddToIJV(ssL,vi3,vi1,cot2);
-    safe_AddToIJV(ssL,vi1,vi3,cot2);
-
-    safe_AddToIJV(ssL,vi1,vi1,-cot2);
-    safe_AddToIJV(ssL,vi1,vi1,-cot3);
-    safe_AddToIJV(ssL,vi2,vi2,-cot3);
-    safe_AddToIJV(ssL,vi2,vi2,-cot1);
-    safe_AddToIJV(ssL,vi3,vi3,-cot1);
-    safe_AddToIJV(ssL,vi3,vi3,-cot2);
-  }
-}
-
-// First build adjacency list then use it to build a cotan matrix loop over
-// vertices in order
-inline void cotmatrix_adjacencylist(
-  const Eigen::MatrixXd & V, 
-  const Eigen::MatrixXi & F, 
-  Eigen::SparseMatrix<double>& L)
-{
-  // adjacency list
-  std::vector<std::vector<int> > A;
-  //adjacency_list(F,A);
-}
-
-// Build a cotmatrix by building a list of values to add in an IJV list, then
-// sort the IJV list and *add* them to the sparsematrix in sorted order
-inline void cotmatrix_sort_ijv(
-  const Eigen::MatrixXd & V, 
-  const Eigen::MatrixXi & F, 
-  Eigen::SparseMatrix<double>& L)
-{
-  // Assumes vertices are 3D or 2D
-  assert((V.cols() == 3) || (V.cols() == 2));
-  int dim = V.cols();
-  // Assumes faces are triangles
-  assert(F.cols() == 3);
-
-  vector<IJV<int,double> > Lijv;
-  // We know that we will have 12 entries per face
-  Lijv.reserve(6*F.rows());
-
-  // Loop over triangles
-  for (unsigned i = 0; i < F.rows(); i++)
-  {
-    // Corner indices of this triangle
-    int vi1 = F(i,0);
-    int vi2 = F(i,1);
-    int vi3 = F(i,2);
-    // Grab corner positions of this triangle
-    Eigen::Vector3d v1(V(vi1,0), V(vi1,1), V(vi1,2));
-    Eigen::Vector3d v2(V(vi2,0), V(vi2,1), V(vi2,2));
-    Eigen::Vector3d v3(V(vi3,0), V(vi3,1), V(vi3,2));
-    // Compute cotangent of angles at each corner
-    double cot1, cot2, cot3;
-    computeCotWeights(v1, v2, v3, cot1, cot2, cot3);
-    // Throw each corner's cotangent at opposite edge (in both directions)
-    Lijv.push_back(IJV<int,double>(vi1, vi2,cot3));
-    //Lijv.push_back(IJV<int,double>(vi2, vi1,cot3));
-    Lijv.push_back(IJV<int,double>(vi2, vi3,cot1));
-    //Lijv.push_back(IJV<int,double>(vi3, vi2,cot1));
-    Lijv.push_back(IJV<int,double>(vi3, vi1,cot2));
-    //Lijv.push_back(IJV<int,double>(vi1, vi3,cot2));
-    //// diagonal entries
-    Lijv.push_back(IJV<int,double>(vi1, vi1,-cot3));
-    //Lijv.push_back(IJV<int,double>(vi2, vi2,-cot3));
-    Lijv.push_back(IJV<int,double>(vi2, vi2,-cot1));
-    //Lijv.push_back(IJV<int,double>(vi3, vi3,-cot1));
-    Lijv.push_back(IJV<int,double>(vi3, vi3,-cot2));
-    //Lijv.push_back(IJV<int,double>(vi1, vi1,-cot2));
-  }
-  sort(Lijv.begin(),Lijv.end());
-
-  L = Eigen::SparseMatrix<double>(V.rows(),V.rows());
-  L.reserve(7*V.rows());
-
-  // Now that all the (i,j,v) triplets are sorted we can add them to the
-  // SparseMatrix directly
-  int i = -1;
-  int j = -1;
-  double v = 0;
-  vector<IJV<int,double> >::iterator last;
-  for(
-    vector<IJV<int,double> >::iterator Lit = Lijv.begin();
-    Lit != Lijv.end();
-    Lit++)
-  {
-    // Sum up non-unique entries
-    if(i == Lit->i && j == Lit->j)
-    {
-      last->v += Lit->v;
-      Lit->v = 0;
-    }else
-    {
-      i = Lit->i;
-      j = Lit->j;
-      last = Lit;
-    }
-  }
-
-  i = -1;
-  j = -1;
-  // Now our ijv list is sorted and we don't have dups
-  for(
-    vector<IJV<int,double> >::iterator Lit = Lijv.begin();
-    Lit != Lijv.end();
-    Lit++)
-  {
-    // only consider non-zeros
-    if(Lit->v != 0)
-    {
-      // If new outer then need to start
-      if(i != Lit->i)
-      {
-        i = Lit->i;
-        L.startVec(i);
-      }
-      L.insertBack(Lit->j,Lit->i) = Lit->v;
-    }
-  }
-  L.finalize();
-  L = L + SparseMatrix<double>(L.transpose());
-}
-
-int main(int argc, char * argv[])
-{
-  if(argc < 2)
-  {
-    printf("Usage:\n  ./example mesh.obj\n");
-    return 1;
-  }
-  // Read in a triangle mesh
-  MatrixXd V;
-  MatrixXi F;
-  readOBJ(argv[1],V,F);
-  // Should be 3D triangle mesh
-  assert(V.cols() == 3);
-  assert(F.cols() == 3);
-  // Print info about the mesh
-  printf("#vertices: %d\n",(int)V.rows());
-  printf("#faces: %d\n",(int)F.rows());
-  printf("min face index: %d\n",(int)F.minCoeff());
-  printf("max face index: %d\n",(int)F.maxCoeff());
-
-  double before;
-  int trials;
-  int max_trials = 10;
-  SparseMatrix<double> L;
-
-  printf("cotmatrix:\n  ");
-  before = get_seconds();
-  for(trials = 0;trials<max_trials;trials++)
-  {
-    cotmatrix(V,F,L);
-  }
-  printf("%g\n",(get_seconds()-before)/(double)trials);
-  if(L.rows() < 10)
-  {
-    print_ijv(L);
-  }
-
-  printf("cotmatrix_dyncast:\n  ");
-  before = get_seconds();
-  for(trials = 0;trials<max_trials;trials++)
-  {
-    cotmatrix_dyncast(V,F,L);
-  }
-  printf("%g\n",(get_seconds()-before)/(double)trials);
-  if(L.rows() < 10)
-  {
-    print_ijv(L);
-  }
-
-  //printf("cotmatrix_sparsesolver:\n  ");
-  //before = get_seconds();
-  //for(trials = 0;trials<max_trials;trials++)
-  //{
-  //  cotmatrix_sparsesolver(V,F,L);
-  //}
-  //printf("%g\n",(get_seconds()-before)/(double)trials);
-
-  printf("cotmatrix_sort_ijv:\n  ");
-  before = get_seconds();
-  for(trials = 0;trials<max_trials;trials++)
-  {
-    cotmatrix_sort_ijv(V,F,L);
-  }
-  printf("%g\n",(get_seconds()-before)/(double)trials);
-  if(L.rows() < 10)
-  {
-    print_ijv(L);
-  }
-
-  return 0;
-}

+ 0 - 1
examples/sparse/max.obj.REMOVED.git-id

@@ -1 +0,0 @@
-e417d5c76348eda6e2788556f09a03b0ba6dd7b0

+ 0 - 37
examples/sparse/test.cpp

@@ -1,37 +0,0 @@
-#!/bin/bash
-//usr/bin/tail -n +2 $0 | g++ -o main -x c++ - && ./main && rm main && exit
-#include "IJV.h"
-
-#include <cstdio>
-#include <vector>
-#include <algorithm>
-using namespace std;
-
-int print_ijv(const IJV<int,double> & ijv)
-{
-  printf("%d %d %g\n",
-    ijv.i,
-    ijv.j,
-    ijv.v);
-}
-
-int main(int argc, char * argv[])
-{
-  vector<IJV<int,double> > Aijv;
-  Aijv.push_back(IJV<int,double>(1,2,10));
-  Aijv.push_back(IJV<int,double>(4,2,10));
-  Aijv.push_back(IJV<int,double>(4,3,10));
-  Aijv.push_back(IJV<int,double>(9,2,10));
-  Aijv.push_back(IJV<int,double>(1,2,10));
-  Aijv.push_back(IJV<int,double>(1,3,10));
-  Aijv.push_back(IJV<int,double>(1,1,10));
-  Aijv.push_back(IJV<int,double>(3,2,10));
-
-  printf("Original:\n");
-  for_each(Aijv.begin(),Aijv.end(),print_ijv);
-  sort(Aijv.begin(),Aijv.end());
-  printf("Sorted:\n");
-  for_each(Aijv.begin(),Aijv.end(),print_ijv);
-
-  return 0;
-}