/* * @function polynomial_remove_null_monomials * * Remove all monomials from polynomial where coefficient is 0 */ static void polynomial_remove_null_monomials(Polynomial *polynomial) { assert(polynomial != NULL); Monomial *current = polynomial->first, *previous = NULL; while(current != NULL) { double coefficient = monomial_get_coefficient(current); if(is_coefficient_null(coefficient)) { // remove this monomial if(current == polynomial->first) { polynomial->first = monomial_get_next(current); monomial_free(¤t); current = polynomial->first; } else { Monomial *next = monomial_get_next(current); monomial_free(¤t); current = next; monomial_set_next(previous, current); } continue; } previous = current; current = monomial_get_next(current); } polynomial_recalculate_degree(polynomial); }
Polynomial* polynomial_product(const Polynomial* leftp, const Polynomial* rightp) { assert(leftp != NULL); assert(rightp != NULL); /* * Steps for the product of two polynomials: * - compute the degree of the product * - create an array to store the product * - compute the product by adding the product of each monomial in leftp with each monomial in rightp to the array * - convert the array back to a polynomial */ // compute the degree of the product long result_degree = leftp->degree + rightp->degree; // create an array to store the product double *result_coefficients = malloc(sizeof(double) * (result_degree + 1)); if(!result_coefficients) { fprintf(stderr, "Fatal error: couldn't allocate %zu bytes!\nExiting\n", sizeof(double) * (result_degree + 1)); exit(EXIT_FAILURE); } int index_coefficient = 0; for(; index_coefficient < result_degree + 1; index_coefficient++) { result_coefficients[index_coefficient] = 0; } // compute the product by adding the product of each monomial in leftp with each monomial in rightp to the array Monomial *current = leftp->first; while(current != NULL) { Monomial *rightm = rightp->first; while(rightm != NULL) { Monomial *productm = monomial_product(current, rightm); long productm_degree = monomial_get_degree(productm); double productm_coefficient = monomial_get_coefficient(productm); result_coefficients[productm_degree] += productm_coefficient; monomial_free(&productm); rightm = monomial_get_next(rightm); } current = monomial_get_next(current); } Polynomial *product = polynomial_create(result_coefficients, result_degree); polynomial_remove_null_monomials(product); free(result_coefficients); return product; }
void polynomial_free(Polynomial** polynomial) { assert(polynomial != NULL); assert(*polynomial != NULL); Monomial* current = (*polynomial)->first, *next = NULL; while(current != NULL) { next = monomial_get_next(current); monomial_free(¤t); current = next; } free(*polynomial); *polynomial = NULL; }
void polynomial_remove(polynomial_t *p, unsigned long degree) { monomial_t *current = NULL, *tmp = NULL; // Mesure de sécurité if (p == NULL) return; // On parcourt le polynôme jusqu'au monôme à supprimer current = p->first; while (current != NULL && current->degree != degree) current = current->next; // Si on n'a pas trouvé le monôme, on arrête if (current == NULL) return; // On retire le monôme du polynôme if (current->previous != NULL) current->previous->next = current->next; else p->first = current->next; if (current->next != NULL) current->next->previous = current->previous; else p->last = current->previous; // Si c'était le monôme de plus grand degré if (p->degree == current->degree) { // On doit retrouver le nouveau degré du polynôme (par défaut, il vaut 0) tmp = p->first; p->degree = 0; while (tmp != NULL) { if (tmp != current && tmp->degree > p->degree) p->degree = tmp->degree; } } // On libère le monôme de la mémoire et on décrémente la taille du polynôme monomial_free(current); p->size--; }
void polynomial_free(polynomial_t *p) { monomial_t *m = NULL, *tmp = NULL; // Petite mesure de sécurité if (p == NULL) return; // On libère de la mémoire tous les monômes du polynôme m = p->first; while (m != NULL) { tmp = m->next; monomial_free(m); m = tmp; } // Et on libère le reste de la mémoire free(p->name); free(p); }
void polynomial_insert(polynomial_t *p, monomial_t *m) { monomial_t *current = NULL; complex_t *tmp = NULL; // Mesure de sécurité if (p == NULL || m == NULL) return; // On parcourt la liste jusqu'à ce que la puissance de monôme ne soit plus inférieure current = p->first; while (current != NULL && m->degree < current->degree) current = current->next; // S'il n'y a pas d'éléments dans la liste if (current == NULL && p->first == NULL && p->last == NULL) { // On définit le monôme comme le premier et dernier élément du polynôme p->first = m; p->last = m; p->degree = m->degree; p->size++; } else if (current == NULL) // Si on se trouve à la fin du polynôme { // On définit la nouvelle fin du polynôme m->previous = p->last; m->previous->next = m; p->last = m; p->size++; } else if (current->degree == m->degree) // Si on est dans le polynôme et que le monôme courant à le même degré { // On fait la somme des facteurs tmp = complex_sum(current->coef, m->coef); if (tmp == NULL) return; complex_free(current->coef); current->coef = tmp; // Si notre monôme a un coefficient nul if (current->coef->mod == 0.0) polynomial_remove(p, current->degree); // Et on libère le monôme à insérer pour n'en garder qu'un monomial_free(m); } else // Sinon { // On place le monôme dans le polynôme m->previous = current->previous; m->next = current; // On règle les liens ascendant et descendant du monôme current->previous = m; if (m->previous != NULL) m->previous->next = m; else p->first = m; // Si le monôme inséré a le plus grand degré if (m->degree > p->degree) p->degree = m->degree; p->size++; } }