diff --git a/chapter2/code/floats/float-twice.c b/chapter2/code/floats/float-twice.c index 9da5fad5..f4ba69f0 100644 --- a/chapter2/code/floats/float-twice.c +++ b/chapter2/code/floats/float-twice.c @@ -18,8 +18,8 @@ float_bits float_twice(float_bits f) { if (exp == 0) { /* Denormalized */ frac <<= 1; - } else if (exp == 0xFF - 1) { - /* twice to oo */ + } else if (exp == 0xFE || exp == 0xFF) { + /* twice to INF */ exp = 0xFF; frac = 0; } else { diff --git a/chapter2/code/tsub-ok.c b/chapter2/code/tsub-ok.c index b95cdec3..3c34e3e1 100644 --- a/chapter2/code/tsub-ok.c +++ b/chapter2/code/tsub-ok.c @@ -2,27 +2,60 @@ * tsub-ok.c */ #include -#include #include +#include -/* Determine whether arguments can be substracted without overflow */ -int tsub_ok(int x, int y) { - if (y == INT_MIN) { - return 0; - } +int tsub_ok(int x, int y) +{ + int is_ok = 1; - int neg_y = -y; - int sum = x + neg_y; - int pos_over = x > 0 && neg_y > 0 && sum < 0; - int neg_over = x < 0 && neg_y < 0 && sum >= 0; + is_ok &= (y != INT_MIN); - return !(pos_over || neg_over); -} + int sub = x - y; + int sig_mask = INT_MIN; + + int x_is_neg = x & sig_mask; + int x_is_pos = !x_is_neg && x != 0; + int y_is_neg = y & sig_mask; + int y_is_pos = !y_is_neg && y != 0; + int sub_is_not_neg = !(sub & sig_mask); + int sub_is_not_pos = (sub & sig_mask) | sub == 0; + + int pos_over = x_is_pos && y_is_neg && sub_is_not_pos; + int neg_over = x_is_neg && y_is_pos && sub_is_not_neg; + + is_ok &= !pos_over; + is_ok &= !neg_over; -int main(int argc, char* argv[]) { - assert(!tsub_ok(0x00, INT_MIN)); - assert(tsub_ok(0x00, 0x00)); - return 0; + return is_ok; } +int main() +{ + // y 为 INT_MIN 导致溢出 + int x = 0x12345678; + int y = INT_MIN; + printf("tsub_ok(0x%08x, 0x%08x) = %d\n", x, y, tsub_ok(x, y)); + assert(!tsub_ok(x, y)); + + // sub 为正溢出 + x = INT_MAX; + y = INT_MIN + 1; + printf("tsub_ok(0x%08x, 0x%08x) = %d\n", x, y, tsub_ok(x, y)); + assert(!tsub_ok(x, y)); + + // sub 为负溢出 + x = INT_MIN; + y = INT_MAX; + printf("tsub_ok(0x%08x, 0x%08x) = %d\n", x, y, tsub_ok(x, y)); + assert(!tsub_ok(x, y)); + + // sub is ok + x = 0x77654321; + y = 0x12345678; + printf("tsub_ok(0x%08x, 0x%08x) = %d\n", x, y, tsub_ok(x, y)); + assert(tsub_ok(x, y)); + + return 0; +} diff --git a/chapter2/code/unsigned-high-prod.c b/chapter2/code/unsigned-high-prod.c index 55fa76f9..096d6c41 100644 --- a/chapter2/code/unsigned-high-prod.c +++ b/chapter2/code/unsigned-high-prod.c @@ -3,33 +3,47 @@ */ #include #include +#include #include -int signed_high_prod(int x, int y) { - int64_t mul = (int64_t) x * y; - return mul >> 32; +int signed_high_prod(int x, int y) +{ + int64_t mul = (int64_t)x * y; + int res = mul >> 32; + return res; } -unsigned unsigned_high_prod(unsigned x, unsigned y) { - /* TODO calculations */ - int sig_x = x >> 31; - int sig_y = y >> 31; - int signed_prod = signed_high_prod(x, y); - return signed_prod + x * sig_y + y * sig_x; -} +unsigned unsigned_high_prod(unsigned x, unsigned y) +{ -/* a theorically correct version to test unsigned_high_prod func */ -unsigned another_unsigned_high_prod(unsigned x, unsigned y) { - uint64_t mul = (uint64_t) x * y; - return mul >> 32; -} + unsigned hp = signed_high_prod(x, y); + + int sig_mask = INT_MIN; + + /** + * 68 页的 (2-18) 中 + * 带有 2^w 权重的项会出现在高 w 位中 + */ -int main(int argc, char* argv[]) { - unsigned x = 0x12345678; - unsigned y = 0xFFFFFFFF; + (x & sig_mask) && (hp += y); + (y & sig_mask) && (hp += x); - assert(another_unsigned_high_prod(x, y) == unsigned_high_prod(x, y)); - return 0; + return hp; } +unsigned unsigned_high_prod_2(unsigned x, unsigned y) +{ + uint64_t mul = (uint64_t)x * y; + return mul >> 32; +} + +int main(int argc, char *argv[]) +{ + unsigned x = 0x12345678; + unsigned y = 0xFFFFFFFF; + printf("unsigned(%X, %X) = %X\n", x, y, unsigned_high_prod(x, y)); + assert(unsigned_high_prod_2(x, y) == unsigned_high_prod(x, y)); + + return 0; +}