#include "p3pack.h"


/*****************************************************************************/
void
bmat_print(unsigned *A, int nbits)
/* Print binary matrix A */
{
   int i,j;
   unsigned ipiv;

   printf("        Matrix                                        \n");
   printf("------------------------------------------------------\n");
   for (i=0,ipiv=1;i<nbits;i++,ipiv<<=1) {
      printf("| ");
      for (j=0;j<nbits;j++) {
         if (A[j] & ipiv)
            printf("1 ");
         else
            printf("0 ");
      }
      printf("|\n");
   }
   printf("------------------------------------------------------\n");
}

void inputdata(int mat[], int rhs[], int *nbits)
{
   int i,j,k;
   printf("Size of problem : ");
   scanf("%d",nbits);
   printf("\n");
   printf("Enter matrix row by row : \n");
   for (i=0;i<(*nbits);i++) {
      printf ("   row %d : ",i);
      for (j=0;j<(*nbits);j++) {
         scanf( "%d",&k);
         if (k) mat[i*(*nbits) + j] = 1;
         else   mat[i*(*nbits) + j] = 0;
      }
   }
   printf("\nEnter rhs as a row : ");
   for (j=0;j<(*nbits);j++) {
      scanf( "%d",&k);
      if (k) rhs[j] = 1;
      else   rhs[j] = 0;
   }
}

main()
{
   int rhs[32],mat[32*32];
   int nbits,i,j,err;
   BL_PERMUT A,B,C;
   PERMUT_ROUT R;
   struct FFTCTL *ctrl;
 
   /* make perfect shuffle and bit conjugation permutation */
   printf("Size of problem (try e.g. 16) : ");
   scanf("%d",&nbits);
   for(i=0;i<nbits-1;i++) {
      rhs[i] = i+1;
   }
   rhs[nbits-1] = 0;
 
   A = blp_btprmNew(rhs,nbits);

   printf("Permutation A :\n");
   blp_print(A);

   printf("\nRouting.\n");
   R = blp_rout(A);
   err = pmr_blpCheck(A,R);
   if (err) printf("Error in permutation!\n");
   else printf("Permutation is correct!\n");

   /* timing */
   {
      double megas;
      int i,j,numiter;
      struct timeval beg,end;
      double stime, etime, eltime;
      plural unsigned long long *llarr;

      numiter = 1000/(R->nmem);
      if (numiter <1) numiter = 1;

      P_MALLOC(llarr,16*R->nmem,plural unsigned long long);

      printf("\nTiming for perfect shuffle & conjug. in all bits:\n");
      printf("------------------------------------------------\n");

      gettimeofday(&beg,0);
      for (i=0;i<numiter;i++) {
         pmr_free(R);
         R = blp_rout(A);
      }
      gettimeofday(&end,0);
      stime = beg.tv_sec + 0.000001*beg.tv_usec;
      etime = end.tv_sec + 0.000001*end.tv_usec;
      eltime = (etime - stime);
      megas = (numiter*nproc*R->nmem)/(eltime*1.0e6);
      printf("Routing speed: %f mega-routings\n",megas);

      printf("Blocksize 1:\n");
      for (j=1;j<9;j<<=1) {
         gettimeofday(&beg,0);
         for (i=0;i<numiter;i++) {
            permut(llarr,8,j,1,R);
         }
         gettimeofday(&end,0);
         stime = beg.tv_sec + 0.000001*beg.tv_usec;
         etime = end.tv_sec + 0.000001*end.tv_usec;
         eltime = (etime - stime);
         megas = (numiter*nproc*R->nmem)/(eltime*1.0e6);
         printf("Permutation speed, %d bit: %f mega-permuts %5.2f Mbyte/sec\n",
         j*8,megas,megas*j);
      }

      printf("Blocksize 8:\n");
      for (j=1;j<9;j<<=1) {
         gettimeofday(&beg,0);
         for (i=0;i<numiter;i++) {
            permut(llarr,8,j,1,R);
         }
         gettimeofday(&end,0);
         stime = beg.tv_sec + 0.000001*beg.tv_usec;
         etime = end.tv_sec + 0.000001*end.tv_usec;
         eltime = (etime - stime);
         megas = (numiter*nproc*R->nmem)/(eltime*1.0e6);
         printf("Permutation speed, %d bit: %f mega-permuts %5.2f Mbyte/sec\n",
         j*64,megas,megas*j*8);
      }

      /* make perfect shuffle in memory bits (could be done easier) */
      for(i=0;i<32;i++) {
         rhs[i] = 0;
         for(j=0;j<32;j++)
            mat[i*nbits+j] = 0;
      }
      for(i=0;i<lnproc;i++) {
         mat[i*nbits+i] = 1;
      }
      for(i=lnproc;i<nbits-1;i++) {
         mat[i*nbits+i+1] = 1;
      }
      mat[(nbits-1)*nbits+lnproc] = 1;
   
      blp_free(A);
      A = blp_iMatNew(mat,rhs,nbits);
      pmr_free(R);
      R = blp_rout(A);

      printf("\nTiming for perf. shuffle in memory bits:\n");
      printf("-----------------------------------------\n");

      gettimeofday(&beg,0);
      for (i=0;i<numiter;i++) {
         pmr_free(R);
         R = blp_rout(A);
      }
      gettimeofday(&end,0);
      stime = beg.tv_sec + 0.000001*beg.tv_usec;
      etime = end.tv_sec + 0.000001*end.tv_usec;
      eltime = (etime - stime);
      megas = (numiter*nproc*R->nmem)/(eltime*1.0e6);
      printf("Routing speed: %f mega-routings\n",megas);

      numiter *= 5;
      printf("Blocksize 1:\n");
      for (j=1;j<9;j<<=1) {
         gettimeofday(&beg,0);
         for (i=0;i<numiter;i++) {
            permut(llarr,8,j,1,R);
         }
         gettimeofday(&end,0);
         stime = beg.tv_sec + 0.000001*beg.tv_usec;
         etime = end.tv_sec + 0.000001*end.tv_usec;
         eltime = (etime - stime);
         megas = (numiter*nproc*R->nmem)/(eltime*1.0e6);
         printf("Permutation speed, %d bit: %f mega-permuts %5.2f Mbyte/sec\n",
         j*8,megas,megas*j);
      }

      printf("Blocksize 8:\n");
      for (j=1;j<9;j<<=1) {
         gettimeofday(&beg,0);
         for (i=0;i<numiter;i++) {
            permut(llarr,8,j,1,R);
         }
         gettimeofday(&end,0);
         stime = beg.tv_sec + 0.000001*beg.tv_usec;
         etime = end.tv_sec + 0.000001*end.tv_usec;
         eltime = (etime - stime);
         megas = (numiter*nproc*R->nmem)/(eltime*1.0e6);
         printf("Permutation speed, %d bit: %f mega-permuts %5.2f Mbyte/sec\n",
         j*64,megas,megas*j*8);
      }

      p_free(llarr);
   }
}
