gmpy2_mpc.h
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_mpc.h * 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 #ifndef GMPY_MPC_H 28 #define GMPY_MPC_H 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 35 /* gmpy_mpc C API extension header file. 36 * 37 * Provide interface to the MPC (Multiple Precision Complex) library. 38 * 39 * Version 2.00, April 2011 (created) casevh 40 * 41 * This file is expected to be included from gmpy.h 42 */ 43 44 #if defined(MS_WIN32) && defined(_MSC_VER) 45 # pragma comment(lib,"mpc.lib") 46 #endif 47 48 static PyTypeObject MPC_Type; 49 #define MPC_Check(v) (((PyObject*)v)->ob_type == &MPC_Type) 50 51 /* 52 * Define macros for comparing with zero, checking if either component is 53 * 'nan' or 'inf', etc. Based on the macros found in mpc-impl.h. 54 */ 55 56 #define MPC_IS_ZERO_P(x) \ 57 (mpfr_zero_p(mpc_realref(MPC(x))) && \ 58 mpfr_zero_p(mpc_imagref(MPC(x)))) 59 60 #define MPC_IS_NAN_P(x) \ 61 ((mpfr_nan_p(mpc_realref(MPC(x))) && !mpfr_inf_p(mpc_imagref(MPC(x)))) || \ 62 (mpfr_nan_p(mpc_imagref(MPC(x))) && !mpfr_inf_p(mpc_realref(MPC(x))))) 63 64 #define MPC_IS_INF_P(x) \ 65 (mpfr_inf_p(mpc_realref(MPC(x))) || \ 66 mpfr_inf_p(mpc_imagref(MPC(x)))) 67 68 #define MPC_IS_FINITE_P(x) \ 69 (mpfr_number_p(mpc_realref(MPC(x))) && \ 70 mpfr_number_p(mpc_imagref(MPC(x)))) 71 72 /* V is the value that is expected to be returned. 73 * CTX is the context. 74 * NAME is prepended to the error message. 75 */ 76 77 #define GMPY_MPC_CHECK_RANGE(V, CTX) \ 78 { \ 79 int rcr, rci; \ 80 rcr = MPC_INEX_RE(V->rc); \ 81 rci = MPC_INEX_IM(V->rc); \ 82 if (mpfr_regular_p(mpc_realref(V->c)) && \ 83 (!((mpc_realref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \ 84 (mpc_realref(V->c)->_mpfr_exp <= CTX->ctx.emax)))) { \ 85 mpfr_exp_t _oldemin, _oldemax; \ 86 _oldemin = mpfr_get_emin(); \ 87 _oldemax = mpfr_get_emax(); \ 88 mpfr_set_emin(CTX->ctx.emin); \ 89 mpfr_set_emax(CTX->ctx.emax); \ 90 rcr = mpfr_check_range(mpc_realref(V->c), rcr, GET_REAL_ROUND(CTX)); \ 91 mpfr_set_emin(_oldemin); \ 92 mpfr_set_emax(_oldemax); \ 93 } \ 94 if (mpfr_regular_p(mpc_imagref(V->c)) && \ 95 (!((mpc_imagref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \ 96 (mpc_imagref(V->c)->_mpfr_exp <= CTX->ctx.emax)))) { \ 97 mpfr_exp_t _oldemin, _oldemax; \ 98 _oldemin = mpfr_get_emin(); \ 99 _oldemax = mpfr_get_emax(); \ 100 mpfr_set_emin(CTX->ctx.emin); \ 101 mpfr_set_emax(CTX->ctx.emax); \ 102 rci = mpfr_check_range(mpc_imagref(V->c), rci, GET_IMAG_ROUND(CTX)); \ 103 mpfr_set_emin(_oldemin); \ 104 mpfr_set_emax(_oldemax); \ 105 } \ 106 V->rc = MPC_INEX(rcr, rci); \ 107 } 108 109 #define GMPY_MPC_SUBNORMALIZE(V, CTX) \ 110 { \ 111 int rcr, rci; \ 112 rcr = MPC_INEX_RE(V->rc); \ 113 rci = MPC_INEX_IM(V->rc); \ 114 if (CTX->ctx.subnormalize && \ 115 (!((mpc_realref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \ 116 (mpc_realref(V->c)->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(mpc_realref(V->c)) - 2)))) { \ 117 mpfr_exp_t _oldemin, _oldemax; \ 118 _oldemin = mpfr_get_emin(); \ 119 _oldemax = mpfr_get_emax(); \ 120 mpfr_set_emin(CTX->ctx.emin); \ 121 mpfr_set_emax(CTX->ctx.emax); \ 122 rcr = mpfr_subnormalize(mpc_realref(V->c), rcr, GET_REAL_ROUND(CTX)); \ 123 mpfr_set_emin(_oldemin); \ 124 mpfr_set_emax(_oldemax); \ 125 } \ 126 if (CTX->ctx.subnormalize && \ 127 (!((mpc_imagref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \ 128 (mpc_imagref(V->c)->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(mpc_imagref(V->c)) - 2)))) { \ 129 mpfr_exp_t _oldemin, _oldemax; \ 130 _oldemin = mpfr_get_emin(); \ 131 _oldemax = mpfr_get_emax(); \ 132 mpfr_set_emin(CTX->ctx.emin); \ 133 mpfr_set_emax(CTX->ctx.emax); \ 134 rci = mpfr_check_range(mpc_imagref(V->c), rci, GET_IMAG_ROUND(CTX)); \ 135 mpfr_set_emin(_oldemin); \ 136 mpfr_set_emax(_oldemax); \ 137 } \ 138 V->rc = MPC_INEX(rcr, rci); \ 139 } 140 141 #define GMPY_MPC_EXCEPTIONS(V, CTX) \ 142 do { \ 143 int _invalid = 0, _underflow = 0, _overflow = 0, _inexact = 0; \ 144 int rcr, rci; \ 145 rcr = MPC_INEX_RE(V->rc); \ 146 rci = MPC_INEX_IM(V->rc); \ 147 if (MPC_IS_NAN_P(V)) { \ 148 CTX->ctx.invalid = 1; \ 149 _invalid = 1; \ 150 } \ 151 if (V->rc) { \ 152 CTX->ctx.inexact = 1; \ 153 _inexact = 1; \ 154 } \ 155 if ((rcr && mpfr_zero_p(mpc_realref(V->c))) || (rci && mpfr_zero_p(mpc_imagref(V->c)))) { \ 156 CTX->ctx.underflow = 1; \ 157 _underflow = 1; \ 158 } \ 159 if ((rcr && mpfr_inf_p(mpc_realref(V->c))) || (rci && mpfr_inf_p(mpc_imagref(V->c)))) { \ 160 CTX->ctx.overflow = 1; \ 161 _overflow = 1; \ 162 } \ 163 if (CTX->ctx.traps) { \ 164 if ((CTX->ctx.traps & TRAP_UNDERFLOW) && _underflow) { \ 165 GMPY_UNDERFLOW("underflow"); \ 166 Py_XDECREF((PyObject*)V); \ 167 V = NULL; \ 168 } \ 169 if ((CTX->ctx.traps & TRAP_OVERFLOW) && _overflow) { \ 170 GMPY_OVERFLOW("overflow"); \ 171 Py_XDECREF((PyObject*)V); \ 172 V = NULL; \ 173 } \ 174 if ((CTX->ctx.traps & TRAP_INEXACT) && _inexact) { \ 175 GMPY_INEXACT("inexact result"); \ 176 Py_XDECREF((PyObject*)V); \ 177 V = NULL; \ 178 } \ 179 if ((CTX->ctx.traps & TRAP_INVALID) && _invalid) { \ 180 GMPY_INVALID("invalid operation"); \ 181 Py_XDECREF((PyObject*)V); \ 182 V = NULL; \ 183 } \ 184 } \ 185 } while(0); \ 186 187 #define GMPY_MPC_CLEANUP(V, CTX) \ 188 GMPY_MPC_CHECK_RANGE(V, CTX); \ 189 GMPY_MPC_SUBNORMALIZE(V, CTX); \ 190 GMPY_MPC_EXCEPTIONS(V, CTX); \ 191 192 static void _GMPy_MPC_Cleanup(MPC_Object **v, CTXT_Object *ctext); 193 194 #ifdef __cplusplus 195 } 196 #endif 197 #endif