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

📄 mtwist.c

📁 symbian下ffmpeg编程。。废了好大劲下下来的!。
💻 C
📖 第 1 页 / 共 3 页
字号:
 * corresponding decimal constant.  So we will compute the correct number at * run time as part of initialization, which will produce a nice exact * result. */double			mt_32_to_double;					/* Multiplier to convert long to dbl */double			mt_64_to_double;					/* Mult'r to cvt long long to dbl *//* * In the recurrence relation, the new value is XORed with MATRIX_A only if * the lower bit is nonzero.  Since most modern machines don't like to * branch, it's vastly faster to handle this decision by indexing into an * array.  The chosen bit is used as an index into the following vector, * which produces either zero or MATRIX_A and thus the desired effect. */static unsigned long	matrix_decider[2] =			  {0x0, MATRIX_A};/* * Mark a PRNG's state as having been initialized.  This is the only * way to set that field nonzero; that way we can be sure that the * constants are set properly before the PRNG is used. * * As a side effect, set up some constants that the PRNG assumes are * valid.  These are calculated at initialization time rather than * being written as decimal constants because I frankly don't trust * the compiler's ASCII conversion routines. */void mts_mark_initialized(    mt_state*		state)		/* State vector to mark initialized */    {    int			i;		/* Power of 2 being calculated */    /*     * Figure out the proper multiplier for long-to-double conversion.  We     * don't worry too much about efficiency, since the assumption is that     * initialization is vastly rarer than generation of random numbers.     */    mt_32_to_double = 1.0;    for (i = 0;  i < BIT_WIDTH;  i++)	mt_32_to_double /= 2.0;    mt_64_to_double = mt_32_to_double;    for (i = 0;  i < BIT_WIDTH;  i++)	mt_64_to_double /= 2.0;    state->initialized = 1;    }/* * Initialize a Mersenne Twist PRNG from a 32-bit seed. * * According to Matsumoto and Nishimura's paper, the seed array needs to be * filled with nonzero values.  (My own interpretation is that there needs * to be at least one nonzero value).  They suggest using Knuth's PRNG from * Line 25, Table 1, p.102, "The Art of Computer Programming," Vol. 2 (2nd * ed.), 1981.  I find that rather odd, since that particular PRNG is * sensitive to having an initial seed of zero (there are many other PRNGs * out there that have an additive component, so that a seed of zero does * not generate a repeating-zero sequence).  However, one thing I learned * from reading Knuth is that you shouldn't second-guess mathematicians * about PRNGs.  Also, by following M & N's approach, we will be compatible * with other implementations.  So I'm going to stick with their version, * with the single addition that a zero seed will be changed to their * default seed. */void mts_seed32(    mt_state*		state,		/* State vector to initialize */    unsigned long	seed)		/* 32-bit seed to start from */    {    int			i;		/* Loop index */    if (seed == 0)	seed = DEFAULT_SEED32_OLD;    /*     * Fill the state vector using Knuth's PRNG.  Be sure to mask down     * to 32 bits in case we're running on a machine with 64-bit     * longs.     */    state->statevec[MT_STATE_SIZE - 1] = seed & 0xffffffff;    for (i = MT_STATE_SIZE - 2;  i >= 0;  i--)        state->statevec[i] =          (KNUTH_MULTIPLIER_OLD * state->statevec[i + 1]) & 0xffffffff;    state->stateptr = MT_STATE_SIZE;    mts_mark_initialized(state);    /*     * Matsumoto and Nishimura's implementation refreshes the PRNG     * immediately after running the Knuth algorithm.  This is     * probably a good thing, since Knuth's PRNG doesn't generate very     * good numbers.     */    mts_refresh(state);    }/* * Initialize a Mersenne Twist PRNG from a 32-bit seed, using * Matsumoto and Nishimura's newer reference implementation (Jan. 9, * 2002). */void mts_seed32new(    mt_state*		state,		/* State vector to initialize */    unsigned long	seed)		/* 32-bit seed to start from */    {    int			i;		/* Loop index */    unsigned long	nextval;	/* Next value being calculated */    /*     * Fill the state vector using Knuth's PRNG.  Be sure to mask down     * to 32 bits in case we're running on a machine with 64-bit     * longs.     */    state->statevec[MT_STATE_SIZE - 1] = seed & 0xffffffffUL;    for (i = MT_STATE_SIZE - 2;  i >= 0;  i--)	{	nextval = state->statevec[i + 1] >> KNUTH_SHIFT;	nextval ^= state->statevec[i + 1];	nextval *= KNUTH_MULTIPLIER_NEW;	nextval += (MT_STATE_SIZE - 1) - i;	state->statevec[i] = nextval & 0xffffffffUL;	}    state->stateptr = MT_STATE_SIZE;    mts_mark_initialized(state);    /*     * Matsumoto and Nishimura's implementation refreshes the PRNG     * immediately after running the Knuth algorithm.  This is     * probably a good thing, since Knuth's PRNG doesn't generate very     * good numbers.     */    mts_refresh(state);    }/* * Initialize a Mersenne Twist RNG from a 624-long seed. * * The 32-bit seeding routine given by Matsumoto and Nishimura has the * drawback that there are only 2^32 different PRNG sequences that can be * generated by calling that function.  This function solves that problem by * allowing a full 624*32-bit state to be given.  (Note that 31 bits of the * given state are ignored; see the paper for details.) * * Since an all-zero state would cause the PRNG to cycle, we detect * that case and abort the program (silently, since there is no * portable way to produce a message in both C and C++ environments). * An alternative would be to artificially force the state to some * known nonzero value.  However, I feel that if the user is providing * a full state, it's a bug to provide all zeros and we we shouldn't * conceal the bug by generating apparently correct output. */void mts_seedfull(    mt_state*		state,		/* State vector to initialize */    unsigned long	seeds[MT_STATE_SIZE])					/* Seed array to start from */    {    int			had_nz = 0;	/* NZ if at least one NZ seen */    int			i;		/* Loop index */    for (i = 0;  i < MT_STATE_SIZE;  i++)        {        if (seeds[i] != 0)	    had_nz = 1;        state->statevec[MT_STATE_SIZE - i - 1] = seeds[i];	}    if (!had_nz)	{	/*	 * It would be nice to abort with a message.  Unfortunately, fprintf	 * isn't compatible with all implementations of C++.  In the	 * interest of C++ compatibility, therefore, we will simply abort	 * silently.  It will unfortunately be up to a programmer to run	 * under a debugger (or examine the core dump) to discover the cause	 * of the abort.	 */	abort();	}    state->stateptr = MT_STATE_SIZE;    mts_mark_initialized(state);    }/* * Choose a seed based on some moderately random input.  Prefers * /dev/urandom as a source of random numbers, but uses the lower bits * of the current time if /dev/urandom is not available.  In any case, * only provides 32 bits of entropy. */void mts_seed(    mt_state*		state)		/* State vector to seed */    {    mts_devseed(state, DEVURANDOM);    }/* * Choose a seed based on some fairly random input.  Prefers * /dev/random as a source of random numbers, but uses the lower bits * of the current time if /dev/random is not available.  In any case, * only provides 32 bits of entropy. */void mts_goodseed(    mt_state*		state)		/* State vector to seed */    {    mts_devseed(state, DEVRANDOM);    }/* * Choose a seed based on a random-number device given by the caller. * If that device can't be opened, use the lower 32 bits from the * current time. */static void mts_devseed(    mt_state*		state,		/* State vector to seed */    char*		seed_dev)	/* Device to seed from */    {    int			bytesread;	/* Byte count read from device */    int			nextbyte;	/* Index of next byte to read */    FILE*		ranfile;	/* Access to device */    union	{	char		ranbuffer[sizeof (unsigned long)];					/* Space for reading random int */	unsigned long	randomvalue;	/* Random value for initialization */	}			randomunion;	/* Union for reading random int */#ifdef WIN32    struct _timeb	tb;		/* Time of day (Windows mode) */#else /* WIN32 */    struct timeval	tv;		/* Time of day */    struct timezone	tz;		/* Dummy for gettimeofday */#endif /* WIN32 */    ranfile = fopen(seed_dev, "rb");    if (ranfile != NULL)	{	for (nextbyte = 0;	  nextbyte < (int)sizeof randomunion.ranbuffer;	  nextbyte += bytesread)	    {	    bytesread = fread(&randomunion.ranbuffer[nextbyte], 1,	      sizeof randomunion.ranbuffer - nextbyte, ranfile);	    if (bytesread == 0)		break;	    }	fclose(ranfile);	if (nextbyte == sizeof randomunion.ranbuffer)	    {	    mts_seed32new(state, randomunion.randomvalue);	    return;	    }	}    /*     * The device isn't available.  Use the time.  We will     * assume that the time of day is accurate to microsecond     * resolution, which is true on most modern machines.     */#ifdef WIN32    (void) _ftime (&tb);#else /* WIN32 */    (void) gettimeofday (&tv, &tz);#endif /* WIN32 */    /*     * We just let the excess part of the seconds field overflow     */#ifdef WIN32    randomunion.randomvalue = tb.time * 1000 + tb.millitm;#else /* WIN32 */    randomunion.randomvalue = tv.tv_sec * 1000000 + tv.tv_usec;#endif /* WIN32 */    mts_seed32new(state, randomunion.randomvalue);    }/* * Choose a seed based on the best random input available.  Prefers * /dev/random as a source of random numbers, and reads the entire * 624-long state from that device.  Because of this approach, the * function can take a long time (in real time) to complete, since * /dev/random may have to wait quite a while before it can provide * that much randomness.  If /dev/random is unavailable, falls back to * calling mts_goodseed. */void mts_bestseed(    mt_state*		state)		/* State vector to seed */    {    int			bytesread;	/* Byte count read from device */    int			nextbyte;	/* Index of next byte to read */    FILE*		ranfile;	/* Access to device */    ranfile = fopen("/dev/random", "rb");    if (ranfile == NULL)	{	mts_goodseed(state);	return;	}    for (nextbyte = 0;      nextbyte < (int)sizeof state->statevec;      nextbyte += bytesread)	{	bytesread = fread((char *)&state->statevec + nextbyte, 1,	  sizeof state->statevec - nextbyte, ranfile);	if (bytesread == 0)	    {	    /*	     * Something went wrong.  Fall back to time-based seeding.	     */	    fclose(ranfile);	    mts_goodseed(state);	    return;	    }	}    }

⌨️ 快捷键说明

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