-
Notifications
You must be signed in to change notification settings - Fork 0
/
binary64.hpp
118 lines (104 loc) · 3.71 KB
/
binary64.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* Calculates the IEEE 754 standard 64-bit binary floating-point
representation of a real number. */
#ifndef BINARY64_HPP_INCLUDE
#define BINARY64_HPP_INCLUDE
#include <iostream>
#include <iomanip>
#include <bitset>
struct Binary64
{
static const int NBIT = 64, NBIT_EXPONENT = 11, NBIT_MANTISSA = 52;
union { double float64; unsigned long ulong64; } data;
std::bitset<NBIT> bits;
// Initialization with a double precision floating-point number input.
Binary64(double number) {
this->data.float64 = number;
this->bits = std::bitset<NBIT>(data.ulong64);
}
// Initialization with the bits as input.
Binary64(std::bitset<NBIT> &bits) {
this->data.ulong64 = bits.to_ulong();
this->bits = bits;
}
// Change the stored bit at idx with val.
void modify_bits(size_t idx, int val) {
this->bits[idx] = val;
this->data.ulong64 = this->bits.to_ulong();
return;
}
// Change the stored bits at idxs with vals.
void modify_bits(std::initializer_list<size_t> &&idxs,
std::initializer_list<int> &&vals) {
size_t idxs_size = idxs.size();
for (size_t k = 0; k < idxs_size; k++)
this->bits[*(idxs.begin() + k)] = *(vals.begin() + k);
this->data.ulong64 = this->bits.to_ulong();
return;
}
};
int getNumZeroBitsExponent(const Binary64 &number) {
int numZeroBitsExponent = 0;
for (int k = number.NBIT-2; k > number.NBIT_MANTISSA-1; k--) {
if (number.bits[static_cast<size_t>(k)] == 0)
numZeroBitsExponent++;
}
return numZeroBitsExponent;
}
int getNumZeroBitsMantissa(const Binary64 &number) {
int numZeroBitsMantissa = 0;
for (int k = number.NBIT_MANTISSA-1; k >= 0; k--) {
if (number.bits[static_cast<size_t>(k)] == 0)
numZeroBitsMantissa++;
}
return numZeroBitsMantissa;
}
void printSignBit(const Binary64 &number) {
std::cout << number.bits[number.NBIT-1] << " ";
}
void printExponentBits(const Binary64 &number) {
for (int k = number.NBIT - 2; k > number.NBIT_MANTISSA-1; k--)
std::cout << number.bits[static_cast<size_t>(k)];
std::cout << " ";
}
void printMantissaBits(const Binary64 &number) {
for (int k = number.NBIT_MANTISSA-1; k >= 0; k--)
std::cout << number.bits[static_cast<size_t>(k)];
}
void printStatus(const Binary64 &number, int &numZeroBitsExponent,
int &numZeroBitsMantissa) {
std::cout << "\nStatus : ";
// NaNs and infinities
if (numZeroBitsExponent == 0)
std::cout << "Exceptional";
// De-normalized numbers
if (numZeroBitsExponent == number.NBIT_EXPONENT
&& numZeroBitsMantissa < number.NBIT_MANTISSA)
std::cout << "De-normal";
// Positive and negative 0
if (numZeroBitsExponent == number.NBIT_EXPONENT
&& numZeroBitsMantissa == number.NBIT_MANTISSA) {
if (number.bits[number.NBIT-1] == 0)
std::cout << "Normal";
else
std::cout << "Exceptional";
}
// Normalized numbers
if (numZeroBitsExponent > 0
&& numZeroBitsExponent < number.NBIT_EXPONENT)
std::cout << "Normal";
}
// Output stream of a Binary64 struct.
std::ostream& operator<<(std::ostream &output, const Binary64 &number) {
int numZeroBitsExponent = getNumZeroBitsExponent(number);
int numZeroBitsMantissa = getNumZeroBitsMantissa(number);
std::cout.precision(16);
output << "Float64 : " << number.data.float64 << std::endl;
output << "Binary64: ";
printSignBit(number);
printExponentBits(number);
printMantissaBits(number);
printStatus(number, numZeroBitsExponent, numZeroBitsMantissa);
output << "\nHex Form: 0x"<< std::hex << number.data.ulong64 << "\n";
return output;
}
#endif