示例#1
0
文件: improve.c 项目: akobel/MPSolve
static int
get_approximated_bits (mps_approximation * appr)
{
  rdpe_t module;

  mpc_rmod (module, appr->mvalue);

  return (rdpe_log (module) - rdpe_log (appr->drad)) / LOG2 - 1;
}
示例#2
0
文件: improve.c 项目: akobel/MPSolve
static rdpe_t *
evaluate_root_conditioning (mps_context * ctx, mps_polynomial * p, mps_approximation ** appr, int n)
{
  int i;

  rdpe_t * root_conditioning = rdpe_valloc (n);

  for (i = 0; i < n; i++)
    {
      mpc_t value;
      rdpe_t error, module;
      mpc_init2 (value, appr[i]->wp);

      mps_polynomial_meval (ctx, p, appr[i]->mvalue, value, error);
      mpc_rmod (module, value);

      /* Get the relative error of this evaluation */
      if (!rdpe_eq_zero (module))
        rdpe_div_eq (error, module);
      else
        rdpe_set_d (error, DBL_EPSILON * p->degree);

      /* log2(error) + wp - log(n) is a good estimate of log(k) */
      rdpe_set_d (root_conditioning[i], rdpe_log (error) / LOG2 + appr[i]->wp - log2 (n));
      rdpe_exp_eq (root_conditioning[i]);

      rdpe_div_eq (root_conditioning[i], appr[i]->drad);

      mpc_clear (value);
    }

  return root_conditioning;
}
示例#3
0
文件: improve.c 项目: akobel/MPSolve
/**
 * @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);
}
示例#4
0
文件: main.c 项目: robol/MPSolve
/**
 * @brief Check consistency of data and makes some basic adjustments.
 *
 * This routine check, for example, if there are zero roots in the polynomial
 * (i.e. no costant term) and deflates the polynomial if necessary (shifting
 * the coefficients).
 *
 * It sets the value of the parameter <code>which_case</code> to <code>'f'</code>
 * if a floating point phase is enough, or to <code>'d'</code> if
 * a <code>dpe</code> phase is needed.
 *
 * @param s The <code>mps_context</code> associated with the current computation.
 * @param which_case the address of the variable which_case;
 */
MPS_PRIVATE void
mps_check_data (mps_context * s, char *which_case)
{
  rdpe_t min_coeff, max_coeff, tmp;
  mps_monomial_poly *p = NULL;
  int i;

  /* case of user-defined polynomial */
  if (! MPS_IS_MONOMIAL_POLY (s->active_poly))
    {
      if (s->output_config->multiplicity)
        mps_error (s,
                   "Multiplicity detection not yet implemented for user polynomial");
      if (s->output_config->root_properties)
        mps_error (s,
                   "Real/imaginary detection not yet implemented for user polynomial");
      *which_case = 'd';
      return;
    }
  else
    p = MPS_MONOMIAL_POLY (s->active_poly);

  /* Check consistency of input */
  if (rdpe_eq (p->dap[s->n], rdpe_zero))
    {
      mps_warn (s, "The leading coefficient is zero");
      do
        (s->n)--;
      while (rdpe_eq (p->dap[s->n], rdpe_zero));

      MPS_POLYNOMIAL (p)->degree = s->n;
    }

  /* Compute min_coeff */
  if (rdpe_lt (p->dap[0], p->dap[s->n]))
    rdpe_set (min_coeff, p->dap[0]);
  else
    rdpe_set (min_coeff, p->dap[s->n]);

  /* Compute max_coeff and its logarithm */
  rdpe_set (max_coeff, p->dap[0]);
  for (i = 1; i <= s->n; i++)
    if (rdpe_lt (max_coeff, p->dap[i]))
      rdpe_set (max_coeff, p->dap[i]);
  s->lmax_coeff = rdpe_log (max_coeff);

  /*  Multiplicity and sep */
  if (s->output_config->multiplicity)
    {
      if (MPS_STRUCTURE_IS_INTEGER (s->active_poly->structure))
        {
          mps_compute_sep (s);
        }
      else if (MPS_STRUCTURE_IS_RATIONAL (s->active_poly->structure))
        {
          mps_warn (s, "The multiplicity option has not been yet implemented");
          s->sep = 0.0;
        }
      else
        {
          mps_warn (s, "The input polynomial has neither integer nor rational");
          mps_warn (s, " coefficients: unable to compute multiplicities");
          s->sep = 0.0;
        }
    }

  /* Real/Imaginary detection */
  if (s->output_config->root_properties ||
      s->output_config->search_set == MPS_SEARCH_SET_REAL ||
      s->output_config->search_set == MPS_SEARCH_SET_IMAG)
    {
      if (MPS_STRUCTURE_IS_INTEGER (s->active_poly->structure))
        {
          mps_compute_sep (s);
        }
      else if (MPS_STRUCTURE_IS_RATIONAL (s->active_poly->structure))
        {
          mps_error (s,
                     "The real/imaginary option has not been yet implemented for rational input");
          return;
        }
      else
        {
          mps_error (s, "The input polynomial has neither integer nor rational "
                     "coefficients: unable to perform real/imaginary options");
          return;
        }
    }

  /* Select cases (dpe or floating point)
   * First normalize the polynomial (only the float version) */
  rdpe_div (tmp, max_coeff, min_coeff);
  rdpe_mul_eq_d (tmp, (double)(s->n + 1));
  rdpe_mul_eq (tmp, rdpe_mind);
  rdpe_div_eq (tmp, rdpe_maxd);

  if (rdpe_lt (tmp, rdpe_one))
    {
      mpc_t m_min_coeff;
      cdpe_t c_min_coeff;

      /* if  (n+1)*max_coeff/min_coeff < dhuge/dtiny -  float case */
      *which_case = 'f';
      rdpe_mul_eq (min_coeff, max_coeff);
      rdpe_mul (tmp, rdpe_mind, rdpe_maxd);
      rdpe_div (min_coeff, tmp, min_coeff);
      rdpe_sqrt_eq (min_coeff);

      rdpe_set (cdpe_Re (c_min_coeff), min_coeff);
      rdpe_set (cdpe_Im (c_min_coeff), rdpe_zero);

      mpc_init2 (m_min_coeff, mpc_get_prec (p->mfpc[0]));
      mpc_set_cdpe (m_min_coeff, c_min_coeff);

      /* min_coeff = sqrt(dhuge*dtiny/(min_coeff*max_coeff))
       * NOTE: This is enabled for floating point polynomials only
       * for the moment, but it may work nicely also for other representations. */
      {
        for (i = 0; i <= s->n; i++)
          {
            /* Multiply the MP leading coefficient */
            mpc_mul_eq (p->mfpc[i], m_min_coeff);

            rdpe_mul (tmp, p->dap[i], min_coeff);
            rdpe_set (p->dap[i], tmp);
            p->fap[i] = rdpe_get_d (tmp);

            mpc_get_cdpe (p->dpc[i], p->mfpc[i]);
            cdpe_get_x (p->fpc[i], p->dpc[i]);
          }
      }

      mpc_clear (m_min_coeff);
    }
  else
    *which_case = 'd';
}