4 * Floating point read/write functions.
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * Reference: ISO C99 standard 5.2.4
23 #include <babeltrace/ctf/types.h>
25 #include <float.h> /* C99 floating point definitions */
26 #include <limits.h> /* C99 limits */
27 #include <babeltrace/endian.h>
31 * This library is limited to binary representation of floating point values.
32 * We use hardware support for conversion between 32 and 64-bit floating
37 * Aliasing float/double and unsigned long is not strictly permitted by strict
38 * aliasing, but in practice declaration prunning is well supported, and this permits
39 * us to use per-word read/writes rather than per-byte.
42 #if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
43 #define HAS_TYPE_PRUNING
48 #error "Unsupported floating point radix"
55 #ifdef HAS_TYPE_PRUNING
56 unsigned long bits
[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
58 unsigned char bits
[sizeof(double)];
63 * This mutex protects the static temporary float and double
64 * declarations (static_float_declaration and static_double_declaration).
66 static pthread_mutex_t float_mutex
= PTHREAD_MUTEX_INITIALIZER
;
68 static struct declaration_float
*static_float_declaration
,
69 *static_double_declaration
;
75 static void float_lock(void)
79 ret
= pthread_mutex_lock(&float_mutex
);
83 static void float_unlock(void)
87 ret
= pthread_mutex_unlock(&float_mutex
);
91 int _ctf_float_copy(struct stream_pos
*destp
,
92 struct definition_float
*dest_definition
,
93 struct stream_pos
*srcp
,
94 const struct definition_float
*src_definition
)
98 /* We only support copy of same-size floats for now */
99 assert(src_definition
->declaration
->sign
->len
==
100 dest_definition
->declaration
->sign
->len
);
101 assert(src_definition
->declaration
->exp
->len
==
102 dest_definition
->declaration
->exp
->len
);
103 assert(src_definition
->declaration
->mantissa
->len
==
104 dest_definition
->declaration
->mantissa
->len
);
106 if (src_definition
->declaration
->byte_order
== LITTLE_ENDIAN
) {
107 ret
= ctf_integer_read(srcp
, &src_definition
->mantissa
->p
);
110 ret
= ctf_integer_read(srcp
, &src_definition
->exp
->p
);
113 ret
= ctf_integer_read(srcp
, &src_definition
->sign
->p
);
117 ret
= ctf_integer_read(srcp
, &src_definition
->sign
->p
);
120 ret
= ctf_integer_read(srcp
, &src_definition
->exp
->p
);
123 ret
= ctf_integer_read(srcp
, &src_definition
->mantissa
->p
);
128 dest_definition
->mantissa
->value
._unsigned
=
129 src_definition
->mantissa
->value
._unsigned
;
130 dest_definition
->exp
->value
._signed
=
131 src_definition
->exp
->value
._signed
;
132 dest_definition
->sign
->value
._unsigned
=
133 src_definition
->sign
->value
._unsigned
;
136 if (dest_definition
->declaration
->byte_order
== LITTLE_ENDIAN
) {
137 ret
= ctf_integer_write(destp
, &dest_definition
->mantissa
->p
);
140 ret
= ctf_integer_write(destp
, &dest_definition
->exp
->p
);
143 ret
= ctf_integer_write(destp
, &dest_definition
->sign
->p
);
147 ret
= ctf_integer_write(destp
, &dest_definition
->sign
->p
);
150 ret
= ctf_integer_write(destp
, &dest_definition
->exp
->p
);
153 ret
= ctf_integer_write(destp
, &dest_definition
->mantissa
->p
);
160 int ctf_float_read(struct stream_pos
*ppos
, struct definition
*definition
)
162 struct definition_float
*float_definition
=
163 container_of(definition
, struct definition_float
, p
);
164 const struct declaration_float
*float_declaration
=
165 float_definition
->declaration
;
166 struct ctf_stream_pos
*pos
= ctf_pos(ppos
);
167 union doubleIEEE754 u
;
168 struct definition
*tmpdef
;
169 struct definition_float
*tmpfloat
;
170 struct ctf_stream_pos destp
;
171 struct mmap_align mma
;
175 switch (float_declaration
->mantissa
->len
+ 1) {
177 tmpdef
= static_float_declaration
->p
.definition_new(
178 &static_float_declaration
->p
,
179 NULL
, 0, 0, "__tmpfloat");
182 tmpdef
= static_double_declaration
->p
.definition_new(
183 &static_double_declaration
->p
,
184 NULL
, 0, 0, "__tmpfloat");
190 tmpfloat
= container_of(tmpdef
, struct definition_float
, p
);
191 memset(&destp
, 0, sizeof(destp
));
192 ctf_init_pos(&destp
, -1, O_RDWR
);
193 mmap_align_set_addr(&mma
, (char *) u
.bits
);
194 destp
.base_mma
= &mma
;
195 destp
.packet_size
= sizeof(u
) * CHAR_BIT
;
196 ctf_align_pos(pos
, float_declaration
->p
.alignment
);
197 ret
= _ctf_float_copy(&destp
.parent
, tmpfloat
, ppos
, float_definition
);
198 switch (float_declaration
->mantissa
->len
+ 1) {
200 float_definition
->value
= u
.vf
;
203 float_definition
->value
= u
.vd
;
211 definition_unref(tmpdef
);
217 int ctf_float_write(struct stream_pos
*ppos
, struct definition
*definition
)
219 struct definition_float
*float_definition
=
220 container_of(definition
, struct definition_float
, p
);
221 const struct declaration_float
*float_declaration
=
222 float_definition
->declaration
;
223 struct ctf_stream_pos
*pos
= ctf_pos(ppos
);
224 union doubleIEEE754 u
;
225 struct definition
*tmpdef
;
226 struct definition_float
*tmpfloat
;
227 struct ctf_stream_pos srcp
;
228 struct mmap_align mma
;
232 switch (float_declaration
->mantissa
->len
+ 1) {
234 tmpdef
= static_float_declaration
->p
.definition_new(
235 &static_float_declaration
->p
,
236 NULL
, 0, 0, "__tmpfloat");
239 tmpdef
= static_double_declaration
->p
.definition_new(
240 &static_double_declaration
->p
,
241 NULL
, 0, 0, "__tmpfloat");
247 tmpfloat
= container_of(tmpdef
, struct definition_float
, p
);
248 ctf_init_pos(&srcp
, -1, O_RDONLY
);
249 mmap_align_set_addr(&mma
, (char *) u
.bits
);
250 srcp
.base_mma
= &mma
;
251 srcp
.packet_size
= sizeof(u
) * CHAR_BIT
;
252 switch (float_declaration
->mantissa
->len
+ 1) {
254 u
.vf
= float_definition
->value
;
257 u
.vd
= float_definition
->value
;
263 ctf_align_pos(pos
, float_declaration
->p
.alignment
);
264 ret
= _ctf_float_copy(ppos
, float_definition
, &srcp
.parent
, tmpfloat
);
267 definition_unref(tmpdef
);
273 void __attribute__((constructor
)) ctf_float_init(void)
275 static_float_declaration
=
276 float_declaration_new(FLT_MANT_DIG
,
277 sizeof(float) * CHAR_BIT
- FLT_MANT_DIG
,
280 static_double_declaration
=
281 float_declaration_new(DBL_MANT_DIG
,
282 sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
284 __alignof__(double));
287 void __attribute__((destructor
)) ctf_float_fini(void)
289 declaration_unref(&static_float_declaration
->p
);
290 declaration_unref(&static_double_declaration
->p
);