gmpy2_mpz_divmod.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_mpz_divmod.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 /* This file contains functions related to division and remainder. */ 29 30 /* 31 ************************************************************************** 32 * Ceiling division and remainder. 33 ************************************************************************** 34 */ 35 36 PyDoc_STRVAR(doc_c_divmod, 37 "c_divmod(x, y) -> (quotient, remainder)\n\n" 38 "Return the quotient and remainder of x divided by y. The quotient\n" 39 "is rounded towards +Inf (ceiling rounding) and the remainder will\n" 40 "have the opposite sign of y. x and y must be integers."); 41 42 static PyObject * 43 GMPy_MPZ_c_divmod(PyObject *self, PyObject *args) 44 { 45 PyObject *result = NULL; 46 MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL; 47 48 if (PyTuple_GET_SIZE(args) != 2) { 49 TYPE_ERROR("c_divmod() requires 'mpz','mpz' arguments"); 50 return NULL; 51 } 52 53 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 54 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 55 !(q = GMPy_MPZ_New(NULL)) || 56 !(r = GMPy_MPZ_New(NULL)) || 57 !(result = PyTuple_New(2))) { 58 59 goto err; 60 } 61 62 if (mpz_sgn(tempy->z) == 0) { 63 ZERO_ERROR("c_divmod() division by 0"); 64 goto err; 65 } 66 67 mpz_cdiv_qr(q->z, r->z, tempx->z, tempy->z); 68 69 Py_DECREF((PyObject*)tempx); 70 Py_DECREF((PyObject*)tempy); 71 PyTuple_SET_ITEM(result, 0, (PyObject*)q); 72 PyTuple_SET_ITEM(result, 1, (PyObject*)r); 73 return result; 74 75 err: 76 Py_XDECREF(result); 77 Py_XDECREF((PyObject*)tempx); 78 Py_XDECREF((PyObject*)tempy); 79 Py_XDECREF((PyObject*)q); 80 Py_XDECREF((PyObject*)r); 81 return NULL; 82 } 83 84 PyDoc_STRVAR(doc_c_div, 85 "c_div(x, y) -> quotient\n\n" 86 "Return the quotient of x divided by y. The quotient is rounded\n" 87 "towards +Inf (ceiling rounding). x and y must be integers."); 88 89 static PyObject * 90 GMPy_MPZ_c_div(PyObject *self, PyObject *args) 91 { 92 MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL; 93 94 if (PyTuple_GET_SIZE(args) != 2) { 95 TYPE_ERROR("c_div() requires 'mpz','mpz' arguments"); 96 return NULL; 97 } 98 99 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 100 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 101 !(q = GMPy_MPZ_New(NULL))) { 102 103 goto err; 104 } 105 106 if (mpz_sgn(tempy->z) == 0) { 107 ZERO_ERROR("c_div() division by 0"); 108 goto err; 109 } 110 111 mpz_cdiv_q(q->z, tempx->z, tempy->z); 112 113 Py_DECREF((PyObject*)tempx); 114 Py_DECREF((PyObject*)tempy); 115 return (PyObject*)q; 116 117 err: 118 Py_XDECREF((PyObject*)tempx); 119 Py_XDECREF((PyObject*)tempy); 120 Py_XDECREF((PyObject*)q); 121 return NULL; 122 } 123 124 PyDoc_STRVAR(doc_c_mod, 125 "c_mod(x, y) -> remainder\n\n" 126 "Return the remainder of x divided by y. The remainder will have\n" 127 "the opposite sign of y. x and y must be integers."); 128 129 static PyObject * 130 GMPy_MPZ_c_mod(PyObject *self, PyObject *args) 131 { 132 MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL; 133 134 if (PyTuple_GET_SIZE(args) != 2) { 135 TYPE_ERROR("c_mod() requires 'mpz','mpz' arguments"); 136 return NULL; 137 } 138 139 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 140 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 141 !(r = GMPy_MPZ_New(NULL))) { 142 143 goto err; 144 } 145 146 if (mpz_sgn(tempy->z) == 0) { 147 ZERO_ERROR("c_mod() division by 0"); 148 goto err; 149 } 150 151 mpz_cdiv_r(r->z, tempx->z, tempy->z); 152 153 Py_DECREF((PyObject*)tempx); 154 Py_DECREF((PyObject*)tempy); 155 return (PyObject*)r; 156 157 err: 158 Py_XDECREF((PyObject*)tempx); 159 Py_XDECREF((PyObject*)tempy); 160 Py_XDECREF((PyObject*)r); 161 return NULL; 162 } 163 164 /* 165 ************************************************************************** 166 * Floor division and remainder. 167 ************************************************************************** 168 */ 169 170 PyDoc_STRVAR(doc_f_divmod, 171 "f_divmod(x, y) -> (quotient, remainder)\n\n" 172 "Return the quotient and remainder of x divided by y. The quotient\n" 173 "is rounded towards -Inf (floor rounding) and the remainder will\n" 174 "have the same sign as y. x and y must be integers."); 175 176 static PyObject * 177 GMPy_MPZ_f_divmod(PyObject *self, PyObject *args) 178 { 179 PyObject *result = NULL; 180 MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL; 181 182 if (PyTuple_GET_SIZE(args) != 2) { 183 TYPE_ERROR("f_divmod() requires 'mpz','mpz' arguments"); 184 return NULL; 185 } 186 187 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 188 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 189 !(q = GMPy_MPZ_New(NULL)) || 190 !(r = GMPy_MPZ_New(NULL)) || 191 !(result = PyTuple_New(2))) { 192 193 goto err; 194 } 195 196 if (mpz_sgn(tempy->z) == 0) { 197 ZERO_ERROR("f_divmod() division by 0"); 198 goto err; 199 } 200 201 mpz_fdiv_qr(q->z, r->z, tempx->z, tempy->z); 202 203 Py_DECREF((PyObject*)tempx); 204 Py_DECREF((PyObject*)tempy); 205 PyTuple_SET_ITEM(result, 0, (PyObject*)q); 206 PyTuple_SET_ITEM(result, 1, (PyObject*)r); 207 return result; 208 209 err: 210 Py_XDECREF(result); 211 Py_XDECREF((PyObject*)tempx); 212 Py_XDECREF((PyObject*)tempy); 213 Py_XDECREF((PyObject*)q); 214 Py_XDECREF((PyObject*)r); 215 return NULL; 216 } 217 218 PyDoc_STRVAR(doc_f_div, 219 "f_div(x, y) -> quotient\n\n" 220 "Return the quotient of x divided by y. The quotient is rounded\n" 221 "towards -Inf (floor rounding). x and y must be integers."); 222 223 static PyObject * 224 GMPy_MPZ_f_div(PyObject *self, PyObject *args) 225 { 226 MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL; 227 228 if(PyTuple_GET_SIZE(args) != 2) { 229 TYPE_ERROR("f_div() requires 'mpz','mpz' arguments"); 230 return NULL; 231 } 232 233 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 234 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 235 !(q = GMPy_MPZ_New(NULL))) { 236 237 goto err; 238 } 239 240 if (mpz_sgn(tempy->z) == 0) { 241 ZERO_ERROR("f_div() division by 0"); 242 goto err; 243 } 244 245 mpz_fdiv_q(q->z, tempx->z, tempy->z); 246 247 Py_DECREF((PyObject*)tempx); 248 Py_DECREF((PyObject*)tempy); 249 return (PyObject*)q; 250 251 err: 252 Py_XDECREF((PyObject*)tempx); 253 Py_XDECREF((PyObject*)tempy); 254 Py_XDECREF((PyObject*)q); 255 return NULL; 256 } 257 258 PyDoc_STRVAR(doc_f_mod, 259 "f_mod(x, y) -> remainder\n\n" 260 "Return the remainder of x divided by y. The remainder will have\n" 261 "the same sign as y. x and y must be integers."); 262 263 static PyObject * 264 GMPy_MPZ_f_mod(PyObject *self, PyObject *args) 265 { 266 MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL; 267 268 if (PyTuple_GET_SIZE(args) != 2) { 269 TYPE_ERROR("f_mod() requires 'mpz','mpz' arguments"); 270 return NULL; 271 } 272 273 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 274 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 275 !(r = GMPy_MPZ_New(NULL))) { 276 277 goto err; 278 } 279 280 if (mpz_sgn(tempy->z) == 0) { 281 ZERO_ERROR("f_mod() division by 0"); 282 goto err; 283 } 284 285 mpz_fdiv_r(r->z, tempx->z, tempy->z); 286 287 Py_DECREF((PyObject*)tempx); 288 Py_DECREF((PyObject*)tempy); 289 return (PyObject*)r; 290 291 err: 292 Py_XDECREF((PyObject*)tempx); 293 Py_XDECREF((PyObject*)tempy); 294 Py_XDECREF((PyObject*)r); 295 return NULL; 296 } 297 298 /* 299 ************************************************************************** 300 * Truncating division and remainder. 301 ************************************************************************** 302 */ 303 304 PyDoc_STRVAR(doc_t_divmod, 305 "t_divmod(x, y) -> (quotient, remainder)\n\n" 306 "Return the quotient and remainder of x divided by y. The quotient\n" 307 "is rounded towards zero (truncation) and the remainder will have\n" 308 "the same sign as x. x and y must be integers."); 309 310 static PyObject * 311 GMPy_MPZ_t_divmod(PyObject *self, PyObject *args) 312 { 313 PyObject *result = NULL; 314 MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL; 315 316 if (PyTuple_GET_SIZE(args) != 2) { 317 TYPE_ERROR("t_divmod() requires 'mpz','mpz' arguments"); 318 return NULL; 319 } 320 321 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 322 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 323 !(q = GMPy_MPZ_New(NULL)) || 324 !(r = GMPy_MPZ_New(NULL)) || 325 !(result = PyTuple_New(2))) { 326 327 goto err; 328 } 329 330 if (mpz_sgn(tempy->z) == 0) { 331 ZERO_ERROR("t_divmod() division by 0"); 332 goto err; 333 } 334 335 mpz_tdiv_qr(q->z, r->z, tempx->z, tempy->z); 336 337 Py_DECREF((PyObject*)tempx); 338 Py_DECREF((PyObject*)tempy); 339 PyTuple_SET_ITEM(result, 0, (PyObject*)q); 340 PyTuple_SET_ITEM(result, 1, (PyObject*)r); 341 return result; 342 343 err: 344 Py_XDECREF(result); 345 Py_XDECREF((PyObject*)tempx); 346 Py_XDECREF((PyObject*)tempy); 347 Py_XDECREF((PyObject*)q); 348 Py_XDECREF((PyObject*)r); 349 return NULL; 350 } 351 352 PyDoc_STRVAR(doc_t_div, 353 "t_div(x, y) -> quotient\n\n" 354 "Return the quotient of x divided by y. The quotient is rounded\n" 355 "towards 0. x and y must be integers."); 356 357 static PyObject * 358 GMPy_MPZ_t_div(PyObject *self, PyObject *args) 359 { 360 MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL; 361 362 if (PyTuple_GET_SIZE(args) != 2) { 363 TYPE_ERROR("t_div() requires 'mpz','mpz' arguments"); 364 return NULL; 365 } 366 367 368 369 370 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 371 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 372 !(q = GMPy_MPZ_New(NULL))) { 373 374 goto err; 375 } 376 377 if (mpz_sgn(tempy->z) == 0) { 378 ZERO_ERROR("t_div() division by 0"); 379 goto err; 380 } 381 382 mpz_tdiv_q(q->z, tempx->z, tempy->z); 383 384 Py_DECREF((PyObject*)tempx); 385 Py_DECREF((PyObject*)tempy); 386 return (PyObject*)q; 387 388 err: 389 Py_XDECREF((PyObject*)tempx); 390 Py_XDECREF((PyObject*)tempy); 391 Py_XDECREF((PyObject*)q); 392 return NULL; 393 } 394 395 PyDoc_STRVAR(doc_t_mod, 396 "t_mod(x, y) -> remainder\n\n" 397 "Return the remainder of x divided by y. The remainder will have\n" 398 "the same sign as x. x and y must be integers."); 399 400 static PyObject * 401 GMPy_MPZ_t_mod(PyObject *self, PyObject *args) 402 { 403 MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL; 404 405 if (PyTuple_GET_SIZE(args) != 2) { 406 TYPE_ERROR("t_mod() requires 'mpz','mpz' arguments"); 407 return NULL; 408 } 409 410 if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || 411 !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || 412 !(r = GMPy_MPZ_New(NULL))) { 413 414 goto err; 415 } 416 417 if (mpz_sgn(tempy->z) == 0) { 418 ZERO_ERROR("t_mod() division by 0"); 419 goto err; 420 } 421 422 mpz_tdiv_r(r->z, tempx->z, tempy->z); 423 424 Py_DECREF((PyObject*)tempx); 425 Py_DECREF((PyObject*)tempy); 426 return (PyObject*)r; 427 428 err: 429 Py_XDECREF((PyObject*)tempx); 430 Py_XDECREF((PyObject*)tempy); 431 Py_XDECREF((PyObject*)r); 432 return NULL; 433 }