Commit | Line | Data |
---|---|---|
e63124bc MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Encoding and decoding floating-point values | |
4 | * | |
5 | * (c) 2023 Straylight/Edgeware | |
6 | */ | |
7 | ||
8 | /*----- Licensing notice --------------------------------------------------* | |
9 | * | |
10 | * This file is part of the mLib utilities library. | |
11 | * | |
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. | |
16 | * | |
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. | |
21 | * | |
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, | |
25 | * USA. | |
26 | */ | |
27 | ||
28 | /*----- Header files ------------------------------------------------------*/ | |
29 | ||
30 | #include <float.h> | |
31 | #include <math.h> | |
32 | ||
33 | #include "bits.h" | |
34 | #include "buf.h" | |
b1a20bee | 35 | #include "fltfmt.h" |
289651a7 | 36 | #include "macros.h" |
e63124bc | 37 | |
289651a7 MW |
38 | /*----- Constants ---------------------------------------------------------*/ |
39 | ||
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. | |
43 | */ | |
44 | #define IGNERR (FLTERR_INEXACT | FLTERR_OFLOW | FLTERR_UFLOW) | |
45 | ||
46 | /*----- Main code ---------------------------------------------------------*/ | |
47 | ||
48 | #define FORMATS(_) \ | |
49 | _(flt, float, f32, 4) \ | |
50 | _(dbl, double, f64, 8) | |
e63124bc | 51 | |
b1a20bee | 52 | /* --- @buf_getf{32,64}{,l,b} --- * |
31d0247c | 53 | * |
b1a20bee MW |
54 | * Arguments: @buf *b@ = a buffer to read from |
55 | * @float *x_out@, @double *x_out@ = where to put the result | |
31d0247c | 56 | * |
b1a20bee MW |
57 | * Returns: Zero on success, %$-1$% on failure (and the buffer is |
58 | * broken). | |
31d0247c | 59 | * |
b1a20bee MW |
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. | |
31d0247c MW |
63 | */ |
64 | ||
289651a7 MW |
65 | #define DEFGET1(ty, cty, fty, e, xe, w) \ |
66 | int GLUE3(buf_get, fty, xe)(buf *b, cty *x_out) \ | |
67 | { \ | |
68 | const octet *p; \ | |
69 | unsigned err; \ | |
70 | \ | |
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); } \ | |
74 | return (0); \ | |
75 | } \ | |
76 | int (GLUE3(dbuf_get, fty, xe))(dbuf *db, cty *x_out) \ | |
77 | { return (GLUE3(dbuf_get, fty, xe)(db, x_out)); } | |
78 | ||
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) | |
83 | ||
84 | FORMATS(DEFGET) | |
85 | ||
86 | #undef DEFGET1 | |
87 | #undef DEFGET | |
31d0247c | 88 | |
b1a20bee | 89 | /* --- @buf_putf{32,64}{,l,b} --- * |
31d0247c MW |
90 | * |
91 | * Arguments: @buf *b@ = a buffer to write to | |
92 | * @double x@ = a number to write | |
93 | * | |
b1a20bee MW |
94 | * Returns: Zero on success, %$-1$% on failure (and the buffer is |
95 | * broken). | |
31d0247c | 96 | * |
b1a20bee MW |
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. | |
31d0247c MW |
100 | */ |
101 | ||
289651a7 MW |
102 | #define DEFPUT1(ty, cty, fty, e, xe, w) \ |
103 | int GLUE3(buf_put, fty, xe)(buf *b, cty x) \ | |
104 | { \ | |
105 | octet *p; \ | |
106 | unsigned err; \ | |
107 | \ | |
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); } \ | |
111 | return (0); \ | |
112 | } \ | |
113 | int (GLUE3(dbuf_put, fty, xe))(dbuf *db, cty x) \ | |
114 | { return (GLUE3(dbuf_put, fty, xe)(db, x)); } | |
115 | ||
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) | |
120 | ||
121 | FORMATS(DEFPUT) | |
122 | ||
123 | #undef DEFPUT1 | |
124 | #undef DEFPUT | |
31d0247c | 125 | |
e63124bc | 126 | /*----- That's all, folks -------------------------------------------------*/ |