1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:17:44 +00:00

LibCrypto: Add bitwise operations (and/or/xor)

This commit is contained in:
AnotherTest 2020-06-06 01:36:03 +04:30 committed by Andreas Kling
parent fbb1d9afe5
commit 02c53fd1f9
5 changed files with 333 additions and 0 deletions

View file

@ -158,6 +158,42 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::minus(const UnsignedBigInteger& o
return result;
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_or(const UnsignedBigInteger& other) const
{
UnsignedBigInteger result;
bitwise_or_without_allocation(*this, other, result);
return result;
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_and(const UnsignedBigInteger& other) const
{
UnsignedBigInteger result;
bitwise_and_without_allocation(*this, other, result);
return result;
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_xor(const UnsignedBigInteger& other) const
{
UnsignedBigInteger result;
bitwise_xor_without_allocation(*this, other, result);
return result;
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_not() const
{
UnsignedBigInteger result;
bitwise_not_without_allocation(*this, result);
return result;
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const
{
UnsignedBigInteger output;
@ -340,6 +376,153 @@ void UnsignedBigInteger::subtract_without_allocation(
ASSERT(borrow == 0);
}
/**
* Complexity: O(N) where N is the number of words in the shorter value
* Method:
* Apply <op> word-wise until words in the shorter value are used up
* then copy the rest of the words verbatim from the longer value.
*/
FLATTEN void UnsignedBigInteger::bitwise_or_without_allocation(
const UnsignedBigInteger& left,
const UnsignedBigInteger& right,
UnsignedBigInteger& output)
{
// If either of the BigInts are invalid, the output is just the other one.
if (left.is_invalid()) {
output.set_to(right);
return;
}
if (right.is_invalid()) {
output.set_to(left);
return;
}
const UnsignedBigInteger *shorter, *longer;
if (left.length() < right.length()) {
shorter = &left;
longer = &right;
} else {
shorter = &right;
longer = &left;
}
output.m_words.resize_and_keep_capacity(longer->length());
size_t longer_offset = longer->length() - shorter->length();
for (size_t i = 0; i < shorter->length(); ++i)
output.m_words[i] = longer->words()[i] | shorter->words()[i];
__builtin_memcpy(output.m_words.data() + shorter->length(), longer->words().data() + shorter->length(), sizeof(u32) * longer_offset);
}
/**
* Complexity: O(N) where N is the number of words in the shorter value
* Method:
* Apply 'and' word-wise until words in the shorter value are used up
* and zero the rest.
*/
FLATTEN void UnsignedBigInteger::bitwise_and_without_allocation(
const UnsignedBigInteger& left,
const UnsignedBigInteger& right,
UnsignedBigInteger& output)
{
// If either of the BigInts are invalid, the output is just the other one.
if (left.is_invalid()) {
output.set_to(right);
return;
}
if (right.is_invalid()) {
output.set_to(left);
return;
}
const UnsignedBigInteger *shorter, *longer;
if (left.length() < right.length()) {
shorter = &left;
longer = &right;
} else {
shorter = &right;
longer = &left;
}
output.m_words.resize_and_keep_capacity(longer->length());
size_t longer_offset = longer->length() - shorter->length();
for (size_t i = 0; i < shorter->length(); ++i)
output.m_words[i] = longer->words()[i] & shorter->words()[i];
__builtin_memset(output.m_words.data() + shorter->length(), 0, sizeof(u32) * longer_offset);
}
/**
* Complexity: O(N) where N is the number of words in the shorter value
* Method:
* Apply 'xor' word-wise until words in the shorter value are used up
* and copy the rest.
*/
FLATTEN void UnsignedBigInteger::bitwise_xor_without_allocation(
const UnsignedBigInteger& left,
const UnsignedBigInteger& right,
UnsignedBigInteger& output)
{
// If either of the BigInts are invalid, the output is just the other one.
if (left.is_invalid()) {
output.set_to(right);
return;
}
if (right.is_invalid()) {
output.set_to(left);
return;
}
const UnsignedBigInteger *shorter, *longer;
if (left.length() < right.length()) {
shorter = &left;
longer = &right;
} else {
shorter = &right;
longer = &left;
}
output.m_words.resize_and_keep_capacity(longer->length());
size_t longer_offset = longer->length() - shorter->length();
for (size_t i = 0; i < shorter->length(); ++i)
output.m_words[i] = longer->words()[i] ^ shorter->words()[i];
__builtin_memcpy(output.m_words.data() + shorter->length(), longer->words().data() + shorter->length(), sizeof(u32) * longer_offset);
}
/**
* Complexity: O(N) where N is the number of words
*/
FLATTEN void UnsignedBigInteger::bitwise_not_without_allocation(
const UnsignedBigInteger& right,
UnsignedBigInteger& output)
{
// If the value is invalid, the output value is invalid as well.
if (right.is_invalid()) {
output.invalidate();
return;
}
if (right.length() == 0) {
output.set_to_0();
return;
}
output.m_words.resize_and_keep_capacity(right.length());
if (right.length() > 1) {
for (size_t i = 0; i < right.length() - 1; ++i)
output.m_words[i] = ~right.words()[i];
}
auto last_word_index = right.length() - 1;
auto last_word = right.words()[last_word_index];
output.m_words[last_word_index] = ((u32)0xffffffffffffffff >> __builtin_clz(last_word)) & ~last_word;
}
/**
* Complexity : O(N + num_bits % 8) where N is the number of words in the number
* Shift method :