Commit 57269d0c authored by Andrew M. Kuchling's avatar Andrew M. Kuchling

Remove mpz, rotor, xreadlines modules

parent 810b76ae
......@@ -180,7 +180,6 @@ class PyBuildExt(build_ext):
exts.append( Extension('_weakref', ['_weakref.c']) )
exts.append( Extension('_symtable', ['symtablemodule.c']) )
exts.append( Extension('xreadlines', ['xreadlinesmodule.c']) )
# array objects
exts.append( Extension('array', ['arraymodule.c']) )
......@@ -244,10 +243,7 @@ class PyBuildExt(build_ext):
# Memory-mapped files (also works on Win32).
exts.append( Extension('mmap', ['mmapmodule.c']) )
# Lance Ellinghaus's modules:
# enigma-inspired encryption
exts.append( Extension('rotor', ['rotormodule.c']) )
# syslog daemon interface
# Lance Ellinghaus's syslog daemon interface
exts.append( Extension('syslog', ['syslogmodule.c']) )
# George Neville-Neil's timing module:
......@@ -361,23 +357,6 @@ class PyBuildExt(build_ext):
include_dirs = db_inc,
libraries = dblib) )
# The mpz module interfaces to the GNU Multiple Precision library.
# You need to ftp the GNU MP library.
# This was originally written and tested against GMP 1.2 and 1.3.2.
# It has been modified by Rob Hooft to work with 2.0.2 as well, but I
# haven't tested it recently. For a more complete module,
# refer to pympz.sourceforge.net.
# A compatible MP library unencombered by the GPL also exists. It was
# posted to comp.sources.misc in volume 40 and is widely available from
# FTP archive sites. One URL for it is:
# ftp://gatekeeper.dec.com/.b/usenet/comp.sources.misc/volume40/fgmp/part01.Z
if (self.compiler.find_library_file(lib_dirs, 'gmp')):
exts.append( Extension('mpz', ['mpzmodule.c'],
libraries = ['gmp'] ) )
# Unix-only modules
if platform not in ['mac', 'win32']:
# Steen Lumholt's termios module
......
/* MPZ module */
/* This module provides an interface to an alternate Multi-Precision
library, GNU MP in this case */
/* XXX note: everywhere where mpz_size is called,
sizeof (limb) == sizeof (long) has been assumed. */
/* MPZ objects */
#include "Python.h"
#include <sys/types.h> /* For size_t */
/*
** These are the cpp-flags used in this file...
**
**
** MPZ_MDIV_BUG works around the mpz_m{div,mod,...} routines.
** This bug has been fixed in a later release of
** GMP.
**
** MPZ_GET_STR_BUG mpz_get_str corrupts memory, seems to be fixed
** in a later release
**
** MPZ_DEBUG generates a bunch of diagnostic messages
**
** MPZ_SPARE_MALLOC if set, results in extra code that tries to
** minimize the creation of extra objects.
**
** MPZ_TEST_DIV extra diagnostic output on stderr, when division
** routines are involved
**
** MPZ_LIB_DOES_CHECKING if set, assumes that mpz library doesn't call
** alloca with arg < 0 (when casted to a signed
** integral type).
**
** MPZ_CONVERSIONS_AS_METHODS if set, presents the conversions as
** methods. e.g., `mpz(5).long() == 5L'
** Later, Guido provided an interface to the
** standard functions. So this flag has no been
** cleared, and `long(mpz(5)) == 5L'
**
** MP_TEST_ALLOC If set, you would discover why MPZ_GET_STR_BUG
** is needed
**
** MAKEDUMMYINT Must be set if dynamic linking will be used
*/
/*
** IMHO, mpz_m{div,mod,divmod}() do the wrong things when the denominator < 0
** This has been fixed with gmp release 2.0
*/
/*#define MPZ_MDIV_BUG fixed the (for me) nexessary parts in libgmp.a */
/*
** IMO, mpz_get_str() assumes a bit too large target space, if he doesn't
** allocate it himself
*/
#include "gmp.h"
#if __GNU_MP__ + 0 >= 2
#define GMP2
#define BITS_PER_MP_LIMB mp_bits_per_limb
#else
#define MPZ_GET_STR_BUG
#include "gmp-mparam.h"
#endif
typedef struct {
PyObject_HEAD
MP_INT mpz; /* the actual number */
} mpzobject;
static PyTypeObject MPZtype;
#define is_mpzobject(v) ((v)->ob_type == &MPZtype)
static const char initialiser_name[] = "mpz";
/* #define MPZ_DEBUG */
static mpzobject *
newmpzobject(void)
{
mpzobject *mpzp;
#ifdef MPZ_DEBUG
fputs( "mpz_object() called...\n", stderr );
#endif /* def MPZ_DEBUG */
mpzp = PyObject_New(mpzobject, &MPZtype);
if (mpzp == NULL)
return NULL;
mpz_init(&mpzp->mpz); /* actual initialisation */
return mpzp;
} /* newmpzobject() */
#ifdef MPZ_GET_STR_BUG
#include "longlong.h"
#endif /* def MPZ_GET_STR_BUG */
static PyObject *
mpz_format(PyObject *objp, int base, unsigned char withname)
{
mpzobject *mpzp = (mpzobject *)objp;
PyStringObject *strobjp;
size_t i;
int cmpres;
int taglong;
char *cp;
char prefix[5], *tcp;
tcp = &prefix[0];
if (mpzp == NULL || !is_mpzobject(mpzp)) {
PyErr_BadInternalCall();
return NULL;
}
assert(base >= 2 && base <= 36);
if (withname)
i = strlen(initialiser_name) + 2; /* e.g. 'mpz(' + ')' */
else
i = 0;
if ((cmpres = mpz_cmp_si(&mpzp->mpz, 0L)) == 0)
base = 10; /* '0' in every base, right */
else if (cmpres < 0) {
*tcp++ = '-';
i += 1; /* space to hold '-' */
}
#ifdef MPZ_DEBUG
fprintf(stderr, "mpz_format: mpz_sizeinbase %d\n",
(int)mpz_sizeinbase(&mpzp->mpz, base));
#endif /* def MPZ_DEBUG */
#ifdef MPZ_GET_STR_BUG
#ifdef GMP2
i += ((size_t) abs(mpzp->mpz._mp_size) * BITS_PER_MP_LIMB
* __mp_bases[base].chars_per_bit_exactly) + 1;
#else
i += ((size_t) abs(mpzp->mpz.size) * BITS_PER_MP_LIMB
* __mp_bases[base].chars_per_bit_exactly) + 1;
#endif
#else /* def MPZ_GET_STR_BUG */
i += (int)mpz_sizeinbase(&mpzp->mpz, base);
#endif /* def MPZ_GET_STR_BUG else */
if (base == 16) {
*tcp++ = '0';
*tcp++ = 'x';
i += 2; /* space to hold '0x' */
}
else if (base == 8) {
*tcp++ = '0';
i += 1; /* space to hold the extra '0' */
}
else if (base > 10) {
*tcp++ = '0' + base / 10;
*tcp++ = '0' + base % 10;
*tcp++ = '#';
i += 3; /* space to hold e.g. '12#' */
}
else if (base < 10) {
*tcp++ = '0' + base;
*tcp++ = '#';
i += 2; /* space to hold e.g. '6#' */
}
/*
** the following code looks if we need a 'L' attached to the number
** it will also attach an 'L' to the value -0x80000000
*/
taglong = 0;
if (mpz_size(&mpzp->mpz) > 1
|| (long)mpz_get_ui(&mpzp->mpz) < 0L) {
taglong = 1;
i += 1; /* space to hold 'L' */
}
#ifdef MPZ_DEBUG
fprintf(stderr, "mpz_format: requesting string size %d\n", i);
#endif /* def MPZ_DEBUG */
if ((strobjp =
(PyStringObject *)PyString_FromStringAndSize((char *)0, i))
== NULL)
return NULL;
/* get the beginning of the string memory and start copying things */
cp = PyString_AS_STRING(strobjp);
if (withname) {
strcpy(cp, initialiser_name);
cp += strlen(initialiser_name);
*cp++ = '('; /*')'*/
}
/* copy the already prepared prefix; e.g. sign and base indicator */
*tcp = '\0';
strcpy(cp, prefix);
cp += tcp - prefix;
/* since' we have the sign already, let the lib think it's a positive
number */
if (cmpres < 0)
mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
(void)mpz_get_str(cp, base, &mpzp->mpz);
if (cmpres < 0)
mpz_neg(&mpzp->mpz,&mpzp->mpz); /* hack Hack HAck HACk HACK */
#ifdef MPZ_DEBUG
fprintf(stderr, "mpz_format: base (ultim) %d, mpz_get_str: %s\n",
base, cp);
#endif /* def MPZ_DEBUG */
cp += strlen(cp);
if (taglong)
*cp++ = 'L';
if (withname)
*cp++ = /*'('*/ ')';
*cp = '\0';
#ifdef MPZ_DEBUG
fprintf(stderr,
"mpz_format: cp (str end) %p, begin %p, diff %d, i %d\n",
cp, PyString_AS_STRING(strobjp),
cp - PyString_AS_STRING(strobjp), i);
#endif /* def MPZ_DEBUG */
assert(cp - PyString_AS_STRING(strobjp) <= i);
if (cp - PyString_AS_STRING(strobjp) != i) {
strobjp->ob_size -= i - (cp - PyString_AS_STRING(strobjp));
}
return (PyObject *)strobjp;
} /* mpz_format() */
/* MPZ methods */
static void
mpz_dealloc(mpzobject *mpzp)
{
#ifdef MPZ_DEBUG
fputs( "mpz_dealloc() called...\n", stderr );
#endif /* def MPZ_DEBUG */
mpz_clear(&mpzp->mpz);
PyObject_Del(mpzp);
} /* mpz_dealloc() */
/* pointers to frequently used values 0, 1 and -1 */
static mpzobject *mpz_value_zero, *mpz_value_one, *mpz_value_mone;
static int
mpz_compare(mpzobject *a, mpzobject *b)
{
int cmpres;
/* guido sez it's better to return -1, 0 or 1 */
return (cmpres = mpz_cmp( &a->mpz, &b->mpz )) == 0 ? 0
: cmpres > 0 ? 1 : -1;
} /* mpz_compare() */
static PyObject *
mpz_addition(mpzobject *a, mpzobject *b)
{
mpzobject *z;
#ifdef MPZ_SPARE_MALLOC
if (mpz_cmp_ui(&a->mpz, (unsigned long int)0) == 0) {
Py_INCREF(b);
return (PyObject *)b;
}
if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
Py_INCREF(a);
return (PyObject *)a;
}
#endif /* def MPZ_SPARE_MALLOC */
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_add(&z->mpz, &a->mpz, &b->mpz);
return (PyObject *)z;
} /* mpz_addition() */
static PyObject *
mpz_substract(mpzobject *a, mpzobject *b)
{
mpzobject *z;
#ifdef MPZ_SPARE_MALLOC
if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
Py_INCREF(a);
return (PyObject *)a;
}
#endif /* MPZ_SPARE_MALLOC */
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_sub(&z->mpz, &a->mpz, &b->mpz);
return (PyObject *)z;
} /* mpz_substract() */
static PyObject *
mpz_multiply(mpzobject *a, mpzobject *b)
{
#ifdef MPZ_SPARE_MALLOC
int cmpres;
#endif /* def MPZ_SPARE_MALLOC */
mpzobject *z;
#ifdef MPZ_SPARE_MALLOC
if ((cmpres = mpz_cmp_ui(&a->mpz, (unsigned long int)0)) == 0) {
Py_INCREF(mpz_value_zero);
return (PyObject *)mpz_value_zero;
}
if (cmpres > 0 && mpz_cmp_ui(&a->mpz, (unsigned long int)1) == 0) {
Py_INCREF(b);
return (PyObject *)b;
}
if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long_int)0)) == 0) {
Py_INCREF(mpz_value_zero);
return (PyObject *)mpz_value_zero;
}
if (cmpres > 0 && mpz_cmp_ui(&b->mpz, (unsigned long int)1) == 0) {
Py_INCREF(a);
return (PyObject *)a;
}
#endif /* MPZ_SPARE_MALLOC */
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_mul( &z->mpz, &a->mpz, &b->mpz );
return (PyObject *)z;
} /* mpz_multiply() */
static PyObject *
mpz_divide(mpzobject *a, mpzobject *b)
{
#ifdef MPZ_SPARE_MALLOC
int cmpres;
#endif /* def MPZ_SPARE_MALLOC */
mpzobject *z;
if ((
#ifdef MPZ_SPARE_MALLOC
cmpres =
#endif /* def MPZ_SPARE_MALLOC */
mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
PyErr_SetString(PyExc_ZeroDivisionError, "mpz./ by zero");
return NULL;
}
#ifdef MPZ_SPARE_MALLOC
if (cmpres > 0 && mpz_cmp_ui(&b->mpz(unsigned long int)1) == 0) {
Py_INCREF(a);
return (PyObject *)a;
}
#endif /* def MPZ_SPARE_MALLOC */
if ((z = newmpzobject()) == NULL)
return NULL;
#ifdef MPZ_TEST_DIV
fputs("mpz_divide: div result", stderr);
mpz_div(&z->mpz, &a->mpz, &b->mpz);
mpz_out_str(stderr, 10, &z->mpz);
putc('\n', stderr);
#endif /* def MPZ_TEST_DIV */
#ifdef MPZ_MDIV_BUG
if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
!= (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)) {
/*
** numerator has other sign than denominator: we have
** to look at the remainder for a correction, since mpz_mdiv
** also calls mpz_divmod, I can as well do it myself
*/
MP_INT tmpmpz;
mpz_init(&tmpmpz);
mpz_divmod(&z->mpz, &tmpmpz, &a->mpz, &b->mpz);
if (mpz_cmp_ui(&tmpmpz, (unsigned long int)0) != 0)
mpz_sub_ui(&z->mpz, &z->mpz, (unsigned long int)1);
mpz_clear(&tmpmpz);
}
else
mpz_div(&z->mpz, &a->mpz, &b->mpz);
/* the ``naive'' implementation does it right for operands
having the same sign */
#else /* def MPZ_MDIV_BUG */
mpz_mdiv(&z->mpz, &a->mpz, &b->mpz);
#endif /* def MPZ_MDIV_BUG else */
#ifdef MPZ_TEST_DIV
fputs("mpz_divide: mdiv result", stderr);
mpz_out_str(stderr, 10, &z->mpz);
putc('\n', stderr);
#endif /* def MPZ_TEST_DIV */
return (PyObject *)z;
} /* mpz_divide() */
static PyObject *
mpz_remainder(mpzobject *a, mpzobject *b)
{
#ifdef MPZ_SPARE_MALLOC
int cmpres;
#endif /* def MPZ_SPARE_MALLOC */
mpzobject *z;
if ((
#ifdef MPZ_SPARE_MALLOC
cmpres =
#endif /* def MPZ_SPARE_MALLOC */
mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
PyErr_SetString(PyExc_ZeroDivisionError, "mpz.% by zero");
return NULL;
}
#ifdef MPZ_SPARE_MALLOC
if (cmpres > 0) {
if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)2)) == 0)
{
Py_INCREF(mpz_value_one);
return (PyObject *)mpz_value_one;
}
if (cmpres < 0) {
/* b must be 1 now */
Py_INCREF(mpz_value_zero);
return (PyObject *)mpz_value_zero;
}
}
#endif /* def MPZ_SPARE_MALLOC */
if ((z = newmpzobject()) == NULL)
return NULL;
#ifdef MPZ_TEST_DIV
fputs("mpz_remain: mod result", stderr);
mpz_mod(&z->mpz, &a->mpz, &b->mpz);
mpz_out_str(stderr, 10, &z->mpz);
putc('\n', stderr);
#endif /* def MPZ_TEST_DIV */
#ifdef MPZ_MDIV_BUG
/* the ``naive'' implementation does it right for operands
having the same sign */
mpz_mod(&z->mpz, &a->mpz, &b->mpz);
/* assumption: z, a and b all point to different locations */
if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
!= (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)
&& mpz_cmp_ui(&z->mpz, (unsigned long int)0) != 0)
mpz_add(&z->mpz, &z->mpz, &b->mpz);
/*
** numerator has other sign than denominator: we have
** to look at the remainder for a correction, since mpz_mdiv
** also calls mpz_divmod, I can as well do it myself
*/
#else /* def MPZ_MDIV_BUG */
mpz_mmod(&z->mpz, &a->mpz, &b->mpz);
#endif /* def MPZ_MDIV_BUG else */
#ifdef MPZ_TEST_DIV
fputs("mpz_remain: mmod result", stderr);
mpz_out_str(stderr, 10, &z->mpz);
putc('\n', stderr);
#endif /* def MPZ_TEST_DIV */
return (PyObject *)z;
} /* mpz_remainder() */
static PyObject *
mpz_div_and_mod(mpzobject *a, mpzobject *b)
{
PyObject *z = NULL;
mpzobject *x = NULL, *y = NULL;
if (mpz_cmp_ui(&b->mpz, (unsigned long int)0) == 0) {
PyErr_SetString(PyExc_ZeroDivisionError, "mpz.divmod by zero");
return NULL;
}
if ((z = PyTuple_New(2)) == NULL
|| (x = newmpzobject()) == NULL
|| (y = newmpzobject()) == NULL) {
Py_XDECREF(z);
Py_XDECREF(x);
Py_XDECREF(y);
return NULL;
}
#ifdef MPZ_TEST_DIV
fputs("mpz_divmod: dm result", stderr);
mpz_divmod(&x->mpz, &y->mpz, &a->mpz, &b->mpz);
mpz_out_str(stderr, 10, &x->mpz);
putc('\n', stderr);
mpz_out_str(stderr, 10, &y->mpz);
putc('\n', stderr);
#endif /* def MPZ_TEST_DIV */
#ifdef MPZ_MDIV_BUG
mpz_divmod(&x->mpz, &y->mpz, &a->mpz, &b->mpz);
if ((mpz_cmp_ui(&a->mpz, (unsigned long int)0) < 0)
!= (mpz_cmp_ui(&b->mpz, (unsigned long int)0) < 0)
&& mpz_cmp_ui(&y->mpz, (unsigned long int)0) != 0) {
/*
** numerator has other sign than denominator: we have
** to look at the remainder for a correction.
*/
mpz_add(&y->mpz, &y->mpz, &b->mpz);
mpz_sub_ui(&x->mpz, &x->mpz, (unsigned long int)1);
}
#else /* def MPZ_MDIV_BUG */
mpz_mdivmod( &x->mpz, &y->mpz, &a->mpz, &b->mpz );
#endif /* def MPZ_MDIV_BUG else */
#ifdef MPZ_TEST_DIV
fputs("mpz_divmod: mdm result", stderr);
mpz_out_str(stderr, 10, &x->mpz);
putc('\n', stderr);
mpz_out_str(stderr, 10, &y->mpz);
putc('\n', stderr);
#endif /* def MPZ_TEST_DIV */
(void)PyTuple_SetItem(z, 0, (PyObject *)x);
(void)PyTuple_SetItem(z, 1, (PyObject *)y);
return z;
} /* mpz_div_and_mod() */
static PyObject *
mpz_power(mpzobject *a, mpzobject *b, mpzobject *m)
{
mpzobject *z;
int cmpres;
if ((PyObject *)m != Py_None) {
mpzobject *z2;
Py_INCREF(Py_None);
z=(mpzobject *)mpz_power(a, b, (mpzobject *)Py_None);
Py_DECREF(Py_None);
if (z==NULL) return((PyObject *)z);
z2=(mpzobject *)mpz_remainder(z, m);
Py_DECREF(z);
return((PyObject *)z2);
}
if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
/* the gnu-mp lib sets pow(0,0) to 0, we to 1 */
Py_INCREF(mpz_value_one);
return (PyObject *)mpz_value_one;
}
if (cmpres < 0) {
PyErr_SetString(PyExc_ValueError,
"mpz.pow to negative exponent");
return NULL;
}
if ((cmpres = mpz_cmp_ui(&a->mpz, (unsigned long int)0)) == 0) {
/* the base is 0 */
Py_INCREF(mpz_value_zero);
return (PyObject *)mpz_value_zero;
}
else if (cmpres > 0
&& mpz_cmp_ui(&a->mpz, (unsigned long int)1) == 0) {
/* the base is 1 */
Py_INCREF(mpz_value_one);
return (PyObject *)mpz_value_one;
}
else if (cmpres < 0
&& mpz_cmp_si(&a->mpz, (long int)-1) == 0) {
MP_INT tmpmpz;
/* the base is -1: pow(-1, any) == 1,-1 for even,uneven b */
/* XXX this code needs to be optimized: what's better?
mpz_mmod_ui or mpz_mod_2exp, I choose for the latter
for *un*obvious reasons */
/* is the exponent even? */
mpz_init(&tmpmpz);
/* look to the remainder after a division by (1 << 1) */
mpz_mod_2exp(&tmpmpz, &b->mpz, (unsigned long int)1);
if (mpz_cmp_ui(&tmpmpz, (unsigned int)0) == 0) {
mpz_clear(&tmpmpz);
Py_INCREF(mpz_value_one);
return (PyObject *)mpz_value_one;
}
mpz_clear(&tmpmpz);
Py_INCREF(mpz_value_mone);
return (PyObject *)mpz_value_mone;
}
#ifdef MPZ_LIB_DOES_CHECKING
/* check if it's doable: sizeof(exp) > sizeof(long) &&
abs(base) > 1 ?? --> No Way */
if (mpz_size(&b->mpz) > 1)
return (PyObject *)PyErr_NoMemory();
#else /* def MPZ_LIB_DOES_CHECKING */
/* wet finger method */
if (mpz_cmp_ui(&b->mpz, (unsigned long int)0x10000) >= 0) {
PyErr_SetString(PyExc_ValueError,
"mpz.pow outrageous exponent");
return NULL;
}
#endif /* def MPZ_LIB_DOES_CHECKING else */
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_pow_ui(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
return (PyObject *)z;
} /* mpz_power() */
static PyObject *
mpz_negative(mpzobject *v)
{
mpzobject *z;
#ifdef MPZ_SPARE_MALLOC
if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) == 0) {
/* -0 == 0 */
Py_INCREF(v);
return (PyObject *)v;
}
#endif /* def MPZ_SPARE_MALLOC */
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_neg(&z->mpz, &v->mpz);
return (PyObject *)z;
} /* mpz_negative() */
static PyObject *
mpz_positive(mpzobject *v)
{
Py_INCREF(v);
return (PyObject *)v;
} /* mpz_positive() */
static PyObject *
mpz_absolute(mpzobject *v)
{
mpzobject *z;
if (mpz_cmp_ui(&v->mpz, (unsigned long int)0) >= 0) {
Py_INCREF(v);
return (PyObject *)v;
}
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_neg(&z->mpz, &v->mpz);
return (PyObject *)z;
} /* mpz_absolute() */
static int
mpz_nonzero(mpzobject *v)
{
return mpz_cmp_ui(&v->mpz, (unsigned long int)0) != 0;
} /* mpz_nonzero() */
static PyObject *
py_mpz_invert(mpzobject *v)
{
mpzobject *z;
/* I think mpz_com does exactly what needed */
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_com(&z->mpz, &v->mpz);
return (PyObject *)z;
} /* py_mpz_invert() */
static PyObject *
mpz_lshift(mpzobject *a, mpzobject *b)
{
int cmpres;
mpzobject *z;
if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
/* a << 0 == a */
Py_INCREF(a);
return (PyObject *)a;
}
if (cmpres < 0) {
PyErr_SetString(PyExc_ValueError,
"mpz.<< negative shift count");
return NULL;
}
#ifdef MPZ_LIB_DOES_CHECKING
if (mpz_size(&b->mpz) > 1)
return (PyObject *)PyErr_NoMemory();
#else /* def MPZ_LIB_DOES_CHECKING */
/* wet finger method */
if (mpz_cmp_ui(&b->mpz, (unsigned long int)0x10000) >= 0) {
PyErr_SetString(PyExc_ValueError,
"mpz.<< outrageous shift count");
return NULL;
}
#endif /* def MPZ_LIB_DOES_CHECKING else */
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_mul_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
return (PyObject *)z;
} /* mpz_lshift() */
static PyObject *
mpz_rshift(mpzobject *a, mpzobject *b)
{
int cmpres;
mpzobject *z;
if ((cmpres = mpz_cmp_ui(&b->mpz, (unsigned long int)0)) == 0) {
/* a >> 0 == a */
Py_INCREF(a);
return (PyObject *)a;
}
if (cmpres < 0) {
PyErr_SetString(PyExc_ValueError,
"mpz.>> negative shift count");
return NULL;
}
if (mpz_size(&b->mpz) > 1)
return (PyObject *)PyErr_NoMemory();
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_div_2exp(&z->mpz, &a->mpz, mpz_get_ui(&b->mpz));
return (PyObject *)z;
} /* mpz_rshift() */
static PyObject *
mpz_andfunc(mpzobject *a, mpzobject *b)
{
mpzobject *z;
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_and(&z->mpz, &a->mpz, &b->mpz);
return (PyObject *)z;
} /* mpz_andfunc() */
/* hack Hack HAck HACk HACK, XXX this code is dead slow */
void
mpz_xor(MP_INT *res, const MP_INT *op1, const MP_INT *op2)
{
MP_INT tmpmpz;
mpz_init(&tmpmpz);
mpz_and(res, op1, op2);
mpz_com(&tmpmpz, res);
mpz_ior(res, op1, op2);
mpz_and(res, res, &tmpmpz);
mpz_clear(&tmpmpz);
} /* mpz_xor() HACK */
static PyObject *
mpz_xorfunc(mpzobject *a, mpzobject *b)
{
mpzobject *z;
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_xor(&z->mpz, &a->mpz, &b->mpz);
return (PyObject *)z;
} /* mpz_xorfunc() */
static PyObject *
mpz_orfunc(mpzobject *a, mpzobject *b)
{
mpzobject *z;
if ((z = newmpzobject()) == NULL)
return NULL;
mpz_ior(&z->mpz, &a->mpz, &b->mpz);
return (PyObject *)z;
} /* mpz_orfunc() */
/* MPZ initialisation */
#include "longintrepr.h"
static PyObject *
MPZ_mpz(PyObject *self, PyObject *args)
{
mpzobject *mpzp;
#ifdef MPZ_DEBUG
fputs("MPZ_mpz() called...\n", stderr);
#endif /* def MPZ_DEBUG */
/* at least we know it's some object */
/* note DON't Py_DECREF args */
if (PyInt_Check(args)) {
long lval = PyInt_AS_LONG(args);
if (lval == (long)0) {
Py_INCREF(mpz_value_zero);
mpzp = mpz_value_zero;
}
else if (lval == (long)1) {
Py_INCREF(mpz_value_one);
mpzp = mpz_value_one;
}
else if ((mpzp = newmpzobject()) == NULL)
return NULL;
else mpz_set_si(&mpzp->mpz, lval);
}
else if (PyLong_Check(args)) {
MP_INT mplongdigit;
int i;
unsigned char isnegative;
if ((mpzp = newmpzobject()) == NULL)
return NULL;
mpz_set_si(&mpzp->mpz, 0L);
mpz_init(&mplongdigit);
/* how we're gonna handle this? */
if ((isnegative =
((i = ((PyLongObject *)args)->ob_size) < 0) ))
i = -i;
while (i--) {
mpz_set_ui(&mplongdigit,
(unsigned long)
((PyLongObject *)args)->ob_digit[i]);
mpz_mul_2exp(&mplongdigit,&mplongdigit,
(unsigned long int)i * SHIFT);
mpz_ior(&mpzp->mpz, &mpzp->mpz, &mplongdigit);
}
if (isnegative)
mpz_neg(&mpzp->mpz, &mpzp->mpz);
/* get rid of allocation for tmp variable */
mpz_clear(&mplongdigit);
}
else if (PyString_Check(args)) {
unsigned char *cp = (unsigned char *)PyString_AS_STRING(args);
int len = PyString_GET_SIZE(args);
MP_INT mplongdigit;
if ((mpzp = newmpzobject()) == NULL)
return NULL;
mpz_set_si(&mpzp->mpz, 0L);
mpz_init(&mplongdigit);
/* let's do it the same way as with the long conversion:
without thinking how it can be faster (-: :-) */
cp += len;
while (len--) {
mpz_set_ui(&mplongdigit, (unsigned long)*--cp );
mpz_mul_2exp(&mplongdigit,&mplongdigit,
(unsigned long int)len * 8);
mpz_ior(&mpzp->mpz, &mpzp->mpz, &mplongdigit);
}
/* get rid of allocation for tmp variable */
mpz_clear(&mplongdigit);
}
else if (is_mpzobject(args)) {
Py_INCREF(args);
mpzp = (mpzobject *)args;
}
else {
PyErr_SetString(PyExc_TypeError,
"mpz.mpz() expects integer, long, string or mpz object argument");
return NULL;
}
#ifdef MPZ_DEBUG
fputs("MPZ_mpz: created mpz=", stderr);
mpz_out_str(stderr, 10, &mpzp->mpz);
putc('\n', stderr);
#endif /* def MPZ_DEBUG */
return (PyObject *)mpzp;
} /* MPZ_mpz() */
static mpzobject *
mpz_mpzcoerce(PyObject *z)
{
/* shortcut: 9 out of 10 times the type is already ok */
if (is_mpzobject(z)) {
Py_INCREF(z);
return (mpzobject *)z; /* coercion succeeded */
}
/* what types do we accept?: intobjects and longobjects */
if (PyInt_Check(z) || PyLong_Check(z))
return (mpzobject *)MPZ_mpz((PyObject *)NULL, z);
PyErr_SetString(PyExc_TypeError,
"number coercion (to mpzobject) failed");
return NULL;
} /* mpz_mpzcoerce() */
/* Forward */
static void mpz_divm(MP_INT *res, const MP_INT *num,
const MP_INT *den, const MP_INT *mod);
static PyObject *
MPZ_powm(PyObject *self, PyObject *args)
{
PyObject *base, *exp, *mod;
mpzobject *mpzbase = NULL, *mpzexp = NULL, *mpzmod = NULL;
mpzobject *z = NULL;
int tstres;
if (!PyArg_ParseTuple(args, "OOO", &base, &exp, &mod))
return NULL;
if ((mpzbase = mpz_mpzcoerce(base)) == NULL
|| (mpzexp = mpz_mpzcoerce(exp)) == NULL
|| (mpzmod = mpz_mpzcoerce(mod)) == NULL
|| (z = newmpzobject()) == NULL) {
Py_XDECREF(mpzbase);
Py_XDECREF(mpzexp);
Py_XDECREF(mpzmod);
Py_XDECREF(z);
return NULL;
}
if ((tstres=mpz_cmp_ui(&mpzexp->mpz, (unsigned long int)0)) == 0) {
Py_DECREF(mpzbase);
Py_DECREF(mpzexp);
Py_DECREF(mpzmod);
Py_DECREF(z);
Py_INCREF(mpz_value_one);
return (PyObject *)mpz_value_one;
}
if (mpz_cmp_ui(&mpzmod->mpz, 0) == 0) {
Py_DECREF(mpzbase);
Py_DECREF(mpzexp);
Py_DECREF(mpzmod);
Py_DECREF(z);
PyErr_SetString(PyExc_ValueError, "modulus cannot be 0");
return NULL;
}
if (tstres < 0) {
MP_INT absexp;
/* negative exp */
mpz_init_set(&absexp, &mpzexp->mpz);
mpz_abs(&absexp, &absexp);
mpz_powm(&z->mpz, &mpzbase->mpz, &absexp, &mpzmod->mpz);
mpz_divm(&z->mpz, &mpz_value_one->mpz, &z->mpz, &mpzmod->mpz);
mpz_clear(&absexp);
}
else {
mpz_powm(&z->mpz, &mpzbase->mpz, &mpzexp->mpz, &mpzmod->mpz);
}
Py_DECREF(mpzbase);
Py_DECREF(mpzexp);
Py_DECREF(mpzmod);
return (PyObject *)z;
} /* MPZ_powm() */
static PyObject *
MPZ_gcd(PyObject *self, PyObject *args)
{
PyObject *op1, *op2;
mpzobject *mpzop1 = NULL, *mpzop2 = NULL;
mpzobject *z;
if (!PyArg_ParseTuple(args, "OO", &op1, &op2))
return NULL;
if ((mpzop1 = mpz_mpzcoerce(op1)) == NULL
|| (mpzop2 = mpz_mpzcoerce(op2)) == NULL
|| (z = newmpzobject()) == NULL) {
Py_XDECREF(mpzop1);
Py_XDECREF(mpzop2);
return NULL;
}
/* ok, we have three mpzobjects, and an initialised result holder */
mpz_gcd(&z->mpz, &mpzop1->mpz, &mpzop2->mpz);
Py_DECREF(mpzop1);
Py_DECREF(mpzop2);
return (PyObject *)z;
} /* MPZ_gcd() */
static PyObject *
MPZ_gcdext(PyObject *self, PyObject *args)
{
PyObject *op1, *op2, *z = NULL;
mpzobject *mpzop1 = NULL, *mpzop2 = NULL;
mpzobject *g = NULL, *s = NULL, *t = NULL;
if (!PyArg_ParseTuple(args, "OO", &op1, &op2))
return NULL;
if ((mpzop1 = mpz_mpzcoerce(op1)) == NULL
|| (mpzop2 = mpz_mpzcoerce(op2)) == NULL
|| (z = PyTuple_New(3)) == NULL
|| (g = newmpzobject()) == NULL
|| (s = newmpzobject()) == NULL
|| (t = newmpzobject()) == NULL) {
Py_XDECREF(mpzop1);
Py_XDECREF(mpzop2);
Py_XDECREF(z);
Py_XDECREF(g);
Py_XDECREF(s);
/*Py_XDECREF(t);*/
return NULL;
}
mpz_gcdext(&g->mpz, &s->mpz, &t->mpz, &mpzop1->mpz, &mpzop2->mpz);
Py_DECREF(mpzop1);
Py_DECREF(mpzop2);
(void)PyTuple_SetItem(z, 0, (PyObject *)g);
(void)PyTuple_SetItem(z, 1, (PyObject *)s);
(void)PyTuple_SetItem(z, 2, (PyObject *)t);
return (PyObject *)z;
} /* MPZ_gcdext() */
static PyObject *
MPZ_sqrt(PyObject *self, PyObject *args)
{
mpzobject *mpzop = NULL;
mpzobject *z;
if ((mpzop = mpz_mpzcoerce(args)) == NULL
|| (z = newmpzobject()) == NULL) {
Py_XDECREF(mpzop);
return NULL;
}
mpz_sqrt(&z->mpz, &mpzop->mpz);
Py_DECREF(mpzop);
return (PyObject *)z;
} /* MPZ_sqrt() */
static PyObject *
MPZ_sqrtrem(PyObject *self, PyObject *args)
{
PyObject *z = NULL;
mpzobject *mpzop = NULL;
mpzobject *root = NULL, *rem = NULL;
if ((mpzop = mpz_mpzcoerce(args)) == NULL
|| (z = PyTuple_New(2)) == NULL
|| (root = newmpzobject()) == NULL
|| (rem = newmpzobject()) == NULL) {
Py_XDECREF(mpzop);
Py_XDECREF(z);
Py_XDECREF(root);
/*Py_XDECREF(rem);*/
return NULL;
}
mpz_sqrtrem(&root->mpz, &rem->mpz, &mpzop->mpz);
Py_DECREF(mpzop);
(void)PyTuple_SetItem(z, 0, (PyObject *)root);
(void)PyTuple_SetItem(z, 1, (PyObject *)rem);
return (PyObject *)z;
} /* MPZ_sqrtrem() */
static void
mpz_divm(MP_INT *res, const MP_INT *num, const MP_INT *den, const MP_INT *mod)
{
MP_INT s0, s1, q, r, x, d0, d1;
mpz_init_set(&s0, num);
mpz_init_set_ui(&s1, 0);
mpz_init(&q);
mpz_init(&r);
mpz_init(&x);
mpz_init_set(&d0, den);
mpz_init_set(&d1, mod);
#ifdef GMP2
while (d1._mp_size != 0) {
#else
while (d1.size != 0) {
#endif
mpz_divmod(&q, &r, &d0, &d1);
mpz_set(&d0, &d1);
mpz_set(&d1, &r);
mpz_mul(&x, &s1, &q);
mpz_sub(&x, &s0, &x);
mpz_set(&s0, &s1);
mpz_set(&s1, &x);
}
#ifdef GMP2
if (d0._mp_size != 1 || d0._mp_d[0] != 1)
res->_mp_size = 0; /* trouble: the gcd != 1; set s to zero */
#else
if (d0.size != 1 || d0.d[0] != 1)
res->size = 0; /* trouble: the gcd != 1; set s to zero */
#endif
else {
#ifdef MPZ_MDIV_BUG
/* watch out here! first check the signs, and then perform
the mpz_mod() since mod could point to res */
if ((s0.size < 0) != (mod->size < 0)) {
mpz_mod(res, &s0, mod);
if (res->size)
mpz_add(res, res, mod);
}
else
mpz_mod(res, &s0, mod);
#else /* def MPZ_MDIV_BUG */
mpz_mmod(res, &s0, mod);
#endif /* def MPZ_MDIV_BUG else */
}
mpz_clear(&s0);
mpz_clear(&s1);
mpz_clear(&q);
mpz_clear(&r);
mpz_clear(&x);
mpz_clear(&d0);
mpz_clear(&d1);
} /* mpz_divm() */
static PyObject *
MPZ_divm(PyObject *self, PyObject *args)
{
PyObject *num, *den, *mod;
mpzobject *mpznum, *mpzden = NULL, *mpzmod = NULL;
mpzobject *z = NULL;
if (!PyArg_ParseTuple(args, "OOO", &num, &den, &mod))
return NULL;
if ((mpznum = mpz_mpzcoerce(num)) == NULL
|| (mpzden = mpz_mpzcoerce(den)) == NULL
|| (mpzmod = mpz_mpzcoerce(mod)) == NULL
|| (z = newmpzobject()) == NULL ) {
Py_XDECREF(mpznum);
Py_XDECREF(mpzden);
Py_XDECREF(mpzmod);
return NULL;
}
mpz_divm(&z->mpz, &mpznum->mpz, &mpzden->mpz, &mpzmod->mpz);
Py_DECREF(mpznum);
Py_DECREF(mpzden);
Py_DECREF(mpzmod);
if (mpz_cmp_ui(&z->mpz, (unsigned long int)0) == 0) {
Py_DECREF(z);
PyErr_SetString(PyExc_ValueError,
"gcd(den, mod) != 1 or num == 0");
return NULL;
}
return (PyObject *)z;
} /* MPZ_divm() */
static PyObject *
mpz_int(mpzobject *self)
{
long sli;
if (mpz_size(&self->mpz) > 1
|| (sli = (long)mpz_get_ui(&self->mpz)) < (long)0 ) {
PyErr_SetString(PyExc_ValueError,
"mpz.int() arg too long to convert");
return NULL;
}
if (mpz_cmp_ui(&self->mpz, (unsigned long)0) < 0)
sli = -sli;
return PyInt_FromLong(sli);
} /* mpz_int() */
static PyObject *
mpz_long(mpzobject *self)
{
int i, isnegative;
unsigned long int uli;
PyLongObject *longobjp;
int ldcount;
int bitpointer, newbitpointer;
MP_INT mpzscratch;
/* determine length of python-long to be allocated */
if ((longobjp = _PyLong_New(i = (int)
((mpz_size(&self->mpz) * BITS_PER_MP_LIMB
+ SHIFT - 1) /
SHIFT))) == NULL)
return NULL;
/* determine sign, and copy self to scratch var */
mpz_init_set(&mpzscratch, &self->mpz);
if ((isnegative = (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0)))
mpz_neg(&mpzscratch, &mpzscratch);
/* let those bits come, let those bits go,
e.g. dismantle mpzscratch, build PyLongObject */
bitpointer = 0; /* the number of valid bits in stock */
newbitpointer = 0;
ldcount = 0; /* the python-long limb counter */
uli = (unsigned long int)0;
while (i--) {
longobjp->ob_digit[ldcount] = uli & MASK;
/* check if we've had enough bits for this digit */
if (bitpointer < SHIFT) {
uli = mpz_get_ui(&mpzscratch);
longobjp->ob_digit[ldcount] |=
(uli << bitpointer) & MASK;
uli >>= SHIFT-bitpointer;
bitpointer += BITS_PER_MP_LIMB;
mpz_div_2exp(&mpzscratch, &mpzscratch,
BITS_PER_MP_LIMB);
}
else
uli >>= SHIFT;
bitpointer -= SHIFT;
ldcount++;
}
assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
mpz_clear(&mpzscratch);
assert(ldcount <= longobjp->ob_size);
/* long_normalize() is file-static */
/* longobjp = long_normalize(longobjp); */
while (ldcount > 0 && longobjp->ob_digit[ldcount-1] == 0)
ldcount--;
longobjp->ob_size = ldcount;
if (isnegative)
longobjp->ob_size = -longobjp->ob_size;
return (PyObject *)longobjp;
} /* mpz_long() */
/* I would have avoided pow() anyways, so ... */
static const double multiplier = 256.0 * 256.0 * 256.0 * 256.0;
static PyObject *
mpz_float(mpzobject *self)
{
int i, isnegative;
double x;
double mulstate;
MP_INT mpzscratch;
i = (int)mpz_size(&self->mpz);
/* determine sign, and copy abs(self) to scratch var */
if ((isnegative = (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0)))
{
mpz_init(&mpzscratch);
mpz_neg(&mpzscratch, &self->mpz);
}
else
mpz_init_set(&mpzscratch, &self->mpz);
/* let those bits come, let those bits go,
e.g. dismantle mpzscratch, build PyFloatObject */
/* Can this overflow? Dunno, protect against that possibility. */
PyFPE_START_PROTECT("mpz_float", return 0)
x = 0.0;
mulstate = 1.0;
while (i--) {
x += mulstate * mpz_get_ui(&mpzscratch);
mulstate *= multiplier;
mpz_div_2exp(&mpzscratch, &mpzscratch, BITS_PER_MP_LIMB);
}
PyFPE_END_PROTECT(mulstate)
assert(mpz_cmp_ui(&mpzscratch, (unsigned long int)0) == 0);
mpz_clear(&mpzscratch);
if (isnegative)
x = -x;
return PyFloat_FromDouble(x);
} /* mpz_float() */
static PyObject *
mpz_hex(mpzobject *self)
{
return mpz_format((PyObject *)self, 16, (unsigned char)1);
} /* mpz_hex() */
static PyObject *
mpz_oct(mpzobject *self)
{
return mpz_format((PyObject *)self, 8, (unsigned char)1);
} /* mpz_oct() */
static PyObject *
mpz_binary(mpzobject *self)
{
int size;
PyStringObject *strobjp;
char *cp;
MP_INT mp;
unsigned long ldigit;
if (mpz_cmp_ui(&self->mpz, (unsigned long int)0) < 0) {
PyErr_SetString(PyExc_ValueError,
"mpz.binary() arg must be >= 0");
return NULL;
}
mpz_init_set(&mp, &self->mpz);
size = (int)mpz_size(&mp);
if ((strobjp = (PyStringObject *)
PyString_FromStringAndSize(
(char *)0, size * sizeof (unsigned long int))) == NULL)
return NULL;
/* get the beginning of the string memory and start copying things */
cp = PyString_AS_STRING(strobjp);
/* this has been programmed using a (fairly) decent lib-i/f it could
be must faster if we looked into the GMP lib */
while (size--) {
ldigit = mpz_get_ui(&mp);
mpz_div_2exp(&mp, &mp, BITS_PER_MP_LIMB);
*cp++ = (unsigned char)(ldigit & 0xFF);
*cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
*cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
*cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
if (sizeof(ldigit) == 8 && BITS_PER_MP_LIMB == 64) {
*cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
*cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
*cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
*cp++ = (unsigned char)((ldigit >>= 8) & 0xFF);
}
}
while (strobjp->ob_size && !*--cp)
strobjp->ob_size--;
return (PyObject *)strobjp;
} /* mpz_binary() */
static PyMethodDef mpz_methods[] = {
#ifdef MPZ_CONVERSIONS_AS_METHODS
{"int", mpz_int, METH_NOARGS},
{"long", mpz_long, METH_NOARGS},
{"float", mpz_float, METH_NOARGS},
{"hex", mpz_hex, METH_NOARGS},
{"oct", mpz_oct, METH_NOARGS},
#endif /* def MPZ_CONVERSIONS_AS_METHODS */
{"binary", (PyCFunction)mpz_binary, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
static PyObject *
mpz_getattr(mpzobject *self, char *name)
{
return Py_FindMethod(mpz_methods, (PyObject *)self, name);
} /* mpz_getattr() */
static int
mpz_coerce(PyObject **pv, PyObject **pw)
{
PyObject *z;
#ifdef MPZ_DEBUG
fputs("mpz_coerce() called...\n", stderr);
#endif /* def MPZ_DEBUG */
assert(is_mpzobject(*pv));
/* always convert other arg to mpz value, except for floats */
if (!PyFloat_Check(*pw)) {
if ((z = (PyObject *)mpz_mpzcoerce(*pw)) == NULL)
return -1; /* -1: an error always has been set */
Py_INCREF(*pv);
*pw = z;
}
else {
if ((z = mpz_float((mpzobject *)(*pv))) == NULL)
return -1;
Py_INCREF(*pw);
*pv = z;
}
return 0; /* coercion succeeded */
} /* mpz_coerce() */
static PyObject *
mpz_repr(PyObject *v)
{
return mpz_format(v, 10, (unsigned char)1);
} /* mpz_repr() */
#define UF (unaryfunc)
#define BF (binaryfunc)
#define TF (ternaryfunc)
#define IF (inquiry)
#define CF (coercion)
static PyNumberMethods mpz_as_number = {
BF mpz_addition, /*nb_add*/
BF mpz_substract, /*nb_subtract*/
BF mpz_multiply, /*nb_multiply*/
BF mpz_divide, /*nb_divide*/
BF mpz_remainder, /*nb_remainder*/
BF mpz_div_and_mod, /*nb_divmod*/
TF mpz_power, /*nb_power*/
UF mpz_negative, /*nb_negative*/
UF mpz_positive, /*tp_positive*/
UF mpz_absolute, /*tp_absolute*/
IF mpz_nonzero, /*tp_nonzero*/
UF py_mpz_invert, /*nb_invert*/
BF mpz_lshift, /*nb_lshift*/
BF mpz_rshift, /*nb_rshift*/
BF mpz_andfunc, /*nb_and*/
BF mpz_xorfunc, /*nb_xor*/
BF mpz_orfunc, /*nb_or*/
CF mpz_coerce, /*nb_coerce*/
#ifndef MPZ_CONVERSIONS_AS_METHODS
UF mpz_int, /*nb_int*/
UF mpz_long, /*nb_long*/
UF mpz_float, /*nb_float*/
UF mpz_oct, /*nb_oct*/
UF mpz_hex, /*nb_hex*/
#endif /* ndef MPZ_CONVERSIONS_AS_METHODS */
};
static PyTypeObject MPZtype = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"mpz.mpz", /*tp_name*/
sizeof(mpzobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)mpz_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)mpz_getattr, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)mpz_compare, /*tp_compare*/
(reprfunc)mpz_repr, /*tp_repr*/
&mpz_as_number, /*tp_as_number*/
};
/* List of functions exported by this module */
static PyMethodDef mpz_functions[] = {
#if 0
{initialiser_name, MPZ_mpz, METH_O},
#else /* 0 */
/* until guido ``fixes'' struct PyMethodDef */
{(char *)initialiser_name, MPZ_mpz, METH_O},
#endif /* 0 else */
{"powm", MPZ_powm, METH_VARARGS},
{"gcd", MPZ_gcd, METH_VARARGS},
{"gcdext", MPZ_gcdext, METH_VARARGS},
{"sqrt", MPZ_sqrt, METH_O},
{"sqrtrem", MPZ_sqrtrem, METH_O},
{"divm", MPZ_divm, METH_VARARGS},
{NULL, NULL} /* Sentinel */
};
/* #define MP_TEST_ALLOC */
#ifdef MP_TEST_ALLOC
#define MP_TEST_SIZE 4
static const char mp_test_magic[MP_TEST_SIZE] = {'\xAA','\xAA','\xAA','\xAA'};
static mp_test_error(int *location)
{
/* assumptions: *alloc returns address divisible by 4,
mpz_* routines allocate in chunks divisible by four */
fprintf(stderr, "MP_TEST_ERROR: location holds 0x%08d\n", *location );
Py_FatalError("MP_TEST_ERROR");
} /* static mp_test_error() */
#define MP_EXTRA_ALLOC(size) ((size) + MP_TEST_SIZE)
#define MP_SET_TEST(basep,size) (void)memcpy( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE)
#define MP_DO_TEST(basep,size) if ( !memcmp( ((char *)(basep))+(size), mp_test_magic, MP_TEST_SIZE ) ) \
; \
else \
mp_test_error((int *)((char *)(basep) + size))
#else /* def MP_TEST_ALLOC */
#define MP_EXTRA_ALLOC(size) (size)
#define MP_SET_TEST(basep,size)
#define MP_DO_TEST(basep,size)
#endif /* def MP_TEST_ALLOC else */
void *mp_allocate(size_t alloc_size)
{
void *res;
#ifdef MPZ_DEBUG
fprintf(stderr, "mp_allocate : size %ld\n",
alloc_size);
#endif /* def MPZ_DEBUG */
if ( (res = malloc(MP_EXTRA_ALLOC(alloc_size))) == NULL )
Py_FatalError("mp_allocate failure");
#ifdef MPZ_DEBUG
fprintf(stderr, "mp_allocate : address %08p\n", res);
#endif /* def MPZ_DEBUG */
MP_SET_TEST(res,alloc_size);
return res;
} /* mp_allocate() */
void *mp_reallocate(void *ptr, size_t old_size, size_t new_size)
{
void *res;
#ifdef MPZ_DEBUG
fprintf(stderr, "mp_reallocate: old address %08p, old size %ld\n",
ptr, old_size);
#endif /* def MPZ_DEBUG */
MP_DO_TEST(ptr, old_size);
if ( (res = realloc(ptr, MP_EXTRA_ALLOC(new_size))) == NULL )
Py_FatalError("mp_reallocate failure");
#ifdef MPZ_DEBUG
fprintf(stderr, "mp_reallocate: new address %08p, new size %ld\n",
res, new_size);
#endif /* def MPZ_DEBUG */
MP_SET_TEST(res, new_size);
return res;
} /* mp_reallocate() */
void mp_free(void *ptr, size_t size)
{
#ifdef MPZ_DEBUG
fprintf(stderr, "mp_free : old address %08p, old size %ld\n",
ptr, size);
#endif /* def MPZ_DEBUG */
MP_DO_TEST(ptr, size);
free(ptr);
} /* mp_free() */
/* Initialize this module. */
PyMODINIT_FUNC
initmpz(void)
{
PyObject *module;
PyObject *dict;
#ifdef MPZ_DEBUG
fputs( "initmpz() called...\n", stderr );
#endif /* def MPZ_DEBUG */
mp_set_memory_functions( mp_allocate, mp_reallocate, mp_free );
MPZtype.ob_type = &PyType_Type;
module = Py_InitModule("mpz", mpz_functions);
/* create some frequently used constants */
if ((mpz_value_zero = newmpzobject()) == NULL)
goto finally;
mpz_set_ui(&mpz_value_zero->mpz, (unsigned long int)0);
if ((mpz_value_one = newmpzobject()) == NULL)
goto finally;
mpz_set_ui(&mpz_value_one->mpz, (unsigned long int)1);
if ((mpz_value_mone = newmpzobject()) == NULL)
goto finally;
mpz_set_si(&mpz_value_mone->mpz, (long)-1);
dict = PyModule_GetDict(module);
if (dict != NULL) {
PyDict_SetItemString(dict, "MPZType", (PyObject*)&MPZtype);
}
finally:
return;
} /* initmpz() */
#ifdef MAKEDUMMYINT
int _mpz_dummy_int; /* XXX otherwise, we're .bss-less (DYNLOAD->Jack?) */
#endif /* def MAKEDUMMYINT */
/***********************************************************
Copyright 1994 by Lance Ellinghouse,
Cathedral City, California Republic, United States of America.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Lance Ellinghouse
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
/* This creates an encryption and decryption engine I am calling
a rotor due to the original design was a hardware rotor with
contacts used in Germany during WWII.
Rotor Module:
- rotor.newrotor('key') -> rotorobject (default of 6 rotors)
- rotor.newrotor('key', num_rotors) -> rotorobject
Rotor Objects:
- ro.setkey('string') -> None (resets the key as defined in newrotor().
- ro.encrypt('string') -> encrypted string
- ro.decrypt('encrypted string') -> unencrypted string
- ro.encryptmore('string') -> encrypted string
- ro.decryptmore('encrypted string') -> unencrypted string
NOTE: the {en,de}cryptmore() methods use the setup that was
established via the {en,de}crypt calls. They will NOT
re-initalize the rotors unless: 1) They have not been
initialized with {en,de}crypt since the last setkey() call;
2) {en,de}crypt has not been called for this rotor yet.
NOTE: you MUST use the SAME key in rotor.newrotor()
if you wish to decrypt an encrypted string.
Also, the encrypted string is NOT 0-127 ASCII.
It is considered BINARY data.
*/
/* Rotor objects */
#include "Python.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef struct {
PyObject_HEAD
int seed[3];
short key[5];
int isinited;
int size;
int size_mask;
int rotors;
unsigned char *e_rotor; /* [num_rotors][size] */
unsigned char *d_rotor; /* [num_rotors][size] */
unsigned char *positions; /* [num_rotors] */
unsigned char *advances; /* [num_rotors] */
} Rotorobj;
static PyTypeObject Rotor_Type;
#define is_rotor(v) ((v)->ob_type == &Rotor_Type)
/* This defines the necessary routines to manage rotor objects */
static void
set_seed(Rotorobj *r)
{
r->seed[0] = r->key[0];
r->seed[1] = r->key[1];
r->seed[2] = r->key[2];
r->isinited = FALSE;
}
/* Return the next random number in the range [0.0 .. 1.0) */
static double
r_random(Rotorobj *r)
{
int x, y, z;
double val, term;
x = r->seed[0];
y = r->seed[1];
z = r->seed[2];
x = 171 * (x % 177) - 2 * (x/177);
y = 172 * (y % 176) - 35 * (y/176);
z = 170 * (z % 178) - 63 * (z/178);
if (x < 0) x = x + 30269;
if (y < 0) y = y + 30307;
if (z < 0) z = z + 30323;
r->seed[0] = x;
r->seed[1] = y;
r->seed[2] = z;
term = (double)(
(((double)x)/(double)30269.0) +
(((double)y)/(double)30307.0) +
(((double)z)/(double)30323.0)
);
val = term - (double)floor((double)term);
if (val >= 1.0)
val = 0.0;
return val;
}
static short
r_rand(Rotorobj *r, short s)
{
return (short)((short)(r_random(r) * (double)s) % s);
}
static void
set_key(Rotorobj *r, char *key)
{
unsigned long k1=995, k2=576, k3=767, k4=671, k5=463;
size_t i;
size_t len = strlen(key);
for (i = 0; i < len; i++) {
unsigned short ki = Py_CHARMASK(key[i]);
k1 = (((k1<<3 | k1>>13) + ki) & 65535);
k2 = (((k2<<3 | k2>>13) ^ ki) & 65535);
k3 = (((k3<<3 | k3>>13) - ki) & 65535);
k4 = ((ki - (k4<<3 | k4>>13)) & 65535);
k5 = (((k5<<3 | k5>>13) ^ ~ki) & 65535);
}
r->key[0] = (short)k1;
r->key[1] = (short)(k2|1);
r->key[2] = (short)k3;
r->key[3] = (short)k4;
r->key[4] = (short)k5;
set_seed(r);
}
/* These define the interface to a rotor object */
static Rotorobj *
rotorobj_new(int num_rotors, char *key)
{
Rotorobj *xp;
xp = PyObject_New(Rotorobj, &Rotor_Type);
if (xp == NULL)
return NULL;
set_key(xp, key);
xp->size = 256;
xp->size_mask = xp->size - 1;
xp->size_mask = 0;
xp->rotors = num_rotors;
xp->e_rotor = NULL;
xp->d_rotor = NULL;
xp->positions = NULL;
xp->advances = NULL;
if (!(xp->e_rotor = PyMem_NEW(unsigned char, num_rotors * xp->size)))
goto finally;
if (!(xp->d_rotor = PyMem_NEW(unsigned char, num_rotors * xp->size)))
goto finally;
if (!(xp->positions = PyMem_NEW(unsigned char, num_rotors)))
goto finally;
if (!(xp->advances = PyMem_NEW(unsigned char, num_rotors)))
goto finally;
return xp;
finally:
if (xp->e_rotor)
PyMem_DEL(xp->e_rotor);
if (xp->d_rotor)
PyMem_DEL(xp->d_rotor);
if (xp->positions)
PyMem_DEL(xp->positions);
if (xp->advances)
PyMem_DEL(xp->advances);
Py_DECREF(xp);
return (Rotorobj*)PyErr_NoMemory();
}
/* These routines implement the rotor itself */
/* Here is a fairly sophisticated {en,de}cryption system. It is based on
the idea of a "rotor" machine. A bunch of rotors, each with a
different permutation of the alphabet, rotate around a different amount
after encrypting one character. The current state of the rotors is
used to encrypt one character.
The code is smart enough to tell if your alphabet has a number of
characters equal to a power of two. If it does, it uses logical
operations, if not it uses div and mod (both require a division).
You will need to make two changes to the code 1) convert to c, and
customize for an alphabet of 255 chars 2) add a filter at the begining,
and end, which subtracts one on the way in, and adds one on the way
out.
You might wish to do some timing studies. Another viable alternative
is to "byte stuff" the encrypted data of a normal (perhaps this one)
encryption routine.
j'
*/
/* Note: the C code here is a fairly straightforward transliteration of a
* rotor implemented in lisp. The original lisp code has been removed from
* this file to for simplification, but I've kept the docstrings as
* comments in front of the functions.
*/
/* Set ROTOR to the identity permutation */
static void
RTR_make_id_rotor(Rotorobj *r, unsigned char *rtr)
{
register int j;
register int size = r->size;
for (j = 0; j < size; j++) {
rtr[j] = (unsigned char)j;
}
}
/* The current set of encryption rotors */
static void
RTR_e_rotors(Rotorobj *r)
{
int i;
for (i = 0; i < r->rotors; i++) {
RTR_make_id_rotor(r, &(r->e_rotor[(i*r->size)]));
}
}
/* The current set of decryption rotors */
static void
RTR_d_rotors(Rotorobj *r)
{
register int i, j;
for (i = 0; i < r->rotors; i++) {
for (j = 0; j < r->size; j++) {
r->d_rotor[((i*r->size)+j)] = (unsigned char)j;
}
}
}
/* The positions of the rotors at this time */
static void
RTR_positions(Rotorobj *r)
{
int i;
for (i = 0; i < r->rotors; i++) {
r->positions[i] = 1;
}
}
/* The number of positions to advance the rotors at a time */
static void
RTR_advances(Rotorobj *r)
{
int i;
for (i = 0; i < r->rotors; i++) {
r->advances[i] = 1;
}
}
/* Permute the E rotor, and make the D rotor its inverse
* see Knuth for explanation of algorithm.
*/
static void
RTR_permute_rotor(Rotorobj *r, unsigned char *e, unsigned char *d)
{
short i = r->size;
short q;
unsigned char j;
RTR_make_id_rotor(r,e);
while (2 <= i) {
q = r_rand(r,i);
i--;
j = e[q];
e[q] = (unsigned char)e[i];
e[i] = (unsigned char)j;
d[j] = (unsigned char)i;
}
e[0] = (unsigned char)e[0];
d[(e[0])] = (unsigned char)0;
}
/* Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
* Set the advancement, position, and permutation of the rotors
*/
static void
RTR_init(Rotorobj *r)
{
int i;
set_seed(r);
RTR_positions(r);
RTR_advances(r);
RTR_e_rotors(r);
RTR_d_rotors(r);
for (i = 0; i < r->rotors; i++) {
r->positions[i] = (unsigned char) r_rand(r, (short)r->size);
r->advances[i] = (1+(2*(r_rand(r, (short)(r->size/2)))));
RTR_permute_rotor(r,
&(r->e_rotor[(i*r->size)]),
&(r->d_rotor[(i*r->size)]));
}
r->isinited = TRUE;
}
/* Change the RTR-positions vector, using the RTR-advances vector */
static void
RTR_advance(Rotorobj *r)
{
register int i=0, temp=0;
if (r->size_mask) {
while (i < r->rotors) {
temp = r->positions[i] + r->advances[i];
r->positions[i] = temp & r->size_mask;
if ((temp >= r->size) && (i < (r->rotors - 1))) {
r->positions[(i+1)] = 1 + r->positions[(i+1)];
}
i++;
}
} else {
while (i < r->rotors) {
temp = r->positions[i] + r->advances[i];
r->positions[i] = temp%r->size;
if ((temp >= r->size) && (i < (r->rotors - 1))) {
r->positions[(i+1)] = 1 + r->positions[(i+1)];
}
i++;
}
}
}
/* Encrypt the character P with the current rotor machine */
static unsigned char
RTR_e_char(Rotorobj *r, unsigned char p)
{
register int i=0;
register unsigned char tp=p;
if (r->size_mask) {
while (i < r->rotors) {
tp = r->e_rotor[(i*r->size) +
(((r->positions[i] ^ tp) &
r->size_mask))];
i++;
}
} else {
while (i < r->rotors) {
tp = r->e_rotor[(i*r->size) +
(((r->positions[i] ^ tp) %
(unsigned int) r->size))];
i++;
}
}
RTR_advance(r);
return ((unsigned char)tp);
}
/* Decrypt the character C with the current rotor machine */
static unsigned char
RTR_d_char(Rotorobj *r, unsigned char c)
{
register int i = r->rotors - 1;
register unsigned char tc = c;
if (r->size_mask) {
while (0 <= i) {
tc = (r->positions[i] ^
r->d_rotor[(i*r->size)+tc]) & r->size_mask;
i--;
}
} else {
while (0 <= i) {
tc = (r->positions[i] ^
r->d_rotor[(i*r->size)+tc]) %
(unsigned int) r->size;
i--;
}
}
RTR_advance(r);
return(tc);
}
/* Perform a rotor encryption of the region from BEG to END by KEY */
static void
RTR_e_region(Rotorobj *r, unsigned char *beg, int len, int doinit)
{
register int i;
if (doinit || r->isinited == FALSE)
RTR_init(r);
for (i = 0; i < len; i++) {
beg[i] = RTR_e_char(r, beg[i]);
}
}
/* Perform a rotor decryption of the region from BEG to END by KEY */
static void
RTR_d_region(Rotorobj *r, unsigned char *beg, int len, int doinit)
{
register int i;
if (doinit || r->isinited == FALSE)
RTR_init(r);
for (i = 0; i < len; i++) {
beg[i] = RTR_d_char(r, beg[i]);
}
}
/* Rotor methods */
static void
rotor_dealloc(Rotorobj *xp)
{
if (xp->e_rotor)
PyMem_DEL(xp->e_rotor);
if (xp->d_rotor)
PyMem_DEL(xp->d_rotor);
if (xp->positions)
PyMem_DEL(xp->positions);
if (xp->advances)
PyMem_DEL(xp->advances);
PyObject_Del(xp);
}
static PyObject *
rotorobj_encrypt(Rotorobj *self, PyObject *args)
{
char *string = NULL;
int len = 0;
PyObject *rtn = NULL;
char *tmp;
if (!PyArg_ParseTuple(args, "s#:encrypt", &string, &len))
return NULL;
if (!(tmp = PyMem_NEW(char, len+5))) {
PyErr_NoMemory();
return NULL;
}
memset(tmp, '\0', len+1);
memcpy(tmp, string, len);
RTR_e_region(self, (unsigned char *)tmp, len, TRUE);
rtn = PyString_FromStringAndSize(tmp, len);
PyMem_DEL(tmp);
return(rtn);
}
static PyObject *
rotorobj_encrypt_more(Rotorobj *self, PyObject *args)
{
char *string = NULL;
int len = 0;
PyObject *rtn = NULL;
char *tmp;
if (!PyArg_ParseTuple(args, "s#:encrypt_more", &string, &len))
return NULL;
if (!(tmp = PyMem_NEW(char, len+5))) {
PyErr_NoMemory();
return NULL;
}
memset(tmp, '\0', len+1);
memcpy(tmp, string, len);
RTR_e_region(self, (unsigned char *)tmp, len, FALSE);
rtn = PyString_FromStringAndSize(tmp, len);
PyMem_DEL(tmp);
return(rtn);
}
static PyObject *
rotorobj_decrypt(Rotorobj *self, PyObject *args)
{
char *string = NULL;
int len = 0;
PyObject *rtn = NULL;
char *tmp;
if (!PyArg_ParseTuple(args, "s#:decrypt", &string, &len))
return NULL;
if (!(tmp = PyMem_NEW(char, len+5))) {
PyErr_NoMemory();
return NULL;
}
memset(tmp, '\0', len+1);
memcpy(tmp, string, len);
RTR_d_region(self, (unsigned char *)tmp, len, TRUE);
rtn = PyString_FromStringAndSize(tmp, len);
PyMem_DEL(tmp);
return(rtn);
}
static PyObject *
rotorobj_decrypt_more(Rotorobj *self, PyObject *args)
{
char *string = NULL;
int len = 0;
PyObject *rtn = NULL;
char *tmp;
if (!PyArg_ParseTuple(args, "s#:decrypt_more", &string, &len))
return NULL;
if (!(tmp = PyMem_NEW(char, len+5))) {
PyErr_NoMemory();
return NULL;
}
memset(tmp, '\0', len+1);
memcpy(tmp, string, len);
RTR_d_region(self, (unsigned char *)tmp, len, FALSE);
rtn = PyString_FromStringAndSize(tmp, len);
PyMem_DEL(tmp);
return(rtn);
}
static PyObject *
rotorobj_setkey(Rotorobj *self, PyObject *args)
{
char *key;
if (!PyArg_ParseTuple(args, "s:setkey", &key))
return NULL;
set_key(self, key);
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef
rotorobj_methods[] = {
{"encrypt", (PyCFunction)rotorobj_encrypt, METH_VARARGS},
{"encryptmore", (PyCFunction)rotorobj_encrypt_more, METH_VARARGS},
{"decrypt", (PyCFunction)rotorobj_decrypt, METH_VARARGS},
{"decryptmore", (PyCFunction)rotorobj_decrypt_more, METH_VARARGS},
{"setkey", (PyCFunction)rotorobj_setkey, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
/* Return a rotor object's named attribute. */
static PyObject *
rotorobj_getattr(Rotorobj *s, char *name)
{
return Py_FindMethod(rotorobj_methods, (PyObject*)s, name);
}
static PyTypeObject Rotor_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"rotor.rotor", /*tp_name*/
sizeof(Rotorobj), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)rotor_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)rotorobj_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_hash*/
};
static PyObject *
rotor_rotor(PyObject *self, PyObject *args)
{
Rotorobj *r;
char *string;
int num_rotors = 6;
if (!PyArg_ParseTuple(args, "s|i:newrotor", &string, &num_rotors))
return NULL;
r = rotorobj_new(num_rotors, string);
return (PyObject *)r;
}
static struct PyMethodDef
rotor_methods[] = {
{"newrotor", rotor_rotor, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
PyMODINIT_FUNC
initrotor(void)
{
Rotor_Type.ob_type = &PyType_Type;
(void)Py_InitModule("rotor", rotor_methods);
if (PyErr_Warn(PyExc_DeprecationWarning,
"the rotor module uses an insecure algorithm "
"and is deprecated") < 0)
return;
}
#include "Python.h"
PyDoc_STRVAR(xreadlines_doc,
"xreadlines(f)\n\
\n\
Return an xreadlines object for the file f.");
typedef struct {
PyObject_HEAD
PyObject *file;
PyObject *lines;
int lineslen;
int lineno;
int abslineno;
} PyXReadlinesObject;
static PyTypeObject XReadlinesObject_Type;
static void
xreadlines_dealloc(PyXReadlinesObject *op)
{
Py_XDECREF(op->file);
Py_XDECREF(op->lines);
PyObject_DEL(op);
}
/* A larger chunk size doesn't seem to make a difference */
#define CHUNKSIZE 8192
static PyXReadlinesObject *
newreadlinesobject(PyObject *file)
{
PyXReadlinesObject *op;
op = PyObject_NEW(PyXReadlinesObject, &XReadlinesObject_Type);
if (op == NULL)
return NULL;
Py_XINCREF(file);
op->file = file;
op->lines = NULL;
op->abslineno = op->lineno = op->lineslen = 0;
return op;
}
static PyObject *
xreadlines(PyObject *self, PyObject *args)
{
PyObject *file;
PyXReadlinesObject *ret;
if (!PyArg_ParseTuple(args, "O:xreadlines", &file))
return NULL;
ret = newreadlinesobject(file);
return (PyObject*)ret;
}
static PyObject *
xreadlines_common(PyXReadlinesObject *a)
{
if (a->lineno >= a->lineslen) {
Py_XDECREF(a->lines);
a->lines = PyObject_CallMethod(a->file, "readlines", "(i)",
CHUNKSIZE);
if (a->lines == NULL)
return NULL;
a->lineno = 0;
if ((a->lineslen = PySequence_Size(a->lines)) < 0)
return NULL;
}
a->abslineno++;
return PySequence_GetItem(a->lines, a->lineno++);
}
static PyObject *
xreadlines_item(PyXReadlinesObject *a, int i)
{
if (i != a->abslineno) {
PyErr_SetString(PyExc_RuntimeError,
"xreadlines object accessed out of order");
return NULL;
}
return xreadlines_common(a);
}
static PyObject *
xreadlines_iternext(PyXReadlinesObject *a)
{
PyObject *res;
res = xreadlines_common(a);
if (res == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
PyErr_Clear();
return res;
}
static PyObject *
xreadlines_next(PyXReadlinesObject *a, PyObject *args)
{
PyObject *res;
if (!PyArg_ParseTuple(args, ""))
return NULL;
res = xreadlines_common(a);
if (res == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
PyErr_SetObject(PyExc_StopIteration, Py_None);
return res;
}
PyDoc_STRVAR(next_doc, "x.next() -> the next line or raise StopIteration");
static PyMethodDef xreadlines_methods[] = {
{"next", (PyCFunction)xreadlines_next, METH_VARARGS, next_doc},
{NULL, NULL}
};
static PyObject *
xreadlines_getattr(PyObject *a, char *name)
{
return Py_FindMethod(xreadlines_methods, a, name);
}
static PySequenceMethods xreadlines_as_sequence = {
0, /*sq_length*/
0, /*sq_concat*/
0, /*sq_repeat*/
(intargfunc)xreadlines_item, /*sq_item*/
};
static PyTypeObject XReadlinesObject_Type = {
PyObject_HEAD_INIT(NULL)
0,
"xreadlines.xreadlines",
sizeof(PyXReadlinesObject),
0,
(destructor)xreadlines_dealloc, /* tp_dealloc */
0, /* tp_print */
xreadlines_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
&xreadlines_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)xreadlines_iternext, /* tp_iternext */
};
static PyMethodDef xreadlines_functions[] = {
{"xreadlines", xreadlines, METH_VARARGS, xreadlines_doc},
{NULL, NULL}
};
PyMODINIT_FUNC
initxreadlines(void)
{
XReadlinesObject_Type.ob_type = &PyType_Type;
Py_InitModule("xreadlines", xreadlines_functions);
PyErr_Warn(PyExc_DeprecationWarning,
"xreadlines is deprecated; use 'for line in file'.");
}
......@@ -300,7 +300,6 @@ class PyBuildExt(build_ext):
exts.append( Extension('_hotshot', ['_hotshot.c']) )
exts.append( Extension('_weakref', ['_weakref.c']) )
exts.append( Extension('xreadlines', ['xreadlinesmodule.c']) )
# array objects
exts.append( Extension('array', ['arraymodule.c']) )
......@@ -389,9 +388,7 @@ class PyBuildExt(build_ext):
if platform not in ['atheos', 'mac']:
exts.append( Extension('mmap', ['mmapmodule.c']) )
# Lance Ellinghaus's modules:
# enigma-inspired encryption
exts.append( Extension('rotor', ['rotormodule.c']) )
# Lance Ellinghaus's syslog module
if platform not in ['mac']:
# syslog daemon interface
exts.append( Extension('syslog', ['syslogmodule.c']) )
......@@ -629,25 +626,6 @@ class PyBuildExt(build_ext):
exts.append( Extension('gdbm', ['gdbmmodule.c'],
libraries = ['gdbm'] ) )
# The mpz module interfaces to the GNU Multiple Precision library.
# You need to ftp the GNU MP library.
# This was originally written and tested against GMP 1.2 and 1.3.2.
# It has been modified by Rob Hooft to work with 2.0.2 as well, but I
# haven't tested it recently, and it definitely doesn't work with
# GMP 4.0. For more complete modules, refer to
# http://gmpy.sourceforge.net and
# http://www.egenix.com/files/python/mxNumber.html
# A compatible MP library unencumbered by the GPL also exists. It was
# posted to comp.sources.misc in volume 40 and is widely available from
# FTP archive sites. One URL for it is:
# ftp://gatekeeper.dec.com/.b/usenet/comp.sources.misc/volume40/fgmp/part01.Z
if (self.compiler.find_library_file(lib_dirs, 'gmp')):
exts.append( Extension('mpz', ['mpzmodule.c'],
libraries = ['gmp'] ) )
# Unix-only modules
if platform not in ['mac', 'win32']:
# Steen Lumholt's termios module
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment