1 针对int类型数据的处理
总所周之PyIntObject中int是按照c语言中的long进行存储的,其支持字符,字符串,long, size_t等各种数据类型转换。
1.1)针对自身有效范围,单目运算的负号越界处理。
/* Integer overflow checking for unary negation: on a 2's-complement
* box, -x overflows iff x is the most negative long. In this case we
* get -x == x. However, -x is undefined (by C) if x /is/ the most
* negative long (it's a signed overflow case), and some compilers care.
* So we cast x to unsigned long first. However, then other compilers
* warn about applying unary minus to an unsigned operand. Hence the
* weird "0-".
*/
#define UNARY_NEG_WOULD_OVERFLOW(x) \
((x) < 0 && (unsigned long)(x) == 0-(unsigned long)(x))
1.2)从Ssize_t(signed long)和size_t(unsigned long)转换过来时,判断是否超过long的最大值表示范围(0x7fffffffffffffff~ -0x7fffffffffffffff -1L),超过则通过PyLongObject中的_PyLong_FromByteArray处理;
1.3)判断加法是否溢出; (x^a) >= 0 || (x^b) >= 0 (减法将b取负号处理)
详见: python整数各位相加_Python判断整数相加溢出_weixin_39911056的博客-CSDN博客
static PyObject *
int_add(PyIntObject *v, PyIntObject *w)
{
register long a, b, x;
CONVERT_TO_LONG(v, a);
CONVERT_TO_LONG(w, b);
x = a + b;
if ((x^a) >= 0 || (x^b) >= 0)
return PyInt_FromLong(x);
return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);
}
1.4)乘法溢出处理
通过正常的CPU指令去进行预算,溢出时进行比特级别的运算。(其中升到long和double位宽进行运输)
static PyObject *
int_mul(PyObject *v, PyObject *w)
{
long a, b;
long longprod; /* a*b in native long arithmetic */
double doubled_longprod; /* (double)longprod */
double doubleprod; /* (double)a * (double)b */
CONVERT_TO_LONG(v, a);
CONVERT_TO_LONG(w, b);
longprod = a * b;
doubleprod = (double)a * (double)b;
doubled_longprod = (double)longprod;
/* Fast path for normal case: small multiplicands, and no info
is lost in either method. */
if (doubled_longprod == doubleprod)
return PyInt_FromLong(longprod);
/* Somebody somewhere lost info. Close enough, or way off? Note
that a != 0 and b != 0 (else doubled_longprod == doubleprod == 0).
The difference either is or isn't significant compared to the
true value (of which doubleprod is a good approximation).
*/
{
const double diff = doubled_longprod - doubleprod;
const double absdiff = diff >= 0.0 ? diff : -diff;
const double absprod = doubleprod >= 0.0 ? doubleprod :
-doubleprod;
/* absdiff/absprod <= 1/32 iff
32 * absdiff <= absprod -- 5 good bits is "close enough" */
// An approximatation。
if (32.0 * absdiff <= absprod)
return PyInt_FromLong(longprod);
else
return PyLong_Type.tp_as_number->nb_multiply(v, w);
}
}