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 <ctf/ctf-types.h>
27 #include <float.h> /* C99 floating point definitions */
31 * This library is limited to binary representation of floating point values.
32 * Sign-extension of the exponents is assumed to keep the NaN, +inf, -inf
33 * values, but this should be double-checked (TODO).
37 * Aliasing float/double and unsigned long is not strictly permitted by strict
38 * aliasing, but in practice type prunning is well supported, and this permits
39 * us to use per-word read/writes rather than per-byte.
42 #if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
43 #define HAS_TYPE_PRUNING
48 #error "Unsupported floating point radix"
54 #ifdef HAS_TYPE_PRUNING
55 unsigned long bits
[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
57 unsigned char bits
[sizeof(double)];
61 union ldoubleIEEE754
{
63 #ifdef HAS_TYPE_PRUNING
64 unsigned long bits
[(sizeof(long double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
66 unsigned char bits
[sizeof(long double)];
71 size_t sign_start
, exp_start
, mantissa_start
, len
;
74 void ctf_float_copy(unsigned char *destp
, const struct ctf_float
*dest
,
75 const unsigned char *src
, const struct ctf_float
*src
)
77 struct pos_len destpos
, srcpos
;
83 destpos
.len
= dest
.exp_len
+ dest
.mantissa_len
;
84 if (dest
.byte_order
== LITTLE_ENDIAN
) {
85 destpos
.sign_start
= destpos
.len
- 1;
86 destpos
.exp_start
= destpos
.sign_start
- dest
->exp_len
;
87 destpos
.mantissa_start
= 0;
89 destpos
.sign_start
= 0;
90 destpos
.exp_start
= 1;
91 destpos
.mantissa_start
= destpos
.exp_start
+ dest
->exp_len
;
94 srcpos
.len
= src
.exp_len
+ src
.mantissa_len
;
95 if (src
.byte_order
== LITTLE_ENDIAN
) {
96 srcpos
.sign_start
= srcpos
.len
- 1;
97 srcpos
.exp_start
= srcpos
.sign_start
- src
->exp_len
;
98 srcpos
.mantissa_start
= 0;
100 srcpos
.sign_start
= 0;
101 srcpos
.exp_start
= 1;
102 srcpos
.mantissa_start
= srcpos
.exp_start
+ src
->exp_len
;
106 tmp
.u
= bitfield_unsigned_read(ptr
, srcpos
.sign_start
, 1,
108 bitfield_unsigned_write(&u
.bits
, destpos
.sign_start
, 1,
109 dest
->byte_order
, tmp
.u
);
111 /* mantissa (without leading 1). No sign extend. */
112 tmp
.u
= bitfield_unsigned_read(ptr
, srcpos
.mantissa_start
,
113 src
->mantissa_len
- 1, src
->byte_order
);
114 bitfield_unsigned_write(&u
.bits
, destpos
.mantissa_start
,
115 dest
->mantissa_len
- 1, dest
->byte_order
, tmp
.u
);
117 /* exponent, with sign-extend. */
118 tmp
.s
= bitfield_signed_read(ptr
, srcpos
.exp_start
, src
->exp_len
,
120 bitfield_signed_write(&u
.bits
, destpos
.exp_start
, dest
->exp_len
,
121 dest
->byte_order
, tmp
.s
);
124 double ctf_double_read(const unsigned char *ptr
, const struct ctf_float
*src
)
126 union doubleIEEE754 u
;
127 struct ctf_float dest
= {
128 .exp_len
= sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
129 .mantissa_len
= DBL_MANT_DIG
,
130 .byte_order
= BYTE_ORDER
,
133 float_copy(&u
.bits
, &dest
, ptr
, src
);
137 size_t ctf_double_write(unsigned char *ptr
, const struct ctf_float
*dest
,
140 union doubleIEEE754 u
;
141 struct ctf_float src
= {
142 .exp_len
= sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
,
143 .mantissa_len
= DBL_MANT_DIG
,
144 .byte_order
= BYTE_ORDER
,
150 float_copy(ptr
, dest
, &u
.bits
, &src
);
155 long double ctf_ldouble_read(const unsigned char *ptr
,
156 const struct ctf_float
*src
)
158 union ldoubleIEEE754 u
;
159 struct ctf_float dest
= {
160 .exp_len
= sizeof(double) * CHAR_BIT
- LDBL_MANT_DIG
,
161 .mantissa_len
= LDBL_MANT_DIG
,
162 .byte_order
= BYTE_ORDER
,
165 float_copy(&u
.bits
, &dest
, ptr
, src
);
169 size_t ctf_ldouble_write(unsigned char *ptr
, const struct ctf_float
*dest
,
172 union ldoubleIEEE754 u
;
173 struct ctf_float src
= {
174 .exp_len
= sizeof(double) * CHAR_BIT
- LDBL_MANT_DIG
,
175 .mantissa_len
= LDBL_MANT_DIG
,
176 .byte_order
= BYTE_ORDER
,
182 float_copy(ptr
, dest
, &u
.bits
, &src
);
This page took 0.032704 seconds and 4 git commands to generate.