static PyObject * GMPy_Complex_Add(PyObject *x, PyObject *y, CTXT_Object *context) { MPC_Object *result = NULL; CHECK_CONTEXT(context); if (!(result = GMPy_MPC_New(0, 0, context))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } if (MPC_Check(x) && MPC_Check(y)) { SET_MPC_MPC_WAS_NAN(context, x, y); result->rc = mpc_add(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context)); _GMPy_MPC_Cleanup(&result, context); return (PyObject*)result; } if (IS_COMPLEX(x) && IS_COMPLEX(y)) { MPC_Object *tempx = NULL, *tempy = NULL; if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context)) || !(tempy = GMPy_MPC_From_Complex(y, 1, 1, context))) { /* LCOV_EXCL_START */ Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ } SET_MPC_MPC_WAS_NAN(context, tempx, tempy); result->rc = mpc_add(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); _GMPy_MPC_Cleanup(&result, context); return (PyObject*)result; } /* LCOV_EXCL_START */ Py_DECREF((PyObject*)result); SYSTEM_ERROR("Internal error in GMPy_Complex_Add()."); return NULL; /* LCOV_EXCL_STOP */ }
static PyObject * GMPy_Number_Minus(PyObject *x, CTXT_Object *context) { if (MPZ_Check(x)) return _GMPy_MPZ_Minus(x, context); if (MPQ_Check(x)) return _GMPy_MPQ_Minus(x, context); if (MPFR_Check(x)) return _GMPy_MPFR_Minus(x, context); if (MPC_Check(x)) return _GMPy_MPC_Minus(x, context); if (IS_INTEGER(x)) return GMPy_Integer_Minus(x, context); if (IS_RATIONAL_ONLY(x)) return GMPy_Rational_Minus(x, context); if (IS_REAL_ONLY(x)) return GMPy_Real_Minus(x, context); if (IS_COMPLEX_ONLY(x)) return GMPy_Complex_Minus(x, context); TYPE_ERROR("minus() argument type not supported"); return NULL; }
static PyObject * GMPy_Complex_Is_NAN(PyObject *x, CTXT_Object *context) { MPC_Object *tempx; int res; if (MPC_Check(x)) { res = MPC_IS_NAN_P(x); } else { CHECK_CONTEXT(context); if (!(tempx = GMPy_MPC_From_Complex(x, 1, 1, context))) { return NULL; } res = MPC_IS_NAN_P(tempx); Py_DECREF((PyObject*)tempx); } if (res) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } }
static MPC_Object * GMPy_MPC_From_MPC(MPC_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context) { MPC_Object *result = NULL; assert(MPC_Check(obj)); /* Optimize the critical case when prec==1 or obj is NaN or Inf. */ if ((rprec == 1 && iprec == 1) || (!mpfr_number_p(mpc_realref(obj->c)) && !mpfr_number_p(mpc_imagref(obj->c)))) { Py_INCREF((PyObject*)obj); return obj; } CHECK_CONTEXT(context); if (rprec == 0) rprec = GET_REAL_PREC(context); else if (rprec == 1) rprec = mpfr_get_prec(mpc_realref(obj->c)); if (iprec == 0) iprec = GET_IMAG_PREC(context); else if (iprec == 1) iprec = mpfr_get_prec(mpc_imagref(obj->c)); /* Try to identify when an additional reference to existing instance can * be returned. It is possible when (1) the precision matches, (2) the * exponent is valid and not in the range that might require subnormal- * ization, and (3) subnormalize is not enabled. */ if ((rprec == mpfr_get_prec(mpc_realref(obj->c))) && (iprec == mpfr_get_prec(mpc_imagref(obj->c))) && (!context->ctx.subnormalize) && (mpc_realref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_realref(obj->c)) - 1)) && (mpc_realref(obj->c)->_mpfr_exp <= context->ctx.emax) && (mpc_imagref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_imagref(obj->c)) - 1)) && (mpc_imagref(obj->c)->_mpfr_exp <= context->ctx.emax) ) { Py_INCREF((PyObject*)obj); return obj; } if ((result = GMPy_MPC_New(rprec, iprec, context))) { result->rc = mpc_set(result->c, obj->c, GET_MPC_ROUND(context)); _GMPy_MPC_Cleanup(&result, context); } return result; }
static PyObject * GMPy_Complex_Sub(PyObject *x, PyObject *y, CTXT_Object *context) { MPC_Object *result = NULL; CHECK_CONTEXT(context); if (!(result = GMPy_MPC_New(0, 0, context))) return NULL; if (MPC_Check(x) && MPC_Check(y)) { result->rc = mpc_sub(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context)); goto done; } if (IS_COMPLEX(x) && IS_COMPLEX(y)) { MPC_Object *tempx, *tempy; tempx = GMPy_MPC_From_Complex(x, 1, 1, context); tempy = GMPy_MPC_From_Complex(y, 1, 1, context); if (!tempx || !tempy) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } result->rc = mpc_sub(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); goto done; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; done: GMPY_MPC_CLEANUP(result, context, "subtraction"); return (PyObject*)result; }
static MPC_Object * GMPy_MPC_From_Complex(PyObject* obj, mp_prec_t rprec, mp_prec_t iprec, CTXT_Object *context) { CHECK_CONTEXT(context); if (MPC_Check(obj)) return GMPy_MPC_From_MPC((MPC_Object*)obj, rprec, iprec, context); if (MPFR_Check(obj)) return GMPy_MPC_From_MPFR((MPFR_Object*)obj, rprec, iprec, context); if (PyFloat_Check(obj)) return GMPy_MPC_From_PyFloat(obj, rprec, iprec, context); if (PyComplex_Check(obj)) return GMPy_MPC_From_PyComplex(obj, rprec, iprec, context); if (MPQ_Check(obj)) return GMPy_MPC_From_MPQ((MPQ_Object*)obj, rprec, iprec, context); if (MPZ_Check(obj) || XMPZ_Check(obj)) return GMPy_MPC_From_MPZ((MPZ_Object*)obj, rprec, iprec, context); if (PyIntOrLong_Check(obj)) return GMPy_MPC_From_PyIntOrLong(obj, rprec, iprec, context); if (IS_DECIMAL(obj)) return GMPy_MPC_From_Decimal(obj, rprec, iprec, context); if (IS_FRACTION(obj)) return GMPy_MPC_From_Fraction(obj, rprec, iprec, context); TYPE_ERROR("object could not be converted to 'mpc'"); return NULL; }
static PyObject * GMPy_MPC_Format(PyObject *self, PyObject *args) { PyObject *result = NULL, *tempstr = NULL; char *realbuf = 0, *imagbuf = 0, *tempbuf = 0, *fmtcode = 0; char *p, *rfmtptr, *ifmtptr, *fmtptr; char rfmt[100], ifmt[100], fmt[30]; int rbuflen, ibuflen; int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0; int seenround = 0, seenconv = 0, seenstyle = 0, mpcstyle = 0; if (!MPC_Check(self)) { TYPE_ERROR("requires 'mpc' object"); return NULL; } if (!PyArg_ParseTuple(args, "s", &fmtcode)) { return NULL; } rfmtptr = rfmt; ifmtptr = ifmt; fmtptr = fmt; *(rfmtptr++) = '%'; *(ifmtptr++) = '%'; for (p = fmtcode; *p != '\00'; p++) { if (*p == '<' || *p == '>' || *p == '^') { if (seenalign || seensign || seendecimal || seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(fmtptr++) = *p; seenalign = 1; continue; } } if (*p == '+' || *p == ' ' || *p == '-') { if (seensign || seendecimal || seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(rfmtptr++) = *p; *(ifmtptr++) = *p; seensign = 1; continue; } } if (!seensign) { *(rfmtptr++) = '-'; *(ifmtptr++) = '-'; seensign = 1; } if (*p == '.') { if (seendecimal == 2 || seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { if (!seendecimal) { *(rfmtptr++) = *p; *(ifmtptr++) = *p; } seendecimal++; if (seendecimal == 2) { while (isdigit(*(ifmtptr-1))) ifmtptr--; } continue; } } if (isdigit(*p)) { if (seendigits || seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else if (seendecimal == 1) { *(rfmtptr++) = *p; *(ifmtptr++) = *p; continue; } else if (seendecimal == 2) { *(ifmtptr++) = *p; continue; } else { if (fmtptr == fmt) { *(fmtptr++) = '>'; seenalign = 1; } *(fmtptr++) = *p; continue; } } if (!seendigits) { seendigits = 1; *(rfmtptr++) = 'R'; *(ifmtptr++) = 'R'; } if (*p == 'U' || *p == 'D' || *p == 'Y' || *p == 'Z' || *p == 'N' ) { if (seenround || seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { *(rfmtptr++) = *p; *(ifmtptr++) = *p; seenround = 1; continue; } } if (*p == 'P' || *p == 'M') { if (seenstyle) { VALUE_ERROR("Invalid conversion specification"); return NULL; } else { if (*p == 'M') mpcstyle = 1; seenstyle = 1; continue; } } if (*p == 'a' || *p == 'A' || *p == 'b' || *p == 'e' || *p == 'E' || *p == 'f' || *p == 'F' || *p == 'g' || *p == 'G' ) { *(rfmtptr++) = *p; *(ifmtptr++) = *p; seenconv = 1; break; } VALUE_ERROR("Invalid conversion specification"); return NULL; } if (!seensign) { *(rfmtptr++) = '-'; *(ifmtptr++) = '-'; } if (!seendigits) { *(rfmtptr++) = 'R'; *(ifmtptr++) = 'R'; } if (!seenconv) { *(rfmtptr++) = 'f'; *(ifmtptr++) = 'f'; } *(rfmtptr) = '\00'; *(ifmtptr) = '\00'; *(fmtptr) = '\00'; /* Format the real part.... */ rbuflen = mpfr_asprintf(&realbuf, rfmt, mpc_realref(MPC(self))); if (rbuflen < 0) { mpfr_free_str(realbuf); SYSTEM_ERROR("Internal error in mpfr_asprintf"); return NULL; } /* Format the imaginary part. If Python style is wanted, convert the '-' * or ' ' sign indicator to '+'. */ if (!mpcstyle) { if (ifmt[1] == ' ' || ifmt[1] == '-' || ifmt[1] == '+') { ifmt[1] = '+'; } else { mpfr_free_str(realbuf); VALUE_ERROR("Invalid conversion specification for imag"); return NULL; } } ibuflen = mpfr_asprintf(&imagbuf, ifmt, mpc_imagref(MPC(self))); if (ibuflen < 0) { mpfr_free_str(realbuf); mpfr_free_str(imagbuf); SYSTEM_ERROR("Internal error in mpfr_asprintf"); return NULL; } /* Combine the real and imaginary components into a single buffer. * Include space for '(', ' ', and 'j)' and possibly appending '.0' twice. */ tempbuf = GMPY_MALLOC(rbuflen + ibuflen + 10); if (!tempbuf) { mpfr_free_str(realbuf); mpfr_free_str(imagbuf); return PyErr_NoMemory(); } tempbuf[0] = '\00'; if (mpcstyle) strcat(tempbuf, "("); strcat(tempbuf, realbuf); /* If there isn't a decimal point in the output and the output * is short and only consists of digits, then append .0 */ if (strlen(realbuf) < 50 && strlen(realbuf) == strspn(realbuf, "+- 0123456789")) { strcat(tempbuf, ".0"); } if (mpcstyle) strcat(tempbuf, " "); else { /* Need to insert + if imag is nan or +inf. */ if (mpfr_nan_p(mpc_imagref(MPC(self))) || (mpfr_inf_p(mpc_imagref(MPC(self))) && mpfr_sgn(mpc_imagref(MPC(self))) > 0)) { strcat(tempbuf, "+"); } } strcat(tempbuf, imagbuf); if (strlen(imagbuf) < 50 && strlen(imagbuf) == strspn(imagbuf, "+- 0123456789")) { strcat(tempbuf, ".0"); } if (mpcstyle) strcat(tempbuf, ")"); else strcat(tempbuf, "j"); mpfr_free_str(realbuf); mpfr_free_str(imagbuf); tempstr = Py_BuildValue("s", tempbuf); if (!tempstr) { GMPY_FREE(tempbuf); return NULL; } result = PyObject_CallMethod(tempstr, "__format__", "(s)", fmt); Py_DECREF(tempstr); return result; }