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

📄 random.cpp

📁 Bubble Oscillation Algorithm. It is used to implement balancing load traffic, which is similar to wh
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 */
void BSD_srandom( unsigned long x ) {
	register long i;

	if (rand_type == TYPE_0)
		state[0] = x;
	else {
		state[0] = x;
		for (i = 1; i < rand_deg; i++)
			state[i] = good_rand(state[i - 1]);
		fptr = &state[rand_sep];
		rptr = &state[0];
		for (i = 0; i < 10 * rand_deg; i++)
			(void) BSD_random();
	}
}

/*
 * initstate:
 *
 * Initialize the state information in the given array of n bytes for future
 * random number generation.  Based on the number of bytes we are given, and
 * the break values for the different R.N.G.'s, we choose the best (largest)
 * one we can and set things up for it.  srandom() is then called to
 * initialize the state information.
 *
 * Note that on return from srandom(), we set state[-1] to be the type
 * multiplexed with the current value of the rear pointer; this is so
 * successive calls to initstate() won't lose this information and will be
 * able to restart with setstate().
 *
 * Note: the first thing we do is save the current state, if any, just like
 * setstate() so that it doesn't matter when initstate is called.
 *
 * Returns a pointer to the old state.
 *
 * Note: The Sparc platform requires that arg_state begin on a long
 * word boundary; otherwise a bus error will occur. Even so, lint will
 * complain about mis-alignment, but you should disregard these messages.
 */
char *initstate(unsigned long seed,   /* seed for R.N.G. */
                char *arg_state,      /* pointer to state array */
                long n) {             /* # bytes of state info */

	register char *ostate = (char *)(&state[-1]);
	register long *long_arg_state = (long *) arg_state;

	if (rand_type == TYPE_0)
		state[-1] = rand_type;
	else
		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
	if (n < BREAK_0) {
		(void)fprintf(stderr, "random: not enough state (%ld bytes); ignored.\n", n);
		return(0);
	}
	if (n < BREAK_1) {
		rand_type = TYPE_0;
		rand_deg = DEG_0;
		rand_sep = SEP_0;
	} else if (n < BREAK_2) {
		rand_type = TYPE_1;
		rand_deg = DEG_1;
		rand_sep = SEP_1;
	} else if (n < BREAK_3) {
		rand_type = TYPE_2;
		rand_deg = DEG_2;
		rand_sep = SEP_2;
	} else if (n < BREAK_4) {
		rand_type = TYPE_3;
		rand_deg = DEG_3;
		rand_sep = SEP_3;
	} else {
		rand_type = TYPE_4;
		rand_deg = DEG_4;
		rand_sep = SEP_4;
	}
	state = (long *) (long_arg_state + 1); /* first location */
	end_ptr = &state[rand_deg];	/* must set end_ptr before srandom */
	BSD_srandom(seed);
	if (rand_type == TYPE_0)
		long_arg_state[0] = rand_type;
	else
		long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
	return(ostate);
}

/*
 * getstate:
 *
 * Return the state from the current RNG
 * 
 * Can be used to re-start RNG later with setstate;
 * 
 */
char *getstate( int *length ) {   /* store the length of the array */
  /* store the position of rptr */
	if (rand_type == TYPE_0)
		state[-1] = rand_type;
	else
		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
  /* return the length of state array */
  *length = (end_ptr - state + 1) * 4;
  return (char *)(&state[-1]);
}

/*
 * setstate:
 *
 * Restore the state from the given state array.
 *
 * Note: it is important that we also remember the locations of the pointers
 * in the current state information, and restore the locations of the pointers
 * from the old state information.  This is done by multiplexing the pointer
 * location into the zeroeth word of the state information.
 *
 * Note that due to the order in which things are done, it is OK to call
 * setstate() with the same state as the current state.
 *
 * Returns a pointer to the old state information.
 *
 * Note: The Sparc platform requires that arg_state begin on a long
 * word boundary; otherwise a bus error will occur. Even so, lint will
 * complain about mis-alignment, but you should disregard these messages.
 */
char *setstate(char *arg_state) {   /* pointer to state array */

	register long *new_state = (long *) arg_state;
	register long type = new_state[0] % MAX_TYPES;
	register long rear = new_state[0] / MAX_TYPES;
	char *ostate = (char *)(&state[-1]);

	if (rand_type == TYPE_0)
		state[-1] = rand_type;
	else
		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
	switch(type) {
	case TYPE_0:
	case TYPE_1:
	case TYPE_2:
	case TYPE_3:
	case TYPE_4:
		rand_type = type;
		rand_deg = degrees[type];
		rand_sep = seps[type];
		break;
	default:
		(void)fprintf(stderr, "random: state info corrupted; not changed.\n");
	}
	state = (long *) (new_state + 1);
	if (rand_type != TYPE_0) {
		rptr = &state[rear];
		fptr = &state[(rear + rand_sep) % rand_deg];
	}
	end_ptr = &state[rand_deg];		/* set end_ptr too */
	return(ostate);
}

/*
 * random:
 *
 * If we are using the trivial TYPE_0 R.N.G., just do the old linear
 * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is
 * the same in all the other cases due to all the global variables that have
 * been set up.  The basic operation is to add the number at the rear pointer
 * into the one at the front pointer.  Then both pointers are advanced to
 * the next location cyclically in the table.  The value returned is the sum
 * generated, reduced to 31 bits by throwing away the "least random" low bit.
 *
 * Note: the code takes advantage of the fact that both the front and
 * rear pointers can't wrap on the same call by not testing the rear
 * pointer if the front one has wrapped.
 *
 * Returns a 31-bit random number.
 */
long BSD_random() {
	register long i;
	register long *f, *r;

	if (rand_type == TYPE_0) {
		i = state[0];
		state[0] = i = (good_rand(i)) & 0x7fffffff;
	} else {
		/*
		 * Use local variables rather than static variables for speed.
		 */
		f = fptr; r = rptr;
		*f += *r;
		i = (*f >> 1) & 0x7fffffff;	/* chucking least random bit */
		if (++f >= end_ptr) {
			f = state;
			++r;
		}
		else if (++r >= end_ptr) {
			r = state;
		}

		fptr = f; rptr = r;
	}
	return(i);
}

/* For testing */
/*
main() {
  int i, len;
  char buf1[128], *p, buf2[128];

  printf("seeding random with 0x19610910: \n");
//  BSD_srandom(0x19610910);
  BSD_srandom(0x19610911);

  printf("generating 10 pseudo-random numbers:\n");
  for (i = 0; i < 10; i++) {
    printf("next random number = %d\n", BSD_random());
  }

  printf("\nsave the state......\n");
  p = getstate(&len);
  for(i=0; i<len; i++) {
    buf1[i]=*p;
    buf2[i]=*p;
    p++;
  }

  printf("\ngenerating the next 10 pseudo-random numbers:\n");
  for (i = 0; i < 10; i++) {
    printf("next random number = %d\n", BSD_random());
  }

  printf("\nrestore the state......\n");
  setstate(buf1);

  printf("\ngenerating another 10 pseudo-random numbers:\n");
  for (i = 0; i < 10; i++) {
    printf("next random number = %d\n", BSD_random());
  }

  printf("\nrestore the state again......\n");
  setstate(buf2);

  printf("\ngenerating another 10 pseudo-random numbers:\n");
  for (i = 0; i < 10; i++) {
    printf("next random number = %d\n", BSD_random());
  }

  return 0;
}
*/
/* for testing */

⌨️ 快捷键说明

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