mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:42:44 +00:00 
			
		
		
		
	LibCrypto: Added BigInteger 'division by u16' operator
This commit is contained in:
		
							parent
							
								
									0efd58bf6d
								
							
						
					
					
						commit
						8aeccf4f02
					
				
					 3 changed files with 67 additions and 13 deletions
				
			
		|  | @ -52,14 +52,17 @@ UnsignedBigInteger UnsignedBigInteger::import_data(const u8* ptr, size_t length) | ||||||
| size_t UnsignedBigInteger::export_data(AK::ByteBuffer& data) | size_t UnsignedBigInteger::export_data(AK::ByteBuffer& data) | ||||||
| { | { | ||||||
|     UnsignedBigInteger copy { *this }; |     UnsignedBigInteger copy { *this }; | ||||||
|  |     UnsignedBigInteger quotient; | ||||||
|  |     UnsignedBigInteger remainder; | ||||||
| 
 | 
 | ||||||
|     size_t size = trimmed_length() * sizeof(u32); |     size_t size = trimmed_length() * sizeof(u32); | ||||||
|     size_t i = 0; |     size_t i = 0; | ||||||
|     for (; i < size; ++i) { |     for (; i < size; ++i) { | ||||||
|         if (copy.length() == 0) |         if (copy.trimmed_length() == 0) | ||||||
|             break; |             break; | ||||||
|         data[size - i - 1] = copy.m_words[0] & 0xff; |         data[size - i - 1] = copy.m_words[0] & 0xff; | ||||||
|         copy = copy.divided_by(256).quotient; |         divide_u16_without_allocation(copy, 256, quotient, remainder); | ||||||
|  |         copy.set_to(quotient); | ||||||
|     } |     } | ||||||
|     return i; |     return i; | ||||||
| } | } | ||||||
|  | @ -79,12 +82,14 @@ String UnsignedBigInteger::to_base10() const | ||||||
| { | { | ||||||
|     StringBuilder builder; |     StringBuilder builder; | ||||||
|     UnsignedBigInteger temp(*this); |     UnsignedBigInteger temp(*this); | ||||||
|  |     UnsignedBigInteger quotient; | ||||||
|  |     UnsignedBigInteger remainder; | ||||||
| 
 | 
 | ||||||
|     while (temp != UnsignedBigInteger { 0 }) { |     while (temp != UnsignedBigInteger { 0 }) { | ||||||
|         auto div_result = temp.divided_by({ 10 }); |         divide_u16_without_allocation(temp, 10, quotient, remainder); | ||||||
|         ASSERT(div_result.remainder.words()[0] < 10); |         ASSERT(remainder.words()[0] < 10); | ||||||
|         builder.append(static_cast<char>(div_result.remainder.words()[0] + '0')); |         builder.append(static_cast<char>(remainder.words()[0] + '0')); | ||||||
|         temp = div_result.quotient; |         temp.set_to(quotient); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto reversed_string = builder.to_string(); |     auto reversed_string = builder.to_string(); | ||||||
|  | @ -102,6 +107,13 @@ void UnsignedBigInteger::set_to_0() | ||||||
|     m_is_invalid = false; |     m_is_invalid = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void UnsignedBigInteger::set_to(u32 other) | ||||||
|  | { | ||||||
|  |     m_is_invalid = false; | ||||||
|  |     m_words.clear_with_capacity(); | ||||||
|  |     m_words.append(other); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void UnsignedBigInteger::set_to(const UnsignedBigInteger& other) | void UnsignedBigInteger::set_to(const UnsignedBigInteger& other) | ||||||
| { | { | ||||||
|     m_is_invalid = other.m_is_invalid; |     m_is_invalid = other.m_is_invalid; | ||||||
|  | @ -168,6 +180,13 @@ FLATTEN UnsignedDivisionResult UnsignedBigInteger::divided_by(const UnsignedBigI | ||||||
|     UnsignedBigInteger quotient; |     UnsignedBigInteger quotient; | ||||||
|     UnsignedBigInteger remainder; |     UnsignedBigInteger remainder; | ||||||
| 
 | 
 | ||||||
|  |     // If we actually have a u16-compatible divisor, short-circuit to the
 | ||||||
|  |     // less computationally-intensive "divide_u16_without_allocation" method.
 | ||||||
|  |     if (divisor.trimmed_length() == 1 && divisor.m_words[0] < (1 << 16)) { | ||||||
|  |         divide_u16_without_allocation(*this, divisor.m_words[0], quotient, remainder); | ||||||
|  |         return UnsignedDivisionResult { quotient, remainder }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     UnsignedBigInteger temp_shift_result; |     UnsignedBigInteger temp_shift_result; | ||||||
|     UnsignedBigInteger temp_shift_plus; |     UnsignedBigInteger temp_shift_plus; | ||||||
|     UnsignedBigInteger temp_shift; |     UnsignedBigInteger temp_shift; | ||||||
|  | @ -434,6 +453,41 @@ FLATTEN void UnsignedBigInteger::divide_without_allocation( | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Complexity : O(N) where N is the number of digits in the numerator | ||||||
|  |  * Division method : | ||||||
|  |  * Starting from the most significant one, for each half-word of the numerator, combine it | ||||||
|  |  * with the existing remainder if any, divide the combined number as a u32 operation and | ||||||
|  |  * update the quotient / remainder as needed. | ||||||
|  |  */ | ||||||
|  | FLATTEN void UnsignedBigInteger::divide_u16_without_allocation( | ||||||
|  |     const UnsignedBigInteger& numerator, | ||||||
|  |     u32 denominator, | ||||||
|  |     UnsignedBigInteger& quotient, | ||||||
|  |     UnsignedBigInteger& remainder) | ||||||
|  | { | ||||||
|  |     ASSERT(denominator < (1 << 16)); | ||||||
|  |     u32 remainder_word = 0; | ||||||
|  |     auto numerator_length = numerator.trimmed_length(); | ||||||
|  |     quotient.set_to_0(); | ||||||
|  |     quotient.m_words.resize(numerator_length); | ||||||
|  |     for (int word_index = numerator_length - 1; word_index >= 0; --word_index) { | ||||||
|  |         auto word_high = numerator.m_words[word_index] >> 16; | ||||||
|  |         auto word_low = numerator.m_words[word_index] & ((1 << 16) - 1); | ||||||
|  | 
 | ||||||
|  |         auto number_to_divide_high = (remainder_word << 16) | word_high; | ||||||
|  |         auto quotient_high = number_to_divide_high / denominator; | ||||||
|  |         remainder_word = number_to_divide_high % denominator; | ||||||
|  | 
 | ||||||
|  |         auto number_to_divide_low = remainder_word << 16 | word_low; | ||||||
|  |         auto quotient_low = number_to_divide_low / denominator; | ||||||
|  |         remainder_word = number_to_divide_low % denominator; | ||||||
|  | 
 | ||||||
|  |         quotient.m_words[word_index] = (quotient_high << 16) | quotient_low; | ||||||
|  |     } | ||||||
|  |     remainder.set_to(remainder_word); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ALWAYS_INLINE void UnsignedBigInteger::shift_left_by_n_words( | ALWAYS_INLINE void UnsignedBigInteger::shift_left_by_n_words( | ||||||
|     const UnsignedBigInteger& number, |     const UnsignedBigInteger& number, | ||||||
|     const size_t number_of_words, |     const size_t number_of_words, | ||||||
|  |  | ||||||
|  | @ -65,6 +65,7 @@ public: | ||||||
|     const AK::Vector<u32, STARTING_WORD_SIZE>& words() const { return m_words; } |     const AK::Vector<u32, STARTING_WORD_SIZE>& words() const { return m_words; } | ||||||
| 
 | 
 | ||||||
|     void set_to_0(); |     void set_to_0(); | ||||||
|  |     void set_to(u32 other); | ||||||
|     void set_to(const UnsignedBigInteger& other); |     void set_to(const UnsignedBigInteger& other); | ||||||
|     void invalidate() { m_is_invalid = true; } |     void invalidate() { m_is_invalid = true; } | ||||||
| 
 | 
 | ||||||
|  | @ -87,6 +88,7 @@ public: | ||||||
|     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 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 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); |     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); | ||||||
|  |     static void divide_u16_without_allocation(const UnsignedBigInteger& numerator, u32 denominator, UnsignedBigInteger& quotient, UnsignedBigInteger& remainder); | ||||||
| 
 | 
 | ||||||
|     bool operator==(const UnsignedBigInteger& other) const; |     bool operator==(const UnsignedBigInteger& other) const; | ||||||
|     bool operator!=(const UnsignedBigInteger& other) const; |     bool operator!=(const UnsignedBigInteger& other) const; | ||||||
|  |  | ||||||
|  | @ -39,7 +39,6 @@ static auto ModularInverse(const UnsignedBigInteger& a_, const UnsignedBigIntege | ||||||
|         return { 1 }; |         return { 1 }; | ||||||
| 
 | 
 | ||||||
|     UnsignedBigInteger one { 1 }; |     UnsignedBigInteger one { 1 }; | ||||||
|     UnsignedBigInteger two { 2 }; |  | ||||||
|     UnsignedBigInteger temp_1; |     UnsignedBigInteger temp_1; | ||||||
|     UnsignedBigInteger temp_2; |     UnsignedBigInteger temp_2; | ||||||
|     UnsignedBigInteger temp_3; |     UnsignedBigInteger temp_3; | ||||||
|  | @ -82,11 +81,11 @@ static auto ModularInverse(const UnsignedBigInteger& a_, const UnsignedBigIntege | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 // u /= 2
 |                 // u /= 2
 | ||||||
|                 UnsignedBigInteger::divide_without_allocation(u, two, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); |                 UnsignedBigInteger::divide_u16_without_allocation(u, 2, temp_quotient, temp_remainder); | ||||||
|                 u.set_to(temp_quotient); |                 u.set_to(temp_quotient); | ||||||
| 
 | 
 | ||||||
|                 // d /= 2
 |                 // d /= 2
 | ||||||
|                 UnsignedBigInteger::divide_without_allocation(d, two, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); |                 UnsignedBigInteger::divide_u16_without_allocation(d, 2, temp_quotient, temp_remainder); | ||||||
|                 d.set_to(temp_quotient); |                 d.set_to(temp_quotient); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -107,11 +106,11 @@ static auto ModularInverse(const UnsignedBigInteger& a_, const UnsignedBigIntege | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // v /= 2
 |             // v /= 2
 | ||||||
|             UnsignedBigInteger::divide_without_allocation(v, two, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); |             UnsignedBigInteger::divide_u16_without_allocation(v, 2, temp_quotient, temp_remainder); | ||||||
|             v.set_to(temp_quotient); |             v.set_to(temp_quotient); | ||||||
| 
 | 
 | ||||||
|             // x /= 2
 |             // x /= 2
 | ||||||
|             UnsignedBigInteger::divide_without_allocation(x, two, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); |             UnsignedBigInteger::divide_u16_without_allocation(x, 2, temp_quotient, temp_remainder); | ||||||
|             x.set_to(temp_quotient); |             x.set_to(temp_quotient); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -129,7 +128,6 @@ static auto ModularPower(const UnsignedBigInteger& b, const UnsignedBigInteger& | ||||||
|     UnsignedBigInteger ep { e }; |     UnsignedBigInteger ep { e }; | ||||||
|     UnsignedBigInteger base { b }; |     UnsignedBigInteger base { b }; | ||||||
|     UnsignedBigInteger exp { 1 }; |     UnsignedBigInteger exp { 1 }; | ||||||
|     UnsignedBigInteger two { 2 }; |  | ||||||
| 
 | 
 | ||||||
|     UnsignedBigInteger temp_1; |     UnsignedBigInteger temp_1; | ||||||
|     UnsignedBigInteger temp_2; |     UnsignedBigInteger temp_2; | ||||||
|  | @ -151,7 +149,7 @@ static auto ModularPower(const UnsignedBigInteger& b, const UnsignedBigInteger& | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // ep = ep / 2;
 |         // ep = ep / 2;
 | ||||||
|         UnsignedBigInteger::divide_without_allocation(ep, two, temp_1, temp_2, temp_3, temp_4, temp_quotient, temp_remainder); |         UnsignedBigInteger::divide_u16_without_allocation(ep, 2, temp_quotient, temp_remainder); | ||||||
|         ep.set_to(temp_quotient); |         ep.set_to(temp_quotient); | ||||||
| 
 | 
 | ||||||
|         // base = (base * base) % m;
 |         // base = (base * base) % m;
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 DexesTTP
						DexesTTP