mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 23:37:36 +00:00
LibCrypto: Add UnsignedBigInteger subtraction and comparison
This commit is contained in:
parent
6201f741d4
commit
e0cf40518c
3 changed files with 138 additions and 8 deletions
|
@ -64,11 +64,47 @@ UnsignedBigInteger UnsignedBigInteger::add(const UnsignedBigInteger& other)
|
|||
return result;
|
||||
}
|
||||
|
||||
UnsignedBigInteger UnsignedBigInteger::sub(const UnsignedBigInteger& other)
|
||||
{
|
||||
UnsignedBigInteger result;
|
||||
|
||||
if (*this < other) {
|
||||
dbg() << "WARNING: bigint subtraction creates a negative number!";
|
||||
return UnsignedBigInteger::create_invalid();
|
||||
}
|
||||
|
||||
u8 borrow = 0;
|
||||
for (size_t i = 0; i < other.length(); ++i) {
|
||||
ASSERT(!(borrow == 1 && m_words[i] == 0));
|
||||
|
||||
if (m_words[i] - borrow < other.m_words[i]) {
|
||||
u64 after_borrow = static_cast<u64>(m_words[i] - borrow) + (UINT32_MAX + 1);
|
||||
result.m_words.append(static_cast<u32>(after_borrow - static_cast<u64>(other.m_words[i])));
|
||||
borrow = 1;
|
||||
} else {
|
||||
result.m_words.append(m_words[i] - borrow - other.m_words[i]);
|
||||
borrow = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = other.length(); i < length(); ++i) {
|
||||
ASSERT(!(borrow == 1 && m_words[i] == 0));
|
||||
result.m_words.append(m_words[i] - borrow);
|
||||
borrow = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool UnsignedBigInteger::operator==(const UnsignedBigInteger& other) const
|
||||
{
|
||||
if (trimmed_length() != other.trimmed_length()) {
|
||||
return false;
|
||||
}
|
||||
if (is_invalid() != other.is_invalid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < trimmed_length(); ++i) {
|
||||
if (m_words[i] != other.words()[i])
|
||||
return false;
|
||||
|
@ -76,6 +112,23 @@ bool UnsignedBigInteger::operator==(const UnsignedBigInteger& other) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool UnsignedBigInteger::operator<(const UnsignedBigInteger& other) const
|
||||
{
|
||||
if (trimmed_length() < other.trimmed_length()) {
|
||||
return true;
|
||||
}
|
||||
if (trimmed_length() > other.trimmed_length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length = trimmed_length();
|
||||
if (length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_words[length - 1] < other.m_words[length - 1];
|
||||
}
|
||||
|
||||
size_t UnsignedBigInteger::trimmed_length() const
|
||||
{
|
||||
size_t num_leading_zeroes = 0;
|
||||
|
@ -86,4 +139,11 @@ size_t UnsignedBigInteger::trimmed_length() const
|
|||
return length() - num_leading_zeroes;
|
||||
}
|
||||
|
||||
UnsignedBigInteger UnsignedBigInteger::create_invalid()
|
||||
{
|
||||
UnsignedBigInteger invalid(0);
|
||||
invalid.invalidate();
|
||||
return invalid;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,9 +35,12 @@ public:
|
|||
UnsignedBigInteger(u32 x) { m_words.append(x); }
|
||||
UnsignedBigInteger() {}
|
||||
|
||||
static UnsignedBigInteger create_invalid();
|
||||
|
||||
const AK::Vector<u32>& words() const { return m_words; }
|
||||
|
||||
UnsignedBigInteger add(const UnsignedBigInteger& other);
|
||||
UnsignedBigInteger sub(const UnsignedBigInteger& other);
|
||||
|
||||
size_t length() const { return m_words.size(); }
|
||||
|
||||
|
@ -45,15 +48,26 @@ public:
|
|||
size_t trimmed_length() const;
|
||||
|
||||
bool operator==(const UnsignedBigInteger& other) const;
|
||||
bool operator<(const UnsignedBigInteger& other) const;
|
||||
|
||||
void invalidate() { m_is_invalid = true; }
|
||||
bool is_invalid() const { return m_is_invalid; }
|
||||
|
||||
private:
|
||||
AK::Vector<u32> m_words;
|
||||
|
||||
// Used to indicate a negative result, or a result of an invalid operation
|
||||
bool m_is_invalid { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
inline const LogStream& operator<<(const LogStream& stream, const Crypto::UnsignedBigInteger value)
|
||||
{
|
||||
if (value.is_invalid()) {
|
||||
stream << "Invalid BigInt";
|
||||
return stream;
|
||||
}
|
||||
for (int i = value.length() - 1; i >= 0; --i) {
|
||||
stream << value.words()[i] << "|";
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue