3 * Encoding and decoding floating-point values
5 * (c) 2023 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the mLib utilities library.
12 * mLib is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU Library General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
17 * mLib is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
20 * License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with mLib. If not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 /*----- Header files ------------------------------------------------------*/
38 /*----- Constants ---------------------------------------------------------*/
40 /* Tolerable errors. These aren't great, and all of them imply a failure to
41 * faithfully pass the value on, but they're also the inevitable consequence
42 * of having different floating-point systems.
44 #define IGNERR (FLTERR_INEXACT | FLTERR_OFLOW | FLTERR_UFLOW)
46 /*----- Main code ---------------------------------------------------------*/
49 _(flt, float, f32, 4) \
50 _(dbl, double, f64, 8)
52 /* --- @buf_getf{32,64}{,l,b} --- *
54 * Arguments: @buf *b@ = a buffer to read from
55 * @float *x_out@, @double *x_out@ = where to put the result
57 * Returns: Zero on success, %$-1$% on failure (and the buffer is
60 * Use: Get an IEEE Binary32 or Binary64 value from the buffer.
61 * Conversion is performed using the `fltfmt' machinery, with
62 * the usual round-to-nearest/ties-to-even rounding mode.
65 #define DEFGET1(ty, cty, fty, e, xe, w) \
66 int GLUE3(buf_get, fty, xe)(buf *b, cty *x_out) \
71 p = buf_get(b, w); if (!p) return (-1); \
72 err = fltfmt_##fty##e##to##ty(x_out, p, FLTRND_NEAREVEN); \
73 if (err&~IGNERR) { BBREAK(b); return (-1); } \
76 int (GLUE3(dbuf_get, fty, xe))(dbuf *db, cty *x_out) \
77 { return (GLUE3(dbuf_get, fty, xe)(db, x_out)); }
79 #define DEFGET(ty, cty, fty, w) \
80 DEFGET1(ty, cty, fty, b, EMPTY, w) \
81 DEFGET1(ty, cty, fty, l, l, w) \
82 DEFGET1(ty, cty, fty, b, b, w)
89 /* --- @buf_putf{32,64}{,l,b} --- *
91 * Arguments: @buf *b@ = a buffer to write to
92 * @double x@ = a number to write
94 * Returns: Zero on success, %$-1$% on failure (and the buffer is
97 * Use: Get an IEEE Binary32 or Binary64 value from the buffer.
98 * Conversion is performed using the `fltfmt' machinery, with
99 * the usual round-to-nearest/ties-to-even rounding mode.
102 #define DEFPUT1(ty, cty, fty, e, xe, w) \
103 int GLUE3(buf_put, fty, xe)(buf *b, cty x) \
108 p = buf_get(b, w); if (!p) return (-1); \
109 err = fltfmt_##ty##to##fty##e(p, x, FLTRND_NEAREVEN); \
110 if (err&~IGNERR) { BBREAK(b); return (-1); } \
113 int (GLUE3(dbuf_put, fty, xe))(dbuf *db, cty x) \
114 { return (GLUE3(dbuf_put, fty, xe)(db, x)); }
116 #define DEFPUT(ty, cty, fty, w) \
117 DEFPUT1(ty, cty, fty, b, EMPTY, w) \
118 DEFPUT1(ty, cty, fty, l, l, w) \
119 DEFPUT1(ty, cty, fty, b, b, w)
126 /*----- That's all, folks -------------------------------------------------*/