mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 02:57:44 +00:00
LibCrypto: Add bitwise operations (and/or/xor)
This commit is contained in:
parent
fbb1d9afe5
commit
02c53fd1f9
5 changed files with 333 additions and 0 deletions
|
@ -139,6 +139,57 @@ FLATTEN SignedBigInteger SignedBigInteger::minus(const UnsignedBigInteger& other
|
|||
return { other.minus(m_unsigned_data), true };
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(const UnsignedBigInteger& other) const
|
||||
{
|
||||
return { unsigned_value().bitwise_or(other), m_sign };
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(const UnsignedBigInteger& other) const
|
||||
{
|
||||
return { unsigned_value().bitwise_and(other), false };
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(const UnsignedBigInteger& other) const
|
||||
{
|
||||
return { unsigned_value().bitwise_xor(other), m_sign };
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_not() const
|
||||
{
|
||||
return { unsigned_value().bitwise_not(), !m_sign };
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(const SignedBigInteger& other) const
|
||||
{
|
||||
auto result = bitwise_or(other.unsigned_value());
|
||||
|
||||
// The sign bit will have to be OR'd manually.
|
||||
if (other.is_negative())
|
||||
result.negate();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_and(const SignedBigInteger& other) const
|
||||
{
|
||||
auto result = bitwise_and(other.unsigned_value());
|
||||
|
||||
// The sign bit will have to be AND'd manually.
|
||||
result.m_sign = is_negative() || other.is_negative();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(const SignedBigInteger& other) const
|
||||
{
|
||||
auto result = bitwise_xor(other.unsigned_value());
|
||||
|
||||
// The sign bit will have to be XOR'd manually.
|
||||
result.m_sign = is_negative() ^ other.is_negative();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SignedBigInteger::operator==(const UnsignedBigInteger& other) const
|
||||
{
|
||||
if (m_sign)
|
||||
|
|
|
@ -107,12 +107,19 @@ public:
|
|||
|
||||
SignedBigInteger plus(const SignedBigInteger& other) const;
|
||||
SignedBigInteger minus(const SignedBigInteger& other) const;
|
||||
SignedBigInteger bitwise_or(const SignedBigInteger& other) const;
|
||||
SignedBigInteger bitwise_and(const SignedBigInteger& other) const;
|
||||
SignedBigInteger bitwise_xor(const SignedBigInteger& other) const;
|
||||
SignedBigInteger bitwise_not() const;
|
||||
SignedBigInteger shift_left(size_t num_bits) const;
|
||||
SignedBigInteger multiplied_by(const SignedBigInteger& other) const;
|
||||
SignedDivisionResult divided_by(const SignedBigInteger& divisor) const;
|
||||
|
||||
SignedBigInteger plus(const UnsignedBigInteger& other) const;
|
||||
SignedBigInteger minus(const UnsignedBigInteger& other) const;
|
||||
SignedBigInteger bitwise_or(const UnsignedBigInteger& other) const;
|
||||
SignedBigInteger bitwise_and(const UnsignedBigInteger& other) const;
|
||||
SignedBigInteger bitwise_xor(const UnsignedBigInteger& other) const;
|
||||
SignedBigInteger multiplied_by(const UnsignedBigInteger& other) const;
|
||||
SignedDivisionResult divided_by(const UnsignedBigInteger& divisor) const;
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -83,6 +83,10 @@ public:
|
|||
|
||||
UnsignedBigInteger plus(const UnsignedBigInteger& other) const;
|
||||
UnsignedBigInteger minus(const UnsignedBigInteger& other) const;
|
||||
UnsignedBigInteger bitwise_or(const UnsignedBigInteger& other) const;
|
||||
UnsignedBigInteger bitwise_and(const UnsignedBigInteger& other) const;
|
||||
UnsignedBigInteger bitwise_xor(const UnsignedBigInteger& other) const;
|
||||
UnsignedBigInteger bitwise_not() const;
|
||||
UnsignedBigInteger shift_left(size_t num_bits) const;
|
||||
UnsignedBigInteger multiplied_by(const UnsignedBigInteger& other) const;
|
||||
UnsignedDivisionResult divided_by(const UnsignedBigInteger& divisor) const;
|
||||
|
@ -91,6 +95,10 @@ public:
|
|||
|
||||
static void add_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output);
|
||||
static void subtract_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output);
|
||||
static void bitwise_or_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output);
|
||||
static void bitwise_and_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output);
|
||||
static void bitwise_xor_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& output);
|
||||
static void bitwise_not_without_allocation(const UnsignedBigInteger& left, UnsignedBigInteger& output);
|
||||
static void shift_left_without_allocation(const UnsignedBigInteger& number, size_t bits_to_shift_by, UnsignedBigInteger& temp_result, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output);
|
||||
static void multiply_without_allocation(const UnsignedBigInteger& left, const UnsignedBigInteger& right, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_plus, UnsignedBigInteger& output);
|
||||
static void divide_without_allocation(const UnsignedBigInteger& numerator, const UnsignedBigInteger& denominator, UnsignedBigInteger& temp_shift_result, UnsignedBigInteger& temp_shift_plus, UnsignedBigInteger& temp_shift, UnsignedBigInteger& temp_minus, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue