/******************************************************************/
/*                         gensatandre.c                          */
/******************************************************************/
/*       Generation d'une donnee r-SAT aleatoire "in.dat"         */
/******************************************************************/

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

#define or  ||
#define and &&

int N; /* valeur du nombre de variables */
int P; /* valeur du nombre de clauses */
int R; /* valeur de la longueur des clauses */ 

unsigned long int G; /* valeur du germe aleatoire */

int **SAT; /* matrice PxR des variables par clause */

int *REP;
int i,j;

FILE *f;

unsigned long int RAND;
unsigned long int RANDMAX;
unsigned long int randomax;

/**************************************************************/
 unsigned long int random()
/**************************************************************/
{RAND=RAND*1103515245+12345;
 return (unsigned long int) RAND%RANDMAX;
}

/**************************************************************/
 irandom(g) unsigned long int g;
/**************************************************************/
{RAND=g;
}

/**************************************************************/
 unsigned long int cr(n,p) int n,p;
/**************************************************************/
{int j; double c;

 if ((n>=p) && (p>=0)) {
  for (c=1.0,j=p-1;j>=0;j--) c=c*(n-j)/(p-j);
  return (unsigned long int)c; }
 else return 0;
}
  
/**************************************************************/
 unsigned long int powi(x,r) int x,r;
/**************************************************************/
{int i; unsigned long int pw;

 if (r<0) printf("Erreur : powi(x,r) avec r=%d\n",r);
 else {
  for (pw=1,i=1;i<=r;i++) pw=pw*x;
  return pw;
 }
}

/**************************************************************/
 geneREP_comb(n,r,kcr) int n,r; unsigned long int kcr;
/**************************************************************/
{int i,i1; char ok;
 
 for (i=1,i1=1;i<=r;i1++,i++)
  for (ok=0;ok==0;)
   if (kcr<cr(n-i1,r-i)) {
    REP[i-1]=i1; ok=1;
   } else {
    kcr=kcr-cr(n-i1,r-i); i1++;
   }
}

/**************************************************************/
 geneREP_inst(n,ir) int n; unsigned long int ir;
/**************************************************************/
{int j;

 for (j=1;j<=n;j++)
  if (ir<powi(2,n-j)) REP[j-1]=1;
  else {
   REP[j-1]=-1; ir=ir-powi(2,n-j);
  }
}
  
/**************************************************************/
 main(argc,argv) int argc; char *argv[];
/**************************************************************/
{

 printf("variables (n) = "); 
 scanf("%d",&N);
 printf("clauses (p) = "); 
 scanf("%d",&P);
 printf("longueur (r) = "); 
 scanf("%d",&R);
 printf("Germe (g) = "); 
 scanf("%d",&G);

 REP=(int *) malloc(R*sizeof(int));
 SAT=(int **) malloc(P*sizeof(long));
 for (i=0;i<P;i++) SAT[i]=(int *) malloc(R*sizeof(int));

 RANDMAX=cr(N,R);
 irandom(G);
 for (i=0;i<P;i++) {
  geneREP_comb(N,R,random());
  for (j=0;j<R;j++) SAT[i][j]=REP[j];
 }

 RANDMAX=32768; randomax=powi(2,R);
 irandom(G);
 for (i=0;i<P;i++) {
  geneREP_inst(R,random()*randomax/RANDMAX);
  for (j=0;j<R;j++) SAT[i][j]=SAT[i][j]*REP[j];
 }


 f=fopen("in.dat","w");
 if (f==NULL) 
  printf("Erreur : ouverture du fichier \"%s\"\n","in.dat");
 fprintf(f,"%d\n%d\n%d\n%d\n",N,P,R,G);
 for (i=0;i<P;i++) {
  for (j=0;j<R;j++) fprintf(f," %3d",SAT[i][j]);
  fprintf(f,"\n");
 }
 fclose(f);

}
