@@ -130,6 +130,33 @@ static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*);
130
130
// string conversion work the same in all circumstances).
131
131
132
132
#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
+
133
160
#if PY_VERSION_HEX >= 0x030C00A5
134
161
#define __Pyx_PyLong_Digits (x ) (((PyLongObject*)x)->long_value.ob_digit)
135
162
#else
@@ -413,14 +440,12 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
413
440
#endif
414
441
if (likely (PyLong_CheckExact (b ))) {
415
442
#if CYTHON_USE_PYLONG_INTERNALS
416
- const digit * digits = __Pyx_PyLong_Digits (b );
417
- const Py_ssize_t size = Py_SIZE (b );
418
443
// 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 );
423
446
} else {
447
+ const digit * digits = __Pyx_PyLong_Digits (b );
448
+ const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount (b );
424
449
switch (size ) {
425
450
{{for _size in (2 , 3 , 4 )}}
426
451
{{for _case in (_size , - _size )}}
@@ -486,24 +511,12 @@ static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj) {
486
511
double val ;
487
512
if (PyLong_CheckExact (obj )) {
488
513
#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 ;
503
517
}
504
- #else
505
- val = PyLong_AsDouble (obj );
506
518
#endif
519
+ val = PyLong_AsDouble (obj );
507
520
} else if (PyUnicode_CheckExact (obj )) {
508
521
val = __Pyx_PyUnicode_AsDouble (obj );
509
522
} else if (PyBytes_CheckExact (obj )) {
@@ -976,24 +989,31 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
976
989
if (likely (PyLong_Check (x ))) {
977
990
if (is_unsigned ) {
978
991
#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
+ }
990
1010
}
991
- }
992
- break ;
993
- {{ endfor } }
1011
+ break ;
1012
+ {{ endfor }}
1013
+ }
994
1014
}
995
1015
#endif
996
- #if CYTHON_COMPILING_IN_CPYTHON
1016
+ #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
997
1017
if (unlikely (Py_SIZE (x ) < 0 )) {
998
1018
goto raise_neg_overflow ;
999
1019
}
@@ -1017,24 +1037,26 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
1017
1037
} else {
1018
1038
// signed
1019
1039
#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
+ }
1033
1055
}
1034
- }
1035
- break ;
1036
- {{endfor }}
1037
- {{ endfor } }
1056
+ break ;
1057
+ {{ endfor }}
1058
+ {{endfor }}
1059
+ }
1038
1060
}
1039
1061
#endif
1040
1062
if ((sizeof ({{TYPE }}) <= sizeof (long))) {
0 commit comments