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

Last change on this file was 826, checked in by meunier, 7 years ago
  • Mise à jour NR2 et Rosenfeld
File size: 54.5 KB
RevLine 
[805]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>
[821]14#if PARMERGE
15#include <pthread.h>
16#endif
[805]17
18#include "nrc_os_config.h"
[821]19#include "config.h"
[805]20#include "nrc.h"
[821]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>
[826]28    #include <assert.h>
[805]29#endif
30
[821]31
[805]32#include "util.h"
33#include "ecc_common.h"
34#include "palette.h"
35#include "bmpNR.h"
[821]36#include "clock.h"
[805]37#include "str_ext.h"
[821]38#include "ecc_features.h"
[805]39
40// -----------
41// -- local --
42// -----------
43
44#include "mca.h"
45
[821]46extern pthread_barrier_t main_barrier;
47extern int display_features;
[805]48
[821]49CLOCK_DEC;
50
51
52// -----------------------------------------
53static uint32 FindRoot(uint32 * T, uint32 e)
54// -----------------------------------------
[805]55{
56    uint32 r;
57   
[821]58    assert(e != 0);
[805]59    r = e;
60    while (T[r] < r) {
61        r = T[r];
62    }
[822]63
64    assert(r != 0);
[805]65    return r;
66}
67
68
[821]69// ----------------------------------------------------------
70static uint32 FindRoot_Dist(uint32 ** D, uint32 r, int shift)
71// ----------------------------------------------------------
[805]72{
73    uint32 e;
74    uint32 e1;
75    uint32 e0;
[821]76
77    assert(r != 0);
[805]78   
79    int mask = (1 << shift) - 1;
80   
[822]81    MCA_VERBOSE3(printf("%s(%d, %d) \n", __func__, r, shift));
[805]82    do {
83        e  = r;
84        e1 = r >> shift;
85        e0 = r & mask;
86        r = D[e1][e0];
[822]87        MCA_VERBOSE3(printf("%s: D(%d) = D[%d,%d] = %d (alpha = %d)\n", __func__, e, e1, e0, r, shift));
[805]88    } while (r < e);
[822]89    MCA_VERBOSE3(printf("%s = %d \n\n", __func__, r));
[821]90    assert(r != 0);
[805]91    return r;
92}
93
94
[821]95#if !FEATURES
96// --------------------------------------------------------------------------------
97static void SetRoot_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift)
98// --------------------------------------------------------------------------------
[805]99{
[821]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;
[805]107}
[821]108#endif // !FEATURES
[805]109
110
[821]111#if FEATURES && !PARMERGE
[822]112// -----------------------------------------------------------------------------------------------------------
113static void SetRoot_Features_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift, RegionStats ** F)
114// -----------------------------------------------------------------------------------------------------------
[805]115{
[821]116    assert(root != 0 && eps != 0);
117
[822]118    MCA_VERBOSE3(printf("F(%d) += F(%d)\n", eps, root));
[821]119   
[805]120    int mask = (1 << shift) - 1;
[821]121
122    uint32 r1 = root >> shift;
123    uint32 r0 = root & mask;
[805]124   
[821]125    D[r1][r0] = eps;
[805]126   
[821]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;
[805]142}
[821]143#endif // FEATURES && !PARMERGE
[805]144
145
[823]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) {
[826]167        // Someone changed the root of epsilon or "root", need to find the new root
[823]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
[821]182#if FEATURES && PARMERGE
[822]183// --------------------------------------------------------------------------------------------------------------------
184static bool SetRoot_Parallel_Features_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift, RegionStats ** F)
185// --------------------------------------------------------------------------------------------------------------------
[805]186{
[821]187    assert(root != 0 && eps != 0);
188
[822]189    MCA_VERBOSE3(printf("F(%d) += F(%d)\n", eps, root));
[821]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
[826]205        //printf("race cond 1\n");
[821]206        pthread_spin_unlock(&F[e1][e0].lock);
207        pthread_spin_unlock(&F[r1][r0].lock);
208        return false;
[805]209    }
[821]210    if (D[r1][r0] != root) {
[822]211        // Someone change the root of "root", need to find the new root
[826]212        //printf("race cond 2\n");
[821]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;
[805]233}
[821]234#endif // FEATURES && PARMERGE
[805]235
236
[826]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;
[821]249
[826]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
[821]272#if FAST
273// --------------------------------------------------------
274static uint32 QuickUnion2(uint32 * T, uint32 e1, uint32 e2)
275// --------------------------------------------------------
[805]276{
277    // version QU de Union2
[821]278    uint32 r1 = FindRoot(T, e1);
279    uint32 r2 = FindRoot(T, e2);
[805]280   
[821]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
[805]286    }
[821]287    if (r2 > eps) {
288        T[r2] = eps; // SetRoot sans besoin de remonter
[805]289    }
[821]290    assert(e1 != 0 && e2 != 0 && r1 != 0 && r2 != 0);
[805]291   
[821]292    return eps;
[805]293}
[821]294#endif // FAST
[805]295
296
[821]297#if FAST
298// ---------------------------------------------------
299static uint32 use1_QU_Rosenfeld(uint32 e1, uint32 * T)
300// ---------------------------------------------------
[805]301{
[821]302    return FindRoot(T, e1);
[805]303}
[821]304#endif // FAST
[805]305
306
[821]307#if FAST
308// --------------------------------------------------------------
309static uint32 use2_QU_Rosenfeld(uint32 e1, uint32 e2, uint32 * T)
310// --------------------------------------------------------------
[805]311{
312    return QuickUnion2(T, e1, e2);
313}
[821]314#endif // FAST
[805]315
316
[822]317#if FAST && !FEATURES && !PARMERGE && !ARSP
[821]318// ---------------------------------------------------------------------------------------
319static void vuse2_Rosenfeld_Dist(uint32 ed, uint32 el, uint32 * T, uint32 ** D, int alpha)
320// ---------------------------------------------------------------------------------------
[805]321{
[821]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    }
[805]340}
341
[822]342// FAST && !FEATURES && !PARMERGE && !ARSP
[805]343
[821]344// -----------------------------------------------------------------------------------------------------
345static void vuse3_Rosenfeld_Dist(uint32 ed1, uint32 ed2, uint32 el3, uint32 * T, uint32 ** D, int alpha)
346// -----------------------------------------------------------------------------------------------------
[805]347{
[821]348    uint32 r1 = FindRoot_Dist(D, ed1, alpha);
349    uint32 r2 = FindRoot_Dist(D, ed2, alpha);
[805]350   
[821]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);
[805]355   
[821]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   
[822]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)
[821]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}
[822]373#endif // FAST && !FEATURES && !PARMERGE && !ARSP
[821]374
375
[822]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// ------------------------------------------------------------------------------------------------------------------
[821]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) {
[805]392        return; // evite la backdoor
393    }
394   
[821]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);
[805]399    }
400    else {
[821]401        SetRoot_Features_Rosenfeld_Dist(D, rd, rl, alpha, F);
[805]402    }
403}
404
[822]405// FAST && FEATURES && !PARMERGE && !ARSP
[805]406
[822]407// --------------------------------------------------------------------------------------------------------------------------------
408static void vuse3_Features_Rosenfeld_Dist(uint32 ed1, uint32 ed2, uint32 el3, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
409// --------------------------------------------------------------------------------------------------------------------------------
[805]410{
[821]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);
[805]415   
[821]416    uint32 r3 = T[el3]; // local - distant
417    assert(r3 != 0);
418    r3 = FindRoot_Dist(D, r3, alpha);
[805]419   
[821]420    assert(r1 != 0 && r2 != 0 && r3 != 0);
421
422    if (r1 == r2 && r2 == r3) {
[805]423        return;
424    }
425   
[821]426    uint32 eps = ui32Min3(r1, r2, r3);  // forcement positifs car appel depuis optimizedBorder qui a fait un test
[805]427   
[821]428    if (r1 > eps) {
429        SetRoot_Features_Rosenfeld_Dist(D, r1, eps, alpha, F);
[805]430    }
[821]431    if (r2 > eps && r2 != r1) {
432        SetRoot_Features_Rosenfeld_Dist(D, r2, eps, alpha, F);
[805]433    }
[821]434    if (r3 > eps && r3 != r2 && r3 != r1) {
435        SetRoot_Features_Rosenfeld_Dist(D, r3, eps, alpha, F);
[805]436    }
437}
[822]438#endif // FAST && FEATURES && !PARMERGE && !ARSP
[805]439
440
[826]441#if FAST && PARMERGE && ARSP
[822]442// ----------------------------------------------------------------------------------------------------------------
443static bool SetRoot_Parallel_Arsp_Rosenfeld_Dist(uint32 ** D, uint32 root, uint32 eps, int shift, RegionStats ** F)
444// ----------------------------------------------------------------------------------------------------------------
[805]445{
[826]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.
[822]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   
[826]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
[822]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}
[826]470#endif // FAST && PARMERGE && ARSP
[822]471
472
[826]473#if FAST && PARMERGE && ARSP
[822]474// ------------------------------------------------------------------------------------------------------------------------------
475static inline bool FindSmallerAncestor_Link(uint32 ** D, uint32_t rl, uint32_t el, uint32_t rd, uint32_t shift, RegionStats ** F)
476// ------------------------------------------------------------------------------------------------------------------------------
477{
[826]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
[821]483    bool ok;
[822]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
[826]508// FAST && PARMERGE && ARSP
[822]509
510// -----------------------------------------------------------------------------------------------------------------------
511static void vuse2_Parallel_Arsp_Rosenfeld_Dist(uint32 ed, uint32 el, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
512// -----------------------------------------------------------------------------------------------------------------------
513{
[821]514    assert(ed != 0 && el != 0);
[822]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
[826]559// FAST && PARMERGE && ARSP
[822]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}
[826]663#endif // FAST && PARMERGE && ARSP
[822]664
665
666
[823]667#if FAST && PARMERGE && !ARSP // Valid for FEATURES and !FEATURES
[822]668// ---------------------------------------------------------------------------------------------------------------------------
[823]669static void vuse2_Parallel_Rosenfeld_Dist(uint32 ed, uint32 el, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
[822]670// ---------------------------------------------------------------------------------------------------------------------------
671{
672    bool ok;
673    assert(ed != 0 && el != 0);
[821]674    uint32 rl = T[el]; // car le premier acces est local
675    assert(rl != 0);
676
677    uint32 rd;
[805]678   
[821]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) {
[823]692            // Features or No Features depending on config
693            ok = SetRoot_Parallel_FNF(D, rl, rd, alpha, F);
[821]694        }
695        else {
[823]696            ok = SetRoot_Parallel_FNF(D, rd, rl, alpha, F);
[821]697        }
698    } while (!ok);
699}
700
[823]701// FAST && PARMERGE && !ARSP
[821]702
[822]703// -----------------------------------------------------------------------------------------------------------------------------------------
[823]704static void vuse3_Parallel_Rosenfeld_Dist(uint32 ed1, uint32 ed2, uint32 el3, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
[822]705// -----------------------------------------------------------------------------------------------------------------------------------------
[821]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);
[805]719   
[821]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) {
[823]732            ok1 = SetRoot_Parallel_FNF(D, r1, eps, alpha, F);
[821]733        }
734        if (r2 > eps && r2 != r1) {
[823]735            ok2 = SetRoot_Parallel_FNF(D, r2, eps, alpha, F);
[821]736        }
737        if (r3 > eps && r3 != r2 && r3 != r1) {
[823]738            ok3 = SetRoot_Parallel_FNF(D, r3, eps, alpha, F);
[821]739        }
740    } while (!(ok1 && ok2 && ok3));
[805]741}
[823]742#endif // FAST && PARMERGE && !ARSP
[805]743
744
[821]745
[822]746#if FAST
747// ------------------------------------------------------------------------------------------------------------------------
748static void optimizedBorder_Rosenfeld_Dist(uint32 ** E, int i, int j, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
749// ------------------------------------------------------------------------------------------------------------------------
[805]750{
[821]751    uint32 a, b, c, x;
[805]752   
[821]753    x = E[i][j];
754    if (x) {
755        b = E[i - 1][j];
756        if (b) {
[822]757            vuse2_Rosenfeld(b, x, T, D, alpha, F); // dist, local
[821]758        }
759        else {
760            c = E[i - 1][j + 1];
761            if (c) {
762                a = E[i - 1][j - 1];
763                if (a) {
[822]764                    vuse3_Rosenfeld(a, c, x, T, D, alpha, F); // dist, local
[805]765                }
766                else {
[822]767                    vuse2_Rosenfeld(c, x, T, D, alpha, F); // dist, local
[805]768                }
769            }
770            else {
[821]771                a = E[i - 1][j - 1];
772                if (a) {
[822]773                    vuse2_Rosenfeld(a, x, T, D, alpha, F); // dist, local
[805]774                }
775            }
776        }
777    }
778}
779
[822]780// FAST
[805]781
[822]782// ----------------------------------------------------------------------------------------------------------------------------
783static void optimizedBorderLeft_Rosenfeld_Dist(uint32 ** E, int i, int j, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
784// ----------------------------------------------------------------------------------------------------------------------------
[805]785{
[821]786    uint32 x = E[i][j];
787    if (x) {
788        uint32 b = E[i - 1][j];
789        if (b) {
[822]790            vuse2_Rosenfeld(b, x, T, D, alpha, F); // dist, local
[821]791        }
792        else {
793            uint32 c = E[i - 1][j + 1];
794            if (c) {
[822]795                vuse2_Rosenfeld(c, x, T, D, alpha, F); // dist, local
[821]796            }
797        }
798    }
799}
800
[822]801// FAST
[821]802
[822]803// -----------------------------------------------------------------------------------------------------------------------------
804static void optimizedBorderRight_Rosenfeld_Dist(uint32 ** E, int i, int j, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
805// -----------------------------------------------------------------------------------------------------------------------------
[821]806{
[805]807    // copie de optimizedBorder_Rosenfeld
[821]808    // test d'existance de ex en local local
809
810    uint32 b = E[i - 1][j];
811    uint32 x = E[i][j];
[805]812   
[821]813    if (x) {
814        if (b) {
[822]815            vuse2_Rosenfeld(b, x, T, D, alpha, F); // dist, local
[805]816        }
817        else {
[821]818            uint32 a = E[i - 1][j - 1];
[805]819            if (a) {
[822]820                vuse2_Rosenfeld(a, x, T, D, alpha, F); // dist, local
[805]821            }
822        }
823    }
824}
825
[822]826// FAST
[805]827
[822]828// -------------------------------------------------------------------------------------------------------------------------------------------
829static void borderMerging_Fast_Rosenfeld_Dist(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
830// -------------------------------------------------------------------------------------------------------------------------------------------
[805]831{
[821]832    // Prologue
[822]833    optimizedBorderLeft_Rosenfeld_Dist(E, i, 0, T, D, alpha, F);
[821]834    // Boucle principale
835    for (int j = 1; j < width - 1; j++) {
[822]836        optimizedBorder_Rosenfeld_Dist(E, i, j, T, D, alpha, F);
[805]837    }
[821]838    // Epilogue
[822]839    optimizedBorderRight_Rosenfeld_Dist(E, i, width - 1, T, D, alpha, F);
[805]840}
[822]841#endif // FAST
[805]842
843
[821]844
[822]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// -------------------------------------------------------------------------------------------------------------------------------------------
[805]849{
[821]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    // --------------
[822]859    MCA_VERBOSE3(printf("[%s] i = %d\n", __func__, i));
[821]860   
861    ex = E[i][j];
862   
863    if (ex) {
864       
[822]865        MCA_VERBOSE3(printf("[%s] j = %d\n", __func__, j));
[821]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           
[822]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));
[821]886           
887            // Quick-Union
888            if (r2 > eps) {
[822]889                SetRoot_Rosenfeld(D, r2, eps, alpha, F);
890                MCA_VERBOSE3(printf("D[%5d] <- %d\n", r2, eps));
[821]891            }
892            // Pour le cas où r2 == r3, il ne faut pas ajouter deux fois les features
[822]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));
[821]900            }
[822]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));
[821]906            }
[822]907            MCA_VERBOSE3(printf("---------------------------\n"));
[821]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           
[822]921            MCA_VERBOSE3(printf("[%s] j = %d\n", __func__, j));
[821]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
[822]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));
[821]944               
[822]945               
[821]946                // Quick-Union
947                if (r1 > eps) {
[822]948                    SetRoot_Rosenfeld(D, r1, eps, alpha, F);
949                    MCA_VERBOSE3(printf("D[%5d] <- %d\n", r1, eps));
[821]950                }
[822]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));
[821]958                }
[822]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));
[821]966                }
[822]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));
[821]972                }
[822]973                MCA_VERBOSE3(puts("---------------------------\n"));
[821]974            }
975        }
976    }
977   
978    // --------------
979    // -- epilogue --
980    // --------------
981   
982    j = width - 1;
983    ex = E[i][j];
984   
985    if (ex) {
986       
[822]987        MCA_VERBOSE3(printf("[%s] j = %d\n", __func__, j));
[821]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           
[822]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));
[821]1008           
1009            // Quick-Union
1010            if (r1 > eps) {
[822]1011                SetRoot_Rosenfeld(D, r1, eps, alpha, F);
1012                MCA_VERBOSE3(printf("D[%5d] <- %d\n", r1, eps));
[821]1013            }
[822]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));
[821]1021            }
[822]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));
[821]1027            }
[822]1028            MCA_VERBOSE3(printf("---------------------------\n"));
[821]1029        }
1030    }
1031}
[822]1032#endif // SLOW
[821]1033
1034
1035
[822]1036// --------------------------------------------------------------------------------------------------------------------------------------
1037static void borderMerging_Rosenfeld_Dist(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ** D, int alpha, RegionStats ** F)
1038// --------------------------------------------------------------------------------------------------------------------------------------
[821]1039{
[822]1040#if FAST
1041    borderMerging_Fast_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);
1042#endif // FAST
[821]1043#if SLOW
[822]1044    borderMerging_Slow_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);
1045#endif // SLOW
[805]1046}
1047
1048
[821]1049// ----------------------------------------------------------------------------------------------------
1050static uint32 line0Labeling_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1051// ----------------------------------------------------------------------------------------------------
1052{
[805]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
[821]1088#if SLOW
1089// --------------------------------------------------------------------------------------------------------
1090static uint32 lineLabeling_Slow_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1091// --------------------------------------------------------------------------------------------------------
[805]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}
[821]1253#endif // SLOW
[805]1254
1255
[821]1256#if FAST
1257// ---------------------------------------------------------------------------------------------
1258static uint32 optimizedAccessLeft_DT_Rosenfeld(uint32 ** E, int i, int j, uint32 * T, uint32 ne)
1259// ---------------------------------------------------------------------------------------------
[805]1260{
[821]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
[822]1281// FAST
[821]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
[822]1313// FAST
[821]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
[822]1363// FAST
[821]1364
1365// --------------------------------------------------------------------------------------------------------
1366static uint32 lineLabeling_Fast_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1367// --------------------------------------------------------------------------------------------------------
1368{
1369    uint8 x;
[805]1370    // avec DT et QU
[821]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];
[805]1382        if (x) {
1383            ne = optimizedAccess_DT_Rosenfeld(E, i, j, T, ne);
1384        }
1385        else {
1386            E[i][j] = 0;
1387        }
1388    }
[821]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    }
[805]1397    return ne;
1398}
[821]1399#endif // FAST
[805]1400
1401
[821]1402// ---------------------------------------------------------------------------------------------------
1403static uint32 lineLabeling_Rosenfeld(uint8 ** X, int i, int width, uint32 ** E, uint32 * T, uint32 ne)
1404// ---------------------------------------------------------------------------------------------------
[805]1405{
[821]1406#if SLOW
[805]1407    return lineLabeling_Slow_Rosenfeld(X, i, width, E, T, ne);
[821]1408#elif FAST
1409    return lineLabeling_Fast_Rosenfeld(X, i, width, E, T, ne);
1410#endif
[805]1411}
1412
1413
[821]1414// -----------------------------------------------------------------------
1415static uint32 countTable_Range_Rosenfeld(uint32 * T, uint32 e0, uint32 e1)
1416// -----------------------------------------------------------------------
[805]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
[822]1430// ------------------------------------------------------------------------------------------
1431static void solveTable_Range_Rosenfeld(uint32 * T, uint32 e0, uint32 e1, RegionStats * Stats)
1432// ------------------------------------------------------------------------------------------
[805]1433{
1434    uint32 e, r;
1435   
1436    for (e = e0; e <= e1; e++) {
1437        r = T[T[e]];
[822]1438        assert(r != 0);
[805]1439        if (r < e) {
1440            T[e] = r; // racine de la classe d'equivalence
[826]1441#if FEATURES && !(PARMERGE && ARSP)
[821]1442            RegionStats_Accumulate_Stats1_From_Index(Stats, r, e);
1443#endif
[805]1444        }
1445    }
1446}
1447
1448
[822]1449// --------------------------------------------
1450static void MCA_Label_Rosenfeld_PAR1(MCA * mca)
1451// --------------------------------------------
[805]1452{
[821]1453    if (mca->p == 0) { 
[822]1454        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
[821]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;
[823]1464    uint32 ne_prev = mca->ne_prev;
[821]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
[823]1474    CLOCK_THREAD_START_STEP(mca->p, 0);
1475
1476    set_ui32vector_j(T, e0, ne_prev);
[822]1477#if FEATURES
[823]1478    zero_RegionStatsVector(stats, e0, ne_prev);
[822]1479#endif
[821]1480
1481    if (mca->p == 0) {
[822]1482        MCA_VERBOSE3(display_ui8matrix_positive(X, i0, i1, 0, width - 1, 5, "Xp"); printf("\n"));
[821]1483    }
1484
1485    // ---------------------------- //
1486    // -- Etiquetage d'une bande -- //
1487    // ---------------------------- //
1488
1489    ne = line0Labeling_Rosenfeld(X, i0, width, E, T, ne);
[822]1490#if FEATURES
[821]1491    lineFeaturesComputation(E, i0, width, stats);
[822]1492#endif
[821]1493
1494    for (int i = i0 + 1; i <= i1; i++) {
1495        ne = lineLabeling_Rosenfeld(X, i, width, E, T, ne); // Slow or Fast
[822]1496#if FEATURES
[821]1497        lineFeaturesComputation(E, i, width, stats);
[822]1498#endif
[821]1499    }
1500    mca->ne = ne; //plus grande etiquette de l'intervalle [e0..e1]
1501
1502    if (mca->p == 0) {
[822]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"));
[821]1506    }
1507
1508    // ------------------------------------------------------ //
1509    // -- Fermeture transitive sans pack de chaque table T -- //
1510    // ------------------------------------------------------ //
1511
[822]1512    solveTable_Range_Rosenfeld(T, e0, ne, stats);
[821]1513
1514    if (mca->p == 0) {
[822]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"));
[821]1518    }
1519    CLOCK_THREAD_END_STEP(mca->p, 0);
1520}
1521
1522
[822]1523
1524#if PARMERGE
[821]1525// -----------------------------------------------------
[822]1526static void MCA_Label_Rosenfeld_PAR2(MCA * mca)
[821]1527// -----------------------------------------------------
1528{
1529    int p = mca->p;
1530    int nb_level = mca->nb_level;
1531
1532    if (mca->p == 0) {
[822]1533        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
[821]1534    }
1535   
1536    // ------------------------------
[822]1537    // -- parallel border merging --
[821]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
[822]1556        borderMerging_Rosenfeld_Dist(X, i, width, E, T, D, alpha, F);  // (i) et (i-1)
[821]1557    }
1558    pthread_barrier_wait(&main_barrier);
1559    CLOCK_THREAD_END_STEP(p, 1);
1560
1561
1562    // ---------------------------------
1563    // -- parallel transitive closure --
1564    // ---------------------------------
[822]1565     
[821]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        }
[822]1573        MCA_VERBOSE3(printf("p%d : T[%d] <- %d\n", p, e, r));
[821]1574    }
1575    CLOCK_THREAD_END_STEP(p, 2);
1576
[826]1577#if FEATURES && ARSP
1578    pthread_barrier_wait(&main_barrier);
1579#endif
1580
[821]1581    // To avoid uninitialized accesses
1582    CLOCK_THREAD_START_STEP(p, 3);
[826]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
[821]1587    CLOCK_THREAD_END_STEP(p, 3);
1588}
[822]1589#endif // PARMERGE
[821]1590
1591
[822]1592#if !PARMERGE
1593// --------------------------------------------
1594static void MCA_Label_Rosenfeld_PYR2(MCA * mca)
1595// --------------------------------------------
[821]1596{
[822]1597    // input
[821]1598    int p = mca->p;
1599    int nb_level = mca->nb_level;
1600
1601    if (mca->p == 0) {
[822]1602        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
[821]1603    }
1604   
1605    // ------------------------------
[822]1606    // -- pyramidal border merging --
[821]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);
[822]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
[821]1628    if (p != 0) { // thread 0 never has any merge to do
[822]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        }
[821]1640    }
1641    pthread_barrier_wait(&main_barrier);
[822]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
[821]1651    CLOCK_THREAD_END_STEP(p, 1);
[822]1652   
[821]1653
1654    // ---------------------------------
1655    // -- parallel transitive closure --
1656    // ---------------------------------
[822]1657   
[821]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        }
[822]1665        MCA_VERBOSE3(printf("p%d : T[%d] <- %d\n", p, e, r));
[821]1666    }
1667    CLOCK_THREAD_END_STEP(p, 2);
1668}
[826]1669#endif // !PARMERGE
[821]1670
1671
[822]1672// -------------------------------------
1673void MCA_Label_Rosenfeld_PAR3(MCA * mca)
1674// -------------------------------------
[805]1675{
[822]1676    // input
1677    if (mca->p == 0) {
1678        MCA_VERBOSE2(printf("*** %s ***\n", __func__));
1679    }
[805]1680   
[822]1681    int i0 = mca->i0;
1682    int i1 = mca->i1;
1683    int j0 = 0;
1684    int j1 = mca->width - 1;
[805]1685
[822]1686    uint32 ** E = mca->E;
1687    uint32 * T = mca->T;
[821]1688
[826]1689    CLOCK_THREAD_START_STEP(mca->p, 4);
[822]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        }
[821]1697    }
[826]1698    CLOCK_THREAD_END_STEP(mca->p, 4);
[821]1699}
1700
1701
[822]1702
[821]1703// ======================================================================
1704#if TARGET_OS == GIETVM
[822]1705__attribute__((constructor)) void * MCA_Label_Rosenfeld(void * arg)
[821]1706#else
[822]1707void * MCA_Label_Rosenfeld(void * arg)
[821]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)
[822]1722    MCA_VERBOSE3(printf("mca->p = %d pour (x = %d, y = %d, lpid = %d)\n", mca->p, x, y, lpid));
[821]1723#endif
1724
1725    CLOCK_THREAD_START(mca->p);
1726
[823]1727    int num_runs = mca->nr;
[821]1728
[823]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 
[821]1747#if PARMERGE
[823]1748        MCA_Label_Rosenfeld_PAR2(mca);
[821]1749#else
[823]1750        MCA_Label_Rosenfeld_PYR2(mca);
[821]1751#endif
[823]1752        pthread_barrier_wait(&main_barrier);
1753 
1754        MCA_Label_Rosenfeld_PAR3(mca);
1755        pthread_barrier_wait(&main_barrier);
[821]1756
[823]1757        MCA_Gather_ImageL(mca);
1758        pthread_barrier_wait(&main_barrier);
1759       
1760        CLOCK_THREAD_COMPUTE_END(mca->p);
[821]1761
[823]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
[821]1781 
[822]1782#if FEATURES
[821]1783    if (display_features) {
1784        if (mca->p == 0) {
1785            int i = 1;
[822]1786            MCA_VERBOSE1(printf("[STATS]\n"));
[821]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;
[822]1793                MCA_VERBOSE1(RegionStats_DisplayStats_Sparse(T, e0, e0 + ne, stats, NULL, &i));
[821]1794            }
[822]1795            MCA_VERBOSE1(printf("[/STATS]\n"));
[821]1796        }
1797    }
[822]1798#endif
[821]1799
1800    CLOCK_THREAD_END(mca->p);
1801
1802#if TARGET_OS == GIETVM
[805]1803    if (mca->p != 0) {
[821]1804        exit(0);
[805]1805    }
[821]1806#endif
1807
1808    return NULL;
[805]1809}
1810
[821]1811
[805]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.