gmpy2_convert_gmp.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_convert_gmp.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 /* This file contains all the conversion functions for GMP data types. 28 * 29 * Overview 30 * -------- 31 * gmpy2 tries to optimize the performance and accuracy of conversions from 32 * other numeric types. gmpy2 uses a LBYL (Look Before You Leap) approach and 33 * identifies the numeric type before conversion before conversion to a gmpy2 34 * type. The basic operations (+, -, *, /) are optimized to directly work with 35 * some basic types such as C longs or doubles. 36 */ 37 38 /* ======================================================================== * 39 * Conversion between native Python objects and MPZ. * 40 * ======================================================================== */ 41 42 static MPZ_Object * 43 GMPy_MPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context) 44 { 45 MPZ_Object *result; 46 int negative; 47 Py_ssize_t len; 48 PyLongObject *templong = (PyLongObject*)obj; 49 50 if(!(result = GMPy_MPZ_New(context))) { 51 /* LCOV_EXCL_START */ 52 return NULL; 53 /* LCOV_EXCL_STOP */ 54 } 55 56 #ifdef PY2 57 if (PyInt_Check(obj)) { 58 mpz_set_si(result->z, PyInt_AS_LONG(obj)); 59 return result; 60 } 61 #endif 62 63 switch (Py_SIZE(templong)) { 64 case -1: 65 mpz_set_si(result->z, -(sdigit)templong->ob_digit[0]); 66 break; 67 case 0: 68 mpz_set_si(result->z, 0); 69 break; 70 case 1: 71 mpz_set_si(result->z, templong->ob_digit[0]); 72 break; 73 default: 74 mpz_set_si(result->z, 0); 75 76 if (Py_SIZE(templong) < 0) { 77 len = - Py_SIZE(templong); 78 negative = 1; 79 } else { 80 len = Py_SIZE(templong); 81 negative = 0; 82 } 83 84 mpz_import(result->z, len, -1, sizeof(templong->ob_digit[0]), 0, 85 sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit); 86 87 if (negative) { 88 mpz_neg(result->z, result->z); 89 } 90 } 91 return result; 92 } 93 94 /* To support creation of temporary mpz objects. */ 95 static void 96 mpz_set_PyIntOrLong(mpz_t z, PyObject *obj) 97 { 98 int negative; 99 Py_ssize_t len; 100 PyLongObject *templong = (PyLongObject*)obj; 101 102 #ifdef PY2 103 if (PyInt_Check(obj)) { 104 mpz_set_si(z, PyInt_AS_LONG(obj)); 105 return; 106 } 107 #endif 108 109 switch (Py_SIZE(templong)) { 110 case -1: 111 mpz_set_si(z, -(sdigit)templong->ob_digit[0]); 112 break; 113 case 0: 114 mpz_set_si(z, 0); 115 break; 116 case 1: 117 mpz_set_si(z, templong->ob_digit[0]); 118 break; 119 default: 120 mpz_set_si(z, 0); 121 122 if (Py_SIZE(templong) < 0) { 123 len = - Py_SIZE(templong); 124 negative = 1; 125 } else { 126 len = Py_SIZE(templong); 127 negative = 0; 128 } 129 130 mpz_import(z, len, -1, sizeof(templong->ob_digit[0]), 0, 131 sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit); 132 133 if (negative) { 134 mpz_neg(z, z); 135 } 136 } 137 return; 138 } 139 140 static MPZ_Object * 141 GMPy_MPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context) 142 { 143 MPZ_Object *result; 144 145 if (!(result = GMPy_MPZ_New(context))) { 146 /* LCOV_EXCL_START */ 147 return NULL; 148 /* LCOV_EXCL_STOP */ 149 } 150 151 if (mpz_set_PyStr(result->z, s, base) == -1) { 152 Py_DECREF((PyObject*)result); 153 return NULL; 154 } 155 return result; 156 } 157 158 static MPZ_Object * 159 GMPy_MPZ_From_PyFloat(PyObject *obj, CTXT_Object *context) 160 { 161 MPZ_Object *result; 162 163 if ((result = GMPy_MPZ_New(context))) { 164 double d = PyFloat_AsDouble(obj); 165 166 if (Py_IS_NAN(d)) { 167 Py_DECREF((PyObject*)result); 168 VALUE_ERROR("'mpz' does not support NaN"); 169 return NULL; 170 } 171 if (Py_IS_INFINITY(d)) { 172 Py_DECREF((PyObject*)result); 173 OVERFLOW_ERROR("'mpz' does not support Infinity"); 174 return NULL; 175 } 176 mpz_set_d(result->z, d); 177 } 178 return result; 179 } 180 181 static PyObject * 182 GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context) 183 { 184 int negative; 185 size_t count, size; 186 PyLongObject *result; 187 188 /* Assume gmp uses limbs as least as large as the builtin longs do */ 189 190 if (mpz_sgn(obj->z) < 0) { 191 negative = 1; 192 } else { 193 negative = 0; 194 } 195 196 size = (mpz_sizeinbase(obj->z, 2) + PyLong_SHIFT - 1) / PyLong_SHIFT; 197 198 if (!(result = _PyLong_New(size))) { 199 /* LCOV_EXCL_START */ 200 return NULL; 201 /* LCOV_EXCL_STOP */ 202 } 203 204 mpz_export(result->ob_digit, &count, -1, sizeof(result->ob_digit[0]), 0, 205 sizeof(result->ob_digit[0])*8 - PyLong_SHIFT, obj->z); 206 207 if (count == 0) { 208 result->ob_digit[0] = 0; 209 } 210 211 /* long_normalize() is file-static so we must reimplement it */ 212 /* longobjp = long_normalize(longobjp); */ 213 while ((size>0) && (result->ob_digit[size-1] == 0)) { 214 size--; 215 } 216 #if PY_VERSION_HEX >= 0x030900A4 217 Py_SET_SIZE(result, size); 218 #else 219 Py_SIZE(result) = size; 220 #endif 221 222 if (negative) { 223 #if PY_VERSION_HEX >= 0x030900A4 224 Py_SET_SIZE(result, - Py_SIZE(result)); 225 #else 226 Py_SIZE(result) = - Py_SIZE(result); 227 #endif 228 } 229 return (PyObject*)result; 230 } 231 232 #ifdef PY2 233 static PyObject * 234 GMPy_MPZ_Long_Slot(MPZ_Object *self) 235 { 236 return GMPy_PyLong_From_MPZ(self, NULL); 237 } 238 #endif 239 240 /* The PyIntOrLong functions should be used when converting a number back 241 * to a Python value since is automatically returns an "int" or "long" when 242 * using Python 2.x. The PyLong_From functions (above) should only be used 243 * when a PyLong is specifically needed for Python 2.x. 244 */ 245 246 static PyObject * 247 GMPy_PyIntOrLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context) 248 { 249 250 #ifdef PY2 251 if (mpz_fits_slong_p(obj->z)) { 252 /* cast is safe since we know it fits in a signed long */ 253 return PyInt_FromLong((long)mpz_get_si(obj->z)); 254 } 255 #endif 256 257 return GMPy_PyLong_From_MPZ(obj, context); 258 } 259 260 static PyObject * 261 GMPy_MPZ_Int_Slot(MPZ_Object *self) 262 { 263 return GMPy_PyIntOrLong_From_MPZ(self, NULL); 264 } 265 266 static PyObject * 267 GMPy_PyFloat_From_MPZ(MPZ_Object *obj, CTXT_Object *context) 268 { 269 double res; 270 271 res = mpz_get_d(obj->z); 272 273 if (Py_IS_INFINITY(res)) { 274 OVERFLOW_ERROR("'mpz' too large to convert to float"); 275 return NULL; 276 } 277 278 return PyFloat_FromDouble(res); 279 } 280 281 static PyObject * 282 GMPy_MPZ_Float_Slot(MPZ_Object *self) 283 { 284 return GMPy_PyFloat_From_MPZ(self, NULL); 285 } 286 287 static PyObject * 288 GMPy_PyStr_From_MPZ(MPZ_Object *obj, int base, int option, CTXT_Object *context) 289 { 290 return mpz_ascii(obj->z, base, option, 0); 291 } 292 293 static MPZ_Object * 294 GMPy_MPZ_From_Integer(PyObject *obj, CTXT_Object *context) 295 { 296 MPZ_Object *result = NULL; 297 298 if (MPZ_Check(obj)) { 299 Py_INCREF(obj); 300 return (MPZ_Object*)obj; 301 } 302 303 if (PyIntOrLong_Check(obj)) 304 return GMPy_MPZ_From_PyIntOrLong(obj, context); 305 306 if (XMPZ_Check(obj)) 307 return GMPy_MPZ_From_XMPZ((XMPZ_Object*)obj, context); 308 309 if (HAS_STRICT_MPZ_CONVERSION(obj)) { 310 result = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL); 311 312 if (result != NULL && MPZ_Check(result)) { 313 return result; 314 } 315 else { 316 Py_XDECREF((PyObject*)result); 317 goto error; 318 } 319 } 320 321 error: 322 TYPE_ERROR("cannot convert object to mpz"); 323 return NULL; 324 } 325 326 static MPZ_Object * 327 GMPy_MPZ_From_IntegerWithType(PyObject *obj, int xtype, CTXT_Object *context) 328 { 329 MPZ_Object *result = NULL; 330 331 if (IS_TYPE_MPZ(xtype)) { 332 Py_INCREF(obj); 333 return (MPZ_Object*)obj; 334 } 335 336 if (IS_TYPE_PyInteger(xtype)) 337 return GMPy_MPZ_From_PyIntOrLong(obj, context); 338 339 if (IS_TYPE_XMPZ(xtype)) 340 return GMPy_MPZ_From_XMPZ((XMPZ_Object*)obj, context); 341 342 if (IS_TYPE_HAS_MPZ(xtype)) { 343 result = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL); 344 345 if (result != NULL && MPZ_Check(result)) { 346 return result; 347 } 348 else { 349 Py_XDECREF((PyObject*)result); 350 goto error; 351 } 352 } 353 354 error: 355 TYPE_ERROR("cannot convert object to mpz"); 356 return NULL; 357 } 358 359 static MPZ_Object * 360 GMPy_MPZ_From_IntegerWithTypeAndCopy(PyObject *obj, int xtype, CTXT_Object *context) 361 { 362 MPZ_Object *result = NULL, *temp = NULL; 363 364 result = GMPy_MPZ_From_IntegerWithType(obj, xtype, context); 365 366 if (result == NULL) 367 return result; 368 369 if (Py_REFCNT(result) == 1) 370 return result; 371 372 if (!(temp = GMPy_MPZ_New(context))) { 373 /* LCOV_EXCL_START */ 374 return NULL; 375 /* LCOV_EXCL_STOP */ 376 } 377 378 mpz_set(temp->z, result->z); 379 Py_DECREF((PyObject*)result); 380 return temp; 381 } 382 383 /* str and repr implementations for mpz */ 384 static PyObject * 385 GMPy_MPZ_Str_Slot(MPZ_Object *self) 386 { 387 /* base-10, no tag */ 388 return GMPy_PyStr_From_MPZ(self, 10, 0, NULL); 389 } 390 391 static PyObject * 392 GMPy_MPZ_Repr_Slot(MPZ_Object *self) 393 { 394 /* base-10, with tag */ 395 return GMPy_PyStr_From_MPZ(self, 10, 1, NULL); 396 } 397 398 #ifdef SHARED 399 /* Helper function for argument parsing. Not used in static build. */ 400 401 static int 402 GMPy_MPZ_ConvertArg(PyObject *arg, PyObject **ptr) 403 { 404 MPZ_Object *result = GMPy_MPZ_From_IntegerWithType(arg, GMPy_ObjectType(arg), NULL); 405 406 if (result) { 407 *ptr = (PyObject*)result; 408 return 1; 409 } 410 else { 411 TYPE_ERROR("argument can not be converted to 'mpz'"); 412 return 0; 413 } 414 } 415 #endif 416 417 /* ======================================================================== * 418 * Conversion between native Python objects/MPZ and XMPZ. * 419 * ======================================================================== */ 420 421 static XMPZ_Object * 422 GMPy_XMPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context) 423 { 424 XMPZ_Object *result; 425 int negative; 426 Py_ssize_t len; 427 PyLongObject *templong = (PyLongObject*)obj; 428 429 if(!(result = GMPy_XMPZ_New(context))) { 430 /* LCOV_EXCL_START */ 431 return NULL; 432 /* LCOV_EXCL_STOP */ 433 } 434 435 #ifdef PY2 436 if (PyInt_Check(obj)) { 437 mpz_set_si(result->z, PyInt_AS_LONG(obj)); 438 return result; 439 } 440 #endif 441 442 switch (Py_SIZE(templong)) { 443 case -1: 444 mpz_set_si(result->z, -(sdigit)templong->ob_digit[0]); 445 break; 446 case 0: 447 mpz_set_si(result->z, 0); 448 break; 449 case 1: 450 mpz_set_si(result->z, templong->ob_digit[0]); 451 break; 452 default: 453 mpz_set_si(result->z, 0); 454 455 if (Py_SIZE(templong) < 0) { 456 len = - Py_SIZE(templong); 457 negative = 1; 458 } else { 459 len = Py_SIZE(templong); 460 negative = 0; 461 } 462 463 mpz_import(result->z, len, -1, sizeof(templong->ob_digit[0]), 0, 464 sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit); 465 466 if (negative) { 467 mpz_neg(result->z, result->z); 468 } 469 } 470 return result; 471 } 472 473 static XMPZ_Object * 474 GMPy_XMPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context) 475 { 476 XMPZ_Object *result; 477 478 if (!(result = GMPy_XMPZ_New(context))) 479 return NULL; 480 481 if (mpz_set_PyStr(result->z, s, base) == -1) { 482 Py_DECREF((PyObject*)result); 483 return NULL; 484 } 485 return result; 486 } 487 488 static XMPZ_Object * 489 GMPy_XMPZ_From_PyFloat(PyObject *obj, CTXT_Object *context) 490 { 491 XMPZ_Object *result; 492 493 if ((result = GMPy_XMPZ_New(context))) { 494 double d = PyFloat_AsDouble(obj); 495 496 if (Py_IS_NAN(d)) { 497 Py_DECREF((PyObject*)result); 498 VALUE_ERROR("'xmpz' does not support NaN"); 499 return NULL; 500 } 501 if (Py_IS_INFINITY(d)) { 502 Py_DECREF((PyObject*)result); 503 OVERFLOW_ERROR("'xmpz' does not support Infinity"); 504 return NULL; 505 } 506 mpz_set_d(result->z, d); 507 } 508 return result; 509 } 510 511 static XMPZ_Object * 512 GMPy_XMPZ_From_MPZ(MPZ_Object *obj, CTXT_Object *context) 513 { 514 XMPZ_Object *result; 515 516 if ((result = GMPy_XMPZ_New(context))) 517 mpz_set(result->z, obj->z); 518 519 return result; 520 } 521 522 static XMPZ_Object * 523 GMPy_XMPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context) 524 { 525 XMPZ_Object *result; 526 527 if ((result = GMPy_XMPZ_New(context))) 528 mpz_set(result->z, obj->z); 529 530 return result; 531 } 532 533 static PyObject * 534 GMPy_PyStr_From_XMPZ(XMPZ_Object *obj, int base, int option, CTXT_Object *context) 535 { 536 return mpz_ascii(obj->z, base, option, 1); 537 } 538 539 static MPZ_Object * 540 GMPy_MPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context) 541 { 542 MPZ_Object *result; 543 544 if ((result = GMPy_MPZ_New(context))) 545 mpz_set(result->z, obj->z); 546 547 return result; 548 } 549 550 /* str and repr implementations for xmpz */ 551 static PyObject * 552 GMPy_XMPZ_Str_Slot(XMPZ_Object *self) 553 { 554 /* base-10, no tag */ 555 return GMPy_PyStr_From_XMPZ(self, 10, 0, NULL); 556 } 557 558 static PyObject * 559 GMPy_XMPZ_Repr_Slot(XMPZ_Object *self) 560 { 561 /* base-10, with tag */ 562 return GMPy_PyStr_From_XMPZ(self, 10, 1, NULL); 563 } 564 565 /* ======================================================================== * 566 * Conversion between native Python objects/MPZ/XMPZ and MPQ. * 567 * ======================================================================== */ 568 569 static MPQ_Object * 570 GMPy_MPQ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context) 571 { 572 MPQ_Object *result; 573 MPZ_Object *temp; 574 575 temp = GMPy_MPZ_From_PyIntOrLong(obj, context); 576 577 if (!temp) 578 return NULL; 579 580 if ((result = GMPy_MPQ_New(context))) { 581 mpq_set_z(result->q, temp->z); 582 Py_DECREF((PyObject*)temp); 583 } 584 return result; 585 } 586 587 static MPQ_Object * 588 GMPy_MPQ_From_PyStr(PyObject *s, int base, CTXT_Object *context) 589 { 590 MPQ_Object *result; 591 char *cp; 592 char exp_char = 'E'; 593 Py_ssize_t len, i; 594 PyObject *ascii_str = NULL; 595 long expt = 0; 596 597 if (!(result = GMPy_MPQ_New(context))) { 598 /* LCOV_EXCL_START */ 599 return NULL; 600 /* LCOV_EXCL_STOP */ 601 } 602 603 if (PyBytes_Check(s)) { 604 len = PyBytes_Size(s); 605 cp = PyBytes_AsString(s); 606 } 607 else if (PyUnicode_Check(s)) { 608 ascii_str = PyUnicode_AsASCIIString(s); 609 if (!ascii_str) { 610 VALUE_ERROR("string contains non-ASCII characters"); 611 goto error; 612 } 613 len = PyBytes_Size(ascii_str); 614 cp = PyBytes_AsString(ascii_str); 615 } 616 else { 617 TYPE_ERROR("object is not string or Unicode"); 618 goto error; 619 } 620 621 /* Don't allow NULL characters */ 622 for (i = 0; i < len; i++) { 623 if (cp[i] == '\0') { 624 VALUE_ERROR("string contains NULL characters"); 625 goto error; 626 } 627 } 628 629 { 630 char *whereslash = strchr((char*)cp, '/'); 631 char *wheredot = strchr((char*)cp, '.'); 632 char *whereexp = strchr((char*)cp, 'E'); 633 634 if (!whereexp) { 635 whereexp = strchr((char*)cp, 'e'); 636 exp_char = 'e'; 637 } 638 639 if (whereslash && wheredot) { 640 VALUE_ERROR("illegal string: both . and / found"); 641 goto error; 642 } 643 644 if (wheredot && (base != 10)) { 645 VALUE_ERROR("illegal string: embedded . requires base=10"); 646 goto error; 647 } 648 649 /* If base=10, no slash is found, and an exponent symbol is found, then 650 * assume we have decimal number in scientific format. 651 */ 652 if (whereexp && !whereslash && (base == 10)) { 653 /* Temporarily shorten the string and continue processing as 654 * normal. We'll deal with the exponent later. 655 */ 656 *whereexp = '\0'; 657 expt = atol(whereexp+1); 658 } 659 660 /* Handle the case where an embedded decimal point exists. An optional 661 * exponent is also allowed. We take advantage of the fact that 662 * mpz_set_str() ignores embedded space characters. We count the 663 * number of digits after the decimal point and then replace the '.' 664 * with a ' '. We've already inserted a NUL byte to terminate the 665 * string in the case when an exponent was entered. The value for 666 * the exponent has already been read. 667 */ 668 669 if (wheredot) { 670 char *counter; 671 long digits = 0; 672 673 counter = wheredot; 674 digits = 0; 675 *wheredot = ' '; 676 while (*++counter != '\0') { 677 if (isdigit(*counter)) 678 digits++; 679 } 680 if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) { 681 if (wheredot) 682 *wheredot = '.'; 683 /* Restore the exponent! */ 684 if (whereexp && !whereslash && (base == 10)) 685 *whereexp = exp_char; 686 VALUE_ERROR("invalid digits"); 687 goto error; 688 } 689 /* Process the exponent. */ 690 digits = expt - digits; 691 if (digits < 0) { 692 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-digits)); 693 } 694 else { 695 /* Use the denominator instead of a temporary variable. */ 696 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(digits)); 697 mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q)); 698 mpz_set_ui(mpq_denref(result->q), 1); 699 } 700 mpq_canonicalize(result->q); 701 702 /* Restore the decimal point. */ 703 *wheredot = '.'; 704 705 /* Restore the exponent! */ 706 if (whereexp && (base == 10)) 707 *whereexp = exp_char; 708 709 goto finish; 710 } 711 712 if (whereslash) 713 *whereslash = '\0'; 714 715 /* Read the numerator. */ 716 if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) { 717 if (whereslash) 718 *whereslash = '/'; 719 VALUE_ERROR("invalid digits"); 720 goto error; 721 } 722 723 /* If a slash was present, read the denominator. */ 724 if (whereslash) { 725 *whereslash = '/'; 726 if (-1 == mpz_set_str(mpq_denref(result->q), whereslash+1, base)) { 727 VALUE_ERROR("invalid digits"); 728 goto error; 729 } 730 if (0 == mpz_sgn(mpq_denref(result->q))) { 731 ZERO_ERROR("zero denominator in mpq()"); 732 goto error; 733 } 734 mpq_canonicalize(result->q); 735 } 736 else { 737 /* Since no slash was present, either the denominator is 1 or a 738 * power of 10. 739 */ 740 741 if (expt <= 0) { 742 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-expt)); 743 } 744 else { 745 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(expt)); 746 mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q)); 747 mpz_set_ui(mpq_denref(result->q), 1); 748 } 749 mpq_canonicalize(result->q); 750 if (whereexp && (base == 10)) 751 *whereexp = exp_char; 752 } 753 } 754 755 finish: 756 Py_XDECREF(ascii_str); 757 return result; 758 759 error: 760 Py_DECREF((PyObject*)result); 761 Py_XDECREF(ascii_str); 762 return NULL; 763 } 764 765 static MPQ_Object * 766 GMPy_MPQ_From_PyFloat(PyObject *obj, CTXT_Object *context) 767 { 768 MPQ_Object *result; 769 770 if ((result = GMPy_MPQ_New(context))) { 771 double d = PyFloat_AsDouble(obj); 772 773 if (Py_IS_NAN(d)) { 774 Py_DECREF((PyObject*)result); 775 VALUE_ERROR("'mpq' does not support NaN"); 776 return NULL; 777 } 778 if (Py_IS_INFINITY(d)) { 779 Py_DECREF((PyObject*)result); 780 OVERFLOW_ERROR("'mpq' does not support Infinity"); 781 return NULL; 782 } 783 mpq_set_d(result->q, d); 784 } 785 786 return result; 787 } 788 789 static MPQ_Object * 790 GMPy_MPQ_From_MPZ(MPZ_Object *obj, CTXT_Object *context) 791 { 792 MPQ_Object *result; 793 794 if ((result = GMPy_MPQ_New(context))) 795 mpq_set_z(result->q, obj->z); 796 797 return result; 798 } 799 800 static MPQ_Object * 801 GMPy_MPQ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context) 802 { 803 MPQ_Object *result; 804 805 if ((result = GMPy_MPQ_New(context))) 806 mpq_set_z(result->q, obj->z); 807 808 return result; 809 } 810 811 static MPZ_Object * 812 GMPy_MPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context) 813 { 814 MPZ_Object *result; 815 816 if ((result = GMPy_MPZ_New(context))) 817 mpz_set_q(result->z, obj->q); 818 819 return result; 820 } 821 822 static XMPZ_Object * 823 GMPy_XMPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context) 824 { 825 XMPZ_Object *result; 826 827 if ((result = GMPy_XMPZ_New(context))) 828 mpz_set_q(result->z, obj->q); 829 830 return result; 831 } 832 #ifdef PY2 833 static PyObject * 834 GMPy_PyLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context) 835 { 836 PyObject *result; 837 MPZ_Object *temp; 838 839 temp = GMPy_MPZ_From_MPQ(obj, context); 840 841 if (!temp) { 842 /* LCOV_EXCL_START */ 843 return NULL; 844 /* LCOV_EXCL_STOP */ 845 } 846 847 result = GMPy_PyLong_From_MPZ(temp, context); 848 Py_DECREF((PyObject*)temp); 849 850 return result; 851 } 852 853 static PyObject * 854 GMPy_MPQ_Long_Slot(MPQ_Object *self) 855 { 856 return GMPy_PyLong_From_MPQ(self, NULL); 857 } 858 #endif 859 860 static PyObject * 861 GMPy_PyIntOrLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context) 862 { 863 PyObject *result; 864 MPZ_Object *temp; 865 866 temp = GMPy_MPZ_From_MPQ(obj, context); 867 868 if (!temp) { 869 /* LCOV_EXCL_START */ 870 return NULL; 871 /* LCOV_EXCL_STOP */ 872 } 873 874 result = GMPy_PyIntOrLong_From_MPZ(temp, context); 875 Py_DECREF((PyObject*)temp); 876 877 return result; 878 } 879 880 static PyObject * 881 GMPy_MPQ_Int_Slot(MPQ_Object *self) 882 { 883 return GMPy_PyIntOrLong_From_MPQ(self, NULL); 884 } 885 886 static char* _qtag = "mpq("; 887 888 static PyObject * 889 GMPy_PyStr_From_MPQ(MPQ_Object *obj, int base, int option, CTXT_Object *context) 890 { 891 PyObject *result = NULL, *numstr = NULL, *denstr = NULL; 892 char buffer[50], *p; 893 894 numstr = mpz_ascii(mpq_numref(obj->q), base, 0, 0); 895 if (!numstr) { 896 /* LCOV_EXCL_START */ 897 return NULL; 898 /* LCOV_EXCL_STOP */ 899 } 900 901 /* Check if denominator is 1 and no tag is requested. If so, just 902 * return the numerator. 903 */ 904 if (!(option & 1) && (0 == mpz_cmp_ui(mpq_denref(obj->q),1))) 905 return numstr; 906 907 denstr = mpz_ascii(mpq_denref(obj->q), base, 0, 0); 908 if (!denstr) { 909 /* LCOV_EXCL_START */ 910 Py_DECREF(numstr); 911 return NULL; 912 /* LCOV_EXCL_STOP */ 913 } 914 915 /* Build the format string. */ 916 p = buffer; 917 if (option & 1) { 918 strcpy(p, _qtag); 919 p += strlen(p); 920 } 921 922 #ifdef PY2 923 *(p++) = '%'; 924 *(p++) = 's'; 925 if (option & 1) 926 *(p++) = ','; 927 else 928 *(p++) = '/'; 929 *(p++) = '%'; 930 *(p++) = 's'; 931 if (option & 1) 932 *(p++) = ')'; 933 *(p++) = '\00'; 934 result = PyString_FromFormat(buffer, PyString_AS_STRING(numstr), 935 PyString_AS_STRING(denstr)); 936 #else 937 *(p++) = '%'; 938 *(p++) = 'U'; 939 if (option & 1) 940 *(p++) = ','; 941 else 942 *(p++) = '/'; 943 *(p++) = '%'; 944 *(p++) = 'U'; 945 if (option & 1) 946 *(p++) = ')'; 947 *(p++) = '\00'; 948 result = PyUnicode_FromFormat(buffer, numstr, denstr); 949 #endif 950 Py_DECREF(numstr); 951 Py_DECREF(denstr); 952 return result; 953 } 954 955 static PyObject * 956 GMPy_PyFloat_From_MPQ(MPQ_Object *obj, CTXT_Object *context) 957 { 958 double res; 959 960 res = mpq_get_d(obj->q); 961 962 if (Py_IS_INFINITY(res)) { 963 OVERFLOW_ERROR("'mpq' too large to convert to float"); 964 return NULL; 965 } 966 967 return PyFloat_FromDouble(res); 968 } 969 970 static PyObject * 971 GMPy_MPQ_Float_Slot(MPQ_Object *self) 972 { 973 return GMPy_PyFloat_From_MPQ(self, NULL); 974 } 975 976 static MPQ_Object* 977 GMPy_MPQ_From_Fraction(PyObject* obj, CTXT_Object *context) 978 { 979 MPQ_Object *result; 980 PyObject *num, *den; 981 982 if (!(result = GMPy_MPQ_New(context))) { 983 /* LCOV_EXCL_START */ 984 return NULL; 985 /* LCOV_EXCL_STOP */ 986 } 987 mpq_set_si(result->q, 0, 1); 988 989 num = PyObject_GetAttrString(obj, "numerator"); 990 den = PyObject_GetAttrString(obj, "denominator"); 991 if (!num || !PyIntOrLong_Check(num) || !den || !PyIntOrLong_Check(den)) { 992 SYSTEM_ERROR("Object does not appear to be Fraction"); 993 Py_XDECREF(num); 994 Py_XDECREF(den); 995 Py_DECREF((PyObject*)result); 996 return NULL; 997 } 998 mpz_set_PyIntOrLong(mpq_numref(result->q), num); 999 mpz_set_PyIntOrLong(mpq_denref(result->q), den); 1000 Py_DECREF(num); 1001 Py_DECREF(den); 1002 return result; 1003 } 1004 1005 static MPQ_Object* 1006 GMPy_MPQ_From_Number(PyObject *obj, CTXT_Object *context) 1007 { 1008 if (MPQ_Check(obj)) { 1009 Py_INCREF(obj); 1010 return (MPQ_Object*)obj; 1011 } 1012 1013 if (MPZ_Check(obj)) 1014 return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context); 1015 1016 if (MPFR_Check(obj)) 1017 return GMPy_MPQ_From_MPFR((MPFR_Object*)obj, context); 1018 1019 if (PyFloat_Check(obj)) 1020 return GMPy_MPQ_From_PyFloat(obj, context); 1021 1022 if (PyIntOrLong_Check(obj)) 1023 return GMPy_MPQ_From_PyIntOrLong(obj, context); 1024 1025 if (XMPZ_Check(obj)) 1026 return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context); 1027 1028 if (IS_FRACTION(obj)) 1029 return GMPy_MPQ_From_Fraction(obj, context); 1030 1031 if (HAS_MPQ_CONVERSION(obj)) { 1032 MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL); 1033 1034 if (res != NULL && MPQ_Check(res)) { 1035 return res; 1036 } 1037 else { 1038 Py_XDECREF((PyObject*)res); 1039 goto error; 1040 } 1041 } 1042 1043 if (HAS_MPZ_CONVERSION(obj)) { 1044 MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL); 1045 1046 if (res != NULL && MPZ_Check(res)) { 1047 MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context); 1048 Py_DECREF(res); 1049 return temp; 1050 } 1051 else { 1052 Py_XDECREF((PyObject*)res); 1053 goto error; 1054 } 1055 } 1056 1057 error: 1058 TYPE_ERROR("cannot convert object to mpq"); 1059 return NULL; 1060 } 1061 1062 static MPQ_Object* 1063 GMPy_MPQ_From_NumberWithType(PyObject *obj, int xtype, CTXT_Object *context) 1064 { 1065 if (IS_TYPE_MPQ(xtype)) { 1066 Py_INCREF(obj); 1067 return (MPQ_Object*)obj; 1068 } 1069 1070 if (IS_TYPE_MPZ(xtype)) 1071 return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context); 1072 1073 if (IS_TYPE_MPFR(xtype)) 1074 return GMPy_MPQ_From_MPFR((MPFR_Object*)obj, context); 1075 1076 if (IS_TYPE_PyFloat(xtype)) 1077 return GMPy_MPQ_From_PyFloat(obj, context); 1078 1079 if (IS_TYPE_PyInteger(xtype)) 1080 return GMPy_MPQ_From_PyIntOrLong(obj, context); 1081 1082 if (IS_TYPE_XMPZ(xtype)) 1083 return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context); 1084 1085 if (IS_TYPE_PyFraction(xtype)) 1086 return GMPy_MPQ_From_Fraction(obj, context); 1087 1088 if (IS_TYPE_HAS_MPQ(xtype)) { 1089 MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL); 1090 1091 if (res != NULL && MPQ_Check(res)) { 1092 return res; 1093 } 1094 else { 1095 Py_XDECREF((PyObject*)res); 1096 goto error; 1097 } 1098 } 1099 1100 if (IS_TYPE_HAS_MPZ(xtype)) { 1101 MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL); 1102 1103 if (res != NULL && MPZ_Check(res)) { 1104 MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context); 1105 Py_DECREF(res); 1106 return temp; 1107 } 1108 else { 1109 Py_XDECREF((PyObject*)res); 1110 goto error; 1111 } 1112 } 1113 1114 error: 1115 TYPE_ERROR("cannot convert object to mpq"); 1116 return NULL; 1117 } 1118 1119 static MPQ_Object* 1120 GMPy_MPQ_From_RationalWithTypeAndCopy(PyObject *obj, int xtype, CTXT_Object *context) 1121 { 1122 MPQ_Object *result = NULL, *temp = NULL; 1123 1124 result = GMPy_MPQ_From_RationalWithType(obj, xtype, context); 1125 1126 if (result == NULL) 1127 return result; 1128 1129 if (Py_REFCNT(result) == 1) 1130 return result; 1131 1132 if (!(temp = GMPy_MPQ_New(context))) { 1133 /* LCOV_EXCL_START */ 1134 return NULL; 1135 /* LCOV_EXCL_STOP */ 1136 } 1137 1138 mpq_set(temp->q, result->q); 1139 Py_DECREF((PyObject*)result); 1140 return temp; 1141 } 1142 1143 static MPQ_Object* 1144 GMPy_MPQ_From_Rational(PyObject *obj, CTXT_Object *context) 1145 { 1146 if (MPQ_Check(obj)) { 1147 Py_INCREF(obj); 1148 return (MPQ_Object*)obj; 1149 } 1150 1151 if (MPZ_Check(obj)) 1152 return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context); 1153 1154 if (PyIntOrLong_Check(obj)) 1155 return GMPy_MPQ_From_PyIntOrLong(obj, context); 1156 1157 if (XMPZ_Check(obj)) 1158 return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context); 1159 1160 if (IS_FRACTION(obj)) 1161 return GMPy_MPQ_From_Fraction(obj, context); 1162 1163 if (HAS_MPQ_CONVERSION(obj)) { 1164 MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL); 1165 1166 if (res != NULL && MPQ_Check(res)) { 1167 return res; 1168 } 1169 else { 1170 Py_XDECREF((PyObject*)res); 1171 goto error; 1172 } 1173 } 1174 1175 if (HAS_MPZ_CONVERSION(obj)) { 1176 MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL); 1177 1178 if (res != NULL && MPZ_Check(res)) { 1179 MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context); 1180 Py_DECREF(res); 1181 return temp; 1182 } 1183 else { 1184 Py_XDECREF((PyObject*)res); 1185 goto error; 1186 } 1187 } 1188 1189 error: 1190 TYPE_ERROR("cannot convert object to mpq"); 1191 return NULL; 1192 } 1193 1194 static MPQ_Object* 1195 GMPy_MPQ_From_RationalWithType(PyObject *obj, int xtype, CTXT_Object *context) 1196 { 1197 if (IS_TYPE_MPQ(xtype)) { 1198 Py_INCREF(obj); 1199 return (MPQ_Object*)obj; 1200 } 1201 1202 if (IS_TYPE_MPZ(xtype)) 1203 return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context); 1204 1205 if (IS_TYPE_PyInteger(xtype)) 1206 return GMPy_MPQ_From_PyIntOrLong(obj, context); 1207 1208 if (IS_TYPE_XMPZ(xtype)) 1209 return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context); 1210 1211 if (IS_TYPE_PyFraction(xtype)) 1212 return GMPy_MPQ_From_Fraction(obj, context); 1213 1214 if (IS_TYPE_HAS_MPQ(xtype)) { 1215 MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL); 1216 1217 if (res != NULL && MPQ_Check(res)) { 1218 return res; 1219 } 1220 else { 1221 Py_XDECREF((PyObject*)res); 1222 goto error; 1223 } 1224 } 1225 1226 if (IS_TYPE_HAS_MPZ(xtype)) { 1227 MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL); 1228 1229 if (res != NULL && MPZ_Check(res)) { 1230 MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context); 1231 Py_DECREF(res); 1232 return temp; 1233 } 1234 else { 1235 Py_XDECREF((PyObject*)res); 1236 goto error; 1237 } 1238 } 1239 1240 error: 1241 TYPE_ERROR("cannot convert object to mpq"); 1242 return NULL; 1243 } 1244 1245 /* 1246 * coerce any number to a mpq 1247 */ 1248 1249 #ifdef SHARED 1250 /* Helper function for argument parsing. Not used in static build. */ 1251 1252 int 1253 GMPy_MPQ_ConvertArg(PyObject *arg, PyObject **ptr) 1254 { 1255 MPQ_Object* result = GMPy_MPQ_From_NumberWithType(arg, GMPy_ObjectType(arg), NULL); 1256 1257 if (result) { 1258 *ptr = (PyObject*)result; 1259 return 1; 1260 } 1261 else { 1262 if (!PyErr_Occurred()) { 1263 TYPE_ERROR("argument can not be converted to 'mpq'"); 1264 } 1265 return 0; 1266 } 1267 } 1268 1269 #endif 1270 1271 /* str and repr implementations for mpq */ 1272 static PyObject * 1273 GMPy_MPQ_Str_Slot(MPQ_Object *self) 1274 { 1275 /* base-10, no tag */ 1276 return GMPy_PyStr_From_MPQ(self, 10, 0, NULL); 1277 } 1278 1279 static PyObject * 1280 GMPy_MPQ_Repr_Slot(MPQ_Object *self) 1281 { 1282 /* base-10, with tag */ 1283 return GMPy_PyStr_From_MPQ(self, 10, 1, NULL); 1284 } 1285