/* Main control of the folding mapping.
        1. This routine only folds the 3 true dimensions. T dimension (if in virtual node mode)
           is handled specifically in the caller of this routine.
        2. finished = perm_next( ndims, perm_array[ndims] )
           gets the next permutation. It returns 1 when there is no next permutation.
           For ndims = 3, the permutation sequence is
                0,1,2 --> 0,2,1 --> 1,0,2 --> 1,2,0 --> 2,0,1 --> 2,0,1 --> finished.
        3. fail = find_fold( dims1[ndims1], dims2[ndims2], fold[3][3] )
           searchs a folding schedule, the folding schedule is stored in matrix fold[3][3]
           e.g. fold[i][j] = 3 indicates to unfold dimension i onto dimension j.
           fold[i][i] has no meaning.
           For 3D case as here, there will be at most 2 non-zero, non-diagonal entries.
           Diagonal entries are useless here.
           Further more, when the 2 non-zero entries are in the same row, the virtual cartesian is
           unfolded from the row_id dimension onto the other dimensions in physical cartesian.
           when the 2 entries are in the same coloum, the virtual cartesian is actually
           folded from the physical cartesian.
        4. perform_fold( vir_coord[], phy_coord[], fold[3][3] )
           does the folding following the schedule given by fold[3][3].
 */
static int perm_dims_match( int nd1, int d1[], int c1[], int nd2, int d2[], int c2[] )
{
    int perm[3] = {0,1,2};
    int fold[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}};
    int fail, finished;
    int dd2[3], i;

    fail = 1;
    finished = 0;
    while( !finished )
    {
        for (i=0; i<3; i++) dd2[i] = d2[perm[i]];
        fail = find_fold( nd1, d1, nd2, dd2, fold );
        if (!fail) { break; }
        finished = perm_next( nd2, perm );
    }

    if (fail) return 1;

    perform_fold( nd1, d1, c1, nd2, d2, c2, perm, fold );

    return 0;
}
Example #2
0
File: enum.c Project: rdebath/sgt
void test_perm(int n)
{
    int a1[PERM_NMAX], a2[PERM_NMAX], aprev[PERM_NMAX], count[PERM_NMAX];
    int i, j, index, eindex;

#ifndef QUIET
    printf("perm enumeration tests, n=%d\n", n);
#endif

    eindex = 0;
    perm_first(a1, n);
    do {

	index = perm_to_index(a1, n);
	perm_from_index(a2, n, index);

#ifndef QUIET
	{
	    const char *sep;
	    putchar('{');
	    sep = "";
	    for (i = 0; i < n; i++) {
		printf("%s%d", sep, a1[i]);
		sep = ",";
	    }
	    printf("} -> %d -> {", index);
	    sep = "";
	    for (i = 0; i < n; i++) {
		printf("%s%d", sep, a2[i]);
		sep = ",";
	    }
	    printf("}\n");
	}
#endif

	/*
	 * Check that a1 contains the numbers 0..n-1 in some order.
	 */
	for (i = 0; i < n; i++)
	    count[i] = 0;
	for (i = 0; i < n; i++) {
	    LE(0, a1[i]);
	    LT(a1[i], n);
	    EQ(count[i], 0);
	    count[i]++;
	}

	/*
	 * Check that a1 is lexicographically strictly greater than
	 * the previous permutation, if any.
	 */
	if (eindex > 0) {
	    for (i = 0; i < n; i++) {
		LE(aprev[i], a1[i]);
		if (aprev[i] < a1[i])
		    break;
	    }
	    LT(i, n);
	}
	memcpy(aprev, a1, sizeof(*a1) * n);

	/*
	 * Check that perm_to_index got the answer right.
	 */
	EQ(index, eindex);

	/*
	 * And perm_from_index.
	 */
	EQ(memcmp(a2, a1, sizeof(*a1)*n), 0);

	eindex++;
    } while (perm_next(a1, n));

#ifndef QUIET
    printf("perm discontinuous tests, n=%d\n", n);
#endif

    /*
     * Now do a bunch of these tests again, with the input
     * permutation _not_ being simple increasing integers.
     */
    eindex = 0;
    for (i = 0; i < n; i++)
	a1[i] = i + i*i + i*i*i;

    do {

	index = perm_to_index(a1, n);

#ifndef QUIET
	{
	    const char *sep;
	    putchar('{');
	    sep = "";
	    for (i = 0; i < n; i++) {
		printf("%s%d", sep, a1[i]);
		sep = ",";
	    }
	    printf("} -> %d\n", index);
	}
#endif

	/*
	 * Check that a1 contains the right numbers in some order.
	 */
	for (i = 0; i < n; i++)
	    count[i] = 0;
	for (i = 0; i < n; i++) {
	    for (j = 0; j < n; j++)
		if (a1[i] == j + j*j + j*j*j)
		    break;
	    LT(j, n);
	    EQ(count[j], 0);
	    count[j]++;
	}

	/*
	 * Check that a1 is lexicographically strictly greater than
	 * the previous permutation, if any.
	 */
	if (eindex > 0) {
	    for (i = 0; i < n; i++) {
		LE(aprev[i], a1[i]);
		if (aprev[i] < a1[i])
		    break;
	    }
	    LT(i, n);
	}
	memcpy(aprev, a1, sizeof(*a1) * n);

	/*
	 * Check that perm_to_index got the answer right.
	 */
	EQ(index, eindex);

	eindex++;
    } while (perm_next(a1, n));

    EQ(eindex, perm_count(n));
}