1
// This file is part of Eigen, a lightweight C++ template library
4
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
6
// Eigen is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU Lesser General Public
8
// License as published by the Free Software Foundation; either
9
// version 3 of the License, or (at your option) any later version.
11
// Alternatively, you can redistribute it and/or
12
// modify it under the terms of the GNU General Public License as
13
// published by the Free Software Foundation; either version 2 of
14
// the License, or (at your option) any later version.
16
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19
// GNU General Public License for more details.
21
// You should have received a copy of the GNU Lesser General Public
22
// License and a copy of the GNU General Public License along with
23
// Eigen. If not, see <http://www.gnu.org/licenses/>.
25
#ifndef EIGEN_COMPRESSED_STORAGE_H
26
#define EIGEN_COMPRESSED_STORAGE_H
28
/** Stores a sparse set of values as a list of values and a list of indices.
31
template<typename _Scalar,typename _Index>
32
class CompressedStorage
36
typedef _Scalar Scalar;
41
typedef typename NumTraits<Scalar>::Real RealScalar;
46
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
49
CompressedStorage(size_t size)
50
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
55
CompressedStorage(const CompressedStorage& other)
56
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
61
CompressedStorage& operator=(const CompressedStorage& other)
64
memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
65
memcpy(m_indices, other.m_indices, m_size * sizeof(Index));
69
void swap(CompressedStorage& other)
71
std::swap(m_values, other.m_values);
72
std::swap(m_indices, other.m_indices);
73
std::swap(m_size, other.m_size);
74
std::swap(m_allocatedSize, other.m_allocatedSize);
83
void reserve(size_t size)
85
size_t newAllocatedSize = m_size + size;
86
if (newAllocatedSize > m_allocatedSize)
87
reallocate(newAllocatedSize);
92
if (m_allocatedSize>m_size)
96
void resize(size_t size, float reserveSizeFactor = 0)
98
if (m_allocatedSize<size)
99
reallocate(size + size_t(reserveSizeFactor*size));
103
void append(const Scalar& v, Index i)
105
Index id = static_cast<Index>(m_size);
111
inline size_t size() const { return m_size; }
112
inline size_t allocatedSize() const { return m_allocatedSize; }
113
inline void clear() { m_size = 0; }
115
inline Scalar& value(size_t i) { return m_values[i]; }
116
inline const Scalar& value(size_t i) const { return m_values[i]; }
118
inline Index& index(size_t i) { return m_indices[i]; }
119
inline const Index& index(size_t i) const { return m_indices[i]; }
121
static CompressedStorage Map(Index* indices, Scalar* values, size_t size)
123
CompressedStorage res;
124
res.m_indices = indices;
125
res.m_values = values;
126
res.m_allocatedSize = res.m_size = size;
130
/** \returns the largest \c k such that for all \c j in [0,k) index[\c j]\<\a key */
131
inline Index searchLowerIndex(Index key) const
133
return searchLowerIndex(0, m_size, key);
136
/** \returns the largest \c k in [start,end) such that for all \c j in [start,k) index[\c j]\<\a key */
137
inline Index searchLowerIndex(size_t start, size_t end, Index key) const
141
size_t mid = (end+start)>>1;
142
if (m_indices[mid]<key)
147
return static_cast<Index>(start);
150
/** \returns the stored value at index \a key
151
* If the value does not exist, then the value \a defaultValue is returned without any insertion. */
152
inline Scalar at(Index key, Scalar defaultValue = Scalar(0)) const
156
else if (key==m_indices[m_size-1])
157
return m_values[m_size-1];
158
// ^^ optimization: let's first check if it is the last coefficient
159
// (very common in high level algorithms)
160
const size_t id = searchLowerIndex(0,m_size-1,key);
161
return ((id<m_size) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
164
/** Like at(), but the search is performed in the range [start,end) */
165
inline Scalar atInRange(size_t start, size_t end, Index key, Scalar defaultValue = Scalar(0)) const
169
else if (end>start && key==m_indices[end-1])
170
return m_values[end-1];
171
// ^^ optimization: let's first check if it is the last coefficient
172
// (very common in high level algorithms)
173
const size_t id = searchLowerIndex(start,end-1,key);
174
return ((id<end) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
177
/** \returns a reference to the value at index \a key
178
* If the value does not exist, then the value \a defaultValue is inserted
179
* such that the keys are sorted. */
180
inline Scalar& atWithInsertion(Index key, Scalar defaultValue = Scalar(0))
182
size_t id = searchLowerIndex(0,m_size,key);
183
if (id>=m_size || m_indices[id]!=key)
186
for (size_t j=m_size-1; j>id; --j)
188
m_indices[j] = m_indices[j-1];
189
m_values[j] = m_values[j-1];
192
m_values[id] = defaultValue;
197
void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
201
for (size_t i=0; i<n; ++i)
203
if (!internal::isMuchSmallerThan(value(i), reference, epsilon))
215
inline void reallocate(size_t size)
217
Scalar* newValues = new Scalar[size];
218
Index* newIndices = new Index[size];
219
size_t copySize = (std::min)(size, m_size);
221
memcpy(newValues, m_values, copySize * sizeof(Scalar));
222
memcpy(newIndices, m_indices, copySize * sizeof(Index));
226
m_values = newValues;
227
m_indices = newIndices;
228
m_allocatedSize = size;
235
size_t m_allocatedSize;
239
#endif // EIGEN_COMPRESSED_STORAGE_H