/src/gmpy_mpz_inplace.c
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