mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 17:37:47 +00:00
LibCrypto: Replace from_base{2,8,10,16}() & to_base10 with from_base(N)
This allows us to support parsing and serializing BigIntegers to and from any base N (such that 2 <= N <= 36).
This commit is contained in:
parent
a768131720
commit
005d75656e
14 changed files with 56 additions and 132 deletions
|
@ -27,57 +27,30 @@ size_t SignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) cons
|
|||
return m_unsigned_data.export_data(bytes_view, remove_leading_zeros) + 1;
|
||||
}
|
||||
|
||||
static bool parse_sign(StringView& str)
|
||||
SignedBigInteger SignedBigInteger::from_base(u16 N, StringView str)
|
||||
{
|
||||
bool sign = false;
|
||||
auto sign = false;
|
||||
if (str.length() > 1) {
|
||||
auto maybe_sign = str[0];
|
||||
if (maybe_sign == '-') {
|
||||
str = str.substring_view(1, str.length() - 1);
|
||||
str = str.substring_view(1);
|
||||
sign = true;
|
||||
}
|
||||
if (maybe_sign == '+')
|
||||
str = str.substring_view(1, str.length() - 1);
|
||||
str = str.substring_view(1);
|
||||
}
|
||||
return sign;
|
||||
}
|
||||
|
||||
SignedBigInteger SignedBigInteger::from_base10(StringView str)
|
||||
{
|
||||
auto sign = parse_sign(str);
|
||||
auto unsigned_data = UnsignedBigInteger::from_base10(str);
|
||||
auto unsigned_data = UnsignedBigInteger::from_base(N, str);
|
||||
return { move(unsigned_data), sign };
|
||||
}
|
||||
|
||||
SignedBigInteger SignedBigInteger::from_base2(StringView str)
|
||||
{
|
||||
auto sign = parse_sign(str);
|
||||
auto unsigned_data = UnsignedBigInteger::from_base2(str);
|
||||
return { move(unsigned_data), sign };
|
||||
}
|
||||
|
||||
SignedBigInteger SignedBigInteger::from_base8(StringView str)
|
||||
{
|
||||
auto sign = parse_sign(str);
|
||||
auto unsigned_data = UnsignedBigInteger::from_base8(str);
|
||||
return { move(unsigned_data), sign };
|
||||
}
|
||||
|
||||
SignedBigInteger SignedBigInteger::from_base16(StringView str)
|
||||
{
|
||||
auto sign = parse_sign(str);
|
||||
auto unsigned_data = UnsignedBigInteger::from_base16(str);
|
||||
return { move(unsigned_data), sign };
|
||||
}
|
||||
|
||||
String SignedBigInteger::to_base10() const
|
||||
String SignedBigInteger::to_base(u16 N) const
|
||||
{
|
||||
StringBuilder builder;
|
||||
|
||||
if (m_sign)
|
||||
builder.append('-');
|
||||
|
||||
builder.append(m_unsigned_data.to_base10());
|
||||
builder.append(m_unsigned_data.to_base(N));
|
||||
|
||||
return builder.to_string();
|
||||
}
|
||||
|
|
|
@ -62,11 +62,8 @@ public:
|
|||
|
||||
size_t export_data(Bytes, bool remove_leading_zeros = false) const;
|
||||
|
||||
static SignedBigInteger from_base2(StringView str);
|
||||
static SignedBigInteger from_base8(StringView str);
|
||||
static SignedBigInteger from_base10(StringView str);
|
||||
String to_base10() const;
|
||||
static SignedBigInteger from_base16(StringView str);
|
||||
static SignedBigInteger from_base(u16 N, StringView str);
|
||||
String to_base(u16 N) const;
|
||||
|
||||
u64 to_u64() const;
|
||||
|
||||
|
@ -144,5 +141,5 @@ struct SignedDivisionResult {
|
|||
inline Crypto::SignedBigInteger
|
||||
operator""_sbigint(const char* string, size_t length)
|
||||
{
|
||||
return Crypto::SignedBigInteger::from_base10({ string, length });
|
||||
return Crypto::SignedBigInteger::from_base(10, { string, length });
|
||||
}
|
||||
|
|
|
@ -66,60 +66,23 @@ size_t UnsignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) co
|
|||
return out;
|
||||
}
|
||||
|
||||
UnsignedBigInteger UnsignedBigInteger::from_base10(const String& str)
|
||||
UnsignedBigInteger UnsignedBigInteger::from_base(u16 N, const String& str)
|
||||
{
|
||||
VERIFY(N <= 36);
|
||||
UnsignedBigInteger result;
|
||||
UnsignedBigInteger ten { 10 };
|
||||
UnsignedBigInteger base { N };
|
||||
|
||||
for (auto& c : str) {
|
||||
if (c == '_')
|
||||
continue;
|
||||
result = result.multiplied_by(ten).plus(parse_ascii_digit(c));
|
||||
result = result.multiplied_by(base).plus(parse_ascii_base36_digit(c));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnsignedBigInteger UnsignedBigInteger::from_base2(const String& str)
|
||||
{
|
||||
UnsignedBigInteger result;
|
||||
UnsignedBigInteger two { 2 };
|
||||
|
||||
for (auto& c : str) {
|
||||
if (c == '_')
|
||||
continue;
|
||||
result = result.multiplied_by(two).plus(parse_ascii_digit(c));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnsignedBigInteger UnsignedBigInteger::from_base8(const String& str)
|
||||
{
|
||||
UnsignedBigInteger result;
|
||||
UnsignedBigInteger eight { 8 };
|
||||
|
||||
for (auto& c : str) {
|
||||
if (c == '_')
|
||||
continue;
|
||||
result = result.multiplied_by(eight).plus(parse_ascii_digit(c));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnsignedBigInteger UnsignedBigInteger::from_base16(const String& str)
|
||||
{
|
||||
UnsignedBigInteger result;
|
||||
UnsignedBigInteger sixteen { 16 };
|
||||
|
||||
for (auto& c : str) {
|
||||
if (c == '_')
|
||||
continue;
|
||||
result = result.multiplied_by(sixteen).plus(parse_ascii_hex_digit(c));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String UnsignedBigInteger::to_base10() const
|
||||
String UnsignedBigInteger::to_base(u16 N) const
|
||||
{
|
||||
VERIFY(N <= 36);
|
||||
if (*this == UnsignedBigInteger { 0 })
|
||||
return "0";
|
||||
|
||||
|
@ -129,19 +92,13 @@ String UnsignedBigInteger::to_base10() const
|
|||
UnsignedBigInteger remainder;
|
||||
|
||||
while (temp != UnsignedBigInteger { 0 }) {
|
||||
UnsignedBigIntegerAlgorithms::divide_u16_without_allocation(temp, 10, quotient, remainder);
|
||||
VERIFY(remainder.words()[0] < 10);
|
||||
builder.append(static_cast<char>(remainder.words()[0] + '0'));
|
||||
UnsignedBigIntegerAlgorithms::divide_u16_without_allocation(temp, N, quotient, remainder);
|
||||
VERIFY(remainder.words()[0] < N);
|
||||
builder.append(to_ascii_base36_digit(remainder.words()[0]));
|
||||
temp.set_to(quotient);
|
||||
}
|
||||
|
||||
auto reversed_string = builder.to_string();
|
||||
builder.clear();
|
||||
for (int i = reversed_string.length() - 1; i >= 0; --i) {
|
||||
builder.append(reversed_string[i]);
|
||||
}
|
||||
|
||||
return builder.to_string();
|
||||
return builder.to_string().reverse();
|
||||
}
|
||||
|
||||
u64 UnsignedBigInteger::to_u64() const
|
||||
|
|
|
@ -53,11 +53,8 @@ public:
|
|||
|
||||
size_t export_data(Bytes, bool remove_leading_zeros = false) const;
|
||||
|
||||
static UnsignedBigInteger from_base2(const String& str);
|
||||
static UnsignedBigInteger from_base8(const String& str);
|
||||
static UnsignedBigInteger from_base10(const String& str);
|
||||
String to_base10() const;
|
||||
static UnsignedBigInteger from_base16(const String& str);
|
||||
static UnsignedBigInteger from_base(u16 N, const String& str);
|
||||
String to_base(u16 N) const;
|
||||
|
||||
u64 to_u64() const;
|
||||
|
||||
|
@ -131,5 +128,5 @@ struct AK::Formatter<Crypto::UnsignedBigInteger> : Formatter<StringView> {
|
|||
inline Crypto::UnsignedBigInteger
|
||||
operator""_bigint(const char* string, size_t length)
|
||||
{
|
||||
return Crypto::UnsignedBigInteger::from_base10({ string, length });
|
||||
return Crypto::UnsignedBigInteger::from_base(10, { string, length });
|
||||
}
|
||||
|
|
|
@ -218,7 +218,7 @@ bool is_probably_prime(const UnsignedBigInteger& p)
|
|||
UnsignedBigInteger random_big_prime(size_t bits)
|
||||
{
|
||||
VERIFY(bits >= 33);
|
||||
UnsignedBigInteger min = UnsignedBigInteger::from_base10("6074001000").shift_left(bits - 33);
|
||||
UnsignedBigInteger min = UnsignedBigInteger::from_base(10, "6074001000").shift_left(bits - 33);
|
||||
UnsignedBigInteger max = UnsignedBigInteger { 1 }.shift_left(bits).minus(1);
|
||||
for (;;) {
|
||||
auto p = random_number(min, max);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue