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
;
75 void ctf_float_copy(unsigned char *destp
, const struct ctf_float
*dest
,
76 const unsigned char *src
, const struct ctf_float
*src
)
78 struct pos_len destpos
, srcpos
;
84 destpos
.len
= dest
.exp_len
+ dest
.mantissa_len
;
85 if (dest
.byte_order
== LITTLE_ENDIAN
) {
86 destpos
.sign_start
= destpos
.len
- 1;
87 destpos
.exp_start
= destpos
.sign_start
- dest
->exp_len
;
88 destpos
.mantissa_start
= 0;
90 destpos
.sign_start
= 0;
91 destpos
.exp_start
= 1;
92 destpos
.mantissa_start
= destpos
.exp_start
+ dest
->exp_len
;
95 srcpos
.len
= src
.exp_len
+ src
.mantissa_len
;
96 if (src
.byte_order
== LITTLE_ENDIAN
) {
97 srcpos
.sign_start
= srcpos
.len
- 1;
98 srcpos
.exp_start
= srcpos
.sign_start
- src
->exp_len
;
99 srcpos
.mantissa_start
= 0;
101 srcpos
.sign_start
= 0;
102 srcpos
.exp_start
= 1;
103 srcpos
.mantissa_start
= srcpos
.exp_start
+ src
->exp_len
;
107 tmp
.u
= ctf_bitfield_unsigned_read(ptr
, srcpos
.sign_start
, 1,
109 ctf_bitfield_unsigned_write(&u
.bits
, destpos
.sign_start
, 1,
110 dest
->byte_order
, tmp
.u
);
112 /* mantissa (without leading 1). No sign extend. */
113 tmp
.u
= ctf_bitfield_unsigned_read(ptr
, srcpos
.mantissa_start
,
114 src
->mantissa_len
- 1,
116 ctf_bitfield_unsigned_write(&u
.bits
, destpos
.mantissa_start
,
117 dest
->mantissa_len
- 1, dest
->byte_order
,
120 /* exponent, with sign-extend. */
121 tmp
.s
= ctf_bitfield_signed_read(ptr
, srcpos
.exp_start
, src
->exp_len
,
123 ctf_bitfield_signed_write(&u
.bits
, destpos
.exp_start
, dest
->exp_len
,
124 dest
->byte_order
, tmp
.s
);
127 double ctf_double_read(const unsigned char *ptr
, const struct ctf_float
*src
)
129 union doubleIEEE754 u
;
130 struct ctf_float dest
= {
131 .exp_len
= sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
132 .mantissa_len
= DBL_MANT_DIG
,
133 .byte_order
= BYTE_ORDER
,
136 ctf_float_copy(&u
.bits
, &dest
, ptr
, src
);
140 size_t ctf_double_write(unsigned char *ptr
, const struct ctf_float
*dest
,
143 union doubleIEEE754 u
;
144 struct ctf_float src
= {
145 .exp_len
= sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
146 .mantissa_len
= DBL_MANT_DIG
,
147 .byte_order
= BYTE_ORDER
,
153 ctf_float_copy(ptr
, dest
, &u
.bits
, &src
);
158 long double ctf_ldouble_read(const unsigned char *ptr
,
159 const struct ctf_float
*src
)
161 union ldoubleIEEE754 u
;
162 struct ctf_float dest
= {
163 .exp_len
= sizeof(double) * CHAR_BIT
- LDBL_MANT_DIG
,
164 .mantissa_len
= LDBL_MANT_DIG
,
165 .byte_order
= BYTE_ORDER
,
168 ctf_float_copy(&u
.bits
, &dest
, ptr
, src
);
172 size_t ctf_ldouble_write(unsigned char *ptr
, const struct ctf_float
*dest
,
175 union ldoubleIEEE754 u
;
176 struct ctf_float src
= {
177 .exp_len
= sizeof(double) * CHAR_BIT
- LDBL_MANT_DIG
,
178 .mantissa_len
= LDBL_MANT_DIG
,
179 .byte_order
= BYTE_ORDER
,
185 ctf_float_copy(ptr
, dest
, &u
.bits
, &src
);
This page took 0.040144 seconds and 5 git commands to generate.