Back to index

python3.2  3.2.2
Classes | Defines | Functions | Variables
_randommodule.c File Reference
#include "Python.h"
#include <time.h>

Go to the source code of this file.

Classes

struct  RandomObject

Defines

#define N   624
#define M   397
#define MATRIX_A   0x9908b0dfUL /* constant vector a */
#define UPPER_MASK   0x80000000UL /* most significant w-r bits */
#define LOWER_MASK   0x7fffffffUL /* least significant r bits */
#define RandomObject_Check(v)   (Py_TYPE(v) == &Random_Type)

Functions

static unsigned long genrand_int32 (RandomObject *self)
static PyObjectrandom_random (RandomObject *self)
static void init_genrand (RandomObject *self, unsigned long s)
static PyObjectinit_by_array (RandomObject *self, unsigned long init_key[], unsigned long key_length)
static PyObjectrandom_seed (RandomObject *self, PyObject *args)
static PyObjectrandom_getstate (RandomObject *self)
static PyObjectrandom_setstate (RandomObject *self, PyObject *state)
static PyObjectrandom_getrandbits (RandomObject *self, PyObject *args)
static PyObjectrandom_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
 PyDoc_STRVAR (random_doc,"Random() -> create a random number generator with its own internal state.")
 PyDoc_STRVAR (module_doc,"Module implements the Mersenne Twister random number generator.")
PyMODINIT_FUNC PyInit__random (void)

Variables

static PyTypeObject Random_Type
static PyMethodDef random_methods []
static struct PyModuleDef

Class Documentation

struct RandomObject

Definition at line 79 of file _randommodule.c.

Class Members
int index
PyObject_HEAD unsigned long state

Define Documentation

#define LOWER_MASK   0x7fffffffUL /* least significant r bits */

Definition at line 77 of file _randommodule.c.

#define M   397

Definition at line 74 of file _randommodule.c.

#define MATRIX_A   0x9908b0dfUL /* constant vector a */

Definition at line 75 of file _randommodule.c.

#define N   624

Definition at line 73 of file _randommodule.c.

#define RandomObject_Check (   v)    (Py_TYPE(v) == &Random_Type)

Definition at line 87 of file _randommodule.c.

#define UPPER_MASK   0x80000000UL /* most significant w-r bits */

Definition at line 76 of file _randommodule.c.


Function Documentation

static unsigned long genrand_int32 ( RandomObject self) [static]

Definition at line 95 of file _randommodule.c.

{
    unsigned long y;
    static unsigned long mag01[2]={0x0UL, MATRIX_A};
    /* mag01[x] = x * MATRIX_A  for x=0,1 */
    unsigned long *mt;

    mt = self->state;
    if (self->index >= N) { /* generate N words at one time */
        int kk;

        for (kk=0;kk<N-M;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        for (;kk<N-1;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];

        self->index = 0;
    }

    y = mt[self->index++];
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);
    return y;
}

Here is the caller graph for this function:

static PyObject* init_by_array ( RandomObject self,
unsigned long  init_key[],
unsigned long  key_length 
) [static]

Definition at line 171 of file _randommodule.c.

{
    unsigned int i, j, k;       /* was signed in the original code. RDH 12/16/2002 */
    unsigned long *mt;

    mt = self->state;
    init_genrand(self, 19650218UL);
    i=1; j=0;
    k = (N>key_length ? N : key_length);
    for (; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
                 + init_key[j] + j; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++; j++;
        if (i>=N) { mt[0] = mt[N-1]; i=1; }
        if (j>=key_length) j=0;
    }
    for (k=N-1; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
                 - i; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++;
        if (i>=N) { mt[0] = mt[N-1]; i=1; }
    }

    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
    Py_INCREF(Py_None);
    return Py_None;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void init_genrand ( RandomObject self,
unsigned long  s 
) [static]

Definition at line 146 of file _randommodule.c.

{
    int mti;
    unsigned long *mt;

    mt = self->state;
    mt[0]= s & 0xffffffffUL;
    for (mti=1; mti<N; mti++) {
        mt[mti] =
        (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
        /* In the previous versions, MSBs of the seed affect   */
        /* only MSBs of the array mt[].                                */
        /* 2002/01/09 modified by Makoto Matsumoto                     */
        mt[mti] &= 0xffffffffUL;
        /* for >32 bit machines */
    }
    self->index = mti;
    return;
}

Here is the caller graph for this function:

PyDoc_STRVAR ( random_doc  ,
"Random() -> create a random number generator with its own internal state."   
)
PyDoc_STRVAR ( module_doc  ,
"Module implements the Mersenne Twister random number generator."   
)

Definition at line 513 of file _randommodule.c.

{
    PyObject *m;

    if (PyType_Ready(&Random_Type) < 0)
        return NULL;
    m = PyModule_Create(&_randommodule);
    if (m == NULL)
        return NULL;
    Py_INCREF(&Random_Type);
    PyModule_AddObject(m, "Random", (PyObject *)&Random_Type);
    return m;
}

Here is the call graph for this function:

static PyObject* random_getrandbits ( RandomObject self,
PyObject args 
) [static]

Definition at line 373 of file _randommodule.c.

{
    int k, i, bytes;
    unsigned long r;
    unsigned char *bytearray;
    PyObject *result;

    if (!PyArg_ParseTuple(args, "i:getrandbits", &k))
        return NULL;

    if (k <= 0) {
        PyErr_SetString(PyExc_ValueError,
                        "number of bits must be greater than zero");
        return NULL;
    }

    bytes = ((k - 1) / 32 + 1) * 4;
    bytearray = (unsigned char *)PyMem_Malloc(bytes);
    if (bytearray == NULL) {
        PyErr_NoMemory();
        return NULL;
    }

    /* Fill-out whole words, byte-by-byte to avoid endianness issues */
    for (i=0 ; i<bytes ; i+=4, k-=32) {
        r = genrand_int32(self);
        if (k < 32)
            r >>= (32 - k);
        bytearray[i+0] = (unsigned char)r;
        bytearray[i+1] = (unsigned char)(r >> 8);
        bytearray[i+2] = (unsigned char)(r >> 16);
        bytearray[i+3] = (unsigned char)(r >> 24);
    }

    /* little endian order to match bytearray assignment order */
    result = _PyLong_FromByteArray(bytearray, bytes, 1, 0);
    PyMem_Free(bytearray);
    return result;
}

Here is the call graph for this function:

static PyObject* random_getstate ( RandomObject self) [static]

Definition at line 312 of file _randommodule.c.

{
    PyObject *state;
    PyObject *element;
    int i;

    state = PyTuple_New(N+1);
    if (state == NULL)
        return NULL;
    for (i=0; i<N ; i++) {
        element = PyLong_FromUnsignedLong(self->state[i]);
        if (element == NULL)
            goto Fail;
        PyTuple_SET_ITEM(state, i, element);
    }
    element = PyLong_FromLong((long)(self->index));
    if (element == NULL)
        goto Fail;
    PyTuple_SET_ITEM(state, i, element);
    return state;

Fail:
    Py_DECREF(state);
    return NULL;
}

Here is the call graph for this function:

static PyObject* random_new ( PyTypeObject type,
PyObject args,
PyObject kwds 
) [static]

Definition at line 414 of file _randommodule.c.

{
    RandomObject *self;
    PyObject *tmp;

    if (type == &Random_Type && !_PyArg_NoKeywords("Random()", kwds))
        return NULL;

    self = (RandomObject *)type->tp_alloc(type, 0);
    if (self == NULL)
        return NULL;
    tmp = random_seed(self, args);
    if (tmp == NULL) {
        Py_DECREF(self);
        return NULL;
    }
    Py_DECREF(tmp);
    return (PyObject *)self;
}

Here is the call graph for this function:

static PyObject* random_random ( RandomObject self) [static]

Definition at line 138 of file _randommodule.c.

{
    unsigned long a=genrand_int32(self)>>5, b=genrand_int32(self)>>6;
    return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0));
}

Here is the call graph for this function:

static PyObject* random_seed ( RandomObject self,
PyObject args 
) [static]

Definition at line 207 of file _randommodule.c.

{
    PyObject *result = NULL;            /* guilty until proved innocent */
    PyObject *masklower = NULL;
    PyObject *thirtytwo = NULL;
    PyObject *n = NULL;
    unsigned long *key = NULL;
    unsigned long keymax;               /* # of allocated slots in key */
    unsigned long keyused;              /* # of used slots in key */
    int err;

    PyObject *arg = NULL;

    if (!PyArg_UnpackTuple(args, "seed", 0, 1, &arg))
        return NULL;

    if (arg == NULL || arg == Py_None) {
        time_t now;

        time(&now);
        init_genrand(self, (unsigned long)now);
        Py_INCREF(Py_None);
        return Py_None;
    }
    /* If the arg is an int or long, use its absolute value; else use
     * the absolute value of its hash code.
     */
    if (PyLong_Check(arg))
        n = PyNumber_Absolute(arg);
    else {
        long hash = PyObject_Hash(arg);
        if (hash == -1)
            goto Done;
        n = PyLong_FromUnsignedLong((unsigned long)hash);
    }
    if (n == NULL)
        goto Done;

    /* Now split n into 32-bit chunks, from the right.  Each piece is
     * stored into key, which has a capacity of keymax chunks, of which
     * keyused are filled.  Alas, the repeated shifting makes this a
     * quadratic-time algorithm; we'd really like to use
     * _PyLong_AsByteArray here, but then we'd have to break into the
     * long representation to figure out how big an array was needed
     * in advance.
     */
    keymax = 8;         /* arbitrary; grows later if needed */
    keyused = 0;
    key = (unsigned long *)PyMem_Malloc(keymax * sizeof(*key));
    if (key == NULL)
        goto Done;

    masklower = PyLong_FromUnsignedLong(0xffffffffU);
    if (masklower == NULL)
        goto Done;
    thirtytwo = PyLong_FromLong(32L);
    if (thirtytwo == NULL)
        goto Done;
    while ((err=PyObject_IsTrue(n))) {
        PyObject *newn;
        PyObject *pychunk;
        unsigned long chunk;

        if (err == -1)
            goto Done;
        pychunk = PyNumber_And(n, masklower);
        if (pychunk == NULL)
            goto Done;
        chunk = PyLong_AsUnsignedLong(pychunk);
        Py_DECREF(pychunk);
        if (chunk == (unsigned long)-1 && PyErr_Occurred())
            goto Done;
        newn = PyNumber_Rshift(n, thirtytwo);
        if (newn == NULL)
            goto Done;
        Py_DECREF(n);
        n = newn;
        if (keyused >= keymax) {
            unsigned long bigger = keymax << 1;
            if ((bigger >> 1) != keymax) {
                PyErr_NoMemory();
                goto Done;
            }
            key = (unsigned long *)PyMem_Realloc(key,
                                    bigger * sizeof(*key));
            if (key == NULL)
                goto Done;
            keymax = bigger;
        }
        assert(keyused < keymax);
        key[keyused++] = chunk;
    }

    if (keyused == 0)
        key[keyused++] = 0UL;
    result = init_by_array(self, key, keyused);
Done:
    Py_XDECREF(masklower);
    Py_XDECREF(thirtytwo);
    Py_XDECREF(n);
    PyMem_Free(key);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PyObject* random_setstate ( RandomObject self,
PyObject state 
) [static]

Definition at line 339 of file _randommodule.c.

{
    int i;
    unsigned long element;
    long index;

    if (!PyTuple_Check(state)) {
        PyErr_SetString(PyExc_TypeError,
            "state vector must be a tuple");
        return NULL;
    }
    if (PyTuple_Size(state) != N+1) {
        PyErr_SetString(PyExc_ValueError,
            "state vector is the wrong size");
        return NULL;
    }

    for (i=0; i<N ; i++) {
        element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
        if (element == (unsigned long)-1 && PyErr_Occurred())
            return NULL;
        self->state[i] = element & 0xffffffffUL; /* Make sure we get sane state */
    }

    index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
    if (index == -1 && PyErr_Occurred())
        return NULL;
    self->index = (int)index;

    Py_INCREF(Py_None);
    return Py_None;
}

Here is the call graph for this function:


Variable Documentation

struct PyModuleDef [static]
Initial value:
 {
    PyModuleDef_HEAD_INIT,
    "_random",
    module_doc,
    -1,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
}

Definition at line 500 of file _randommodule.c.

Initial value:
 {
    {"random",          (PyCFunction)random_random,  METH_NOARGS,
        PyDoc_STR("random() -> x in the interval [0, 1).")},
    {"seed",            (PyCFunction)random_seed,  METH_VARARGS,
        PyDoc_STR("seed([n]) -> None.  Defaults to current time.")},
    {"getstate",        (PyCFunction)random_getstate,  METH_NOARGS,
        PyDoc_STR("getstate() -> tuple containing the current state.")},
    {"setstate",          (PyCFunction)random_setstate,  METH_O,
        PyDoc_STR("setstate(state) -> None.  Restores generator state.")},
    {"getrandbits",     (PyCFunction)random_getrandbits,  METH_VARARGS,
        PyDoc_STR("getrandbits(k) -> x.  Generates a long int with "
                  "k random bits.")},
    {NULL,              NULL}           
}

Definition at line 434 of file _randommodule.c.

static PyTypeObject Random_Type [static]

Definition at line 85 of file _randommodule.c.