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