source: soft/giet_vm/applications/rosenfeld/src-par/mca_rosenfeld.c @ 827

Last change on this file since 827 was 826, checked in by meunier, 7 years ago
  • Mise à jour NR2 et Rosenfeld
File size: 54.5 KB
Line 
1/* ----------------------- */
2/* --- mca_rosenfeld.c --- */
3/* ----------------------- */
4
5/*
6 * Copyright (c) 2016 Lionel Lacassagne, LIP6, UPMC, CNRS
7 * Init  : 2016/03/03
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <math.h>
14#if PARMERGE
15#include <pthread.h>
16#endif
17
18#include "nrc_os_config.h"
19#include "config.h"
20#include "nrc.h"
21
22#if TARGET_OS == GIETVM
23    #include <user_barrier.h>
24    #include <user_lock.h>
25    #include <giet_config.h>
26#else
27    #include <stdbool.h>
28    #include <assert.h>
29#endif
30
31
32#include "util.h"
33#include "ecc_common.h"
34#include "palette.h"
35#include "bmpNR.h"
36#include "clock.h"
37#include "str_ext.h"
38#include "ecc_features.h"
39
40// -----------
41// -- local --
42// -----------
43
44#include "mca.h"
45
46extern pthread_barrier_t main_barrier;
47extern int display_features;
48
49CLOCK_DEC;
50
51
52// -----------------------------------------
53static uint32 FindRoot(uint32 * T, uint32 e)
54// -----------------------------------------
55{
56    uint32 r;
57   
58    assert(e != 0);
59    r = e;
60    while (T[r] < r) {
61        r = T[r];
62    }
63
64    assert(r != 0);
65    return r;
66}
67
68
69// ----------------------------------------------------------
70static uint32 FindRoot_Dist(uint32 ** D, uint32 r, int shift)
71// ----------------------------------------------------------
72{
73    uint32 e;
74    uint32 e1;
75    uint32 e0;
76
77    assert(r != 0);
78   
79    int mask = (1 << shift) - 1;
80   
81    MCA_VERBOSE3(printf("%s(%d, %d) \n", __func__, r, shift));
82    do {
83        e  = r;
84        e1 = r >> shift;
85        e0 = r & mask;
86        r = D[e1][e0];
87        MCA_VERBOSE3(printf("%s: D(%d) = D[%d,%d] = %d (alpha = %d)\n", __func__, e, e1, e0, r, shift));
88    } while (r < e);
89    MCA_VERBOSE3(printf("%s = %d \n\n", __func__, r));
90    assert(r != 0);
91    return r;
92}
93
94
95#if !FEATURES
96// --------------------------------------------------------------------------------
97static void SetRoot_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift)
98// --------------------------------------------------------------------------------
99{
100    int mask = (1 << shift) - 1;
101    assert(root != 0 && eps != 0);
102   
103    uint32 r1 = root >> shift;
104    uint32 r0 = root & mask;
105   
106    D[r1][r0] = eps;
107}
108#endif // !FEATURES
109
110
111#if FEATURES && !PARMERGE
112// -----------------------------------------------------------------------------------------------------------
113static void SetRoot_Features_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift, RegionStats ** F)
114// -----------------------------------------------------------------------------------------------------------
115{
116    assert(root != 0 && eps != 0);
117
118    MCA_VERBOSE3(printf("F(%d) += F(%d)\n", eps, root));
119   
120    int mask = (1 << shift) - 1;
121
122    uint32 r1 = root >> shift;
123    uint32 r0 = root & mask;
124   
125    D[r1][r0] = eps;
126   
127    uint32 e1 = eps >> shift;
128    uint32 e0 = eps & mask;
129   
130    // version Dist de "RegionStats_Accumulate_Stats1_From_Index"
131   
132    // F(eps) = F(eps) U F(root)
133   
134    F[e1][e0].xmin = ui16min2(F[e1][e0].xmin, F[r1][r0].xmin);
135    F[e1][e0].xmax = ui16max2(F[e1][e0].xmax, F[r1][r0].xmax);
136    F[e1][e0].ymin = ui16min2(F[e1][e0].ymin, F[r1][r0].ymin);
137    F[e1][e0].ymax = ui16max2(F[e1][e0].ymax, F[r1][r0].ymax);
138   
139    F[e1][e0].+= F[r1][r0].S;
140    F[e1][e0].Sx += F[r1][r0].Sx;
141    F[e1][e0].Sy += F[r1][r0].Sy;
142}
143#endif // FEATURES && !PARMERGE
144
145
146#if !FEATURES && PARMERGE
147// -----------------------------------------------------------------------------------------------------------
148static bool SetRoot_Parallel_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift, RegionStats ** F)
149// -----------------------------------------------------------------------------------------------------------
150{
151    assert(root != 0 && eps != 0);
152
153    MCA_VERBOSE3(printf("F(%d) += F(%d)\n", eps, root));
154   
155    int mask = (1 << shift) - 1;
156
157    uint32 r1 = root >> shift;
158    uint32 r0 = root & mask;
159   
160    uint32 e1 = eps >> shift;
161    uint32 e0 = eps & mask;
162
163    // Locking towards the root (first root, then eps)
164    pthread_spin_lock(&F[r1][r0].lock);
165    pthread_spin_lock(&F[e1][e0].lock);
166    if (D[e1][e0] != eps || D[r1][r0] != root) {
167        // Someone changed the root of epsilon or "root", need to find the new root
168        pthread_spin_unlock(&F[e1][e0].lock);
169        pthread_spin_unlock(&F[r1][r0].lock);
170        return false;
171    }
172
173    D[r1][r0] = eps;
174   
175    pthread_spin_unlock(&F[e1][e0].lock);
176    pthread_spin_unlock(&F[r1][r0].lock);
177    return true;
178}
179#endif // !FEATURES && PARMERGE
180
181
182#if FEATURES && PARMERGE
183// --------------------------------------------------------------------------------------------------------------------
184static bool SetRoot_Parallel_Features_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift, RegionStats ** F)
185// --------------------------------------------------------------------------------------------------------------------
186{
187    assert(root != 0 && eps != 0);
188
189    MCA_VERBOSE3(printf("F(%d) += F(%d)\n", eps, root));
190   
191    int mask = (1 << shift) - 1;
192
193    uint32 r1 = root >> shift;
194    uint32 r0 = root & mask;
195   
196    uint32 e1 = eps >> shift;
197    uint32 e0 = eps & mask;
198
199    // Locking towards the root (first root, then eps)
200    pthread_spin_lock(&F[r1][r0].lock);
201    pthread_spin_lock(&F[e1][e0].lock);
202    // FIXME: merge these conditions later, when they both appear
203    if (D[e1][e0] != eps) {
204        // Someone change the root of epsilon, need to find the new root
205        //printf("race cond 1\n");
206        pthread_spin_unlock(&F[e1][e0].lock);
207        pthread_spin_unlock(&F[r1][r0].lock);
208        return false;
209    }
210    if (D[r1][r0] != root) {
211        // Someone change the root of "root", need to find the new root
212        //printf("race cond 2\n");
213        pthread_spin_unlock(&F[e1][e0].lock);
214        pthread_spin_unlock(&F[r1][r0].lock);
215        return false;
216    }
217
218    D[r1][r0] = eps;
219   
220    // F(eps) = F(eps) U F(root)
221    F[e1][e0].xmin = ui16min2(F[e1][e0].xmin, F[r1][r0].xmin);
222    F[e1][e0].xmax = ui16max2(F[e1][e0].xmax, F[r1][r0].xmax);
223    F[e1][e0].ymin = ui16min2(F[e1][e0].ymin, F[r1][r0].ymin);
224    F[e1][e0].ymax = ui16max2(F[e1][e0].ymax, F[r1][r0].ymax);
225   
226    F[e1][e0].+= F[r1][r0].S;
227    F[e1][e0].Sx += F[r1][r0].Sx;
228    F[e1][e0].Sy += F[r1][r0].Sy;
229
230    pthread_spin_unlock(&F[e1][e0].lock);
231    pthread_spin_unlock(&F[r1][r0].lock);
232    return true;
233}
234#endif // FEATURES && PARMERGE
235
236
237#if FEATURES && PARMERGE && ARSP
238// ------------------------------------------------------------------------------------------
239static void Propagate_Features(uint32 e0, uint32 e1, uint32 * T, RegionStats ** F, int shift)
240// ------------------------------------------------------------------------------------------
241{
242    uint32 i;
243    const int mask = (1 << shift) - 1;
244    for (i = e0; i <= e1; i++) {
245        uint32 root = T[i];
246        if (root != i) {
247            uint32 r1 = root >> shift;
248            uint32 r0 = root & mask;
249
250            uint32 l1 = i >> shift;
251            uint32 l0 = i & mask;
252            // We only lock the destination Features object
253            pthread_spin_lock(&F[r1][r0].lock);
254
255            // F(eps) = F(eps) U F(root)
256            F[r1][r0].xmin = ui16min2(F[l1][l0].xmin, F[r1][r0].xmin);
257            F[r1][r0].xmax = ui16max2(F[l1][l0].xmax, F[r1][r0].xmax);
258            F[r1][r0].ymin = ui16min2(F[l1][l0].ymin, F[r1][r0].ymin);
259            F[r1][r0].ymax = ui16max2(F[l1][l0].ymax, F[r1][r0].ymax);
260
261            F[r1][r0].+= F[l1][l0].S;
262            F[r1][r0].Sx += F[l1][l0].Sx;
263            F[r1][r0].Sy += F[l1][l0].Sy;
264
265            pthread_spin_unlock(&F[r1][r0].lock);
266        }
267    }
268}
269#endif // FEATURES && PARMERGE && ARSP
270
271
272#if FAST
273// --------------------------------------------------------
274static uint32 QuickUnion2(uint32 * T, uint32 e1, uint32 e2)
275// --------------------------------------------------------
276{
277    // version QU de Union2
278    uint32 r1 = FindRoot(T, e1);
279    uint32 r2 = FindRoot(T, e2);
280   
281    assert(e1 != 0 && e2 != 0 && r1 != 0 && r2 != 0);
282    uint32 eps = ui32Min2(r1, r2);
283
284    if (r1 > eps) {
285        T[r1] = eps; // SetRoot sans besoin de remonter
286    }
287    if (r2 > eps) {
288        T[r2] = eps; // SetRoot sans besoin de remonter
289    }
290    assert(e1 != 0 && e2 != 0 && r1 != 0 && r2 != 0);
291   
292    return eps;
293}
294#endif // FAST
295
296
297#if FAST
298// ---------------------------------------------------
299static uint32 use1_QU_Rosenfeld(uint32 e1, uint32 * T)
300// ---------------------------------------------------
301{
302    return FindRoot(T, e1);
303}
304#endif // FAST
305
306
307#if FAST
308// --------------------------------------------------------------
309static uint32 use2_QU_Rosenfeld(uint32 e1, uint32 e2, uint32 * T)
310// --------------------------------------------------------------
311{
312    return QuickUnion2(T, e1, e2);
313}
314#endif // FAST
315
316
317#if FAST && !FEATURES && !PARMERGE && !ARSP
318// ---------------------------------------------------------------------------------------
319static void vuse2_Rosenfeld_Dist(uint32 ed, uint32 el, uint32 * T, uint32 ** D, int alpha)
320// ---------------------------------------------------------------------------------------
321{
322    uint32 rd = FindRoot_Dist(D, ed, alpha);
323   
324    uint32 rl = T[el]; // car le premier acces est local
325    rl = FindRoot_Dist(D, rl, alpha);
326   
327    assert(ed != 0 && el != 0 && rd != 0 && rl != 0);
328    if (rd == rl) {
329        return; // evite la backdoor
330    }
331   
332    // forcement positifs car appel depuis optimizedBorder
333    // qui a fait un test
334    if (rd < rl) {
335        SetRoot_Rosenfeld_Dist(D, rl, rd, alpha);
336    }
337    else {
338        SetRoot_Rosenfeld_Dist(D, rd, rl, alpha);
339    }
340}
341
342// FAST && !FEATURES && !PARMERGE && !ARSP
343
344// -----------------------------------------------------------------------------------------------------
345static void vuse3_Rosenfeld_Dist(uint32 ed1, uint32 ed2, uint32 el3, uint32 * T, uint32 ** D, int alpha)
346// -----------------------------------------------------------------------------------------------------
347{
348    uint32 r1 = FindRoot_Dist(D, ed1, alpha);
349    uint32 r2 = FindRoot_Dist(D, ed2, alpha);
350   
351    uint32 r3 = T[el3]; // local - distant
352    r3 = FindRoot_Dist(D, r3, alpha);
353
354    assert(ed1 != 0 && ed2 != 0 && el3 != 0 && r1 != 0 && r2 != 0 && r3 != 0);
355   
356    if (r1 == r2 && r2 == r3) {
357        return;
358    }
359   
360    uint32 eps = ui32Min3(r1, r2, r3);  // forcement positifs car appel depuis optimizedBorder qui a fait un test
361   
362    // On ne fait pas le test car on peut faire le SetRoot plusieurs fois sur le même élément (on n'accumule pas de stats)
363    if (r1 > eps) {
364        SetRoot_Rosenfeld_Dist(D, r1, eps, alpha);
365    }
366    if (r2 > eps) {
367        SetRoot_Rosenfeld_Dist(D, r2, eps, alpha);
368    }
369    if (r3 > eps) {
370        SetRoot_Rosenfeld_Dist(D, r3, eps, alpha);
371    }
372}
373#endif // FAST && !FEATURES && !PARMERGE && !ARSP
374
375
376#if FAST && FEATURES && !PARMERGE && !ARSP
377// ------------------------------------------------------------------------------------------------------------------
378static void vuse2_Features_Rosenfeld_Dist(uint32 ed, uint32 el, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
379// ------------------------------------------------------------------------------------------------------------------
380{
381    assert(ed != 0 && el != 0);
382
383    uint32 rd = FindRoot_Dist(D, ed, alpha);
384   
385    uint32 rl = T[el]; // car le premier acces est local
386    assert(rl != 0);
387    rl = FindRoot_Dist(D, rl, alpha);
388   
389    assert(rd != 0 && rl != 0);
390
391    if (rd == rl) {
392        return; // evite la backdoor
393    }
394   
395    // forcement positifs car appel depuis optimizedBorder
396    // qui a fait un test
397    if (rd < rl) {
398        SetRoot_Features_Rosenfeld_Dist(D, rl, rd, alpha, F);
399    }
400    else {
401        SetRoot_Features_Rosenfeld_Dist(D, rd, rl, alpha, F);
402    }
403}
404
405// FAST && FEATURES && !PARMERGE && !ARSP
406
407// --------------------------------------------------------------------------------------------------------------------------------
408static void vuse3_Features_Rosenfeld_Dist(uint32 ed1, uint32 ed2, uint32 el3, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
409// --------------------------------------------------------------------------------------------------------------------------------
410{
411    assert(ed1 != 0 && ed2 != 0 && el3 != 0);
412
413    uint32 r1 = FindRoot_Dist(D, ed1, alpha);
414    uint32 r2 = FindRoot_Dist(D, ed2, alpha);
415   
416    uint32 r3 = T[el3]; // local - distant
417    assert(r3 != 0);
418    r3 = FindRoot_Dist(D, r3, alpha);
419   
420    assert(r1 != 0 && r2 != 0 && r3 != 0);
421
422    if (r1 == r2 && r2 == r3) {
423        return;
424    }
425   
426    uint32 eps = ui32Min3(r1, r2, r3);  // forcement positifs car appel depuis optimizedBorder qui a fait un test
427   
428    if (r1 > eps) {
429        SetRoot_Features_Rosenfeld_Dist(D, r1, eps, alpha, F);
430    }
431    if (r2 > eps && r2 != r1) {
432        SetRoot_Features_Rosenfeld_Dist(D, r2, eps, alpha, F);
433    }
434    if (r3 > eps && r3 != r2 && r3 != r1) {
435        SetRoot_Features_Rosenfeld_Dist(D, r3, eps, alpha, F);
436    }
437}
438#endif // FAST && FEATURES && !PARMERGE && !ARSP
439
440
441#if FAST && PARMERGE && ARSP
442// ----------------------------------------------------------------------------------------------------------------
443static bool SetRoot_Parallel_Arsp_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift, RegionStats ** F)
444// ----------------------------------------------------------------------------------------------------------------
445{
446    // QM : Pour la version avec features, on est obligé de faire l'accumulation à la fin une fois la fermeture
447    // transitive globale réalisée : sinon, on peut perdre des features quand on propage vers un epsilon qui
448    // n'est pas une racine.
449    assert(root != 0 && eps != 0);
450
451    uint32_t mask = (1 << shift) - 1;
452
453    uint32_t r1 = root >> shift;
454    uint32_t r0 = root & mask;
455   
456    // @QM
457    // A priori ici il n'y a pas besoin de prendre le lock sur eps
458    // car ce n'est pas une racine
459    pthread_spin_lock(&F[r1][r0].lock);
460    if (D[r1][r0] != root) {
461        pthread_spin_unlock(&F[r1][r0].lock);
462        return false;
463    }
464
465    D[r1][r0] = eps;
466   
467    pthread_spin_unlock(&F[r1][r0].lock);
468    return true;
469}
470#endif // FAST && PARMERGE && ARSP
471
472
473#if FAST && PARMERGE && ARSP
474// ------------------------------------------------------------------------------------------------------------------------------
475static inline bool FindSmallerAncestor_Link(uint32 ** D, uint32_t rl, uint32_t el, uint32_t rd, uint32_t shift, RegionStats ** F)
476// ------------------------------------------------------------------------------------------------------------------------------
477{
478    // Fait pointer rd (racine) vers rl (pas racine) a priori
479    // mais il faut que l'élément vers lequel rd pointe soit plus petit que rd
480    // On "remonte" donc vers la racine de rl jusqu'à atteindre un élément plus petit que rd
481    // Si on atteint la racine de rl et que cette derniÚre est toujours plus grande que rd,
482    // on fait alors pointer rl vers rd
483    bool ok;
484    uint32_t el1, el0;
485    uint32_t mask = (1 << shift) - 1;
486    while (rl < el && rl > rd) {
487        el = rl;
488        el1 = rl >> shift;
489        el0 = rl & mask;
490        rl = D[el1][el0];
491    }
492    if (rd != rl) {
493        if (rl == el && rl > rd) {
494            // L'ordre s'est inversé : on fait pointer rl vers rd
495            ok = SetRoot_Parallel_Arsp_Rosenfeld_Dist(D, rl, rd, shift, F);
496        }
497        else {
498            // On fait pointer rd vers rl
499            ok = SetRoot_Parallel_Arsp_Rosenfeld_Dist(D, rd, rl, shift, F);
500        }
501    }
502    else {
503        ok = true;
504    }
505    return ok;
506}
507
508// FAST && PARMERGE && ARSP
509
510// -----------------------------------------------------------------------------------------------------------------------
511static void vuse2_Parallel_Arsp_Rosenfeld_Dist(uint32 ed, uint32 el, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
512// -----------------------------------------------------------------------------------------------------------------------
513{
514    assert(ed != 0 && el != 0);
515 
516    uint32_t shift = alpha;
517    uint32_t mask = (1 << shift) - 1;
518   
519    uint32_t rd = ed;
520    uint32_t rl = el;
521
522    uint32_t ed1;
523    uint32_t el1;
524    uint32_t ed0;
525    uint32_t el0;
526
527    bool ok;
528
529    // Fusion ed - el
530    do {
531        do {
532            ed = rd;
533            el = rl;
534            ed1 = rd >> shift;
535            el1 = rl >> shift;
536            ed0 = rd & mask;
537            el0 = rl & mask;
538            rd = D[ed1][ed0];
539            rl = D[el1][el0];
540        } while (rl < el && rd < ed);
541
542        assert(rl != 0 && rd != 0);
543
544        if (rd != rl) {
545            if (rd == ed) {
546                ok = FindSmallerAncestor_Link(D, rl, el, rd, shift, F);
547            }
548            else {
549                assert(rl == el);
550                ok = FindSmallerAncestor_Link(D, rd, ed, rl, shift, F);
551            }
552        }
553        else {
554            ok = true;
555        }
556    } while (!ok);
557}
558
559// FAST && PARMERGE && ARSP
560
561// -------------------------------------------------------------------------------------------------------------------------------------
562static void vuse3_Parallel_Arsp_Rosenfeld_Dist(uint32 ed1, uint32 ed2, uint32 el3, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
563// -------------------------------------------------------------------------------------------------------------------------------------
564{
565    assert(ed1 != 0 && ed2 != 0 && el3 != 0);
566 
567    uint32_t shift = alpha;
568    uint32_t mask = (1 << shift) - 1;
569   
570    uint32_t r1 = ed1;
571    uint32_t r2 = ed2;
572    uint32_t r3 = el3;
573
574    uint32_t e11;
575    uint32_t e21;
576    uint32_t e31;
577    uint32_t e10;
578    uint32_t e20;
579    uint32_t e30;
580
581    uint32_t r0;
582    uint32_t ed0;
583    uint32_t e00;
584    uint32_t e01;
585
586    // Pas d'init pour que valgrind détecte une erreur si bool est lu sans être affecté
587    bool ok;
588
589    // Fusion ed1 - ed2
590    do {
591        do {
592            ed1 = r1;
593            ed2 = r2;
594            e11 = r1 >> shift;
595            e21 = r2 >> shift;
596            e10 = r1 & mask;
597            e20 = r2 & mask;
598            r1 = D[e11][e10];
599            r2 = D[e21][e20];
600        } while (r1 < ed1 && r2 < ed2);
601
602        assert(r1 != 0 && r2 != 0);
603
604        if (r1 != r2) {
605            if (r1 == ed1) {
606                ok = FindSmallerAncestor_Link(D, r2, ed2, r1, shift, F);
607            }
608            else {
609                assert(r2 == ed2);
610                ok = FindSmallerAncestor_Link(D, r1, ed1, r2, shift, F);
611            }
612        }
613        else {
614            ok = true;
615        }
616    } while (!ok);
617
618    // Fusion r0 = min(r1, r2) avec r3
619    if (r1 < r2) {
620        r0 = r1;
621        ed0 = r1;
622        e00 = e10;
623        e01 = e11;
624    }
625    else {
626        r0 = r2;
627        ed0 = r2;
628        e00 = e20;
629        e01 = e21;
630    }
631
632    // r0 est déjà une racine
633    goto r0_is_root;
634    do {
635        do {
636            ed0 = r0;
637            el3 = r3;
638            e01 = r0 >> shift;
639            e31 = r3 >> shift;
640            e00 = r0 & mask;
641            e30 = r3 & mask;
642            r0 = D[e01][e00];
643            r3 = D[e31][e30];
644        } while (r0 < ed0 && r3 < el3);
645
646        assert(r0 != 0 && r3 != 0);
647
648        if (r0 != r3) {
649            if (r0 == ed0) {
650r0_is_root:
651                ok = FindSmallerAncestor_Link(D, r3, el3, r0, shift, F);
652            }
653            else {
654                assert(r3 == el3);
655                ok = FindSmallerAncestor_Link(D, r0, ed0, r3, shift, F);
656            }
657        }
658        else {
659            ok = true;
660        }
661    } while (!ok);
662}
663#endif // FAST && PARMERGE && ARSP
664
665
666
667#if FAST && PARMERGE && !ARSP // Valid for FEATURES and !FEATURES
668// ---------------------------------------------------------------------------------------------------------------------------
669static void vuse2_Parallel_Rosenfeld_Dist(uint32 ed, uint32 el, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
670// ---------------------------------------------------------------------------------------------------------------------------
671{
672    bool ok;
673    assert(ed != 0 && el != 0);
674    uint32 rl = T[el]; // car le premier acces est local
675    assert(rl != 0);
676
677    uint32 rd;
678   
679    do {
680        rd = FindRoot_Dist(D, ed, alpha); // no lock
681        rl = FindRoot_Dist(D, rl, alpha);
682
683        assert(rd != 0 && rl != 0);
684
685        if (rd == rl) {
686            return; // evite la backdoor
687        }
688
689        // forcement positifs car appel depuis optimizedBorder
690        // qui a fait un test
691        if (rd < rl) {
692            // Features or No Features depending on config
693            ok = SetRoot_Parallel_FNF(D, rl, rd, alpha, F);
694        }
695        else {
696            ok = SetRoot_Parallel_FNF(D, rd, rl, alpha, F);
697        }
698    } while (!ok);
699}
700
701// FAST && PARMERGE && !ARSP
702
703// -----------------------------------------------------------------------------------------------------------------------------------------
704static void vuse3_Parallel_Rosenfeld_Dist(uint32 ed1, uint32 ed2, uint32 el3, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
705// -----------------------------------------------------------------------------------------------------------------------------------------
706{
707    bool ok1, ok2, ok3;
708    assert(ed1 != 0 && ed2 != 0 && el3 != 0);
709
710    uint32 r1;
711    uint32 r2;
712    uint32 r3 = T[el3]; // local - distant
713    assert(r3 != 0);
714
715    do {
716        r1 = FindRoot_Dist(D, ed1, alpha);
717        r2 = FindRoot_Dist(D, ed2, alpha);
718        r3 = FindRoot_Dist(D, r3, alpha);
719   
720        assert(r1 != 0 && r2 != 0 && r3 != 0);
721
722        if (r1 == r2 && r2 == r3) {
723            return;
724        }
725   
726        uint32 eps = ui32Min3(r1, r2, r3);  // forcement positifs car appel depuis optimizedBorder qui a fait un test
727   
728        ok1 = true;
729        ok2 = true;
730        ok3 = true;
731        if (r1 > eps) {
732            ok1 = SetRoot_Parallel_FNF(D, r1, eps, alpha, F);
733        }
734        if (r2 > eps && r2 != r1) {
735            ok2 = SetRoot_Parallel_FNF(D, r2, eps, alpha, F);
736        }
737        if (r3 > eps && r3 != r2 && r3 != r1) {
738            ok3 = SetRoot_Parallel_FNF(D, r3, eps, alpha, F);
739        }
740    } while (!(ok1 && ok2 && ok3));
741}
742#endif // FAST && PARMERGE && !ARSP
743
744
745
746#if FAST
747// ------------------------------------------------------------------------------------------------------------------------
748static void optimizedBorder_Rosenfeld_Dist(uint32 ** E, int i, int j, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
749// ------------------------------------------------------------------------------------------------------------------------
750{
751    uint32 a, b, c, x;
752   
753    x = E[i][j];
754    if (x) {
755        b = E[i - 1][j];
756        if (b) {
757            vuse2_Rosenfeld(b, x, T, D, alpha, F); // dist, local
758        }
759        else {
760            c = E[i - 1][j + 1];
761            if (c) {
762                a = E[i - 1][j - 1];
763                if (a) {
764                    vuse3_Rosenfeld(a, c, x, T, D, alpha, F); // dist, local
765                }
766                else {
767                    vuse2_Rosenfeld(c, x, T, D, alpha, F); // dist, local
768                }
769            }
770            else {
771                a = E[i - 1][j - 1];
772                if (a) {
773                    vuse2_Rosenfeld(a, x, T, D, alpha, F); // dist, local
774                }
775            }
776        }
777    }
778}
779
780// FAST
781
782// ----------------------------------------------------------------------------------------------------------------------------
783static void optimizedBorderLeft_Rosenfeld_Dist(uint32 ** E, int i, int j, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
784// ----------------------------------------------------------------------------------------------------------------------------
785{
786    uint32 x = E[i][j];
787    if (x) {
788        uint32 b = E[i - 1][j];
789        if (b) {
790            vuse2_Rosenfeld(b, x, T, D, alpha, F); // dist, local
791        }
792        else {
793            uint32 c = E[i - 1][j + 1];
794            if (c) {
795                vuse2_Rosenfeld(c, x, T, D, alpha, F); // dist, local
796            }
797        }
798    }
799}
800
801// FAST
802
803// -----------------------------------------------------------------------------------------------------------------------------
804static void optimizedBorderRight_Rosenfeld_Dist(uint32 ** E, int i, int j, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
805// -----------------------------------------------------------------------------------------------------------------------------
806{
807    // copie de optimizedBorder_Rosenfeld
808    // test d'existance de ex en local local
809
810    uint32 b = E[i - 1][j];
811    uint32 x = E[i][j];
812   
813    if (x) {
814        if (b) {
815            vuse2_Rosenfeld(b, x, T, D, alpha, F); // dist, local
816        }
817        else {
818            uint32 a = E[i - 1][j - 1];
819            if (a) {
820                vuse2_Rosenfeld(a, x, T, D, alpha, F); // dist, local
821            }
822        }
823    }
824}
825
826// FAST
827
828// -------------------------------------------------------------------------------------------------------------------------------------------
829static void borderMerging_Fast_Rosenfeld_Dist(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
830// -------------------------------------------------------------------------------------------------------------------------------------------
831{
832    // Prologue
833    optimizedBorderLeft_Rosenfeld_Dist(E, i, 0, T, D, alpha, F);
834    // Boucle principale
835    for (int j = 1; j < width - 1; j++) {
836        optimizedBorder_Rosenfeld_Dist(E, i, j, T, D, alpha, F);
837    }
838    // Epilogue
839    optimizedBorderRight_Rosenfeld_Dist(E, i, width - 1, T, D, alpha, F);
840}
841#endif // FAST
842
843
844
845#if SLOW
846// -------------------------------------------------------------------------------------------------------------------------------------------
847static void borderMerging_Slow_Rosenfeld_Dist(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
848// -------------------------------------------------------------------------------------------------------------------------------------------
849{
850    int j = 0;
851   
852    uint32 eps;
853    uint32 e1, e2, e3, ex;
854    uint32 r1, r2, r3, rx;
855   
856    // --------------
857    // -- prologue --
858    // --------------
859    MCA_VERBOSE3(printf("[%s] i = %d\n", __func__, i));
860   
861    ex = E[i][j];
862   
863    if (ex) {
864       
865        MCA_VERBOSE3(printf("[%s] j = %d\n", __func__, j));
866       
867        e2 = E[i - 1][j];
868        e3 = E[i - 1][j + 1];
869       
870        if (e2 || e3) {
871       
872            // test pour eviter acces distant
873            r2 = e2 ? FindRoot_Dist(D, e2, alpha) : 0;
874            r3 = e3 ? FindRoot_Dist(D, e3, alpha) : 0;
875
876            rx = T[ex];
877            rx = FindRoot_Dist(D, rx, alpha);
878           
879            eps = ui32MinNonNul3(r2, r3, rx);
880           
881            MCA_VERBOSE3(printf("\n"));
882            MCA_VERBOSE3(printf("e2  = %5d -> r2 = %5d\n", e2, r2));
883            MCA_VERBOSE3(printf("e3  = %5d -> r3 = %5d\n", e3, r3));
884            MCA_VERBOSE3(printf("ex  = %5d -> rx = %5d\n", ex, rx));
885            MCA_VERBOSE3(printf("eps = %5d\n", eps));
886           
887            // Quick-Union
888            if (r2 > eps) {
889                SetRoot_Rosenfeld(D, r2, eps, alpha, F);
890                MCA_VERBOSE3(printf("D[%5d] <- %d\n", r2, eps));
891            }
892            // Pour le cas où r2 == r3, il ne faut pas ajouter deux fois les features
893            //if (r3 > 0) {
894            //    r3 = FindRoot_Dist(D, r3, alpha);
895            //}
896            //if (r3 > eps) {
897            if (r3 > eps && r3 != r2) {
898                SetRoot_Rosenfeld(D, r3, eps, alpha, F);
899                MCA_VERBOSE3(printf("D[%5d] <- %d\n", r3, eps));
900            }
901            //rx = FindRoot_Dist(D, rx, alpha);
902            //if (rx > eps) {
903            if (rx > eps && rx != r3 && rx != r2) {
904                SetRoot_Rosenfeld(D, rx, eps, alpha, F);
905                MCA_VERBOSE3(printf("D[%5d] <- %d\n", rx, eps));
906            }
907            MCA_VERBOSE3(printf("---------------------------\n"));
908        }
909    }
910   
911    // -----------------------
912    // -- boucle principale --
913    // -----------------------
914   
915    for (j = 0 + 1; j < width - 1; j++) {
916       
917        ex = E[i][j];
918       
919        if (ex) {
920           
921            MCA_VERBOSE3(printf("[%s] j = %d\n", __func__, j));
922           
923            e1 = E[i - 1][j - 1];
924            e2 = E[i - 1][j];
925            e3 = E[i - 1][j + 1];
926           
927            if (e1 || e2 || e3) {
928                // test pour eviter un acces distant
929                r1 = e1 ? FindRoot_Dist(D, e1, alpha) : 0;
930                r2 = e2 ? FindRoot_Dist(D, e2, alpha) : 0;
931                r3 = e3 ? FindRoot_Dist(D, e3, alpha) : 0;
932
933                rx = T[ex];
934                rx = FindRoot_Dist(D, rx, alpha);
935               
936                eps = ui32MinNonNul4(r1, r2, r3, rx);
937
938                MCA_VERBOSE3(printf("\n"));
939                MCA_VERBOSE3(printf("e1  = %5d -> r1 = %5d\n", e1, r1));
940                MCA_VERBOSE3(printf("e2  = %5d -> r2 = %5d\n", e2, r2));
941                MCA_VERBOSE3(printf("e3  = %5d -> r3 = %5d\n", e3, r3));
942                MCA_VERBOSE3(printf("ex  = %5d -> rx = %5d\n", ex, rx));
943                MCA_VERBOSE3(printf("eps = %5d\n", eps));
944               
945               
946                // Quick-Union
947                if (r1 > eps) {
948                    SetRoot_Rosenfeld(D, r1, eps, alpha, F);
949                    MCA_VERBOSE3(printf("D[%5d] <- %d\n", r1, eps));
950                }
951                //if (r2 > 0) {
952                //    r2 = FindRoot_Dist(D, r2, alpha);
953                //}
954                if (r2 > eps && r2 != r1) {
955                //if (r2 > eps) {
956                    SetRoot_Rosenfeld(D, r2, eps, alpha, F);
957                    MCA_VERBOSE3(printf("D[%5d] <- %d\n", r2, eps));
958                }
959                //if (r3 > 0) {
960                //    r3 = FindRoot_Dist(D, r3, alpha);
961                //}
962                if (r3 > eps && r3 != r2 && r3 != r1) {
963                //if (r3 > eps) {
964                    SetRoot_Rosenfeld(D, r3, eps, alpha, F);
965                    MCA_VERBOSE3(printf("D[%5d] <- %d\n", r3, eps));
966                }
967                //rx = FindRoot_Dist(D, rx, alpha);
968                if (rx > eps && rx != r3 && rx != r2 && rx != r1) {
969                //if (rx > eps) {
970                    SetRoot_Rosenfeld(D, rx, eps, alpha, F);
971                    MCA_VERBOSE3(printf("D[%5d] <- %d\n", rx, eps));
972                }
973                MCA_VERBOSE3(puts("---------------------------\n"));
974            }
975        }
976    }
977   
978    // --------------
979    // -- epilogue --
980    // --------------
981   
982    j = width - 1;
983    ex = E[i][j];
984   
985    if (ex) {
986       
987        MCA_VERBOSE3(printf("[%s] j = %d\n", __func__, j));
988       
989        e1 = E[i - 1][j - 1];
990        e2 = E[i - 1][j];
991       
992        if (e1 || e2) {
993       
994            // test pour eviter acces distant
995            r1 = e1 ? FindRoot_Dist(D, e1, alpha) : 0;
996            r2 = e2 ? FindRoot_Dist(D, e2, alpha) : 0;
997
998            rx = T[ex];
999            rx = FindRoot_Dist(D, rx, alpha);
1000           
1001            eps = ui32MinNonNul3(r1, r2, rx);
1002           
1003            MCA_VERBOSE3(printf("\n"));
1004            MCA_VERBOSE3(printf("e1  = %5d -> r1 = %5d\n", e1, r1));
1005            MCA_VERBOSE3(printf("e2  = %5d -> r2 = %5d\n", e2, r2));
1006            MCA_VERBOSE3(printf("ex  = %5d -> rx = %5d\n", ex, rx));
1007            MCA_VERBOSE3(printf("eps = %5d\n", eps));
1008           
1009            // Quick-Union
1010            if (r1 > eps) {
1011                SetRoot_Rosenfeld(D, r1, eps, alpha, F);
1012                MCA_VERBOSE3(printf("D[%5d] <- %d\n", r1, eps));
1013            }
1014            //if (r2 > 0) {
1015            //    r2 = FindRoot_Dist(D, r2, alpha);
1016            //}
1017            if (r2 > eps && r2 != r1) {
1018            //if (r2 > eps) {
1019                SetRoot_Rosenfeld(D, r2, eps, alpha, F);
1020                MCA_VERBOSE3(printf("D[%5d] <- %d\n", r2, eps));
1021            }
1022            //rx = FindRoot_Dist(D, rx, alpha);
1023            if (rx > eps && rx != r2 && rx != r1) {
1024            //if (rx > eps) {
1025                SetRoot_Rosenfeld(D, rx, eps, alpha, F);
1026                MCA_VERBOSE3(printf("D[%5d] <- %d\n", rx, eps));
1027            }
1028            MCA_VERBOSE3(printf("---------------------------\n"));
1029        }
1030    }
1031}
1032#endif // SLOW
1033
1034
1035
1036// --------------------------------------------------------------------------------------------------------------------------------------
1037static void borderMerging_Rosenfeld_Dist(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
1038// --------------------------------------------------------------------------------------------------------------------------------------
1039{
1040#if FAST
1041    borderMerging_Fast_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);
1042#endif // FAST
1043#if SLOW
1044    borderMerging_Slow_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);
1045#endif // SLOW
1046}
1047
1048
1049// ----------------------------------------------------------------------------------------------------
1050static uint32 line0Labeling_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1051// ----------------------------------------------------------------------------------------------------
1052{
1053    int j;
1054    uint8 x;
1055    uint32 e4;
1056    uint32 r4;
1057   
1058    // prologue : j = 0
1059    x = X[i][0];
1060    if (x) {
1061        E[i][0] = ++ne;
1062    }
1063    else {
1064        E[i][0] = 0;
1065    }
1066   
1067    // boucle et epilogue j = [1..width-1]
1068    for (j = 1; j <= width - 1; j++) {
1069        x = X[i][j];
1070        if (x)  {
1071            e4 = E[i][j - 1];
1072           
1073            if (e4 == 0) {
1074                E[i][j] = ++ne;
1075            }
1076            else {
1077                E[i][j] = e4;
1078            }
1079        }
1080        else {
1081            E[i][j] = 0;
1082        }
1083    }
1084    return ne;
1085}
1086
1087
1088#if SLOW
1089// --------------------------------------------------------------------------------------------------------
1090static uint32 lineLabeling_Slow_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1091// --------------------------------------------------------------------------------------------------------
1092{
1093    // version lineLabeling_Rosenfeld_UF_QU_8C avec Quick-Union
1094   
1095    int j;
1096   
1097    uint8 x;
1098    uint32 e;
1099    uint32 e1, e2, e3, e4;
1100    uint32 r1, r2, r3, r4;
1101   
1102    // --------------
1103    // -- prologue --
1104    // --------------
1105   
1106    j = 0;
1107    x = X[i][j];
1108   
1109    if (x) {
1110       
1111        e2 = E[i - 1][j];
1112        e3 = E[i - 1][j + 1];
1113       
1114        // nouvel element
1115        if (e2 == 0 && e3 == 0) {
1116            e = ++ne;
1117            E[i][j] = e;
1118        }
1119        else {
1120            // etiquettes identiques
1121            if (e2 == e3) {
1122                e = e2;
1123                E[i][j] = e; 
1124            }
1125            else {   
1126                // cas general
1127                r2 = (e2 == 0) ? 0 : FindRoot(T, e2);
1128                r3 = (e3 == 0) ? 0 : FindRoot(T, e3);
1129               
1130                e = ui32MinNonNul2(r2, r3);
1131               
1132                // Quick-Union
1133                if (r2 > e) {
1134                    T[r2] = e;
1135                }
1136                if (r3 > e) {
1137                    T[r3] = e;
1138                }
1139                E[i][j] = e;
1140            }
1141        }
1142    }
1143    else {
1144        E[i][j] = 0;
1145    } // x
1146   
1147    // -----------------------
1148    // -- boucle principale --
1149    // -----------------------
1150   
1151    for (j = 0 + 1; j < width - 1; j++) {
1152       
1153        x = X[i][j];
1154       
1155        if (x)  {
1156            e1 = E[i - 1][j - 1];
1157            e2 = E[i - 1][j];
1158            e3 = E[i - 1][j + 1];
1159            e4 = E[i][j - 1];
1160           
1161            // nouvel element
1162            if (e1 == 0 && e2 == 0 && e3 == 0 && e4 == 0) {
1163                e = ++ne;
1164                E[i][j] = e;
1165            }
1166            else {
1167                // etiquettes identiques
1168                if (e1 == e2 && e1 == e3 && e1 == e4) {
1169                    e = e1;
1170                    E[i][j] = e;
1171                }
1172                else {
1173                    // cas general
1174                    r1 = (e1 == 0) ? 0 : FindRoot(T, e1);
1175                    r2 = (e2 == 0) ? 0 : FindRoot(T, e2);
1176                    r3 = (e3 == 0) ? 0 : FindRoot(T, e3);
1177                    r4 = (e4 == 0) ? 0 : FindRoot(T, e4);
1178                   
1179                    e = ui32MinNonNul4(r1, r2, r3, r4);
1180                   
1181                    // Quick-Union
1182                    if (r1 > e) {
1183                        T[r1] = e;
1184                    }
1185                    if (r2 > e) {
1186                        T[r2] = e;
1187                    }
1188                    if (r3 > e) {
1189                        T[r3] = e;
1190                    }
1191                    if (r4 > e) {
1192                        T[r4] = e;
1193                    }
1194                    E[i][j] = e;
1195                }
1196            }
1197        }
1198        else {
1199            E[i][j] = 0;
1200        } // x
1201    } // j
1202   
1203    // --------------
1204    // -- epilogue --
1205    // --------------
1206    j = width - 1;
1207    x = X[i][j];
1208   
1209    if (x) {
1210        e1 = E[i - 1][j - 1];
1211        e2 = E[i - 1][j];
1212        e4 = E[i][j - 1];
1213       
1214        // nouvel element
1215        if (e1 == 0 && e2 == 0 && e4 == 0) {
1216            e = ++ne;
1217            E[i][j] = e;
1218        }
1219        else {
1220            // etiquettes identiques
1221            if (e1 == e2 && e1 == e4) {
1222                e = e1;
1223                E[i][j] = e;
1224            }
1225            else {
1226                // cas general
1227                r1 = (e1 == 0) ? 0 : FindRoot(T, e1);
1228                r2 = (e2 == 0) ? 0 : FindRoot(T, e2);
1229                r4 = (e4 == 0) ? 0 : FindRoot(T, e4);
1230               
1231                e = ui32MinNonNul3(r1, r2, r4);
1232               
1233                // Quick-Union
1234                if (r1 > e) {
1235                    T[r1] = e;
1236                }
1237                if (r2 > e) {
1238                    T[r2] = e;
1239                }
1240                if (r4 > e) {
1241                    T[r4] = e;
1242                }
1243                E[i][j] = e;
1244            }
1245        }
1246    }
1247    else {
1248        E[i][j] = 0;
1249    } // x
1250   
1251    return ne;
1252}
1253#endif // SLOW
1254
1255
1256#if FAST
1257// ---------------------------------------------------------------------------------------------
1258static uint32 optimizedAccessLeft_DT_Rosenfeld(uint32 ** E, int i, int j, uint32 * T, uint32 ne)
1259// ---------------------------------------------------------------------------------------------
1260{
1261    // Decision Tree 8-connexe avec Quick-Union
1262    uint32 b, c, e;
1263   
1264    b = E[i - 1][j];
1265    if (b) {
1266        e = use1_QU_Rosenfeld(b, T);
1267    }
1268    else {
1269        c = E[i - 1][j + 1];
1270        if (c) {
1271            e = use1_QU_Rosenfeld(c, T);
1272        }
1273        else {
1274            e = ++ne;
1275        }
1276    }
1277    E[i][j] = e;
1278    return ne;
1279}
1280
1281// FAST
1282
1283// ----------------------------------------------------------------------------------------------
1284static uint32 optimizedAccessRight_DT_Rosenfeld(uint32 ** E, int i, int j, uint32 * T, uint32 ne)
1285// ----------------------------------------------------------------------------------------------
1286{
1287    // Decision Tree 8-connexe avec Quick-Union
1288    uint32 a, b, d, e;
1289   
1290    b = E[i - 1][j];
1291    if (b) {
1292        e = use1_QU_Rosenfeld(b, T);
1293    }
1294    else {
1295        a = E[i - 1][j - 1];
1296        if (a) {
1297            e = use1_QU_Rosenfeld(a, T);
1298        }
1299        else {
1300            d = E[i][j - 1];
1301            if (d) {
1302                e = use1_QU_Rosenfeld(d, T);
1303            }
1304            else {
1305                e = ++ne;
1306            }
1307        }
1308    }
1309    E[i][j] = e;
1310    return ne;
1311}
1312
1313// FAST
1314
1315// -----------------------------------------------------------------------------------------
1316static uint32 optimizedAccess_DT_Rosenfeld(uint32 ** E, int i, int j, uint32 * T, uint32 ne)
1317// -----------------------------------------------------------------------------------------
1318{
1319    // Decision Tree 8-connexe avec Quick-Union
1320    uint32 a, b, c, d, e;
1321   
1322    b = E[i - 1][j];
1323    if (b) {
1324        e = use1_QU_Rosenfeld(b, T);
1325    }
1326    else {
1327        c = E[i - 1][j + 1];
1328        if (c) {
1329            a = E[i - 1][j - 1];
1330            if (a) {
1331                e = use2_QU_Rosenfeld(a, c, T);
1332            }
1333            else {
1334                d = E[i][j - 1];
1335                if (d) {
1336                    e = use2_QU_Rosenfeld(c, d, T);
1337                }
1338                else {
1339                    e = use1_QU_Rosenfeld(c, T);
1340                }
1341            }
1342        }
1343        else {
1344            a = E[i - 1][j - 1];
1345            if (a) {
1346                e = use1_QU_Rosenfeld(a, T);
1347            }
1348            else {
1349                d = E[i][j - 1];
1350                if (d) {
1351                    e = use1_QU_Rosenfeld(d, T);
1352                }
1353                else {
1354                    e = ++ne;
1355                }
1356            }
1357        }
1358    }
1359    E[i][j] = e;
1360    return ne;
1361}
1362
1363// FAST
1364
1365// --------------------------------------------------------------------------------------------------------
1366static uint32 lineLabeling_Fast_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1367// --------------------------------------------------------------------------------------------------------
1368{
1369    uint8 x;
1370    // avec DT et QU
1371    // Left Border
1372    x = X[i][0];
1373    if (x) {
1374        ne = optimizedAccessLeft_DT_Rosenfeld(E, i, 0, T, ne);
1375    }
1376    else {
1377        E[i][0] = 0;
1378    }
1379    // Middle
1380    for (int j = 1; j < width - 1; j++) {
1381        uint8 x = X[i][j];
1382        if (x) {
1383            ne = optimizedAccess_DT_Rosenfeld(E, i, j, T, ne);
1384        }
1385        else {
1386            E[i][j] = 0;
1387        }
1388    }
1389    // Right Border
1390    x = X[i][width - 1];
1391    if (x) {
1392        ne = optimizedAccessRight_DT_Rosenfeld(E, i, width - 1, T, ne);
1393    }
1394    else {
1395        E[i][width - 1] = 0;
1396    }
1397    return ne;
1398}
1399#endif // FAST
1400
1401
1402// ---------------------------------------------------------------------------------------------------
1403static uint32 lineLabeling_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1404// ---------------------------------------------------------------------------------------------------
1405{
1406#if SLOW
1407    return lineLabeling_Slow_Rosenfeld(X, i, width, E, T, ne);
1408#elif FAST
1409    return lineLabeling_Fast_Rosenfeld(X, i, width, E, T, ne);
1410#endif
1411}
1412
1413
1414// -----------------------------------------------------------------------
1415static uint32 countTable_Range_Rosenfeld(uint32 * T, uint32 e0, uint32 e1)
1416// -----------------------------------------------------------------------
1417{
1418    uint32 e;
1419    uint32 nr = 0; // nombre de racines = de composantes connexes
1420   
1421    for (e = e0; e <= e1; e++) {
1422        if (e == T[e]) {
1423            nr += 1;
1424        }
1425    }
1426    return nr;
1427}
1428
1429
1430// ------------------------------------------------------------------------------------------
1431static void solveTable_Range_Rosenfeld(uint32 * T, uint32 e0, uint32 e1, RegionStats * Stats)
1432// ------------------------------------------------------------------------------------------
1433{
1434    uint32 e, r;
1435   
1436    for (e = e0; e <= e1; e++) {
1437        r = T[T[e]];
1438        assert(r != 0);
1439        if (r < e) {
1440            T[e] = r; // racine de la classe d'equivalence
1441#if FEATURES && !(PARMERGE && ARSP)
1442            RegionStats_Accumulate_Stats1_From_Index(Stats, r, e);
1443#endif
1444        }
1445    }
1446}
1447
1448
1449// --------------------------------------------
1450static void MCA_Label_Rosenfeld_PAR1(MCA * mca)
1451// --------------------------------------------
1452{
1453    if (mca->p == 0) { 
1454        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
1455    }
1456   
1457
1458    int i0 = mca->i0;
1459    int i1 = mca->i1;
1460    int width = mca->width;
1461
1462    uint32 e0 = mca->e0;
1463    uint32 e1 = mca->e1;
1464    uint32 ne_prev = mca->ne_prev;
1465    uint32 ne = e0 - 1;
1466    uint32 nr = 0;
1467
1468    // local memory zones
1469    uint8 **  X = mca->X;
1470    uint32 ** E = mca->E;
1471    uint32 *  T = mca->T;
1472    RegionStats * stats = mca->stats;
1473
1474    CLOCK_THREAD_START_STEP(mca->p, 0);
1475
1476    set_ui32vector_j(T, e0, ne_prev);
1477#if FEATURES
1478    zero_RegionStatsVector(stats, e0, ne_prev);
1479#endif
1480
1481    if (mca->p == 0) {
1482        MCA_VERBOSE3(display_ui8matrix_positive(X, i0, i1, 0, width - 1, 5, "Xp"); printf("\n"));
1483    }
1484
1485    // ---------------------------- //
1486    // -- Etiquetage d'une bande -- //
1487    // ---------------------------- //
1488
1489    ne = line0Labeling_Rosenfeld(X, i0, width, E, T, ne);
1490#if FEATURES
1491    lineFeaturesComputation(E, i0, width, stats);
1492#endif
1493
1494    for (int i = i0 + 1; i <= i1; i++) {
1495        ne = lineLabeling_Rosenfeld(X, i, width, E, T, ne); // Slow or Fast
1496#if FEATURES
1497        lineFeaturesComputation(E, i, width, stats);
1498#endif
1499    }
1500    mca->ne = ne; //plus grande etiquette de l'intervalle [e0..e1]
1501
1502    if (mca->p == 0) {
1503        MCA_VERBOSE3(printf("ne = %d\n", ne));
1504        MCA_VERBOSE3(display_ui32matrix_positive(E, i0, i1, 0, width - 1, 5, "Ep"); printf("\n"));
1505        MCA_VERBOSE3(display_ui32vector_number(T, e0, ne, "%5d", "Tp_avant"));
1506    }
1507
1508    // ------------------------------------------------------ //
1509    // -- Fermeture transitive sans pack de chaque table T -- //
1510    // ------------------------------------------------------ //
1511
1512    solveTable_Range_Rosenfeld(T, e0, ne, stats);
1513
1514    if (mca->p == 0) {
1515        MCA_VERBOSE3(nr = countTable_Range_Rosenfeld(T, e0, ne);
1516                     printf("p = %d : e = [%d..%d] -> ne = %d -> nr = %d\n", mca->p, e0, ne, (ne - e0 + 1), nr));
1517        MCA_VERBOSE3(display_ui32vector_number(T, e0, ne, "%5d", "Tp_apres"));
1518    }
1519    CLOCK_THREAD_END_STEP(mca->p, 0);
1520}
1521
1522
1523
1524#if PARMERGE
1525// -----------------------------------------------------
1526static void MCA_Label_Rosenfeld_PAR2(MCA * mca)
1527// -----------------------------------------------------
1528{
1529    int p = mca->p;
1530    int nb_level = mca->nb_level;
1531
1532    if (mca->p == 0) {
1533        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
1534    }
1535   
1536    // ------------------------------
1537    // -- parallel border merging --
1538    // ------------------------------
1539   
1540    // local variables
1541    int i = mca->i0;
1542    int width = mca->width;
1543    int alpha = mca->alpha;
1544    uint32 e0 = mca->e0;
1545    uint32 e1 = mca->ne;
1546
1547    // local memory zones
1548    uint8 **  X = mca->X;
1549    uint32 ** E = mca->E;
1550    uint32 *  T = mca->T;
1551    uint32 ** D = mca->D;
1552    RegionStats ** F = mca->F;
1553
1554    CLOCK_THREAD_START_STEP(p, 1);
1555    if (p != 0) { // thread 0 never has any merge to do
1556        borderMerging_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);  // (i) et (i-1)
1557    }
1558    pthread_barrier_wait(&main_barrier);
1559    CLOCK_THREAD_END_STEP(p, 1);
1560
1561
1562    // ---------------------------------
1563    // -- parallel transitive closure --
1564    // ---------------------------------
1565     
1566    CLOCK_THREAD_START_STEP(p, 2);
1567    for (uint32 e = e0; e <= e1; e++) {
1568        uint32 r = T[e]; // acces local
1569        if (r < e) {
1570            r = FindRoot_Dist(D, e, alpha); // acces distant
1571            T[e] = r;
1572        }
1573        MCA_VERBOSE3(printf("p%d : T[%d] <- %d\n", p, e, r));
1574    }
1575    CLOCK_THREAD_END_STEP(p, 2);
1576
1577#if FEATURES && ARSP
1578    pthread_barrier_wait(&main_barrier);
1579#endif
1580
1581    // To avoid uninitialized accesses
1582    CLOCK_THREAD_START_STEP(p, 3);
1583    // With FEATURES and ARSP, STEP 3 is the Features propagation
1584#if FEATURES && ARSP
1585    Propagate_Features(e0, e1, T, F, mca->alpha);
1586#endif
1587    CLOCK_THREAD_END_STEP(p, 3);
1588}
1589#endif // PARMERGE
1590
1591
1592#if !PARMERGE
1593// --------------------------------------------
1594static void MCA_Label_Rosenfeld_PYR2(MCA * mca)
1595// --------------------------------------------
1596{
1597    // input
1598    int p = mca->p;
1599    int nb_level = mca->nb_level;
1600
1601    if (mca->p == 0) {
1602        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
1603    }
1604   
1605    // ------------------------------
1606    // -- pyramidal border merging --
1607    // ------------------------------
1608   
1609    // local variables
1610    int i = mca->i0;
1611    int width = mca->width;
1612    int alpha = mca->alpha;
1613    uint32 e0 = mca->e0;
1614    uint32 e1 = mca->ne;
1615
1616    // local memory zones
1617    uint8 **  X = mca->X;
1618    uint32 ** E = mca->E;
1619    uint32 *  T = mca->T;
1620    uint32 ** D = mca->D;
1621    RegionStats ** F = mca->F;
1622
1623    CLOCK_THREAD_START_STEP(p, 1);
1624#if PYR_BARRIERS
1625    // Version optimisée qui fait faire un break aux processeurs qui n'ont plus
1626    // à faire de merge.
1627    // Implique de pré-calculer le nombre de threads à chaque barriÚre
1628    if (p != 0) { // thread 0 never has any merge to do
1629        int been_active = 0;
1630        for (int level = 0; level < nb_level; level++) {
1631            if ((p + (1 << level)) % (1 << (level + 1)) == 0) {
1632                borderMerging_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);  // (i) et (i-1)
1633                been_active = 1;
1634            }
1635            else if (been_active) {
1636                break;
1637            }
1638            pthread_barrier_wait(&mca->barriers[level]);
1639        }
1640    }
1641    pthread_barrier_wait(&main_barrier);
1642#else
1643    for (int level = 1; level <= nb_level; level++) {
1644        if ((p + (1 << (level - 1))) % (1 << level) == 0) {
1645            // thread actif
1646            borderMerging_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);  // (i) et (i-1)
1647        }
1648        pthread_barrier_wait(&main_barrier);
1649    }
1650#endif
1651    CLOCK_THREAD_END_STEP(p, 1);
1652   
1653
1654    // ---------------------------------
1655    // -- parallel transitive closure --
1656    // ---------------------------------
1657   
1658    CLOCK_THREAD_START_STEP(p, 2);
1659    for (uint32 e = e0; e <= e1; e++) {
1660        uint32 r = T[e]; // acces local
1661        if (r < e) {
1662            r = FindRoot_Dist(D, e, alpha); // acces distant
1663            T[e] = r;
1664        }
1665        MCA_VERBOSE3(printf("p%d : T[%d] <- %d\n", p, e, r));
1666    }
1667    CLOCK_THREAD_END_STEP(p, 2);
1668}
1669#endif // !PARMERGE
1670
1671
1672// -------------------------------------
1673void MCA_Label_Rosenfeld_PAR3(MCA * mca)
1674// -------------------------------------
1675{
1676    // input
1677    if (mca->p == 0) {
1678        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
1679    }
1680   
1681    int i0 = mca->i0;
1682    int i1 = mca->i1;
1683    int j0 = 0;
1684    int j1 = mca->width - 1;
1685
1686    uint32 ** E = mca->E;
1687    uint32 * T = mca->T;
1688
1689    CLOCK_THREAD_START_STEP(mca->p, 4);
1690    for (int i = i0; i <= i1; i++) {
1691        for (int j = j0; j <= j1; j++) {
1692            uint32 e = E[i][j];
1693            if (e != 0) {
1694                E[i][j] = T[e];
1695            }
1696        }
1697    }
1698    CLOCK_THREAD_END_STEP(mca->p, 4);
1699}
1700
1701
1702
1703// ======================================================================
1704#if TARGET_OS == GIETVM
1705__attribute__((constructor)) void * MCA_Label_Rosenfeld(void * arg)
1706#else
1707void * MCA_Label_Rosenfeld(void * arg)
1708#endif
1709// ======================================================================
1710{
1711    MCA * mca = (MCA *) arg;
1712#if TARGET_OS == GIETVM
1713    unsigned int x, y, lpid;
1714    giet_proc_xyp(&x, &y, &lpid);
1715    // Mettre à jour mca->p en fonction de x, y, lpid
1716    // pour que les allocations faites par le main soient locales,
1717    // i.e.
1718    mca->p = (x * Y_SIZE + y) * NB_PROCS_MAX + lpid;
1719    // We have :
1720    // mca->p = 4 pour (x = 0, y = 1, lpid = 0)
1721    // mca->p = 5 pour (x = 0, y = 1, lpid = 1)
1722    MCA_VERBOSE3(printf("mca->p = %d pour (x = %d, y = %d, lpid = %d)\n", mca->p, x, y, lpid));
1723#endif
1724
1725    CLOCK_THREAD_START(mca->p);
1726
1727    int num_runs = mca->nr;
1728
1729    // We always perform one more run than the num_runs
1730    // value, so as to know "ne", i.e. the number of
1731    // elements to reset in the T and F tables (labels and stats)
1732    // After this first extra run, clock times are not accumulated
1733    // and thus are lost.
1734    // Note: the CLOCK_THREAD_START will still include this first run,
1735    // and in case of multiple runs, only averaged times should be
1736    // considered.
1737    for (int run = 0; run < num_runs + 1; run++) {
1738
1739        CLOCK_THREAD_COMPUTE_START(mca->p);
1740
1741        MCA_Scatter_ImageX(mca);
1742        pthread_barrier_wait(&main_barrier);
1743
1744        MCA_Label_Rosenfeld_PAR1(mca);
1745        pthread_barrier_wait(&main_barrier);
1746 
1747#if PARMERGE
1748        MCA_Label_Rosenfeld_PAR2(mca);
1749#else
1750        MCA_Label_Rosenfeld_PYR2(mca);
1751#endif
1752        pthread_barrier_wait(&main_barrier);
1753 
1754        MCA_Label_Rosenfeld_PAR3(mca);
1755        pthread_barrier_wait(&main_barrier);
1756
1757        MCA_Gather_ImageL(mca);
1758        pthread_barrier_wait(&main_barrier);
1759       
1760        CLOCK_THREAD_COMPUTE_END(mca->p);
1761
1762        if (run == 0) {
1763            // Mise à jour du ne_prev par chaque thread
1764            mca->ne_prev = mca->ne;
1765            mca->ne = 0;
1766        }
1767        else {
1768            // Accumulation du temps COMPUTE et de toutes les STEP
1769            if (mca->p == 0) {
1770                CLOCK_ACCUMULATE;
1771            }
1772            assert(mca->ne == mca->ne_prev);
1773            // Reinitialisation de "ne" s'il ne s'agit pas du dernier run
1774            if (run != num_runs) {
1775                mca->ne = 0;
1776            }
1777        }
1778        pthread_barrier_wait(&main_barrier);
1779    }
1780
1781 
1782#if FEATURES
1783    if (display_features) {
1784        if (mca->p == 0) {
1785            int i = 1;
1786            MCA_VERBOSE1(printf("[STATS]\n"));
1787            for (int p = 0; p < mca->np; p++) {
1788                MCA * mca_par = mca->mca->mcas[p];
1789                uint32 e0 = mca_par->e0;
1790                uint32 ne = mca_par->ne - mca_par->e0; // number of elements
1791                uint32 * T = mca_par->T;
1792                RegionStats * stats = mca_par->stats;
1793                MCA_VERBOSE1(RegionStats_DisplayStats_Sparse(T, e0, e0 + ne, stats, NULL, &i));
1794            }
1795            MCA_VERBOSE1(printf("[/STATS]\n"));
1796        }
1797    }
1798#endif
1799
1800    CLOCK_THREAD_END(mca->p);
1801
1802#if TARGET_OS == GIETVM
1803    if (mca->p != 0) {
1804        exit(0);
1805    }
1806#endif
1807
1808    return NULL;
1809}
1810
1811
1812// Local Variables:
1813// tab-width: 4
1814// c-basic-offset: 4
1815// c-file-offsets:((innamespace . 0)(inline-open . 0))
1816// indent-tabs-mode: nil
1817// End:
1818
1819// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1820
Note: See TracBrowser for help on using the repository browser.