示例#1
0
文件: nestedness.c 项目: rforge/vegan
void i2rand(int *vec, int imax)
{
    vec[0] = IRAND(imax);
    do {
	vec[1] = IRAND(imax);
    } while (vec[1] == vec[0]);
}
示例#2
0
SEXP do_rcfill(SEXP n, SEXP rs, SEXP cs)
{
    int nrow = length(rs), ncol = length(cs), nmat = asInteger(n);
    int *rfill, *cfill, *rind, *cind;
    int rlen, clen, i, j, k, offset;

    if(TYPEOF(rs) != INTSXP)
	rs = coerceVector(rs, INTSXP);
    PROTECT(rs);
    if(TYPEOF(cs) != INTSXP)
	cs = coerceVector(cs, INTSXP);
    PROTECT(cs);
    int *rowsum = INTEGER(rs);
    int *colsum = INTEGER(cs);
    
    rfill = (int *) R_alloc(nrow, sizeof(int));
    cfill = (int *) R_alloc(ncol, sizeof(int));
    rind = (int *) R_alloc(nrow, sizeof(int));
    cind = (int *) R_alloc(ncol, sizeof(int));
    SEXP out = PROTECT(alloc3DArray(INTSXP, nrow, ncol, nmat));
    int *x = INTEGER(out);
    memset(x, 0, nmat * nrow * ncol * sizeof(int));

    /* collect matrices */
    GetRNGstate();
    for (k = 0; k < nmat; k++) {
	offset = k * nrow * ncol;
	/* initialize fills (0) and indices (0..n) */
	for (i = 0, rlen = -1; i < nrow; i++) {
	    if (rowsum[i] > 0) /* skip empty rows */
		rind[++rlen] = i;
	    rfill[i] = 0;
	}
	for (j = 0, clen = -1; j < ncol; j++) {
	    if (colsum[j] > 0)
		cind[++clen] = j;
	    cfill[j] = 0;
	}
	/* items 0..rlen/clen of rind/cind have the indices of
	 * rows/columns which still can be filled. When the row/column
	 * gets full, replace its index with the last index and reduce
	 * rlen/clen by one */
	while (rlen >= 0) {
	    i = IRAND(rlen);
	    j = IRAND(clen);
	    x[offset + rind[i] + nrow * cind[j]]++;
	    if (++rfill[rind[i]] >= rowsum[rind[i]])
		rind[i] = rind[rlen--];
	    if (++cfill[cind[j]] >= colsum[cind[j]])
		cind[j] = cind[clen--];
	}
    }
    PutRNGstate();
    UNPROTECT(3);
    return out;
}
示例#3
0
static void get2x2(int len, int nr, int *acbd)
{
    int i0, j0, i, j;
    acbd[0] = IRAND(len); /* a */
    i0 = acbd[0] % nr;
    j0 = acbd[0] / nr;
    do {
        acbd[3] = IRAND(len); /* d */
        i = acbd[3] % nr;
        j = acbd[3] / nr;
    } while (i == i0 || j == j0);
    acbd[1] = i + j0 * nr; /* c */
    acbd[2] = i0 + j * nr; /* b */
}
示例#4
0
static void swap(int *m, int *nr, int *nc, int *thin)
{

    int i, a, b, c, d, row[2], col[2], nr1 = (*nr) - 1, nc1 = (*nc) -1,
	n1 = (*nr) * (*nc) - 1;
    size_t intcheck;

    /* Get and Put RNG in calling C function */
    /* GetRNGstate(); */

    for (i=0, intcheck=0; i < *thin; i++) {
	for(;;) {
	    if (intcheck % 10000 == 9999)
		R_CheckUserInterrupt();
	    intcheck++;
	    /* see trialswap & quasiswap for the logic */
	    a = IRAND(n1);
	    row[0] = a % (*nr);
	    col[0] = a / (*nr);
	    do {row[1] = IRAND(nr1);} while (row[1] == row[0]);
	    c = INDX(row[1], col[0], *nr);
	    /* bail out before next row if non-swappable */
	    if (m[a] == m[c])
		continue;
	    do {col[1] = IRAND(nc1);} while (col[1] == col[0]);
	    b = INDX(row[0], col[1], *nr);
	    d = INDX(row[1], col[1], *nr);
	    /* if we are here m[a] != m[c], and only three elements
	       need be tested for the unique matrix -- start from
	       tests that fail most likely */
	    if (m[d] == 1 && m[a] == 1 && m[b] == 0) {
		m[a] = 0;
		m[d] = 0;
		m[b] = 1;
		m[c] = 1;
		break;
	    } 
	    if (m[b] == 1 && m[c] == 1 && m[d] == 0) {
		m[a] = 1;
		m[d] = 1;
		m[b] = 0;
		m[c] = 0;
		break;
	    }
	}
    }
    /* PutRNGstate(); */
}
示例#5
0
static void trialswap(int *m, int *nr, int *nc, int *thin)
{
    int i, a, b, c, d, row[2], col[2];

    /* Get and Set RNG in calling C function */
    /* GetRNGstate(); */

    for (i=0; i < *thin; i++) {
	/* get corner item m[a] and its row and column index */
	a = IRAND((*nr) * (*nc) - 1);
	row[0] = a % (*nr);
	col[0] = a / (*nr);
	/* get its side-by-side neighbour in a different row */
	do {row[1] = IRAND((*nr) - 1);} while (row[1] == row[0]);
	c = INDX(row[1], col[0], *nr);
	/* not swappable if neighbours are identical: bail out at
	   probability (1-f)^2 + f^2 where f is the relative column
	   fill */
	if (m[a] == m[c])
	    continue;
	/* get second col and its items */
	do {col[1] = IRAND((*nc) - 1);} while (col[1] == col[0]);
	b = INDX(row[0], col[1], *nr);
	d = INDX(row[1], col[1], *nr);
        /* there are 16 possible matrices, but only two can be
	 * swapped. Find signature of each matrix with bitwise shift
	 * and OR. */
	switch(m[a] | m[b] << 1 | m[c] << 2 | m[d] << 3) {
	case 6: /* 0110 -> 1001 */
	    m[a] = 1;
	    m[b] = 0;
	    m[c] = 0;
	    m[d] = 1;
	    break;
	case 9: /* 1001 -> 0110 */
	    m[a] = 0;
	    m[b] = 1;
	    m[c] = 1;
	    m[d] = 0;
	    break;
	default:
	    break;
	}
    }

    /* PutRNGstate(); */
}
示例#6
0
static void curveball(int *m, int *nr, int *nc, int *thin, int *uniq)
{
    int row[2], i, j, jind, ind, nsp1, nsp2, itmp, tmp;

    /* Set RNG in calling C code */
    /* GetRNGstate(); */

    for (i = 0; i < *thin; i++) {
	/* Random sites */
	I2RAND(row, (*nr)-1);
	/* uniq is a vector of unique species for a random pair of
	   rows, It need not be zeroed between thin loops because ind
	   keeps track of used elements. */
	for (j = 0, ind = -1, nsp1 = 0, nsp2 = 0; j < (*nc); j++) {
	    jind = j * (*nr);
	    if (m[row[0] + jind] > 0 && m[row[1] + jind] == 0) {
		uniq[++ind] = j;
		nsp1++;
	    }
	    if (m[row[1] + jind] > 0 && m[row[0] + jind] == 0) {
		uniq[++ind] = j;
		nsp2++;
	    }
	}
	/* uniq contains indices of unique species: shuffle these and
	 * allocate nsp1 first to row[0] and the rest to row[1] */
	if (nsp1 > 0 && nsp2 > 0) { /* something to swap? */
	    for (j = ind; j >= nsp1; j--) {
		itmp = IRAND(j);
		tmp = uniq[j];
		uniq[j] = uniq[itmp];
		uniq[itmp] = tmp;
	    }
	    for (j = 0; j < nsp1; j++) {
		m[INDX(row[0], uniq[j], *nr)] = 1;
		m[INDX(row[1], uniq[j], *nr)] = 0;
	    }
	    for (j = nsp1; j <= ind; j++) {
		m[INDX(row[0], uniq[j], *nr)] = 0;
		m[INDX(row[1], uniq[j], *nr)] = 1;
	    }
	}
    }

    /* PutRNGstate(); */
}
示例#7
0
// TODO this is just my console test app, clean up this mess!
int main(int argc, char *argv[]) {
	(void) argc;
	(void) argv;

	VIDEO_Init();
	PAD_Init();

	SYS_SetResetCallback(stmcb);
	SYS_SetPowerCallback(stmcb);

	gfx_video_init(NULL);
	gfx_init();
	gfx_con_init(NULL);

	printf("startup\n");

	gfx_tex_t tex;
	memset(&tex, 0, sizeof(gfx_tex_t));
	if (!gfx_tex_init(&tex, GFX_TF_RGB565, 0, 16, 16)) {
		printf("failed to init tex!\n");
		return 1;
	}
	memset(tex.pixels, 0xe070, 16 * 16 * 2);
	gfx_tex_flush_texture(&tex);

	gfx_screen_coords_t coords_bg;
	gfx_coords(&coords_bg, &tex, GFX_COORD_FULLSCREEN);

	srand(gettime());

	u64 frame = 0;
	u16 b;
	bool pf = false;
	u32 retries;
	u8 fg = 7, bg = 0;
	u32 i;
	char buf[32];

	while (!quit) {
		b = 0;
		if (PAD_ScanPads() & 1) {
			b = PAD_ButtonsDown(0);
		
			gfx_con_set_alpha(0xff - PAD_TriggerR(0), 0xff - PAD_TriggerL(0));
		}

		if (b & PAD_BUTTON_A)
			quit = true;

		if (b & PAD_BUTTON_B)
			pf = !pf;

		if (b & PAD_BUTTON_X)
			printf(S_RED("Hello") " " S_BLUE("world") "!\n");

		if (pf) {
			for (i = 0; i < gfx_con_get_columns() * gfx_con_get_rows(); ++i) {
				printf(CON_ESC "%u;1m" CON_ESC "%um%c", 30 + IRAND(8),
						40 + IRAND(8), 0x20 + IRAND(16 * 9));
			}
		}

		if (b & PAD_TRIGGER_Z) {
			gfx_con_reset();
			fg = 7;
			bg = 0;
		}

		if (b & 15) {
			if (b & PAD_BUTTON_LEFT) {
				fg = (fg + 8 - 1) % 8;
				gfx_con_set_foreground_color(fg, true);
			}
			if (b & PAD_BUTTON_RIGHT) {
				fg = (fg + 1) % 8;
				gfx_con_set_foreground_color(fg, true);
			}
			if (b & PAD_BUTTON_UP) {
				bg = (bg + 8 - 1) % 8;
				gfx_con_set_background_color(bg, false);
			}
			if (b & PAD_BUTTON_DOWN) {
				bg = (bg + 1) % 8;
				gfx_con_set_background_color(bg, false);
			}

			printf("new color selected: %u %u\n", fg, bg);
		}

		sprintf(buf, "frame: %llu", frame);
		gfx_con_save_attr();
		gfx_con_set_pos(1, gfx_con_get_columns() - strlen(buf) + 1);
		printf(CON_COLRESET "%s", buf);
		gfx_con_restore_attr();

		retries = 0;
		while (!gfx_frame_start()) {
			retries++;
			if (retries > 1000) {
				printf("gx hates you\n");
				gfx_frame_abort();
				return -1;
			}

			usleep(50);
		}

		gfx_draw_tex(&tex, &coords_bg);
		gfx_con_draw();

		gfx_frame_end();

		frame++;
	}

	printf("shutdown\n");

	gfx_tex_deinit(&tex);
	gfx_con_deinit();
	gfx_deinit();
	gfx_video_deinit();

	return 0;
}
示例#8
0
void OrganizedData::process(RawData* raw, int nBlock, double pTest, int nSupport)
{
    int nData = raw->nData, nDim = raw->nDim - 1;

    this->nSupport = nSupport;
    this->nBlock   = nBlock;
    this->nDim     = nDim;

    train   = field<mat>(nBlock,2);
    test    = field<mat>(nBlock,2);
    support = field<mat>(1,2);

    mat xm(nSupport,nDim),
        ym(nSupport,1);

    vec mark(nData); mark.fill(0);

    printf("Randomly selecting %d supporting point ...\n", nSupport);

    for (int i = 0; i < nSupport; i++)
	{
		int pos = IRAND(0, nData - 1);
		while (mark[pos] > 0)
			pos = IRAND(0, nData - 1);
		mark[pos] = 1;
		for (int j = 0; j < nDim; j++)
			xm(i, j) = raw->X(pos,j);
		ym(i,0) = raw->X(pos,nDim);
	}

	support(0,0) = xm; xm.clear();
	support(0,1) = ym; ym.clear();

    cout << "Partitioning the remaining data into " << nBlock << " cluster using K-Mean ..." << endl;

    vvd _remain;

    for (int i = 0; i < nData; i++) if (!mark(i))
    {
        rowvec R = raw->X.row(i);
        _remain.push_back(r2v(R));
    }

    mat remaining = v2m(_remain);

    mark.clear();

    RawData* remain = new RawData(remaining);

    KMean* partitioner = new KMean(remain);

    Partition* clusters = partitioner->cluster(nBlock);

    cout << "Packaging training/testing data points into their respective cluster" << endl;

    for (int i = 0; i < nBlock; i++)
    {
        cout << "Processing block " << i + 1 << endl;

        int bSize   = (int) clusters->member[i].size(),
            tSize   = (int) floor(bSize * pTest),
            pos     = 0,
            counter = 0;

        mark = vec(bSize); mark.fill(0);

        if (bSize > tSize)  // if we can afford to draw tSize test points from this block without depleting it ...
        {
            mat xt(tSize,nDim),
                yt(tSize,1);

            for (int j = 0; j < tSize; j++)
            {
                pos = IRAND(0, bSize - 1);
				while (mark[pos] > 0)
					pos = IRAND(0, bSize - 1);
				mark[pos] = 1; pos = clusters->member[i][pos];

				for (int t = 0; t < nDim; t++)
					xt(j, t) = remain->X(pos,t);
				yt(j,0) = remain->X(pos,nDim);
            }

            bSize  -= tSize;
            nTest  += tSize;

            test(i,0) = xt; xt.clear();
            test(i,1) = yt; yt.clear();
        }

        nTrain += bSize;

        mat xb(bSize,nDim),
            yb(bSize,1);

        //cout << remain->X.n_rows << endl;

        for (int j = 0; j < (int)mark.n_elem; j++) if (mark[j] < 1)
        {
            for (int t = 0; t < nDim; t++) {
                xb(counter,t) = remain->X(clusters->member[i][j],t);
            }
            yb(counter++,0) = remain->X(clusters->member[i][j],nDim);
        }

        train(i,0) = xb; xb.clear();
        train(i,1) = yb; yb.clear();

        mark.clear();

        printf("Done ! nData[%d] = %d, nTrain[%d] = %d, nTest[%d] = %d .\n", i, (int) clusters->member[i].size(), i, train(i,0).n_rows, i, (int) test(i,0).n_rows);
    }
}
示例#9
0
static void quasiswap(int *m, int *nr, int *nc, int *thin)
{
    int i, n, mtot, ss, row[2], col[2], n1, nr1, nc1, a, b, c, d;
    size_t intcheck;

    nr1 = (*nr) - 1;
    nc1 = (*nc) - 1;

    /* Get matrix total 'mtot' and sum-of-squares 'ss' */

    n = (*nr) * (*nc);
    for (i = 0, mtot = 0, ss = 0; i < n; i++) {
	mtot += m[i];
	ss += m[i] * m[i];
    }
    n1 = n - 1;

    /* Get R RNG in the calling C function */
    /* GetRNGstate(); */

    /* Quasiswap while there are entries > 1 */

    intcheck  = 0; /* check interrupts */
    while (ss > mtot) {
	for (i = 0; i < *thin; i++) {
	    /* first item and its row & column indices */
	    a = IRAND(n1);
	    row[0] = a % (*nr);
	    col[0] = a / (*nr);
	    /* neighbour from the same col but different row */
	    do {row[1] = IRAND(nr1);} while (row[1] == row[0]);
	    c = INDX(row[1], col[0], *nr);
	    /* if neighbours are both zero, cannot be quasiswapped
	       (probability (1-f)^2 with relative col fill f) */
	    if (m[c] == 0 && m[a] == 0)
		continue;
	    /* second col */
	    do {col[1] = IRAND(nc1);} while (col[1] == col[0]);
	    b = INDX(row[0], col[1], *nr);
	    d = INDX(row[1], col[1], *nr);
	    /* m[a] has 50% chance of being > 0, m[d] less, so have it first */
	    if (m[d] > 0 && m[a] > 0 && m[a] + m[d] - m[b] - m[c] >= 2) {
		ss -= 2 * (m[a] + m[d] - m[b] - m[c] - 2);
		m[a]--;
		m[d]--;
		m[b]++;
		m[c]++;
	    } else if (m[c] > 0 && m[b] > 0 &&
		       m[b] + m[c] - m[a] - m[d] >= 2) {
		ss -= 2 * (m[b] + m[c] - m[a] - m[d] - 2);
		m[a]++;
		m[d]++;
		m[b]--;
		m[c]--;
	    }
	}
	/* interrupt? */
	if (intcheck % 10000 == 9999)
	    R_CheckUserInterrupt();
	intcheck++;
    }

    /* Set R RNG in the calling function */
    /* PutRNGstate(); */
}
示例#10
0
static void greedyqswap(int *m, int nr, int nc, int thin, int *big)
{
    int i, j, n, biglen, pick, row[2], col[2], nr1, nc1, a, b, c, d;
    size_t intcheck;

    nr1 = nr - 1;
    nc1 = nc - 1;

    /* big contains indices of cells > 1 */

    n = nr * nc;
    for (i = 0, biglen = -1; i < n; i++) {
	if (m[i] > 1)
	    big[++biglen] = i;
    }

    intcheck  = 0; /* check interrupts */
    while (biglen > -1) {
	for (i = 0; i < thin; i++) {
	    /* pick one item to the m[a] corner */
	    if (i == 0) { /* greedy! */
		pick = IRAND(biglen);
		a = big[pick];
	    } else { /* thin! */
		a = IRAND(n-1);
	    }
	    row[0] = a % nr;
	    col[0] = a / nr;
	    /* get the second item in the first column */
	    do {row[1] = IRAND(nr1);} while (row[1] == row[0]);
	    c = INDX(row[1], col[0], nr);
	    /* unswappable if the first row is all zeros */
	    if (m[a] == 0 && m[c] == 0)
		continue;
	    /* second column, third and fourth items */
	    do {col[1] = IRAND(nc1);} while (col[1] == col[0]);
	    b = INDX(row[0], col[1], nr);
	    d = INDX(row[1], col[1], nr);
	    if (m[d] > 0 && m[a] > 0 && m[a] + m[d] - m[b] - m[c] >= 2) {
		m[a]--;
		m[d]--;
		m[b]++;
		m[c]++;
		/* Update big & biglen. a & d were decremented, and if
		 * they now are 1, they are removed from big. We know
		 * pick for a, but the location of d must be searched
		 * in big. b & c were incremented and if they now are
		 * 2, they must be added to big. */
		if (m[a] == 1) {
		    if (i == 0) { /* not thinning: know the pick */
			big[pick] = big[biglen--];
		    } else { /* thinning: must search in big */
			for (j = 0; j <= biglen; j++) {
			    if (a == big[j]) {
				big[j] = big[biglen--];
				break;
			    }
			}
		    }
		}
		if (m[d] == 1) {
		    for (j = 0; j <= biglen; j++) {
			if (d == big[j]) {
			    big[j] = big[biglen--];
			    break;
			}
		    }
		}
		if (m[b] == 2)
		    big[++biglen] = b;
		if (m[c] == 2)
		    big[++biglen] = c;
	    } else if (m[c] > 0 && m[b] > 0 &&
		       m[b] + m[c] - m[a] - m[d] >= 2) {
		m[a]++;
		m[d]++;
		m[b]--;
		m[c]--;
		/* update is mirror operation of the one above */
		if (m[b] == 1) {
		    for (j = 0; j <= biglen; j++) {
			if (b == big[j]) {
			    big[j] = big[biglen--];
			    break;
			}
		    }
		}
		if (m[c] == 1) {
		    for (j = 0; j <= biglen; j++) {
			if (c == big[j]) {
			    big[j] = big[biglen--];
			    break;
			}
		    }
		}
		if (m[a] == 2)
		    big[++biglen] = a;
		if (m[d] == 2)
		    big[++biglen] = d;
	    }
	}
	/* interrupt? */
	if (intcheck % 10000 == 9999)
	    R_CheckUserInterrupt();
	intcheck++;
    }
}
示例#11
0
static void boostedqswap(int *m, int nr, int nc, int *work)
{
    int i, j, k, n = nr * nc, tot, ss, isp1, isp2, isp,
	row[2], intcheck;

    /* ss (sum of squares) is equal to tot when all entries are 1 or
     * 0 */
    for(i = 0, tot = 0, ss = 0; i < n; i++) {
	tot += m[i];
	ss += m[i] * m[i];
    }
    /* quasiswap to binary matrix */
    intcheck = 0;
    while(ss > tot) {
	I2RAND(row, nr-1);
	/* find pairs that can be swapped individually */
	for(j = 0, isp1 = -1, isp2 = -1; j < nc; j++) {
	    k = j * nr;
	    if (m[row[0] + k] == m[row[1] + k])
		continue;
	    /* must be different: first nc elements of work contains
	     * cases where first row is larger, and elements after nc
	     * where first is smaller */
	    if (m[row[0] + k] > m[row[1] + k])
		work[++isp1] = j;
	    else {
		isp2++;
		work[isp2 + nc] = j;
	    }
	}
	/* quasiswap min(isp1, isp2) + 1 elements */
	if (isp1 > -1 && isp2 > -1) { /* something to quasiswap? */
	    isp = (isp1 < isp2) ? isp1 : isp2;
#if BOOSTSAMPLE
	    /* If we swap all that we can (up to isp), species move in
	     *  blocks and retain their co-occurrence patterns. In
	     *  extreme cases (isp1 == isp2, no >1 values), picking
	     *  same two rows in succession will be idempotent and
	     *  reinstate the initial pattern. If we only swap a
	     *  random number of possible swaps, we add randomness. If
	     *  we think that we do not need to add randomness because
	     *  we start from random configuration and only want to
	     *  reduce >1 values to 1, we can swap all, and run about
	     *  2x faster. */
	    isp = IRAND(isp);
#endif
	    /* partial shuffle to discard elements > isp */
	    if (isp1 > isp) {
		for(j = isp1; j > isp; j--) {
		    k = IRAND(j);
		    work[k] = work[j]; /* throw away extra species */
		}
	    }
	    if (isp2 > isp) {
		for (j = isp2; j > isp; j--) {
		    k = IRAND(j);
		    work[k + nc] = work[j + nc];
		}
	    }
	    /* quasiswap when row[0] > row[1] */
	    for(j = 0; j <= isp; j++) {
		k = work[j] * nr;
		ss -= 2 * (m[row[0] + k] - m[row[1] + k]) - 2;
		m[row[0] + k]--;
		m[row[1] + k]++;
	    }
	    /* ... and when row[0] < row[1] */
	    for(j = 0; j <= isp; j++) {
		k = work[j + nc] * nr;
		ss -= 2 * (m[row[1] + k] - m[row[0] + k]) - 2;
		m[row[0] + k]++;
		m[row[1] + k]--;
	    }
	}
	if (intcheck % 10000 == 9999)
	    R_CheckUserInterrupt(); /* may not terminate at all */
	intcheck++;
    } /* while(ss > tot) */
}
示例#12
0
static void backtrack(int *out, int *rowsum, int *colsum, int fill,
		      int nr, int nc, int *rfill, int *cfill, int *ind)
{
    int tmp, i, j, k, ir, ic;
    int izero = nr * nc - 1, ielig = nr * nc - 1, npick = 0, oldpick = 0,
	ndrop = 1, dropouts[BACKSTEP], idrop = 0, lastpick = 0;

    /* initialize */
    for(i = 0; i < nr * nc; i++)
	ind[i] = i;
    memset(rfill, 0, nr * sizeof(int));
    memset(cfill, 0, nc * sizeof(int));

    /* check for empty rows/columns and move their indices from eligible */

    for (ir=0; ir < nr; ir++)
	if (rowsum[ir] <= 0)
	    for (i = ielig; i > EMPTY; i--)
		if (ind[i] % nr == ir) {
		    SWAP(ind[i], ind[ielig]);
		    ielig--;
		}
    for (ic=0; ic < nc; ic++)
	if (colsum[ic] <= 0)
	    for (i = ielig; i > EMPTY; i--)
		if (ind[i] / nr == ic) {
		    SWAP(ind[i], ind[ielig]);
		    ielig--;
		}
    
    /* Start working */
    while(npick < fill) { /* outermost loop (placeholder) */
	/* fill */
#if LOUD
	Rprintf("\nFILL ");
#endif
	while(ielig > EMPTY) {
	    i = IRAND(ielig); /* eligible: always succeed */
#if LOUD
	    Rprintf("pick %d ", i);
#endif
	    ir = ind[i] % nr; /* row */
	    ic = ind[i] / nr; /* column */
	    npick++;
	    SWAP(ind[i], ind[ielig]); /* move after izero */
	    if (ielig < izero) {
		SWAP(ind[ielig], ind[izero]);
	    }
	    ielig--;
	    izero--;
	    /* update fills and move from eligible if marginal sum reached */
	    if (++rfill[ir] == rowsum[ir])
		for(i = ielig; i > EMPTY; i--)
		    if (ind[i] % nr == ir) {
#if LOUD
			Rprintf("ban %d ", i);
#endif
			SWAP(ind[i], ind[ielig]);
			ielig--;
		    }
	    if (++cfill[ic] == colsum[ic])
		for (i = ielig; i > EMPTY; i--)
		    if (ind[i] / nr == ic) {
#if LOUD
			Rprintf("ban %d ", i);
#endif
			SWAP(ind[i], ind[ielig]);
			ielig--;
		    }
	}
	/* get out */
#if LOUD
	if (npick != oldpick) Rprintf("\n*** PICKED %d ", npick);
#endif
	R_CheckUserInterrupt();
	if (npick == fill)
	    break;
	
#if RESET
	
	/* if we did worse than previously, undo: remove picked items
	 * and put back the ones removed as dropouts */

	if (npick < oldpick) {
#if LOUD
	    Rprintf("\nRESET ");
#endif
	    /* first items after izero were added in the last cycle --
	     * these should be removed except for the originally
	     * dropped items (dropouts) that should be kept */

	    lastpick = izero + ndrop - oldpick + npick;
	    for (i = izero+1; i <= lastpick; i++) {
		k = imatch(ind[i], dropouts, idrop+1);
		if (k == EMPTY)  { /* remove pick: not a dropout */
#if LOUD
		    Rprintf("drop %d ", i);
#endif
		    rfill[ind[i] % nr]--;
		    cfill[ind[i] / nr]--;
		    npick--;
		    izero++;
		    if (izero < i) {
			SWAP(ind[i], ind[izero]);
		    }
		} else { /* remove from dropouts */
#if LOUD
		    Rprintf("keep %d ", i);
#endif
		    dropouts[k] = dropouts[idrop--];
		}
	    }
	    
	    /* The dropouts are among first items of ind: search these and
	     * add back to picked. */

	    i = EMPTY;
	    while(idrop > EMPTY) {
		k = imatch(ind[++i], dropouts, idrop+1);
		if (k != EMPTY) { /* pick back this item */
#if LOUD
		    Rprintf("pick %d ", i);
#endif
		    rfill[ind[i] % nr]++;
		    cfill[ind[i] / nr]++;
		    SWAP(ind[i], ind[izero]);
		    izero--;
		    npick++;
		    dropouts[k] = dropouts[idrop--];
		}
	    }
	}

#endif /* RESET */
	
        /* backtrack: remove picked items and update marginal totals
	 * and see if any items become eligible. If 'npick' did not
	 * improve from the best 'oldpick', increase 'ndrop' up to
	 * BACKSTEP, and reset 'ndrop' to 1 if 'npick' improved.  */

	if (oldpick < npick) {
	    ndrop = 1;
	    oldpick = npick;
	} else if (ndrop < BACKSTEP && ndrop < npick) {
	    ndrop++;
	}
#if LOUD
	Rprintf("\nBACKTRACK %d: ", ndrop);
#endif
	for (j = 0, idrop = EMPTY; j < ndrop; j++) {
	    i = IRAND(npick-1) + izero + 1;
#if LOUD
	    Rprintf("%d ", i);
#endif
	    dropouts[++idrop] = ind[i]; /* save removed */
	    rfill[ind[i] % nr]--;
	    cfill[ind[i] / nr]--;
	    npick--;
	    ielig++;
	    izero++;
	    SWAP(ind[i], ind[izero]);
	    SWAP(ind[izero], ind[ielig]); /* if elig is EMPTY: move to ind[0] */
	}
	/* see what can be moved to eligible */
	for (i = izero; i > ielig; i--) {
	    ir = ind[i] % nr;
	    ic = ind[i] / nr;
	    if (rfill[ir] < rowsum[ir] && cfill[ic] < colsum[ic]) {
#if LOUD
		Rprintf("free %d ", i);
#endif
		ielig++;
		SWAP(ind[i], ind[ielig]);
	    }
	}
    }

    /* output */
    memset(out, 0, nr * nc * sizeof(int));
    /* put 1's in their places */
    for (i = izero+1; i < nr*nc; i++)
	out[ind[i]] = 1;
}