PageRenderTime 29ms CodeModel.GetById 8ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/gmpy_mpz_inplace.c

http://gmpy.googlecode.com/
C | 359 lines | 285 code | 43 blank | 31 comment | 67 complexity | c86985c31276cf447ea0bbf546193b2a MD5 | raw file
  1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2 * gmpy_mpz_inplace.c                                                      *
  3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4 * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision   *
  5 * libraries.                                                              *
  6 *                                                                         *
  7 * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,               *
  8 *           2008, 2009 Alex Martelli                                      *
  9 *                                                                         *
 10 * Copyright 2008, 2009, 2010, 2011, 2012, 2013 Case Van Horsen            *
 11 *                                                                         *
 12 * This file is part of GMPY2.                                             *
 13 *                                                                         *
 14 * GMPY2 is free software: you can redistribute it and/or modify it under  *
 15 * the terms of the GNU Lesser General Public License as published by the  *
 16 * Free Software Foundation, either version 3 of the License, or (at your  *
 17 * option) any later version.                                              *
 18 *                                                                         *
 19 * GMPY2 is distributed in the hope that it will be useful, but WITHOUT    *
 20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   *
 21 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public    *
 22 * License for more details.                                               *
 23 *                                                                         *
 24 * You should have received a copy of the GNU Lesser General Public        *
 25 * License along with GMPY2; if not, see <http://www.gnu.org/licenses/>    *
 26 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 27
 28
 29/* Provides inplace operations for mpz. */
 30
 31#include <math.h>
 32
 33static PyObject *
 34Pympz_inplace_add(PyObject *self, PyObject *other)
 35{
 36    PympzObject *rz;
 37    mpz_t tempz;
 38    mpir_si temp_si;
 39    int overflow;
 40
 41    if (!(rz = (PympzObject*)Pympz_new()))
 42        return NULL;
 43
 44    if (CHECK_MPZANY(other)) {
 45        mpz_add(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
 46        return (PyObject*)rz;
 47    }
 48
 49    if (PyIntOrLong_Check(other)) {
 50        temp_si = PyLong_AsSIAndOverflow(other, &overflow);
 51        if (overflow) {
 52            mpz_inoc(tempz);
 53            mpz_set_PyIntOrLong(tempz, other);
 54            mpz_add(rz->z, Pympz_AS_MPZ(self), tempz);
 55            mpz_cloc(tempz);
 56        }
 57        else if(temp_si >= 0) {
 58            mpz_add_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
 59        }
 60        else {
 61            mpz_sub_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
 62        }
 63        return (PyObject*)rz;
 64    }
 65
 66    Py_RETURN_NOTIMPLEMENTED;
 67}
 68
 69static PyObject *
 70Pympz_inplace_sub(PyObject *self, PyObject *other)
 71{
 72    PympzObject *rz;
 73    mpz_t tempz;
 74    mpir_si temp_si;
 75    int overflow;
 76
 77    if (!(rz = (PympzObject*)Pympz_new()))
 78        return NULL;
 79
 80    if (CHECK_MPZANY(other)) {
 81        mpz_sub(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
 82        return (PyObject*)rz;
 83    }
 84
 85    if (PyIntOrLong_Check(other)) {
 86        temp_si = PyLong_AsSIAndOverflow(other, &overflow);
 87        if (overflow) {
 88            mpz_inoc(tempz);
 89            mpz_set_PyIntOrLong(tempz, other);
 90            mpz_sub(rz->z, Pympz_AS_MPZ(self), tempz);
 91            mpz_cloc(tempz);
 92        }
 93        else if(temp_si >= 0) {
 94            mpz_sub_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
 95        }
 96        else {
 97            mpz_add_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
 98        }
 99        return (PyObject*)rz;
100    }
101
102    Py_RETURN_NOTIMPLEMENTED;
103}
104
105static PyObject *
106Pympz_inplace_mul(PyObject *self, PyObject *other)
107{
108    PympzObject *rz;
109    mpz_t tempz;
110    mpir_si temp_si;
111    int overflow;
112
113    if (!(rz = (PympzObject*)Pympz_new()))
114        return NULL;
115
116    if (CHECK_MPZANY(other)) {
117        mpz_mul(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
118        return (PyObject*)rz;
119    }
120
121    if (PyIntOrLong_Check(other)) {
122        temp_si = PyLong_AsSIAndOverflow(other, &overflow);
123        if (overflow) {
124            mpz_inoc(tempz);
125            mpz_set_PyIntOrLong(tempz, other);
126            mpz_mul(rz->z, Pympz_AS_MPZ(self), tempz);
127            mpz_cloc(tempz);
128        }
129        else {
130            mpz_mul_si(rz->z, Pympz_AS_MPZ(self), temp_si);
131        }
132        return (PyObject*)rz;
133    }
134
135    Py_RETURN_NOTIMPLEMENTED;
136}
137
138/* Pympany_floordiv follows the // semantics from Python 3.x. The result is
139 * an mpz when the arguments are mpz or mpq, but the result is an mpf when
140 * the arguments are mpf.
141 */
142
143static PyObject *
144Pympz_inplace_floordiv(PyObject *self, PyObject *other)
145{
146    PympzObject *rz;
147    mpz_t tempz;
148    mpir_si temp_si;
149    int overflow;
150
151    if (!(rz = (PympzObject*)Pympz_new()))
152        return NULL;
153
154    if (CHECK_MPZANY(other)) {
155        if (mpz_sgn(Pympz_AS_MPZ(other)) == 0) {
156            ZERO_ERROR("mpz division by zero");
157            return NULL;
158        }
159        mpz_fdiv_q(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
160        return (PyObject*)rz;
161    }
162
163    if (PyIntOrLong_Check(other)) {
164        temp_si = PyLong_AsSIAndOverflow(other, &overflow);
165        if (overflow) {
166            mpz_inoc(tempz);
167            mpz_set_PyIntOrLong(tempz, other);
168            mpz_fdiv_q(rz->z, Pympz_AS_MPZ(self), tempz);
169            mpz_cloc(tempz);
170        }
171        else if(temp_si == 0) {
172            ZERO_ERROR("mpz division by zero");
173            return NULL;
174        }
175        else if(temp_si > 0) {
176            mpz_fdiv_q_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
177        }
178        else {
179            mpz_cdiv_q_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
180            mpz_neg(rz->z, rz->z);
181        }
182        return (PyObject*)rz;
183    }
184
185    Py_RETURN_NOTIMPLEMENTED;
186}
187
188static PyObject *
189Pympz_inplace_rem(PyObject *self, PyObject *other)
190{
191    PympzObject *rz;
192    mpz_t tempz;
193    mpir_si temp_si;
194    int overflow;
195
196    if (!(rz = (PympzObject*)Pympz_new()))
197        return NULL;
198
199     if (CHECK_MPZANY(other)) {
200        if (mpz_sgn(Pympz_AS_MPZ(other)) == 0) {
201            ZERO_ERROR("mpz modulo by zero");
202            return NULL;
203        }
204        mpz_fdiv_r(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
205        return (PyObject*)rz;
206    }
207
208   if (PyIntOrLong_Check(other)) {
209        temp_si = PyLong_AsSIAndOverflow(other, &overflow);
210        if (overflow) {
211            mpz_inoc(tempz);
212            mpz_set_PyIntOrLong(tempz, other);
213            mpz_fdiv_r(rz->z, Pympz_AS_MPZ(self), tempz);
214            mpz_cloc(tempz);
215        }
216        else if(temp_si > 0) {
217            mpz_fdiv_r_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
218        }
219        else if(temp_si == 0) {
220            ZERO_ERROR("mpz modulo by zero");
221            return NULL;
222        }
223        else {
224            mpz_cdiv_r_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
225        }
226        return (PyObject*)rz;
227    }
228
229    Py_RETURN_NOTIMPLEMENTED;
230}
231
232static PyObject *
233Pympz_inplace_rshift(PyObject *self, PyObject *other)
234{
235    PympzObject *rz;
236    mpir_si temp_si;
237    int overflow;
238
239    if (!(rz = (PympzObject*)Pympz_new()))
240        return NULL;
241
242    if (CHECK_MPZANY(other)) {
243        if (mpz_sgn(Pympz_AS_MPZ(other)) < 0) {
244            VALUE_ERROR("negative shift count");
245            Py_DECREF((PyObject*)rz);
246            return NULL;
247        }
248        if (!mpz_fits_si_p(Pympz_AS_MPZ(other))) {
249            OVERFLOW_ERROR("outrageous shift count");
250            Py_DECREF((PyObject*)rz);
251            return NULL;
252        }
253        temp_si = mpz_get_si(Pympz_AS_MPZ(other));
254        mpz_fdiv_q_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
255        return (PyObject*)rz;
256    }
257
258    if (PyIntOrLong_Check(other)) {
259        temp_si = PyLong_AsSIAndOverflow(other, &overflow);
260        if (overflow) {
261            VALUE_ERROR("outrageous shift count");
262            Py_DECREF((PyObject*)rz);
263            return NULL;
264        }
265        else if(temp_si >= 0) {
266            mpz_fdiv_q_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
267            return (PyObject *)rz;
268        }
269        else {
270            VALUE_ERROR("negative shift count");
271            Py_DECREF((PyObject*)rz);
272            return NULL;
273        }
274    }
275
276    Py_RETURN_NOTIMPLEMENTED;
277}
278
279static PyObject *
280Pympz_inplace_lshift(PyObject *self, PyObject *other)
281{
282    PympzObject *rz;
283    mpir_si temp_si;
284    int overflow;
285
286    if (!(rz = (PympzObject*)Pympz_new()))
287        return NULL;
288
289    if (CHECK_MPZANY(other)) {
290        if (mpz_sgn(Pympz_AS_MPZ(other)) < 0) {
291            VALUE_ERROR("negative shift count");
292            Py_DECREF((PyObject*)rz);
293            return NULL;
294        }
295        if (!mpz_fits_si_p(Pympz_AS_MPZ(other))) {
296            OVERFLOW_ERROR("outrageous shift count");
297            Py_DECREF((PyObject*)rz);
298            return NULL;
299        }
300        temp_si = mpz_get_si(Pympz_AS_MPZ(other));
301        mpz_mul_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
302        return (PyObject*)rz;
303    }
304
305    if (PyIntOrLong_Check(other)) {
306        temp_si = PyLong_AsSIAndOverflow(other, &overflow);
307        if (overflow) {
308            VALUE_ERROR("outrageous shift count");
309            Py_DECREF((PyObject*)rz);
310            return NULL;
311        }
312        else if(temp_si >= 0) {
313            mpz_mul_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
314            return (PyObject *)rz;
315        }
316        else {
317            VALUE_ERROR("negative shift count");
318            Py_DECREF((PyObject*)rz);
319            return NULL;
320        }
321    }
322
323    Py_RETURN_NOTIMPLEMENTED;
324}
325
326static PyObject *
327Pympz_inplace_pow(PyObject *self, PyObject *other, PyObject *mod)
328{
329    PympzObject *r, *e = 0;
330    mpir_ui el;
331
332    if (mod != Py_None) {
333        Py_RETURN_NOTIMPLEMENTED;
334    }
335
336    if (!(e = Pympz_From_Integer(other))) {
337        PyErr_Clear();
338        Py_RETURN_NOTIMPLEMENTED;
339    }
340    if (mpz_sgn(e->z) < 0) {
341        PyErr_Clear();
342        Py_DECREF((PyObject*)e);
343        Py_RETURN_NOTIMPLEMENTED;
344    }
345    if (!mpz_fits_ui_p(e->z)) {
346        PyErr_Clear();
347        Py_DECREF((PyObject*)e);
348        Py_RETURN_NOTIMPLEMENTED;
349    }
350    if (!(r = (PympzObject*)Pympz_new())) {
351        Py_DECREF((PyObject*)e);
352        return NULL;
353    }
354    el = mpz_get_ui(e->z);
355    mpz_pow_ui(r->z, Pympz_AS_MPZ(self), el);
356    Py_DECREF((PyObject*)e);
357    return (PyObject*)r;
358}
359