gmpy2_mul.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_mul.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 /* This file implements the * operator, gmpy2.mul() and context.mul(). 28 */ 29 30 /* Multiply two Integer objects (see gmpy2_convert.c). If an error occurs, 31 * NULL is returned and an exception is set. If either x or y can't be 32 * converted into an mpz, Py_NotImplemented is returned. */ 33 34 static PyObject * 35 GMPy_Integer_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, 36 CTXT_Object *context) 37 { 38 MPZ_Object *result = NULL; 39 40 if (!(result = GMPy_MPZ_New(context))) { 41 /* LCOV_EXCL_START */ 42 return NULL; 43 /* LCOV_EXCL_STOP */ 44 } 45 46 if (IS_TYPE_MPZANY(xtype)) { 47 if (IS_TYPE_MPZANY(ytype)) { 48 mpz_mul(result->z, MPZ(x), MPZ(y)); 49 return (PyObject*)result; 50 } 51 52 if (IS_TYPE_PyInteger(ytype)) { 53 int error; 54 long temp = PyLong_AsLongAndOverflow(y, &error); 55 56 if (!error) { 57 mpz_mul_si(result->z, MPZ(x), temp); 58 } 59 else { 60 mpz_set_PyIntOrLong(result->z, y); 61 mpz_mul(result->z, MPZ(x), result->z); 62 } 63 return (PyObject*)result; 64 } 65 } 66 67 if (IS_TYPE_MPZANY(ytype)) { 68 if (IS_TYPE_PyInteger(xtype)) { 69 int error; 70 long temp = PyLong_AsLongAndOverflow(x, &error); 71 72 if (!error) { 73 mpz_mul_si(result->z, MPZ(y), temp); 74 } 75 else { 76 mpz_set_PyIntOrLong(result->z, x); 77 mpz_mul(result->z, result->z, MPZ(y)); 78 } 79 return (PyObject*)result; 80 } 81 } 82 83 if (IS_TYPE_INTEGER(xtype) && (IS_TYPE_INTEGER(ytype))) { 84 MPZ_Object *tempx = NULL, *tempy = NULL; 85 86 if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) || 87 !(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) { 88 /* LCOV_EXCL_START */ 89 Py_XDECREF((PyObject*)tempx); 90 Py_XDECREF((PyObject*)tempy); 91 Py_DECREF((PyObject*)result); 92 return NULL; 93 /* LCOV_EXCL_STOP */ 94 } 95 96 mpz_mul(result->z, tempx->z, tempy->z); 97 Py_DECREF((PyObject*)tempx); 98 Py_DECREF((PyObject*)tempy); 99 return (PyObject*)result; 100 } 101 102 Py_DECREF((PyObject*)result); 103 TYPE_ERROR("mul() argument type not supported"); 104 return NULL; 105 } 106 107 static PyObject * 108 GMPy_Rational_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, 109 CTXT_Object *context) 110 { 111 MPQ_Object *result = NULL; 112 113 if (!(result = GMPy_MPQ_New(context))) { 114 /* LCOV_EXCL_START */ 115 return NULL; 116 /* LCOV_EXCL_STOP */ 117 } 118 119 if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype)) { 120 mpq_mul(result->q, MPQ(x), MPQ(y)); 121 return (PyObject*)result; 122 } 123 124 if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) { 125 MPQ_Object *tempx = NULL, *tempy = NULL; 126 127 if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) || 128 !(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) { 129 /* LCOV_EXCL_START */ 130 Py_XDECREF((PyObject*)tempx); 131 Py_XDECREF((PyObject*)tempy); 132 Py_DECREF((PyObject*)result); 133 return NULL; 134 /* LCOV_EXCL_STOP */ 135 } 136 137 mpq_mul(result->q, tempx->q, tempy->q); 138 Py_DECREF((PyObject*)tempx); 139 Py_DECREF((PyObject*)tempy); 140 return (PyObject*)result; 141 } 142 143 Py_DECREF((PyObject*)result); 144 TYPE_ERROR("mul() argument type not supported"); 145 return NULL; 146 } 147 148 static PyObject * 149 GMPy_Real_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, 150 CTXT_Object *context) 151 { 152 MPFR_Object *result = NULL; 153 154 CHECK_CONTEXT(context); 155 156 if (!(result = GMPy_MPFR_New(0, context))) { 157 /* LCOV_EXCL_START */ 158 return NULL; 159 /* LCOV_EXCL_STOP */ 160 } 161 162 if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype)) { 163 mpfr_clear_flags(); 164 result->rc = mpfr_mul(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context)); 165 _GMPy_MPFR_Cleanup(&result, context); 166 return (PyObject*)result; 167 } 168 169 if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) { 170 MPFR_Object *tempx = NULL, *tempy = NULL; 171 172 if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) || 173 !(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) { 174 /* LCOV_EXCL_START */ 175 Py_XDECREF((PyObject*)tempx); 176 Py_XDECREF((PyObject*)tempy); 177 Py_DECREF((PyObject*)result); 178 return NULL; 179 /* LCOV_EXCL_STOP */ 180 } 181 182 mpfr_clear_flags(); 183 result->rc = mpfr_mul(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context)); 184 Py_DECREF((PyObject*)tempx); 185 Py_DECREF((PyObject*)tempy); 186 _GMPy_MPFR_Cleanup(&result, context); 187 return (PyObject*)result; 188 } 189 190 Py_DECREF((PyObject*)result); 191 TYPE_ERROR("mul() argument type not supported"); 192 return NULL; 193 } 194 195 /* GMPy_Complex_Mul(x, y, context) returns x*y using the provided context. If 196 * an error occurs, NULL is returned and an exception is set. If either x or 197 * y can't be converted to an mpc, then Py_NotImplemented is returned. */ 198 199 static PyObject * 200 GMPy_Complex_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, 201 CTXT_Object *context) 202 { 203 MPC_Object *result = NULL; 204 205 CHECK_CONTEXT(context); 206 207 if (!(result = GMPy_MPC_New(0, 0, context))) { 208 /* LCOV_EXCL_START */ 209 return NULL; 210 /* LCOV_EXCL_STOP */ 211 } 212 213 if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype)) { 214 result->rc = mpc_mul(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context)); 215 _GMPy_MPC_Cleanup(&result, context); 216 return (PyObject*)result; 217 } 218 219 if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) { 220 MPC_Object *tempx = NULL, *tempy = NULL; 221 222 if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) || 223 !(tempy = GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context))) { 224 /* LCOV_EXCL_START */ 225 Py_XDECREF((PyObject*)tempx); 226 Py_XDECREF((PyObject*)tempy); 227 Py_DECREF((PyObject*)result); 228 return NULL; 229 /* LCOV_EXCL_STOP */ 230 } 231 result->rc = mpc_mul(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context)); 232 Py_DECREF((PyObject*)tempx); 233 Py_DECREF((PyObject*)tempy); 234 _GMPy_MPC_Cleanup(&result, context); 235 return (PyObject*)result; 236 } 237 238 Py_DECREF((PyObject*)result); 239 TYPE_ERROR("mul() argument type not supported"); 240 return NULL; 241 } 242 243 static PyObject * 244 GMPy_Number_Mul(PyObject *x, PyObject *y, CTXT_Object *context) 245 { 246 int xtype = GMPy_ObjectType(x); 247 int ytype = GMPy_ObjectType(y); 248 249 if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) 250 return GMPy_Integer_MulWithType(x, xtype, y, ytype, context); 251 252 if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) 253 return GMPy_Rational_MulWithType(x, xtype, y, ytype, context); 254 255 if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) 256 return GMPy_Real_MulWithType(x, xtype, y, ytype, context); 257 258 if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) 259 return GMPy_Complex_MulWithType(x, xtype, y, ytype, context); 260 261 TYPE_ERROR("mul() argument type not supported"); 262 return NULL; 263 } 264 265 /* Implement all the slot methods here. */ 266 267 static PyObject * 268 GMPy_Number_Mul_Slot(PyObject *x, PyObject *y) 269 { 270 int xtype = GMPy_ObjectType(x); 271 int ytype = GMPy_ObjectType(y); 272 273 if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) 274 return GMPy_Integer_MulWithType(x, xtype, y, ytype, NULL); 275 276 if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) 277 return GMPy_Rational_MulWithType(x, xtype, y, ytype, NULL); 278 279 if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) 280 return GMPy_Real_MulWithType(x, xtype, y, ytype, NULL); 281 282 if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) 283 return GMPy_Complex_MulWithType(x, xtype, y, ytype, NULL); 284 285 Py_RETURN_NOTIMPLEMENTED; 286 } 287 288 /* Implement context.mul() and gmpy2.mul(). */ 289 290 PyDoc_STRVAR(GMPy_doc_function_mul, 291 "mul(x, y) -> number\n\n" 292 "Return x * y."); 293 294 PyDoc_STRVAR(GMPy_doc_context_mul, 295 "context.mul(x, y) -> number\n\n" 296 "Return x * y."); 297 298 static PyObject * 299 GMPy_Context_Mul(PyObject *self, PyObject *args) 300 { 301 CTXT_Object *context = NULL; 302 303 if (PyTuple_GET_SIZE(args) != 2) { 304 TYPE_ERROR("mul() requires 2 arguments"); 305 return NULL; 306 } 307 308 if (self && CTXT_Check(self)) { 309 context = (CTXT_Object*)self; 310 } 311 else { 312 CHECK_CONTEXT(context); 313 } 314 315 return GMPy_Number_Mul(PyTuple_GET_ITEM(args, 0), 316 PyTuple_GET_ITEM(args, 1), 317 context); 318 } 319