diff --git a/src/math/frexpf.c b/src/math/frexpf.c index f43da51..6eefa7d 100644 --- a/src/math/frexpf.c +++ b/src/math/frexpf.c @@ -33,7 +33,7 @@ int main(void) err++; } d = ulperrf(y, p->y, p->dy); - if (!checkulp(d, p->r)) { + if (!checkulp(d, p->r) || yi != p->i) { printf("%s:%d: %s frexpf(%a) want %a,%lld got %a,%d ulperr %.3f = %a + %a\n", p->file, p->line, rstr(p->r), p->x, p->y, p->i, y, yi, d, d-p->dy, p->dy); err++; diff --git a/src/math/gen/functions.h b/src/math/gen/functions.h index b8e3180..c13a166 100644 --- a/src/math/gen/functions.h +++ b/src/math/gen/functions.h @@ -159,3 +159,6 @@ T(lgammal, l_li) T(lgamma_r, d_di) T(lgammaf_r, f_fi) T(lgammal_r, l_li) +T(ilogb, d_i) +T(ilogbf, f_i) +T(ilogbl, l_i) diff --git a/src/math/gen/gen.h b/src/math/gen/gen.h index 80c2da5..da3d716 100644 --- a/src/math/gen/gen.h +++ b/src/math/gen/gen.h @@ -27,13 +27,6 @@ #define inf INFINITY #define nan NAN -struct f1 { int r; float x; float y; float dy; int e; }; -struct f2 { int r; float x; float x2; float y; float dy; int e; }; -struct d1 { int r; double x; double y; float dy; int e; }; -struct d2 { int r; double x; double x2; double y; float dy; int e; }; -struct l1 { int r; long double x; long double y; float dy; int e; }; -struct l2 { int r; long double x; long double x2; long double y; float dy; int e; }; - struct t { int type; int r; diff --git a/src/math/gen/mp.c b/src/math/gen/mp.c index 56badb5..0331313 100644 --- a/src/math/gen/mp.c +++ b/src/math/gen/mp.c @@ -673,3 +673,32 @@ int mpscalblnl(struct t *t) { return mpldexpl(t); } int mplgamma_r(struct t *t) { return mplgamma(t); } int mplgammaf_r(struct t *t) { return mplgammaf(t); } int mplgammal_r(struct t *t) { return mplgammal(t); } + +int mpilogb(struct t *t) +{ + MPFR_DECL_INIT(mx, 53); + + mpfr_set_d(mx, t->x, MPFR_RNDN); + t->i = mpfr_get_exp(mx) - 1; + t->e = 0; + return 0; +} +int mpilogbf(struct t *t) +{ + MPFR_DECL_INIT(mx, 24); + + mpfr_set_flt(mx, t->x, MPFR_RNDN); + t->i = mpfr_get_exp(mx) - 1; + t->e = 0; + return 0; +} +int mpilogbl(struct t *t) +{ + MPFR_DECL_INIT(mx, 64); + + mpfr_set_ld(mx, t->x, MPFR_RNDN); + t->i = mpfr_get_exp(mx) - 1; + t->e = 0; + return 0; +} + diff --git a/src/math/gen/mplibm.c b/src/math/gen/mplibm.c index 4b3ad3f..0546202 100644 --- a/src/math/gen/mplibm.c +++ b/src/math/gen/mplibm.c @@ -388,3 +388,25 @@ int mplgammal_r(struct t *t) return 0; } +int mpilogb(struct t *t) +{ + setupfenv(t->r); + t->i = ilogb(t->x); + t->e = getexcept(); + return 0; +} +int mpilogbf(struct t *t) +{ + setupfenv(t->r); + t->i = ilogbf(t->x); + t->e = getexcept(); + return 0; +} +int mpilogbl(struct t *t) +{ + setupfenv(t->r); + t->i = ilogbl(t->x); + t->e = getexcept(); + return 0; +} + diff --git a/src/math/gen/template/d_i.c b/src/math/gen/template/d_i.c new file mode 100644 index 0000000..3b7e491 --- /dev/null +++ b/src/math/gen/template/d_i.c @@ -0,0 +1,40 @@ +#include +#include +#include "util.h" + +static struct d_i t[] = { +HEADERS +}; + +int main(void) +{ + #pragma STDC FENV_ACCESS ON + int yi; + float d; + int e, i, err = 0; + struct d_i *p; + + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + fesetround(p->r); + feclearexcept(FE_ALL_EXCEPT); + yi = ___(p->x); + e = fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW); + + if (!checkexcept(e, p->e, p->r)) { + printf("%s:%d: bad fp exception: %s ___(%a)=%lld, want %s", + p->file, p->line, rstr(p->r), p->x, p->i, estr(p->e)); + printf(" got %s\n", estr(e)); + err++; + } + if (yi != p->i) { + printf("%s:%d: %s ___(%a) want %lld got %d\n", + p->file, p->line, rstr(p->r), p->x, p->i, yi); + err++; + } + } + return !!err; +} diff --git a/src/math/gen/template/f_fi.c b/src/math/gen/template/f_fi.c index 1e19a4c..4a2104e 100644 --- a/src/math/gen/template/f_fi.c +++ b/src/math/gen/template/f_fi.c @@ -32,7 +32,7 @@ int main(void) err++; } d = ulperrf(y, p->y, p->dy); - if (!checkulp(d, p->r)) { + if (!checkulp(d, p->r) || yi != p->i) { printf("%s:%d: %s ___(%a) want %a,%lld got %a,%d ulperr %.3f = %a + %a\n", p->file, p->line, rstr(p->r), p->x, p->y, p->i, y, yi, d, d-p->dy, p->dy); err++; diff --git a/src/math/gen/template/f_i.c b/src/math/gen/template/f_i.c new file mode 100644 index 0000000..e5f0302 --- /dev/null +++ b/src/math/gen/template/f_i.c @@ -0,0 +1,40 @@ +#include +#include +#include "util.h" + +static struct f_i t[] = { +HEADERS +}; + +int main(void) +{ + #pragma STDC FENV_ACCESS ON + int yi; + float d; + int e, i, err = 0; + struct f_i *p; + + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + fesetround(p->r); + feclearexcept(FE_ALL_EXCEPT); + yi = ___(p->x); + e = fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW); + + if (!checkexcept(e, p->e, p->r)) { + printf("%s:%d: bad fp exception: %s ___(%a)=%lld, want %s", + p->file, p->line, rstr(p->r), p->x, p->i, estr(p->e)); + printf(" got %s\n", estr(e)); + err++; + } + if (yi != p->i) { + printf("%s:%d: %s ___(%a) want %lld got %d\n", + p->file, p->line, rstr(p->r), p->x, p->i, yi); + err++; + } + } + return !!err; +} diff --git a/src/math/gen/template/l_i.c b/src/math/gen/template/l_i.c new file mode 100644 index 0000000..26b3470 --- /dev/null +++ b/src/math/gen/template/l_i.c @@ -0,0 +1,44 @@ +#include +#include +#include "util.h" + +static struct l_i t[] = { +#if LDBL_MANT_DIG == 53 +DHEADERS +#elif LDBL_MANT_DIG == 64 +HEADERS +#endif +}; + +int main(void) +{ + #pragma STDC FENV_ACCESS ON + int yi; + float d; + int e, i, err = 0; + struct l_i *p; + + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + fesetround(p->r); + feclearexcept(FE_ALL_EXCEPT); + yi = ___(p->x); + e = fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW); + + if (!checkexcept(e, p->e, p->r)) { + printf("%s:%d: bad fp exception: %s ___(%La)=%lld, want %s", + p->file, p->line, rstr(p->r), p->x, p->i, estr(p->e)); + printf(" got %s\n", estr(e)); + err++; + } + if (yi != p->i) { + printf("%s:%d: %s ___(%La) want %lld got %d\n", + p->file, p->line, rstr(p->r), p->x, p->i, yi); + err++; + } + } + return !!err; +} diff --git a/src/math/ilogb.c b/src/math/ilogb.c new file mode 100644 index 0000000..c0915a1 --- /dev/null +++ b/src/math/ilogb.c @@ -0,0 +1,41 @@ +#include +#include +#include "util.h" + +static struct d_i t[] = { +#include "sanity/ilogb.h" + +}; + +int main(void) +{ + #pragma STDC FENV_ACCESS ON + int yi; + float d; + int e, i, err = 0; + struct d_i *p; + + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + fesetround(p->r); + feclearexcept(FE_ALL_EXCEPT); + yi = ilogb(p->x); + e = fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW); + + if (!checkexcept(e, p->e, p->r)) { + printf("%s:%d: bad fp exception: %s ilogb(%a)=%lld, want %s", + p->file, p->line, rstr(p->r), p->x, p->i, estr(p->e)); + printf(" got %s\n", estr(e)); + err++; + } + if (yi != p->i) { + printf("%s:%d: %s ilogb(%a) want %lld got %d\n", + p->file, p->line, rstr(p->r), p->x, p->i, yi); + err++; + } + } + return !!err; +} diff --git a/src/math/ilogbf.c b/src/math/ilogbf.c new file mode 100644 index 0000000..2ca0068 --- /dev/null +++ b/src/math/ilogbf.c @@ -0,0 +1,41 @@ +#include +#include +#include "util.h" + +static struct f_i t[] = { +#include "sanity/ilogbf.h" + +}; + +int main(void) +{ + #pragma STDC FENV_ACCESS ON + int yi; + float d; + int e, i, err = 0; + struct f_i *p; + + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + fesetround(p->r); + feclearexcept(FE_ALL_EXCEPT); + yi = ilogbf(p->x); + e = fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW); + + if (!checkexcept(e, p->e, p->r)) { + printf("%s:%d: bad fp exception: %s ilogbf(%a)=%lld, want %s", + p->file, p->line, rstr(p->r), p->x, p->i, estr(p->e)); + printf(" got %s\n", estr(e)); + err++; + } + if (yi != p->i) { + printf("%s:%d: %s ilogbf(%a) want %lld got %d\n", + p->file, p->line, rstr(p->r), p->x, p->i, yi); + err++; + } + } + return !!err; +} diff --git a/src/math/ilogbl.c b/src/math/ilogbl.c new file mode 100644 index 0000000..aa1b3aa --- /dev/null +++ b/src/math/ilogbl.c @@ -0,0 +1,46 @@ +#include +#include +#include "util.h" + +static struct l_i t[] = { +#if LDBL_MANT_DIG == 53 +#include "sanity/ilogb.h" + +#elif LDBL_MANT_DIG == 64 +#include "sanity/ilogbl.h" + +#endif +}; + +int main(void) +{ + #pragma STDC FENV_ACCESS ON + int yi; + float d; + int e, i, err = 0; + struct l_i *p; + + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + fesetround(p->r); + feclearexcept(FE_ALL_EXCEPT); + yi = ilogbl(p->x); + e = fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW); + + if (!checkexcept(e, p->e, p->r)) { + printf("%s:%d: bad fp exception: %s ilogbl(%La)=%lld, want %s", + p->file, p->line, rstr(p->r), p->x, p->i, estr(p->e)); + printf(" got %s\n", estr(e)); + err++; + } + if (yi != p->i) { + printf("%s:%d: %s ilogbl(%La) want %lld got %d\n", + p->file, p->line, rstr(p->r), p->x, p->i, yi); + err++; + } + } + return !!err; +} diff --git a/src/math/lgammaf.c b/src/math/lgammaf.c index 47051e3..86d83db 100644 --- a/src/math/lgammaf.c +++ b/src/math/lgammaf.c @@ -34,7 +34,7 @@ int main(void) err++; } d = ulperrf(y, p->y, p->dy); - if (!checkulp(d, p->r)) { + if (!checkulp(d, p->r) || yi != p->i) { printf("%s:%d: %s lgammaf(%a) want %a,%lld got %a,%d ulperr %.3f = %a + %a\n", p->file, p->line, rstr(p->r), p->x, p->y, p->i, y, yi, d, d-p->dy, p->dy); err++; diff --git a/src/math/lgammaf_r.c b/src/math/lgammaf_r.c index 11ca8e3..8f69e0c 100644 --- a/src/math/lgammaf_r.c +++ b/src/math/lgammaf_r.c @@ -33,7 +33,7 @@ int main(void) err++; } d = ulperrf(y, p->y, p->dy); - if (!checkulp(d, p->r)) { + if (!checkulp(d, p->r) || yi != p->i) { printf("%s:%d: %s lgammaf_r(%a) want %a,%lld got %a,%d ulperr %.3f = %a + %a\n", p->file, p->line, rstr(p->r), p->x, p->y, p->i, y, yi, d, d-p->dy, p->dy); err++; diff --git a/src/math/sanity/ilogb.h b/src/math/sanity/ilogb.h new file mode 100644 index 0000000..7efaa58 --- /dev/null +++ b/src/math/sanity/ilogb.h @@ -0,0 +1,10 @@ +T(RN, -0x1.02239f3c6a8f1p+3, 3, 0) +T(RN, 0x1.161868e18bc67p+2, 2, 0) +T(RN, -0x1.0c34b3e01e6e7p+3, 3, 0) +T(RN, -0x1.a206f0a19dcc4p+2, 2, 0) +T(RN, 0x1.288bbb0d6a1e6p+3, 3, 0) +T(RN, 0x1.52efd0cd80497p-1, -1, 0) +T(RN, -0x1.a05cc754481d1p-2, -2, 0) +T(RN, 0x1.1f9ef934745cbp-1, -1, 0) +T(RN, 0x1.8c5db097f7442p-1, -1, 0) +T(RN, -0x1.5b86ea8118a0ep-1, -1, 0) diff --git a/src/math/sanity/ilogbf.h b/src/math/sanity/ilogbf.h new file mode 100644 index 0000000..df25899 --- /dev/null +++ b/src/math/sanity/ilogbf.h @@ -0,0 +1,10 @@ +T(RN, -0x1.0223ap+3, 3, 0) +T(RN, 0x1.161868p+2, 2, 0) +T(RN, -0x1.0c34b4p+3, 3, 0) +T(RN, -0x1.a206fp+2, 2, 0) +T(RN, 0x1.288bbcp+3, 3, 0) +T(RN, 0x1.52efdp-1, -1, 0) +T(RN, -0x1.a05cc8p-2, -2, 0) +T(RN, 0x1.1f9efap-1, -1, 0) +T(RN, 0x1.8c5dbp-1, -1, 0) +T(RN, -0x1.5b86eap-1, -1, 0) diff --git a/src/math/sanity/ilogbl.h b/src/math/sanity/ilogbl.h new file mode 100644 index 0000000..92f820e --- /dev/null +++ b/src/math/sanity/ilogbl.h @@ -0,0 +1,10 @@ +T(RN, -0x1.02239f3c6a8f13dep+3L, 3, 0) +T(RN, 0x1.161868e18bc67782p+2L, 2, 0) +T(RN, -0x1.0c34b3e01e6e682cp+3L, 3, 0) +T(RN, -0x1.a206f0a19dcc3948p+2L, 2, 0) +T(RN, 0x1.288bbb0d6a1e5bdap+3L, 3, 0) +T(RN, 0x1.52efd0cd80496a5ap-1L, -1, 0) +T(RN, -0x1.a05cc754481d0bdp-2L, -2, 0) +T(RN, 0x1.1f9ef934745cad6p-1L, -1, 0) +T(RN, 0x1.8c5db097f744257ep-1L, -1, 0) +T(RN, -0x1.5b86ea8118a0e2bcp-1L, -1, 0) diff --git a/src/math/sanity/j0l.h b/src/math/sanity/j0l.h deleted file mode 100644 index 2ab9cfa..0000000 --- a/src/math/sanity/j0l.h +++ /dev/null @@ -1,10 +0,0 @@ -T(RN, -0x1.02239f3c6a8f13dep+3L, 0x1.3ecac9327b83da68p-3L, -0x1.ca2bf8p-5, INEXACT) -T(RN, 0x1.161868e18bc67782p+2L, -0x1.69612a9105745e1p-2L, -0x1.cbcae6p-4, INEXACT) -T(RN, -0x1.0c34b3e01e6e682cp+3L, 0x1.2fd575f8ad8c5192p-4L, -0x1.c21578p-2, INEXACT) -T(RN, -0x1.a206f0a19dcc3948p+2L, 0x1.0f2e220b69812a82p-2L, -0x1.60a902p-3, INEXACT) -T(RN, 0x1.288bbb0d6a1e5bdap+3L, -0x1.3528d44599375b04p-3L, -0x1.4a0b2p-2, INEXACT) -T(RN, 0x1.52efd0cd80496a5ap-1L, 0x1.c96cc73e4a92d2dap-1L, -0x1.1a88cp-2, INEXACT) -T(RN, -0x1.a05cc754481d0bdp-2L, 0x1.eb0e4b64aa8d73b8p-1L, -0x1.0cd56p-2, INEXACT) -T(RN, 0x1.1f9ef934745cad6p-1L, 0x1.d865721eff3120b2p-1L, 0x1.ac5aa6p-2, INEXACT) -T(RN, 0x1.8c5db097f744257ep-1L, 0x1.b61d359fb77bcd54p-1L, -0x1.cb8a56p-2, INEXACT) -T(RN, -0x1.5b86ea8118a0e2bcp-1L, 0x1.c6b4501b05a3741ap-1L, 0x1.950002p-3, INEXACT) diff --git a/src/math/sanity/j1l.h b/src/math/sanity/j1l.h deleted file mode 100644 index 56692f4..0000000 --- a/src/math/sanity/j1l.h +++ /dev/null @@ -1,10 +0,0 @@ -T(RN, -0x1.02239f3c6a8f13dep+3L, -0x1.f2def55fbf5a9384p-3L, -0x1.07c388p-2, INEXACT) -T(RN, 0x1.161868e18bc67782p+2L, -0x1.7d48aacc4b124218p-3L, 0x1.5c39a2p-3, INEXACT) -T(RN, -0x1.0c34b3e01e6e682cp+3L, -0x1.14890a09c4ef434p-2L, 0x1.373684p-4, INEXACT) -T(RN, -0x1.a206f0a19dcc3948p+2L, 0x1.288dbd86fec97402p-3L, 0x1.d09fp-2, INEXACT) -T(RN, 0x1.288bbb0d6a1e5bdap+3L, 0x1.a6564e6ccad3f18cp-3L, 0x1.55bb0ep-3, INEXACT) -T(RN, 0x1.52efd0cd80496a5ap-1L, 0x1.40b4d5149fe157c4p-2L, -0x1.47bccap-3, INEXACT) -T(RN, -0x1.a05cc754481d0bdp-2L, -0x1.97d1273f3fd01b56p-3L, -0x1.58719ep-3, INEXACT) -T(RN, 0x1.1f9ef934745cad6p-1L, 0x1.146c6965ab4ce622p-2L, -0x1.5c5a7cp-4, INEXACT) -T(RN, 0x1.8c5db097f744257ep-1L, 0x1.6f67a8cdd55148dcp-2L, -0x1.5dd1e6p-2, INEXACT) -T(RN, -0x1.5b86ea8118a0e2bcp-1L, -0x1.47e4ba219f50ec6ap-2L, 0x1.2d38ep-2, INEXACT) diff --git a/src/math/sanity/y0l.h b/src/math/sanity/y0l.h deleted file mode 100644 index aa3a221..0000000 --- a/src/math/sanity/y0l.h +++ /dev/null @@ -1,10 +0,0 @@ -T(RN, -0x1.02239f3c6a8f13dep+3L, nan, 0x0p+0, INVALID) -T(RN, 0x1.161868e18bc67782p+2L, -0x1.293dc7b9b494bb34p-3L, 0x1.bcf78cp-2, INEXACT) -T(RN, -0x1.0c34b3e01e6e682cp+3L, nan, 0x0p+0, INVALID) -T(RN, -0x1.a206f0a19dcc3948p+2L, nan, 0x0p+0, INVALID) -T(RN, 0x1.288bbb0d6a1e5bdap+3L, 0x1.b65800c37acbd066p-3L, 0x1.44eb34p-2, INEXACT) -T(RN, 0x1.52efd0cd80496a5ap-1L, -0x1.de7c075a80e46016p-3L, -0x1.bee94p-2, INEXACT) -T(RN, -0x1.a05cc754481d0bdp-2L, nan, 0x0p+0, INVALID) -T(RN, 0x1.1f9ef934745cad6p-1L, -0x1.6ea9b7e5ba012c86p-2L, -0x1.f725e2p-2, INEXACT) -T(RN, 0x1.8c5db097f744257ep-1L, -0x1.ccadb2ae7e0f1ef2p-4L, 0x1.e9404cp-5, INEXACT) -T(RN, -0x1.5b86ea8118a0e2bcp-1L, nan, 0x0p+0, INVALID) diff --git a/src/math/sanity/y1l.h b/src/math/sanity/y1l.h deleted file mode 100644 index ea7da40..0000000 --- a/src/math/sanity/y1l.h +++ /dev/null @@ -1,10 +0,0 @@ -T(RN, -0x1.02239f3c6a8f13dep+3L, nan, 0x0p+0, INVALID) -T(RN, 0x1.161868e18bc67782p+2L, 0x1.5ab54680a596400ep-2L, -0x1.cddd8ap-3, INEXACT) -T(RN, -0x1.0c34b3e01e6e682cp+3L, nan, 0x0p+0, INVALID) -T(RN, -0x1.a206f0a19dcc3948p+2L, nan, 0x0p+0, INVALID) -T(RN, 0x1.288bbb0d6a1e5bdap+3L, 0x1.4d2f9a5b066b0c1ap-3L, -0x1.e2f31p-2, INEXACT) -T(RN, 0x1.52efd0cd80496a5ap-1L, -0x1.2887c4a1be0bb6aap+0L, -0x1.bba6bcp-2, INEXACT) -T(RN, -0x1.a05cc754481d0bdp-2L, nan, 0x0p+0, INVALID) -T(RN, 0x1.1f9ef934745cad6p-1L, -0x1.55417537f9faceaap+0L, 0x1.71da42p-2, INEXACT) -T(RN, 0x1.8c5db097f744257ep-1L, -0x1.02189c42315d140cp+0L, -0x1.9c5444p-3, INEXACT) -T(RN, -0x1.5b86ea8118a0e2bcp-1L, nan, 0x0p+0, INVALID) diff --git a/src/math/util.h b/src/math/util.h index b24046d..50b923a 100644 --- a/src/math/util.h +++ b/src/math/util.h @@ -78,6 +78,9 @@ struct l_li {POS int r; long double x; long double y; float dy; long long i; int struct di_d {POS int r; double x; long long i; double y; float dy; int e; }; struct fi_f {POS int r; float x; long long i; float y; float dy; int e; }; struct li_l {POS int r; long double x; long long i; long double y; float dy; int e; }; +struct d_i {POS int r; double x; long long i; int e; }; +struct f_i {POS int r; float x; long long i; int e; }; +struct l_i {POS int r; long double x; long long i; int e; }; #undef POS char *estr(int);