t/t-bytes.py: Check that indexing, slicing, etc. return `C.ByteString'.
[catacomb-python] / field.c
diff --git a/field.c b/field.c
index 9f51f5f..c23f311 100644 (file)
--- a/field.c
+++ b/field.c
@@ -1,13 +1,11 @@
 /* -*-c-*-
  *
- * $Id$
- *
  * Abstract fields
  *
  * (c) 2004 Straylight/Edgeware
  */
 
-/*----- Licensing notice --------------------------------------------------* 
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of the Python interface to Catacomb.
  *
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * Catacomb/Python is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with Catacomb/Python; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@@ -44,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);
@@ -68,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);
 }
 
@@ -128,16 +126,6 @@ static mp *tofe(field *f, PyObject *o)
   return (y);
 }
 
-mp *getfe(field *f, PyObject *o)
-{
-  mp *x = 0;
-  if ((x = tofe(f, o)) == 0) {
-    PyErr_Format(PyExc_TypeError, "can't convert %.100s to fe",
-                o->ob_type->tp_name);
-  }
-  return (x);
-}
-
 /*----- Field elements ----------------------------------------------------*/
 
 static int febinop(PyObject *x, PyObject *y,
@@ -231,13 +219,7 @@ 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);
-}
+  { return (mphash(FE_X(me))); }
 
 static int fe_pycoerce(PyObject **x, PyObject **y)
 {
@@ -263,10 +245,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)
@@ -280,7 +264,7 @@ static PyObject *fe_pylong(PyObject *x)
 #define BASEOP(name, radix, pre)                                       \
   static PyObject *fe_py##name(PyObject *x) {                          \
     mp *xx = F_OUT(FE_F(x), MP_NEW, FE_X(x));                          \
-    PyObject *rc = mp_topystring(FE_X(x), radix, 0, pre, 0);           \
+    PyObject *rc = mp_topystring(xx, radix, 0, pre, 0);                        \
     MP_DROP(xx);                                                       \
     return (rc);                                                       \
   }
@@ -343,8 +327,8 @@ static PyObject *feget__value(PyObject *me, void *hunoz)
 static PyGetSetDef fe_pygetset[] = {
 #define GETSETNAME(op, name) fe##op##_##name
   GET  (field,         "X.field -> field containing X")
-  GET  (value,         "X.value -> `natural' integer representation of X")
-  GET  (_value,        "X._value -> internal integer representation of X")
+  GET  (value,         "X.value -> `natural' MP/GF representation of X")
+  GET  (_value,        "X._value -> internal MP/GF representation of X")
 #undef GETSETNAME
   { 0 }
 };
@@ -408,7 +392,7 @@ static PyNumberMethods fe_pynumber = {
 
 static PyTypeObject fe_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.FE",                       /* @tp_name@ */
+  "FE",                                        /* @tp_name@ */
   sizeof(fe_pyobj),                    /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -472,10 +456,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)));
@@ -531,14 +515,14 @@ static PyGetSetDef field_pygetset[] = {
 static PyMethodDef field_pymethods[] = {
 #define METHNAME(name) fmeth_##name
   METH (_adopt,        "F._adopt(X) -> FE")
-  KWMETH(rand,         "F.rand(rng = rand) -> FE, uniformly distributed")
+  KWMETH(rand,         "F.rand([rng = rand]) -> FE, uniformly distributed")
 #undef METHNAME
   { 0 }
 };
 
 static PyTypeObject field_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.Field",                    /* @tp_name@ */
+  "Field",                             /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -591,9 +575,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)
@@ -610,13 +594,13 @@ static PyObject *pfget_p(PyObject *me, void *hunoz)
 
 static PyGetSetDef primefield_pygetset[] = {
 #define GETSETNAME(op, name) pf##op##_##name
-  GET  (p,             "F.p -> prime field characteristic")
+  GET  (p,             "F.p -> prime field characteristic")
 #undef GETSETNAME
 };
 
 static PyTypeObject primefield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeField",               /* @tp_name@ */
+  "PrimeField",                                /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -639,7 +623,7 @@ static PyTypeObject primefield_pytype_skel = {
     Py_TPFLAGS_BASETYPE,
 
   /* @tp_doc@ */
-  "Prime fields.",
+"PrimeField(P): prime fields.",
 
   0,                                   /* @tp_traverse@ */
   0,                                   /* @tp_clear@ */
@@ -667,10 +651,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");
@@ -683,7 +667,7 @@ end:
 
 static PyTypeObject niceprimefield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.NicePrimeField",           /* @tp_name@ */
+  "NicePrimeField",                    /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -706,7 +690,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@ */
@@ -736,14 +720,14 @@ static PyObject *bfget_m(PyObject *me, void *hunoz)
 
 static PyGetSetDef binfield_pygetset[] = {
 #define GETSETNAME(op, name) bf##op##_##name
-  GET  (m,             "F.m -> field polynomial degree")
+  GET  (m,             "F.m -> field polynomial degree")
 #undef GETSETNAME
   { 0 }
 };
 
 static PyTypeObject binfield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinField",                 /* @tp_name@ */
+  "BinField",                          /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -766,7 +750,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@ */
@@ -794,9 +778,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");
@@ -807,16 +791,19 @@ end:
   return (0);
 }
 
+static PyObject *bfget_p(PyObject *me, void *hunoz)
+  { return (gf_pywrap(MP_COPY(FIELD_F(me)->m))); }
+
 static PyGetSetDef binpolyfield_pygetset[] = {
-#define GETSETNAME(op, name) pf##op##_##name
-  GET  (p,             "F.p -> field polynomial")
+#define GETSETNAME(op, name) bf##op##_##name
+  GET  (p,             "F.p -> field polynomial")
 #undef GETSETNAME
   { 0 }
 };
 
 static PyTypeObject binpolyfield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinPolyField",             /* @tp_name@ */
+  "BinPolyField",                      /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -839,7 +826,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@ */
@@ -867,10 +854,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);
@@ -887,18 +874,18 @@ static PyObject *bnfget_beta(PyObject *me, void *hunoz)
 }
 
 static PyGetSetDef binnormfield_pygetset[] = {
-#define GETSETNAME(op, name) pf##op##_##name
-  GET  (p,             "F.p -> field polynomial")
+#define GETSETNAME(op, name) bf##op##_##name
+  GET  (p,             "F.p -> field polynomial")
 #undef GETSETNAME
 #define GETSETNAME(op, name) bnf##op##_##name
-  GET  (beta,          "F.beta -> conversion factor")
+  GET  (beta,          "F.beta -> conversion factor")
 #undef GETSETNAME
   { 0 }
 };
 
 static PyTypeObject binnormfield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinNormField",             /* @tp_name@ */
+  "BinNormField",                      /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -921,7 +908,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@ */
@@ -958,7 +945,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);
@@ -966,7 +953,7 @@ end:
 
 static PyMethodDef methods[] = {
 #define METHNAME(func) meth_##func
-  METH (_Field_parse,          "parse(STR) -> F, REST")
+  METH (_Field_parse,          "parse(STR) -> F, REST")
 #undef METHNAME
   { 0 }
 };