Exemple #1
0
/**
 * @brief Dump status of all the root approximations
 */
MPS_PRIVATE void
mps_dump_status (mps_context * s, FILE * outstr)
{
  int i;

  MPS_DEBUG (s, "              Approximation              Attributes       Inclusion");
  for (i = 0; i < s->n; i++)
    {
      MPS_DEBUG (s, "Status  %4d: %-25s  %-15s  %-15s", i,
                 MPS_ROOT_STATUS_TO_STRING (s->root[i]->status),
                 MPS_ROOT_ATTRS_TO_STRING (s->root[i]->attrs),
                 MPS_ROOT_INCLUSION_TO_STRING (s->root[i]->inclusion));
    }
}
Exemple #2
0
static void
mps_context_init (mps_context * s)
{
  mpf_t test;

  /* Set default streams */
  s->instr = stdin;
  s->outstr = stdout;
  s->logstr = stdout;

  /* Allocate space for the configurations */
  s->input_config = (mps_input_configuration*)mps_malloc (sizeof(mps_input_configuration));
  s->output_config = (mps_output_configuration*)mps_malloc (sizeof(mps_output_configuration));

  mps_set_default_values (s);

  /* Find minimum GMP supported precision */
  mpf_init2 (test, 1);
  s->minimum_gmp_precision = mpf_get_prec (test);
  mpf_clear (test);

  /* Set standard precision */
  s->output_config->prec = (int)(0.9 * DBL_DIG * LOG2_10);
  MPS_DEBUG (s, "Setting prec_out to %ld digits", s->output_config->prec);

  mps_mp_set_prec (s, DBL_DIG * LOG2_10 + 1);

  s->initialized = false;
  s->exit_required = false;
}
Exemple #3
0
/**
 * @brief Free all the data allocated with <code>mps_allocate_data()</code>
 *
 * @param s The <code>mps_context</code> of the computation.
 */
void
mps_free_data (mps_context * s)
{
  int i;

  if (s->debug_level & MPS_DEBUG_MEMORY)
    {
      MPS_DEBUG (s, "Deallocating data");
    }

  if (s->bmpc)
    {
      mpc_vclear (s->bmpc, s->n * s->pool->n);
      free (s->bmpc);
      s->bmpc = NULL;
    }

  mps_clusterization_free (s, s->clusterization);
  free (s->order);

  for (i = 0; i < s->n; i++)
    mps_approximation_free (s, s->root[i]);
  free (s->root);

  for (i = 0; i <= s->deg; i++)
    mpc_clear (s->mfpc1[i]);
  mpc_vfree (s->mfpc1);

  cplx_vfree (s->fppc1);
  for (i = 0; i <= s->deg; i++)
    {
      mpc_clear (s->mfppc1[i]);
    }

  free (s->mfppc1);

  /* free temporary vectors */
  free (s->spar1);
  free (s->h);
  free (s->again_old);

  free (s->oldpunt);
  free (s->clust_aux);
  free (s->punt_aux);
  free (s->punt_out);
  free (s->clust_out);

  free (s->fap1);
  free (s->fap2);

  rdpe_vfree (s->dap1);
  cdpe_vfree (s->dpc1);
  cdpe_vfree (s->dpc2);

  free (s->partitioning);
  free (s->fradii);
  rdpe_vfree (s->dradii);

  mps_thread_pool_free (s, s->pool);
}
Exemple #4
0
/**
 * @brief Compute the mp_complex values of the coefficients of p(x)
 * with the  current precision of mpwds words, given the
 * rational or integer coefficients.
 *
 * @param s The <code>mps_context</code> of the computation.
 * @param prec The precision that should be set and to which the data should
 * be adjusted.
 */
void 
mps_prepare_data (mps_context * s, long int prec)
{
  MPS_DEBUG_THIS_CALL;

  pthread_mutex_lock (&s->precision_mutex);

  if (s->debug_level & MPS_DEBUG_MEMORY)
    MPS_DEBUG (s, "Increasing working precision to %ld bits", prec);

  MPS_LOCK (s->data_prec_max);

  if (prec > s->data_prec_max.value)
    {
      s->data_prec_max.value = mps_raise_data (s, prec);
    }
  else 
    {
      mps_polynomial_raise_data (s, s->active_poly, prec);
    }

  MPS_UNLOCK (s->data_prec_max);

  pthread_mutex_unlock (&s->precision_mutex);
}
Exemple #5
0
/**
 * @brief Resets the data to the highest used precision
 *
 * @param s The <code>mps_context</code> of the computation.
 */
void
mps_restore_data (mps_context * s)
{
  MPS_LOCK (s->data_prec_max);
  if (s->debug_level & MPS_DEBUG_MEMORY)
    MPS_DEBUG (s, "Restore data to %ld bits", s->data_prec_max.value);

  if (s->data_prec_max.value)
    {
      MPS_UNLOCK (s->data_prec_max);
      mps_raise_data_raw (s, s->data_prec_max.value);
    }
  else
    MPS_UNLOCK (s->data_prec_max);
}
Exemple #6
0
/**
 * @brief Set the monomial poly p as the input polynomial for
 * the current equation.
 *
 * @param s The mps_context to set the monomial_poly into.
 * @param p The mps_monomial_poly to solve.
 */
void
mps_context_set_input_poly (mps_context * s, mps_polynomial * p)
{
  MPS_DEBUG_THIS_CALL (s);

  MPS_DEBUG (s, "Setting input poly");

  if (p->degree < 0)
    {
      mps_error (s, "Polynomial degree should be positive");
      return;
    }

  int i;
  s->active_poly = p;

  if (!p->thread_safe)
    mps_thread_pool_set_concurrency_limit (s, s->pool, 1);

  /* Set the density or sparsity of the polynomial, if it's not
   * a user polynomial */
  if (MPS_IS_MONOMIAL_POLY (p))
    {
      int original_degree = p->degree;
      mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p);

      /* Deflate the polynomial if necessary */
      mps_monomial_poly_deflate (s, p);
      s->zero_roots = original_degree - p->degree;

      MPS_DEBUG_WITH_INFO (s, "Degree = %d", p->degree);

      /* Check if the input polynomial is sparse or not. We can simply check if
       * the again vector is all of true values */
      p->density = MPS_DENSITY_DENSE;
      for (i = 0; i <= MPS_POLYNOMIAL (mp)->degree; ++i)
        {
          if (!mp->spar[i])
            {
              p->density = MPS_DENSITY_SPARSE;
              break;
            }
        }
    }

  mps_context_set_degree (s, p->degree);
}
Exemple #7
0
void
mps_context_init (mps_context * s)
{
  /* Set default streams */
  s->instr = stdin;
  s->outstr = stdout;
  s->logstr = stdout;

  /* Allocate space for the configurations */
  s->input_config  = (mps_input_configuration  *) mps_malloc (sizeof (mps_input_configuration));
  s->output_config = (mps_output_configuration *) mps_malloc (sizeof (mps_output_configuration));

  mps_set_default_values (s);

  /* Set standard precision */
  s->output_config->prec = (int) (0.9 * DBL_DIG * LOG2_10);
  MPS_DEBUG (s, "Setting prec_out to %ld digits", s->output_config->prec);

  mps_mp_set_prec (s, DBL_DIG * LOG2_10 + 1);

  s->initialized = false;
}
Exemple #8
0
/**
 * @brief Improve all the approximations up to prec_out digits.
 *
 * For each approximation compute the value of sigma such that, given some
 * approximations \f$x_j\f$ of the roots, \f$r_j\f$ the values of the
 * inclusion radii and \f$d_i\f$ the number of correct digits:
 * \f[
 *   e_j < e_0 * \sigma^{2^j} \qquad \sigma=\frac{k}{k-1}=\frac{1}{1-t} \qquad k=\frac{1}{t}
 * \f]
 * and
 * \f[
 *   t = \min_j |z_i-z_j|-r_j
 * \f]
 * Then compute the number of digits needed for the j-th
 * iteration i.e., if \f$cond\f$ is the conditioning of the root:
 * \f[
 *   d_j = \log(\frac{e_j}{|x|}) + cond
 * \f]
 * where
 * \f[
 *   \log(\frac{e_j}{|x|}) = (f+g){2j} \qquad
 *   cond = \log(\frac{rad}{\epsilon})
 * \f]
 * and
 * \f[
 *   cond \approx \lVert p \rVert (1+ \frac{|x_i|}{a_n \prod_{j \neq i} |x_i-x_j|}
 * \f]
 * and
 * \f[
 *   cond \approx \frac{r_i}{\epsilon |x_i|}
 * \f]
 * for user-defined polynomials.
 *
 * <code>s->mpwp</code> denotes the number of bits of the current working
 * precision.
 *
 * @param ctx The mps_context associated with the computation.
 */
MPS_PRIVATE void
mps_improve (mps_context * ctx)
{
  int i;
  long int current_precision = 0L;
  int approximated_roots = 0;
  mps_polynomial * p = ctx->active_poly;
  rdpe_t * root_conditioning = NULL;

  ctx->operation = MPS_OPERATION_REFINEMENT;

  /* We need to be able to evaluate the Newton correction in a point
   * in order to perform the refinement. This is not necessary true
   * for custom polynomial types, so add a check in here */
  if (p->mnewton == NULL && p->density != MPS_DENSITY_USER)
    return;

  /* Set lastphase to mp */
  ctx->lastphase = mp_phase;

  /* Determine the conditioning of the roots */
  root_conditioning = evaluate_root_conditioning (ctx, p, ctx->root, ctx->n);

  /* We adopt the strategy of various iterations refinements on
   * the approximations by setting the precision of the input
   * polynomial in an increasing sequence. */

  /* We start by determining the minimum precision at which we can
   * extract some information. */
  current_precision = LONG_MAX;
  for (i = 0; i < ctx->n; i++)
    {
      if (ctx->root[i]->wp < current_precision)
        current_precision = ctx->root[i]->wp;

      if (MPS_ROOT_STATUS_IS_APPROXIMATED (ctx->root[i]->status) ||
	  ctx->root[i]->inclusion == MPS_ROOT_INCLUSION_OUT)
        approximated_roots++;
    }

  /* Start by iterating on the roots that are not approximated, and
   * continue until we get all of them. */
  while (approximated_roots < ctx->n)
    {
      mps_polynomial_raise_data (ctx, p, current_precision);

      MPS_DEBUG (ctx, "Step of improvement");

      for (i = 0; i < ctx->n; i++)
        if (ctx->root[i]->status == MPS_ROOT_STATUS_ISOLATED && 
	    ctx->root[i]->inclusion != MPS_ROOT_INCLUSION_OUT)
          {
            /* Evaluate the necessary precision to iterate on this root.
             * If the the current polynomial precision is enough, iterate on it.
             * Otherwise, let it for the next round. */
            long int necessary_precision = get_approximated_bits (ctx->root[i]) + log2 (ctx->n) +
                                           rdpe_log (root_conditioning[i]) / LOG2;

            if (necessary_precision < current_precision)
              {
                __improve_root_data * data = mps_new (__improve_root_data);
                data->ctx = ctx;
                data->p = p;
                data->root = ctx->root[i];
                data->precision = current_precision;

                mps_thread_pool_assign (ctx, NULL, improve_root_wrapper, data);
              }
          }

      mps_thread_pool_wait (ctx, ctx->pool);

      for (i = 0; i < ctx->n; i++)
        if (!MPS_ROOT_STATUS_IS_APPROXIMATED (ctx->root[i]->status) &&
            get_approximated_bits (ctx->root[i]) >= ctx->output_config->prec)
          {
            ctx->root[i]->status = MPS_ROOT_STATUS_APPROXIMATED;
            approximated_roots++;

            if (ctx->debug_level & MPS_DEBUG_IMPROVEMENT)
              MPS_DEBUG (ctx, "Approximated roots = %d", approximated_roots);
          }

      /* Increase precision to reach the desired number of approximated roots */
      current_precision = 2 * current_precision;

      /* Check if we have gone too far with the precision, and we have gone over
       * the maximum precision allowed for this polynomial. */
      if (current_precision > p->prec && p->prec != 0)
        {
          ctx->over_max = true;
          goto cleanup;
        }

      /* Increase data prec max that will be useful to the end user to know
       * the precision needed to hold these approximations. */
      ctx->data_prec_max.value = current_precision;

      if (ctx->debug_level & MPS_DEBUG_IMPROVEMENT)
        MPS_DEBUG (ctx, "Increasing precision to %ld", current_precision);
    }

cleanup:

  free (root_conditioning);
}
Exemple #9
0
/**
 * @brief Dump all the current approximation to the logstr selected
 * in the current mps_context.
 *
 * @param s A pointer to the current mps_context.
 *
 * This function is tipically used when encountering some errors.
 */
void
mps_dump (mps_context * s)
{
  int i;
  FILE * dmpstr = s->logstr;

  MPS_DEBUG (s, "Dumping the approximations:");

  /* output current status */
  /* fprintf (dmpstr, */
  /*          "Phase=%d, In=%d, Out=%d, Uncertain=%d, Zero=%d, Clusters=%ld\n", */
  /*          s->lastphase, s->count[0], s->count[1], s->count[2], s->zero_roots, */
  /*          s->clusterization->n); */

  MPS_DEBUG (s, "Phase = %s, In = %d, Out = %d, Uncertain = %d, Zero = %d, Cluster = %ld",
             MPS_PHASE_TO_STRING (s->lastphase), s->count[0], s->count[1], s->count[2],
             s->zero_roots, s->clusterization->n);

  /* output current approximations */
  /* fprintf (dmpstr, "\nCurrent approximations:\n"); */
  MPS_DEBUG (s, "Current approximations:");
  for (i = 0; i < s->n; i++)
    {
      switch (s->lastphase)
        {
        case no_phase:
        case float_phase:
          MPS_DEBUG_CPLX (s, s->root[i]->fvalue, "Approximation  %4d", i);
          break;

        case dpe_phase:
          MPS_DEBUG_CDPE (s, s->root[i]->dvalue, "Approximation  %4d", i);
          break;

        case mp_phase:
          MPS_DEBUG_MPC (s, s->mpwp, s->root[i]->mvalue, "Approximation  %4d", i);
          break;
        }
    }

  /* output radii */
  MPS_DEBUG (s, "Current radii:");
  for (i = 0; i < s->n; i++)
    {
      switch (s->lastphase)
        {
        case no_phase:
        case float_phase:
          MPS_DEBUG (s, "Radius of root %4d = %e", i, s->root[i]->frad);
          break;

        case dpe_phase:
        case mp_phase:
          MPS_DEBUG_RDPE (s, s->root[i]->drad, "Radius of root %4d", i);
          break;
        }
    }

  MPS_DEBUG (s, " ");
  mps_dump_status (s, dmpstr);
}
Exemple #10
0
/**
 * @brief Multithread worker for mps_thread_dpolzer ()
 */
static void *
mps_thread_dpolzer_worker (void *data_ptr)
{
  int iter, i;
  rdpe_t rad1, rtmp;
  cdpe_t corr, abcorr;

  /* Parse input data */
  mps_thread_worker_data *data = (mps_thread_worker_data*)data_ptr;
  mps_context *s = data->s;
  mps_polynomial *p = s->active_poly;
  mps_thread_job job;

  while (!(*data->excep) && (*data->nzeros < data->required_zeros))
    {
      job = mps_thread_job_queue_next (s, data->queue);
      i = job.i;
      iter = job.iter;

      /* Check if we got over the maximum number of iterations */
      if (job.iter == MPS_THREAD_JOB_EXCEP)
        {
          (*data->excep) = true;
          return 0;
        }

      /* Make sure that we are the only one iterating on this root */
      if (s->pool->n > 1)
	pthread_mutex_lock (&data->roots_mutex[i]);

      if (s->root[i]->again)
        {
          /* Check if, while we were waiting, excep condition has been reached */
          if (*data->excep || !s->root[i]->again || (*data->nzeros > data->required_zeros))
            {
	      if (s->pool->n > 1)
		pthread_mutex_unlock (&data->roots_mutex[i]);
              return 0;
            }

          (*data->it)++;
          rdpe_set (rad1, s->root[i]->drad);

          mps_polynomial_dnewton (s, p, s->root[i], corr);
          if (iter == 0 && !s->root[i]->again && rdpe_gt (s->root[i]->drad, rad1)
              && rdpe_ne (rad1, rdpe_zero))
            rdpe_set (s->root[i]->drad, rad1);
          /************************************************
             The above condition is needed to manage with the case where
             at the first iteration the starting point is already in the
             root neighbourhood and the actually computed radius is too
             big since the value of the first derivative is too small.
             In this case the previous radius bound, obtained by means of
             Rouche' is more reliable and strict
           **********************************************/

          if (s->root[i]->again
              /* the correction is performed only if iter!=1 or rad(i)!=rad1 */
              || iter != 0
              || rdpe_ne (s->root[i]->drad, rad1))
            {
              mps_daberth (s, s->root[i], abcorr);
              cdpe_mul_eq (abcorr, corr);
              cdpe_sub (abcorr, cdpe_one, abcorr);
              if (cdpe_eq_zero (abcorr))
                {
                  MPS_DEBUG (s, "Aberth correction is zero.");
                  s->lastphase = dpe_phase;
                  cdpe_set_d (abcorr, DBL_EPSILON, 0);
                }

              cdpe_div (abcorr, corr, abcorr);
              cdpe_sub_eq (s->root[i]->dvalue, abcorr);
              cdpe_mod (rtmp, abcorr);
              rdpe_add_eq (s->root[i]->drad, rtmp);
            }

          /* check for new approximated roots */
          if (!s->root[i]->again)
            {
              (*data->nzeros)++;
              if ((*data->nzeros) >= data->required_zeros)
                {
		  if (s->pool->n > 1)
		    pthread_mutex_unlock (&data->roots_mutex[i]);
                  return 0;
                }
            }
        }

      if (s->pool->n > 1)
	pthread_mutex_unlock (&data->roots_mutex[i]);
    }

  return NULL;
}
Exemple #11
0
/**
 * @brief Worker for the fpolzer routine.
 */
void *
mps_thread_fpolzer_worker (void *data_ptr)
{
  mps_thread_worker_data *data = (mps_thread_worker_data*)data_ptr;
  mps_context *s = data->s;
  mps_polynomial *p = s->active_poly;
  int i, iter;
  cplx_t corr, abcorr, froot;
  double rad1, modcorr;
  mps_thread_job job;

  while (!(*data->excep) && (*data->nzeros) < data->required_zeros)
    {
      job = mps_thread_job_queue_next (s, data->queue);
      i = job.i;
      iter = job.iter;

      /* Check if we got over the maximum number of iterations */
      if (job.iter == MPS_THREAD_JOB_EXCEP)
        {
          (*data->excep) = true;
          return 0;
        }

      /* Lock this roots to make sure that we are the only one working on it */
      pthread_mutex_lock (&data->roots_mutex[i]);

      if (s->root[i]->again)
        {
          /* Check if, while we were waiting, excep condition has been reached */
          if (*data->excep || !s->root[i]->again || (*data->nzeros > data->required_zeros))
            {
              pthread_mutex_unlock (&data->roots_mutex[i]);
              return 0;
            }

          (*data->it)++;

          rad1 = s->root[i]->frad;

          /* Make a local copy of the root */
          pthread_mutex_lock (&data->aberth_mutex[i]);
          cplx_set (froot, s->root[i]->fvalue);
          pthread_mutex_unlock (&data->aberth_mutex[i]);

          mps_polynomial_fnewton (s, p, s->root[i], corr);

	  if (cplx_check_fpe (corr))
	    {
	      /* If we get a floating point exception we need to switch to DPE
	       * arithmetic. */
	      s->root[i]->frad = rad1;
	      s->skip_float = true;
	      s->root[i]->again = false;
	    }

          if (iter == 0 && !s->root[i]->again && s->root[i]->frad > rad1 && rad1 != 0)
            s->root[i]->frad = rad1;
          /***************************************
               The above condition is needed to cope with the case
               where at the first iteration the starting point
               is already in the root neighbourhood and the actually
               computed radius is too big since the value of the first
               derivative is too small.
               In this case the previous radius bound, obtained by
               means of Rouche' is more reliable and strict
           **************************************/

          if (s->root[i]->again
              /* the correction is performed only if iter!=1 or rad(i)!=rad1 */
              || iter != 0 || s->root[i]->frad != rad1)
            {
              mps_faberth (s, s->root[i], abcorr);

              cplx_mul_eq (abcorr, corr);
              cplx_sub (abcorr, cplx_one, abcorr);

              if (cplx_eq_zero (abcorr))
                {
                  MPS_DEBUG (s, "Aberth correction is zero");
                  cplx_set_d (abcorr, DBL_EPSILON, 0);
                }

              cplx_div (abcorr, corr, abcorr);
              cplx_sub_eq (froot, abcorr);
              modcorr = cplx_mod (abcorr);
              s->root[i]->frad += modcorr;

              pthread_mutex_lock (&data->aberth_mutex[i]);
              cplx_set (s->root[i]->fvalue, froot);
              pthread_mutex_unlock (&data->aberth_mutex[i]);
            }

          /* check for new approximated roots */
          if (!s->root[i]->again)
            {
              (*data->nzeros)++;
              if (*data->nzeros >= data->required_zeros)
                {
                  pthread_mutex_unlock (&data->roots_mutex[i]);
                  return 0;
                }
            }
        }

      pthread_mutex_unlock (&data->roots_mutex[i]);
    }

  return NULL;
}
Exemple #12
0
/**
 * @brief Main routine of the program that implements the algorithm
 * in the standard polynomial version.
 *
 * The program is divided into many parts
 * - Check the correctness of data, scale coefficients if
 *   needed, and select cases: the variable <code>which_case</code> is
 *   <code>'f'</code> or <code>'d'</code>  according to float or dpe case.
 * - Call msolve or dsolve according to the value of which_case.
 * - Allocate MP variables mfpc, mroot, drad (if needed).
 * - Start MPsolve loop
 *   - prepare data according to the current precision
 *      and to the data_type (density/sparsity/user)
 *   - Call msolve with the current precision
 * - check for termination
 */
MPS_PRIVATE void
mps_standard_mpsolve (mps_context * s)
{
  int i, nzc;
  char which_case;
  mps_boolean d_after_f, computed;

#ifndef DISABLE_DEBUG
  clock_t *my_timer = mps_start_timer ();
#endif

  mps_allocate_data (s);

  if (s->DOLOG)
    s->debug_level |= MPS_DEBUG_TRACE;

  /* == 1 ==  Setup variables, i.e. copy coefficients
     into dpr, dpc and similar. */
  mps_setup (s);

  s->lastphase = no_phase;
  computed = false;
  s->over_max = false;

  /* == 2 ==  Resume from pre-computed roots */
  if (s->resume)
    {
      mps_error (s, "Resume not supported yet");
#ifndef DISABLE_DEBUG
      mps_stop_timer (my_timer);
#endif
      return;
    }

  /* == 3 ==  Check data and get starting phase */
  if (s->skip_float)
    which_case = 'd';
  else
    which_case = 'f';

  /* This variable is true if we need a dpe phase after the
   * float phase */
  d_after_f = false;

  /* Check if a dpe phase is needed and deflate polynomial */
  mps_check_data (s, &which_case);

  /* Check for errors in check data */
  if (mps_context_has_errors (s))
    {
#ifndef DISABLE_DEBUG
      mps_stop_timer (my_timer);
#endif
      return;
    }

  rdpe_set_2dl (s->eps_out, 1.0, -s->output_config->prec);

  if (s->DOLOG)
    fprintf (s->logstr, "Which_case = %c, skip_float= %d\n", which_case,
             s->skip_float);

  /* == 4 ==  Float phase */
  if (which_case == 'f')
    {
      if (s->DOLOG)
        fprintf (s->logstr, "Float phase ...\n");
      mps_fsolve (s, &d_after_f);
      s->lastphase = float_phase;

      if (s->DOLOG)
        mps_dump (s);

      computed = mps_check_stop (s);
      if (computed && s->output_config->goal != MPS_OUTPUT_GOAL_APPROXIMATE)
        goto exit_sub;
      /* stop for COUNT and ISOLATE goals */
    }

  /* == 5 ==  DPE phase */
  if (which_case == 'd' || d_after_f)
    {                           /* DPE phase */
      if (s->DOLOG)
        fprintf (s->logstr, "DPE phase ...\n");
      /* If we are arriving from a float phase copy the floating points
       * roots approximations in the DPE root approximations. */
      if (d_after_f)
        for (i = 0; i < s->n; i++)
          {
            rdpe_set_d (s->root[i]->drad, s->root[i]->frad);
            cdpe_set_x (s->root[i]->dvalue, s->root[i]->fvalue);
          }
      s->lastphase = dpe_phase;
      mps_dsolve (s, d_after_f);

      if (s->DOLOG)
        mps_dump (s);

      computed = mps_check_stop (s);
      if (computed && s->output_config->goal != MPS_OUTPUT_GOAL_APPROXIMATE)
        goto exit_sub;
    }

  /* == 6 ==   Allocate MP variables mfpc, mroot, drad, mfppc, mfppc1
   * (the real input case is not implemented yet ) */
  MPS_DEBUG (s, "Starting MP phase");

  s->lastphase = mp_phase;

  /* ==== 6.1 initialize mp variables */
  mps_mp_set_prec (s, 2 * DBL_MANT_DIG);

  /* Prepare data according to the current working precision */
  mps_prepare_data (s, s->mpwp);

  /* ==== 6.2 set initial values for mp variables */
  for (i = 0; i < s->n; i++)
    {
      if (which_case == 'd' || d_after_f)
        mpc_set_cdpe (s->root[i]->mvalue, s->root[i]->dvalue);
      else
        {
          mpc_set_cplx (s->root[i]->mvalue, s->root[i]->fvalue);
          rdpe_set_d (s->root[i]->drad, s->root[i]->frad);
        }
    }
  if (computed && s->output_config->goal == MPS_OUTPUT_GOAL_APPROXIMATE)
    {
      MPS_DEBUG (s, "Exiting since the approximation are computed and the goal is MPS_OUTPUT_GOAL_APPROXIMATE");
      goto exit_sub;
    }

  MPS_DEBUG (s, "s->mpwp = %ld, s->mpwp_max = %ld", s->mpwp, s->mpwp_max);
  MPS_DEBUG (s, "s->input_config->prec = %ld", s->active_poly->prec);

  /* == 7 ==  Start MPSolve loop */
  s->mpwp = mps_context_get_minimum_precision (s);

  /* Poor man GMP - machine precision detection. We need that min_prec is contained
   * in the interval [ DBL_MANT_DIG , 2 * DBL_MANT_DIG ]. This is probably true on most
   * architectures with the instruction above, but we want to be sure. */
  while (s->mpwp < DBL_MANT_DIG)
    s->mpwp <<= 1;
  while (s->mpwp > 2 * DBL_MANT_DIG)
    s->mpwp >>= 1;

  while (!computed && s->mpwp < s->mpwp_max)
    {
      s->mpwp *= 2;

      if (s->mpwp > s->mpwp_max)
        {
          s->mpwp = s->mpwp_max;
          s->over_max = true;
        }

      if (s->DOLOG)
        fprintf (s->logstr, "MAIN: mp_loop: mpwp=%ld\n", s->mpwp);

      /* == 7.1 ==   prepare data according to the current precision */
      mps_mp_set_prec (s, s->mpwp);
      mps_prepare_data (s, s->mpwp);

      /* == 7.2 ==   Call msolve with the current precision */
      if (s->DOLOG)
        fprintf (s->logstr, "MAIN: now call msolve nclust=%ld\n", s->clusterization->n);
      mps_msolve (s);
      s->lastphase = mp_phase;

      /* if (s->DOLOG) dump(logstr); */

      if (s->DOLOG)
        {                       /* count isolated zeros */
          nzc = 0;
          for (i = 0; i < s->n; i++)
            {
              if (s->root[i]->status == MPS_ROOT_STATUS_ISOLATED ||
                  s->root[i]->status == MPS_ROOT_STATUS_APPROXIMATED)
                nzc++;
            }
          fprintf (s->logstr, "MAIN: isolated %d roots\n", nzc);
          fprintf (s->logstr, "MAIN: after msolve check stop\n");
        }

      /* == 7.3 ==  Check the stop condition */
      computed = mps_check_stop (s);
      mps_mmodify (s, true);

      /* == 7.4 ==  reset the status vector */
      for (i = 0; i < s->n; i++)
        if (s->root[i]->status == MPS_ROOT_STATUS_NEW_CLUSTERED)
          s->root[i]->status = MPS_ROOT_STATUS_CLUSTERED;
    }

  /* == 8 ==  Check for termination */
  if (!computed)
    {
      if (s->over_max)
        {
          s->over_max = true;
          /* mps_error (s, "Reached the maximum working precision"); */
          MPS_DEBUG (s, "Reached the maximum working precision");
          goto exit_sub;
        }
      else
        {
          /* mps_warn (s, "Reached the input precision"); */
          MPS_DEBUG (s, "Reached the input precision");
          goto exit_sub;
        }
    }

exit_sub:

  /* == 9 ==  Check inclusion disks */
  if (computed && s->clusterization->n < s->n)
    if (!mps_inclusion (s))
      {
        mps_error (s, "Unable to compute inclusion disks");
        return;
      }

  /* == 10 ==  Refine roots */
  if (computed && !s->over_max && s->output_config->goal == MPS_OUTPUT_GOAL_APPROXIMATE)
    {
      s->lastphase = mp_phase;
      mps_improve (s);
    }

  /* == 11 == Check inclusions */
  /* This step is disabled since it cause problems with the lar* kind of polynomials. 
   * To be re-enabled a careful check of the necessary precision to avoid NULL DERIVATIVE
   * warnings should be implemented. 
   * if (s->active_poly->prec > 0)
   *   mps_validate_inclusions (s);
   */

  /* == 12 ==  Restore to highest used precision */
  if (s->lastphase == mp_phase)
    mps_restore_data (s);

#ifndef DISABLE_DEBUG
  {
    unsigned long time = mps_stop_timer (my_timer);
    MPS_DEBUG (s, "Total time using MPSolve: %lu ms", time);
  }
#endif

  /* Finally copy the roots ready for output */
  mps_copy_roots (s);
}