Hacker’s Delight 里的各种技巧真有意思。
乘法
Chapter8,32位符号整型乘积的高32位:
int mulhs(int u, int v) {
unsigned int u0, v0, w0;
int u1, v1, w1, w2, t;
u0 = u & 0xFFFF; u1 = u >> 16;
v0 = v & 0xFFFF; v1 = v >> 16;
w0 = u0*v0;
t = u1*v0 + (w0 >> 16);
w1 = t & 0xFFFF;
w2 = t >> 16;
w1 = u0*v1 + w1;
return u1*v1 + w2 + (w1 >> 16);
}
unsigned int mulhs(unsigned int u, unsigned int v) {
unsigned int u0, v0, w0;
unsigned int u1, v1, w1, w2, t;
u0 = u & 0xFFFF; u1 = u >> 16;
v0 = v & 0xFFFF; v1 = v >> 16;
w0 = u0*v0;
t = u1*v0 + (w0 >> 16);
w1 = t & 0xFFFF;
w2 = t >> 16;
w1 = u0*v1 + w1;
return u1*v1 + w2 + (w1 >> 16);
}
拼凑一下可以算出完整的64位乘积:
long long int mul32(int u, int v)
{
int h = mulhs(u, v);
int l = u * v;
return ((long long int)h << 32 | l);
}
long long unsigned int mul32(unsigned int u, unsigned int v)
{
unsigned int h = mulhs(u, v);
unsigned int l = u * v;
return ((long long unsigned int)h << 32 | l);
}
后面的习题提到低32位的运算用有符号或者无符号都是相同的,测试了一下确实如此。
for a 32×32 ⇒ 64 bit multiplication, the low-order 32 bits of the product are the same whether the operands are interpreted as signed or unsigned integers.
这种把长位宽的运算拆成高低两部分分别计算的方法,在用SIMD做优化的时候可能会有用,因为一些SIMD指令集并没有现成的长位宽运算指令,只好自行拼凑了。