@@ -43,8 +43,6 @@ typedef struct _longobject PyLongObject; /* Revealed in longintrepr.h */
4343 The allocation function takes care of allocating extra memory
4444 so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available.
4545
46- 内存分配函数要小心额外的内存,
47-
4846 CAUTION: Generic code manipulating subtypes of PyVarObject has to
4947 aware that ints abuse ob_size's sign bit.
5048
@@ -239,7 +237,6 @@ _PyLong_Init(void)
239237}
240238```
241239
242-
243240## 整数的存储结构
244241
245242`源文件:`[Objects/longobject.c](https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L1581)
@@ -293,3 +290,231 @@ print(num)
293290![ longobject storage] ( longobject_storage.png )
294291
295292注:这里的 30 是由 ** PyLong_SHIFT** 决定的,64位系统中,** PyLong_SHIFT** 为30,否则 ** PyLong_SHIFT** 为15
293+
294+ ## 整数对象的数值操作
295+
296+ 可以看到整数对象的数值操作较多,由于篇幅限制无法一一分析,这里只分析整数的部分方法
297+
298+ ` 源文件: ` [ Objects/longobject.c] ( https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L5341 )
299+
300+ ``` c
301+ // Objects/longobject.c
302+
303+ static PyNumberMethods long_as_number = {
304+ (binaryfunc)long_add, /*nb_add 加法 */
305+ (binaryfunc)long_sub, /*nb_subtract 减法 */
306+ (binaryfunc)long_mul, /*nb_multiply 乘法 */
307+ long_mod, /*nb_remainder 取余 */
308+ long_divmod, /*nb_divmod */
309+ long_pow, /*nb_power 求幂 */
310+ (unaryfunc)long_neg, /*nb_negative */
311+ (unaryfunc)long_long, /*tp_positive */
312+ (unaryfunc)long_abs, /*tp_absolute 绝对值 */
313+ (inquiry)long_bool, /*tp_bool 求bool值 */
314+ (unaryfunc)long_invert, /*nb_invert 反转 */
315+ long_lshift, /*nb_lshift 逻辑左移 */
316+ (binaryfunc)long_rshift, /*nb_rshift 逻辑右移 */
317+ long_and, /*nb_and 与操作 */
318+ long_xor, /*nb_xor 异或 */
319+ long_or, /*nb_or 或操作 */
320+ long_long, /*nb_int*/
321+ 0, /*nb_reserved*/
322+ long_float, /*nb_float*/
323+ 0, /* nb_inplace_add */
324+ 0, /* nb_inplace_subtract */
325+ 0, /* nb_inplace_multiply */
326+ 0, /* nb_inplace_remainder */
327+ 0, /* nb_inplace_power */
328+ 0, /* nb_inplace_lshift */
329+ 0, /* nb_inplace_rshift */
330+ 0, /* nb_inplace_and */
331+ 0, /* nb_inplace_xor */
332+ 0, /* nb_inplace_or */
333+ long_div, /* nb_floor_divide */
334+ long_true_divide, /* nb_true_divide */
335+ 0, /* nb_inplace_floor_divide */
336+ 0, /* nb_inplace_true_divide */
337+ long_long, /* nb_index */
338+ };
339+ ```
340+
341+ ### 整数相加
342+
343+ ` 源文件: ` [ Objects/longobject.c] ( https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L2990 )
344+
345+ ``` c
346+ // Objects/longobject.c
347+
348+ /* Add the absolute values of two integers. */
349+
350+ static PyLongObject *
351+ x_add (PyLongObject * a, PyLongObject * b)
352+ {
353+ Py_ssize_t size_a = Py_ABS(Py_SIZE(a)), size_b = Py_ABS(Py_SIZE(b));
354+ PyLongObject * z;
355+ Py_ssize_t i;
356+ digit carry = 0;
357+
358+ /* Ensure a is the larger of the two: */
359+ // 确保 a 大于 b
360+ if (size_a < size_b) {
361+ { PyLongObject *temp = a; a = b; b = temp; }
362+ { Py_ssize_t size_temp = size_a;
363+ size_a = size_b;
364+ size_b = size_temp; }
365+ }
366+ z = _PyLong_New(size_a+1);
367+ if (z == NULL)
368+ return NULL;
369+ for (i = 0; i < size_b; ++i) {
370+ carry += a->ob_digit[i] + b->ob_digit[i];
371+ z->ob_digit[i] = carry & PyLong_MASK;
372+ carry >>= PyLong_SHIFT;
373+ }
374+ for (; i < size_a; ++i) {
375+ carry += a->ob_digit[i];
376+ z->ob_digit[i] = carry & PyLong_MASK;
377+ carry >>= PyLong_SHIFT;
378+ }
379+ z->ob_digit[i] = carry;
380+ return long_normalize(z);
381+ }
382+
383+ /* Subtract the absolute values of two integers. * /
384+
385+ static PyLongObject *
386+ x_sub(PyLongObject * a, PyLongObject * b)
387+ {
388+ Py_ssize_t size_a = Py_ABS(Py_SIZE(a)), size_b = Py_ABS(Py_SIZE(b));
389+ PyLongObject * z;
390+ Py_ssize_t i;
391+ int sign = 1;
392+ digit borrow = 0;
393+
394+ /* Ensure a is the larger of the two: */
395+ // 确保 a 大于 b
396+ if (size_a < size_b) {
397+ sign = -1;
398+ { PyLongObject *temp = a; a = b; b = temp; }
399+ { Py_ssize_t size_temp = size_a;
400+ size_a = size_b;
401+ size_b = size_temp; }
402+ }
403+ else if (size_a == size_b) {
404+ /* Find highest digit where a and b differ: */
405+ // 找到最高位 a 与 b的差异
406+ i = size_a;
407+ while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
408+ ;
409+ if (i < 0)
410+ return (PyLongObject *)PyLong_FromLong(0);
411+ if (a->ob_digit[i] < b->ob_digit[i]) {
412+ sign = -1;
413+ { PyLongObject *temp = a; a = b; b = temp; }
414+ }
415+ size_a = size_b = i+1;
416+ }
417+ z = _PyLong_New(size_a);
418+ if (z == NULL)
419+ return NULL;
420+ for (i = 0; i < size_b; ++i) {
421+ /* The following assumes unsigned arithmetic
422+ works module 2**N for some N>PyLong_SHIFT. */
423+ borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
424+ z->ob_digit[i] = borrow & PyLong_MASK;
425+ borrow >>= PyLong_SHIFT;
426+ borrow &= 1; /* Keep only one sign bit 只保留一位符号位 */
427+ }
428+ for (; i < size_a; ++i) {
429+ borrow = a->ob_digit[i] - borrow;
430+ z->ob_digit[i] = borrow & PyLong_MASK;
431+ borrow >>= PyLong_SHIFT;
432+ borrow &= 1; /* Keep only one sign bit */
433+ }
434+ assert(borrow == 0);
435+ if (sign < 0) {
436+ Py_SIZE(z) = -Py_SIZE(z);
437+ }
438+ return long_normalize(z);
439+ }
440+
441+ static PyObject *
442+ long_add(PyLongObject * a, PyLongObject * b)
443+ {
444+ PyLongObject * z;
445+
446+ CHECK_BINOP(a, b);
447+
448+ if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
449+ return PyLong_FromLong(MEDIUM_VALUE(a) + MEDIUM_VALUE(b));
450+ }
451+ if (Py_SIZE(a) < 0) {
452+ if (Py_SIZE(b) < 0) {
453+ z = x_add(a, b);
454+ if (z != NULL) {
455+ /* x_add received at least one multiple-digit int,
456+ and thus z must be a multiple-digit int.
457+ That also means z is not an element of
458+ small_ints, so negating it in-place is safe. */
459+ assert(Py_REFCNT(z) == 1);
460+ Py_SIZE(z) = -(Py_SIZE(z));
461+ }
462+ }
463+ else
464+ z = x_sub(b, a);
465+ }
466+ else {
467+ if (Py_SIZE(b) < 0)
468+ z = x_sub(a, b);
469+ else
470+ z = x_add(a, b);
471+ }
472+ return (PyObject *)z;
473+ }
474+ ```
475+
476+ 可以看到整数的加法运算函数long_add根据 a、b的ob_size 又细分为两个函数做处理 x_add 和 x_sub
477+
478+ 加法运算函数 x_add 从 ob_digit 数组的低位开始依次按位相加,carry做进位处理,
479+ 然后做处理a对象的高位数字,最后使用 long_normalize 函数调整 ob_size,确保ob_digit[abs(ob_size)-1]不为零,其过程大致如下图
480+
481+ 
482+
483+ 减法运算函数 x_sub 的过程大致如下图
484+
485+ 
486+
487+ ### 整数相乘
488+
489+ `源文件:`[Objects/longobject.c](https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L3547)
490+
491+ ```c
492+ // Objects/longobject.c
493+ static PyObject *
494+ long_mul(PyLongObject *a, PyLongObject *b)
495+ {
496+ PyLongObject *z;
497+
498+ CHECK_BINOP(a, b);
499+
500+ /* fast path for single-digit multiplication */
501+ if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
502+ stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b);
503+ return PyLong_FromLongLong((long long)v);
504+ }
505+
506+ z = k_mul(a, b);
507+ /* Negate if exactly one of the inputs is negative. */
508+ if (((Py_SIZE(a) ^ Py_SIZE(b)) < 0) && z) {
509+ _PyLong_Negate(&z);
510+ if (z == NULL)
511+ return NULL;
512+ }
513+ return (PyObject *)z;
514+ }
515+ ```
516+
517+ k_mul函数 [ 源文件] (
518+ https://github.com/python/cpython/blob/v3.7.0/Objects/longobject.c#L3268 )
519+
520+ ` k_mul ` 函数是一种快速乘法[ Karatsuba算法] ( https://www.wikiwand.com/zh-hans/Karatsuba算法 ) 的实现
0 commit comments