gmpy2_sub.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_sub.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.sub(), and context.sub(). 28 */ 29 30 /* Subtract 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_SubWithType(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_sub(result->z, MPZ(x), MPZ(y)); 49 return (PyObject*)result; 50 } 51 if (IS_TYPE_PyInteger(ytype)) { 52 int error; 53 long temp = PyLong_AsLongAndOverflow(y, &error); 54 55 if (!error) { 56 if (temp >= 0) { 57 mpz_sub_ui(result->z, MPZ(x), temp); 58 } 59 else { 60 mpz_add_ui(result->z, MPZ(x), -temp); 61 } 62 } 63 else { 64 mpz_set_PyIntOrLong(result->z, y); 65 mpz_sub(result->z, MPZ(x), result->z); 66 } 67 return (PyObject*)result; 68 } 69 } 70 71 if (IS_TYPE_MPZANY(ytype)) { 72 if (IS_TYPE_PyInteger(xtype)) { 73 int error; 74 long temp = PyLong_AsLongAndOverflow(x, &error); 75 76 if (!error) { 77 if (temp >= 0) { 78 mpz_ui_sub(result->z, temp, MPZ(y)); 79 } 80 else { 81 mpz_add_ui(result->z, MPZ(y), -temp); 82 mpz_neg(result->z, result->z); 83 } 84 } 85 else { 86 mpz_set_PyIntOrLong(global.tempz, x); 87 mpz_sub(result->z, global.tempz, MPZ(y)); 88 } 89 return (PyObject*)result; 90 } 91 } 92 93 if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) { 94 MPZ_Object *tempx = NULL, *tempy = NULL; 95 96 if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) || 97 !(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) { 98 /* LCOV_EXCL_START */ 99 Py_XDECREF((PyObject*)tempx); 100 Py_XDECREF((PyObject*)tempy); 101 Py_DECREF((PyObject*)result); 102 return NULL; 103 /* LCOV_EXCL_STOP */ 104 } 105 106 mpz_sub(result->z, tempx->z, tempy->z); 107 Py_DECREF((PyObject*)tempx); 108 Py_DECREF((PyObject*)tempy); 109 return (PyObject*)result; 110 } 111 112 Py_DECREF((PyObject*)result); 113 TYPE_ERROR("sub() argument type not supported"); 114 return NULL; 115 } 116 117 /* Subtract two Rational objects (see gmpy2_convert.h). Returns None and 118 * raises TypeError if both objects are not valid rationals. Pympq_Sub_Rational 119 * is intended to be called from GMPy_Number_Sub(). */ 120 121 static PyObject * 122 GMPy_Rational_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype, 123 CTXT_Object *context) 124 { 125 MPQ_Object *result = NULL; 126 127 if (!(result = GMPy_MPQ_New(context))) { 128 /* LCOV_EXCL_START */ 129 return NULL; 130 /* LCOV_EXCL_STOP */ 131 } 132 133 if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype)) { 134 mpq_sub(result->q, MPQ(x), MPQ(y)); 135 return (PyObject*)result; 136 } 137 138 if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) { 139 MPQ_Object *tempx = NULL, *tempy = NULL; 140 141 if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) || 142 !(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) { 143 /* LCOV_EXCL_START */ 144 Py_XDECREF((PyObject*)tempx); 145 Py_XDECREF((PyObject*)tempy); 146 Py_DECREF((PyObject*)result); 147 return NULL; 148 /* LCOV_EXCL_STOP */ 149 } 150 151 mpq_sub(result->q, tempx->q, tempy->q); 152 Py_DECREF((PyObject*)tempx); 153 Py_DECREF((PyObject*)tempy); 154 return (PyObject*)result; 155 } 156 157 /* LCOV_EXCL_START */ 158 Py_DECREF((PyObject*)result); 159 TYPE_ERROR("sub() argument type not supported"); 160 return NULL; 161 /* LCOV_EXCL_STOP */ 162 } 163 164 /* GMPy_Real_Sub(x, y, context) returns x-y using the provided context. If 165 * provided context is NULL, then the current context is used. If an error 166 * occurs, NULL is returned and an exception is set. If either x or y can't 167 * be converted to an mpfr, then Py_NotImplemented is returned. 168 * GMPy_Real_Sub() will not try to promote the result to a different type 169 * (i.e. mpc). 170 */ 171 172 static PyObject * 173 GMPy_Real_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype, 174 CTXT_Object *context) 175 { 176 MPFR_Object *result = NULL; 177 178 CHECK_CONTEXT(context); 179 180 if (!(result = GMPy_MPFR_New(0, context))) { 181 /* LCOV_EXCL_START */ 182 return NULL; 183 /* LCOV_EXCL_STOP */ 184 } 185 186 if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype)) { 187 mpfr_clear_flags(); 188 result->rc = mpfr_sub(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context)); 189 _GMPy_MPFR_Cleanup(&result, context); 190 return (PyObject*)result; 191 } 192 193 if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) { 194 MPFR_Object *tempx = NULL, *tempy = NULL; 195 196 if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) || 197 !(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) { 198 /* LCOV_EXCL_START */ 199 Py_XDECREF((PyObject*)tempx); 200 Py_XDECREF((PyObject*)tempy); 201 Py_DECREF((PyObject*)result); 202 return NULL; 203 /* LCOV_EXCL_STOP */ 204 } 205 206 mpfr_clear_flags(); 207 208 result->rc = mpfr_sub(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context)); 209 Py_DECREF((PyObject*)tempx); 210 Py_DECREF((PyObject*)tempy); 211 goto done; 212 } 213 214 /* LCOV_EXCL_START */ 215 Py_DECREF((PyObject*)result); 216 TYPE_ERROR("sub() argument type not supported"); 217 return NULL; 218 /* LCOV_EXCL_STOP */ 219 220 done: 221 _GMPy_MPFR_Cleanup(&result, context); 222 return (PyObject*)result; 223 } 224 225 /* GMPy_Complex_Sub(x, y, context) returns x-y using the provided context. If 226 * context is NULL, then the current context is used. If an error occurs, NULL 227 * is returned and an exception is set. If either x or y can't be converted to 228 * an mpc, then Py_NotImplemented is returned. */ 229 230 static PyObject * 231 GMPy_Complex_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype, 232 CTXT_Object *context) 233 { 234 MPC_Object *result = NULL; 235 236 CHECK_CONTEXT(context); 237 238 if (!(result = GMPy_MPC_New(0, 0, context))) { 239 /* LCOV_EXCL_START */ 240 return NULL; 241 /* LCOV_EXCL_STOP */ 242 } 243 244 if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype)) { 245 result->rc = mpc_sub(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context)); 246 _GMPy_MPC_Cleanup(&result, context); 247 return (PyObject*)result; 248 } 249 250 if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) { 251 MPC_Object *tempx = NULL, *tempy = NULL; 252 253 if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) || 254 !(tempy = GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context))) { 255 /* LCOV_EXCL_START */ 256 Py_XDECREF((PyObject*)tempx); 257 Py_XDECREF((PyObject*)tempy); 258 Py_DECREF((PyObject*)result); 259 return NULL; 260 /* LCOV_EXCL_STOP */ 261 } 262 263 result->rc = mpc_sub(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context)); 264 Py_DECREF((PyObject*)tempx); 265 Py_DECREF((PyObject*)tempy); 266 _GMPy_MPC_Cleanup(&result, context); 267 return (PyObject*)result; 268 } 269 270 /* LCOV_EXCL_START */ 271 Py_DECREF((PyObject*)result); 272 TYPE_ERROR("sub() argument type not supported"); 273 return NULL; 274 /* LCOV_EXCL_STOP */ 275 } 276 277 static PyObject * 278 GMPy_Number_Sub(PyObject *x, PyObject *y, CTXT_Object *context) 279 { 280 int xtype = GMPy_ObjectType(x); 281 int ytype = GMPy_ObjectType(y); 282 283 if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) 284 return GMPy_Integer_SubWithType(x, xtype, y, ytype, context); 285 286 if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) 287 return GMPy_Rational_SubWithType(x, xtype, y, ytype, context); 288 289 if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) 290 return GMPy_Real_SubWithType(x, xtype, y, ytype, context); 291 292 if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) 293 return GMPy_Complex_SubWithType(x, xtype, y, ytype, context); 294 295 TYPE_ERROR("sub() argument type not supported"); 296 return NULL; 297 } 298 299 /* Implement all the slot methods here. */ 300 301 static PyObject * 302 GMPy_Number_Sub_Slot(PyObject *x, PyObject *y) 303 { 304 int xtype = GMPy_ObjectType(x); 305 int ytype = GMPy_ObjectType(y); 306 307 if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) 308 return GMPy_Integer_SubWithType(x, xtype, y, ytype, NULL); 309 310 if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) 311 return GMPy_Rational_SubWithType(x, xtype, y, ytype, NULL); 312 313 if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) 314 return GMPy_Real_SubWithType(x, xtype, y, ytype, NULL); 315 316 if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) 317 return GMPy_Complex_SubWithType(x, xtype, y, ytype, NULL); 318 319 Py_RETURN_NOTIMPLEMENTED; 320 } 321 322 /* Implement context.sub() and gmpy2.sub(). */ 323 324 PyDoc_STRVAR(GMPy_doc_sub, 325 "sub(x, y) -> number\n\n" 326 "Return x - y."); 327 328 PyDoc_STRVAR(GMPy_doc_context_sub, 329 "context.sub(x, y) -> number\n\n" 330 "Return x - y."); 331 332 static PyObject * 333 GMPy_Context_Sub(PyObject *self, PyObject *args) 334 { 335 CTXT_Object *context = NULL; 336 337 if (PyTuple_GET_SIZE(args) != 2) { 338 TYPE_ERROR("sub() requires 2 arguments"); 339 return NULL; 340 } 341 342 if (self && CTXT_Check(self)) { 343 context = (CTXT_Object*)self; 344 } 345 else { 346 CHECK_CONTEXT(context); 347 } 348 349 return GMPy_Number_Sub(PyTuple_GET_ITEM(args, 0), 350 PyTuple_GET_ITEM(args, 1), 351 context); 352 } 353