Shuffle

Python trunk

random.py:

def shuffle(self, x, random=None, int=int):
    """x, random=random.random -> shuffle list x in place; return None.

    Optional arg random is a 0-argument function returning a random
    float in [0.0, 1.0); by default, the standard random.random.
    """

    if random is None:
        random = self.random
    for i in reversed(xrange(1, len(x))):
        # pick an element in x[:i+1] with which to exchange x[i]
        j = int(random() * (i+1))
        x[i], x[j] = x[j], x[i]

glibc 2.10

string/strfry.c:

char *
strfry (char *string)
{
  static int init;
  static struct random_data rdata;

  if (!init)
    {
      static char state[32];
      rdata.state = NULL;
      __initstate_r (time ((time_t *) NULL) ^ getpid (),
                     state, sizeof (state), &rdata);
      init = 1;
    }

  size_t len = strlen (string);
  if (len > 0)
    for (size_t i = 0; i < len - 1; ++i)
      {
        int32_t j;
        __random_r (&rdata, &j);
        j = j % (len - i) + i;

        char c = string[i];
        string[i] = string[j];
        string[j] = c;
      }

  return string;
}

glibc 2.6.1

string/strfry.c:

char *
strfry (char *string)
{
  static int init;
  static struct random_data rdata;
  size_t len, i;

  if (!init)
    {
      static char state[32];
      rdata.state = NULL;
      __initstate_r (time ((time_t *) NULL) ^ getpid (),
                     state, sizeof (state), &rdata);
      init = 1;
    }

  len = strlen (string) - 1;
  for (i = 0; i < len; ++i)
    {
      int32_t j;
      __random_r (&rdata, &j);
      j = j % len + 1;

      char c = string[i];
      string[i] = string[j];
      string[j] = c;
    }

  return string;
}

PHP 5.2.3

ext/standard/array.c:

static void array_data_shuffle(zval *array TSRMLS_DC)
{
    Bucket **elems, *temp;
    HashTable *hash;
    int j, n_elems, rnd_idx, n_left;

    n_elems = zend_hash_num_elements(Z_ARRVAL_P(array));

    if (n_elems < 1) {
            return;
    }

    elems = (Bucket **)safe_emalloc(n_elems, sizeof(Bucket *), 0);
    hash = Z_ARRVAL_P(array);
    n_left = n_elems;

    for (j = 0, temp = hash->pListHead; temp; temp = temp->pListNext)
            elems[j++] = temp;
    while (--n_left) {
            rnd_idx = php_rand(TSRMLS_C);
            RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
            if (rnd_idx != n_left) {
                    temp = elems[n_left];
                    elems[n_left] = elems[rnd_idx];
                    elems[rnd_idx] = temp;
            }
    }

    HANDLE_BLOCK_INTERRUPTIONS();
    hash->pListHead = elems[0];
    hash->pListTail = NULL;
    hash->pInternalPointer = hash->pListHead;

    for (j = 0; j < n_elems; j++) {
            if (hash->pListTail) {
                    hash->pListTail->pListNext = elems[j];
            }
            elems[j]->pListLast = hash->pListTail;
            elems[j]->pListNext = NULL;
            hash->pListTail = elems[j];
    }
    temp = hash->pListHead;
    j = 0;
    while (temp != NULL) {
            temp->nKeyLength = 0;
            temp->h = j++;
            temp = temp->pListNext;
    }
    hash->nNextFreeElement = n_elems;
    zend_hash_rehash(hash);
    HANDLE_UNBLOCK_INTERRUPTIONS();

    efree(elems);
}