AmbiVector.h revision c981c48f5bc9aefeffc0bcb0cc3934c2fae179dd
1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_AMBIVECTOR_H
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_AMBIVECTOR_H
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen {
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal {
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \internal
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Hybrid sparse/dense vector class designed for intensive read-write operations.
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * See BasicSparseLLT and SparseProduct for usage examples.
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar, typename _Index>
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass AmbiVector
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef _Scalar Scalar;
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef _Index Index;
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef typename NumTraits<Scalar>::Real RealScalar;
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    AmbiVector(Index size)
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_buffer(0), m_zero(0), m_size(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1)
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      resize(size);
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void init(double estimatedDensity);
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void init(int mode);
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index nonZeros() const;
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Specifies a sub-vector to work on */
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void setBounds(Index start, Index end) { m_start = start; m_end = end; }
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void setZero();
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void restart();
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar& coeffRef(Index i);
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar& coeff(Index i);
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    class Iterator;
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ~AmbiVector() { delete[] m_buffer; }
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void resize(Index size)
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (m_allocatedSize < size)
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        reallocate(size);
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_size = size;
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index size() const { return m_size; }
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void reallocate(Index size)
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // if the size of the matrix is not too large, let's allocate a bit more than needed such
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // that we can handle dense vector even in sparse mode.
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      delete[] m_buffer;
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (size<1000)
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        Index allocSize = (size * sizeof(ListEl))/sizeof(Scalar);
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_allocatedElements = (allocSize*sizeof(Scalar))/sizeof(ListEl);
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_buffer = new Scalar[allocSize];
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_allocatedElements = (size*sizeof(Scalar))/sizeof(ListEl);
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_buffer = new Scalar[size];
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_size = size;
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_start = 0;
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_end = m_size;
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    void reallocateSparse()
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index copyElements = m_allocatedElements;
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_allocatedElements = (std::min)(Index(m_allocatedElements*1.5),m_size);
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index allocSize = m_allocatedElements * sizeof(ListEl);
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Scalar* newBuffer = new Scalar[allocSize];
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      memcpy(newBuffer,  m_buffer,  copyElements * sizeof(ListEl));
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      delete[] m_buffer;
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_buffer = newBuffer;
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // element type of the linked list
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    struct ListEl
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index next;
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index index;
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Scalar value;
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    };
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // used to store data in both mode
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar* m_buffer;
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar m_zero;
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_size;
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_start;
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_end;
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_allocatedSize;
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_allocatedElements;
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_mode;
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // linked list mode
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_llStart;
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_llCurrent;
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_llSize;
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \returns the number of non zeros in the current sub vector */
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath_Index AmbiVector<_Scalar,_Index>::nonZeros() const
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (m_mode==IsSparse)
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return m_llSize;
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return m_end - m_start;
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid AmbiVector<_Scalar,_Index>::init(double estimatedDensity)
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (estimatedDensity>0.1)
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    init(IsDense);
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    init(IsSparse);
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid AmbiVector<_Scalar,_Index>::init(int mode)
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m_mode = mode;
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (m_mode==IsSparse)
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_llSize = 0;
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_llStart = -1;
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** Must be called whenever we might perform a write access
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * with an index smaller than the previous one.
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  *
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  * Don't worry, this function is extremely cheap.
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid AmbiVector<_Scalar,_Index>::restart()
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m_llCurrent = m_llStart;
162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** Set all coefficients of current subvector to zero */
165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid AmbiVector<_Scalar,_Index>::setZero()
167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (m_mode==IsDense)
169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for (Index i=m_start; i<m_end; ++i)
171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_buffer[i] = Scalar(0);
172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_mode==IsSparse);
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_llSize = 0;
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m_llStart = -1;
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath_Scalar& AmbiVector<_Scalar,_Index>::coeffRef(_Index i)
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (m_mode==IsDense)
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return m_buffer[i];
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_buffer);
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // TODO factorize the following code to reduce code generation
190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_mode==IsSparse);
191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    if (m_llSize==0)
192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // this is the first element
194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_llStart = 0;
195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_llCurrent = 0;
196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ++m_llSize;
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      llElements[0].value = Scalar(0);
198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      llElements[0].index = i;
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      llElements[0].next = -1;
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return llElements[0].value;
201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    else if (i<llElements[m_llStart].index)
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      // this is going to be the new first element of the list
205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ListEl& el = llElements[m_llSize];
206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      el.value = Scalar(0);
207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      el.index = i;
208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      el.next = m_llStart;
209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_llStart = m_llSize;
210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ++m_llSize;
211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_llCurrent = m_llStart;
212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return el.value;
213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    else
215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index nextel = llElements[m_llCurrent].next;
217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      eigen_assert(i>=llElements[m_llCurrent].index && "you must call restart() before inserting an element with lower or equal index");
218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      while (nextel >= 0 && llElements[nextel].index<=i)
219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_llCurrent = nextel;
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        nextel = llElements[nextel].next;
222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (llElements[m_llCurrent].index==i)
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        // the coefficient already exists and we found it !
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return llElements[m_llCurrent].value;
228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if (m_llSize>=m_allocatedElements)
232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          reallocateSparse();
234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          llElements = reinterpret_cast<ListEl*>(m_buffer);
235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        eigen_internal_assert(m_llSize<m_allocatedElements && "internal error: overflow in sparse mode");
237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        // let's insert a new coefficient
238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ListEl& el = llElements[m_llSize];
239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        el.value = Scalar(0);
240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        el.index = i;
241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        el.next = llElements[m_llCurrent].next;
242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        llElements[m_llCurrent].next = m_llSize;
243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ++m_llSize;
244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return el.value;
245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath_Scalar& AmbiVector<_Scalar,_Index>::coeff(_Index i)
252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (m_mode==IsDense)
254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return m_buffer[i];
255c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
256c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_buffer);
258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    eigen_assert(m_mode==IsSparse);
259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    if ((m_llSize==0) || (i<llElements[m_llStart].index))
260c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
261c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return m_zero;
262c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
263c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    else
264c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
265c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Index elid = m_llStart;
266c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      while (elid >= 0 && llElements[elid].index<i)
267c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        elid = llElements[elid].next;
268c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
269c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (llElements[elid].index==i)
270c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return llElements[m_llCurrent].value;
271c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
272c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        return m_zero;
273c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
274c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
275c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
276c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
277c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** Iterator over the nonzero coefficients */
278c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename _Scalar,typename _Index>
279c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathclass AmbiVector<_Scalar,_Index>::Iterator
280c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
281c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  public:
282c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef _Scalar Scalar;
283c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    typedef typename NumTraits<Scalar>::Real RealScalar;
284c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
285c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    /** Default constructor
286c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \param vec the vector on which we iterate
287c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * \param epsilon the minimal value used to prune zero coefficients.
288c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * In practice, all coefficients having a magnitude smaller than \a epsilon
289c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      * are skipped.
290c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      */
291c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Iterator(const AmbiVector& vec, RealScalar epsilon = 0)
292c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      : m_vector(vec)
293c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
294c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_epsilon = epsilon;
295c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      m_isDense = m_vector.m_mode==IsDense;
296c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (m_isDense)
297c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
298c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_currentEl = 0;   // this is to avoid a compilation warning
299c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_cachedValue = 0; // this is to avoid a compilation warning
300c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_cachedIndex = m_vector.m_start-1;
301c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ++(*this);
302c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
303c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
304c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
305c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
306c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        m_currentEl = m_vector.m_llStart;
307c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        while (m_currentEl>=0 && internal::abs(llElements[m_currentEl].value)<=m_epsilon)
308c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_currentEl = llElements[m_currentEl].next;
309c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if (m_currentEl<0)
310c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
311c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedValue = 0; // this is to avoid a compilation warning
312c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedIndex = -1;
313c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
314c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        else
315c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
316c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedIndex = llElements[m_currentEl].index;
317c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedValue = llElements[m_currentEl].value;
318c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
319c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
320c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
321c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
322c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index index() const { return m_cachedIndex; }
323c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar value() const { return m_cachedValue; }
324c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
325c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    operator bool() const { return m_cachedIndex>=0; }
326c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
327c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Iterator& operator++()
328c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
329c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (m_isDense)
330c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
331c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        do {
332c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          ++m_cachedIndex;
333c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        } while (m_cachedIndex<m_vector.m_end && internal::abs(m_vector.m_buffer[m_cachedIndex])<m_epsilon);
334c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if (m_cachedIndex<m_vector.m_end)
335c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedValue = m_vector.m_buffer[m_cachedIndex];
336c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        else
337c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedIndex=-1;
338c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
339c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
340c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
341c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
342c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        do {
343c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_currentEl = llElements[m_currentEl].next;
344c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        } while (m_currentEl>=0 && internal::abs(llElements[m_currentEl].value)<m_epsilon);
345c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        if (m_currentEl<0)
346c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
347c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedIndex = -1;
348c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
349c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        else
350c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        {
351c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedIndex = llElements[m_currentEl].index;
352c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath          m_cachedValue = llElements[m_currentEl].value;
353c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        }
354c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
355c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      return *this;
356c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
357c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
358c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  protected:
359c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const AmbiVector& m_vector; // the target vector
360c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_currentEl;            // the current element in sparse/linked-list mode
361c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    RealScalar m_epsilon;       // epsilon used to prune zero coefficients
362c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Index m_cachedIndex;          // current coordinate
363c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar m_cachedValue;       // current value
364c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    bool m_isDense;             // mode of the vector
365c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
366c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
367c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace internal
368c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
369c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen
370c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
371c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_AMBIVECTOR_H
372