PageRenderTime 124ms CodeModel.GetById 25ms app.highlight 90ms RepoModel.GetById 1ms app.codeStats 0ms

/src/gmpy_mpc.c

http://gmpy.googlecode.com/
C | 1524 lines | 1257 code | 214 blank | 53 comment | 266 complexity | 2bde16ee68b87b3c0c9412e47ea69797 MD5 | raw file
   1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   2 * gmpy_mpc.c                                                              *
   3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   4 * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision   *
   5 * libraries.                                                              *
   6 *                                                                         *
   7 * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,               *
   8 *           2008, 2009 Alex Martelli                                      *
   9 *                                                                         *
  10 * Copyright 2008, 2009, 2010, 2011, 2012, 2013 Case Van Horsen            *
  11 *                                                                         *
  12 * This file is part of GMPY2.                                             *
  13 *                                                                         *
  14 * GMPY2 is free software: you can redistribute it and/or modify it under  *
  15 * the terms of the GNU Lesser General Public License as published by the  *
  16 * Free Software Foundation, either version 3 of the License, or (at your  *
  17 * option) any later version.                                              *
  18 *                                                                         *
  19 * GMPY2 is distributed in the hope that it will be useful, but WITHOUT    *
  20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   *
  21 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public    *
  22 * License for more details.                                               *
  23 *                                                                         *
  24 * You should have received a copy of the GNU Lesser General Public        *
  25 * License along with GMPY2; if not, see <http://www.gnu.org/licenses/>    *
  26 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  27
  28PyDoc_STRVAR(doc_mpc_digits,
  29"c.digits(base=10, prec=0) -> ((mant, exp, prec), (mant, exp, prec))\n\n"
  30"Returns up to 'prec' digits in the given base. If 'prec' is 0, as many\n"
  31"digits that are available given c's precision are returned. 'base' must\n"
  32"be between 2 and 62. The result consists of 2 three-element tuples that\n"
  33"contain the mantissa, exponent, and number of bits of precision of the\n"
  34"real and imaginary components.");
  35
  36/* TODO: support keyword arguments. */
  37
  38static PyObject *
  39Pympc_digits(PyObject *self, PyObject *args)
  40{
  41    int base = 10;
  42    int prec = 0;
  43    PyObject *result;
  44
  45    if (self && Pympc_Check(self)) {
  46        if (!PyArg_ParseTuple(args, "|ii", &base, &prec))
  47            return NULL;
  48        Py_INCREF(self);
  49    }
  50    else {
  51        if(!PyArg_ParseTuple(args, "O&|ii", Pympc_convert_arg, &self,
  52                            &base, &prec))
  53        return NULL;
  54    }
  55    result = Pympc_To_PyStr((PympcObject*)self, base, prec);
  56    Py_DECREF(self);
  57    return result;
  58}
  59
  60PyDoc_STRVAR(doc_g_mpc,
  61"mpc() -> mpc(0.0+0.0j)\n\n"
  62"      If no argument is given, return mpc(0.0+0.0j).\n\n"
  63"mpc(c[, precision=0]) -> mpc\n\n"
  64"      Return a new 'mpc' object from an existing complex number\n"
  65"      (either a Python complex object or another 'mpc' object). If\n"
  66"      the precision is not specified, then the precision is taken\n"
  67"      from the current context. The rounding mode is always taken\n"
  68"      from the current context.\n\n"
  69"mpc(r[, i=0[, precision=0]]) -> mpc\n\n"
  70"      Return a new 'mpc' object by converting two non-complex numbers\n"
  71"      into the real and imaginary components of an 'mpc' object. If\n"
  72"      the precision is not specified, then the precision is taken from\n"
  73"      the current context. The rounding mode is always taken from the\n"
  74"      current context.\n\n"
  75"mpc(s[, [precision=0[, base=10]]) -> mpc\n\n"
  76"      Return a new 'mpc' object by converting a string s into a complex\n"
  77"      number. If base is omitted, then a base-10 representation is\n"
  78"      assumed otherwise a base between 2 and 36 can be specified. If\n"
  79"      the precision is not specified, then the precision is taken from\n"
  80"      the current context. The rounding mode is always taken from the\n"
  81"      current context.\n\n"
  82"Note: The precision can be specified either a single number that\n"
  83"      is used for both the real and imaginary components, or as a\n"
  84"      tuple that can specify different precisions for the real\n"
  85"      and imaginary components.");
  86
  87static PyObject *
  88Pygmpy_mpc(PyObject *self, PyObject *args, PyObject *kwargs)
  89{
  90    PympcObject *result = NULL;
  91    PympfrObject *tempreal = NULL, *tempimag = NULL;
  92    PyObject *arg0 = NULL, *arg1 = NULL, *prec = NULL;
  93    int base = 10;
  94    /* Assumes mpfr_prec_t is the same as a long. */
  95    mpfr_prec_t rbits = 0, ibits = 0;
  96    Py_ssize_t argc;
  97    static char *kwlist_c[] = {"c", "precision", NULL};
  98    static char *kwlist_r[] = {"r", "i", "precision", NULL};
  99    static char *kwlist_s[] = {"s", "precision", "base", NULL};
 100
 101    argc = PyTuple_Size(args);
 102
 103    if (argc == 0) {
 104        if ((result = (PympcObject*)Pympc_new(0,0))) {
 105            mpc_set_ui(result->c, 0, GET_MPC_ROUND(context));
 106        }
 107        return (PyObject*)result;
 108    }
 109
 110    arg0 = PyTuple_GetItem(args, 0);
 111    if (PyStrOrUnicode_Check(arg0)) {
 112        /* First argument is a string */
 113
 114        if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi", kwlist_s,
 115                                          &arg0, &prec, &base)))
 116            return NULL;
 117
 118        if (prec) {
 119            if (PyIntOrLong_Check(prec)) {
 120                rbits = (mpfr_prec_t)PyIntOrLong_AsLong(prec);
 121                ibits = rbits;
 122            }
 123            else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
 124                rbits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 0));
 125                ibits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 1));
 126            }
 127            if (PyErr_Occurred()) {
 128                VALUE_ERROR("invalid value for precision in gmpy2.mpc().");
 129                return NULL;
 130            }
 131        }
 132
 133        if (base < 2 || base > 36) {
 134            VALUE_ERROR("base for mpc() must be in the interval 2 ... 36.");
 135            return NULL;
 136        }
 137
 138        result = Pympc_From_PyStr(arg0, base, rbits, ibits);
 139    }
 140    else if (PyComplex_Check(arg0) || Pympc_Check(arg0)) {
 141        /* First argument is a complex number */
 142
 143        if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist_c,
 144                                          &arg0, &prec)))
 145            return NULL;
 146
 147        if (prec) {
 148            if (PyIntOrLong_Check(prec)) {
 149                rbits = (mpfr_prec_t)PyIntOrLong_AsLong(prec);
 150                ibits = rbits;
 151            }
 152            else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
 153                rbits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 0));
 154                ibits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 1));
 155            }
 156            if (PyErr_Occurred()) {
 157                VALUE_ERROR("invalid value for precision in mpc().");
 158                return NULL;
 159            }
 160        }
 161
 162        if (PyComplex_Check(arg0)) {
 163            result = Pympc_From_PyComplex(arg0, rbits, ibits);
 164        }
 165        else {
 166            result = Pympc_From_Pympc(arg0, rbits, ibits);
 167        }
 168    }
 169    else if (isReal(arg0)) {
 170        /* First argument is a real number */
 171
 172        if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO", kwlist_r,
 173                                          &arg0, &arg1, &prec)))
 174            return NULL;
 175
 176        if (prec) {
 177            if (PyIntOrLong_Check(prec)) {
 178                rbits = (mpfr_prec_t)PyIntOrLong_AsLong(prec);
 179                ibits = rbits;
 180            }
 181            else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
 182                rbits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 0));
 183                ibits = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GetItem(prec, 1));
 184            }
 185            if (PyErr_Occurred()) {
 186                VALUE_ERROR("invalid value for precision in mpc().");
 187                return NULL;
 188            }
 189        }
 190
 191        if (arg1 && !isReal(arg1)) {
 192            TYPE_ERROR("invalid type for imaginary component in mpc()");
 193            return NULL;
 194        }
 195
 196        if (arg0) {
 197            tempreal = Pympfr_From_Real(arg0, rbits);
 198        }
 199        else {
 200            if ((tempreal = (PympfrObject*)Pympfr_new(rbits))) {
 201                mpfr_set_ui(Pympfr_AS_MPFR(tempreal), 0, context->ctx.mpfr_round);
 202            }
 203        }
 204
 205        if (arg1) {
 206            tempimag = Pympfr_From_Real(arg1, ibits);
 207        }
 208        else {
 209            if ((tempimag = (PympfrObject*)Pympfr_new(ibits))) {
 210                mpfr_set_ui(Pympfr_AS_MPFR(tempimag), 0, context->ctx.mpfr_round);
 211            }
 212        }
 213
 214        result = (PympcObject*)Pympc_new(rbits, ibits);
 215        if (!tempreal || !tempimag || !result) {
 216            Py_XDECREF(tempreal);
 217            Py_XDECREF(tempimag);
 218            Py_XDECREF(result);
 219            TYPE_ERROR("mpc() requires string or numeric argument.");
 220            return NULL;
 221        }
 222
 223        mpc_set_fr_fr(Pympc_AS_MPC(result), Pympfr_AS_MPFR(tempreal),
 224                      Pympfr_AS_MPFR(tempimag), GET_MPC_ROUND(context));
 225        Py_DECREF(tempreal);
 226        Py_DECREF(tempimag);
 227    }
 228    else {
 229        TYPE_ERROR("mpc() requires numeric or string argument");
 230    }
 231
 232    return (PyObject*)result;
 233}
 234
 235PyDoc_STRVAR(doc_mpc_format,
 236"x.__format__(fmt) -> string\n\n"
 237"Return a Python string by formatting 'x' using the format string\n"
 238"'fmt'. A valid format string consists of:\n"
 239"     optional alignment code:\n"
 240"        '<' -> left shifted in field\n"
 241"        '>' -> right shifted in field\n"
 242"        '^' -> centered in field\n"
 243"     optional leading sign code\n"
 244"        '+' -> always display leading sign\n"
 245"        '-' -> only display minus for negative values\n"
 246"        ' ' -> minus for negative values, space for positive values\n"
 247"     optional width.real_precision.imag_precision\n"
 248"     optional rounding mode:\n"
 249"        'U' -> round toward plus infinity\n"
 250"        'D' -> round toward minus infinity\n"
 251"        'Z' -> round toward zero\n"
 252"        'N' -> round to nearest\n"
 253"     optional output style:\n"
 254"        'P' -> Python style, 1+2j, (default)\n"
 255"        'M' -> MPC style, (1 2)\n"
 256"     optional conversion code:\n"
 257"        'a','A' -> hex format\n"
 258"        'b'     -> binary format\n"
 259"        'e','E' -> scientific format\n"
 260"        'f','F' -> fixed point format\n"
 261"        'g','G' -> fixed or scientific format\n\n"
 262"The default format is 'f'.");
 263
 264static PyObject *
 265Pympc_format(PyObject *self, PyObject *args)
 266{
 267    PyObject *result = 0, *tempstr = 0;
 268    char *realbuf = 0, *imagbuf = 0, *tempbuf = 0, *fmtcode = 0;
 269    char *p, *rfmtptr, *ifmtptr, *fmtptr;
 270    char rfmt[100], ifmt[100], fmt[30];
 271    int rbuflen, ibuflen;
 272    int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0;
 273    int seenround = 0, seenconv = 0, seenstyle = 0, mpcstyle = 0;
 274
 275    if (!Pympc_Check(self)) {
 276        TYPE_ERROR("requires 'mpc' object");
 277        return NULL;
 278    }
 279
 280    if (!PyArg_ParseTuple(args, "s", &fmtcode))
 281        return NULL;
 282
 283    rfmtptr = rfmt;
 284    ifmtptr = ifmt;
 285    fmtptr = fmt;
 286    *(rfmtptr++) = '%';
 287    *(ifmtptr++) = '%';
 288
 289    for (p = fmtcode; *p != '\00'; p++) {
 290        if (*p == '<' || *p == '>' || *p == '^') {
 291            if (seenalign || seensign || seendecimal || seendigits ||
 292                seenround || seenstyle) {
 293                VALUE_ERROR("Invalid conversion specification");
 294                return NULL;
 295            }
 296            else {
 297                *(fmtptr++) = *p;
 298                seenalign = 1;
 299                continue;
 300            }
 301        }
 302        if (*p == '+' || *p == ' ' || *p == '-') {
 303            if (seensign || seendecimal || seendigits || seenround ||
 304                seenstyle) {
 305                VALUE_ERROR("Invalid conversion specification");
 306                return NULL;
 307            }
 308            else {
 309                *(rfmtptr++) = *p;
 310                *(ifmtptr++) = *p;
 311                seensign = 1;
 312                continue;
 313            }
 314        }
 315        if (!seensign) {
 316            *(rfmtptr++) = '-';
 317            *(ifmtptr++) = '-';
 318            seensign = 1;
 319        }
 320        if (*p == '.') {
 321            if (seendecimal == 2 || seendigits || seenround || seenstyle) {
 322                VALUE_ERROR("Invalid conversion specification");
 323                return NULL;
 324            }
 325            else {
 326                if (!seendecimal) {
 327                    *(rfmtptr++) = *p;
 328                    *(ifmtptr++) = *p;
 329                }
 330                seendecimal++;
 331                if (seendecimal == 2) {
 332                    while (isdigit(*(ifmtptr-1)))
 333                        ifmtptr--;
 334                }
 335                continue;
 336            }
 337        }
 338        if (isdigit(*p)) {
 339            if (seendigits || seenround || seenstyle) {
 340                VALUE_ERROR("Invalid conversion specification");
 341                return NULL;
 342            }
 343            else if (seendecimal == 1) {
 344                *(rfmtptr++) = *p;
 345                *(ifmtptr++) = *p;
 346                continue;
 347            }
 348            else if (seendecimal == 2) {
 349                *(ifmtptr++) = *p;
 350                continue;
 351            }
 352            else {
 353                if (fmtptr == fmt) {
 354                    *(fmtptr++) = '>';
 355                    seenalign = 1;
 356                }
 357                *(fmtptr++) = *p;
 358                continue;
 359            }
 360        }
 361        if (!seendigits) {
 362            seendigits = 1;
 363            *(rfmtptr++) = 'R';
 364            *(ifmtptr++) = 'R';
 365        }
 366        if (*p == 'U' || *p == 'D' || *p == 'Y' || *p == 'Z' ||
 367            *p == 'N' ) {
 368            if (seenround || seenstyle) {
 369                VALUE_ERROR("Invalid conversion specification");
 370                return NULL;
 371            }
 372            else {
 373                *(rfmtptr++) = *p;
 374                *(ifmtptr++) = *p;
 375                seenround = 1;
 376                continue;
 377            }
 378        }
 379        if (*p == 'P' || *p == 'M') {
 380            if (seenstyle) {
 381                VALUE_ERROR("Invalid conversion specification");
 382                return NULL;
 383            }
 384            else {
 385                if (*p == 'M')
 386                    mpcstyle = 1;
 387                seenstyle = 1;
 388                continue;
 389            }
 390        }
 391        if (*p == 'a' || *p == 'A' || *p == 'b' || *p == 'e' ||
 392            *p == 'E' || *p == 'f' || *p == 'F' || *p == 'g' ||
 393            *p == 'G' ) {
 394            *(rfmtptr++) = *p;
 395            *(ifmtptr++) = *p;
 396            seenconv = 1;
 397            break;
 398        }
 399        VALUE_ERROR("Invalid conversion specification");
 400        return NULL;
 401    }
 402
 403    if (!seensign) {
 404        *(rfmtptr++) = '-';
 405        *(ifmtptr++) = '-';
 406    }
 407    if (!seendigits) {
 408        *(rfmtptr++) = 'R';
 409        *(ifmtptr++) = 'R';
 410    }
 411    if (!seenconv) {
 412        *(rfmtptr++) = 'f';
 413        *(ifmtptr++) = 'f';
 414    }
 415
 416    *(rfmtptr) = '\00';
 417    *(ifmtptr) = '\00';
 418    *(fmtptr) = '\00';
 419
 420    /* Format the real part.... */
 421
 422    rbuflen = mpfr_asprintf(&realbuf, rfmt,
 423                           mpc_realref(Pympc_AS_MPC(self)));
 424
 425    if (rbuflen < 0) {
 426        mpfr_free_str(realbuf);
 427        SYSTEM_ERROR("Internal error in mpfr_asprintf");
 428        return NULL;
 429    }
 430
 431    /* Format the imaginary part. If Python style is wanted, convert the '-'
 432     * or ' ' sign indicator to '+'. */
 433
 434    if (!mpcstyle) {
 435        if (ifmt[1] == ' ' || ifmt[1] == '-' || ifmt[1] == '+') {
 436            ifmt[1] = '+';
 437        }
 438        else {
 439            mpfr_free_str(realbuf);
 440            VALUE_ERROR("Invalid conversion specification for imag");
 441            return NULL;
 442        }
 443    }
 444
 445    ibuflen = mpfr_asprintf(&imagbuf, ifmt,
 446                           mpc_imagref(Pympc_AS_MPC(self)));
 447
 448    if (ibuflen < 0) {
 449        mpfr_free_str(realbuf);
 450        mpfr_free_str(imagbuf);
 451        SYSTEM_ERROR("Internal error in mpfr_asprintf");
 452        return NULL;
 453    }
 454
 455    /* Combine the real and imaginary components into a single buffer.
 456     * Include space for '(', ' ', and 'j)' and possibly appending '.0' twice.
 457     */
 458
 459    tempbuf = GMPY_MALLOC(rbuflen + ibuflen + 10);
 460    if (!tempbuf) {
 461        mpfr_free_str(realbuf);
 462        mpfr_free_str(imagbuf);
 463        return PyErr_NoMemory();
 464    }
 465    tempbuf[0] = '\00';
 466    if (mpcstyle)
 467        strcat(tempbuf, "(");
 468    strcat(tempbuf, realbuf);
 469
 470    /* If there isn't a decimal point in the output and the output
 471     * is short and only consists of digits, then append .0 */
 472    if (strlen(realbuf) < 50 &&
 473        strlen(realbuf) == strspn(realbuf, "+- 0123456789")) {
 474        strcat(tempbuf, ".0");
 475    }
 476
 477    if (mpcstyle)
 478        strcat(tempbuf, " ");
 479    else {
 480        /* Need to insert + if imag is nan or +inf. */
 481        if (mpfr_nan_p(mpc_imagref(Pympc_AS_MPC(self))) ||
 482            (mpfr_inf_p(mpc_imagref(Pympc_AS_MPC(self))) &&
 483             mpfr_sgn(mpc_imagref(Pympc_AS_MPC(self))) > 0)) {
 484            strcat(tempbuf, "+");
 485        }
 486    }
 487    strcat(tempbuf, imagbuf);
 488    if (strlen(imagbuf) < 50 &&
 489        strlen(imagbuf) == strspn(imagbuf, "+- 0123456789")) {
 490        strcat(tempbuf, ".0");
 491    }
 492
 493    if (mpcstyle)
 494        strcat(tempbuf, ")");
 495    else
 496        strcat(tempbuf, "j");
 497
 498    mpfr_free_str(realbuf);
 499    mpfr_free_str(imagbuf);
 500
 501    tempstr = Py_BuildValue("s", tempbuf);
 502    if (!tempstr) {
 503        GMPY_FREE(tempbuf);
 504        return NULL;
 505    }
 506
 507    result = PyObject_CallMethod(tempstr, "__format__", "(s)", fmt);
 508
 509    Py_DECREF(tempstr);
 510    return result;
 511}
 512
 513static PyObject *
 514Pympc_abs(PyObject *self)
 515{
 516    PympfrObject *result = 0;
 517    PympcObject *tempx = 0;
 518
 519    result = (PympfrObject*)Pympfr_new(0);
 520    tempx = Pympc_From_Complex(self, 0, 0);
 521    if (!tempx || !result) {
 522        SYSTEM_ERROR("Can't convert argument to 'mpc'.");
 523        Py_XDECREF((PyObject*)tempx);
 524        Py_XDECREF((PyObject*)result);
 525        return NULL;
 526    }
 527
 528    result->rc = mpc_abs(result->f, tempx->c, GET_MPC_ROUND(context));
 529    Py_DECREF((PyObject*)tempx);
 530
 531    MPFR_SUBNORMALIZE(result);
 532    MPFR_CHECK_INVALID(result, "invalid operation in 'mpc' __abs__");
 533    MPFR_CHECK_UNDERFLOW(result, "underflow in 'mpc' __abs__");
 534    MPFR_CHECK_OVERFLOW(result, "overflow in 'mpc' __abs__");
 535    MPFR_CHECK_INEXACT(result, "inexact result in 'mpc' __abs__");
 536  done:
 537    if (PyErr_Occurred()) {
 538        Py_DECREF((PyObject*)result);
 539        result = NULL;
 540    }
 541    return (PyObject*)result;
 542}
 543
 544static PyObject *
 545Pympc_neg(PympcObject *self)
 546{
 547    PympcObject *result = 0;
 548
 549    if (!(result = (PympcObject*)Pympc_new(0, 0)))
 550        return NULL;
 551
 552    if (!(self = Pympc_From_Complex((PyObject*)self, 0, 0))) {
 553        SYSTEM_ERROR("__neg__() requires 'mpc' argument");
 554        Py_DECREF(result);
 555        return NULL;
 556    }
 557
 558    result->rc = mpc_neg(result->c, self->c, GET_MPC_ROUND(context));
 559
 560    MPC_CLEANUP(result, "__neg__");
 561}
 562
 563static PyObject *
 564Pympc_pos(PympcObject *self)
 565{
 566    PympcObject *result = 0;
 567
 568    if (!(result = Pympc_From_Complex((PyObject*)self, 0, 0))) {
 569        SYSTEM_ERROR("__pos__ requires 'mpc' argument");
 570        return NULL;
 571    }
 572
 573    MPC_CLEANUP(result, "__pos__");
 574}
 575
 576/* Support Pympany_square */
 577
 578static PyObject *
 579Pympc_sqr(PyObject* self, PyObject *other)
 580{
 581    PympcObject *result;
 582
 583    PARSE_ONE_MPC_OTHER("square() requires 'mpc' argument");
 584
 585    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
 586        Py_DECREF(self);
 587        return NULL;
 588    }
 589
 590    result->rc = mpc_sqr(result->c, Pympc_AS_MPC(self),
 591                         GET_MPC_ROUND(context));
 592    Py_DECREF(self);
 593
 594    MPC_CLEANUP(result, "square()");
 595}
 596
 597static PyObject *
 598Pympc_pow(PyObject *base, PyObject *exp, PyObject *m)
 599{
 600    PympcObject *tempb, *tempe, *result;
 601
 602    if (m != Py_None) {
 603        TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers");
 604        return NULL;
 605    }
 606
 607    tempb = Pympc_From_Complex(base, 0, 0);
 608    tempe = Pympc_From_Complex(exp, 0, 0);
 609
 610    if (!tempe || !tempb) {
 611        Py_XDECREF((PyObject*)tempe);
 612        Py_XDECREF((PyObject*)tempb);
 613        Py_RETURN_NOTIMPLEMENTED;
 614    }
 615
 616    result = (PympcObject*)Pympc_new(0, 0);
 617
 618    if (!result) {
 619        Py_DECREF((PyObject*)tempe);
 620        Py_DECREF((PyObject*)tempb);
 621        return NULL;
 622    }
 623
 624    if (MPC_IS_ZERO_P(tempb) && MPC_IS_ZERO_P(tempe)) {
 625        mpc_set_ui(result->c, 1, GET_MPC_ROUND(context));
 626        Py_DECREF((PyObject*)tempe);
 627        Py_DECREF((PyObject*)tempb);
 628        return (PyObject*)result;
 629    }
 630
 631    if (MPC_IS_ZERO_P(tempb) &&
 632        (!mpfr_zero_p(mpc_imagref(tempe->c)) ||
 633         mpfr_sgn(mpc_realref(tempe->c)) < 0)) {
 634
 635        context->ctx.divzero = 1;
 636        if (context->ctx.trap_divzero) {
 637            GMPY_DIVZERO("zero cannot be raised to a negative or complex power");
 638            Py_DECREF((PyObject*)tempe);
 639            Py_DECREF((PyObject*)tempb);
 640            Py_DECREF((PyObject*)result);
 641            return NULL;
 642        }
 643    }
 644
 645    result->rc = mpc_pow(result->c, tempb->c,
 646                         tempe->c, GET_MPC_ROUND(context));
 647    Py_DECREF((PyObject*)tempe);
 648    Py_DECREF((PyObject*)tempb);
 649
 650    MPC_CLEANUP(result, "pow()");
 651}
 652
 653/* Implement the conjugate() method. */
 654
 655PyDoc_STRVAR(doc_mpc_conjugate,
 656"x.conjugate() -> mpc\n\n"
 657"Returns the conjugate of x.");
 658
 659static PyObject *
 660Pympc_conjugate(PyObject *self, PyObject *args)
 661{
 662    PympcObject *result;
 663
 664    PARSE_ONE_MPC_ARGS("conjugate() requires 'mpc' argument");
 665
 666    if (!(result = (PympcObject*)Pympc_new(0,0))) {
 667        Py_DECREF(self);
 668        return NULL;
 669    }
 670
 671    result->rc = mpc_conj(result->c, Pympc_AS_MPC(self),
 672                          GET_MPC_ROUND(context));
 673    Py_DECREF(self);
 674
 675    MPC_CLEANUP(result, "conjugate()");
 676}
 677
 678/* Implement the .precision attribute of an mpfr. */
 679
 680static PyObject *
 681Pympc_getprec_attrib(PympcObject *self, void *closure)
 682{
 683    mpfr_prec_t rprec = 0, iprec = 0;
 684
 685    mpc_get_prec2(&rprec, &iprec, self->c);
 686    return Py_BuildValue("(nn)", rprec, iprec);
 687}
 688
 689/* Implement the .rc attribute of an mpfr. */
 690
 691static PyObject *
 692Pympc_getrc_attrib(PympcObject *self, void *closure)
 693{
 694    return Py_BuildValue("(ii)", MPC_INEX_RE(self->rc), MPC_INEX_IM(self->rc));
 695}
 696
 697/* Implement the .imag attribute of an mpfr. */
 698
 699static PyObject *
 700Pympc_getimag_attrib(PympcObject *self, void *closure)
 701{
 702    PympfrObject *result;
 703
 704    if ((result = (PympfrObject*)Pympfr_new(0)))
 705        mpc_imag(result->f, self->c, context->ctx.mpfr_round);
 706    return (PyObject*)result;
 707}
 708
 709/* Implement the .real attribute of an mpfr. */
 710
 711static PyObject *
 712Pympc_getreal_attrib(PympcObject *self, void *closure)
 713{
 714    PympfrObject *result;
 715
 716    if ((result = (PympfrObject*)Pympfr_new(0)))
 717        mpc_real(result->f, self->c, context->ctx.mpfr_round);
 718    return (PyObject*)result;
 719}
 720
 721/* Implement the nb_bool slot. */
 722
 723static int
 724Pympc_nonzero(PympcObject *self)
 725{
 726    return !MPC_IS_ZERO_P(self->c);
 727}
 728
 729/* To work with the MPC_IS_ macros, NAN, INF, FINITE, and ZERO are
 730 * all upper-case.
 731 */
 732
 733#define MPC_TEST_OTHER(NAME, msg) \
 734static PyObject * \
 735Pympc_is_##NAME(PyObject *self, PyObject *other)\
 736{\
 737    if(self && Pympc_Check(self)) {\
 738        Py_INCREF(self);\
 739    }\
 740    else if(Pympc_Check(other)) {\
 741        self = other;\
 742        Py_INCREF((PyObject*)self);\
 743    }\
 744    else if (!(self = (PyObject*)Pympc_From_Complex(other, 0, 0))) {\
 745        PyErr_SetString(PyExc_TypeError, msg);\
 746        return NULL;\
 747    }\
 748    if (MPC_IS_##NAME##_P(self)) {\
 749        Py_DECREF(self);\
 750        Py_RETURN_TRUE;\
 751    }\
 752    else {\
 753        Py_DECREF(self);\
 754        Py_RETURN_FALSE;\
 755    }\
 756}
 757
 758MPC_TEST_OTHER(NAN, "is_nan() requires 'mpc' argument");
 759
 760MPC_TEST_OTHER(INF, "is_infinite() requires 'mpc' argument");
 761
 762MPC_TEST_OTHER(FINITE, "is_finite() requires 'mpc' argument");
 763
 764MPC_TEST_OTHER(ZERO, "is_zero() requires 'mpc' argument");
 765
 766PyDoc_STRVAR(doc_mpc_phase,
 767"phase(x) -> mpfr\n\n"
 768"Return the phase angle, also known as argument, of a complex x.");
 769
 770static PyObject *
 771Pympc_phase(PyObject *self, PyObject *other)
 772{
 773    PympfrObject *result;
 774
 775    PARSE_ONE_MPC_OTHER("phase() requires 'mpc' argument");
 776
 777    if (!(result = (PympfrObject*)Pympfr_new(0))) {
 778        Py_DECREF(self);
 779        return NULL;
 780    }
 781
 782    result->rc = mpc_arg(result->f, Pympc_AS_MPC(self),
 783                         context->ctx.mpfr_round);
 784    Py_DECREF((PyObject*)self);
 785
 786    MPFR_SUBNORMALIZE(result);
 787    MPFR_CHECK_OVERFLOW(result, "overflow in 'mpc' phase()");
 788    MPFR_CHECK_INVALID(result, "invalid operation 'mpc' phase()");
 789    MPFR_CHECK_UNDERFLOW(result, "underflow in 'mpc' phase()");
 790    MPFR_CHECK_INEXACT(result, "inexact operation in 'mpc' phase()");
 791  done:
 792    if (PyErr_Occurred()) {
 793        Py_DECREF((PyObject*)result);
 794        result = NULL;
 795    }
 796    return (PyObject*)result;
 797}
 798
 799PyDoc_STRVAR(doc_mpc_norm,
 800"norm(x) -> mpfr\n\n"
 801"Return the norm of a complex x. The norm(x) is defined as\n"
 802"x.real**2 + x.imag**2. abs(x) is the square root of norm(x).\n");
 803
 804static PyObject *
 805Pympc_norm(PyObject *self, PyObject *other)
 806{
 807    PympfrObject *result;
 808
 809    PARSE_ONE_MPC_OTHER("norm() requires 'mpc' argument");
 810
 811    if (!(result = (PympfrObject*)Pympfr_new(0))) {
 812        Py_DECREF(self);
 813        return NULL;
 814    }
 815
 816    result->rc = mpc_norm(result->f, Pympc_AS_MPC(self),
 817                          context->ctx.mpfr_round);
 818    Py_DECREF((PyObject*)self);
 819
 820    MPFR_SUBNORMALIZE(result);
 821    MPFR_CHECK_OVERFLOW(result, "overflow in 'mpc' norm()");
 822    MPFR_CHECK_INVALID(result, "invalid operation 'mpc' norm()");
 823    MPFR_CHECK_UNDERFLOW(result, "underflow in 'mpc' norm()");
 824    MPFR_CHECK_INEXACT(result, "inexact operation in 'mpc' norm()");
 825  done:
 826    if (PyErr_Occurred()) {
 827        Py_DECREF((PyObject*)result);
 828        result = NULL;
 829    }
 830    return (PyObject*)result;
 831}
 832
 833PyDoc_STRVAR(doc_mpc_polar,
 834"polar(x) -> (abs(x), phase(x))\n\n"
 835"Return the polar coordinate form of a complex x that is in\n"
 836"rectangular form.");
 837
 838static PyObject *
 839Pympc_polar(PyObject *self, PyObject *other)
 840{
 841    PyObject *abs, *phase, *result;
 842
 843    PARSE_ONE_MPC_OTHER("norm() requires 'mpc' argument");
 844
 845    if (!(abs = Pympc_abs(self))) {
 846        Py_DECREF(self);
 847        return NULL;
 848    }
 849    if (!(phase = Pympc_phase(self, other))) {
 850        Py_DECREF(abs);
 851        Py_DECREF(self);
 852        return NULL;
 853    }
 854
 855    result = Py_BuildValue("(NN)", abs, phase);
 856    if (!result) {
 857        Py_DECREF(abs);
 858        Py_DECREF(phase);
 859    }
 860    Py_DECREF(self);
 861    return result;
 862}
 863
 864PyDoc_STRVAR(doc_mpc_rect,
 865"rect(x) -> mpc\n\n"
 866"Return the polar coordinate form of a complex x that is in\n"
 867"rectangular form.");
 868
 869/* Note: does not properly check for inexact or underflow */
 870
 871static PyObject *
 872Pympc_rect(PyObject *self, PyObject *args)
 873{
 874    PyObject *other;
 875    PympcObject *result;
 876
 877    PARSE_TWO_MPFR_ARGS(other, "rect() requires 'mpfr','mpfr' arguments");
 878
 879    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
 880        Py_DECREF(self);
 881        Py_DECREF(other);
 882        return NULL;
 883    }
 884
 885    mpfr_cos(mpc_realref(result->c), Pympfr_AS_MPFR(other),
 886             GET_REAL_ROUND(context));
 887    mpfr_mul(mpc_realref(result->c), mpc_realref(result->c),
 888             Pympfr_AS_MPFR(self), GET_REAL_ROUND(context));
 889    mpfr_sin(mpc_imagref(result->c), Pympfr_AS_MPFR(other),
 890             GET_IMAG_ROUND(context));
 891    mpfr_mul(mpc_imagref(result->c), mpc_imagref(result->c),
 892             Pympfr_AS_MPFR(self), GET_IMAG_ROUND(context));
 893    Py_DECREF(self);
 894    Py_DECREF(other);
 895
 896    MPC_CLEANUP(result, "rect()");
 897}
 898
 899PyDoc_STRVAR(doc_mpc_proj,
 900"proj(x) -> mpc\n\n"
 901"Returns the projection of a complex x on to the Riemann sphere.");
 902
 903static PyObject *
 904Pympc_proj(PyObject *self, PyObject *other)
 905{
 906    PympcObject *result;
 907
 908    PARSE_ONE_MPC_OTHER("proj() requires 'mpc' argument");
 909
 910    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
 911        Py_DECREF(self);
 912        return NULL;
 913    }
 914
 915    result->rc = mpc_proj(result->c, Pympc_AS_MPC(self),
 916                          GET_MPC_ROUND(context));
 917    Py_DECREF(self);
 918
 919    MPC_CLEANUP(result, "proj()");
 920}
 921
 922#define MPC_UNIOP(NAME) \
 923static PyObject * \
 924Pympc_##NAME(PyObject* self, PyObject *other) \
 925{ \
 926    PympcObject *result; \
 927    PARSE_ONE_MPC_OTHER(#NAME "() requires 'mpc' argument"); \
 928    if (!(result = (PympcObject*)Pympc_new(0, 0))) { \
 929        Py_DECREF(self); \
 930        return NULL; \
 931    } \
 932    result->rc = mpc_##NAME(result->c, Pympc_AS_MPC(self), GET_MPC_ROUND(context)); \
 933    Py_DECREF(self); \
 934    MPC_CLEANUP(result, #NAME"()"); \
 935}
 936
 937MPC_UNIOP(log)
 938
 939MPC_UNIOP(log10)
 940
 941MPC_UNIOP(exp)
 942
 943MPC_UNIOP(sin)
 944
 945MPC_UNIOP(cos)
 946
 947MPC_UNIOP(tan)
 948
 949MPC_UNIOP(sinh)
 950
 951MPC_UNIOP(cosh)
 952
 953MPC_UNIOP(tanh)
 954
 955MPC_UNIOP(asin)
 956
 957MPC_UNIOP(acos)
 958
 959MPC_UNIOP(atan)
 960
 961MPC_UNIOP(asinh)
 962
 963MPC_UNIOP(acosh)
 964
 965MPC_UNIOP(atanh)
 966
 967MPC_UNIOP(sqrt)
 968
 969static PyObject *
 970Pympc_sin_cos(PyObject *self, PyObject *other)
 971{
 972    PympcObject *s, *c;
 973    PyObject *result;
 974    int code;
 975
 976    PARSE_ONE_MPC_OTHER("sin_cos() requires 'mpc' argument");
 977
 978    s = (PympcObject*)Pympc_new(0, 0);
 979    c = (PympcObject*)Pympc_new(0, 0);
 980    result = PyTuple_New(2);
 981    if (!s || !c || !result) {
 982        Py_DECREF(self);
 983        return NULL;
 984    }
 985
 986    code = mpc_sin_cos(s->c, c->c, Pympc_AS_MPC(self),
 987                       GET_MPC_ROUND(context), GET_MPC_ROUND(context));
 988    s->rc = MPC_INEX1(code);
 989    c->rc = MPC_INEX2(code);
 990    MPC_SUBNORMALIZE(s);
 991    MPC_SUBNORMALIZE(c);
 992    MPC_CHECK_FLAGS(s, "sin_cos()");
 993    MPC_CHECK_FLAGS(c, "sin_cos()");
 994
 995  done:
 996    Py_DECREF(self);
 997    if (PyErr_Occurred()) {
 998        Py_XDECREF((PyObject*)s);
 999        Py_XDECREF((PyObject*)c);
1000        Py_XDECREF(result);
1001        result = NULL;
1002    }
1003    else {
1004        PyTuple_SET_ITEM(result, 0, (PyObject*)s);
1005        PyTuple_SET_ITEM(result, 1, (PyObject*)c);
1006    }
1007    return result;
1008}
1009
1010static PyObject *
1011Pympc_fma(PyObject *self, PyObject *args)
1012{
1013    PympcObject *result, *x, *y, *z;
1014
1015    if (PyTuple_GET_SIZE(args) != 3) {
1016        TYPE_ERROR("fma() requires 'mpc','mpc','mpc' arguments.");
1017        return NULL;
1018    }
1019
1020    result = (PympcObject*)Pympc_new(0, 0);
1021    x = Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0);
1022    y = Pympc_From_Complex(PyTuple_GET_ITEM(args, 1), 0, 0);
1023    z = Pympc_From_Complex(PyTuple_GET_ITEM(args, 2), 0, 0);
1024    if (!result || !x || !y || !z) {
1025        TYPE_ERROR("fma() requires 'mpc','mpc','mpc' arguments.");
1026        goto done;
1027    }
1028
1029    result->rc = mpc_fma(result->c, x->c, y->c, z->c,
1030                         context->ctx.mpfr_round);
1031    MPC_SUBNORMALIZE(result);
1032    MPC_CHECK_FLAGS(result, "fma()");
1033
1034  done:
1035    Py_XDECREF((PyObject*)x);
1036    Py_XDECREF((PyObject*)y);
1037    Py_XDECREF((PyObject*)z);
1038    if (PyErr_Occurred()) {
1039        Py_XDECREF(result);
1040        result = NULL;
1041    }
1042    return (PyObject*)result;
1043}
1044
1045static PyObject *
1046Pympc_fms(PyObject *self, PyObject *args)
1047{
1048    PympcObject *result, *x, *y, *z;
1049
1050    if (PyTuple_GET_SIZE(args) != 3) {
1051        TYPE_ERROR("fms() requires 'mpc','mpc','mpc' arguments.");
1052        return NULL;
1053    }
1054
1055    result = (PympcObject*)Pympc_new(0, 0);
1056    x = Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0);
1057    y = Pympc_From_Complex(PyTuple_GET_ITEM(args, 1), 0, 0);
1058    z = Pympc_From_Complex(PyTuple_GET_ITEM(args, 2), 0, 0);
1059    if (!result || !x || !y || !z) {
1060        TYPE_ERROR("fms() requires 'mpc','mpc','mpc' arguments.");
1061        goto done;
1062    }
1063
1064    mpc_neg(z->c, z->c, GET_MPC_ROUND(context));
1065    result->rc = mpc_fma(result->c, x->c, y->c, z->c,
1066                         context->ctx.mpfr_round);
1067    MPC_SUBNORMALIZE(result);
1068    MPC_CHECK_FLAGS(result, "fms()");
1069
1070  done:
1071    Py_XDECREF((PyObject*)x);
1072    Py_XDECREF((PyObject*)y);
1073    Py_XDECREF((PyObject*)z);
1074    if (PyErr_Occurred()) {
1075        Py_XDECREF(result);
1076        result = NULL;
1077    }
1078    return (PyObject*)result;
1079}
1080
1081static PyObject *
1082Pympc_div_2exp(PyObject *self, PyObject *args)
1083{
1084    PympcObject *result = 0;
1085    unsigned long exp = 0;
1086
1087    if (!PyArg_ParseTuple(args, "O&k", Pympc_convert_arg, &self, &exp)) {
1088        TYPE_ERROR("div_2exp() requires 'mpc', 'int' arguments");
1089        return NULL;
1090    }
1091
1092    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1093        Py_DECREF(self);
1094        return NULL;
1095    }
1096
1097    result->rc = mpc_div_2ui(Pympc_AS_MPC(result), Pympc_AS_MPC(self),
1098                              exp, GET_MPC_ROUND(context));
1099    Py_DECREF(self);
1100
1101    MPC_CLEANUP(result, "div_2exp()");
1102}
1103
1104static PyObject *
1105Pympc_mul_2exp(PyObject *self, PyObject *args)
1106{
1107    PympcObject *result = 0;
1108    unsigned long exp = 0;
1109
1110    if (!PyArg_ParseTuple(args, "O&k", Pympc_convert_arg, &self, &exp)) {
1111        TYPE_ERROR("mul_2exp() requires 'mpc', 'int' arguments");
1112        return NULL;
1113    }
1114
1115    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1116        Py_DECREF(self);
1117        return NULL;
1118    }
1119
1120    result->rc = mpc_mul_2ui(Pympc_AS_MPC(result), Pympc_AS_MPC(self),
1121                             exp, GET_MPC_ROUND(context));
1122    Py_DECREF(self);
1123
1124    MPC_CLEANUP(result, "mul_2exp()");
1125}
1126
1127static Py_hash_t
1128Pympc_hash(PympcObject *self)
1129{
1130    Py_uhash_t hashreal, hashimag, combined;
1131
1132    if (self->hash_cache != -1)
1133        return self->hash_cache;
1134
1135    hashreal = (Py_uhash_t)_mpfr_hash(mpc_realref(self->c));
1136    if (hashreal == (Py_uhash_t)-1)
1137        return -1;
1138    hashimag = (Py_uhash_t)_mpfr_hash(mpc_imagref(self->c));
1139    if (hashimag == (Py_uhash_t)-1)
1140        return -1;
1141    combined = hashreal + _PyHASH_IMAG * hashimag;
1142    if (combined == (Py_uhash_t)-1)
1143        combined = (Py_uhash_t)-2;
1144    self->hash_cache = combined;
1145    return (Py_hash_t)combined;
1146}
1147
1148static PyObject *
1149Pympc_add_fast(PyObject *x, PyObject *y)
1150{
1151    PympcObject *result;
1152
1153    if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) {
1154        if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1155            return NULL;
1156        }
1157        result->rc = mpc_add(result->c,
1158                             Pympc_AS_MPC(x),
1159                             Pympc_AS_MPC(y),
1160                             GET_MPC_ROUND(context));
1161        MPC_CLEANUP(result, "addition");
1162        return (PyObject*)result;
1163    }
1164    else {
1165        return Pybasic_add(x, y);
1166    }
1167}
1168
1169static PyObject *
1170Pympc_add(PyObject *self, PyObject *args)
1171{
1172    PympcObject *result;
1173    PyObject *other;
1174
1175    PARSE_TWO_MPC_ARGS(other, "add() requires 'mpc','mpc' arguments");
1176
1177    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1178        Py_DECREF(self);
1179        Py_DECREF(other);
1180        return NULL;
1181    }
1182
1183    result->rc = mpc_add(result->c, Pympc_AS_MPC(self),
1184                         Pympc_AS_MPC(other), GET_MPC_ROUND(context));
1185    Py_DECREF(self);
1186    Py_DECREF(other);
1187    MPC_CLEANUP(result, "add()");
1188}
1189
1190static PyObject *
1191Pympc_sub_fast(PyObject *x, PyObject *y)
1192{
1193    PympcObject *result;
1194
1195    if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) {
1196        if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1197            return NULL;
1198        }
1199        result->rc = mpc_sub(result->c,
1200                             Pympc_AS_MPC(x),
1201                             Pympc_AS_MPC(y),
1202                             GET_MPC_ROUND(context));
1203        MPC_CLEANUP(result, "subtraction");
1204        return (PyObject*)result;
1205    }
1206    else {
1207        return Pybasic_sub(x, y);
1208    }
1209}
1210
1211static PyObject *
1212Pympc_sub(PyObject *self, PyObject *args)
1213{
1214    PympcObject *result;
1215    PyObject *other;
1216
1217    PARSE_TWO_MPC_ARGS(other, "sub() requires 'mpc','mpc' arguments");
1218
1219    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1220        Py_DECREF(self);
1221        Py_DECREF(other);
1222        return NULL;
1223    }
1224
1225    result->rc = mpc_sub(result->c, Pympc_AS_MPC(self),
1226                         Pympc_AS_MPC(other), GET_MPC_ROUND(context));
1227    Py_DECREF(self);
1228    Py_DECREF(other);
1229    MPC_CLEANUP(result, "sub()");
1230}
1231
1232static PyObject *
1233Pympc_mul_fast(PyObject *x, PyObject *y)
1234{
1235    PympcObject *result;
1236
1237    if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) {
1238        if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1239            return NULL;
1240        }
1241        result->rc = mpc_mul(result->c,
1242                             Pympc_AS_MPC(x),
1243                             Pympc_AS_MPC(y),
1244                             GET_MPC_ROUND(context));
1245        MPC_CLEANUP(result, "multiplication");
1246        return (PyObject*)result;
1247    }
1248    else {
1249        return Pybasic_mul(x, y);
1250    }
1251}
1252
1253static PyObject *
1254Pympc_mul(PyObject *self, PyObject *args)
1255{
1256    PympcObject *result;
1257    PyObject *other;
1258
1259    PARSE_TWO_MPC_ARGS(other, "mul() requires 'mpc','mpc' arguments");
1260
1261    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1262        Py_DECREF(self);
1263        Py_DECREF(other);
1264        return NULL;
1265    }
1266
1267    result->rc = mpc_mul(result->c, Pympc_AS_MPC(self),
1268                         Pympc_AS_MPC(other), GET_MPC_ROUND(context));
1269    Py_DECREF(self);
1270    Py_DECREF(other);
1271    MPC_CLEANUP(result, "mul()");
1272}
1273
1274static PyObject *
1275Pympc_truediv_fast(PyObject *x, PyObject *y)
1276{
1277    PympcObject *result;
1278
1279    if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) {
1280        if (MPC_IS_ZERO_P(y)) {
1281            context->ctx.divzero = 1;
1282            if (context->ctx.trap_divzero) {
1283                GMPY_DIVZERO("'mpc' division by zero");
1284                return NULL;
1285            }
1286        }
1287        if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1288            return NULL;
1289        }
1290        result->rc = mpc_div(result->c,
1291                             Pympc_AS_MPC(x),
1292                             Pympc_AS_MPC(y),
1293                             GET_MPC_ROUND(context));
1294        MPC_CLEANUP(result, "division");
1295        return (PyObject*)result;
1296    }
1297    else {
1298        return Pybasic_truediv(x, y);
1299    }
1300}
1301
1302#ifdef PY2
1303static PyObject *
1304Pympc_div2_fast(PyObject *x, PyObject *y)
1305{
1306    PympcObject *result;
1307
1308    if (Pympc_CheckAndExp(x) && Pympc_CheckAndExp(y)) {
1309        if (MPC_IS_ZERO_P(y)) {
1310            context->ctx.divzero = 1;
1311            if (context->ctx.trap_divzero) {
1312                GMPY_DIVZERO("'mpc' division by zero");
1313                return NULL;
1314            }
1315        }
1316        if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1317            return NULL;
1318        }
1319        result->rc = mpc_div(result->c,
1320                             Pympc_AS_MPC(x),
1321                             Pympc_AS_MPC(y),
1322                             GET_MPC_ROUND(context));
1323        MPC_CLEANUP(result, "division");
1324        return (PyObject*)result;
1325    }
1326    else {
1327        return Pybasic_div2(x, y);
1328    }
1329}
1330#endif
1331
1332static PyObject *
1333Pympc_div(PyObject *self, PyObject *args)
1334{
1335    PympcObject *result;
1336    PyObject *other;
1337
1338    PARSE_TWO_MPC_ARGS(other, "div() requires 'mpc','mpc' arguments");
1339
1340    if (!(result = (PympcObject*)Pympc_new(0, 0))) {
1341        Py_DECREF(self);
1342        Py_DECREF(other);
1343        return NULL;
1344    }
1345
1346    if (MPC_IS_ZERO_P(Pympc_AS_MPC(other))) {
1347        context->ctx.divzero = 1;
1348        if (context->ctx.trap_divzero) {
1349            GMPY_DIVZERO("'mpc' division by zero");
1350            Py_DECREF(self);
1351            Py_DECREF(other);
1352            return NULL;
1353        }
1354    }
1355
1356    result->rc = mpc_div(result->c, Pympc_AS_MPC(self),
1357                         Pympc_AS_MPC(other), GET_MPC_ROUND(context));
1358    Py_DECREF(self);
1359    Py_DECREF(other);
1360    MPC_CLEANUP(result, "div()");
1361}
1362
1363PyDoc_STRVAR(doc_mpc_sizeof,
1364"x.__sizeof__()\n\n"
1365"Returns the amount of memory consumed by x.");
1366
1367static PyObject *
1368Pympc_sizeof(PyObject *self, PyObject *other)
1369{
1370    return PyIntOrLong_FromSize_t(sizeof(PympcObject) + \
1371        (((mpc_realref(Pympc_AS_MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
1372        mp_bits_per_limb) * sizeof(mp_limb_t)) + \
1373        (((mpc_imagref(Pympc_AS_MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
1374        mp_bits_per_limb) * sizeof(mp_limb_t)));
1375}
1376
1377static PyMethodDef Pympc_methods[] =
1378{
1379    { "__complex__", Pympc_To_PyComplex, METH_VARARGS, doc_mpc_complex },
1380    { "__format__", Pympc_format, METH_VARARGS, doc_mpc_format },
1381    { "__sizeof__", Pympc_sizeof, METH_NOARGS, doc_mpc_sizeof },
1382    { "conjugate", Pympc_conjugate, METH_NOARGS, doc_mpc_conjugate },
1383    { "digits", Pympc_digits, METH_VARARGS, doc_mpc_digits },
1384    { NULL, NULL, 1 }
1385};
1386
1387
1388#ifdef PY3
1389static PyNumberMethods mpc_number_methods =
1390{
1391    (binaryfunc) Pympc_add_fast,         /* nb_add                  */
1392    (binaryfunc) Pympc_sub_fast,         /* nb_subtract             */
1393    (binaryfunc) Pympc_mul_fast,         /* nb_multiply             */
1394    (binaryfunc) Pybasic_rem,            /* nb_remainder            */
1395    (binaryfunc) Pybasic_divmod,         /* nb_divmod               */
1396    (ternaryfunc) Pympany_pow,           /* nb_power                */
1397    (unaryfunc) Pympc_neg,               /* nb_negative             */
1398    (unaryfunc) Pympc_pos,               /* nb_positive             */
1399    (unaryfunc) Pympc_abs,               /* nb_absolute             */
1400    (inquiry) Pympc_nonzero,             /* nb_bool                 */
1401        0,                               /* nb_invert               */
1402        0,                               /* nb_lshift               */
1403        0,                               /* nb_rshift               */
1404        0,                               /* nb_and                  */
1405        0,                               /* nb_xor                  */
1406        0,                               /* nb_or                   */
1407    (unaryfunc) Pympc_To_PyLong,         /* nb_int                  */
1408        0,                               /* nb_reserved             */
1409    (unaryfunc) Pympc_To_PyFloat,        /* nb_float                */
1410        0,                               /* nb_inplace_add          */
1411        0,                               /* nb_inplace_subtract     */
1412        0,                               /* nb_inplace_multiply     */
1413        0,                               /* nb_inplace_remainder    */
1414        0,                               /* nb_inplace_power        */
1415        0,                               /* nb_inplace_lshift       */
1416        0,                               /* nb_inplace_rshift       */
1417        0,                               /* nb_inplace_and          */
1418        0,                               /* nb_inplace_xor          */
1419        0,                               /* nb_inplace_or           */
1420    (binaryfunc) Pybasic_floordiv,       /* nb_floor_divide         */
1421    (binaryfunc) Pympc_truediv_fast,     /* nb_true_divide          */
1422        0,                               /* nb_inplace_floor_divide */
1423        0,                               /* nb_inplace_true_divide  */
1424        0,                               /* nb_index                */
1425};
1426#else
1427static PyNumberMethods mpc_number_methods =
1428{
1429    (binaryfunc) Pympc_add_fast,         /* nb_add                  */
1430    (binaryfunc) Pympc_sub_fast,         /* nb_subtract             */
1431    (binaryfunc) Pympc_mul_fast,         /* nb_multiply             */
1432    (binaryfunc) Pympc_div2_fast,        /* nb_divide               */
1433    (binaryfunc) Pybasic_rem,            /* nb_remainder            */
1434    (binaryfunc) Pybasic_divmod,         /* nb_divmod               */
1435    (ternaryfunc) Pympany_pow,           /* nb_power                */
1436    (unaryfunc) Pympc_neg,               /* nb_negative             */
1437    (unaryfunc) Pympc_pos,               /* nb_positive             */
1438    (unaryfunc) Pympc_abs,               /* nb_absolute             */
1439    (inquiry) Pympc_nonzero,             /* nb_bool                 */
1440        0,                               /* nb_invert               */
1441        0,                               /* nb_lshift               */
1442        0,                               /* nb_rshift               */
1443        0,                               /* nb_and                  */
1444        0,                               /* nb_xor                  */
1445        0,                               /* nb_or                   */
1446        0,                               /* nb_coerce               */
1447    (unaryfunc) Pympc_To_PyIntOrLong,    /* nb_int                  */
1448    (unaryfunc) Pympc_To_PyLong,         /* nb_long                 */
1449    (unaryfunc) Pympc_To_PyFloat,        /* nb_float                */
1450        0,                               /* nb_oct                  */
1451        0,                               /* nb_hex                  */
1452        0,                               /* nb_inplace_add          */
1453        0,                               /* nb_inplace_subtract     */
1454        0,                               /* nb_inplace_multiply     */
1455        0,                               /* nb_inplace_divide       */
1456        0,                               /* nb_inplace_remainder    */
1457        0,                               /* nb_inplace_power        */
1458        0,                               /* nb_inplace_lshift       */
1459        0,                               /* nb_inplace_rshift       */
1460        0,                               /* nb_inplace_and          */
1461        0,                               /* nb_inplace_xor          */
1462        0,                               /* nb_inplace_or           */
1463    (binaryfunc) Pybasic_floordiv,       /* nb_floor_divide         */
1464    (binaryfunc) Pympc_truediv_fast,     /* nb_true_divide          */
1465        0,                               /* nb_inplace_floor_divide */
1466        0,                               /* nb_inplace_true_divide  */
1467};
1468#endif
1469
1470static PyGetSetDef Pympc_getseters[] =
1471{
1472    {"precision", (getter)Pympc_getprec_attrib, NULL, "precision in bits", NULL},
1473    {"rc", (getter)Pympc_getrc_attrib, NULL, "return code", NULL},
1474    {"imag", (getter)Pympc_getimag_attrib, NULL, "imaginary component", NULL},
1475    {"real", (getter)Pympc_getreal_attrib, NULL, "real component", NULL},
1476    {NULL}
1477};
1478
1479static PyTypeObject Pympc_Type =
1480{
1481    /* PyObject_HEAD_INIT(&PyType_Type) */
1482#ifdef PY3
1483    PyVarObject_HEAD_INIT(NULL, 0)
1484#else
1485    PyObject_HEAD_INIT(0)
1486    0,                                      /* ob_size          */
1487#endif
1488    "mpc",                                  /* tp_name          */
1489    sizeof(PympcObject),                    /* tp_basicsize     */
1490        0,                                  /* tp_itemsize      */
1491    /* methods */
1492    (destructor) Pympc_dealloc,             /* tp_dealloc       */
1493        0,                                  /* tp_print         */
1494        0,                                  /* tp_getattr       */
1495        0,                                  /* tp_setattr       */
1496        0,                                  /* tp_reserved      */
1497    (reprfunc) Pympc_To_Repr,               /* tp_repr          */
1498    &mpc_number_methods,                    /* tp_as_number     */
1499        0,                                  /* tp_as_sequence   */
1500        0,                                  /* tp_as_mapping    */
1501    (hashfunc) Pympc_hash,                  /* tp_hash          */
1502        0,                                  /* tp_call          */
1503    (reprfunc) Pympc_To_Str,                /* tp_str           */
1504        0,                                  /* tp_getattro      */
1505        0,                                  /* tp_setattro      */
1506        0,                                  /* tp_as_buffer     */
1507#ifdef PY3
1508    Py_TPFLAGS_DEFAULT,                     /* tp_flags         */
1509#else
1510    Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES,  /* tp_flags */
1511#endif
1512    "MPC-based complex number",             /* tp_doc           */
1513        0,                                  /* tp_traverse      */
1514        0,                                  /* tp_clear         */
1515    (richcmpfunc)&mpany_richcompare,        /* tp_richcompare   */
1516        0,                                  /* tp_weaklistoffset*/
1517        0,                                  /* tp_iter          */
1518        0,                                  /* tp_iternext      */
1519    Pympc_methods,                          /* tp_methods       */
1520        0,                                  /* tp_members       */
1521    Pympc_getseters,                        /* tp_getset        */
1522};
1523
1524