/*    REALIGN11
Testing REALIGN directive */

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

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

static void realign111();
static void realign112();
static void realign1121();
static void realign112r();
static void realign113();
static void realign113r();
static void realign114();
static void realign1141();
static void realign115();
static void realign116();

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

static int NL = 1000;
static int ER = 10000;

static int erria, errib, i, j, ia, ib;

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

    /* ALIGN arrB[i] WITH arrA[i]  REALIGN arrB[i] WITH arrA[2*i+8] */
    realign111();
    /* ALIGN arrB[i] WITH arrA[i+4]  REALIGN arrB[i] WITH arrA[i+8] */
    realign112();
    /* ALIGN arrB[i] WITH arrA[i+2]  REALIGN arrB[i] WITH arrA[2*i+5] */
    realign1121();
    /* ALIGN arrB[i] WITH arrA[i+4]  REALIGN arrB[i] WITH arrA[-i+8] */
//  realign112r();
    /* ALIGN arrB[i] WITH arrA[3*i+2] REALIGN arrB[i] WITH arrA[2*i+1] */
    realign113();
    /* ALIGN arrB[i] WITH arrA[-i+8] REALIGN arrB[i] WITH arrA[3*i+2] */
//  realign113r();
    /* ALIGN arrB[i] WITH arrA[2*i+8]  REALIGN arrB[i] WITH arrA[i] */
    realign114();
    /* ALIGN arrB[i] WITH arrA[2*i]  REALIGN arrB[i] WITH arrA[i+2] */
    realign1141();
    /* ALIGN arrB[ ] WITH arrA[ ]  REALIGN arrB[i] WITH arrA[i+4] */
    realign115();
    /* ALIGN arrB[i] WITH arrA[4*i+3]  REALIGN arrB[] WITH arrA[] */
    realign116();

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

/* ---------------------------------------------REALIGN111 */
        /* ALIGN arrB[i] WITH arrA[i]  REALIGN arrB[i] WITH arrA[2*i+8] */
void realign111()
{
    #define AN1 30
    #define BN1 8

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li] */
    int k1i = 1,li = 0;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri] */
    int kr1i = 2, lri = 8;   /* lri = -1 RTS err */
    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([i] with A1[k1i * i + li])
    int B1[BN1];

    char tname[] = "realign111 ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1, B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 0;

    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i;
        if (((i-li) == (((i-li)/k1i) * k1i)) &&
           (((i-li)/k1i) >= 0) &&
           (((i-li)/k1i) < BN1)) {
                 ib = (i-li)/k1i;
                 B1[ib] = ib;
        }
    }

    } /* end region */

    #pragma dvm realign (B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual (erria, errib)

    #pragma dvm region inlocal(A1, B1)
    {
    #pragma dvm parallel([i] on B1[i]) private(ia), reduction(min(erria), min(errib))
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != (i))
            errib = Min(errib, i);
        ia=kr1i * i + lri;
        if (A1[ia] != (ia))
            erria = Min(erria, i);
    }

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}
/* ---------------------------------------------REALIGN112 */
        /* ALIGN arrB[i] WITH arrA[i+4]  REALIGN arrB[i] WITH arrA[i+8] */
void realign112()
{
    #define AN1 16
    #define BN1 4

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li] */
    int k1i = 1,li = 4;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri] */
    int kr1i = 1,lri = 8;

    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([i] with A1[k1i * i + li])
    int B1[BN1];

    char tname[] = "realign112 ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1, B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 1;

    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i * 2;
        if (((i-li) == (((i-li)/k1i) * k1i)) &&
           (((i-li)/k1i) >= 0) &&
           (((i-li)/k1i) < BN1)){
              ib = (i-li)/k1i;
              B1[ib] += ib;
        }
    }

    } /* end region */

    #pragma dvm realign(B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual (erria, errib)

    #pragma dvm region inout(A1, B1)
    {
    #pragma dvm parallel([i] on B1[i]) private(ia), reduction(min(erria), min(errib))
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != (i+1))
            errib = Min(errib, i);
        ia=kr1i * i + lri;
        if (A1[ia] != ia*2)
            erria = Min(erria, i);
    }

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}
/* ---------------------------------------------REALIGN1121*/
    /* ALIGN arrB[i] WITH arrA[i+2]  REALIGN arrB[i] WITH arrA[2*i+5] */
void realign1121()
{
    int AN1 = 25;
    int BN1 = 7;

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li] */
    int k1i = 1;
    int li = 4;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri] */
    int kr1i = 2;
    int lri = 5;

    char tname[] = "realign1121";

    #pragma dvm array distribute[block]
    int *A1;
    #pragma dvm array
    int *B1;

    A1 = malloc(sizeof(int[AN1]));
    B1 = malloc(sizeof(int[BN1]));

    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erria = ER;
    errib = ER;

    #pragma dvm region
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 2;
    }

    #pragma dvm region inout(B1), out(A1)
    {
    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i;
        if (((i - li) == (((i - li) / k1i) * k1i)) &&
            (((i - li) / k1i) >= 0) &&
            (((i - li) / k1i) < BN1))
        {
            ib = (i - li) / k1i;
            B1[ib] += ib;
        }
    }
    }

    #pragma dvm realign(B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual(erria, errib)

    #pragma dvm region
    {
    #pragma dvm parallel([i] on B1[i]) reduction(min(erria), min(errib)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i+2)
            errib = Min(errib, i);
        ia = kr1i * i + lri;
        if (A1[ia] != ia)
            erria = Min(erria, i);
    }
    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    free(B1);
    free(A1);
}

/* ---------------------------------------------REALIGN112r  */
        /* ALIGN arrB[i] WITH arrA[i+4]  REALIGN arrB[i] WITH arrA[-i+8] */
void realign112r()
{
    #define AN1 12
    #define BN1 5

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li] */
    int k1i = 1,li = 4;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri] */
    int kr1i = -1,lri = 8;

    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([i] with A1[k1i * i + li])
    int B1[BN1];

    char tname[] = "realign112r ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 0;

    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i;
        if (((i-li) == (((i-li)/k1i) * k1i)) &&
           (((i-li)/k1i) >= 0) &&
           (((i-li)/k1i) < BN1)){
              ib = (i-li)/k1i;
              B1[ib] = ib;
        }
    }

    } /* end region */

    #pragma dvm realign(B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual (erria, errib)

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i]) private(ia), reduction(min(erria), min(errib))
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != (i))
            errib = Min(errib, i);
        ia=kr1i * i + lri;
        if (A1[ia] != (ia))
            erria = Min(erria, i);
    }

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}

/* ---------------------------------------------REALIGN113 */
        /* ALIGN arrB[i] WITH arrA[3*i+2] REALIGN arrB[i] WITH arrA[2*i+1] */
void realign113()
{
    #define AN1 30
    #define BN1 6

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li]  */
    int k1i = 3,li = -2;   /* 3*i + (-2) - RTS err */
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri]  */
    int kr1i = 2,lri = -1;

    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([i] with A1[k1i * i - li])
    int B1[BN1];

    char tname[] = "realign113 ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 5;

    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i+3;
//        if (((i-li) == (((i-li)/k1i) * k1i)) &&
//           (((i-li)/k1i) >= 0) &&
//           (((i-li)/k1i) < BN1)) {
//              ib = (i-li)/k1i;
//              B1[ib] = B1[ib] + ib;
//        }
//    }
        if (((i+li) == (((i+li)/k1i) * k1i)) &&
           (((i+li)/k1i) >= 0) &&
           (((i+li)/k1i) < BN1)) {
              ib = (i+li)/k1i;
              B1[ib] = B1[ib] + ib;
        }
    }

    } /* end region */

    #pragma dvm realign(B1[i] with A1[kr1i * i - lri])

    #pragma dvm actual (erria, errib)

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i]) reduction(min(erria), min(errib)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i+5)
            errib = Min(errib, i);
        ia=kr1i * i - lri;
        if (A1[ia] != (ia+3))
            erria = Min(erria, i);
    }

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}
/* ---------------------------------------------REALIGN113r  */
       /* ALIGN arrB[i] WITH arrA[-i+8] REALIGN arrB[i] WITH arrA[3*i+2] */
void realign113r()
{
    #define AN1 18
    #define BN1 5

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li]  */
    int k1i = -1,li  = 8;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri]  */
    int kr1i = 3,lri  = 2;

    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([i] with A1[k1i * i + li])
    int B1[BN1];

    char tname[] = "realign113r ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 0;

    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i;
        if (((i-li) == (((i-li)/k1i) * k1i)) &&
           (((i-li)/k1i) >= 0) &&
           (((i-li)/k1i) < BN1)) {
              ib = (i-li)/k1i;
              B1[ib] = ib;
        }
    }

    } /* end region */

    #pragma dvm realign(B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual (erria, errib)

    #pragma dvm region
    {
    #pragma dvm parallel([i] on B1[i]) reduction(min(erria),min(errib)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != (i))
            errib = Min(errib, i);
        ia=kr1i * i + lri;
        if (A1[ia] != (ia))
            erria = Min(erria, i);
    }

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}

/* ---------------------------------------------REALIGN114  */
        /* ALIGN arrB[i] WITH arrA[2*i+8]  REALIGN arrB[i] WITH arrA[i] */
void realign114()
{
    #define AN1 24
    #define BN1 8

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li]  */
    int k1i = 2, li = 8;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri]  */
    int kr1i = 1, lri = 0;

    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([i] with A1[k1i * i + li])
    int B1[BN1];

    char tname[] = "realign114 ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1, B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 0;

    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i;
        if (((i-li) == (((i-li)/k1i) * k1i)) &&
           (((i-li)/k1i) >= 0) &&
           (((i-li)/k1i) < BN1)) {
              ib = (i-li)/k1i;
              B1[ib] = ib;
        }
    }

    } /* end region */

    #pragma dvm realign(B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual (erria, errib)

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i]) reduction(min(erria), min(errib)), private (ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != (i))
            errib = Min(errib, i);
        ia=kr1i * i + lri;
        if (A1[ia] != (ia))
            erria = Min(erria, i);
    }

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}
/* ------ ---------------------------------------REALIGN1141*/
    /* ALIGN arrB[i] WITH arrA[4*i]  REALIGN arrB[i] WITH arrA[i+2] */
void realign1141()
{
    int AN1 = 24;
    int BN1 = 6;

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li]  */
    int k1i = 4;
    int li = 0;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri]  */
    int kr1i = 1;
    int lri = 2;

    char tname[] = "realign1141";

    #pragma dvm array distribute[block]
    int *A1;
    #pragma dvm array
    int *B1;

    A1 = malloc(sizeof(int[AN1]));
    B1 = malloc(sizeof(int[BN1]));

    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erria = ER;
    errib = ER;

    #pragma dvm region out(B1, A1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = 4;

    #pragma dvm parallel([i] on A1[i]) private(ib)
    for (i = 0; i < AN1; i++)
    {
        A1[i] = i+2;
        if (((i - li) == (((i - li) / k1i) * k1i)) &&
            (((i - li) / k1i) >= 0) &&
            (((i - li) / k1i) < BN1))
        {
            ib = (i - li) / k1i;
            B1[ib] += ib;
        }
    }
    }

    #pragma dvm realign(B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual(erria, errib)

    #pragma dvm region
    {
    #pragma dvm parallel([i] on B1[i]) reduction(min(erria), min(errib)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i+4)
            errib = Min(errib, i);
        ia = kr1i * i + lri;
        if (A1[ia] != ia+2)
            erria = Min(erria, i);
    }
    }

    #pragma dvm get_actual(erria, errib)

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

    free(B1);
    free(A1);
}
/* ---------------------------------------------REALIGN115  */
       /* ALIGN arrB[ ] WITH arrA[ ]  REALIGN arrB[i] WITH arrA[i+4] */
void realign115()
{
    #define AN1 16
    #define BN1 8

/* parameters for ALIGN arrB[] WITH arrA[]  */
    int k1i = 0,li  = 0;
/* parameters for REALIGN arrB[i] WITH arrA[kr1i*i+lri]  */
    int kr1i = 1,lri  = 4;

    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([] with A1[])
    int B1[BN1];

    char tname[] = "realign115 ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1, B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = i;

    #pragma dvm parallel([i] on A1[i])
    for (i = 0; i < AN1; i++)
        A1[i] = i;

    } /* end region */

    #pragma dvm realign(B1[i] with A1[kr1i * i + lri])

    #pragma dvm actual (erria, errib)

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i]) private (ia), reduction(min(erria), min(errib))
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != (i))
            errib = Min(errib, i);
        ia=kr1i * i + lri;
        if (A1[ia] != (ia))
            erria = Min(erria, i);
    }

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}
/* ---------------------------------------------REALIGN116 */
       /* ALIGN arrB[i] WITH arrA[4*i+3]  REALIGN arrB[] WITH arrA[] */
void realign116()
{
    #define AN1 35
    #define BN1 8

/* parameters for ALIGN arrB[i] WITH arrA[k1i*i+li]  */
    int k1i = 4,li = 3;  /* 4*i-3  RTS err */
/* parameters for REALIGN arrB[] WITH arrA[]  */
    int kr1i = 0,lri = 0;

    #pragma dvm array distribute[block]
    int A1[AN1];
    #pragma dvm array align([i] with A1[k1i*i+li])
    int B1[BN1];

    char tname[] = "realign116 ";

    erria = ER;
    errib = ER;

    #pragma dvm region inout(A1, B1)
    {
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = i+6;

    #pragma dvm parallel([i] on A1[i])
    for (i = 0; i < AN1; i++)
        A1[i] = (i+1)*3;

    } /* end region */

    #pragma dvm realign(B1[] with A1[])

    #pragma dvm actual (erria, errib)

    #pragma dvm region inout(A1,B1)
    {
    #pragma dvm parallel([i] on B1[i]) reduction(min(errib))
    for (i = 0; i < BN1; i++)
        if (B1[i] != i+6)
            errib = Min(errib, i);
    #pragma dvm parallel([i] on A1[i]) reduction(min(erria))
    for (i = 0; i < AN1; i++)
        if (A1[i] != (i+1)*3)
            erria = Min(erria, i);

    } /* end region */

    #pragma dvm get_actual(erria, errib)

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

    #undef AN1
    #undef BN1
}
/*-------------------------------------------------------*/
void ansyes(const char name[])
{
    printf ("%s  -  complete\n", name);
}

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