GMP faulty naive primality algorithm c++ - c++

I implemented the following GMP function for an RSA program. Basically, the program generates random mpz*t numbers until one of them returns true for this function.
bool isPrime(const mpz_t bignum)
{
mpz_t modnum; mpz_init(modnum);
if(mpz_cmp_ui(bignum,4)<0 && mpz_cmp_si(bignum,0)>=0) {
fprintf(stderr,"Trivially prime.\n");
return false;
}
else if(mpz_mod_ui(modnum,bignum,2)==0)
return false;
mpz_clear(modnum);
mpz_t i,rootnum;
mpz_inits(i,modnum,rootnum,NULL);
mpz_sqrt(rootnum,bignum);
mpz_set_str(i,"3",10);
for(;mpz_cmp(rootnum,i)>0; mpz_add_ui(i,i,2)) {
mpz_mod(modnum,bignum,i);
if(mpz_cmp(modnum,i)==0)
return false;
}
mpz_clears(modnum,i,rootnum,NULL);
return true;
}
Here is the function that calls isPrime() as a subroutine:
void generate_pq(mpz_t& p, mpz_t& q)
{
gmp_randstate_t rstate;
gmp_randinit_default(rstate);
gmp_randseed_ui(rstate,time(NULL));
printf("\nGenerating keys...\n");
do {
mpz_urandomb(p,rstate,32);
} while(!isPrime(p));
printf("\n***** p *****\n");
gmp_printf(" %Zd\n",p);
do {
mpz_urandomb(q,rstate,32);
} while(!isPrime(q));
gmp_randclear(rstate);
printf("\n***** q *****\n");
gmp_printf(" %Zd\n",q);
}
The program compiles and runs no problem. However, the numbers generated are not prime and yet isPrime() still returns true for them. Could anyone point out the flaw in the algorithm of my primality test? Here is the regular int version of my isPrime() function, if you'd like to compare:
bool isPrime(uint64_t n)
{
//waste of time
if(n < 4) {
fprintf(stderr,"Trivially prime.\n");
return true;
}
//even #, not prime
else if(n%2==0) {
return false;
}
//check if divisible by all odd #s < sqrt(n)
for(uint64_t i=3; i<(uint64_t)sqrt(n+1); i+=2) {
if(n%i==0) {
return false;
}
}
return true;
}

The error was in my for-loop.
for(;mpz_cmp(rootnum,i)>0; mpz_add_ui(i,i,2)) {
mpz_mod(modnum,bignum,i);
if(mpz_cmp(modnum,i)==0) // <-----not supposed to do if(modnum==i)
return false;
The correct version of this for-loop is here:
for(;mpz_cmp(rootnum,i)>0; mpz_add_ui(i,i,2)) {
mpz_mod(modnum,bignum,i);
if(mpz_cmp_ui(modnum,0)==0) // <-- if bignum % modnum == 0, return false
return false;

Related

Difference between flow of if....if block and if....else block

So I was just solving this question the previous day
https://leetcode.com/problems/search-a-2d-matrix-ii/
I was able to solve the problem....but was confused in the execution of if...else block vs if...if block.
The if...else block didn't give me any error while the if....if block gave me an error of IndexOutOfBoundException for length = 1.
Can someone please tell me what's the difference in Layman's term and what am I doing wrong here?
Here is my code ---->
class Solution {
public boolean searchMatrix(int[][] m, int target) {
int x =m.length;
int n= m[0].length;
int i = 0 , j=n-1;
while(i<x && j>=0){
if(m[i][j]==target){
return true;
}
if(m[i][j]>target){
j--;
}
if(m[i][j]<target) {
i++;
}
}
return false;
}
}
************************************* VS ******************************************
class Solution {
public boolean searchMatrix(int[][] m, int target) {
int x =m.length;
int n= m[0].length;
int i = 0 , j=n-1;
while(i<x && j>=0){
if(m[i][j]==target){
return true;
}
if(m[i][j]>target){
j--;
}
else {
i++;
}
}
return false;
}
}
One issue is that this can take you off the bottom of your matrix if j=0.
if(m[i][j]>target){
j--;
}
if(m[i][j]<target) {
i++;
Let's say m[3][0] > target, and you subtract 1 from j, giving j=-1. In your if-else solution, the else is skipped, the while loop then sees that j<0, and the loop exits. Fine.
But in your if-if solution, it then executes if(m[3][-1]<target), which causes the IndexOutOfBoundException
There may be other scenarios too - I haven't checked.

why doesnt the bool function return false?

I'm soo sorry I searched for and read similar questions but couldn't understand/use them to solve my own.
Im writing a bool function within an if statement but the function doesn't seem to return false, what am I doing wrong.
My bool function just checks if there are more than one of the given number in an array:
bool findsame(int a[], int b){
int k=0;
for(int i=0;i<20;i++){
if(a[i]==b){
k++;
}
}
if(k>1){
return true;
}
else{
return false;
}
}
int main()
{
const int size=20;
int a[size]={4,4};
int b=4;
if(findsame(a,b)){
cout<<"true";
}
}
I think you got confused why "false" is not getting printed on console with the function returning the false value.
You need to add to an extra else statement to print false on the console:
if(findsame(a,b)){
std::cout<<"true";
}else{
std::cout<<"false";
}
Also, there are two 4 values in the array, therefore always true will get printed.
Try passing value of b other than 4 and 0.
Have a look at the following implementation where value of variable b is equal to 1:
#include<iostream>
bool findsame(int a[], int b){
int k=0;
for(int i=0;i<20;i++){
if(a[i]==b){
k++;
}
}
if(k>1){
return true;
}
else{
return false;
}
}
int main()
{
const int size=20;
int a[size]={4,4};
int b=1;
if(findsame(a,b)){
std::cout<<"true";
}else{
std::cout<<"false";
}
}
Output:
false
PS: I have also tested code for the value of b = 4 and it prints true. Check and Run the code here: https://onlinegdb.com/S1LR5PtvD

What is the problem with this boolean function?

I was wondering what I may have done wrong in writing this simple function which is supposed to return true if the given number is a prime, or false if not a prime.
bool isPrime(int num)
{
if (num <= 1)
{
status = false;
}
else
{
for (int i = 1; i <= num; i++)
{
if (num % i == 0)
{
dividers++;
}
}
if (dividers == 2)
{
status = true;
}
else
{
status = false;
}
}
return status;
}
Obviously, my main looks like this:
bool isPrime(int num);
bool status;
int dividers = 0;
int main() {
isPrime(2);
if (!isPrime)
{
std::cout << "Not prime" << std::endl;
}
else
{
std::cout << "Prime" << std::endl;
}
return 0;
}
I'm a C++ beginner and I'd really appreciate it if someone could help me there and correct my logic.
Have a good day:)
The immediate problem is in this two lines:
isPrime(2);
if (!isPrime)
The first line calls the function and discards the returned value. The second line converts a pointer to the function to bool. The output of your code does not depend on what you actually do in isPrime.
That is not how you call a function and use its result!
Instead you want
if (isPrime(2)) {
or
bool isP = isPrime(2);
if (isP) { ...
As mentioned in comments, there are also problems in the implementation of isPrime, but I hope this is enough to set you back on the right track.
PS: You should get rid of the global variable status. You do not need both, the return value and a global that stores the result, and if you can choose, you should definitely go for the return value.

Returns in Recursive Function in C++

I'm a little confused here. Let's look at the following code:
bool testing(int i) {
if((i%2)==0) {
return true;
} else {
--i;
testing(i);
}
return false;
}
When I do testing(5), I was expecting the function to return true because at some point, 5 will become 4, so 4 % 2 == 0, so the function will return true but it just wasn't the case. What's wrong?
You should return testing(i); instead of just testing(i);
The idea of recursion is when a function calls itself, directly or indirectly.
The function in your code will become recursive if it is modified to:
bool testing(int i){
// test if even, if so return true
if((i % 2) == 0){
return true;
// otherwise decrement and test again
}else{
// at this point the function calls itself with decremented argument
return testing(--i);
}
// I doubt that this case will be ever returned
// more likely your function will return "true" or run "forever" decrementing
return false;
}
To avoid infinite cycles you need a base case, termination condition that produces result without recursion. For example if i becomes very small or negative you return false.
bool testing(int i){
// base case
if(i < 0) return false;
// rest of the function
if((i % 2) == 0){
return true;
}else{
return testing(--i);
}
}
Making it a bit more concise, you finally have three cases:
bool testing(int i){
// base case
if(i < 0) return false;
// test if even
if((i % 2) == 0) return true;
// recursion step
return testing(--i);
}
For further reading, check this
You don't bubble up the final return value; you need to use return on the recursive call. Additionally, you can simplify the pre-decrement:
return testing(--i);
Because of you only call testing(i) function. That's why it's not call recursively.
you should write return testing(i)
it returns false because its return value is overridden by the last statement of "return false".

How to break out of a while loop with a boolean?

I am trying to break out of several nested while loops and I am having trouble. I want this program to break out into the outer loop, which will run only a certain amount of times. I tried doing it with a boolean but my program terminates too early. It is an N-Queens problem where I am solving for 1x1, 2x2, 3x3,...nxn queens.
Here is my code:
bool ok(int *q, int col)
{
for(int i=0; i<col; i++)
if(q[col]==q[i] || (col-i)==abs(q[col]-q[i])) return false;
return true;
};
void print(int q[], int n, int cnt)
{
//static int count =0;
cout<<"There are "<<cnt<<" solutions for "<<n<<" queens." <<endl;
};
int main()
{
int n;
int *q;
cout<<"Please enter the size of the board:"<<endl;
cin>>n;
int static count = 0;
int c = 1;
int a = 1;
bool from_backtrack=false;
while(a!=n){
q= new int[a];
q[0]=0;
bool foundSolution=true;
while(foundSolution)
{
if (c==a){
a++;
}
while(c<a)
{
if(!from_backtrack)
q[c] = -1; //Start at the top
from_backtrack=false;
while(q[c]<a)
{
q[c]++;
if (q[c]==a)
{
c--;
if(c==-1) {
print(q, n, count);
foundSolution=false;
//system("PAUSE"); exit(1);
}
continue;
}
if( ok(q,c) ) break; //get out of the closest while loop
}
c++;
}
count++;
c--;
if(c==-1) {
print(q, n, count);
foundSolution=false;
//system("PAUSE"); exit(1);
}
from_backtrack=true;
}
delete[a] q;
a++;
}
system("PAUSE");
}
The most elegant way would be to wrap some of your inner loops in a function.
It will be easier to read and to control.
At my work, we employ MISRA guidelines which state "... only 1 break per while loop". This has caused me to rewrite my if and while loops:
bool can_continue = true;
if (can_continue)
{
status = Do_Something();
if (status != SUCCESS)
{
can_continue = false;
}
}
if (can_continue)
{
status = Do_Another_Thing();
can_continue = status == SUCCESS;
}
//.. and so on.
The idea is to set a flag to "false" if execution can't continue. Check it after any segment can cause execution to fail.
while( true ){
if( condition == true ){
goto bye;
}
}
:bye
Just don't submit this on your homework...
Think it is as crazy as useless.
However, suppose you want 3 iterations, you'll define an array of bool of 3 elements (all set to true). On each iteration you set the current element to false, until you reach the end of your array.