/ src / gmpy2_mpc.h
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