GMP/MPIR multiplicaiton 中的主要代码片段是 mpn_mul_basecase:
mp_limb_t addmul_1(mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
{
mp_limb_t ul, cl, hpl, lpl, rl;
cl = 0;
do
{
ul = *up++;
umul_ppmm(hpl, lpl, ul, vl);
lpl += cl;
cl = (lpl < cl) + hpl;
rl = *rp;
lpl = rl + lpl;
cl += lpl < rl;
*rp++ = lpl;
} while (--n != 0);
return cl;
}
VC++ 在哪里
# define umul_ppmm(xh, xl, m0, m1) \
do { \
xl = _umul128( (m0), (m1), &xh); \
} while (0)
对于 128 位类型的 GCC:
do { \
mp_limb_double_t w = (mp_limb_double_t)x * y; \
r_lo = (mp_limb_t)w; \
r_hi = (mp_limb_t)(w >> GMP_LIMB_BITS); \
} while (0)
但是指定处理器(我的处理器是 Haswell)的优化 asm 代码要快两倍:https ://github.com/wbhart/mpir/blob/master/mpn/x86_64w/haswell/addmul_1.asm 为什么?因为这个循环被扩展或者使用mulx而不是mul?我注意到源内存必须由 RSI 有效索引,而目标内存必须由 RDI 有效索引。但我不知道必须读取+添加+写入的索引存储单元的效率如何。可以用普通的C对其进行优化吗?我看到的是 _addcarry_u64 ,但也很慢。