silleee: added silleee_add and silleee_sub
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,4 +1,4 @@
|
|||||||
LIBFILES=sileee.c
|
LIBFILES=silleee.c
|
||||||
TESTFILES=$(wildcard tests/*.c)
|
TESTFILES=$(wildcard tests/*.c)
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
90
silleee.c
90
silleee.c
@@ -1,7 +1,95 @@
|
|||||||
|
#include "silleee.h"
|
||||||
|
|
||||||
silleee silleee_sub(silleee x, silleee y) {
|
silleee silleee_sub(silleee x, silleee y) {
|
||||||
y ^= 0x80000000;
|
y ^= 0x80000000;
|
||||||
return silleee_add(x, y);
|
return silleee_add(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
silleee silleee_add(silleeee x, silleeee 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);
|
||||||
}
|
}
|
||||||
|
10
silleee.h
10
silleee.h
@@ -1,10 +1,12 @@
|
|||||||
#define asreal(x) (*((float *) &x))
|
#define assilleee(x) (*((float *) &x))
|
||||||
#define exponent(x) (((x >> 23) & 0xff) - 127)
|
#define exponent(x) (((x >> 23) & 0xff) - 127)
|
||||||
#define sign_bit 1 << 31
|
#define sign_bit 1 << 31
|
||||||
#define sign(x) ((x & sign_bit) >> 31)
|
#define sign(x) ((x & sign_bit) >> 31)
|
||||||
#define mantissa(x) ((x & sign_bit) ? ((x & 0x7fffff) | 0x800000) : 0)
|
#define mantissa(x) ((x & 0x7fffffff) ? ((x & 0x7fffff) | sign_bit) : 0)
|
||||||
|
#define pack_silleee(sign, exponent, mantissa) \
|
||||||
|
((silleee)((sign<<31)|((exponent+127)<<23)|(mantissa&0x7fffff)))
|
||||||
|
|
||||||
typedef long unsigned silleee;
|
typedef long unsigned silleee;
|
||||||
|
|
||||||
sillee silleee_add(sillee, sillee);
|
silleee silleee_add(silleee, silleee);
|
||||||
sillee silleee_sub(sillee, sillee);
|
silleee silleee_sub(silleee, silleee);
|
||||||
|
34
tests/test.c
34
tests/test.c
@@ -8,11 +8,41 @@
|
|||||||
ASSERT_IN_RANGE(0, delta, DELTA);\
|
ASSERT_IN_RANGE(0, delta, DELTA);\
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST silleee_zeros_is_zero() {
|
TEST silleee_addition() {
|
||||||
|
silleee x, y, res;
|
||||||
|
assilleee(x) = 1.0;
|
||||||
|
assilleee(y) = 2.0;
|
||||||
|
|
||||||
|
assilleee(res) = 3.0;
|
||||||
|
ASSERT_EQ_FMT(res, silleee_add(x, y), "%lu");
|
||||||
|
|
||||||
|
assilleee(y) = 0.25;
|
||||||
|
|
||||||
|
assilleee(res) = 1.25;
|
||||||
|
ASSERT_EQ_FMT(res, silleee_add(x, y), "%lu");
|
||||||
|
|
||||||
|
PASS();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST silleee_subtraction() {
|
||||||
|
silleee x, y, res;
|
||||||
|
assilleee(x) = 2.0;
|
||||||
|
assilleee(y) = 1.0;
|
||||||
|
|
||||||
|
assilleee(res) = 1.0;
|
||||||
|
ASSERT_EQ_FMT(res, silleee_sub(x, y), "%lu");
|
||||||
|
|
||||||
|
assilleee(y) = 0.25;
|
||||||
|
|
||||||
|
assilleee(res) = 1.75;
|
||||||
|
ASSERT_EQ_FMT(res, silleee_sub(x, y), "%lu");
|
||||||
|
|
||||||
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
SUITE(tests) {
|
SUITE(tests) {
|
||||||
RUN_TEST(silly_zeros_is_zero);
|
RUN_TEST(silleee_addition);
|
||||||
|
RUN_TEST(silleee_subtraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
GREATEST_MAIN_DEFS();
|
GREATEST_MAIN_DEFS();
|
||||||
|
Reference in New Issue
Block a user