4 * Floating point read/write functions.
6 * Copyright (c) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Reference: ISO C99 standard 5.2.4
25 #include <babeltrace/ctf/types.h>
27 #include <float.h> /* C99 floating point definitions */
28 #include <limits.h> /* C99 limits */
32 * This library is limited to binary representation of floating point values.
33 * Sign-extension of the exponents is assumed to keep the NaN, +inf, -inf
34 * values, but this should be double-checked (TODO).
38 * Aliasing float/double and unsigned long is not strictly permitted by strict
39 * aliasing, but in practice type prunning is well supported, and this permits
40 * us to use per-word read/writes rather than per-byte.
43 #if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
44 #define HAS_TYPE_PRUNING
49 #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)];
62 union ldoubleIEEE754
{
64 #ifdef HAS_TYPE_PRUNING
65 unsigned long bits
[(sizeof(long double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
67 unsigned char bits
[sizeof(long double)];
72 size_t sign_start
, exp_start
, mantissa_start
, len
;
77 void ctf_float_copy(unsigned char *destp
, const struct type_class_float
*dest
,
78 const unsigned char *src
, const struct type_class_float
*src
)
80 struct pos_len destpos
, srcpos
;
86 destpos
.len
= dest
->exp_len
+ dest
->mantissa_len
;
87 if (dest
->byte_order
== LITTLE_ENDIAN
) {
88 destpos
.sign_start
= destpos
.len
- 1;
89 destpos
.exp_start
= destpos
.sign_start
- dest
->exp_len
;
90 destpos
.mantissa_start
= 0;
92 destpos
.sign_start
= 0;
93 destpos
.exp_start
= 1;
94 destpos
.mantissa_start
= destpos
.exp_start
+ dest
->exp_len
;
97 srcpos
.len
= src
->exp_len
+ src
->mantissa_len
;
98 if (src
->byte_order
== LITTLE_ENDIAN
) {
99 srcpos
.sign_start
= srcpos
.len
- 1;
100 srcpos
.exp_start
= srcpos
.sign_start
- src
->exp_len
;
101 srcpos
.mantissa_start
= 0;
103 srcpos
.sign_start
= 0;
104 srcpos
.exp_start
= 1;
105 srcpos
.mantissa_start
= srcpos
.exp_start
+ src
->exp_len
;
109 tmp
.u
= ctf_bitfield_unsigned_read(ptr
, srcpos
.sign_start
, 1,
111 ctf_bitfield_unsigned_write(&u
.bits
, destpos
.sign_start
, 1,
112 dest
->byte_order
, tmp
.u
);
114 /* mantissa (without leading 1). No sign extend. */
115 tmp
.u
= ctf_bitfield_unsigned_read(ptr
, srcpos
.mantissa_start
,
116 src
->mantissa_len
- 1,
118 ctf_bitfield_unsigned_write(&u
.bits
, destpos
.mantissa_start
,
119 dest
->mantissa_len
- 1, dest
->byte_order
,
122 /* exponent, with sign-extend. */
123 tmp
.s
= ctf_bitfield_signed_read(ptr
, srcpos
.exp_start
, src
->exp_len
,
125 ctf_bitfield_signed_write(&u
.bits
, destpos
.exp_start
, dest
->exp_len
,
126 dest
->byte_order
, tmp
.s
);
129 double ctf_double_read(const unsigned char *ptr
, const struct type_class_float
*src
)
131 union doubleIEEE754 u
;
132 struct ctf_float dest
= {
133 .exp_len
= sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
134 .mantissa_len
= DBL_MANT_DIG
,
135 .byte_order
= BYTE_ORDER
,
138 ctf_float_copy(&u
.bits
, &dest
, ptr
, src
);
142 size_t ctf_double_write(unsigned char *ptr
, const struct type_class_float
*dest
,
145 union doubleIEEE754 u
;
146 struct ctf_float src
= {
147 .exp_len
= sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
148 .mantissa_len
= DBL_MANT_DIG
,
149 .byte_order
= BYTE_ORDER
,
155 ctf_float_copy(ptr
, dest
, &u
.bits
, &src
);
160 long double ctf_ldouble_read(const unsigned char *ptr
,
161 const struct type_class_float
*src
)
163 union ldoubleIEEE754 u
;
164 struct ctf_float dest
= {
165 .exp_len
= sizeof(double) * CHAR_BIT
- LDBL_MANT_DIG
,
166 .mantissa_len
= LDBL_MANT_DIG
,
167 .byte_order
= BYTE_ORDER
,
170 ctf_float_copy(&u
.bits
, &dest
, ptr
, src
);
174 size_t ctf_ldouble_write(unsigned char *ptr
, const struct type_class_float
*dest
,
177 union ldoubleIEEE754 u
;
178 struct ctf_float src
= {
179 .exp_len
= sizeof(double) * CHAR_BIT
- LDBL_MANT_DIG
,
180 .mantissa_len
= LDBL_MANT_DIG
,
181 .byte_order
= BYTE_ORDER
,
187 ctf_float_copy(ptr
, dest
, &u
.bits
, &src
);
This page took 0.035415 seconds and 6 git commands to generate.