diff --git a/homework/chapter2/65.c b/homework/chapter2/65.c new file mode 100644 index 0000000..1e737f5 --- /dev/null +++ b/homework/chapter2/65.c @@ -0,0 +1,16 @@ +#include + +/* Return 1 when x contains an odd number of 1s; 0 otherwise. + Assume w=32 */ +int odd_ones(unsigned x) { + x = x ^ (x >> 16); + x = x ^ (x >> 8); + x = x ^ (x >> 4); + x = x ^ (x >> 2); + x = x ^ (x >> 1); + return x & 1; +} + +int main() { + printf("%d %d\n", odd_ones(0xF1F1F0F1), odd_ones(0xFF00AAAA)); +} \ No newline at end of file diff --git a/homework/chapter2/66.c b/homework/chapter2/66.c new file mode 100644 index 0000000..37518dd --- /dev/null +++ b/homework/chapter2/66.c @@ -0,0 +1,26 @@ +#include + +/* + * Generate mask indicating leftmost 1 in x. Assume w=32. + * For example, 0xFF00 -> 0x8000, and 0x6600 --> 0x4000. + * If x = 0, then return 0. + */ +int leftmost_one(unsigned x) { + unsigned t = x; + t = t >> 1; + + t = t | (t >> 1); + t = t | (t >> 2); + t = t | (t >> 4); + t = t | (t >> 8); + t = t | (t >> 16); + + return (t + 1) & x; +} + +int main() { + printf("%.8X %.8X\n", 0x06050403, leftmost_one(0x06050403)); + printf("%.8X %.8X\n", 0xF0F0F0F0, leftmost_one(0xF0F0F0F0)); + printf("%.8X %.8X\n", 0x00000000, leftmost_one(0x00000000)); + printf("%.8X %.8X\n", 0x00000001, leftmost_one(0x00000001)); +} \ No newline at end of file diff --git a/homework/chapter2/75.c b/homework/chapter2/75.c new file mode 100644 index 0000000..75b68ee --- /dev/null +++ b/homework/chapter2/75.c @@ -0,0 +1,23 @@ +#include +#include + +int signed_high_prod(int x, int y) { + long long p = (long long) x * y; + return p >> 32; +} + +unsigned unsigned_high_prod(unsigned x, unsigned y) { + int w = sizeof(int) << 3; + return signed_high_prod(x, y) + (((int) y >> (w - 1)) & x) + (((int) x >> (w - 1)) & y); +} + +int main() { + unsigned x = 0x71827364, y = 0xF0E1D2C3; + assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y); + x = 0x91827364, y = 0xF0E1D2C3; + assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y); + x = 0x71827364, y = 0x60E1D2C3; + assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y); + x = 0x91827364, y = 0x60E1D2C3; + assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y); +} \ No newline at end of file diff --git a/homework/chapter2/80.c b/homework/chapter2/80.c new file mode 100644 index 0000000..8d0950c --- /dev/null +++ b/homework/chapter2/80.c @@ -0,0 +1,20 @@ +#include +#include + +int threefourths(int x) { + int p = x >> 2, q = x & 3; + return p + (p << 1) + q + ((!q | (x >> 31)) & 1) - 1; +} + +int main() { + int x = 0x88659612; + for (int i = 0; i < 100; i++) { + x++; + assert(threefourths(x) == (long long) x * 3 / 4); + } + x = 0x79642695; + for (int i = 0; i < 100; i++) { + x++; + assert(threefourths(x) == (long long) x * 3 / 4); + } +} \ No newline at end of file diff --git a/homework/chapter2/README.md b/homework/chapter2/README.md new file mode 100644 index 0000000..d16939b --- /dev/null +++ b/homework/chapter2/README.md @@ -0,0 +1,21 @@ +## 2.65 +定义一次操作为将 $w$ 位的整数 $x$ 从中间分成两个 $\frac{w}{2}$ 位的整数 $y$ 和 $z$,接着令 `x=y^z`。进行该操作 5 次后得到答案。 + +我们将这样的思路称为“折半递归法”。 +## 2.66 +第一次操作,我们令 `x = x | (x >> 1)`,这样 $x$ 的最高位所在 `1` 连续段长度必然不小于 2。 + +第二次操作,令 `x = x | (x >> 2)`,依次类推。通过 5 次操作即可实现提示中的转换。 +## 2.75 +$x,y$ 是无符号整数,$x'=U2T_w(x),y'=U2T_w(y)$。 + +$$ +\begin{aligned} +x'\times y'&=(x+x_{w-1}2^w)\times(y+y_{w-1}2^w)\\ +&=x\times y+(x_{w-1}\times y+y_{w-1}\times x)2^w+x_{w-1}y_{w-1}2^{2w} +\end{aligned}$$ + +因此有 $U2B_{2w}(x'\times y')=T2B_{2w}(x\times y+(x_{w-1}\times y+y_{w-1}\times x)2^w)$。即令 `a = signed_high_prod(x, y), b = unsigned_high_prod(x', y')`,$T2B_w(a+x_{w-1}\times y+y_{w-1}\times x)=U2B_w(b)$。 + +## 2.80 +先得到粗糙的答案 `(x >> 2) + ((x >> 2) << 1)`,再根据 `x & 3` 进行修正。 \ No newline at end of file