2010-04-29 7 views
0

Hey, j'essaie de convertir une fonction que j'ai écrite pour générer un tableau de longs qui représente les triangles de Pascal dans une fonction qui retourne un tableau de mpz_t. Cependant, avec le code suivant:Faire le triangle de pascal avec 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; 
} 

Je reçois des erreurs disant: types incompatibles dans l'attribution de toutes les lignes où une position dans le triangle est fixé (i.e. .: triangle [position] = un;).

Est-ce que quelqu'un sait ce que je peux faire mal?

Répondre

3

mpz_t est défini comme un tableau de longueur 1 de struct __mpz_struct, ce qui empêche l'affectation. Cela est dû au fait que l'affectation C normale est une copie superficielle et que les divers types numériques gmp stockent des pointeurs vers des tableaux de "limbs" qui doivent être copiés en profondeur. Vous devez utiliser mpz_set ou mpz_init_set (ou même mpz_init_set_si) pour affecter des entiers MP, en vous assurant d'initialiser la destination avant d'utiliser la première.

De plus, vous devriez appeler mpz_clear au plus une fois pour chaque mpz_init (ils sont comme malloc et gratuit à cet égard, et pour les mêmes raisons). En appelant mpz_init(new_nom) dans la boucle externe mpz_clear(new_num) dans la boucle interne, vous introduisez un bug qui sera évident lorsque vous examinez les résultats de make_triangle. Cependant, vous n'avez même pas besoin de new_num; initialiser l'élément suivant de triangle et l'utiliser comme destination de mpz_add.

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

Petite optimisation numérique: vous pouvez mettre à jour last_row_pos en utilisant une addition et la soustraction plutôt que deux soustractions, une multiplication et la division. Voyez si vous pouvez comprendre comment.