11#ifndef EIGEN_AMBIVECTOR_H
12#define EIGEN_AMBIVECTOR_H
15#include "./InternalHeaderCheck.h"
26template <
typename Scalar_,
typename StorageIndex_>
29 using Scalar = Scalar_;
30 using StorageIndex = StorageIndex_;
32 explicit AmbiVector(Index size)
38 m_allocatedElements(0),
39 m_denseConstructed(0),
44 void init(
double estimatedDensity);
47 Index nonZeros()
const;
50 void setBounds(Index start, Index end) {
51 m_start = convert_index(start);
52 m_end = convert_index(end);
58 Scalar& coeffRef(Index i);
59 Scalar& coeff(Index i);
65 internal::aligned_free(m_buffer);
68 void resize(Index size) {
69 if (m_allocatedSize < size) reallocate(size);
70 m_size = convert_index(size);
78 StorageIndex size()
const {
return m_size; }
88 StorageIndex convert_index(Index idx) {
return internal::convert_index<StorageIndex>(idx); }
90 ListEl* listElements() {
return static_cast<ListEl*
>(
static_cast<void*
>(m_buffer)); }
91 const ListEl* listElements()
const {
return static_cast<const ListEl*
>(
static_cast<const void*
>(m_buffer)); }
93 void reallocate(Index size) {
97 internal::aligned_free(m_buffer);
100 allocSize = numext::div_ceil<Index>(size *
sizeof(ListEl),
sizeof(Scalar));
101 m_allocatedElements = convert_index((allocSize *
sizeof(Scalar)) /
sizeof(ListEl));
104 m_allocatedElements = convert_index((size *
sizeof(Scalar)) /
sizeof(ListEl));
107 m_buffer =
static_cast<Scalar*
>(internal::aligned_malloc(allocSize *
sizeof(Scalar)));
108 m_allocatedSize = convert_index(allocSize);
112 void reallocateSparse() {
113 Index copyElements = m_llSize;
114 StorageIndex newAllocatedElements = (std::min)(StorageIndex(m_allocatedElements * 1.5), m_size);
115 Index allocSize = newAllocatedElements *
sizeof(ListEl);
116 allocSize = numext::div_ceil<Index>(allocSize,
sizeof(Scalar));
117 Scalar* newBuffer =
static_cast<Scalar*
>(internal::aligned_malloc(allocSize *
sizeof(Scalar)));
118 ListEl* newElements =
static_cast<ListEl*
>(
static_cast<void*
>(newBuffer));
122 EIGEN_TRY { internal::move_construct_elements_of_array(newElements, listElements(), copyElements); }
124 internal::aligned_free(newBuffer);
127 internal::destruct_elements_of_array(listElements(), copyElements);
128 internal::aligned_free(m_buffer);
129 m_buffer = newBuffer;
130 m_allocatedElements = newAllocatedElements;
131 m_allocatedSize = convert_index(allocSize);
138 static ListEl* constructListEl(ListEl* dst, StorageIndex index, StorageIndex next) {
139 return ::new (
static_cast<void*
>(dst)) ListEl{next, index, Scalar(0)};
143 void destructElements() {
144 if (m_mode == IsDense) {
145 internal::destruct_elements_of_array(m_buffer, m_denseConstructed);
146 m_denseConstructed = 0;
147 }
else if (m_mode == IsSparse) {
148 internal::destruct_elements_of_array(listElements(), m_llSize);
157 StorageIndex m_start;
159 StorageIndex m_allocatedSize;
160 StorageIndex m_allocatedElements;
161 StorageIndex m_denseConstructed;
165 StorageIndex m_llStart;
166 StorageIndex m_llCurrent;
167 StorageIndex m_llSize;
171template <
typename Scalar_,
typename StorageIndex_>
172Index AmbiVector<Scalar_, StorageIndex_>::nonZeros()
const {
173 if (m_mode == IsSparse)
176 return m_end - m_start;
179template <
typename Scalar_,
typename StorageIndex_>
180void AmbiVector<Scalar_, StorageIndex_>::init(
double estimatedDensity) {
181 if (estimatedDensity > 0.1)
187template <
typename Scalar_,
typename StorageIndex_>
188void AmbiVector<Scalar_, StorageIndex_>::init(
int mode) {
189 if (mode != m_mode) {
191 m_mode = convert_index(mode);
192 }
else if (m_mode == IsSparse) {
194 internal::destruct_elements_of_array(listElements(), m_llSize);
196 if (m_mode == IsDense && m_denseConstructed < m_size) {
199 internal::default_construct_elements_of_array(m_buffer + m_denseConstructed, m_size - m_denseConstructed);
200 m_denseConstructed = m_size;
215template <
typename Scalar_,
typename StorageIndex_>
216void AmbiVector<Scalar_, StorageIndex_>::restart() {
217 m_llCurrent = m_llStart;
221template <
typename Scalar_,
typename StorageIndex_>
222void AmbiVector<Scalar_, StorageIndex_>::setZero() {
223 if (m_mode == IsDense) {
224 for (Index i = m_start; i < m_end; ++i) m_buffer[i] = Scalar(0);
226 eigen_assert(m_mode == IsSparse);
229 internal::destruct_elements_of_array(listElements(), m_llSize);
235template <
typename Scalar_,
typename StorageIndex_>
236Scalar_& AmbiVector<Scalar_, StorageIndex_>::coeffRef(Index i) {
237 if (m_mode == IsDense)
240 ListEl* EIGEN_RESTRICT llElements = listElements();
242 eigen_assert(m_mode == IsSparse);
245 ListEl& el = *constructListEl(llElements, convert_index(i), -1);
250 }
else if (i < llElements[m_llStart].index) {
252 ListEl& el = *constructListEl(llElements + m_llSize, convert_index(i), m_llStart);
253 m_llStart = m_llSize;
254 m_llCurrent = m_llStart;
258 StorageIndex nextel = llElements[m_llCurrent].next;
259 eigen_assert(i >= llElements[m_llCurrent].index &&
260 "you must call restart() before inserting an element with lower or equal index");
261 while (nextel >= 0 && llElements[nextel].index <= i) {
262 m_llCurrent = nextel;
263 nextel = llElements[nextel].next;
266 if (llElements[m_llCurrent].index == i) {
268 return llElements[m_llCurrent].value;
270 if (m_llSize >= m_allocatedElements) {
272 llElements = listElements();
274 eigen_internal_assert(m_llSize < m_allocatedElements &&
"internal error: overflow in sparse mode");
276 ListEl& el = *constructListEl(llElements + m_llSize, convert_index(i), llElements[m_llCurrent].next);
277 llElements[m_llCurrent].next = m_llSize;
285template <
typename Scalar_,
typename StorageIndex_>
286Scalar_& AmbiVector<Scalar_, StorageIndex_>::coeff(Index i) {
287 if (m_mode == IsDense)
290 ListEl* EIGEN_RESTRICT llElements = listElements();
291 eigen_assert(m_mode == IsSparse);
292 if ((m_llSize == 0) || (i < llElements[m_llStart].index)) {
295 Index elid = m_llStart;
296 while (elid >= 0 && llElements[elid].index < i) elid = llElements[elid].next;
298 if (elid >= 0 && llElements[elid].index == i)
299 return llElements[elid].value;
307template <
typename Scalar_,
typename StorageIndex_>
308class AmbiVector<Scalar_, StorageIndex_>::
Iterator {
310 using Scalar = Scalar_;
311 using RealScalar =
typename NumTraits<Scalar>::Real;
319 explicit Iterator(
const AmbiVector& vec,
const RealScalar& epsilon = 0) : m_vector(vec) {
322 m_isDense = m_vector.m_mode == IsDense;
326 m_cachedIndex = m_vector.m_start - 1;
329 const ListEl* EIGEN_RESTRICT llElements = m_vector.listElements();
330 m_currentEl = m_vector.m_llStart;
331 while (m_currentEl >= 0 && abs(llElements[m_currentEl].value) <= m_epsilon)
332 m_currentEl = llElements[m_currentEl].next;
333 if (m_currentEl < 0) {
337 m_cachedIndex = llElements[m_currentEl].index;
338 m_cachedValue = llElements[m_currentEl].value;
343 StorageIndex index()
const {
return m_cachedIndex; }
344 Scalar value()
const {
return m_cachedValue; }
346 operator bool()
const {
return m_cachedIndex >= 0; }
348 Iterator& operator++() {
353 }
while (m_cachedIndex < m_vector.m_end && abs(m_vector.m_buffer[m_cachedIndex]) <= m_epsilon);
354 if (m_cachedIndex < m_vector.m_end)
355 m_cachedValue = m_vector.m_buffer[m_cachedIndex];
359 const ListEl* EIGEN_RESTRICT llElements = m_vector.listElements();
361 m_currentEl = llElements[m_currentEl].next;
362 }
while (m_currentEl >= 0 && abs(llElements[m_currentEl].value) <= m_epsilon);
363 if (m_currentEl < 0) {
366 m_cachedIndex = llElements[m_currentEl].index;
367 m_cachedValue = llElements[m_currentEl].value;
374 const AmbiVector& m_vector;
375 StorageIndex m_currentEl;
376 RealScalar m_epsilon;
377 StorageIndex m_cachedIndex;
378 Scalar m_cachedValue;
Definition AmbiVector.h:308
Iterator(const AmbiVector &vec, const RealScalar &epsilon=0)
Definition AmbiVector.h:319