mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 12:23:15 +00:00
AK: Replace linear exponentiation by binary in MinimalBigInt
This further optimizes floating point parsing (specifically with a large amount of digits). The commit shaves additional 20% of the run time for 750-digit numbers. No performance degradation is noticeable for small numbers.
This commit is contained in:
parent
80517b5a70
commit
4653b38808
|
@ -1529,50 +1529,131 @@ public:
|
||||||
|
|
||||||
void multiply_with_power_of_5(u32 exponent)
|
void multiply_with_power_of_5(u32 exponent)
|
||||||
{
|
{
|
||||||
// FIXME: We might be able to store a bigger power of 5 but this would
|
// FIXME: Using UFixedBigInt here does not feel right. We need to nicely (without
|
||||||
// require a wide multiply, so perhaps using u4096 would be
|
// reinterpret_cast and ifs) convert u64 to NativeWord (if NativeWord == u32)
|
||||||
// better to get wide multiply and not duplicate logic.
|
// and one of UFixedBigInt constructors happens to do this exact job.
|
||||||
static constexpr Array<u64, 28> power_of_5 = {
|
//
|
||||||
1ul,
|
// To calculate this lookup table, we compute 5 ** (2 ** i) for all i \in [0; 10], split
|
||||||
5ul,
|
// numbers into 64-bit words and concatenate the results, writing corresponding sizes to
|
||||||
25ul,
|
// `sizes` array in `power_of_5` lambda.
|
||||||
125ul,
|
static constexpr UFixedBigInt<82 * 64> power_of_5_coefficients = { {
|
||||||
625ul,
|
5ull,
|
||||||
3125ul,
|
25ull,
|
||||||
15625ul,
|
625ull,
|
||||||
78125ul,
|
390625ull,
|
||||||
390625ul,
|
152587890625ull,
|
||||||
1953125ul,
|
3273344365508751233ull,
|
||||||
9765625ul,
|
1262ull,
|
||||||
48828125ul,
|
7942358959831785217ull,
|
||||||
244140625ul,
|
16807427164405733357ull,
|
||||||
1220703125ul,
|
1593091ull,
|
||||||
6103515625ul,
|
279109966635548161ull,
|
||||||
30517578125ul,
|
2554917779393558781ull,
|
||||||
152587890625ul,
|
14124656261812188652ull,
|
||||||
762939453125ul,
|
11976055582626787546ull,
|
||||||
3814697265625ul,
|
2537941837315ull,
|
||||||
19073486328125ul,
|
13750482914757213185ull,
|
||||||
95367431640625ul,
|
1302999927698857842ull,
|
||||||
476837158203125ul,
|
14936872543252795590ull,
|
||||||
2384185791015625ul,
|
2788415840139466767ull,
|
||||||
11920928955078125ul,
|
2095640732773017264ull,
|
||||||
59604644775390625ul,
|
7205570348933370714ull,
|
||||||
298023223876953125ul,
|
7348167152523113408ull,
|
||||||
1490116119384765625ul,
|
9285516396840364274ull,
|
||||||
7450580596923828125ul,
|
6907659600622710236ull,
|
||||||
};
|
349175ull,
|
||||||
|
8643096425819600897ull,
|
||||||
|
6743743997439985372ull,
|
||||||
|
14059704609098336919ull,
|
||||||
|
10729359125898331411ull,
|
||||||
|
4933048501514368705ull,
|
||||||
|
12258131603170554683ull,
|
||||||
|
2172371001088594721ull,
|
||||||
|
13569903330219142946ull,
|
||||||
|
13809142207969578845ull,
|
||||||
|
16716360519037769646ull,
|
||||||
|
9631256923806107285ull,
|
||||||
|
12866941232305103710ull,
|
||||||
|
1397931361048440292ull,
|
||||||
|
7619627737732970332ull,
|
||||||
|
12725409486282665900ull,
|
||||||
|
11703051443360963910ull,
|
||||||
|
9947078370803086083ull,
|
||||||
|
13966287901448440471ull,
|
||||||
|
121923442132ull,
|
||||||
|
17679772531488845825ull,
|
||||||
|
2216509366347768155ull,
|
||||||
|
1568689219195129479ull,
|
||||||
|
5511594616325588277ull,
|
||||||
|
1067709417009240089ull,
|
||||||
|
9070650952098657518ull,
|
||||||
|
11515285870634858015ull,
|
||||||
|
2539561553659505564ull,
|
||||||
|
17604889300961091799ull,
|
||||||
|
14511540856854204724ull,
|
||||||
|
12099083339557485471ull,
|
||||||
|
7115240299237943815ull,
|
||||||
|
313979240050606788ull,
|
||||||
|
10004784664717172195ull,
|
||||||
|
15570268847930131473ull,
|
||||||
|
10359715202835930803ull,
|
||||||
|
17685054012115162812ull,
|
||||||
|
13183273382855797757ull,
|
||||||
|
7743260039872919062ull,
|
||||||
|
9284593436392572926ull,
|
||||||
|
11105921222066415013ull,
|
||||||
|
18198799323400703846ull,
|
||||||
|
16314988383739458320ull,
|
||||||
|
4387527177871570570ull,
|
||||||
|
8476708682254672590ull,
|
||||||
|
4925096874831034057ull,
|
||||||
|
14075687868072027455ull,
|
||||||
|
112866656203221926ull,
|
||||||
|
9852830467773230418ull,
|
||||||
|
25755239915196746ull,
|
||||||
|
2201493076310172510ull,
|
||||||
|
8342165458688466438ull,
|
||||||
|
13954006576066379050ull,
|
||||||
|
15193819059903295636ull,
|
||||||
|
12565616718911389531ull,
|
||||||
|
3815854855847885129ull,
|
||||||
|
15696762163583540628ull,
|
||||||
|
805ull,
|
||||||
|
} };
|
||||||
|
|
||||||
static constexpr u32 max_step = power_of_5.size() - 1;
|
// power_of_5[i] = 5 ** (2 ** i)
|
||||||
static constexpr u64 max_power = power_of_5[max_step];
|
static constexpr auto power_of_5 = [&] {
|
||||||
|
constexpr size_t powers_count = 11;
|
||||||
|
|
||||||
while (exponent >= max_step) {
|
Array<UnsignedStorageReadonlySpan, powers_count> result;
|
||||||
multiply_with_small(max_power);
|
Array<size_t, powers_count> sizes = { 1, 1, 1, 1, 1, 2, 3, 5, 10, 19, 38 };
|
||||||
exponent -= max_step;
|
|
||||||
|
size_t offset = 0;
|
||||||
|
for (size_t i = 0; i < powers_count; ++i) {
|
||||||
|
if constexpr (SameAs<NativeWord, u32>)
|
||||||
|
sizes[i] *= 2;
|
||||||
|
result[i] = UnsignedStorageReadonlySpan(power_of_5_coefficients.span().slice(offset, sizes[i]));
|
||||||
|
offset += sizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exponent > 0)
|
return result;
|
||||||
multiply_with_small(power_of_5[exponent]);
|
}();
|
||||||
|
|
||||||
|
VERIFY(exponent < (1 << power_of_5.size()));
|
||||||
|
|
||||||
|
// Binary exponentiation
|
||||||
|
for (size_t i = 0; i < power_of_5.size(); ++i) {
|
||||||
|
if (exponent >> i & 1) {
|
||||||
|
if (power_of_5[i].size() == 1) {
|
||||||
|
multiply_with_small(power_of_5[i][0]);
|
||||||
|
} else {
|
||||||
|
auto copy = *this;
|
||||||
|
StorageOperations::baseline_mul(copy.get_storage(), power_of_5[i],
|
||||||
|
get_storage(m_used_length + power_of_5[i].size()), g_null_allocator);
|
||||||
|
trim_last_word_if_zero();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void multiply_with_power_of_2(u32 exponent)
|
void multiply_with_power_of_2(u32 exponent)
|
||||||
|
|
Loading…
Reference in a new issue