Add support for floating point fields in the Python bindings
[babeltrace.git] / formats / ctf / types / float.c
CommitLineData
6dc2ca62
MD
1/*
2 * Common Trace Format
3 *
4 * Floating point read/write functions.
5 *
64fa3fec
MD
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6dc2ca62 9 *
ccd7e1c8
MD
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
de0ba614 16 *
ccd7e1c8
MD
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
6dc2ca62 19 *
c462e188
MD
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 *
de0ba614 28 * Reference: ISO C99 standard 5.2.4
6dc2ca62
MD
29 */
30
d79865b9 31#include <babeltrace/ctf/types.h>
6dc2ca62 32#include <glib.h>
de0ba614 33#include <float.h> /* C99 floating point definitions */
a3dbc794 34#include <limits.h> /* C99 limits */
9b0422a0 35#include <babeltrace/endian.h>
f530d9ce 36#include <pthread.h>
6dc2ca62 37
de0ba614
MD
38/*
39 * This library is limited to binary representation of floating point values.
f72803ca
MD
40 * We use hardware support for conversion between 32 and 64-bit floating
41 * point values.
de0ba614
MD
42 */
43
6dc2ca62
MD
44/*
45 * Aliasing float/double and unsigned long is not strictly permitted by strict
f6625916 46 * aliasing, but in practice declaration prunning is well supported, and this permits
6dc2ca62
MD
47 * us to use per-word read/writes rather than per-byte.
48 */
49
50#if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
51#define HAS_TYPE_PRUNING
52#endif
53
de0ba614
MD
54#if (FLT_RADIX != 2)
55
56#error "Unsupported floating point radix"
57
6dc2ca62 58#endif
6dc2ca62
MD
59
60union doubleIEEE754 {
f72803ca
MD
61 double vd;
62 float vf;
6dc2ca62
MD
63#ifdef HAS_TYPE_PRUNING
64 unsigned long bits[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
65#else
66 unsigned char bits[sizeof(double)];
67#endif
68};
69
f530d9ce
JD
70/*
71 * This mutex protects the static temporary float and double
72 * declarations (static_float_declaration and static_double_declaration).
73 */
74static pthread_mutex_t float_mutex = PTHREAD_MUTEX_INITIALIZER;
75
f72803ca
MD
76static struct declaration_float *static_float_declaration,
77 *static_double_declaration;
d11e9c49 78
de0ba614 79struct pos_len {
08c82b90 80 size_t len;
de0ba614
MD
81};
82
f530d9ce
JD
83static void float_lock(void)
84{
85 int ret;
86
87 ret = pthread_mutex_lock(&float_mutex);
88 assert(!ret);
89}
90
91static void float_unlock(void)
92{
93 int ret;
94
95 ret = pthread_mutex_unlock(&float_mutex);
96 assert(!ret);
97}
98
1cf393f6 99static int _ctf_float_copy(struct bt_stream_pos *destp,
c5e74408 100 struct definition_float *dest_definition,
1cf393f6 101 struct bt_stream_pos *srcp,
c5e74408 102 const struct definition_float *src_definition)
6dc2ca62 103{
c5e74408
MD
104 int ret;
105
f72803ca
MD
106 /* We only support copy of same-size floats for now */
107 assert(src_definition->declaration->sign->len ==
108 dest_definition->declaration->sign->len);
109 assert(src_definition->declaration->exp->len ==
110 dest_definition->declaration->exp->len);
111 assert(src_definition->declaration->mantissa->len ==
112 dest_definition->declaration->mantissa->len);
11d43b90 113 /* Read */
d11e9c49 114 if (src_definition->declaration->byte_order == LITTLE_ENDIAN) {
c5e74408
MD
115 ret = ctf_integer_read(srcp, &src_definition->mantissa->p);
116 if (ret)
117 return ret;
118 ret = ctf_integer_read(srcp, &src_definition->exp->p);
119 if (ret)
120 return ret;
121 ret = ctf_integer_read(srcp, &src_definition->sign->p);
122 if (ret)
123 return ret;
de0ba614 124 } else {
c5e74408
MD
125 ret = ctf_integer_read(srcp, &src_definition->sign->p);
126 if (ret)
127 return ret;
128 ret = ctf_integer_read(srcp, &src_definition->exp->p);
129 if (ret)
130 return ret;
131 ret = ctf_integer_read(srcp, &src_definition->mantissa->p);
132 if (ret)
133 return ret;
6dc2ca62 134 }
d11e9c49
MD
135
136 dest_definition->mantissa->value._unsigned =
137 src_definition->mantissa->value._unsigned;
138 dest_definition->exp->value._signed =
139 src_definition->exp->value._signed;
140 dest_definition->sign->value._unsigned =
141 src_definition->sign->value._unsigned;
142
11d43b90 143 /* Write */
d11e9c49 144 if (dest_definition->declaration->byte_order == LITTLE_ENDIAN) {
c5e74408
MD
145 ret = ctf_integer_write(destp, &dest_definition->mantissa->p);
146 if (ret)
147 return ret;
148 ret = ctf_integer_write(destp, &dest_definition->exp->p);
149 if (ret)
150 return ret;
151 ret = ctf_integer_write(destp, &dest_definition->sign->p);
152 if (ret)
153 return ret;
de0ba614 154 } else {
c5e74408
MD
155 ret = ctf_integer_write(destp, &dest_definition->sign->p);
156 if (ret)
157 return ret;
158 ret = ctf_integer_write(destp, &dest_definition->exp->p);
159 if (ret)
160 return ret;
161 ret = ctf_integer_write(destp, &dest_definition->mantissa->p);
162 if (ret)
163 return ret;
6dc2ca62 164 }
c5e74408 165 return 0;
11d43b90 166}
de0ba614 167
0d69b916 168int ctf_float_read(struct bt_stream_pos *ppos, struct bt_definition *definition)
6dc2ca62 169{
d11e9c49
MD
170 struct definition_float *float_definition =
171 container_of(definition, struct definition_float, p);
172 const struct declaration_float *float_declaration =
173 float_definition->declaration;
174 struct ctf_stream_pos *pos = ctf_pos(ppos);
f72803ca 175 union doubleIEEE754 u;
0d69b916 176 struct bt_definition *tmpdef;
f72803ca 177 struct definition_float *tmpfloat;
46322b33 178 struct ctf_stream_pos destp;
aee35fcc 179 struct mmap_align mma;
c5e74408 180 int ret;
11d43b90 181
f530d9ce 182 float_lock();
f72803ca
MD
183 switch (float_declaration->mantissa->len + 1) {
184 case FLT_MANT_DIG:
185 tmpdef = static_float_declaration->p.definition_new(
186 &static_float_declaration->p,
187 NULL, 0, 0, "__tmpfloat");
188 break;
189 case DBL_MANT_DIG:
190 tmpdef = static_double_declaration->p.definition_new(
191 &static_double_declaration->p,
192 NULL, 0, 0, "__tmpfloat");
193 break;
194 default:
f530d9ce
JD
195 ret = -EINVAL;
196 goto end;
f72803ca
MD
197 }
198 tmpfloat = container_of(tmpdef, struct definition_float, p);
86b06ede 199 memset(&destp, 0, sizeof(destp));
ca334c72 200 ctf_init_pos(&destp, NULL, -1, O_RDWR);
aee35fcc
MD
201 mmap_align_set_addr(&mma, (char *) u.bits);
202 destp.base_mma = &mma;
f72803ca 203 destp.packet_size = sizeof(u) * CHAR_BIT;
d11e9c49 204 ctf_align_pos(pos, float_declaration->p.alignment);
c5e74408 205 ret = _ctf_float_copy(&destp.parent, tmpfloat, ppos, float_definition);
f72803ca
MD
206 switch (float_declaration->mantissa->len + 1) {
207 case FLT_MANT_DIG:
208 float_definition->value = u.vf;
209 break;
210 case DBL_MANT_DIG:
211 float_definition->value = u.vd;
212 break;
213 default:
f530d9ce
JD
214 ret = -EINVAL;
215 goto end_unref;
f72803ca 216 }
f530d9ce
JD
217
218end_unref:
13fad8b6 219 bt_definition_unref(tmpdef);
f530d9ce
JD
220end:
221 float_unlock();
c5e74408 222 return ret;
de0ba614
MD
223}
224
0d69b916 225int ctf_float_write(struct bt_stream_pos *ppos, struct bt_definition *definition)
de0ba614 226{
d11e9c49
MD
227 struct definition_float *float_definition =
228 container_of(definition, struct definition_float, p);
229 const struct declaration_float *float_declaration =
230 float_definition->declaration;
231 struct ctf_stream_pos *pos = ctf_pos(ppos);
f72803ca 232 union doubleIEEE754 u;
0d69b916 233 struct bt_definition *tmpdef;
f72803ca 234 struct definition_float *tmpfloat;
27611b66 235 struct ctf_stream_pos srcp = { { 0 } };
aee35fcc 236 struct mmap_align mma;
c5e74408 237 int ret;
11d43b90 238
f530d9ce 239 float_lock();
f72803ca
MD
240 switch (float_declaration->mantissa->len + 1) {
241 case FLT_MANT_DIG:
242 tmpdef = static_float_declaration->p.definition_new(
243 &static_float_declaration->p,
244 NULL, 0, 0, "__tmpfloat");
245 break;
246 case DBL_MANT_DIG:
247 tmpdef = static_double_declaration->p.definition_new(
248 &static_double_declaration->p,
249 NULL, 0, 0, "__tmpfloat");
250 break;
251 default:
f530d9ce
JD
252 ret = -EINVAL;
253 goto end;
f72803ca
MD
254 }
255 tmpfloat = container_of(tmpdef, struct definition_float, p);
ca334c72 256 ctf_init_pos(&srcp, NULL, -1, O_RDONLY);
aee35fcc
MD
257 mmap_align_set_addr(&mma, (char *) u.bits);
258 srcp.base_mma = &mma;
f72803ca
MD
259 srcp.packet_size = sizeof(u) * CHAR_BIT;
260 switch (float_declaration->mantissa->len + 1) {
261 case FLT_MANT_DIG:
262 u.vf = float_definition->value;
263 break;
264 case DBL_MANT_DIG:
265 u.vd = float_definition->value;
266 break;
267 default:
f530d9ce
JD
268 ret = -EINVAL;
269 goto end_unref;
f72803ca 270 }
d11e9c49 271 ctf_align_pos(pos, float_declaration->p.alignment);
c5e74408 272 ret = _ctf_float_copy(ppos, float_definition, &srcp.parent, tmpfloat);
f530d9ce
JD
273
274end_unref:
13fad8b6 275 bt_definition_unref(tmpdef);
f530d9ce
JD
276end:
277 float_unlock();
c5e74408 278 return ret;
de0ba614 279}
6dc2ca62 280
e5a73b90
JG
281double bt_get_float(const struct bt_definition *field)
282{
283 struct definition_float *definition =
284 container_of(field, struct definition_float, p);
285
286 return definition->value;
287}
288
2e937fb4 289static
d11e9c49 290void __attribute__((constructor)) ctf_float_init(void)
de0ba614 291{
f72803ca 292 static_float_declaration =
becd02a1 293 bt_float_declaration_new(FLT_MANT_DIG,
f72803ca
MD
294 sizeof(float) * CHAR_BIT - FLT_MANT_DIG,
295 BYTE_ORDER,
296 __alignof__(float));
297 static_double_declaration =
becd02a1 298 bt_float_declaration_new(DBL_MANT_DIG,
f72803ca 299 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
11d43b90 300 BYTE_ORDER,
f72803ca 301 __alignof__(double));
de0ba614
MD
302}
303
2e937fb4 304static
d11e9c49 305void __attribute__((destructor)) ctf_float_fini(void)
de0ba614 306{
e6b4b4f4
JD
307 bt_declaration_unref(&static_float_declaration->p);
308 bt_declaration_unref(&static_double_declaration->p);
6dc2ca62 309}
This page took 0.044307 seconds and 4 git commands to generate.