Further progress.
authormdw <mdw>
Sun, 13 Jan 2002 13:48:44 +0000 (13:48 +0000)
committermdw <mdw>
Sun, 13 Jan 2002 13:48:44 +0000 (13:48 +0000)
ec-exp.h [new file with mode: 0644]
ec-prime.c
ec.c
ec.h
f-prime.c
field.h

diff --git a/ec-exp.h b/ec-exp.h
new file mode 100644 (file)
index 0000000..c760c43
--- /dev/null
+++ b/ec-exp.h
@@ -0,0 +1,76 @@
+/* -*-c-*-
+ *
+ * $Id: ec-exp.h,v 1.1 2002/01/13 13:48:44 mdw Exp $
+ *
+ * Exponentiation operations for elliptic curves
+ *
+ * (c) 2001 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * Catacomb 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 Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: ec-exp.h,v $
+ * Revision 1.1  2002/01/13 13:48:44  mdw
+ * Further progress.
+ *
+ */
+
+#ifndef CATACOMB_EC_EXP_H
+#define CATACOMB_EC_EXP_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Exponentation definitions -----------------------------------------*/
+
+#define EXP_TYPE ec
+
+#define EXP_COPY(d, x) do {                                            \
+  d.x = MP_COPY(x.x);                                                  \
+  d.y = MP_COPY(x.y);                                                  \
+  d.z = x.z ? MP_COPY(x.x) : MP_NEW;                                   \
+} while (0)  
+#define EXP_DROP(x) EC_DESTROY(c, &x)
+
+#define EXP_MUL(a, x) EC_ADD(c, &a, &a, &x)
+#define EXP_SQR(a) EC_DBL(c, &a, &a);
+
+#define EXP_SETMUL(d, x, y) do {                                       \
+  EC_CREATE(&d);                                                       \
+  EC_ADD(c, &d, &x, &y);                                               \
+} while (0)
+#define EXP_SETSQR(d, x) do {                                          \
+  EC_CREATE(&d);                                                       \
+  EC_DBL(c, &d, &x);                                                   \
+} while (0)
+
+#include "exp.h"
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
index 5a806da..09733ce 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: ec-prime.c,v 1.1 2001/04/29 18:12:33 mdw Exp $
+ * $Id: ec-prime.c,v 1.2 2002/01/13 13:48:44 mdw Exp $
  *
  * Elliptic curves over prime fields
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: ec-prime.c,v $
+ * Revision 1.2  2002/01/13 13:48:44  mdw
+ * Further progress.
+ *
  * Revision 1.1  2001/04/29 18:12:33  mdw
  * Prototype version.
  *
@@ -48,25 +51,93 @@ typedef struct ecctx {
 
 /*----- Main code ---------------------------------------------------------*/
 
-static void ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+static ec *ecneg(ec_cuvrve *c, ec *d, const ec *p)
+{
+  EC_COPY(d, p);
+  d->y = F_NEG(c->f, d->y, d->y);
+  return (d);
+}
+
+static ec *ecdbl(ec_curve *c, ec *d, const ec *a)
 {
-  /* --- Deal with the simple cases --- */
+  if (EC_ATINF(a))
+    EC_SETINF(d);
+  else if (!MP_LEN(a->y))
+    EC_COPY(d, a);
+  else {
+    field *f = c->f;
+    ecctx *cc = (ecctx *)c;
+    mp *lambda;
+    mp *dy, *dx;
+
+    dx = F_SQR(f, MP_NEW, a->x);
+    dy = F_DBL(f, MP_NEW, a->y);
+    dx = F_TPL(f, dx, dx);
+    dx = F_ADD(f, dx, dx, cc->a);
+    dy = F_INV(f, dy, dy);
+    lambda = F_MUL(d, MP_NEW, dx, dy);
+
+    dx = F_SQR(f, dx, lambda);
+    dy = F_DBL(d, dy, a->x);
+    dx = F_SUB(f, dx, dx, dy);
+    dy = F_SUB(f, dy, a->x, dx);
+    dy = F_MUL(f, dy, lambda, dy);
+    dy = F_SUB(f, dy, dy, a->y);
 
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
+  }
+  return (d);
+}
+
+static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+{
   if (a == b)
     ecdbl(c, d, a);
   else if (EC_ATINF(a))
     EC_COPY(d, b);
   else if (EC_ATINF(b))
     EC_COPY(d, a);
-  else if (MP_EQ(a->x, b->x) && MP_EQ(a->z, b->z)) {
-    if ((a->y->f ^ b->y->f) & MP_NEG)
+  else {
+    field *f = c->f;
+    mp *lambda;
+    mp *dy, *dx;
+
+    if (!MP_EQ(a->x, b->x)) {
+      dy = F_SUB(f, MP_NEW, a->y, b->y);
+      dx = F_SUB(f, MP_NEW, a->x, b->x);
+      dx = F_INV(f, dx, dx);
+      lambda = F_MUL(f, MP_NEW, dy, dx);
+    } else if (!MP_LEN(a->y) || !MP_EQ(a->y, b->y)) {
       EC_SETINF(d);
-    else
-      ecdbl(c, d, a);
-  } else {
+      return (d);
+    } else {
+      ecctx *cc = (ecctx *)c;
+      dx = F_SQR(f, MP_NEW, a->x);
+      dx = F_TPL(f, dx, dx);
+      dx = F_ADD(f, dx, dx, cc->a);
+      dy = F_DBL(f, MP_NEW, a->y);
+      dy = F_INV(f, dy, dy);
+      lambda = F_MUL(d, MP_NEW, dx, dy);
+    }
+
+    dx = F_SQR(f, dx, lambda);
+    dx = F_SUB(f, dx, dx, a->x);
+    dx = F_SUB(f, dx, dx, b->x);
+    dy = F_SUB(f, dy, b->x, dx);
+    dy = F_MUL(f, dy, lambda, dy);
+    dy = F_SUB(f, dy, dy, b->y);
 
-    /* --- 
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
   }
+  return (d);
 }
 
 /*----- That's all, folks -------------------------------------------------*/
diff --git a/ec.c b/ec.c
index 37d8ad3..ce4e428 100644 (file)
--- a/ec.c
+++ b/ec.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: ec.c,v 1.2 2001/05/07 17:29:44 mdw Exp $
+ * $Id: ec.c,v 1.3 2002/01/13 13:48:44 mdw Exp $
  *
  * Elliptic curve definitions
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: ec.c,v $
+ * Revision 1.3  2002/01/13 13:48:44  mdw
+ * Further progress.
+ *
  * Revision 1.2  2001/05/07 17:29:44  mdw
  * Treat projective coordinates as an internal representation.  Various
  * minor interface changes.
@@ -42,6 +45,7 @@
 /*----- Header files ------------------------------------------------------*/
 
 #include "ec.h"
+#include "ec-exp.h"
 
 /*----- Trivial wrappers --------------------------------------------------*/
 
@@ -186,6 +190,28 @@ ec *ec_projout(ec_curve *c, ec *d, const ec *p)
   return (d);
 }
 
+/* --- @ec_stdsub@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *a, *b@ = the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Standard point subtraction operation, in terms of negation
+ *             and addition.  This isn't as efficient as a ready-made
+ *             subtraction operator.
+ */
+
+ec *ec_stdsub(ec_curve *c, ec *d, const ec *a, const ec *b)
+{
+  ec t = EC_INIT;
+  EC_NEG(c, &t, b);
+  EC_SUB(c, d, a, &t);
+  EC_DESTROY(&t);
+  return (d);
+}
+
 /*----- Real arithmetic ---------------------------------------------------*/
 
 /* --- @ec_find@ --- *
@@ -249,65 +275,42 @@ ec *ec_dbl(ec_curve *c, ec *d, const ec *p)
   return (EC_OUT(c, d, d));
 }
 
-/* --- @ec_mul@ --- *
+/* --- @ec_imul@, @ec_mul@ --- *
  *
  * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
  *             @ec *d@ = pointer to the destination point
  *             @const ec *p@ = pointer to the generator point
  *             @mp *n@ = integer multiplier
  *
- * Returns:    ---
+ * Returns:    The destination @d@.
  *
- * Use:                Multiplies a point by a scalar, returning %$n p$%.
+ * Use:                Multiplies a point by a scalar, returning %$n p$%.  The
+ *             @imul@ variant uses internal representations for argument
+ *             and result.
  */
 
-ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n)
+ec *ec_imul(ec_curve *c, ec *d, const ec *p, mp *n)
 {
-  mpscan sc;
-  ec g = EC_INIT;
-  unsigned sq = 0;
+  ec t = EC_INIT;
 
+  EC_COPY(&t, p);
+  if (t.x && (n->f & MP_BURN))
+    t.x->f |= MP_BURN;
+  MP_SHRINK(n);
   EC_SETINF(d);
-  if (EC_ATINF(p))
-    return;
-
-  mp_rscan(&sc, n);
-  if (!MP_RSTEP(&sc))
-    goto exit;
-  while (!MP_RBIT(&sc))
-    MP_RSTEP(&sc);
-
-  EC_IN(c, &g, p);
-  if ((n->f & MP_BURN) && !(g.x->f & MP_BURN))
-    MP_DEST(g.x, 0, MP_BURN);
-  if ((n->f & MP_BURN) && !(g.y->f & MP_BURN))
-    MP_DEST(g.y, 0, MP_BURN);
-
-  for (;;) {
-    EC_ADD(c, d, d, &g);
-    sq = 0;
-    for (;;) {
-      if (!MP_RSTEP(&sc))
-       goto done;
-      if (MP_RBIT(&sc))
-       break;
-      sq++;
-    }
-    sq++;
-    while (sq) {
-      EC_DBL(c, d, d);
-      sq--;
-    }
-  }
-
-done:
-  while (sq) {
-    EC_DBL(c, d, d);
-    sq--;
-  }
+  if (MP_LEN(n) == 0)
+    ;
+  else if (MP_LEN(n) < EXP_THRESH)
+    EXP_SIMPLE(&d, t, n);
+  else
+    EXP_WINDOW(&d, t, n);
+  return (d);
+}
 
-  EC_DESTROY(&g);
-exit:
+ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n)
+{
+  EC_IN(c, d, p);
+  ec_imul(c, d, d, n);
   return (EC_OUT(c, d, d));
 }
 
diff --git a/ec.h b/ec.h
index 12ff823..2efe939 100644 (file)
--- a/ec.h
+++ b/ec.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: ec.h,v 1.2 2001/05/07 17:29:44 mdw Exp $
+ * $Id: ec.h,v 1.3 2002/01/13 13:48:44 mdw Exp $
  *
  * Elliptic curve definitions
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: ec.h,v $
+ * Revision 1.3  2002/01/13 13:48:44  mdw
+ * Further progress.
+ *
  * Revision 1.2  2001/05/07 17:29:44  mdw
  * Treat projective coordinates as an internal representation.  Various
  * minor interface changes.
 
 /*----- Data structures ---------------------------------------------------*/
 
+/* --- An elliptic curve representation --- */
+
 typedef struct ec_curve {
   const struct ec_ops *ops;            /* Curve operations */
   field *f;                            /* Underlying field structure */
 } ec_curve;
 
+/* --- An elliptic curve point --- */
+
 typedef struct ec {
   mp *x, *y;                           /* Point coordinates */
   mp *z;                               /* Common denominator (or null) */
 } ec;
 
+/* --- A factor for simultaneous multiplication --- */
+
+typedef struct ec_mulfactor {
+  ec base;                             /* The point */
+  ec *exp;                             /* The exponent */
+} ec_mulfactor;
+
+/* --- Elliptic curve operations --- */
+
 typedef struct ec_ops {
   void (*destroy)(ec_curve */*c*/);
   ec *(*in)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
   ec *(*out)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
   ec *(*find)(ec_curve */*c*/, ec */*d*/, mp */*x*/);
+  ec *(*neg)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
   ec *(*add)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/);
+  ec *(*sub)(ec_curve */*c*/, ec */*d*/, const ec */*p*/, const ec */*q*/);
   ec *(*dbl)(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 } ec_ops;
 
-#define EC_DESTROY(c)          (c)->ops->destroy((c))
-
 #define EC_IN(c, d, p)         (c)->ops->in((c), (d), (p))
 #define EC_OUT(c, d, p)                (c)->ops->in((c), (d), (p))
 
 #define EC_FIND(c, d, x)       (c)->ops->find((c), (d), (x))
+#define EC_NEG(c, d, x)                (c)->ops->neg((c), (d), (x))
 #define EC_ADD(c, d, p, q)     (c)->ops->add((c), (d), (p), (q))
+#define EC_SUB(c, d, p, q)     (c)->ops->sub((c), (d), (p), (q))
 #define EC_DBL(c, d, p)                (c)->ops->dbl((c), (d), (p))
 
 /*----- Simple memory management things -----------------------------------*/
@@ -175,9 +193,9 @@ extern ec *ec_setinf(ec */*p*/);
     if (EC_ATINF(p))                                                   \
       _d->x = _d->y = _d->z = MP_NEW;                                  \
     else {                                                             \
-      _d->x = _p->x;                                                   \
-      _d->y = _p->y;                                                   \
-      _d->z = _p->z;                                                   \
+      _d->x = MP_COPY(_p->x);                                          \
+      _d->y = MP_COPY(_p->y);                                          \
+      _d->z = _p->z ? MP_COPY(_p->z) : MP_NEW;                         \
     }                                                                  \
   }                                                                    \
 } while (0)
@@ -186,33 +204,31 @@ extern ec *ec_copy(ec */*d*/, const ec */*p*/);
 
 /*----- Interesting arithmetic --------------------------------------------*/
 
-/* --- @ec_denorm@ --- *
+/* --- @ec_in@ --- *
  *
  * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
  *             @ec *d@ = pointer to the destination point
  *             @const ec *p@ = pointer to the source point
  *
- * Returns:    ---
+ * Returns:    The destination point.
  *
- * Use:                Denormalizes the given point, converting to internal
- *             representations and setting the denominator to 1.
+ * Use:                Converts a point to internal representation.
  */
 
-extern void ec_denorm(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+extern ec *ec_in(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 
-/* --- @ec_norm@ --- *
+/* --- @ec_out@ --- *
  *
  * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
  *             @ec *d@ = pointer to the destination point
  *             @const ec *p@ = pointer to the source point
  *
- * Returns:    ---
+ * Returns:    The destination point.
  *
- * Use:                Normalizes the given point, by dividing through by the
- *             denominator and returning to external representation.
+ * Use:                Converts a point to external representation.
  */
 
-extern void ec_norm(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+extern ec *ec_out(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 
 /* --- @ec_find@ --- *
  *
@@ -220,12 +236,28 @@ extern void ec_norm(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
  *             @ec *d@ = pointer to the destination point
  *             @mp *x@ = a possible x-coordinate
  *
- * Returns:    Zero if OK, nonzero if there isn't a point there.
+ * Returns:    The destination if OK, or null if no point was found.
  *
- * Use:                Finds a point on an elliptic curve with a given x-coordinate.
+ * Use:                Finds a point on an elliptic curve with a given
+ *             x-coordinate.  If there is no point with the given
+ *             %$x$%-coordinate, a null pointer is returned and the
+ *             destination is left invalid.
  */
 
-extern void ec_find(ec_curve */*c*/, ec */*d*/, mp */*x*/);
+extern ec *ec_find(ec_curve */*c*/, ec */*d*/, mp */*x*/);
+
+/* --- @ec_neg@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p@ = pointer to the operand point
+ *
+ * Returns:    The destination point.
+ *
+ * Use:                Computes the negation of the given point.
+ */
+
+extern ec *ec_neg(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 
 /* --- @ec_add@ --- *
  *
@@ -241,6 +273,20 @@ extern void ec_find(ec_curve */*c*/, ec */*d*/, mp */*x*/);
 extern ec *ec_add(ec_curve */*c*/, ec */*d*/,
                  const ec */*p*/, const ec */*q*/);
 
+/* --- @ec_sub@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec *p, *q@ = pointers to the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Subtracts one point from another on an elliptic curve.
+ */
+
+extern ec *ec_sub(ec_curve */*c*/, ec */*d*/,
+                 const ec */*p*/, const ec */*q*/);
+
 /* --- @ec_dbl@ --- *
  *
  * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
@@ -254,7 +300,7 @@ extern ec *ec_add(ec_curve */*c*/, ec */*d*/,
 
 extern ec *ec_dbl(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 
-/* --- @ec_mul@ --- *
+/* --- @ec_mul@, @ec_imul@ --- *
  *
  * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
  *             @ec *d@ = pointer to the destination point
@@ -263,10 +309,31 @@ extern ec *ec_dbl(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
  *
  * Returns:    The destination @d@.
  *
- * Use:                Multiplies a point by a scalar, returning %$n p$%.
+ * Use:                Multiplies a point by a scalar, returning %$n p$%.  The
+ *             @imul@ variant uses internal representations for argument
+ *             and result.
  */
 
 extern ec *ec_mul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/);
+extern ec *ec_imul(ec_curve */*c*/, ec */*d*/, const ec */*p*/, mp */*n*/);
+
+/* --- @ec_mmul@, @ec_immul@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination point
+ *             @const ec_mulfactor *f@ = pointer to vector of factors
+ *             @size_t n@ = number of factors
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Does simultaneous point multiplication.  The @immul@ variant
+ *             uses internal representations for arguments and result.
+ */
+
+extern ec *ec_mmul(ec_curve */*c*/, ec */*d*/,
+                  const ec_mulfactor */*f*/, size_t /*n*/);
+extern ec *ec_immul(ec_curve */*c*/, ec */*d*/,
+                   const ec_mulfactor */*f*/, size_t /*n*/);
 
 /*----- Standard curve operations -----------------------------------------*/
 
@@ -301,9 +368,35 @@ extern ec *ec_idout(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 extern ec *ec_projin(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 extern ec *ec_projout(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
 
+/* --- @ec_stdsub@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an elliptic curve
+ *             @ec *d@ = pointer to the destination
+ *             @const ec *a, *b@ = the operand points
+ *
+ * Returns:    The destination @d@.
+ *
+ * Use:                Standard point subtraction operation, in terms of negation
+ *             and addition.  This isn't as efficient as a ready-made
+ *             subtraction operator.
+ */
+
+extern ec *ec_stdsub(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
+
 /*----- Creating curves ---------------------------------------------------*/
 
-/* --- @ec_prime@ --- *
+/* --- @ec_destroycurve@ --- *
+ *
+ * Arguments:  @ec_curve *c@ = pointer to an ellptic curve
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a description of an elliptic curve.
+ */
+
+extern void ec_destroycurve(ec_curve */*c*/);
+
+/* --- @ec_prime@, @ec_primeproj@ --- *
  *
  * Arguments:  @field *f@ = the underyling field for this elliptic curve
  *             @mp *a, *b@ = the coefficients for this curve
@@ -311,10 +404,12 @@ extern ec *ec_projout(ec_curve */*c*/, ec */*d*/, const ec */*p*/);
  * Returns:    A pointer to the curve.
  *
  * Use:                Creates a curve structure for an elliptic curve defined over
- *             a prime field.
+ *             a prime field.  The @primeproj@ variant uses projective
+ *             coordinates, which can be a win.
  */
 
 extern ec_curve *ec_prime(field */*f*/, mp */*a*/, mp */*b*/);
+extern ec_curve *ec_primeproj(field */*f*/, mp */*a*/, mp */*b*/);
 
 /* --- @ec_bin@ --- *
  *
index 1a7b9e8..a9673b8 100644 (file)
--- a/f-prime.c
+++ b/f-prime.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: f-prime.c,v 1.1 2001/04/29 18:12:33 mdw Exp $
+ * $Id: f-prime.c,v 1.2 2002/01/13 13:48:44 mdw Exp $
  *
  * Prime fields with Montgomery arithmetic
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: f-prime.c,v $
+ * Revision 1.2  2002/01/13 13:48:44  mdw
+ * Further progress.
+ *
  * Revision 1.1  2001/04/29 18:12:33  mdw
  * Prototype version.
  *
@@ -72,6 +75,12 @@ static mp *fout(field *ff, mp *d, mp *x)
   return (mpmont_reduce(&f->mm, d, x));
 }
 
+static mp *fneg(field *ff, mp *d, mp *x)
+{
+  fctx *f = (fctx *)ff;
+  return (mp_sub(d, f->mm.m, x));
+}
+
 static mp *fadd(field *ff, mp *d, mp *x, mp *y)
 {
   return (mp_add(d, x, y));
@@ -137,7 +146,7 @@ static mp *fsqrt(field *ff, mp *d, mp *x)
 static field_ops fops = {
   fdestroy,
   fin, fout,
-  fadd, fsub, fmul, fsqr, finv, freduce,
+  fneg, fadd, fsub, fmul, fsqr, finv, freduce,
   fdbl, ftpl, fsqrt
 };
 
diff --git a/field.h b/field.h
index 87d3865..5a70649 100644 (file)
--- a/field.h
+++ b/field.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: field.h,v 1.2 2001/05/07 17:30:13 mdw Exp $
+ * $Id: field.h,v 1.3 2002/01/13 13:48:44 mdw Exp $
  *
  * Definitions for field arithmetic
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: field.h,v $
+ * Revision 1.3  2002/01/13 13:48:44  mdw
+ * Further progress.
+ *
  * Revision 1.2  2001/05/07 17:30:13  mdw
  * Add an internal-representation no-op function.
  *
@@ -67,6 +70,7 @@ typedef struct field_ops {
   mp *(*in)(field */*f*/, mp */*d*/, mp */*x*/);
   mp *(*out)(field */*f*/, mp */*d*/, mp */*x*/);
 
+  mp *(*neg)(field */*f*/, mp */*d*/, mp */*x*/);
   mp *(*add)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
   mp *(*sub)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
   mp *(*mul)(field */*f*/, mp */*d*/, mp */*x*/, mp */*y*/);
@@ -86,6 +90,7 @@ typedef struct field_ops {
 
 #define F_IN(f, d, x)          (f)->ops->in((f), (d), (x))
 #define F_OUT(f, d, x)         (f)->ops->out((f), (d), (x))
+#define F_NEG(f, d, x)         (f)->ops->neg((f), (d), (x))
 #define F_ADD(f, d, x, y)      (f)->ops->add((f), (d), (x), (y))
 #define F_SUB(f, d, x, y)      (f)->ops->sub((f), (d), (x), (y))
 #define F_MUL(f, d, x, y)      (f)->ops->mul((f), (d), (x), (y))