Changeset 391 for python/trunk/Modules/_randommodule.c
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Modules/_randommodule.c
r2 r391 3 3 /* ------------------------------------------------------------------ 4 4 The code in this module was based on a download from: 5 5 http://www.math.keio.ac.jp/~matumoto/MT2002/emt19937ar.html 6 6 7 7 It was modified in 2002 by Raymond Hettinger as follows: 8 8 9 * the principal computational lines untouched except for tabbing.10 11 12 13 14 15 16 17 18 19 20 21 9 * the principal computational lines untouched. 10 11 * renamed genrand_res53() to random_random() and wrapped 12 in python calling/return code. 13 14 * genrand_int32() and the helper functions, init_genrand() 15 and init_by_array(), were declared static, wrapped in 16 Python calling/return code. also, their global data 17 references were replaced with structure references. 18 19 * unused functions from the original were deleted. 20 new, original C python code was added to implement the 21 Random() interface. 22 22 23 23 The following are the verbatim comments from the original code: … … 37 37 38 38 1. Redistributions of source code must retain the above copyright 39 39 notice, this list of conditions and the following disclaimer. 40 40 41 41 2. Redistributions in binary form must reproduce the above copyright 42 43 42 notice, this list of conditions and the following disclaimer in the 43 documentation and/or other materials provided with the distribution. 44 44 45 45 3. The names of its contributors may not be used to endorse or promote 46 47 46 products derived from this software without specific prior written 47 permission. 48 48 49 49 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS … … 68 68 69 69 #include "Python.h" 70 #include <time.h> 70 #include <time.h> /* for seeding to current time */ 71 71 72 72 /* Period parameters -- These are all magic. Don't change. */ 73 73 #define N 624 74 74 #define M 397 75 #define MATRIX_A 0x9908b0dfUL 75 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ 76 76 #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ 77 77 #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ 78 78 79 79 typedef struct { 80 81 82 80 PyObject_HEAD 81 unsigned long state[N]; 82 int index; 83 83 } RandomObject; 84 84 85 85 static PyTypeObject Random_Type; 86 86 87 #define RandomObject_Check(v) 87 #define RandomObject_Check(v) (Py_TYPE(v) == &Random_Type) 88 88 89 89 … … 95 95 genrand_int32(RandomObject *self) 96 96 { 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 97 unsigned long y; 98 static unsigned long mag01[2]={0x0UL, MATRIX_A}; 99 /* mag01[x] = x * MATRIX_A for x=0,1 */ 100 unsigned long *mt; 101 102 mt = self->state; 103 if (self->index >= N) { /* generate N words at one time */ 104 int kk; 105 106 for (kk=0;kk<N-M;kk++) { 107 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); 108 mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL]; 109 } 110 for (;kk<N-1;kk++) { 111 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); 112 mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; 113 } 114 y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); 115 mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 116 117 self->index = 0; 118 } 119 119 120 120 y = mt[self->index++]; … … 138 138 random_random(RandomObject *self) 139 139 { 140 141 140 unsigned long a=genrand_int32(self)>>5, b=genrand_int32(self)>>6; 141 return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0)); 142 142 } 143 143 … … 146 146 init_genrand(RandomObject *self, unsigned long s) 147 147 { 148 149 150 151 152 153 154 155 156 157 158 /* only MSBs of the array mt[].*/159 /* 2002/01/09 modified by Makoto Matsumoto*/160 161 162 163 164 148 int mti; 149 unsigned long *mt; 150 151 mt = self->state; 152 mt[0]= s & 0xffffffffUL; 153 for (mti=1; mti<N; mti++) { 154 mt[mti] = 155 (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 156 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 157 /* In the previous versions, MSBs of the seed affect */ 158 /* only MSBs of the array mt[]. */ 159 /* 2002/01/09 modified by Makoto Matsumoto */ 160 mt[mti] &= 0xffffffffUL; 161 /* for >32 bit machines */ 162 } 163 self->index = mti; 164 return; 165 165 } 166 166 … … 171 171 init_by_array(RandomObject *self, unsigned long init_key[], unsigned long key_length) 172 172 { 173 unsigned int i, j, k;/* was signed in the original code. RDH 12/16/2002 */174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 173 unsigned int i, j, k; /* was signed in the original code. RDH 12/16/2002 */ 174 unsigned long *mt; 175 176 mt = self->state; 177 init_genrand(self, 19650218UL); 178 i=1; j=0; 179 k = (N>key_length ? N : key_length); 180 for (; k; k--) { 181 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) 182 + init_key[j] + j; /* non linear */ 183 mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 184 i++; j++; 185 if (i>=N) { mt[0] = mt[N-1]; i=1; } 186 if (j>=key_length) j=0; 187 } 188 for (k=N-1; k; k--) { 189 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) 190 - i; /* non linear */ 191 mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 192 i++; 193 if (i>=N) { mt[0] = mt[N-1]; i=1; } 194 } 195 195 196 196 mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ … … 207 207 random_seed(RandomObject *self, PyObject *args) 208 208 { 209 PyObject *result = NULL;/* guilty until proved innocent */210 211 212 213 214 unsigned long keymax;/* # of allocated slots in key */215 unsigned long keyused;/* # of used slots in key */216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 keymax = 8;/* arbitrary; grows later if needed */254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 209 PyObject *result = NULL; /* guilty until proved innocent */ 210 PyObject *masklower = NULL; 211 PyObject *thirtytwo = NULL; 212 PyObject *n = NULL; 213 unsigned long *key = NULL; 214 unsigned long keymax; /* # of allocated slots in key */ 215 unsigned long keyused; /* # of used slots in key */ 216 int err; 217 218 PyObject *arg = NULL; 219 220 if (!PyArg_UnpackTuple(args, "seed", 0, 1, &arg)) 221 return NULL; 222 223 if (arg == NULL || arg == Py_None) { 224 time_t now; 225 226 time(&now); 227 init_genrand(self, (unsigned long)now); 228 Py_INCREF(Py_None); 229 return Py_None; 230 } 231 /* If the arg is an int or long, use its absolute value; else use 232 * the absolute value of its hash code. 233 */ 234 if (PyInt_Check(arg) || PyLong_Check(arg)) 235 n = PyNumber_Absolute(arg); 236 else { 237 long hash = PyObject_Hash(arg); 238 if (hash == -1) 239 goto Done; 240 n = PyLong_FromUnsignedLong((unsigned long)hash); 241 } 242 if (n == NULL) 243 goto Done; 244 245 /* Now split n into 32-bit chunks, from the right. Each piece is 246 * stored into key, which has a capacity of keymax chunks, of which 247 * keyused are filled. Alas, the repeated shifting makes this a 248 * quadratic-time algorithm; we'd really like to use 249 * _PyLong_AsByteArray here, but then we'd have to break into the 250 * long representation to figure out how big an array was needed 251 * in advance. 252 */ 253 keymax = 8; /* arbitrary; grows later if needed */ 254 keyused = 0; 255 key = (unsigned long *)PyMem_Malloc(keymax * sizeof(*key)); 256 if (key == NULL) 257 goto Done; 258 259 masklower = PyLong_FromUnsignedLong(0xffffffffU); 260 if (masklower == NULL) 261 goto Done; 262 thirtytwo = PyInt_FromLong(32L); 263 if (thirtytwo == NULL) 264 goto Done; 265 while ((err=PyObject_IsTrue(n))) { 266 PyObject *newn; 267 PyObject *pychunk; 268 unsigned long chunk; 269 270 if (err == -1) 271 goto Done; 272 pychunk = PyNumber_And(n, masklower); 273 if (pychunk == NULL) 274 goto Done; 275 chunk = PyLong_AsUnsignedLong(pychunk); 276 Py_DECREF(pychunk); 277 if (chunk == (unsigned long)-1 && PyErr_Occurred()) 278 goto Done; 279 newn = PyNumber_Rshift(n, thirtytwo); 280 if (newn == NULL) 281 goto Done; 282 Py_DECREF(n); 283 n = newn; 284 if (keyused >= keymax) { 285 unsigned long bigger = keymax << 1; 286 if ((bigger >> 1) != keymax) { 287 PyErr_NoMemory(); 288 goto Done; 289 } 290 key = (unsigned long *)PyMem_Realloc(key, 291 bigger * sizeof(*key)); 292 if (key == NULL) 293 goto Done; 294 keymax = bigger; 295 } 296 assert(keyused < keymax); 297 key[keyused++] = chunk; 298 } 299 300 if (keyused == 0) 301 key[keyused++] = 0UL; 302 result = init_by_array(self, key, keyused); 303 303 Done: 304 305 306 307 308 304 Py_XDECREF(masklower); 305 Py_XDECREF(thirtytwo); 306 Py_XDECREF(n); 307 PyMem_Free(key); 308 return result; 309 309 } 310 310 … … 312 312 random_getstate(RandomObject *self) 313 313 { 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 314 PyObject *state; 315 PyObject *element; 316 int i; 317 318 state = PyTuple_New(N+1); 319 if (state == NULL) 320 return NULL; 321 for (i=0; i<N ; i++) { 322 element = PyLong_FromUnsignedLong(self->state[i]); 323 if (element == NULL) 324 goto Fail; 325 PyTuple_SET_ITEM(state, i, element); 326 } 327 element = PyLong_FromLong((long)(self->index)); 328 if (element == NULL) 329 goto Fail; 330 PyTuple_SET_ITEM(state, i, element); 331 return state; 332 332 333 333 Fail: 334 335 334 Py_DECREF(state); 335 return NULL; 336 336 } 337 337 … … 339 339 random_setstate(RandomObject *self, PyObject *state) 340 340 { 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 341 int i; 342 unsigned long element; 343 long index; 344 345 if (!PyTuple_Check(state)) { 346 PyErr_SetString(PyExc_TypeError, 347 "state vector must be a tuple"); 348 return NULL; 349 } 350 if (PyTuple_Size(state) != N+1) { 351 PyErr_SetString(PyExc_ValueError, 352 "state vector is the wrong size"); 353 return NULL; 354 } 355 356 for (i=0; i<N ; i++) { 357 element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i)); 358 if (element == (unsigned long)-1 && PyErr_Occurred()) 359 return NULL; 360 self->state[i] = element & 0xffffffffUL; /* Make sure we get sane state */ 361 } 362 363 index = PyLong_AsLong(PyTuple_GET_ITEM(state, i)); 364 if (index == -1 && PyErr_Occurred()) 365 return NULL; 366 self->index = (int)index; 367 368 Py_INCREF(Py_None); 369 return Py_None; 370 370 } 371 371 … … 390 390 391 391 Finally, the self->index value is set to N so that the generator itself 392 kicks in on the next call to random(). 392 kicks in on the next call to random(). This assures that all results 393 393 have been through the generator and do not just reflect alterations to 394 394 the underlying state. … … 398 398 random_jumpahead(RandomObject *self, PyObject *n) 399 399 { 400 long i, j; 401 PyObject *iobj; 402 PyObject *remobj; 403 unsigned long *mt, tmp; 404 405 if (!PyInt_Check(n) && !PyLong_Check(n)) { 406 PyErr_Format(PyExc_TypeError, "jumpahead requires an " 407 "integer, not '%s'", 408 Py_TYPE(n)->tp_name); 409 return NULL; 410 } 411 412 mt = self->state; 413 for (i = N-1; i > 1; i--) { 414 iobj = PyInt_FromLong(i); 415 if (iobj == NULL) 416 return NULL; 417 remobj = PyNumber_Remainder(n, iobj); 418 Py_DECREF(iobj); 419 if (remobj == NULL) 420 return NULL; 421 j = PyInt_AsLong(remobj); 422 Py_DECREF(remobj); 423 if (j == -1L && PyErr_Occurred()) 424 return NULL; 425 tmp = mt[i]; 426 mt[i] = mt[j]; 427 mt[j] = tmp; 428 } 429 430 for (i = 0; i < N; i++) 431 mt[i] += i+1; 432 433 self->index = N; 434 Py_INCREF(Py_None); 435 return Py_None; 400 long i, j; 401 PyObject *iobj; 402 PyObject *remobj; 403 unsigned long *mt, tmp, nonzero; 404 405 if (!PyInt_Check(n) && !PyLong_Check(n)) { 406 PyErr_Format(PyExc_TypeError, "jumpahead requires an " 407 "integer, not '%s'", 408 Py_TYPE(n)->tp_name); 409 return NULL; 410 } 411 412 mt = self->state; 413 for (i = N-1; i > 1; i--) { 414 iobj = PyInt_FromLong(i); 415 if (iobj == NULL) 416 return NULL; 417 remobj = PyNumber_Remainder(n, iobj); 418 Py_DECREF(iobj); 419 if (remobj == NULL) 420 return NULL; 421 j = PyInt_AsLong(remobj); 422 Py_DECREF(remobj); 423 if (j == -1L && PyErr_Occurred()) 424 return NULL; 425 tmp = mt[i]; 426 mt[i] = mt[j]; 427 mt[j] = tmp; 428 } 429 430 nonzero = 0; 431 for (i = 1; i < N; i++) { 432 mt[i] += i+1; 433 mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 434 nonzero |= mt[i]; 435 } 436 437 /* Ensure the state is nonzero: in the unlikely event that mt[1] through 438 mt[N-1] are all zero, set the MSB of mt[0] (see issue #14591). In the 439 normal case, we fall back to the pre-issue 14591 behaviour for mt[0]. */ 440 if (nonzero) { 441 mt[0] += 1; 442 mt[0] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 443 } 444 else { 445 mt[0] = 0x80000000UL; 446 } 447 448 self->index = N; 449 Py_INCREF(Py_None); 450 return Py_None; 436 451 } 437 452 … … 439 454 random_getrandbits(RandomObject *self, PyObject *args) 440 455 { 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 456 int k, i, bytes; 457 unsigned long r; 458 unsigned char *bytearray; 459 PyObject *result; 460 461 if (!PyArg_ParseTuple(args, "i:getrandbits", &k)) 462 return NULL; 463 464 if (k <= 0) { 465 PyErr_SetString(PyExc_ValueError, 466 "number of bits must be greater than zero"); 467 return NULL; 468 } 469 470 bytes = ((k - 1) / 32 + 1) * 4; 471 bytearray = (unsigned char *)PyMem_Malloc(bytes); 472 if (bytearray == NULL) { 473 PyErr_NoMemory(); 474 return NULL; 475 } 476 477 /* Fill-out whole words, byte-by-byte to avoid endianness issues */ 478 for (i=0 ; i<bytes ; i+=4, k-=32) { 479 r = genrand_int32(self); 480 if (k < 32) 481 r >>= (32 - k); 482 bytearray[i+0] = (unsigned char)r; 483 bytearray[i+1] = (unsigned char)(r >> 8); 484 bytearray[i+2] = (unsigned char)(r >> 16); 485 bytearray[i+3] = (unsigned char)(r >> 24); 486 } 487 488 /* little endian order to match bytearray assignment order */ 489 result = _PyLong_FromByteArray(bytearray, bytes, 1, 0); 490 PyMem_Free(bytearray); 491 return result; 477 492 } 478 493 … … 480 495 random_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 481 496 { 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 497 RandomObject *self; 498 PyObject *tmp; 499 500 if (type == &Random_Type && !_PyArg_NoKeywords("Random()", kwds)) 501 return NULL; 502 503 self = (RandomObject *)type->tp_alloc(type, 0); 504 if (self == NULL) 505 return NULL; 506 tmp = random_seed(self, args); 507 if (tmp == NULL) { 508 Py_DECREF(self); 509 return NULL; 510 } 511 Py_DECREF(tmp); 512 return (PyObject *)self; 498 513 } 499 514 500 515 static PyMethodDef random_methods[] = { 501 {"random",(PyCFunction)random_random, METH_NOARGS,502 503 {"seed",(PyCFunction)random_seed, METH_VARARGS,504 505 {"getstate",(PyCFunction)random_getstate, METH_NOARGS,506 507 {"setstate",(PyCFunction)random_setstate, METH_O,508 509 {"jumpahead", (PyCFunction)random_jumpahead,METH_O,510 511 512 {"getrandbits",(PyCFunction)random_getrandbits, METH_VARARGS,513 514 515 {NULL, NULL}/* sentinel */516 {"random", (PyCFunction)random_random, METH_NOARGS, 517 PyDoc_STR("random() -> x in the interval [0, 1).")}, 518 {"seed", (PyCFunction)random_seed, METH_VARARGS, 519 PyDoc_STR("seed([n]) -> None. Defaults to current time.")}, 520 {"getstate", (PyCFunction)random_getstate, METH_NOARGS, 521 PyDoc_STR("getstate() -> tuple containing the current state.")}, 522 {"setstate", (PyCFunction)random_setstate, METH_O, 523 PyDoc_STR("setstate(state) -> None. Restores generator state.")}, 524 {"jumpahead", (PyCFunction)random_jumpahead, METH_O, 525 PyDoc_STR("jumpahead(int) -> None. Create new state from " 526 "existing state and integer.")}, 527 {"getrandbits", (PyCFunction)random_getrandbits, METH_VARARGS, 528 PyDoc_STR("getrandbits(k) -> x. Generates a long int with " 529 "k random bits.")}, 530 {NULL, NULL} /* sentinel */ 516 531 }; 517 532 … … 520 535 521 536 static PyTypeObject Random_Type = { 522 523 "_random.Random",/*tp_name*/524 sizeof(RandomObject),/*tp_basicsize*/525 0,/*tp_itemsize*/526 527 0,/*tp_dealloc*/528 0,/*tp_print*/529 0,/*tp_getattr*/530 0,/*tp_setattr*/531 0,/*tp_compare*/532 0,/*tp_repr*/533 0,/*tp_as_number*/534 0,/*tp_as_sequence*/535 0,/*tp_as_mapping*/536 0,/*tp_hash*/537 0,/*tp_call*/538 0,/*tp_str*/539 PyObject_GenericGetAttr,/*tp_getattro*/540 0,/*tp_setattro*/541 0,/*tp_as_buffer*/542 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/*tp_flags*/543 random_doc,/*tp_doc*/544 0,/*tp_traverse*/545 0,/*tp_clear*/546 0,/*tp_richcompare*/547 0,/*tp_weaklistoffset*/548 0,/*tp_iter*/549 0,/*tp_iternext*/550 random_methods,/*tp_methods*/551 0,/*tp_members*/552 0,/*tp_getset*/553 0,/*tp_base*/554 0,/*tp_dict*/555 0,/*tp_descr_get*/556 0,/*tp_descr_set*/557 0,/*tp_dictoffset*/558 0,/*tp_init*/559 0,/*tp_alloc*/560 random_new,/*tp_new*/561 _PyObject_Del,/*tp_free*/562 0,/*tp_is_gc*/537 PyVarObject_HEAD_INIT(NULL, 0) 538 "_random.Random", /*tp_name*/ 539 sizeof(RandomObject), /*tp_basicsize*/ 540 0, /*tp_itemsize*/ 541 /* methods */ 542 0, /*tp_dealloc*/ 543 0, /*tp_print*/ 544 0, /*tp_getattr*/ 545 0, /*tp_setattr*/ 546 0, /*tp_compare*/ 547 0, /*tp_repr*/ 548 0, /*tp_as_number*/ 549 0, /*tp_as_sequence*/ 550 0, /*tp_as_mapping*/ 551 0, /*tp_hash*/ 552 0, /*tp_call*/ 553 0, /*tp_str*/ 554 PyObject_GenericGetAttr, /*tp_getattro*/ 555 0, /*tp_setattro*/ 556 0, /*tp_as_buffer*/ 557 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 558 random_doc, /*tp_doc*/ 559 0, /*tp_traverse*/ 560 0, /*tp_clear*/ 561 0, /*tp_richcompare*/ 562 0, /*tp_weaklistoffset*/ 563 0, /*tp_iter*/ 564 0, /*tp_iternext*/ 565 random_methods, /*tp_methods*/ 566 0, /*tp_members*/ 567 0, /*tp_getset*/ 568 0, /*tp_base*/ 569 0, /*tp_dict*/ 570 0, /*tp_descr_get*/ 571 0, /*tp_descr_set*/ 572 0, /*tp_dictoffset*/ 573 0, /*tp_init*/ 574 0, /*tp_alloc*/ 575 random_new, /*tp_new*/ 576 _PyObject_Del, /*tp_free*/ 577 0, /*tp_is_gc*/ 563 578 }; 564 579 … … 569 584 init_random(void) 570 585 { 571 572 573 574 575 576 577 578 579 580 } 586 PyObject *m; 587 588 if (PyType_Ready(&Random_Type) < 0) 589 return; 590 m = Py_InitModule3("_random", NULL, module_doc); 591 if (m == NULL) 592 return; 593 Py_INCREF(&Random_Type); 594 PyModule_AddObject(m, "Random", (PyObject *)&Random_Type); 595 }
Note:
See TracChangeset
for help on using the changeset viewer.