mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-26 09:22:34 +00:00 
			
		
		
		
	 f4e6f58cc6
			
		
	
	
		f4e6f58cc6
		
	
	
	
	
		
			
			This makes it clearer which variables are operating on words instead of directly operating on raw values.
		
			
				
	
	
		
			83 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
 | |
|  * Copyright (c) 2020-2021, Dex♪ <dexes.ttp@gmail.com>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include "UnsignedBigIntegerAlgorithms.h"
 | |
| 
 | |
| namespace Crypto {
 | |
| 
 | |
| /**
 | |
|  * Complexity: O(N^2) where N is the number of words in the larger number
 | |
|  * Division method:
 | |
|  * We loop over the bits of the divisor, attempting to subtract divisor<<i from the dividend.
 | |
|  * If the result is non-negative, it means that divisor*2^i "fits" in the dividend,
 | |
|  * so we set the ith bit in the quotient and reduce divisor<<i from the dividend.
 | |
|  * When we're done, what's left from the dividend is the remainder.
 | |
|  */
 | |
| FLATTEN void UnsignedBigIntegerAlgorithms::divide_without_allocation(
 | |
|     UnsignedBigInteger const& numerator,
 | |
|     UnsignedBigInteger const& denominator,
 | |
|     UnsignedBigInteger& temp_shift_result,
 | |
|     UnsignedBigInteger& temp_shift_plus,
 | |
|     UnsignedBigInteger& temp_shift,
 | |
|     UnsignedBigInteger& temp_minus,
 | |
|     UnsignedBigInteger& quotient,
 | |
|     UnsignedBigInteger& remainder)
 | |
| {
 | |
|     quotient.set_to_0();
 | |
|     remainder.set_to(numerator);
 | |
| 
 | |
|     // iterate all bits
 | |
|     for (int word_index = numerator.trimmed_length() - 1; word_index >= 0; --word_index) {
 | |
|         for (int bit_index = UnsignedBigInteger::BITS_IN_WORD - 1; bit_index >= 0; --bit_index) {
 | |
|             size_t shift_amount = word_index * UnsignedBigInteger::BITS_IN_WORD + bit_index;
 | |
|             shift_left_without_allocation(denominator, shift_amount, temp_shift_result, temp_shift_plus, temp_shift);
 | |
| 
 | |
|             subtract_without_allocation(remainder, temp_shift, temp_minus);
 | |
|             if (!temp_minus.is_invalid()) {
 | |
|                 remainder.set_to(temp_minus);
 | |
|                 quotient.set_bit_inplace(shift_amount);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * 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 UnsignedBigIntegerAlgorithms::divide_u16_without_allocation(
 | |
|     UnsignedBigInteger const& numerator,
 | |
|     UnsignedBigInteger::Word denominator,
 | |
|     UnsignedBigInteger& quotient,
 | |
|     UnsignedBigInteger& remainder)
 | |
| {
 | |
|     VERIFY(denominator < (1 << 16));
 | |
|     UnsignedBigInteger::Word 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);
 | |
| }
 | |
| 
 | |
| }
 |