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 *
GMPy_MPZ_c_divmod(PyObject * self,PyObject * args)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 *
GMPy_MPZ_c_div(PyObject * self,PyObject * args)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 *
GMPy_MPZ_c_mod(PyObject * self,PyObject * args)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 *
GMPy_MPZ_f_divmod(PyObject * self,PyObject * args)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 *
GMPy_MPZ_f_div(PyObject * self,PyObject * args)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 *
GMPy_MPZ_f_mod(PyObject * self,PyObject * args)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 *
GMPy_MPZ_t_divmod(PyObject * self,PyObject * args)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 *
GMPy_MPZ_t_div(PyObject * self,PyObject * args)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 *
GMPy_MPZ_t_mod(PyObject * self,PyObject * args)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 }
434