Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions chapter2/code/floats/float-twice.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
65 changes: 49 additions & 16 deletions chapter2/code/tsub-ok.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,60 @@
* tsub-ok.c
*/
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <assert.h>

/* 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;
}
54 changes: 34 additions & 20 deletions chapter2/code/unsigned-high-prod.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,47 @@
*/
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <inttypes.h>

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;
}