Free Electron
SparseArray.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __solve_SparseArray_h__
8 #define __solve_SparseArray_h__
9 
10 #define FE_SA_PREALLOC 8
11 #define FE_SA_GROW 1.5f
12 
13 namespace fe
14 {
15 namespace ext
16 {
17 
18 /**************************************************************************//**
19  @brief Row-Compressed Sparse Container
20 
21  @ingroup solve
22 *//***************************************************************************/
23 template<class T>
25 {
26  public:
27  SparseArray(U32 prealloc=FE_SA_PREALLOC);
28  SparseArray(const SparseArray<T> &other);
29  ~SparseArray(void);
30 
31  SparseArray<T>& operator=(const SparseArray<T> &other);
32 
33  /// @brief Remove all existing values
34  void reset(U32 prealloc=FE_SA_PREALLOC);
35 
36  /// @brief Zero existing values, but do not remove
37  void clear(void);
38 
39  /// @brief Return the largest index
40  U32 size(void) const { return m_used? m_maxIndex+1: 0; }
41 
42  /// @brief Return the entry at the particular index
43  T& operator[](U32 index);
44 
45  /// @brief Return the const entry at the particular index
46  T operator[](U32 index) const;
47 
48  /** @brief Return the number of actual stored entries
49 
50  This can be less than the size.
51  Using entry() instead of operator[] can be helpful
52  to limit an iteration to only the values that
53  are actually set, instead of reading lots of zeros.
54  */
55  U32 entries(void) const { return m_used; }
56 
57  /// @brief Return the index at a storage location
58  U32 index(U32 location) const { return m_pIndex[location]; }
59 
60  /// @brief Return the entry at a storage location
61  T& entry(U32 location) { return m_pData[location]; }
62 
63  /// @brief Return the const entry at a storage location
64  T entry(U32 location) const { return m_pData[location]; }
65 
66 
67  private:
68  void grow(void);
69  void initialize(U32 prealloc);
70 
71  U32 m_allocated;
72  U32 m_used;
73  U32 m_maxIndex;
74  U32 m_cacheLocation;
75  U32* m_pIndex;
76  T* m_pData;
77 };
78 
79 
80 template<class T>
81 inline SparseArray<T>::SparseArray(U32 prealloc):
82  m_pIndex(NULL),
83  m_pData(NULL)
84 {
85  initialize(prealloc);
86 }
87 
88 template<class T>
89 inline void SparseArray<T>::initialize(U32 prealloc)
90 {
91  if(prealloc)
92  {
93  m_pIndex=new U32[prealloc];
94  m_pData=new T[prealloc];
95  }
96 
97  m_allocated=prealloc;
98  m_used=0;
99  m_maxIndex=0;
100  m_cacheLocation=0;
101 }
102 
103 template<class T>
104 inline SparseArray<T>::SparseArray(const SparseArray<T> &other):
105  m_used(0),
106  m_pIndex(NULL),
107  m_pData(NULL)
108 {
109  operator=(other);
110 }
111 
112 template<class T>
113 inline SparseArray<T>::~SparseArray(void)
114 {
115  delete[] m_pIndex;
116  delete[] m_pData;
117 }
118 
119 template<class T>
120 inline void SparseArray<T>::reset(U32 prealloc)
121 {
122  delete[] m_pIndex;
123  delete[] m_pData;
124  initialize(prealloc);
125 }
126 
127 template<class T>
128 inline void SparseArray<T>::clear(void)
129 {
130  for(U32 m=0;m<m_used;m++)
131  {
132  m_pData[m]=defaultByType(m_pData[0]);
133  }
134 }
135 
136 template<class T>
138 {
139  while(m_cacheLocation &&
140  (m_cacheLocation>=m_used || m_pIndex[m_cacheLocation]>index))
141  m_cacheLocation--;
142  while(m_cacheLocation<m_used && m_pIndex[m_cacheLocation]<index)
143  m_cacheLocation++;
144 
145  if(m_cacheLocation>=m_used || m_pIndex[m_cacheLocation]!=index)
146  {
147  if(m_used==m_allocated)
148  {
149  grow();
150  }
151  for(U32 m=m_used;m>m_cacheLocation;m--)
152  {
153  m_pIndex[m]=m_pIndex[m-1];
154  m_pData[m]=m_pData[m-1];
155  }
156  m_pIndex[m_cacheLocation]=index;
157  m_pData[m_cacheLocation]=defaultByType(m_pData[0]);
158  m_used++;
159 
160  if(m_maxIndex<index)
161  {
162  m_maxIndex=index;
163  }
164  }
165 
166  return m_pData[m_cacheLocation];
167 }
168 
169 template<class T>
171 {
172  U32 location=0;
173  while(location<m_used && m_pIndex[location]<index)
174  location++;
175 
176  if(location<m_used && m_pIndex[location]==index)
177  {
178  return m_pData[location];
179  }
180 
181  return defaultByType(m_pData[0]);
182 }
183 
184 template<class T>
186 {
187  if(this != &other)
188  {
189  clear();
190 
191  U32 count=other.m_used;
192  for(U32 i = 0; i < count; i++)
193  {
194  operator[](other.m_pIndex[i])=other.m_pData[i];
195  }
196  }
197  m_cacheLocation=0;
198  return *this;
199 }
200 
201 template<class T>
202 inline void SparseArray<T>::grow(void)
203 {
204  U32 newsize=U32(m_allocated*FE_SA_GROW);
205  U32* pNewIndex=new U32[newsize];
206  T* pNewData=new T[newsize];
207 
208  //* TODO we could do the insertion shift here instead of copying some twice
209  for(U32 m=0;m<m_used;m++)
210  {
211  pNewIndex[m]=m_pIndex[m];
212  pNewData[m]=m_pData[m];
213  }
214 
215  delete[] m_pIndex;
216  delete[] m_pData;
217 
218  m_allocated=newsize;
219  m_pIndex=pNewIndex;
220  m_pData=pNewData;
221 }
222 
223 /** Print to a string
224  @relates SparseArray
225  */
226 template<class T>
227 inline String print(const SparseArray<T> &rhs,BWORD sparse=FALSE)
228 {
229  U32 size=sparse? rhs.entries(): rhs.size();
230 
231  String s = "";
232  for(U32 i = 0; i < size; i++)
233  {
234  if(i)
235  {
236  s.cat(" ");
237  }
238  if(sparse)
239  {
240  s.catf("%d:%.6G", rhs.index(i), rhs.entry(i));
241  }
242  else
243  {
244  s.catf("%.6G", rhs[i]);
245  }
246  }
247  return s;
248 }
249 
250 } /* namespace ext */
251 } /* namespace fe */
252 
253 #endif /* __solve_SparseArray_h__ */
254 
void clear(void)
Zero existing values, but do not remove.
Definition: SparseArray.h:128
kernel
Definition: namespace.dox:3
T entry(U32 location) const
Return the const entry at a storage location.
Definition: SparseArray.h:64
T & entry(U32 location)
Return the entry at a storage location.
Definition: SparseArray.h:61
Row-Compressed Sparse Container.
Definition: SparseArray.h:24
T & operator[](U32 index)
Return the entry at the particular index.
Definition: SparseArray.h:137
String & cat(const char *operand)
Append the current String with the given text.
Definition: String.cc:545
U32 entries(void) const
Return the number of actual stored entries.
Definition: SparseArray.h:55
Automatically reference-counted string container.
Definition: String.h:128
U32 index(U32 location) const
Return the index at a storage location.
Definition: SparseArray.h:58
String & catf(const char *fmt,...)
Populate the string as with sPrintf(), but by concatenating the results to the existing string...
Definition: String.cc:554
String print(const SparseArray< T > &rhs, BWORD sparse=FALSE)
Print to a string.
Definition: SparseArray.h:227
void reset(U32 prealloc=FE_SA_PREALLOC)
Remove all existing values.
Definition: SparseArray.h:120
U32 size(void) const
Return the largest index.
Definition: SparseArray.h:40