runtime: implement round() (fixes #198).

From https://github.com/bpowers/musl/blob/master/src/math/round.c.
This commit is contained in:
whitequark 2015-12-20 04:06:03 +08:00
parent 54aeb5030d
commit d5216879d4
1 changed files with 33 additions and 0 deletions

View File

@ -17,6 +17,8 @@
#include "dds.h" #include "dds.h"
#include "rtio.h" #include "rtio.h"
double round(double x);
void ksupport_abort(void); void ksupport_abort(void);
int64_t now; int64_t now;
@ -82,6 +84,9 @@ static const struct symbol runtime_exports[] = {
{"__moddi3", &__moddi3}, {"__moddi3", &__moddi3},
{"__powidf2", &__powidf2}, {"__powidf2", &__powidf2},
/* libm */
{"round", &round},
/* exceptions */ /* exceptions */
{"_Unwind_Resume", &_Unwind_Resume}, {"_Unwind_Resume", &_Unwind_Resume},
{"__artiq_personality", &__artiq_personality}, {"__artiq_personality", &__artiq_personality},
@ -118,6 +123,34 @@ static const struct symbol runtime_exports[] = {
{NULL, NULL} {NULL, NULL}
}; };
double round(double x)
{
union {double f; uint64_t i;} u = {x};
int e = u.i >> 52 & 0x7ff;
double y;
if (e >= 0x3ff+52)
return x;
if (u.i >> 63)
x = -x;
if (e < 0x3ff-1) {
/* we don't do it in ARTIQ */
/* raise inexact if x!=0 */
// FORCE_EVAL(x + 0x1p52);
return 0*u.f;
}
y = (double)(x + 0x1p52) - 0x1p52 - x;
if (y > 0.5)
y = y + x - 1;
else if (y <= -0.5)
y = y + x + 1;
else
y = y + x;
if (u.i >> 63)
y = -y;
return y;
}
/* called by libunwind */ /* called by libunwind */
int fprintf(FILE *stream, const char *fmt, ...) int fprintf(FILE *stream, const char *fmt, ...)
{ {