Much wider support for Catacomb in all its glory.
[catacomb-perl] / group.xs
diff --git a/group.xs b/group.xs
new file mode 100644 (file)
index 0000000..51af11c
--- /dev/null
+++ b/group.xs
@@ -0,0 +1,428 @@
+# ---?---
+#
+# $Id$
+#
+# Abstract groups
+#
+# (c) 2001 Straylight/Edgeware
+#
+
+#----- Licensing notice -----------------------------------------------------
+#
+# This file is part of the Perl interface to Catacomb.
+#
+# Catacomb/Perl is free software; you can redistribute it and/or modify
+# 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/Perl 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/Perl; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+MODULE = Catacomb PACKAGE = Catacomb::Group PREFIX = group_
+
+Group *
+prime(me, p, g, q)
+       SV *me
+       mp *p
+       mp *g
+       mp *q
+       PREINIT:
+       gprime_param gp;
+       CODE:
+       gp.p = p;
+       gp.q = q;
+       gp.g = g;
+       RETVAL = group_prime(&gp);
+       OUTPUT:
+       RETVAL
+
+Group *
+binary(me, p, g, q)
+       SV *me
+       mp *p
+       mp *g
+       mp *q
+       PREINIT:
+       gbin_param gb;
+       CODE:
+       gb.p = p;
+       gb.q = q;
+       gb.g = g;
+       RETVAL = group_binary(&gb);
+       OUTPUT:
+       RETVAL
+
+Group *
+ec(me, c, g, r, h)
+       SV *me
+       EC_Curve *c
+       ec *g
+       mp *r
+       mp *h
+       PREINIT:
+       ec_info ei;
+       CODE:
+       ei.c = copy_curve(c);
+       EC_CREATE(&ei.g);
+       EC_COPY(&ei.g, g);
+       ei.r = MP_COPY(r);
+       ei.h = MP_COPY(h);
+       RETVAL = group_ec(&ei);
+       OUTPUT:
+       RETVAL
+
+Group *
+byname(me, n)
+       SV *me
+       char *n
+       PREINIT:
+       const char *e;
+       CODE:
+       if ((e = group_fromstring(n, &RETVAL)) != 0)
+         croak("bad group name: `%s'", e);
+       OUTPUT:
+       RETVAL
+
+SV *
+DESTROY(g)
+       Group *g
+       CODE:
+       G_DESTROYGROUP(g);
+       XSRETURN_YES;
+
+ge *
+_i(g)
+       Group *g
+       CODE:
+       RETVAL = G_CREATE(g);
+       G_COPY(g, RETVAL, g->i);
+       OUTPUT:
+       RETVAL
+
+ge *
+_g(g)
+       Group *g
+       CODE:
+       RETVAL = G_CREATE(g);
+       G_COPY(g, RETVAL, g->g);
+       OUTPUT:
+       RETVAL
+
+mp *
+r(g)
+       Group *g
+       CODE:
+       RETVAL = MP_COPY(g->r);
+       OUTPUT:
+       RETVAL
+
+mp *
+h(g)
+       Group *g
+       CODE:
+       RETVAL = MP_COPY(g->h);
+       OUTPUT:
+       RETVAL
+
+bool
+group_samep(g, h)
+       Group *g
+       Group *h
+
+void
+check(g, rng = &rand_global)
+       Group *g
+       grand *rng
+       PREINIT:
+       const char *e;
+       PPCODE:
+       e = G_CHECK(g, rng);
+       if (!e)
+         XSRETURN_YES;
+       XPUSHs(&PL_sv_undef);
+       if (GIMME_V == G_ARRAY)
+         XPUSHs(sv_2mortal(newSVpv(e, 0)));
+
+SV *
+_checkelt(g, x)
+       Group *g
+       ge *x
+       CODE:
+       if (group_check(g, x))
+         XSRETURN_UNDEF;
+       else 
+         XSRETURN_YES;   
+
+SV *
+_destroyelement(g, x)
+       Group *g
+       ge *x
+       CODE:
+       G_DESTROY(g, x);
+       XSRETURN_YES;
+
+bool
+_identp(g, x)
+       Group *g
+       ge *x
+       CODE:
+       RETVAL = G_IDENTP(g, x);
+       OUTPUT:
+       RETVAL
+
+SV *
+get(g)
+       Group *g
+       CODE:
+       RETVAL = info_group(g);
+       OUTPUT:
+       RETVAL
+
+bool
+_eq(g, x, y)
+       Group *g
+       ge *x
+       ge *y
+       CODE:
+       RETVAL = G_EQ(g, x, y);
+       OUTPUT:
+       RETVAL
+
+ge *
+_mul(g, x, y)
+       Group *g
+       ge *x
+       ge *y
+       CODE:
+       RETVAL = G_CREATE(g);
+       G_MUL(g, RETVAL, x, y);
+       OUTPUT:
+       RETVAL
+
+ge *
+_sqr(g, x)
+       Group *g
+       ge *x
+       CODE:
+       RETVAL = G_CREATE(g);
+       G_SQR(g, RETVAL, x);
+       OUTPUT:
+       RETVAL
+
+ge *
+_inv(g, x)
+       Group *g
+       ge *x
+       CODE:
+       RETVAL = G_CREATE(g);
+       G_INV(g, RETVAL, x);
+       OUTPUT:
+       RETVAL
+
+ge *
+_div(g, x, y)
+       Group *g
+       ge *x
+       ge *y
+       CODE:
+       RETVAL = G_CREATE(g);
+       G_DIV(g, RETVAL, x, y);
+       OUTPUT:
+       RETVAL
+
+ge *
+_exp(g, x, n)
+       Group *g
+       ge *x
+       mp *n
+       CODE:
+       RETVAL = G_CREATE(g);
+       G_EXP(g, RETVAL, x, n);
+       OUTPUT:
+       RETVAL
+
+ge *
+_mexp(g, ...)
+       Group *g
+       PREINIT:
+       group_expfactor *v;
+       size_t i, j, n;
+       CODE:
+       if (items < 3 || !(items & 1)) {
+         croak("Usage: Catacomb::Group::mexp"
+               "(g, x_0, n_0, x_1, n_1, ...");
+       }
+       n = (items - 1)/2;
+       v = xmalloc(n * sizeof(group_expfactor));
+       for (i = 1, j = 0; i < items; i += 2, j++) {
+         v[j].base = ptrfromsv(ST(i), "Catacomb::Group::Element", "p_i");
+         v[j].exp = mp_fromsv(ST(i + 1), "x_i", 0, 0);
+       }
+       RETVAL = G_CREATE(g);
+       G_MEXP(g, RETVAL, v, n);
+       xfree(v);
+       OUTPUT:
+       RETVAL
+
+mp *
+_toint(g, x)
+       Group *g
+       ge *x
+       CODE:
+       RETVAL = G_TOINT(g, MP_NEW, x);
+       OUTPUT:
+       RETVAL
+
+ge *
+_fromint(g, x)
+       Group *g
+       mp *x
+       CODE:
+       RETVAL = G_CREATE(g);
+       if (G_FROMINT(g, RETVAL, x)) {
+         G_DESTROY(g, RETVAL);
+         RETVAL = 0;
+       }
+       OUTPUT:
+       RETVAL
+
+ec *
+_toec(g, x)
+       Group *g
+       ge *x
+       CODE:
+       RETVAL = CREATE(ec);
+       EC_CREATE(RETVAL);
+       if (G_TOEC(g, RETVAL, x)) {
+         DESTROY(RETVAL);
+         RETVAL = 0;
+       }
+       OUTPUT:
+       RETVAL
+
+ge *
+_fromec(g, x)
+       Group *g
+       ec *x
+       CODE:
+       RETVAL = G_CREATE(g);
+       if (G_FROMEC(g, RETVAL, x)) {
+         G_DESTROY(g, RETVAL);
+         RETVAL = 0;
+       }
+       OUTPUT:
+       RETVAL
+
+SV *
+_putbuf(g, x)
+       Group *g
+       ge *x
+       PREINIT:
+       buf b;
+       size_t n = g->noctets + 8; /* Guess */
+       CODE:
+       RETVAL = NEWSV(0, n);
+       buf_init(&b, SvPVX(RETVAL), n);
+       if (G_TOBUF(g, &b, x))
+         croak("unexpected failure in Catacomb::Group::putbuf");
+       SvCUR_set(RETVAL, BLEN(&b));
+       OUTPUT:
+       RETVAL
+
+void
+_getbuf(g, s)
+       Group *g
+       SV *s
+       PREINIT:
+       ge *x;
+       buf b;
+       char *q;
+       STRLEN n;
+       CODE:
+       q = SvPV(s, n);
+       buf_init(&b, q, n);
+       x = G_CREATE(g);
+       if (G_FROMBUF(g, &b, x))
+         G_DESTROY(g, x);
+       else {
+         XPUSHs(RET(x, "Catacomb::Group::Element"));
+         if (GIMME_V == G_ARRAY)
+           XPUSHs(sv_2mortal(newSVpvn(BCUR(&b), BLEFT(&b))));
+       }
+
+SV *
+_putraw(g, x)
+       Group *g
+       ge *x
+       PREINIT:
+       buf b;
+       size_t n = g->noctets;
+       CODE:
+       RETVAL = NEWSV(0, n);
+       buf_init(&b, SvPVX(RETVAL), n);
+       if (G_TORAW(g, &b, x))
+         croak("unexpected failure in Catacomb::Group::putraw");
+       SvCUR_set(RETVAL, BLEN(&b));
+       OUTPUT:
+       RETVAL
+
+void
+_getraw(g, s)
+       Group *g
+       SV *s
+       PREINIT:
+       ge *x;
+       buf b;
+       char *q;
+       STRLEN n;
+       CODE:
+       q = SvPV(s, n);
+       buf_init(&b, q, n);
+       x = G_CREATE(g);
+       if (G_FROMRAW(g, &b, x))
+         G_DESTROY(g, x);
+       else {
+         XPUSHs(RET(x, "Catacomb::Group::Element"));
+         if (GIMME_V == G_ARRAY)
+           XPUSHs(sv_2mortal(newSVpvn(BCUR(&b), BLEFT(&b))));
+       }
+
+SV *
+_tostring(g, x)
+       Group *g
+       ge *x
+       CODE:
+       RETVAL = NEWSV(0, 64);
+       if (group_writesv(g, x, RETVAL)) {
+         SvREFCNT_dec(RETVAL);
+         XSRETURN_UNDEF;
+       }
+       OUTPUT:
+       RETVAL  
+
+void
+_fromstring(g, s)
+       Group *g
+       SV *s
+       PREINIT:
+       mptext_stringctx ms;
+       STRLEN len;
+       ge *x;
+       PPCODE:
+       ms.buf = SvPV(s, len);
+       ms.lim = ms.buf + len;
+       x = G_CREATE(g);
+       if (G_READ(g, x, &mptext_stringops, &ms))
+         G_DESTROY(g, x);
+       else {
+         XPUSHs(RET(x, "Catacomb::Group::Element"));
+         if (GIMME_V == G_ARRAY)
+           XPUSHs(sv_2mortal(newSVpvn(ms.buf, ms.lim - ms.buf)));
+       }