+/* -*-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 -------------------------------------------------*/