From: Alex M. <al...@us...> - 2006-02-26 07:08:23
|
Update of /cvsroot/gmpy/gmpy/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12984/src Modified Files: gmpy.c Log Message: Added experimental support for decimal.Decimal, etc - version now 1.02 (rc) Index: gmpy.c =================================================================== RCS file: /cvsroot/gmpy/gmpy/src/gmpy.c,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** gmpy.c 26 Feb 2006 06:44:19 -0000 1.18 --- gmpy.c 26 Feb 2006 07:08:18 -0000 1.19 *************** *** 9,12 **** --- 9,13 ---- * cleanups & reorgs leading to 1.0: Alex Martelli (until Aug 2003) * further cleanups and bugfixes leading to 1.01, Alex Martelli (Nov 2005) + * minor bugfixes+new decimal (&c) support to 1.02, Alex Martelli (Feb 2006) * * Some hacks by Gustavo Niemeyer <nie...@co...>. *************** *** 105,109 **** * 1.0: * minor cleanups, ensure support for Python 2.3 ! * fixed misdiagnosis of some argument couns in macro * SELF_ONE_ARG_CONVERTED (tx to Paul Rubin!) * --- 106,110 ---- * 1.0: * minor cleanups, ensure support for Python 2.3 ! * fixed misdiagnosis of some argument counts in macro * SELF_ONE_ARG_CONVERTED (tx to Paul Rubin!) * *************** *** 118,121 **** --- 119,126 ---- * 1.02: * fix warning in comparison of mpq's + * added support of mpq('12.34') [[string w/o a slash, but with a dot]] + * added experimental support for decimal.Decimal (and user-coded types) + * via wider use of special conversion methods (if present) and their + * sly insertion on-the-fly into the decimal.Decimal class (!) * */ *************** *** 142,146 **** #endif ! char gmpy_version[] = "1.01"; char _gmpy_cvs[] = "$Id$"; --- 147,151 ---- #endif ! char gmpy_version[] = "1.02"; char _gmpy_cvs[] = "$Id$"; *************** *** 1094,1097 **** --- 1099,1105 ---- * denominator (if none, just numerator!); decimal point NOT allowed. * + * Added in gmpy 1.02: also support a string of the form '12.34', i.e., + * WITH a decimal point and WITHOUT a slash + * * Binary-form: 4-byte numerator length (upper bit set if <0), then * numerator (as above for mpz), then denominator (ditto). *************** *** 1169,1173 **** --- 1177,1193 ---- { char* whereslash = strchr((char*)cp,'/'); + char* wheredot = 0; if(whereslash) *whereslash = 0; + else { + wheredot = strchr((char*)cp, '.'); + if(wheredot) { + PympfObject* temp = str2mpf(stringarg, base, 4*len); + if(temp) { + newob = mpf2mpq((PyObject*)temp); + Py_DECREF((PyObject*)temp); + } + return newob; + } + } if(-1 == mpz_set_str(mpq_numref(newob->q), (char*)cp, base)) { if(whereslash) *whereslash = '/'; *************** *** 2048,2052 **** --- 2068,2082 ---- } else if(PyLong_Check(obj)) { newob = long2mpq(obj); + } else if(PyObject_HasAttrString(obj, "__gmpy_q__")) { + PyObject* result = PyObject_CallMethod(obj, "__gmpy_q__", ""); + if(result) { + if(Pympq_Check(result)) { + newob = (PympqObject *)result; + } else { + Py_DECREF(result); + } + } } + if(options.debug) fprintf(stderr,"any2mpq(%p)->%p\n", obj, newob); *************** *** 2073,2076 **** --- 2103,2115 ---- } else if(PyFloat_Check(obj)) { newob = float2mpz(obj); + } else if(PyObject_HasAttrString(obj, "__gmpy_z__")) { + PyObject* result = PyObject_CallMethod(obj, "__gmpy_z__", ""); + if(result) { + if(Pympz_Check(result)) { + newob = (PympzObject *)result; + } else { + Py_DECREF(result); + } + } } if(options.debug) *************** *** 2102,2106 **** --- 2141,2155 ---- } else if(PyLong_Check(obj)) { newob = long2mpf(obj, bits); + } else if(PyObject_HasAttrString(obj, "__gmpy_f__")) { + PyObject* result = PyObject_CallMethod(obj, "__gmpy_f__", ""); + if(result) { + if(Pympf_Check(result)) { + newob = (PympfObject *)result; + } else { + Py_DECREF(result); + } + } } + if(options.debug) fprintf(stderr, "anynum2mpf(%p,%d)->%p (%d)\n", obj, *************** *** 2145,2150 **** return 1; } else { ! PyErr_SetString(PyExc_TypeError, ! "argument can not be converted to mpq"); return 0; } --- 2194,2201 ---- return 1; } else { ! if(!PyErr_Occurred()) { ! PyErr_SetString(PyExc_TypeError, ! "argument can not be converted to mpq"); ! } return 0; } *************** *** 2899,2904 **** self = (PyObject*)anynum2mpq(self); if(!self) { ! PyErr_SetString(PyExc_TypeError, ! "first argument to qdiv not a number"); return last_try("qdiv", 1, 2, args); } --- 2950,2957 ---- self = (PyObject*)anynum2mpq(self); if(!self) { ! if(!PyErr_Occurred()) { ! PyErr_SetString(PyExc_TypeError, ! "first argument to qdiv not a number"); ! } return last_try("qdiv", 1, 2, args); } *************** *** 2909,2914 **** if(!other) { Py_DECREF(self); ! PyErr_SetString(PyExc_TypeError, ! "second argument to qdiv not a number"); return last_try("qdiv", 1, 2, args); } --- 2962,2969 ---- if(!other) { Py_DECREF(self); ! if(!PyErr_Occurred()) { ! PyErr_SetString(PyExc_TypeError, ! "second argument to qdiv not a number"); ! } return last_try("qdiv", 1, 2, args); } *************** *** 3189,3194 **** newob = anynum2mpq(obj); if(!newob) { ! PyErr_SetString(PyExc_TypeError, ! "gmpy.mpq() expects numeric or string argument"); return NULL; } --- 3244,3251 ---- newob = anynum2mpq(obj); if(!newob) { ! if(!PyErr_Occurred()) { ! PyErr_SetString(PyExc_TypeError, ! "gmpy.mpq() expects numeric or string argument"); ! } return NULL; } *************** *** 3546,3550 **** result = (PyObject*) anynum2mpz(result); if (result) ! result = (PyObject*) anynum2mpq(result); } return result; --- 3603,3607 ---- result = (PyObject*) anynum2mpz(result); if (result) ! result = (PyObject*) anynum2mpq(result); } return result; *************** *** 3564,3568 **** result = (PyObject*) anynum2mpz(result); if (result) ! result = (PyObject*) anynum2mpf(result, 0); } return result; --- 3621,3625 ---- result = (PyObject*) anynum2mpz(result); if (result) ! result = (PyObject*) anynum2mpf(result, 0); } return result; *************** *** 4184,4188 **** return 0; } else { ! PyErr_SetString(PyExc_TypeError, "coercion to gmpy.mpq type failed"); return -1; } --- 4241,4248 ---- return 0; } else { ! if(!PyErr_Occurred()) { ! PyErr_SetString(PyExc_TypeError, ! "coercion to gmpy.mpq type failed"); ! } return -1; } *************** *** 4540,4544 **** /* Check for convergence */ if (!(mpf_cmp_si(r_i2, 0) && ! mpf_get_prec(r_i2) >= (unsigned)precision)) { mpf_mul(pi->f, pi->f, r_i4); mpf_div(pi->f, pi->f, r_i3); --- 4600,4604 ---- /* Check for convergence */ if (!(mpf_cmp_si(r_i2, 0) && ! mpf_get_prec(r_i2) >= (unsigned)precision)) { mpf_mul(pi->f, pi->f, r_i4); mpf_div(pi->f, pi->f, r_i3); *************** *** 5785,5789 **** static char _gmpy_docs[] = "\ ! gmpy 1.01 - General Multiprecision arithmetic for PYthon:\n\ exposes functionality from the GMP 4 library to Python 2.{2,3,4}.\n\ \n\ --- 5845,5849 ---- static char _gmpy_docs[] = "\ ! gmpy 1.02 - General Multiprecision arithmetic for PYthon:\n\ exposes functionality from the GMP 4 library to Python 2.{2,3,4}.\n\ \n\ *************** *** 5824,5826 **** --- 5884,5912 ---- if (options.debug) fprintf(stderr, "gmpy_module at %p\n", gmpy_module); + + /* Experimental: adapt module decimal to our needs */ + char* tweak_decimal = + "def __gmpy_z__(self, f=gmpy.mpz): return f(int(self))\n" + "def __gmpy_q__(self, f=gmpy.mpq): return f(str(self))\n" + "def __gmpy_f__(self, f=gmpy.mpf): return f(str(self))\n" + "try:\n" + " decimal.Decimal.__gmpy_z__ = __gmpy_z__\n" + " decimal.Decimal.__gmpy_q__ = __gmpy_q__\n" + " decimal.Decimal.__gmpy_f__ = __gmpy_f__\n" + "except: pass\n" + ; + PyObject* decimal_module = PyImport_ImportModule("decimal"); + if(decimal_module) { + PyObject* namespace = PyDict_New(); + PyDict_SetItemString(namespace, "decimal", decimal_module); + PyDict_SetItemString(namespace, "gmpy", gmpy_module); + PyDict_SetItemString(namespace, "int", (PyObject*)&PyInt_Type); + PyDict_SetItemString(namespace, "str", (PyObject*)&PyString_Type); + PyObject* result = PyRun_String(tweak_decimal, Py_file_input, + namespace, namespace); + Py_DECREF(namespace); + Py_XDECREF(result); + } else { + PyErr_Clear(); + } } |