Finish float
[babeltrace.git] / formats / ctf / types / float.c
CommitLineData
6dc2ca62
MD
1/*
2 * Common Trace Format
3 *
4 * Floating point read/write functions.
5 *
de0ba614 6 * Copyright (c) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6dc2ca62 7 *
de0ba614
MD
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.
12 *
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.
17 *
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
6dc2ca62 21 *
de0ba614 22 * Reference: ISO C99 standard 5.2.4
6dc2ca62
MD
23 */
24
d79865b9 25#include <babeltrace/ctf/types.h>
6dc2ca62 26#include <glib.h>
de0ba614 27#include <float.h> /* C99 floating point definitions */
a3dbc794 28#include <limits.h> /* C99 limits */
6dc2ca62
MD
29#include <endian.h>
30
de0ba614
MD
31/*
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).
35 */
36
6dc2ca62
MD
37/*
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.
41 */
42
43#if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
44#define HAS_TYPE_PRUNING
45#endif
46
de0ba614
MD
47#if (FLT_RADIX != 2)
48
49#error "Unsupported floating point radix"
50
6dc2ca62 51#endif
6dc2ca62
MD
52
53union doubleIEEE754 {
54 double v;
55#ifdef HAS_TYPE_PRUNING
56 unsigned long bits[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
57#else
58 unsigned char bits[sizeof(double)];
59#endif
60};
61
de0ba614
MD
62union ldoubleIEEE754 {
63 long double v;
64#ifdef HAS_TYPE_PRUNING
65 unsigned long bits[(sizeof(long double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
66#else
67 unsigned char bits[sizeof(long double)];
68#endif
69};
70
71struct pos_len {
72 size_t sign_start, exp_start, mantissa_start, len;
73};
74
11d43b90
MD
75void _ctf_float_copy(struct stream_pos *destp,
76 const struct type_class_float *dest_class,
77 struct stream_pos *srcp,
78 const struct type_class_float *src_class)
6dc2ca62 79{
11d43b90
MD
80 uint8_t sign;
81 int64_t exp;
82 uint64_t mantissa;
de0ba614 83
11d43b90
MD
84 /* Read */
85 if (src->byte_order == LITTLE_ENDIAN) {
86 mantissa = ctf_bitfield_unsigned_read(srcp,
87 src_class->mantissa);
88 exp = ctf_bitfield_signed_read(srcp, src_class->exp);
89 sign = ctf_bitfield_unsigned_read(srcp, src_class->sign);
de0ba614 90 } else {
11d43b90
MD
91 sign = ctf_bitfield_unsigned_read(srcp, src_class->sign);
92 exp = ctf_bitfield_signed_read(srcp, src_class->exp);
93 mantissa = ctf_bitfield_unsigned_read(srcp,
94 src_class->mantissa);
6dc2ca62 95 }
11d43b90
MD
96 /* Write */
97 if (dest->byte_order == LITTLE_ENDIAN) {
98 ctf_bitfield_unsigned_write(destp, dest_class->mantissa,
99 mantissa);
100 ctf_bitfield_signed_write(destp, dest_class->exp, exp);
101 ctf_bitfield_unsigned_write(destp, dest_class->sign, sign);
de0ba614 102 } else {
11d43b90
MD
103 ctf_bitfield_unsigned_write(destp, dest_class->sign, sign);
104 ctf_bitfield_signed_write(destp, dest_class->exp, exp);
105 ctf_bitfield_unsigned_write(destp, dest_class->mantissa,
106 mantissa);
6dc2ca62 107 }
11d43b90 108}
de0ba614 109
11d43b90
MD
110void ctf_float_copy(struct stream_pos *dest, struct stream_pos *src,
111 const struct type_class_float *float_class)
112{
113 align_pos(src, float_class->p.alignment);
114 align_pos(dest, float_class->p.alignment);
115 _ctf_float_copy(dest, float_class, src, float_class);
6dc2ca62
MD
116}
117
11d43b90
MD
118double ctf_double_read(struct stream_pos *srcp,
119 const struct type_class_float *float_class)
6dc2ca62 120{
de0ba614 121 union doubleIEEE754 u;
11d43b90
MD
122 struct ctf_float *dest_class = float_type_new(NULL,
123 DBL_MANT_DIG,
124 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
125 BYTE_ORDER,
126 __alignof__(double));
127 struct stream_pos destp;
128
129 align_pos(srcp, float_class->p.alignment);
130 init_pos(&destp, &u.bits);
131 _ctf_float_copy(&destp, dest_class, srcp, float_class);
132 float_type_free(dest_class);
de0ba614
MD
133 return u.v;
134}
135
11d43b90
MD
136void ctf_double_write(struct stream_pos *destp,
137 const struct type_class_float *float_class,
138 double v)
de0ba614
MD
139{
140 union doubleIEEE754 u;
11d43b90
MD
141 struct ctf_float *src_class = float_type_new(NULL,
142 DBL_MANT_DIG,
143 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
144 BYTE_ORDER,
145 __alignof__(double));
146 struct stream_pos srcp;
147
de0ba614 148 u.v = v;
11d43b90
MD
149 align_pos(destp, float_class->p.alignment);
150 init_pos(&srcp, &u.bits);
151 _ctf_float_copy(destp, float_class, &srcp, src_class);
152 float_type_free(src_class);
de0ba614 153}
6dc2ca62 154
11d43b90
MD
155long double ctf_ldouble_read(struct stream_pos *srcp,
156 const struct type_class_float *float_class)
de0ba614
MD
157{
158 union ldoubleIEEE754 u;
11d43b90
MD
159 struct ctf_float *dest_class = float_type_new(NULL,
160 LDBL_MANT_DIG,
161 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG,
162 BYTE_ORDER,
163 __alignof__(long double));
164 struct stream_pos destp;
165
166 align_pos(srcp, float_class->p.alignment);
167 init_pos(&destp, &u.bits);
168 _ctf_float_copy(&destp, dest_class, srcp, float_class);
169 float_type_free(dest_class);
de0ba614
MD
170 return u.v;
171}
172
11d43b90
MD
173void ctf_ldouble_write(struct stream_pos *destp,
174 const struct type_class_float *float_class,
175 long double v)
de0ba614
MD
176{
177 union ldoubleIEEE754 u;
11d43b90
MD
178 struct ctf_float *src_class = float_type_new(NULL,
179 LDBL_MANT_DIG,
180 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG,
181 BYTE_ORDER,
182 __alignof__(long double));
183 struct stream_pos srcp;
184
de0ba614 185 u.v = v;
11d43b90
MD
186 align_pos(destp, float_class->p.alignment);
187 init_pos(&srcp, &u.bits);
188 _ctf_float_copy(destp, float_class, &srcp, src_class);
189 float_type_free(src_class);
6dc2ca62 190}
This page took 0.030028 seconds and 4 git commands to generate.