void i2rand(int *vec, int imax) { vec[0] = IRAND(imax); do { vec[1] = IRAND(imax); } while (vec[1] == vec[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; }
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 */ }
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(); */ }
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(); */ }
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(); */ }
// 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; }
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); } }
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(); */ }
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++; } }
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) */ }
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; }