X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/b1a20beee623c83315c3ce21abc7bcce103c6efb..c752173df370bd9eb5024697034f18a075358dd1:/struct/buf-float.c diff --git a/struct/buf-float.c b/struct/buf-float.c index 5b5b625..e163ff7 100644 --- a/struct/buf-float.c +++ b/struct/buf-float.c @@ -33,8 +33,21 @@ #include "bits.h" #include "buf.h" #include "fltfmt.h" +#include "macros.h" -/*----- External functions ------------------------------------------------*/ +/*----- Constants ---------------------------------------------------------*/ + +/* Tolerable errors. These aren't great, and all of them imply a failure to + * faithfully pass the value on, but they're also the inevitable consequence + * of having different floating-point systems. + */ +#define IGNERR (FLTERR_INEXACT | FLTERR_OFLOW | FLTERR_UFLOW) + +/*----- Main code ---------------------------------------------------------*/ + +#define FORMATS(_) \ + _(flt, float, f32, 4) \ + _(dbl, double, f64, 8) /* --- @buf_getf{32,64}{,l,b} --- * * @@ -49,67 +62,29 @@ * the usual round-to-nearest/ties-to-even rounding mode. */ -int buf_getf32(buf *b, float *x_out) -{ - const octet *p; - - p = buf_get(b, 4); if (!p) return (-1); - fltfmt_f32btoflt(x_out, p, FLTRND_NEAREVEN); return (0); -} - -int buf_getf32l(buf *b, float *x_out) -{ - const octet *p; - - p = buf_get(b, 4); if (!p) return (-1); - fltfmt_f32ltoflt(x_out, p, FLTRND_NEAREVEN); return (0); -} - -int buf_getf32b(buf *b, float *x_out) -{ - const octet *p; - - p = buf_get(b, 4); if (!p) return (-1); - fltfmt_f32ltoflt(x_out, p, FLTRND_NEAREVEN); return (0); -} - -int (dbuf_getf32)(dbuf *db, float *x_out) - { return (dbuf_getf32(db, x_out)); } -int (dbuf_getf32l)(dbuf *db, float *x_out) - { return (dbuf_getf32l(db, x_out)); } -int (dbuf_getf32b)(dbuf *db, float *x_out) - { return (dbuf_getf32b(db, x_out)); } - -int buf_getf64(buf *b, double *x_out) -{ - const octet *p; - - p = buf_get(b, 8); if (!p) return (-1); - fltfmt_f64btodbl(x_out, p, FLTRND_NEAREVEN); return (0); -} - -int buf_getf64l(buf *b, double *x_out) -{ - const octet *p; - - p = buf_get(b, 8); if (!p) return (-1); - fltfmt_f64ltodbl(x_out, p, FLTRND_NEAREVEN); return (0); -} - -int buf_getf64b(buf *b, double *x_out) -{ - const octet *p; - - p = buf_get(b, 8); if (!p) return (-1); - fltfmt_f64ltodbl(x_out, p, FLTRND_NEAREVEN); return (0); -} - -int (dbuf_getf64)(dbuf *db, double *x_out) - { return (dbuf_getf64(db, x_out)); } -int (dbuf_getf64l)(dbuf *db, double *x_out) - { return (dbuf_getf64l(db, x_out)); } -int (dbuf_getf64b)(dbuf *db, double *x_out) - { return (dbuf_getf64b(db, x_out)); } +#define DEFGET1(ty, cty, fty, e, xe, w) \ + int GLUE3(buf_get, fty, xe)(buf *b, cty *x_out) \ + { \ + const octet *p; \ + unsigned err; \ + \ + p = buf_get(b, w); if (!p) return (-1); \ + err = fltfmt_##fty##e##to##ty(x_out, p, FLTRND_NEAREVEN); \ + if (err&~IGNERR) { BBREAK(b); return (-1); } \ + return (0); \ + } \ + int (GLUE3(dbuf_get, fty, xe))(dbuf *db, cty *x_out) \ + { return (GLUE3(dbuf_get, fty, xe)(db, x_out)); } + +#define DEFGET(ty, cty, fty, w) \ + DEFGET1(ty, cty, fty, b, EMPTY, w) \ + DEFGET1(ty, cty, fty, l, l, w) \ + DEFGET1(ty, cty, fty, b, b, w) + +FORMATS(DEFGET) + +#undef DEFGET1 +#undef DEFGET /* --- @buf_putf{32,64}{,l,b} --- * * @@ -124,66 +99,28 @@ int (dbuf_getf64b)(dbuf *db, double *x_out) * the usual round-to-nearest/ties-to-even rounding mode. */ -int buf_putf32(buf *b, float x) -{ - octet *p; - - p = buf_get(b, 4); if (!p) return (-1); - fltfmt_flttof32b(p, x, FLTRND_NEAREVEN); return (0); -} - -int buf_putf32l(buf *b, float x) -{ - octet *p; - - p = buf_get(b, 4); if (!p) return (-1); - fltfmt_flttof32l(p, x, FLTRND_NEAREVEN); return (0); -} - -int buf_putf32b(buf *b, float x) -{ - octet *p; - - p = buf_get(b, 4); if (!p) return (-1); - fltfmt_flttof32b(p, x, FLTRND_NEAREVEN); return (0); -} - -int (dbuf_putf32)(dbuf *db, float x) - { return (dbuf_putf32(db, x)); } -int (dbuf_putf32l)(dbuf *db, float x) - { return (dbuf_putf32l(db, x)); } -int (dbuf_putf32b)(dbuf *db, float x) - { return (dbuf_putf32b(db, x)); } - -int buf_putf64(buf *b, double x) -{ - octet *p; - - p = buf_get(b, 8); if (!p) return (-1); - fltfmt_dbltof64b(p, x, FLTRND_NEAREVEN); return (0); -} - -int buf_putf64l(buf *b, double x) -{ - octet *p; - - p = buf_get(b, 8); if (!p) return (-1); - fltfmt_dbltof64l(p, x, FLTRND_NEAREVEN); return (0); -} - -int buf_putf64b(buf *b, double x) -{ - octet *p; - - p = buf_get(b, 8); if (!p) return (-1); - fltfmt_dbltof64b(p, x, FLTRND_NEAREVEN); return (0); -} - -int (dbuf_putf64)(dbuf *db, double x) - { return (dbuf_putf64(db, x)); } -int (dbuf_putf64l)(dbuf *db, double x) - { return (dbuf_putf64l(db, x)); } -int (dbuf_putf64b)(dbuf *db, double x) - { return (dbuf_putf64b(db, x)); } +#define DEFPUT1(ty, cty, fty, e, xe, w) \ + int GLUE3(buf_put, fty, xe)(buf *b, cty x) \ + { \ + octet *p; \ + unsigned err; \ + \ + p = buf_get(b, w); if (!p) return (-1); \ + err = fltfmt_##ty##to##fty##e(p, x, FLTRND_NEAREVEN); \ + if (err&~IGNERR) { BBREAK(b); return (-1); } \ + return (0); \ + } \ + int (GLUE3(dbuf_put, fty, xe))(dbuf *db, cty x) \ + { return (GLUE3(dbuf_put, fty, xe)(db, x)); } + +#define DEFPUT(ty, cty, fty, w) \ + DEFPUT1(ty, cty, fty, b, EMPTY, w) \ + DEFPUT1(ty, cty, fty, l, l, w) \ + DEFPUT1(ty, cty, fty, b, b, w) + +FORMATS(DEFPUT) + +#undef DEFPUT1 +#undef DEFPUT /*----- That's all, folks -------------------------------------------------*/