#include <string.h>
#include <math.h>
#include <stdio.h>
union u {
unsigned long long u; /* assumed to be 64-bit */
double d;
};
void smalldouble_to_cell(void*p, double d)
{
union u u;
u.d = d;
unsigned long long rest = u.u & 0x7fffffffffffffff;
unsigned long long packed;
if (rest > 0x7ff0000000000000)
/* NaN */
packed = u.u & 0xfffffffffffffffe;
else
{
unsigned long long sign = u.u & 0x8000000000000000;
if (rest >= 0x3ff0000000000000)
rest = 0x3ff0000000000000;
packed = sign | (rest << 1);
}
}
void double_to_cell(void *p, double d)
{
smalldouble_to_cell
(p
, ldexp(d
, -512));}
double smalldouble_from_cell(void*p)
{
union u u;
unsigned long long l;
unsigned long long sign = l & 0x8000000000000000;
unsigned long long rest = (l & 0x7fffffffffffffff) >> 1;
if (rest >= 0x3ff0000000000000) rest <<= 1;
u.u = sign | rest;
return u.d;
}
double double_from_cell(void*p)
{
double d = smalldouble_from_cell(p);
}
void float_cell_add(void *d, void *s1, void *s2)
{
double d1 = smalldouble_from_cell(s1);
double d2 = smalldouble_from_cell(s2);
smalldouble_to_cell(d, d1 + d2);
}
void float_cell_sub(void *d, void *s1, void *s2)
{
double d1 = smalldouble_from_cell(s1);
double d2 = smalldouble_from_cell(s2);
smalldouble_to_cell(d, d1 - d2);
}
void float_cell_mul(void *d, void *s1, void *s2)
{
double d1 = smalldouble_from_cell(s1);
double d2 = smalldouble_from_cell(s2);
smalldouble_to_cell
(d
, ldexp(d1
, +512) * d2
);}
void float_cell_div(void *d, void *s1, void *s2)
{
double d1 = smalldouble_from_cell(s1);
double d2 = smalldouble_from_cell(s2);
smalldouble_to_cell
(d
, ldexp(d1
/d2
, -512));}
int main()
{
unsigned long long l1, l2, l3;
double_to_cell(&l1, 3.0);
double_to_cell(&l2, 7.0);
float_cell_add(&l3, &l1, &l2);
printf("3.0 + 7.0 = %f\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, nextafter(1.0, 2.0));
double_to_cell(&l2, nextafter(1.5, 0.0));
float_cell_add(&l3, &l1, &l2);
printf("(1+) + (1.5-) = %f\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, 1.0e-168);
double_to_cell(&l2, 1.3e-168);
float_cell_add(&l3, &l1, &l2);
printf("(1.0-168) + (1.3-168) = %e\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, 1.0e-90);
double_to_cell(&l2, 1.3e-78);
float_cell_mul(&l3, &l1, &l2);
printf("(1.0-90) * (1.3-78) = %e\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, 1.0e+70);
double_to_cell(&l2, 1.3e+78);
float_cell_mul(&l3, &l1, &l2);
printf("(1.0+70) * (1.3+78) = %e\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, 1.0e+90);
double_to_cell(&l2, 1.3e+78);
float_cell_mul(&l3, &l1, &l2);
printf("(1.0+90) * (1.3+78) = %e\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, 1.0e+90);
double_to_cell(&l2, 1.3e+78);
float_cell_div(&l3, &l1, &l2);
printf("(1.0+90) / (1.3+78) = %e\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, 1.0e200);
double_to_cell(&l2, 1.0e-200);
float_cell_div(&l3, &l1, &l2);
printf("inf / 0 = %e\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
double_to_cell(&l1, 1.0e200);
double_to_cell(&l2, 1.0e-200);
float_cell_mul(&l3, &l1, &l2);
printf("inf * 0 = %e\n", double_from_cell
(&l3
)); printf("representations: %llx %llx %llx\n", l1
, l2
, l3
);
return 0;
}
I2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8bWF0aC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCnVuaW9uIHUgewogIHVuc2lnbmVkIGxvbmcgbG9uZyB1OyAvKiBhc3N1bWVkIHRvIGJlIDY0LWJpdCAqLwogIGRvdWJsZSBkOwp9OwoKdm9pZCBzbWFsbGRvdWJsZV90b19jZWxsKHZvaWQqcCwgZG91YmxlIGQpCnsKICB1bmlvbiB1IHU7CiAgdS5kID0gZDsKICB1bnNpZ25lZCBsb25nIGxvbmcgcmVzdCA9IHUudSAmIDB4N2ZmZmZmZmZmZmZmZmZmZjsKICB1bnNpZ25lZCBsb25nIGxvbmcgcGFja2VkOwogIGlmIChyZXN0ID4gMHg3ZmYwMDAwMDAwMDAwMDAwKQogICAgLyogTmFOICovCiAgICBwYWNrZWQgPSB1LnUgJiAweGZmZmZmZmZmZmZmZmZmZmU7CiAgZWxzZSAKICAgIHsKICAgICAgdW5zaWduZWQgbG9uZyBsb25nIHNpZ24gPSB1LnUgJiAweDgwMDAwMDAwMDAwMDAwMDA7CiAgICAgIGlmIChyZXN0ID49IDB4M2ZmMDAwMDAwMDAwMDAwMCkKICAgIHJlc3QgPSAweDNmZjAwMDAwMDAwMDAwMDA7CiAgICAgIHBhY2tlZCA9IHNpZ24gfCAocmVzdCA8PCAxKTsKICAgIH0KICBtZW1jcHkocCwgJnBhY2tlZCwgOCk7Cn0KCnZvaWQgZG91YmxlX3RvX2NlbGwodm9pZCAqcCwgZG91YmxlIGQpCnsKICBzbWFsbGRvdWJsZV90b19jZWxsKHAsIGxkZXhwKGQsIC01MTIpKTsKfQoKZG91YmxlIHNtYWxsZG91YmxlX2Zyb21fY2VsbCh2b2lkKnApCnsKICB1bmlvbiB1IHU7CiAgdW5zaWduZWQgbG9uZyBsb25nIGw7CiAgbWVtY3B5KCZsLCBwLCA4KTsKICB1bnNpZ25lZCBsb25nIGxvbmcgc2lnbiA9IGwgJiAweDgwMDAwMDAwMDAwMDAwMDA7CiAgdW5zaWduZWQgbG9uZyBsb25nIHJlc3QgPSAobCAmIDB4N2ZmZmZmZmZmZmZmZmZmZikgPj4gMTsKICBpZiAocmVzdCA+PSAweDNmZjAwMDAwMDAwMDAwMDApIHJlc3QgPDw9IDE7CiAgdS51ID0gc2lnbiB8IHJlc3Q7CiAgcmV0dXJuIHUuZDsKfQoKZG91YmxlIGRvdWJsZV9mcm9tX2NlbGwodm9pZCpwKQp7CiAgZG91YmxlIGQgPSBzbWFsbGRvdWJsZV9mcm9tX2NlbGwocCk7CiAgcmV0dXJuIGxkZXhwKGQsICs1MTIpOwp9Cgp2b2lkIGZsb2F0X2NlbGxfYWRkKHZvaWQgKmQsIHZvaWQgKnMxLCB2b2lkICpzMikKewogIGRvdWJsZSBkMSA9IHNtYWxsZG91YmxlX2Zyb21fY2VsbChzMSk7CiAgZG91YmxlIGQyID0gc21hbGxkb3VibGVfZnJvbV9jZWxsKHMyKTsKICBzbWFsbGRvdWJsZV90b19jZWxsKGQsIGQxICsgZDIpOwp9Cgp2b2lkIGZsb2F0X2NlbGxfc3ViKHZvaWQgKmQsIHZvaWQgKnMxLCB2b2lkICpzMikKewogIGRvdWJsZSBkMSA9IHNtYWxsZG91YmxlX2Zyb21fY2VsbChzMSk7CiAgZG91YmxlIGQyID0gc21hbGxkb3VibGVfZnJvbV9jZWxsKHMyKTsKICBzbWFsbGRvdWJsZV90b19jZWxsKGQsIGQxIC0gZDIpOwp9Cgp2b2lkIGZsb2F0X2NlbGxfbXVsKHZvaWQgKmQsIHZvaWQgKnMxLCB2b2lkICpzMikKewogIGRvdWJsZSBkMSA9IHNtYWxsZG91YmxlX2Zyb21fY2VsbChzMSk7CiAgZG91YmxlIGQyID0gc21hbGxkb3VibGVfZnJvbV9jZWxsKHMyKTsKICBzbWFsbGRvdWJsZV90b19jZWxsKGQsIGxkZXhwKGQxLCArNTEyKSAqIGQyKTsKfQoKdm9pZCBmbG9hdF9jZWxsX2Rpdih2b2lkICpkLCB2b2lkICpzMSwgdm9pZCAqczIpCnsKICBkb3VibGUgZDEgPSBzbWFsbGRvdWJsZV9mcm9tX2NlbGwoczEpOwogIGRvdWJsZSBkMiA9IHNtYWxsZG91YmxlX2Zyb21fY2VsbChzMik7CiAgc21hbGxkb3VibGVfdG9fY2VsbChkLCBsZGV4cChkMS9kMiwgLTUxMikpOwp9CgppbnQgbWFpbigpCnsKICB1bnNpZ25lZCBsb25nIGxvbmcgbDEsIGwyLCBsMzsKCiAgZG91YmxlX3RvX2NlbGwoJmwxLCAzLjApOwogIGRvdWJsZV90b19jZWxsKCZsMiwgNy4wKTsKICBmbG9hdF9jZWxsX2FkZCgmbDMsICZsMSwgJmwyKTsKICBwcmludGYoIjMuMCArIDcuMCA9ICVmXG4iLCBkb3VibGVfZnJvbV9jZWxsKCZsMykpOwogIHByaW50ZigicmVwcmVzZW50YXRpb25zOiAlbGx4ICVsbHggJWxseFxuIiwgbDEsIGwyICwgbDMpOwoKICBkb3VibGVfdG9fY2VsbCgmbDEsIG5leHRhZnRlcigxLjAsIDIuMCkpOwogIGRvdWJsZV90b19jZWxsKCZsMiwgbmV4dGFmdGVyKDEuNSwgMC4wKSk7CiAgZmxvYXRfY2VsbF9hZGQoJmwzLCAmbDEsICZsMik7CiAgcHJpbnRmKCIoMSspICsgKDEuNS0pID0gJWZcbiIsIGRvdWJsZV9mcm9tX2NlbGwoJmwzKSk7CiAgcHJpbnRmKCJyZXByZXNlbnRhdGlvbnM6ICVsbHggJWxseCAlbGx4XG4iLCBsMSwgbDIgLCBsMyk7CgogIGRvdWJsZV90b19jZWxsKCZsMSwgMS4wZS0xNjgpOwogIGRvdWJsZV90b19jZWxsKCZsMiwgMS4zZS0xNjgpOwogIGZsb2F0X2NlbGxfYWRkKCZsMywgJmwxLCAmbDIpOwogIHByaW50ZigiKDEuMC0xNjgpICsgKDEuMy0xNjgpID0gJWVcbiIsIGRvdWJsZV9mcm9tX2NlbGwoJmwzKSk7CiAgcHJpbnRmKCJyZXByZXNlbnRhdGlvbnM6ICVsbHggJWxseCAlbGx4XG4iLCBsMSwgbDIgLCBsMyk7CgogIGRvdWJsZV90b19jZWxsKCZsMSwgMS4wZS05MCk7CiAgZG91YmxlX3RvX2NlbGwoJmwyLCAxLjNlLTc4KTsKICBmbG9hdF9jZWxsX211bCgmbDMsICZsMSwgJmwyKTsKICBwcmludGYoIigxLjAtOTApICogKDEuMy03OCkgPSAlZVxuIiwgZG91YmxlX2Zyb21fY2VsbCgmbDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgZG91YmxlX3RvX2NlbGwoJmwxLCAxLjBlKzcwKTsKICBkb3VibGVfdG9fY2VsbCgmbDIsIDEuM2UrNzgpOwogIGZsb2F0X2NlbGxfbXVsKCZsMywgJmwxLCAmbDIpOwogIHByaW50ZigiKDEuMCs3MCkgKiAoMS4zKzc4KSA9ICVlXG4iLCBkb3VibGVfZnJvbV9jZWxsKCZsMykpOwogIHByaW50ZigicmVwcmVzZW50YXRpb25zOiAlbGx4ICVsbHggJWxseFxuIiwgbDEsIGwyICwgbDMpOwoKICBkb3VibGVfdG9fY2VsbCgmbDEsIDEuMGUrOTApOwogIGRvdWJsZV90b19jZWxsKCZsMiwgMS4zZSs3OCk7CiAgZmxvYXRfY2VsbF9tdWwoJmwzLCAmbDEsICZsMik7CiAgcHJpbnRmKCIoMS4wKzkwKSAqICgxLjMrNzgpID0gJWVcbiIsIGRvdWJsZV9mcm9tX2NlbGwoJmwzKSk7CiAgcHJpbnRmKCJyZXByZXNlbnRhdGlvbnM6ICVsbHggJWxseCAlbGx4XG4iLCBsMSwgbDIgLCBsMyk7CgogIGRvdWJsZV90b19jZWxsKCZsMSwgMS4wZSs5MCk7CiAgZG91YmxlX3RvX2NlbGwoJmwyLCAxLjNlKzc4KTsKICBmbG9hdF9jZWxsX2RpdigmbDMsICZsMSwgJmwyKTsKICBwcmludGYoIigxLjArOTApIC8gKDEuMys3OCkgPSAlZVxuIiwgZG91YmxlX2Zyb21fY2VsbCgmbDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgZG91YmxlX3RvX2NlbGwoJmwxLCAxLjBlMjAwKTsKICBkb3VibGVfdG9fY2VsbCgmbDIsIDEuMGUtMjAwKTsKICBmbG9hdF9jZWxsX2RpdigmbDMsICZsMSwgJmwyKTsKICBwcmludGYoImluZiAvIDAgPSAlZVxuIiwgZG91YmxlX2Zyb21fY2VsbCgmbDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgZG91YmxlX3RvX2NlbGwoJmwxLCAxLjBlMjAwKTsKICBkb3VibGVfdG9fY2VsbCgmbDIsIDEuMGUtMjAwKTsKICBmbG9hdF9jZWxsX211bCgmbDMsICZsMSwgJmwyKTsKICBwcmludGYoImluZiAqIDAgPSAlZVxuIiwgZG91YmxlX2Zyb21fY2VsbCgmbDMpKTsKICBwcmludGYoInJlcHJlc2VudGF0aW9uczogJWxseCAlbGx4ICVsbHhcbiIsIGwxLCBsMiAsIGwzKTsKCiAgcmV0dXJuIDA7Cn0K