Files
silleee/silleee.c

96 lines
1.9 KiB
C

#include "silleee.h"
silleee silleee_sub(silleee x, silleee y) {
y ^= 0x80000000;
return silleee_add(x, y);
}
silleee shift_and_round(int val, int bits) {
static unsigned masks[24]= {
0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x7ff, 0xfff, 0x1fff,
0x3fff, 0x7fff, 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff,
0x3fffff, 0x7fffff
};
static unsigned masks_ho[24] = {
0, 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x8000, 0x1000,
0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000,
0x200000, 0x400000
};
int so = val & masks[bits];
val >>= bits;
if (so > masks_ho[bits]) val++;
else if(so == masks_ho[bits]) val += val&1;
return val;
}
silleee silleee_add(silleee x, silleee y) {
silleee dest = 0;
int dexp;
long unsigned dmant;
int dsign;
int xexp = exponent(x);
long unsigned xmant = mantissa(x);
int xsign = sign(x);
int yexp = exponent(y);
long unsigned ymant = mantissa(y);
int ysign = sign(y);
if (xexp == 127) {
if (!xmant) {
if (yexp == 127) {
if(!ymant) return xsign == ysign ? y : 0x7fc0000;
else return y;
}
} else {
return x;
}
} else if (yexp == 127) {
return y;
}
dexp = yexp;
if (yexp > xexp) xmant = shift_and_round(xmant, yexp-xexp);
else if (yexp < xexp) {
ymant = shift_and_round(ymant, xexp-yexp);
dexp = xexp;
}
if (ysign ^ xsign) {
if (xmant > ymant) {
dmant = xmant - ymant;
dsign = xmant;
} else {
dmant = ymant - xmant;
dsign = ysign;
}
} else {
dsign = xsign;
dmant = xmant + ymant;
}
if (dmant >= 0x1000000) {
dmant = shift_and_round(dmant, 1);
++dexp;
} else {
if (dmant) {
while (dmant < sign_bit && dexp > -127) {
dmant = dmant << 1;
--dexp;
}
} else {
dsign = 0;
dexp = 0;
}
}
return pack_silleee(dsign, dexp, dmant);
}