Loading...
Searching...
No Matches
flatVector2D.tpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25#ifndef __BITPIT_FLAT_VECTOR_2D_TPP__
26#define __BITPIT_FLAT_VECTOR_2D_TPP__
27
28#include <vector>
29#include <cassert>
30#include <iostream>
31#include <memory>
32
33#include "binary_stream.hpp"
34
35namespace bitpit {
36
45template<class T>
46OBinaryStream& operator<<(OBinaryStream &buffer, const FlatVector2D<T> &vector)
47{
48 buffer << vector.m_index;
49 buffer << vector.m_v;
50
51 return buffer;
52}
53
62template<class T>
63IBinaryStream& operator>>(IBinaryStream &buffer, FlatVector2D<T> &vector)
64{
65 buffer >> vector.m_index;
66 buffer >> vector.m_v;
67
68 return buffer;
74template <class T>
76 : m_index(initialize ? 1 : 0, 0L)
77{
78}
79
87template <class T>
88FlatVector2D<T>::FlatVector2D(const std::vector<std::size_t> &sizes, const T &value)
89{
90 initialize(sizes.size(), sizes.data(), 1, &value, 0);
91}
92
101template <class T>
102FlatVector2D<T>::FlatVector2D(std::size_t nVectors, std::size_t size, const T &value)
104 initialize(nVectors, &size, 0, &value, 0);
115template <class T>
116FlatVector2D<T>::FlatVector2D(std::size_t nVectors, const std::size_t *sizes, const T &value)
118 initialize(nVectors, sizes, 1, &value, 0);
119}
128template <class T>
129FlatVector2D<T>::FlatVector2D(std::size_t nVectors, const std::size_t *sizes, const T *values)
131 initialize(nVectors, sizes, 1, values, 1);
132}
140template <class T>
141FlatVector2D<T>::FlatVector2D(const std::vector<std::vector<T> > &vector2D)
142{
143 initialize(vector2D);
151template <class T>
153{
154 return (!m_index.empty());
155}
164template <class T>
165void FlatVector2D<T>::initialize(const std::vector<std::size_t> &sizes, const T &value)
166{
167 initialize(sizes.size(), sizes.data(), 1, &value, 1);
168}
169
178template <class T>
179void FlatVector2D<T>::initialize(std::size_t nVectors, std::size_t size, const T &value)
180{
181 initialize(nVectors, &size, 0, &value, 0);
182}
183
192template <class T>
193void FlatVector2D<T>::initialize(std::size_t nVectors, const std::size_t *sizes, const T &value)
194{
195 initialize(nVectors, sizes, 1, &value, 0);
196}
197
198
206template <class T>
207void FlatVector2D<T>::initialize(std::size_t nVectors, const std::size_t *sizes, const T *values)
208{
209 initialize(nVectors, sizes, 1, values, 1);
210}
211
221template <class T>
222void FlatVector2D<T>::initialize(std::size_t nVectors,
223 const std::size_t *sizes, std::size_t sizesStride,
224 const T *values, std::size_t valuesStride)
225{
226 std::size_t nItems = 0;
227 for (std::size_t i = 0; i < nVectors; ++i) {
228 nItems += *(sizes + i * sizesStride);
229 }
230
231 // Check if the container need reallocation
232 //
233 // If the current number of items is different from the number of items
234 // the container should contain after the initialization, a reallocation
235 // is needed.
236 bool reallocateIndex = (nVectors != size());
237 bool reallocateValues = (nItems != getItemCount());
238
239 // Destroy current data structures
240 //
241 // Index and the storage data will probabily be stored in memory
242 // regions contigous to each other. To reduce memory fragmentation
243 // it's better to deallocate the container before updating its
244 // data structures.
245 if (reallocateIndex || reallocateValues) {
246 destroy(reallocateIndex, reallocateValues);
247 }
248
249 // Initialize the indexes
250 if (reallocateIndex) {
251 m_index.resize(nVectors + 1);
252 }
253
254 m_index[0] = 0;
255 for (std::size_t i = 0; i < nVectors; ++i) {
256 m_index[i+1] = m_index[i] + *(sizes + i * sizesStride);
257 }
258
259 // Initialize the storage
260 if (valuesStride == 0) {
261 if (reallocateValues) {
262 m_v.assign(nItems, *values);
263 } else {
264 for (std::size_t k = 0; k < nItems; ++k) {
265 m_v[k] = *values;
266 }
267 }
268 } else {
269 if (reallocateValues) {
270 m_v.resize(nItems);
271 }
272
273 std::size_t k = 0;
274 for (std::size_t i = 0; i < nVectors; ++i) {
275 std::size_t subArraySize = *(sizes + i * sizesStride);
276 for (std::size_t j = 0; j < subArraySize; ++j) {
277 m_v[k++] = *(values + i * valuesStride + j);
278 }
279 }
280 }
281}
282
289template <class T>
290void FlatVector2D<T>::initialize(const std::vector<std::vector<T> > &vector2D)
291{
292 std::size_t nVectors = vector2D.size();
293
294 std::size_t nItems = 0;
295 for (std::size_t i = 0; i < nVectors; ++i) {
296 nItems += vector2D[i].size();
297 }
298
299 // Check if the container need reallocation
300 //
301 // If the current number of items is different from the number of items
302 // the container should contain after the initialization, a reallocation
303 // is needed.
304 bool reallocateIndex = (nVectors != size());
305 bool reallocateValues = (nItems != getItemCount());
306
307 // Destroy current data structures
308 //
309 // Index and the storage data will probabily be stored in memory
310 // regions contigous to each other. To reduce memory fragmentation
311 // it's better to deallocate the container before updating its
312 // data structures.
313 if (reallocateIndex || reallocateValues) {
314 destroy(reallocateIndex, reallocateValues);
315 }
316
317 // Initialize the indexes
318 if (reallocateIndex) {
319 m_index.resize(nVectors + 1);
320 }
321
322 m_index[0] = 0;
323 for (std::size_t i = 0; i < nVectors; ++i) {
324 m_index[i+1] = m_index[i] + vector2D[i].size();
325 }
326
327 // Initialize the storage
328 if (reallocateValues) {
329 m_v.resize(nItems);
330 }
331
332 std::size_t k = 0;
333 for (std::size_t i = 0; i < nVectors; ++i) {
334 std::size_t subArraySize = vector2D[i].size();
335 for (std::size_t j = 0; j < subArraySize; ++j) {
336 m_v[k++] = vector2D[i][j];
337 }
338 }
339}
340
347template <class T>
349{
350 m_v.assign(other.m_v.begin(), other.m_v.end());
351 m_index.assign(other.m_index.begin(), other.m_index.end());
352}
353
360template <class T>
362{
363 destroy(true, true);
364}
365
375template <class T>
376void FlatVector2D<T>::destroy(bool destroyIndex, bool destroyValues)
377{
378 if (destroyIndex) {
379 m_index.clear();
380 m_index.shrink_to_fit();
381 }
382
383 if (destroyValues) {
384 m_v.clear();
385 m_v.shrink_to_fit();
386 }
387}
388
400template <class T>
401void FlatVector2D<T>::reserve(std::size_t nVectors, std::size_t nItems)
402{
403 m_index.reserve(nVectors + 1);
404 if (nItems > 0) {
405 m_v.reserve(nItems);
406 }
407}
408
414template <class T>
416{
417 m_index.swap(other.m_index);
418 m_v.swap(other.m_v);
419}
420
427template <class T>
429{
430 std::fill(m_v.begin(), m_v.end(), value);
431}
432
438template <class T>
440{
441 return m_index == rhs.m_index && m_v == rhs.m_v;
442}
443
449template <class T>
451{
452 return size() == 0;
453}
454
465template <class T>
466void FlatVector2D<T>::clear(bool release)
467{
468 if (release) {
469 std::vector<T>(0).swap(m_v);
470
471 std::vector<size_t>(1, 0L).swap(m_index);
472 } else {
473 m_v.clear();
474
475 m_index.resize(1);
476 m_index[0] = 0;
477 }
478}
479
490template <class T>
492{
493 std::size_t nVectors = size();
494 if (release) {
495 std::vector<T>(0).swap(m_v);
496
497 std::vector<size_t>(nVectors + 1, 0L).swap(m_index);
498 } else {
499 m_v.clear();
500
501 m_index.assign(nVectors + 1, 0L);
502 }
503}
504
510template <class T>
512{
513 m_v.shrink_to_fit();
514 m_index.shrink_to_fit();
515}
516
524template <class T>
525const std::size_t * FlatVector2D<T>::indices() const noexcept
526{
527 return m_index.data();
528}
529
540template <class T>
541const std::size_t * FlatVector2D<T>::indices(std::size_t i) const noexcept
542{
543 return (m_index.data() + i);
544}
545
554template <class T>
556{
557 return m_v.data();
558}
559
568template <class T>
569const T * FlatVector2D<T>::data() const noexcept
570{
571 return m_v.data();
572}
573
582template <class T>
583const std::vector<T> & FlatVector2D<T>::vector() const
584{
585 return m_v;
586}
587
594template <class T>
596{
597 pushBack(0);
598}
599
611template <class T>
612void FlatVector2D<T>::pushBack(std::size_t subArraySize, const T &value)
613{
614 std::size_t previousLastIndex = m_index.back();
615 m_index.emplace_back(previousLastIndex + subArraySize);
616
617 m_v.resize(m_v.size() + subArraySize, value);
618}
619
628template <class T>
629void FlatVector2D<T>::pushBack(const std::vector<T> &subArray)
630{
631 pushBack(subArray.size(), subArray.data());
632}
633
643template <class T>
644void FlatVector2D<T>::pushBack(std::size_t subArraySize, const T *subArray)
645{
646 std::size_t previousLastIndex = m_index.back();
647 m_index.emplace_back(previousLastIndex + subArraySize);
648
649 m_v.insert(m_v.end(), subArray, subArray + subArraySize);
650}
651
659template <class T>
661{
662 m_index.back()++;
663
664 m_v.emplace_back(value);
665}
666
674template <class T>
676{
677 m_index.back()++;
678
679 m_v.emplace_back(std::move(value));
680}
681
690template <class T>
691void FlatVector2D<T>::pushBackItem(std::size_t i, const T &value)
692{
693 assert(isIndexValid(i));
694
695 m_v.insert(m_v.begin() + m_index[i+1], value);
696
697 std::size_t nIndexes = m_index.size();
698 for (std::size_t k = i + 1; k < nIndexes; ++k) {
699 m_index[k]++;
700 }
701}
702
703
712template <class T>
713void FlatVector2D<T>::pushBackItem(std::size_t i, T &&value)
714{
715 assert(isIndexValid(i));
716
717 m_v.insert(m_v.begin() + m_index[i+1], std::move(value));
718
719 std::size_t nIndexes = m_index.size();
720 for (std::size_t k = i + 1; k < nIndexes; ++k) {
721 m_index[k]++;
722 }
723}
724
731template <class T>
733{
734 if (size() == 0) {
735 return;
736 }
737
738 m_index.pop_back();
739 m_v.resize(m_index.back() + 1);
740}
741
747template <class T>
749{
750 if (getItemCount(size() - 1) == 0) {
751 return;
752 }
753
754 m_index.back()--;
755 m_v.resize(m_index.back() + 1);
756}
757
765template <class T>
767{
768 assert(isIndexValid(i));
769
770 if (getItemCount(i) == 0) {
771 return;
772 }
773
774 m_v.erase(m_v.begin() + m_index[i+1] - 1);
775
776 std::size_t nIndexes = m_index.size();
777 for (std::size_t k = i + 1; k < nIndexes; ++k) {
778 m_index[k]--;
779 }
780}
781
790template <class T>
791void FlatVector2D<T>::erase(std::size_t i)
792{
793 assert(isIndexValid(i));
794
795 m_v.erase(m_v.begin() + m_index[i], m_v.begin() + m_index[i+1] - 1);
796 m_index.erase(m_index.begin() + i + 1);
797}
798
805template <class T>
806void FlatVector2D<T>::eraseItem(std::size_t i, std::size_t j)
807{
808 assert(isIndexValid(i, j));
809
810 m_v.erase(m_v.begin() + m_index[i] + j);
811
812 std::size_t nIndexes = m_index.size();
813 for (std::size_t k = i + 1; k < nIndexes; ++k) {
814 m_index[k]--;
815 }
816}
817
825template <class T>
826void FlatVector2D<T>::setItem(std::size_t i, std::size_t j, const T &value)
827{
828 assert(isIndexValid(i, j));
829 (*this)[i][j] = value;
830}
831
839template <class T>
840void FlatVector2D<T>::setItem(std::size_t i, std::size_t j, T &&value)
841{
842 assert(isIndexValid(i, j));
843 (*this)[i][j] = std::move(value);
844}
845
853template <class T>
854T & FlatVector2D<T>::getItem(std::size_t i, std::size_t j)
855{
856 assert(isIndexValid(i, j));
857 return (*this)[i][j];
858}
859
867template <class T>
868const T & FlatVector2D<T>::getItem(std::size_t i, std::size_t j) const
869{
870 assert(isIndexValid(i, j));
871 return (*this)[i][j];
872}
873
880template <class T>
881const T * FlatVector2D<T>::get(std::size_t i) const
882{
883 assert(!empty());
884 assert(isIndexValid(i));
885 return (*this)[i];
886}
887
894template <class T>
895T * FlatVector2D<T>::get(std::size_t i)
896{
897 assert(!empty());
898 assert(isIndexValid(i));
899 return (*this)[i];
900}
901
908template <class T>
909void FlatVector2D<T>::rawSetItem(std::size_t k, const T &value)
910{
911 m_v[k] = value;
912}
913
920template <class T>
921void FlatVector2D<T>::rawSetItem(std::size_t k, T &&value)
922{
923 m_v[k] = std::move(value);
924}
925
932template <class T>
934{
935 return m_v[k];
936}
937
944template <class T>
945const T & FlatVector2D<T>::rawGetItem(std::size_t k) const
946{
947 return m_v[k];
948}
949
955template <class T>
957{
958 return get(size() - 1);
959}
960
966template <class T>
968{
969 return get(0);
970}
971
977template <class T>
978std::size_t FlatVector2D<T>::size() const
979{
980 if (!isInitialized()) {
981 return 0;
982 }
983
984 return (m_index.size() - 1);
985}
986
994template <class T>
995std::size_t FlatVector2D<T>::capacity() const
996{
997 if (!isInitialized()) {
998 return 0;
999 }
1000
1001 return m_index.capacity() - 1;
1002}
1003
1007template <class T>
1009{
1010 if (size() == 0) {
1011 return;
1012 }
1013
1014 m_index[1] = m_index.back();
1015 m_index.resize(2);
1016}
1017
1023template <class T>
1025{
1026 if (!isInitialized()) {
1027 return 0;
1028 }
1029
1030 return m_v.size();
1031}
1032
1039template <class T>
1040std::size_t FlatVector2D<T>::getItemCount(std::size_t i) const
1041{
1042 if (!isInitialized()) {
1043 return 0;
1044 }
1045
1046 return m_index[i + 1] - m_index[i];
1047}
1048
1056template <class T>
1058{
1059 return m_v.capacity();
1060}
1061
1067template <class T>
1069{
1070 return ((2 + m_index.size())*sizeof(size_t) + m_v.size() * sizeof(T));
1071}
1072
1079template <class T>
1080const T* FlatVector2D<T>::operator[](std::size_t i) const
1081{
1082 assert(isIndexValid(i));
1083
1084 if (m_v.empty()) {
1085 return nullptr;
1086 }
1087
1088 std::size_t index = m_index[i];
1089 return &m_v[index];
1090}
1091
1098template <class T>
1099T* FlatVector2D<T>::operator[](std::size_t i)
1100{
1101 assert(isIndexValid(i));
1102
1103 if (m_v.empty()) {
1104 return nullptr;
1105 }
1106
1107 std::size_t index = m_index[i];
1108 return &m_v[index];
1109}
1110
1117template <class T>
1118bool FlatVector2D<T>::isIndexValid(std::size_t i) const
1119{
1120 return (i < size());
1121}
1122
1130template <class T>
1131bool FlatVector2D<T>::isIndexValid(std::size_t i, std::size_t j) const
1132{
1133 if (!isIndexValid(i)) {
1134 return false;
1135 }
1136
1137 return (j < (m_index[i+1] - m_index[i]));
1138}
1139
1140}
1141
1142#endif
Metafunction for generation of a flattened vector of vectors.
const std::size_t * indices() const noexcept
bool isInitialized() const
void clearItems(bool release=true)
T & getItem(std::size_t i, std::size_t j)
bool operator==(const FlatVector2D &rhs) const
void swap(FlatVector2D &other) noexcept
T & rawGetItem(std::size_t k)
const std::vector< T > & vector() const
std::size_t getItemCapacity() const
FlatVector2D(bool initialize=true)
void rawSetItem(std::size_t k, const T &value)
std::size_t size() const
void clear(bool release=true)
void reserve(std::size_t nVectors, std::size_t nItems=0)
std::size_t getItemCount() const
void initialize(const std::vector< std::size_t > &sizes, const T &value=T())
void eraseItem(std::size_t i, std::size_t j)
void erase(std::size_t i)
const T * get(std::size_t i) const
std::size_t capacity() const
std::size_t getBinarySize() const
void setItem(std::size_t i, std::size_t j, const T &value)
void pushBackItem(const T &value)
Logger & operator<<(Logger &logger, LoggerManipulator< T > &&m)
Definition logger.hpp:367
--- layout: doxygen_footer ---