#include <string.h>
#include <math.h>
#include <stdio.h>
union u {
unsigned long long u; /* assumed to be 64-bit */
double d;
};
typedef unsigned long long boxed;
boxed smalldouble_to_boxed(double d)
{
union u u;
u.d = d;
boxed rest = u.u & 0x7fffffffffffffff;
boxed packed;
if (rest > 0x7ff0000000000000)
/* NaN */
packed = u.u;
else
{
boxed sign = u.u & 0x8000000000000000;
if (rest >= 0x3ff0000000000000)
/* inf */
rest = 0x3ff0000000000000;
packed = sign | (rest << 1);
}
return packed | 1;
}
boxed double_to_boxed(double d)
{
return smalldouble_to_boxed
(ldexp(d
, -512)); }
double smalldouble_from_boxed(boxed l)
{
union u u;
boxed sign = l & 0x8000000000000000;
boxed rest = (l & 0x7fffffffffffffff) >> 1;
if (rest >= 0x3ff0000000000000) rest <<= 1;
u.u = sign | rest;
return u.d;
}
double double_from_boxed(boxed l)
{
double d = smalldouble_from_boxed(l);
}
boxed smalldouble_add(boxed s1, boxed s2)
{
double d1 = smalldouble_from_boxed(s1);
double d2 = smalldouble_from_boxed(s2);
return smalldouble_to_boxed(d1 + d2);
}
boxed smalldouble_sub(boxed s1, boxed s2)
{
double d1 = smalldouble_from_boxed(s1);
double d2 = smalldouble_from_boxed(s2);
return smalldouble_to_boxed(d1 - d2);
}
boxed smalldouble_mul(boxed s1, boxed s2)
{
double d1 = smalldouble_from_boxed(s1);
double d2 = smalldouble_from_boxed(s2);
return smalldouble_to_boxed
(ldexp(d1
, +512) * d2
); }
boxed smalldouble_div(boxed s1, boxed s2)
{
double d1 = smalldouble_from_boxed(s1);
double d2 = smalldouble_from_boxed(s2);
return smalldouble_to_boxed
(ldexp(d1
/d2
, -512)); }
int main()
{
boxed l1, l2, l3;
l1 = double_to_boxed(3.0);
l2 = double_to_boxed(7.0);
l3 = smalldouble_add(l1, l2);
printf("3.0 + 7.0 = %f\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(nextafter(1.0, 2.0));
l2 = double_to_boxed(nextafter(1.5, 0.0));
l3 = smalldouble_add(l1, l2);
printf("(1+) + (1.5-) = %f\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.0e-168);
l2 = double_to_boxed(1.3e-168);
l3 = smalldouble_add(l1, l2);
printf("(1.0-168) + (1.3-168) = %e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.00000000001e-155);
l2 = double_to_boxed(1.0e-155);
l3 = smalldouble_sub(l1, l2);
printf("(1.0...01-155) + (1.0-155) = %.16e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.0e-90);
l2 = double_to_boxed(1.3e-78);
l3 = smalldouble_mul(l1, l2);
printf("(1.0-90) * (1.3-78) = %e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.0e+70);
l2 = double_to_boxed(1.3e+78);
l3 = smalldouble_mul(l1, l2);
printf("(1.0+70) * (1.3+78) = %e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.0e+90);
l2 = double_to_boxed(1.3e+78);
l3 = smalldouble_mul(l1, l2);
printf("(1.0+90) * (1.3+78) = %e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.0e+90);
l2 = double_to_boxed(1.3e+78);
l3 = smalldouble_div(l1, l2);
printf("(1.0+90) / (1.3+78) = %e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.0e200);
l2 = double_to_boxed(1.0e-200);
l3 = smalldouble_div(l1, l2);
printf("inf / 0 = %e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
l1 = double_to_boxed(1.0e200);
l2 = double_to_boxed(1.0e-200);
l3 = smalldouble_mul(l1, l2);
printf("inf * 0 = %e\n", double_from_boxed
(l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
return 0;
}
I2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8bWF0aC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCnVuaW9uIHUgewogIHVuc2lnbmVkIGxvbmcgbG9uZyB1OyAvKiBhc3N1bWVkIHRvIGJlIDY0LWJpdCAqLwogIGRvdWJsZSBkOwp9OwoKdHlwZWRlZiB1bnNpZ25lZCBsb25nIGxvbmcgYm94ZWQ7Cgpib3hlZCBzbWFsbGRvdWJsZV90b19ib3hlZChkb3VibGUgZCkKewogIHVuaW9uIHUgdTsKICB1LmQgPSBkOwogIGJveGVkIHJlc3QgPSB1LnUgJiAweDdmZmZmZmZmZmZmZmZmZmY7CiAgYm94ZWQgcGFja2VkOwogIGlmIChyZXN0ID4gMHg3ZmYwMDAwMDAwMDAwMDAwKQogICAgLyogTmFOICovCiAgICBwYWNrZWQgPSB1LnU7CiAgZWxzZSAKICAgIHsKICAgICAgYm94ZWQgc2lnbiA9IHUudSAmIDB4ODAwMDAwMDAwMDAwMDAwMDsKICAgICAgaWYgKHJlc3QgPj0gMHgzZmYwMDAwMDAwMDAwMDAwKQogICAgLyogaW5mICovCglyZXN0ID0gMHgzZmYwMDAwMDAwMDAwMDAwOwogICAgICBwYWNrZWQgPSBzaWduIHwgKHJlc3QgPDwgMSk7CiAgICB9CiAgcmV0dXJuIHBhY2tlZCB8IDE7Cn0KCmJveGVkIGRvdWJsZV90b19ib3hlZChkb3VibGUgZCkKewogIHJldHVybiBzbWFsbGRvdWJsZV90b19ib3hlZChsZGV4cChkLCAtNTEyKSk7Cn0KCmRvdWJsZSBzbWFsbGRvdWJsZV9mcm9tX2JveGVkKGJveGVkIGwpCnsKICB1bmlvbiB1IHU7CiAgYm94ZWQgc2lnbiA9IGwgJiAweDgwMDAwMDAwMDAwMDAwMDA7CiAgYm94ZWQgcmVzdCA9IChsICYgMHg3ZmZmZmZmZmZmZmZmZmZmKSA+PiAxOwogIGlmIChyZXN0ID49IDB4M2ZmMDAwMDAwMDAwMDAwMCkgcmVzdCA8PD0gMTsKICB1LnUgPSBzaWduIHwgcmVzdDsKICByZXR1cm4gdS5kOwp9Cgpkb3VibGUgZG91YmxlX2Zyb21fYm94ZWQoYm94ZWQgbCkKewogIGRvdWJsZSBkID0gc21hbGxkb3VibGVfZnJvbV9ib3hlZChsKTsKICByZXR1cm4gbGRleHAoZCwgKzUxMik7Cn0KCmJveGVkIHNtYWxsZG91YmxlX2FkZChib3hlZCBzMSwgYm94ZWQgczIpCnsKICBkb3VibGUgZDEgPSBzbWFsbGRvdWJsZV9mcm9tX2JveGVkKHMxKTsKICBkb3VibGUgZDIgPSBzbWFsbGRvdWJsZV9mcm9tX2JveGVkKHMyKTsKICByZXR1cm4gc21hbGxkb3VibGVfdG9fYm94ZWQoZDEgKyBkMik7Cn0KCmJveGVkIHNtYWxsZG91YmxlX3N1Yihib3hlZCBzMSwgYm94ZWQgczIpCnsKICBkb3VibGUgZDEgPSBzbWFsbGRvdWJsZV9mcm9tX2JveGVkKHMxKTsKICBkb3VibGUgZDIgPSBzbWFsbGRvdWJsZV9mcm9tX2JveGVkKHMyKTsKICByZXR1cm4gc21hbGxkb3VibGVfdG9fYm94ZWQoZDEgLSBkMik7Cn0KCmJveGVkIHNtYWxsZG91YmxlX211bChib3hlZCBzMSwgYm94ZWQgczIpCnsKICBkb3VibGUgZDEgPSBzbWFsbGRvdWJsZV9mcm9tX2JveGVkKHMxKTsKICBkb3VibGUgZDIgPSBzbWFsbGRvdWJsZV9mcm9tX2JveGVkKHMyKTsKICByZXR1cm4gc21hbGxkb3VibGVfdG9fYm94ZWQobGRleHAoZDEsICs1MTIpICogZDIpOwp9Cgpib3hlZCBzbWFsbGRvdWJsZV9kaXYoYm94ZWQgczEsIGJveGVkIHMyKQp7CiAgZG91YmxlIGQxID0gc21hbGxkb3VibGVfZnJvbV9ib3hlZChzMSk7CiAgZG91YmxlIGQyID0gc21hbGxkb3VibGVfZnJvbV9ib3hlZChzMik7CiAgcmV0dXJuIHNtYWxsZG91YmxlX3RvX2JveGVkKGxkZXhwKGQxL2QyLCAtNTEyKSk7Cn0KCmludCBtYWluKCkKewogIGJveGVkIGwxLCBsMiwgbDM7CgogIGwxID0gZG91YmxlX3RvX2JveGVkKDMuMCk7CiAgbDIgPSBkb3VibGVfdG9fYm94ZWQoNy4wKTsKICBsMyA9IHNtYWxsZG91YmxlX2FkZChsMSwgbDIpOwogIHByaW50ZigiMy4wICsgNy4wID0gJWZcbiIsIGRvdWJsZV9mcm9tX2JveGVkKGwzKSk7CiAgcHJpbnRmKCJyZXByZXNlbnRhdGlvbnM6ICVsbHggJWxseCAlbGx4XG4iLCBsMSwgbDIgLCBsMyk7CgogIGwxID0gZG91YmxlX3RvX2JveGVkKG5leHRhZnRlcigxLjAsIDIuMCkpOwogIGwyID0gZG91YmxlX3RvX2JveGVkKG5leHRhZnRlcigxLjUsIDAuMCkpOwogIGwzID0gc21hbGxkb3VibGVfYWRkKGwxLCBsMik7CiAgcHJpbnRmKCIoMSspICsgKDEuNS0pID0gJWZcbiIsIGRvdWJsZV9mcm9tX2JveGVkKGwzKSk7CiAgcHJpbnRmKCJyZXByZXNlbnRhdGlvbnM6ICVsbHggJWxseCAlbGx4XG4iLCBsMSwgbDIgLCBsMyk7CgogIGwxID0gZG91YmxlX3RvX2JveGVkKDEuMGUtMTY4KTsKICBsMiA9IGRvdWJsZV90b19ib3hlZCgxLjNlLTE2OCk7CiAgbDMgPSBzbWFsbGRvdWJsZV9hZGQobDEsIGwyKTsKICBwcmludGYoIigxLjAtMTY4KSArICgxLjMtMTY4KSA9ICVlXG4iLCBkb3VibGVfZnJvbV9ib3hlZChsMykpOwogIHByaW50ZigicmVwcmVzZW50YXRpb25zOiAlbGx4ICVsbHggJWxseFxuIiwgbDEsIGwyICwgbDMpOwoKICBsMSA9IGRvdWJsZV90b19ib3hlZCgxLjAwMDAwMDAwMDAxZS0xNTUpOwogIGwyID0gZG91YmxlX3RvX2JveGVkKDEuMGUtMTU1KTsKICBsMyA9IHNtYWxsZG91YmxlX3N1YihsMSwgbDIpOwogIHByaW50ZigiKDEuMC4uLjAxLTE1NSkgKyAoMS4wLTE1NSkgPSAlLjE2ZVxuIiwgZG91YmxlX2Zyb21fYm94ZWQobDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgbDEgPSBkb3VibGVfdG9fYm94ZWQoMS4wZS05MCk7CiAgbDIgPSBkb3VibGVfdG9fYm94ZWQoMS4zZS03OCk7CiAgbDMgPSBzbWFsbGRvdWJsZV9tdWwobDEsIGwyKTsKICBwcmludGYoIigxLjAtOTApICogKDEuMy03OCkgPSAlZVxuIiwgZG91YmxlX2Zyb21fYm94ZWQobDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgbDEgPSBkb3VibGVfdG9fYm94ZWQoMS4wZSs3MCk7CiAgbDIgPSBkb3VibGVfdG9fYm94ZWQoMS4zZSs3OCk7CiAgbDMgPSBzbWFsbGRvdWJsZV9tdWwobDEsIGwyKTsKICBwcmludGYoIigxLjArNzApICogKDEuMys3OCkgPSAlZVxuIiwgZG91YmxlX2Zyb21fYm94ZWQobDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgbDEgPSBkb3VibGVfdG9fYm94ZWQoMS4wZSs5MCk7CiAgbDIgPSBkb3VibGVfdG9fYm94ZWQoMS4zZSs3OCk7CiAgbDMgPSBzbWFsbGRvdWJsZV9tdWwobDEsIGwyKTsKICBwcmludGYoIigxLjArOTApICogKDEuMys3OCkgPSAlZVxuIiwgZG91YmxlX2Zyb21fYm94ZWQobDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgbDEgPSBkb3VibGVfdG9fYm94ZWQoMS4wZSs5MCk7CiAgbDIgPSBkb3VibGVfdG9fYm94ZWQoMS4zZSs3OCk7CiAgbDMgPSBzbWFsbGRvdWJsZV9kaXYobDEsIGwyKTsKICBwcmludGYoIigxLjArOTApIC8gKDEuMys3OCkgPSAlZVxuIiwgZG91YmxlX2Zyb21fYm94ZWQobDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgbDEgPSBkb3VibGVfdG9fYm94ZWQoMS4wZTIwMCk7CiAgbDIgPSBkb3VibGVfdG9fYm94ZWQoMS4wZS0yMDApOwogIGwzID0gc21hbGxkb3VibGVfZGl2KGwxLCBsMik7CiAgcHJpbnRmKCJpbmYgLyAwID0gJWVcbiIsIGRvdWJsZV9mcm9tX2JveGVkKGwzKSk7CiAgcHJpbnRmKCJyZXByZXNlbnRhdGlvbnM6ICVsbHggJWxseCAlbGx4XG4iLCBsMSwgbDIgLCBsMyk7CgogIGwxID0gZG91YmxlX3RvX2JveGVkKDEuMGUyMDApOwogIGwyID0gZG91YmxlX3RvX2JveGVkKDEuMGUtMjAwKTsKICBsMyA9IHNtYWxsZG91YmxlX211bChsMSwgbDIpOwogIHByaW50ZigiaW5mICogMCA9ICVlXG4iLCBkb3VibGVfZnJvbV9ib3hlZChsMykpOwogIHByaW50ZigicmVwcmVzZW50YXRpb25zOiAlbGx4ICVsbHggJWxseFxuIiwgbDEsIGwyICwgbDMpOwoKICByZXR1cm4gMDsKfQo=