summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/mpw/test/Makefile.am2
-rw-r--r--python/mpw/test/test_methods.py41
-rw-r--r--python/rpmmpw-py.c150
3 files changed, 123 insertions, 70 deletions
diff --git a/python/mpw/test/Makefile.am b/python/mpw/test/Makefile.am
index ddf713ac6..e9c22d8c7 100644
--- a/python/mpw/test/Makefile.am
+++ b/python/mpw/test/Makefile.am
@@ -13,4 +13,4 @@ EXTRA_DIST = \
all:
check:
- python test_all.py
+ python test_all.py verbose
diff --git a/python/mpw/test/test_methods.py b/python/mpw/test/test_methods.py
index 686fd78b0..068019ded 100644
--- a/python/mpw/test/test_methods.py
+++ b/python/mpw/test/test_methods.py
@@ -12,24 +12,26 @@ import tempfile
from pprint import pprint
import unittest
-from rpm import mpw
+import rpm
import mpz
from test_all import verbose
DASH = '-'
-
#----------------------------------------------------------------------
class BasicTestCase(unittest.TestCase):
+ a = 0x0000000987654321L
+ b = 0x0000000000000010L
+ c = 0x0fedcba000000000L
def setUp(self):
- mpw().Debug(0)
+ rpm.mpw().Debug(0)
pass
def tearDown(self):
- mpw().Debug(0)
+ rpm.mpw().Debug(0)
pass
#----------------------------------------
@@ -39,27 +41,35 @@ class BasicTestCase(unittest.TestCase):
print '\n', '-=' * 30
print "Running %s.test01_SimpleMethods..." % \
self.__class__.__name__
+ print "\ta:\t%s\t%s\t0x%x" % (type(self.a), self.a, self.a)
+ print "\tb:\t%s\t%s\t0x%x" % (type(self.b), self.b, self.b)
+ print "\tc:\t%s\t%s\t0x%x" % (type(self.c), self.c, self.c)
- wa = mpw("0000000987654321")
- wb = mpw("0000000000000010")
- wc = mpw("0fedcba000000000")
- za = mpz.mpz(0x0000000987654321)
- zb = mpz.mpz(0x0000000000000010)
- zc = mpz.mpz(0x0fedcba000000000)
+ wa = rpm.mpw(self.a)
+ wb = rpm.mpw(self.b)
+ wc = rpm.mpw(self.c)
+ za = mpz.mpz(self.a)
+ zb = mpz.mpz(self.b)
+ zc = mpz.mpz(self.c)
print "__int__:\t", int(wb), "\t", int(zb)
- print "__long__:\t", long(wb), "\t", long(zb)
- print "__float__:\t", float(wb), "\t", float(zb)
+ assert int(wb) == int(zb)
+ print "__long__:\t", long(wa), "\t", long(za)
+# assert str(long(wb)) == str(long(zb))
+ print "__float__:\t", float(wa), "\t", float(za)
+ assert float(wb) == float(zb)
zs = hex(za)
zs = zs[4:len(zs)-1]
print "__hex__:\t", hex(wa), "\t", zs
+ assert hex(wa) == zs
zs = oct(za)
zs = zs[4:len(zs)-1]
print "__oct__:\t", oct(wa), "\t", zs
+ assert oct(wa) == zs
print "__neg__:\t", (-wa), "\t", long(-za)
- print "__pos__:\t", (+wa), "\t", long(mpz.MPZType.__pos__(za))
+ print "__pos__:\t", (+wa), "\t", long(+za)
print "__abs__:\t", abs(wa), "\t", long(abs(za))
print "__invert__:\t", (~wa), "\t", long(~za)
@@ -68,6 +78,7 @@ class BasicTestCase(unittest.TestCase):
print "__mul__:\t", (wa * wb), "\t", long(za * zb)
print "__div__:\t", (wa / wb), "\t", long(za / zb)
print "__mod__:\t", (wa % wb), "\t", long(za % zb)
+
wq, wr = divmod(wa, wb)
zq, zr = divmod(za, zb)
print "__divmod__ q:\t", wq, "\t", long(zq)
@@ -81,8 +92,8 @@ class BasicTestCase(unittest.TestCase):
print "__xor__:\t", (wa ^ wa), "\t", long(za ^ za)
print "__or__:\t", (wa | wc), "\t", long(za | zc)
-# print mpw.__complex__(b)
-# print mpw.__coerce__(b, i)
+# print rpm.mpw.__complex__(b)
+# print rpm.mpw.__coerce__(b, i)
del wa
del wb
diff --git a/python/rpmmpw-py.c b/python/rpmmpw-py.c
index 77689f242..b47449886 100644
--- a/python/rpmmpw-py.c
+++ b/python/rpmmpw-py.c
@@ -5,6 +5,8 @@
#include "system.h"
#include "Python.h"
+#include "longintrepr.h"
+
#ifdef __LCLINT__
#undef PyObject_HEAD
#define PyObject_HEAD int _PyObjectHead;
@@ -17,6 +19,23 @@
#include "debug.h"
+#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
+
+#define BITS_TO_DIGITS(_b) (((_b) + SHIFT - 1)/SHIFT)
+#define DIGITS_TO_BITS(_d) ((_d) * SHIFT)
+
+#define MP_ROUND_B2W(_b) MP_BITS_TO_WORDS((_b) + MP_WBITS - 1)
+
+/*@unchecked@*/
+static int _ie = 0x44332211;
+/*@unchecked@*/
+static union _dendian {
+/*@unused@*/ int i;
+ char b[4];
+} *_endian = (union _dendian *)&_ie;
+#define IS_BIG_ENDIAN() (_endian->b[0] == '\x44')
+#define IS_LITTLE_ENDIAN() (_endian->b[0] == '\x11')
+
/*@unchecked@*/
static int _mpw_debug = 0;
@@ -312,7 +331,7 @@ mpsizeinbase(size_t xsize, mpw* xdata, size_t base)
return 1;
/* XXX assumes positive integer. */
- nbits = 32 * xsize - mpmszcnt(xsize, xdata);
+ nbits = MP_WORDS_TO_BITS(xsize) - mpmszcnt(xsize, xdata);
if ((base & (base-1)) == 0) { /* exact power of 2 */
size_t lbits = mp_bases[base].big_base;
res = (nbits + (lbits - 1)) / lbits;
@@ -385,7 +404,7 @@ fprintf(stderr, "*** mpstr(%p[%d], %p[%d], %d):\t", t, nt, data, size, base), mp
mpndivmod(zdata, asize, adata, 1, &base, wksp);
-if (_mpw_debug < 0) {
+if (_mpw_debug < -1) {
fprintf(stderr, " a %p[%d]:\t", adata, asize), mpfprintln(stderr, asize, adata);
fprintf(stderr, " z %p[%d]:\t", zdata, asize+1), mpfprintln(stderr, asize+1, zdata);
}
@@ -444,12 +463,12 @@ fprintf(stderr, "*** mpw_format(%p,%d,%d):\t", z, zbase, addL), mpfprintln(stder
} else if (zsign) {
*tcp++ = '-';
i += 1; /* space to hold '-' */
- zsize = (nt + 31)/32;
+ zsize = MP_ROUND_B2W(nt);
zdata = alloca(zsize * sizeof(*zdata));
mpsetx(zsize, zdata, zsize, z->n.data + (z->n.size - zsize));
mpneg(zsize, zdata);
} else {
- zsize = (nt + 31)/32;
+ zsize = MP_ROUND_B2W(nt);
zdata = z->n.data + (z->n.size - zsize);
}
@@ -761,19 +780,19 @@ static void mpnpow_w(mpnumber* n, size_t xsize, const mpw* xdata,
}
/* Normalize (to mpw boundary) exponent. */
- pdata += psize - ((pbits+31)/32);
- psize -= (pbits/32);
+ pdata += psize - MP_ROUND_B2W(pbits);
+ psize -= MP_BITS_TO_WORDS(pbits);
/* Calculate size of result. */
if (xbits == 0) xbits = 1;
nbits = (*pdata) * xbits;
- nsize = (nbits + 31)/32;
+ nsize = MP_ROUND_B2W(nbits);
/* XXX Add 1 word to carry sign bit */
- if (!mpmsbset(xsize, xdata) && (nbits & (32 -1)) == 0)
+ if (!mpmsbset(xsize, xdata) && (nbits & (MP_WBITS - 1)) == 0)
nsize++;
- size = ((15 * xbits)+31)/32;
+ size = MP_ROUND_B2W(15 * xbits);
if (_mpw_debug < 0)
fprintf(stderr, "*** pbits %d xbits %d nsize %d size %d\n", pbits, xbits, nsize, size);
@@ -861,60 +880,68 @@ fprintf(stderr, "*** mpw_str(%p): \"%s\"\n", a, PyString_AS_STRING(so));
/** \ingroup py_c
*/
-static int mpw_init(mpwObject * s, PyObject *args, PyObject *kwds)
+static int mpw_init(mpwObject * z, PyObject *args, PyObject *kwds)
/*@modifies s @*/
{
PyObject * o = NULL;
- size_t words = 0;
long l = 0;
if (!PyArg_ParseTuple(args, "|O:Cvt", &o)) return -1;
if (o == NULL) {
- if (s->n.data == NULL)
- mpnsetw(&s->n, 0);
+ mpnsetw(&z->n, l);
} else if (PyInt_Check(o)) {
l = PyInt_AsLong(o);
- words = sizeof(l)/sizeof(words);
+ mpnsetw(&z->n, l);
} else if (PyLong_Check(o)) {
- l = PyLong_AsLong(o);
- words = sizeof(l)/sizeof(words);
+ PyLongObject *lo = (PyLongObject *)o;
+ int lsize = ABS(lo->ob_size);
+ int lbits = DIGITS_TO_BITS(lsize);
+ size_t zsize = MP_BITS_TO_WORDS(lbits) + 1;
+ mpw* zdata = alloca(zsize * sizeof(*zdata));
+ unsigned char * zb = (unsigned char *) zdata;
+ size_t nzb = MP_WORDS_TO_BYTES(zsize);
+ int is_littleendian = 0;
+ int is_signed = 1;
+
+ /* Grab long as big-endian signed octets. */
+ if (_PyLong_AsByteArray(lo, zb, nzb, is_littleendian, is_signed))
+ return -1;
+
+ /* Endian swap zdata's mpw elements. */
+ if (IS_LITTLE_ENDIAN()) {
+ mpw w = 0;
+ int zx = 0;
+ while (nzb) {
+ w <<= 8;
+ w |= *zb++;
+ nzb--;
+ if ((nzb % MP_WBYTES) == 0) {
+ zdata[zx++] = w;
+ w = 0;
+ }
+ }
+ }
+ mpnset(&z->n, zsize, zdata);
} else if (PyFloat_Check(o)) {
double d = PyFloat_AsDouble(o);
/* XXX TODO: check for overflow/underflow. */
l = (long) (d + 0.5);
- words = sizeof(l)/sizeof(words);
+ mpnsetw(&z->n, l);
} else if (PyString_Check(o)) {
const unsigned char * hex = PyString_AsString(o);
/* XXX TODO: check for hex. */
- mpnsethex(&s->n, hex);
+ mpnsethex(&z->n, hex);
} else if (is_mpw(o)) {
mpwObject *a = (mpwObject *)o;
- mpnsize(&s->n, a->n.size);
- if (a->n.size > 0)
- mpsetx(s->n.size, s->n.data, a->n.size, a->n.data);
+ mpncopy(&z->n, &a->n);
} else {
PyErr_SetString(PyExc_TypeError, "non-numeric coercion failed (mpw_init)");
return -1;
}
- if (words > 0) {
- mpnsize(&s->n, words);
- switch (words) {
- case 2:
-/*@-shiftimplementation @*/
- s->n.data[0] = (l >> 32) & 0xffffffff;
-/*@=shiftimplementation @*/
- s->n.data[1] = (l ) & 0xffffffff;
- break;
- case 1:
- s->n.data[0] = (l ) & 0xffffffff;
- break;
- }
- }
-
if (_mpw_debug)
-fprintf(stderr, "*** mpw_init(%p[%s],%p[%s],%p[%s]):\t", s, lbl(s), args, lbl(args), kwds, lbl(kwds)), mpfprintln(stderr, s->n.size, s->n.data);
+fprintf(stderr, "*** mpw_init(%p[%s],%p[%s],%p[%s]):\t", z, lbl(z), args, lbl(args), kwds, lbl(kwds)), mpfprintln(stderr, z->n.size, z->n.data);
return 0;
}
@@ -1076,7 +1103,7 @@ fprintf(stderr, " b %p[%d]:\t", m->n.data, m->n.size), mpfprintln(stderr, m->
size_t znorm;
mpmul(zdata, x->n.size, x->n.data, m->n.size, m->n.data);
- znorm = zsize - (mpbitcnt(zsize, zdata) + 31)/32;
+ znorm = zsize - MP_ROUND_B2W(mpbitcnt(zsize, zdata));
zsize -= znorm;
zdata += znorm;
mpnset(&z->n, zsize, zdata);
@@ -1084,10 +1111,10 @@ fprintf(stderr, " b %p[%d]:\t", m->n.data, m->n.size), mpfprintln(stderr, m->
case '/':
{ size_t asize = x->n.size;
mpw* adata = x->n.data;
- size_t anorm = asize - (mpbitcnt(asize, adata) + 31)/32;
+ size_t anorm = asize - MP_ROUND_B2W(mpbitcnt(asize, adata));
size_t bsize = m->n.size;
mpw* bdata = m->n.data;
- size_t bnorm = bsize - (mpbitcnt(bsize, bdata) + 31)/32;
+ size_t bnorm = bsize - MP_ROUND_B2W(mpbitcnt(bsize, bdata));
size_t zsize;
mpw* zdata;
size_t znorm;
@@ -1133,7 +1160,7 @@ fprintf(stderr, " b %p[%d]:\t", m->n.data, m->n.size), mpfprintln(stderr, m->
mpnset(&z->n, zsize, zdata);
} break;
case '<':
- { size_t bnorm = m->n.size - (mpbitcnt(m->n.size, m->n.data) + 31)/32;
+ { size_t bnorm = m->n.size - MP_ROUND_B2W(mpbitcnt(m->n.size, m->n.data));
size_t bsize = m->n.size - bnorm;
mpw* bdata = m->n.data + bnorm;
size_t count = 0;
@@ -1144,7 +1171,7 @@ fprintf(stderr, " b %p[%d]:\t", m->n.data, m->n.size), mpfprintln(stderr, m->
mplshift(z->n.size, z->n.data, count);
} break;
case '>':
- { size_t bnorm = m->n.size - (mpbitcnt(m->n.size, m->n.data) + 31)/32;
+ { size_t bnorm = m->n.size - MP_ROUND_B2W(mpbitcnt(m->n.size, m->n.data));
size_t bsize = m->n.size - bnorm;
mpw* bdata = m->n.data + bnorm;
size_t count = 0;
@@ -1182,7 +1209,7 @@ fprintf(stderr, " b %p[%d]:\t", m->n.data, m->n.size), mpfprintln(stderr, m->
}
break;
case 'P':
- { size_t bnorm = m->n.size - (mpbitcnt(m->n.size, m->n.data) + 31)/32;
+ { size_t bnorm = m->n.size - MP_ROUND_B2W(mpbitcnt(m->n.size, m->n.data));
size_t bsize = m->n.size - bnorm;
mpw* bdata = m->n.data + bnorm;
mpnpow_w(&z->n, x->n.size, x->n.data, bsize, bdata);
@@ -1745,7 +1772,7 @@ static PyObject *
mpw_int(mpwObject * a)
/*@*/
{
- size_t anorm = a->n.size - (mpbitcnt(a->n.size, a->n.data) + 31)/32;
+ size_t anorm = a->n.size - MP_ROUND_B2W(mpbitcnt(a->n.size, a->n.data));
size_t asize = a->n.size - anorm;
mpw* adata = a->n.data + anorm;
@@ -1764,19 +1791,34 @@ static PyObject *
mpw_long(mpwObject * a)
/*@*/
{
- size_t anorm = a->n.size - (mpbitcnt(a->n.size, a->n.data) + 31)/32;
+ size_t abits = mpbitcnt(a->n.size, a->n.data);
+ size_t anorm = a->n.size - (abits + MP_WBITS - 1);
size_t asize = a->n.size - anorm;
mpw* adata = a->n.data + anorm;
+ size_t asign = mpmsbset(asize, adata);
+ size_t zsize = asize;
+ mpw* zdata = alloca(zsize * sizeof(*zdata));
+ int lsize = BITS_TO_DIGITS(abits);
+ PyLongObject *lo = _PyLong_New(lsize);
+ int digx;
- if (asize > 1) {
- PyErr_SetString(PyExc_ValueError, "mpw_long() arg too long to convert");
+ if (lo == NULL)
return NULL;
+
+ mpcopy(asize, zdata, adata);
+ if (asign)
+ mpneg(zsize, zdata);
+
+ for (digx = 0; digx < lsize; digx++) {
+ lo->ob_digit[digx] = zdata[zsize - 1] & MASK;
+ mprshift(zsize, zdata, SHIFT);
}
-if (_mpw_debug)
-fprintf(stderr, "*** mpw_long(%p):\t%08lx\n", a, (long)(asize ? adata[0] : 0));
+ while (digx > 0 && lo->ob_digit[digx-1] == 0)
+ digx--;
+ lo->ob_size = (asign == 0 ? digx : -digx);
- return Py_BuildValue("l", (asize ? adata[0] : 0));
+ return (PyObject *)lo;
}
static PyObject *
@@ -1859,7 +1901,7 @@ mpw_inplace_multiply(mpwObject * a, mpwObject * b)
size_t znorm;
mpmul(zdata, a->n.size, a->n.data, b->n.size, b->n.data);
- znorm = zsize - (mpbitcnt(zsize, zdata) + 31)/32;
+ znorm = zsize - MP_ROUND_B2W(mpbitcnt(zsize, zdata));
zsize -= znorm;
zdata += znorm;
@@ -1923,7 +1965,7 @@ mpw_inplace_remainder(mpwObject * a, mpwObject * b)
{
size_t bsize = b->n.size;
mpw* bdata = b->n.data;
- size_t bnorm = bsize - (mpbitcnt(bsize, bdata) + 31)/32;
+ size_t bnorm = bsize - MP_ROUND_B2W(mpbitcnt(bsize, bdata));
size_t zsize = a->n.size;
mpw* zdata = alloca(zsize * sizeof(*zdata));
mpw* wksp;
@@ -1959,7 +2001,7 @@ static PyObject *
mpw_inplace_lshift(mpwObject * a, mpwObject * b)
/*@modifies a @*/
{
- size_t bnorm = b->n.size - (mpbitcnt(b->n.size, b->n.data) + 31)/32;
+ size_t bnorm = b->n.size - MP_ROUND_B2W(mpbitcnt(b->n.size, b->n.data));
size_t bsize = b->n.size - bnorm;
mpw* bdata = b->n.data + bnorm;
size_t count = 0;
@@ -1980,7 +2022,7 @@ static PyObject *
mpw_inplace_rshift(mpwObject * a, mpwObject * b)
/*@modifies a @*/
{
- size_t bnorm = b->n.size - (mpbitcnt(b->n.size, b->n.data) + 31)/32;
+ size_t bnorm = b->n.size - MP_ROUND_B2W(mpbitcnt(b->n.size, b->n.data));
size_t bsize = b->n.size - bnorm;
mpw* bdata = b->n.data + bnorm;
size_t count = 0;