Создание треугольника Паскаля с помощью mpz_t

Эй, я пытаюсь преобразовать функцию, которую я написал для создания массива длинных чисел, представляющих треугольники Паскаля, в функцию, которая возвращает массив mpz_t. Однако со следующим кодом:

mpz_t* make_triangle(int rows, int* count) {
//compute triangle size using 1 + 2 + 3 + ... n = n(n + 1) / 2
*count = (rows * (rows + 1)) / 2;
mpz_t* triangle = malloc((*count) * sizeof(mpz_t));

//fill in first two rows
mpz_t one;
mpz_init(one);
mpz_set_si(one, 1);
triangle[0] = one; triangle[1] = one; triangle[2] = one;

int nums_to_fill = 1;
int position = 3;
int last_row_pos;
int r, i;
for(r = 3; r <= rows; r++) {
    //left most side
    triangle[position] = one;
    position++;

    //inner numbers
    mpz_t new_num;
    mpz_init(new_num);
    last_row_pos = ((r - 1) * (r - 2)) / 2;
    for(i = 0; i < nums_to_fill; i++) {
        mpz_add(new_num, triangle[last_row_pos + i], triangle[last_row_pos + i + 1]);
        triangle[position] = new_num;
        mpz_clear(new_num);
        position++;
    }
    nums_to_fill++;

    //right most side
    triangle[position] = one;
    position++;
}

return triangle;
}

Я получаю сообщения об ошибках: несовместимые типы при назначении для всех строк, в которых задается позиция в треугольнике (например: треугольник [позиция] = один;).

Кто-нибудь знает, что я могу делать неправильно?


person SDLFunTimes    schedule 29.04.2010    source источник


Ответы (1)


mpz_t определяется как массив длины 1 из struct __mpz_struct, что предотвращает присваивание. Это делается потому, что обычное присваивание C является поверхностной копией, а различные числовые типы gmp хранят указатели на массивы "конечности", которые необходимо глубоко скопировать. Вам нужно использовать mpz_set или mpz_init_set (или даже mpz_init_set_si) для назначения целых чисел MP , убедившись, что вы инициализируете место назначения перед использованием первого.

Кроме того, вы должны вызывать mpz_clear не более одного раза для каждого mpz_init (в этом отношении они аналогичны malloc и свободны по тем же причинам). Вызывая mpz_init(new_nom) во внешнем цикле mpz_clear(new_num) во внутреннем цикле, вы вносите ошибку, которая будет очевидна при изучении результатов make_triangle. Однако вам даже не нужно new_num; инициализировать следующий элемент triangle и использовать его в качестве места назначения mpz_add.

    mpz_init(triangle[position]);
    mpz_add(triangle[position++], triangle[last_row_pos + i], triangle[last_row_pos + i + 1]);

Небольшая числовая оптимизация: вы можете обновить last_row_pos, используя сложение и вычитание, а не два вычитания, умножение и деление. Посмотрим, сможешь ли ты понять, как это сделать.

person outis    schedule 29.04.2010