TrioCFD 1.9.8
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 Trie le tableau array dans l'ordre croissant et retire les doublons.
19 *
20 */
21template <typename _TYPE_, typename _SIZE_>
22void array_trier_retirer_doublons(TRUSTArray<_TYPE_,_SIZE_>& array)
23{
24 // IntVect n'est pas traite correctement car on ne fait pas un resize() mais un resize_array().
25 assert(typeid(array) != typeid(TRUSTVect<_TYPE_, _SIZE_>));
26 const _SIZE_ size = array.size_array();
27 if (size == 0)
28 return;
29 // Tri dans l'ordre croissant
30 array.ordonne_array();
31
32 // Retire les doublons
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 calcule l'intersection entre les deux listes d'entiers liste1 et liste2.
40 *
41 * Le resultat est mis dans liste1.
42 * Les deux listes doivent etre triees et sans doublons. liste1 est
43 * triee en sortie.
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; // Pointeur en lecture dans liste2
52 _SIZE_ k = 0; // Pointeur en ecriture
53 for (_SIZE_ i = 0; i < sz1; i++)
54 {
55 // On verifie que les listes sont triees dans l'ordre croissant
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 // Avancer dans liste2 jusqu'a trouver ou depasser liste1[i]
60 while (j < sz2 && liste2[j] < valeur_i)
61 j++;
62 if (j == sz2)
63 break; // Bout de liste, on a fini
64 if (liste2[j] == valeur_i)
65 {
66 liste1[k] = valeur_i;
67 k++; // On garde cette valeur
68 }
69 }
70 liste1.resize_array(k);
71}
72
73/*! @brief Retire de "sorted_array" les elements qui figurent dans "sorted_elements".
74 *
75 * Les deux tableaux doivent etre initialement ordonnes dans l'ordre croissant.
76 * Exemple:
77 * En entree sorted_array=[1,4,9,10,12,18], sorted_elements=[3,5,9,10,18,25]
78 * En sortie 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 dans sorted_array (en lecture)
84 int i_write = 0; // Index dans sorted_array (la ou on ecrit)
85 int j = 0; // Index dans 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 // Tableau trie ?
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 // On avance dans la liste sorted_elements jusqu'a trouver ou depasser
99 // l'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); // Tableau trie ?
106 j_value = sorted_elements_list[j];
107 }
108
109 if (j == m || j_value != i_value)
110 {
111 // i_value ne figure pas dans le tableau sorted_elements, on le garde
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 tri lexicographique du tableau tab (par ordre croissant de la premiere colonne, si premiere colonne identique, ordre croissant
130 *
131 * de la deuxieme, etc).
132 * Le tableau ne doit pas etre un tableau distribue.
133 * Valeur de retour: nombre de colonnes du tableau (produit des tab.dimension(i) pour i>0)
134 *
135 */
136template <typename _TYPE_, typename _SIZE_>
137int tri_lexicographique_tableau(TRUSTTab<_TYPE_,_SIZE_>& tab)
138{
139 // On verifie que le tableau n'est pas un tableau distribue:
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 Idem que tri_lexicographique_tableau mais on trie le tableau index qui contient les indices de lignes du tableau tab tel que tab(index[i], *) soit
180 *
181 * croissant quant i augmente. Tri de tous les indices de index...
182 * Si le tableau index est de taille nulle, on en cree un de taille tab.dimension_tot(0)
183 * Sinon on suppose qu'il contient deja des indices de lignes dans tab.
184 * Valeur de retour: nombre de colonnes du tableau (produit des tab.dimension(i) pour 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 // On verifie que le tableau n'est pas un tableau distribue:
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 Trie le tableau tab dans l'ordre lexicographique et retire les doublons (attention [1,2] n'est pas egal a [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; // Taille du tableau apres suppression
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; // Derniere ligne retenue
260 for (_SIZE_ i = 1; i < nb_lignes; i++)
261 {
262 // Si la ligne i est differente de la ligne j, on la conserve:
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 cherche par un tri lexicographique les lignes identiques de "tab" et initialise les tailles et contenus de renum et renum_inverse.
360 *
361 * renum est de taille tab.dimension_tot(0).
362 * renum[i] contiendra l'indice de la ligne i dans le tableau reduit trie (contenant les lignes uniques)
363 * renum_inverse contient, pour chaque ligne du tableau reduit trie, le plus petit indice de la ligne
364 * correspondante dans tab.
365 * on peut construire le tableau reduit trie en extayant les lignes 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 // Je re-ecris completement cette fonction
372
373 // index permet de parcourir le tableau tab dans l'ordre
374 ArrOfInt index;
375 tri_lexicographique_tableau_indirect(tab, index);
376 const int n = index.size_array();
377
378 // on redimensionne renum et 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; // compteur de lignes dans le tableau reduit
383 int latest = -1; // indice dans le tableau initial de la derniere ligne ajoutee dans le tableau reduit
384
385 for (int i=0; i<n; ++i)
386 {
387 // on parcourt tab dans l'ordre croissant donne par index.
388 // si la ligne courante est differente de la derniere ligne ajoutee dans le tableau reduit,
389 // on incremente count et on met a jour latest.
390 if ( ( latest < 0 ) || ( !(same_line(tab,index[i],index[latest]))) )
391 {
392 ++count;
393 latest=i;
394 }
395
396 // on indique dans renum ou se trouve la ligne courante dans le tableau reduit
397 renum[index[i]] = count;
398
399 // on ajoute la derniere ligne traitee au tableau reduit
400 renum_inverse[count] = index[latest];
401 }
402
403 // on redimensionne renum_inverse a la taille du tableau reduit
404
405 renum_inverse.resize_array(count+1);
406 // FIN MODIF ELI LAUCOIN 31/01/2012
407}
408
409/*! @brief cherche la "valeur" dans le tableau tab par recherche binaire Le tableau tab doit etre trie dans l'ordre croissant
410 *
411* Si elle n'est pas trouvee, renvoie -1 (y compris si tab est vide),
412 * sinon, renvoie un index i tel que tab[i] == valeur
413 * (si la valeur figure plusieurs fois dans le tableau, on ne renvoie
414 * pas forcement la premiere occurence).
415 *
416 * Utilise dans Trio !
417 */
418int array_bsearch(const ArrOfInt& tab, int valeur)
419{
420 // attention tout est important !
421 int i = 0;
422 int j = tab.size_array(); // j = fin de tableau + 1 (important)
423 while (j > i)
424 {
425 // Le tableau doit etre trie
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; // prendre la valeur milieu et pas milieu - 1
431 else if (val < valeur)
432 i = milieu + 1; // prendre la valeur milieu + 1 et pas milieu
433 else
434 return milieu;
435 }
436 // Si on arrive ici, c'est que i==j, donc
437 // - soit j == fin de tableau + 1 et on n'a pas trouve la valeur
438 // - soit tab[j] a ete teste et n'est pas egale a valeur
439 // Dans les deux cas, valeur n'est pas dans le tableau
440 return -1;
441}
static double precision_geom
Definition Objet_U.h:86
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
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
: Tableau a n entrees pour 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