/src/gmpy_mpmath.c

http://gmpy.googlecode.com/ · C · 378 lines · 298 code · 36 blank · 44 comment · 65 complexity · 9601009b6d7f60b58734f2cae80e5504 MD5 · raw file

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2. * gmpy_mpmath.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. /* Internal helper function for mpmath. */
  28. static PyObject *
  29. mpmath_build_mpf(long sign, PympzObject *man, PyObject *exp, mpir_si bc)
  30. {
  31. PyObject *tup, *tsign, *tbc;
  32. if (!(tup = PyTuple_New(4))) {
  33. Py_DECREF((PyObject*)man);
  34. Py_DECREF(exp);
  35. return NULL;
  36. }
  37. if (!(tsign = PyIntOrLong_FromLong(sign))) {
  38. Py_DECREF((PyObject*)man);
  39. Py_DECREF(exp);
  40. Py_DECREF(tup);
  41. return NULL;
  42. }
  43. if (!(tbc = PyIntOrLong_FromSI(bc))) {
  44. Py_DECREF((PyObject*)man);
  45. Py_DECREF(exp);
  46. Py_DECREF(tup);
  47. Py_DECREF(tsign);
  48. return NULL;
  49. }
  50. PyTuple_SET_ITEM(tup, 0, tsign);
  51. PyTuple_SET_ITEM(tup, 1, (PyObject*)man);
  52. PyTuple_SET_ITEM(tup, 2, (exp)?exp:PyIntOrLong_FromLong(0));
  53. PyTuple_SET_ITEM(tup, 3, tbc);
  54. return tup;
  55. }
  56. PyDoc_STRVAR(doc_mpmath_normalizeg,
  57. "_mpmath_normalize(...): helper function for mpmath.");
  58. static PyObject *
  59. Pympz_mpmath_normalize(PyObject *self, PyObject *args)
  60. {
  61. long sign = 0;
  62. mpir_si bc = 0, prec = 0, shift, zbits, carry = 0;
  63. PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0, *rndstr = 0;
  64. PympzObject *man = 0, *upper = 0, *lower = 0;
  65. char rnd = 0;
  66. if (PyTuple_GET_SIZE(args) == 6) {
  67. /* Need better error-checking here. Under Python 3.0, overflow into
  68. C-long is possible. */
  69. sign = clong_From_Integer(PyTuple_GET_ITEM(args, 0));
  70. man = (PympzObject *)PyTuple_GET_ITEM(args, 1);
  71. exp = PyTuple_GET_ITEM(args, 2);
  72. bc = SI_From_Integer(PyTuple_GET_ITEM(args, 3));
  73. prec = SI_From_Integer(PyTuple_GET_ITEM(args, 4));
  74. rndstr = PyTuple_GET_ITEM(args, 5);
  75. if (PyErr_Occurred()) {
  76. TYPE_ERROR("arguments long, PympzObject*, PyObject*, long, long, char needed");
  77. return NULL;
  78. }
  79. }
  80. else {
  81. TYPE_ERROR("6 arguments required");
  82. return NULL;
  83. }
  84. if (!Pympz_Check(man)) {
  85. TYPE_ERROR("argument is not an mpz");
  86. return NULL;
  87. }
  88. /* If rndstr really is a string, extract the first character. */
  89. if (Py2or3String_Check(rndstr)) {
  90. rnd = Py2or3String_AsString(rndstr)[0];
  91. }
  92. else {
  93. VALUE_ERROR("invalid rounding mode specified");
  94. return NULL;
  95. }
  96. /* If the mantissa is 0, return the normalized representation. */
  97. if (!mpz_sgn(man->z)) {
  98. Py_INCREF((PyObject*)man);
  99. return mpmath_build_mpf(0, man, 0, 0);
  100. }
  101. /* if bc <= prec and the number is odd return it */
  102. if ((bc <= prec) && mpz_odd_p(man->z)) {
  103. Py_INCREF((PyObject*)man);
  104. Py_INCREF((PyObject*)exp);
  105. return mpmath_build_mpf(sign, man, exp, bc);
  106. }
  107. if (!(upper = (PympzObject*)Pympz_new()) ||
  108. !(lower = (PympzObject*)Pympz_new())) {
  109. Py_XDECREF((PyObject*)upper);
  110. Py_XDECREF((PyObject*)lower);
  111. }
  112. shift = bc - prec;
  113. if (shift>0) {
  114. switch (rnd) {
  115. case 'f':
  116. if(sign) {
  117. mpz_cdiv_q_2exp(upper->z, man->z, shift);
  118. }
  119. else {
  120. mpz_fdiv_q_2exp(upper->z, man->z, shift);
  121. }
  122. break;
  123. case 'c':
  124. if(sign) {
  125. mpz_fdiv_q_2exp(upper->z, man->z, shift);
  126. }
  127. else {
  128. mpz_cdiv_q_2exp(upper->z, man->z, shift);
  129. }
  130. break;
  131. case 'd':
  132. mpz_fdiv_q_2exp(upper->z, man->z, shift);
  133. break;
  134. case 'u':
  135. mpz_cdiv_q_2exp(upper->z, man->z, shift);
  136. break;
  137. case 'n':
  138. default:
  139. mpz_tdiv_r_2exp(lower->z, man->z, shift);
  140. mpz_tdiv_q_2exp(upper->z, man->z, shift);
  141. if (mpz_sgn(lower->z)) {
  142. /* lower is not 0 so it must have at least 1 bit set */
  143. if (mpz_sizeinbase(lower->z, 2) == shift) {
  144. /* lower is >= 1/2 */
  145. if (mpz_scan1(lower->z, 0) == shift-1) {
  146. /* lower is exactly 1/2 */
  147. if (mpz_odd_p(upper->z))
  148. carry = 1;
  149. }
  150. else {
  151. carry = 1;
  152. }
  153. }
  154. }
  155. if (carry)
  156. mpz_add_ui(upper->z, upper->z, 1);
  157. }
  158. if (!(tmp = PyIntOrLong_FromSI(shift))) {
  159. Py_DECREF((PyObject*)upper);
  160. Py_DECREF((PyObject*)lower);
  161. return NULL;
  162. }
  163. if (!(newexp = PyNumber_Add(exp, tmp))) {
  164. Py_DECREF((PyObject*)upper);
  165. Py_DECREF((PyObject*)lower);
  166. Py_DECREF(tmp);
  167. return NULL;
  168. }
  169. Py_DECREF(tmp);
  170. bc = prec;
  171. }
  172. else {
  173. mpz_set(upper->z, man->z);
  174. newexp = exp;
  175. Py_INCREF(newexp);
  176. }
  177. /* Strip trailing 0 bits. */
  178. if ((zbits = mpz_scan1(upper->z, 0)))
  179. mpz_tdiv_q_2exp(upper->z, upper->z, zbits);
  180. if (!(tmp = PyIntOrLong_FromSI(zbits))) {
  181. Py_DECREF((PyObject*)upper);
  182. Py_DECREF((PyObject*)lower);
  183. Py_DECREF(newexp);
  184. return NULL;
  185. }
  186. if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
  187. Py_DECREF((PyObject*)upper);
  188. Py_DECREF((PyObject*)lower);
  189. Py_DECREF(tmp);
  190. Py_DECREF(newexp);
  191. return NULL;
  192. }
  193. Py_DECREF(newexp);
  194. Py_DECREF(tmp);
  195. bc -= zbits;
  196. /* Check if one less than a power of 2 was rounded up. */
  197. if (!mpz_cmp_ui(upper->z, 1))
  198. bc = 1;
  199. Py_DECREF((PyObject*)lower);
  200. return mpmath_build_mpf(sign, upper, newexp2, bc);
  201. }
  202. PyDoc_STRVAR(doc_mpmath_createg,
  203. "_mpmath_create(...): helper function for mpmath.");
  204. static PyObject *
  205. Pympz_mpmath_create(PyObject *self, PyObject *args)
  206. {
  207. long sign;
  208. mpir_si bc, shift, zbits, carry = 0, prec = 0;
  209. PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0;
  210. PympzObject *man = 0, *upper = 0, *lower = 0;
  211. const char *rnd = "f";
  212. if (PyTuple_GET_SIZE(args) < 2) {
  213. TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
  214. return NULL;
  215. }
  216. switch (PyTuple_GET_SIZE(args)) {
  217. case 4:
  218. rnd = Py2or3String_AsString(PyTuple_GET_ITEM(args, 3));
  219. case 3:
  220. prec = SI_From_Integer(PyTuple_GET_ITEM(args, 2));
  221. if (prec == -1 && PyErr_Occurred())
  222. return NULL;
  223. prec = ABS(prec);
  224. case 2:
  225. exp = PyTuple_GET_ITEM(args, 1);
  226. case 1:
  227. man = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0));
  228. if (!man) {
  229. TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
  230. return NULL;
  231. }
  232. }
  233. /* If the mantissa is 0, return the normalized representation. */
  234. if (!mpz_sgn(man->z)) {
  235. return mpmath_build_mpf(0, man, 0, 0);
  236. }
  237. upper = (PympzObject*)Pympz_new();
  238. lower = (PympzObject*)Pympz_new();
  239. if (!upper || !lower) {
  240. Py_DECREF((PyObject*)man);
  241. Py_XDECREF((PyObject*)upper);
  242. Py_XDECREF((PyObject*)lower);
  243. return NULL;
  244. }
  245. /* Extract sign, make man positive, and set bit count */
  246. sign = (mpz_sgn(man->z) == -1);
  247. mpz_abs(upper->z, man->z);
  248. bc = mpz_sizeinbase(upper->z, 2);
  249. if (!prec) prec = bc;
  250. shift = bc - prec;
  251. if (shift > 0) {
  252. switch (rnd[0]) {
  253. case 'f':
  254. if(sign) {
  255. mpz_cdiv_q_2exp(upper->z, upper->z, shift);
  256. }
  257. else {
  258. mpz_fdiv_q_2exp(upper->z, upper->z, shift);
  259. }
  260. break;
  261. case 'c':
  262. if(sign) {
  263. mpz_fdiv_q_2exp(upper->z, upper->z, shift);
  264. }
  265. else {
  266. mpz_cdiv_q_2exp(upper->z, upper->z, shift);
  267. }
  268. break;
  269. case 'd':
  270. mpz_fdiv_q_2exp(upper->z, upper->z, shift);
  271. break;
  272. case 'u':
  273. mpz_cdiv_q_2exp(upper->z, upper->z, shift);
  274. break;
  275. case 'n':
  276. default:
  277. mpz_tdiv_r_2exp(lower->z, upper->z, shift);
  278. mpz_tdiv_q_2exp(upper->z, upper->z, shift);
  279. if (mpz_sgn(lower->z)) {
  280. /* lower is not 0 so it must have at least 1 bit set */
  281. if (mpz_sizeinbase(lower->z, 2)==shift) {
  282. /* lower is >= 1/2 */
  283. if (mpz_scan1(lower->z, 0)==shift-1) {
  284. /* lower is exactly 1/2 */
  285. if (mpz_odd_p(upper->z))
  286. carry = 1;
  287. }
  288. else {
  289. carry = 1;
  290. }
  291. }
  292. }
  293. if (carry)
  294. mpz_add_ui(upper->z, upper->z, 1);
  295. }
  296. if (!(tmp = PyIntOrLong_FromSI(shift))) {
  297. Py_DECREF((PyObject*)upper);
  298. Py_DECREF((PyObject*)lower);
  299. return NULL;
  300. }
  301. if (!(newexp = PyNumber_Add(exp, tmp))) {
  302. Py_DECREF((PyObject*)man);
  303. Py_DECREF((PyObject*)upper);
  304. Py_DECREF((PyObject*)lower);
  305. Py_DECREF(tmp);
  306. return NULL;
  307. }
  308. Py_DECREF(tmp);
  309. bc = prec;
  310. }
  311. else {
  312. newexp = exp;
  313. Py_INCREF(newexp);
  314. }
  315. /* Strip trailing 0 bits. */
  316. if ((zbits = mpz_scan1(upper->z, 0)))
  317. mpz_tdiv_q_2exp(upper->z, upper->z, zbits);
  318. if (!(tmp = PyIntOrLong_FromSI(zbits))) {
  319. Py_DECREF((PyObject*)man);
  320. Py_DECREF((PyObject*)upper);
  321. Py_DECREF((PyObject*)lower);
  322. Py_DECREF(newexp);
  323. return NULL;
  324. }
  325. if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
  326. Py_DECREF((PyObject*)man);
  327. Py_DECREF((PyObject*)upper);
  328. Py_DECREF((PyObject*)lower);
  329. Py_DECREF(tmp);
  330. Py_DECREF(newexp);
  331. return NULL;
  332. }
  333. Py_DECREF(newexp);
  334. Py_DECREF(tmp);
  335. bc -= zbits;
  336. /* Check if one less than a power of 2 was rounded up. */
  337. if (!mpz_cmp_ui(upper->z, 1))
  338. bc = 1;
  339. Py_DECREF((PyObject*)lower);
  340. Py_DECREF((PyObject*)man);
  341. return mpmath_build_mpf(sign, upper, newexp2, bc);
  342. }