TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Array_tools.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Array_tools.h>
17
18/*! @brief Sorts the array in ascending order and removes duplicates.
19 *
20 */
21template <typename _TYPE_, typename _SIZE_>
22void array_trier_retirer_doublons(TRUSTArray<_TYPE_,_SIZE_>& array)
23{
24 // IntVect is not handled correctly because we use resize_array() instead of resize().
25 assert(typeid(array) != typeid(TRUSTVect<_TYPE_, _SIZE_>));
26 const _SIZE_ size = array.size_array();
27 if (size == 0)
28 return;
29 // Sort in ascending order
30 array.ordonne_array();
31
32 // Remove duplicates
33 auto last = std::unique(array.addr(), array.addr()+size);
34 _SIZE_ new_size = static_cast<_SIZE_>(std::distance(array.addr(), last));
35 array.resize_array(new_size);
36}
37
38
39/*! @brief Computes the intersection of the two integer lists liste1 and liste2.
40 *
41 * The result is stored in liste1.
42 * Both lists must be sorted and without duplicates. liste1 is
43 * sorted on output.
44 *
45 */
46template <typename _TYPE_, typename _SIZE_>
47void array_calculer_intersection(TRUSTArray<_TYPE_,_SIZE_>& liste1, const TRUSTArray<_TYPE_,_SIZE_>& liste2)
48{
49 const _SIZE_ sz1 = liste1.size_array();
50 const _SIZE_ sz2 = liste2.size_array();
51 _SIZE_ j = 0; // Read pointer in liste2
52 _SIZE_ k = 0; // Write pointer
53 for (_SIZE_ i = 0; i < sz1; i++)
54 {
55 // Check that the lists are sorted in ascending order
56 assert((i >= sz1-1) || (liste1[i] < liste1[i+1]));
57 assert((j >= sz2-1) || (liste2[j] < liste2[j+1]));
58 const _TYPE_ valeur_i = liste1[i];
59 // Advance in liste2 until we find or exceed liste1[i]
60 while (j < sz2 && liste2[j] < valeur_i)
61 j++;
62 if (j == sz2)
63 break; // End of list, we are done
64 if (liste2[j] == valeur_i)
65 {
66 liste1[k] = valeur_i;
67 k++; // Keep this value
68 }
69 }
70 liste1.resize_array(k);
71}
72
73/*! @brief Removes from "sorted_array" the elements that appear in "sorted_elements".
74 *
75 * Both arrays must initially be sorted in ascending order.
76 * Example:
77 * Input: sorted_array=[1,4,9,10,12,18], sorted_elements=[3,5,9,10,18,25]
78 * Output: sorted_array=[1,4,12]
79 *
80 */
81void array_retirer_elements(ArrOfInt& sorted_array, const ArrOfInt& sorted_elements_list)
82{
83 int i_read; // Index in sorted_array (reading)
84 int i_write = 0; // Index in sorted_array (writing position)
85 int j = 0; // Index in sorted_elements
86 const int n = sorted_array.size_array();
87 const int m = sorted_elements_list.size_array();
88 if (m == 0)
89 return;
90
91 int j_value = sorted_elements_list[j];
92 for (i_read = 0; i_read < n; i_read++)
93 {
94 // Array sorted?
95 assert(i_read == 0 || sorted_array[i_read] > sorted_array[i_read-1]);
96 const int i_value = sorted_array[i_read];
97
98 // Advance in the sorted_elements list until we find or exceed
99 // element i_value
100 while ((j_value < i_value) && (j < m))
101 {
102 j++;
103 if (j == m)
104 break;
105 assert(sorted_elements_list[j] > j_value); // Array sorted?
106 j_value = sorted_elements_list[j];
107 }
108
109 if (j == m || j_value != i_value)
110 {
111 // i_value does not appear in the sorted_elements array, keep it
112 sorted_array[i_write] = i_value;
113 i_write++;
114 }
115 }
116 sorted_array.resize_array(i_write);
117}
118
119template <typename _SIZE_>
120static inline int same_line(const IntTab_T<_SIZE_>& v, _SIZE_ i, _SIZE_ j)
121{
122 const int ls = v.line_size();
123 for (int k = 0; k < ls; k++)
124 if (v(i,k) != v(j,k))
125 return 0;
126 return 1;
127}
128
129/*! @brief Lexicographic sort of the array tab (ascending order of the first column; if the first column is identical, ascending order
130 *
131 * of the second column, etc.).
132 * The array must not be a distributed array.
133 * Return value: number of columns of the array (product of tab.dimension(i) for i>0).
134 *
135 */
136template <typename _TYPE_, typename _SIZE_>
137int tri_lexicographique_tableau(TRUSTTab<_TYPE_,_SIZE_>& tab)
138{
139 // Check that the array is not a distributed array:
140 assert(!tab.get_md_vector());
141
142 const _SIZE_ nb_lignes = tab.dimension(0);
143 const int nb_colonnes = tab.line_size();
144 if (nb_lignes != 0)
145 {
146 tab.ensureDataOnHost();
147 if (nb_colonnes == 1)
148 tab.ordonne_array();
149 else if (nb_colonnes == 2)
150 {
151 using pairs = std::array<_TYPE_, 2>;
152 _TYPE_ *ptr = tab.addr();
153 pairs* tmp = reinterpret_cast<pairs*>(ptr);
154 std::sort(tmp, tmp+nb_lignes);
155 }
156 else if (nb_colonnes == 3)
157 {
158 using triplets = std::array<_TYPE_, 3>;
159 _TYPE_ *ptr = tab.addr();
160 triplets* tmp = reinterpret_cast<triplets*>(ptr);
161 std::sort(tmp, tmp+nb_lignes);
162 }
163 else if (nb_colonnes == 4)
164 {
165 using quadruplets = std::array<_TYPE_, 4>;
166 _TYPE_ *ptr = tab.addr();
167 quadruplets* tmp = reinterpret_cast<quadruplets*>(ptr);
168 std::sort(tmp, tmp+nb_lignes);
169 }
170 else
171 {
172 Cerr << "tri_lexicographique_tableau not supported for TRUST tabs with more than 4 columns" << finl;
174 }
175 }
176 return nb_colonnes;
177}
178
179/*! @brief Same as tri_lexicographique_tableau but sorts the index array which contains row indices of tab such that tab(index[i], *) is
180 *
181 * increasing as i increases. Sorts all indices in index...
182 * If the index array has zero size, one of size tab.dimension_tot(0) is created.
183 * Otherwise it is assumed to already contain row indices into tab.
184 * Return value: number of columns of the array (product of tab.dimension(i) for i>0).
185 *
186 */
187template <typename _TYPE_, typename _SIZE_>
188int tri_lexicographique_tableau_indirect(const TRUSTTab<_TYPE_,_SIZE_>& tab, ArrOfInt_T<_SIZE_>& index)
189{
190 using int_t = _SIZE_;
191 // Check that the array is not a distributed array:
192 assert(!tab.get_md_vector());
193
194 const int_t dimtab = tab.dimension_tot(0);
195 if (index.size_array() == 0 && dimtab > 0)
196 {
197 index.resize_array(dimtab, RESIZE_OPTIONS::NOCOPY_NOINIT);
198 for (int_t i = 0; i < dimtab; i++)
199 index[i] = i;
200 }
201
202 const int_t nb_lignes = index.size_array();
203 const int nb_colonnes = tab.line_size();
204 const int nb_dim = tab.nb_dim();
205 const double epsilon = Objet_U::precision_geom;
206
207 if (nb_lignes != 0)
208 {
209 std::sort(index.begin(), index.end(), [&](int_t a, int_t b)
210 {
211 if(nb_dim == 1)
212 return ( tab(a)<tab(b) );
213 for (int i = 0; i < nb_colonnes; i++)
214 {
215 if ( std::fabs(tab(a,i)-tab(b,i)) > epsilon )
216 return ( tab(a,i)<tab(b,i) );
217 }
218 return false;
219 });
220 }
221 return nb_colonnes;
222}
223
224/*! @brief Sorts the array tab in lexicographic order and removes duplicates (note: [1,2] is not equal to [2,1]).
225 *
226 */
227template <typename _SIZE_>
228void tableau_trier_retirer_doublons(IntTab_T<_SIZE_>& tab)
229{
230 const _SIZE_ nb_lignes = tab.dimension(0);
231 if (nb_lignes == 0) return;
232 int nb_colonnes = tab.line_size();
233
234 if (nb_colonnes == 1)
235 array_trier_retirer_doublons(tab);
236 else
237 {
238 nb_colonnes = tri_lexicographique_tableau(tab);
239 if (nb_colonnes == 2)
240 {
241 _SIZE_ j = 1; // Array size after removal
242 _SIZE_ last_x = tab(0, 0);
243 _SIZE_ last_y = tab(0, 1);
244 for (_SIZE_ i = 1; i < nb_lignes; i++)
245 {
246 const _SIZE_ x = tab(i, 0);
247 const _SIZE_ y = tab(i, 1);
248 if (x != last_x || y != last_y)
249 {
250 tab(j, 0) = last_x = x;
251 tab(j, 1) = last_y = y;
252 j++;
253 }
254 }
255 tab.resize_dim0(j);
256 }
257 else
258 {
259 _SIZE_ j = 0; // Last retained row
260 for (_SIZE_ i = 1; i < nb_lignes; i++)
261 {
262 // If row i differs from row j, keep it:
263 if (!same_line(tab, i, j))
264 {
265 j++;
266 for (int k = 0; k < nb_colonnes; k++)
267 tab(j, k) = tab(i, k);
268 }
269 }
270 tab.resize_dim0(j+1);
271 }
272 }
273}
274
275// Explicit instanciations
276//template const IntVect_T<int> *fct_qsort_tab_ptr<int>;
277template int tri_lexicographique_tableau_indirect(const TRUSTTab<int,int>& tab, ArrOfInt_T<int>& index);
278template int tri_lexicographique_tableau_indirect(const TRUSTTab<double,int>& tab, ArrOfInt_T<int>& index);
279template int tri_lexicographique_tableau(TRUSTTab<int,int>& tab);
280template int tri_lexicographique_tableau(TRUSTTab<double,int>& tab);
281template void tableau_trier_retirer_doublons(IntTab_T<int>& tab);
282template void array_calculer_intersection(TRUSTArray<int,int>& liste1, const TRUSTArray<int,int>& liste2);
283template void array_trier_retirer_doublons(TRUSTArray<int,int>& array);
284template void array_trier_retirer_doublons(TRUSTArray<double,int>& array);
285
286#if INT_is_64_ == 2
287//template const IntVect_T<trustIdType> *fct_qsort_tab_ptr<trustIdType>;
288template int tri_lexicographique_tableau_indirect(const TRUSTTab<int,trustIdType>& tab, ArrOfInt_T<trustIdType>& index);
289template int tri_lexicographique_tableau_indirect(const TRUSTTab<trustIdType,trustIdType>& tab, ArrOfInt_T<trustIdType>& index);
290template int tri_lexicographique_tableau_indirect(const TRUSTTab<double,trustIdType>& tab, ArrOfInt_T<trustIdType>& index);
291template int tri_lexicographique_tableau(TRUSTTab<int,trustIdType>& tab);
292template int tri_lexicographique_tableau(TRUSTTab<trustIdType,int>& tab);
293template int tri_lexicographique_tableau(TRUSTTab<trustIdType,trustIdType>& tab);
294template int tri_lexicographique_tableau(TRUSTTab<double,trustIdType>& tab);
295template void tableau_trier_retirer_doublons(IntTab_T<trustIdType>& tab);
296template void array_calculer_intersection(TRUSTArray<int,trustIdType>& liste1, const TRUSTArray<int,trustIdType>& liste2);
297template void array_trier_retirer_doublons(TRUSTArray<int,trustIdType>& array);
298template void array_trier_retirer_doublons(TRUSTArray<trustIdType,trustIdType>& array);
299template void array_trier_retirer_doublons(TRUSTArray<double,trustIdType>& array);
300
301// BigIntTab = TRUSTTab<int, trustIdType>: value type int, size type trustIdType - doesn't fit IntTab_T<_SIZE_>
302static inline int same_line_big(const BigIntTab& v, trustIdType i, trustIdType j)
303{
304 const int ls = v.line_size();
305 for (int k = 0; k < ls; k++)
306 if (v(i,k) != v(j,k))
307 return 0;
308 return 1;
309}
310
311void tableau_trier_retirer_doublons(BigIntTab& tab)
312{
313 const trustIdType nb_lignes = tab.dimension(0);
314 if (nb_lignes == 0) return;
315 int nb_colonnes = tab.line_size();
316
317 if (nb_colonnes == 1)
318 array_trier_retirer_doublons(tab);
319 else
320 {
321 nb_colonnes = tri_lexicographique_tableau(tab);
322 if (nb_colonnes == 2)
323 {
324 trustIdType j = 1;
325 int last_x = tab(0, 0);
326 int last_y = tab(0, 1);
327 for (trustIdType i = 1; i < nb_lignes; i++)
328 {
329 const int x = tab(i, 0);
330 const int y = tab(i, 1);
331 if (x != last_x || y != last_y)
332 {
333 tab(j, 0) = last_x = x;
334 tab(j, 1) = last_y = y;
335 j++;
336 }
337 }
338 tab.resize_dim0(j);
339 }
340 else
341 {
342 trustIdType j = 0;
343 for (trustIdType i = 1; i < nb_lignes; i++)
344 {
345 if (!same_line_big(tab, i, j))
346 {
347 j++;
348 for (int k = 0; k < nb_colonnes; k++)
349 tab(j, k) = tab(i, k);
350 }
351 }
352 tab.resize_dim0(j+1);
353 }
354 }
355}
356#endif
357
358
359/*! @brief Finds identical rows in "tab" by lexicographic sort and initializes the sizes and contents of renum and renum_inverse.
360 *
361 * renum has size tab.dimension_tot(0).
362 * renum[i] will contain the index of row i in the reduced sorted array (containing unique rows).
363 * renum_inverse contains, for each row of the reduced sorted array, the smallest index of the
364 * corresponding row in tab.
365 * The reduced sorted array can be constructed by extracting rows tab( renum_inverse[i], ...).
366 *
367 */
368void calculer_renum_sans_doublons(const IntTab& tab, ArrOfInt& renum, ArrOfInt& renum_inverse)
369{
370 // MODIF ELI LAUCOIN 31/01/2012:
371 // Completely rewriting this function
372
373 // index allows traversal of tab in order
374 ArrOfInt index;
375 tri_lexicographique_tableau_indirect(tab, index);
376 const int n = index.size_array();
377
378 // resize renum and renum_index
379 renum.resize_array(n, RESIZE_OPTIONS::NOCOPY_NOINIT);
380 renum_inverse.resize_array(n, RESIZE_OPTIONS::NOCOPY_NOINIT);
381
382 int count = -1; // row counter in the reduced array
383 int latest = -1; // index in the original array of the last row added to the reduced array
384
385 for (int i=0; i<n; ++i)
386 {
387 // traverse tab in ascending order given by index.
388 // if the current row differs from the last row added to the reduced array,
389 // increment count and update latest.
390 if ( ( latest < 0 ) || ( !(same_line(tab,index[i],index[latest]))) )
391 {
392 ++count;
393 latest=i;
394 }
395
396 // record in renum where the current row is in the reduced array
397 renum[index[i]] = count;
398
399 // add the last processed row to the reduced array
400 renum_inverse[count] = index[latest];
401 }
402
403 // resize renum_inverse to the size of the reduced array
404
405 renum_inverse.resize_array(count+1);
406 // END MODIF ELI LAUCOIN 31/01/2012
407}
408
409/*! @brief Searches for "valeur" in the array tab by binary search. The array tab must be sorted in ascending order.
410 *
411* If not found, returns -1 (including if tab is empty),
412 * otherwise returns an index i such that tab[i] == valeur
413 * (if the value appears multiple times in the array, the first occurrence
414 * is not necessarily returned).
415 *
416 * Used in Trio!
417 */
418int array_bsearch(const ArrOfInt& tab, int valeur)
419{
420 // attention: all details matter!
421 int i = 0;
422 int j = tab.size_array(); // j = end of array + 1 (important)
423 while (j > i)
424 {
425 // The array must be sorted
426 assert(j == tab.size_array() || tab[i] <= tab[j]);
427 const int milieu = (i + j) / 2;
428 const int val = tab[milieu];
429 if (val > valeur)
430 j = milieu; // take the middle value, not milieu - 1
431 else if (val < valeur)
432 i = milieu + 1; // take milieu + 1, not milieu
433 else
434 return milieu;
435 }
436 // If we reach here, i==j, so either:
437 // - j == end of array + 1 and the value was not found
438 // - tab[j] was tested and is not equal to valeur
439 // In both cases, valeur is not in the array
440 return -1;
441}
static double precision_geom
Definition Objet_U.h:81
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Represents a an array of int/int64/double/... values.
Definition TRUSTArray.h:81
Iterator_ end()
Definition TRUSTArray.h:112
_SIZE_ size_array() const
_TYPE_ * addr()
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void ordonne_array()
Iterator_ begin()
Definition TRUSTArray.h:111
N-dimensional array for N <= 4.
Definition TRUSTTab.h:31
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
void resize_dim0(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:459
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123