////////////////////////////////////////////////////////////////////////////////
#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);
}
////////////////////////////////////////////////////////////////////////////////