前兩篇分別實作了 Comba 乘法(O(n²) 但常數極小)與 Karatsuba 乘法(O(n^1.585) 適合大數)。本篇將兩者結合,實作高效的有符號大整數乘法。
used)皆 ≥ KARATSUBA_MUL_CUTOFF(通常 32~64 位元)時,使用 Karatsuba 遞迴bn_mul_bn 完整實作int bn_mul_bn(bignum *z, const bignum *x, const bignum *y) {
int ret = 0;
bignum ta[1], tb[1];
bn_init(ta); bn_init(tb);
// 1. 判斷是否走 Karatsuba
if (BN_MIN(x->used, y->used) >= KARATSUBA_MUL_CUTOFF) {
BN_CHECK(bn_mul_karatsuba(z, x, y));
} else {
// 2. Comba 路徑:處理輸出與輸入重疊 (z == x 或 z == y)
if (x == z) { BN_CHECK(bn_copy(ta, x)); x = ta; }
if (y == z) { BN_CHECK(bn_copy(tb, y)); y = tb; }
// 3. 擴充結果精度並歸零
BN_CHECK(bn_grow(z, x->used + y->used));
BN_CHECK(bn_set_word(z, 0));
z->used = x->used + y->used;
// 4. 呼叫 Comba 核心
bn_mul_comba(z, x, y);
// 5. 設定符號:同號為正,異號為負
z->sign = (x->sign == y->sign) ? 1 : -1;
}
clean:
bn_free(ta); bn_free(tb);
return ret;
}
ta、tb 的必要性Comba 乘法一開始會將 z 歸零。若呼叫端傳入 bn_mul_bn(z, z, y)(即 z = z * y),直接操作會破壞輸入值。解法:偵測別名後,先 bn_copy 到臨時變數,再讓 x/y 指向臨時變數。
Comba/Karatsuba 僅計算絕對值乘積,最後依 x->sign、y->sign 設定 z->sign。這簡化了核心乘法邏輯(只需處理非負數)。
bn_init 僅初始化結構體,bn_free 安全釋放(即使未分配記憶體也安全)。clean 標籤確保所有路徑都釋放資源。
bn_copy 以提升效能至此,大整數加減乘除核心已具備:
下一篇將探討單精度乘法優化:為何不直接用 Comba/Karatsuba,以及專用實作技巧。