/*********************************************************/
/*   linearcong.c                                        */
/*    Este programa implementa o algoritmo linear        */
/*    congruente.                                        */
/*   Fernando Henrique Ferraz Pereira da Rosa            */
/*   Vagner Aparecido Pedro Junior                       */
/*   Data:  21/11/2002                                   */
/*                                                       */
/*********************************************************/

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

int verifica_primo(int n);
int sorteia_c(unsigned int aux,unsigned int m);

int main (int argc,char **argv) {
 unsigned int n,aux,x0,c,next,m,i,a;
 srand(time(0));

 if (argc != 2 && argc != 3) {
  printf("Uso:    \n %s n [semente]\n" 
         "     com numero o n o numero de numeros aleatorios que voce quer\n"
         "     gerar e opcionalmente uma semente.\n\n",argv[0]);
  return(0);
 }
 
 sscanf(argv[1],"%d",&n);
 aux = sqrt(n*10);
 while (verifica_primo(aux) == 0) 
  aux--;

 m = aux*aux;
 a = aux+1;
 c = sorteia_c(aux,m);
   
 if (argc == 3)
  sscanf(argv[2],"%d",&x0);
 else
  x0 = ((double)rand()/RAND_MAX)*m;
 
 printf("x0 = %d\n"
        "a = %d\n"
        "c = %d\n"
        "aux = %d\n"
        "m = %d\n",x0,a,c,aux,m);
  
 for (i=0;i<n;i++) {
  next = (a*x0 + c) % m;
  x0 = next;
  printf("%.20f\n",(double)next/m);
 }
 return(0);
}

/* verifica_primo: verifica se n e' um numero e' primo
 *    Pos: retorna 1 se for primo.
 *         retorna 0 caso contrario.
 */
 
int verifica_primo(int n)
{
 int i,pausa;
 pausa = n/2;
 
 if (n == 0)
  return(0);
  
 for(i=2;i < pausa;i++)
  if (n % i == 0)
   return(0);

 return(1);
}
 
 /* sorteia_c: acha um valor para c, tal que
  *     c e m sao primos entre si.
  */
  
int sorteia_c(unsigned int aux,unsigned int m)
{
 int num; 
 num = ((double)rand()/RAND_MAX)*m/10;
 while (num == aux)
  num = ((double)rand()/RAND_MAX)*m/10;
 return(num);
}

