1 //==- lib/Support/ScaledNumber.cpp - Support for scaled numbers -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Implementation of some scaled number algorithms.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Support/ScaledNumber.h"
15 #include "llvm/ADT/APFloat.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/raw_ostream.h"
21 using namespace llvm::ScaledNumbers
;
23 std::pair
<uint64_t, int16_t> ScaledNumbers::multiply64(uint64_t LHS
,
25 // Separate into two 32-bit digits (U.L).
26 auto getU
= [](uint64_t N
) { return N
>> 32; };
27 auto getL
= [](uint64_t N
) { return N
& UINT32_MAX
; };
28 uint64_t UL
= getU(LHS
), LL
= getL(LHS
), UR
= getU(RHS
), LR
= getL(RHS
);
30 // Compute cross products.
31 uint64_t P1
= UL
* UR
, P2
= UL
* LR
, P3
= LL
* UR
, P4
= LL
* LR
;
33 // Sum into two 64-bit digits.
34 uint64_t Upper
= P1
, Lower
= P4
;
35 auto addWithCarry
= [&](uint64_t N
) {
36 uint64_t NewLower
= Lower
+ (getL(N
) << 32);
37 Upper
+= getU(N
) + (NewLower
< Lower
);
43 // Check whether the upper digit is empty.
45 return std::make_pair(Lower
, 0);
47 // Shift as little as possible to maximize precision.
48 unsigned LeadingZeros
= countLeadingZeros(Upper
);
49 int Shift
= 64 - LeadingZeros
;
51 Upper
= Upper
<< LeadingZeros
| Lower
>> Shift
;
52 return getRounded(Upper
, Shift
,
53 Shift
&& (Lower
& UINT64_C(1) << (Shift
- 1)));
56 static uint64_t getHalf(uint64_t N
) { return (N
>> 1) + (N
& 1); }
58 std::pair
<uint32_t, int16_t> ScaledNumbers::divide32(uint32_t Dividend
,
60 assert(Dividend
&& "expected non-zero dividend");
61 assert(Divisor
&& "expected non-zero divisor");
63 // Use 64-bit math and canonicalize the dividend to gain precision.
64 uint64_t Dividend64
= Dividend
;
66 if (int Zeros
= countLeadingZeros(Dividend64
)) {
70 uint64_t Quotient
= Dividend64
/ Divisor
;
71 uint64_t Remainder
= Dividend64
% Divisor
;
73 // If Quotient needs to be shifted, leave the rounding to getAdjusted().
74 if (Quotient
> UINT32_MAX
)
75 return getAdjusted
<uint32_t>(Quotient
, Shift
);
77 // Round based on the value of the next bit.
78 return getRounded
<uint32_t>(Quotient
, Shift
, Remainder
>= getHalf(Divisor
));
81 std::pair
<uint64_t, int16_t> ScaledNumbers::divide64(uint64_t Dividend
,
83 assert(Dividend
&& "expected non-zero dividend");
84 assert(Divisor
&& "expected non-zero divisor");
86 // Minimize size of divisor.
88 if (int Zeros
= countTrailingZeros(Divisor
)) {
93 // Check for powers of two.
95 return std::make_pair(Dividend
, Shift
);
97 // Maximize size of dividend.
98 if (int Zeros
= countLeadingZeros(Dividend
)) {
103 // Start with the result of a divide.
104 uint64_t Quotient
= Dividend
/ Divisor
;
107 // Continue building the quotient with long division.
108 while (!(Quotient
>> 63) && Dividend
) {
109 // Shift Dividend and check for overflow.
110 bool IsOverflow
= Dividend
>> 63;
114 // Get the next bit of Quotient.
116 if (IsOverflow
|| Divisor
<= Dividend
) {
122 return getRounded(Quotient
, Shift
, Dividend
>= getHalf(Divisor
));
125 int ScaledNumbers::compareImpl(uint64_t L
, uint64_t R
, int ScaleDiff
) {
126 assert(ScaleDiff
>= 0 && "wrong argument order");
127 assert(ScaleDiff
< 64 && "numbers too far apart");
129 uint64_t L_adjusted
= L
>> ScaleDiff
;
135 return L
> L_adjusted
<< ScaleDiff
? 1 : 0;
138 static void appendDigit(std::string
&Str
, unsigned D
) {
143 static void appendNumber(std::string
&Str
, uint64_t N
) {
145 appendDigit(Str
, N
% 10);
150 static bool doesRoundUp(char Digit
) {
163 static std::string
toStringAPFloat(uint64_t D
, int E
, unsigned Precision
) {
164 assert(E
>= ScaledNumbers::MinScale
);
165 assert(E
<= ScaledNumbers::MaxScale
);
167 // Find a new E, but don't let it increase past MaxScale.
168 int LeadingZeros
= ScaledNumberBase::countLeadingZeros64(D
);
169 int NewE
= std::min(ScaledNumbers::MaxScale
, E
+ 63 - LeadingZeros
);
170 int Shift
= 63 - (NewE
- E
);
171 assert(Shift
<= LeadingZeros
);
172 assert(Shift
== LeadingZeros
|| NewE
== ScaledNumbers::MaxScale
);
173 assert(Shift
>= 0 && Shift
< 64 && "undefined behavior");
177 // Check for a denormal.
178 unsigned AdjustedE
= E
+ 16383;
180 assert(E
== ScaledNumbers::MaxScale
);
184 // Build the float and print it.
185 uint64_t RawBits
[2] = {D
, AdjustedE
};
186 APFloat
Float(APFloat::x87DoubleExtended(), APInt(80, RawBits
));
187 SmallVector
<char, 24> Chars
;
188 Float
.toString(Chars
, Precision
, 0);
189 return std::string(Chars
.begin(), Chars
.end());
192 static std::string
stripTrailingZeros(const std::string
&Float
) {
193 size_t NonZero
= Float
.find_last_not_of('0');
194 assert(NonZero
!= std::string::npos
&& "no . in floating point string");
196 if (Float
[NonZero
] == '.')
199 return Float
.substr(0, NonZero
+ 1);
202 std::string
ScaledNumberBase::toString(uint64_t D
, int16_t E
, int Width
,
203 unsigned Precision
) {
207 // Canonicalize exponent and digits.
215 if (int Shift
= std::min(int16_t(countLeadingZeros64(D
)), E
)) {
222 } else if (E
> -64) {
224 Below0
= D
<< (64 + E
);
225 } else if (E
== -64) {
226 // Special case: shift by 64 bits is undefined behavior.
228 } else if (E
> -120) {
229 Below0
= D
>> (-E
- 64);
230 Extra
= D
<< (128 + E
);
231 ExtraShift
= -64 - E
;
234 // Fall back on APFloat for very small and very large numbers.
235 if (!Above0
&& !Below0
)
236 return toStringAPFloat(D
, E
, Precision
);
238 // Append the digits before the decimal.
240 size_t DigitsOut
= 0;
242 appendNumber(Str
, Above0
);
243 DigitsOut
= Str
.size();
246 std::reverse(Str
.begin(), Str
.end());
248 // Return early if there's nothing after the decimal.
252 // Append the decimal and beyond.
254 uint64_t Error
= UINT64_C(1) << (64 - Width
);
256 // We need to shift Below0 to the right to make space for calculating
257 // digits. Save the precision we're losing in Extra.
258 Extra
= (Below0
& 0xf) << 56 | (Extra
>> 8);
261 size_t AfterDot
= Str
.size();
271 Below0
+= (Extra
>> 60);
272 Extra
= Extra
& (UINT64_MAX
>> 4);
273 appendDigit(Str
, Below0
>> 60);
274 Below0
= Below0
& (UINT64_MAX
>> 4);
275 if (DigitsOut
|| Str
.back() != '0')
278 } while (Error
&& (Below0
<< 4 | Extra
>> 60) >= Error
/ 2 &&
279 (!Precision
|| DigitsOut
<= Precision
|| SinceDot
< 2));
281 // Return early for maximum precision.
282 if (!Precision
|| DigitsOut
<= Precision
)
283 return stripTrailingZeros(Str
);
285 // Find where to truncate.
287 std::max(Str
.size() - (DigitsOut
- Precision
), AfterDot
+ 1);
289 // Check if there's anything to truncate.
290 if (Truncate
>= Str
.size())
291 return stripTrailingZeros(Str
);
293 bool Carry
= doesRoundUp(Str
[Truncate
]);
295 return stripTrailingZeros(Str
.substr(0, Truncate
));
297 // Round with the first truncated digit.
298 for (std::string::reverse_iterator
I(Str
.begin() + Truncate
), E
= Str
.rend();
312 // Add "1" in front if we still need to carry.
313 return stripTrailingZeros(std::string(Carry
, '1') + Str
.substr(0, Truncate
));
316 raw_ostream
&ScaledNumberBase::print(raw_ostream
&OS
, uint64_t D
, int16_t E
,
317 int Width
, unsigned Precision
) {
318 return OS
<< toString(D
, E
, Width
, Precision
);
321 void ScaledNumberBase::dump(uint64_t D
, int16_t E
, int Width
) {
322 print(dbgs(), D
, E
, Width
, 0) << "[" << Width
<< ":" << D
<< "*2^" << E