+ return (d);
+}
+
+static void ecdestroy(ec_curve *c)
+{
+ ecctx *cc = (ecctx *)c;
+ MP_DROP(cc->a);
+ MP_DROP(cc->b);
+ DESTROY(cc);
+}
+
+/* --- @ec_prime@, @ec_primeproj@ --- *
+ *
+ * Arguments: @field *f@ = the underyling field for this elliptic curve
+ * @mp *a, *b@ = the coefficients for this curve
+ *
+ * Returns: A pointer to the curve.
+ *
+ * Use: Creates a curve structure for an elliptic curve defined over
+ * 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)
+{
+ ecctx *cc = CREATE(ecctx);
+ cc->c.ops = &ec_primeops;
+ cc->c.f = f;
+ cc->a = MP_COPY(a);
+ cc->b = MP_COPY(b);
+ return (&cc->c);
+}
+
+static const ec_ops ec_primeops = {
+ ecdestroy, ec_idin, ec_idout, 0, ecneg, ecadd, ec_stdsub, ecdbl
+};
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#define MP(x) mp_readstring(MP_NEW, #x, 0, 0)
+
+int main(void)
+{
+ field *f;
+ ec_curve *c;
+ ec g = EC_INIT, d = EC_INIT;
+ mp *p, *a, *b, *r;
+
+ a = MP(-3);
+ b = MP(0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1);
+ p = MP(6277101735386680763835789423207666416083908700390324961279);
+ r = MP(6277101735386680763835789423176059013767194773182842284081);
+
+ f = field_prime(p);
+ c = ec_prime(f, a, b);
+
+ g.x = MP(0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012);
+ g.y = MP(0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811);
+
+ ec_mul(c, &d, &g, r);
+ MP_PRINT("d.x", d.x);
+ MP_PRINT("d.y", d.y);
+
+ ec_destroy(&d);
+ ec_destroy(&g);
+ ec_destroycurve(c);
+ F_DESTROY(f);
+
+ return (0);