+ec *ec_projfix(ec_curve *c, ec *d, const ec *p)
+{
+ if (EC_ATINF(p))
+ EC_SETINF(d);
+ else if (d->z == c->f->one)
+ EC_COPY(d, p);
+ else {
+ mp *z, *zz;
+ field *f = c->f;
+ z = F_INV(f, MP_NEW, p->z);
+ zz = F_SQR(f, MP_NEW, z);
+ z = F_MUL(f, z, zz, z);
+ d->x = F_MUL(f, d->x, p->x, zz);
+ d->y = F_MUL(f, d->y, p->y, z);
+ mp_drop(z);
+ mp_drop(zz);
+ mp_drop(d->z);
+ d->z = MP_COPY(f->one);
+ }
+ return (d);
+}
+
+/* --- @ec_stdsub@ --- *
+ *
+ * Arguments: @ec_curve *c@ = pointer to an elliptic curve
+ * @ec *d@ = pointer to the destination
+ * @const ec *p, *q@ = the operand points
+ *
+ * Returns: The destination @d@.
+ *
+ * Use: Standard point subtraction operation, in terms of negation
+ * and addition. This isn't as efficient as a ready-made
+ * subtraction operator.
+ */
+
+ec *ec_stdsub(ec_curve *c, ec *d, const ec *p, const ec *q)
+{
+ ec t = EC_INIT;
+ EC_NEG(c, &t, q);
+ EC_FIX(c, &t, &t);
+ EC_ADD(c, d, p, &t);
+ EC_DESTROY(&t);
+ return (d);
+}
+
+/*----- Creating curves ---------------------------------------------------*/
+
+/* --- @ec_destroycurve@ --- *
+ *
+ * Arguments: @ec_curve *c@ = pointer to an ellptic curve
+ *
+ * Returns: ---
+ *
+ * Use: Destroys a description of an elliptic curve.
+ */
+
+void ec_destroycurve(ec_curve *c) { c->ops->destroy(c); }
+