2

I want to recursively calculate the determinant of a 2D matrix, according to the definition of cofactors and their use in calculating the determinant. My code is:

double **supr_mat(int size, double mat[size][size], int nb_colonne)
{
    double **temp;
    *temp = malloc((size - 1) * sizeof(double*));
    if(*temp == NULL)
        return 0;
    for(int i = 0; i < size - 1; i++)                  
    {
        temp[i] = malloc((size - 1)*sizeof(double));
        if(temp[i] == NULL)
        {
            for(int k = 0; k < i; k++)
                free(temp[i]);
            free(*temp);
            return 0;
        }
        for(int j = 0; j < size -1; j++)
            temp[i][j] = 0;
    }
    for(int i = 0; i < size - 1; i++)               //suppresses line, column.
    {
        for(int j = 0; j < size - 1; j++)
        {
            if(j<nb_colonne)
                temp[i][j] = mat[i+1][j];
            else
                temp[i][j] = mat[i+1][j+1];
        }
    }
    return temp;
}

void destroy_supr_mat(double** temp, int size)
{
    for(int i = 0; i < size; i++)
        free(temp[i]);
    free(*temp);
}

double determinant(int size, double mat[size][size])
{
    double det = 0;
    double temp[size - 1][size - 1];
    if(size == 1)
        return mat[0][0];
    for(int i = 0; i < size; i++)
    {
        temp = supr_mat(size, mat, i);
        if(i%2==0)
            det += (-1)*mat[0][i]*determinant(size - 1, temp);
        else
            det += 1*mat[0][i]*determinant(size - 1, temp);
    }
    free(temp, size - 1);
    return det;
}

I get the following error: assignment to expression with array type: temp = supr_mat(size, mat, i); I don't understand why there would be such an error there since my function returns an address and not an array. Compiling also gives me some warnings about pointer types, so I guess I have misunderstood something. Any explanation would be appreciated. I also suppose the recursive algorithm is correct, but I am not sure.

Desperados
  • 434
  • 5
  • 13

1 Answers1

0

double**is not the same as double[size - 1][size - 1]. It's implemented not a pointer on a pointer. It is actually "equivalent" to... double* (implemented as a pointer to the 2D data directly, not as a pointer to a pointer to the data). So you have to change your code to accommodate this issue.

You can also use the VLA in place, you don't have to allocate anything (not sure the size-1 works, but you get the idea):

void supr_mat(int size, double mat[size][size], int nb_colonne, double temp[size-1][size-1])
{
for(int i = 0; i < size - 1; i++)               //suppresses line, column.
{
    for(int j = 0; j < size - 1; j++)
    {
        if(j<nb_colonne)
            temp[i][j] = mat[i+1][j];
        else
            temp[i][j] = mat[i+1][j+1];
    }
}
}
Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
  • Unfortunately I cannot change the prototype 'determinant(int size, double mat[size][size]', which is what is really confusing me...I need temp to be double[size -1][size - 1], so I can pass it as an argument in the function. Could you explain in a bit more detail how I can avoid this problem or, even better post a solution? – Desperados Oct 20 '18 at 13:50
  • 1
    Then do a call in place for `super_mat`, you don't need to return it if you pass it first. And it's fully allocated already. – Matthieu Brucher Oct 20 '18 at 13:53
  • 1
    Adding an example for VLA use. – Matthieu Brucher Oct 20 '18 at 13:55
  • "It is actually equivalent to... `double*`" -- not sure what you mean by this. `double arr[size][size]` decays to a pointer to `double (arr*)[size]` in most expressions. OP could return: `double (*supr_mat(int size, double mat[size][size], int nb_colonne))[];`, i.e., return a pointer to an array, or more legibly use `typedef double (row *)[]` with `row supr_mat(int size, double mat[size][size], int nb_colonne)`. – ad absurdum Oct 20 '18 at 14:09
  • Changed the explanation. – Matthieu Brucher Oct 20 '18 at 14:15
  • "implemented as a pointer to the 2D data directly" -- Hmmm. `double [][]` does not decay to a pointer to a 2d array. Remember that in C a 2d array is really an array of 1d arrays, and when arrays decay, they decay to pointers to their first elements. So `double [][]` will decay to a pointer to a 1d array. – ad absurdum Oct 20 '18 at 14:22
  • Yes, but it is implemented as a 1D array, there is no intermediate array of pointers to the different rows. – Matthieu Brucher Oct 20 '18 at 14:26