Причина этого кроется в реализации mpn
. В частности, если вы склонны математически, вы поймете, что N - это набор натуральных чисел (1,2,3,4 ...), тогда как Z - это набор целых чисел (..., - 2, -1,0 1,2, ...).
Внедрение библиотеки bignum для Z равносильно тому, чтобы сделать это для N и принять во внимание некоторые специальные правила для операций со знаками, то есть отслеживать, нужно ли вам добавлять или вычитать и каков результат.
Теперь о том, как реализована библиотека bignum ... вот строка, чтобы дать вам подсказку:
typedef unsigned int mp_limb_t;
typedef mp_limb_t * mp_ptr;
А теперь давайте посмотрим на сигнатуру функции, работающую на этом:
__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t));
По сути, речь идет о том, что «конечность» - это целочисленное поле, представляющее биты числа, а все число представляется в виде огромного массива. Умная часть заключается в том, что gmp делает все это очень эффективным, хорошо оптимизированным способом.
В любом случае, вернемся к обсуждению. По сути, единственный способ передавать массивы в C - это, как вы знаете, передавать указатели на эти массивы, что эффективно позволяет передавать по ссылке. Теперь, чтобы отслеживать, что происходит, определены два типа: mp_ptr
, который представляет собой массив mp_limb_t
, достаточно большой для хранения вашего числа, и mp_srcptr
, который является константной версией этого, так что вы не можете случайно изменить биты исходных текстов того, что вы используете. Основная идея заключается в том, что большинство функций следуют этой схеме:
func(ptr output, src in1, src in2)
и т.д.. Таким образом, я подозреваю, что mpz_*
функции следуют этому соглашению просто чтобы быть последовательными, и это потому, что так думают авторы.
Короткая версия: из-за того, как вам нужно реализовать bignum lib, это необходимо.