/* GetDetVal.c */

#include <stdio.h>

#define DataFile "MatrixDataFile2.txt"
#define NN 1001

    /* maximum number entries = NN-1 */
#define INF 0XEFFFFF

void KBToMat(int*);
int FileToMat(int*);
void DisplayMat(int*);
void MatAtoFile(int*);
int Det(int*);

void main(void)
{
 int   Mat[NN];   char CH;

 puts("Where is the data for the Ugraph?");
 puts("If it will be typed in on the (K)eyboard, type K");
 puts("If it is already in the GraphData (F)ile, type F");
INX:
 CH=(char)getchar(); getchar();
 if ((CH=='K') || (CH=='k')) {KBToMat(Mat); goto NXT;}
 if ((CH=='F') || (CH=='f')) {if (FileToMat(Mat)) goto NXT; else goto FIN;}
 puts("Error: enter either K or F");  goto INX;

NXT: 


 puts("\nMatrix has the form:");
 DisplayMat(Mat);
/*
 puts("\nChange data?");
 printf(" if YES then press Y key. Pressing any other letter key means NO  ");
 CH = (char)getchar(); getchar();
 if (CH=='y') CH='Y';
 if (CH=='Y') {EDITMatA(A);  goto EDT;}
*/

 if (Mat[0]/100 == Mat[0]%100)
     printf("Determinant value of the matrix is  %d\n",Det(Mat));
 else puts("No determinant value for a matrix not square");

/* MatAtoFile(A,NAME); */

FIN:
 getchar();
}

/*****************************************************************************/


int FileToMat(int *P)
{
 FILE *F;   char TITLF[]=DataFile;
 char CH,*S,GrStr[NN];  int I,K,M,N=0,CNT,Sign,   *PP;

  if ((F=fopen(TITLF,"r"))==NULL)
    {printf("Cannot find file %s\n",TITLF); return 0;}

     /************* list input-datas already in file ***********/

CH=(char)fgetc(F);     PP=P;

LP2:
 while ((!feof(F)) && (CH != '[')) CH=(char)fgetc(F);     /* find next [ */

 K=0;
 if (!feof(F))
  {
   N++; printf("%d  ",N);
   while (CH != ']') {putchar(CH); CH=(char)fgetc(F);}
   puts("]\n");
   goto LP2;
  }

 INX:
  puts("Input number before the selected data-input (zero to abort):");
  scanf("%d",&K); getchar();
  if (!K) {fclose(F); return 0;}
  if ((K<0) || (K>N)) {printf("Number must be between 1 and %d\n",N); goto INX;}

  rewind(F);

  CH = (char)fgetc(F);
  for (I=1; I<K; I++)
   {
    while (CH != ']') CH = (char)fgetc(F);
   CH = (char)fgetc(F);
  }

  while (CH != '[') CH = (char)fgetc(F);
  S=GrStr;    *S=CH;         /* CH =  [ */
  S++;

  CH = (char)fgetc(F); if ((CH=='m') || (CH=='M')) {*S='M'; S++;}
  else
   {
    puts("Input-array in file not marked 'M' (after '[') for Matrix data");
   return 0;
  }

    /**** Copy character array in file to GrStr ********/

  CH = (char)fgetc(F);
  while (CH!=']') {*S=CH; S++; CH = (char)fgetc(F);}
  *S = CH;
  fclose(F);
  S++; *S='\0';
/*
  puts("Input-data from file is:");
  puts(GrStr);   /* getchar();   /* check data file */

           /*********GrStr to A ******************/

  S=GrStr;


 S++;

 /* Get Size of matrix */
 while ((*S<'0') || (*S>'9')) S++;
 K=0; while ((*S>='0') && (*S<='9')) {K = 10*K + *S-48; S++;}
 M=K/100;  N=K%100;


 *P=100*M + N; P++;

 CNT=M*N;       /* CNT = total number of entries */

 while (CNT)
  {
   while ((*S<'0') || (*S>'9')) S++;
   S--; if (*S=='-') Sign=-1; else Sign=1; S++;
   K=0; while ((*S>='0') && (*S<='9')) {K = 10*K + *S-48; S++;}
   if (Sign==1)*P=K; else *P=-K;  P++;
   CNT--;
  }
 *P=INF;
 return *PP;
}


/*****************************************************************************/

void KBToMat(int *P)
{
 int I,J,K,M,N;


INX:
 puts("Enter size of matrix ROWSxCOLUMNS (0x0 termimates input)  ");
 scanf("%dx%d",&M,&N); getchar();
 if ((M>12) || (N>12)) {puts("No size larger than 12"); goto INX;}
 *P = 100*M + N;  P++;

 for (I=1; I<=M; I++)
  {
   printf("Prepare to enter %d numbers in row %d\n",N,I);
   for (J=1; J<=N; J++)
    {
     if (J==1) puts("first number");
     if ((J>1) && (J<N)) puts("next number");
     if (J==N) puts("last number");
     scanf("%d",&K); getchar();
     *P=K; P++;
    }
  }

 *P=INF;
 return;
}

/*************************** Print A as a Matrix *****************************/

void DisplayMat(int *P)        /* P -> linear matrix array */
 {
  int I,J,K,M,N,Max=0,T;    char S1[] = "%1d%2d%3d%4d%5d%6d%7d%8d%9d",S2[3];

  M=*P/100;  N=*P%100;  P++;
  for (I=1; I<=M; I++)
   {
    for (J=1; J<=N; J++)
     {
      if (*P>=0) K=*P; else K=-*P;
      if (K>Max) Max=K;
    }
  }

 T=1; K=1;
 while (T<=Max) {T=T*10; K++;} 
 for (I=0; I<3; I++) S2[I] = S1[3*K+I];  S2[3]='\0';


 for (I=1; I<=M; I++)
   {
    for (J=1; J<=N; J++) {printf(S2,*P); P++;}
    puts("");
  }

 return;
}





/**************************************************************************/

int Det(int *A)
   /*  NN has been defined globally so that NN-1 is the maximum length of
         any permutation (to prevent rollover of counters).
       Receive integer N, 2<=N<NN, and a pointer A to an array of length NN+1;
       The first permutation is odd; after that the odd-even alternate */
{
 int CNT,H,I,J,K,N,PROD,COPY;    int ODD=1,SUM=0;
 int R[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     D[]={1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  PERM[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13};

 N=A[0]%100;

 if (N<2 || N>NN)
  {printf("Input %d  not between limits  2 and %d\n",N,NN); return 0;}
 CNT=1; for (I=1; I<=N; I++) CNT*=I;   /* CNT = N! */

 while (CNT)
  {              /* form a sum of products of N! terms from matrix A */
   K=0; I=N;
  INDEX:      /* but first, construct a new PERMutation from the old one */
     R[I] = J = R[I] + D[I];
     if (J==I) {D[I]=-1; goto LOOP;}
     if (J) goto TRANSPOSE;
     D[I]=1; K++;
  LOOP:
     if (I>2) {I--; goto INDEX;}
     J=1;
  TRANSPOSE:
     J+=K; COPY=PERM[J]; PERM[J]=PERM[J+1]; PERM[J+1]=COPY;
     /* note: odd and even permutations alternate during the generation */

   /* Using permutation PERM form a product PROD of entries from the matrix A */
     PROD=1;
     for (H=1; H<=N; H++) PROD*= A[(H-1)*N + PERM[H]];   /* row H */
    /* PROD = A[1,PERM[I]]* **** * A[N,PERM[N]] */

/*If permutation even, PROD is added to SUM; if odd then -PROD is added */
     if(ODD) SUM-=PROD; else SUM+=PROD;
     ODD=1-ODD;
     CNT--;
  } /* end of while CNT */   
 return SUM;
}


