Mostly complete beecrypt bindings.
authorjbj <devnull@localhost>
Fri, 11 Apr 2003 00:52:17 +0000 (00:52 +0000)
committerjbj <devnull@localhost>
Fri, 11 Apr 2003 00:52:17 +0000 (00:52 +0000)
CVS patchset: 6737
CVS date: 2003/04/11 00:52:17

beecrypt/mp32.c
beecrypt/mp32.h
python/bc.py [new file with mode: 0644]
python/rpmbc-py.c

index d404ec7..6f01944 100644 (file)
@@ -439,6 +439,19 @@ void mp32clrlsb(register uint32 xsize, register uint32* xdata)
 }
 #endif
 
+#ifndef ASM_MP32AND
+void mp32and(register uint32 size, register uint32* xdata, register const uint32* ydata)
+{
+       do
+       {
+               --size;
+/*@-boundsread@*/
+               xdata[size] &= ydata[size];
+/*@=boundsread@*/
+       } while (size);
+}
+#endif
+
 #ifndef ASM_MP32XOR
 void mp32xor(register uint32 size, register uint32* xdata, register const uint32* ydata)
 {
@@ -452,6 +465,19 @@ void mp32xor(register uint32 size, register uint32* xdata, register const uint32
 }
 #endif
 
+#ifndef ASM_MP32OR
+void mp32or(register uint32 size, register uint32* xdata, register const uint32* ydata)
+{
+       do
+       {
+               --size;
+/*@-boundsread@*/
+               xdata[size] |= ydata[size];
+/*@=boundsread@*/
+       } while (size);
+}
+#endif
+
 #ifndef ASM_MP32NOT
 /*@-boundswrite@*/
 void mp32not(register uint32 xsize, register uint32* xdata)
index e922865..e13e2c4 100644 (file)
@@ -246,11 +246,23 @@ void mp32clrlsb(uint32 xsize, uint32* xdata)
 /**
  */
 BEECRYPTAPI /*@unused@*/
+void mp32and(uint32 size, uint32* xdata, const uint32* ydata)
+       /*@modifies xdata @*/;
+
+/**
+ */
+BEECRYPTAPI /*@unused@*/
 void mp32xor(uint32 size, uint32* xdata, const uint32* ydata)
        /*@modifies xdata @*/;
 
 /**
  */
+BEECRYPTAPI /*@unused@*/
+void mp32or(uint32 size, uint32* xdata, const uint32* ydata)
+       /*@modifies xdata @*/;
+
+/**
+ */
 /*@-exportlocal@*/
 BEECRYPTAPI
 void mp32not(uint32 xsize, uint32* xdata)
diff --git a/python/bc.py b/python/bc.py
new file mode 100644 (file)
index 0000000..b58e230
--- /dev/null
@@ -0,0 +1,55 @@
+import rpm
+
+i = 1
+a = rpm.bc("987654321")
+b = rpm.bc("10")
+c = rpm.bc("fedcba000000000")
+
+rpm.bc.__add__(a, b)
+rpm.bc.__sub__(a, b)
+rpm.bc.__mul__(a, b)
+rpm.bc.__div__(a, b)
+rpm.bc.__mod__(a, b)
+
+#rpm.bc.__divmod__(a, b)
+#rpm.bc.__pow__(a, b)
+
+rpm.bc.__lshift__(a, b)
+rpm.bc.__rshift__(a, b)
+
+rpm.bc.__and__(a, c)
+rpm.bc.__xor__(a, a)
+rpm.bc.__or__(a, c)
+
+rpm.bc.__neg__(a)
+rpm.bc.__pos__(a)
+rpm.bc.__abs__(a)
+rpm.bc.__invert__(a)
+
+rpm.bc.__int__(b)
+rpm.bc.__long__(b)
+#rpm.bc.__float__(b)
+#rpm.bc.__complex__(b)
+#rpm.bc.__oct__(b)
+#rpm.bc.__hex__(b)
+rpm.bc.__coerce__(b, i)
+
+d = rpm.bc("987654321");       rpm.bc.__iadd__(d, b)
+d = rpm.bc("987654321");       rpm.bc.__isub__(d, b)
+d = rpm.bc("987654321");       rpm.bc.__imul__(d, b)
+d = rpm.bc("987654321");       rpm.bc.__idiv__(d, b)
+d = rpm.bc("987654321");       rpm.bc.__imod__(d, b)
+
+d = rpm.bc("987654321");       rpm.bc.__ilshift__(d, b)
+d = rpm.bc("987654321");       rpm.bc.__irshift__(d, b)
+
+d = rpm.bc("987654321");       rpm.bc.__iand__(d, c)
+d = rpm.bc("987654321");       rpm.bc.__ixor__(d, a)
+d = rpm.bc("987654321");       rpm.bc.__ior__(d, c)
+
+#b = rpm.bc("123456789")
+#print "b: ", a
+#
+#c = a + b
+#print "c: ", c
+
index 24836b3..d40e626 100644 (file)
@@ -21,6 +21,113 @@ static int _bc_debug = 1;
 
 #define is_rpmbc(o)    ((o)->ob_type == &rpmbc_Type)
 
+#ifdef NOTYET
+static const char initialiser_name[] = "rpmbc";
+
+static PyObject *
+rpmbc_format(rpmbcObject * s, int base, unsigned char withname)
+{
+    PyStringObject * so;
+    size_t i;
+       int cmpres;
+       int taglong;
+       char *cp;
+       char prefix[5];
+
+    char * tcp = &prefix[0];
+
+    if (s == NULL || !is_rpmbc(s)) {
+       PyErr_BadInternalCall();
+       return NULL;
+    }
+
+    assert(base >= 2 && base <= 36);
+
+    if (withname)
+       i = strlen(initialiser_name) + 2; /* e.g. 'rpmbc(' + ')' */
+    else
+       i = 0;
+
+    if (mp32z(s->n.size, s->n.data))
+       base = 10;      /* '0' in every base, right */
+    else if (mp32msbset(s->n.size, s->n.data)) {
+       *tcp++ = '-';
+       i += 1;         /* space to hold '-' */
+    }
+
+       i += (int)mpz_sizeinbase(&s->mpz, base);
+
+    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(&s->mpz) > 1
+           || (long)mpz_get_ui(&s->mpz) < 0L) {
+               taglong = 1;
+               i += 1;         /* space to hold 'L' */
+       }
+
+    so = (PyStringObject *)PyString_FromStringAndSize((char *)0, i);
+    if (so == NULL)
+       return NULL;
+
+    /* get the beginning of the string memory and start copying things */
+    cp = PyString_AS_STRING(so);
+    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(&s->mpz,&s->mpz);       /* hack Hack HAck HACk HACK */
+       (void)mpz_get_str(cp, base, &s->mpz);
+       if (cmpres < 0)
+               mpz_neg(&s->mpz,&s->mpz);       /* hack Hack HAck HACk HACK */
+    cp += strlen(cp);
+
+    if (taglong)
+       *cp++ = 'L';
+    if (withname)
+       *cp++ = /*'('*/ ')';
+
+    *cp = '\0';
+
+    assert(cp - PyString_AS_STRING(so) <= i);
+
+    if (cp - PyString_AS_STRING(so) != i)
+       so->ob_size -= i - (cp - PyString_AS_STRING(so));
+
+    return (PyObject *)so;
+}
+#endif
+
 /* ---------- */
 
 static void
@@ -65,21 +172,18 @@ fprintf(stderr, "*** rpmbc_repr(%p)\n", a);
 
 /** \ingroup python
  */
-static int rpmbc_init(rpmbcObject * s, PyObject *args, PyObject *kwds)
-       /*@modifies s @*/
+static int rpmbc_init(rpmbcObject * z, PyObject *args, PyObject *kwds)
+       /*@modifies z @*/
 {
     PyObject * o = NULL;
     uint32 words = 0;
     long l = 0;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_init(%p[%s],%p[%s],%p[%s])\n", s, lbl(s), args, lbl(args), kwds, lbl(kwds));
-
     if (!PyArg_ParseTuple(args, "|O:Cvt", &o)) return -1;
 
     if (o == NULL) {
-       if (s->n.data == NULL)
-           mp32nsetw(&s->n, 0);
+       if (z->n.data == NULL)
+           mp32nsetw(&z->n, 0);
     } else if (PyInt_Check(o)) {
        l = PyInt_AsLong(o);
        words = sizeof(l)/sizeof(words);
@@ -94,27 +198,30 @@ fprintf(stderr, "*** rpmbc_init(%p[%s],%p[%s],%p[%s])\n", s, lbl(s), args, lbl(a
     } else if (PyString_Check(o)) {
        const unsigned char * hex = PyString_AsString(o);
        /* XXX TODO: check for hex. */
-       mp32nsethex(&s->n, hex);
+       mp32nsethex(&z->n, hex);
     } else {
        PyErr_SetString(PyExc_TypeError, "non-numeric coercion failed (rpmbc_init)");
        return -1;
     }
 
     if (words > 0) {
-       mp32nsize(&s->n, words);
+       mp32nsize(&z->n, words);
        switch (words) {
        case 2:
 /*@-shiftimplementation @*/
-           s->n.data[0] = (l >> 32) & 0xffffffff;
+           z->n.data[0] = (l >> 32) & 0xffffffff;
 /*@=shiftimplementation @*/
-           s->n.data[1] = (l      ) & 0xffffffff;
+           z->n.data[1] = (l      ) & 0xffffffff;
            break;
        case 1:
-           s->n.data[0] = (l      ) & 0xffffffff;
+           z->n.data[0] = (l      ) & 0xffffffff;
            break;
        }
     }
 
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_init(%p[%s],%p[%s],%p[%s]):\t", z, lbl(z), args, lbl(args), kwds, lbl(kwds)), mp32println(stderr, z->n.size, z->n.data);
+
     return 0;
 }
 
@@ -150,7 +257,7 @@ rpmbc_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
     if (ns != NULL)
        mp32nzero(&((rpmbcObject *)ns)->n);
 
-if (_bc_debug)
+if (_bc_debug < 0)
 fprintf(stderr, "*** rpmbc_new(%p[%s],%p[%s],%p[%s]) ret %p[%s]\n", subtype, lbl(subtype), args, lbl(args), kwds, lbl(kwds), ns, lbl(ns));
     return ns;
 }
@@ -292,13 +399,14 @@ rpmbc_add(rpmbcObject * a, rpmbcObject * b)
     rpmbcObject * z;
     uint32 carry;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_add(%p,%p)\n", a, b);
-
     if ((z = rpmbc_New()) != NULL) {
        mp32ninit(&z->n, a->n.size, a->n.data);
        carry = mp32addx(z->n.size, z->n.data, b->n.size, b->n.data);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_add(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -309,13 +417,14 @@ rpmbc_subtract(rpmbcObject * a, rpmbcObject * b)
     rpmbcObject * z;
     uint32 carry;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_subtract(%p,%p)\n", a, b);
-
     if ((z = rpmbc_New()) != NULL) {
        mp32ninit(&z->n, a->n.size, a->n.data);
        carry = mp32subx(z->n.size, z->n.data, b->n.size, b->n.data);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_subtract(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -325,14 +434,15 @@ rpmbc_multiply(rpmbcObject * a, rpmbcObject * b)
 {
     rpmbcObject * z;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_multiply(%p,%p)\n", a, b);
-
     if ((z = rpmbc_New()) != NULL) {
        /* XXX TODO: calculate zsize of result. */
        mp32nsize(&z->n, (a->n.size + b->n.size));
        mp32mul(z->n.data, a->n.size, a->n.data, b->n.size, b->n.data);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_multiply(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -343,9 +453,6 @@ rpmbc_divide(rpmbcObject * a, rpmbcObject * b)
     rpmbcObject * z = NULL;
     uint32 * wksp;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_divide(%p,%p)\n", a, b);
-
     if (mp32z(b->n.size, b->n.data)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "rpmbc_divide by zero");
        return NULL;
@@ -360,6 +467,11 @@ fprintf(stderr, "*** rpmbc_divide(%p,%p)\n", a, b);
     mp32nsize(&z->n, a->n.size);
     mp32ndivmod(z->n.data, a->n.size, a->n.data, b->n.size, b->n.data, wksp);
 
+    free(wksp);
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_divide(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -369,15 +481,16 @@ rpmbc_remainder(rpmbcObject * a, rpmbcObject * b)
 {
     rpmbcObject * z;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_remainder(%p,%p)\n", a, b);
-
     if ((z = rpmbc_New()) != NULL) {
        uint32 * wksp = malloc(a->n.size+1);
        mp32nsize(&z->n, a->n.size);
        mp32nmod(z->n.data, a->n.size, a->n.data, b->n.size, b->n.data, wksp);
        free(wksp);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_remainder(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -431,13 +544,14 @@ rpmbc_negative(rpmbcObject * a)
 {
     rpmbcObject * z;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_negative(%p)\n", a);
-
     if ((z = rpmbc_New()) != NULL) {
        mp32ninit(&z->n, a->n.size, a->n.data);
        mp32neg(z->n.size, z->n.data);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_negative(%p):\t", a), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -445,10 +559,11 @@ static PyObject *
 rpmbc_positive(rpmbcObject * a)
        /*@*/
 {
+    Py_INCREF(a);
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_positive(%p)\n", a);
+fprintf(stderr, "*** rpmbc_positive(%p):\t", a), mp32println(stderr, a->n.size, a->n.data);
 
-    Py_INCREF(a);
     return (PyObject *)a;
 }
 
@@ -458,9 +573,6 @@ rpmbc_absolute(rpmbcObject * a)
 {
     rpmbcObject * z;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_absolute(%p)\n", a);
-
     if (mp32msbset(a->n.size, a->n.data) == 0) {
        Py_INCREF(a);
        return (PyObject *)a;
@@ -470,6 +582,10 @@ fprintf(stderr, "*** rpmbc_absolute(%p)\n", a);
        mp32ninit(&z->n, a->n.size, a->n.data);
        mp32neg(z->n.size, z->n.data);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_absolute(%p):\t", a), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -486,9 +602,17 @@ static PyObject *
 rpmbc_invert(rpmbcObject * a)
        /*@*/
 {
+    rpmbcObject * z;
+
+    if ((z = rpmbc_New()) != NULL) {
+       mp32ninit(&z->n, a->n.size, a->n.data);
+       mp32not(z->n.size, z->n.data);
+    }
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_invert(%p)\n", a);
-    return NULL;
+fprintf(stderr, "*** rpmbc_invert(%p):\t", a), mp32println(stderr, z->n.size, z->n.data);
+
+    return (PyObject *)z;
 }
 
 static PyObject *
@@ -498,13 +622,17 @@ rpmbc_lshift(rpmbcObject * a, rpmbcObject * b)
     rpmbcObject * z;
     uint32 count = 0;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_lshift(%p[%s],%p[%s])\n", a, lbl(a), b, lbl(b));
-
+    /* XXX check shift count in range. */
     if ((z = rpmbc_New()) != NULL) {
+       if (b->n.size == 1)
+           count = b->n.data[0];
        mp32ninit(&z->n, a->n.size, a->n.data);
        mp32lshift(z->n.size, z->n.data, count);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_lshift(%p[%s],%p[%s]):\t", a, lbl(a), b, lbl(b)), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -515,13 +643,17 @@ rpmbc_rshift(rpmbcObject * a, rpmbcObject * b)
     rpmbcObject * z;
     uint32 count = 0;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_rshift(%p[%s],%p[%s])\n", a, lbl(a), b, lbl(b));
-
+    /* XXX check shift count in range. */
     if ((z = rpmbc_New()) != NULL) {
+       if (b->n.size == 1)
+           count = b->n.data[0];
        mp32ninit(&z->n, a->n.size, a->n.data);
        mp32rshift(z->n.size, z->n.data, count);
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_rshift(%p[%s],%p[%s]):\t", a, lbl(a), b, lbl(b)), mp32println(stderr, z->n.size, z->n.data);
+
     return (PyObject *)z;
 }
 
@@ -529,27 +661,78 @@ static PyObject *
 rpmbc_and(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
+    rpmbcObject * z;
+
+    if ((z = rpmbc_New()) != NULL) {
+       rpmbcObject * c, * d;
+
+       if (a->n.size <= b->n.size) {
+           c = a;
+           d = b;
+       } else {
+           c = b;
+           d = a;
+       }
+       mp32ninit(&z->n, c->n.size, c->n.data);
+       mp32and(z->n.size, z->n.data, d->n.data + (d->n.size - c->n.size));
+    }
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_and(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_and(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
+    return (PyObject *)z;
 }
 
 static PyObject *
 rpmbc_xor(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
+    rpmbcObject * z;
+
+    if ((z = rpmbc_New()) != NULL) {
+       rpmbcObject * c, * d;
+
+       if (a->n.size <= b->n.size) {
+           c = a;
+           d = b;
+       } else {
+           c = b;
+           d = a;
+       }
+       mp32ninit(&z->n, c->n.size, c->n.data);
+       mp32xor(z->n.size, z->n.data, d->n.data + (d->n.size - c->n.size));
+    }
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_xor(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_xor(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
+    return (PyObject *)z;
 }
 
 static PyObject *
 rpmbc_or(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
+    rpmbcObject * z;
+
+    if ((z = rpmbc_New()) != NULL) {
+       rpmbcObject * c, * d;
+
+       if (a->n.size <= b->n.size) {
+           c = a;
+           d = b;
+       } else {
+           c = b;
+           d = a;
+       }
+       mp32ninit(&z->n, c->n.size, c->n.data);
+       mp32or(z->n.size, z->n.data, d->n.data + (d->n.size - c->n.size));
+    }
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_or(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_or(%p,%p):\t", a, b), mp32println(stderr, z->n.size, z->n.data);
+
+    return (PyObject *)z;
 }
 
 static int
@@ -605,13 +788,14 @@ static PyObject *
 rpmbc_int(rpmbcObject * a)
        /*@*/
 {
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_int(%p)\n", a);
-
     if (mp32size(a->n.size, a->n.data) > 1) {
        PyErr_SetString(PyExc_ValueError, "rpmbc_int: arg too long to convert");
        return NULL;
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_int(%p):\t%08x\n", a, (int)(a->n.data ? a->n.data[0] : 0));
+
     return Py_BuildValue("i", (a->n.data ? a->n.data[0] : 0));
 }
 
@@ -619,12 +803,14 @@ static PyObject *
 rpmbc_long(rpmbcObject * a)
        /*@*/
 {
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_long(%p)\n", a);
     if (mp32size(a->n.size, a->n.data) > 1) {
-       PyErr_SetString(PyExc_ValueError, "rpmbc_int() arg too long to convert");
+       PyErr_SetString(PyExc_ValueError, "rpmbc_long() arg too long to convert");
        return NULL;
     }
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_long(%p):\t%08lx\n", a, (long)(a->n.data ? a->n.data[0] : 0));
+
     return Py_BuildValue("l", (a->n.data ? a->n.data[0] : 0));
 }
 
@@ -661,12 +847,13 @@ rpmbc_inplace_add(rpmbcObject * a, rpmbcObject * b)
 {
     uint32 carry;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_add(%p,%p)\n", a, b);
-
     carry = mp32addx(a->n.size, a->n.data, b->n.size, b->n.data);
 
-    return NULL;
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_inplace_add(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
@@ -675,44 +862,72 @@ rpmbc_inplace_subtract(rpmbcObject * a, rpmbcObject * b)
 {
     uint32 carry;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_subtract(%p,%p)\n", a, b);
-
     carry = mp32subx(a->n.size, a->n.data, b->n.size, b->n.data);
 
-    return NULL;
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_inplace_subtract(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
 rpmbc_inplace_multiply(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
-    uint32 * result = NULL;
-
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_multiply(%p,%p)\n", a, b);
+    uint32 * result = xmalloc((a->n.size + b->n.size) * sizeof(*result));
 
     mp32mul(result, a->n.size, a->n.data, b->n.size, b->n.data);
 
-    return NULL;
+    free(a->n.data);
+    a->n.size += b->n.size;
+    a->n.data = result;
+
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_inplace_multiply(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
 rpmbc_inplace_divide(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
+    uint32 * result = xmalloc(a->n.size * sizeof(*result));
+    uint32 * wksp = xmalloc(b->n.size+1);
+
+    mp32ndivmod(result, a->n.size, a->n.data, b->n.size, b->n.data, wksp);
+
+    free(wksp);
+    free(a->n.data);
+    a->n.data = result;
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_divide(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_inplace_divide(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
 rpmbc_inplace_remainder(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
+    uint32 * result = xmalloc(a->n.size * sizeof(*result));
+    uint32 * wksp = xmalloc(a->n.size+1);
+
+    mp32nmod(result, a->n.size, a->n.data, b->n.size, b->n.data, wksp);
+
+    free(wksp);
+    free(a->n.data);
+    a->n.data = result;
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_remainder(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_inplace_remainder(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
@@ -720,8 +935,10 @@ rpmbc_inplace_power(rpmbcObject * a, rpmbcObject * b, rpmbcObject * c)
        /*@*/
 {
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_power(%p,%p,%p)\n", a, b, c);
-    return NULL;
+fprintf(stderr, "*** rpmbc_inplace_power(%p,%p,%p):\t", a, b, c), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
@@ -730,12 +947,16 @@ rpmbc_inplace_lshift(rpmbcObject * a, rpmbcObject * b)
 {
     uint32 count = 0;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_lshift(%p,%p)\n", a, b);
-
+    /* XXX check shift count in range. */
+    if (b->n.size == 1)
+       count = b->n.data[0];
     mp32lshift(a->n.size, a->n.data, count);
 
-    return NULL;
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_inplace_lshift(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
@@ -744,38 +965,69 @@ rpmbc_inplace_rshift(rpmbcObject * a, rpmbcObject * b)
 {
     uint32 count = 0;
 
-if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_rshift(%p,%p)\n", a, b);
-
+    /* XXX check shift count in range. */
+    if (b->n.size == 1)
+       count = b->n.data[0];
     mp32rshift(a->n.size, a->n.data, count);
 
-    return NULL;
+if (_bc_debug)
+fprintf(stderr, "*** rpmbc_inplace_rshift(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
 rpmbc_inplace_and(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
+    if (a->n.size <= b->n.size)
+       mp32and(a->n.size, a->n.data, b->n.data + (b->n.size - a->n.size));
+    else {
+       memset(a->n.data, 0, (a->n.size - b->n.size) * sizeof(*a->n.data));
+       mp32and(a->n.size, a->n.data + (a->n.size - b->n.size), b->n.data);
+    }
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_and(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_inplace_and(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
 rpmbc_inplace_xor(rpmbcObject * a, rpmbcObject * b)
 {
+    if (a->n.size <= b->n.size)
+       mp32xor(a->n.size, a->n.data, b->n.data + (b->n.size - a->n.size));
+    else {
+       memset(a->n.data, 0, (a->n.size - b->n.size) * sizeof(*a->n.data));
+       mp32xor(a->n.size, a->n.data + (a->n.size - b->n.size), b->n.data);
+    }
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_xor(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_inplace_xor(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
 rpmbc_inplace_or(rpmbcObject * a, rpmbcObject * b)
        /*@*/
 {
+    if (a->n.size <= b->n.size)
+       mp32or(a->n.size, a->n.data, b->n.data + (b->n.size - a->n.size));
+    else {
+       memset(a->n.data, 0, (a->n.size - b->n.size) * sizeof(*a->n.data));
+       mp32or(a->n.size, a->n.data + (a->n.size - b->n.size), b->n.data);
+    }
+
 if (_bc_debug)
-fprintf(stderr, "*** rpmbc_inplace_or(%p,%p)\n", a, b);
-    return NULL;
+fprintf(stderr, "*** rpmbc_inplace_or(%p,%p):\t", a, b), mp32println(stderr, a->n.size, a->n.data);
+
+    Py_INCREF(a);
+    return (PyObject *)a;
 }
 
 static PyObject *
@@ -833,6 +1085,7 @@ static PyNumberMethods rpmbc_as_number = {
        (binaryfunc) rpmbc_xor,                 /* nb_xor */
        (binaryfunc) rpmbc_or,                  /* nb_or */
        (coercion) rpmbc_coerce,                /* nb_coerce */
+
        (unaryfunc) rpmbc_int,                  /* nb_int */
        (unaryfunc) rpmbc_long,                 /* nb_long */
        (unaryfunc) rpmbc_float,                /* nb_float */