#include <stdio.h>
#include <gmp.h>
#include <mpi.h>

/* Some handy defines */
#define MOD_SIZE 128
#define CENT 10
#define BASE 10

/* A quick prototype */
int gen_num(mpz_t n);
int mod_size = MOD_SIZE;

int main (int argc, char * argv[]) {

  int myid,numprocs;
  int done = 0;

  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
  MPI_Comm_rank(MPI_COMM_WORLD,&myid);

  if (argc == 2)
    mod_size = atoi(argv[1]);
  else
    if (myid == 0)
      printf("You can pass in a number for MOD_SIZE on the command line\n");

  if (myid == 0)
    printf("Current MOD_SIZE == %d\n\n",mod_size);

  mpz_t N;

  mpz_init2(N,mod_size);

  /* run the N generator function */
  gen_num(N);

  fprintf(stdout,"N=");
  mpz_out_str(stdout, BASE,N);
  fprintf(stdout,"\n");

  while(!done) {

    if (myid == 0) {
      /* Here's where I can act as the root process */
      break;  /* instead we'll just quit out */
    }

    /* 
       Simple algorithm for finding P and Q

       P = a_prime
       Q = next_prime_after(P)

       while P != Q && P*Q != N 
          Q = next_prime
	  if ( Q >= sqrt(N) )
	    P = next_prime
	    Q = next_prime_after(P)

       $$ But how does one distribute this algorithm? $$
    */
    
    
  }

  MPI_Finalize();

  return 0;
}

int gen_num(mpz_t n) {

  mpz_t p;
  mpz_t q;

  gmp_randstate_t state;
	
	
  mpz_init2(p,mod_size/2);
  mpz_init2(q,mod_size/2);
	
  mpz_init2(n,mod_size);
	
  gmp_randinit_default (state);
	
  mpz_urandomb (p, state, mod_size/2);
  mpz_setbit (p, mod_size / 2 - 1);
  mpz_setbit (p, mod_size / 2 - 2);
  mpz_nextprime (p, p);

  mpz_urandomb (q, state, mod_size/2);
  mpz_setbit (q, mod_size / 2 - 1);
  mpz_setbit (q, mod_size / 2 - 2);
  mpz_nextprime (q, q);
  	
  while( mpz_cmp(q ,p) == 0 ) {
    mpz_nextprime (q, q);
  }
	
	
  mpz_mul(n,p,q);
	
	
  /**************
   fprintf(stdout,"P=");
   mpz_out_str(stdout, BASE,p);
   fprintf(stdout,"\nQ=");
   mpz_out_str(stdout, BASE,q);
   fprintf(stdout,"\nN=");
   mpz_out_str(stdout, BASE,n);
   fprintf(stdout,"\n");
	
  *************/	
	
  return 0;

}
