void mps_context_set_degree (mps_context * s, int n) { if (s->initialized) { if (s->secular_equation != NULL) { mps_secular_equation_free (s, MPS_POLYNOMIAL (s->secular_equation)); s->secular_equation = NULL; } mps_context_resize (s, n); } s->deg = s->n = n; /* Check if the numer of thread is greater of the number of roots, and in that case decrease it */ if (s->n_threads > s->deg) { MPS_DEBUG_WITH_INFO (s, "Adjusting concurrency limit to %d", s->deg); mps_thread_pool_set_concurrency_limit (s, s->pool, s->deg); } /* If a secular equation is present in the old context we should free it * now so it will be reallocated on the first call to the algorithm. */ if (s->secular_equation && MPS_POLYNOMIAL (s->secular_equation)->degree < n) mps_secular_equation_free (s, MPS_POLYNOMIAL (s->secular_equation)); s->secular_equation = NULL; }
int main (int argc, char * argv[]) { /* Create a new mps_context that will be used to solve a Quadratic polynomial * of the selected degree. */ mps_context * ctx = mps_context_new (); if (argc > 3 || argc < 2) { fprintf (stderr, "Usage: %s n [starting_file] \n" "\n" "Parameters: \n" " - n is the level of the Quadratic polynomial to solve\n\n" " - starting_file is an optional file with the approximations that shall be \n" " use as starting points.\n", argv[0]); return EXIT_FAILURE; } int n = atoi (argv[1]); if (n <= 0) { fprintf (stderr, "Please specify a positive integer as Quadratic level.\n"); return EXIT_FAILURE; } if (argc == 3) starting_file = argv[2]; mps_quadratic_poly *mp = mps_quadratic_poly_new (ctx, n); mps_context_set_input_poly (ctx, MPS_POLYNOMIAL (mp)); mps_context_select_algorithm (ctx, MPS_ALGORITHM_SECULAR_GA); mps_context_set_starting_phase (ctx, float_phase); mps_context_set_avoid_multiprecision (ctx, true); mps_mpsolve (ctx); mps_approximation ** apprs = mps_context_get_approximations (ctx); for (int i = 0; i < mps_context_get_degree (ctx); i++) { cplx_t value; mps_approximation_get_fvalue (ctx, apprs[i], value); printf (" "); cplx_out_str (stdout, value); printf ("\n"); mps_approximation_free (ctx, apprs[i]); } free (apprs); mps_quadratic_poly_free (ctx, MPS_POLYNOMIAL (mp)); mps_context_free (ctx); return EXIT_SUCCESS; }
/** * @brief Free a not more useful mps_context. * * @param s the mps_context struct pointer to free. */ void mps_context_free (mps_context * s) { if (s->initialized) mps_free_data (s); free (s->input_config); free (s->output_config); /* Check if secular equation or monomial poly need to be freed */ if (s->active_poly != NULL) mps_polynomial_free (s, s->active_poly); s->active_poly = NULL; if (s->secular_equation) mps_secular_equation_free (s, MPS_POLYNOMIAL (s->secular_equation)); /* Close input and output streams if they're not stdin, stdout and * stderr */ if (s->instr != stdin && s->instr != NULL) fclose (s->instr); if (s->logstr != stderr && s->logstr != stdout && s->logstr != NULL) fclose (s->logstr); free (s); }
/** * @brief Allocate a new Mandelbrot polynomial of the specified level. * * Mandelbrot polynomials are defined by recurrence as \f$P_0(z) = 0\f$, * \f$P_{k+1} = P_{k}(z)^2 + z\f$. The polynomial \f$P_k(z)\f$ is called the * \f$k\f$-th level Mandelbrot polynomial. * * @param ctx The current mps_context. * @param level The desired level for the Mandelbrot polynomial. * @return A pointer to a newly-allocated mps_mandelbrot_poly. */ mps_mandelbrot_poly * mps_mandelbrot_poly_new (mps_context * ctx, int level) { mps_mandelbrot_poly *mp = mps_new (mps_mandelbrot_poly); mps_polynomial *p = MPS_POLYNOMIAL (mp); mps_polynomial_init (ctx, p); mp->level = level; p->degree = pow(2, level) - 1; p->type_name = "mps_mandelbrot_poly"; p->structure = MPS_STRUCTURE_REAL_INTEGER; p->density = MPS_DENSITY_DENSE; /* Load methods */ p->fnewton = mps_mandelbrot_poly_fnewton; p->dnewton = mps_mandelbrot_poly_dnewton; p->mnewton = mps_mandelbrot_poly_mnewton; p->feval = mps_mandelbrot_poly_feval; p->deval = mps_mandelbrot_poly_deval; p->meval = mps_mandelbrot_poly_meval; p->dstart = mps_mandelbrot_poly_dstart; p->fstart = mps_mandelbrot_poly_fstart; p->free = mps_mandelbrot_poly_free; return mp; }
mps_monomial_matrix_poly* mps_monomial_matrix_poly_new (mps_context * ctx, int degree, int m, mps_boolean monic) { mps_monomial_matrix_poly * poly = mps_new (mps_monomial_matrix_poly); MPS_POLYNOMIAL (poly)->degree = degree; MPS_POLYNOMIAL (poly)->type_name = "mps_monomial_matrix_poly"; /* Matrix polynomial specific fields */ poly->monic = monic; poly->m = m; /* Allocation of the necessary memory to hold all the matrices. */ poly->P = malloc (sizeof (double) * poly->m * poly->m * (degree + 1)); /* Setup the overloaded methods for our matrix polynomial */ MPS_POLYNOMIAL (poly)->free = mps_monomial_matrix_poly_free; mps_polynomial_init (ctx, MPS_POLYNOMIAL (poly)); return poly; }
END_TEST START_TEST (rational_matrix_creation) { int degree = 6; int size = 14; int i, j, k; mps_context * ctx = mps_context_new (); mps_monomial_matrix_poly *mp = mps_monomial_matrix_poly_new (ctx, 6, 14, false); /* Set the coefficients in the matrices */ for (k = 0; k <= degree; k++) { mpq_t *mr, *mi; mr = mps_newv (mpq_t, size * size); mi = mps_newv (mpq_t, size * size); mpq_vinit (mr, size * size); mpq_vinit (mi, size * size); for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { mpq_set_si (MPS_MATRIX_ELEM (mr, i, j, size), i - j, i + j + 1); mpq_canonicalize (MPS_MATRIX_ELEM (mr, i, j, size)); mpq_set_si (MPS_MATRIX_ELEM (mi, i, j, size), 2 * i + 3 * j + 5, i + 2 * j + 1); mpq_canonicalize (MPS_MATRIX_ELEM (mi, i, j, size)); } } mps_monomial_matrix_poly_set_coefficient_q (ctx, mp, k, mr, mi); mpq_vclear (mr, size * size); mpq_vclear (mi, size * size); free (mr); free (mi); } mps_monomial_matrix_poly_free (ctx, MPS_POLYNOMIAL (mp)); mps_context_free (ctx); }
/** * @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); }
/** * @brief Free a not more useful mps_context. * * @param s the mps_context struct pointer to free. */ void mps_context_free (mps_context * s) { /* Close input and output streams if they're not stdin, stdout and * stderr. For the case in which this context will re-used, set them * to their default values. */ if (s->instr != stdin && s->instr != NULL) fclose (s->instr); if (s->logstr != stderr && s->logstr != stdout && s->logstr != NULL) fclose (s->logstr); s->instr = stdin; s->logstr = stderr; /* There's no need to resize bmpc since they will be allocated on demand. * We free them here to correct bad assumptions on the size of this * vector. */ free (s->bmpc); s->bmpc = NULL; pthread_mutex_lock (&context_factory_mutex); if (context_factory_size < MPS_CONTEXT_FACTORY_MAXIMUM_SIZE) { context_factory = mps_realloc (context_factory, sizeof(mps_context*) * (context_factory_size + 1)); context_factory[context_factory_size++] = s; pthread_mutex_unlock (&context_factory_mutex); return; } pthread_mutex_unlock (&context_factory_mutex); if (s->initialized) mps_free_data (s); mps_thread_pool_free (s, s->pool); free (s->input_config); free (s->output_config); s->active_poly = NULL; if (s->secular_equation) mps_secular_equation_free (s, MPS_POLYNOMIAL (s->secular_equation)); free (s); }
/** * @brief Set active polynomial as a integer coefficient * polynomial of degree <code>n</code> with coefficient exactly * determined by components of vector coeff. * * Precisely, if \f${\mathrm coeff}\f$ is a vector of \f$n+1\f$ components, * \f[ * p(x) = \sum_{i = 0}^{n} {\mathrm coeff}_i x^i * \f] */ int mps_context_set_poly_i (mps_context * s, int *coeff, long unsigned int n) { int i; /* Allocate data in mps_context to hold the polynomial of degree n */ mps_monomial_poly * p = mps_monomial_poly_new (s, n); /* Fill polynomial */ for (i = 0; i <= n; i++) { mpq_set_si (p->initial_mqp_r[i], coeff[i], 1U); } mps_context_set_input_poly (s, MPS_POLYNOMIAL (p)); return 0; }
/** * @brief Set active polynomial as a real floating point coefficient * polynomial of degree <code>n</code> with coefficient exactly * determined by components of vector coeff. * * Precisely, if \f${\mathrm coeff}\f$ is a vector of \f$n+1\f$ components, * \f[ * p(x) = \sum_{i = 0}^{n} {\mathrm coeff}_i x^i * \f] */ int mps_context_set_poly_d (mps_context * s, cplx_t * coeff, long unsigned int n) { int i; /* Allocate space for a polynomial of degree n */ mps_monomial_poly * p = mps_monomial_poly_new (s, n); /* Fill polynomial coefficients */ for (i = 0; i <= n; i++) { mps_monomial_poly_set_coefficient_d (s, p, i, cplx_Re (coeff[i]), cplx_Im (coeff[i])); } mps_context_set_input_poly (s, MPS_POLYNOMIAL (p)); return 0; }
/** * @brief Caller for mps_solve routine. * * Since fortran complex are * identical to internal mpsolve cplx_t complex type, i.e. * two double in a struct, we can simply cast silently the * arguments of the fortran routine. */ void mps_roots_ (int * n, cplx_t * coeff, cplx_t * roots) { /* Create a new mps_context and a new polynomial */ mps_context *s = mps_context_new (); mps_monomial_poly * p = mps_monomial_poly_new (s, *n); int i; for (i = 0; i <= *n; i++) mps_monomial_poly_set_coefficient_d (s, p, i, cplx_Re (coeff[i]), cplx_Im (coeff[i])); mps_context_set_input_poly (s, MPS_POLYNOMIAL (p)); /* Set the output precision to DBL_EPSILON and the default goal * to approximate. Try to find all the possible digits representable * in floating point. */ mps_context_set_output_prec (s, 53); mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_APPROXIMATE); mps_mpsolve (s); mps_context_get_roots_d (s, &roots, NULL); mps_context_free (s); }
/** * @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'; }
/** * @brief Setup vectors and variables */ MPS_PRIVATE void mps_setup (mps_context * s) { int i; mps_polynomial *p = s->active_poly; mpf_t mptemp; mpc_t mptempc; if (s->DOLOG) { /* fprintf (s->logstr, "Goal = %5s\n", s->goal); */ /* fprintf (s->logstr, "Data type = %3s\n", s->data_type); */ fprintf (s->logstr, "Degree = %d\n", s->n); fprintf (s->logstr, "Input prec. = %ld digits\n", (long)(s->active_poly->prec * LOG10_2)); fprintf (s->logstr, "Output prec. = %ld digits\n", (long)(s->output_config->prec * LOG10_2)); } /* setup temporary vectors */ if (MPS_IS_MONOMIAL_POLY (p) && MPS_DENSITY_IS_SPARSE (s->active_poly->density)) { mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p); for (i = 0; i <= p->degree; i++) { mp->fap[i] = 0.0; mp->fpr[i] = 0.0; rdpe_set (mp->dap[i], rdpe_zero); cplx_set (mp->fpc[i], cplx_zero); rdpe_set (mp->dpr[i], rdpe_zero); cdpe_set (mp->dpc[i], cdpe_zero); } } /* Indexes of the first (and only) cluster start from * 0 and reach n */ mps_cluster_reset (s); /* set input and output epsilon */ rdpe_set_2dl (s->eps_in, 1.0, 1 - s->active_poly->prec); rdpe_set_2dl (s->eps_out, 1.0, 1 - s->output_config->prec); /* precision of each root */ for (i = 0; i < s->n; i++) s->root[i]->wp = 53; /* output order info */ for (i = 0; i < s->n; i++) s->order[i] = i; /* reset root counts */ s->count[0] = s->count[1] = s->count[2] = 0; /* compute DPE approximations */ if (MPS_IS_MONOMIAL_POLY (p)) { mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p); /* init temporary mp variables */ mpf_init2 (mptemp, DBL_MANT_DIG); mpc_init2 (mptempc, DBL_MANT_DIG); /* main loop */ s->skip_float = false; for (i = 0; i <= s->n; i++) { if (MPS_DENSITY_IS_SPARSE (s->active_poly->density) && !mp->spar[i]) continue; if (MPS_STRUCTURE_IS_REAL (s->active_poly->structure)) { if (MPS_STRUCTURE_IS_RATIONAL (s->active_poly->structure) || MPS_STRUCTURE_IS_INTEGER (s->active_poly->structure)) { mpf_set_q (mptemp, mp->initial_mqp_r[i]); mpf_get_rdpe (mp->dpr[i], mptemp); /*#G GMP 2.0.2 bug begin */ if (rdpe_sgn (mp->dpr[i]) != mpq_sgn (mp->initial_mqp_r[i])) rdpe_neg_eq (mp->dpr[i]); /*#G GMP bug end */ } if (MPS_STRUCTURE_IS_FP (s->active_poly->structure)) mpf_get_rdpe (mp->dpr[i], mpc_Re (mp->mfpc[i])); cdpe_set_e (mp->dpc[i], mp->dpr[i], rdpe_zero); /* compute dap[i] and check for float phase */ rdpe_abs (mp->dap[i], mp->dpr[i]); rdpe_abs (mp->dap[i], mp->dpr[i]); if (rdpe_gt (mp->dap[i], rdpe_maxd) || rdpe_lt (mp->dap[i], rdpe_mind)) s->skip_float = true; } else if (MPS_STRUCTURE_IS_COMPLEX (s->active_poly->structure)) { if (MPS_STRUCTURE_IS_RATIONAL (s->active_poly->structure) || MPS_STRUCTURE_IS_INTEGER (s->active_poly->structure)) { mpc_set_q (mptempc, mp->initial_mqp_r[i], mp->initial_mqp_i[i]); mpc_get_cdpe (mp->dpc[i], mptempc); /*#G GMP 2.0.2 bug begin */ if (rdpe_sgn (cdpe_Re (mp->dpc[i])) != mpq_sgn (mp->initial_mqp_r[i])) rdpe_neg_eq (cdpe_Re (mp->dpc[i])); if (rdpe_sgn (cdpe_Im (mp->dpc[i])) != mpq_sgn (mp->initial_mqp_i[i])) rdpe_neg_eq (cdpe_Im (mp->dpc[i])); /*#G GMP bug end */ } else if (MPS_STRUCTURE_IS_FP (s->active_poly->structure)) mpc_get_cdpe (mp->dpc[i], mp->mfpc[i]); /* compute dap[i] */ cdpe_mod (mp->dap[i], mp->dpc[i]); if (rdpe_gt (mp->dap[i], rdpe_maxd) || rdpe_lt (mp->dap[i], rdpe_mind)) s->skip_float = true; } } /* free temporary mp variables */ mpf_clear (mptemp); mpc_clear (mptempc); /* adjust input data type */ if (MPS_STRUCTURE_IS_FP (s->active_poly->structure) && s->skip_float) s->active_poly->structure = MPS_STRUCTURE_IS_REAL (s->active_poly->structure) ? MPS_STRUCTURE_REAL_BIGFLOAT : MPS_STRUCTURE_COMPLEX_BIGFLOAT; /* prepare floating point vectors */ if (!s->skip_float) for (i = 0; i <= MPS_POLYNOMIAL (p)->degree; i++) { if (MPS_DENSITY_IS_SPARSE (s->active_poly->density) || !mp->spar[i]) continue; if (MPS_STRUCTURE_IS_REAL (s->active_poly->structure)) { mp->fpr[i] = rdpe_get_d (mp->dpr[i]); mp->fap[i] = fabs (mp->fpr[i]); cplx_set_d (mp->fpc[i], mp->fpr[i], 0.0); } else { cdpe_get_x (mp->fpc[i], mp->dpc[i]); mp->fap[i] = cplx_mod (mp->fpc[i]); } } } }