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 <stdlib.h>
14 #include <mps/mps.h>
15 
16 #define MPS_MPF_TEMP_SIZE 6
17 
18 struct mps_tls {
19   pthread_t thread;
20   mpf_t *data;
21   long int precision;
22   struct mps_tls *next;
23 };
24 
25 typedef struct mps_tls mps_tls;
26 
27 static pthread_once_t once_key_created = PTHREAD_ONCE_INIT;
28 static pthread_key_t key;
29 
30 static void
mps_mpc_cache_cleanup(void * pointer)31 mps_mpc_cache_cleanup (void * pointer)
32 {
33   mps_tls *ptr = pointer;
34   int i;
35 
36   for (i = 0; i < MPS_MPF_TEMP_SIZE; i++)
37     mpf_clear (ptr->data[i]);
38 
39   free(ptr->data);
40   free (ptr);
41 }
42 
43 static mps_tls *
create_new_mps_tls(long int precision_needed)44 create_new_mps_tls (long int precision_needed)
45 {
46   mps_tls *ptr;
47   int i;
48 
49   ptr = mps_new (mps_tls);
50 
51   ptr->data = mps_newv (mpf_t, MPS_MPF_TEMP_SIZE);
52   ptr->precision = precision_needed;
53 
54   for (i = 0; i < MPS_MPF_TEMP_SIZE; i++)
55     mpf_init2 (ptr->data[i], precision_needed);
56 
57   /* Set up a destructor for this data in case the thread exits */
58   pthread_setspecific (key, ptr);
59 
60   return ptr;
61 }
62 
63 static void
adjust_mps_tls_precision(mps_tls * ptr,long int precision_needed)64 adjust_mps_tls_precision (mps_tls *ptr, long int precision_needed)
65 {
66   int i;
67 
68   for (i = 0; i < MPS_MPF_TEMP_SIZE; i++)
69     mpf_set_prec (ptr->data[i], precision_needed);
70 
71   ptr->precision = precision_needed;
72 }
73 
74 static void
create_key(void)75 create_key (void)
76 {
77   pthread_key_create (&key, mps_mpc_cache_cleanup);
78 }
79 
80 static mpf_t*
init(long int precision_needed)81 init (long int precision_needed)
82 {
83   pthread_once (&once_key_created, create_key);
84   mps_tls *ptr = pthread_getspecific (key);
85 
86   /* This means that we have to create a new entry */
87   if (ptr == NULL)
88     {
89       ptr = create_new_mps_tls (precision_needed);
90     }
91   else if (ptr->precision < precision_needed || precision_needed < .25 * ptr->precision)
92     {
93       adjust_mps_tls_precision (ptr, precision_needed);
94     }
95 
96   return ptr->data;
97 }
98 
99 
100 /***********************************************************
101 **              functions for mpc_t                       **
102 ***********************************************************/
103 
104 /* constructors / destructors */
105 void
mpc_init(mpc_t c)106 mpc_init (mpc_t c)
107 {
108   printf ("mpc_init () called\n");
109   abort ();
110   mpf_init (mpc_Re (c));
111   mpf_init (mpc_Im (c));
112 }
113 
114 void
mpc_init2(mpc_t c,unsigned long int prec)115 mpc_init2 (mpc_t c, unsigned long int prec)
116 {
117   prec = (prec <= 2) ? 53 : prec;
118   mpf_init2 (mpc_Re (c), prec);
119   mpf_init2 (mpc_Im (c), prec);
120 }
121 
122 void
mpc_clear(mpc_t c)123 mpc_clear (mpc_t c)
124 {
125   mpf_clear (mpc_Re (c));
126   mpf_clear (mpc_Im (c));
127 }
128 
129 /* precision related functions */
130 void
mpc_set_prec(mpc_t c,unsigned long int prec)131 mpc_set_prec (mpc_t c, unsigned long int prec)
132 {
133   prec = (prec <= 2) ? 53 : prec;
134   if (mpf_get_prec (mpc_Re (c)) < prec)
135     {
136       mpf_set_prec (mpc_Re (c), prec);
137       mpf_set_prec (mpc_Im (c), prec);
138     }
139   else
140     {
141       mpf_set_prec (mpc_Re (c), prec);
142       mpf_set_prec (mpc_Im (c), prec);
143     }
144 }
145 
146 unsigned long int
mpc_get_prec(const mpc_t c)147 mpc_get_prec (const mpc_t c)
148 {
149   return mpf_get_prec (mpc_Re (c));
150 }
151 
152 void
mpc_set_prec_raw(mpc_t c,unsigned long int prec)153 mpc_set_prec_raw (mpc_t c, unsigned long int prec)
154 {
155   mpf_set_prec_raw (mpc_Re (c), prec);
156   mpf_set_prec_raw (mpc_Im (c), prec);
157 }
158 
159 /* assignment functions */
160 void
mpc_swap(mpc_t c1,mpc_t c2)161 mpc_swap (mpc_t c1, mpc_t c2)
162 /* c1 <-> c2 */
163 {
164   mpc_t t;
165 
166   mpc_Move (t, c1);
167   mpc_Move (c1, c2);
168   mpc_Move (c2, t);
169 }
170 
171 void
mpc_set(mpc_t rc,const mpc_t c)172 mpc_set (mpc_t rc, const mpc_t c)
173 {
174   mpf_set (mpc_Re (rc), mpc_Re (c));
175   mpf_set (mpc_Im (rc), mpc_Im (c));
176 }
177 
178 void
mpc_set_ui(mpc_t c,unsigned long int ir,unsigned long int ii)179 mpc_set_ui (mpc_t c, unsigned long int ir, unsigned long int ii)
180 {
181   mpf_set_ui (mpc_Re (c), ir);
182   mpf_set_ui (mpc_Im (c), ii);
183 }
184 
185 void
mpc_set_si(mpc_t c,signed long int ir,signed long int ii)186 mpc_set_si (mpc_t c, signed long int ir, signed long int ii)
187 {
188   mpf_set_si (mpc_Re (c), ir);
189   mpf_set_si (mpc_Im (c), ii);
190 }
191 
192 void
mpc_set_d(mpc_t c,double dr,double di)193 mpc_set_d (mpc_t c, double dr, double di)
194 {
195   mpf_set_d (mpc_Re (c), dr);
196   mpf_set_d (mpc_Im (c), di);
197 }
198 
199 void
mpc_set_z(mpc_t c,mpz_t zr,mpz_t zi)200 mpc_set_z (mpc_t c, mpz_t zr, mpz_t zi)
201 {
202   mpf_set_z (mpc_Re (c), zr);
203   mpf_set_z (mpc_Im (c), zi);
204 }
205 
206 void
mpc_set_q(mpc_t c,mpq_t qr,mpq_t qi)207 mpc_set_q (mpc_t c, mpq_t qr, mpq_t qi)
208 {
209   mpf_set_q (mpc_Re (c), qr);
210   mpf_set_q (mpc_Im (c), qi);
211 }
212 
213 void
mpc_set_f(mpc_t c,mpf_t fr,mpf_t fi)214 mpc_set_f (mpc_t c, mpf_t fr, mpf_t fi)
215 {
216   mpf_set (mpc_Re (c), fr);
217   mpf_set (mpc_Im (c), fi);
218 }
219 
220 int
mpc_set_str(mpc_t c,char * sr,char * si,int base)221 mpc_set_str (mpc_t c, char *sr, char *si, int base)
222 {
223   if (mpf_set_str (mpc_Re (c), sr, base) != 0)
224     return -1;
225   return mpf_set_str (mpc_Im (c), si, base);
226 }
227 
228 void
mpc_init_set(mpc_t rc,mpc_t c)229 mpc_init_set (mpc_t rc, mpc_t c)
230 {
231   mpf_init_set (mpc_Re (rc), mpc_Re (c));
232   mpf_init_set (mpc_Im (rc), mpc_Im (c));
233 }
234 
235 void
mpc_init_set_ui(mpc_t c,unsigned long int ir,unsigned long int ii)236 mpc_init_set_ui (mpc_t c, unsigned long int ir, unsigned long int ii)
237 {
238   mpf_init_set_ui (mpc_Re (c), ir);
239   mpf_init_set_ui (mpc_Im (c), ii);
240 }
241 
242 void
mpc_init_set_si(mpc_t c,signed long int ir,signed long int ii)243 mpc_init_set_si (mpc_t c, signed long int ir, signed long int ii)
244 {
245   mpf_init_set_si (mpc_Re (c), ir);
246   mpf_init_set_si (mpc_Im (c), ii);
247 }
248 
249 void
mpc_init_set_d(mpc_t c,double dr,double di)250 mpc_init_set_d (mpc_t c, double dr, double di)
251 {
252   mpf_init_set_d (mpc_Re (c), dr);
253   mpf_init_set_d (mpc_Im (c), di);
254 }
255 
256 void
mpc_init_set_f(mpc_t c,mpf_t fr,mpf_t fi)257 mpc_init_set_f (mpc_t c, mpf_t fr, mpf_t fi)
258 {
259   mpf_init_set (mpc_Re (c), fr);
260   mpf_init_set (mpc_Im (c), fi);
261 }
262 
263 int
mpc_init_set_str(mpc_t c,char * sr,char * si,int base)264 mpc_init_set_str (mpc_t c, char *sr, char *si, int base)
265 {
266   if (!mpf_init_set_str (mpc_Re (c), sr, base))
267     return -1;
268   return mpf_init_set_str (mpc_Im (c), si, base);
269 }
270 
271 /* unary functions */
272 void
mpc_neg(mpc_t rc,mpc_t c)273 mpc_neg (mpc_t rc, mpc_t c)
274 {
275   mpf_neg (mpc_Re (rc), mpc_Re (c));
276   mpf_neg (mpc_Im (rc), mpc_Im (c));
277 }
278 
279 void
mpc_smod(mpf_t f,mpc_t c)280 mpc_smod (mpf_t f, mpc_t c)
281 {
282   mpf_t *t = init (mpf_get_prec (f));
283 
284   mpf_mul (f, mpc_Re (c), mpc_Re (c));
285   mpf_mul (*t, mpc_Im (c), mpc_Im (c));
286   mpf_add (f, f, *t);
287 }
288 
289 void
mpc_rmod(rdpe_t r,mpc_t c)290 mpc_rmod (rdpe_t r, mpc_t c)
291 {
292   cdpe_t cdtmp;
293 
294   mpc_get_cdpe (cdtmp, c);
295   cdpe_mod (r, cdtmp);
296 }
297 
298 void
mpc_mod(mpf_t f,mpc_t c)299 mpc_mod (mpf_t f, mpc_t c)
300 {
301   mpf_t *t = init (mpf_get_prec (f));
302 
303   mpf_mul (f, mpc_Re (c), mpc_Re (c));
304   mpf_mul (*t, mpc_Im (c), mpc_Im (c));
305   mpf_add (f, f, *t);
306   mpf_sqrt (f, f);
307 }
308 
309 void
mpc_con(mpc_t rc,mpc_t c)310 mpc_con (mpc_t rc, mpc_t c)
311 {
312   mpc_set (rc, c);
313   mpf_neg (mpc_Im (rc), mpc_Im (rc));
314 }
315 
316 void
mpc_inv(mpc_t rc,mpc_t c)317 mpc_inv (mpc_t rc, mpc_t c)
318 {
319   mpf_t *f = init (mpf_get_prec (mpc_Re (rc))) + 5;
320 
321   mpc_smod (*f, c);
322   mpc_con (rc, c);
323   mpf_div (mpc_Re (rc), mpc_Re (rc), *f);
324   mpf_div (mpc_Im (rc), mpc_Im (rc), *f);
325 }
326 
327 void
mpc_inv2(mpc_t rc,mpc_t c)328 mpc_inv2 (mpc_t rc, mpc_t c)
329 {
330   mpf_t *f = init (mpf_get_prec (mpc_Re (rc))) + 5;
331 
332   mpc_smod (*f, c);
333   mpf_ui_div (*f, 1L, *f);
334   mpc_con (rc, c);
335   mpf_mul (mpc_Re (rc), mpc_Re (rc), *f);
336   mpf_mul (mpc_Im (rc), mpc_Im (rc), *f);
337 }
338 
339 void
mpc_sqr(mpc_t rc,mpc_t c)340 mpc_sqr (mpc_t rc, mpc_t c)
341 {
342   mpf_t *f = init (mpf_get_prec (mpc_Re (rc)));
343 
344   mpf_mul (*f, mpc_Re (c), mpc_Im (c));
345   mpf_mul (mpc_Re (rc), mpc_Re (c), mpc_Re (c));
346   mpf_mul (mpc_Im (rc), mpc_Im (c), mpc_Im (c));
347 
348   mpf_sub (mpc_Re (rc), mpc_Re (rc), mpc_Im (rc));
349   mpf_mul_2exp (mpc_Im (rc), *f, 1);
350 }
351 
352 void
mpc_rot(mpc_t rc,mpc_t c)353 mpc_rot (mpc_t rc, mpc_t c)
354 {
355   mpf_t *f = init (mpf_get_prec (mpc_Re (rc)));
356 
357   mpf_set (*f, mpc_Re (c));
358   mpf_set (mpc_Re (rc), mpc_Im (c));
359   mpf_set (mpc_Im (rc), *f);
360   mpf_neg (mpc_Re (rc), mpc_Re (rc));
361 }
362 
363 void
mpc_flip(mpc_t rc,mpc_t c)364 mpc_flip (mpc_t rc, mpc_t c)
365 {
366   mpf_t f;
367 
368   mpf_init2 (f, mpf_get_prec (mpc_Re (rc)));
369 
370   mpf_set (f, mpc_Re (c));
371   mpf_set (mpc_Re (rc), mpc_Im (c));
372   mpf_set (mpc_Im (rc), f);
373 
374   mpf_clear (f);
375 }
376 
377 /* binary functions */
378 void
mpc_add(mpc_t rc,mpc_t c1,mpc_t c2)379 mpc_add (mpc_t rc, mpc_t c1, mpc_t c2)
380 {
381   mpf_add (mpc_Re (rc), mpc_Re (c1), mpc_Re (c2));
382   mpf_add (mpc_Im (rc), mpc_Im (c1), mpc_Im (c2));
383 }
384 
385 void
mpc_add_f(mpc_t rc,mpc_t c,mpf_t f)386 mpc_add_f (mpc_t rc, mpc_t c, mpf_t f)
387 {
388   mpf_add (mpc_Re (rc), mpc_Re (c), f);
389 }
390 
391 void
mpc_add_ui(mpc_t rc,mpc_t c,unsigned long int r,unsigned long int i)392 mpc_add_ui (mpc_t rc, mpc_t c, unsigned long int r, unsigned long int i)
393 {
394   mpf_add_ui (mpc_Re (rc), mpc_Re (c), r);
395   mpf_add_ui (mpc_Im (rc), mpc_Im (c), i);
396 }
397 
398 void
mpc_sub(mpc_t rc,mpc_t c1,mpc_t c2)399 mpc_sub (mpc_t rc, mpc_t c1, mpc_t c2)
400 {
401   mpf_sub (mpc_Re (rc), mpc_Re (c1), mpc_Re (c2));
402   mpf_sub (mpc_Im (rc), mpc_Im (c1), mpc_Im (c2));
403 }
404 
405 void
mpc_sub_f(mpc_t rc,mpc_t c,mpf_t f)406 mpc_sub_f (mpc_t rc, mpc_t c, mpf_t f)
407 {
408   mpf_sub (mpc_Re (rc), mpc_Re (c), f);
409 }
410 
411 void
mpc_f_sub(mpc_t rc,mpf_t f,mpc_t c)412 mpc_f_sub (mpc_t rc, mpf_t f, mpc_t c)
413 {
414   mpf_sub (mpc_Re (rc), f, mpc_Re (c));
415 }
416 
417 void
mpc_sub_ui(mpc_t rc,mpc_t c,unsigned long int r,unsigned long int i)418 mpc_sub_ui (mpc_t rc, mpc_t c, unsigned long int r, unsigned long int i)
419 {
420   mpf_sub_ui (mpc_Re (rc), mpc_Re (c), r);
421   mpf_sub_ui (mpc_Im (rc), mpc_Im (c), i);
422 }
423 
424 void
mpc_ui_sub(mpc_t rc,unsigned long int r,unsigned long int i,mpc_t c)425 mpc_ui_sub (mpc_t rc, unsigned long int r, unsigned long int i, mpc_t c)
426 {
427   mpf_ui_sub (mpc_Re (rc), r, mpc_Re (c));
428   mpf_ui_sub (mpc_Im (rc), i, mpc_Im (c));
429 }
430 
431 void
mpc_mul(mpc_t rc,mpc_t c1,mpc_t c2)432 mpc_mul (mpc_t rc, mpc_t c1, mpc_t c2)
433 {
434   mpf_t *s1, *s2, *s3;
435 
436   s1 = init (mpf_get_prec (mpc_Re (rc)));
437   s2 = s1 + 1;
438   s3 = s2 + 1;
439 
440   mpf_sub (*s1, mpc_Re (c1), mpc_Im (c1));
441   mpf_add (*s2, mpc_Re (c2), mpc_Im (c2));
442   mpf_mul (*s1, *s1, *s2);
443   mpf_mul (*s2, mpc_Re (c1), mpc_Im (c2));
444   mpf_mul (*s3, mpc_Im (c1), mpc_Re (c2));
445   mpf_sub (mpc_Re (rc), *s1, *s2);
446   mpf_add (mpc_Re (rc), mpc_Re (rc), *s3);
447   mpf_add (mpc_Im (rc), *s2, *s3);
448 }
449 
450 void
mpc_mul_f(mpc_t rc,mpc_t c,mpf_t f)451 mpc_mul_f (mpc_t rc, mpc_t c, mpf_t f)
452 {
453   mpf_mul (mpc_Re (rc), mpc_Re (c), f);
454   mpf_mul (mpc_Im (rc), mpc_Im (c), f);
455 }
456 
457 void
mpc_mul_ui(mpc_t rc,mpc_t c,unsigned long int i)458 mpc_mul_ui (mpc_t rc, mpc_t c, unsigned long int i)
459 {
460   mpf_mul_ui (mpc_Re (rc), mpc_Re (c), i);
461   mpf_mul_ui (mpc_Im (rc), mpc_Im (c), i);
462 }
463 
464 void
mpc_mul_2exp(mpc_t rc,mpc_t c,unsigned long int i)465 mpc_mul_2exp (mpc_t rc, mpc_t c, unsigned long int i)
466 {
467   mpf_mul_2exp (mpc_Re (rc), mpc_Re (c), i);
468   mpf_mul_2exp (mpc_Im (rc), mpc_Im (c), i);
469 }
470 
471 void
mpc_div(mpc_t rc,mpc_t c1,mpc_t c2)472 mpc_div (mpc_t rc, mpc_t c1, mpc_t c2)
473 {
474   /* Find a good offset so that we don't pollute mul and inv registers */
475   mpc_t t;
476 
477   mpc_init2 (t, mpf_get_prec (mpc_Re (rc)));
478 
479   mpc_inv (t, c2);
480   mpc_mul (rc, c1, t);
481   mpc_clear (t);
482 }
483 
484 void
mpc_div_f(mpc_t rc,mpc_t c,mpf_t f)485 mpc_div_f (mpc_t rc, mpc_t c, mpf_t f)
486 {
487   mpf_div (mpc_Re (rc), mpc_Re (c), f);
488   mpf_div (mpc_Im (rc), mpc_Im (c), f);
489 }
490 
491 void
mpc_f_div(mpc_t rc,mpf_t f,mpc_t c)492 mpc_f_div (mpc_t rc, mpf_t f, mpc_t c)
493 {
494   mpc_t t;
495 
496   mpc_init2 (t, mpf_get_prec (mpc_Re (rc)));
497 
498   mpc_inv (t, c);
499   mpc_mul_f (rc, t, f);
500 
501   mpc_clear (t);
502 }
503 
504 void
mpc_div_ui(mpc_t rc,mpc_t c,unsigned long int i)505 mpc_div_ui (mpc_t rc, mpc_t c, unsigned long int i)
506 {
507   mpf_div_ui (mpc_Re (rc), mpc_Re (c), i);
508   mpf_div_ui (mpc_Im (rc), mpc_Im (c), i);
509 }
510 
511 void
mpc_ui_div(mpc_t rc,unsigned long int i,mpc_t c)512 mpc_ui_div (mpc_t rc, unsigned long int i, mpc_t c)
513 {
514   mpc_set_ui(rc, i, 0L);
515   mpc_div_eq(rc, c);
516 }
517 
518 void
mpc_div_2exp(mpc_t rc,mpc_t c,unsigned long int i)519 mpc_div_2exp (mpc_t rc, mpc_t c, unsigned long int i)
520 {
521   mpf_div_2exp (mpc_Re (rc), mpc_Re (c), i);
522   mpf_div_2exp (mpc_Im (rc), mpc_Im (c), i);
523 }
524 
525 void
mpc_pow_si(mpc_t rc,mpc_t c,register signed long int i)526 mpc_pow_si (mpc_t rc, mpc_t c, register signed long int i)
527 /* rc = c^i, i integer */
528 {
529   mpc_t t;
530 
531   mpc_init2 (t, mpf_get_prec (mpc_Re (rc)));
532 
533   mpc_set (t, c);
534   if (i < 0)
535     {
536       mpc_inv_eq (t);
537       i = -i;
538     }
539   if (i & 1)
540     mpc_set (rc, t);
541   else
542     mpc_set_ui (rc, 1, 0);
543   i >>= 1;                      /* divide i by 2 */
544 
545   while (i)
546     {
547       mpc_sqr_eq (t);
548       if (i & 1)
549         mpc_mul_eq (rc, t);
550       i >>= 1;                  /* divide i by 2 */
551     }
552 
553   mpc_clear (t);
554 }
555 
556 /* op= style functions */
557 void
mpc_smod_eq(mpc_t c)558 mpc_smod_eq (mpc_t c)
559 {
560   mpf_mul (mpc_Re (c), mpc_Re (c), mpc_Re (c));
561   mpf_mul (mpc_Im (c), mpc_Im (c), mpc_Im (c));
562   mpf_add (mpc_Re (c), mpc_Re (c), mpc_Im (c));
563   mpf_set_ui (mpc_Im (c), 0);
564 }
565 
566 void
mpc_mod_eq(mpc_t c)567 mpc_mod_eq (mpc_t c)
568 {
569   mpf_mul (mpc_Re (c), mpc_Re (c), mpc_Re (c));
570   mpf_mul (mpc_Im (c), mpc_Im (c), mpc_Im (c));
571   mpf_add (mpc_Re (c), mpc_Re (c), mpc_Im (c));
572   mpf_sqrt (mpc_Re (c), mpc_Re (c));
573   mpf_set_ui (mpc_Im (c), 0);
574 }
575 
576 void
mpc_rot_eq(mpc_t c)577 mpc_rot_eq (mpc_t c)
578 {
579   mpf_t f;
580 
581   mpf_Move (f, mpc_Re (c));
582   mpf_Move (mpc_Re (c), mpc_Im (c));
583   mpf_Move (mpc_Im (c), f);
584   mpf_neg (mpc_Re (c), mpc_Re (c));
585 }
586 
587 void
mpc_flip_eq(mpc_t c)588 mpc_flip_eq (mpc_t c)
589 {
590   mpf_t f;
591 
592   mpf_Move (f, mpc_Re (c));
593   mpf_Move (mpc_Re (c), mpc_Im (c));
594   mpf_Move (mpc_Im (c), f);
595 }
596 
597 /* comparison functions */
598 int
mpc_eq(mpc_t c1,mpc_t c2,unsigned long int i)599 mpc_eq (mpc_t c1, mpc_t c2, unsigned long int i)
600 {
601   if (!mpf_eq (mpc_Re (c1), mpc_Re (c2), i))
602     return -1;
603   return mpf_eq (mpc_Im (c1), mpc_Im (c2), i);
604 }
605 
606 int
mpc_eq_zero(mpc_t c)607 mpc_eq_zero (mpc_t c)
608 {
609   if (mpf_sgn (mpc_Re (c)) || mpf_sgn (mpc_Im (c)))
610     return 0;
611   else
612     return 1;
613 }
614 
615 int
mpc_eq_one(mpc_t c)616 mpc_eq_one (mpc_t c)
617 {
618   if (mpf_sgn (mpc_Im (c)) || mpf_cmp_ui (mpc_Re (c), 1))
619     return 0;
620   else
621     return 1;
622 }
623 
624 /* I/O functions */
625 size_t
mpc_out_str_2u(FILE * f,int base,size_t n_digits_r,size_t n_digits_i,mpc_t c)626 mpc_out_str_2u (FILE * f, int base, size_t n_digits_r,
627                 size_t n_digits_i, mpc_t c)
628 /* unformatted output */
629 {
630   if (f == NULL)
631     f = stdout;
632   if (!mpf_out_str (f, base, n_digits_r, mpc_Re (c)))
633     return 0;
634   if (fprintf (f, " ") < 0)
635     return 0;
636   if (!mpf_out_str (f, base, n_digits_i, mpc_Im (c)))
637     return 0;
638   else
639     return 1;
640 }
641 
642 size_t
mpc_out_str_2(FILE * f,int base,size_t n_digits_r,size_t n_digits_i,mpc_t c)643 mpc_out_str_2 (FILE * f, int base, size_t n_digits_r,
644                size_t n_digits_i, mpc_t c)
645 /* formatted output */
646 {
647   if (f == NULL)
648     f = stdout;
649   if (fprintf (f, "(") < 0)
650     return 0;
651   if (!mpf_out_str (f, base, n_digits_r, mpc_Re (c)))
652     return 0;
653   if (fprintf (f, ", ") < 0)
654     return 0;
655   if (!mpf_out_str (f, base, n_digits_i, mpc_Im (c)))
656     return 0;
657   if (fprintf (f, ")") < 0)
658     return 0;
659   else
660     return 1;
661 }
662 
663 size_t
mpc_inp_str_u(mpc_t c,FILE * f,int base)664 mpc_inp_str_u (mpc_t c, FILE * f, int base)
665 /* unformatted input */
666 {
667   if (f == NULL)
668     f = stdin;
669   if (!mpf_inp_str (mpc_Re (c), f, base))
670     return 0;
671   if (fscanf (f, " ") < 0)
672     return 0;
673   if (!mpf_inp_str (mpc_Im (c), f, base))
674     return 0;
675   else
676     return 1;
677 }
678 
679 size_t
mpc_inp_str(mpc_t c,FILE * f,int base)680 mpc_inp_str (mpc_t c, FILE * f, int base)
681 /* formatted input */
682 {
683   if (f == NULL)
684     f = stdin;
685   if (fscanf (f, "(") < 0)
686     return 0;
687   if (!mpf_inp_str (mpc_Re (c), f, base))
688     return 0;
689   if (fscanf (f, ", ") < 0)
690     return 0;
691   if (!mpf_inp_str (mpc_Im (c), f, base))
692     return 0;
693   if (fscanf (f, ")") < 0)
694     return 0;
695   else
696     return 1;
697 }
698 
699 /* vector functions */
700 void
mpc_vinit(mpc_t v[],long size)701 mpc_vinit (mpc_t v[], long size)
702 {
703   long i;
704 
705   for (i = 0; i < size; i++)
706     mpc_init (v[i]);
707 }
708 
709 void
mpc_vinit2(mpc_t v[],long size,long prec)710 mpc_vinit2 (mpc_t v[], long size, long prec)
711 {
712   long i;
713 
714   for (i = 0; i < size; i++)
715     mpc_init2 (v[i], prec);
716 }
717 
718 void
mpc_vclear(mpc_t v[],long size)719 mpc_vclear (mpc_t v[], long size)
720 {
721   long i;
722 
723   for (i = 0; i < size; i++)
724     mpc_clear (v[i]);
725   /* free(v); */
726 }
727 
728 /***********************************************************
729 **                                                        **
730 ***********************************************************/
731