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
;
148 struct mmap_align mma
;
151 switch (float_declaration
->mantissa
->len
+ 1) {
153 tmpdef
= static_float_declaration
->p
.definition_new(
154 &static_float_declaration
->p
,
155 NULL
, 0, 0, "__tmpfloat");
158 tmpdef
= static_double_declaration
->p
.definition_new(
159 &static_double_declaration
->p
,
160 NULL
, 0, 0, "__tmpfloat");
165 tmpfloat
= container_of(tmpdef
, struct definition_float
, p
);
166 memset(&destp
, 0, sizeof(destp
));
167 ctf_init_pos(&destp
, -1, O_RDWR
);
168 mmap_align_set_addr(&mma
, (char *) u
.bits
);
169 destp
.base_mma
= &mma
;
170 destp
.packet_size
= sizeof(u
) * CHAR_BIT
;
171 ctf_align_pos(pos
, float_declaration
->p
.alignment
);
172 ret
= _ctf_float_copy(&destp
.parent
, tmpfloat
, ppos
, float_definition
);
173 switch (float_declaration
->mantissa
->len
+ 1) {
175 float_definition
->value
= u
.vf
;
178 float_definition
->value
= u
.vd
;
183 definition_unref(tmpdef
);
187 int ctf_float_write(struct stream_pos
*ppos
, struct definition
*definition
)
189 struct definition_float
*float_definition
=
190 container_of(definition
, struct definition_float
, p
);
191 const struct declaration_float
*float_declaration
=
192 float_definition
->declaration
;
193 struct ctf_stream_pos
*pos
= ctf_pos(ppos
);
194 union doubleIEEE754 u
;
195 struct definition
*tmpdef
;
196 struct definition_float
*tmpfloat
;
197 struct ctf_stream_pos srcp
;
198 struct mmap_align mma
;
201 switch (float_declaration
->mantissa
->len
+ 1) {
203 tmpdef
= static_float_declaration
->p
.definition_new(
204 &static_float_declaration
->p
,
205 NULL
, 0, 0, "__tmpfloat");
208 tmpdef
= static_double_declaration
->p
.definition_new(
209 &static_double_declaration
->p
,
210 NULL
, 0, 0, "__tmpfloat");
215 tmpfloat
= container_of(tmpdef
, struct definition_float
, p
);
216 ctf_init_pos(&srcp
, -1, O_RDONLY
);
217 mmap_align_set_addr(&mma
, (char *) u
.bits
);
218 srcp
.base_mma
= &mma
;
219 srcp
.packet_size
= sizeof(u
) * CHAR_BIT
;
220 switch (float_declaration
->mantissa
->len
+ 1) {
222 u
.vf
= float_definition
->value
;
225 u
.vd
= float_definition
->value
;
230 ctf_align_pos(pos
, float_declaration
->p
.alignment
);
231 ret
= _ctf_float_copy(ppos
, float_definition
, &srcp
.parent
, tmpfloat
);
232 definition_unref(tmpdef
);
236 void __attribute__((constructor
)) ctf_float_init(void)
238 static_float_declaration
=
239 float_declaration_new(FLT_MANT_DIG
,
240 sizeof(float) * CHAR_BIT
- FLT_MANT_DIG
,
243 static_double_declaration
=
244 float_declaration_new(DBL_MANT_DIG
,
245 sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
247 __alignof__(double));
250 void __attribute__((destructor
)) ctf_float_fini(void)
252 declaration_unref(&static_float_declaration
->p
);
253 declaration_unref(&static_double_declaration
->p
);