/*    ALIGNDYN11
TESTING align CLAUSE for dynamic arrays*/

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

static void align111();
static void align1111();
static void align1112();
static void align112();
static void align113();
static void align114();
static void align115();

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

static int NL = 1000;
static int ER = 10000;
static int erri, i, j, ia, ib;

int main(int an, char **as)
{
    printf("=== START OF ALIGNDYN11 ===================\n");
            /* ALIGN arrB[i] WITH arrA[i]  normal*/
    align111();
            /* ALIGN arrB[i] WITH arrA[i]  small array*/
    align1111();
            /* ALIGN arrB[i] WITH arrA[2*i+3]  small array*/
    align1112();
             /* ALIGN arrB[i] WITH arrA[i+4]  shift along i*/
    align112();
             /* ALIGN arrB[i] WITH arrA[-i+8] reverse on i*/
//    align113();
             /* ALIGN arrB[i] WITH arrA[2*i+8]  stretching along i*/
    align114();
             /* ALIGN arrB[] WITH arrA[]*/
    align115();
    printf("=== END OF ALIGNDYN11 =====================\n");
    return 0;
}
/* ---------------------------------------------ALIGN111*/
/* ALIGN arrB[i] WITH arrA[i] normal*/
void align111()
{
/*     parameters for ALIGN arrB[i] WITH arrA[k1i * i + li]*/
    int AN1 = 8;
    int BN1 = 8;
    int k1i = 1;
    int k2i = 0;
    int li = 0;
    char tname[] = "align111 ";

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

    /* create arrays */
    A1 = malloc(AN1 * sizeof(int));
    B1 = malloc(BN1 * sizeof(int));
    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erri = ER;
    #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;
        }
    }
    #pragma dvm parallel([i] on B1[i]) reduction(min(erri)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i)
            if (erri > i) erri = i;
        ia = k1i * i + li;
        if (A1[ia] != ia)
            if (erri > i) erri = i;
    }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(B1);
    free(A1);
}
/* ---------------------------------------------ALIGN1111*/
/* ALIGN arrB[i] WITH arrA[i] small array*/
void align1111()
{
/*     parameters for ALIGN arrB[i] WITH arrA[k1i * i + li]*/
    int AN1 = 5;
    int BN1 = 2;
    int k1i = 1;
    int k2i = 0;
    int li = 0;
    char tname[] = "align1111";

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

    /* create arrays */
    A1 = malloc(AN1 * sizeof(int));
    B1 = malloc(BN1 * sizeof(int));
    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erri = ER;
    #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;
        }
    }
    #pragma dvm parallel([i] on B1[i]) reduction(min(erri)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i)
            if (erri > i) erri = i;
        ia = k1i * i + li;
        if (A1[ia] != ia)
            if (erri > i) erri = i;
    }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(B1);
    free(A1);
}
/* ---------------------------------------------ALIGN1112*/
/* ALIGN arrB[i] WITH arrA[2*i+1]  small array*/
void align1112()
{
/*     parameters for ALIGN arrB[i] WITH arrA[k1i * i + li]*/
    int AN1 = 5;
    int BN1 = 2;
    int k1i = 2;
    int k2i = 0;
    int li = 1;
    char tname[] = "align1112";

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

    /* create arrays */
    A1 = malloc(AN1 * sizeof(int));
    B1 = malloc(BN1 * sizeof(int));
    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erri = ER;
    #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;
        }
    }
    #pragma dvm parallel([i] on B1[i]) reduction(min(erri)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i)
            if (erri > i) erri = i;
        ia = k1i * i + li;
        if (A1[ia] != ia)
            if (erri > i) erri = i;
    }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(B1);
    free(A1);
}
/* ---------------------------------------------ALIGN112*/
/* ALIGN arrB[i] WITH arrA[i+4]  shift along i*/
void align112()
{
/*     parameters for ALIGN arrB[i] WITH arrA[k1i * i + li]*/
    int AN1 = 8;
    int BN1 = 4;
    int k1i = 1;
    int k2i = 0;
    int li = 4;
    char tname[] = "align112 ";

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

    /* create arrays */
    A1 = malloc(AN1 * sizeof(int));
    B1 = malloc(BN1 * sizeof(int));
    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erri = ER;
    #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;
        }
    }
    #pragma dvm parallel([i] on B1[i]) reduction(min(erri)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i)
            if (erri > i) erri = i;
        ia = k1i * i + li;
        if (A1[ia] != ia)
            if (erri > i) erri = i;
    }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(B1);
    free(A1);
}
/* ---------------------------------------------ALIGN113*/
/* ALIGN arrB[i] WITH arrA[-i+8] reverse on i*/
void align113()
{
/*     parameters for ALIGN arrB[i] WITH arrA[k1i * i + li]*/
    int AN1 = 8;
    int BN1 = 8;
    int k1i = -1;
    int k2i = 0;
    int li = 8;
    char tname[] = "align113 ";

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

    /* create arrays */
    A1 = malloc(AN1 * sizeof(int));
    B1 = malloc(BN1 * sizeof(int));
    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erri = ER;
    #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;
        }
    }
    #pragma dvm parallel([i] on B1[i]) reduction(min(erri)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i)
            if (erri > i) erri = i;
        ia = k1i * i + li;
        if (A1[ia] != ia)
            if (erri > i) erri = i;
    }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(B1);
    free(A1);
}
/* ---------------------------------------------ALIGN114*/
/* ALIGN arrB[i] WITH arrA[2*i+8]  stretching along i*/
void align114()
{
/*     parameters for ALIGN arrB[i] WITH arrA[k1i * i + li]  */
    int AN1 = 24;
    int BN1 = 8;
    int k1i = 2;
    int k2i = 0;
    int li = 8;
    char tname[] = "align114 ";

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

    /* create arrays */
    A1 = malloc(AN1 * sizeof(int));
    B1 = malloc(BN1 * sizeof(int));
    #pragma dvm realign(B1[i] with A1[k1i * i + li])

    erri = ER;
    #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;
        }
    }
    #pragma dvm parallel([i] on B1[i]) reduction(min(erri)), private(ia)
    for (i = 0; i < BN1; i++)
    {
        if (B1[i] != i)
            if (erri > i) erri = i;
        ia = k1i * i + li;
        if (A1[ia] != ia)
            if (erri > i) erri = i;
    }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(B1);
    free(A1);
}
/* ---------------------------------------------ALIGN115*/
/* ALIGN arrB[] WITH arrA[]*/
void align115()
{
/*    parameters for ALIGN arrB[i] WITH arrA[k1i * i + li]*/
    int AN1 = 24;
    int BN1 = 8;
    int k1i = 0;
    int k2i = 0;
    int li  = 0;
    char tname[] = "align115 ";

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

    A1 = malloc(AN1 * sizeof(int));
    B1 = malloc(BN1 * sizeof(int));
    #pragma dvm realign(B1[] with A1[])

    erri = ER;
    #pragma dvm parallel([i] on B1[i])
    for (i = 0; i < BN1; i++)
        B1[i] = i;
    #pragma dvm parallel([i] on A1[i]) reduction(min(erri)), private(j)
    for (i = 0; i < AN1; i++)
        for (j = 0; j < BN1; j++)
        {
            if (B1[j] != j)
                if (erri > j) erri = j;
        }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(B1);
    free(A1);
}

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

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