xref: /third_party/musl/libc-test/src/math/gen/util.c (revision 570af302)
1570af302Sopenharmony_ci#include <stdlib.h>
2570af302Sopenharmony_ci#include <stdio.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci#include <stdint.h>
5570af302Sopenharmony_ci#include "gen.h"
6570af302Sopenharmony_ci
7570af302Sopenharmony_ciint eulpf(float x)
8570af302Sopenharmony_ci{
9570af302Sopenharmony_ci	union { float f; uint32_t i; } u = { x };
10570af302Sopenharmony_ci	int e = u.i>>23 & 0xff;
11570af302Sopenharmony_ci
12570af302Sopenharmony_ci	if (!e)
13570af302Sopenharmony_ci		e++;
14570af302Sopenharmony_ci	return e - 0x7f - 23;
15570af302Sopenharmony_ci}
16570af302Sopenharmony_ci
17570af302Sopenharmony_ciint eulp(double x)
18570af302Sopenharmony_ci{
19570af302Sopenharmony_ci	union { double f; uint64_t i; } u = { x };
20570af302Sopenharmony_ci	int e = u.i>>52 & 0x7ff;
21570af302Sopenharmony_ci
22570af302Sopenharmony_ci	if (!e)
23570af302Sopenharmony_ci		e++;
24570af302Sopenharmony_ci	return e - 0x3ff - 52;
25570af302Sopenharmony_ci}
26570af302Sopenharmony_ci
27570af302Sopenharmony_ciint eulpl(long double x)
28570af302Sopenharmony_ci{
29570af302Sopenharmony_ci#if LDBL_MANT_DIG == 53
30570af302Sopenharmony_ci	return eulp(x);
31570af302Sopenharmony_ci#elif LDBL_MANT_DIG == 64
32570af302Sopenharmony_ci	union { long double f; struct {uint64_t m; uint16_t e; uint16_t pad;} i; } u = { x };
33570af302Sopenharmony_ci	int e = u.i.e & 0x7fff;
34570af302Sopenharmony_ci
35570af302Sopenharmony_ci	if (!e)
36570af302Sopenharmony_ci		e++;
37570af302Sopenharmony_ci	return e - 0x3fff - 63;
38570af302Sopenharmony_ci#else
39570af302Sopenharmony_ci	// TODO
40570af302Sopenharmony_ci	return 0;
41570af302Sopenharmony_ci#endif
42570af302Sopenharmony_ci}
43570af302Sopenharmony_ci
44570af302Sopenharmony_cidouble ulperr(double y, double ycr, double dy)
45570af302Sopenharmony_ci{
46570af302Sopenharmony_ci	return dy + scalbn(ycr - y, -eulp(ycr));
47570af302Sopenharmony_ci}
48570af302Sopenharmony_ci
49570af302Sopenharmony_cichar *skipstr(char *buf, char *sep)
50570af302Sopenharmony_ci{
51570af302Sopenharmony_ci	while (*buf && strchr(sep, *buf))
52570af302Sopenharmony_ci		buf++;
53570af302Sopenharmony_ci	return buf;
54570af302Sopenharmony_ci}
55570af302Sopenharmony_ci
56570af302Sopenharmony_ciint splitstr(char **a, int n, char *buf, char *sep)
57570af302Sopenharmony_ci{
58570af302Sopenharmony_ci	int i, j;
59570af302Sopenharmony_ci
60570af302Sopenharmony_ci	for (i = j = 0; j < n; j++) {
61570af302Sopenharmony_ci		for (; buf[i] && strchr(sep, buf[i]); i++)
62570af302Sopenharmony_ci				buf[i] = 0;
63570af302Sopenharmony_ci		a[j] = buf + i;
64570af302Sopenharmony_ci		if (buf[i] == 0)
65570af302Sopenharmony_ci			break;
66570af302Sopenharmony_ci		for (i++; buf[i] && !strchr(sep, buf[i]); i++);
67570af302Sopenharmony_ci	}
68570af302Sopenharmony_ci	return j;
69570af302Sopenharmony_ci}
70570af302Sopenharmony_ci
71570af302Sopenharmony_cichar *dropcomm(char *buf)
72570af302Sopenharmony_ci{
73570af302Sopenharmony_ci	char *p = buf;
74570af302Sopenharmony_ci
75570af302Sopenharmony_ci	for (; *p; p++)
76570af302Sopenharmony_ci		if ((*p == '/' && p[1] == '/') || *p == '#') {
77570af302Sopenharmony_ci			*p = 0;
78570af302Sopenharmony_ci			break;
79570af302Sopenharmony_ci		}
80570af302Sopenharmony_ci	return buf;
81570af302Sopenharmony_ci}
82570af302Sopenharmony_ci
83570af302Sopenharmony_ci#define length(a) (sizeof(a)/sizeof(*a))
84570af302Sopenharmony_ci#define flag(x) {x, #x}
85570af302Sopenharmony_cistatic struct {
86570af302Sopenharmony_ci	int flag;
87570af302Sopenharmony_ci	char *s;
88570af302Sopenharmony_ci} eflags[] = {
89570af302Sopenharmony_ci	flag(INEXACT),
90570af302Sopenharmony_ci	flag(INVALID),
91570af302Sopenharmony_ci	flag(DIVBYZERO),
92570af302Sopenharmony_ci	flag(UNDERFLOW),
93570af302Sopenharmony_ci	flag(OVERFLOW)
94570af302Sopenharmony_ci};
95570af302Sopenharmony_ci
96570af302Sopenharmony_cichar *estr(int f)
97570af302Sopenharmony_ci{
98570af302Sopenharmony_ci	static char buf[256];
99570af302Sopenharmony_ci	char *p = buf;
100570af302Sopenharmony_ci	int i, all = 0;
101570af302Sopenharmony_ci
102570af302Sopenharmony_ci	for (i = 0; i < length(eflags); i++)
103570af302Sopenharmony_ci		if (f & eflags[i].flag) {
104570af302Sopenharmony_ci			p += sprintf(p, "%s%s", all ? "|" : "", eflags[i].s);
105570af302Sopenharmony_ci			all |= eflags[i].flag;
106570af302Sopenharmony_ci		}
107570af302Sopenharmony_ci	if (all != f) {
108570af302Sopenharmony_ci		p += sprintf(p, "%s%d", all ? "|" : "", f & ~all);
109570af302Sopenharmony_ci		all = f;
110570af302Sopenharmony_ci	}
111570af302Sopenharmony_ci	p += sprintf(p, "%s", all ? "" : "0");
112570af302Sopenharmony_ci	return buf;
113570af302Sopenharmony_ci}
114570af302Sopenharmony_ci
115570af302Sopenharmony_ciint econv(int *f, char *s)
116570af302Sopenharmony_ci{
117570af302Sopenharmony_ci	char *a[16];
118570af302Sopenharmony_ci	char *e;
119570af302Sopenharmony_ci	int i,j,k,n;
120570af302Sopenharmony_ci
121570af302Sopenharmony_ci	*f = 0;
122570af302Sopenharmony_ci	n = splitstr(a, length(a), s, "|");
123570af302Sopenharmony_ci	for (i = 0; i < n; i++) {
124570af302Sopenharmony_ci		for (j = 0; j < length(eflags); j++)
125570af302Sopenharmony_ci			if (strcmp(a[i], eflags[j].s) == 0) {
126570af302Sopenharmony_ci				*f |= eflags[j].flag;
127570af302Sopenharmony_ci				break;
128570af302Sopenharmony_ci			}
129570af302Sopenharmony_ci		if (j == length(eflags)) {
130570af302Sopenharmony_ci			k = strtol(a[i], &e, 0);
131570af302Sopenharmony_ci			if (*e)
132570af302Sopenharmony_ci				return -1;
133570af302Sopenharmony_ci			*f |= k;
134570af302Sopenharmony_ci		}
135570af302Sopenharmony_ci	}
136570af302Sopenharmony_ci	return 0;
137570af302Sopenharmony_ci}
138570af302Sopenharmony_ci
139570af302Sopenharmony_cichar *rstr(int r)
140570af302Sopenharmony_ci{
141570af302Sopenharmony_ci	switch (r) {
142570af302Sopenharmony_ci	case RN: return "RN";
143570af302Sopenharmony_ci	case RZ: return "RZ";
144570af302Sopenharmony_ci	case RU: return "RU";
145570af302Sopenharmony_ci	case RD: return "RD";
146570af302Sopenharmony_ci	}
147570af302Sopenharmony_ci	return "R?";
148570af302Sopenharmony_ci}
149570af302Sopenharmony_ci
150570af302Sopenharmony_ciint rconv(int *r, char *s)
151570af302Sopenharmony_ci{
152570af302Sopenharmony_ci	if (strcmp(s, "RN") == 0)
153570af302Sopenharmony_ci		*r = RN;
154570af302Sopenharmony_ci	else if (strcmp(s, "RZ") == 0)
155570af302Sopenharmony_ci		*r = RZ;
156570af302Sopenharmony_ci	else if (strcmp(s, "RD") == 0)
157570af302Sopenharmony_ci		*r = RD;
158570af302Sopenharmony_ci	else if (strcmp(s, "RU") == 0)
159570af302Sopenharmony_ci		*r = RU;
160570af302Sopenharmony_ci	else
161570af302Sopenharmony_ci		return -1;
162570af302Sopenharmony_ci	return 0;
163570af302Sopenharmony_ci}
164570af302Sopenharmony_ci
165570af302Sopenharmony_civoid setupfenv(int r)
166570af302Sopenharmony_ci{
167570af302Sopenharmony_ci	fesetround(r);
168570af302Sopenharmony_ci	feclearexcept(FE_ALL_EXCEPT);
169570af302Sopenharmony_ci}
170570af302Sopenharmony_ci
171570af302Sopenharmony_ciint getexcept(void)
172570af302Sopenharmony_ci{
173570af302Sopenharmony_ci	return fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW);
174570af302Sopenharmony_ci}
175570af302Sopenharmony_ci
176