/*
   Обращение матриц методом окаймления
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <dos.h>
#include <time.h>
#include <float.h>
#include <conio.h>
#define rnd ((rand()/32767.0)*2-1)
typedef float * FU ;
void prrivet(FU,FU,int,int);
void pechat(FU, int, int, char *);
void handinit(FU, int);
void result(FU, FU, FU, FU, float, int);
void umn(FU, FU, FU, int, int, int);
void umnn(FU, float, int, int);
void sub(FU, FU, FU, int);
void inition(FU, int, int);
void prisv(FU, FU, int, int);
void Test(FU a,int m,int n)
FU memory(int, int);


void main(void)
{
  int t,n,w,i,j,g,v1,v2,dv;char q; long *v;
  float d,B22,A22,S,na1,na2,na3,na4;float sum=0.0;
  FU OA11,A12,A21,Ann,R1,R22,RR,B11,B12,B21,RRR,TT,cc,c1;

/*  cleardevise();   */
  srand(time(NULL));
do {  clrscr();
//  printf("\n\t\t Обращение матриц методом [окаймления/разб.клетки]\n");
//  printf("\n\t Введите размер матрицы : ");
//  scanf("%d",&n);
  v1=time(v);
   Ann=memory(4,4);clrscr();
/*Инициализация и печать Аnn*/
//  inition(Ann,n,n);
   Test(Ann,4,4);
   pechat(Ann,4,4,"Исходная :");

  OA11=memory(2,2); cc=memory(2,2); c1=memory(2,2);
  *(cc)=*(Ann); *(cc+1)=*(Ann+1);
  *(cc+2)=*(Ann+n); *(cc+3)=*(Ann+n+1);
  d=*(cc)**(cc+3)-*(cc+1)**(cc+2);
  *(OA11)=*(cc+3)/d; *(OA11+1)=-*(cc+1)/d;
  *(OA11+2)=-*(cc+2)/d; *(OA11+3)=*(cc)/d;
  umn(OA11,cc,c1,2,2,2);      //    2    2    2
  free(cc);free(c1);          //  2||  2||  2||
  for(t=2;t<n;t++)            //   ||   ||   ||
    { A12=memory(t,1);        //
      A21=memory(1,t);        //
      for(i=0,j=t;i<t;i++)    //
	*(A12+i)=*(Ann+i*n+j);
      for(j=0,i=t;j<t;j++)
	*(A21+j)=*(Ann+i*n+j);
      A22=*(Ann+t*n+t);//printf("\nA22:%f",A22);
      R1=memory(1,t); R22=memory(1,1);      //     2    2    2
      umn(A21,OA11,R1,1,t,t);               //   1||  2||   1||
      umn(R1,A12,R22,1,t,1);                //         ||
      B22=1/(A22-*R22); /*--Клетка B22--*/  //
      B21=memory(1,t);                      //
      prisv(R1,B21,1,t);                    //
      umnn(B21,-B22,1,t);
      B12=memory(t,1);
      umn(OA11,A12,B12,t,t,1);
      umnn(B12,-B22,t,1);
      B11=memory(t,t);
      umn(B12,R1,B11,t,1,t);
      sub(OA11,B11,B11,t);
      free(OA11); free(A12); free(A21); free(R1);
      OA11=memory(t+1,t+1);
/*Составляем обращенную матрицу OA11 из клеток B11,B12,B21,B22*/
      result(B11,B12,B21,OA11,B22,t+1);
      free(B11); free(B12); free(B21);
      d=B22=A22=S=na1=na2=na3=na4=0.0;
  }
  v2=time(v);
  dv=v2-v1;
  pechat( OA11,t,t,"Обращенная матрица :");
  TT=memory(t,t);
  umn(OA11,Ann,TT,t,t,t);
  pechat( TT,t,t,"Проверка [ ЕдИничная матрица ]:");

  for(i=0;i<t;i++)
  { for(j=0;j<t;j++)
   if(i==j) sum+=(*(TT+i*t+j)-1)*(*(TT+i*t+j)-1);
   else sum+=*(TT+i*t+j)**(TT+i*t+j);
  }
   sum=sqrt(sum);
   printf("\n Km :%2.7f",sum);printf("\tВремя : %d ",dv);
  free(OA11); free(Ann); free(TT);sum=0.0;
  
   printf("\n Снова ? :Y/N  ");
   scanf("%s",&q);
   } while( q!='n');
}
/*--Умножение матриц--*/
void umn(FU a,FU b,FU c,int n,int m,int q)
{
  int i,j,k;
  float s;

  for(i=0;i<n;i++)
    for(j=0;j<q;j++)
      {
	for(s=k=0;k<m;k++)
	  s+=*(a+i*m+k)**(b+k*q+j);
	*(c+i*q+j)=s;
      }
 }
/*--Умножение матрицы на число--*/
void umnn(FU a,float l,int m,int n)
{
  int i;

  for(i=0;i<m*n;i++)
    {
      *(a+i)*=l;
    }
}
/*--Вычитание матриц--*/
void sub(FU a,FU b,FU c,int n)
{
  int i,j;

  for(i=0;i<n;i++)
    for(j=0;j<n;j++)
      *(c+i*n+j)=*(a+i*n+j)-*(b+i*n+j);
}
/*Составляем обращенную матрицу OA11 из клеток B11,B12,B21,B22*/
void result(FU B11,FU B12,FU B21,FU RR,float B22,int n)
{
  int i,j,n1;

  n1=n-1;
  for(i=0;i<n1;i++)
    {
      for(j=0;j<n1;j++)
	*(RR+i*n+j)=*(B11+i*n1+j);
      *(RR+i*n+n1)=*(B12+i);
    }
  for(i=n*n1,j=0;j<n1;j++)
    *(RR+i+j)=*(B21+j);
  *(RR+(n*n)-1)=B22;
}
/*--Печать матрицы и текста--*/
void pechat(FU a,int m,int n,char *str)
{
  int i,j;

  puts(str);
  for(i=0;i<m;i++)
    {
      for(j=0;j<n;j++)
	printf("%6.3f ",*(a+i*n+j));
      printf("\n");
    }
}
/*--Выделение памяти--*/
FU memory(int m,int n)
{
  FU mas;

  mas=(FU)malloc(m*n*sizeof(float));
  return(mas);
}
/*--Инициализация матрицы--*/
void inition(FU a,int m,int n)
{
  int j;

  for(j=0;j<m*n;j++)
    *(a+j)=rnd;
}

void Test(FU a,int m,int n)
{
  int j,i;

      *(a)=2;  *(a+1)=-1;  *(a+2)=1;  *(a+3)=2;
    *(a+4)=0;   *(a+5)=1;  *(a+6)=1;  *(a+7)=0;
   *(a+8)=-1;   *(a+9)=1; *(a+10)=1; *(a+11)=1;
   *(a+12)=1;  *(a+13)=1; *(a+14)=1; *(a+15)=0;
}








/*--Присвоение матрице B значения матрицы A--*/
void prisv(FU a,FU b,int m,int n)
{
  int i;

  for(i=0;i<m*n;i++)
    *(b+i)=*(a+i);
}
/*--Ручной ввод--*/
void handinit(FU a,int n)
{
  int x,y,i,j;
  float p;

  for(i=0,y=3,x=3,j=1;i<n*n;i++,j++)
    {
      x+=8;
      gotoxy(x,y); scanf("%f",&p);
      *(a+i)=p;
      if(j==n) { j=0; x=3; y+=2; }
    }
}
void prrivet(FU a,FU b,int n,int t)
{
  int i,j;
  for(i=0;i<t;i++)
    {
      for(j=0;j<t;j++)
	*(a+i*t+j)=*(b+i*n+j);
    }
}


/* Конец */
