Modulo Congruence

////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <math>
////////////////////////////////////////////////////////////////////////////////
void numberQuery(unsigned long long &a, unsigned long long &n, 
	unsigned long long &m);
unsigned long long powertworesidual(unsigned long long a, unsigned long long n,
	 unsigned long long m);
unsigned long long nonpowertworesidual(unsigned long long a, 
	unsigned long long n, unsigned long long m);
////////////////////////////////////////////////////////////////////////////////
int main(void)
{

	unsigned long long a = 0, n = 0, m = 0, buff = 0;

	for(int i = 0; i < 4; i++)
	{
		numberQuery(a, n, m);
		if(!n)
		{
			buff = 1 % m;
		}
		else if(n == 2)
		{
			buff = (long long)pow(a, n) % m;
		}
		else if(!(n & (n - 1))) // If it is a power of 2 number
		{
			std::cout << "\nPower entered is a power of 2\n";
			buff = powertworesidual(a, n, m);
		}

		else // it is not a power of 2
		{
			std::cout << "\nPower entered is not a power of 2\n";
			buff = nonpowertworesidual(a, n, m);
		}
		
		std::cout << std::endl << "The residual calculated by the C++"
			<< " modulo operator of " << a << "^" << n << " mod " 
				<< m << " is " << 
					((unsigned long long)pow(a, n) % m);
		
		std::cout << std::endl << "The residual calculated by the "
			<< "books algorithm of " << a << "^" << n << " mod " 
				<< m << " is " << buff;
	}
}
////////////////////////////////////////////////////////////////////////////////
void numberQuery(unsigned long long &a, unsigned long long &n, 
	unsigned long long &m)
{
	std::cout << std::endl << "Please enter a value for \"a\": ";
	std::cin >> a;
	std::cout << std::endl << "Please enter a value for \"n\": ";
	std::cin >> n;
	std::cout << std::endl << "Please enter a value for the modulus: ";
	std::cin >> m;

	while(m == 0)
	{
		std::cout << "Cannot divide by zero, please re-enter m\n";
		std::cin >> m;
	}
	std::cout << "\nYou entered: \na: " << a << "\nn: " << n << 
		"\nmodulus: " << m << std::endl;
	return;
}
////////////////////////////////////////////////////////////////////////////////
unsigned long long powertworesidual(unsigned long long a, 
	unsigned long long n, unsigned long long m)
{
	long long residual = 0;

/* since it is a power of two, we can safely use two as a constant
** the log2 value is how many times it can be halved, so use a loop
** and multiply by two each time. I am assuming this is what the book
** meant, because the example was short and only showed 4 into 2, 2.
*/
	residual = ((unsigned long long)pow(a, 2) % m);

	for (int i = 0; i < (log2(n)-1); i++)
	{
		residual = ((unsigned long long)pow(residual, 2) % m);
	}
	
	return residual; 
}
////////////////////////////////////////////////////////////////////////////////
unsigned long long nonpowertworesidual(unsigned long long a, 
	unsigned long long n, unsigned long long m)
{
	unsigned long long residual = 1;
	unsigned long long distance = 0;
	
	while(n != 0)// While there are still bits left
	{
	
		if(n & 0x1) // if it is set
		{
		/* multiply by a, to the power of 2 to the power of the bits
		** position mod m. This is a clever way to avoid conversion
		*/
			residual *= ((unsigned long long)pow(a, 
				(unsigned long long)pow(2, distance)) % m); 
		}

		distance++; // maintain distance
		n >>= 1; // bitshift right to check next bit
	}

	return (residual % m);
}
////////////////////////////////////////////////////////////////////////////////

Leave a Reply

Your email address will not be published. Required fields are marked *