1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include "gen.h"
6
eulpf(float x)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
eulp(double x)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
eulpl(long double x)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
ulperr(double y,double ycr,double dy)44 double ulperr(double y, double ycr, double dy)
45 {
46 return dy + scalbn(ycr - y, -eulp(ycr));
47 }
48
skipstr(char * buf,char * sep)49 char *skipstr(char *buf, char *sep)
50 {
51 while (*buf && strchr(sep, *buf))
52 buf++;
53 return buf;
54 }
55
splitstr(char ** a,int n,char * buf,char * sep)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
dropcomm(char * buf)71 char *dropcomm(char *buf)
72 {
73 char *p = buf;
74
75 for (; *p; p++)
76 if ((*p == '/' && p[1] == '/') || *p == '#') {
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
estr(int f)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
econv(int * f,char * s)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
rstr(int r)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
rconv(int * r,char * s)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
setupfenv(int r)165 void setupfenv(int r)
166 {
167 fesetround(r);
168 feclearexcept(FE_ALL_EXCEPT);
169 }
170
getexcept(void)171 int getexcept(void)
172 {
173 return fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW);
174 }
175
176