Add cyclic group abstraction, with test code. Separate off exponentation
[u/mdw/catacomb] / group-exp.c
diff --git a/group-exp.c b/group-exp.c
new file mode 100644 (file)
index 0000000..72bd5a0
--- /dev/null
@@ -0,0 +1,121 @@
+/* -*-c-*-
+ *
+ * $Id: group-exp.c,v 1.1 2004/04/01 12:50:09 mdw Exp $
+ *
+ * Exponentiation for abstract groups
+ *
+ * (c) 2004 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: group-exp.c,v $
+ * Revision 1.1  2004/04/01 12:50:09  mdw
+ * Add cyclic group abstraction, with test code.  Separate off exponentation
+ * functions for better static linking.  Fix a buttload of bugs on the way.
+ * Generally ensure that negative exponents do inversion correctly.  Add
+ * table of standard prime-field subgroups.  (Binary field subgroups are
+ * currently unimplemented but easy to add if anyone ever finds a good one.)
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "group.h"
+#include "group-exp.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @group_stdexp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @ge *x@ = base element
+ *             @mp *n@ = exponent
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = x^n$% efficiently.
+ */
+
+void group_stdexp(group *gg, ge *d, ge *x, mp *n)
+{
+  ge *t = G_CREATE(gg);
+
+  G_COPY(gg, t, x);
+  MP_SHRINK(n);
+  G_COPY(gg, d, gg->i);
+  if (n->f & MP_BURN)
+    G_BURN(gg, t);
+  if (MP_LEN(n) == 0)
+    ;
+  else {
+    if (n->f & MP_NEG)
+      G_INV(gg, t, t);
+    if (MP_LEN(n) < EXP_THRESH)
+      EXP_SIMPLE(d, t, n);
+    else
+      EXP_WINDOW(d, t, n);
+  }
+  G_DESTROY(gg, t);
+}
+
+/* --- @group_stdmexp@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @ge *d@ = destination pointer
+ *             @const group_expfactor *f@ = vector of factors
+ *             @size_t n@ = number of factors
+ *
+ * Returns:    ---
+ *
+ * Use:                Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently.
+ */
+
+#undef EXP_WINSZ
+#define EXP_WINSZ 3
+
+void group_stdmexp(group *gg, ge *d, const group_expfactor *f, size_t n)
+{
+  group_expfactor *ff = xmalloc(n * sizeof(group_expfactor));
+  size_t i;
+
+  for (i = 0; i < n; i++) {
+    ff[i].base = G_CREATE(gg);
+    MP_SHRINK(f[i].exp);
+    if (f[i].exp->f & MP_NEG)
+      G_INV(gg, ff[i].base, f[i].base);
+    else
+      G_COPY(gg, ff[i].base, f[i].base);
+    if (f[i].exp->f & MP_BURN)
+      G_BURN(gg, ff[i].base);
+    ff[i].exp = f[i].exp;
+  }
+  G_COPY(gg, d, gg->i);
+  EXP_SIMUL(d, ff, n);
+  for (i = 0; i < n; i++)
+    G_DESTROY(gg, ff[i].base);
+  xfree(ff);
+}
+
+/*----- That's all, folks -------------------------------------------------*/