Stop using gnulib's flexmember module.
[upkg.git] / src / uobject / primitives.c
blobb90734811d7bc25f7bbd2790d3e977153eb31d06
1 /*
2 * upkg: tool for manipulating Unreal Tournament packages.
3 * Copyright © 2012, 2020 Nick Bowler
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <config.h>
20 #include <math.h>
22 #include <uobject/uobject.h>
23 #include "pack.h"
26 * Deserialize an IEEE 754 binary32 value in "little endian" (for whatever
27 * that term is worth in this context). That is, when interpreted as a little
28 * endian 32-bit unsigned integer: bit 31 is the sign, bits 30-23 are the
29 * (biased) exponent, and bits 22-0 are the encoded part of the significand.
31 * The implementation is designed to be agnostic of the platform's actual
32 * float type, but the conversion may be lossy if "float" is not itself a
33 * binary32 format. NaN payloads are not preserved.
35 float u_unpack_binary32_le(const unsigned char *buf)
37 unsigned long raw;
38 long significand;
39 int exponent;
40 float result;
42 raw = unpack_32_le(buf);
43 exponent = (raw & 0x7f800000) >> 23;
44 significand = (raw & 0x007fffff) >> 0;
46 switch (exponent) {
47 case 255:
48 result = significand ? NAN : INFINITY;
49 break;
50 default:
51 significand |= 0x00800000;
52 /* fall through */
53 case 0:
54 result = ldexpf(significand, exponent-126-24);
57 return copysignf(result, raw & 0x80000000 ? -1 : 1);