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>
30 * This library is limited to binary representation of floating point values.
31 * We use hardware support for conversion between 32 and 64-bit floating
36 * Aliasing float/double and unsigned long is not strictly permitted by strict
37 * aliasing, but in practice declaration prunning is well supported, and this permits
38 * us to use per-word read/writes rather than per-byte.
41 #if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
42 #define HAS_TYPE_PRUNING
47 #error "Unsupported floating point radix"
54 #ifdef HAS_TYPE_PRUNING
55 unsigned long bits
[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
57 unsigned char bits
[sizeof(double)];
61 static struct declaration_float
*static_float_declaration
,
62 *static_double_declaration
;
65 size_t sign_start
, exp_start
, mantissa_start
, len
;
68 int _ctf_float_copy(struct stream_pos
*destp
,
69 struct definition_float
*dest_definition
,
70 struct stream_pos
*srcp
,
71 const struct definition_float
*src_definition
)
75 /* We only support copy of same-size floats for now */
76 assert(src_definition
->declaration
->sign
->len
==
77 dest_definition
->declaration
->sign
->len
);
78 assert(src_definition
->declaration
->exp
->len
==
79 dest_definition
->declaration
->exp
->len
);
80 assert(src_definition
->declaration
->mantissa
->len
==
81 dest_definition
->declaration
->mantissa
->len
);
83 if (src_definition
->declaration
->byte_order
== LITTLE_ENDIAN
) {
84 ret
= ctf_integer_read(srcp
, &src_definition
->mantissa
->p
);
87 ret
= ctf_integer_read(srcp
, &src_definition
->exp
->p
);
90 ret
= ctf_integer_read(srcp
, &src_definition
->sign
->p
);
94 ret
= ctf_integer_read(srcp
, &src_definition
->sign
->p
);
97 ret
= ctf_integer_read(srcp
, &src_definition
->exp
->p
);
100 ret
= ctf_integer_read(srcp
, &src_definition
->mantissa
->p
);
105 dest_definition
->mantissa
->value
._unsigned
=
106 src_definition
->mantissa
->value
._unsigned
;
107 dest_definition
->exp
->value
._signed
=
108 src_definition
->exp
->value
._signed
;
109 dest_definition
->sign
->value
._unsigned
=
110 src_definition
->sign
->value
._unsigned
;
113 if (dest_definition
->declaration
->byte_order
== LITTLE_ENDIAN
) {
114 ret
= ctf_integer_write(destp
, &dest_definition
->mantissa
->p
);
117 ret
= ctf_integer_write(destp
, &dest_definition
->exp
->p
);
120 ret
= ctf_integer_write(destp
, &dest_definition
->sign
->p
);
124 ret
= ctf_integer_write(destp
, &dest_definition
->sign
->p
);
127 ret
= ctf_integer_write(destp
, &dest_definition
->exp
->p
);
130 ret
= ctf_integer_write(destp
, &dest_definition
->mantissa
->p
);
137 int ctf_float_read(struct stream_pos
*ppos
, struct definition
*definition
)
139 struct definition_float
*float_definition
=
140 container_of(definition
, struct definition_float
, p
);
141 const struct declaration_float
*float_declaration
=
142 float_definition
->declaration
;
143 struct ctf_stream_pos
*pos
= ctf_pos(ppos
);
144 union doubleIEEE754 u
;
145 struct definition
*tmpdef
;
146 struct definition_float
*tmpfloat
;
147 struct ctf_stream_pos destp
;
150 switch (float_declaration
->mantissa
->len
+ 1) {
152 tmpdef
= static_float_declaration
->p
.definition_new(
153 &static_float_declaration
->p
,
154 NULL
, 0, 0, "__tmpfloat");
157 tmpdef
= static_double_declaration
->p
.definition_new(
158 &static_double_declaration
->p
,
159 NULL
, 0, 0, "__tmpfloat");
164 tmpfloat
= container_of(tmpdef
, struct definition_float
, p
);
165 ctf_init_pos(&destp
, -1, O_RDWR
);
166 destp
.base
= (char *) u
.bits
;
167 destp
.packet_size
= sizeof(u
) * CHAR_BIT
;
168 ctf_align_pos(pos
, float_declaration
->p
.alignment
);
169 ret
= _ctf_float_copy(&destp
.parent
, tmpfloat
, ppos
, float_definition
);
170 switch (float_declaration
->mantissa
->len
+ 1) {
172 float_definition
->value
= u
.vf
;
175 float_definition
->value
= u
.vd
;
180 definition_unref(tmpdef
);
184 int ctf_float_write(struct stream_pos
*ppos
, struct definition
*definition
)
186 struct definition_float
*float_definition
=
187 container_of(definition
, struct definition_float
, p
);
188 const struct declaration_float
*float_declaration
=
189 float_definition
->declaration
;
190 struct ctf_stream_pos
*pos
= ctf_pos(ppos
);
191 union doubleIEEE754 u
;
192 struct definition
*tmpdef
;
193 struct definition_float
*tmpfloat
;
194 struct ctf_stream_pos srcp
;
197 switch (float_declaration
->mantissa
->len
+ 1) {
199 tmpdef
= static_float_declaration
->p
.definition_new(
200 &static_float_declaration
->p
,
201 NULL
, 0, 0, "__tmpfloat");
204 tmpdef
= static_double_declaration
->p
.definition_new(
205 &static_double_declaration
->p
,
206 NULL
, 0, 0, "__tmpfloat");
211 tmpfloat
= container_of(tmpdef
, struct definition_float
, p
);
212 ctf_init_pos(&srcp
, -1, O_RDONLY
);
213 srcp
.base
= (char *) u
.bits
;
214 srcp
.packet_size
= sizeof(u
) * CHAR_BIT
;
215 switch (float_declaration
->mantissa
->len
+ 1) {
217 u
.vf
= float_definition
->value
;
220 u
.vd
= float_definition
->value
;
225 ctf_align_pos(pos
, float_declaration
->p
.alignment
);
226 ret
= _ctf_float_copy(ppos
, float_definition
, &srcp
.parent
, tmpfloat
);
227 definition_unref(tmpdef
);
231 void __attribute__((constructor
)) ctf_float_init(void)
233 static_float_declaration
=
234 float_declaration_new(FLT_MANT_DIG
,
235 sizeof(float) * CHAR_BIT
- FLT_MANT_DIG
,
238 static_double_declaration
=
239 float_declaration_new(DBL_MANT_DIG
,
240 sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
242 __alignof__(double));
245 void __attribute__((destructor
)) ctf_float_fini(void)
247 declaration_unref(&static_float_declaration
->p
);
248 declaration_unref(&static_double_declaration
->p
);