Use inheritance for trace descriptor and positions
[babeltrace.git] / formats / ctf / types / float.c
CommitLineData
6dc2ca62
MD
1/*
2 * Common Trace Format
3 *
4 * Floating point read/write functions.
5 *
ccd7e1c8 6 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6dc2ca62 7 *
ccd7e1c8
MD
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
de0ba614 14 *
ccd7e1c8
MD
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
6dc2ca62 17 *
de0ba614 18 * Reference: ISO C99 standard 5.2.4
6dc2ca62
MD
19 */
20
d79865b9 21#include <babeltrace/ctf/types.h>
6dc2ca62 22#include <glib.h>
de0ba614 23#include <float.h> /* C99 floating point definitions */
a3dbc794 24#include <limits.h> /* C99 limits */
6dc2ca62
MD
25#include <endian.h>
26
de0ba614
MD
27/*
28 * This library is limited to binary representation of floating point values.
29 * Sign-extension of the exponents is assumed to keep the NaN, +inf, -inf
30 * values, but this should be double-checked (TODO).
31 */
32
6dc2ca62
MD
33/*
34 * Aliasing float/double and unsigned long is not strictly permitted by strict
f6625916 35 * aliasing, but in practice declaration prunning is well supported, and this permits
6dc2ca62
MD
36 * us to use per-word read/writes rather than per-byte.
37 */
38
39#if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
40#define HAS_TYPE_PRUNING
41#endif
42
de0ba614
MD
43#if (FLT_RADIX != 2)
44
45#error "Unsupported floating point radix"
46
6dc2ca62 47#endif
6dc2ca62
MD
48
49union doubleIEEE754 {
50 double v;
51#ifdef HAS_TYPE_PRUNING
52 unsigned long bits[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
53#else
54 unsigned char bits[sizeof(double)];
55#endif
56};
57
de0ba614
MD
58union ldoubleIEEE754 {
59 long double v;
60#ifdef HAS_TYPE_PRUNING
61 unsigned long bits[(sizeof(long double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
62#else
63 unsigned char bits[sizeof(long double)];
64#endif
65};
66
67struct pos_len {
68 size_t sign_start, exp_start, mantissa_start, len;
69};
70
11d43b90 71void _ctf_float_copy(struct stream_pos *destp,
f6625916 72 const struct declaration_float *dest_declaration,
11d43b90 73 struct stream_pos *srcp,
f6625916 74 const struct declaration_float *src_declaration)
6dc2ca62 75{
11d43b90
MD
76 uint8_t sign;
77 int64_t exp;
78 uint64_t mantissa;
de0ba614 79
11d43b90 80 /* Read */
f6625916
MD
81 if (src_declaration->byte_order == LITTLE_ENDIAN) {
82 mantissa = ctf_uint_read(srcp, src_declaration->mantissa);
83 exp = ctf_int_read(srcp, src_declaration->exp);
84 sign = ctf_uint_read(srcp, src_declaration->sign);
de0ba614 85 } else {
f6625916
MD
86 sign = ctf_uint_read(srcp, src_declaration->sign);
87 exp = ctf_int_read(srcp, src_declaration->exp);
88 mantissa = ctf_uint_read(srcp, src_declaration->mantissa);
6dc2ca62 89 }
11d43b90 90 /* Write */
f6625916
MD
91 if (dest_declaration->byte_order == LITTLE_ENDIAN) {
92 ctf_uint_write(destp, dest_declaration->mantissa, mantissa);
93 ctf_int_write(destp, dest_declaration->exp, exp);
94 ctf_uint_write(destp, dest_declaration->sign, sign);
de0ba614 95 } else {
f6625916
MD
96 ctf_uint_write(destp, dest_declaration->sign, sign);
97 ctf_int_write(destp, dest_declaration->exp, exp);
98 ctf_uint_write(destp, dest_declaration->mantissa, mantissa);
6dc2ca62 99 }
11d43b90 100}
de0ba614 101
11d43b90 102void ctf_float_copy(struct stream_pos *dest, struct stream_pos *src,
f6625916 103 const struct declaration_float *float_declaration)
11d43b90 104{
46322b33
MD
105 ctf_align_pos(ctf_pos(src), float_declaration->p.alignment);
106 ctf_align_pos(ctf_pos(dest), float_declaration->p.alignment);
f6625916 107 _ctf_float_copy(dest, float_declaration, src, float_declaration);
6dc2ca62
MD
108}
109
11d43b90 110double ctf_double_read(struct stream_pos *srcp,
f6625916 111 const struct declaration_float *float_declaration)
6dc2ca62 112{
de0ba614 113 union doubleIEEE754 u;
add40b62
MD
114 struct declaration_float *dest_declaration =
115 float_declaration_new(DBL_MANT_DIG,
11d43b90
MD
116 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
117 BYTE_ORDER,
118 __alignof__(double));
46322b33 119 struct ctf_stream_pos destp;
11d43b90 120
46322b33
MD
121 ctf_align_pos(ctf_pos(srcp), float_declaration->p.alignment);
122 ctf_init_pos(&destp, -1);
0f980a35 123 destp.base = (char *) u.bits;
46322b33 124 _ctf_float_copy(&destp.parent, dest_declaration, srcp, float_declaration);
f6625916 125 declaration_unref(&dest_declaration->p);
de0ba614
MD
126 return u.v;
127}
128
11d43b90 129void ctf_double_write(struct stream_pos *destp,
f6625916 130 const struct declaration_float *float_declaration,
11d43b90 131 double v)
de0ba614
MD
132{
133 union doubleIEEE754 u;
add40b62
MD
134 struct declaration_float *src_declaration =
135 float_declaration_new(DBL_MANT_DIG,
11d43b90
MD
136 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
137 BYTE_ORDER,
138 __alignof__(double));
46322b33 139 struct ctf_stream_pos srcp;
11d43b90 140
de0ba614 141 u.v = v;
46322b33
MD
142 ctf_align_pos(ctf_pos(destp), float_declaration->p.alignment);
143 ctf_init_pos(&srcp, -1);
0f980a35 144 srcp.base = (char *) u.bits;
46322b33 145 _ctf_float_copy(destp, float_declaration, &srcp.parent, src_declaration);
f6625916 146 declaration_unref(&src_declaration->p);
de0ba614 147}
6dc2ca62 148
11d43b90 149long double ctf_ldouble_read(struct stream_pos *srcp,
f6625916 150 const struct declaration_float *float_declaration)
de0ba614
MD
151{
152 union ldoubleIEEE754 u;
add40b62
MD
153 struct declaration_float *dest_declaration =
154 float_declaration_new(LDBL_MANT_DIG,
11d43b90
MD
155 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG,
156 BYTE_ORDER,
157 __alignof__(long double));
46322b33 158 struct ctf_stream_pos destp;
11d43b90 159
46322b33
MD
160 ctf_align_pos(ctf_pos(srcp), float_declaration->p.alignment);
161 ctf_init_pos(&destp, -1);
0f980a35 162 destp.base = (char *) u.bits;
46322b33 163 _ctf_float_copy(&destp.parent, dest_declaration, srcp, float_declaration);
f6625916 164 declaration_unref(&dest_declaration->p);
de0ba614
MD
165 return u.v;
166}
167
11d43b90 168void ctf_ldouble_write(struct stream_pos *destp,
f6625916 169 const struct declaration_float *float_declaration,
11d43b90 170 long double v)
de0ba614
MD
171{
172 union ldoubleIEEE754 u;
add40b62
MD
173 struct declaration_float *src_declaration =
174 float_declaration_new(LDBL_MANT_DIG,
11d43b90
MD
175 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG,
176 BYTE_ORDER,
177 __alignof__(long double));
46322b33 178 struct ctf_stream_pos srcp;
11d43b90 179
de0ba614 180 u.v = v;
46322b33
MD
181 ctf_align_pos(ctf_pos(destp), float_declaration->p.alignment);
182 ctf_init_pos(&srcp, -1);
0f980a35 183 srcp.base = (char *) u.bits;
46322b33 184 _ctf_float_copy(destp, float_declaration, &srcp.parent, src_declaration);
f6625916 185 declaration_unref(&src_declaration->p);
6dc2ca62 186}
This page took 0.031563 seconds and 4 git commands to generate.