##// END OF EJS Templates
Merge pull request 218 from SCIQLOP-Initialisation develop...
perrinel -
r510:42ae2f2974df merge
parent child
Show More
@@ -1,39 +1,64
1 1 #ifndef SCIQLOP_SORTUTILS_H
2 2 #define SCIQLOP_SORTUTILS_H
3 3
4 4 #include <algorithm>
5 5 #include <numeric>
6 6 #include <vector>
7 7
8 8 /**
9 9 * Utility class with methods for sorting data
10 10 */
11 11 struct SortUtils {
12 12 /**
13 13 * Generates a vector representing the index of insertion of each data of a container if this
14 14 * one had to be sorted according to a comparison function.
15 15 *
16 16 * For example:
17 17 * If the container is a vector {1; 4; 2; 5; 3} and the comparison function is std::less, the
18 18 * result would be : {0; 3; 1; 4; 2}
19 19 *
20 20 * @tparam Container the type of the container.
21 21 * @tparam Compare the type of the comparison function
22 22 * @param container the container from which to generate the result. The container must have a
23 23 * at() method that returns a value associated to an index
24 24 * @param compare the comparison function
25 25 */
26 26 template <typename Container, typename Compare>
27 27 static std::vector<int> sortPermutation(const Container &container, const Compare &compare)
28 28 {
29 29 auto permutation = std::vector<int>{};
30 30 permutation.resize(container.size());
31 31
32 32 std::iota(permutation.begin(), permutation.end(), 0);
33 33 std::sort(permutation.begin(), permutation.end(),
34 34 [&](int i, int j) { return compare(container.at(i), container.at(j)); });
35 35 return permutation;
36 36 }
37
38 /**
39 * Sorts a container according to indices passed in parameter
40 * @param container the container sorted
41 * @param sortPermutation the indices used to sort the container
42 * @return the container sorted
43 * @warning no verification is made on validity of sortPermutation (i.e. the vector has unique
44 * indices and its range is [0 ; vector.size()[ )
45 */
46 template <typename Container>
47 static Container sort(const Container &container, const std::vector<int> &sortPermutation)
48 {
49 if (container.size() != sortPermutation.size()) {
50 return Container{};
51 }
52
53 // Inits result
54 auto sortedData = Container{};
55 sortedData.resize(container.size());
56
57 std::transform(sortPermutation.cbegin(), sortPermutation.cend(), sortedData.begin(),
58 [&container](int i) { return container.at(i); });
59
60 return sortedData;
61 }
37 62 };
38 63
39 64 #endif // SCIQLOP_SORTUTILS_H
@@ -1,169 +1,230
1 1 #ifndef SCIQLOP_ARRAYDATA_H
2 2 #define SCIQLOP_ARRAYDATA_H
3 3
4 #include <Common/SortUtils.h>
5
4 6 #include <QReadLocker>
5 7 #include <QReadWriteLock>
6 8 #include <QVector>
7 9
8 10 #include <memory>
9 11
12 template <int Dim>
13 class ArrayData;
14
15 using DataContainer = QVector<QVector<double> >;
16
17 namespace arraydata_detail {
18
19 /// Struct used to sort ArrayData
20 template <int Dim>
21 struct Sort {
22 static std::shared_ptr<ArrayData<Dim> > sort(const DataContainer &data,
23 const std::vector<int> &sortPermutation)
24 {
25 auto nbComponents = data.size();
26 auto sortedData = DataContainer(nbComponents);
27
28 for (auto i = 0; i < nbComponents; ++i) {
29 sortedData[i] = SortUtils::sort(data.at(i), sortPermutation);
30 }
31
32 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
33 }
34 };
35
36 /// Specialization for uni-dimensional ArrayData
37 template <>
38 struct Sort<1> {
39 static std::shared_ptr<ArrayData<1> > sort(const DataContainer &data,
40 const std::vector<int> &sortPermutation)
41 {
42 return std::make_shared<ArrayData<1> >(SortUtils::sort(data.at(0), sortPermutation));
43 }
44 };
45
46 } // namespace arraydata_detail
47
10 48 /**
11 49 * @brief The ArrayData class represents a dataset for a data series.
12 50 *
13 51 * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim
14 * template-parameter.
52 * template-parameter. In a case of a two-dimensional dataset, each dataset component has the same
53 * number of values
15 54 *
16 55 * @tparam Dim the dimension of the ArrayData (one or two)
17 56 * @sa IDataSeries
18 57 */
19 58 template <int Dim>
20 59 class ArrayData {
21 60 public:
22 /**
23 * Ctor for a unidimensional ArrayData
24 * @param nbColumns the number of values the ArrayData will hold
25 */
26 template <int D = Dim, typename = std::enable_if_t<D == 1> >
27 explicit ArrayData(int nbColumns) : m_Data{1, QVector<double>{}}
28 {
29 QWriteLocker locker{&m_Lock};
30 m_Data[0].resize(nbColumns);
31 }
61 // ///// //
62 // Ctors //
63 // ///// //
32 64
33 65 /**
34 66 * Ctor for a unidimensional ArrayData
35 67 * @param data the data the ArrayData will hold
36 68 */
37 69 template <int D = Dim, typename = std::enable_if_t<D == 1> >
38 70 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
39 71 {
40 QWriteLocker locker{&m_Lock};
41 72 m_Data[0] = std::move(data);
42 73 }
43 74
44 /// Copy ctor
45 explicit ArrayData(const ArrayData &other)
46 {
47 QReadLocker otherLocker{&other.m_Lock};
48 QWriteLocker locker{&m_Lock};
49 m_Data = other.m_Data;
50 }
51
52 75 /**
53 * @return the data at a specified index
54 * @remarks index must be a valid position
55 * @remarks this method is only available for a unidimensional ArrayData
76 * Ctor for a two-dimensional ArrayData. The number of components (number of vectors) must be
77 * greater than 2 and each component must have the same number of values
78 * @param data the data the ArrayData will hold
79 * @throws std::invalid_argument if the number of components is less than 2
80 * @remarks if the number of values is not the same for each component, no value is set
56 81 */
57 template <int D = Dim, typename = std::enable_if_t<D == 1> >
58 double at(int index) const noexcept
82 template <int D = Dim, typename = std::enable_if_t<D == 2> >
83 explicit ArrayData(DataContainer data)
59 84 {
60 QReadLocker locker{&m_Lock};
61 return m_Data[0].at(index);
62 }
85 auto nbComponents = data.size();
86 if (nbComponents < 2) {
87 throw std::invalid_argument{
88 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
89 .arg(data.size())
90 .toStdString()};
91 }
63 92
64 /**
65 * Sets a data at a specified index. The index has to be valid to be effective
66 * @param index the index to which the data will be set
67 * @param data the data to set
68 * @remarks this method is only available for a unidimensional ArrayData
69 */
70 template <int D = Dim, typename = std::enable_if_t<D == 1> >
71 void setData(int index, double data) noexcept
72 {
73 QWriteLocker locker{&m_Lock};
74 if (index >= 0 && index < m_Data.at(0).size()) {
75 m_Data[0].replace(index, data);
93 auto nbValues = data.front().size();
94 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
95 return component.size() == nbValues;
96 })) {
97 m_Data = std::move(data);
98 }
99 else {
100 m_Data = DataContainer{nbComponents, QVector<double>{}};
76 101 }
77 102 }
78 103
79 /**
80 * @return the data as a vector
81 * @remarks this method is only available for a unidimensional ArrayData
82 */
83 template <int D = Dim, typename = std::enable_if_t<D == 1> >
84 QVector<double> data() const noexcept
104 /// Copy ctor
105 explicit ArrayData(const ArrayData &other)
85 106 {
86 QReadLocker locker{&m_Lock};
87 return m_Data[0];
107 QReadLocker otherLocker{&other.m_Lock};
108 m_Data = other.m_Data;
88 109 }
89 110
90 /**
91 * @return the data as a vector, as a const reference
92 * @remarks this method is only available for a unidimensional ArrayData
93 */
94 template <int D = Dim, typename = std::enable_if_t<D == 1> >
95 const QVector<double> &cdata() const noexcept
96 {
97 QReadLocker locker{&m_Lock};
98 return m_Data.at(0);
99 }
111 // /////////////// //
112 // General methods //
113 // /////////////// //
100 114
101 115 /**
102 * Merges into the array data an other array data
116 * Merges into the array data an other array data. The two array datas must have the same number
117 * of components so the merge can be done
103 118 * @param other the array data to merge with
104 119 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
105 120 * inserted at the end
106 * @remarks this method is only available for a unidimensional ArrayData
107 121 */
108 template <int D = Dim, typename = std::enable_if_t<D == 1> >
109 void add(const ArrayData<1> &other, bool prepend = false)
122 void add(const ArrayData<Dim> &other, bool prepend = false)
110 123 {
111 124 QWriteLocker locker{&m_Lock};
112 if (!m_Data.empty()) {
113 QReadLocker otherLocker{&other.m_Lock};
125 QReadLocker otherLocker{&other.m_Lock};
126
127 auto nbComponents = m_Data.size();
128 if (nbComponents != other.m_Data.size()) {
129 return;
130 }
114 131
132 for (auto componentIndex = 0; componentIndex < nbComponents; ++componentIndex) {
115 133 if (prepend) {
116 const auto &otherData = other.data();
134 const auto &otherData = other.data(componentIndex);
117 135 const auto otherDataSize = otherData.size();
118 136
119 auto &data = m_Data[0];
137 auto &data = m_Data[componentIndex];
120 138 data.insert(data.begin(), otherDataSize, 0.);
121 139
122 140 for (auto i = 0; i < otherDataSize; ++i) {
123 141 data.replace(i, otherData.at(i));
124 142 }
125 143 }
126 144 else {
127 m_Data[0] += other.data();
145 m_Data[componentIndex] += other.data(componentIndex);
128 146 }
129 147 }
130 148 }
131 149
132 template <int D = Dim, typename = std::enable_if_t<D == 1> >
150 void clear()
151 {
152 QWriteLocker locker{&m_Lock};
153
154 auto nbComponents = m_Data.size();
155 for (auto i = 0; i < nbComponents; ++i) {
156 m_Data[i].clear();
157 }
158 }
159
160 /**
161 * @return the data of a component
162 * @param componentIndex the index of the component to retrieve the data
163 * @return the component's data, empty vector if the index is invalid
164 */
165 QVector<double> data(int componentIndex) const noexcept
166 {
167 QReadLocker locker{&m_Lock};
168
169 return (componentIndex >= 0 && componentIndex < m_Data.size()) ? m_Data.at(componentIndex)
170 : QVector<double>{};
171 }
172
173 /// @return the size (i.e. number of values) of a single component
174 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
133 175 int size() const
134 176 {
135 177 QReadLocker locker{&m_Lock};
136 178 return m_Data[0].size();
137 179 }
138 180
139 template <int D = Dim, typename = std::enable_if_t<D == 1> >
140 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> sortPermutation)
181 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
141 182 {
142 183 QReadLocker locker{&m_Lock};
184 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
185 }
143 186
144 const auto &data = m_Data.at(0);
145
146 // Inits result
147 auto sortedData = QVector<double>{};
148 sortedData.resize(data.size());
149
150 std::transform(sortPermutation.cbegin(), sortPermutation.cend(), sortedData.begin(),
151 [&data](int i) { return data[i]; });
187 // ///////////// //
188 // 1-dim methods //
189 // ///////////// //
152 190
153 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
191 /**
192 * @return the data at a specified index
193 * @remarks index must be a valid position
194 * @remarks this method is only available for a unidimensional ArrayData
195 */
196 template <int D = Dim, typename = std::enable_if_t<D == 1> >
197 double at(int index) const noexcept
198 {
199 QReadLocker locker{&m_Lock};
200 return m_Data[0].at(index);
154 201 }
155 202
203 /**
204 * @return the data as a vector, as a const reference
205 * @remarks this method is only available for a unidimensional ArrayData
206 */
156 207 template <int D = Dim, typename = std::enable_if_t<D == 1> >
157 void clear()
208 const QVector<double> &cdata() const noexcept
158 209 {
159 QWriteLocker locker{&m_Lock};
160 m_Data[0].clear();
210 QReadLocker locker{&m_Lock};
211 return m_Data.at(0);
161 212 }
162 213
214 /**
215 * @return the data as a vector
216 * @remarks this method is only available for a unidimensional ArrayData
217 */
218 template <int D = Dim, typename = std::enable_if_t<D == 1> >
219 QVector<double> data() const noexcept
220 {
221 QReadLocker locker{&m_Lock};
222 return m_Data[0];
223 }
163 224
164 225 private:
165 QVector<QVector<double> > m_Data;
226 DataContainer m_Data;
166 227 mutable QReadWriteLock m_Lock;
167 228 };
168 229
169 230 #endif // SCIQLOP_ARRAYDATA_H
@@ -1,17 +1,18
1 1 # On ignore toutes les règles vera++ pour le fichier spimpl
2 2 Common/spimpl\.h:\d+:.*
3 3
4 4 # Ignore false positive relative to two class definitions in a same file
5 5 DataSourceItem\.h:\d+:.*IPSIS_S01.*
6 6
7 7 # Ignore false positive relative to a template class
8 8 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
9 ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail)
9 10 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
10 11 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
11 12 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
12 13
13 14 # Ignore false positive relative to an alias
14 15 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
15 16
16 17 # Ignore false positive relative to unnamed namespace
17 18 VariableController\.cpp:\d+:.*IPSIS_F13.*
General Comments 0
You need to be logged in to leave comments. Login now