/*    REALIGN44
Testing REALIGN directive */

#include <math.h>
#include <stdlib.h>
#include <stdio.h>

#define Min(a, b) ((a) < (b) ? (a) : (b))

static void realign441();
static void realign442();
static void realign443();
static void realign444();

static void ansyes(const char tname[]);
static void ansno(const char tname[]);

static int NL = 10000;
static int ER = 100000;
static int erria, errib, i, j, k, n, m, na, ma, ia, ib, nb, mb, ja, jb, s, cs;

int main(int an, char **as)
{
    printf("=== START OF REALIGN44 ======================\n");

    /* ALIGN arrB[i][j][n][m] WITH arrA[i][j][n][m]
       REALIGN arrB[][j][n][] WITH arrA[j][n][1][3] */
    realign441();
    /* ALIGN arrB[][j][n][i] WITH arrA[i][j][][n]
       REALIGN arrB[i][j][][m] WITH arrA[i][j][2][m] */
    realign442();
    /* ALIGN arrB[i][j][n][m] WITH arrA[i][2*j][3*n][4*m]
       REALIGN arrB[i][j][n][m] WITH arrA[i+1][j+2]+[n+3][m+4] */
    realign443();
    /* ALIGN arrB[i][j][n][m] WITH arrA[m][i][j][n]
       REALIGN arrB[i][j][n][m] WITH arrA[i+2][3*j+4][2*n+2][m+1] */
    realign444();

    printf("=== END OF REALIGN44 ========================\n");
    return 0;
}

/* ---------------------------------------------REALIGN441*/
    /* ALIGN arrB[i][j][n][m] WITH arrA[i][j][n][m]
       REALIGN arrB[][j][n][] WITH arrA[j][n][1][3] */
void realign441()
{
    #define AN1 6
    #define AN2 8
    #define AN3 5
    #define AN4 7
    #define BN1 2
    #define BN2 5
    #define BN3 4
    #define BN4 3
/*  parameters for ALIGN arrB[i][j][n][m] WITH arrA[k1i*i+li][k2j*j+lj][k3n*n+ln][k4m*m+lm] */
    int k1i = 1, li = 0;
    int k2j = 1, lj = 0;
    int k3n = 1, ln = 0;
    int k4m = 1, lm = 0;
/*  parameters for REALIGN arrB[*][j][n][*] WITH arrA[kr2j*j+lrj][kr3n*n+lrn][lri][lrm] */
    int kr1i = 0, lri = 1;
    int kr2j = 1, lrj = 0;
    int kr3n = 1, lrn = 0;
    int kr4m = 0, lrm = 3;

    #pragma dvm array distribute[block][block][block][block]
    int A4[AN1][AN2][AN3][AN4];
    #pragma dvm array align([i][j][n][m] with A4[k1i*i + li][k2j*j + lj][k3n*n + ln][k4m*m + lm])
    int B4[BN1][BN2][BN3][BN4];
    char tname[] = "realign441";

    erria = ER;
    errib = ER;

    #pragma dvm region
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m])
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    B4[i][j][n][m] = 0;

    #pragma dvm parallel([i][j][n][m] on A4[i][j][n][m]) private(ib, jb, nb, mb)
    for (i = 0; i < AN1; i++)
        for (j = 0; j < AN2; j++)
            for (n = 0; n < AN3; n++)
                for (m = 0; m < AN4; m++)
                {
                    A4[i][j][n][m] = i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;
                    if (((i - li) == (((i - li) / k1i) * k1i)) &&
                        ((j - lj) == (((j - lj) / k2j) * k2j)) &&
                        ((n - ln) == (((n - ln) / k3n) * k3n)) &&
                        ((m - lm) == (((m - lm) / k4m) * k4m)) &&
                        (((i - li) / k1i) >= 0) &&
                        (((j - lj) / k2j) >= 0) &&
                        (((n - ln) / k3n) >= 0) &&
                        (((m - lm) / k4m) >= 0) &&
                        (((i - li) / k1i) < BN1) &&
                        (((j - lj) / k2j) < BN2) &&
                        (((n - ln) / k3n) < BN3) &&
                        (((m - lm) / k4m) < BN4))
                    {
                        ib = (i - li) / k1i;
                        jb = (j - lj) / k2j;
                        nb = (n - ln) / k3n;
                        mb = (m - lm) / k4m;
                        B4[ib][jb][nb][mb] = ib * NL / 10 + jb * NL / 100 + nb * NL / 1000 + mb;
                    }
                }
    }

    #pragma dvm realign(B4[][j][n][] with A4[kr2j*j+lrj][kr3n*n+lrn][lri][lrm])

    s = 0;

    #pragma dvm actual(erria, errib, s)

    #pragma dvm region
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m]) reduction(min(erria), min(errib), sum(s)), private(ia, ja, na, ma)
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                {
                    int val = i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;
                    s += B4[i][j][n][m];
                    if (B4[i][j][n][m] !=val)
                        errib = Min(errib, val);

                    ia=kr2j*j+lrj;
                    ja=kr3n*n+lrn;
                    na=lri;
                    ma=lrm;
                    val = ia * NL / 10 + ja * NL / 100 + na * NL / 1000 + ma;
                    if (A4[ia][ja][na][ma] != val)
                        erria = Min(erria, val);
                }

    }

    #pragma dvm get_actual(erria, errib, s)

    cs = 0;
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    cs = cs + i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;

    if ((erria == ER) && (errib == ER) && (s == cs))
        ansyes(tname);
    else {
        ansno(tname);
        printf ("%d, %d, %d\n", erria, errib, s);
    }
    #undef AN1
    #undef AN2
    #undef AN3
    #undef AN4
    #undef BN1
    #undef BN2
    #undef BN3
    #undef BN4
}

/* ---------------------------------------------REALIGN442*/
    /*  ALIGN arrB[][j][n][i] WITH arrA[i][j][][n]
        REALIGN arrB[i][j][][m] WITH arrA[i][j][2][m] */
void realign442()
{
    int AN1 = 5, AN2 = 5, AN3 = 5, AN4 = 5;
    int BN1 = 2, BN2 = 2, BN3 = 2, BN4 = 2;

/*  parameters for ALIGN arrB[*][j][n][i] WITH arrA4(k1i*i+li,k2j*j+lj,*,k3m*n+lm) */
    int k1i = 1, li = 0;
    int k2j = 1, lj = 0;
    int k3n = 0, ln = 0;
    int k3m = 1, lm = 0;
/*  parameters for REALIGN arrB[i][j][*][m] WITH arrA(kr1i*i+lri,kr2j*j+lrj,lrn,kr4m*m+lrm) */
    int kr1i = 1, lri = 0;
    int kr2j = 1, lrj = 0;
    int kr3n = 0, lrn = 2;
    int kr4m = 1, lrm = 0;

    char tname[] = "realign442";

    #pragma dvm array distribute[block][block][block][block]
    int (*A4)[AN2][AN3][AN4];
    #pragma dvm array
    int (*B4)[BN2][BN3][BN4];

    A4 = malloc(sizeof(int[AN1][AN2][AN3][AN4]));
    B4 = malloc(sizeof(int[BN1][BN2][BN3][BN4]));

    #pragma dvm realign(B4[][j][n][i] with A4[k1i*i + li][k2j*j + lj][][k3m*n + lm])

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A4, B4)
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m])
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    B4[i][j][n][m] = 0;

    #pragma dvm parallel([i][j][n][m] on A4[i][j][n][m]) private(ib, jb, nb, mb, k)
    for (i = 0; i < AN1; i++)
        for (j = 0; j < AN2; j++)
            for (n = 0; n < AN3; n++)
                for (m = 0; m < AN4; m++)
                {
                    A4[i][j][n][m] = i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;
                    for (k = 0; k < BN1; k++)
                    {
                        if (((i - li) == (((i - li) / k1i) * k1i)) &&
                            ((j - lj) == (((j - lj) / k2j) * k2j)) &&
                            ((m - lm) == (((m - lm) / k3m) * k3m)) &&
                            (((i - li) / k1i) >= 0) &&
                            (((j - lj) / k2j) >= 0) &&
                            (((m - lm) / k3m) >= 0) &&
                            (((i - li) / k1i) < BN4) &&
                            (((j - lj) / k2j) < BN2) &&
                            (((m - lm) / k3m) < BN3))
                        {
                            mb = (i - li) / k1i;
                            jb = (j - lj) / k2j;
                            ib = k;
                            nb = (m - lm) / k3m;
                            B4[ib][jb][nb][mb] = ib * NL / 10 + jb * NL / 100 + nb * NL / 1000 + mb;
                        }
                    }
                }
    }

    #pragma dvm realign(B4[i][j][][m] with A4[kr1i*i+lri][kr2j*j+lrj][lrn][kr4m*m+lrm])
    s = 0;
    #pragma dvm actual(erria, errib, s)

    #pragma dvm region
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m]) reduction(min(erria), min(errib), sum(s)), private(ia, ja, na, ma)
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                {
                    int val = i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;
                    s += B4[i][j][n][m];
                    if (B4[i][j][n][m] != val)
                        errib = Min(errib,val);

                    ia = kr1i*i + lri;
                    ja = kr2j*j + lrj;
                    na = lrn;
                    ma = kr4m*m + lrm;
                    val = ia * NL / 10 + ja * NL / 100 + na * NL / 1000 + ma;
                    if (A4[ia][ja][na][ma] != val)
                        erria = Min(erria, val);
                }

    }
    #pragma dvm get_actual(erria, errib, s)

    cs = 0;
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    cs = cs + i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;

    // printf("erri = %u, ER = %u, s = %u, cs = %u\n", erri, ER, s, cs);

    if ((erria == ER) && (errib == ER) && (s == cs))
        ansyes(tname);
    else
        ansno(tname);

    free(B4);
    free(A4);
}

/* ---------------------------------------------REALIGN443*/
    /* ALIGN arrB[i][j][n][m] WITH arrA[i][2*j][3*n][4*m]
       REALIGN arrB[i][j][n][m] WITH arrA[i+1][j+2]+[n+3][m+4] */

void realign443()
{
    #define AN1 10
    #define AN2 8
    #define AN3 14
    #define AN4 12
    #define BN1 4
    #define BN2 3
    #define BN3 5
    #define BN4 3
/*  parameters for ALIGN arrB[i][j][n][m] WITH arrA[k1i*i+li][k2j*j+lj][k3n*n+ln][k4m*m+lm] */
    int k1i = 1, li = 0;
    int k2j = 2, lj = 0;
    int k3n = 3, ln = 0;
    int k4m = 4, lm = 0;
/*  parameters for REALIGN arrB[i][j][n][m] WITH arrA[kr1i*i+lri][kr2j*j+lrj][kr3n*n+lrn][kr4m*m+lrm] */
    int kr1i = 1, lri = 1;
    int kr2j = 1, lrj = 2;
    int kr3n = 1, lrn = 3;
    int kr4m = 1, lrm = 4;

    #pragma dvm array distribute[block][block][block][block]
    int A4[AN1][AN2][AN3][AN4];
    #pragma dvm array align([i][j][n][m] with A4[k1i*i + li][k2j*j + lj][k3n*n + ln][k4m*m + lm])
    int B4[BN1][BN2][BN3][BN4];
    char tname[] = "realign443";

    erria = ER;
    errib = ER;

    #pragma dvm region
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m])
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    B4[i][j][n][m] = 5;

    #pragma dvm parallel([i][j][n][m] on A4[i][j][n][m]) private(ib, jb, nb, mb)
    for (i = 0; i < AN1; i++)
        for (j = 0; j < AN2; j++)
            for (n = 0; n < AN3; n++)
                for (m = 0; m < AN4; m++)
                {
                    A4[i][j][n][m] = i * NL / 10 + j * NL / 100 + n * NL / 1000 + m + 1;
                    if (((i - li) == (((i - li) / k1i) * k1i)) &&
                        ((j - lj) == (((j - lj) / k2j) * k2j)) &&
                        ((n - ln) == (((n - ln) / k3n) * k3n)) &&
                        ((m - lm) == (((m - lm) / k4m) * k4m)) &&
                        (((i - li) / k1i) >= 0) &&
                        (((j - lj) / k2j) >= 0) &&
                        (((n - ln) / k3n) >= 0) &&
                        (((m - lm) / k4m) >= 0) &&
                        (((i - li) / k1i) < BN1) &&
                        (((j - lj) / k2j) < BN2) &&
                        (((n - ln) / k3n) < BN3) &&
                        (((m - lm) / k4m) < BN4))
                    {
                        ib = (i - li) / k1i;
                        jb = (j - lj) / k2j;
                        nb = (n - ln) / k3n;
                        mb = (m - lm) / k4m;
                        B4[ib][jb][nb][mb] += ib * NL / 10 + jb * NL / 100 + nb * NL / 1000 + mb;
                    }
                }
    }

    #pragma dvm realign(B4[i][j][n][m] with A4[kr1i*i + lri][kr2j*j + lrj][kr3n*n + lrn][kr4m*m + lrm])

    s = 0;

    #pragma dvm actual(erria, errib, s)

    #pragma dvm region
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m]) reduction(min(erria), min(errib), sum(s)), private(ia, ja, na, ma)
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                {
                    int val = i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;
                    s += B4[i][j][n][m];
                    if (B4[i][j][n][m] != val + 5)
                        errib = Min(errib, val);

                    ia=kr1i*i+lri;
                    ja=kr2j*j+lrj;
                    na=kr3n*n+lrn;
                    ma=kr4m*m+lrm;
                    val = ia * NL / 10 + ja * NL / 100 + na * NL / 1000 + ma;
                    if (A4[ia][ja][na][ma] != val + 1)
                        erria = Min(erria, val);
                }

    }

    #pragma dvm get_actual(erria, errib, s)

    cs = 0;
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    cs = cs + i * NL / 10 + j * NL / 100 + n * NL / 1000 + m + 5;

    if ((erria == ER) && (errib == ER) && (s == cs))
        ansyes(tname);
    else
    {
        ansno(tname);
//      printf ("%d, %d, %d\n", erria, errib, s);
    }
    #undef AN1
    #undef AN2
    #undef AN3
    #undef AN4
    #undef BN1
    #undef BN2
    #undef BN3
    #undef BN4
}

/* ---------------------------------------------REAGLIGN444*/
    /* ALIGN arrB[i][j][n][m] WITH arrA[m][i+1][j][2*n]
       REALIGN arrB[i][j][n][m] WITH arrA[i+2][3*j+4][2*n+2][m+1] */

void realign444()
{
    #define AN1 12
    #define AN2 15
    #define AN3 16
    #define AN4 10
    #define BN1 4
    #define BN2 4
    #define BN3 5
    #define BN4 3
/*  parameters for ALIGN arrB[i][j][n][m] WITH arrA4[k4m*m+lm][k1i*i+li][k2j*j+lj][k3n*n+ln] */
    int k1i = 1, li = 1;
    int k2j = 1, lj = 0;
    int k3n = 2, ln = 0;
    int k4m = 1, lm = 0;
/*  parameters for REALIGN arrB[i][j][n][m] WITH arrA[kr1i*i+lri][kr2j*j+lrj][kr3n*n+lrn][kr4m*m+lrm] */
    int kr1i = 1, lri = 2;
    int kr2j = 3, lrj = 4;
    int kr3n = 2, lrn = 2;
    int kr4m = 1, lrm = 1;

    #pragma dvm array distribute[block][block][block][block]
    int A4[AN1][AN2][AN3][AN4];
    #pragma dvm array align([i][j][n][m] with A4[k4m*m+lm][k1i*i+li][k2j*j+lj][k3n*n+ln])
    int B4[BN1][BN2][BN3][BN4];
    char tname[] = "realign444";

    erria = ER;
    errib = ER;

    #pragma dvm region
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m])
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    B4[i][j][n][m] = 4;

    #pragma dvm parallel([i][j][n][m] on A4[i][j][n][m]) private(ib, jb, nb, mb)
    for (i = 0; i < AN1; i++)
        for (j = 0; j < AN2; j++)
            for (n = 0; n < AN3; n++)
                for (m = 0; m < AN4; m++)
                {
                    A4[i][j][n][m] = 10 + i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;
                    if (
                       ((i-lm) == (((i-lm)/k4m) * k4m)) &&
                       ((j-li) == (((j-li)/k1i) * k1i)) &&
                       ((n-lj) == (((n-lj)/k2j) * k2j)) &&
                       ((m-ln) == (((m-ln)/k3n) * k3n)) &&
                       (((i-lm)/k4m) >= 0) &&
                       (((j-li)/k1i) >= 0) &&
                       (((n-lj)/k2j) >= 0) &&
                       (((m-ln)/k3n) >= 0) &&
                       (((i-lm)/k4m) < BN4)&&
                       (((j-li)/k1i) < BN1) &&
                       (((n-lj)/k2j) < BN2) &&
                       (((m-ln)/k3n) < BN3)
                      )
                    {
                        ib = (j-li)/k1i;
                        jb = (n-lj)/k2j;
                        nb = (m-ln)/k3n;
                        mb = (i-lm)/k4m;
                        B4[ib][jb][nb][mb] += ib * NL / 10 + jb * NL / 100 + nb * NL / 1000 + mb;
                    }
                }

    } /* end region */

    #pragma dvm realign(B4[i][j][n][m] with A4[kr1i*i + lri][kr2j*j + lrj][kr3n*n + lrn][kr4m*m + lrm])

    s = 0;

    #pragma dvm actual(erria, errib, s)

    #pragma dvm region
    {
    #pragma dvm parallel([i][j][n][m] on B4[i][j][n][m]) reduction(min(erria), min(errib), sum(s)), private(ia, ja, na, ma)
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                {
                    int val = i * NL / 10 + j * NL / 100 + n * NL / 1000 + m;
                    s += B4[i][j][n][m];
                    if (B4[i][j][n][m] != val+4)
                        errib = Min(errib, val);

                    ia=kr1i*i+lri;
                    ja=kr2j*j+lrj;
                    na=kr3n*n+lrn;
                    ma=kr4m*m+lrm;
                    val = ia * NL / 10 + ja * NL / 100 + na * NL / 1000 + ma;
                    if (A4[ia][ja][na][ma] != val+10)
                        erria = Min(erria, val);
                }
    }

    #pragma dvm get_actual(erria, errib, s)

    cs = 0;
    for (i = 0; i < BN1; i++)
        for (j = 0; j < BN2; j++)
            for (n = 0; n < BN3; n++)
                for (m = 0; m < BN4; m++)
                    cs = cs + i * NL / 10 + j * NL / 100 + n * NL / 1000 + m + 4;

    if ((erria == ER) && (errib == ER) && (s == cs))
        ansyes(tname);
    else
        ansno(tname);

    #undef AN1
    #undef AN2
    #undef AN3
    #undef AN4
    #undef BN1
    #undef BN2
    #undef BN3
    #undef BN4
}
/* --------------------------------------------- */

void ansyes(const char name[])
{
    printf("%s  -  complete\n", name);
}

void ansno(const char name[])
{
    printf("%s  -  ***error\n", name);
}
