AK: Delete unused and untested sqrt, pow and pow_mod from UFixedBigInt

This commit is contained in:
Dan Klishch 2022-11-22 01:25:47 +03:00 committed by Andrew Kaster
parent 8f8e31e780
commit 2470fab05e
Notes: sideshowbarker 2024-07-16 23:27:19 +09:00
2 changed files with 2 additions and 133 deletions

View File

@ -475,130 +475,8 @@ public:
return *this;
}
constexpr R sqrt() const
{
// Bitwise method: https://en.wikipedia.org/wiki/Integer_square_root#Using_bitwise_operations
// the bitwise method seems to be way faster then Newtons:
// https://quick-bench.com/q/eXZwW1DVhZxLE0llumeCXkfOK3Q
if (*this == 1u)
return 1u;
ssize_t shift = (sizeof(R) * 8 - clz()) & ~1ULL;
// should be equivalent to:
// long shift = 2;
// while ((val >> shift) != 0)
// shift += 2;
R res = 0u;
while (shift >= 0) {
res = res << 1u;
R large_cand = (res | 1u);
if (*this >> (size_t)shift >= large_cand * large_cand)
res = large_cand;
shift -= 2;
}
return res;
}
constexpr R pow(u64 exp)
{
// Montgomery's Ladder Technique
// https://en.wikipedia.org/wiki/Exponentiation_by_squaring#Montgomery's_ladder_technique
R x1 = *this;
R x2 = *this * *this;
u64 exp_copy = exp;
for (ssize_t i = sizeof(u64) * 8 - count_leading_zeroes(exp) - 2; i >= 0; --i) {
if (exp_copy & 1u) {
x2 *= x1;
x1 *= x1;
} else {
x1 *= x2;
x2 *= x2;
}
exp_copy >>= 1u;
}
return x1;
}
template<Unsigned U>
requires(sizeof(U) > sizeof(u64)) constexpr R pow(U exp)
{
// Montgomery's Ladder Technique
// https://en.wikipedia.org/wiki/Exponentiation_by_squaring#Montgomery's_ladder_technique
R x1 = *this;
R x2 = *this * *this;
U exp_copy = exp;
for (ssize_t i = sizeof(U) * 8 - exp().clz() - 2; i >= 0; --i) {
if (exp_copy & 1u) {
x2 *= x1;
x1 *= x1;
} else {
x1 *= x2;
x2 *= x2;
}
exp_copy >>= 1u;
}
return x1;
}
template<Unsigned U>
constexpr U pow_mod(u64 exp, U mod)
{
// Left to right binary method:
// https://en.wikipedia.org/wiki/Modular_exponentiation#Left-to-right_binary_method
// FIXME: this is not sidechanel proof
if (!mod)
return 0u;
U res = 1;
u64 exp_copy = exp;
for (size_t i = sizeof(u64) - count_leading_zeroes(exp) - 1u; i < exp; ++i) {
res *= res;
res %= mod;
if (exp_copy & 1u) {
res = (*this * res) % mod;
}
exp_copy >>= 1u;
}
return res;
}
template<Unsigned ExpT, Unsigned U>
requires(sizeof(ExpT) > sizeof(u64)) constexpr U pow_mod(ExpT exp, U mod)
{
// Left to right binary method:
// https://en.wikipedia.org/wiki/Modular_exponentiation#Left-to-right_binary_method
// FIXME: this is not side channel proof
if (!mod)
return 0u;
U res = 1;
ExpT exp_copy = exp;
for (size_t i = sizeof(ExpT) - exp.clz() - 1u; i < exp; ++i) {
res *= res;
res %= mod;
if (exp_copy & 1u) {
res = (*this * res) % mod;
}
exp_copy >>= 1u;
}
return res;
}
constexpr size_t log2()
{
// FIXME: proper rounding
return sizeof(R) - clz();
}
constexpr size_t logn(u64 base)
{
// FIXME: proper rounding
return log2() / (sizeof(u64) - count_leading_zeroes(base));
}
template<Unsigned U>
requires(sizeof(U) > sizeof(u64)) constexpr size_t logn(U base)
{
// FIXME: proper rounding
return log2() / base.log2();
}
// Note: If there ever be need for non side-channel proof sqrt/pow/pow_mod of UFixedBigInt, you
// can restore them from Git history.
#undef DEFINE_STANDARD_BINARY_OPERATOR
#undef DEFINE_STANDARD_COMPOUND_ASSIGNMENT

View File

@ -39,15 +39,6 @@ TEST_CASE(identities)
}
}
TEST_CASE(sqrt)
{
srand(0);
for (int i = 0; i < test_iterations; ++i) {
u256 x = get_random<u128>();
EXPECT_EQ((x * x).sqrt(), x);
}
}
TEST_CASE(add_overflow_propagation)
{
u256 a = NumericLimits<u128>::max();