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