gmpy2_mpfr.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_mpfr.c * 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 28 /* General purpose functions are defined here. They are used as an alternative 29 * to code bloat via macro overuse. 30 */ 31 32 static void 33 _GMPy_MPFR_Cleanup(MPFR_Object **v, CTXT_Object *ctext) 34 { 35 /* GMPY_MPFR_CHECK_RANGE(V, CTX) */ 36 if (mpfr_regular_p((*v)->f) && 37 (!(((*v)->f->_mpfr_exp >= ctext->ctx.emin) && 38 ((*v)->f->_mpfr_exp <= ctext->ctx.emax)))) { 39 mpfr_exp_t _oldemin, _oldemax; 40 _oldemin = mpfr_get_emin(); 41 _oldemax = mpfr_get_emax(); 42 mpfr_set_emin(ctext->ctx.emin); 43 mpfr_set_emax(ctext->ctx.emax); \ 44 (*v)->rc = mpfr_check_range((*v)->f, (*v)->rc, GET_MPFR_ROUND(ctext)); 45 mpfr_set_emin(_oldemin); 46 mpfr_set_emax(_oldemax); 47 } 48 49 /* GMPY_MPFR_SUBNORMALIZE(V, CTX) */ 50 if (ctext->ctx.subnormalize && 51 (*v)->f->_mpfr_exp >= ctext->ctx.emin && 52 (*v)->f->_mpfr_exp <= ctext->ctx.emin + mpfr_get_prec((*v)->f) - 2) { 53 mpfr_exp_t _oldemin, _oldemax; 54 _oldemin = mpfr_get_emin(); 55 _oldemax = mpfr_get_emax(); 56 mpfr_set_emin(ctext->ctx.emin); 57 mpfr_set_emax(ctext->ctx.emax); 58 (*v)->rc = mpfr_subnormalize((*v)->f, (*v)->rc, GET_MPFR_ROUND(ctext)); 59 mpfr_set_emin(_oldemin); 60 mpfr_set_emax(_oldemax); 61 } 62 63 /* GMPY_MPFR_EXCEPTIONS(V, CTX) */ 64 ctext->ctx.underflow |= mpfr_underflow_p(); 65 ctext->ctx.overflow |= mpfr_overflow_p(); 66 ctext->ctx.invalid |= mpfr_nanflag_p(); 67 ctext->ctx.inexact |= mpfr_inexflag_p(); 68 ctext->ctx.divzero |= mpfr_divby0_p(); 69 if (ctext->ctx.traps) { 70 if ((ctext->ctx.traps & TRAP_UNDERFLOW) && mpfr_underflow_p()) { 71 PyErr_SetString(GMPyExc_Underflow, "underflow"); 72 Py_XDECREF((PyObject*)(*v)); 73 (*v) = NULL; 74 } 75 if ((ctext->ctx.traps & TRAP_OVERFLOW) && mpfr_overflow_p()) { 76 PyErr_SetString(GMPyExc_Overflow, "overflow"); 77 Py_XDECREF((PyObject*)(*v)); 78 (*v) = NULL; 79 } 80 if ((ctext->ctx.traps & TRAP_INEXACT) && mpfr_inexflag_p()) { 81 PyErr_SetString(GMPyExc_Inexact, "inexact result"); 82 Py_XDECREF((PyObject*)(*v)); 83 (*v) = NULL; 84 } 85 if ((ctext->ctx.traps & TRAP_INVALID) && mpfr_nanflag_p()) { 86 PyErr_SetString(GMPyExc_Invalid, "invalid operation"); 87 Py_XDECREF((PyObject*)(*v)); 88 (*v) = NULL; 89 } 90 if ((ctext->ctx.traps & TRAP_DIVZERO) && mpfr_divby0_p()) { 91 PyErr_SetString(GMPyExc_DivZero, "division by zero"); 92 Py_XDECREF((PyObject*)(*v)); 93 (*v) = NULL; 94 } 95 } 96 } 97 98 PyDoc_STRVAR(GMPy_doc_mpfr, 99 "mpfr() -> mpfr(0.0)\n\n" 100 " If no argument is given, return mpfr(0.0).\n\n" 101 "mpfr(n [, precision=0 [, context]]) -> mpfr\n\n" 102 " Return an 'mpfr' object after converting a numeric value. See\n" 103 " below for the interpretation of precision.\n\n" 104 "mpfr(s [, precision=0 [, base=0 [, context]]]) -> mpfr\n\n" 105 " Return a new 'mpfr' object by converting a string s made of\n" 106 " digits in the given base, possibly with fraction-part (with a\n" 107 " period as a separator) and/or exponent-part (with an exponent\n" 108 " marker 'e' for base<=10, else '@'). The base of the string\n" 109 " representation must be 0 or in the interval [2,62]. If the base\n" 110 " is 0, the leading digits of the string are used to identify the\n" 111 " base: 0b implies base=2, 0x implies base=16, otherwise base=10\n" 112 " is assumed.\n\n" 113 "Note: If a precision greater than or equal to 2 is specified, then it\n" 114 " is used.\n\n" 115 " A precision of 0 (the default) implies the precision of either\n" 116 " the specified context or the current context is used.\n\n" 117 " A precision of 1 minimizes the loss of precision by following\n" 118 " these rules:\n" 119 " 1) If n is a radix-2 floating point number, then the full\n" 120 " precision of n is retained.\n" 121 " 2) If n is an integer, then the precision is the bit length\n" 122 " of the integer.\n" ); 123 124 #ifdef PY3 125 static PyNumberMethods mpfr_number_methods = 126 { 127 (binaryfunc) GMPy_Number_Add_Slot, /* nb_add */ 128 (binaryfunc) GMPy_Number_Sub_Slot, /* nb_subtract */ 129 (binaryfunc) GMPy_Number_Mul_Slot, /* nb_multiply */ 130 (binaryfunc) GMPy_Number_Mod_Slot, /* nb_remainder */ 131 (binaryfunc) GMPy_Number_DivMod_Slot, /* nb_divmod */ 132 (ternaryfunc) GMPy_Number_Pow_Slot, /* nb_power */ 133 (unaryfunc) GMPy_MPFR_Minus_Slot, /* nb_negative */ 134 (unaryfunc) GMPy_MPFR_Plus_Slot, /* nb_positive */ 135 (unaryfunc) GMPy_MPFR_Abs_Slot, /* nb_absolute */ 136 (inquiry) GMPy_MPFR_NonZero_Slot, /* nb_bool */ 137 0, /* nb_invert */ 138 0, /* nb_lshift */ 139 0, /* nb_rshift */ 140 0, /* nb_and */ 141 0, /* nb_xor */ 142 0, /* nb_or */ 143 (unaryfunc) GMPy_MPFR_Int_Slot, /* nb_int */ 144 0, /* nb_reserved */ 145 (unaryfunc) GMPy_MPFR_Float_Slot, /* nb_float */ 146 0, /* nb_inplace_add */ 147 0, /* nb_inplace_subtract */ 148 0, /* nb_inplace_multiply */ 149 0, /* nb_inplace_remainder */ 150 0, /* nb_inplace_power */ 151 0, /* nb_inplace_lshift */ 152 0, /* nb_inplace_rshift */ 153 0, /* nb_inplace_and */ 154 0, /* nb_inplace_xor */ 155 0, /* nb_inplace_or */ 156 (binaryfunc) GMPy_Number_FloorDiv_Slot, /* nb_floor_divide */ 157 (binaryfunc) GMPy_Number_TrueDiv_Slot, /* nb_true_divide */ 158 0, /* nb_inplace_floor_divide */ 159 0, /* nb_inplace_true_divide */ 160 0, /* nb_index */ 161 }; 162 #else 163 static PyNumberMethods mpfr_number_methods = 164 { 165 (binaryfunc) GMPy_Number_Add_Slot, /* nb_add */ 166 (binaryfunc) GMPy_Number_Sub_Slot, /* nb_subtract */ 167 (binaryfunc) GMPy_Number_Mul_Slot, /* nb_multiply */ 168 (binaryfunc) GMPy_Number_TrueDiv_Slot, /* nb_divide */ 169 (binaryfunc) GMPy_Number_Mod_Slot, /* nb_remainder */ 170 (binaryfunc) GMPy_Number_DivMod_Slot, /* nb_divmod */ 171 (ternaryfunc) GMPy_Number_Pow_Slot, /* nb_power */ 172 (unaryfunc) GMPy_MPFR_Minus_Slot, /* nb_negative */ 173 (unaryfunc) GMPy_MPFR_Plus_Slot, /* nb_positive */ 174 (unaryfunc) GMPy_MPFR_Abs_Slot, /* nb_absolute */ 175 (inquiry) GMPy_MPFR_NonZero_Slot, /* nb_bool */ 176 0, /* nb_invert */ 177 0, /* nb_lshift */ 178 0, /* nb_rshift */ 179 0, /* nb_and */ 180 0, /* nb_xor */ 181 0, /* nb_or */ 182 0, /* nb_coerce */ 183 (unaryfunc) GMPy_MPFR_Int_Slot, /* nb_int */ 184 (unaryfunc) GMPy_MPFR_Long_Slot, /* nb_long */ 185 (unaryfunc) GMPy_MPFR_Float_Slot, /* nb_float */ 186 0, /* nb_oct */ 187 0, /* nb_hex */ 188 0, /* nb_inplace_add */ 189 0, /* nb_inplace_subtract */ 190 0, /* nb_inplace_multiply */ 191 0, /* nb_inplace_divide */ 192 0, /* nb_inplace_remainder */ 193 0, /* nb_inplace_power */ 194 0, /* nb_inplace_lshift */ 195 0, /* nb_inplace_rshift */ 196 0, /* nb_inplace_and */ 197 0, /* nb_inplace_xor */ 198 0, /* nb_inplace_or */ 199 (binaryfunc) GMPy_Number_FloorDiv_Slot, /* nb_floor_divide */ 200 (binaryfunc) GMPy_Number_TrueDiv_Slot, /* nb_true_divide */ 201 0, /* nb_inplace_floor_divide */ 202 0, /* nb_inplace_true_divide */ 203 }; 204 #endif 205 206 static PyGetSetDef Pympfr_getseters[] = 207 { 208 {"precision", (getter)GMPy_MPFR_GetPrec_Attrib, NULL, "precision in bits", NULL}, 209 {"rc", (getter)GMPy_MPFR_GetRc_Attrib, NULL, "return code", NULL}, 210 {"imag", (getter)GMPy_MPFR_GetImag_Attrib, NULL, "imaginary component", NULL}, 211 {"real", (getter)GMPy_MPFR_GetReal_Attrib, NULL, "real component", NULL}, 212 {NULL} 213 }; 214 215 static PyMethodDef Pympfr_methods [] = 216 { 217 { "__ceil__", GMPy_MPFR_Method_Ceil, METH_NOARGS, GMPy_doc_mpfr_ceil_method }, 218 { "__floor__", GMPy_MPFR_Method_Floor, METH_NOARGS, GMPy_doc_mpfr_floor_method }, 219 { "__format__", GMPy_MPFR_Format, METH_VARARGS, GMPy_doc_mpfr_format }, 220 { "__round__", GMPy_MPFR_Method_Round10, METH_VARARGS, GMPy_doc_method_round10 }, 221 { "__sizeof__", GMPy_MPFR_SizeOf_Method, METH_NOARGS, GMPy_doc_mpfr_sizeof_method }, 222 { "__trunc__", GMPy_MPFR_Method_Trunc, METH_NOARGS, GMPy_doc_mpfr_trunc_method }, 223 { "as_integer_ratio", GMPy_MPFR_Integer_Ratio_Method, METH_NOARGS, GMPy_doc_method_integer_ratio }, 224 { "as_mantissa_exp", GMPy_MPFR_Mantissa_Exp_Method, METH_NOARGS, GMPy_doc_method_mantissa_exp }, 225 { "as_simple_fraction", (PyCFunction)GMPy_MPFR_Simple_Fraction_Method, METH_VARARGS | METH_KEYWORDS, GMPy_doc_method_simple_fraction }, 226 { "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate }, 227 { "digits", GMPy_MPFR_Digits_Method, METH_VARARGS, GMPy_doc_mpfr_digits_method }, 228 { "is_finite", GMPy_MPFR_Is_Finite_Method, METH_NOARGS, GMPy_doc_method_is_finite }, 229 { "is_infinite", GMPy_MPFR_Is_Infinite_Method, METH_NOARGS, GMPy_doc_method_is_infinite }, 230 { "is_integer", GMPy_MPFR_Is_Integer_Method, METH_NOARGS, GMPy_doc_method_is_integer }, 231 { "is_nan", GMPy_MPFR_Is_NAN_Method, METH_NOARGS, GMPy_doc_method_is_nan }, 232 { "is_signed", GMPy_MPFR_Is_Regular_Method, METH_NOARGS, GMPy_doc_method_is_regular }, 233 { "is_signed", GMPy_MPFR_Is_Signed_Method, METH_NOARGS, GMPy_doc_method_is_signed }, 234 { "is_zero", GMPy_MPFR_Is_Zero_Method, METH_NOARGS, GMPy_doc_method_is_zero }, 235 { NULL, NULL, 1 } 236 }; 237 238 static PyTypeObject MPFR_Type = 239 { 240 /* PyObject_HEAD_INIT(&PyType_Type) */ 241 #ifdef PY3 242 PyVarObject_HEAD_INIT(NULL, 0) 243 #else 244 PyObject_HEAD_INIT(0) 245 0, /* ob_size */ 246 #endif 247 "mpfr", /* tp_name */ 248 sizeof(MPFR_Object), /* tp_basicsize */ 249 0, /* tp_itemsize */ 250 /* methods */ 251 (destructor) GMPy_MPFR_Dealloc, /* tp_dealloc */ 252 0, /* tp_print */ 253 0, /* tp_getattr */ 254 0, /* tp_setattr */ 255 0, /* tp_reserved */ 256 (reprfunc) GMPy_MPFR_Repr_Slot, /* tp_repr */ 257 &mpfr_number_methods, /* tp_as_number */ 258 0, /* tp_as_sequence */ 259 0, /* tp_as_mapping */ 260 (hashfunc) GMPy_MPFR_Hash_Slot, /* tp_hash */ 261 0, /* tp_call */ 262 (reprfunc) GMPy_MPFR_Str_Slot, /* tp_str */ 263 (getattrofunc) 0, /* tp_getattro */ 264 (setattrofunc) 0, /* tp_setattro */ 265 0, /* tp_as_buffer */ 266 #ifdef PY3 267 Py_TPFLAGS_DEFAULT, /* tp_flags */ 268 #else 269 Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */ 270 #endif 271 GMPy_doc_mpfr, /* tp_doc */ 272 0, /* tp_traverse */ 273 0, /* tp_clear */ 274 (richcmpfunc)&GMPy_RichCompare_Slot, /* tp_richcompare */ 275 0, /* tp_weaklistoffset*/ 276 0, /* tp_iter */ 277 0, /* tp_iternext */ 278 Pympfr_methods, /* tp_methods */ 279 0, /* tp_members */ 280 Pympfr_getseters, /* tp_getset */ 281 0, /* tp_base */ 282 0, /* tp_dict */ 283 0, /* tp_descr_get */ 284 0, /* tp_descr_set */ 285 0, /* tp_dictoffset */ 286 0, /* tp_init */ 287 0, /* tp_alloc */ 288 GMPy_MPFR_NewInit, /* tp_new */ 289 0, /* tp_free */ 290 }; 291