Port to Python 3.
[catacomb-python] / mp.c
diff --git a/mp.c b/mp.c
index 3f96a4e..e299a7d 100644 (file)
--- a/mp.c
+++ b/mp.c
@@ -56,6 +56,12 @@ mp *mp_frompylong(PyObject *obj)
   mp *x;
   mpw *p;
 
+#ifdef PY3
+  int ov;
+  long j = PyLong_AsLongAndOverflow(obj, &ov);
+  if (!ov) return mp_fromlong(MP_NEW, j);
+#endif
+
   sz = Py_SIZE(l);
   if (sz < 0) sz = -sz;
   bits = (unsigned long)sz * PyLong_SHIFT;
@@ -229,8 +235,10 @@ mp *tomp(PyObject *o)
       return (0);
     return (x);
   }
+#ifdef PY2
   else if (PyInt_Check(o))
     return (mp_fromlong(MP_NEW, PyInt_AS_LONG(o)));
+#endif
   else if ((l = PyNumber_Long(o)) != 0) {
     x = mp_frompylong(l);
     Py_DECREF(l);
@@ -503,7 +511,9 @@ static mp *gf_modinv_checked(mp *d, mp *x, mp *p)
 #define BASEOP(name, radix, pre)                                       \
   static PyObject *mp_py##name(PyObject *x)                            \
     { return mp_topystring(MP_X(x), radix, 0, pre, 0); }
+#ifdef PY2
 BASEOP(oct, 8, "0");
+#endif
 BASEOP(hex, 16, "0x");
 #undef BASEOP
 
@@ -515,8 +525,10 @@ static PyObject *mp_pyint(PyObject *x)
   if (!mp_tolong_checked(MP_X(x), &l, 0)) return (PyInt_FromLong(l));
   else return mp_topylong(MP_X(x));
 }
+#ifdef PY2
 static PyObject *mp_pylong(PyObject *x)
   { return (mp_topylong(MP_X(x))); }
+#endif
 static PyObject *mp_pyfloat(PyObject *x)
 {
   PyObject *l = mp_topylong(MP_X(x));
@@ -525,6 +537,7 @@ static PyObject *mp_pyfloat(PyObject *x)
   return (PyFloat_FromDouble(f));
 }
 
+#ifdef PY2
 #define COERCE(pre, PRE)                                               \
   static int pre##_pycoerce(PyObject **x, PyObject **y)                        \
   {                                                                    \
@@ -544,6 +557,7 @@ static PyObject *mp_pyfloat(PyObject *x)
 COERCE(mp, MP)
 COERCE(gf, GF)
 #undef COERCE
+#endif
 
 static PyObject *mp_pyrichcompare(PyObject *x, PyObject *y, int op)
 {
@@ -559,8 +573,10 @@ static PyObject *mp_pyrichcompare(PyObject *x, PyObject *y, int op)
   return (rc);
 }
 
+#ifdef PY2
 static int mp_pycompare(PyObject *x, PyObject *y)
   { return mp_cmp(MP_X(x), MP_X(y)); }
+#endif
 
 static PyObject *mp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
@@ -930,7 +946,9 @@ static const PyNumberMethods mp_pynumber = {
   mp_pyadd,                            /* @nb_add@ */
   mp_pysub,                            /* @nb_subtract@ */
   mp_pymul,                            /* @nb_multiply@ */
+#ifdef PY2
   0,                                   /* @nb_divide@ */
+#endif
   mp_pymod,                            /* @nb_remainder@ */
   mp_pydivmod,                         /* @nb_divmod@ */
   mp_pyexp,                            /* @nb_power@ */
@@ -944,17 +962,23 @@ static const PyNumberMethods mp_pynumber = {
   mp_pyand2c,                          /* @nb_and@ */
   mp_pyxor2c,                          /* @nb_xor@ */
   mp_pyor2c,                           /* @nb_or@ */
+#ifdef PY2
   mp_pycoerce,                         /* @nb_coerce@ */
+#endif
   mp_pyint,                            /* @nb_int@ */
-  mp_pylong,                           /* @nb_long@ */
+  PY23(mp_pylong, 0),                  /* @nb_long@ */
   mp_pyfloat,                          /* @nb_float@ */
+#ifdef PY2
   mp_pyoct,                            /* @nb_oct@ */
   mp_pyhex,                            /* @nb_hex@ */
+#endif
 
   0,                                   /* @nb_inplace_add@ */
   0,                                   /* @nb_inplace_subtract@ */
   0,                                   /* @nb_inplace_multiply@ */
+#ifdef PY2
   0,                                   /* @nb_inplace_divide@ */
+#endif
   0,                                   /* @nb_inplace_remainder@ */
   0,                                   /* @nb_inplace_power@ */
   0,                                   /* @nb_inplace_lshift@ */
@@ -981,7 +1005,7 @@ static const PyTypeObject mp_pytype_skel = {
   0,                                   /* @tp_print@ */
   0,                                   /* @tp_getattr@ */
   0,                                   /* @tp_setattr@ */
-  mp_pycompare,                                /* @tp_compare@ */
+  PY23(mp_pycompare, 0),               /* @tp_compare@/@tp_as_async@ */
   mp_pyrepr,                           /* @tp_repr@ */
   PYNUMBER(mp),                                /* @tp_as_number@ */
   0,                                   /* @tp_as_sequence@ */
@@ -1000,13 +1024,16 @@ static const PyTypeObject mp_pytype_skel = {
   "Multiprecision integers, similar to `long' but more efficient and\n"
   "versatile.  Support all the standard arithmetic operations, with\n"
   "implicit conversions from `PrimeFilter', and other objects which\n"
-  "convert to `long'.\n"
+  "convert to `" PY23("long", "int") "'.\n"
   "\n"
   "Constructor MP(X, [radix = R]) attempts to convert X to an `MP'.  If\n"
   "X is a string, it's read in radix-R form, or we look for a prefix\n"
   "if R = 0.  Other acceptable things are field elements, elliptic curve\n"
+  PY23(
   "points, group elements, Python `int' and `long' objects, and anything\n"
-  "with an integer conversion.\n"
+  "with an integer conversion.\n",
+  "points, group elements, Python `int' objects, and anything with an\n"
+  "integer conversion.\n")
   "\n"
   "Notes:\n"
   "\n"
@@ -2115,7 +2142,9 @@ static const PyNumberMethods gf_pynumber = {
   gf_pyadd,                            /* @nb_add@ */
   gf_pysub,                            /* @nb_subtract@ */
   gf_pymul,                            /* @nb_multiply@ */
+#ifdef PY2
   0,                                   /* @nb_divide@ */
+#endif
   gf_pymod,                            /* @nb_remainder@ */
   gf_pydivmod,                         /* @nb_divmod@ */
   gf_pyexp,                            /* @nb_power@ */
@@ -2129,17 +2158,23 @@ static const PyNumberMethods gf_pynumber = {
   gf_pyand,                            /* @nb_and@ */
   gf_pyxor,                            /* @nb_xor@ */
   gf_pyor,                             /* @nb_or@ */
+#ifdef PY2
   gf_pycoerce,                         /* @nb_coerce@ */
+#endif
   mp_pyint,                            /* @nb_int@ */
-  mp_pylong,                           /* @nb_long@ */
+  PY23(mp_pylong, 0),                  /* @nb_long@ */
   0 /* doesn't make any sense */,      /* @nb_float@ */
+#ifdef PY2
   mp_pyoct,                            /* @nb_oct@ */
   mp_pyhex,                            /* @nb_hex@ */
+#endif
 
   0,                                   /* @nb_inplace_add@ */
   0,                                   /* @nb_inplace_subtract@ */
   0,                                   /* @nb_inplace_multiply@ */
+#ifdef PY2
   0,                                   /* @nb_inplace_divide@ */
+#endif
   0,                                   /* @nb_inplace_remainder@ */
   0,                                   /* @nb_inplace_power@ */
   0,                                   /* @nb_inplace_lshift@ */
@@ -2188,8 +2223,11 @@ static const PyTypeObject gf_pytype_skel = {
   "Constructor GF(X, [radix = R]) attempts to convert X to a `GF'.  If\n"
   "X is a string, it's read in radix-R form, or we look for a prefix\n"
   "if R = 0.  Other acceptable things are field elements, elliptic curve\n"
+  PY23(
   "points, group elements, Python `int' and `long' objects, and anything\n"
-  "with an integer conversion.\n"
+  "with an integer conversion.\n",
+  "points, group elements, Python `int' objects, and anything with an\n"
+  "integer conversion.\n")
   "\n"
   "The name is hopelessly wrong from a technical point of view, but\n"
   "but it's much easier to type than `p2' or `c2' or whatever.\n"