/** * @brief The same of <code>mps_raise_data()</code> but using * raw routines of GMP, that will not change allocations. * * @param s The <code>mps_context</code> of the computation. * @param prec The desired precision. */ void mps_raise_data_raw (mps_context * s, long int prec) { int k; if (!MPS_IS_MONOMIAL_POLY (s->active_poly)) return; mps_monomial_poly *p = MPS_MONOMIAL_POLY (s->active_poly); /* raise the precision of mroot */ for (k = 0; k < s->n; k++) mpc_set_prec_raw (s->root[k]->mvalue, prec); /* raise the precision of mfpc */ if (MPS_IS_MONOMIAL_POLY (s->active_poly)) for (k = 0; k < s->n + 1; k++) mpc_set_prec_raw (p->mfpc[k], prec); /* Raise the precision of sparse vectors */ if (MPS_DENSITY_IS_SPARSE (s->active_poly->density)) for (k = 0; k < s->n; k++) if (p->spar[k + 1]) mpc_set_prec_raw (p->mfppc[k], prec); /* raise the precision of auxiliary variables */ for (k = 0; k < s->n + 1; k++) { mpc_set_prec_raw (s->mfpc1[k], prec); mpc_set_prec_raw (s->mfppc1[k], prec); } }
/** * @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 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'; }
int main (int argc, char **argv) { #if HAVE_GRAPHICAL_DEBUGGER mps_boolean graphic_debug = false; #endif /* Create a new status */ s = mps_context_new (); /* Associate the SIGUSR1 signal to the mps_dump () function */ #ifndef __WINDOWS signal (SIGUSR1, status); #endif /* Leave this value to -1 if not precision has been enforced * by the user. Otherwise, override the polynomial input * precision. */ long int input_precision = -1; char * inline_poly = NULL; FILE *infile; /* Parse options */ mps_opt *opt; mps_phase phase = no_phase; /* This will be true if the user has explicitely selected the algorithm, otherwise we will be using our own heuristic. */ mps_boolean explicit_algorithm_selection = false; opt = NULL; while ((mps_getopts (&opt, &argc, &argv, MPSOLVE_GETOPT_STRING))) { switch (opt->optchar) { case 'l': { FILE* logstr = fopen (opt->optvalue, "w"); if (!logstr) mps_error (s, "Cannot open selected log file."); mps_context_set_log_stream (s, logstr); } break; case 'v': #ifdef HAVE_CONFIG_H printf (PACKAGE_STRING "\n"); #else printf ("MPSolve 3.1.5\n"); #endif mps_context_free (s); exit (EXIT_SUCCESS); case 'r': mps_context_select_starting_strategy (s, MPS_STARTING_STRATEGY_RECURSIVE); break; case 'O': /* Select the desired output format */ if (!opt->optvalue) { mps_error (s, "An argument is needed for option 'O'"); break; } switch (*opt->optvalue) { case 'f': mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_FULL); break; case 'b': mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_BARE); break; case 'g': mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_GNUPLOT); if (*(opt->optvalue + 1) == 'f') { mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_GNUPLOT_FULL); s->gnuplot_format = "xyerrorbars"; } else if (*(opt->optvalue + 1) == 'p') { mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_GNUPLOT_FULL); s->gnuplot_format = "points"; } break; case 'v': mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_VERBOSE); break; case 'c': mps_context_set_output_format (s, MPS_OUTPUT_FORMAT_COMPACT); break; default: mps_error (s, "The selected output format is not supported"); break; } break; /* select search set */ case 'S': switch (*opt->optvalue) { case 'a': s->output_config->search_set = MPS_SEARCH_SET_COMPLEX_PLANE; break; case 'r': s->output_config->search_set = MPS_SEARCH_SET_POSITIVE_REAL_PART; break; case 'l': s->output_config->search_set = MPS_SEARCH_SET_NEGATIVE_REAL_PART; break; case 'u': s->output_config->search_set = MPS_SEARCH_SET_POSITIVE_IMAG_PART; break; case 'd': s->output_config->search_set = MPS_SEARCH_SET_NEGATIVE_IMAG_PART; break; case 'i': s->output_config->search_set = MPS_SEARCH_SET_UNITARY_DISC; break; case 'o': s->output_config->search_set = MPS_SEARCH_SET_UNITARY_DISC_COMPL; break; case 'R': s->output_config->search_set = MPS_SEARCH_SET_REAL; break; case 'I': s->output_config->search_set = MPS_SEARCH_SET_IMAG; break; case 'U': s->output_config->search_set = MPS_SEARCH_SET_CUSTOM; break; default: mps_error (s, "Bad search set switch: ", opt->optvalue, ", use a|r|l|u|d|i|o|R|I|U"); } if (strlen (opt->optvalue) != 1) mps_error (s, "Bad set: ", opt->optvalue); break; /* select multiplicity */ case 'M': switch (*opt->optvalue) { case '+': s->output_config->multiplicity = true; break; case '-': s->output_config->multiplicity = false; break; default: mps_error (s, "Bad multiplicity switch: ", opt->optvalue, ", use +|-"); } if (strlen (opt->optvalue) != 3) mps_error (s, "Bad multiplicity option: ", opt->optvalue); break; /* detection */ case 'D': switch (*opt->optvalue) { case 'n': s->output_config->root_properties = MPS_OUTPUT_PROPERTY_NONE; break; case 'r': s->output_config->root_properties = MPS_OUTPUT_PROPERTY_REAL; break; case 'i': s->output_config->root_properties = MPS_OUTPUT_PROPERTY_IMAGINARY; break; case 'b': s->output_config->root_properties = MPS_OUTPUT_PROPERTY_REAL | MPS_OUTPUT_PROPERTY_IMAGINARY; break; default: mps_error (s, "Bad detection switch: ", opt->optvalue, ", use n|r|i|b"); } if (strlen (opt->optvalue) != 1) mps_error (s, "Bad detection option: ", opt->optvalue); break; /* I/O streams */ case 'R': s->rtstr = fopen (opt->optvalue, "r"); if (s->rtstr == NULL) mps_error (s, "Cannot open roots file: ", opt->optvalue); s->resume = true; break; /* Additional checks */ case 'C': switch (*opt->optvalue) { case 'R': s->chkrad = true; break; case 'r': s->chkrad = false; break; default: mps_error (s, "Bad check switch: ", opt->optvalue, ", use R|r"); } if (strlen (opt->optvalue) != 1) mps_error (s, "Bad check option: ", opt->optvalue); break; case 'a': explicit_algorithm_selection = true; switch (*opt->optvalue) { case 'u': mps_context_select_algorithm (s, MPS_ALGORITHM_STANDARD_MPSOLVE); break; case 's': mps_context_select_algorithm (s, MPS_ALGORITHM_SECULAR_GA); break; default: mps_error (s, "The selected algorithm is not supported"); break; } break; case 'b': mps_context_set_jacobi_iterations (s, true); break; case 'c': mps_context_set_crude_approximation_mode (s, true); break; case 'o': mps_context_set_output_prec (s, (atoi (opt->optvalue)) * LOG2_10 + 1); break; case 'i': input_precision = atoi (opt->optvalue) * LOG2_10; break; case 'G': switch (*opt->optvalue) { case 'a': mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_APPROXIMATE); break; case 'i': mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_ISOLATE); break; case 'c': mps_context_set_output_goal (s, MPS_OUTPUT_GOAL_COUNT); break; default: mps_error (s, "The selected goal does not exists"); break; } break; case 'p': inline_poly = strdup (opt->optvalue); break; #ifndef DISABLE_DEBUG case 'd': mps_context_add_debug_domain (s, MPS_DEBUG_INFO); if (!opt->optvalue) break; /* If debugging was enabled, parse debug_level */ while (*opt->optvalue) { char output[255]; switch (*opt->optvalue++) { case 't': mps_context_add_debug_domain (s, MPS_DEBUG_TRACE); break; case 'a': mps_context_add_debug_domain (s, MPS_DEBUG_APPROXIMATIONS); break; case 'c': mps_context_add_debug_domain (s, MPS_DEBUG_CLUSTER); break; case 'i': mps_context_add_debug_domain (s, MPS_DEBUG_IMPROVEMENT); break; case 'w': mps_context_add_debug_domain (s, MPS_DEBUG_TIMINGS); break; case 'o': mps_context_add_debug_domain (s, MPS_DEBUG_IO); break; case 'm': mps_context_add_debug_domain (s, MPS_DEBUG_MEMORY); break; case 'f': mps_context_add_debug_domain (s, MPS_DEBUG_FUNCTION_CALLS); break; case 'p': mps_context_add_debug_domain (s, MPS_DEBUG_PACKETS); break; case 'r': mps_context_add_debug_domain (s, MPS_DEBUG_REGENERATION); break; default: sprintf (output, "Unrecognized debug option: %c", *(opt->optvalue - 1)); mps_error (s, output); break; } } break; #endif #if HAVE_GRAPHICAL_DEBUGGER case 'x': graphic_debug = true; break; #endif case 's': if (opt->optvalue == NULL) { mps_error (s, "You need to specify a valid file with -s"); break; } else { s->rtstr = fopen (opt->optvalue, "r"); if (! s->rtstr) { mps_error (s, "Cannot open the given file: %s", opt->optvalue); break; } else { mps_context_select_starting_strategy (s, MPS_STARTING_STRATEGY_FILE); } } break; case 't': switch (opt->optvalue[0]) { case 'f': phase = float_phase; break; case 'd': phase = dpe_phase; break; default: usage (s, argv[0]); } break; case 'j': mps_thread_pool_set_concurrency_limit (s, NULL, atoi (opt->optvalue)); s->n_threads = atoi (opt->optvalue); break; default: usage (s, argv[0]); break; } } #if HAVE_GRAPHICAL_DEBUGGER if (graphic_debug) { /* Init GTK only if graphic debug is requested. In all other case is unnecessary * and will waste computational time that is likely to bias benchmarks. */ gtk_init (&argc, &argv); logger = mps_iteration_logger_new (); mps_iteration_logger_set_mps_context (logger, s); g_signal_connect (GTK_WIDGET (logger), "delete_event", G_CALLBACK (on_iteration_logger_destroy), NULL); gtk_widget_show_all (GTK_WIDGET (logger)); } #endif if (mps_context_has_errors (s)) { mps_print_errors (s); return EXIT_FAILURE; } if (argc > 2) usage (s, argv[0]); /* If no file is provided use standard input */ if (inline_poly) { // poly = mps_parse_inline_poly_from_string (s, inline_poly); mps_abstract_input_stream * stream = (mps_abstract_input_stream *) mps_memory_file_stream_new (inline_poly); poly = mps_monomial_yacc_parser (s, stream); if (mps_context_has_errors (s)) { mps_print_errors (s); return EXIT_FAILURE; } free (inline_poly); } else { if (argc == 1) infile = stdin; else infile = fopen (argv[1], "r"); if (!infile) { mps_error (s, "Cannot open input file for read, aborting."); mps_print_errors (s); return EXIT_FAILURE; } /* Parse the input stream and if a polynomial is given as output, * allocate also a secular equation to be used in regeneration */ poly = mps_parse_stream (s, infile); } if (!poly) { mps_error (s, "Error while parsing the polynomial, aborting."); mps_print_errors (s); return EXIT_FAILURE; } else mps_context_set_input_poly (s, poly); /* Override input precision if needed */ if (input_precision >= 0) mps_polynomial_set_input_prec (s, poly, input_precision); /* Perform some heuristic for the algorithm selection, but only if the user * hasn't explicitely selected one. */ if (! explicit_algorithm_selection) { mps_context_select_algorithm (s, (MPS_IS_MONOMIAL_POLY (poly) && MPS_DENSITY_IS_SPARSE (poly->density)) ? MPS_ALGORITHM_STANDARD_MPSOLVE : MPS_ALGORITHM_SECULAR_GA ); } /* Close the file if it's not stdin */ if (argc == 2 && ! inline_poly) fclose (infile); /* Select the starting phase according to user input */ mps_context_set_starting_phase (s, phase); /* Solve the polynomial */ #if HAVE_GRAPHICAL_DEBUGGER if (graphic_debug) { mps_mpsolve_async (s, cleanup_context, NULL); gtk_main (); } else { #endif mps_mpsolve (s); cleanup_context (s, NULL); #if HAVE_GRAPHICAL_DEBUGGER } #endif }
/** * @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]); } } } }