Выделение места для верхних треугольных матриц в алгебраической записи

Я работаю над проектом (написанным на C), включающим матричную факторизацию, и мне нужна помощь. Моя цель - выделить память для верхней треугольной матрицы, и я хочу получить к ней доступ с помощью алгебраической записи строк и столбцов (т.е. i, j в {1,2,...,n} вместо i, j в {0,1,...,n-1}). Например, в матрице 5x5 я должен иметь доступ к элементу [3][4], если введу matrix[3][4].

Мой код для верхней треугольной матрицы с неалгебраическим индексом выглядит следующим образом:

double** malloc_sup_matrix (int n)
{
    double**    L;
    int         i;

    L = (double**)malloc((n)*sizeof(double*));

    if(L == NULL)
        printerror("allocating space for the matrix (rows).");        

    for(i = 0;  i < n;  i++)
    {
        L[i] = (double*)malloc((n-i)*sizeof(double));
        if(L[i] == NULL)
            printerror("allocating space for the matrix (cols).");
        L[i]-=i;
    }
    return L;
}

Мой код для алгебраического индекса один (я еще не проверяю, является ли выделенное пространство нулевым, я сделаю это, когда перестану возиться с этим):

    int**   m;
    int     i, n;

    n = 10;

    m = (int**)malloc((n+1)*sizeof(int*));
    for(i = 0; i < n; i++)
    {
        m[i] = (int*)calloc((n+1)-(i),sizeof(int));
        m[i] -= i;
    }

    m--;
    for(i = 0; i < n; i++)
    {
        m[i]--;
    }

Он работает именно так, как я хочу, но у меня возникают проблемы с освобождением используемого пространства. Вот как я это делаю:

    for(i = 1; i <= n; i++)
    {
        m[i]++;
    }    

    for(i = 0; i < n; i++)
    {
        m[i] += (i);
        free(m[i]);
    }
    m++;
    free(m);

У вас есть предложения? Заранее большое спасибо ^^.


person Ignasi Sánchez    schedule 25.04.2015    source источник
comment
но у меня проблемы с освобождением места, которое я использовал. Пожалуйста, будьте явными. В чем проблема?   -  person kaylum    schedule 25.04.2015
comment
Я бы предложил переосмыслить вашу концепцию хранения. Вместо того, чтобы выделять место для n векторов разного размера (которые могут лежать где угодно в памяти), вы также можете использовать один вектор размерности n(n+1)/2. Это имеет несколько преимуществ, среди которых совместимость с Blas и Lapack.   -  person davidhigh    schedule 25.04.2015


Ответы (1)


В этой строке есть проблема:

m--;
for(i = 0; i < n; i++)
{
    m[i]--;
}

Вы уменьшаете m, но затем продолжаете и индексируете его с 0 ... Я думаю, вы можете в конечном итоге испортить структуры кучи.

Мне удалось сделать так, чтобы ваш код valgrind был безошибочным:

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


int main(int argc, char *argv[])
{
    int**   m;
    int     i, j, n;

    n = 10;

    m = (int**)malloc((n+1)*sizeof(int*));
    for(i = 0; i < n; i++)
    {
        m[i] = (int*)calloc((n+1)-(i), sizeof(int));
        m[i] -= i;
    }

    for(i = 0; i < n; i++)
    {
        m[i]--;
    }

    m--;

    /* Access it like m[1][1] ... m[n][n], m[i][j] (with i <= j) */

    /*
    for (i = 1; i <= n; i++) {
        for (j = i; j <= n; j++) {
            m[i][j] = i+j;
        }
    }
    */

    m++;

    for(i = 0; i < n; i++)
    {
        m[i]++;
    }

    for(i = 0; i < n; i++)
    {
        m[i] += (i);
        free(m[i]);
    }

    free(m);

    return 0;
}
person dragosht    schedule 25.04.2015