bytestring.c (bytestring_pyrepeat): Don't divide by zero.
[catacomb-python] / field.c
diff --git a/field.c b/field.c
index a18a942..f2a0d2f 100644 (file)
--- a/field.c
+++ b/field.c
@@ -42,9 +42,9 @@ static PyObject *fe_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   PyObject *x;
   mp *z;
-  char *kwlist[] = { "x", 0 };
+  static const char *const kwlist[] = { "x", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:fe", kwlist, &x))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:fe", KWLIST, &x))
     return (0);
   if (FE_PYCHECK(x) && FE_F(x) == FIELD_F(ty)) RETURN_OBJ(x);
   if ((z = getmp(x)) == 0) return (0);
@@ -66,7 +66,7 @@ static PyObject *field_dopywrap(PyTypeObject *ty, field *f)
   fobj->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   fobj->ty.ht_type.tp_free = 0;
   fobj->ty.ht_type.tp_new = fe_pynew;
-  PyType_Ready(&fobj->ty.ht_type);
+  typeready(&fobj->ty.ht_type);
   return ((PyObject *)fobj);
 }
 
@@ -230,11 +230,13 @@ end:
 
 static long fe_pyhash(PyObject *me)
 {
-  long i = mp_tolong(FE_X(me));
-  i ^= 0xdcf62d6c; /* random perturbance */
-  if (i == -1)
-    i = -2;
-  return (i);
+  size_t sz = FE_F(me)->noctets;
+  uint32 h = 0xe0c127ca + FE_F(me)->ops->ty;
+  octet *p = xmalloc(sz);
+  mp_storeb(FE_X(me), p, sz);
+  h = unihash_hash(&unihash_global, h, p, sz);
+  xfree(p);
+  return (h % LONG_MAX);
 }
 
 static int fe_pycoerce(PyObject **x, PyObject **y)
@@ -261,10 +263,12 @@ end:
 static PyObject *fe_pyint(PyObject *x)
 {
   long l;
+  PyObject *rc;
   mp *xx = F_OUT(FE_F(x), MP_NEW, FE_X(x));
-  if (mp_tolong_checked(xx, &l)) { MP_DROP(xx); return (0); }
+  if (!mp_tolong_checked(xx, &l, 0)) rc = PyInt_FromLong(l);
+  else rc = mp_topylong(xx);
   MP_DROP(xx);
-  return (PyInt_FromLong(l));
+  return (rc);
 }
 
 static PyObject *fe_pylong(PyObject *x)
@@ -470,10 +474,10 @@ end:
 
 static PyObject *fmeth_rand(PyObject *me, PyObject *arg, PyObject *kw)
 {
-  char *kwlist[] = { "rng", 0 };
+  static const char *const kwlist[] = { "rng", 0 };
   grand *r = &rand_global;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:rand", kwlist,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:rand", KWLIST,
                                   convgrand, &r))
     return (0);
   return (fe_pywrap(me, F_RAND(FIELD_F(me), MP_NEW, r)));
@@ -589,9 +593,9 @@ static PyObject *primefield_pynew(PyTypeObject *ty,
 {
   mp *xx = 0;
   field *f;
-  char *kwlist[] = { "p", 0 };
+  static const char *const kwlist[] = { "p", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:primefield", kwlist,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:primefield", KWLIST,
                                   convmp, &xx))
     goto end;
   if ((f = field_prime(xx)) == 0)
@@ -637,7 +641,7 @@ static PyTypeObject primefield_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-  "Prime fields.",
+"PrimeField(P): prime fields.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -665,10 +669,10 @@ static PyObject *niceprimefield_pynew(PyTypeObject *ty,
 {
   mp *xx = 0;
   field *f;
-  char *kwlist[] = { "p", 0 };
+  static const char *const kwlist[] = { "p", 0 };
 
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:niceprimefield",
-                                  kwlist, convmp, &xx))
+                                  KWLIST, convmp, &xx))
     goto end;
   if ((f = field_niceprime(xx)) == 0)
     VALERR("bad prime for niceprimefield");
@@ -704,7 +708,7 @@ static PyTypeObject niceprimefield_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-  "Nice prime fields.",
+"NicePrimeField(P): prime field using Solinas reduction.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -764,7 +768,7 @@ static PyTypeObject binfield_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-  "Binary fields.  Abstract class.",
+"Binary fields.  Abstract class.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -792,9 +796,9 @@ static PyObject *binpolyfield_pynew(PyTypeObject *ty,
 {
   mp *xx = 0;
   field *f;
-  char *kwlist[] = { "p", 0 };
+  static const char *const kwlist[] = { "p", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:binpolyfield", kwlist,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:binpolyfield", KWLIST,
                                   convgf, &xx))
     goto end;
   if ((f = field_binpoly(xx)) == 0) VALERR("bad poly for binpolyfield");
@@ -837,7 +841,7 @@ static PyTypeObject binpolyfield_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-  "Binary fields with polynomial basis representation.",
+"BinPolyField(P): binary fields with polynomial basis representation.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -865,10 +869,10 @@ static PyObject *binnormfield_pynew(PyTypeObject *ty,
 {
   mp *xx = 0, *yy = 0;
   field *f;
-  char *kwlist[] = { "p", "beta", 0 };
+  static const char *const kwlist[] = { "p", "beta", 0 };
 
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:binnormfield",
-                                  kwlist, convgf, &xx, convgf, &yy))
+                                  KWLIST, convgf, &xx, convgf, &yy))
     goto end;
   if ((f = field_binnorm(xx, yy)) == 0) VALERR("bad args for binnormfield");
   MP_DROP(xx); MP_DROP(yy);
@@ -919,7 +923,7 @@ static PyTypeObject binnormfield_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-  "Binary fields with normal basis representation.",
+"BinNormField(P, BETA): binary fields with normal basis representation.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -956,7 +960,7 @@ static PyObject *meth__Field_parse(PyObject *me, PyObject *arg)
   qd.p = p;
   qd.e = 0;
   if ((f = field_parse(&qd)) == 0)
-    SYNERR(qd.e);
+    VALERR(qd.e);
   rc = Py_BuildValue("(Ns)", field_pywrap(f), qd.p);
 end:
   return (rc);