Merge branch 'master' of git+ssh://metalzone.distorted.org.uk/~mdw/public-git/catacomb/
[u/mdw/catacomb] / gf-gcd.c
index 64d61d4..048d29d 100644 (file)
--- a/gf-gcd.c
+++ b/gf-gcd.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: gf-gcd.c,v 1.1.2.1 2004/03/21 22:39:46 mdw Exp $
+ * $Id$
  *
  * Euclidian algorithm on binary polynomials
  *
  * MA 02111-1307, USA.
  */
 
-/*----- Revision history --------------------------------------------------* 
- *
- * $Log: gf-gcd.c,v $
- * Revision 1.1.2.1  2004/03/21 22:39:46  mdw
- * Elliptic curves on binary fields work.
- *
- */
-
 /*----- Header files ------------------------------------------------------*/
 
 #include "gf.h"
@@ -114,28 +106,20 @@ void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b)
     return;
   }
 
-  /* --- Take a reference to the arguments --- */
-
-  a = MP_COPY(a);
-  b = MP_COPY(b);
-
-  /* --- Make sure @a@ and @b@ are not both even --- */
-
-  MP_SPLIT(a); a->f &= ~MP_NEG;
-  MP_SPLIT(b); b->f &= ~MP_NEG;
+  /* --- Main extended Euclidean algorithm --- */
 
   u = MP_COPY(a);
   v = MP_COPY(b);
 
-  while (MP_LEN(v)) {
+  while (!MP_ZEROP(v)) {
     mp *t;
     gf_div(&q, &u, u, v);
     if (f & f_ext) {
       t = gf_mul(MP_NEW, X, q);
-      t = gf_add(t, x, t);
+      t = gf_add(t, t, x);
       MP_DROP(x); x = X; X = t;
       t = gf_mul(MP_NEW, Y, q);
-      t = gf_add(t, y, t);
+      t = gf_add(t, t, y);
       MP_DROP(y); y = Y; Y = t;
     }
     t = u; u = v; v = t;
@@ -180,7 +164,28 @@ void gf_gcd(mp **gcd, mp **xx, mp **yy, mp *a, mp *b)
 
   MP_DROP(v);
   MP_DROP(X); MP_DROP(Y);
-  MP_DROP(a); MP_DROP(b);
+}
+
+/* -- @gf_modinv@ --- *
+ *
+ * Arguments:  @mp *d@ = destination
+ *             @mp *x@ = argument
+ *             @mp *p@ = modulus
+ *
+ * Returns:    The inverse %$x^{-1} \bmod p$%.
+ *
+ * Use:                Computes a modular inverse, the catch being that the
+ *             arguments and results are binary polynomials.  An assertion
+ *             fails if %$p$% has no inverse.
+ */
+
+mp *gf_modinv(mp *d, mp *x, mp *p)
+{
+  mp *g = MP_NEW;
+  gf_gcd(&g, 0, &d, p, x);
+  assert(MP_EQ(g, MP_ONE));
+  mp_drop(g);
+  return (d);
 }
 
 /*----- Test rig ----------------------------------------------------------*/
@@ -199,7 +204,7 @@ static int gcd(dstr *v)
   mp *gg = MP_NEW, *xx = MP_NEW, *yy = MP_NEW;
   gf_gcd(&gg, &xx, &yy, a, b);
   if (!MP_EQ(x, xx)) {
-    fputs("\n*** mp_gcd(x) failed", stderr);
+    fputs("\n*** gf_gcd(x) failed", stderr);
     fputs("\na      = ", stderr); mp_writefile(a, stderr, 16);
     fputs("\nb      = ", stderr); mp_writefile(b, stderr, 16);
     fputs("\nexpect = ", stderr); mp_writefile(x, stderr, 16);
@@ -208,7 +213,7 @@ static int gcd(dstr *v)
     ok = 0;
   }
   if (!MP_EQ(y, yy)) {
-    fputs("\n*** mp_gcd(y) failed", stderr);
+    fputs("\n*** gf_gcd(y) failed", stderr);
     fputs("\na      = ", stderr); mp_writefile(a, stderr, 16);
     fputs("\nb      = ", stderr); mp_writefile(b, stderr, 16);
     fputs("\nexpect = ", stderr); mp_writefile(y, stderr, 16);
@@ -228,7 +233,7 @@ static int gcd(dstr *v)
   }
 
   if (!MP_EQ(g, gg)) {
-    fputs("\n*** mp_gcd(gcd) failed", stderr);
+    fputs("\n*** gf_gcd(gcd) failed", stderr);
     fputs("\na      = ", stderr); mp_writefile(a, stderr, 16);
     fputs("\nb      = ", stderr); mp_writefile(b, stderr, 16);
     fputs("\nexpect = ", stderr); mp_writefile(g, stderr, 16);