PageRenderTime 40ms CodeModel.GetById 24ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/gmpy_mpc.h

http://gmpy.googlecode.com/
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