1
+ /*
2
+ Copyright 2010 Brent W. Lewis
3
+ coder0xff on hotmail
4
+
5
+ This file is part of QPFloat.
6
+
7
+ QPFloat is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ QPFloat is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with QPFloat. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+ #include " Stdafx.h"
22
+ #include " DoubleDecomposition.h"
23
+ #include " Helpers.h"
24
+
25
+ #define DBL_SIGNIFICANT_BITS 52
26
+ #define DBL_EXPONENT_BITS 11
27
+ #define DBL_EXPONENT_BIAS 0x3FF
28
+
29
+ #define DBL_MANTISSA_BYTES (DBL_SIGNIFICANT_BITS + 7 ) / 8
30
+ #define DBL_EXPONENT_MASK ((1 << DBL_EXPONENT_BITS) - 1 )
31
+ #define DBL_EXPONENT_MAX (DBL_EXPONENT_MASK - DBL_EXPONENT_BIAS)
32
+ #define DBL_EXPONENT_MIN (-DBL_EXPONENT_BIAS)
33
+
34
+ #ifdef _MANAGED
35
+ #pragma unmanaged
36
+ #endif
37
+
38
+ bool DoubleDecomposition::GetSign ()
39
+ {
40
+ byte* ptr = (byte*)&value + 7 ;
41
+ return (*ptr & (byte)0x80 ) != 0 ;
42
+ }
43
+
44
+ void DoubleDecomposition::SetSign (bool value)
45
+ {
46
+ byte* ptr = (byte*)&this ->value + 7 ;
47
+ if (value)
48
+ *ptr |= 0x80 ;
49
+ else
50
+ *ptr &= 0x7F ;
51
+ }
52
+
53
+ ui16 DoubleDecomposition::GetBiasedExponent ()
54
+ {
55
+ ui16* ptr = ((ui16*)&this ->value ) + 3 ;
56
+ return (ui16)((*ptr >> 4 ) & 0x7FF );
57
+ }
58
+
59
+ void DoubleDecomposition::SetBiasedExponent (ui16 value)
60
+ {
61
+ const int exponentTruncate = (1 << DBL_EXPONENT_BITS) - 1 ;
62
+ ui16* ptr = ((ui16*)&this ->value ) + 3 ;
63
+ *ptr = (ui16)(*ptr & 0x800F | (value & exponentTruncate) << 4 );
64
+ }
65
+
66
+ int DoubleDecomposition::GetUnbiasedExponent ()
67
+ {
68
+ return (int )GetBiasedExponent () - DBL_EXPONENT_BIAS;
69
+ }
70
+
71
+ void DoubleDecomposition::SetUnbiasedExponent (int value)
72
+ {
73
+ if (value >= DBL_EXPONENT_MAX)
74
+ {
75
+ bool s = GetSign ();
76
+ value = 0 ;
77
+ SetSign (s);
78
+ SetBiasedExponent ((1 << DBL_EXPONENT_BITS) - 1 ); // infinity
79
+ return ;
80
+ }
81
+ if (value < DBL_EXPONENT_MIN) value = DBL_EXPONENT_MIN; // -1023 results in a subnormal
82
+ SetBiasedExponent ((ui16)(value + DBL_EXPONENT_BIAS));
83
+ }
84
+
85
+ void DoubleDecomposition::GetMantissa (byte* data, int byteCount)
86
+ {
87
+ if (byteCount < DBL_MANTISSA_BYTES) throw -1 ;
88
+ BitBlockTransfer (&value, 0 , data, byteCount * 8 - DBL_SIGNIFICANT_BITS, DBL_SIGNIFICANT_BITS); // place in H.O.
89
+ }
90
+
91
+ void DoubleDecomposition::SetMantissa (byte* data, int byteCount)
92
+ {
93
+ if (GetBiasedExponent () == DBL_EXPONENT_MASK)
94
+ {
95
+ // cannot set the mantissa while exponent represents infinity
96
+ // since it'd create an invalid value
97
+ return ;
98
+ }
99
+ int bitCount = byteCount * 8 ;
100
+ double * dptr = &value;
101
+ if (bitCount < DBL_SIGNIFICANT_BITS) ClearBlock ((byte*)dptr, 0 , DBL_SIGNIFICANT_BITS);
102
+ bool carry = false ;
103
+ if (bitCount > DBL_SIGNIFICANT_BITS) carry = ReadBit (data, bitCount - DBL_SIGNIFICANT_BITS - 1 );
104
+ // load highest order bits into highest order bits
105
+ if (!carry)
106
+ {
107
+ BitWindowTransfer (data, 0 , bitCount, bitCount, (byte*)dptr, 0 , DBL_SIGNIFICANT_BITS, DBL_SIGNIFICANT_BITS);
108
+ }
109
+ if (carry)
110
+ {
111
+ ui64 mantissaMask = ((ui64)1 << DBL_SIGNIFICANT_BITS) - 1 ;
112
+ ui64* ui64Ptr = (ui64*)dptr;
113
+ if ((*ui64Ptr & mantissaMask) == mantissaMask)
114
+ {
115
+ // we cannot simply increment because it'd overflow
116
+ // instead we clear all the bits and increment the exponent
117
+ *ui64Ptr &= ~mantissaMask;
118
+ SetBiasedExponent (GetBiasedExponent ()+1 ); // we know it's not ExponentMax already because we checked at the beginning of the func
119
+ }
120
+ else
121
+ {
122
+ // we can increment the whole ui64 without it overflowing to the exponent part
123
+ // but first we need to copy it in ^^
124
+ BitWindowTransfer (data, 0 , bitCount, bitCount, (byte*)dptr, 0 , DBL_SIGNIFICANT_BITS, DBL_SIGNIFICANT_BITS);
125
+ (*ui64Ptr)++;
126
+ }
127
+ }
128
+ }
129
+
130
+ #ifdef _MANAGED
131
+ #pragma unmanaged
132
+ #endif
0 commit comments