[llvm] [APFloat] Fix literals with long significands. (PR #102051)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 3 14:22:23 PDT 2024
================
@@ -761,27 +745,45 @@ ulpsFromBoundary(const APFloatBase::integerPart *parts, unsigned int bits,
return ~(APFloatBase::integerPart) 0; /* A lot. */
}
-/* Place pow(5, power) in DST, and return the number of parts used.
- DST must be at least one part larger than size of the answer. */
-static unsigned int
-powerOf5(APFloatBase::integerPart *dst, unsigned int power) {
+/* Calculate and return pow(5, power). */
+static SmallVector<APFloatBase::integerPart, 0> powerOf5(unsigned int power) {
static const APFloatBase::integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, 15625, 78125 };
- APFloatBase::integerPart pow5s[maxPowerOfFiveParts * 2 + 5];
+
+ // Make sure that the following expression does not overflow.
+ assert(power <= UINT_MAX / 815);
+
+ // A tight upper bound on number of parts required to hold the value
+ // pow(5, power) is
+ //
+ // power * 815 / (351 * integerPartWidth) + 1
+ //
+ // However, whilst the result may require only this many parts,
+ // because we are multiplying two values to get it, the
+ // multiplication may require an extra part with the excess part
+ // being zero (consider the trivial case of 1 * 1, tcFullMultiply
+ // requires two parts to hold the single-part result). So we add an
+ // extra one to guarantee enough space whilst multiplying.
+ const unsigned int maxPowerOfFiveParts =
+ 2 + ((power * 815) / (351 * APFloatBase::integerPartWidth));
+
+ SmallVector<APFloatBase::integerPart, 0> pow5s(maxPowerOfFiveParts * 2 + 5);
----------------
keinflue wrote:
The actual minimum size required (see lines above) is `9` and I think `SmallVector`'s default is smaller. It increases with both the length of the significand of the floating point literal as well as its exponent. I used `0` because I have no idea what a good estimation for typical floating point literals is. The old code used a fixed size array of roughly length 1200. I could of course use that, but felt that it was a bit much waste of stack space for the typical use case. All in all the arrays took roughly 14kB stack.
https://github.com/llvm/llvm-project/pull/102051
More information about the llvm-commits
mailing list