/*
 * @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(&current);
        current = polynomial->first;
      } else {
        Monomial *next = monomial_get_next(current);
        monomial_free(&current);
        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(&current);
    current = next;
  }

  free(*polynomial);
  *polynomial = NULL;
}
Exemple #4
0
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--;
}
Exemple #5
0
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);
}
Exemple #6
0
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++;
	}
}