1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * gmpy2_convert_mpc.c *
3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4 * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision *
5 * libraries. *
6 * *
7 * Copyright 2000 - 2009 Alex Martelli *
8 * *
9 * Copyright 2008 - 2021 Case Van Horsen *
10 * *
11 * This file is part of GMPY2. *
12 * *
13 * GMPY2 is free software: you can redistribute it and/or modify it under *
14 * the terms of the GNU Lesser General Public License as published by the *
15 * Free Software Foundation, either version 3 of the License, or (at your *
16 * option) any later version. *
17 * *
18 * GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
21 * License for more details. *
22 * *
23 * You should have received a copy of the GNU Lesser General Public *
24 * License along with GMPY2; if not, see <http://www.gnu.org/licenses/> *
25 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
26
27 /* Please see the documentation for GMPy_MPFR_From_MPFR for detailed
28 * description of this function.
29 */
30
31
32 static MPC_Object *
GMPy_MPC_From_MPC(MPC_Object * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)33 GMPy_MPC_From_MPC(MPC_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
34 CTXT_Object *context)
35 {
36 MPC_Object *result = NULL;
37
38 /* Optimize the critical case when prec==1 or obj is NaN or Inf. */
39
40 if ((rprec == 1 && iprec == 1) ||
41 (!mpfr_number_p(mpc_realref(obj->c)) &&
42 !mpfr_number_p(mpc_imagref(obj->c)))) {
43 Py_INCREF((PyObject*)obj);
44 return obj;
45 }
46
47 CHECK_CONTEXT(context);
48
49 if (rprec == 0)
50 rprec = GET_REAL_PREC(context);
51 else if (rprec == 1)
52 rprec = mpfr_get_prec(mpc_realref(obj->c));
53
54 if (iprec == 0)
55 iprec = GET_IMAG_PREC(context);
56 else if (iprec == 1)
57 iprec = mpfr_get_prec(mpc_imagref(obj->c));
58
59 /* Try to identify when an additional reference to existing instance can
60 * be returned. It is possible when (1) the precision matches, (2) the
61 * exponent is valid and not in the range that might require subnormal-
62 * ization, and (3) subnormalize is not enabled.
63 */
64
65 if ((rprec == mpfr_get_prec(mpc_realref(obj->c))) &&
66 (iprec == mpfr_get_prec(mpc_imagref(obj->c))) &&
67 (!context->ctx.subnormalize) &&
68 (mpc_realref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_realref(obj->c)) - 1)) &&
69 (mpc_realref(obj->c)->_mpfr_exp <= context->ctx.emax) &&
70 (mpc_imagref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_imagref(obj->c)) - 1)) &&
71 (mpc_imagref(obj->c)->_mpfr_exp <= context->ctx.emax)
72 ) {
73
74 Py_INCREF((PyObject*)obj);
75 return obj;
76 }
77
78 if ((result = GMPy_MPC_New(rprec, iprec, context))) {
79 result->rc = mpc_set(result->c, obj->c, GET_MPC_ROUND(context));
80 _GMPy_MPC_Cleanup(&result, context);
81 }
82 return result;
83 }
84
85 static MPC_Object *
GMPy_MPC_From_PyComplex(PyObject * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)86 GMPy_MPC_From_PyComplex(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
87 CTXT_Object *context)
88 {
89 MPC_Object *result;
90
91 CHECK_CONTEXT(context);
92
93 if (rprec == 0)
94 rprec = GET_REAL_PREC(context);
95 else if (rprec == 1)
96 rprec = DBL_MANT_DIG;
97
98 if (iprec == 0)
99 iprec = GET_IMAG_PREC(context);
100 else if (iprec == 1)
101 rprec = DBL_MANT_DIG;
102
103 if ((result = GMPy_MPC_New(rprec, iprec, context))) {
104 result->rc = mpc_set_d_d(result->c, PyComplex_RealAsDouble(obj),
105 PyComplex_ImagAsDouble(obj), GET_MPC_ROUND(context));
106 if (rprec != 1 || iprec != 1) {
107 GMPY_MPC_CHECK_RANGE(result, context);
108 }
109 GMPY_MPC_SUBNORMALIZE(result, context);
110 GMPY_MPC_EXCEPTIONS(result, context);
111 }
112 return result;
113 }
114
115 static MPC_Object *
GMPy_MPC_From_MPFR(MPFR_Object * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)116 GMPy_MPC_From_MPFR(MPFR_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
117 CTXT_Object *context)
118 {
119 MPC_Object *result;
120
121 CHECK_CONTEXT(context);
122
123 if (rprec == 0)
124 rprec = GET_REAL_PREC(context);
125 else if (rprec == 1)
126 rprec = mpfr_get_prec(obj->f);
127
128 if (iprec == 0)
129 iprec = GET_IMAG_PREC(context);
130 else if (iprec == 1)
131 rprec = mpfr_get_prec(obj->f);
132
133 if ((result = GMPy_MPC_New(rprec, iprec, context))) {
134 result->rc = mpc_set_fr(result->c, obj->f, GET_MPC_ROUND(context));
135 if (rprec != 1) {
136 GMPY_MPC_CHECK_RANGE(result, context);
137 }
138 GMPY_MPC_SUBNORMALIZE(result, context);
139 GMPY_MPC_EXCEPTIONS(result, context);
140 }
141 return result;
142 }
143
144 static MPC_Object *
GMPy_MPC_From_PyFloat(PyObject * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)145 GMPy_MPC_From_PyFloat(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
146 CTXT_Object *context)
147 {
148 MPC_Object *result;
149
150 CHECK_CONTEXT(context);
151
152 if (rprec == 0)
153 rprec = GET_REAL_PREC(context);
154 else if (rprec == 1)
155 rprec = DBL_MANT_DIG;
156
157 if (iprec == 0)
158 iprec = GET_IMAG_PREC(context);
159 else if (iprec == 1)
160 rprec = DBL_MANT_DIG;
161
162 if ((result = GMPy_MPC_New(rprec, iprec, context))) {
163 result->rc = mpc_set_d(result->c, PyFloat_AS_DOUBLE(obj),
164 GET_MPC_ROUND(context));
165 if (rprec != 1) {
166 GMPY_MPC_CHECK_RANGE(result, context);
167 }
168 GMPY_MPC_SUBNORMALIZE(result, context);
169 GMPY_MPC_EXCEPTIONS(result, context);
170 }
171 return result;
172 }
173
174 static MPC_Object *
GMPy_MPC_From_MPZ(MPZ_Object * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)175 GMPy_MPC_From_MPZ(MPZ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
176 CTXT_Object *context)
177 {
178 MPC_Object *result = NULL;
179
180 CHECK_CONTEXT(context);
181
182 if (rprec < 2) {
183 rprec = GET_REAL_PREC(context);
184 }
185
186 if (iprec < 2) {
187 iprec = GET_IMAG_PREC(context);
188 }
189
190 if ((result = GMPy_MPC_New(rprec, iprec, context))) {
191 result->rc = mpc_set_z(result->c, obj->z, GET_MPC_ROUND(context));
192 if (rprec != 1) {
193 GMPY_MPC_CHECK_RANGE(result, context);
194 }
195 GMPY_MPC_SUBNORMALIZE(result, context);
196 GMPY_MPC_EXCEPTIONS(result, context);
197 }
198 return result;
199 }
200
201 static MPC_Object *
GMPy_MPC_From_MPQ(MPQ_Object * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)202 GMPy_MPC_From_MPQ(MPQ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
203 CTXT_Object *context)
204 {
205 MPC_Object *result = NULL;
206
207 CHECK_CONTEXT(context);
208
209 if (rprec < 2) {
210 rprec = GET_REAL_PREC(context);
211 }
212
213 if (iprec < 2) {
214 iprec = GET_IMAG_PREC(context);
215 }
216
217 if ((result = GMPy_MPC_New(rprec, iprec, context))) {
218 result->rc = mpc_set_q(result->c, obj->q, GET_MPC_ROUND(context));
219 if (rprec != 1) {
220 GMPY_MPC_CHECK_RANGE(result, context);
221 }
222 GMPY_MPC_SUBNORMALIZE(result, context);
223 GMPY_MPC_EXCEPTIONS(result, context);
224 }
225 return result;
226 }
227
228 static MPC_Object *
GMPy_MPC_From_Fraction(PyObject * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)229 GMPy_MPC_From_Fraction(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
230 CTXT_Object *context)
231 {
232 MPC_Object *result = NULL;
233 MPQ_Object *tempq;
234
235 CHECK_CONTEXT(context);
236
237 if ((tempq = GMPy_MPQ_From_Fraction(obj, context))) {
238 result = GMPy_MPC_From_MPQ(tempq, rprec, iprec, context);
239 Py_DECREF((PyObject*)tempq);
240 }
241 return result;
242 }
243
244 static MPC_Object *
GMPy_MPC_From_PyIntOrLong(PyObject * obj,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)245 GMPy_MPC_From_PyIntOrLong(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
246 CTXT_Object *context)
247 {
248 MPC_Object *result = NULL;
249 MPZ_Object *tempz;
250
251 CHECK_CONTEXT(context);
252
253 if ((tempz = GMPy_MPZ_From_PyIntOrLong(obj, context))) {
254 result = GMPy_MPC_From_MPZ(tempz, rprec, iprec, context);
255 Py_DECREF((PyObject*)tempz);
256 }
257
258 return result;
259 }
260
261 /* Python's string representation of a complex number differs from the format
262 * used by MPC. Both MPC and Python surround the complex number with '(' and
263 * ')' but Python adds a 'j' after the imaginary component and MPC requires a
264 * space between the real and imaginery components. GMPy_MPC_From_PyStr tries
265 * to work around the differences as by reading two MPFR-compatible numbers
266 * from the string and storing into the real and imaginary components
267 * respectively.
268 */
269
270 static MPC_Object *
GMPy_MPC_From_PyStr(PyObject * s,int base,mpfr_prec_t rprec,mpfr_prec_t iprec,CTXT_Object * context)271 GMPy_MPC_From_PyStr(PyObject *s, int base, mpfr_prec_t rprec, mpfr_prec_t iprec,
272 CTXT_Object *context)
273 {
274 MPC_Object *result;
275 Py_ssize_t len;
276 char *cp, *unwind, *tempchar, *lastchar;
277 int firstp = 0, lastp = 0, real_rc = 0, imag_rc = 0;
278 PyObject *ascii_str = ascii_str = GMPy_RemoveUnderscoreASCII(s);
279
280 if (!ascii_str) return NULL;
281
282 len = PyBytes_Size(ascii_str);
283 cp = (char*)PyBytes_AsString(ascii_str);
284
285 CHECK_CONTEXT(context);
286
287 if (!(result = GMPy_MPC_New(rprec, iprec, context))) {
288 Py_XDECREF(ascii_str);
289 return NULL;
290 }
291
292 /* Get a pointer to the last valid character (ignoring trailing
293 * whitespace.) */
294 lastchar = cp + len - 1;
295 while (isspace(*lastchar))
296 lastchar--;
297
298 /* Skip trailing ). */
299 if (*lastchar == ')') {
300 lastp = 1;
301 lastchar--;
302 }
303
304 /* Skip trailing j. */
305 if (*lastchar == 'j')
306 lastchar--;
307
308 /* Skip leading whitespace. */
309 while (isspace(*cp))
310 cp++;
311
312 /* Skip a leading (. */
313 if (*cp == '(') {
314 firstp = 1;
315 cp++;
316 }
317
318 if (firstp != lastp) goto invalid_string;
319
320 /* Read the real component first. */
321 unwind = cp;
322 real_rc = mpfr_strtofr(mpc_realref(result->c), cp, &tempchar, base,
323 GET_REAL_ROUND(context));
324
325 /* Verify that at least one valid character was read. */
326 if (cp == tempchar) goto invalid_string;
327
328 /* If the next character is a j, then the real component is 0 and
329 * we just read the imaginary componenet.
330 */
331 if (*tempchar == 'j') {
332 mpfr_set_zero(mpc_realref(result->c), MPFR_RNDN);
333 cp = unwind;
334 }
335 else {
336 /* Read the imaginary component next. */
337 cp = tempchar;
338 }
339
340 imag_rc = mpfr_strtofr(mpc_imagref(result->c), cp, &tempchar, base,
341 GET_IMAG_ROUND(context));
342
343 if (cp == tempchar && tempchar > lastchar)
344 goto valid_string;
345
346 if (*tempchar != 'j' && *cp != ' ')
347 goto invalid_string;
348
349 if (tempchar <= lastchar)
350 goto invalid_string;
351
352 valid_string:
353 Py_XDECREF(ascii_str);
354 result->rc = MPC_INEX(real_rc, imag_rc);
355
356 if (rprec != 1 || iprec != 1) {
357 GMPY_MPC_CHECK_RANGE(result, context);
358 }
359 GMPY_MPC_SUBNORMALIZE(result, context);
360 GMPY_MPC_EXCEPTIONS(result, context);
361
362 return result;
363
364 invalid_string:
365 VALUE_ERROR("invalid string in mpc()");
366 Py_DECREF((PyObject*)result);
367 Py_XDECREF(ascii_str);
368 return NULL;
369 }
370
371 /* See the comments for GMPy_MPFR_From_Real_Temp. */
372
373 static MPC_Object *
GMPy_MPC_From_ComplexWithType(PyObject * obj,int xtype,mp_prec_t rprec,mp_prec_t iprec,CTXT_Object * context)374 GMPy_MPC_From_ComplexWithType(PyObject* obj, int xtype, mp_prec_t rprec,
375 mp_prec_t iprec, CTXT_Object *context)
376 {
377 CHECK_CONTEXT(context);
378
379 if (IS_TYPE_MPC(xtype))
380 return GMPy_MPC_From_MPC((MPC_Object*)obj, rprec, iprec, context);
381
382 if (IS_TYPE_MPFR(xtype))
383 return GMPy_MPC_From_MPFR((MPFR_Object*)obj, rprec, iprec, context);
384
385 if (IS_TYPE_PyFloat(xtype))
386 return GMPy_MPC_From_PyFloat(obj, rprec, iprec, context);
387
388 if (IS_TYPE_PyComplex(xtype))
389 return GMPy_MPC_From_PyComplex(obj, rprec, iprec, context);
390
391 if (IS_TYPE_MPQ(xtype))
392 return GMPy_MPC_From_MPQ((MPQ_Object*)obj, rprec, iprec, context);
393
394 if (IS_TYPE_MPZANY(xtype))
395 return GMPy_MPC_From_MPZ((MPZ_Object*)obj, rprec, iprec, context);
396
397 if (IS_TYPE_PyInteger(xtype))
398 return GMPy_MPC_From_PyIntOrLong(obj, rprec, iprec, context);
399
400 if (IS_TYPE_PyFraction(xtype))
401 return GMPy_MPC_From_Fraction(obj, rprec, iprec, context);
402
403 if (IS_TYPE_HAS_MPC(xtype)) {
404 MPC_Object * res = (MPC_Object *) PyObject_CallMethod(obj, "__mpc__", NULL);
405
406 if (res != NULL && MPC_Check(res)) {
407 return res;
408 }
409 else {
410 Py_XDECREF((PyObject*)res);
411 goto error;
412 }
413 }
414
415 if (IS_TYPE_HAS_MPFR(xtype)) {
416 MPFR_Object * res = (MPFR_Object *) PyObject_CallMethod(obj, "__mpfr__", NULL);
417
418 if (res != NULL && MPFR_Check(res)) {
419 MPC_Object * temp = GMPy_MPC_From_MPFR(res, rprec, iprec, context);
420 Py_DECREF(res);
421 return temp;
422 }
423 else {
424 Py_XDECREF((PyObject*)res);
425 goto error;
426 }
427 }
428
429 if (IS_TYPE_HAS_MPQ(xtype)) {
430 MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
431
432 if (res != NULL && MPQ_Check(res)) {
433 MPC_Object * temp = GMPy_MPC_From_MPQ(res, rprec, iprec, context);
434 Py_DECREF(res);
435 return temp;
436 }
437 else {
438 Py_XDECREF((PyObject*)res);
439 goto error;
440 }
441 }
442
443 if (IS_TYPE_HAS_MPZ(xtype)) {
444 MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
445
446 if (res != NULL && MPZ_Check(res)) {
447 MPC_Object * temp = GMPy_MPC_From_MPZ(res, rprec, iprec, context);
448 Py_DECREF(res);
449 return temp;
450 }
451 else {
452 Py_XDECREF((PyObject*)res);
453 goto error;
454 }
455 }
456
457 error:
458 TYPE_ERROR("object could not be converted to 'mpc'");
459 return NULL;
460 }
461
462 static MPC_Object *
GMPy_MPC_From_Complex(PyObject * obj,mp_prec_t rprec,mp_prec_t iprec,CTXT_Object * context)463 GMPy_MPC_From_Complex(PyObject* obj, mp_prec_t rprec, mp_prec_t iprec,
464 CTXT_Object *context)
465 {
466 return GMPy_MPC_From_ComplexWithType(obj, GMPy_ObjectType(obj),
467 rprec, iprec, context);
468 }
469
470 static MPC_Object *
GMPy_MPC_From_ComplexWithTypeAndCopy(PyObject * obj,int xtype,mp_prec_t rprec,mp_prec_t iprec,CTXT_Object * context)471 GMPy_MPC_From_ComplexWithTypeAndCopy(PyObject* obj, int xtype, mp_prec_t rprec,
472 mp_prec_t iprec, CTXT_Object *context)
473 {
474 MPC_Object *result = NULL, *temp = NULL;
475
476 result = GMPy_MPC_From_ComplexWithType(obj, xtype, rprec, iprec, context);
477
478 if (result == NULL)
479 return result;
480
481 if (Py_REFCNT(result) == 1)
482 return result;
483
484 if (!(temp = GMPy_MPC_New(rprec = mpfr_get_prec(mpc_realref(result->c)),
485 iprec = mpfr_get_prec(mpc_imagref(result->c)),
486 context))) {
487 /* LCOV_EXCL_START */
488 Py_DECREF(result);
489 return NULL;
490 /* LCOV_EXCL_STOP */
491 }
492
493 /* Since the precision of temp is the same as the precision of result,
494 * there shouldn't be any rounding.
495 */
496
497 mpc_set(temp->c, result->c, MPFR_RNDN);
498 Py_DECREF((PyObject*)result);
499 return temp;
500 }
501
502 static PyObject *
GMPy_PyStr_From_MPC(MPC_Object * self,int base,int digits,CTXT_Object * context)503 GMPy_PyStr_From_MPC(MPC_Object *self, int base, int digits, CTXT_Object *context)
504 {
505 PyObject *tempreal = 0, *tempimag = 0, *result;
506
507 CHECK_CONTEXT(context);
508
509 if (!((base >= 2) && (base <= 62))) {
510 VALUE_ERROR("base must be in the interval [2,62]");
511 return NULL;
512 }
513 if ((digits < 0) || (digits == 1)) {
514 VALUE_ERROR("digits must be 0 or >= 2");
515 return NULL;
516 }
517
518 tempreal = mpfr_ascii(mpc_realref(self->c), base, digits,
519 MPC_RND_RE(GET_MPC_ROUND(context)));
520 tempimag = mpfr_ascii(mpc_imagref(self->c), base, digits,
521 MPC_RND_IM(GET_MPC_ROUND(context)));
522
523 if (!tempreal || !tempimag) {
524 Py_XDECREF(tempreal);
525 Py_XDECREF(tempimag);
526 return NULL;
527 }
528
529 result = Py_BuildValue("(NN)", tempreal, tempimag);
530 if (!result) {
531 Py_DECREF(tempreal);
532 Py_DECREF(tempimag);
533 }
534 return result;
535 }
536
537 static PyObject *
GMPy_MPC_Float_Slot(PyObject * self)538 GMPy_MPC_Float_Slot(PyObject *self)
539 {
540 TYPE_ERROR("can't covert 'mpc' to 'float'");
541 return NULL;
542 }
543
544 PyDoc_STRVAR(GMPy_doc_mpc_complex, "Convert 'mpc' to 'complex'.");
545
546 static PyObject *
GMPy_PyComplex_From_MPC(PyObject * self,PyObject * other)547 GMPy_PyComplex_From_MPC(PyObject *self, PyObject *other)
548 {
549 CTXT_Object *context = NULL;
550 double real, imag;
551
552 CHECK_CONTEXT(context);
553
554 real = mpfr_get_d(mpc_realref(MPC(self)), GET_REAL_ROUND(context));
555 imag = mpfr_get_d(mpc_imagref(MPC(self)), GET_IMAG_ROUND(context));
556
557 return PyComplex_FromDoubles(real, imag);
558 }
559
560 #ifdef PY2
561 static PyObject *
GMPy_MPC_Long_Slot(PyObject * self)562 GMPy_MPC_Long_Slot(PyObject *self)
563 {
564 TYPE_ERROR("can't covert mpc to long");
565 return NULL;
566 }
567 #endif
568
569 static PyObject *
GMPy_MPC_Int_Slot(PyObject * self)570 GMPy_MPC_Int_Slot(PyObject *self)
571 {
572 TYPE_ERROR("can't covert mpc to int");
573 return NULL;
574 }
575
576 #ifdef SHARED
577 /*
578 * coerce any number to a mpc
579 */
580
581 int
GMPy_MPC_ConvertArg(PyObject * arg,PyObject ** ptr)582 GMPy_MPC_ConvertArg(PyObject *arg, PyObject **ptr)
583 {
584 MPC_Object *newob = GMPy_MPC_From_Complex(arg, 0, 0, NULL);
585
586 if (newob) {
587 *ptr = (PyObject*)newob;
588 return 1;
589 }
590 else {
591 TYPE_ERROR("can't convert argument to 'mpc'");
592 return 0;
593 }
594 }
595 #endif
596
597 /* str and repr implementations for mpc */
598 static PyObject *
GMPy_MPC_Str_Slot(MPC_Object * self)599 GMPy_MPC_Str_Slot(MPC_Object *self)
600 {
601 PyObject *result, *temp;
602 mpfr_prec_t rbits, ibits;
603 long rprec, iprec;
604 char fmtstr[60];
605
606 mpc_get_prec2(&rbits, &ibits, MPC(self));
607 rprec = (long)(log10(2) * (double)rbits) + 2;
608 iprec = (long)(log10(2) * (double)ibits) + 2;
609
610 sprintf(fmtstr, "{0:.%ld.%ldg}", rprec, iprec);
611
612 temp = Py_BuildValue("s", fmtstr);
613 if (!temp)
614 return NULL;
615 result = PyObject_CallMethod(temp, "format", "O", self);
616 Py_DECREF(temp);
617 return result;
618 }
619
620 static PyObject *
GMPy_MPC_Repr_Slot(MPC_Object * self)621 GMPy_MPC_Repr_Slot(MPC_Object *self)
622 {
623 PyObject *result, *temp;
624 mpfr_prec_t rbits, ibits;
625 long rprec, iprec;
626 char fmtstr[60];
627
628 mpc_get_prec2(&rbits, &ibits, MPC(self));
629 rprec = (long)(log10(2) * (double)rbits) + 2;
630 iprec = (long)(log10(2) * (double)ibits) + 2;
631
632 if (rbits != DBL_MANT_DIG || ibits !=DBL_MANT_DIG)
633 sprintf(fmtstr, "mpc('{0:.%ld.%ldg}',(%ld,%ld))",
634 rprec, iprec, rbits, ibits);
635 else
636 sprintf(fmtstr, "mpc('{0:.%ld.%ldg}')", rprec, iprec);
637
638 temp = Py_BuildValue("s", fmtstr);
639 if (!temp)
640 return NULL;
641 result = PyObject_CallMethod(temp, "format", "O", self);
642 Py_DECREF(temp);
643 return result;
644 }
645
646
647
648