API cleanups, offset by bit.
[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
bed864a7
MD
75/* TODO */
76
fc93b2bd
MD
77void ctf_float_copy(unsigned char *destp, const struct type_class_float *dest,
78 const unsigned char *src, const struct type_class_float *src)
6dc2ca62 79{
de0ba614 80 struct pos_len destpos, srcpos;
dd617f8a
MD
81 union {
82 unsigned long long u;
83 long long s;
84 } tmp;
de0ba614 85
fc93b2bd
MD
86 destpos.len = dest->exp_len + dest->mantissa_len;
87 if (dest->byte_order == LITTLE_ENDIAN) {
de0ba614
MD
88 destpos.sign_start = destpos.len - 1;
89 destpos.exp_start = destpos.sign_start - dest->exp_len;
90 destpos.mantissa_start = 0;
91 } else {
92 destpos.sign_start = 0;
93 destpos.exp_start = 1;
94 destpos.mantissa_start = destpos.exp_start + dest->exp_len;
6dc2ca62 95 }
de0ba614 96
fc93b2bd
MD
97 srcpos.len = src->exp_len + src->mantissa_len;
98 if (src->byte_order == LITTLE_ENDIAN) {
de0ba614
MD
99 srcpos.sign_start = srcpos.len - 1;
100 srcpos.exp_start = srcpos.sign_start - src->exp_len;
101 srcpos.mantissa_start = 0;
102 } else {
103 srcpos.sign_start = 0;
104 srcpos.exp_start = 1;
105 srcpos.mantissa_start = srcpos.exp_start + src->exp_len;
6dc2ca62 106 }
de0ba614
MD
107
108 /* sign */
d79865b9
MD
109 tmp.u = ctf_bitfield_unsigned_read(ptr, srcpos.sign_start, 1,
110 src->byte_order);
111 ctf_bitfield_unsigned_write(&u.bits, destpos.sign_start, 1,
112 dest->byte_order, tmp.u);
de0ba614 113
6ca23e32 114 /* mantissa (without leading 1). No sign extend. */
d79865b9
MD
115 tmp.u = ctf_bitfield_unsigned_read(ptr, srcpos.mantissa_start,
116 src->mantissa_len - 1,
117 src->byte_order);
118 ctf_bitfield_unsigned_write(&u.bits, destpos.mantissa_start,
119 dest->mantissa_len - 1, dest->byte_order,
120 tmp.u);
de0ba614
MD
121
122 /* exponent, with sign-extend. */
d79865b9
MD
123 tmp.s = ctf_bitfield_signed_read(ptr, srcpos.exp_start, src->exp_len,
124 src->byte_order);
125 ctf_bitfield_signed_write(&u.bits, destpos.exp_start, dest->exp_len,
126 dest->byte_order, tmp.s);
6dc2ca62
MD
127}
128
fc93b2bd 129double ctf_double_read(const unsigned char *ptr, const struct type_class_float *src)
6dc2ca62 130{
de0ba614
MD
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,
136 };
137
d79865b9 138 ctf_float_copy(&u.bits, &dest, ptr, src);
de0ba614
MD
139 return u.v;
140}
141
fc93b2bd 142size_t ctf_double_write(unsigned char *ptr, const struct type_class_float *dest,
de0ba614
MD
143 double v)
144{
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,
150 };
6dc2ca62
MD
151
152 if (!ptr)
153 goto end;
de0ba614 154 u.v = v;
d79865b9 155 ctf_float_copy(ptr, dest, &u.bits, &src);
de0ba614
MD
156end:
157 return len;
158}
6dc2ca62 159
de0ba614 160long double ctf_ldouble_read(const unsigned char *ptr,
fc93b2bd 161 const struct type_class_float *src)
de0ba614
MD
162{
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,
168 };
169
d79865b9 170 ctf_float_copy(&u.bits, &dest, ptr, src);
de0ba614
MD
171 return u.v;
172}
173
fc93b2bd 174size_t ctf_ldouble_write(unsigned char *ptr, const struct type_class_float *dest,
de0ba614
MD
175 long double v)
176{
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,
182 };
183
184 if (!ptr)
185 goto end;
186 u.v = v;
d79865b9 187 ctf_float_copy(ptr, dest, &u.bits, &src);
6dc2ca62
MD
188end:
189 return len;
190}
This page took 0.031018 seconds and 4 git commands to generate.