Пример #1
0
/**
 * @brief Update the MP version of the roots to the latest and greatest approximations.
 *
 * @param s A pointer to the current mps_context.
 */
MPS_PRIVATE void
mps_copy_roots (mps_context * s)
{
  int i;

  MPS_DEBUG_THIS_CALL (s);

  switch (s->lastphase)
    {
    case no_phase:
      mps_error (s, "Nothing to copy");
      break;

    case float_phase:
      if (s->DOSORT)
        mps_fsort (s);
      for (i = 0; i < s->n; i++)
        {
          mpc_set_prec (s->root[i]->mvalue, DBL_MANT_DIG);
          mpc_set_cplx (s->root[i]->mvalue, s->root[i]->fvalue);
          rdpe_set_d (s->root[i]->drad, s->root[i]->frad);
        }
      break;

    case dpe_phase:
      if (s->DOSORT)
        mps_dsort (s);
      for (i = 0; i < s->n; i++)
        {
          mpc_set_prec (s->root[i]->mvalue, DBL_MANT_DIG);
          mpc_set_cdpe (s->root[i]->mvalue, s->root[i]->dvalue);
        }
      break;

    case mp_phase:
      if (s->DOSORT)
        mps_msort (s);
      break;
    }
}
Пример #2
0
void
mps_maberth_s_wl (mps_context * s, int j, mps_cluster * cluster, mpc_t abcorr,
                  pthread_mutex_t * aberth_mutexes)
{
  int k;
  mps_root * root;
  cdpe_t z, temp;
  mpc_t diff, mroot;
  
  mpc_init2 (mroot, s->mpwp);
  mpc_init2 (diff, s->mpwp);

  pthread_mutex_lock (&aberth_mutexes[j]);
  mpc_set (mroot, s->root[j]->mvalue);
  pthread_mutex_unlock (&aberth_mutexes[j]);

  cdpe_set (temp, cdpe_zero);
  for (root = cluster->first; root != NULL; root = root->next)
    {
      k = root->k;
      if (k == j)
        continue;

      pthread_mutex_lock (&aberth_mutexes[k]);
      mpc_sub (diff, mroot, s->root[k]->mvalue);
      pthread_mutex_unlock (&aberth_mutexes[k]);
      mpc_get_cdpe (z, diff);

      if (cdpe_eq_zero(z))
        continue;

      cdpe_inv_eq (z);
      cdpe_add_eq (temp, z);
    }
  mpc_set_cdpe (abcorr, temp);

  mpc_clear (mroot);
  mpc_clear (diff);
}
Пример #3
0
/**
 * @brief Compute Aberth correction for j-th root, without
 * selective correction.
 */
void
mps_maberth (mps_context * s, mps_approximation * root, mpc_t abcorr)
{
  int i;
  cdpe_t z, temp;
  mpc_t diff;

  mpc_init2 (diff, s->mpwp);

  cdpe_set (temp, cdpe_zero);
  for (i = 0; i < s->n; i++)
    {
      if (s->root[i] == root)
        continue;
      mpc_sub (diff, root->mvalue, s->root[i]->mvalue);
      mpc_get_cdpe (z, diff);
      cdpe_inv_eq (z);
      cdpe_add_eq (temp, z);
    }
  mpc_set_cdpe (abcorr, temp);

  mpc_clear (diff);
}
Пример #4
0
/**
 * @brief Compute Aberth correction for the j-th root,
 * but only with other roots of the <code>jc</code>-th
 * cluster.
 */
void
mps_maberth_s (mps_context * s, mps_approximation * ab_root, mps_cluster * cluster, mpc_t abcorr)
{
  mps_root * root;
  cdpe_t z, temp;
  mpc_t diff;

  mpc_init2 (diff, s->mpwp);

  cdpe_set (temp, cdpe_zero);
  for (root = cluster->first; root != NULL; root = root->next)
    {
      mps_approximation * appr = s->root[root->k];
      if (appr == ab_root)
        continue;
      mpc_sub (diff, ab_root->mvalue, appr->mvalue);
      mpc_get_cdpe (z, diff);
      cdpe_inv_eq (z);
      cdpe_add_eq (temp, z);
    }
  mpc_set_cdpe (abcorr, temp);

  mpc_clear (diff);
}
Пример #5
0
/**
 * @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';
}
Пример #6
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);
}