5b1aa4889ee7ad6d4751e513d13233ef88faf2d6
[libc-test] / src / math / gen / util.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include "gen.h"
6
7 int eulpf(float x)
8 {
9         union { float f; uint32_t i; } u = { x };
10         int e = u.i>>23 & 0xff;
11
12         if (!e)
13                 e++;
14         return e - 0x7f - 23;
15 }
16
17 int eulp(double x)
18 {
19         union { double f; uint64_t i; } u = { x };
20         int e = u.i>>52 & 0x7ff;
21
22         if (!e)
23                 e++;
24         return e - 0x3ff - 52;
25 }
26
27 int eulpl(long double x)
28 {
29 #if LDBL_MANT_DIG == 53
30         return eulp(x);
31 #elif LDBL_MANT_DIG == 64
32         union { long double f; struct {uint64_t m; uint16_t e; uint16_t pad;} i; } u = { x };
33         int e = u.i.e & 0x7fff;
34
35         if (!e)
36                 e++;
37         return e - 0x3fff - 63;
38 #else
39         // TODO
40         return 0;
41 #endif
42 }
43
44 double ulperr(double y, double ycr, double dy)
45 {
46         return dy + scalbn(ycr - y, -eulp(ycr));
47 }
48
49 char *skipstr(char *buf, char *sep)
50 {
51         while (*buf && strchr(sep, *buf))
52                 buf++;
53         return buf;
54 }
55
56 int splitstr(char **a, int n, char *buf, char *sep)
57 {
58         int i, j;
59
60         for (i = j = 0; j < n; j++) {
61                 for (; buf[i] && strchr(sep, buf[i]); i++)
62                                 buf[i] = 0;
63                 a[j] = buf + i;
64                 if (buf[i] == 0)
65                         break;
66                 for (i++; buf[i] && !strchr(sep, buf[i]); i++);
67         }
68         return j;
69 }
70
71 char *dropcomm(char *buf)
72 {
73         char *p = buf;
74
75         for (; *p; p++)
76                 if (*p == '/' && p[1] == '/') {
77                         *p = 0;
78                         break;
79                 }
80         return buf;
81 }
82
83 #define length(a) (sizeof(a)/sizeof(*a))
84 #define flag(x) {x, #x}
85 static struct {
86         int flag;
87         char *s;
88 } eflags[] = {
89         flag(INEXACT),
90         flag(INVALID),
91         flag(DIVBYZERO),
92         flag(UNDERFLOW),
93         flag(OVERFLOW)
94 };
95
96 char *estr(int f)
97 {
98         static char buf[256];
99         char *p = buf;
100         int i, all = 0;
101
102         for (i = 0; i < length(eflags); i++)
103                 if (f & eflags[i].flag) {
104                         p += sprintf(p, "%s%s", all ? "|" : "", eflags[i].s);
105                         all |= eflags[i].flag;
106                 }
107         if (all != f) {
108                 p += sprintf(p, "%s%d", all ? "|" : "", f & ~all);
109                 all = f;
110         }
111         p += sprintf(p, "%s", all ? "" : "0");
112         return buf;
113 }
114
115 int econv(int *f, char *s)
116 {
117         char *a[16];
118         char *e;
119         int i,j,k,n;
120
121         *f = 0;
122         n = splitstr(a, length(a), s, "|");
123         for (i = 0; i < n; i++) {
124                 for (j = 0; j < length(eflags); j++)
125                         if (strcmp(a[i], eflags[j].s) == 0) {
126                                 *f |= eflags[j].flag;
127                                 break;
128                         }
129                 if (j == length(eflags)) {
130                         k = strtol(a[i], &e, 0);
131                         if (*e)
132                                 return -1;
133                         *f |= k;
134                 }
135         }
136         return 0;
137 }
138
139 char *rstr(int r)
140 {
141         switch (r) {
142         case RN: return "RN";
143         case RZ: return "RZ";
144         case RU: return "RU";
145         case RD: return "RD";
146         }
147         return "R?";
148 }
149
150 int rconv(int *r, char *s)
151 {
152         if (strcmp(s, "RN") == 0)
153                 *r = RN;
154         else if (strcmp(s, "RZ") == 0)
155                 *r = RZ;
156         else if (strcmp(s, "RD") == 0)
157                 *r = RD;
158         else if (strcmp(s, "RU") == 0)
159                 *r = RU;
160         else
161                 return -1;
162         return 0;
163 }
164
165 void setupfenv(int r)
166 {
167         fesetround(r);
168         feclearexcept(FE_ALL_EXCEPT);
169 }
170
171 int getexcept(void)
172 {
173         return fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW);
174 }
175