79
79
#define UPPER_MASK 0x80000000U /* most significant w-r bits */
80
80
#define LOWER_MASK 0x7fffffffU /* least significant r bits */
81
81
82
+ typedef struct {
83
+ PyObject * Random_Type ;
84
+ PyObject * Long___abs__ ;
85
+ } _randomstate ;
86
+
87
+ #define _randomstate (o ) ((_randomstate *)PyModule_GetState(o))
88
+
89
+ static struct PyModuleDef _randommodule ;
90
+
91
+ #define _randomstate_global _randomstate(PyState_FindModule(&_randommodule))
92
+
82
93
typedef struct {
83
94
PyObject_HEAD
84
95
int index ;
85
96
uint32_t state [N ];
86
97
} RandomObject ;
87
98
88
- static PyTypeObject Random_Type ;
89
-
90
- #define RandomObject_Check (v ) (Py_TYPE(v) == &Random_Type)
91
99
92
100
#include "clinic/_randommodule.c.h"
93
101
@@ -256,6 +264,7 @@ random_seed(RandomObject *self, PyObject *arg)
256
264
uint32_t * key = NULL ;
257
265
size_t bits , keyused ;
258
266
int res ;
267
+ PyObject * args [1 ];
259
268
260
269
if (arg == NULL || arg == Py_None ) {
261
270
if (random_seed_urandom (self ) < 0 ) {
@@ -272,10 +281,14 @@ random_seed(RandomObject *self, PyObject *arg)
272
281
* So: if the arg is a PyLong, use its absolute value.
273
282
* Otherwise use its hash value, cast to unsigned.
274
283
*/
275
- if (PyLong_Check (arg )) {
284
+ if (PyLong_CheckExact (arg )) {
285
+ n = PyNumber_Absolute (arg );
286
+ } else if (PyLong_Check (arg )) {
276
287
/* Calling int.__abs__() prevents calling arg.__abs__(), which might
277
288
return an invalid value. See issue #31478. */
278
- n = PyLong_Type .tp_as_number -> nb_absolute (arg );
289
+ args [0 ] = arg ;
290
+ n = _PyObject_Vectorcall (_randomstate_global -> Long___abs__ , args , 0 ,
291
+ NULL );
279
292
}
280
293
else {
281
294
Py_hash_t hash = PyObject_Hash (arg );
@@ -500,10 +513,12 @@ random_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
500
513
RandomObject * self ;
501
514
PyObject * tmp ;
502
515
503
- if (type == & Random_Type && !_PyArg_NoKeywords ("Random" , kwds ))
516
+ if (type == (PyTypeObject * )_randomstate_global -> Random_Type &&
517
+ !_PyArg_NoKeywords ("Random()" , kwds )) {
504
518
return NULL ;
519
+ }
505
520
506
- self = (RandomObject * )type -> tp_alloc (type , 0 );
521
+ self = (RandomObject * )PyType_GenericAlloc (type , 0 );
507
522
if (self == NULL )
508
523
return NULL ;
509
524
tmp = random_seed (self , args );
@@ -527,77 +542,97 @@ static PyMethodDef random_methods[] = {
527
542
PyDoc_STRVAR (random_doc ,
528
543
"Random() -> create a random number generator with its own internal state." );
529
544
530
- static PyTypeObject Random_Type = {
531
- PyVarObject_HEAD_INIT (NULL , 0 )
532
- "_random.Random" , /*tp_name*/
533
- sizeof (RandomObject ), /*tp_basicsize*/
534
- 0 , /*tp_itemsize*/
535
- /* methods */
536
- 0 , /*tp_dealloc*/
537
- 0 , /*tp_vectorcall_offset*/
538
- 0 , /*tp_getattr*/
539
- 0 , /*tp_setattr*/
540
- 0 , /*tp_as_async*/
541
- 0 , /*tp_repr*/
542
- 0 , /*tp_as_number*/
543
- 0 , /*tp_as_sequence*/
544
- 0 , /*tp_as_mapping*/
545
- 0 , /*tp_hash*/
546
- 0 , /*tp_call*/
547
- 0 , /*tp_str*/
548
- PyObject_GenericGetAttr , /*tp_getattro*/
549
- 0 , /*tp_setattro*/
550
- 0 , /*tp_as_buffer*/
551
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /*tp_flags*/
552
- random_doc , /*tp_doc*/
553
- 0 , /*tp_traverse*/
554
- 0 , /*tp_clear*/
555
- 0 , /*tp_richcompare*/
556
- 0 , /*tp_weaklistoffset*/
557
- 0 , /*tp_iter*/
558
- 0 , /*tp_iternext*/
559
- random_methods , /*tp_methods*/
560
- 0 , /*tp_members*/
561
- 0 , /*tp_getset*/
562
- 0 , /*tp_base*/
563
- 0 , /*tp_dict*/
564
- 0 , /*tp_descr_get*/
565
- 0 , /*tp_descr_set*/
566
- 0 , /*tp_dictoffset*/
567
- 0 , /*tp_init*/
568
- 0 , /*tp_alloc*/
569
- random_new , /*tp_new*/
570
- PyObject_Free , /*tp_free*/
571
- 0 , /*tp_is_gc*/
545
+ static PyType_Slot Random_Type_slots [] = {
546
+ {Py_tp_doc , random_doc },
547
+ {Py_tp_methods , random_methods },
548
+ {Py_tp_new , random_new },
549
+ {Py_tp_free , PyObject_Free },
550
+ {0 , 0 },
551
+ };
552
+
553
+ static PyType_Spec Random_Type_spec = {
554
+ "_random.Random" ,
555
+ sizeof (RandomObject ),
556
+ 0 ,
557
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
558
+ Random_Type_slots
572
559
};
573
560
574
561
PyDoc_STRVAR (module_doc ,
575
562
"Module implements the Mersenne Twister random number generator." );
576
563
564
+ static int
565
+ _random_traverse (PyObject * module , visitproc visit , void * arg )
566
+ {
567
+ Py_VISIT (_randomstate (module )-> Random_Type );
568
+ return 0 ;
569
+ }
570
+
571
+ static int
572
+ _random_clear (PyObject * module )
573
+ {
574
+ Py_CLEAR (_randomstate (module )-> Random_Type );
575
+ return 0 ;
576
+ }
577
+
578
+ static void
579
+ _random_free (void * module )
580
+ {
581
+ _random_clear ((PyObject * )module );
582
+ }
577
583
578
584
static struct PyModuleDef _randommodule = {
579
585
PyModuleDef_HEAD_INIT ,
580
586
"_random" ,
581
587
module_doc ,
582
- -1 ,
583
- NULL ,
588
+ sizeof (_randomstate ),
584
589
NULL ,
585
590
NULL ,
586
- NULL ,
587
- NULL
591
+ _random_traverse ,
592
+ _random_clear ,
593
+ _random_free ,
588
594
};
589
595
590
596
PyMODINIT_FUNC
591
597
PyInit__random (void )
592
598
{
593
599
PyObject * m ;
594
600
595
- if (PyType_Ready (& Random_Type ) < 0 )
601
+ PyObject * Random_Type = PyType_FromSpec (& Random_Type_spec );
602
+ if (Random_Type == NULL ) {
596
603
return NULL ;
604
+ }
605
+
597
606
m = PyModule_Create (& _randommodule );
598
- if (m == NULL )
607
+ if (m == NULL ) {
608
+ Py_DECREF (Random_Type );
599
609
return NULL ;
600
- Py_INCREF (& Random_Type );
601
- PyModule_AddObject (m , "Random" , (PyObject * )& Random_Type );
610
+ }
611
+ _randomstate (m )-> Random_Type = Random_Type ;
612
+
613
+ Py_INCREF (Random_Type );
614
+ PyModule_AddObject (m , "Random" , Random_Type );
615
+
616
+ /* Look up and save int.__abs__, which is needed in random_seed(). */
617
+ PyObject * longval = NULL , * longtype = NULL ;
618
+ longval = PyLong_FromLong (0 );
619
+ if (longval == NULL ) goto fail ;
620
+
621
+ longtype = PyObject_Type (longval );
622
+ if (longtype == NULL ) goto fail ;
623
+
624
+ PyObject * abs = PyObject_GetAttrString (longtype , "__abs__" );
625
+ if (abs == NULL ) goto fail ;
626
+
627
+ Py_DECREF (longtype );
628
+ Py_DECREF (longval );
629
+ _randomstate (m )-> Long___abs__ = abs ;
630
+
602
631
return m ;
632
+
633
+ fail :
634
+ Py_XDECREF (longtype );
635
+ Py_XDECREF (longval );
636
+ Py_DECREF (m );
637
+ return NULL ;
603
638
}
0 commit comments