#include <assert.h>#include "shuffle.h" voidshuffle_init(Shuffle *s, int (*rndrange)(int max_excluding), int total, int first){ assert(first < total && total > 0); s->m = s->n = total; s->i = 0; s->xi = s->x0 = first; if(total < 4){ s->a = 1; s->c = 3; s->m = 7; return; } s->m += 1; s->m |= s->m >> 1; s->m |= s->m >> 2; s->m |= s->m >> 4; s->m |= s->m >> 8; s->m |= s->m >> 16; s->a = 1 + rndrange(s->m/4)*4; /* 1 ≤ a < m && a mod 4 = 1 */ s->c = 3 + rndrange((s->m-2)/2)*2; /* 3 ≤ c < m-1 && c mod 2 = 1 */} voidshuffle_resize(Shuffle *s, int total){ assert(total > 0); s->n = total;} static intnext(Shuffle *s){ int res; res = s->xi; if(s->n < 2){ /* if it's less than two items, just use the first one (if any) */ s->x0 = s->xi = s->i = 0; return 0; }else if(s->x0 >= s->n){ /* if items were removed up to this one -- update for a period */ s->x0 = 0; } for(;;){ s->xi = (s->a*s->xi + s->c) & s->m; if(s->xi < s->n){ s->i++; if(s->xi == s->x0) s->i = 0; break; } } return res;} intshuffle_one(Shuffle *s, int index){ assert(index >= 0); if(s->n < 1 || index < 0) return 0; index %= s->n; while(s->i < s->n && s->i != index) next(s); return next(s);}
#include <assert.h>
#include "shuffle.h"
void
shuffle_init(Shuffle *s, int (*rndrange)(int max_excluding), int total, int first)
{
assert(first < total && total > 0);
s->m = s->n = total;
s->i = 0;
s->xi = s->x0 = first;
if(total < 4){
s->a = 1;
s->c = 3;
s->m = 7;
return;
}
s->m += 1;
s->m |= s->m >> 1;
s->m |= s->m >> 2;
s->m |= s->m >> 4;
s->m |= s->m >> 8;
s->m |= s->m >> 16;
s->a = 1 + rndrange(s->m/4)*4; /* 1 ≤ a < m && a mod 4 = 1 */
s->c = 3 + rndrange((s->m-2)/2)*2; /* 3 ≤ c < m-1 && c mod 2 = 1 */
}
void
shuffle_resize(Shuffle *s, int total)
{
assert(total > 0);
s->n = total;
}
static int
next(Shuffle *s)
{
int res;
res = s->xi;
if(s->n < 2){
/* if it's less than two items, just use the first one (if any) */
s->x0 = s->xi = s->i = 0;
return 0;
}else if(s->x0 >= s->n){
/* if items were removed up to this one -- update for a period */
s->x0 = 0;
}
for(;;){
s->xi = (s->a*s->xi + s->c) & s->m;
if(s->xi < s->n){
s->i++;
if(s->xi == s->x0)
s->i = 0;
break;
}
}
return res;
}
int
shuffle_one(Shuffle *s, int index)
{
assert(index >= 0);
if(s->n < 1 || index < 0)
return 0;
index %= s->n;
while(s->i < s->n && s->i != index)
next(s);
return next(s);
}