1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2008-2009 Guillaume Saupin <guillaume.saupin (at) cea.fr> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_SKYLINE_STORAGE_H 11 #define EIGEN_SKYLINE_STORAGE_H 12 13 namespace Eigen { 14 15 /** Stores a skyline set of values in three structures : 16 * The diagonal elements 17 * The upper elements 18 * The lower elements 19 * 20 */ 21 template<typename Scalar> 22 class SkylineStorage { 23 typedef typename NumTraits<Scalar>::Real RealScalar; 24 typedef SparseIndex Index; 25 public: 26 27 SkylineStorage() 28 : m_diag(0), 29 m_lower(0), 30 m_upper(0), 31 m_lowerProfile(0), 32 m_upperProfile(0), 33 m_diagSize(0), 34 m_upperSize(0), 35 m_lowerSize(0), 36 m_upperProfileSize(0), 37 m_lowerProfileSize(0), 38 m_allocatedSize(0) { 39 } 40 41 SkylineStorage(const SkylineStorage& other) 42 : m_diag(0), 43 m_lower(0), 44 m_upper(0), 45 m_lowerProfile(0), 46 m_upperProfile(0), 47 m_diagSize(0), 48 m_upperSize(0), 49 m_lowerSize(0), 50 m_upperProfileSize(0), 51 m_lowerProfileSize(0), 52 m_allocatedSize(0) { 53 *this = other; 54 } 55 56 SkylineStorage & operator=(const SkylineStorage& other) { 57 resize(other.diagSize(), other.m_upperProfileSize, other.m_lowerProfileSize, other.upperSize(), other.lowerSize()); 58 memcpy(m_diag, other.m_diag, m_diagSize * sizeof (Scalar)); 59 memcpy(m_upper, other.m_upper, other.upperSize() * sizeof (Scalar)); 60 memcpy(m_lower, other.m_lower, other.lowerSize() * sizeof (Scalar)); 61 memcpy(m_upperProfile, other.m_upperProfile, m_upperProfileSize * sizeof (Index)); 62 memcpy(m_lowerProfile, other.m_lowerProfile, m_lowerProfileSize * sizeof (Index)); 63 return *this; 64 } 65 66 void swap(SkylineStorage& other) { 67 std::swap(m_diag, other.m_diag); 68 std::swap(m_upper, other.m_upper); 69 std::swap(m_lower, other.m_lower); 70 std::swap(m_upperProfile, other.m_upperProfile); 71 std::swap(m_lowerProfile, other.m_lowerProfile); 72 std::swap(m_diagSize, other.m_diagSize); 73 std::swap(m_upperSize, other.m_upperSize); 74 std::swap(m_lowerSize, other.m_lowerSize); 75 std::swap(m_allocatedSize, other.m_allocatedSize); 76 } 77 78 ~SkylineStorage() { 79 delete[] m_diag; 80 delete[] m_upper; 81 if (m_upper != m_lower) 82 delete[] m_lower; 83 delete[] m_upperProfile; 84 delete[] m_lowerProfile; 85 } 86 87 void reserve(Index size, Index upperProfileSize, Index lowerProfileSize, Index upperSize, Index lowerSize) { 88 Index newAllocatedSize = size + upperSize + lowerSize; 89 if (newAllocatedSize > m_allocatedSize) 90 reallocate(size, upperProfileSize, lowerProfileSize, upperSize, lowerSize); 91 } 92 93 void squeeze() { 94 if (m_allocatedSize > m_diagSize + m_upperSize + m_lowerSize) 95 reallocate(m_diagSize, m_upperProfileSize, m_lowerProfileSize, m_upperSize, m_lowerSize); 96 } 97 98 void resize(Index diagSize, Index upperProfileSize, Index lowerProfileSize, Index upperSize, Index lowerSize, float reserveSizeFactor = 0) { 99 if (m_allocatedSize < diagSize + upperSize + lowerSize) 100 reallocate(diagSize, upperProfileSize, lowerProfileSize, upperSize + Index(reserveSizeFactor * upperSize), lowerSize + Index(reserveSizeFactor * lowerSize)); 101 m_diagSize = diagSize; 102 m_upperSize = upperSize; 103 m_lowerSize = lowerSize; 104 m_upperProfileSize = upperProfileSize; 105 m_lowerProfileSize = lowerProfileSize; 106 } 107 108 inline Index diagSize() const { 109 return m_diagSize; 110 } 111 112 inline Index upperSize() const { 113 return m_upperSize; 114 } 115 116 inline Index lowerSize() const { 117 return m_lowerSize; 118 } 119 120 inline Index upperProfileSize() const { 121 return m_upperProfileSize; 122 } 123 124 inline Index lowerProfileSize() const { 125 return m_lowerProfileSize; 126 } 127 128 inline Index allocatedSize() const { 129 return m_allocatedSize; 130 } 131 132 inline void clear() { 133 m_diagSize = 0; 134 } 135 136 inline Scalar& diag(Index i) { 137 return m_diag[i]; 138 } 139 140 inline const Scalar& diag(Index i) const { 141 return m_diag[i]; 142 } 143 144 inline Scalar& upper(Index i) { 145 return m_upper[i]; 146 } 147 148 inline const Scalar& upper(Index i) const { 149 return m_upper[i]; 150 } 151 152 inline Scalar& lower(Index i) { 153 return m_lower[i]; 154 } 155 156 inline const Scalar& lower(Index i) const { 157 return m_lower[i]; 158 } 159 160 inline Index& upperProfile(Index i) { 161 return m_upperProfile[i]; 162 } 163 164 inline const Index& upperProfile(Index i) const { 165 return m_upperProfile[i]; 166 } 167 168 inline Index& lowerProfile(Index i) { 169 return m_lowerProfile[i]; 170 } 171 172 inline const Index& lowerProfile(Index i) const { 173 return m_lowerProfile[i]; 174 } 175 176 static SkylineStorage Map(Index* upperProfile, Index* lowerProfile, Scalar* diag, Scalar* upper, Scalar* lower, Index size, Index upperSize, Index lowerSize) { 177 SkylineStorage res; 178 res.m_upperProfile = upperProfile; 179 res.m_lowerProfile = lowerProfile; 180 res.m_diag = diag; 181 res.m_upper = upper; 182 res.m_lower = lower; 183 res.m_allocatedSize = res.m_diagSize = size; 184 res.m_upperSize = upperSize; 185 res.m_lowerSize = lowerSize; 186 return res; 187 } 188 189 inline void reset() { 190 memset(m_diag, 0, m_diagSize * sizeof (Scalar)); 191 memset(m_upper, 0, m_upperSize * sizeof (Scalar)); 192 memset(m_lower, 0, m_lowerSize * sizeof (Scalar)); 193 memset(m_upperProfile, 0, m_diagSize * sizeof (Index)); 194 memset(m_lowerProfile, 0, m_diagSize * sizeof (Index)); 195 } 196 197 void prune(Scalar reference, RealScalar epsilon = dummy_precision<RealScalar>()) { 198 //TODO 199 } 200 201 protected: 202 203 inline void reallocate(Index diagSize, Index upperProfileSize, Index lowerProfileSize, Index upperSize, Index lowerSize) { 204 205 Scalar* diag = new Scalar[diagSize]; 206 Scalar* upper = new Scalar[upperSize]; 207 Scalar* lower = new Scalar[lowerSize]; 208 Index* upperProfile = new Index[upperProfileSize]; 209 Index* lowerProfile = new Index[lowerProfileSize]; 210 211 Index copyDiagSize = (std::min)(diagSize, m_diagSize); 212 Index copyUpperSize = (std::min)(upperSize, m_upperSize); 213 Index copyLowerSize = (std::min)(lowerSize, m_lowerSize); 214 Index copyUpperProfileSize = (std::min)(upperProfileSize, m_upperProfileSize); 215 Index copyLowerProfileSize = (std::min)(lowerProfileSize, m_lowerProfileSize); 216 217 // copy 218 memcpy(diag, m_diag, copyDiagSize * sizeof (Scalar)); 219 memcpy(upper, m_upper, copyUpperSize * sizeof (Scalar)); 220 memcpy(lower, m_lower, copyLowerSize * sizeof (Scalar)); 221 memcpy(upperProfile, m_upperProfile, copyUpperProfileSize * sizeof (Index)); 222 memcpy(lowerProfile, m_lowerProfile, copyLowerProfileSize * sizeof (Index)); 223 224 225 226 // delete old stuff 227 delete[] m_diag; 228 delete[] m_upper; 229 delete[] m_lower; 230 delete[] m_upperProfile; 231 delete[] m_lowerProfile; 232 m_diag = diag; 233 m_upper = upper; 234 m_lower = lower; 235 m_upperProfile = upperProfile; 236 m_lowerProfile = lowerProfile; 237 m_allocatedSize = diagSize + upperSize + lowerSize; 238 m_upperSize = upperSize; 239 m_lowerSize = lowerSize; 240 } 241 242 public: 243 Scalar* m_diag; 244 Scalar* m_upper; 245 Scalar* m_lower; 246 Index* m_upperProfile; 247 Index* m_lowerProfile; 248 Index m_diagSize; 249 Index m_upperSize; 250 Index m_lowerSize; 251 Index m_upperProfileSize; 252 Index m_lowerProfileSize; 253 Index m_allocatedSize; 254 255 }; 256 257 } // end namespace Eigen 258 259 #endif // EIGEN_COMPRESSED_STORAGE_H 260