#include <math.h>
// =======================================================================
// Модификация метода оптимального исключения - обращение матриц.
// #define ABS(x) (((x)<0) ? -(x) : (x) )
#define ABS(x) (fabs(x))
/* =======================================================================
  Входные данные:
    - RowsS - исходная матрица 
    - RowsD - единичная матрица
    - N - порядок матрицы.
  Выход:
    0 - матрица вырождена;
    1 - инверсия выполнена.
    Матрица RowsD содержит результат, матрица RowsS испорчена.
======================================================================= */
extern int __pascal mp_mtMatInverse(double **RowsS, double **RowsD, int N)
{
  int i,j,k,ind;
  double elem,max,*row;
  // Цикл по столбцам
  for(k=0;k<N;k++)
  {
    // Типовая методика выбора ведущего элемента по столбцу.
    ind=k;
    max=ABS(RowsS[ind][k]);
    for(i=ind+1;i<N;i++)
    {
      elem=ABS(RowsS[i][k]);
      if(elem>max)
      {
        ind=i;
        max=elem;
      }
    }
//    if(max==0.0) return 0;
    // Перестановка строк матриц
    if(ind!=k)
    {
      row=RowsS[ind];
      RowsS[ind]=RowsS[k];
      RowsS[k]=row;
      row=RowsD[ind];
      RowsD[ind]=RowsD[k];
      RowsD[k]=row;
    }
    // Собственно решение.
    elem = RowsS[k][k];
    for(j=k+1;j<N;j++)
      RowsS[k][j]/=elem;
    for(j=0;j<N;j++)
      RowsD[k][j]/=elem;
    // Непреобразованная часть матрицы состоит из двух подматриц:
    // - верхней: (0,k+1) - (k-1,N-1)
    // - нижней:  (k+1,k+1) - (N-1,N-1)
    // Элементы подматриц пересчитываются по правилу прямоугольника.
    for(i=0;i<k;i++)
    {
      for(j=k+1;j<N;j++)
        RowsS[i][j]-=RowsS[i][k]*RowsS[k][j];
      for(j=0;j<N;j++)
        RowsD[i][j]-=RowsS[i][k]*RowsD[k][j];
    }
    for(i=k+1;i<N;i++)
    {
      for(j=k+1;j<N;j++)
        RowsS[i][j]-=RowsS[i][k]*RowsS[k][j];
      for(j=0;j<N;j++)
        RowsD[i][j]-=RowsS[i][k]*RowsD[k][j];
    }
  }
  return 1;
}
