4 * Floating point read/write functions.
6 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * Reference: ISO C99 standard 5.2.4
10 * Dual LGPL v2.1/GPL v2 license.
13 #include <ctf/ctf-types.h>
18 * Aliasing float/double and unsigned long is not strictly permitted by strict
19 * aliasing, but in practice type prunning is well supported, and this permits
20 * us to use per-word read/writes rather than per-byte.
23 #if defined(__GNUC__) || defined(__MINGW32__) || defined(_MSC_VER)
24 #define HAS_TYPE_PRUNING
29 #ifdef HAS_TYPE_PRUNING
30 unsigned long bits
[(sizeof(float) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
32 unsigned char bits
[sizeof(float)];
38 #ifdef HAS_TYPE_PRUNING
39 unsigned long bits
[(sizeof(double) + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
41 unsigned char bits
[sizeof(double)];
45 double float_read(const uint8_t *ptr
, size_t len
, int byte_order
)
47 int rbo
= (byte_order
!= __FLOAT_WORD_ORDER
); /* reverse byte order */
56 return (double) *(const float *) ptr
;
58 * Need to reverse byte order. Read the opposite from our
61 if (__FLOAT_WORD_ORDER
== LITTLE_ENDIAN
) {
63 tmp
= bitfield_unsigned_read(ptr
, 0, 1, BIG_ENDIAN
);
64 bitfield_unsigned_write(&u
.bits
, 31, 1, LITTLE_ENDIAN
,
66 tmp
= bitfield_unsigned_read(ptr
, 1, 8, BIG_ENDIAN
);
67 bitfield_unsigned_write(&u
.bits
, 23, 8, LITTLE_ENDIAN
,
69 tmp
= bitfield_unsigned_read(ptr
, 9, 23, BIG_ENDIAN
);
70 bitfield_unsigned_write(&u
.bits
, 0, 23, LITTLE_ENDIAN
,
73 /* Read little endian */
74 tmp
= bitfield_unsigned_read(ptr
, 31, 1, LITTLE_ENDIAN
);
75 bitfield_unsigned_write(&u
.bits
, 0, 1, BIG_ENDIAN
,
77 tmp
= bitfield_unsigned_read(ptr
, 23, 8, LITTLE_ENDIAN
);
78 bitfield_unsigned_write(&u
.bits
, 1, 8, BIG_ENDIAN
,
80 tmp
= bitfield_unsigned_read(ptr
, 0, 23, LITTLE_ENDIAN
);
81 bitfield_unsigned_write(&u
.bits
, 9, 23, BIG_ENDIAN
,
88 union doubleIEEE754 u
;
92 return (double) *(const double *) ptr
;
94 * Need to reverse byte order. Read the opposite from our
97 if (__FLOAT_WORD_ORDER
== LITTLE_ENDIAN
) {
99 tmp
= bitfield_unsigned_read(ptr
, 0, 1, BIG_ENDIAN
);
100 bitfield_unsigned_write(&u
.bits
, 63, 1, LITTLE_ENDIAN
,
102 tmp
= bitfield_unsigned_read(ptr
, 1, 11, BIG_ENDIAN
);
103 bitfield_unsigned_write(&u
.bits
, 52, 11, LITTLE_ENDIAN
,
105 tmp
= bitfield_unsigned_read(ptr
, 12, 52, BIG_ENDIAN
);
106 bitfield_unsigned_write(&u
.bits
, 0, 52, LITTLE_ENDIAN
,
109 /* Read little endian */
110 tmp
= bitfield_unsigned_read(ptr
, 63, 1, LITTLE_ENDIAN
);
111 bitfield_unsigned_write(&u
.bits
, 0, 1, BIG_ENDIAN
,
113 tmp
= bitfield_unsigned_read(ptr
, 52, 11, LITTLE_ENDIAN
);
114 bitfield_unsigned_write(&u
.bits
, 1, 11, BIG_ENDIAN
,
116 tmp
= bitfield_unsigned_read(ptr
, 0, 52, LITTLE_ENDIAN
);
117 bitfield_unsigned_write(&u
.bits
, 12, 52, BIG_ENDIAN
,
123 printf("float read unavailable for size %u\n", len
);
128 size_t float_write(uint8_t *ptr
, size_t len
, int byte_order
, double v
)
130 int rbo
= (byte_order
!= __FLOAT_WORD_ORDER
); /* reverse byte order */
138 union floatIEEE754 u
;
142 *(float *) ptr
= (float) v
;
147 * Need to reverse byte order. Write the opposite from our
150 if (__FLOAT_WORD_ORDER
== LITTLE_ENDIAN
) {
151 /* Write big endian */
152 tmp
= bitfield_unsigned_read(ptr
, 31, 1, LITTLE_ENDIAN
);
153 bitfield_unsigned_write(&u
.bits
, 0, 1, BIG_ENDIAN
,
155 tmp
= bitfield_unsigned_read(ptr
, 23, 8, LITTLE_ENDIAN
);
156 bitfield_unsigned_write(&u
.bits
, 1, 8, BIG_ENDIAN
,
158 tmp
= bitfield_unsigned_read(ptr
, 0, 23, LITTLE_ENDIAN
);
159 bitfield_unsigned_write(&u
.bits
, 9, 23, BIG_ENDIAN
,
162 /* Write little endian */
163 tmp
= bitfield_unsigned_read(ptr
, 0, 1, BIG_ENDIAN
);
164 bitfield_unsigned_write(&u
.bits
, 31, 1, LITTLE_ENDIAN
,
166 tmp
= bitfield_unsigned_read(ptr
, 1, 8, BIG_ENDIAN
);
167 bitfield_unsigned_write(&u
.bits
, 23, 8, LITTLE_ENDIAN
,
169 tmp
= bitfield_unsigned_read(ptr
, 9, 23, BIG_ENDIAN
);
170 bitfield_unsigned_write(&u
.bits
, 0, 23, LITTLE_ENDIAN
,
177 union doubleIEEE754 u
;
186 * Need to reverse byte order. Write the opposite from our
189 if (__FLOAT_WORD_ORDER
== LITTLE_ENDIAN
) {
190 /* Write big endian */
191 tmp
= bitfield_unsigned_read(ptr
, 63, 1, LITTLE_ENDIAN
);
192 bitfield_unsigned_write(&u
.bits
, 0, 1, BIG_ENDIAN
,
194 tmp
= bitfield_unsigned_read(ptr
, 52, 11, LITTLE_ENDIAN
);
195 bitfield_unsigned_write(&u
.bits
, 1, 11, BIG_ENDIAN
,
197 tmp
= bitfield_unsigned_read(ptr
, 0, 52, LITTLE_ENDIAN
);
198 bitfield_unsigned_write(&u
.bits
, 12, 52, BIG_ENDIAN
,
201 /* Write little endian */
202 tmp
= bitfield_unsigned_read(ptr
, 0, 1, BIG_ENDIAN
);
203 bitfield_unsigned_write(&u
.bits
, 63, 1, LITTLE_ENDIAN
,
205 tmp
= bitfield_unsigned_read(ptr
, 1, 11, BIG_ENDIAN
);
206 bitfield_unsigned_write(&u
.bits
, 52, 11, LITTLE_ENDIAN
,
208 tmp
= bitfield_unsigned_read(ptr
, 12, 52, BIG_ENDIAN
);
209 bitfield_unsigned_write(&u
.bits
, 0, 52, LITTLE_ENDIAN
,
215 printf("float write unavailable for size %u\n", len
);
This page took 0.035928 seconds and 4 git commands to generate.