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@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
13namespace 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 */
21template<typename Scalar>
22class SkylineStorage {
23    typedef typename NumTraits<Scalar>::Real RealScalar;
24    typedef SparseIndex Index;
25public:
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
201protected:
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
242public:
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