• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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