Blame src/common/mtest.c

Szabolcs Nagy cfa23c
#include <stdio.h>
Szabolcs Nagy cfa23c
#include <stdint.h>
Szabolcs Nagy cfa23c
#include "mtest.h"
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
int eulpf(float x)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	union { float f; uint32_t i; } u = { x };
Szabolcs Nagy cfa23c
	int e = u.i>>23 & 0xff;
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
	if (!e)
Szabolcs Nagy cfa23c
		e++;
Szabolcs Nagy cfa23c
	return e - 0x7f - 23;
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
int eulp(double x)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	union { double f; uint64_t i; } u = { x };
Szabolcs Nagy cfa23c
	int e = u.i>>52 & 0x7ff;
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
	if (!e)
Szabolcs Nagy cfa23c
		e++;
Szabolcs Nagy cfa23c
	return e - 0x3ff - 52;
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
int eulpl(long double x)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
#if LDBL_MANT_DIG == 53
Szabolcs Nagy cfa23c
	return eulp(x);
Szabolcs Nagy cfa23c
#elif LDBL_MANT_DIG == 64
Szabolcs Nagy cfa23c
	union { long double f; struct {uint64_t m; uint16_t e; uint16_t pad;} i; } u = { x };
Szabolcs Nagy cfa23c
	int e = u.i.e & 0x7fff;
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
	if (!e)
Szabolcs Nagy cfa23c
		e++;
Szabolcs Nagy cfa23c
	return e - 0x3fff - 63;
Szabolcs Nagy cfa23c
#else
Szabolcs Nagy cfa23c
	// TODO
Szabolcs Nagy cfa23c
	return 0;
Szabolcs Nagy cfa23c
#endif
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
float ulperrf(float got, float want, float dwant)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	if (isnan(got) && isnan(want))
Szabolcs Nagy cfa23c
		return 0;
Szabolcs Nagy cfa23c
	if (got == want) {
Szabolcs Nagy cfa23c
		if (signbit(got) == signbit(want))
Szabolcs Nagy cfa23c
			return dwant;
Szabolcs Nagy cfa23c
		return inf;
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	if (isinf(got)) {
Szabolcs Nagy cfa23c
		got = copysignf(0x1p127, got);
Szabolcs Nagy cfa23c
		want *= 0.5;
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	return scalbn(got - want, -eulpf(want)) + dwant;
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
float ulperr(double got, double want, float dwant)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	if (isnan(got) && isnan(want))
Szabolcs Nagy cfa23c
		return 0;
Szabolcs Nagy cfa23c
	if (got == want) {
Szabolcs Nagy cfa23c
		if (signbit(got) == signbit(want))
Szabolcs Nagy cfa23c
			return dwant;
Szabolcs Nagy cfa23c
		return inf; // treat 0 sign errors badly
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	if (isinf(got)) {
Szabolcs Nagy cfa23c
		got = copysign(0x1p1023, got);
Szabolcs Nagy cfa23c
		want *= 0.5;
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	return scalbn(got - want, -eulp(want)) + dwant;
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
float ulperrl(long double got, long double want, float dwant)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
#if LDBL_MANT_DIG == 53
Szabolcs Nagy cfa23c
	return ulperr(got, want, dwant);
Szabolcs Nagy cfa23c
#elif LDBL_MANT_DIG == 64
Szabolcs Nagy cfa23c
	if (isnan(got) && isnan(want))
Szabolcs Nagy cfa23c
		return 0;
Szabolcs Nagy cfa23c
	if (got == want) {
Szabolcs Nagy cfa23c
		if (signbit(got) == signbit(want))
Szabolcs Nagy cfa23c
			return dwant;
Szabolcs Nagy cfa23c
		return inf;
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	if (isinf(got)) {
Szabolcs Nagy cfa23c
		got = copysignl(0x1p16383L, got);
Szabolcs Nagy cfa23c
		want *= 0.5;
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	return scalbnl(got - want, -eulpl(want)) + dwant;
Szabolcs Nagy cfa23c
#else
Szabolcs Nagy cfa23c
	// TODO
Szabolcs Nagy cfa23c
	return inf;
Szabolcs Nagy cfa23c
#endif
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
#define length(a) (sizeof(a)/sizeof*(a))
Szabolcs Nagy cfa23c
#define flag(x) {x, #x}
Szabolcs Nagy cfa23c
static struct {
Szabolcs Nagy cfa23c
	int flag;
Szabolcs Nagy cfa23c
	char *s;
Szabolcs Nagy cfa23c
} eflags[] = {
Szabolcs Nagy cfa23c
	flag(INEXACT),
Szabolcs Nagy cfa23c
	flag(INVALID),
Szabolcs Nagy cfa23c
	flag(DIVBYZERO),
Szabolcs Nagy cfa23c
	flag(UNDERFLOW),
Szabolcs Nagy cfa23c
	flag(OVERFLOW)
Szabolcs Nagy cfa23c
};
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
char *estr(int f)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	static char buf[256];
Szabolcs Nagy cfa23c
	char *p = buf;
Szabolcs Nagy cfa23c
	int i, all = 0;
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
	for (i = 0; i < length(eflags); i++)
Szabolcs Nagy cfa23c
		if (f & eflags[i].flag) {
Szabolcs Nagy cfa23c
			p += sprintf(p, "%s%s", all ? "|" : "", eflags[i].s);
Szabolcs Nagy cfa23c
			all |= eflags[i].flag;
Szabolcs Nagy cfa23c
		}
Szabolcs Nagy cfa23c
	if (all != f) {
Szabolcs Nagy cfa23c
		p += sprintf(p, "%s%d", all ? "|" : "", f & ~all);
Szabolcs Nagy cfa23c
		all = f;
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	p += sprintf(p, "%s", all ? "" : "0");
Szabolcs Nagy cfa23c
	return buf;
Szabolcs Nagy cfa23c
}
Szabolcs Nagy cfa23c
Szabolcs Nagy cfa23c
char *rstr(int r)
Szabolcs Nagy cfa23c
{
Szabolcs Nagy cfa23c
	switch (r) {
Szabolcs Nagy cfa23c
	case RN: return "RN";
Szabolcs Nagy cfa23c
#ifdef FE_TOWARDZERO
Szabolcs Nagy cfa23c
	case RZ: return "RZ";
Szabolcs Nagy cfa23c
#endif
Szabolcs Nagy cfa23c
#ifdef FE_UPWARD
Szabolcs Nagy cfa23c
	case RU: return "RU";
Szabolcs Nagy cfa23c
#endif
Szabolcs Nagy cfa23c
#ifdef FE_DOWNWARD
Szabolcs Nagy cfa23c
	case RD: return "RD";
Szabolcs Nagy cfa23c
#endif
Szabolcs Nagy cfa23c
	}
Szabolcs Nagy cfa23c
	return "R?";
Szabolcs Nagy cfa23c
}