]> git.tdb.fi Git - libs/datafile.git/blob - source/binfloat.h
Fix incorrect order of memcpy args
[libs/datafile.git] / source / binfloat.h
1 #ifndef MSP_DATAFILE_BINFLOAT_H_
2 #define MSP_DATAFILE_BINFLOAT_H_
3
4 #include <climits>
5 #include <cstdint>
6 #include <cstring>
7
8 namespace Msp {
9 namespace DataFile {
10
11 /**
12 Facilitates splitting floating-point numbers into parts and putting them back
13 together.  Supports arbitary sizes up to 64 bits.  The 16, 32 and 64 bit
14 formats exactly match those defined by ISO/IEC 60559:2011.
15
16 The exponent is stored in an unbiased form.  The mantissa is stored with the
17 integer part included, aligned to the high bits of a 64-bit integer.
18 */
19 struct BinFloat
20 {
21         struct Bits
22         {
23                 unsigned exponent;
24                 unsigned mantissa;
25
26                 Bits(unsigned);
27         };
28
29         template<typename T>
30         struct MatchingInt;
31
32         bool sign;
33         bool infinity;
34         int exponent;
35         std::uint64_t mantissa;
36
37         static BinFloat explode(std::uint64_t, const Bits &);
38
39         template<typename T>
40         static BinFloat explode_iec559(T v);
41
42         std::uint64_t compose(const Bits &);
43
44         template<typename T>
45         T compose_iec559();
46 };
47
48 template<>
49 struct BinFloat::MatchingInt<float> { typedef std::uint32_t Type; };
50
51 template<>
52 struct BinFloat::MatchingInt<double> { typedef std::uint64_t Type; };
53
54 template<typename T>
55 inline BinFloat BinFloat::explode_iec559(T v)
56 {
57         typename MatchingInt<T>::Type i;
58         memcpy(&i, &v, sizeof(T));
59         return explode(i, sizeof(T)*CHAR_BIT);
60 }
61
62 template<typename T>
63 inline T BinFloat::compose_iec559()
64 {
65         typename MatchingInt<T>::Type i = compose(sizeof(T)*CHAR_BIT);
66         T v;
67         memcpy(&v, &i, sizeof(T));
68         return v;
69 }
70
71 } // namespace DataFile
72 } // namespace Msp
73
74 #endif