File tree Expand file tree Collapse file tree 1 file changed +23
-8
lines changed Expand file tree Collapse file tree 1 file changed +23
-8
lines changed Original file line number Diff line number Diff line change @@ -584,21 +584,36 @@ double CPyTagged_TrueDivide(CPyTagged x, CPyTagged y) {
584584
585585// int.bit_length()
586586CPyTagged CPyTagged_BitLength (CPyTagged self ) {
587+ // Handle zero
588+ if (self == 0 ) {
589+ return 0 ;
590+ }
591+
592+ // Fast path for small (tagged) ints
593+ if (CPyTagged_CheckShort (self )) {
594+ Py_ssize_t val = CPyTagged_ShortAsSsize_t (self );
595+ Py_ssize_t absval = val < 0 ? - val : val ;
596+ int bits = 0 ;
597+ while (absval ) {
598+ absval >>= 1 ;
599+ bits ++ ;
600+ }
601+ return bits << 1 ;
602+ }
603+
604+ // Slow path for big ints
587605 PyObject * pyint = CPyTagged_StealAsObject (self );
588606 if (!PyLong_Check (pyint )) {
589607 Py_DECREF (pyint );
590608 PyErr_SetString (PyExc_TypeError , "self must be int" );
591609 return CPY_INT_TAG ;
592610 }
593- PyObject * res = PyObject_CallMethod ( pyint , "bit_length" , NULL );
611+ int bits = _PyLong_NumBits (( PyLongObject * ) pyint );
594612 Py_DECREF (pyint );
595- if (!res ) {
596- return CPY_INT_TAG ;
597- }
598- long value = PyLong_AsLong (res );
599- Py_DECREF (res );
600- if (value == -1 && PyErr_Occurred ()) {
613+ if (bits < 0 ) {
614+ // _PyLong_NumBits sets an error on failure
601615 return CPY_INT_TAG ;
602616 }
603- return value << 1 ;
617+ return bits << 1 ;
604618}
619+
You can’t perform that action at this time.
0 commit comments