PageRenderTime 115ms CodeModel.GetById 21ms RepoModel.GetById 2ms app.codeStats 0ms

/src/gmpy_context.c

http://gmpy.googlecode.com/
C | 1210 lines | 1056 code | 105 blank | 49 comment | 192 complexity | b6d49f7521d13f2626efc8d864dc6753 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, LGPL-2.1
  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2. * gmpy_context.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. /* A GMPyContextObject contains an instance of the C struct gmpy_context
  28. * and a PyObject* used to reference the enclosing instance when used as a
  29. * context manager in Python.
  30. *
  31. * gmpy2 uses a global pointer "context" to refer to the active
  32. * GMPyContextObject.
  33. *
  34. * WARNING: The context manager is not thread-safe. This may be fixed in a
  35. * future version.
  36. */
  37. /* Create and delete Context objects. */
  38. static PyObject *
  39. GMPyContext_new(void)
  40. {
  41. GMPyContextObject *result;
  42. if ((result = PyObject_New(GMPyContextObject, &GMPyContext_Type))) {
  43. result->ctx.mpfr_prec = DBL_MANT_DIG;
  44. result->ctx.mpfr_round = MPFR_RNDN;
  45. result->ctx.emax = MPFR_EMAX_DEFAULT;
  46. result->ctx.emin = MPFR_EMIN_DEFAULT;
  47. result->ctx.subnormalize = 0;
  48. result->ctx.underflow = 0;
  49. result->ctx.overflow = 0;
  50. result->ctx.inexact = 0;
  51. result->ctx.invalid = 0;
  52. result->ctx.erange = 0;
  53. result->ctx.divzero = 0;
  54. result->ctx.trap_underflow = 0;
  55. result->ctx.trap_overflow = 0;
  56. result->ctx.trap_inexact = 0;
  57. result->ctx.trap_invalid = 0;
  58. result->ctx.trap_erange = 0;
  59. result->ctx.trap_divzero = 0;
  60. result->ctx.trap_expbound = 0;
  61. #ifdef WITHMPC
  62. result->ctx.real_prec = -1;
  63. result->ctx.imag_prec = -1;
  64. result->ctx.real_round = -1;
  65. result->ctx.imag_round = -1;
  66. result->ctx.allow_complex = 0;
  67. #endif
  68. }
  69. return (PyObject*)result;
  70. };
  71. static void
  72. GMPyContext_dealloc(GMPyContextObject *self)
  73. {
  74. PyObject_Del(self);
  75. };
  76. PyDoc_STRVAR(doc_context_ieee,
  77. "ieee(bitwidth) -> context\n\n"
  78. "Return a new context corresponding to a standard IEEE floating point\n"
  79. "format. The currently supported precisions are 32, 64, and 128 bits.");
  80. static PyObject *
  81. GMPyContext_ieee(PyObject *self, PyObject *other)
  82. {
  83. long bitwidth;
  84. GMPyContextObject *result;
  85. bitwidth = PyIntOrLong_AsLong(other);
  86. if (bitwidth == -1 && PyErr_Occurred()) {
  87. TYPE_ERROR("ieee() requires 'int' argument");
  88. return NULL;
  89. }
  90. if (bitwidth == 32) {
  91. result = (GMPyContextObject*)GMPyContext_new();
  92. if (result) {
  93. result->ctx.subnormalize = 1;
  94. result->ctx.mpfr_prec = 24;
  95. result->ctx.emax = 128;
  96. result->ctx.emin = -148;
  97. }
  98. return (PyObject*)result;
  99. }
  100. else if (bitwidth == 64) {
  101. result = (GMPyContextObject*)GMPyContext_new();
  102. if (result) {
  103. result->ctx.subnormalize = 1;
  104. result->ctx.mpfr_prec = 53;
  105. result->ctx.emax = 1024;
  106. result->ctx.emin = -1073;
  107. }
  108. return (PyObject*)result;
  109. }
  110. else if (bitwidth == 128) {
  111. result = (GMPyContextObject*)GMPyContext_new();
  112. if (result) {
  113. result->ctx.subnormalize = 1;
  114. result->ctx.mpfr_prec = 113;
  115. result->ctx.emax = 16384;
  116. result->ctx.emin = -16493;
  117. }
  118. return (PyObject*)result;
  119. }
  120. else {
  121. VALUE_ERROR("bitwidth must be 32, 64, or 128");
  122. return NULL;
  123. }
  124. }
  125. /* Create and delete ContextManager objects. */
  126. static PyObject *
  127. GMPyContextManager_new(void)
  128. {
  129. return (PyObject*)PyObject_New(GMPyContextManagerObject,
  130. &GMPyContextManager_Type);
  131. };
  132. static void
  133. GMPyContextManager_dealloc(GMPyContextManagerObject *self)
  134. {
  135. PyObject_Del(self);
  136. };
  137. /* Helper function to convert to convert a rounding mode to a string. */
  138. static PyObject *
  139. _round_to_name(int val)
  140. {
  141. if (val == MPFR_RNDN) return Py2or3String_FromString("RoundToNearest");
  142. if (val == MPFR_RNDZ) return Py2or3String_FromString("RoundToZero");
  143. if (val == MPFR_RNDU) return Py2or3String_FromString("RoundUp");
  144. if (val == MPFR_RNDD) return Py2or3String_FromString("RoundDown");
  145. if (val == MPFR_RNDA) return Py2or3String_FromString("RoundAwayZero");
  146. if (val == GMPY_DEFAULT) return Py2or3String_FromString("Default");
  147. return NULL;
  148. };
  149. static PyObject *
  150. GMPyContext_repr(GMPyContextObject *self)
  151. {
  152. PyObject *format;
  153. PyObject *tuple;
  154. PyObject *result = NULL;
  155. int i = 0;
  156. #ifdef WITHMPC
  157. tuple = PyTuple_New(23);
  158. #else
  159. tuple = PyTuple_New(18);
  160. #endif
  161. if (!tuple) return NULL;
  162. #ifdef WITHMPC
  163. format = Py2or3String_FromString(
  164. "context(precision=%s, real_prec=%s, imag_prec=%s,\n"
  165. " round=%s, real_round=%s, imag_round=%s,\n"
  166. " emax=%s, emin=%s,\n"
  167. " subnormalize=%s,\n"
  168. " trap_underflow=%s, underflow=%s,\n"
  169. " trap_overflow=%s, overflow=%s,\n"
  170. " trap_inexact=%s, inexact=%s,\n"
  171. " trap_invalid=%s, invalid=%s,\n"
  172. " trap_erange=%s, erange=%s,\n"
  173. " trap_divzero=%s, divzero=%s,\n"
  174. " trap_expbound=%s,\n"
  175. " allow_complex=%s)"
  176. );
  177. #else
  178. format = Py2or3String_FromString(
  179. "context(precision=%s,\n"
  180. " round=%s,\n"
  181. " emax=%s, emin=%s,\n"
  182. " subnormalize=%s,\n"
  183. " trap_underflow=%s, underflow=%s,\n"
  184. " trap_overflow=%s, overflow=%s,\n"
  185. " trap_inexact=%s, inexact=%s,\n"
  186. " trap_invalid=%s, invalid=%s,\n"
  187. " trap_erange=%s, erange=%s,\n"
  188. " trap_divzero=%s, divzero=%s,\n"
  189. " trap_expbound=%s)"
  190. );
  191. #endif
  192. if (!format) {
  193. Py_DECREF(tuple);
  194. return NULL;
  195. }
  196. PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.mpfr_prec));
  197. #ifdef WITHMPC
  198. if (self->ctx.real_prec == GMPY_DEFAULT)
  199. PyTuple_SET_ITEM(tuple, i++, Py2or3String_FromString("Default"));
  200. else
  201. PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.real_prec));
  202. if (self->ctx.imag_prec == GMPY_DEFAULT)
  203. PyTuple_SET_ITEM(tuple, i++, Py2or3String_FromString("Default"));
  204. else
  205. PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.imag_prec));
  206. #endif
  207. PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.mpfr_round));
  208. #ifdef WITHMPC
  209. PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.real_round));
  210. PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.imag_round));
  211. #endif
  212. PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.emax));
  213. PyTuple_SET_ITEM(tuple, i++, PyIntOrLong_FromLong(self->ctx.emin));
  214. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.subnormalize));
  215. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_underflow));
  216. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.underflow));
  217. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_overflow));
  218. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.overflow));
  219. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_inexact));
  220. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.inexact));
  221. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_invalid));
  222. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.invalid));
  223. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_erange));
  224. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.erange));
  225. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_divzero));
  226. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.divzero));
  227. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.trap_expbound));
  228. #ifdef WITHMPC
  229. PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.allow_complex));
  230. #endif
  231. if (!PyErr_Occurred())
  232. result = Py2or3String_Format(format, tuple);
  233. else
  234. SYSTEM_ERROR("internal error in GMPyContext_repr");
  235. Py_DECREF(format);
  236. Py_DECREF(tuple);
  237. return result;
  238. };
  239. static PyObject *
  240. GMPyContextManager_repr(GMPyContextManagerObject *self)
  241. {
  242. return Py_BuildValue("s", "<gmpy2.ContextManagerObject>");
  243. }
  244. PyDoc_STRVAR(doc_get_context,
  245. "get_context() -> gmpy2 context\n\n"
  246. "Return a reference to the current context.");
  247. static PyObject *
  248. GMPyContext_get_context(PyObject *self, PyObject *args)
  249. {
  250. Py_INCREF((PyObject*)context);
  251. return (PyObject*)context;
  252. }
  253. PyDoc_STRVAR(doc_context_copy,
  254. "context.copy() -> gmpy2 context\n\n"
  255. "Return a copy of a context.");
  256. static PyObject *
  257. GMPyContext_context_copy(PyObject *self, PyObject *other)
  258. {
  259. GMPyContextObject *result;
  260. result = (GMPyContextObject*)GMPyContext_new();
  261. result->ctx = ((GMPyContextObject*)self)->ctx;
  262. return (PyObject*)result;
  263. }
  264. PyDoc_STRVAR(doc_local_context,
  265. "local_context([context[,keywords]]) -> context manager\n\n"
  266. "Create a context manager object that will restore the current context\n"
  267. "when the 'with ...' block terminates. The temporary context for the\n"
  268. "'with ...' block is based on the current context if no context is\n"
  269. "specified. Keyword arguments are supported and will modify the\n"
  270. "temporary new context.");
  271. static PyObject *
  272. GMPyContext_local_context(PyObject *self, PyObject *args, PyObject *kwargs)
  273. {
  274. GMPyContextManagerObject *result;
  275. PyObject *local_args = args;
  276. int arg_context = 0;
  277. #ifdef WITHMPC
  278. static char *kwlist[] = {
  279. "precision", "real_prec", "imag_prec", "round",
  280. "real_round", "imag_round", "emax", "emin", "subnormalize",
  281. "trap_underflow", "trap_overflow", "trap_inexact",
  282. "trap_invalid", "trap_erange", "trap_divzero",
  283. "trap_expbound", "allow_complex", NULL };
  284. #else
  285. static char *kwlist[] = {
  286. "precision", "round", "emax", "emin", "subnormalize",
  287. "trap_underflow", "trap_overflow", "trap_inexact",
  288. "trap_invalid", "trap_erange", "trap_divzero", "trap_expbound",
  289. NULL };
  290. #endif
  291. if (PyTuple_GET_SIZE(args) == 1 && GMPyContext_Check(PyTuple_GET_ITEM(args, 0))) {
  292. arg_context = 1;
  293. if (!(local_args = PyTuple_New(0)))
  294. return NULL;
  295. }
  296. else if (PyTuple_GET_SIZE(args)) {
  297. VALUE_ERROR("local_context() only supports [context[,keyword]] arguments");
  298. return NULL;
  299. }
  300. if (!(result = (GMPyContextManagerObject*)GMPyContextManager_new()))
  301. return NULL;
  302. if (arg_context) {
  303. result->new_ctx = ((GMPyContextObject*)PyTuple_GET_ITEM(args, 0))->ctx;
  304. }
  305. else {
  306. result->new_ctx = context->ctx;
  307. }
  308. result->old_ctx = context->ctx;
  309. #ifdef WITHMPC
  310. if (!(PyArg_ParseTupleAndKeywords(local_args, kwargs,
  311. "|llliiilliiiiiiiii", kwlist,
  312. &result->new_ctx.mpfr_prec,
  313. &result->new_ctx.real_prec,
  314. &result->new_ctx.imag_prec,
  315. &result->new_ctx.mpfr_round,
  316. &result->new_ctx.real_round,
  317. &result->new_ctx.imag_round,
  318. &result->new_ctx.emax,
  319. &result->new_ctx.emin,
  320. &result->new_ctx.subnormalize,
  321. &result->new_ctx.trap_underflow,
  322. &result->new_ctx.trap_overflow,
  323. &result->new_ctx.trap_inexact,
  324. &result->new_ctx.trap_invalid,
  325. &result->new_ctx.trap_erange,
  326. &result->new_ctx.trap_divzero,
  327. &result->new_ctx.trap_expbound,
  328. &result->new_ctx.allow_complex))) {
  329. #else
  330. if (!(PyArg_ParseTupleAndKeywords(local_args, kwargs,
  331. "|lilliiiiiiii", kwlist,
  332. &result->new_ctx.mpfr_prec,
  333. &result->new_ctx.mpfr_round,
  334. &result->new_ctx.emax,
  335. &result->new_ctx.emin,
  336. &result->new_ctx.subnormalize,
  337. &result->new_ctx.trap_underflow,
  338. &result->new_ctx.trap_overflow,
  339. &result->new_ctx.trap_inexact,
  340. &result->new_ctx.trap_invalid,
  341. &result->new_ctx.trap_erange,
  342. &result->new_ctx.trap_divzero,
  343. &result->new_ctx.trap_expbound))) {
  344. #endif
  345. VALUE_ERROR("invalid keyword arguments in local_context()");
  346. goto error;
  347. }
  348. /* Sanity check for values. */
  349. if (result->new_ctx.mpfr_prec < MPFR_PREC_MIN ||
  350. result->new_ctx.mpfr_prec > MPFR_PREC_MAX) {
  351. VALUE_ERROR("invalid value for precision");
  352. goto error;
  353. }
  354. #ifdef WITHMPC
  355. if (!(result->new_ctx.real_prec == GMPY_DEFAULT ||
  356. (result->new_ctx.real_prec >= MPFR_PREC_MIN &&
  357. result->new_ctx.real_prec <= MPFR_PREC_MAX))) {
  358. VALUE_ERROR("invalid value for real_prec");
  359. goto error;
  360. }
  361. if (!(result->new_ctx.imag_prec == GMPY_DEFAULT ||
  362. (result->new_ctx.imag_prec >= MPFR_PREC_MIN &&
  363. result->new_ctx.imag_prec <= MPFR_PREC_MAX))) {
  364. VALUE_ERROR("invalid value for imag_prec");
  365. goto error;
  366. }
  367. #endif
  368. if (!(result->new_ctx.mpfr_round == MPFR_RNDN ||
  369. result->new_ctx.mpfr_round == MPFR_RNDZ ||
  370. result->new_ctx.mpfr_round == MPFR_RNDU ||
  371. result->new_ctx.mpfr_round == MPFR_RNDD ||
  372. result->new_ctx.mpfr_round == MPFR_RNDA)) {
  373. VALUE_ERROR("invalid value for round");
  374. goto error;
  375. }
  376. #ifdef WITHMPC
  377. if (result->new_ctx.mpfr_round == MPFR_RNDA) {
  378. /* Since RNDA is not supported for MPC, set the MPC rounding modes
  379. * to MPFR_RNDN.
  380. */
  381. result->new_ctx.real_round = MPFR_RNDN;
  382. result->new_ctx.imag_round = MPFR_RNDN;
  383. }
  384. if (!(result->new_ctx.real_round == MPFR_RNDN ||
  385. result->new_ctx.real_round == MPFR_RNDZ ||
  386. result->new_ctx.real_round == MPFR_RNDU ||
  387. result->new_ctx.real_round == MPFR_RNDD ||
  388. result->new_ctx.real_round == GMPY_DEFAULT)) {
  389. VALUE_ERROR("invalid value for real_round");
  390. goto error;
  391. }
  392. if (!(result->new_ctx.imag_round == MPFR_RNDN ||
  393. result->new_ctx.imag_round == MPFR_RNDZ ||
  394. result->new_ctx.imag_round == MPFR_RNDU ||
  395. result->new_ctx.imag_round == MPFR_RNDD ||
  396. result->new_ctx.imag_round == GMPY_DEFAULT)) {
  397. VALUE_ERROR("invalid value for imag_round");
  398. goto error;
  399. }
  400. #endif
  401. if (!(result->new_ctx.emin < 0 && result->new_ctx.emax > 0)) {
  402. VALUE_ERROR("invalid values for emin and/or emax");
  403. goto error;
  404. }
  405. if (mpfr_set_emin(result->new_ctx.emin)) {
  406. VALUE_ERROR("invalid value for emin");
  407. goto error;
  408. }
  409. if (mpfr_set_emax(result->new_ctx.emax)) {
  410. VALUE_ERROR("invalid value for emax");
  411. goto error;
  412. }
  413. if (arg_context) {
  414. Py_DECREF(local_args);
  415. }
  416. return (PyObject*)result;
  417. error:
  418. if (arg_context) {
  419. Py_DECREF(local_args);
  420. }
  421. Py_DECREF((PyObject*)result);
  422. return NULL;
  423. }
  424. #ifdef WITHMPC
  425. PyDoc_STRVAR(doc_context,
  426. "context() -> context manager\n\n"
  427. "Return a new context for controlling MPFR and MPC arithmetic. To load\n"
  428. "the new context, use set_context(). Options can only be specified as\n"
  429. "keyword arguments. \n\n"
  430. " precision: precision, in bits, of an MPFR result\n"
  431. " real_prec: precision, in bits, of Re(MPC)\n"
  432. " -1 implies use mpfr_prec\n"
  433. " imag_prec: precision, in bits, of Im(MPC)\n"
  434. " -1 implies use real_prec\n"
  435. " round: rounding mode for MPFR\n"
  436. " real_round: rounding mode for Re(MPC)\n"
  437. " -1 implies use mpfr_round\n"
  438. " imag_round: rounding mode for Im(MPC)\n"
  439. " -1 implies use real_round\n"
  440. " e_max: maximum allowed exponent\n"
  441. " e_min: minimum allowed exponent\n"
  442. " subnormalize: if True, subnormalized results can be returned\n"
  443. " trap_underflow: if True, raise exception for underflow\n"
  444. " if False, set underflow flag\n"
  445. " trap_overflow: if True, raise exception for overflow\n"
  446. " if False, set overflow flag and return Inf or -Inf\n"
  447. " trap_inexact: if True, raise exception for inexact result\n"
  448. " if False, set inexact flag\n"
  449. " trap_invalid: if True, raise exception for invalid operation\n"
  450. " if False, set invalid flag and return NaN\n"
  451. " trap_erange: if True, raise exception for range error\n"
  452. " if False, set erange flag\n"
  453. " trap_divzero: if True, raise exception for division by zero\n"
  454. " if False, set divzero flag and return Inf or -Inf\n"
  455. " trap_expbound: if True, raise exception when mpfr/mpc exponent\n"
  456. " no longer valid in current context\n"
  457. " if False, mpfr/mpc with exponent out-of-bounds\n"
  458. " will be coerced to either 0 or Infinity\n"
  459. " allow_complex: if True, allow mpfr functions to return mpc\n"
  460. " if False, mpfr functions cannot return an mpc\n");
  461. #else
  462. PyDoc_STRVAR(doc_context,
  463. "context() -> context\n\n"
  464. "Return a new context for controlling MPFR arithmetic. To load the\n"
  465. "new context, use set_context(). Options can only be specified as\n"
  466. "keyword arguments. \n\n"
  467. " precision: precision, in bits, of an MPFR result\n"
  468. " round: rounding mode for MPFR\n"
  469. " e_max: maximum allowed exponent\n"
  470. " e_min: minimum allowed exponent\n"
  471. " subnormalize: if True, subnormalized results can be returned\n"
  472. " trap_underflow: if True, raise exception for underflow\n"
  473. " if False, set underflow flag\n"
  474. " trap_overflow: if True, raise exception for overflow\n"
  475. " if False, set overflow flag and return Inf or -Inf\n"
  476. " trap_inexact: if True, raise exception for inexact result\n"
  477. " if False, set inexact flag\n"
  478. " trap_invalid: if True, raise exception for invalid operation\n"
  479. " if False, set invalid flag and return NaN\n"
  480. " trap_erange: if True, raise exception for range error\n"
  481. " if False, set erange flag\n"
  482. " trap_divzero: if True, raise exception for division by zero\n"
  483. " if False, set divzero flag and return Inf or -Inf\n"
  484. " trap_expbound: if True, raise exception when mpfr/mpc exponent\n"
  485. " no longer valid in current context\n"
  486. " if False, mpfr/mpc with exponent out-of-bounds will\n"
  487. " coerced to either 0 or Infinity\n");
  488. #endif
  489. static PyObject *
  490. GMPyContext_context(PyObject *self, PyObject *args, PyObject *kwargs)
  491. {
  492. GMPyContextObject *result;
  493. #ifdef WITHMPC
  494. static char *kwlist[] = {
  495. "precision", "real_prec", "imag_prec", "round",
  496. "real_round", "imag_round", "emax", "emin", "subnormalize",
  497. "trap_underflow", "trap_overflow", "trap_inexact",
  498. "trap_invalid", "trap_erange", "trap_divzero", "trap_expbound",
  499. "allow_complex", NULL };
  500. #else
  501. static char *kwlist[] = {
  502. "precision", "round", "emax", "emin", "subnormalize",
  503. "trap_underflow", "trap_overflow", "trap_inexact",
  504. "trap_invalid", "trap_erange", "trap_divzero",
  505. "trap_expbound", NULL };
  506. #endif
  507. if (PyTuple_GET_SIZE(args)) {
  508. VALUE_ERROR("context() only supports keyword arguments");
  509. return NULL;
  510. }
  511. if (!(result = (GMPyContextObject*)GMPyContext_new()))
  512. return NULL;
  513. #ifdef WITHMPC
  514. if (!(PyArg_ParseTupleAndKeywords(args, kwargs,
  515. "|llliiilliiiiiiiii", kwlist,
  516. &result->ctx.mpfr_prec,
  517. &result->ctx.real_prec,
  518. &result->ctx.imag_prec,
  519. &result->ctx.mpfr_round,
  520. &result->ctx.real_round,
  521. &result->ctx.imag_round,
  522. &result->ctx.emax,
  523. &result->ctx.emin,
  524. &result->ctx.subnormalize,
  525. &result->ctx.trap_underflow,
  526. &result->ctx.trap_overflow,
  527. &result->ctx.trap_inexact,
  528. &result->ctx.trap_invalid,
  529. &result->ctx.trap_erange,
  530. &result->ctx.trap_divzero,
  531. &result->ctx.trap_expbound,
  532. &result->ctx.allow_complex))) {
  533. #else
  534. if (!(PyArg_ParseTupleAndKeywords(args, kwargs,
  535. "|lilliiiiiiii", kwlist,
  536. &result->ctx.mpfr_prec,
  537. &result->ctx.mpfr_round,
  538. &result->ctx.emax,
  539. &result->ctx.emin,
  540. &result->ctx.subnormalize,
  541. &result->ctx.trap_underflow,
  542. &result->ctx.trap_overflow,
  543. &result->ctx.trap_inexact,
  544. &result->ctx.trap_invalid,
  545. &result->ctx.trap_erange,
  546. &result->ctx.trap_divzero,
  547. &result->ctx.trap_expbound))) {
  548. #endif
  549. VALUE_ERROR("invalid keyword arguments in context()");
  550. return NULL;
  551. }
  552. /* Sanity check for values. */
  553. if (result->ctx.mpfr_prec < MPFR_PREC_MIN ||
  554. result->ctx.mpfr_prec > MPFR_PREC_MAX) {
  555. Py_DECREF((PyObject*)result);
  556. VALUE_ERROR("invalid value for precision");
  557. return NULL;
  558. }
  559. #ifdef WITHMPC
  560. if (!(result->ctx.real_prec == GMPY_DEFAULT ||
  561. (result->ctx.real_prec >= MPFR_PREC_MIN &&
  562. result->ctx.real_prec <= MPFR_PREC_MAX))) {
  563. Py_DECREF((PyObject*)result);
  564. VALUE_ERROR("invalid value for real_prec");
  565. return NULL;
  566. }
  567. if (!(result->ctx.imag_prec == GMPY_DEFAULT ||
  568. (result->ctx.imag_prec >= MPFR_PREC_MIN &&
  569. result->ctx.imag_prec <= MPFR_PREC_MAX))) {
  570. Py_DECREF((PyObject*)result);
  571. VALUE_ERROR("invalid value for imag_prec");
  572. return NULL;
  573. }
  574. #endif
  575. if (!(result->ctx.mpfr_round == MPFR_RNDN ||
  576. result->ctx.mpfr_round == MPFR_RNDZ ||
  577. result->ctx.mpfr_round == MPFR_RNDU ||
  578. result->ctx.mpfr_round == MPFR_RNDD ||
  579. result->ctx.mpfr_round == MPFR_RNDA)) {
  580. Py_DECREF((PyObject*)result);
  581. VALUE_ERROR("invalid value for round");
  582. return NULL;
  583. }
  584. #ifdef WITHMPC
  585. if (result->ctx.mpfr_round == MPFR_RNDA) {
  586. /* Since RNDA is not supported for MPC, set the MPC rounding modes
  587. to MPFR_RNDN. */
  588. result->ctx.real_round = MPFR_RNDN;
  589. result->ctx.imag_round = MPFR_RNDN;
  590. }
  591. if (!(result->ctx.real_round == MPFR_RNDN ||
  592. result->ctx.real_round == MPFR_RNDZ ||
  593. result->ctx.real_round == MPFR_RNDU ||
  594. result->ctx.real_round == MPFR_RNDD ||
  595. result->ctx.real_round == GMPY_DEFAULT)) {
  596. Py_DECREF((PyObject*)result);
  597. VALUE_ERROR("invalid value for real_round");
  598. return NULL;
  599. }
  600. if (!(result->ctx.imag_round == MPFR_RNDN ||
  601. result->ctx.imag_round == MPFR_RNDZ ||
  602. result->ctx.imag_round == MPFR_RNDU ||
  603. result->ctx.imag_round == MPFR_RNDD ||
  604. result->ctx.imag_round == GMPY_DEFAULT)) {
  605. Py_DECREF((PyObject*)result);
  606. VALUE_ERROR("invalid value for imag_round");
  607. return NULL;
  608. }
  609. #endif
  610. if (!(result->ctx.emin < 0 && result->ctx.emax > 0)) {
  611. VALUE_ERROR("invalid values for emin and/or emax");
  612. Py_DECREF((PyObject*)result);
  613. return NULL;
  614. }
  615. if (mpfr_set_emin(result->ctx.emin)) {
  616. VALUE_ERROR("invalid value for emin");
  617. Py_DECREF((PyObject*)result);
  618. return NULL;
  619. }
  620. if (mpfr_set_emax(result->ctx.emax)) {
  621. VALUE_ERROR("invalid value for emax");
  622. Py_DECREF((PyObject*)result);
  623. return NULL;
  624. }
  625. result->ctx.underflow = 0;
  626. result->ctx.overflow = 0;
  627. result->ctx.inexact = 0;
  628. result->ctx.invalid = 0;
  629. result->ctx.erange = 0;
  630. result->ctx.divzero = 0;
  631. return (PyObject*)result;
  632. }
  633. PyDoc_STRVAR(doc_set_context,
  634. "set_context(context)\n\n"
  635. "Activate a context object controlling MPFR and MPC arithmetic.\n");
  636. static PyObject *
  637. GMPyContext_set_context(PyObject *self, PyObject *other)
  638. {
  639. if (GMPyContext_Check(other)) {
  640. Py_INCREF((PyObject*)other);
  641. Py_DECREF((PyObject*)context);
  642. context = (GMPyContextObject*)other;
  643. mpfr_set_emin(context->ctx.emin);
  644. mpfr_set_emax(context->ctx.emax);
  645. Py_RETURN_NONE;
  646. }
  647. else {
  648. VALUE_ERROR("set_context() requires a context argument");
  649. return NULL;
  650. }
  651. }
  652. static PyObject *
  653. GMPyContextManager_enter(PyObject *self, PyObject *args)
  654. {
  655. GMPyContextObject *result;
  656. if (!(result = (GMPyContextObject*)GMPyContext_new()))
  657. return NULL;
  658. result->ctx = ((GMPyContextManagerObject*)self)->new_ctx;
  659. Py_DECREF((PyObject*)context);
  660. context = (GMPyContextObject*)result;
  661. Py_INCREF((PyObject*)context);
  662. mpfr_set_emin(context->ctx.emin);
  663. mpfr_set_emax(context->ctx.emax);
  664. return (PyObject*)result;
  665. }
  666. static PyObject *
  667. GMPyContextManager_exit(PyObject *self, PyObject *args)
  668. {
  669. GMPyContextObject *result;
  670. if (!(result = (GMPyContextObject*)GMPyContext_new()))
  671. return NULL;
  672. result->ctx = ((GMPyContextManagerObject*)self)->old_ctx;
  673. Py_DECREF((PyObject*)context);
  674. context = (GMPyContextObject*)result;
  675. mpfr_set_emin(context->ctx.emin);
  676. mpfr_set_emax(context->ctx.emax);
  677. Py_RETURN_NONE;
  678. }
  679. static PyObject *
  680. GMPyContext_enter(PyObject *self, PyObject *args)
  681. {
  682. GMPyContextObject *result;
  683. if (!(result = (GMPyContextObject*)GMPyContext_new()))
  684. return NULL;
  685. result->ctx = ((GMPyContextObject*)self)->ctx;
  686. Py_DECREF((PyObject*)context);
  687. context = (GMPyContextObject*)result;
  688. Py_INCREF((PyObject*)context);
  689. mpfr_set_emin(context->ctx.emin);
  690. mpfr_set_emax(context->ctx.emax);
  691. return (PyObject*)result;
  692. }
  693. static PyObject *
  694. GMPyContext_exit(PyObject *self, PyObject *args)
  695. {
  696. Py_DECREF((PyObject*)context);
  697. context = (GMPyContextObject*)self;
  698. Py_INCREF((PyObject*)context);
  699. mpfr_set_emin(context->ctx.emin);
  700. mpfr_set_emax(context->ctx.emax);
  701. Py_RETURN_NONE;
  702. }
  703. PyDoc_STRVAR(doc_context_clear_flags,
  704. "clear_flags()\n\n"
  705. "Clear all MPFR exception flags.");
  706. static PyObject *
  707. GMPyContext_clear_flags(PyObject *self, PyObject *args)
  708. {
  709. ((GMPyContextObject*)self)->ctx.underflow = 0;
  710. ((GMPyContextObject*)self)->ctx.overflow = 0;
  711. ((GMPyContextObject*)self)->ctx.inexact = 0;
  712. ((GMPyContextObject*)self)->ctx.invalid = 0;
  713. ((GMPyContextObject*)self)->ctx.erange = 0;
  714. ((GMPyContextObject*)self)->ctx.divzero = 0;
  715. Py_RETURN_NONE;
  716. }
  717. /* Define the get/set functions. */
  718. #define GETSET_BOOLEAN(NAME) \
  719. static PyObject * \
  720. GMPyContext_get_##NAME(GMPyContextObject *self, void *closure) \
  721. { \
  722. return PyBool_FromLong(self->ctx.NAME); \
  723. }; \
  724. static int \
  725. GMPyContext_set_##NAME(GMPyContextObject *self, PyObject *value, void *closure) \
  726. { \
  727. if (!(PyBool_Check(value))) { \
  728. TYPE_ERROR(#NAME " must be True or False"); \
  729. return -1; \
  730. } \
  731. self->ctx.NAME = (value == Py_True) ? 1 : 0; \
  732. return 0; \
  733. }
  734. GETSET_BOOLEAN(subnormalize);
  735. GETSET_BOOLEAN(underflow);
  736. GETSET_BOOLEAN(overflow);
  737. GETSET_BOOLEAN(inexact);
  738. GETSET_BOOLEAN(invalid);
  739. GETSET_BOOLEAN(erange);
  740. GETSET_BOOLEAN(divzero);
  741. GETSET_BOOLEAN(trap_underflow);
  742. GETSET_BOOLEAN(trap_overflow);
  743. GETSET_BOOLEAN(trap_inexact);
  744. GETSET_BOOLEAN(trap_invalid);
  745. GETSET_BOOLEAN(trap_erange);
  746. GETSET_BOOLEAN(trap_divzero);
  747. GETSET_BOOLEAN(trap_expbound);
  748. #ifdef WITHMPC
  749. GETSET_BOOLEAN(allow_complex)
  750. #endif
  751. static PyObject *
  752. GMPyContext_get_precision(GMPyContextObject *self, void *closure)
  753. {
  754. return PyIntOrLong_FromSsize_t((Py_ssize_t)(self->ctx.mpfr_prec));
  755. }
  756. static int
  757. GMPyContext_set_precision(GMPyContextObject *self, PyObject *value, void *closure)
  758. {
  759. Py_ssize_t temp;
  760. if (!(PyIntOrLong_Check(value))) {
  761. TYPE_ERROR("precision must be Python integer");
  762. return -1;
  763. }
  764. temp = PyIntOrLong_AsSsize_t(value);
  765. if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX || PyErr_Occurred()) {
  766. VALUE_ERROR("invalid value for precision");
  767. return -1;
  768. }
  769. self->ctx.mpfr_prec = (mpfr_prec_t)temp;
  770. return 0;
  771. }
  772. #ifdef WITHMPC
  773. static PyObject *
  774. GMPyContext_get_real_prec(GMPyContextObject *self, void *closure)
  775. {
  776. return PyIntOrLong_FromSsize_t((Py_ssize_t)(GET_REAL_PREC(self)));
  777. }
  778. static int
  779. GMPyContext_set_real_prec(GMPyContextObject *self, PyObject *value, void *closure)
  780. {
  781. Py_ssize_t temp;
  782. if (!(PyIntOrLong_Check(value))) {
  783. TYPE_ERROR("real_prec must be Python integer");
  784. return -1;
  785. }
  786. temp = PyIntOrLong_AsSsize_t(value);
  787. if (temp == -1) {
  788. if (PyErr_Occurred()) {
  789. VALUE_ERROR("invalid value for real_prec");
  790. return -1;
  791. }
  792. }
  793. else if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
  794. VALUE_ERROR("invalid value for real_prec");
  795. return -1;
  796. }
  797. self->ctx.real_prec = (mpfr_prec_t)temp;
  798. return 0;
  799. }
  800. static PyObject *
  801. GMPyContext_get_imag_prec(GMPyContextObject *self, void *closure)
  802. {
  803. return PyIntOrLong_FromSsize_t((Py_ssize_t)(GET_IMAG_PREC(self)));
  804. }
  805. static int
  806. GMPyContext_set_imag_prec(GMPyContextObject *self, PyObject *value, void *closure)
  807. {
  808. Py_ssize_t temp;
  809. if (!(PyIntOrLong_Check(value))) {
  810. TYPE_ERROR("imag_prec must be Python integer");
  811. return -1;
  812. }
  813. temp = PyIntOrLong_AsSsize_t(value);
  814. if (temp == -1) {
  815. if (PyErr_Occurred()) {
  816. VALUE_ERROR("invalid value for imag_prec");
  817. return -1;
  818. }
  819. }
  820. else if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
  821. VALUE_ERROR("invalid value for imag_prec");
  822. return -1;
  823. }
  824. self->ctx.imag_prec = (mpfr_prec_t)temp;
  825. return 0;
  826. }
  827. #endif
  828. static PyObject *
  829. GMPyContext_get_round(GMPyContextObject *self, void *closure)
  830. {
  831. return PyIntOrLong_FromLong((long)(self->ctx.mpfr_round));
  832. }
  833. static int
  834. GMPyContext_set_round(GMPyContextObject *self, PyObject *value, void *closure)
  835. {
  836. long temp;
  837. if (!(PyIntOrLong_Check(value))) {
  838. TYPE_ERROR("round mode must be Python integer");
  839. return -1;
  840. }
  841. temp = PyIntOrLong_AsLong(value);
  842. if (temp == -1 && PyErr_Occurred()) {
  843. VALUE_ERROR("invalid value for round mode");
  844. return -1;
  845. }
  846. if (temp == MPFR_RNDN)
  847. self->ctx.mpfr_round = MPFR_RNDN;
  848. else if (temp == MPFR_RNDZ)
  849. self->ctx.mpfr_round = MPFR_RNDZ;
  850. else if (temp == MPFR_RNDU)
  851. self->ctx.mpfr_round = MPFR_RNDU;
  852. else if (temp == MPFR_RNDD)
  853. self->ctx.mpfr_round = MPFR_RNDD;
  854. else if (temp == MPFR_RNDA) {
  855. self->ctx.mpfr_round = MPFR_RNDA;
  856. #ifdef WITHMPC
  857. /* Since RNDA is not supported for MPC, set the MPC rounding modes
  858. to MPFR_RNDN. */
  859. self->ctx.real_round = MPFR_RNDN;
  860. self->ctx.imag_round = MPFR_RNDN;
  861. #endif
  862. }
  863. else {
  864. VALUE_ERROR("invalid value for round mode");
  865. return -1;
  866. }
  867. return 0;
  868. }
  869. #ifdef WITHMPC
  870. static PyObject *
  871. GMPyContext_get_real_round(GMPyContextObject *self, void *closure)
  872. {
  873. return PyIntOrLong_FromLong((long)GET_REAL_ROUND(self));
  874. }
  875. static int
  876. GMPyContext_set_real_round(GMPyContextObject *self, PyObject *value, void *closure)
  877. {
  878. long temp;
  879. if (!(PyIntOrLong_Check(value))) {
  880. TYPE_ERROR("round mode must be Python integer");
  881. return -1;
  882. }
  883. temp = PyIntOrLong_AsLong(value);
  884. if (temp == -1 && PyErr_Occurred()) {
  885. VALUE_ERROR("invalid value for round mode");
  886. return -1;
  887. }
  888. if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ ||
  889. temp == MPFR_RNDU || temp == MPFR_RNDD) {
  890. self->ctx.real_round = (int)temp;
  891. }
  892. else {
  893. VALUE_ERROR("invalid value for round mode");
  894. return -1;
  895. }
  896. return 0;
  897. }
  898. static PyObject *
  899. GMPyContext_get_imag_round(GMPyContextObject *self, void *closure)
  900. {
  901. return PyIntOrLong_FromLong((long)GET_IMAG_ROUND(self));
  902. }
  903. static int
  904. GMPyContext_set_imag_round(GMPyContextObject *self, PyObject *value, void *closure)
  905. {
  906. long temp;
  907. if (!(PyIntOrLong_Check(value))) {
  908. TYPE_ERROR("round mode must be Python integer");
  909. return -1;
  910. }
  911. temp = PyIntOrLong_AsLong(value);
  912. if (temp == -1 && PyErr_Occurred()) {
  913. VALUE_ERROR("invalid value for round mode");
  914. return -1;
  915. }
  916. if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ ||
  917. temp == MPFR_RNDU || temp == MPFR_RNDD) {
  918. self->ctx.imag_round = (int)temp;
  919. }
  920. else {
  921. VALUE_ERROR("invalid value for round mode");
  922. return -1;
  923. }
  924. return 0;
  925. }
  926. #endif
  927. static PyObject *
  928. GMPyContext_get_emin(GMPyContextObject *self, void *closure)
  929. {
  930. return PyIntOrLong_FromLong(self->ctx.emin);
  931. }
  932. static int
  933. GMPyContext_set_emin(GMPyContextObject *self, PyObject *value, void *closure)
  934. {
  935. long exp;
  936. if (!(PyIntOrLong_Check(value))) {
  937. TYPE_ERROR("emin must be Python integer");
  938. return -1;
  939. }
  940. exp = PyIntOrLong_AsLong(value);
  941. if (exp == -1 && PyErr_Occurred()) {
  942. VALUE_ERROR("requested minimum exponent is invalid");
  943. return -1;
  944. }
  945. if (mpfr_set_emin((mpfr_prec_t)exp)) {
  946. VALUE_ERROR("requested minimum exponent is invalid");
  947. return -1;
  948. }
  949. self->ctx.emin = exp;
  950. mpfr_set_emin(exp);
  951. return 0;
  952. }
  953. static PyObject *
  954. GMPyContext_get_emax(GMPyContextObject *self, void *closure)
  955. {
  956. return PyIntOrLong_FromLong(self->ctx.emax);
  957. }
  958. static int
  959. GMPyContext_set_emax(GMPyContextObject *self, PyObject *value, void *closure)
  960. {
  961. long exp;
  962. if (!(PyIntOrLong_Check(value))) {
  963. TYPE_ERROR("emax must be Python integer");
  964. return -1;
  965. }
  966. exp = PyIntOrLong_AsLong(value);
  967. if (exp == -1 && PyErr_Occurred()) {
  968. VALUE_ERROR("requested maximum exponent is invalid");
  969. return -1;
  970. }
  971. if (mpfr_set_emax((mpfr_prec_t)exp)) {
  972. VALUE_ERROR("requested maximum exponent is invalid");
  973. return -1;
  974. }
  975. self->ctx.emax = exp;
  976. mpfr_set_emax(exp);
  977. return 0;
  978. }
  979. #define ADD_GETSET(NAME) \
  980. {#NAME, \
  981. (getter)GMPyContext_get_##NAME, \
  982. (setter)GMPyContext_set_##NAME, NULL, NULL}
  983. static PyGetSetDef GMPyContext_getseters[] = {
  984. ADD_GETSET(precision),
  985. #ifdef WITHMPC
  986. ADD_GETSET(real_prec),
  987. ADD_GETSET(imag_prec),
  988. #endif
  989. ADD_GETSET(round),
  990. #ifdef WITHMPC
  991. ADD_GETSET(real_round),
  992. ADD_GETSET(imag_round),
  993. #endif
  994. ADD_GETSET(emax),
  995. ADD_GETSET(emin),
  996. ADD_GETSET(subnormalize),
  997. ADD_GETSET(underflow),
  998. ADD_GETSET(overflow),
  999. ADD_GETSET(inexact),
  1000. ADD_GETSET(invalid),
  1001. ADD_GETSET(erange),
  1002. ADD_GETSET(divzero),
  1003. ADD_GETSET(trap_underflow),
  1004. ADD_GETSET(trap_overflow),
  1005. ADD_GETSET(trap_inexact),
  1006. ADD_GETSET(trap_invalid),
  1007. ADD_GETSET(trap_erange),
  1008. ADD_GETSET(trap_divzero),
  1009. ADD_GETSET(trap_expbound),
  1010. #ifdef WITHMPC
  1011. ADD_GETSET(allow_complex),
  1012. #endif
  1013. {NULL}
  1014. };
  1015. static PyMethodDef GMPyContext_methods[] =
  1016. {
  1017. { "clear_flags", GMPyContext_clear_flags, METH_NOARGS,
  1018. doc_context_clear_flags },
  1019. { "copy", GMPyContext_context_copy, METH_NOARGS, doc_context_copy },
  1020. { "__enter__", GMPyContext_enter, METH_NOARGS, NULL },
  1021. { "__exit__", GMPyContext_exit, METH_VARARGS, NULL },
  1022. { NULL, NULL, 1 }
  1023. };
  1024. static PyTypeObject GMPyContext_Type =
  1025. {
  1026. #ifdef PY3
  1027. PyVarObject_HEAD_INIT(0, 0)
  1028. #else
  1029. PyObject_HEAD_INIT(0)
  1030. 0, /* ob_size */
  1031. #endif
  1032. "gmpy2 context", /* tp_name */
  1033. sizeof(GMPyContextObject), /* tp_basicsize */
  1034. 0, /* tp_itemsize */
  1035. (destructor) GMPyContext_dealloc, /* tp_dealloc */
  1036. 0, /* tp_print */
  1037. 0, /* tp_getattr */
  1038. 0, /* tp_setattr */
  1039. 0, /* tp_reserved */
  1040. (reprfunc) GMPyContext_repr, /* tp_repr */
  1041. 0, /* tp_as_number */
  1042. 0, /* tp_as_sequence */
  1043. 0, /* tp_as_mapping */
  1044. 0, /* tp_hash */
  1045. 0, /* tp_call */
  1046. 0, /* tp_str */
  1047. 0, /* tp_getattro */
  1048. 0, /* tp_setattro */
  1049. 0, /* tp_as_buffer */
  1050. Py_TPFLAGS_DEFAULT, /* tp_flags */
  1051. "GMPY2 Context Object", /* tp_doc */
  1052. 0, /* tp_traverse */
  1053. 0, /* tp_clear */
  1054. 0, /* tp_richcompare */
  1055. 0, /* tp_weaklistoffset*/
  1056. 0, /* tp_iter */
  1057. 0, /* tp_iternext */
  1058. GMPyContext_methods, /* tp_methods */
  1059. 0, /* tp_members */
  1060. GMPyContext_getseters, /* tp_getset */
  1061. };
  1062. static PyMethodDef GMPyContextManager_methods[] =
  1063. {
  1064. { "__enter__", GMPyContextManager_enter, METH_NOARGS, NULL },
  1065. { "__exit__", GMPyContextManager_exit, METH_VARARGS, NULL },
  1066. { NULL, NULL, 1 }
  1067. };
  1068. static PyTypeObject GMPyContextManager_Type =
  1069. {
  1070. #ifdef PY3
  1071. PyVarObject_HEAD_INIT(0, 0)
  1072. #else
  1073. PyObject_HEAD_INIT(0)
  1074. 0, /* ob_size */
  1075. #endif
  1076. "gmpy2 context", /* tp_name */
  1077. sizeof(GMPyContextManagerObject), /* tp_basicsize */
  1078. 0, /* tp_itemsize */
  1079. (destructor) GMPyContextManager_dealloc, /* tp_dealloc */
  1080. 0, /* tp_print */
  1081. 0, /* tp_getattr */
  1082. 0, /* tp_setattr */
  1083. 0, /* tp_reserved */
  1084. (reprfunc) GMPyContextManager_repr, /* tp_repr */
  1085. 0, /* tp_as_number */
  1086. 0, /* tp_as_sequence */
  1087. 0, /* tp_as_mapping */
  1088. 0, /* tp_hash */
  1089. 0, /* tp_call */
  1090. 0, /* tp_str */
  1091. 0, /* tp_getattro */
  1092. 0, /* tp_setattro */
  1093. 0, /* tp_as_buffer */
  1094. Py_TPFLAGS_DEFAULT, /* tp_flags */
  1095. "GMPY2 Context manager", /* tp_doc */
  1096. 0, /* tp_traverse */
  1097. 0, /* tp_clear */
  1098. 0, /* tp_richcompare */
  1099. 0, /* tp_weaklistoffset*/
  1100. 0, /* tp_iter */
  1101. 0, /* tp_iternext */
  1102. GMPyContextManager_methods, /* tp_methods */
  1103. 0, /* tp_members */
  1104. 0, /* tp_getset */
  1105. };