Bug squashing.
[catacomb-python] / mp.c
diff --git a/mp.c b/mp.c
index 4c91865..0a0e206 100644 (file)
--- a/mp.c
+++ b/mp.c
 PyTypeObject *mp_pytype = 0;
 PyTypeObject *gf_pytype = 0;
 
-mp *mp_frompylong(PyLongObject *l)
+mp *mp_frompylong(PyObject *obj)
 {
   unsigned long bits;
+  PyLongObject *l = (PyLongObject *)obj;
   int sz;
   size_t w;
   mpd r = 0;
@@ -71,7 +72,7 @@ mp *mp_frompylong(PyLongObject *l)
   return (x);
 }
 
-PyLongObject *mp_topylong(mp *x)
+PyObject *mp_topylong(mp *x)
 {
   unsigned long bits = mp_bits(x);
   int sz = (bits + SHIFT - 1)/SHIFT;
@@ -83,7 +84,7 @@ PyLongObject *mp_topylong(mp *x)
 
   assert(MPW_BITS >= SHIFT);
   while (i < sz && p < x->vl) {
-    r |= *p << b;
+    r |= (mpd)*p++ << b;
     b += MPW_BITS;
     while (i < sz && b >= SHIFT) {
       l->ob_digit[i++] = r & MASK;
@@ -96,15 +97,13 @@ PyLongObject *mp_topylong(mp *x)
     r >>= SHIFT;
   }
   l->ob_size = (x->f & MP_NEG) ? -sz : sz;
-  return (l);
+  return ((PyObject *)l);
 }
 
 mp *mp_frompyobject(PyObject *o, int radix)
 {
   mp *x;
 
-  if ((x = tomp(o)) != 0)
-    return (x);
   if (PyString_Check(o)) {
     mptext_stringctx sc;
     mp *x;
@@ -115,6 +114,8 @@ mp *mp_frompyobject(PyObject *o, int radix)
     if (sc.buf < sc.lim) { MP_DROP(x); return (0); }
     return (x);
   }
+  if ((x = tomp(o)) != 0)
+    return (x);
   return (0);
 }
 
@@ -143,6 +144,13 @@ PyObject *mp_topystring(mp *x, int radix, const char *xpre,
   return (o);
 }
 
+static int good_radix_p(int r, int readp)
+{
+  return ((r >= -255 && r <= -2) ||
+         (readp && r == 0) ||
+         (r >= 2 && r <= 62));
+}
+
 PyObject *mp_pywrap(mp *x)
 {
   mp_pyobj *z = PyObject_New(mp_pyobj, mp_pytype);
@@ -214,7 +222,7 @@ mp *tomp(PyObject *o)
   } else if (PyInt_Check(o))
     return (mp_fromlong(MP_NEW, PyInt_AS_LONG(o)));
   else if ((l = PyNumber_Long(o)) != 0) {
-    x = mp_frompylong((PyLongObject *)l);
+    x = mp_frompylong(l);
     Py_DECREF(l);
     return (x);
   } else {
@@ -448,10 +456,10 @@ static PyObject *mp_pyint(PyObject *x)
   return (PyInt_FromLong(l));
 }
 static PyObject *mp_pylong(PyObject *x)
-  { return (PyObject *)mp_topylong(MP_X(x)); }
+  { return (mp_topylong(MP_X(x))); }
 static PyObject *mp_pyfloat(PyObject *x)
 {
-  PyObject *l = (PyObject *)mp_topylong(MP_X(x));
+  PyObject *l = mp_topylong(MP_X(x));
   double f = PyLong_AsDouble(l);
   Py_DECREF(l);
   return (PyFloat_FromDouble(f));
@@ -488,10 +496,10 @@ static PyObject *mp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
   int radix = 0;
   char *kwlist[] = { "x", "radix", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:mp", kwlist, &x, &radix))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:new", kwlist, &x, &radix))
     goto end;
   if (MP_PYCHECK(x)) RETURN_OBJ(x);
-  if (radix < -255 || radix > 62) VALERR("radix out of range");
+  if (!good_radix_p(radix, 1)) VALERR("bad radix");
   if ((z = mp_frompyobject(x, radix)) == 0) {
     PyErr_Format(PyExc_TypeError, "can't convert %.100s to mp",
                 x->ob_type->tp_name);
@@ -505,10 +513,9 @@ end:
 
 static long mp_pyhash(PyObject *me)
 {
-  long i = mp_tolong(MP_X(me));
-  if (i == -1)
-    i = -2;
-  return (i);
+  long h;
+  PyObject *l = mp_topylong(MP_X(me)); h = PyObject_Hash(l);
+  Py_DECREF(l); return (h);
 }
 
 static PyObject *mpmeth_jacobi(PyObject *me, PyObject *arg)
@@ -517,6 +524,8 @@ static PyObject *mpmeth_jacobi(PyObject *me, PyObject *arg)
   PyObject *z = 0;
 
   if (!PyArg_ParseTuple(arg, "O&:jacobi", convmp, &y)) goto end;
+  if (MP_NEGP(MP_X(me)) || MP_EVENP(MP_X(me)))
+    VALERR("must be positive and odd");
   z = PyInt_FromLong(mp_jacobi(y, MP_X(me)));
 end:
   if (y) MP_DROP(y);
@@ -622,8 +631,7 @@ static PyObject *mpmeth_tostring(PyObject *me, PyObject *arg, PyObject *kw)
   char *kwlist[] = { "radix", 0 };
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:tostring", kwlist, &radix))
     goto end;
-  if (radix < -255 || radix > 62 || radix == -1 || radix == 0 || radix == 1)
-    VALERR("bad radix");
+  if (!good_radix_p(radix, 0)) VALERR("bad radix");
   return (mp_topystring(MP_X(me), radix, 0, 0, 0));
 end:
   return (0);
@@ -881,7 +889,7 @@ static PyObject *meth__MP_fromstring(PyObject *me,
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring",
                                   kwlist, &me, &p, &len, &r))
     goto end;
-  if (r < -255 || r > 62) VALERR("radix out of range");
+  if (!good_radix_p(r, 1)) VALERR("bad radix");
   sc.buf = p; sc.lim = p + len;
   if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0)
     SYNERR("bad integer");
@@ -1683,7 +1691,7 @@ static PyObject *gf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:gf", kwlist, &x, &radix))
     goto end;
   if (GF_PYCHECK(x)) RETURN_OBJ(x);
-  if (radix < -255 || radix > 62) VALERR("radix out of range");
+  if (!good_radix_p(radix, 1)) VALERR("radix out of range");
   if ((z = mp_frompyobject(x, radix)) == 0) {
     PyErr_Format(PyExc_TypeError, "can't convert %.100s to gf",
                 x->ob_type->tp_name);
@@ -1950,7 +1958,7 @@ static PyObject *meth__GF_fromstring(PyObject *me,
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring",
                                   kwlist, &me, &p, &len, &r))
     goto end;
-  if (r < -255 || r > 62) VALERR("radix out of range");
+  if (!good_radix_p(r, 1)) VALERR("radix out of range");
   sc.buf = p; sc.lim = p + len;
   if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0 || MP_NEGP(zz))
     z = Py_BuildValue("(Os#)", Py_None, p, len);