Ejemplo n.º 1
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);
}
Ejemplo n.º 2
0
/**
 * @brief Raise precision performing a real computation of the data.
 *
 * @param s The <code>mps_context</code> of the computation.
 * @param prec The desired precision.
 * @return The precision set (that may be different from the one requested
 * since GMP works only with precision divisible by 64bits.
 */
long int
mps_raise_data (mps_context * s, long int prec)
{
  int k;
  mps_polynomial *p = s->active_poly;

  /* raise the precision of  mroot */
  for (k = 0; k < s->n; k++)
    mpc_set_prec (s->root[k]->mvalue, prec);

  /* raise the precision of auxiliary variables */
  for (k = 0; k < s->n + 1; k++)
    {
      mpc_set_prec (s->mfpc1[k], prec);
      mpc_set_prec (s->mfppc1[k], prec);
    }

  return mps_polynomial_raise_data (s, p, prec);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
mps_boolean
mps_chebyshev_poly_meval (mps_context * ctx, mps_polynomial * poly, mpc_t x, mpc_t value, rdpe_t error)
{
  long int wp = mpc_get_prec (x);

  /* Lower the working precision in case of limited precision coefficients
   * in the input polynomial. */
  if (poly->prec > 0 && poly->prec < wp)
    wp = poly->prec;

  mps_chebyshev_poly * cpoly = MPS_CHEBYSHEV_POLY (poly);
  int i;

  mpc_t t0, t1, ctmp, ctmp2;
  rdpe_t ax, rtmp, rtmp2;

  mpc_rmod (ax, x);
  rdpe_set (error, rdpe_zero);

  /* Make sure that we have sufficient precision to perform the computation */
  mps_polynomial_raise_data (ctx, poly, wp);

  mpc_init2 (t0, wp);
  mpc_init2 (t1, wp);
  mpc_init2 (ctmp, wp);
  mpc_init2 (ctmp2, wp);

  mpc_set (value, cpoly->mfpc[0]);
  mpc_set_ui (t0, 1U, 0U);
  if (poly->degree == 0)
    {
      return true;
    }

  mpc_set (t1, x);
  mpc_mul (ctmp, cpoly->mfpc[1], x);
  mpc_add_eq (value, ctmp);

  mpc_rmod (rtmp, ctmp);
  rdpe_add_eq (error, rtmp);

  for (i = 2; i <= poly->degree; i++)
    {
      mpc_mul (ctmp, x, t1);
      mpc_mul_eq_ui (ctmp, 2U);
      mpc_rmod (rtmp, ctmp);
      mpc_sub_eq (ctmp, t0);

      mpc_rmod (rtmp2, t0);
      rdpe_add_eq (rtmp, rtmp2);

      mpc_mul (ctmp2, ctmp, cpoly->mfpc[i]);
      mpc_add_eq (value, ctmp2);

      rdpe_mul_eq (rtmp, ax);
      rdpe_add_eq (error, rtmp);

      mpc_set (t0, t1);
      mpc_set (t1, ctmp);
    }

  mpc_clear (t0);
  mpc_clear (t1);
  mpc_clear (ctmp);
  mpc_clear (ctmp2);

  rdpe_set_2dl (rtmp, 2.0, -wp);
  rdpe_mul_eq (error, rtmp);

  return true;
}