⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zrand.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 5 页
字号:
 *		a = 6316878969928993981 *		c = 1363042948800878693 * * As we stated before, we must map 0 ==> 0.  The linear congruence * generator would normally map as follows: * *	0 ==> 1363042948800878693	(0 ==> c) * * We can determine which 0<=y<m will produce a given value z by inverting the * linear congruence generator: * *	z = (a*y + c) % m * *	z = a*y % m + c % m * *	z-c % m = a*y % m * *	(z-c % m) * minv(a,m) = (a*y % m) * minv(a,m) *		[minv(a,m) is the multiplicative inverse of a % m] * *	((z-c % m) * minv(a,m)) % m = ((a*y % m) * minv(a,m)) % m * *	((z-c % m) * minv(a,m)) % m = y % m *		[a % m * minv(a,m) = 1 % m by definition] * *	((z-c) * minv(a,m)) % m = y % m * *	((z-c) * minv(a,m)) % m = y *		[we defined y to be 0<=y<m] * * To determine which value maps back into 0, we let z = 0 and compute: * *	((0-c) * minv(a,m)) % m ==> 10239951819489363767 * * and thus we find that the congruence generator would also normally map: * *	10239951819489363767 ==> 0 * * To overcome this, and preserve the 1-to-1 and onto map, we force: * *	0 ==> 0 *	10239951819489363767 ==> 1363042948800878693 * * To repeat, this function converts a values into a seed value.  With the * except of 'seed == 0', every value is mapped into a unique seed value. * This mapping need not be complex, random or secure.	All we attempt * to do here is to allow humans who pick small or successive seed values * to obtain reasonably different sequences from the generators below. * * NOTE: This is NOT a pseudo random number generator.	This function is *	 intended to be used internally by ss100rand() and sshufrand(). */static voidrandreseed64(ZVALUE seed, ZVALUE *res){	ZVALUE t;		/* temp value */	ZVALUE chunk;		/* processed 64 bit chunk value */	ZVALUE seed64;		/* seed mod 2^64 */	HALF *v64;		/* 64 bit array of HALFs */	long chunknum;		/* 64 bit chunk number */	/*	 * quickly return 0 if seed is 0	 */	if (ziszero(seed) || seed.len <= 0) {		itoz(0, res);		return;	}	/*	 * allocate result	 */	seed.sign = 0;	/* use the value of seed */	res->len = (int)(((seed.len+SHALFS-1) / SHALFS) * SHALFS);	res->v = alloc(res->len);	res->sign = 0;	memset(res->v, 0, res->len*sizeof(HALF));  /* default value is 0 */	/*	 * process 64 bit chunks until done	 */	chunknum = 0;	while (!zislezero(seed)) {		/*		 * grab the lower 64 bits of seed		 */		if (zge64b(seed)) {			v64 = alloc(SHALFS);			memcpy(v64, seed.v, SHALFS*sizeof(HALF));			seed64.v = v64;			seed64.len = SHALFS;			seed64.sign = 0;		} else {			zcopy(seed, &seed64);		}		zshiftr(seed, SBITS);		ztrim(&seed);		ztrim(&seed64);		/*		 * do nothing if chunk is zero		 */		if (ziszero(seed64)) {			++chunknum;			zfree(seed64);			continue;		}		/*		 * Compute the linear congruence generator map:		 *		 *	X1 <-- (a*X0 + c) mod m		 *		 * in other words:		 *		 *	chunk == (a_val*seed + c_val) mod 2^64		 */		zmul(seed64, a_val, &t);		zfree(seed64);		zadd(t, c_val, &chunk);		zfree(t);		/*		 * form chunk mod 2^64		 */		if (chunk.len > (SB32)SHALFS) {			/* result is too large, reduce to 64 bits */			v64 = alloc(SHALFS);			memcpy(v64, chunk.v, SHALFS*sizeof(HALF));			free(chunk.v);			chunk.v = v64;			chunk.len = SHALFS;			ztrim(&chunk);		}		/*		 * Normally, the above equation would map:		 *		 *	    f(0) == 1363042948800878693		 *	    f(10239951819489363767) == 0		 *		 * However, we have already forced f(0) == 0.  To preserve the		 * 1-to-1 and onto map property, we force:		 *		 *	    f(10239951819489363767) ==> 1363042948800878693		 */		if (ziszero(chunk)) {			/* load 1363042948800878693 instead of 0 */			zcopy(c_val, &chunk);			memcpy(res->v+(chunknum*SHALFS), c_val.v,			       c_val.len*sizeof(HALF));		/*		 * load the 64 bit chunk into the result		 */		} else {			memcpy(res->v+(chunknum*SHALFS), chunk.v,			       chunk.len*sizeof(HALF));		}		++chunknum;		zfree(chunk);	}	ztrim(res);}/* * zsrand - seed the s100 generator * * given: *	pseed	- ptr to seed of the generator or NULL *	pmat100	- subtractive 100 state table or NULL * * returns: *	previous s100 state */RAND *zsrand(CONST ZVALUE *pseed, CONST MATRIX *pmat100){	RAND *ret;		/* previous s100 state */	CONST VALUE *v;		/* value from a passed matrix */	ZVALUE zscram;		/* scrambled 64 bit seed */	ZVALUE ztmp;		/* temp holding value for zscram */	ZVALUE seed;		/* to hold *pseed */	FULL shufxor[SLEN];	/* zshufxor as an 64 bit array of FULLs */	long indx;		/* index to shuffle slots for seeding */	int i;	/*	 * firewall	 */	if (pseed != NULL && zisneg(*pseed)) {		math_error("neg seeds for srand reserved for future use");		/*NOTREACHED*/	}	/*	 * initialize state if first call	 */	if (!s100.seeded) {		s100 = init_s100;	}	/*	 * save the current state to return later	 */	ret = (RAND *)malloc(sizeof(RAND));	if (ret == NULL) {		math_error("cannot allocate RAND state");		/*NOTREACHED*/	}	*ret = s100;	/*	 * if call was srand(), just return current state	 */	if (pseed == NULL && pmat100 == NULL) {		return ret;	}	/*	 * if call is srand(0), initialize and return quickly	 */	if (pmat100 == NULL && ziszero(*pseed)) {		s100 = init_s100;		return ret;	}	/*	 * clear buffered bits, initialize pointers	 */	s100.seeded = 0; /* not seeded now */	s100.j = INIT_J;	s100.k = INIT_K;	s100.bits = 0;	memset(s100.buffer, 0, sizeof(s100.buffer));	/*	 * load subtractive table	 *	 * We will load the default subtractive table unless we are passed a	 * matrix.  If we are passed a matrix, we will load the first 100	 * values mod 2^64 instead.	 */	if (pmat100 == NULL) {		memcpy(s100.slot, def_subtract, sizeof(def_subtract));	} else {		/*		 * use the first 100 entries from the matrix arg		 */		if (pmat100->m_size < S100) {			math_error("matrix for srand has < 100 elements");			/*NOTREACHED*/		}		for (v=pmat100->m_table, i=0; i < S100; ++i, ++v) {			/* reject if not integer */			if (v->v_type != V_NUM || qisfrac(v->v_num)) {			    math_error("matrix for srand must contain ints");			    /*NOTREACHED*/			}			/* load table element from matrix element mod 2^64 */			SLOAD(s100, i, v->v_num->num);		}	}	/*	 * scramble the seed in 64 bit chunks	 */	if (pseed != NULL) {		seed.sign = pseed->sign;		seed.len = pseed->len;		seed.v = alloc(seed.len);		zcopyval(*pseed, seed);		randreseed64(seed, &zscram);		zfree(seed);	}	/*	 * xor subtractive table with the rehashed lower 64 bits of seed	 */	if (pseed != NULL && !ziszero(zscram)) {		/* xor subtractive table with lower 64 bits of seed */		SMOD64(shufxor, zscram);		for (i=0; i < S100; ++i) {			SXOR(s100, i, shufxor);		}	}	/*	 * shuffle subtractive 100 table according to seed, if passed	 */	if (pseed != NULL && zge64b(zscram)) {		/* prepare the seed for subtractive slot shuffling */		zshiftr(zscram, 64);		ztrim(&zscram);		/* shuffle subtractive table */		for (i=S100-1; i > 0 && !zislezero(zscram); --i) {			/* determine what we will swap with */			indx = zdivi(zscram, i+1, &ztmp);			zfree(zscram);			zscram = ztmp;			/* do nothing if swap with itself */			if (indx == i) {				continue;			}			/* swap slot[i] with slot[indx] */			SSWAP(s100, i, indx);		}		zfree(zscram);	} else if (pseed != NULL) {		zfree(zscram);	}	/*	 * load the shuffle table	 *	 * We will generate SHUFCNT entries from the subtractive 100 slots	 * and fill the shuffle table in consecutive order.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -