/*    DISTRMIX3
Testing DISTRIBUTE and REDISTRIBUTE directive
            GEN_BLOCK, WGT_BLOCK, MULT_BLOCK distributions
*/

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

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

#ifndef _DVMH
#define dvmh_get_num_procs(X) 1
#endif

static void distrmix31();
static void distrmix32();
static void distrmix33();
static void distrmix34();
static void distrmix35();
static void distrmix36();
static void distrmix37();
static void distrmix38();
static void distrmix39();
static void distrmix310();
static void distrmix311();
static void distrmix312();
static void distrmix313();
static void distrmix314();
static void distrmix315();
static void distrmix316();
static void distrmix317();
static void distrmix318();
static void distrmix319();
static void distrmix320();
static void distrmix321();
static void distrmix322();
static void distrmix323();
static void distrmix324();
static void distrmix325();

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

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

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

    /* 31  DISTRIBUTE arrA3[MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]*/
    distrmix31();
    /* 32 DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]*/
    distrmix32();
    /* 33  DISTRIBUTE arrA3[MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][MULT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]*/
    distrmix33();
    /* 34  DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][MULT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][WGT_BLOCK]*/
    distrmix34();
    /* 35  DISTRIBUTE arrA3[MULT_BLOCK][WGT_BLOCK][BLOCK]
              REDISTRIBUTE [WGT_BLOCK][BLOCK][MULT_BLOCK]
              REDISTRIBUTE [BLOCK][MULT_BLOCK][WGT_BLOCK]*/
    distrmix35();
    /* 36  DISTRIBUTE arrA3[WGT_BLOCK][MULT_BLOCK][BLOCK]
              REDISTRIBUTE [MULT_BLOCK][BLOCK][WGT_BLOCK]
              REDISTRIBUTE [BLOCK][WGT_BLOCK][MULT_BLOCK]*/
    distrmix36();
    /* 37  DISTRIBUTE arrA3[MULT_BLOCK][BLOCK][BLOCK]
              REDISTRIBUTE [BLOCK][BLOCK][WGT_BLOCK]
              REDISTRIBUTE [BLOCK][WGT_BLOCK][MULT_BLOCK]*/
    distrmix37();
    /* 38  DISTRIBUTE arrA3[MULT_BLOCK][*][WGT_BLOCK]
              REDISTRIBUTE [*][*][*]
              REDISTRIBUTE [WGT_BLOCK][MULT_BLOCK][*]*/
    distrmix38();
    /* 39  DISTRIBUTE arrA3[MULT_BLOCK][BLOCK][*]
              REDISTRIBUTE [WGT_BLOCK][*][WGT_BLOCK]
              REDISTRIBUTE [*][MULT_BLOCK][*]*/
    distrmix39();
    /* 310  DISTRIBUTE arrA3[WGT_BLOCK][*][*]
              REDISTRIBUTE [MULT_BLOCK][*][WGT_BLOCK]
              REDISTRIBUTE [*][WGT_BLOCK][MULT_BLOCK]*/
    distrmix310();

    /* 311  DISTRIBUTE arrA3[MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]
             REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
             REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]*/
    distrmix311();
    /* 312 DISTRIBUTE arrA3[GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
             REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]
             REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][BLOCK]*/
    distrmix312();
    /* 313  DISTRIBUTE arrA3[BLOCK][BLOCK][MULT_BLOCK]
              REDISTRIBUTE [BLOCK][GEN_BLOCK][BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][WGT_BLOCK]*/
    distrmix313();
    /* 314 DISTRIBUTE arrA3[WGT_BLOCK][BLOCK][MULT_BLOCK]
              REDISTRIBUTE [GEN_BLOCK][BLOCK][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][BLOCK][WGT_BLOCK]*/
    distrmix314();
    /* 315  DISTRIBUTE arrA3[MULT_BLOCK][WGT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [BLOCK][GEN_BLOCK][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]*/
    distrmix315();
    /* 316  DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]*/
    distrmix316();
    /* 317  DISTRIBUTE arrA3[GEN_BLOCK][*][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][*]
              REDISTRIBUTE [*][GEN_BLOCK][BLOCK]*/
    distrmix317();
    /* 318  DISTRIBUTE arrA3[GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
                REDISTRIBUTE [WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
                REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]*/
    distrmix318();

    /* 319 DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
               REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
               REDISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]*/
    distrmix319();
    /* 320  DISTRIBUTE arrA3[BLOCK][GEN_BLOCK][GEN_BLOCK]
                REDISTRIBUTE arrB3[WGT_BLOCK][BLOCK][WGT_BLOCK]*/
    distrmix320();
    /* 321 DISTRIBUTE arrA3[WGT_BLOCK][BLOCK][WGT_BLOCK]
                REDISTRIBUTE [GEN_BLOCK][BLOCK][GEN_BLOCK]*/
    distrmix321();
    /* 322  DISTRIBUTE arrA3[GEN_BLOCK][BLOCK][GEN_BLOCK]
                REDISTRIBUTE [BLOCK][WGT_BLOCK][BLOCK]*/
    distrmix322();
    /* 323 DISTRIBUTE arrA3[BLOCK][WGT_BLOCK][BLOCK]
                REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][*]*/
    distrmix323();
    /* 324 DISTRIBUTE arrA3[GEN_BLOCK][GEN_BLOCK][*]
                REDISTRIBUTE [*][WGT_BLOCK][WGT_BLOCK]
                REDISTRIBUTE [GEN_BLOCK][*][GEN_BLOCK]*/
    distrmix324();
    /* 325  DISTRIBUTE arrA3 [*][GEN_BLOCK][GEN_BLOCK]
                REDISTRIBUTE [*][WGT_BLOCK][*]
                REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]*/
    distrmix325();

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

static int myRand() {
    const unsigned a = 1103515245U;
    const unsigned c = 12345U;
    const unsigned m = ((unsigned)RAND_MAX) + 1U;
    static unsigned prev = 5;
    prev = (a * prev + c) % m;
    return prev;
}

static void genBlocksAxis(const int procCount, const int weight, const int withoutZero, int **blocks) {
    *blocks = (int *)malloc(procCount * sizeof(int));
    int restWeight = weight, i, zeroind = -1;
    if (!withoutZero && procCount > 1)
        zeroind = myRand() % (procCount - 1);
    for (i = 0; i < (procCount - 1); i++) {
        if (i == zeroind)
            (*blocks)[i] = 0;
        else
            (*blocks)[i] = 1 * withoutZero + myRand() % (restWeight - (procCount - (i + 1)));
        restWeight -= (*blocks)[i];
    }
    (*blocks)[i] = restWeight;
}

/* ---------------------------------------------DISTR31*/
/*DISTRIBUTE arrA3[MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]*/
void distrmix31()
{
    #define AN1 32
    #define AN2 32
    #define AN3 32
    int m11 = 4, m21 = 8, m31 = 2;
    int m12 = 2, m22 = 4, m32 = 4;
    double wb1[7] = {2.0, 1.5, 4., 3.0, 2., 3., 2.};
    double wb2[8] = {1.0, 1., 2., 2.0, 1., 1., 2., 2.};
    double wb3[7] = {2.0, 2., 2.6, 3.0, 1., 1.5, 1.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix31";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m11)][multblock(m21)][multblock(m31)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[wgtblock(wb1, 7)][wgtblock(wb2, 8)][wgtblock(wb3, 7)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m12)][multblock(m22)][multblock(m32)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR32*/
/*DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][WGT_BLOCK][WGT_BLOCK] */
void distrmix32()
{
    #define AN1 16
    #define AN2 16
    #define AN3 12
    int m1 = 2, m2 = 4, m3 = 4;
    double wb1[6] = {2.0,5.,0.,3.0, 2., 3.};
    double wb2[8] = {1.2,2.,4.,2.5,3.,1.,3.,2.};
    double wb3[7] = {2.3,1.2,4.6,3.0, 1.5, 2.5, 1.2};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix32";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb1, 6)][wgtblock(wb2, 8)][wgtblock(wb3, 7)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[multblock(m1)][multblock(m2)][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[wgtblock(wb2, 8)][wgtblock(wb3, 7)][wgtblock(wb1, 6)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR33*/
/*DISTRIBUTE arrA3[MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][MULT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]*/
void distrmix33()
{
    #define AN1 12
    #define AN2 18
    #define AN3 20
    int m11 = 2, m21 = 3, m31 = 2;
    int m12 = 6, m22 = 9, m32 = 5;
    double wb1[7] = {2.2, 2.4, 4., 2.5, 3.5, 1.,3};
    double wb2[6] = {1.2, 2., 2.5, 3., 1.5, 3.};
    double wb3[5] = {4.3, 2.2, 2.6, 2.0, 2.5};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix33";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m11)][wgtblock(wb2, 6)][multblock(m31)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[wgtblock(wb1, 7)][multblock(m21)][wgtblock(wb3, 5)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m12)][multblock(m22)][multblock(m32)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR34*/
/* DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [WGT_BLOCK][MULT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][WGT_BLOCK]*/
void distrmix34()
{
    #define AN1 35
    #define AN2 28
    #define AN3 16
    int m1 = 7, m2 = 7, m3 = 4;
    double wb1[8] = {2., 2., 4., 2.7, 3.5, 2., 1., 3.};
    double wb2[6] = {12., 2.5, 3., 1.5, 3., 2.};
    double wb3[7] = {4.,3., 2.2, 2.6, 2.0, 2.5, 1.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix34";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb1, 8)][wgtblock(wb2, 6)][multblock(m3)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[wgtblock(wb2, 6)][multblock(m2)][wgtblock(wb3, 7)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m1)][wgtblock(wb3, 7)][wgtblock(wb1, 8)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR35*/
/* DISTRIBUTE arrA3[MULT_BLOCK][WGT_BLOCK][BLOCK]
               REDISTRIBUTE [WGT_BLOCK][BLOCK][MULT_BLOCK]
               REDISTRIBUTE [BLOCK][MULT_BLOCK][WGT_BLOCK]*/
void distrmix35()
{
    #define AN1 10
    #define AN2 21
    #define AN3 32
    int m1 = 2, m2 = 3, m3 = 4;
    double wb1[7] = {2., 4., 3., 2.5, 5., 1., 2.};
    double wb2[10] = {1., 2., 5., 3., 1., 3., 2., 3., 2., 1.};
    double wb3[8] = {2.3, 2.2, 1.6, 1., 2.0, 2.5, 3., 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix35";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m1)][wgtblock(wb2, 10)][block])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[wgtblock(wb1, 7)][block][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[block][multblock(m2)][wgtblock(wb3, 8)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR36*/
/* DISTRIBUTE arrA3[WGT_BLOCK][MULT_BLOCK][BLOCK]
             REDISTRIBUTE [MULT_BLOCK][BLOCK][WGT_BLOCK]
             REDISTRIBUTE [BLOCK][WGT_BLOCK][MULT_BLOCK]*/
void distrmix36()
{
    #define AN1 16
    #define AN2 28
    #define AN3 16
    int m1 = 2, m2 = 7, m3 = 4;
    double wb1[8] = {1.2, 2., 4., 2.5, 3., 1., 3., 2.};
    double wb2[7] = {2., 2., 4., 2.5, 3., 1., 3.};
    double wb3[7] = {2.5, 2.2, 4.2, 2.0, 1.5, 3.5, 1.2};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix36";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb1, 8)][multblock(m2)][block])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[multblock(m1)][block][wgtblock(wb3, 7)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[block][wgtblock(wb2, 7)][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR37*/
/* DISTRIBUTE arrA3[MULT_BLOCK][BLOCK][BLOCK]
              REDISTRIBUTE [BLOCK][BLOCK][WGT_BLOCK]
              REDISTRIBUTE [BLOCK][WGT_BLOCK][MULT_BLOCK]*/
void distrmix37()
{
    #define AN1 10
    #define AN2 10
    #define AN3 30
    int m1 = 2, m2 = 5, m3 = 3;
    double wb2[6] = {4., 2.5, 3., 1., 3., 2.};
    double wb3[8] = {1., 2., 3., 3.5, 4., 1., 3., 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix37";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m1)][block][block])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[block][block][wgtblock(wb3, 8)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[block][wgtblock(wb2, 6)][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR38*/
/* DISTRIBUTE arrA3[MULT_BLOCK][*][WGT_BLOCK]
              REDISTRIBUTE [*][*][*]
              REDISTRIBUTE [WGT_BLOCK][MULT_BLOCK][*]*/
void distrmix38()
{
    #define AN1 16
    #define AN2 16
    #define AN3 16
    int m1 = 2, m2 = 1, m3 = 4;
    double wb[11] = {2.2, 3.,3., 2.5, 2., 1., 4., 2., 1., 5., 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix38";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m1)][*][wgtblock(wb, 11)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[*][*][*])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[wgtblock(wb, 8)][multblock(m2)][*])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR39*/
/* DISTRIBUTE arrA3[MULT_BLOCK][BLOCK][*]
             REDISTRIBUTE [WGT_BLOCK][*][WGT_BLOCK]
             REDISTRIBUTE [*][MULT_BLOCK][*]*/
void distrmix39()
{
    #define AN1 18
    #define AN2 6
    #define AN3 30
    int m1 = 3, m2 = 2, m3 = 5;
    double wb[11] = {3.2, 2., 2., 1.5, 4., 2., 3., 2.5, 1.6, 3., 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix39";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m1)][block][*])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[wgtblock(wb, 11)][*][wgtblock(wb, 7)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[*][multblock(m2)][*])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR310*/
/* DISTRIBUTE arrA3[WGT_BLOCK][*][*]
             REDISTRIBUTE [MULT_BLOCK][*][WGT_BLOCK]
             REDISTRIBUTE [*][WGT_BLOCK][MULT_BLOCK]*/
void distrmix310()
{
    #define AN1 25
    #define AN2 35
    #define AN3 10
    int m1 = 5, m2 = 7, m3 = 2;
    double wb[12] = {3., 1., 2., 1.5, 3., 4., 3., 2.5, 1.6, 3., 1.2, 1.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix310";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb, 12)][*][*])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[multblock(m1)][*][wgtblock(wb, 8)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[*][wgtblock(wb, 8)][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR311*/
/* DISTRIBUTE arrA3[MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][MULT_BLOCK]*/
void distrmix311()
{
    #define AN1 15
    #define AN2 15
    #define AN3 28
    int m11 = 3, m21 = 5, m31 = 4;
    int m12 = 5, m22 = 3, m32 = 7;
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix311";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m11)][multblock(m21)][multblock(m31)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[genblock(BS1i)][genblock(BS1j)][genblock(BS1k)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m12)][multblock(m22)][multblock(m32)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR312*/
/* DISTRIBUTE arrA3[GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][BLOCK]*/
void distrmix312()
{
    #define AN1 24
    #define AN2 10
    #define AN3 24
    int m1 = 3, m2 = 2, m3 = 4;
    int *BS1i, *BS1j, *BS1k, *BS2i, *BS2j, *BS2k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS2i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS2j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS2k);
    double wb[10] = {2., 2.5, 3., 4., 3.5, 2.5, 2.6, 3., 2.2, 3.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix312";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[genblock(BS1i)][genblock(BS1j)][genblock(BS1k)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[multblock(m1)][wgtblock(wb, 10)][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[genblock(BS2i)][genblock(BS2j)][block])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(BS2i);
    free(BS2j);
    free(BS2k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR313*/
/* DISTRIBUTE arrA3[BLOCK][BLOCK][MULT_BLOCK]
           REDISTRIBUTE [BLOCK][GEN_BLOCK][BLOCK]
           REDISTRIBUTE [MULT_BLOCK][MULT_BLOCK][WGT_BLOCK]*/
void distrmix313()
{
    #define AN1 12
    #define AN2 24
    #define AN3 36
    int m1 = 2, m2 = 3, m3 = 4;
    int *BS1j;
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    double wb[9] = {1., 2.5, 3., 4., 2.5, 2.6, 3.5, 4.2, 3.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix313";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[block][block][multblock(m3)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[block][genblock(BS1j)][block])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m1)][multblock(m2)][wgtblock(wb, 9)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1j);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR314*/
/* DISTRIBUTE arrA3[WGT_BLOCK][BLOCK][MULT_BLOCK]
              REDISTRIBUTE [GEN_BLOCK][BLOCK][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][BLOCK][WGT_BLOCK]*/
void distrmix314()
{
    #define AN1 24
    #define AN2 15
    #define AN3 12
    int m1 = 4, m2 = 3, m3 = 2;
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb[10] = {3., 2., 2., 4., 2., 3., 2.5, 2.6, 1.2, 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix314";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb, 10)][block][multblock(m3)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[genblock(BS1i)][block][genblock(BS1k)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m1)][block][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR315*/
/* DISTRIBUTE arrA3[MULT_BLOCK][WGT_BLOCK][WGT_BLOCK]
              REDISTRIBUTE [BLOCK][GEN_BLOCK][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]*/
void distrmix315()
{
    #define AN1 21
    #define AN2 14
    #define AN3 16
    int m1 = 3, m2 = 2, m3 = 4;
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb1[8] = {2., 4., 3., 1., 2.5, 2.6, 2.2, 2.};
    double wb2[10] = {4., 2., 2.5, 4., 2., 3., 3.5, 1.6, 3.2, 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix315";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[multblock(m1)][wgtblock(wb1, 8)][wgtblock(wb2, 10)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[block][genblock(BS1j)][genblock(BS1k)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m1)][wgtblock(wb1, 6)][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR316*/
/* DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][MULT_BLOCK]
              REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][MULT_BLOCK]*/
void distrmix316()
{
    #define AN1 33
    #define AN2 44
    #define AN3 55
    int m1 = 3, m2 = 11, m3 = 5;
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb1[7] = {3., 2.5, 2., 4., 2.5, 2.0, 3.5};
    double wb2[8] = {4., 3., 2.5, 2., 2., 3., 3.5, 2.6};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix316";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb1, 7)][wgtblock(wb2, 8)][multblock(m3)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[genblock(BS1i)][genblock(BS1j)][block])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[multblock(m1)][wgtblock(wb1, 7)][multblock(m3)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR317*/
/* DISTRIBUTE arrA3[GEN_BLOCK][*][GEN_BLOCK]
              REDISTRIBUTE [MULT_BLOCK][WGT_BLOCK][*]
              REDISTRIBUTE [*][GEN_BLOCK][BLOCK]*/
void distrmix317()
{
    #define AN1 12
    #define AN2 16
    #define AN3 12
    int m1 = 2, m2 = 4, m3 = 3;
    int *BS1i, *BS1j, *BS2i;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(1), AN2, 1, &BS2i);
    genBlocksAxis(dvmh_get_num_procs(2), AN3, 1, &BS1j);
    double wb[8] = {2., 1., 2.5, 3., 4., 3., 3.5, 4.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix317";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[genblock(BS1i)][*][genblock(BS1j)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[multblock(m1)][wgtblock(wb, 8)][*])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[*][genblock(BS2i)][block])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS2i);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR318*/
/* DISTRIBUTE arrA3[GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
                REDISTRIBUTE [WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
                REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]*/
void distrmix318()
{
    #define AN1 8
    #define AN2 8
    #define AN3 8
    int *BS1i, *BS1j, *BS1k, *BS2i, *BS2j, *BS2k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS2i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS2j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS2k);
    double wb1[7] = {2.0, 1.2, 2.5, 1.4, 2.5, 1.3, 1.};
    double wb2[5] = {2., 1.3, 2., 1.0, 1.7};
    double wb3[6] = {2., 3., 1.3, 2., 1.0, 1.7};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix318";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[genblock(BS1i)][genblock(BS1j)][genblock(BS1k)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[wgtblock(wb1, 7)][wgtblock(wb2, 5)][wgtblock(wb3, 6)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[genblock(BS2i)][genblock(BS2j)][genblock(BS2k)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(BS2i);
    free(BS2j);
    free(BS2k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR319*/
/* DISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]
             REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]
             REDISTRIBUTE arrA3[WGT_BLOCK][WGT_BLOCK][WGT_BLOCK]*/
void distrmix319()
{
    #define AN1 12
    #define AN2 6
    #define AN3 10
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb1[6] = {2.0, 1.2, 2., 2.4, 2.3, 1.6};
    double wb2[5] = {2.4, 1.8, 2., 1.0, 1.7};
    double wb3[8] = {2., 3., 1.3, 2., 1.0, 1.7, 3., 4};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix319";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb1, 6)][wgtblock(wb2, 5)][wgtblock(wb3, 8)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[genblock(BS1i)][genblock(BS1j)][genblock(BS1k)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }
    #pragma dvm redistribute(A3[wgtblock(wb2, 5)][wgtblock(wb3, 6)][wgtblock(wb1, 6)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR320*/
/* DISTRIBUTE arrA3[BLOCK][GEN_BLOCK][GEN_BLOCK]
           REDISTRIBUTE arrA3[WGT_BLOCK][BLOCK][WGT_BLOCK]*/
void distrmix320()
{
    #define AN1 5
    #define AN2 7
    #define AN3 6
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb1[7] = {2.0, 2.2, 3., 2.4, 2.3, 1.6, 0.5};
    double wb2[6] = {2.4, 1.8, 3., 2.0, 1.7, 1.};
    double wb3[8] = {1., 3.5, 2.3, 2., 1.5, 1.7, 3., 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix320";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[block][genblock(BS1j)][genblock(BS1k)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[wgtblock(wb1, 7)][block][wgtblock(wb3, 8)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR321*/
/* DISTRIBUTE arrA3[WGT_BLOCK][BLOCK][WGT_BLOCK]
                REDISTRIBUTE [GEN_BLOCK][BLOCK][GEN_BLOCK]*/
void distrmix321()
{
    #define AN1 16
    #define AN2 16
    #define AN3 16
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb1[6] = {2.5, 3.6, 2.4, 2.3, 1.2, 0.5};
    double wb2[5] = {1.4, 2.8, 3., 3.0, 1.1};
    double wb3[7] = {1., 2.3, 2.2, 3.5, 1.7, 3., 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix321";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[wgtblock(wb1, 6)][block][wgtblock(wb3, 7)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[genblock(BS1i)][block][genblock(BS1k)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR322*/
/* DISTRIBUTE arrA3[GEN_BLOCK][BLOCK][GEN_BLOCK]
               REDISTRIBUTE [BLOCK][WGT_BLOCK][BLOCK]*/
void distrmix322()
{
    #define AN1 24
    #define AN2 16
    #define AN3 8
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb1[5] = {3.2, 2.4, 2.0, 1.0, 2.5};
    double wb2[4] = {2.1, 2.5, 3., 1.1};
    double wb3[6] = {2.3, 2.0, 3.5, 1.5, 3., 2.};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix322";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[genblock(BS1i)][block][genblock(BS1k)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[block][wgtblock(wb2, 4)][block])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR323*/
/* DISTRIBUTE arrA3[BLOCK][WGT_BLOCK][BLOCK]
                REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][*]*/
void distrmix323()
{
    #define AN1 8
    #define AN2 11
    #define AN3 11
    int *BS1i, *BS1j, *BS1k;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    double wb1[7] = {3.2, 2.4, 1., 2., 2.0, 1.0, 2.5};
    double wb2[6] = {3.1, 2.5, 4., 2.1, 2, 2};
    double wb3[6] = {1.2, 3.0, 2.4, 1.0, 3., 2.5};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix323";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[block][wgtblock(wb2, 6)][block])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[genblock(BS1i)][genblock(BS1j)][*])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR324*/
/* DISTRIBUTE arrA3[GEN_BLOCK][GEN_BLOCK][*]
                REDISTRIBUTE [*][WGT_BLOCK][WGT_BLOCK]
                REDISTRIBUTE [GEN_BLOCK][*][GEN_BLOCK]*/
void distrmix324()
{
    #define AN1 12
    #define AN2 12
    #define AN3 21
    int *BS1i, *BS1j, *BS1k, *BS2i, *BS2j;
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS1k);
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS2i);
    genBlocksAxis(dvmh_get_num_procs(2), AN3, 1, &BS2j);
    double wb1[7] = {2.0, 1.2, 2.5, 1.4, 2.5, 1.3, 1.};
    double wb2[5] = {2., 1.3, 2., 1.0, 1.7};
    double wb3[6] = {2., 3., 1.3, 2., 1.0, 1.7};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix324";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[genblock(BS1i)][genblock(BS1j)][*])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[*][wgtblock(wb2, 5)][wgtblock(wb3, 6)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }

    #pragma dvm redistribute(A3[genblock(BS2i)][*][genblock(BS2j)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS1k);
    free(BS2i);
    free(BS2j);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

/* ---------------------------------------------DISTR325*/
/* DISTRIBUTE arrA3 [*][GEN_BLOCK][GEN_BLOCK]
               REDISTRIBUTE [*][WGT_BLOCK][*]
               REDISTRIBUTE [GEN_BLOCK][GEN_BLOCK][GEN_BLOCK]*/
void distrmix325()
{
    #define AN1 7
    #define AN2 6
    #define AN3 7
    int *BS1i, *BS1j, *BS2i, *BS2j, *BS2k;
    genBlocksAxis(dvmh_get_num_procs(1), AN2, 1, &BS1i);
    genBlocksAxis(dvmh_get_num_procs(2), AN3, 1, &BS1j);
    genBlocksAxis(dvmh_get_num_procs(1), AN1, 1, &BS2i);
    genBlocksAxis(dvmh_get_num_procs(2), AN2, 1, &BS2j);
    genBlocksAxis(dvmh_get_num_procs(3), AN3, 1, &BS2k);
    double wb1[6] = {2., 1.3, 2., 1.0, 1.7, 1};
    double wb2[10] = {2.0, 1.2, 2.5, 1.0, 2.5, 1.3, 1., 3., 2., 1.};
    double wb3[6] = {2., 2., 4., 1.3, 2., 1.7};
    #pragma dvm array
    int (*A3)[AN2][AN3];
    char tname[] = "distrmix325";

    erri = ER;

    A3 = malloc(AN1 * AN2 * AN3 * sizeof(int));
    #pragma dvm redistribute(A3[*][genblock(BS1i)][genblock(BS1j)])

    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] = i*NL/10 + j*NL/100 + k;
    }

    #pragma dvm redistribute(A3[*][wgtblock(wb2, 10)][*])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    A3[i][j][k] += 1;
    }

    #pragma dvm redistribute(A3[genblock(BS2i)][genblock(BS2j)][genblock(BS2k)])
    #pragma dvm region
    {
        #pragma dvm parallel([i][j][k] on A3[i][j][k]) reduction(min(erri)), cuda_block(256)
        for (i = 0; i < AN1; i++)
            for (j = 0; j < AN2; j++)
                for (k = 0; k < AN3; k++)
                    if (A3[i][j][k] != i*NL/10 + j*NL/100 + k + 1)
                        erri = Min(erri, i*NL/10 + j*NL/100 + k + 1);
    }

    #pragma dvm get_actual(erri)
    if (erri == ER)
        ansyes(tname);
    else
        ansno(tname);
    free(BS1i);
    free(BS1j);
    free(BS2i);
    free(BS2j);
    free(BS2k);
    free(A3);
    #undef AN1
    #undef AN2
    #undef AN3
}

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

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