aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/SparseLU/SparseLU_Memory.h
diff options
context:
space:
mode:
authorGravatar Desire NUENTSA <desire.nuentsa_wakam@inria.fr>2012-05-25 18:17:57 +0200
committerGravatar Desire NUENTSA <desire.nuentsa_wakam@inria.fr>2012-05-25 18:17:57 +0200
commitb6267507ea08bf572666bf634bc3a6fabe6aba11 (patch)
tree01843518d9cbc5208cc75a31672c7a93c3030af1 /Eigen/src/SparseLU/SparseLU_Memory.h
parentb202c5ed2f3c4fac09c76e34ea728377a79fa15d (diff)
Add preliminary files for SparseLU
Diffstat (limited to 'Eigen/src/SparseLU/SparseLU_Memory.h')
-rw-r--r--Eigen/src/SparseLU/SparseLU_Memory.h242
1 files changed, 242 insertions, 0 deletions
diff --git a/Eigen/src/SparseLU/SparseLU_Memory.h b/Eigen/src/SparseLU/SparseLU_Memory.h
new file mode 100644
index 000000000..6e0fc658d
--- /dev/null
+++ b/Eigen/src/SparseLU/SparseLU_Memory.h
@@ -0,0 +1,242 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+/*
+
+ * NOTE: This file is the modified version of [s,d,c,z]memory.c files in SuperLU
+
+ * -- SuperLU routine (version 3.1) --
+ * Univ. of California Berkeley, Xerox Palo Alto Research Center,
+ * and Lawrence Berkeley National Lab.
+ * August 1, 2008
+ *
+ * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+ * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ */
+
+#ifndef EIGEN_SPARSELU_MEMORY
+#define EIGEN_SPARSELU_MEMORY
+
+#define LU_Reduce(alpha) ((alpha + 1) / 2) // i.e (alpha-1)/2 + 1
+#define LU_GluIntArray(n) (5* (n) + 5)
+#define LU_TempSpace(m, w) ( (2*w + 4 + LU_NO_MARKER) * m * sizeof(Index) \
+ + (w + 1) * m * sizeof(Scalar)
+namespace internal {
+
+/* Allocate various working space needed in the numerical factorization phase.
+ * m_work : space fot the output data structures (lwork is the size)
+ * m_Glu: persistent data to facilitate multiple factors : is it really necessary ??
+ * NOTE Unlike SuperLU, this routine does not allow the user to provide the size to allocate
+ * nor it return an estimated amount of space required.
+ *
+ * Useful variables :
+ * - m_fillratio : Ratio of fill expected
+ * - lwork = -1 : return an estimated size of the required memory
+ * = 0 : Estimate and allocate the memory
+ */
+template <typename Scalar,typename Index>
+int SparseLU::LUMemInit(int lwork)
+{
+ int iword = sizeof(Index);
+ int dword = sizeof(Scalar);
+ int n = m_Glu.n = m_mat.cols();
+ int m = m_mat.rows();
+ m_Glu.num_expansions = 0; // No memory expansions so far ??
+ int estimated_size;
+
+
+ if (!m_Glu.expanders)
+ m_Glu.expanders = new ExpHeader(NO_MEMTYPE);
+
+ if (m_fact_t != SamePattern_SameRowPerm) // Create space for a new factorization
+ {
+ // Guess the size for L\U factors
+ int annz = m_mat.nonZeros();
+ int nzlmax, nzumax, nzlumax;
+ nzumax = nzlumax = m_fillratio * annz; // ???
+ nzlmax = std::max(1, m_fill_ratio/4.) * annz; //???
+
+ // Return the estimated size to the user if necessary
+ if (lwork = -1)
+ {
+ estimated_size = LU_GluIntArray(n) * iword + LU_TempSpace(m, m_panel_size)
+ + (nzlmax + nzumax) * iword + (nzlumax+nzumax) * dword + n);
+ return estimated_size;
+ }
+
+ // Setup the required space
+ // NOTE: In SuperLU, there is an option to let the user provide its own space.
+
+ // Allocate Integer pointers for L\U factors.resize(n+1);
+ m_Glu.supno.resize(n+1);
+ m_Glu.xlsub.resize(n+1);
+ m_Glu.xlusup.resize(n+1);
+ m_Glu.xusub.resize(n+1);
+
+ // Reserve memory for L/U factors
+ m_Glu.lusup = internal::expand<Scalar>(nzlumax, LUSUP, 0, 0, m_Glu);
+ m_Glu.ucol = internal::expand<Scalar>(nzumax, UCOL, 0, 0, m_Glu);
+ m_Glu.lsub = internal::expand<Index>(nzlmax, LSUB, 0, 0, m_Glu);
+ m_Glu.usub = internal::expand<Index>(nzumax, USUB, 0, 1, m_Glu);
+
+ // Check if the memory is correctly allocated,
+ while ( !m_Glu.lusup || !m_Glu.ucol || !m_Glu.lsub || !m_Glu.usub)
+ {
+ //otherwise reduce the estimated size and retry
+ delete [] m_Glu.lusup;
+ delete [] m_Glu.ucol;
+ delete [] m_Glu.lsub;
+ delete [] m_Glu.usub;
+
+ nzlumax /= 2;
+ nzumax /= 2;
+ nzlmax /= 2;
+ eigen_assert (nzlumax > annz && "Not enough memory to perform factorization");
+
+ m_Glu.lusup = internal::expand<Scalar>(nzlumax, LUSUP, 0, 0, m_Glu);
+ m_Glu.ucol = internal::expand<Scalar>(nzumax, UCOL, 0, 0, m_Glu);
+ m_Glu.lsub = internal::expand<Index>(nzlmax, LSUB, 0, 0, m_Glu);
+ m_Glu.usub = internal::expand<Index>(nzumax, USUB, 0, 1, m_Glu);
+ }
+ }
+ else // m_fact == SamePattern_SameRowPerm;
+ {
+ if (lwork = -1)
+ {
+ estimated_size = LU_GluIntArray(n) * iword + LU_TempSpace(m, m_panel_size)
+ + (Glu.nzlmax + Glu.nzumax) * iword + (Glu.nzlumax+Glu.nzumax) * dword + n);
+ return estimated_size;
+ }
+ // Use existing space from previous factorization
+ // Unlike in SuperLU, this should not be necessary here since m_Glu is persistent as a member of the class
+ m_Glu.xsup = m_Lstore.sup_to_col;
+ m_Glu.supno = m_Lstore.col_to_sup;
+ m_Glu.xlsub = m_Lstore.rowind_colptr;
+ m_Glu.xlusup = m_Lstore.nzval_colptr;
+ xusub = m_Ustore.outerIndexPtr();
+
+ m_Glu.expanders[LSUB].size = m_Glu.nzlmax; // Maximum value from previous factorization
+ m_Glu.expanders[LUSUP].size = m_Glu.nzlumax;
+ m_Glu.expanders[USUB].size = GLu.nzumax;
+ m_Glu.expanders[UCOL].size = m_Glu.nzumax;
+ m_Glu.lsub = GLu.expanders[LSUB].mem = m_Lstore.rowind;
+ m_Glu.lusup = GLu.expanders[LUSUP].mem = m_Lstore.nzval;
+ GLu.usub = m_Glu.expanders[USUB].mem = m_Ustore.InnerIndexPtr();
+ m_Glu.ucol = m_Glu.expanders[UCOL].mem = m_Ustore.valuePtr();
+ }
+
+ // LUWorkInit : Now, allocate known working storage
+ int isize = (2 * m_panel_size + 3 + LU_NO_MARKER) * m + n;
+ int dsize = m * m_panel_size + LU_NUM_TEMPV(m, m_panel_size, m_maxsuper, m_rowblk);
+ m_iwork = new Index(isize);
+ eigen_assert( (m_iwork != 0) && "Malloc fails for iwork");
+ m_work = new Scalar(dsize);
+ eigen_assert( (m_work != 0) && "Malloc fails for dwork");
+
+ ++m_Glu.num_expansions;
+ return 0;
+} // end LuMemInit
+
+/**
+ * Expand the existing storage to accomodate more fill-ins
+ */
+template <typename DestType >
+DestType* SparseLU::expand(int& prev_len, // Length from previous call
+ MemType type, // Which part of the memory to expand
+ int len_to_copy, // Size of the memory to be copied to new store
+ int keep_prev) // = 1: use prev_len; Do not expand this vector
+ // = 0: compute new_len to expand)
+{
+
+ float alpha = 1.5; // Ratio of the memory increase
+ int new_len; // New size of the allocated memory
+ if(m_Glu.num_expansions == 0 || keep_prev)
+ new_len = prev_len;
+ else
+ new_len = alpha * prev_len;
+
+ // Allocate new space
+ DestType *new_mem, *old_mem;
+ new_mem = new DestType(new_len);
+ if ( m_Glu.num_expansions != 0 ) // The memory has been expanded before
+ {
+ int tries = 0;
+ if (keep_prev)
+ {
+ if (!new_mem) return 0;
+ }
+ else
+ {
+ while ( !new_mem)
+ {
+ // Reduce the size and allocate again
+ if ( ++tries > 10) return 0;
+ alpha = LU_Reduce(alpha);
+ new_len = alpha * prev_len;
+ new_mem = new DestType(new_len);
+ }
+ } // keep_prev
+ //Copy the previous values to the newly allocated space
+ ExpHeader<DestType>* expanders = m_Glu.expanders;
+ std::memcpy(new_mem, expanders[type].mem, len_to_copy);
+ delete [] expanders[type].mem;
+ }
+ expanders[type].mem = new_mem;
+ expanders[type].size = new_len;
+ prev_len = new_len;
+ if(m_Glu.num_expansions) ++m_Glu.num_expansions;
+ return expanders[type].mem;
+}
+
+/**
+ * \brief Expand the existing storage
+ *
+ * NOTE: The calling sequence of this function is different from that of SuperLU
+ *
+ * \return a pointer to the newly allocated space
+ */
+template <typename DestType>
+DestType* SparseLU::LUMemXpand(int jcol, int next, MemType mem_type, int& maxlen)
+{
+ DestType *newmem;
+ if (memtype == USUB)
+ new_mem = expand<DestType>(maxlen, mem_type, next, 1);
+ else
+ new_mem = expand<DestType>(maxlen, mem_type, next, 0);
+ eigen_assert(new_mem && "Can't expand memory");
+
+ return new_mem;
+
+}
+
+}// Namespace Internal
+#endif \ No newline at end of file