PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/src/gmpy_mpz_inplace.c

http://gmpy.googlecode.com/
C | 359 lines | 285 code | 43 blank | 31 comment | 67 complexity | c86985c31276cf447ea0bbf546193b2a MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, LGPL-2.1
  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. /* Provides inplace operations for mpz. */
  28. #include <math.h>
  29. static PyObject *
  30. Pympz_inplace_add(PyObject *self, PyObject *other)
  31. {
  32. PympzObject *rz;
  33. mpz_t tempz;
  34. mpir_si temp_si;
  35. int overflow;
  36. if (!(rz = (PympzObject*)Pympz_new()))
  37. return NULL;
  38. if (CHECK_MPZANY(other)) {
  39. mpz_add(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
  40. return (PyObject*)rz;
  41. }
  42. if (PyIntOrLong_Check(other)) {
  43. temp_si = PyLong_AsSIAndOverflow(other, &overflow);
  44. if (overflow) {
  45. mpz_inoc(tempz);
  46. mpz_set_PyIntOrLong(tempz, other);
  47. mpz_add(rz->z, Pympz_AS_MPZ(self), tempz);
  48. mpz_cloc(tempz);
  49. }
  50. else if(temp_si >= 0) {
  51. mpz_add_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
  52. }
  53. else {
  54. mpz_sub_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
  55. }
  56. return (PyObject*)rz;
  57. }
  58. Py_RETURN_NOTIMPLEMENTED;
  59. }
  60. static PyObject *
  61. Pympz_inplace_sub(PyObject *self, PyObject *other)
  62. {
  63. PympzObject *rz;
  64. mpz_t tempz;
  65. mpir_si temp_si;
  66. int overflow;
  67. if (!(rz = (PympzObject*)Pympz_new()))
  68. return NULL;
  69. if (CHECK_MPZANY(other)) {
  70. mpz_sub(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
  71. return (PyObject*)rz;
  72. }
  73. if (PyIntOrLong_Check(other)) {
  74. temp_si = PyLong_AsSIAndOverflow(other, &overflow);
  75. if (overflow) {
  76. mpz_inoc(tempz);
  77. mpz_set_PyIntOrLong(tempz, other);
  78. mpz_sub(rz->z, Pympz_AS_MPZ(self), tempz);
  79. mpz_cloc(tempz);
  80. }
  81. else if(temp_si >= 0) {
  82. mpz_sub_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
  83. }
  84. else {
  85. mpz_add_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
  86. }
  87. return (PyObject*)rz;
  88. }
  89. Py_RETURN_NOTIMPLEMENTED;
  90. }
  91. static PyObject *
  92. Pympz_inplace_mul(PyObject *self, PyObject *other)
  93. {
  94. PympzObject *rz;
  95. mpz_t tempz;
  96. mpir_si temp_si;
  97. int overflow;
  98. if (!(rz = (PympzObject*)Pympz_new()))
  99. return NULL;
  100. if (CHECK_MPZANY(other)) {
  101. mpz_mul(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
  102. return (PyObject*)rz;
  103. }
  104. if (PyIntOrLong_Check(other)) {
  105. temp_si = PyLong_AsSIAndOverflow(other, &overflow);
  106. if (overflow) {
  107. mpz_inoc(tempz);
  108. mpz_set_PyIntOrLong(tempz, other);
  109. mpz_mul(rz->z, Pympz_AS_MPZ(self), tempz);
  110. mpz_cloc(tempz);
  111. }
  112. else {
  113. mpz_mul_si(rz->z, Pympz_AS_MPZ(self), temp_si);
  114. }
  115. return (PyObject*)rz;
  116. }
  117. Py_RETURN_NOTIMPLEMENTED;
  118. }
  119. /* Pympany_floordiv follows the // semantics from Python 3.x. The result is
  120. * an mpz when the arguments are mpz or mpq, but the result is an mpf when
  121. * the arguments are mpf.
  122. */
  123. static PyObject *
  124. Pympz_inplace_floordiv(PyObject *self, PyObject *other)
  125. {
  126. PympzObject *rz;
  127. mpz_t tempz;
  128. mpir_si temp_si;
  129. int overflow;
  130. if (!(rz = (PympzObject*)Pympz_new()))
  131. return NULL;
  132. if (CHECK_MPZANY(other)) {
  133. if (mpz_sgn(Pympz_AS_MPZ(other)) == 0) {
  134. ZERO_ERROR("mpz division by zero");
  135. return NULL;
  136. }
  137. mpz_fdiv_q(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
  138. return (PyObject*)rz;
  139. }
  140. if (PyIntOrLong_Check(other)) {
  141. temp_si = PyLong_AsSIAndOverflow(other, &overflow);
  142. if (overflow) {
  143. mpz_inoc(tempz);
  144. mpz_set_PyIntOrLong(tempz, other);
  145. mpz_fdiv_q(rz->z, Pympz_AS_MPZ(self), tempz);
  146. mpz_cloc(tempz);
  147. }
  148. else if(temp_si == 0) {
  149. ZERO_ERROR("mpz division by zero");
  150. return NULL;
  151. }
  152. else if(temp_si > 0) {
  153. mpz_fdiv_q_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
  154. }
  155. else {
  156. mpz_cdiv_q_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
  157. mpz_neg(rz->z, rz->z);
  158. }
  159. return (PyObject*)rz;
  160. }
  161. Py_RETURN_NOTIMPLEMENTED;
  162. }
  163. static PyObject *
  164. Pympz_inplace_rem(PyObject *self, PyObject *other)
  165. {
  166. PympzObject *rz;
  167. mpz_t tempz;
  168. mpir_si temp_si;
  169. int overflow;
  170. if (!(rz = (PympzObject*)Pympz_new()))
  171. return NULL;
  172. if (CHECK_MPZANY(other)) {
  173. if (mpz_sgn(Pympz_AS_MPZ(other)) == 0) {
  174. ZERO_ERROR("mpz modulo by zero");
  175. return NULL;
  176. }
  177. mpz_fdiv_r(rz->z, Pympz_AS_MPZ(self), Pympz_AS_MPZ(other));
  178. return (PyObject*)rz;
  179. }
  180. if (PyIntOrLong_Check(other)) {
  181. temp_si = PyLong_AsSIAndOverflow(other, &overflow);
  182. if (overflow) {
  183. mpz_inoc(tempz);
  184. mpz_set_PyIntOrLong(tempz, other);
  185. mpz_fdiv_r(rz->z, Pympz_AS_MPZ(self), tempz);
  186. mpz_cloc(tempz);
  187. }
  188. else if(temp_si > 0) {
  189. mpz_fdiv_r_ui(rz->z, Pympz_AS_MPZ(self), temp_si);
  190. }
  191. else if(temp_si == 0) {
  192. ZERO_ERROR("mpz modulo by zero");
  193. return NULL;
  194. }
  195. else {
  196. mpz_cdiv_r_ui(rz->z, Pympz_AS_MPZ(self), -temp_si);
  197. }
  198. return (PyObject*)rz;
  199. }
  200. Py_RETURN_NOTIMPLEMENTED;
  201. }
  202. static PyObject *
  203. Pympz_inplace_rshift(PyObject *self, PyObject *other)
  204. {
  205. PympzObject *rz;
  206. mpir_si temp_si;
  207. int overflow;
  208. if (!(rz = (PympzObject*)Pympz_new()))
  209. return NULL;
  210. if (CHECK_MPZANY(other)) {
  211. if (mpz_sgn(Pympz_AS_MPZ(other)) < 0) {
  212. VALUE_ERROR("negative shift count");
  213. Py_DECREF((PyObject*)rz);
  214. return NULL;
  215. }
  216. if (!mpz_fits_si_p(Pympz_AS_MPZ(other))) {
  217. OVERFLOW_ERROR("outrageous shift count");
  218. Py_DECREF((PyObject*)rz);
  219. return NULL;
  220. }
  221. temp_si = mpz_get_si(Pympz_AS_MPZ(other));
  222. mpz_fdiv_q_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
  223. return (PyObject*)rz;
  224. }
  225. if (PyIntOrLong_Check(other)) {
  226. temp_si = PyLong_AsSIAndOverflow(other, &overflow);
  227. if (overflow) {
  228. VALUE_ERROR("outrageous shift count");
  229. Py_DECREF((PyObject*)rz);
  230. return NULL;
  231. }
  232. else if(temp_si >= 0) {
  233. mpz_fdiv_q_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
  234. return (PyObject *)rz;
  235. }
  236. else {
  237. VALUE_ERROR("negative shift count");
  238. Py_DECREF((PyObject*)rz);
  239. return NULL;
  240. }
  241. }
  242. Py_RETURN_NOTIMPLEMENTED;
  243. }
  244. static PyObject *
  245. Pympz_inplace_lshift(PyObject *self, PyObject *other)
  246. {
  247. PympzObject *rz;
  248. mpir_si temp_si;
  249. int overflow;
  250. if (!(rz = (PympzObject*)Pympz_new()))
  251. return NULL;
  252. if (CHECK_MPZANY(other)) {
  253. if (mpz_sgn(Pympz_AS_MPZ(other)) < 0) {
  254. VALUE_ERROR("negative shift count");
  255. Py_DECREF((PyObject*)rz);
  256. return NULL;
  257. }
  258. if (!mpz_fits_si_p(Pympz_AS_MPZ(other))) {
  259. OVERFLOW_ERROR("outrageous shift count");
  260. Py_DECREF((PyObject*)rz);
  261. return NULL;
  262. }
  263. temp_si = mpz_get_si(Pympz_AS_MPZ(other));
  264. mpz_mul_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
  265. return (PyObject*)rz;
  266. }
  267. if (PyIntOrLong_Check(other)) {
  268. temp_si = PyLong_AsSIAndOverflow(other, &overflow);
  269. if (overflow) {
  270. VALUE_ERROR("outrageous shift count");
  271. Py_DECREF((PyObject*)rz);
  272. return NULL;
  273. }
  274. else if(temp_si >= 0) {
  275. mpz_mul_2exp(rz->z, Pympz_AS_MPZ(self), temp_si);
  276. return (PyObject *)rz;
  277. }
  278. else {
  279. VALUE_ERROR("negative shift count");
  280. Py_DECREF((PyObject*)rz);
  281. return NULL;
  282. }
  283. }
  284. Py_RETURN_NOTIMPLEMENTED;
  285. }
  286. static PyObject *
  287. Pympz_inplace_pow(PyObject *self, PyObject *other, PyObject *mod)
  288. {
  289. PympzObject *r, *e = 0;
  290. mpir_ui el;
  291. if (mod != Py_None) {
  292. Py_RETURN_NOTIMPLEMENTED;
  293. }
  294. if (!(e = Pympz_From_Integer(other))) {
  295. PyErr_Clear();
  296. Py_RETURN_NOTIMPLEMENTED;
  297. }
  298. if (mpz_sgn(e->z) < 0) {
  299. PyErr_Clear();
  300. Py_DECREF((PyObject*)e);
  301. Py_RETURN_NOTIMPLEMENTED;
  302. }
  303. if (!mpz_fits_ui_p(e->z)) {
  304. PyErr_Clear();
  305. Py_DECREF((PyObject*)e);
  306. Py_RETURN_NOTIMPLEMENTED;
  307. }
  308. if (!(r = (PympzObject*)Pympz_new())) {
  309. Py_DECREF((PyObject*)e);
  310. return NULL;
  311. }
  312. el = mpz_get_ui(e->z);
  313. mpz_pow_ui(r->z, Pympz_AS_MPZ(self), el);
  314. Py_DECREF((PyObject*)e);
  315. return (PyObject*)r;
  316. }