aaaaaa123456789 icon

C implementation of StableRandom

aaaaaa123456789 | PRO | 10/20/17 08:08:38 AM UTC | 0 ⭐ | 524 👁️ | Never ⏰ | []
C |

1.69 KB

|

None

|

0 👍

/

0 👎

struct stable_random_state {
  unsigned shift:  32;
  unsigned carry:   8;
  unsigned current: 8;
  unsigned prev:    8;
  unsigned linear:  8;
};
 
#define STABLE_RANDOM_NEXT_LINEAR(s) ((s) -> linear *= 73, (s) -> linear += 29, (s) -> linear)
 
unsigned char stable_random (struct stable_random_state * state) {
  unsigned p;
  const unsigned char cycle_start_points[] = {1, 2, 4, 8, 13, 17, 23, 26, 29, 58, 0};
  const unsigned char short_cycles[] = {0x72, 0x4f, 0x9f, 0x7b, 0x1a, 0x7b, 0x84, 0xe5, 0x56, 0x8d, 0xb0, 0x32, 0, 0, 1};
  if (!state -> shift) for (p = 0; p < 4; p ++) state -> shift = (state -> shift << 8) | STABLE_RANDOM_NEXT_LINEAR(state);
  state -> shift ^= state -> shift >> 8;
  state -> shift ^= state -> shift << 9;
  state -> shift ^= state -> shift >> 23;
  if (state -> prev || state -> current)
    for (p = 0; p < (sizeof short_cycles - 3); p += 3) {
      if ((state -> prev == short_cycles[p]) && (state -> current == short_cycles[p + 1]) && (state -> carry == short_cycles[p + 2])) {
        state -> prev = short_cycles[p + 3];
        state -> current = short_cycles[p + 4];
        state -> carry = short_cycles[p + 5];
        break;
      }
    }
  else
    for (p = 0; p < (sizeof cycle_start_points - 1); p ++) if (state -> carry == cycle_start_points[p]) {
      state -> carry = cycle_start_points[p + 1];
      if (!state -> carry) {
        state -> prev = *short_cycles;
        state -> current = short_cycles[1];
        state -> carry = short_cycles[2];
        STABLE_RANDOM_NEXT_LINEAR(state);
      }
      break;
    }
  if (state -> carry >= 210) state -> carry -= 210;
  p = state -> carry + state -> prev + state -> current;
  if (!p || (p == 719)) {
    state -> prev = STABLE_RANDOM_NEXT_LINEAR(state);
    state -> carry = STABLE_RANDOM_NEXT_LINEAR(state);
    state -> current = STABLE_RANDOM_NEXT_LINEAR(state);
    if (state -> carry >= 210) state -> carry -= 210;
  }
  p = 210 * state -> prev + state -> carry;
  state -> prev = state -> current;
  state -> current = p & 0xff;
  state -> carry = p >> 8;
  STABLE_RANDOM_NEXT_LINEAR(state);
  p = state -> shift >> ((state -> linear >> 3) & 24);
  switch ((state -> linear >> 4) & 3) {
    case 0:
      return p + state -> current;
    case 1:
      return p ^ state -> current;
    case 2:
      return p - state -> current;
    default:
      return state -> current - p;
  }
}
 
void stable_random_initialize (struct stable_random_state * state, unsigned seed1, unsigned seed2, unsigned initial_mixing_count) {
  // assuming here that unsigned is 32-bit
  state -> shift = seed1;
  1[(unsigned *) state] = seed2;
  while (initial_mixing_count --) stable_random(state);
}

Comments