]> git.tdb.fi Git - libs/datafile.git/blob - source/binfloat.cpp
Cosmetic changes
[libs/datafile.git] / source / binfloat.cpp
1 #include <cmath>
2 #include "binfloat.h"
3
4 using namespace std;
5
6 namespace Msp {
7 namespace DataFile {
8
9 BinFloat BinFloat::explode(uint64_t value, const Bits &bits)
10 {
11         uint64_t mantissa_mask = (1ULL<<bits.mantissa)-1;
12         int exponent_mask = (1<<bits.exponent)-1;
13
14         BinFloat bf;
15         // Extract biased exponent and sign
16         bf.exponent = (value>>bits.mantissa)&exponent_mask;
17         bf.sign = value>>(bits.mantissa+bits.exponent);
18         bf.infinity = (bf.exponent==exponent_mask);
19
20         if(bf.exponent==0 || bf.infinity)
21                 // Zeroes and infinities have zero mantissa
22                 bf.mantissa = 0;
23         else
24         {
25                 // Extract mantissa, add the implied one and align it to high bits
26                 bf.mantissa = (value&mantissa_mask) | (uint64_t(1)<<bits.mantissa);
27                 bf.mantissa <<= 63-bits.mantissa;
28         }
29
30         // Unbias the exponent
31         bf.exponent -= exponent_mask>>1;
32
33         return bf;
34 }
35
36 uint64_t BinFloat::compose(const Bits &bits)
37 {
38         uint64_t mantissa_mask = (1ULL<<bits.mantissa)-1;
39         int exponent_mask = (1<<bits.exponent)-1;
40
41         int biased_exponent = exponent+(exponent_mask>>1);
42         // Shift down and round the mantissa
43         uint64_t rounded_mantissa = ((mantissa>>(62-bits.mantissa))+1)>>1;
44         // If the integer part is greater than one, we need to use a higher exponent
45         if((rounded_mantissa>>bits.mantissa)>1)
46                 ++biased_exponent;
47
48         if(biased_exponent>=exponent_mask || infinity)
49                 // Overflow, return infinity
50                 return uint64_t(sign<<bits.exponent | exponent_mask)<<bits.mantissa;
51         else if(biased_exponent<=0 || !mantissa)
52                 // Underflow, return zero
53                 return 0;
54         else
55         {
56                 uint64_t value = rounded_mantissa&mantissa_mask;
57                 value |= uint64_t(biased_exponent)<<bits.mantissa;
58                 value |= uint64_t(sign)<<(bits.mantissa+bits.exponent);
59                 return value;
60         }
61 }
62
63
64 // exponent = log_2(bits)*3-7
65 BinFloat::Bits::Bits(unsigned bits):
66         exponent(log(bits)*4.3281-7),
67         mantissa(bits-exponent-1)
68 { }
69
70 } // namespace DataFile
71 } // namespace Msp