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

typedef struct m{
    double **m;
    int M;
    int N;
}matriz;

int CrearMatriz(matriz *mat);
int IngresarMatriz(matriz *mat);
void ImprimirMatriz(matriz mat);
double CalcularDeterminante(const matriz *mat);
void BorrarMatriz(matriz *mat);

int main()
{
    matriz A;
    printf("Ingrese n%cmero de filas:\n",163);
    scanf("%d", &A.M);
    printf("Ingrese n%cmero de columnas:\n", 163);
    scanf("%d", &A.N);
    CrearMatriz(&A);
    IngresarMatriz(&A);
    ImprimirMatriz(A);
    if(A.M==A.N)
        printf("El determinante de la matriz es:\n %8.3lf\n", CalcularDeterminante(&A));
    system("Pause");
    return 0;

}

int CrearMatriz(matriz *mat)
{
    int i,j;
    mat->m=(double**)malloc((mat->M)*sizeof(double*));
    if(mat->m==NULL)
    {
        printf("No se pudo crear matriz.\n");
        return 1;
    }

    for(i=0;i<mat->M;i++)
    {
        mat->m[i]=(double*)malloc((mat->N)*sizeof(double));
        if(mat->m[i]==NULL)
        {
            printf("No hay memoria disponible.\n\n");
            for(j=0;j<i;j++)
                free(mat->m[i]);
            free(mat->m);
            return 1;
        }
    }
    return 0;
}

int IngresarMatriz(matriz *mat)
{
    int i, j;

    for(i=0;i<mat->M;i++)
        for(j=0;j<mat->N;j++)
        {
            printf("Ingrese m[%d][%d]\n",i+1,j+1);
            scanf("%lf", &mat->m[i][j]);
        }
    return 0;
}

void ImprimirMatriz(matriz mat)
{
    int i, j;

    for(i=0;i<mat.M;i++)
    {
        for(j=0;j<mat.N;j++)
            printf("%8.3lf", mat.m[i][j]);
        printf("\n");
    }
}

double CalcularDeterminante(const matriz *mat)
{
    int i, j, j1,j2;
    matriz aux;
    double det;
    if(mat->M==1)
    {
        det=mat->m[0][0];
        return det;
    }
    if(mat->M==2)
    {
        det=mat->m[0][0]*mat->m[1][1];
        det-=mat->m[0][1]*mat->m[1][0];
        return det;
    }

    det=0;
    for(j1=0;j1<mat->M;j1++)
    {
        aux.M=mat->M-1;
        aux.N=mat->M-1;
        CrearMatriz(&aux);
        for(i=1;i<mat->M;i++)
        {
            j2=0;
            for(j=0;j<mat->M;j++)
            {
                if(j==j1)
                    continue;
                aux.m[i-1][j2]=mat->m[i][j];
            j2++;
            }
        }
        det+=mat->m[0][j1]*pow(-1,j1+2)*CalcularDeterminante(&aux);
        BorrarMatriz(&aux);
    }

    return det;
}

void BorrarMatriz(matriz *mat)//Elimina una matriz.
{
    int i;

    for(i=0; i<mat->M; i++)
       free(mat->m[i]);//Libera la memoria se que requirio para crear la matriz.

       free(mat->m);

    mat->m = NULL;
    mat->M = 0;
    mat->N = 0;
}
