クリキー。まず、bignum の実装方法について説明します。GMP やその他のライブラリでは、通常、固定幅フィールドを「リム」または数値の一部として指定します。これらはレジスタのサイズであり、 2 つのレジスタ オーバーフローを追加した場合にキャリー フラグを設定するような命令であるため、32 ビット プラットフォームと 64 ビット プラットフォームでそれぞれuint32_t
orを使用する可能性が高いことを除いて、これまでのところその部分は正しいです。uint64_t
adc
とにかく、要点は、これらの手足はビッグナムの符号ではなく、実際の大きさを表すということです。2 の補数を使用すると、どこかに符号ビットがあることが予想されますが、数値のサイズを変更したい場合 (符号adc
は気にせず、単にバイナリ加算を行うだけです)、古い符号ビットを見つけて抽出する必要があるため、面倒になります。それを覚えておいて、正しい場所に戻してください...非常に遅いです。
各肢のビットを反転して何を達成しようとしているのかわかりません。このような手足のセットを想像すると(単純化の略)
1011 0111 1010 1011 = 47019
最終的には次のようになります。
0100 1000 0101 0100 = 18516
とにかく、GMP は手足のサインを表していません。GMP の符号付き整数型は、次のmpz_t
構造体で定義されています。
typedef struct
{
int _mp_alloc; /* Number of *limbs* allocated and pointed
to by the _mp_d field. */
int _mp_size; /* abs(_mp_size) is the number of limbs the
last field points to. If _mp_size is
negative this is a negative number. */
mp_limb_t *_mp_d; /* Pointer to the limbs. */
} __mpz_struct;
typedef __mpz_struct mpz_t[1];
ご覧のとおり、 _mp_size
GMP が符号付きの数値を表す方法です。
コード (具体的にはmpz/aors.h
) では、これが使用されていることがわかります。
usize = u->_mp_size;
vsize = VARIATION v->_mp_size;
// .....
if ((usize ^ vsize) < 0)
{
/* U and V have different sign. Need to compare them to determine
which operand to subtract from which. */
// does subtraction instead of add.
実際の操作はmpn_
、署名されていない型である一連の関数によって実行されます。
GMP には、サイズを正しく設定できる基本型からのインポート/エクスポート関数がいくつかあります。あなたが何をしようとしているのかよくわかりませんが、それらが不十分であると仮定すると、自分で設定できるはずです.