(original) (raw)

/* Long (arbitrary precision) integer object implementation */ /* XXX The functional organization of this file is terrible */ #include "Python.h" #include "longintrepr.h" #include "formatter_unicode.h" #include #define PY2MPZ(x) (((PyLongObject*)x)->number) long PyInt_GetMax(void) { return LONG_MAX; /* To initialize sys.maxint */ } #ifdef COUNT_ALLOCS int quick_int_allocs, quick_neg_int_allocs; #endif #define ABS(x) ((x) < 0 ? -(x) : (x)) /* Allocate a new long int object with size digits. Return NULL and set exception if we run out of memory. */ PyLongObject * _PyLong_New(void) { PyLongObject *result; result = PyObject_MALLOC(sizeof(PyLongObject)); if (!result) { PyErr_NoMemory(); return NULL; } PyObject_INIT(result, &PyLong_Type); mpz_init (result->number); return result; } PyObject * _PyLong_Copy(PyLongObject *src) { PyLongObject *result; assert(src != NULL); result = _PyLong_New(); mpz_set(result->number, src->number); return (PyObject *)result; } /* Create a new long int object from a C long int */ PyObject * PyLong_FromLong(long ival) { PyLongObject *v; v = _PyLong_New(); mpz_set_si(v->number, ival); return (PyObject *)v; } /* Create a new long int object from a C unsigned long int */ PyObject * PyLong_FromUnsignedLong(unsigned long ival) { PyLongObject *v; v = _PyLong_New(); mpz_set_ui(v->number, ival); return (PyObject *)v; } /* Create a new long int object from a C double */ PyObject * PyLong_FromDouble(double dval) { PyLongObject *v; v = _PyLong_New(); mpz_set_d(v->number, dval); return (PyObject *)v; } /* Checking for overflow in PyLong_AsLong is a PITA since C doesn't define * anything about what happens when a signed integer operation overflows, * and some compilers think they're doing you a favor by being "clever" * then. The bit pattern for the largest postive signed long is * (unsigned long)LONG_MAX, and for the smallest negative signed long * it is abs(LONG_MIN), which we could write -(unsigned long)LONG_MIN. * However, some other compilers warn about applying unary minus to an * unsigned operand. Hence the weird "0-". */ #define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN) #define PY_ABS_SSIZE_T_MIN (0-(size_t)PY_SSIZE_T_MIN) /* Get a C long int from a long int object. Returns -1 and sets an error condition if overflow occurs. */ long PyLong_AsLong(PyObject *vv) { int do_decref = 0; /* if nb_int was called */ if (vv == NULL) { PyErr_BadInternalCall(); return -1; } if (!PyLong_Check(vv)) { PyNumberMethods *nb; if ((nb = vv->ob_type->tp_as_number) == NULL || nb->nb_int == NULL) { PyErr_SetString(PyExc_TypeError, "an integer is required"); return -1; } vv = (*nb->nb_int) (vv); if (vv == NULL) return -1; do_decref = 1; if (!PyLong_Check(vv)) { Py_DECREF(vv); PyErr_SetString(PyExc_TypeError, "nb_int should return int object"); return -1; } } if (do_decref) { Py_DECREF(vv); } return mpz_get_si(PY2MPZ(vv)); } int _PyLong_FitsInLong(PyObject *vv) { if (!PyLong_CheckExact(vv)) { PyErr_BadInternalCall(); return 0; } /* FIXME: Write code */ return 1; } /* Get a Py_ssize_t from a long int object. Returns -1 and sets an error condition if overflow occurs. */ Py_ssize_t PyLong_AsSsize_t(PyObject *vv) { if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; } return mpz_get_si(PY2MPZ(vv)); } /* Get a C unsigned long int from a long int object. Returns -1 and sets an error condition if overflow occurs. */ unsigned long PyLong_AsUnsignedLong(PyObject *vv) { if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return (unsigned long) -1; } return mpz_get_ui(PY2MPZ(vv)); } /* Get a C unsigned long int from a long int object. Returns -1 and sets an error condition if overflow occurs. */ size_t PyLong_AsSize_t(PyObject *vv) { if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return (unsigned long) -1; } return mpz_get_ui(PY2MPZ(vv)); } /* Get a C unsigned long int from a long int object, ignoring the high bits. Returns -1 and sets an error condition if an error occurs. */ unsigned long PyLong_AsUnsignedLongMask(register PyObject *op) { if (op == NULL || !PyLong_Check(op)) { PyErr_BadInternalCall(); return (unsigned long) -1; } /* FIXME: mpz, mask */ return mpz_get_ui(PY2MPZ(op)); } int _PyLong_Sign(PyObject *vv) { long val; assert(v != NULL); assert(PyLong_Check(v)); val = mpz_get_si(PY2MPZ(vv)); return val == 0 ? 0 : (val < 0 ? -1 : 1); } size_t _PyLong_NumBits(PyObject *vv) { assert(v != NULL); assert(PyLong_Check(v)); return mpz_sizeinbase(PY2MPZ(vv), 2); } PyObject * _PyLong_FromByteArray(const unsigned char* bytes, size_t n, int little_endian, int is_signed) { PyLongObject *result; if (n == 0) return PyLong_FromLong(0L); result = _PyLong_New(); if (!result) return NULL; /* FIXME: Use is_signed */ /* FIXME: Check use of little_endian */ mpz_import(result->number, n, 1, sizeof(bytes[0]), little_endian, 0, bytes); return (PyObject*)result; } int _PyLong_AsByteArray(PyLongObject* v, unsigned char* bytes, size_t n, int little_endian, int is_signed) { assert(v != NULL && PyLong_Check(v)); /* FIXME: same warning than mpz_import() call */ mpz_export(bytes, NULL, 1, sizeof(bytes[0]), little_endian, 0, v->number); return 0; } double _PyLong_AsScaledDouble(PyObject *vv, int *exponent) { if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; } /* FIXME: Read exponent */ *exponent = 0; return mpz_get_d(PY2MPZ(vv)); } /* Get a C double from a long int object. */ double PyLong_AsDouble(PyObject *vv) { return mpz_get_d(PY2MPZ(vv)); } /* Create a new long (or int) object from a C pointer */ PyObject * PyLong_FromVoidPtr(void *p) { #ifndef HAVE_LONG_LONG # error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long" #endif #if SIZEOF_LONG_LONG < SIZEOF_VOID_P # error "PyLong_FromVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)" #endif /* special-case null pointer */ if (!p) return PyLong_FromLong(0); return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)(Py_uintptr_t)p); } /* Get a C pointer from a long object (or an int object in some cases) */ void * PyLong_AsVoidPtr(PyObject *vv) { /* This function will allow int or long objects. If vv is neither, then the PyLong_AsLong*() functions will raise the exception: PyExc_SystemError, "bad argument to internal function" */ #if SIZEOF_VOID_P <= SIZEOF_LONG long x; if (PyLong_Check(vv) && _PyLong_Sign(vv) < 0) x = PyLong_AsLong(vv); else x = PyLong_AsUnsignedLong(vv); #else #ifndef HAVE_LONG_LONG # error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long" #endif #if SIZEOF_LONG_LONG < SIZEOF_VOID_P # error "PyLong_AsVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)" #endif PY_LONG_LONG x; if (PyLong_Check(vv) && _PyLong_Sign(vv) < 0) x = PyLong_AsLongLong(vv); else x = PyLong_AsUnsignedLongLong(vv); #endif /* SIZEOF_VOID_P <= SIZEOF_LONG */ if (x == -1 && PyErr_Occurred()) { /* FIXME: Here? */ return NULL; } return (void *)x; } #ifdef HAVE_LONG_LONG /* Initial PY_LONG_LONG support by Chris Herborth (chrish@qnx.com), later * rewritten to use the newer PyLong_{As,From}ByteArray API. */ #define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one /* Create a new long int object from a C PY_LONG_LONG int. */ PyObject * PyLong_FromLongLong(PY_LONG_LONG ival) { PyLongObject *result; result = _PyLong_New(); if (!result) return NULL; /* FIXME: Use MSB */ mpz_set_si(result->number, ival); return (PyObject*)result; } /* Create a new long int object from a C unsigned PY_LONG_LONG int. */ PyObject * PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival) { PyLongObject *result; result = _PyLong_New(); if (!result) return NULL; /* FIXME: Use MSB */ mpz_set_ui(result->number, ival); return (PyObject*)result; } /* Create a new long int object from a C Py_ssize_t. */ PyObject * PyLong_FromSsize_t(Py_ssize_t ival) { #if 0 Py_ssize_t bytes = ival; int one = 1; if (ival < PyLong_BASE) return PyLong_FromLong(ival); return _PyLong_FromByteArray( (unsigned char *)&bytes, SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 1); #else PyLongObject *result; result = _PyLong_New(); if (!result) return NULL; /* FIXME: sizeof(ssize_t) != sizeof(int)? */ mpz_set_si(result->number, ival); return (PyObject*)result; #endif } /* Create a new long int object from a C size_t. */ PyObject * PyLong_FromSize_t(size_t ival) { #if 0 size_t bytes = ival; int one = 1; if (ival < PyLong_BASE) return PyLong_FromLong(ival); return _PyLong_FromByteArray( (unsigned char *)&bytes, SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0); #else PyLongObject *result; result = _PyLong_New(); if (!result) return NULL; /* FIXME: sizeof(size_t) != sizeof(int)? */ mpz_set_ui(result->number, ival); return (PyObject*)result; #endif } /* Get a C PY_LONG_LONG int from a long int object. Return -1 and set an error if overflow occurs. */ PY_LONG_LONG PyLong_AsLongLong(PyObject *vv) { PY_LONG_LONG bytes; if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; } /* FIXME: long long */ bytes = mpz_get_si(PY2MPZ(vv)); return bytes; } /* Get a C unsigned PY_LONG_LONG int from a long int object. Return -1 and set an error if overflow occurs. */ unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(PyObject *vv) { PY_LONG_LONG bytes; if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; } /* FIXME: long long */ bytes = mpz_get_ui(PY2MPZ(vv)); return bytes; } /* Get a C unsigned long int from a long int object, ignoring the high bits. Returns -1 and sets an error condition if an error occurs. */ unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(register PyObject *op) { PY_LONG_LONG bytes; if (op == NULL || !PyLong_Check(op)) { PyErr_BadInternalCall(); return -1; } /* FIXME: long long */ bytes = mpz_get_ui(PY2MPZ(op)); return bytes; } #undef IS_LITTLE_ENDIAN #endif /* HAVE_LONG_LONG */ #define CHECK_BINOP(v,w) \ if (!PyLong_Check(v) || !PyLong_Check(w)) { \ Py_INCREF(Py_NotImplemented); \ return Py_NotImplemented; \ } PyObject * _PyLong_Format(PyObject *aa, int base) { #if 1 register PyLongObject *a = (PyLongObject *)aa; char* c_str; PyObject *str; if (a == NULL || !PyLong_Check(a)) { PyErr_BadInternalCall(); return NULL; } assert(base >= 2 && base <= 36); c_str = mpz_get_str(NULL, base, a->number); if (!c_str) { /* FIXME: mpz set error */ PyErr_NoMemory(); return NULL; } str = PyUnicode_FromFormat(c_str); // str = PyUnicode_FromStringAndSize(c_str, strlen(c_str)); /* NEED MODIFIABLE STRING, ref=1 */ /* FIXME: free c_str ? */ /*free(c_str);*/ return (PyObject *)str; #else register PyLongObject *a = (PyLongObject *)aa; PyObject *str; Py_ssize_t sz; Py_UNICODE *p; if (a == NULL || !PyLong_Check(a)) { PyErr_BadInternalCall(); return NULL; } assert(base >= 2 && base <= 36); /* Compute a rough upper bound for the length of the string */ sz = 1; str = PyUnicode_FromUnicode(NULL, sz); if (str == NULL) return NULL; p = PyUnicode_AS_UNICODE(str) + sz; *p = '\0'; *--p = '0'; if (p != PyUnicode_AS_UNICODE(str)) { Py_UNICODE *q = PyUnicode_AS_UNICODE(str); assert(p > q); do { } while ((*q++ = *p++) != '\0'); q--; if (PyUnicode_Resize(&str, (Py_ssize_t) (q - PyUnicode_AS_UNICODE(str)))) { Py_DECREF(str); return NULL; } } return (PyObject *)str; #endif } PyObject * PyLong_FromString(char *str, char **pend, int base) { PyLongObject *result; int ret; if ((base != 0 && base < 2) || base > 36) { PyErr_SetString(PyExc_ValueError, "int() arg 2 must be >= 2 and <= 36"); return NULL; } result = _PyLong_New(); if (!result) return NULL; /* FIXME: Update pend? */ ret = mpz_set_str(result->number, str, base); if (ret != 0) { PyObject *strobj; Py_ssize_t slen; Py_XDECREF(result); slen = strlen(str) < 200 ? strlen(str) : 200; strobj = PyUnicode_FromStringAndSize(str, slen); if (strobj == NULL) { return NULL; } PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %R", base, strobj); Py_DECREF(strobj); return NULL; } return (PyObject*)result; } PyObject * PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base) { PyObject *result; char *buffer = (char *)PyMem_MALLOC(length+1); if (buffer == NULL) { return NULL; } if (PyUnicode_EncodeDecimal(u, length, buffer, NULL)) { PyMem_FREE(buffer); return NULL; } result = PyLong_FromString(buffer, NULL, base); PyMem_FREE(buffer); return result; } /* Methods */ static void long_dealloc(PyObject *v) { mpz_clear(PY2MPZ(v)); Py_Type(v)->tp_free(v); } static PyObject * long_repr(PyObject *v) { return _PyLong_Format(v, 10); } static int long_compare(PyLongObject *a, PyLongObject *b) { return mpz_cmp(a->number, b->number); } static PyObject * long_richcompare(PyObject *self, PyObject *other, int op) { PyObject *result; CHECK_BINOP(self, other); result = Py_CmpToRich(op, long_compare((PyLongObject*)self, (PyLongObject*)other)); return result; } static long long_hash(PyLongObject *v) { long x; x = mpz_get_si(v->number); if (x == -1) x = -2; return x; } static PyObject * long_add(PyLongObject *a, PyLongObject *b) { PyLongObject *z; CHECK_BINOP(a, b); z = _PyLong_New(); if (!z) return NULL; mpz_add(z->number, a->number, b->number); return (PyObject *)z; } static PyObject * long_sub(PyLongObject *a, PyLongObject *b) { PyLongObject *z; CHECK_BINOP(a, b); z = _PyLong_New(); if (!z) return NULL; mpz_sub(z->number, a->number, b->number); return (PyObject *)z; } static PyObject * long_mul(PyLongObject *a, PyLongObject *b) { PyLongObject *z; CHECK_BINOP(a, b); z = _PyLong_New(); if (!z) return NULL; mpz_mul(z->number, a->number, b->number); return (PyObject *)z; } static PyObject * long_div(PyObject *a, PyObject *b) { PyLongObject *div; CHECK_BINOP(a, b); div = _PyLong_New(); if (!div) return NULL; /* FIXME: What about division by zero? */ mpz_cdiv_q(div->number, PY2MPZ(a), PY2MPZ(b)); return (PyObject *)div; } static PyObject * long_true_divide(PyObject *a, PyObject *b) { double ad, bd; int failed, aexp = -1, bexp = -1; CHECK_BINOP(a, b); ad = _PyLong_AsScaledDouble((PyObject *)a, &aexp); bd = _PyLong_AsScaledDouble((PyObject *)b, &bexp); failed = (ad == -1.0 || bd == -1.0) && PyErr_Occurred(); if (failed) { return NULL; } /* 'aexp' and 'bexp' were initialized to -1 to silence gcc-4.0.x, but should really be set correctly after sucessful calls to _PyLong_AsScaledDouble() */ assert(aexp >= 0 && bexp >= 0); if (bd == 0.0) { PyErr_SetString(PyExc_ZeroDivisionError, "int division or modulo by zero"); return NULL; } /* True value is very close to ad/bd * 2**(PyLong_SHIFT*(aexp-bexp)) */ ad /= bd; /* overflow/underflow impossible here */ /* FIXME: Re-enable this code */ #if 0 aexp -= bexp; if (aexp > INT_MAX / PyLong_SHIFT) goto overflow; else if (aexp < -(INT_MAX / PyLong_SHIFT)) return PyFloat_FromDouble(0.0); /* underflow to 0 */ errno = 0; ad = ldexp(ad, aexp * PyLong_SHIFT); if (Py_OVERFLOWED(ad)) /* ignore underflow to 0.0 */ goto overflow; #endif return PyFloat_FromDouble(ad); #if 0 overflow: PyErr_SetString(PyExc_OverflowError, "int/int too large for a float"); return NULL; #endif } static PyObject * long_mod(PyObject *a, PyObject *b) { PyLongObject *z; CHECK_BINOP(a, b); z = _PyLong_New(); if (!z) return NULL; /* FIXME: division by zero? */ mpz_mod(z->number, PY2MPZ(a), PY2MPZ(b)); return (PyObject *)z; } static PyObject * long_divmod(PyObject *a, PyObject *b) { PyLongObject *div, *mod; PyObject *z; CHECK_BINOP(a, b); div = _PyLong_New(); if (!div) { return NULL; } mod = _PyLong_New(); if (!mod) { Py_DECREF(div); return NULL; } mpz_cdiv_qr(div->number, mod->number, PY2MPZ(a), PY2MPZ(b)); z = PyTuple_New(2); if (z != NULL) { PyTuple_SetItem(z, 0, (PyObject *) div); PyTuple_SetItem(z, 1, (PyObject *) mod); } else { Py_DECREF(div); Py_DECREF(mod); } return z; } /* pow(v, w, x) */ static PyObject * long_pow(PyObject *v, PyObject *w, PyObject *x) { PyLongObject *z; CHECK_BINOP(v, w); z = _PyLong_New(); if (!z) return NULL; /* FIXME: When x is used? */ if (x && x != Py_None) { mpz_powm(z->number, PY2MPZ(v), PY2MPZ(w), PY2MPZ(x)); } else { int exp = mpz_get_si(PY2MPZ(w)); mpz_pow_ui(z->number, PY2MPZ(v), exp); } return (PyObject *)z; } static PyObject * long_invert(PyLongObject *v) { #if 0 /* Implement ~x as -(x+1) */ PyLongObject *x; PyLongObject *w; if (ABS(Py_Size(v)) <=1) return PyLong_FromLong(-(MEDIUM_VALUE(v)+1)); w = (PyLongObject *)PyLong_FromLong(1L); if (w == NULL) return NULL; x = (PyLongObject *) long_add(v, w); Py_DECREF(w); if (x == NULL) return NULL; Py_Size(x) = -(Py_Size(x)); return (PyObject *)x; #else PyLongObject *z = _PyLong_New(); if (!z) return NULL; mpz_neg(z->number, v->number); mpz_add_ui(z->number, z->number, 1); return (PyObject*)z; #endif } static PyObject * long_neg(PyLongObject *v) { PyLongObject *z = _PyLong_New(); if (!z) return NULL; mpz_neg(z->number, v->number); return (PyObject *)z; } static PyObject * long_abs(PyLongObject *v) { PyLongObject *z = _PyLong_New(); if (!z) return NULL; mpz_abs(z->number, v->number); return (PyObject *)z; } static int long_bool(PyLongObject *v) { return mpz_cmp_si(PY2MPZ(v), 0) != 0; } static PyObject * long_rshift(PyLongObject *a, PyLongObject *b) { PyLongObject *z = NULL; long shiftby; //Py_ssize_t newsize, wordshift, loshift, hishift, i, j; CHECK_BINOP(a, b); if ((mpz_cmp_si(PY2MPZ(a), 0) < 0)) { /* Right shifting negative numbers is harder */ PyLongObject *a1, *a2; a1 = (PyLongObject *) long_invert(a); if (a1 == NULL) goto rshift_error; a2 = (PyLongObject *) long_rshift(a1, b); Py_DECREF(a1); if (a2 == NULL) goto rshift_error; z = (PyLongObject *) long_invert(a2); Py_DECREF(a2); } else { shiftby = PyLong_AsLong((PyObject *)b); if (shiftby == -1L && PyErr_Occurred()) goto rshift_error; if (shiftby < 0) { PyErr_SetString(PyExc_ValueError, "negative shift count"); goto rshift_error; } z = _PyLong_New(); if (!z) return NULL; mpz_cdiv_q_2exp(z->number, a->number, shiftby); } rshift_error: return (PyObject *) z; } static PyObject * long_lshift(PyObject *v, PyObject *w) { /* This version due to Tim Peters */ PyLongObject *a = (PyLongObject*)v; PyLongObject *b = (PyLongObject*)w; PyLongObject *z = NULL; long shiftby; // Py_ssize_t oldsize, newsize, wordshift, remshift, i, j; // twodigits accum; CHECK_BINOP(a, b); shiftby = PyLong_AsLong((PyObject *)b); if (shiftby == -1L && PyErr_Occurred()) goto lshift_error; if (shiftby < 0) { PyErr_SetString(PyExc_ValueError, "negative shift count"); goto lshift_error; } if ((long)(int)shiftby != shiftby) { PyErr_SetString(PyExc_ValueError, "outrageous left shift count"); goto lshift_error; } z = _PyLong_New(); if (!z) return NULL; mpz_mul_2exp(z->number, a->number, shiftby); lshift_error: return (PyObject *) z; } /* Bitwise and/xor/or operations */ static PyObject * long_bitwise(PyLongObject *a, int op, /* '&', '|', '^' */ PyLongObject *b) { PyLongObject *z = _PyLong_New(); if (!z) return NULL; switch (op) { case '^': mpz_xor(z->number, PY2MPZ(a), PY2MPZ(b)); break; case '&': mpz_and(z->number, PY2MPZ(a), PY2MPZ(b)); break; case '|': mpz_ior(z->number, PY2MPZ(a), PY2MPZ(b)); break; } return (PyObject*)z; } static PyObject * long_and(PyObject *a, PyObject *b) { PyObject *c; CHECK_BINOP(a, b); c = long_bitwise((PyLongObject*)a, '&', (PyLongObject*)b); return c; } static PyObject * long_xor(PyObject *a, PyObject *b) { PyObject *c; CHECK_BINOP(a, b); c = long_bitwise((PyLongObject*)a, '^', (PyLongObject*)b); return c; } static PyObject * long_or(PyObject *a, PyObject *b) { PyObject *c; CHECK_BINOP(a, b); c = long_bitwise((PyLongObject*)a, '|', (PyLongObject*)b); return c; } static PyObject * long_long(PyObject *v) { if (PyLong_CheckExact(v)) Py_INCREF(v); else v = _PyLong_Copy((PyLongObject *)v); return v; } static PyObject * long_float(PyObject *v) { double result; result = PyLong_AsDouble(v); if (result == -1.0 && PyErr_Occurred()) { return NULL; } return PyFloat_FromDouble(result); } static PyObject * long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *x = NULL; int base = -909; /* unlikely! */ static char *kwlist[] = {"x", "base", 0}; if (type != &PyLong_Type) return long_subtype_new(type, args, kwds); /* Wimp out */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, &x, &base)) { return NULL; } if (x == NULL) return PyLong_FromLong(0L); if (base == -909) return PyNumber_Long(x); else if (PyBytes_Check(x)) { /* Since PyLong_FromString doesn't have a length parameter, * check here for possible NULs in the string. */ char *string = PyBytes_AS_STRING(x); int size = PyBytes_GET_SIZE(x); if (strlen(string) != size) { /* We only see this if there's a null byte in x, x is a str8 or a bytes, *and* a base is given. */ PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %R", base, x); return NULL; } return PyLong_FromString(string, NULL, base); } else if (PyUnicode_Check(x)) return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x), PyUnicode_GET_SIZE(x), base); else { PyErr_SetString(PyExc_TypeError, "int() can't convert non-string with explicit base"); return NULL; } } /* Wimpy, slow approach to tp_new calls for subtypes of long: first create a regular long from whatever arguments we got, then allocate a subtype instance and initialize it from the regular long. The regular long is then thrown away. */ static PyObject * long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyLongObject *tmp, *newobj; assert(PyType_IsSubtype(type, &PyLong_Type)); tmp = (PyLongObject *)long_new(&PyLong_Type, args, kwds); if (tmp == NULL) { return NULL; } assert(PyLong_CheckExact(tmp)); /* FIXME: size=0? */ newobj = (PyLongObject *)type->tp_alloc(type, 0); if (newobj == NULL) { Py_DECREF(tmp); return NULL; } assert(PyLong_Check(newobj)); /* FIXME: check this code */ mpz_init(newobj->number); mpz_set(newobj->number, tmp->number); Py_DECREF(tmp); return (PyObject *)newobj; } static PyObject * long_getnewargs(PyLongObject *v) { return Py_BuildValue("(N)", _PyLong_Copy(v)); } static PyObject * long_getN(PyLongObject *v, void *context) { return PyLong_FromLong((intptr_t)context); } static PyObject * long__format__(PyObject *self, PyObject *args) { /* when back porting this to 2.6, check type of the format_spec and call either unicode_long__format__ or string_long__format__ */ return unicode_long__format__(self, args); } static PyObject * long_round(PyObject *self, PyObject *args) { #define UNDEF_NDIGITS (-0x7fffffff) /* Unlikely ndigits value */ int ndigits = UNDEF_NDIGITS; double x; PyObject *res; if (!PyArg_ParseTuple(args, "|i", &ndigits)) { return NULL; } if (ndigits == UNDEF_NDIGITS) return long_long(self); /* If called with two args, defer to float.__round__(). */ x = PyLong_AsDouble(self); if (x == -1.0 && PyErr_Occurred()) { return NULL; } self = PyFloat_FromDouble(x); if (self == NULL) { return NULL; } res = PyObject_CallMethod(self, "__round__", "i", ndigits); Py_DECREF(self); return res; #undef UNDEF_NDIGITS } static PyMethodDef long_methods[] = { {"conjugate", (PyCFunction)long_long, METH_NOARGS, "Returns self, the complex conjugate of any int."}, {"__trunc__", (PyCFunction)long_long, METH_NOARGS, "Truncating an Integral returns itself."}, {"__floor__", (PyCFunction)long_long, METH_NOARGS, "Flooring an Integral returns itself."}, {"__ceil__", (PyCFunction)long_long, METH_NOARGS, "Ceiling of an Integral returns itself."}, {"__round__", (PyCFunction)long_round, METH_VARARGS, "Rounding an Integral returns itself.\n" "Rounding with an ndigits arguments defers to float.__round__."}, {"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS}, {"__format__", (PyCFunction)long__format__, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; static PyGetSetDef long_getset[] = { {"real", (getter)long_long, (setter)NULL, "the real part of a complex number", NULL}, {"imag", (getter)long_getN, (setter)NULL, "the imaginary part of a complex number", (void*)0}, {"numerator", (getter)long_long, (setter)NULL, "the numerator of a rational number in lowest terms", NULL}, {"denominator", (getter)long_getN, (setter)NULL, "the denominator of a rational number in lowest terms", (void*)1}, {NULL} /* Sentinel */ }; PyDoc_STRVAR(long_doc, "int(x[, base]) -> integer\n\ \n\ Convert a string or number to an integer, if possible. A floating\n\ point argument will be truncated towards zero (this does not include a\n\ string representation of a floating point number!) When converting a\n\ string, use the optional base. It is an error to supply a base when\n\ converting a non-string."); static PyNumberMethods long_as_number = { (binaryfunc) long_add, /*nb_add*/ (binaryfunc) long_sub, /*nb_subtract*/ (binaryfunc) long_mul, /*nb_multiply*/ long_mod, /*nb_remainder*/ long_divmod, /*nb_divmod*/ long_pow, /*nb_power*/ (unaryfunc) long_neg, /*nb_negative*/ (unaryfunc) long_long, /*tp_positive*/ (unaryfunc) long_abs, /*tp_absolute*/ (inquiry) long_bool, /*tp_bool*/ (unaryfunc) long_invert, /*nb_invert*/ long_lshift, /*nb_lshift*/ (binaryfunc) long_rshift, /*nb_rshift*/ long_and, /*nb_and*/ long_xor, /*nb_xor*/ long_or, /*nb_or*/ 0, /*nb_reserved*/ long_long, /*nb_int*/ long_long, /*nb_long*/ long_float, /*nb_float*/ 0, /*nb_oct*/ /* not used */ 0, /*nb_hex*/ /* not used */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ long_div, /* nb_floor_divide */ long_true_divide, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ long_long, /* nb_index */ }; PyTypeObject PyLong_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "int", /* tp_name */ sizeof(PyLongObject), /* tp_basicsize */ 0, /* tp_itemsize */ long_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ long_repr, /* tp_repr */ &long_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)long_hash, /* tp_hash */ 0, /* tp_call */ long_repr, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LONG_SUBCLASS, /* tp_flags */ long_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ long_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ long_methods, /* tp_methods */ 0, /* tp_members */ long_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ long_new, /* tp_new */ PyObject_Del, /* tp_free */ }; int _PyLong_Init(void) { PyObject_INIT(&_Py_TrueStruct, &PyBool_Type); PyObject_INIT(&_Py_FalseStruct, &PyBool_Type); mpz_init(_Py_TrueStruct.number); mpz_init(_Py_FalseStruct.number); mpz_set_si(_Py_TrueStruct.number, 1); return 1; } void PyLong_Fini(void) { mpz_clear(_Py_FalseStruct.number); mpz_clear(_Py_TrueStruct.number); }