/src/gmpy_mpc.h
C++ Header | 330 lines | 239 code | 28 blank | 63 comment | 56 complexity | 7582549cea87f726f4a068b96652ce14 MD5 | raw file
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy_mpc.h * 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 28#ifndef GMPY_MPC_H 29#define GMPY_MPC_H 30 31#ifdef __cplusplus 32extern "C" { 33#endif 34 35 36/* gmpy_mpc C API extension header file. 37 * 38 * Provide interface to the MPC (Multiple Precision Complex) library. 39 * 40 * Version 2.00, April 2011 (created) casevh 41 * 42 * This file is expected to be included from gmpy.h 43 */ 44 45#if defined(MS_WIN32) && defined(_MSC_VER) 46# pragma comment(lib,"mpc.lib") 47#endif 48 49typedef struct { 50 PyObject_HEAD 51 mpc_t c; 52 Py_hash_t hash_cache; 53 int rc; 54 int round_mode; 55} PympcObject; 56 57static PyTypeObject Pympc_Type; 58#define Pympc_AS_MPC(obj) (((PympcObject *)(obj))->c) 59#define Pympc_Check(v) (((PyObject*)v)->ob_type == &Pympc_Type) 60 61/* 62 * Define macros for comparing with zero, checking if either component is 63 * 'nan' or 'inf', etc. 64 */ 65 66#define MPC_IS_ZERO_P(x) \ 67 (mpfr_zero_p(mpc_realref(Pympc_AS_MPC(x))) && \ 68 mpfr_zero_p(mpc_imagref(Pympc_AS_MPC(x)))) 69 70#define MPC_IS_NAN_P(x) \ 71 (mpfr_nan_p(mpc_realref(Pympc_AS_MPC(x))) || \ 72 mpfr_nan_p(mpc_imagref(Pympc_AS_MPC(x)))) 73 74#define MPC_IS_INF_P(x) \ 75 (mpfr_inf_p(mpc_realref(Pympc_AS_MPC(x))) || \ 76 mpfr_inf_p(mpc_imagref(Pympc_AS_MPC(x)))) 77 78#define MPC_IS_FINITE_P(x) \ 79 (mpfr_number_p(mpc_realref(Pympc_AS_MPC(x))) && \ 80 mpfr_number_p(mpc_imagref(Pympc_AS_MPC(x)))) 81 82/* Verify that an object is an mpc and that both components have valid exp */ 83#define Pympc_CheckAndExp(v) \ 84 (Pympc_Check(v) && \ 85 (mpfr_zero_p(mpc_realref(Pympc_AS_MPC(v))) || \ 86 (mpfr_regular_p(mpc_realref(Pympc_AS_MPC(v))) && \ 87 ((mpc_realref(Pympc_AS_MPC(v))->_mpfr_exp >= context->ctx.emin)) && \ 88 ((mpc_realref(Pympc_AS_MPC(v))->_mpfr_exp <= context->ctx.emax)) \ 89 ) \ 90 ) && \ 91 (mpfr_zero_p(mpc_imagref(Pympc_AS_MPC(v))) || \ 92 (mpfr_regular_p(mpc_imagref(Pympc_AS_MPC(v))) && \ 93 ((mpc_imagref(Pympc_AS_MPC(v))->_mpfr_exp >= context->ctx.emin)) && \ 94 ((mpc_imagref(Pympc_AS_MPC(v))->_mpfr_exp <= context->ctx.emax)) \ 95 ) \ 96 ) \ 97 ) 98 99#define MPC_CHECK_UNDERFLOW(mpct, msg) \ 100 if (MPC_IS_ZERO_P(mpct) && mpct->rc) { \ 101 context->ctx.underflow = 1; \ 102 if (context->ctx.trap_underflow) { \ 103 GMPY_UNDERFLOW(msg); \ 104 goto done; \ 105 } \ 106 } 107 108#define MPC_CHECK_OVERFLOW(mpct, msg) \ 109 if (MPC_IS_INF_P(mpct)) { \ 110 context->ctx.overflow = 1; \ 111 if (context->ctx.trap_overflow) { \ 112 GMPY_OVERFLOW(msg); \ 113 goto done; \ 114 } \ 115 } 116 117#define MPC_CHECK_INVALID(mpct, msg) \ 118 if (MPC_IS_NAN_P(mpct)) { \ 119 context->ctx.invalid = 1; \ 120 if (context->ctx.trap_invalid) { \ 121 GMPY_INVALID(msg); \ 122 goto done; \ 123 } \ 124 } 125 126#define MPC_CHECK_INEXACT(mpct, msg) \ 127 if (mpct->rc) { \ 128 context->ctx.inexact = 1; \ 129 if (context->ctx.trap_inexact) { \ 130 GMPY_INEXACT(msg); \ 131 goto done; \ 132 } \ 133 } 134 135#define MPC_CHECK_FLAGS(mpct, NAME) \ 136 MPC_CHECK_INVALID(mpct, "'mpc' invalid operation in "NAME); \ 137 MPC_CHECK_UNDERFLOW(mpct, "'mpc' underflow in "NAME); \ 138 MPC_CHECK_OVERFLOW(mpct, "'mpc' overflow in "NAME); \ 139 MPC_CHECK_INEXACT(mpct, "'mpc' inexact result in "NAME); 140 141#define MPC_SUBNORMALIZE(mpct) \ 142 if (context->ctx.subnormalize) { \ 143 int rcr, rci; \ 144 rcr = MPC_INEX_RE(mpct->rc); \ 145 rci = MPC_INEX_IM(mpct->rc); \ 146 rcr = mpfr_subnormalize(mpc_realref(mpct->c), rcr, GET_REAL_ROUND(context)); \ 147 rci = mpfr_subnormalize(mpc_imagref(mpct->c), rci, GET_IMAG_ROUND(context)); \ 148 mpct->rc = MPC_INEX(rcr, rci); \ 149 } \ 150 151#define MPC_CLEANUP(mpct, NAME) \ 152 MPC_SUBNORMALIZE(mpct); \ 153 MPC_CHECK_FLAGS(mpct, NAME); \ 154 done:\ 155 if (PyErr_Occurred()) { \ 156 Py_DECREF((PyObject*)mpct); \ 157 mpct = NULL; \ 158 } \ 159 return (PyObject*)mpct; 160 161/* 162 * Parses one, and only one, argument into "self" and converts it to an 163 * mpc. Is faster, but not as generic, as using PyArg_ParseTuple. It 164 * supports either gmpy.fname(z) or z.fname(). "self" must be decref'ed. 165 * "msg" should be an error message that includes the function name and 166 * describes the required arguments. 167 */ 168 169#define PARSE_ONE_MPC_ARGS(msg) \ 170 if(self && Pympc_Check(self)) { \ 171 if (PyTuple_GET_SIZE(args) != 0) { \ 172 TYPE_ERROR(msg); \ 173 return NULL; \ 174 } \ 175 if (Pympc_CheckAndExp(self)) { \ 176 Py_INCREF(self); \ 177 } \ 178 else { \ 179 if (!(self = (PyObject*)Pympc_From_Complex(self, 0, 0))) { \ 180 TYPE_ERROR(msg); \ 181 return NULL; \ 182 } \ 183 } \ 184 } \ 185 else { \ 186 if (PyTuple_GET_SIZE(args) != 1) { \ 187 TYPE_ERROR(msg); \ 188 return NULL; \ 189 } \ 190 self = PyTuple_GET_ITEM(args, 0);\ 191 if (Pympc_CheckAndExp(self)) { \ 192 Py_INCREF(self); \ 193 } \ 194 else { \ 195 if (!(self = (PyObject*)Pympc_From_Complex(self, 0, 0))) { \ 196 TYPE_ERROR(msg); \ 197 return NULL; \ 198 } \ 199 } \ 200 } 201 202/* 203 * Parses one, and only one, argument into "self" and converts it to an 204 * mpc. Is faster, but not as generic, as using PyArg_ParseTuple. It 205 * supports either gmpy.fname(z) or z.fname(). "self" must be decref'ed. 206 * "msg" should be an error message that includes the function name and 207 * describes the required arguments. It assumes the functions is declared 208 * as either METH_O or METH_NOARGS. It is faster than PARSE_ONE_MPFR and 209 * passing a tuple as args. 210 */ 211 212#define PARSE_ONE_MPC_OTHER(msg) \ 213 if(self && Pympc_Check(self)) { \ 214 if (Pympc_CheckAndExp(self)) { \ 215 Py_INCREF(self); \ 216 } \ 217 else { \ 218 if (!(self = (PyObject*)Pympc_From_Complex(self, 0, 0))) { \ 219 TYPE_ERROR(msg); \ 220 return NULL; \ 221 } \ 222 } \ 223 } \ 224 else { \ 225 if (Pympc_CheckAndExp(other)) { \ 226 self = other; \ 227 Py_INCREF(self); \ 228 } \ 229 else { \ 230 if (!(self = (PyObject*)Pympc_From_Complex(other, 0, 0))) { \ 231 TYPE_ERROR(msg); \ 232 return NULL; \ 233 } \ 234 } \ 235 } 236 237/* 238 * Parses two, and only two, arguments into "self" and "var" and converts 239 * them both to mpC. Is faster, but not as generic, as using PyArg_ParseTuple. 240 * It supports either gmpy.fname(f,f) or f.fname(f). "self" & "var" must be 241 * decref'ed after use. "msg" should be an error message that includes the 242 * function name and describes the required arguments. Replaces 243 * SELF_MPF_ONE_ARG_CONVERTED(var). 244 */ 245 246#define PARSE_TWO_MPC_ARGS(var, msg) \ 247 if(self && Pympc_Check(self)) { \ 248 if (PyTuple_GET_SIZE(args) != 1) { \ 249 TYPE_ERROR(msg); \ 250 return NULL; \ 251 } \ 252 self = (PyObject*)Pympc_From_Complex(self, 0, 0); \ 253 var = (PyObject*)Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0); \ 254 } \ 255 else { \ 256 if (PyTuple_GET_SIZE(args) != 2) { \ 257 TYPE_ERROR(msg); \ 258 return NULL; \ 259 } \ 260 self = (PyObject*)Pympc_From_Complex(PyTuple_GET_ITEM(args, 0), 0, 0); \ 261 var = (PyObject*)Pympc_From_Complex(PyTuple_GET_ITEM(args, 1), 0, 0); \ 262 } \ 263 if (!self || !var) { \ 264 TYPE_ERROR(msg); \ 265 Py_XDECREF((PyObject*)var); \ 266 Py_XDECREF((PyObject*)self); \ 267 return NULL; \ 268 } 269 270static PyObject * Pympc_digits(PyObject *self, PyObject *args); 271static PyObject * Pygmpy_mpc(PyObject *self, PyObject *args, PyObject *kwargs); 272static PyObject * Pympc_format(PyObject *self, PyObject *args); 273static PyObject * Pympc_abs(PyObject *self); 274static PyObject * Pympc_neg(PympcObject *self); 275static PyObject * Pympc_pos(PympcObject *self); 276static PyObject * Pympc_sqr(PyObject* self, PyObject *other); 277static PyObject * Pympc_pow(PyObject *base, PyObject *exp, PyObject *m); 278static PyObject * Pympc_conjugate(PyObject *self, PyObject *args); 279static PyObject * Pympc_getprec_attrib(PympcObject *self, void *closure); 280static PyObject * Pympc_getrc_attrib(PympcObject *self, void *closure); 281static PyObject * Pympc_getimag_attrib(PympcObject *self, void *closure); 282static PyObject * Pympc_getreal_attrib(PympcObject *self, void *closure); 283static int Pympc_nonzero(PympcObject *self); 284static PyObject * Pympc_is_NAN(PyObject *self, PyObject *other); 285static PyObject * Pympc_is_ZERO(PyObject *self, PyObject *other); 286static PyObject * Pympc_is_INF(PyObject *self, PyObject *other); 287static PyObject * Pympc_is_FINITE(PyObject *self, PyObject *other); 288static PyObject * Pympc_phase(PyObject *self, PyObject *other); 289static PyObject * Pympc_norm(PyObject *self, PyObject *other); 290static PyObject * Pympc_polar(PyObject *self, PyObject *other); 291static PyObject * Pympc_rect(PyObject *self, PyObject *args); 292static PyObject * Pympc_proj(PyObject *self, PyObject *other); 293static PyObject * Pympc_log(PyObject *self, PyObject *other); 294static PyObject * Pympc_log10(PyObject *self, PyObject *other); 295static PyObject * Pympc_exp(PyObject *self, PyObject *other); 296static PyObject * Pympc_sin(PyObject *self, PyObject *other); 297static PyObject * Pympc_cos(PyObject *self, PyObject *other); 298static PyObject * Pympc_tan(PyObject *self, PyObject *other); 299static PyObject * Pympc_sinh(PyObject *self, PyObject *other); 300static PyObject * Pympc_cosh(PyObject *self, PyObject *other); 301static PyObject * Pympc_tanh(PyObject *self, PyObject *other); 302static PyObject * Pympc_asin(PyObject *self, PyObject *other); 303static PyObject * Pympc_acos(PyObject *self, PyObject *other); 304static PyObject * Pympc_atan(PyObject *self, PyObject *other); 305static PyObject * Pympc_asinh(PyObject *self, PyObject *other); 306static PyObject * Pympc_acosh(PyObject *self, PyObject *other); 307static PyObject * Pympc_atanh(PyObject *self, PyObject *other); 308static PyObject * Pympc_sqrt(PyObject *self, PyObject *other); 309static PyObject * Pympc_sin_cos(PyObject *self, PyObject *other); 310static PyObject * Pympc_fma(PyObject *self, PyObject *args); 311static PyObject * Pympc_fms(PyObject *self, PyObject *args); 312static PyObject * Pympc_div_2exp(PyObject *self, PyObject *args); 313static PyObject * Pympc_mul_2exp(PyObject *self, PyObject *args); 314static Py_hash_t Pympc_hash(PympcObject *self); 315static PyObject * Pympc_add_fast(PyObject *x, PyObject *y); 316static PyObject * Pympc_add(PyObject *self, PyObject *args); 317static PyObject * Pympc_sub_fast(PyObject *x, PyObject *y); 318static PyObject * Pympc_sub(PyObject *self, PyObject *args); 319static PyObject * Pympc_mul_fast(PyObject *x, PyObject *y); 320static PyObject * Pympc_mul(PyObject *self, PyObject *args); 321static PyObject * Pympc_truediv_fast(PyObject *x, PyObject *y); 322#ifdef PY2 323static PyObject * Pympc_div2_fast(PyObject *x, PyObject *y); 324#endif 325static PyObject * Pympc_div(PyObject *self, PyObject *args); 326 327#ifdef __cplusplus 328} 329#endif 330#endif