Relicense BabelTrace library to MIT (BSD-style)
[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
35 * aliasing, but in practice type prunning is well supported, and this permits
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
MD
71void _ctf_float_copy(struct stream_pos *destp,
72 const struct type_class_float *dest_class,
73 struct stream_pos *srcp,
74 const struct type_class_float *src_class)
6dc2ca62 75{
11d43b90
MD
76 uint8_t sign;
77 int64_t exp;
78 uint64_t mantissa;
de0ba614 79
11d43b90
MD
80 /* Read */
81 if (src->byte_order == LITTLE_ENDIAN) {
7fe00194
MD
82 mantissa = ctf_uint_read(srcp, src_class->mantissa);
83 exp = ctf_int_read(srcp, src_class->exp);
84 sign = ctf_uint_read(srcp, src_class->sign);
de0ba614 85 } else {
7fe00194
MD
86 sign = ctf_uint_read(srcp, src_class->sign);
87 exp = ctf_int_read(srcp, src_class->exp);
88 mantissa = ctf_uint_read(srcp, src_class->mantissa);
6dc2ca62 89 }
11d43b90
MD
90 /* Write */
91 if (dest->byte_order == LITTLE_ENDIAN) {
7fe00194
MD
92 ctf_uint_write(destp, dest_class->mantissa, mantissa);
93 ctf_int_write(destp, dest_class->exp, exp);
94 ctf_uint_write(destp, dest_class->sign, sign);
de0ba614 95 } else {
7fe00194
MD
96 ctf_uint_write(destp, dest_class->sign, sign);
97 ctf_int_write(destp, dest_class->exp, exp);
98 ctf_uint_write(destp, dest_class->mantissa, mantissa);
6dc2ca62 99 }
11d43b90 100}
de0ba614 101
11d43b90
MD
102void ctf_float_copy(struct stream_pos *dest, struct stream_pos *src,
103 const struct type_class_float *float_class)
104{
105 align_pos(src, float_class->p.alignment);
106 align_pos(dest, float_class->p.alignment);
107 _ctf_float_copy(dest, float_class, src, float_class);
6dc2ca62
MD
108}
109
11d43b90
MD
110double ctf_double_read(struct stream_pos *srcp,
111 const struct type_class_float *float_class)
6dc2ca62 112{
de0ba614 113 union doubleIEEE754 u;
11d43b90
MD
114 struct ctf_float *dest_class = float_type_new(NULL,
115 DBL_MANT_DIG,
116 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
117 BYTE_ORDER,
118 __alignof__(double));
119 struct stream_pos destp;
120
121 align_pos(srcp, float_class->p.alignment);
122 init_pos(&destp, &u.bits);
123 _ctf_float_copy(&destp, dest_class, srcp, float_class);
124 float_type_free(dest_class);
de0ba614
MD
125 return u.v;
126}
127
11d43b90
MD
128void ctf_double_write(struct stream_pos *destp,
129 const struct type_class_float *float_class,
130 double v)
de0ba614
MD
131{
132 union doubleIEEE754 u;
11d43b90
MD
133 struct ctf_float *src_class = float_type_new(NULL,
134 DBL_MANT_DIG,
135 sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
136 BYTE_ORDER,
137 __alignof__(double));
138 struct stream_pos srcp;
139
de0ba614 140 u.v = v;
11d43b90
MD
141 align_pos(destp, float_class->p.alignment);
142 init_pos(&srcp, &u.bits);
143 _ctf_float_copy(destp, float_class, &srcp, src_class);
144 float_type_free(src_class);
de0ba614 145}
6dc2ca62 146
11d43b90
MD
147long double ctf_ldouble_read(struct stream_pos *srcp,
148 const struct type_class_float *float_class)
de0ba614
MD
149{
150 union ldoubleIEEE754 u;
11d43b90
MD
151 struct ctf_float *dest_class = float_type_new(NULL,
152 LDBL_MANT_DIG,
153 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG,
154 BYTE_ORDER,
155 __alignof__(long double));
156 struct stream_pos destp;
157
158 align_pos(srcp, float_class->p.alignment);
159 init_pos(&destp, &u.bits);
160 _ctf_float_copy(&destp, dest_class, srcp, float_class);
161 float_type_free(dest_class);
de0ba614
MD
162 return u.v;
163}
164
11d43b90
MD
165void ctf_ldouble_write(struct stream_pos *destp,
166 const struct type_class_float *float_class,
167 long double v)
de0ba614
MD
168{
169 union ldoubleIEEE754 u;
11d43b90
MD
170 struct ctf_float *src_class = float_type_new(NULL,
171 LDBL_MANT_DIG,
172 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG,
173 BYTE_ORDER,
174 __alignof__(long double));
175 struct stream_pos srcp;
176
de0ba614 177 u.v = v;
11d43b90
MD
178 align_pos(destp, float_class->p.alignment);
179 init_pos(&srcp, &u.bits);
180 _ctf_float_copy(destp, float_class, &srcp, src_class);
181 float_type_free(src_class);
6dc2ca62 182}
This page took 0.030453 seconds and 4 git commands to generate.