/*Copyright (C) 1992, 1995 by Thomas Glen Smith. All Rights Reserved.*/
/* deal APL2 V1.0.0 ****************************************************
* Deal(m,n) returns a vector of length m by making m random selections *
* without replacement from indxsub(n). *
***********************************************************************/
#define INCLUDES APLCB
#include "includes.h"
Aplcb deal(left,rite)
Aplcb left,rite;
{
Endoper; Errstop; Getcb; Indxsub; Iroll; Matchok;
extern int indxorg;
Aplcb out=NULL,wrk;
int count,i,*ip,j,*jp,k,range,unique;
if (!matchok(&left,&rite,APLINT))
return(NULL);
if (!(left->aplcount == 1 && rite->aplcount == 1))
return(errstop(41,left,rite,NULL));
if ((0>(count=*(left->aplptr.aplint))) ||
(0>(range=*(rite->aplptr.aplint))))
return(errstop(42,left,rite,NULL));
if (count > range)
return(errstop(43,left,rite,NULL));
out = getcb(NULL,count,APLINT+APLTEMP,1,NULL); /* vector out */
if (range > 500 || count <= range/16) { /* slow method */
for(k=0; k<count; k++) {
do {
j = iroll(range);
unique = 1;
for(i=0; (i<k) && unique; i++)
unique = j != *(out->aplptr.aplint+i);
} while (!unique);
*(out->aplptr.aplint+k) = j;
}
}
else { /* fast method */
wrk = indxsub(range);
for(i=0; i<count; i++) { /* shuffle the first count elements */
j = iroll(range);
k = *(ip = wrk->aplptr.aplint+i);
*ip = *(jp = wrk->aplptr.aplint+j-indxorg);
*jp = k;
}
ip = wrk->aplptr.aplint;
jp = out->aplptr.aplint;
for(i=0; i<count; i++)
*jp++ = *ip++;
endoper(wrk);
}
return(errstop(0,left,rite,out));
}