/ src / gmpy2_binary.c
gmpy2_binary.c
   1  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   2   * gmpy2_binary.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  /* Conversion routines between GMPY2 objects and a compact, portable
  28   * binary representation. The binary format of GMPY2 is not compatible
  29   * with GMPY 1.x. Methods to read the old format are provided.
  30   */
  31  
  32  /* Provide functions to access the old binary formats. */
  33  
  34  PyDoc_STRVAR(doc_mpz_from_old_binary,
  35  "mpz_from_old_binary(string) -> mpz\n\n"
  36  "Return an 'mpz' from a GMPY 1.x binary format.");
  37  
  38  static PyObject *
  39  GMPy_MPZ_From_Old_Binary(PyObject *self, PyObject *other)
  40  {
  41      unsigned char *cp;
  42      Py_ssize_t len;
  43      int negative = 0;
  44      MPZ_Object *result;
  45  
  46      if (!(PyBytes_Check(other))) {
  47          TYPE_ERROR("mpz_from_old_binary() requires bytes argument");
  48          return NULL;
  49      }
  50  
  51      if (!(result = GMPy_MPZ_New(NULL))) {
  52          /* LCOV_EXCL_START */
  53          return NULL;
  54          /* LCOV_EXCL_STOP */
  55      }
  56  
  57      len = PyBytes_Size(other);
  58      cp = (unsigned char*)PyBytes_AsString(other);
  59  
  60      if (cp[len-1] == 0xFF) {
  61          negative = 1;
  62          --len;
  63      }
  64      mpz_import(result->z, len, -1, sizeof(char), 0, 0, cp);
  65      if (negative)
  66          mpz_neg(result->z, result->z);
  67      return (PyObject*)result;
  68  }
  69  
  70  PyDoc_STRVAR(doc_mpq_from_old_binary,
  71  "mpq_from_old_binary(string) -> mpq\n\n"
  72  "Return an 'mpq' from a GMPY 1.x binary format.");
  73  
  74  static PyObject *
  75  GMPy_MPQ_From_Old_Binary(PyObject *self, PyObject *other)
  76  {
  77      unsigned char *cp;
  78      Py_ssize_t len;
  79      int topper, negative, numlen;
  80      mpz_t numerator, denominator;
  81      MPQ_Object *result;
  82  
  83      if (!(PyBytes_Check(other))) {
  84          TYPE_ERROR("mpq_from_old_binary() requires bytes argument");
  85          return NULL;
  86      }
  87  
  88      if (!(result = GMPy_MPQ_New(NULL))) {
  89          /* LCOV_EXCL_START */
  90          return NULL;
  91          /* LCOV_EXCL_STOP */
  92      }
  93  
  94      len = PyBytes_Size(other);
  95      cp = (unsigned char*)PyBytes_AsString(other);
  96  
  97      if (len < 6) {
  98          VALUE_ERROR("invalid mpq binary (too short)");
  99          Py_DECREF((PyObject*)result);
 100          return NULL;
 101      }
 102  
 103      topper = cp[3] & 0x7f;
 104      negative = cp[3] & 0x80;
 105      numlen = cp[0] + 256 * (cp[1] + 256 * (cp[2] + 256 * topper));
 106      if (len < (4 + numlen + 1)) {
 107          VALUE_ERROR("invalid mpq binary (num len)");
 108          Py_DECREF((PyObject*)result);
 109          return NULL;
 110      }
 111  
 112      mpz_init(numerator);
 113      mpz_init(denominator);
 114      mpz_import(numerator, numlen, -1, sizeof(char), 0, 0, cp+4);
 115      mpz_import(denominator, len-4-numlen, -1, sizeof(char), 0, 0, cp+4+numlen);
 116      if (negative)
 117          mpz_neg(numerator, numerator);
 118  
 119      mpq_set_num(result->q, numerator);
 120      mpq_set_den(result->q, denominator);
 121      mpq_canonicalize(result->q);
 122      mpz_clear(numerator);
 123      mpz_clear(denominator);
 124      return (PyObject*)result;
 125  }
 126  
 127  PyDoc_STRVAR(doc_mpfr_from_old_binary,
 128  "mpfr_from_old_binary(string) -> mpfr\n\n"
 129  "Return an 'mpfr' from a GMPY 1.x binary mpf format.");
 130  
 131  static PyObject *
 132  GMPy_MPFR_From_Old_Binary(PyObject *self, PyObject *other)
 133  {
 134      unsigned char *cp;
 135      Py_ssize_t len;
 136      MPFR_Object *result;
 137      mpfr_t digit;
 138      mpfr_prec_t prec;
 139      int i, codebyte, resusign, exposign, resuzero, precilen;
 140      unsigned int expomag = 0;
 141      CTXT_Object *context = NULL;
 142  
 143      CHECK_CONTEXT(context);
 144  
 145      if (!(PyBytes_Check(other))) {
 146          TYPE_ERROR("mpfr_from_old_binary() requires bytes argument");
 147          return NULL;
 148      }
 149  
 150      len = PyBytes_Size(other);
 151      cp = (unsigned char*)PyBytes_AsString(other);
 152  
 153      if (len == 1) {
 154          prec = 0;
 155      }
 156      else {
 157          prec = (mpfr_prec_t)(8 * (len - 5));
 158          if ((len>=5) && (cp[0]&8)) {
 159              prec = 0;
 160              for (i=4; i>0; --i) {
 161                  prec = (prec << 8) | cp[i];
 162              }
 163          }
 164      }
 165  
 166      /*
 167       * binary format for MP floats: first, a code-byte, then, a LSB
 168       * 4-byte unsigned int (exponent magnitude), then the "mantissa"
 169       * (actually, "significand", but "mantissa" is the usual term...)
 170       * in MSB form.
 171       *
 172       * The codebyte encodes both the signs, exponent and result, or
 173       * also the zeroness of the result (in which case, nothing more).
 174       */
 175      codebyte = cp[0];
 176      resusign = codebyte & 1;
 177      exposign = codebyte & 2;
 178      resuzero = codebyte & 4;
 179      precilen = (codebyte & 8)?4:0;
 180  
 181      /* mpfr zero has a very compact (1-byte) binary encoding!-) */
 182      if (resuzero) {
 183          if (!(result = GMPy_MPFR_New(prec, context))) {
 184              /* LCOV_EXCL_START */
 185              return NULL;
 186              /* LCOV_EXCL_STOP */
 187          }
 188          result->rc = mpfr_set_ui(result->f, 0, MPFR_RNDN);
 189          return (PyObject*)result;
 190      }
 191  
 192      /* all other numbers are 6+ bytes: codebyte, 4-byte exp, 1+
 193       * bytes for the mantissa; check this string is 6+ bytes
 194       */
 195      if (len < 6 + precilen) {
 196          VALUE_ERROR("invalid mpf binary encoding (too short)");
 197          return NULL;
 198      }
 199  
 200      if (!(result = GMPy_MPFR_New(prec, context))) {
 201          /* LCOV_EXCL_START */
 202          return NULL;
 203          /* LCOV_EXCL_STOP */
 204      }
 205  
 206      /* reconstruct exponent */
 207      for (i = 4 + precilen; i > precilen; --i) {
 208          expomag = (expomag<<8) | cp[i];
 209      }
 210  
 211      /* reconstruct 'mantissa' (significand) */
 212      mpfr_set_si(result->f, 0, MPFR_RNDN);
 213      mpfr_init2(digit, prec);
 214      for (i = 5 + precilen; i<len; i++) {
 215          mpfr_set_ui(digit, cp[i], MPFR_RNDN);
 216          mpfr_div_2ui(digit, digit, (unsigned long)((i-4-precilen) * 8),
 217                       context->ctx.mpfr_round);
 218          mpfr_add(result->f, result->f, digit, MPFR_RNDN);
 219      }
 220      mpfr_clear(digit);
 221      /* apply exponent, with its appropriate sign */
 222      if (exposign)
 223          mpfr_div_2ui(result->f, result->f, 8*expomag, MPFR_RNDN);
 224      else
 225          mpfr_mul_2ui(result->f, result->f, 8*expomag, MPFR_RNDN);
 226      /* apply significand-sign (sign of the overall number) */
 227      if (resusign)
 228          mpfr_neg(result->f, result->f, MPFR_RNDN);
 229  
 230      return (PyObject*)result;
 231  }
 232  
 233  /* Format of the binary representation of an mpz/xmpz.
 234   *
 235   * byte[0]:     1 => mpz
 236   *              2 => xmpz
 237   *              3 => mpq  (see Pympq_To_Binary)
 238   *              4 => mpfr (see Pympfr_To_Binary)
 239   *              5 => mpc  (see Pympc_To_Binary)
 240   * byte[1:0-1]: 0 => value is 0
 241   *              1 => value is > 0
 242   *              2 => value is < 0
 243   *              3 => unassigned
 244   * byte[2]+: value
 245   */
 246  
 247  static PyObject *
 248  GMPy_MPZ_To_Binary(MPZ_Object *self)
 249  {
 250      size_t size = 2;
 251      int sgn;
 252      char *buffer;
 253      PyObject *result;
 254  
 255      sgn = mpz_sgn(self->z);
 256      if (sgn == 0) {
 257          TEMP_ALLOC(buffer, size);
 258          buffer[0] = 0x01;
 259          buffer[1] = 0x00;
 260          goto done;
 261      }
 262  
 263      size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2;
 264  
 265      TEMP_ALLOC(buffer, size);
 266      buffer[0] = 0x01;
 267      if (sgn > 0)
 268          buffer[1] = 0x01;
 269      else
 270          buffer[1] = 0x02;
 271      mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z);
 272  
 273    done:
 274      result = PyBytes_FromStringAndSize(buffer, size);
 275      TEMP_FREE(buffer, size);
 276      return result;
 277  }
 278  
 279  static PyObject *
 280  GMPy_XMPZ_To_Binary(XMPZ_Object *self)
 281  {
 282      size_t size = 2;
 283      int sgn;
 284      char *buffer;
 285      PyObject *result;
 286  
 287      sgn = mpz_sgn(self->z);
 288      if (sgn == 0) {
 289          TEMP_ALLOC(buffer, size);
 290          buffer[0] = 0x02;
 291          buffer[1] = 0x00;
 292          goto done;
 293      }
 294  
 295      size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2;
 296  
 297      TEMP_ALLOC(buffer, size);
 298      buffer[0] = 0x02;
 299      if (sgn > 0)
 300          buffer[1] = 0x01;
 301      else
 302          buffer[1] = 0x02;
 303      mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z);
 304  
 305    done:
 306      result = PyBytes_FromStringAndSize(buffer, size);
 307      TEMP_FREE(buffer, size);
 308      return result;
 309  }
 310  
 311  /* Format of the binary representation of an mpq.
 312   *
 313   * byte[0]:     1 => mpz  (see Pympz_To_Binary)
 314   *              2 => xmpz (see Pyxmpz_To_Binary)
 315   *              3 => mpq
 316   *              4 => mpfr (see Pympfr_To_Binary)
 317   *              5 => mpc  (see Pympc_To_Binary)
 318   * byte[1:0-1]: 0 => value is 0
 319   *              1 => value is > 0
 320   *              2 => value is < 0
 321   *              3 => unassigned
 322   * byte[1:2-2]: 0 => 32-bit length (n=4)
 323   *              1 => 64-bit length (n=8)
 324   * byte[2+]:    numerator length, using either 4 or 8 bytes
 325   * byte[2+n]+:  numerator, followed by denominator
 326   */
 327  
 328  static PyObject *
 329  GMPy_MPQ_To_Binary(MPQ_Object *self)
 330  {
 331      size_t sizenum, sizeden, sizesize = 4, size = 2, sizetemp, i;
 332      size_t count = 0;
 333      int sgn;
 334      char *buffer, large = 0x00;
 335      PyObject *result = 0;
 336  
 337      sgn = mpq_sgn(self->q);
 338      if (sgn == 0) {
 339          TEMP_ALLOC(buffer, size);
 340          buffer[0] = 0x03;
 341          buffer[1] = 0x00;
 342          goto done;
 343      }
 344  
 345      sizenum = (mpz_sizeinbase(mpq_numref(self->q), 2) + 7) / 8;
 346      sizeden = (mpz_sizeinbase(mpq_denref(self->q), 2) + 7) / 8;
 347      size = sizenum + sizeden + 2;
 348  
 349      /* Check if sizenum larger than 32 bits. */
 350      if ((sizenum >> 16) >> 16) {
 351          /* Current versions of GMP do not allow values to be this large. The
 352           * test is left to (possibly) support future versions that support
 353           * larger values.
 354           */
 355          /* LCOV_EXCL_START */
 356          large = 0x04;
 357          sizesize = 8;
 358          /* LCOV_EXCL_STOP */
 359      }
 360      size += sizesize;
 361  
 362      TEMP_ALLOC(buffer, size);
 363      buffer[0] = 0x03;
 364      if (sgn > 0)
 365          buffer[1] = 0x01 | large;
 366      else
 367          buffer[1] = 0x02 | large;
 368  
 369      /* Copy sizenum to the buffer. */
 370      sizetemp = sizenum;
 371      for (i=0; i<sizesize; i++) {
 372          buffer[i+2] = (char)(sizetemp & 0xff);
 373          sizetemp >>= 8;
 374      }
 375  
 376      mpz_export(buffer+sizesize+2, &count, -1,
 377                 sizeof(char), 0, 0, mpq_numref(self->q));
 378      if (count != sizenum) {
 379          /* LCOV_EXCL_START */
 380          SYSTEM_ERROR("internal error in Pympq_To_Binary");
 381          TEMP_FREE(buffer, size);
 382          return NULL;
 383          /* LCOV_EXCL_STOP */
 384      }
 385      count = 0;
 386      mpz_export(buffer+sizenum+sizesize+2, &count, -1,
 387                 sizeof(char), 0, 0, mpq_denref(self->q));
 388      if (count != sizeden) {
 389          /* LCOV_EXCL_START */
 390          SYSTEM_ERROR("internal error in Pympq_To_Binary");
 391          TEMP_FREE(buffer, size);
 392          return NULL;
 393          /* LCOV_EXCL_STOP */
 394      }
 395  
 396  
 397    done:
 398      result = PyBytes_FromStringAndSize(buffer, size);
 399      TEMP_FREE(buffer, size);
 400      return result;
 401  }
 402  
 403  /* Format of the binary representation of an mpfr.
 404   *
 405   * byte[0]:      1 => mpz  (see Pympz_To_Binary)
 406   *               2 => xmpz (see Pyxmpz_To_Binary)
 407   *               3 => mpq  (see Pympq_To_Binary)
 408   *               4 => mpfr
 409   *               5 => mpc  (see Pympc_To_Binary)
 410   * byte[1:0]:    0 => value is "special"
 411   *               1 => value is an actual number
 412   * byte[1:1]:    0 => signbit is clear
 413   *               1 => signbit is set
 414   * byte[1:2-2]:  0 => 32-bit lengths (n=4)
 415   *               1 => 64-bit lengths (n=8)
 416   * byte[1:3-4]:  0 => 0 (see signbit)
 417   *               1 => value is NaN
 418   *               2 => value is Inf (see signbit)
 419   *               3 => unassigned
 420   * byte[1:5]:    0 => exponent is positive
 421   *               1 => exponent is negative
 422   * byte[1:6]:    0 => 4 byte limbs
 423   *               1 => 8 byte limbs
 424   * byte[2]:      0 => rc = 0
 425   *               1 => rc > 0
 426   *               2 => rc < 0
 427   * byte[3]:      mpfr.round_mode
 428   * byte[4]+:     precision, saved in 4 or 8 bytes
 429   * byte[4+n]+:   exponent, saved in 4 or 8 bytes
 430   * byte[4+2n]+:  mantissa
 431   */
 432  
 433  static PyObject *
 434  GMPy_MPFR_To_Binary(MPFR_Object *self)
 435  {
 436      size_t sizemant = 0, sizesize = 4, size = 4, sizetemp, i;
 437      mp_limb_t templimb;
 438      mpfr_prec_t precision;
 439      mpfr_exp_t exponent = 0;
 440      int sgn;
 441      char *buffer, *cp, large = 0x00, expsgn = 0x00;
 442      PyObject *result = 0;
 443  
 444      /* Check if the precision, exponent and mantissa length can fit in
 445       * 32 bits.
 446       */
 447  
 448      sgn = mpfr_signbit(self->f);
 449      precision = mpfr_get_prec(self->f);
 450  
 451      /* Exponent and mantiss are only valid for regular numbers
 452       * (not 0, Nan, Inf, -Inf).
 453       */
 454      if (mpfr_regular_p(self->f)) {
 455          exponent = self->f->_mpfr_exp;
 456          if (exponent < 0) {
 457              exponent = -exponent;
 458              expsgn = 0x20;
 459          }
 460          /* Calculate the size of mantissa in limbs */
 461          sizemant = (self->f->_mpfr_prec + mp_bits_per_limb - 1)/mp_bits_per_limb;
 462      }
 463      if (((exponent >> 16) >> 16) ||
 464          ((precision >> 16) >> 16) ||
 465          ((sizemant >> 16) >> 16)) {
 466          /* This can only be tested on 64-bit platforms. lcov will report the
 467           * code as not tested until 64-bit specific tests are created.
 468           */
 469          sizesize = 8;
 470          large = 0x04;
 471      }
 472  
 473      if (!mpfr_regular_p(self->f)) {
 474          /* Only need to save the precision. */
 475          size += sizesize;
 476          TEMP_ALLOC(buffer, size);
 477          buffer[0] = 0x04;
 478  
 479          /* Set to all 0 since we are special. */
 480          buffer[1] = 0x00;
 481  
 482          /* Set the sign bit. */
 483          if (sgn) buffer[1] |= 0x02;
 484  
 485          /* 4 or 8 byte values. */
 486          buffer[1] |= large;
 487  
 488          /* Check if NaN. */
 489          if (mpfr_nan_p(self->f)) buffer[1] |= 0x08;
 490  
 491          /* Check if Infinity. */
 492          if (mpfr_inf_p(self->f)) buffer[1] |= 0x10;
 493  
 494          /* Save the result code */
 495          if (self->rc == 0)     buffer[2] = 0x00;
 496          else if (self->rc > 0) buffer[2] = 0x01;
 497          else                   buffer[2] = 0x02;
 498  
 499          /* Save the precision */
 500          sizetemp = precision;
 501          for (i=0; i<sizesize; i++) {
 502              buffer[i+4] = (char)(sizetemp & 0xff);
 503              sizetemp >>= 8;
 504          }
 505          goto done;
 506      }
 507  
 508      /* Now process all actual numbers. */
 509      size += (2 * sizesize) + (sizemant * (mp_bits_per_limb >> 3));
 510      TEMP_ALLOC(buffer, size);
 511      buffer[0] = 0x04;
 512  
 513      /* Set bit 0 to 1 since we are an actual number. */
 514      buffer[1] = 0x01;
 515  
 516      /* Save the sign bit. */
 517      if (sgn) buffer[1] |= 0x02;
 518  
 519      /* Save the size of the values. */
 520      buffer[1] |= large;
 521  
 522      /* Save the exponent sign. */
 523      buffer[1] |= expsgn;
 524  
 525      /* Save the limb size. */
 526      if ((mp_bits_per_limb >> 3) == 8)
 527          buffer[1] |= 0x40;
 528      /* This branch can only be reached on 32-bit platforms. */
 529      else if ((mp_bits_per_limb >> 3) != 4) {
 530          /* LCOV_EXCL_START */
 531          SYSTEM_ERROR("cannot support current limb size");
 532          TEMP_FREE(buffer, size);
 533          return NULL;
 534          /* LCOV_EXCL_STOP */
 535      }
 536  
 537      /* Save the result code. */
 538      if (self->rc == 0)     buffer[2] = 0x00;
 539      else if (self->rc > 0) buffer[2] = 0x01;
 540      else                   buffer[2] = 0x02;
 541  
 542      /* Rounding mode is no longer used, so just store a null byte. */
 543      buffer[3] = 0x00;
 544  
 545      /* Save the precision */
 546      cp = buffer + 4;
 547      sizetemp = precision;
 548      for (i=0; i<sizesize; i++) {
 549          cp[i] = (char)(sizetemp & 0xff);
 550          sizetemp >>= 8;
 551      }
 552  
 553      /* Save the exponenet */
 554      cp += sizesize;
 555      sizetemp = exponent;
 556      for (i=0; i<sizesize; i++) {
 557          cp[i] = (char)(sizetemp & 0xff);
 558          sizetemp >>= 8;
 559      }
 560  
 561      /* Save the actual mantissa */
 562      cp += sizesize;
 563      for (i=0; i<sizemant; i++) {
 564          templimb = self->f->_mpfr_d[i];
 565  #if GMP_LIMB_BITS == 64
 566          cp[0] = (char)(templimb & 0xff);
 567          templimb >>= 8;
 568          cp[1] = (char)(templimb & 0xff);
 569          templimb >>= 8;
 570          cp[2] = (char)(templimb & 0xff);
 571          templimb >>= 8;
 572          cp[3] = (char)(templimb & 0xff);
 573          templimb >>= 8;
 574          cp[4] = (char)(templimb & 0xff);
 575          templimb >>= 8;
 576          cp[5] = (char)(templimb & 0xff);
 577          templimb >>= 8;
 578          cp[6] = (char)(templimb & 0xff);
 579          templimb >>= 8;
 580          cp[7] = (char)(templimb & 0xff);
 581          cp += 8;
 582  #endif
 583  #if GMP_LIMB_BITS == 32
 584          cp[0] = (char)(templimb & 0xff);
 585          templimb >>= 8;
 586          cp[1] = (char)(templimb & 0xff);
 587          templimb >>= 8;
 588          cp[2] = (char)(templimb & 0xff);
 589          templimb >>= 8;
 590          cp[3] = (char)(templimb & 0xff);
 591          cp += 4;
 592  #endif
 593  }
 594  
 595    done:
 596      result = PyBytes_FromStringAndSize(buffer, size);
 597      TEMP_FREE(buffer, size);
 598      return result;
 599  }
 600  
 601  /* Format of the binary representation of an mpc.
 602   *
 603   * The format consists of the concatenation of mpfrs (real and imaginary)
 604   * converted to binary format. The 0x04 leading byte of each binary string
 605   * is replaced by 0x05.
 606   */
 607  
 608  static PyObject *
 609  GMPy_MPC_To_Binary(MPC_Object *obj)
 610  {
 611      MPFR_Object *real = NULL, *imag = NULL;
 612      PyObject *result = NULL, *temp = NULL;
 613      mpfr_prec_t rprec = 0, iprec = 0;
 614      CTXT_Object *context = NULL;
 615  
 616      CHECK_CONTEXT(context);
 617  
 618      mpc_get_prec2(&rprec, &iprec, obj->c);
 619  
 620      if (!(real = GMPy_MPFR_New(rprec, context)) ||
 621          !(imag = GMPy_MPFR_New(iprec, context))) {
 622          /* LCOV_EXCL_START */
 623          Py_XDECREF((PyObject*)real);
 624          Py_XDECREF((PyObject*)imag);
 625          return NULL;
 626          /* LCOV_EXCL_STOP */
 627      }
 628  
 629      mpfr_set(real->f, mpc_realref(obj->c), MPFR_RNDN);
 630      mpfr_set(imag->f, mpc_imagref(obj->c), MPFR_RNDN);
 631      real->rc = obj->rc;
 632  
 633      if (!(result = GMPy_MPFR_To_Binary(real)) ||
 634          !(temp = GMPy_MPFR_To_Binary(imag))) {
 635          /* LCOV_EXCL_START */
 636          Py_XDECREF((PyObject*)result);
 637          Py_XDECREF((PyObject*)temp);
 638          Py_DECREF((PyObject*)real);
 639          Py_DECREF((PyObject*)imag);
 640          return NULL;
 641          /* LCOV_EXCL_STOP */
 642      }
 643  
 644      Py_DECREF((PyObject*)real);
 645      Py_DECREF((PyObject*)imag);
 646  
 647      PyBytes_AS_STRING(result)[0] = 0x05;
 648      PyBytes_AS_STRING(temp)[0] = 0x05;
 649  
 650      PyBytes_ConcatAndDel(&result, temp);
 651      return result;
 652  }
 653  
 654  PyDoc_STRVAR(doc_from_binary,
 655  "from_binary(bytes) -> gmpy2 object\n"
 656  "Return a Python object from a byte sequence created by\n"
 657  "gmpy2.to_binary().");
 658  
 659  
 660  static PyObject *
 661  GMPy_MPANY_From_Binary(PyObject *self, PyObject *other)
 662  {
 663      unsigned char *buffer, *cp;
 664      Py_ssize_t len;
 665      CTXT_Object *context = NULL;
 666  
 667      CHECK_CONTEXT(context);
 668  
 669      if (!(PyBytes_Check(other))) {
 670          TYPE_ERROR("from_binary() requires bytes argument");
 671          return NULL;
 672      }
 673  
 674      len = PyBytes_Size(other);
 675      if (len < 2) {
 676          VALUE_ERROR("byte sequence too short for from_binary()");
 677          return NULL;
 678      }
 679      buffer = (unsigned char*)PyBytes_AsString(other);
 680      cp = buffer;
 681  
 682      switch (cp[0]) {
 683          case 0x01: {
 684              MPZ_Object *result;
 685  
 686              if (!(result = GMPy_MPZ_New(NULL))) {
 687                  /* LCOV_EXCL_START */
 688                  return NULL;
 689                  /* LCOV_EXCL_STOP */
 690              }
 691              if (cp[1] == 0x00) {
 692                  mpz_set_ui(result->z, 0);
 693                  return (PyObject*)result;
 694              }
 695              mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2);
 696              if (cp[1] == 0x02)
 697                  mpz_neg(result->z, result->z);
 698              return (PyObject*)result;
 699              break;
 700          }
 701          case 0x02: {
 702              XMPZ_Object *result;
 703  
 704              if (!(result = GMPy_XMPZ_New(NULL))) {
 705                  /* LCOV_EXCL_START */
 706                  return NULL;
 707                  /* LCOV_EXCL_STOP */
 708              }
 709              if (cp[1] == 0x00) {
 710                  mpz_set_ui(result->z, 0);
 711                  return (PyObject*)result;
 712              }
 713              mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2);
 714              if (cp[1] == 0x02)
 715                  mpz_neg(result->z, result->z);
 716              return (PyObject*)result;
 717              break;
 718          }
 719          case 0x03: {
 720              MPQ_Object *result;
 721              Py_ssize_t numlen = 0, sizesize = 4, i;
 722              mpz_t num, den;
 723  
 724              if (!(result = GMPy_MPQ_New(NULL))) {
 725                  /* LCOV_EXCL_START */
 726                  return NULL;
 727                  /* LCOV_EXCL_STOP */
 728              }
 729              if (cp[1] == 0x00) {
 730                  mpq_set_ui(result->q, 0, 1);
 731                  return (PyObject*)result;
 732              }
 733              if (cp[1] & 0x04)
 734                  sizesize = 8;
 735  
 736              if (len < 2 + sizesize) {
 737                  VALUE_ERROR("byte sequence too short for from_binary()");
 738                  return NULL;
 739              }
 740  
 741              for (i=sizesize; i>0; --i) {
 742                  numlen = (numlen << 8) + cp[i+1];
 743              }
 744  
 745              if (len < 2 + sizesize + numlen + 1) {
 746                  VALUE_ERROR("byte sequence too short for from_binary()");
 747                  return NULL;
 748              }
 749  
 750              mpz_init(num);
 751              mpz_init(den);
 752              mpz_import(num, numlen, -1,
 753                         sizeof(char), 0, 0, cp+sizesize+2);
 754              mpz_import(den, len-numlen-sizesize-2, -1,
 755                         sizeof(char), 0, 0, cp+sizesize+numlen+2);
 756              mpq_set_num(result->q, num);
 757              mpq_set_den(result->q, den);
 758              mpq_canonicalize(result->q);
 759              mpz_clear(num);
 760              mpz_clear(den);
 761  
 762              if (cp[1] == 0x02)
 763                  mpq_neg(result->q, result->q);
 764              return (PyObject*)result;
 765              break;
 766          }
 767          case 0x04: {
 768              MPFR_Object *result;
 769              Py_ssize_t sizemant = 0, sizesize = 4, i, newmant;
 770              mpfr_prec_t precision = 0;
 771              mpfr_exp_t exponent = 0;
 772              mp_limb_t templimb;
 773              int sgn = 1, expsgn = 1, limbsize = 4;
 774              int newlimbsize = (mp_bits_per_limb >> 3);
 775  
 776              if (len < 4) {
 777                  VALUE_ERROR("byte sequence too short for from_binary()");
 778                  return NULL;
 779              }
 780  
 781              /* Get size of values. */
 782              if (cp[1] & 0x04) sizesize = 8;
 783  
 784              /* Get the original precision. */
 785              for (i=sizesize; i>0; --i) {
 786                  precision = (precision << 8) + cp[i+3];
 787              }
 788  
 789              /* Get the original sign bit. */
 790              if (cp[1] & 0x02) sgn = -1;
 791  
 792              /* Get the original exponent sign. */
 793              if (cp[1] & 0x20) expsgn = -1;
 794  
 795              /* Get the limb size of the originating system. */
 796              if (cp[1] & 0x40) limbsize = 8;
 797  
 798  
 799              if (!(result = GMPy_MPFR_New(precision, context))) {
 800                  /* LCOV_EXCL_START */
 801                  return NULL;
 802                  /* LCOV_EXCL_STOP */
 803              }
 804  
 805              /* Restore the original result code and rounding mode. */
 806  
 807              /* Get the original result code. */
 808              if (cp[2] == 0)      result->rc = 0;
 809              else if (cp[2] == 1) result->rc = 1;
 810              else                 result->rc = -1;
 811  
 812              if (!(cp[1] & 0x01)) {
 813                  /* Process special numbers. */
 814                  if ((cp[1] & 0x18) == 0x00)
 815                      mpfr_set_zero(result->f, sgn);
 816                  else if ((cp[1] & 0x18) == 0x08)
 817                      mpfr_set_nan(result->f);
 818                  else
 819                      mpfr_set_inf(result->f, sgn);
 820                  return (PyObject*)result;
 821              }
 822              /* Process actual numbers. */
 823  
 824              /* Calculate the number of limbs on the original system. */
 825              if (limbsize == 8) sizemant = ((precision + 63) / 64);
 826              else               sizemant = ((precision + 31) / 32);
 827  
 828              /* Calculate the number of limbs on the current system. */
 829              newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
 830  
 831              /* Get the original exponent. */
 832              cp = buffer + 4 + sizesize - 1;
 833              for (i=sizesize; i>0; --i) {
 834                  exponent = (exponent << 8) + cp[i];
 835              }
 836  
 837              if (len < 2 + sizesize) {
 838                  VALUE_ERROR("byte sequence too short for from_binary()");
 839                  return NULL;
 840              }
 841  
 842              /* Check if the mantissa occupies the same number of bytes
 843               * on both the source and target system. */
 844              if (limbsize * sizemant == newmant * newlimbsize) {
 845                  mpfr_set_ui(result->f, 1, MPFR_RNDN);
 846                  cp = buffer + 4 + (2 * sizesize);
 847                  for (i=0; i<newmant; i++) {
 848  #if GMP_LIMB_BITS == 64
 849                      templimb = cp[7];
 850                      templimb = (templimb << 8) + cp[6];
 851                      templimb = (templimb << 8) + cp[5];
 852                      templimb = (templimb << 8) + cp[4];
 853                      templimb = (templimb << 8) + cp[3];
 854                      templimb = (templimb << 8) + cp[2];
 855                      templimb = (templimb << 8) + cp[1];
 856                      templimb = (templimb << 8) + cp[0];
 857  #endif
 858  #if GMP_LIMB_BITS == 32
 859                      templimb = cp[3];
 860                      templimb = (templimb << 8) + cp[2];
 861                      templimb = (templimb << 8) + cp[1];
 862                      templimb = (templimb << 8) + cp[0];
 863  #endif
 864                      result->f->_mpfr_d[i] = templimb;
 865                      cp += newlimbsize;
 866                  }
 867                  result->f->_mpfr_exp = expsgn * exponent;
 868                  if (sgn == -1)
 869                      mpfr_neg(result->f, result->f, MPFR_RNDN);
 870                  return (PyObject*)result;
 871              }
 872              else if (limbsize * sizemant > newmant * newlimbsize) {
 873                  /* Since the amount of saved data is greater than the amount of
 874                   * data needed on the new system, we skip the first 32 bits
 875                   * since they must be 0.
 876                   */
 877  
 878                  /* Verify we are on a 32-bit system and the source was 64-bit. */
 879                  if ((limbsize == 8) && (newlimbsize == 4)) {
 880                      VALUE_ERROR("byte sequence invalid for from_binary()");
 881                      return NULL;
 882                  }
 883  
 884                  mpfr_set_ui(result->f, 1, MPFR_RNDN);
 885                  cp = buffer + 4 + (2 * sizesize) + 4;
 886                  for (i=0; i<newmant; i++) {
 887                      templimb = cp[3];
 888                      templimb = (templimb << 8) + cp[2];
 889                      templimb = (templimb << 8) + cp[1];
 890                      templimb = (templimb << 8) + cp[0];
 891                      result->f->_mpfr_d[i] = templimb;
 892                      cp += newlimbsize;
 893                  }
 894                  result->f->_mpfr_exp = expsgn * exponent;
 895                  if (sgn == -1)
 896                      mpfr_neg(result->f, result->f, MPFR_RNDN);
 897                  return (PyObject*)result;
 898              }
 899              else {
 900                  /* Since the amount of saved data is less than the amount of
 901                   * data needed on the new system, we must "add" 32 0-bits at
 902                   * the low end.
 903                   */
 904  
 905                  /* Verify we are on a 64-bit system and the source was 32-bit. */
 906                  if ((limbsize == 4) && (newlimbsize == 8)) {
 907                      VALUE_ERROR("byte sequence invalid for from_binary()");
 908                      return NULL;
 909                  }
 910  
 911                  mpfr_set_ui(result->f, 1, MPFR_RNDN);
 912                  cp = buffer + 4 + (2 * sizesize);
 913                  templimb = cp[3];
 914                  templimb = (templimb << 8) + cp[2];
 915                  templimb = (templimb << 8) + cp[1];
 916                  templimb = (templimb << 8) + cp[0];
 917                  result->f->_mpfr_d[i] = ((templimb << 16) << 16);
 918                  cp += 4;
 919                  for (i=0; i<newmant-1; i++) {
 920                      templimb = cp[7];
 921                      templimb = (templimb << 8) + cp[6];
 922                      templimb = (templimb << 8) + cp[5];
 923                      templimb = (templimb << 8) + cp[4];
 924                      templimb = (templimb << 8) + cp[3];
 925                      templimb = (templimb << 8) + cp[2];
 926                      templimb = (templimb << 8) + cp[1];
 927                      templimb = (templimb << 8) + cp[0];
 928                      result->f->_mpfr_d[i] = templimb;
 929                      cp += newlimbsize;
 930                  }
 931                  result->f->_mpfr_exp = expsgn * exponent;
 932                  if (sgn == -1)
 933                      mpfr_neg(result->f, result->f, MPFR_RNDN);
 934                  return (PyObject*)result;
 935              }
 936          }
 937          case 0x05: {
 938              MPC_Object *result;
 939              MPFR_Object *real = 0, *imag = 0;
 940              Py_ssize_t sizemant = 0, sizesize = 4, i, newmant;
 941              mpfr_prec_t precision = 0;
 942              mpfr_exp_t exponent = 0;
 943              mp_limb_t templimb;
 944              int sgn = 1, expsgn = 1, limbsize = 4;
 945              int newlimbsize = (mp_bits_per_limb >> 3);
 946              unsigned char *tempbuf;
 947  
 948              if (len < 4) {
 949                  VALUE_ERROR("byte sequence too short for from_binary()");
 950                  return NULL;
 951              }
 952              /* read the real part first */
 953              if (cp[1] & 0x04) sizesize = 8;
 954              for (i=sizesize; i>0; --i) {
 955                  precision = (precision << 8) + cp[i+3];
 956              }
 957              if (cp[1] & 0x02) sgn = -1;
 958              if (cp[1] & 0x20) expsgn = -1;
 959              if (cp[1] & 0x40) limbsize = 8;
 960              if (!(real = GMPy_MPFR_New(precision, context))) {
 961                  /* LCOV_EXCL_START */
 962                  return NULL;
 963                  /* LCOV_EXCL_STOP */
 964              }
 965              if (cp[2] == 0)      real->rc = 0;
 966              else if (cp[2] == 1) real->rc = 1;
 967              else                 real->rc = -1;
 968              if (!(cp[1] & 0x01)) {
 969                  if ((cp[1] & 0x18) == 0x00)
 970                      mpfr_set_zero(real->f, sgn);
 971                  else if ((cp[1] & 0x18) == 0x08)
 972                      mpfr_set_nan(real->f);
 973                  else
 974                      mpfr_set_inf(real->f, sgn);
 975                  cp += 4 + sizesize;
 976                  goto readimag;
 977              }
 978              if (limbsize == 8) sizemant = ((precision + 63) / 64);
 979              else               sizemant = ((precision + 31) / 32);
 980              newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
 981              cp = buffer + 4 + sizesize - 1;
 982              for (i=sizesize; i>0; --i) {
 983                  exponent = (exponent << 8) + cp[i];
 984              }
 985              if (limbsize * sizemant == newmant * newlimbsize) {
 986                  mpfr_set_ui(real->f, 1, MPFR_RNDN);
 987                  cp = buffer + 4 + (2 * sizesize);
 988                  for (i=0; i<newmant; i++) {
 989  #if GMP_LIMB_BITS == 64
 990                      templimb = cp[7];
 991                      templimb = (templimb << 8) + cp[6];
 992                      templimb = (templimb << 8) + cp[5];
 993                      templimb = (templimb << 8) + cp[4];
 994                      templimb = (templimb << 8) + cp[3];
 995                      templimb = (templimb << 8) + cp[2];
 996                      templimb = (templimb << 8) + cp[1];
 997                      templimb = (templimb << 8) + cp[0];
 998  #endif
 999  #if GMP_LIMB_BITS == 32
1000                      templimb = cp[3];
1001                      templimb = (templimb << 8) + cp[2];
1002                      templimb = (templimb << 8) + cp[1];
1003                      templimb = (templimb << 8) + cp[0];
1004  #endif
1005                      real->f->_mpfr_d[i] = templimb;
1006                      cp += newlimbsize;
1007                  }
1008                  real->f->_mpfr_exp = expsgn * exponent;
1009                  if (sgn == -1)
1010                      mpfr_neg(real->f, real->f, MPFR_RNDN);
1011              }
1012              else if (limbsize * sizemant > newmant * newlimbsize) {
1013                  if ((limbsize == 8) && (newlimbsize == 4)) {
1014                      VALUE_ERROR("byte sequence invalid for from_binary()");
1015                      Py_DECREF((PyObject*)real);
1016                      return NULL;
1017                  }
1018                  mpfr_set_ui(real->f, 1, MPFR_RNDN);
1019                  cp = buffer + 4 + (2 * sizesize) + 4;
1020                  for (i=0; i<newmant; i++) {
1021                      templimb = cp[3];
1022                      templimb = (templimb << 8) + cp[2];
1023                      templimb = (templimb << 8) + cp[1];
1024                      templimb = (templimb << 8) + cp[0];
1025                      real->f->_mpfr_d[i] = templimb;
1026                      cp += newlimbsize;
1027                  }
1028                  real->f->_mpfr_exp = expsgn * exponent;
1029                  if (sgn == -1)
1030                      mpfr_neg(real->f, real->f, MPFR_RNDN);
1031              }
1032              else {
1033                  if ((limbsize == 4) && (newlimbsize == 8)) {
1034                      VALUE_ERROR("byte sequence invalid for from_binary()");
1035                      Py_DECREF((PyObject*)real);
1036                      return NULL;
1037                  }
1038                  mpfr_set_ui(real->f, 1, MPFR_RNDN);
1039                  cp = buffer + 4 + (2 * sizesize);
1040                  templimb = cp[3];
1041                  templimb = (templimb << 8) + cp[2];
1042                  templimb = (templimb << 8) + cp[1];
1043                  templimb = (templimb << 8) + cp[0];
1044                  real->f->_mpfr_d[i] = ((templimb << 16) << 16);
1045                  cp += 4;
1046                  for (i=0; i<newmant-1; i++) {
1047                      templimb = cp[7];
1048                      templimb = (templimb << 8) + cp[6];
1049                      templimb = (templimb << 8) + cp[5];
1050                      templimb = (templimb << 8) + cp[4];
1051                      templimb = (templimb << 8) + cp[3];
1052                      templimb = (templimb << 8) + cp[2];
1053                      templimb = (templimb << 8) + cp[1];
1054                      templimb = (templimb << 8) + cp[0];
1055                      real->f->_mpfr_d[i] = templimb;
1056                      cp += newlimbsize;
1057                  }
1058                  real->f->_mpfr_exp = expsgn * exponent;
1059                  if (sgn == -1)
1060                      mpfr_neg(real->f, real->f, MPFR_RNDN);
1061              }
1062    readimag:
1063              /* Set all the variables back to default. */
1064              tempbuf = cp;
1065  
1066              sizemant = 0;
1067              sizesize = 4;
1068              precision = 0;
1069              exponent = 0;
1070              sgn = 1;
1071              expsgn = 1;
1072              limbsize = 4;
1073  
1074              /* Done reading the real part. The next byte should be 0x05. */
1075              if (!(cp[0] == 0x05)) {
1076                  VALUE_ERROR("byte sequence invalid for from_binary()");
1077                  Py_DECREF((PyObject*)real);
1078                  return NULL;
1079              }
1080              if (cp[1] & 0x04) sizesize = 8;
1081              for (i=sizesize; i>0; --i) {
1082                  precision = (precision << 8) + cp[i+3];
1083              }
1084              if (cp[1] & 0x02) sgn = -1;
1085              if (cp[1] & 0x20) expsgn = -1;
1086              if (cp[1] & 0x40) limbsize = 8;
1087              if (!(imag = GMPy_MPFR_New(precision, context))) {
1088                  /* LCOV_EXCL_START */
1089                  Py_DECREF((PyObject*)real);
1090                  return NULL;
1091                  /* LCOV_EXCL_STOP */
1092              }
1093              if (cp[2] == 0)      imag->rc = 0;
1094              else if (cp[2] == 1) imag->rc = 1;
1095              else                 imag->rc = -1;
1096              if (!(cp[1] & 0x01)) {
1097                  if ((cp[1] & 0x18) == 0x00)
1098                      mpfr_set_zero(imag->f, sgn);
1099                  else if ((cp[1] & 0x18) == 0x08)
1100                      mpfr_set_nan(imag->f);
1101                  else
1102                      mpfr_set_inf(imag->f, sgn);
1103                  goto alldone;
1104              }
1105              if (limbsize == 8) sizemant = ((precision + 63) / 64);
1106              else               sizemant = ((precision + 31) / 32);
1107              newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
1108              cp = tempbuf + 4 + sizesize - 1;
1109              for (i=sizesize; i>0; --i) {
1110                  exponent = (exponent << 8) + cp[i];
1111              }
1112              if (limbsize * sizemant == newmant * newlimbsize) {
1113                  mpfr_set_ui(imag->f, 1, MPFR_RNDN);
1114                  cp = tempbuf + 4 + (2 * sizesize);
1115                  for (i=0; i<newmant; i++) {
1116  #if GMP_LIMB_BITS == 64
1117                      templimb = cp[7];
1118                      templimb = (templimb << 8) + cp[6];
1119                      templimb = (templimb << 8) + cp[5];
1120                      templimb = (templimb << 8) + cp[4];
1121                      templimb = (templimb << 8) + cp[3];
1122                      templimb = (templimb << 8) + cp[2];
1123                      templimb = (templimb << 8) + cp[1];
1124                      templimb = (templimb << 8) + cp[0];
1125  #endif
1126  #if GMP_LIMB_BITS == 32
1127                      templimb = cp[3];
1128                      templimb = (templimb << 8) + cp[2];
1129                      templimb = (templimb << 8) + cp[1];
1130                      templimb = (templimb << 8) + cp[0];
1131  #endif
1132                      imag->f->_mpfr_d[i] = templimb;
1133                      cp += newlimbsize;
1134                  }
1135                  imag->f->_mpfr_exp = expsgn * exponent;
1136                  if (sgn == -1)
1137                      mpfr_neg(imag->f, imag->f, MPFR_RNDN);
1138              }
1139              else if (limbsize * sizemant > newmant * newlimbsize) {
1140                  if ((limbsize == 8) && (newlimbsize == 4)) {
1141                      VALUE_ERROR("byte sequence invalid for from_binary()");
1142                      Py_DECREF((PyObject*)real);
1143                      Py_DECREF((PyObject*)imag);
1144                      return NULL;
1145                  }
1146                  mpfr_set_ui(imag->f, 1, MPFR_RNDN);
1147                  cp = tempbuf + 4 + (2 * sizesize) + 4;
1148                  for (i=0; i<newmant; i++) {
1149                      templimb = cp[3];
1150                      templimb = (templimb << 8) + cp[2];
1151                      templimb = (templimb << 8) + cp[1];
1152                      templimb = (templimb << 8) + cp[0];
1153                      imag->f->_mpfr_d[i] = templimb;
1154                      cp += newlimbsize;
1155                  }
1156                  imag->f->_mpfr_exp = expsgn * exponent;
1157                  if (sgn == -1)
1158                      mpfr_neg(imag->f, imag->f, MPFR_RNDN);
1159              }
1160              else {
1161                  if ((limbsize == 4) && (newlimbsize == 8)) {
1162                      VALUE_ERROR("byte sequence invalid for from_binary()");
1163                      Py_DECREF((PyObject*)real);
1164                      Py_DECREF((PyObject*)imag);
1165                      return NULL;
1166                  }
1167                  mpfr_set_ui(imag->f, 1, MPFR_RNDN);
1168                  cp = tempbuf + 4 + (2 * sizesize);
1169                  templimb = cp[3];
1170                  templimb = (templimb << 8) + cp[2];
1171                  templimb = (templimb << 8) + cp[1];
1172                  templimb = (templimb << 8) + cp[0];
1173                  imag->f->_mpfr_d[i] = ((templimb << 16) << 16);
1174                  cp += 4;
1175                  for (i=0; i<newmant-1; i++) {
1176                      templimb = cp[7];
1177                      templimb = (templimb << 8) + cp[6];
1178                      templimb = (templimb << 8) + cp[5];
1179                      templimb = (templimb << 8) + cp[4];
1180                      templimb = (templimb << 8) + cp[3];
1181                      templimb = (templimb << 8) + cp[2];
1182                      templimb = (templimb << 8) + cp[1];
1183                      templimb = (templimb << 8) + cp[0];
1184                      imag->f->_mpfr_d[i] = templimb;
1185                      cp += newlimbsize;
1186                  }
1187                  imag->f->_mpfr_exp = expsgn * exponent;
1188                  if (sgn == -1)
1189                      mpfr_neg(imag->f, imag->f, MPFR_RNDN);
1190              }
1191    alldone:
1192              if (!(result = (MPC_Object*)GMPy_MPC_New(0, 0, context))) {
1193                  /* LCOV_EXCL_START */
1194                  Py_DECREF((PyObject*)real);
1195                  Py_DECREF((PyObject*)imag);
1196                  return NULL;
1197                  /* LCOV_EXCL_STOP */
1198              }
1199              mpfr_swap(mpc_realref(result->c), real->f);
1200              mpfr_swap(mpc_imagref(result->c), imag->f);
1201              Py_DECREF((PyObject*)real);
1202              Py_DECREF((PyObject*)imag);
1203              return (PyObject*)result;
1204          }
1205          default: {
1206              TYPE_ERROR("from_binary() argument type not supported");
1207              return NULL;
1208          }
1209      }
1210  }
1211  
1212  PyDoc_STRVAR(doc_to_binary,
1213  "to_binary(x) -> bytes\n"
1214  "Return a Python byte sequence that is a portable binary\n"
1215  "representation of a gmpy2 object x. The byte sequence can\n"
1216  "be passed to gmpy2.from_binary() to obtain an exact copy of\n"
1217  "x's value. Works with mpz, xmpz, mpq, mpfr, and mpc types. \n"
1218  "Raises TypeError if x is not a gmpy2 object.");
1219  
1220  static PyObject *
1221  GMPy_MPANY_To_Binary(PyObject *self, PyObject *other)
1222  {
1223      if(MPZ_Check(other))
1224          return GMPy_MPZ_To_Binary((MPZ_Object*)other);
1225      else if(XMPZ_Check(other))
1226          return GMPy_XMPZ_To_Binary((XMPZ_Object*)other);
1227      else if(MPQ_Check(other))
1228          return GMPy_MPQ_To_Binary((MPQ_Object*)other);
1229      else if(MPFR_Check(other))
1230          return GMPy_MPFR_To_Binary((MPFR_Object*)other);
1231      else if(MPC_Check(other))
1232          return GMPy_MPC_To_Binary((MPC_Object*)other);
1233      TYPE_ERROR("to_binary() argument type not supported");
1234      return NULL;
1235  }
1236