1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * gmpy2_macros.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 /* This file contains a collection of macros that can be used to reduce
28  * repetitive code. As new macros are written to support of refactoring,
29  * they should be placed here.
30  */
31 
32 /* NAME is used as part of the GMPy function name. It usually uses an upper-
33  *      case first character.
34  * FUNC is the component of the actual name used by MPFR and MPC.
35  *
36  * Note: the following macro can release the GIL.
37  * GMPY_MPFR_MPC_UNIOP_EXWT(NAME, FUNC) creates the following functions:
38  *     GMPy_RealWithType_NAME(x, xtype, context)
39  *     GMPy_ComplexWithType_NAME(x, xtype, context)
40  *     GMPy_Number_NAME(x, context)
41  *     GMPy_Context_NAME(self, other)
42  *     - called with METH_O
43  *
44  * Note: the following macro is only used for is_xxx tests so it does
45  *       not release the GIL.
46  * GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(NAME, FUNC) creates the following functions:
47  *     GMPy_Number_NAME(x, context)
48  *     - assumes GMPy_RealWithType_NAME & GMPy_ComplexWithType_NAME exist
49  *     GMPy_Context_NAME(self, other)
50  *     - called with METH_O
51  *
52  * GMPY_MPFR_MPC_TRIOP_EX(NAME, FUNC) creates the following functions:
53  *     GMPy_Real_NAME(x, y, Z, context)
54  *     GMPy_Complex_NAME(x, y, Z, context)
55  *     GMPy_Number_NAME(x, y, Z, context)
56  *     - assumes GMPy_Integer_NAME & GMPy_Rational_NAME also exist
57  *     GMPy_Context_NAME(self, args)
58  *     - called with METH_VARARGS
59  *
60  * GMPY_MPFR_MPC_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
61  *     GMPy_Number_NAME(x, context)
62  *     - assumes GMPy_Real_NAME & GMPy_Complex_NAME exist
63  *     GMPy_Context_NAME(self, other)
64  *     - called with METH_O
65  *
66  * GMPY_MPFR_UNIOP(NAME, FUNC) creates the following functions:
67  *     GMPy_Real_NAME(x, context)
68  *     GMPy_Number_NAME(x, context)
69  *     GMPy_Context_NAME(self, other)
70  *     - called with METH_O
71  *
72  * GMPY_MPFR_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
73  *     GMPy_Number_NAME(x, context)
74  *     - assumes GMPy_Real_NAME exists
75  *     GMPy_Context_NAME(self, other)
76  *     - called with METH_O
77  *
78  * GMPY_MPFR_BINOP(NAME, FUNC) creates the following functions:
79  *     GMPy_Real_NAME(x, y, context)
80  *     GMPy_Number_NAME(x, y, context)
81  *     GMPy_Context_NAME(self, args)
82  *     - called with METH_VARARGS
83  *
84  */
85 
86 #define GMPY_MPFR_MPC_UNIOP_EXWT(NAME, FUNC) \
87 static PyObject * \
88 GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
89 { \
90     MPFR_Object *result = NULL, *tempx = NULL; \
91     if (IS_TYPE_MPFR(xtype)) { \
92         if (!(result = GMPy_MPFR_New(0, context))) return NULL; \
93         mpfr_clear_flags(); \
94         result->rc = mpfr_##FUNC(result->f, MPFR(x), GET_MPFR_ROUND(context)); \
95         _GMPy_MPFR_Cleanup(&result, context); \
96         return (PyObject*)result; \
97     } \
98     if (IS_TYPE_REAL(xtype)) { \
99         if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) return NULL; \
100         if (!(result = GMPy_MPFR_New(0, context))) { \
101             Py_DECREF(tempx); \
102             return NULL; \
103         } \
104         mpfr_clear_flags(); \
105         result->rc = mpfr_##FUNC(result->f, MPFR(tempx), GET_MPFR_ROUND(context)); \
106         _GMPy_MPFR_Cleanup(&result, context); \
107         Py_DECREF(tempx); \
108         return (PyObject*)result; \
109     } \
110     TYPE_ERROR(#FUNC"() argument type not supported"); \
111     return NULL; \
112 } \
113 static PyObject * \
114 GMPy_ComplexWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
115 { \
116     MPC_Object *result = NULL, *tempx = NULL; \
117     if (IS_TYPE_MPC(xtype)) { \
118         if (!(result = GMPy_MPC_New(0, 0, context))) return NULL; \
119         result->rc = mpc_##FUNC(result->c, MPC(x), GET_MPC_ROUND(context)); \
120         _GMPy_MPC_Cleanup(&result, context); \
121         return (PyObject*)result; \
122     } \
123     if (IS_TYPE_COMPLEX(xtype)) { \
124         if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) return NULL; \
125         if (!(result = GMPy_MPC_New(0, 0, context))) { \
126             Py_DECREF(tempx); \
127             return NULL; \
128         } \
129         result->rc = mpc_##FUNC(result->c, MPC(tempx), GET_MPC_ROUND(context)); \
130         _GMPy_MPC_Cleanup(&result, context); \
131         Py_DECREF(tempx); \
132         return (PyObject*)result; \
133     } \
134     TYPE_ERROR(#FUNC"() argument type not supported"); \
135     return NULL; \
136 } \
137 static PyObject * \
138 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
139 { \
140     CHECK_CONTEXT(context); \
141     int xtype = GMPy_ObjectType(x);\
142     if (IS_TYPE_REAL(xtype)) \
143         return GMPy_RealWithType_##NAME(x, xtype, context); \
144     if (IS_TYPE_COMPLEX(xtype)) \
145         return GMPy_ComplexWithType_##NAME(x, xtype, context); \
146     TYPE_ERROR(#FUNC"() argument type not supported"); \
147     return NULL; \
148 } \
149 static PyObject * \
150 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
151 { \
152     CTXT_Object *context = NULL; \
153     if (self && CTXT_Check(self)) { \
154         context = (CTXT_Object*)self; \
155     } \
156     else { \
157         CHECK_CONTEXT(context); \
158     } \
159     return GMPy_Number_##NAME(other, context); \
160 }
161 
162 /*********************************************************************/
163 
164 #define GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(NAME, FUNC) \
165 static PyObject * \
166 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
167 { \
168     CHECK_CONTEXT(context); \
169     int xtype = GMPy_ObjectType(x); \
170     if (IS_TYPE_REAL(xtype)) \
171         return GMPy_RealWithType_##NAME(x, xtype, context); \
172     if (IS_TYPE_COMPLEX(xtype)) \
173         return GMPy_ComplexWithType_##NAME(x, xtype, context); \
174     TYPE_ERROR(#FUNC"() argument type not supported"); \
175     return NULL; \
176 } \
177 static PyObject * \
178 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
179 { \
180     CTXT_Object *context = NULL; \
181     if (self && CTXT_Check(self)) { \
182         context = (CTXT_Object*)self; \
183     } \
184     else { \
185         CHECK_CONTEXT(context); \
186     } \
187     return GMPy_Number_##NAME(other, context); \
188 } \
189 static PyObject * \
190 GMPy_Number_Method_##NAME(PyObject *self, PyObject *args) \
191 { \
192     return GMPy_Number_##NAME(self, NULL); \
193 } \
194 
195 /*********************************************************************/
196 
197 #define GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(NAME, FUNC) \
198 static PyObject * \
199 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
200 { \
201     CHECK_CONTEXT(context); \
202     int xtype = GMPy_ObjectType(x); \
203     if (IS_TYPE_REAL(xtype)) \
204         return GMPy_RealWithType_##NAME(x, xtype, context); \
205     if (IS_TYPE_COMPLEX(xtype)) \
206         return GMPy_ComplexWithType_##NAME(x, xtype, context); \
207     TYPE_ERROR(#FUNC"() argument type not supported"); \
208     return NULL; \
209 } \
210 static PyObject * \
211 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
212 { \
213     CTXT_Object *context = NULL; \
214     if (self && CTXT_Check(self)) { \
215         context = (CTXT_Object*)self; \
216     } \
217     else { \
218         CHECK_CONTEXT(context); \
219     } \
220     return GMPy_Number_##NAME(other, context); \
221 } \
222 
223 /*********************************************************************/
224 
225 #define GMPY_MPFR_MPC_TRIOP_TEMPLATEWT(NAME, FUNC) \
226 static PyObject * \
227 GMPy_Number_##NAME(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context) \
228 { \
229     CHECK_CONTEXT(context); \
230     int xtype = GMPy_ObjectType(x); \
231     int ytype = GMPy_ObjectType(y); \
232     int ztype = GMPy_ObjectType(z); \
233     if (IS_TYPE_MPZ(xtype) && IS_TYPE_MPZ(ytype) && IS_TYPE_MPZ(ztype)) \
234         return _GMPy_MPZ_##NAME(x, y, z, context); \
235     if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype) && IS_TYPE_MPQ(ztype)) \
236         return _GMPy_MPQ_##NAME(x, y,  z, context); \
237     if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype) && IS_TYPE_MPFR(ztype)) \
238         return _GMPy_MPFR_##NAME(x, y, z, context); \
239     if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype) && IS_TYPE_MPC(ztype)) \
240         return _GMPy_MPC_##NAME(x, y, z, context); \
241     if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype) && IS_TYPE_INTEGER(ztype)) \
242         return GMPy_IntegerWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
243     if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype) && IS_TYPE_RATIONAL(ztype)) \
244         return GMPy_RationalWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
245     if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype) && IS_TYPE_REAL(ztype)) \
246         return GMPy_RealWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
247     if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype) && IS_TYPE_COMPLEX(ztype)) \
248         return GMPy_ComplexWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
249     TYPE_ERROR(#FUNC"() argument type not supported"); \
250     return NULL; \
251 } \
252 static PyObject * \
253 GMPy_Context_##NAME(PyObject *self, PyObject *args) \
254 { \
255     CTXT_Object *context = NULL; \
256     if (PyTuple_GET_SIZE(args) != 3) { \
257         TYPE_ERROR(#FUNC"() requires 3 arguments"); \
258         return NULL; \
259     } \
260     if (self && CTXT_Check(self)) { \
261         context = (CTXT_Object*)self; \
262     } \
263     else { \
264         CHECK_CONTEXT(context); \
265     } \
266     return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), \
267                               PyTuple_GET_ITEM(args, 1), \
268                               PyTuple_GET_ITEM(args, 2), context); \
269 }
270 
271 /*********************************************************************/
272 
273 #define GMPY_MPFR_QUADOP_TEMPLATEWT(NAME, FUNC) \
274 static PyObject * \
275 GMPy_Number_##NAME(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context) \
276 { \
277     CHECK_CONTEXT(context); \
278     int xtype = GMPy_ObjectType(x); \
279     int ytype = GMPy_ObjectType(y); \
280     int ztype = GMPy_ObjectType(z); \
281     int ttype = GMPy_ObjectType(t); \
282     if (IS_TYPE_MPZ(xtype) && IS_TYPE_MPZ(ytype) && IS_TYPE_MPZ(ztype) && IS_TYPE_MPZ(ttype)) \
283         return _GMPy_MPZ_##NAME(x, y, z, t, context); \
284     if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype) && IS_TYPE_MPQ(ztype) && IS_TYPE_MPQ(ttype)) \
285         return _GMPy_MPQ_##NAME(x, y,  z, t, context); \
286     if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype) && IS_TYPE_MPFR(ztype) && IS_TYPE_MPFR(ttype)) \
287         return _GMPy_MPFR_##NAME(x, y, z, t, context); \
288     if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype) && IS_TYPE_INTEGER(ztype) && IS_TYPE_INTEGER(ttype)) \
289         return GMPy_IntegerWithType_##NAME(x, xtype, y, ytype, z, ztype, t, ttype, context); \
290     if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype) && IS_TYPE_RATIONAL(ztype) && IS_TYPE_RATIONAL(ttype)) \
291         return GMPy_RationalWithType_##NAME(x, xtype, y, ytype, z, ztype, t, ttype, context); \
292     if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype) && IS_TYPE_REAL(ztype) && IS_TYPE_REAL(ttype)) \
293         return GMPy_RealWithType_##NAME(x, xtype, y, ytype, z, ztype, t, ttype, context); \
294     TYPE_ERROR(#FUNC"() argument type not supported"); \
295     return NULL; \
296 } \
297 static PyObject * \
298 GMPy_Context_##NAME(PyObject *self, PyObject *args) \
299 { \
300     CTXT_Object *context = NULL; \
301     if (PyTuple_GET_SIZE(args) != 4) { \
302         TYPE_ERROR(#FUNC"() requires 4 arguments"); \
303         return NULL; \
304     } \
305     if (self && CTXT_Check(self)) { \
306         context = (CTXT_Object*)self; \
307     } \
308     else { \
309         CHECK_CONTEXT(context); \
310     } \
311     return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), \
312                               PyTuple_GET_ITEM(args, 1), \
313                               PyTuple_GET_ITEM(args, 2), \
314                               PyTuple_GET_ITEM(args, 3), context); \
315 }
316 
317 /*********************************************************************/
318 
319 #define GMPY_MPFR_UNIOP_NOROUNDWT(NAME, FUNC) \
320 static PyObject * \
321 GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
322 { \
323     MPFR_Object *result = NULL, *tempx = NULL; \
324     result = GMPy_MPFR_New(0, context); \
325     tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
326     if (!result || !tempx) { \
327         Py_XDECREF((PyObject*)result); \
328         Py_XDECREF((PyObject*)tempx); \
329         return NULL; \
330     } \
331     mpfr_clear_flags(); \
332     result->rc = mpfr_##FUNC(result->f, tempx->f); \
333     Py_DECREF((PyObject*)tempx); \
334     _GMPy_MPFR_Cleanup(&result, context); \
335     return (PyObject*)result; \
336 } \
337 static PyObject * \
338 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
339 { \
340     int xtype = GMPy_ObjectType(x); \
341     if (IS_TYPE_REAL(xtype)) \
342         return GMPy_RealWithType_##NAME(x, xtype, context); \
343     TYPE_ERROR(#FUNC"() argument type not supported"); \
344     return NULL; \
345 } \
346 static PyObject * \
347 GMPy_MPFR_Method_##NAME(PyObject *self, PyObject *other) \
348 { \
349     CTXT_Object *context = NULL; \
350     CHECK_CONTEXT(context); \
351     return GMPy_Number_##NAME(self, context); \
352 }\
353 static PyObject * \
354 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
355 { \
356     CTXT_Object *context = NULL; \
357     if (self && CTXT_Check(self)) { \
358         context = (CTXT_Object*)self; \
359     } \
360     else { \
361         CHECK_CONTEXT(context); \
362     } \
363     return GMPy_Number_##NAME(other, context); \
364 }
365 
366 /*********************************************************************/
367 
368 #define GMPY_MPFR_UNIOP_NOROUND_NOMETHODWT(NAME, FUNC) \
369 static PyObject * \
370 GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
371 { \
372     MPFR_Object *result = NULL, *tempx = NULL; \
373     result = GMPy_MPFR_New(0, context); \
374     tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
375     if (!result || !tempx) { \
376         Py_XDECREF((PyObject*)result); \
377         Py_XDECREF((PyObject*)tempx); \
378         return NULL; \
379     } \
380     mpfr_clear_flags(); \
381     result->rc = mpfr_##FUNC(result->f, tempx->f); \
382     Py_DECREF((PyObject*)tempx); \
383     _GMPy_MPFR_Cleanup(&result, context); \
384     return (PyObject*)result; \
385 } \
386 static PyObject * \
387 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
388 { \
389     int xtype = GMPy_ObjectType(x); \
390     if (IS_TYPE_REAL(xtype)) \
391         return GMPy_RealWithType_##NAME(x, xtype, context); \
392     TYPE_ERROR(#FUNC"() argument type not supported"); \
393     return NULL; \
394 } \
395 static PyObject * \
396 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
397 { \
398     CTXT_Object *context = NULL; \
399     if (self && CTXT_Check(self)) { \
400         context = (CTXT_Object*)self; \
401     } \
402     else { \
403         CHECK_CONTEXT(context); \
404     } \
405     return GMPy_Number_##NAME(other, context); \
406 }
407 
408 /*********************************************************************/
409 
410 #define GMPY_MPFR_UNIOP_EXWT(NAME, FUNC) \
411 static PyObject * \
412 GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
413 { \
414     MPFR_Object *result = NULL, *tempx = NULL; \
415     if (IS_TYPE_MPFR(xtype)) { \
416         if (!(result = GMPy_MPFR_New(0, context))) return NULL; \
417         mpfr_clear_flags(); \
418         result->rc = mpfr_##FUNC(result->f, MPFR(x), GET_MPFR_ROUND(context)); \
419         _GMPy_MPFR_Cleanup(&result, context); \
420         return (PyObject*)result; \
421     } \
422     if (IS_TYPE_REAL(xtype)) { \
423         if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) return NULL; \
424         if (!(result = GMPy_MPFR_New(0, context))) { \
425             Py_DECREF(tempx); \
426             return NULL; \
427         } \
428         mpfr_clear_flags(); \
429         result->rc = mpfr_##FUNC(result->f, MPFR(tempx), GET_MPFR_ROUND(context)); \
430         Py_DECREF(tempx); \
431         _GMPy_MPFR_Cleanup(&result, context); \
432         return (PyObject*)result; \
433     } \
434     TYPE_ERROR(#FUNC"() argument type not supported"); \
435     return NULL; \
436 } \
437 static PyObject * \
438 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
439 { \
440     CHECK_CONTEXT(context); \
441     int xtype = GMPy_ObjectType(x);\
442     if (IS_TYPE_REAL(xtype)) \
443         return GMPy_RealWithType_##NAME(x, xtype, context); \
444     TYPE_ERROR(#FUNC"() argument type not supported"); \
445     return NULL; \
446 } \
447 static PyObject * \
448 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
449 { \
450     CTXT_Object *context = NULL; \
451     if (self && CTXT_Check(self)) { \
452         context = (CTXT_Object*)self; \
453     } \
454     else { \
455         CHECK_CONTEXT(context); \
456     } \
457     return GMPy_Number_##NAME(other, context); \
458 }
459 
460 /*********************************************************************/
461 
462 #define GMPY_MPFR_UNIOP_TEMPLATEWT(NAME, FUNC) \
463 static PyObject * \
464 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
465 { \
466     CHECK_CONTEXT(context); \
467     int xtype = GMPy_ObjectType(x);\
468     if (IS_TYPE_REAL(xtype)) \
469         return GMPy_RealWithType_##NAME(x, xtype, context); \
470     TYPE_ERROR(#FUNC"() argument type not supported"); \
471     return NULL; \
472 } \
473 static PyObject * \
474 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
475 { \
476     CTXT_Object *context = NULL; \
477     if (self && CTXT_Check(self)) { \
478         context = (CTXT_Object*)self; \
479     } \
480     else { \
481         CHECK_CONTEXT(context); \
482     } \
483     return GMPy_Number_##NAME(other, context); \
484 }
485 
486 /*********************************************************************/
487 
488 #define GMPY_MPFR_UNIOP_TEMPLATE_EXWT(NAME, FUNC) \
489 static PyObject * \
490 GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
491 { \
492     if (MPFR_Check(x)) \
493         return _GMPy_MPFR_##NAME(x, context); \
494     if (IS_REAL(x)) \
495         return GMPy_Real_##NAME(x, context); \
496     TYPE_ERROR(#FUNC"() argument type not supported"); \
497     return NULL; \
498 } \
499 static PyObject * \
500 GMPy_Context_##NAME(PyObject *self, PyObject *other) \
501 { \
502     CTXT_Object *context = NULL; \
503     if (self && CTXT_Check(self)) { \
504         context = (CTXT_Object*)self; \
505     } \
506     else { \
507         CHECK_CONTEXT(context); \
508     } \
509     return GMPy_Number_##NAME(other, context); \
510 }
511 
512 /*********************************************************************/
513 
514 #define GMPY_MPFR_BINOPWT(NAME, FUNC) \
515 static PyObject * \
516 GMPy_RealWithType_##NAME(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context) \
517 { \
518     MPFR_Object *result = NULL, *tempx = NULL, *tempy = NULL; \
519     tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
520     tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context); \
521     result = GMPy_MPFR_New(0, context); \
522     if (!result || !tempx || !tempy) { \
523         Py_XDECREF((PyObject*)tempx); \
524         Py_XDECREF((PyObject*)tempy); \
525         Py_XDECREF((PyObject*)result); \
526         return NULL; \
527     } \
528     mpfr_clear_flags(); \
529     result->rc = mpfr_##FUNC(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context)); \
530     Py_DECREF((PyObject*)tempx); \
531     Py_DECREF((PyObject*)tempy); \
532     _GMPy_MPFR_Cleanup(&result, context); \
533     return (PyObject*)result; \
534 } \
535 static PyObject * \
536 GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
537 { \
538     int xtype = GMPy_ObjectType(x); \
539     int ytype = GMPy_ObjectType(y); \
540     CHECK_CONTEXT(context); \
541     if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) \
542         return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
543     TYPE_ERROR(#FUNC"() argument type not supported"); \
544     return NULL; \
545 } \
546 static PyObject * \
547 GMPy_Context_##NAME(PyObject *self, PyObject *args) \
548 { \
549     CTXT_Object *context = NULL; \
550     if (PyTuple_GET_SIZE(args) != 2) { \
551         TYPE_ERROR(#FUNC"() requires 2 arguments"); \
552         return NULL; \
553     } \
554     if (self && CTXT_Check(self)) { \
555         context = (CTXT_Object*)self; \
556     } \
557     else { \
558         CHECK_CONTEXT(context); \
559     } \
560     return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
561 } \
562 
563 /* Macro to support functions that require ('mpfr', 'int').
564  * More precisely, the first argument must pass IS_REAL() and the second
565  * argument must pass IS_INTEGER(). The calling sequence passes n first
566  * to the MPFR library.*/
567 
568 /*********************************************************************/
569 
570 #define GMPY_MPFR_BINOP_REAL_LONGWT(NAME, FUNC) \
571 static PyObject * \
572 GMPy_RealWithType_##NAME(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context) \
573 { \
574     MPFR_Object *result = NULL, *tempx = NULL; \
575     long n; \
576     result = GMPy_MPFR_New(0, context); \
577     tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
578     n = GMPy_Integer_AsLongWithType(y, ytype); \
579     if (!result || !tempx || (n == -1 && PyErr_Occurred())) { \
580         Py_XDECREF((PyObject*)tempx); \
581         Py_XDECREF((PyObject*)result); \
582         return NULL; \
583     } \
584     mpfr_clear_flags(); \
585     result->rc = mpfr_##FUNC(result->f, n, tempx->f, GET_MPFR_ROUND(context)); \
586     Py_DECREF((PyObject*)tempx); \
587     _GMPy_MPFR_Cleanup(&result, context); \
588     return (PyObject*)result; \
589 } \
590 static PyObject * \
591 GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
592 { \
593     int xtype = GMPy_ObjectType(x); \
594     int ytype = GMPy_ObjectType(y); \
595     CHECK_CONTEXT(context); \
596     if (IS_TYPE_REAL(xtype) && IS_TYPE_INTEGER(ytype)) \
597         return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
598     TYPE_ERROR(#FUNC"() argument type not supported"); \
599     return NULL; \
600 } \
601 static PyObject * \
602 GMPy_Context_##NAME(PyObject *self, PyObject *args) \
603 { \
604     CTXT_Object *context = NULL; \
605     if (PyTuple_GET_SIZE(args) != 2) { \
606         TYPE_ERROR(#FUNC"() requires 2 arguments"); \
607         return NULL; \
608     } \
609     if (self && CTXT_Check(self)) { \
610         context = (CTXT_Object*)self; \
611     } \
612     else { \
613         CHECK_CONTEXT(context); \
614     } \
615     return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
616 } \
617 
618 /*********************************************************************/
619 
620 #define GMPY_MPFR_BINOP_TEMPLATEWT(NAME, FUNC) \
621 static PyObject * \
622 GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
623 { \
624     int xtype = GMPy_ObjectType(x); \
625     int ytype = GMPy_ObjectType(y); \
626     CHECK_CONTEXT(context); \
627     if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) \
628         return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
629     TYPE_ERROR(#FUNC"() argument type not supported"); \
630     return NULL; \
631 } \
632 static PyObject * \
633 GMPy_Context_##NAME(PyObject *self, PyObject *args) \
634 { \
635     CTXT_Object *context = NULL; \
636     if (PyTuple_GET_SIZE(args) != 2) { \
637         TYPE_ERROR(#FUNC"() requires 2 arguments"); \
638         return NULL; \
639     } \
640     if (self && CTXT_Check(self)) { \
641         context = (CTXT_Object*)self; \
642     } \
643     else { \
644         CHECK_CONTEXT(context); \
645     } \
646     return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
647 } \
648 
649 /*********************************************************************/
650 
651 #define GMPY_MPFR_BINOP_EXWT(NAME, FUNC) \
652 static PyObject * \
653 GMPy_RealWithType_##NAME(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context) \
654 { \
655     MPFR_Object *result = NULL, *tempx = NULL, *tempy = NULL; \
656     CHECK_CONTEXT(context); \
657     tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
658     tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context); \
659     result = GMPy_MPFR_New(0, context); \
660     if (!tempx || !tempy || !result) { \
661         Py_XDECREF(tempx); \
662         Py_XDECREF(tempy); \
663         Py_XDECREF(result); \
664         return NULL; \
665     } \
666     mpfr_clear_flags(); \
667     result->rc = mpfr_##FUNC(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context)); \
668     Py_DECREF(tempx); \
669     Py_DECREF(tempy); \
670     _GMPy_MPFR_Cleanup(&result, context); \
671     return (PyObject*)result; \
672 } \
673 static PyObject * \
674 GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
675 { \
676     int xtype = GMPy_ObjectType(x); \
677     int ytype = GMPy_ObjectType(y); \
678     CHECK_CONTEXT(context); \
679     if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) \
680         return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
681     TYPE_ERROR(#FUNC"() argument type not supported"); \
682     return NULL; \
683 } \
684 static PyObject * \
685 GMPy_Context_##NAME(PyObject *self, PyObject *args) \
686 { \
687     CTXT_Object *context = NULL; \
688     if (PyTuple_GET_SIZE(args) != 2) { \
689         TYPE_ERROR(#FUNC"() requires 2 arguments"); \
690         return NULL; \
691     } \
692     if (self && CTXT_Check(self)) { \
693         context = (CTXT_Object*)self; \
694     } \
695     else { \
696         CHECK_CONTEXT(context); \
697     } \
698     return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
699 }
700