@@ -130,6 +130,33 @@ static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*);
130130// string conversion work the same in all circumstances).
131131
132132#if CYTHON_USE_PYLONG_INTERNALS
133+ #if PY_VERSION_HEX >= 0x030C00A7
134+ #define __Pyx_PyLong_Sign (x ) (((PyLongObject*)x)->long_value.lv_tag & 3)
135+ #define __Pyx_PyLong_IsNeg (x ) ((__Pyx_PyLong_Sign(x) & 2) != 0)
136+ #define __Pyx_PyLong_IsNonNeg (x ) (!__Pyx_PyLong_IsNeg(x))
137+ #define __Pyx_PyLong_IsZero (x ) (__Pyx_PyLong_Sign(x) & 1)
138+ #define __Pyx_PyLong_IsPos (x ) (__Pyx_PyLong_Sign(x) == 0)
139+ #define __Pyx_PyLong_IsCompact (x ) (((PyLongObject*)x)->long_value.lv_tag < (2 << 3)) // (2 << NON_SIZE_BITS)
140+ #define __Pyx_PyLong_CompactValue (x ) ((1 - __Pyx_PyLong_Sign(x)) * (Py_ssize_t) __Pyx_PyLong_Digits(x)[0])
141+ #define __Pyx_PyLong_CompactValueUnsigned (x ) (__Pyx_PyLong_Digits(x)[0])
142+ #define __Pyx_PyLong_DigitCount (x ) (((PyLongObject*)x)->long_value.lv_tag >> 3) // (>> NON_SIZE_BITS)
143+ #define __Pyx_PyLong_SignedDigitCount (x ) \
144+ ((1 - ((PyLongObject*)x)->long_value.lv_tag & 3) * (((PyLongObject*)x)->long_value.lv_tag >> 3)) // (>> NON_SIZE_BITS)
145+ #else // Py < 3.12
146+ #define __Pyx_PyLong_IsNeg (x ) (Py_SIZE(x) < 0)
147+ #define __Pyx_PyLong_IsNonNeg (x ) (Py_SIZE(x) >= 0)
148+ #define __Pyx_PyLong_IsZero (x ) (Py_SIZE(x) == 0)
149+ #define __Pyx_PyLong_IsPos (x ) (Py_SIZE(x) > 0)
150+ #define __Pyx_PyLong_IsCompact (x ) (Py_SIZE(x) == 0 || Py_SIZE(x) == 1 || Py_SIZE(x) == -1)
151+ #define __Pyx_PyLong_CompactValue (x ) \
152+ ((Py_SIZE(x) == 0) ? (sdigit) 0 : ((Py_SIZE(x) < 0) ? -(sdigit)__Pyx_PyLong_Digits(x)[0] : (sdigit)__Pyx_PyLong_Digits(x)[0]))
153+ #define __Pyx_PyLong_CompactValueUnsigned (x ) ((Py_SIZE(x) == 0) ? 0 : __Pyx_PyLong_Digits(x)[0])
154+ #define __Pyx_PyLong_DigitCount (x ) __Pyx_sst_abs(Py_SIZE(x))
155+ #define __Pyx_PyLong_SignedDigitCount (x ) Py_SIZE(x)
156+ #endif
157+
158+ typedef sdigit __Pyx_compact_pylong ;
159+
133160 #if PY_VERSION_HEX >= 0x030C00A5
134161 #define __Pyx_PyLong_Digits (x ) (((PyLongObject*)x)->long_value.ob_digit)
135162 #else
@@ -413,14 +440,12 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
413440#endif
414441 if (likely (PyLong_CheckExact (b ))) {
415442 #if CYTHON_USE_PYLONG_INTERNALS
416- const digit * digits = __Pyx_PyLong_Digits (b );
417- const Py_ssize_t size = Py_SIZE (b );
418443 // handle most common case first to avoid indirect branch and optimise branch prediction
419- if (likely (__Pyx_sst_abs (size ) <= 1 )) {
420- ival = likely (size ) ? digits [0 ] : 0 ;
421- if (size == -1 ) ival = - ival ;
422- return ival ;
444+ if (likely (__Pyx_PyLong_IsCompact (b ))) {
445+ return __Pyx_PyLong_CompactValue (b );
423446 } else {
447+ const digit * digits = __Pyx_PyLong_Digits (b );
448+ const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount (b );
424449 switch (size ) {
425450 {{for _size in (2 , 3 , 4 )}}
426451 {{for _case in (_size , - _size )}}
@@ -486,24 +511,12 @@ static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj) {
486511 double val ;
487512 if (PyLong_CheckExact (obj )) {
488513#if CYTHON_USE_PYLONG_INTERNALS
489- const digit * digits = __Pyx_PyLong_Digits (obj );
490- switch (Py_SIZE (obj )) {
491- case 0 :
492- val = 0.0 ;
493- goto no_error ;
494- // single digit PyLong values always cast safely to double
495- case 1 :
496- val = (double ) digits [0 ];
497- goto no_error ;
498- case -1 :
499- val = (double ) - (sdigit ) digits [0 ];
500- goto no_error ;
501- default :
502- val = PyLong_AsDouble (obj );
514+ if (likely (__Pyx_PyLong_IsCompact (obj ))) {
515+ val = (double ) __Pyx_PyLong_CompactValue (obj );
516+ goto no_error ;
503517 }
504- #else
505- val = PyLong_AsDouble (obj );
506518#endif
519+ val = PyLong_AsDouble (obj );
507520 } else if (PyUnicode_CheckExact (obj )) {
508521 val = __Pyx_PyUnicode_AsDouble (obj );
509522 } else if (PyBytes_CheckExact (obj )) {
@@ -976,24 +989,31 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
976989 if (likely (PyLong_Check (x ))) {
977990 if (is_unsigned ) {
978991#if CYTHON_USE_PYLONG_INTERNALS
979- const digit * digits = __Pyx_PyLong_Digits (x );
980- switch (Py_SIZE (x )) {
981- case 0 : return ({{TYPE }}) 0 ;
982- case 1 : __PYX_VERIFY_RETURN_INT ({{TYPE }}, digit , digits [0 ])
983- {{for _size in (2 , 3 , 4 )}}
984- case {{_size }}:
985- if ((8 * sizeof ({{TYPE }}) > {{_size - 1 }} * PyLong_SHIFT )) {
986- if ((8 * sizeof (unsigned long ) > {{_size }} * PyLong_SHIFT )) {
987- __PYX_VERIFY_RETURN_INT ({{TYPE }}, unsigned long , {{pylong_join (_size , 'digits' )}})
988- } else if ((8 * sizeof ({{TYPE }}) >= {{_size }} * PyLong_SHIFT )) {
989- return ({{TYPE }}) {{pylong_join (_size , 'digits' , TYPE )}};
992+ if (unlikely (__Pyx_PyLong_IsNeg (x ))) {
993+ goto raise_neg_overflow ;
994+ //} else if (__Pyx_PyLong_IsZero(x)) {
995+ // return ({{TYPE}}) 0;
996+ } else if (__Pyx_PyLong_IsCompact (x )) {
997+ __PYX_VERIFY_RETURN_INT ({{TYPE }}, __Pyx_compact_pylong , __Pyx_PyLong_CompactValueUnsigned (x ))
998+ } else {
999+ const digit * digits = __Pyx_PyLong_Digits (x );
1000+ assert (__Pyx_PyLong_DigitCount (x ) > 1 );
1001+ switch (__Pyx_PyLong_DigitCount (x )) {
1002+ {{for _size in (2 , 3 , 4 )}}
1003+ case {{_size }}:
1004+ if ((8 * sizeof ({{TYPE }}) > {{_size - 1 }} * PyLong_SHIFT )) {
1005+ if ((8 * sizeof (unsigned long ) > {{_size }} * PyLong_SHIFT )) {
1006+ __PYX_VERIFY_RETURN_INT ({{TYPE }}, unsigned long , {{pylong_join (_size , 'digits' )}})
1007+ } else if ((8 * sizeof ({{TYPE }}) >= {{_size }} * PyLong_SHIFT )) {
1008+ return ({{TYPE }}) {{pylong_join (_size , 'digits' , TYPE )}};
1009+ }
9901010 }
991- }
992- break ;
993- {{ endfor } }
1011+ break ;
1012+ {{ endfor }}
1013+ }
9941014 }
9951015#endif
996- #if CYTHON_COMPILING_IN_CPYTHON
1016+ #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
9971017 if (unlikely (Py_SIZE (x ) < 0 )) {
9981018 goto raise_neg_overflow ;
9991019 }
@@ -1017,24 +1037,26 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
10171037 } else {
10181038 // signed
10191039#if CYTHON_USE_PYLONG_INTERNALS
1020- const digit * digits = __Pyx_PyLong_Digits (x );
1021- switch (Py_SIZE (x )) {
1022- case 0 : return ({{TYPE }}) 0 ;
1023- case -1 : __PYX_VERIFY_RETURN_INT ({{TYPE }}, sdigit , (sdigit ) (- (sdigit )digits [0 ]))
1024- case 1 : __PYX_VERIFY_RETURN_INT ({{TYPE }}, digit , + digits [0 ])
1025- {{for _size in (2 , 3 , 4 )}}
1026- {{for _case in (- _size , _size )}}
1027- case {{_case }}:
1028- if ((8 * sizeof ({{TYPE }}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT)) {
1029- if ((8 * sizeof (unsigned long) > {{_size }} * PyLong_SHIFT )) {
1030- __PYX_VERIFY_RETURN_INT ({{TYPE }}, {{' long ' if _case < 0 else ' unsigned long '}}, {{' - (long ) ' if _case < 0 else ' '}}{{pylong_join(_size, ' digits ')}})
1031- } else if ((8 * sizeof ({{TYPE }}) - 1 > {{_size }} * PyLong_SHIFT )) {
1032- return ({{TYPE }}) ({{'((%s)-1)*' % TYPE if _case < 0 else ''}}{{pylong_join(_size, ' digits ', TYPE)}});
1040+ if (__Pyx_PyLong_IsCompact (x )) {
1041+ __PYX_VERIFY_RETURN_INT ({{TYPE }}, __Pyx_compact_pylong , __Pyx_PyLong_CompactValue (x ))
1042+ } else {
1043+ const digit * digits = __Pyx_PyLong_Digits (x );
1044+ assert (__Pyx_PyLong_DigitCount (x ) > 1 );
1045+ switch (__Pyx_PyLong_SignedDigitCount (x )) {
1046+ {{for _size in (2 , 3 , 4 )}}
1047+ {{for _case in (- _size , _size )}}
1048+ case {{_case }}:
1049+ if ((8 * sizeof ({{TYPE }}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT)) {
1050+ if ((8 * sizeof (unsigned long) > {{_size }} * PyLong_SHIFT )) {
1051+ __PYX_VERIFY_RETURN_INT ({{TYPE }}, {{' long ' if _case < 0 else ' unsigned long '}}, {{' - (long ) ' if _case < 0 else ' '}}{{pylong_join(_size, ' digits ')}})
1052+ } else if ((8 * sizeof ({{TYPE }}) - 1 > {{_size }} * PyLong_SHIFT )) {
1053+ return ({{TYPE }}) ({{'((%s)-1)*' % TYPE if _case < 0 else ''}}{{pylong_join(_size, ' digits ', TYPE)}});
1054+ }
10331055 }
1034- }
1035- break ;
1036- {{endfor }}
1037- {{ endfor } }
1056+ break ;
1057+ {{ endfor }}
1058+ {{endfor }}
1059+ }
10381060 }
10391061#endif
10401062 if ((sizeof ({{TYPE }}) <= sizeof (long))) {
0 commit comments