1 /*
2  * This file is part of MPSolve 3.2.1
3  *
4  * Copyright (C) 2001-2020, Dipartimento di Matematica "L. Tonelli", Pisa.
5  * License: http://www.gnu.org/licenses/gpl.html GPL version 3 or higher
6  *
7  * Authors:
8  *   Dario Andrea Bini <bini@dm.unipi.it>
9  *   Giuseppe Fiorentino <fiorent@dm.unipi.it>
10  *   Leonardo Robol <leonardo.robol@unipi.it>
11  */
12 
13 #include <mps/mps.h>
14 #include <string.h>
15 #include <assert.h>
16 
17 /**
18  * @brief Return a newly allocated mps_monomial_poly of the given degree.
19  */
20 mps_monomial_poly *
mps_monomial_poly_new(mps_context * s,long int degree)21 mps_monomial_poly_new (mps_context * s, long int degree)
22 {
23   int i;
24   mps_monomial_poly  * mp = mps_new (mps_monomial_poly);
25 
26   mps_polynomial_init (s, MPS_POLYNOMIAL (mp));
27 
28   /* Load monomial-poly methods */
29   mps_polynomial *poly = (mps_polynomial*)mp;
30   poly->type_name = "mps_monomial_poly";
31   poly->feval = mps_monomial_poly_feval;
32   poly->deval = mps_monomial_poly_deval;
33   poly->meval = mps_monomial_poly_meval;
34   poly->fstart = mps_monomial_poly_fstart;
35   poly->dstart = mps_monomial_poly_dstart;
36   poly->mstart = mps_monomial_poly_mstart;
37   poly->free = mps_monomial_poly_free;
38   poly->raise_data = mps_monomial_poly_raise_precision;
39   poly->fnewton = mps_monomial_poly_fnewton;
40   poly->dnewton = mps_monomial_poly_dnewton;
41   poly->mnewton = mps_monomial_poly_mnewton;
42   poly->get_leading_coefficient = mps_monomial_poly_get_leading_coefficient;
43 
44   /* Set the degree of the polynomial */
45   MPS_POLYNOMIAL (mp)->degree = degree;
46 
47   /* Allocate the space for the coefficients of the polynomial, all
48    * the floating point versions. */
49   mp->spar = mps_boolean_valloc (degree + 2);
50   mp->fpc = cplx_valloc (degree + 1);
51   mp->fpr = double_valloc (degree + 1);
52   mp->dpr = rdpe_valloc (degree + 1);
53   mp->dpc = cdpe_valloc (degree + 1);
54   mp->db.mfpc1 = mpc_valloc (degree + 1);
55   mp->db.mfpc2 = mpc_valloc (degree + 1);
56   mp->mfpc = mp->db.mfpc1;
57   mp->db.active = 1;
58   mp->mfpr = mpf_valloc (degree + 1);
59 
60   mpf_vinit2 (mp->mfpr, degree + 1, s->mpwp);
61   mpc_vinit2 (mp->db.mfpc1, degree + 1, s->mpwp);
62   mpc_vinit2 (mp->db.mfpc2, degree + 1, s->mpwp);
63 
64   /* Allocate space for the moduli of the coefficients */
65   mp->fap = double_valloc (degree + 1);
66   mp->dap = rdpe_valloc (degree + 1);
67 
68   /* Allocate space for the coefficients of the derivative */
69   mp->fppc = cplx_valloc (degree + 1);
70   mp->mfppc = mpc_valloc (degree + 1);
71   mpc_vinit2 (mp->mfppc, degree + 1, s->mpwp);
72 
73   /* Allocate space for the coefficients initially parsed as
74    * exact */
75   mp->initial_mqp_r = mpq_valloc (degree + 1);
76   mp->initial_mqp_i = mpq_valloc (degree + 1);
77 
78   mpq_vinit (mp->initial_mqp_r, degree + 1);
79   mpq_vinit (mp->initial_mqp_i, degree + 1);
80 
81   pthread_mutex_init (&mp->regenerating, NULL);
82 
83   mp->mfpc_mutex = mps_newv (pthread_mutex_t, degree + 1);
84   for (i = 0; i <= degree; i++)
85     pthread_mutex_init (&mp->mfpc_mutex[i], NULL);
86 
87   memset (mp->spar, 0, sizeof(mps_boolean) * (degree + 1));
88   memset (mp->fap, 0, sizeof(double) * (degree + 1));
89 
90   for (i = 0; i <= degree; i++)
91     rdpe_set (mp->dap[i], rdpe_zero);
92 
93   MPS_POLYNOMIAL (mp)->structure = MPS_STRUCTURE_UNKNOWN;
94   mp->prec = s->mpwp;
95 
96   return mp;
97 }
98 
99 /**
100  * @brief Free a instance of <code>mps_monomial_poly</code> previously
101  * allocated with <code>mps_monomial_poly_new()</code>.
102  */
103 void
mps_monomial_poly_free(mps_context * s,mps_polynomial * p)104 mps_monomial_poly_free (mps_context * s, mps_polynomial * p)
105 {
106   mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p);
107 
108   mps_boolean_vfree (mp->spar);
109   double_vfree (mp->fpr);
110   cplx_vfree (mp->fpc);
111   rdpe_vfree (mp->dpr);
112   cdpe_vfree (mp->dpc);
113 
114   double_vfree (mp->fap);
115   rdpe_vfree (mp->dap);
116 
117   mpf_vclear (mp->mfpr, MPS_POLYNOMIAL (mp)->degree + 1);
118   mpc_vclear (mp->db.mfpc1, MPS_POLYNOMIAL (mp)->degree + 1);
119   mpc_vclear (mp->db.mfpc2, MPS_POLYNOMIAL (mp)->degree + 1);
120 
121   mpf_vfree (mp->mfpr);
122   mpc_vfree (mp->db.mfpc1);
123   mpc_vfree (mp->db.mfpc2);
124 
125   mpq_vclear (mp->initial_mqp_r, MPS_POLYNOMIAL (mp)->degree + 1);
126   mpq_vclear (mp->initial_mqp_i, MPS_POLYNOMIAL (mp)->degree + 1);
127 
128   mpq_vfree (mp->initial_mqp_r);
129   mpq_vfree (mp->initial_mqp_i);
130 
131   cplx_vfree (mp->fppc);
132   mpc_vclear (mp->mfppc, MPS_POLYNOMIAL (mp)->degree + 1);
133   mpc_vfree (mp->mfppc);
134 
135   free (mp->mfpc_mutex);
136 
137   free (mp);
138 }
139 
140 /**
141  * @brief Raise the precision bits of the multiprecision fields of the
142  * polynomial to selected value.
143  *
144  * If the polynomial coefficients were generated by integer or rational
145  * input they will be autoregenerated.
146  *
147  * @param s  The status of the computation.
148  * @param p The polynomial that need the precision raised, casted to a mps_polynomial.
149  * @param prec The selected bits of precision.
150  * @return The precision set.
151  */
152 long int
mps_monomial_poly_raise_precision(mps_context * s,mps_polynomial * p,long int prec)153 mps_monomial_poly_raise_precision (mps_context * s, mps_polynomial * p, long int prec)
154 {
155   mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p);
156   int k;
157   mpc_t * raising_mfpc;
158 
159   pthread_mutex_lock (&mp->regenerating);
160 
161   /* For floating point coefficients, it might happen that
162    * the coefficients already have higher precision. In that
163    * case, we return now. */
164   if (prec <= mp->prec ||
165       (MPS_STRUCTURE_IS_FP(p->structure) && mpc_get_prec(mp->mfpc[0]) >= prec))
166     {
167       MPS_DEBUG_WITH_INFO(s, "Not increasing precision, the coefficients are already at the required accuracy");
168       pthread_mutex_unlock (&mp->regenerating);
169       return mp->prec;
170     }
171 
172   if (mp->db.active == 1)
173     raising_mfpc = mp->db.mfpc2;
174   else
175     raising_mfpc = mp->db.mfpc1;
176 
177   if (MPS_STRUCTURE_IS_FP(p->structure))
178     {
179       long int current_wp = mpc_get_prec(mp->mfpc[0]);
180       long int raising_wp = mpc_get_prec(raising_mfpc[0]);
181 
182       if (raising_wp > current_wp)
183         {
184           for (k = 0; k <= s->n; k++)
185             {
186               mpc_set_prec (mp->mfpc[k], raising_wp);
187               mpc_set (mp->mfpc[k], raising_mfpc[k]);
188             }
189         }
190     }
191 
192   /* raise the precision of  mfpc */
193   if (MPS_IS_MONOMIAL_POLY (p))
194     for (k = 0; k < MPS_POLYNOMIAL (mp)->degree + 1; k++)
195       {
196         mpc_set_prec (raising_mfpc[k], prec);
197       }
198 
199   /* Raise the precision of p' */
200   if (MPS_DENSITY_IS_SPARSE (p->density))
201     for (k = 0; k < MPS_POLYNOMIAL (mp)->degree; k++)
202       if (mp->spar[k + 1])
203         {
204           mpc_set_prec (mp->mfppc[k], prec);
205           mpc_mul_ui (mp->mfppc[k], mp->mfpc[k + 1], k + 1);
206         }
207 
208   if (MPS_STRUCTURE_IS_INTEGER (p->structure)
209       || MPS_STRUCTURE_IS_RATIONAL (p->structure))
210     {
211       for (k = 0; k <= MPS_POLYNOMIAL (mp)->degree; ++k)
212         {
213           mpf_set_q (mpc_Re (raising_mfpc[k]), mp->initial_mqp_r[k]);
214           mpf_set_q (mpc_Im (raising_mfpc[k]), mp->initial_mqp_i[k]);
215           mpc_rmod (mp->dap[k], raising_mfpc[k]);
216           mp->fap[k] = rdpe_get_d (mp->dap[k]);
217         }
218     }
219   else
220     {
221       for (k = 0; k <= MPS_POLYNOMIAL (mp)->degree; k++)
222         {
223           mpc_set (raising_mfpc[k], mp->mfpc[k]);
224         }
225     }
226 
227   mp->db.active = (mp->db.active % 2) + 1;
228   mp->mfpc = raising_mfpc;
229 
230   mp->prec = prec;
231   pthread_mutex_unlock (&mp->regenerating);
232 
233   return mp->prec;
234 }
235 
236 long int
mps_monomial_poly_get_precision(mps_context * s,mps_monomial_poly * mp)237 mps_monomial_poly_get_precision (mps_context * s, mps_monomial_poly * mp)
238 {
239   return mpc_get_prec (mp->mfpc[0]);
240 }
241 
242 /**
243  * @brief This routine can be used to set the i-th coefficients of the
244  * polynomial with a multiprecision rational number.
245  *
246  * @param s The mps_context the will be used for the computation. This shall be passed
247  * along with the polynomial because it manages user interaction and can perform
248  * error handling.
249  *
250  * @param mp The monomial_poly that will hold the coefficient.
251  * @param i  The exponent of the monomial to which the coefficient is related.
252  * @param real_part The real part of the coefficient.
253  * @param imag_part The imaginary part of the coefficients.
254  */
255 void
mps_monomial_poly_set_coefficient_q(mps_context * s,mps_monomial_poly * mp,long int i,mpq_t real_part,mpq_t imag_part)256 mps_monomial_poly_set_coefficient_q (mps_context * s, mps_monomial_poly * mp, long int i,
257                                      mpq_t real_part, mpq_t imag_part)
258 {
259   /* Updating data_type information */
260   if (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_UNKNOWN)
261     MPS_POLYNOMIAL (mp)->structure = (mpq_sgn (imag_part) != 0) ?
262                                      MPS_STRUCTURE_COMPLEX_RATIONAL : MPS_STRUCTURE_REAL_RATIONAL;
263 
264   if (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_REAL_RATIONAL &&
265       mpq_sgn (imag_part) != 0)
266     MPS_POLYNOMIAL (mp)->structure = MPS_STRUCTURE_COMPLEX_RATIONAL;
267 
268   assert (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_COMPLEX_RATIONAL ||
269           MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_REAL_RATIONAL ||
270           MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_COMPLEX_INTEGER ||
271           MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_REAL_INTEGER);
272 
273   /* Set the coefficients first */
274   mpq_set (mp->initial_mqp_r[i], real_part);
275   mpq_set (mp->initial_mqp_i[i], imag_part);
276 
277   /* Then update the other coefficients */
278   mpf_set_q (mpc_Re (mp->mfpc[i]), real_part);
279   mpf_set_q (mpc_Im (mp->mfpc[i]), imag_part);
280 
281   mpc_get_cdpe (mp->dpc[i], mp->mfpc[i]);
282   mpc_get_cplx (mp->fpc[i], mp->mfpc[i]);
283 
284   if ((mpq_sgn (real_part) == 0) && (mpq_sgn (imag_part) == 0))
285     mp->spar[i] = false;
286   else
287     mp->spar[i] = true;
288 
289   if (mp->spar[i])
290     {
291       mpc_get_cplx (mp->fpc[i], mp->mfpc[i]);
292       mpc_get_cdpe (mp->dpc[i], mp->mfpc[i]);
293 
294       /* Compute modules of coefficients */
295       cdpe_mod (mp->dap[i], mp->dpc[i]);
296       mp->fap[i] = rdpe_get_d (mp->dap[i]);
297 
298       if (i > 0)
299         mpc_mul_ui (mp->mfppc[i - 1], mp->mfppc[i], i);
300     }
301   else
302     {
303       cplx_set (mp->fpc[i], cplx_zero);
304       cdpe_set (mp->dpc[i], cdpe_zero);
305 
306       rdpe_set (mp->dap[i], rdpe_zero);
307       mp->fap[i] = 0.0f;
308     }
309 }
310 
311 /**
312  * @brief Set the coefficient in position i of the mpnomial.
313  *
314  * @param s The <code>mps_context</code> associated to this computation.
315  * @param mp The <code>monomial_poly</code> in which the coefficients will be set.
316  * @param i The index of the coefficient to set.
317  * @param real_part The real part of the coefficient.
318  * @param imag_part The imaginary part of the coefficient.
319  */
320 void
mps_monomial_poly_set_coefficient_d(mps_context * s,mps_monomial_poly * mp,long int i,double real_part,double imag_part)321 mps_monomial_poly_set_coefficient_d (mps_context * s, mps_monomial_poly * mp, long int i,
322                                      double real_part, double imag_part)
323 {
324   /* Updating data structure information */
325   if (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_UNKNOWN)
326     MPS_POLYNOMIAL (mp)->structure = (imag_part == 0) ?
327                                      MPS_STRUCTURE_REAL_FP : MPS_STRUCTURE_COMPLEX_FP;
328 
329   if (imag_part != 0 && MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_REAL_FP)
330     MPS_POLYNOMIAL (mp)->structure = MPS_STRUCTURE_COMPLEX_FP;
331 
332   assert (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_REAL_FP ||
333           MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_COMPLEX_FP);
334 
335   /* Set the coefficients */
336   mpf_set_d (mp->mfpr[i], real_part);
337   mpc_set_d (mp->mfpc[i], real_part, imag_part);
338 
339   /* Update spar */
340   mp->spar[i] = !((real_part == 0) && (imag_part == 0));
341 
342   if (mp->spar[i])
343     {
344       mpc_get_cplx (mp->fpc[i], mp->mfpc[i]);
345       mpc_get_cdpe (mp->dpc[i], mp->mfpc[i]);
346 
347       /* Compute modules of coefficients */
348       cdpe_mod (mp->dap[i], mp->dpc[i]);
349       mp->fap[i] = rdpe_get_d (mp->dap[i]);
350 
351       if (i > 0)
352         mpc_mul_ui (mp->mfppc[i - 1], mp->mfppc[i], i);
353     }
354   else
355     {
356       cplx_set (mp->fpc[i], cplx_zero);
357       cdpe_set (mp->dpc[i], cdpe_zero);
358 
359       rdpe_set (mp->dap[i], rdpe_zero);
360       mp->fap[i] = 0.0f;
361     }
362 }
363 
364 void
mps_monomial_poly_set_coefficient_int(mps_context * s,mps_monomial_poly * mp,long int i,long long real_part,long long imag_part)365 mps_monomial_poly_set_coefficient_int (mps_context * s, mps_monomial_poly * mp, long int i,
366                                        long long real_part, long long imag_part)
367 {
368   /* Updating data_type information */
369   if (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_UNKNOWN)
370     MPS_POLYNOMIAL (mp)->structure = (imag_part) != 0 ?
371                                      MPS_STRUCTURE_COMPLEX_INTEGER : MPS_STRUCTURE_REAL_INTEGER;
372 
373   if (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_REAL_INTEGER &&
374       imag_part != 0)
375     MPS_POLYNOMIAL (mp)->structure = MPS_STRUCTURE_COMPLEX_INTEGER;
376 
377   assert (MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_COMPLEX_INTEGER ||
378           MPS_POLYNOMIAL (mp)->structure == MPS_STRUCTURE_REAL_INTEGER);
379 
380   /* Set the coefficients first */
381   mpq_set_si (mp->initial_mqp_r[i], real_part, 1);
382   mpq_set_si (mp->initial_mqp_i[i], imag_part, 1);
383 
384   /* Then update the other coefficients */
385   mpf_set_q (mpc_Re (mp->mfpc[i]), mp->initial_mqp_r[i]);
386   mpf_set_q (mpc_Im (mp->mfpc[i]), mp->initial_mqp_i[i]);
387 
388   mpc_get_cdpe (mp->dpc[i], mp->mfpc[i]);
389   mpc_get_cplx (mp->fpc[i], mp->mfpc[i]);
390 
391   if ((real_part == 0) && (imag_part == 0))
392     mp->spar[i] = false;
393   else
394     mp->spar[i] = true;
395 
396   if (mp->spar[i])
397     {
398       mpc_get_cplx (mp->fpc[i], mp->mfpc[i]);
399       mpc_get_cdpe (mp->dpc[i], mp->mfpc[i]);
400 
401       /* Compute modules of coefficients */
402       cdpe_mod (mp->dap[i], mp->dpc[i]);
403       mp->fap[i] = rdpe_get_d (mp->dap[i]);
404 
405       if (i > 0)
406         mpc_mul_ui (mp->mfppc[i - 1], mp->mfppc[i], i);
407     }
408   else
409     {
410       cplx_set (mp->fpc[i], cplx_zero);
411       cdpe_set (mp->dpc[i], cdpe_zero);
412 
413       rdpe_set (mp->dap[i], rdpe_zero);
414       mp->fap[i] = 0.0f;
415     }
416 }
417 
418 void
mps_monomial_poly_set_coefficient_f(mps_context * s,mps_monomial_poly * p,long int i,mpc_t coeff)419 mps_monomial_poly_set_coefficient_f (mps_context * s, mps_monomial_poly * p, long int i,
420                                      mpc_t coeff)
421 {
422   /* Updating data_type information */
423   if (MPS_POLYNOMIAL (p)->structure == MPS_STRUCTURE_UNKNOWN)
424     MPS_POLYNOMIAL (p)->structure = MPS_STRUCTURE_COMPLEX_FP;
425 
426   mpc_set_prec (p->mfpc[i], mpc_get_prec(coeff));
427   mpc_set (p->mfpc[i], coeff);
428   mpc_get_cplx (p->fpc[i], p->mfpc[i]);
429   mpc_get_cdpe (p->dpc[i], p->mfpc[i]);
430 
431   mpc_rmod (p->dap[i], p->mfpc[i]);
432   p->fap[i] = rdpe_get_d (p->dap[i]);
433 
434   p->spar[i] = !mpc_eq_zero (coeff);
435 
436   if (i > 0)
437     mpc_mul_ui (p->mfppc[i - 1], p->mfppc[i], i);
438 }
439 
440 /**
441  * @brief Set the \f$i\f$-th coefficient of the polynomial.
442  *
443  * @param s The current mps_context.
444  * @param p The polynomial whose coefficient should be set.
445  * @param i The degree of the coefficient to set.
446  * @param real_coeff A string representing the real part of the coefficient
447  * that should be set, or NULL as an alias for \f$0\f$.
448  * @param imag_coeff A string representing the imaginary part of the coefficient
449  * that should be set, or NULL as an alias for \f$0\f$.
450  */
451 void
mps_monomial_poly_set_coefficient_s(mps_context * s,mps_monomial_poly * p,int i,const char * real_coeff,const char * imag_coeff)452 mps_monomial_poly_set_coefficient_s (mps_context * s, mps_monomial_poly * p,
453                                      int i, const char * real_coeff,
454                                      const char * imag_coeff)
455 {
456   char * eq_real = mps_utils_build_equivalent_rational_string (s, real_coeff);
457   char * eq_imag = mps_utils_build_equivalent_rational_string (s, imag_coeff);
458 
459   mpq_t tmp_real, tmp_imag;
460 
461   mpq_init (tmp_real);
462   mpq_init (tmp_imag);
463 
464   if (eq_real != NULL)
465     mpq_set_str (tmp_real, eq_real, 10);
466   else
467     mps_warn (s, "Invalid input for mps_monomial_set_coefficient_s: %s", real_coeff);
468 
469   if (eq_imag != NULL)
470     mpq_set_str (tmp_imag, eq_imag, 10);
471   else
472     mps_warn (s, "Invalid input for mps_monomial_set_coefficient_s: %s", imag_coeff);
473 
474   mps_monomial_poly_set_coefficient_q (s, p, i, tmp_real, tmp_imag);
475 
476   mpq_clear (tmp_real);
477   mpq_clear (tmp_imag);
478 
479   free (eq_real);
480   free (eq_imag);
481 }
482 
483 /**
484  * @brief Get a double version of the \f$i\f$-th coefficient of the polynomial.
485  *
486  * @param s The current mps_context.
487  * @param p The polynomial of which you want to know the coefficient.
488  * @param i The degree of the coefficient to obtain.
489  * @param output A cplx_t where the result will be stored.
490  */
mps_monomial_poly_get_coefficient_d(mps_context * s,mps_monomial_poly * p,int i,cplx_t output)491 void mps_monomial_poly_get_coefficient_d (mps_context * s, mps_monomial_poly * p,
492                                           int i, cplx_t output)
493 {
494   if (i >= 0 && i <= MPS_POLYNOMIAL (p)->degree)
495     cplx_set (output, p->fpc[i]);
496   else
497     cplx_set (output, cplx_zero);
498 }
499 
500 /**
501  * @brief Get a rational version of the \f$i\f$-th coefficient of the polynomial.
502  *
503  * @param s The current mps_context.
504  * @param p The polynomial of which you want to know the coefficient.
505  * @param i The degree of the coefficient to obtain.
506  * @param real_output A mpq_t where the real part of the result will be stored.
507  * @param imag_output A mpq_t where the imaginary part of the result will be stored.
508  */
mps_monomial_poly_get_coefficient_q(mps_context * s,mps_monomial_poly * p,int i,mpq_t real_output,mpq_t imag_output)509 void mps_monomial_poly_get_coefficient_q (mps_context * s, mps_monomial_poly * p,
510                                           int i, mpq_t real_output, mpq_t imag_output)
511 {
512   mps_polynomial *poly = MPS_POLYNOMIAL (p);
513 
514   if ((!MPS_STRUCTURE_IS_RATIONAL (poly->structure)) &&
515       (!MPS_STRUCTURE_IS_INTEGER (poly->structure)))
516     {
517       mps_error (s, "Cannot extract rational coefficients from a floating point polynomial");
518       return;
519     }
520 
521   if (i >= 0 && i <= poly->degree)
522     {
523       mpq_set (real_output, p->initial_mqp_r[i]);
524       mpq_set (imag_output, p->initial_mqp_i[i]);
525     }
526   else
527     {
528       mpq_set_si (real_output, 0, 1);
529       mpq_set_si (imag_output, 0, 1);
530     }
531 }
532 
533 /**
534  * @brief Get the k-th derivative of p with floating point coefficients
535  * approximated with the precision wp.
536  *
537  * @param s The current mps_context
538  * @param p The polynomial to derive
539  * @param k The order of the derivative that should be computed.
540  * @param wp The selected output working precision
541  */
542 mps_monomial_poly *
mps_monomial_poly_derive(mps_context * s,mps_monomial_poly * p,int k,long int wp)543 mps_monomial_poly_derive (mps_context * s, mps_monomial_poly * p, int k, long int wp)
544 {
545   mps_monomial_poly * d = mps_monomial_poly_new (s, MPS_POLYNOMIAL (p)->degree - k);
546   int i, j;
547 
548   MPS_POLYNOMIAL (d)->structure = MPS_POLYNOMIAL (p)->structure;
549   MPS_POLYNOMIAL (d)->density = MPS_POLYNOMIAL (p)->density;
550   MPS_POLYNOMIAL (d)->prec = MPS_POLYNOMIAL (p)->prec;
551 
552   if (wp != s->mpwp)
553     mps_monomial_poly_raise_precision (s, MPS_POLYNOMIAL (d), wp);
554 
555   switch (MPS_POLYNOMIAL (p)->structure)
556     {
557     case MPS_STRUCTURE_COMPLEX_INTEGER:
558     case MPS_STRUCTURE_COMPLEX_RATIONAL:
559     case MPS_STRUCTURE_REAL_INTEGER:
560     case MPS_STRUCTURE_REAL_RATIONAL:
561     {
562       mpq_t coeff_r;
563       mpq_t coeff_i;
564       mpq_t qtmp;
565       mpq_init (coeff_r);
566       mpq_init (coeff_i);
567       mpq_init (qtmp);
568 
569       for (i = 0; i <= MPS_POLYNOMIAL (d)->degree; i++)
570         {
571           mpq_set (coeff_r, p->initial_mqp_r[i + k]);
572           mpq_set (coeff_i, p->initial_mqp_i[i + k]);
573 
574           for (j = 0; j < k; j++)
575             {
576               mpq_set_si (qtmp, k + i - j, 1);
577               mpq_mul (coeff_r, coeff_r, qtmp);
578               mpq_mul (coeff_i, coeff_i, qtmp);
579             }
580           mps_monomial_poly_set_coefficient_q (s, d, i, coeff_r, coeff_i);
581         }
582 
583       mpq_clear (coeff_r);
584       mpq_clear (coeff_i);
585       mpq_clear (qtmp);
586     }
587 
588     break;
589 
590     default:
591     {
592       mpc_t * coeffs = mps_newv (mpc_t, MPS_POLYNOMIAL (d)->degree + 1);
593       mpc_vinit2 (coeffs, MPS_POLYNOMIAL (d)->degree + 1, wp);
594 
595       for (i = 0; i <= MPS_POLYNOMIAL (d)->degree; i++)
596         mpc_set (coeffs[i], p->mfpc[i + k]);
597 
598       for (j = 0; j < k; j++)
599         for (i = 0; i <= MPS_POLYNOMIAL (d)->degree; i++)
600           mpc_mul_eq_ui (coeffs[i], k + i - j);
601 
602 
603       for (i = 0; i <= MPS_POLYNOMIAL (d)->degree; i++)
604         mps_monomial_poly_set_coefficient_f (s, d, i, coeffs[i]);
605 
606       mpc_vclear (coeffs, MPS_POLYNOMIAL (d)->degree + 1);
607       free (coeffs);
608     }
609     break;
610     }
611 
612   if (MPS_DENSITY_IS_SPARSE (MPS_POLYNOMIAL (d)->density))
613     for (i = 0; i < MPS_POLYNOMIAL (d)->degree; i++)
614       mpc_mul_ui (d->mfppc[i], d->mfpc[i + 1], i + 1);
615 
616   return d;
617 }
618 
619 mps_boolean
mps_monomial_poly_feval(mps_context * ctx,mps_polynomial * p,cplx_t x,cplx_t value,double * error)620 mps_monomial_poly_feval (mps_context *ctx, mps_polynomial *p, cplx_t x, cplx_t value, double * error)
621 {
622   mps_fhorner_with_error (ctx, (mps_monomial_poly*)p, x, value, error);
623   return true;
624 }
625 
626 mps_boolean
mps_monomial_poly_deval(mps_context * ctx,mps_polynomial * p,cdpe_t x,cdpe_t value,rdpe_t error)627 mps_monomial_poly_deval (mps_context *ctx, mps_polynomial *p, cdpe_t x, cdpe_t value, rdpe_t error)
628 {
629   mps_dhorner_with_error (ctx, (mps_monomial_poly*)p, x, value, error);
630   return true;
631 }
632 
633 mps_boolean
mps_monomial_poly_meval(mps_context * ctx,mps_polynomial * p,mpc_t x,mpc_t value,rdpe_t error)634 mps_monomial_poly_meval (mps_context * ctx, mps_polynomial *p, mpc_t x, mpc_t value, rdpe_t error)
635 {
636   mps_mhorner_with_error2 (ctx, (mps_monomial_poly*)p, x, value, error, mpc_get_prec (x));
637   return true;
638 }
639 
640 void
mps_monomial_poly_fstart(mps_context * ctx,mps_polynomial * p,mps_approximation ** approximations)641 mps_monomial_poly_fstart (mps_context * ctx, mps_polynomial * p, mps_approximation ** approximations)
642 {
643   mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p);
644 
645   mps_fstart (ctx, ctx->n, NULL, 0.0, 0.0, ctx->eps_out, mp->fap);
646 }
647 
648 void
mps_monomial_poly_dstart(mps_context * ctx,mps_polynomial * p,mps_approximation ** approximations)649 mps_monomial_poly_dstart (mps_context * ctx, mps_polynomial * p, mps_approximation ** approximations)
650 {
651   mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p);
652 
653   mps_dstart (ctx, ctx->n, NULL, (__rdpe_struct*)rdpe_zero,
654               (__rdpe_struct*)rdpe_zero, ctx->eps_out,
655               mp->dap);
656 }
657 
658 void
mps_monomial_poly_mstart(mps_context * ctx,mps_polynomial * p,mps_approximation ** approximations)659 mps_monomial_poly_mstart (mps_context * ctx, mps_polynomial * p, mps_approximation ** approximations)
660 {
661   mps_monomial_poly *mp = MPS_MONOMIAL_POLY (p);
662   mpc_t gg;
663 
664   mpc_init2 (gg, ctx->mpwp);
665   mpc_set_ui (gg, 0U, 0U);
666   mps_mstart (ctx, ctx->n, NULL, (__rdpe_struct*)rdpe_zero,
667               (__rdpe_struct*)rdpe_zero, mp->dap, gg);
668   mpc_clear (gg);
669 }
670 
671 void
mps_monomial_poly_fnewton(mps_context * ctx,mps_polynomial * p,mps_approximation * root,cplx_t corr)672 mps_monomial_poly_fnewton (mps_context * ctx, mps_polynomial * p,
673                            mps_approximation * root, cplx_t corr)
674 {
675   mps_fnewton (ctx, p, root, corr);
676 }
677 
678 void
mps_monomial_poly_dnewton(mps_context * ctx,mps_polynomial * p,mps_approximation * root,cdpe_t corr)679 mps_monomial_poly_dnewton (mps_context * ctx, mps_polynomial * p,
680                            mps_approximation * root, cdpe_t corr)
681 {
682   mps_dnewton (ctx, p, root, corr);
683 }
684 
685 void
mps_monomial_poly_mnewton(mps_context * ctx,mps_polynomial * p,mps_approximation * root,mpc_t corr,long int wp)686 mps_monomial_poly_mnewton (mps_context * ctx, mps_polynomial * p,
687                            mps_approximation * root, mpc_t corr, long int wp)
688 {
689   mps_mnewton (ctx, p, root, corr, wp);
690 }
691 
692 void
mps_monomial_poly_get_leading_coefficient(mps_context * ctx,mps_polynomial * p,mpc_t leading_coefficient)693 mps_monomial_poly_get_leading_coefficient (mps_context * ctx, mps_polynomial * p,
694                                            mpc_t leading_coefficient)
695 {
696   mpc_set (leading_coefficient, MPS_MONOMIAL_POLY (p)->mfpc[p->degree]);
697 }
698 
mps_monomial_poly_deflate(mps_context * ctx,mps_polynomial * poly)699 void mps_monomial_poly_deflate (mps_context * ctx, mps_polynomial * poly)
700 {
701   int i;
702   mps_monomial_poly * p = MPS_MONOMIAL_POLY (poly);
703 
704   /* count number of zero roots (undeflated input polynomial) */
705   int zero_roots = 0;
706 
707   while (rdpe_eq (p->dap[zero_roots], rdpe_zero) && zero_roots < poly->degree)
708     zero_roots++;
709 
710   /* shift down input vectors */
711   if (zero_roots)
712     {
713       for (i = 0; i <= poly->degree - zero_roots; i++)
714         {
715           rdpe_set (p->dap[i], p->dap[i + zero_roots]);
716           p->fap[i] = p->fap[i + zero_roots];
717           p->fpr[i] = p->fpr[i + zero_roots];
718           cplx_set (p->fpc[i], p->fpc[i + zero_roots]);
719           rdpe_set (p->dpr[i], p->dpr[i + zero_roots]);
720           cdpe_set (p->dpc[i], p->dpc[i + zero_roots]);
721           mpf_set (p->mfpr[i], p->mfpr[i + zero_roots]);
722           mpc_set (p->mfpc[i], p->mfpc[i + zero_roots]);
723           if (i < poly->degree - zero_roots)
724             mpc_set (p->mfppc[i], p->mfppc[i + zero_roots]);
725           mpq_set (p->initial_mqp_r[i], p->initial_mqp_r[i + zero_roots]);
726           mpq_set (p->initial_mqp_i[i], p->initial_mqp_i[i + zero_roots]);
727           p->spar[i] = p->spar[i + zero_roots];
728         }
729     }
730 
731   /* FIXME: We need to reallocate the correct storage for the
732    * polynomial. */
733 
734   poly->degree -= zero_roots;
735 }
736