Metropoli BBS
VIEWER: deal.c MODE: TEXT (ASCII)
/*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));
}
[ RETURN TO DIRECTORY ]