progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / math / ec-bin.c
index c7fe96d..598b7e3 100644 (file)
@@ -317,6 +317,32 @@ static int ecprojcheck(ec_curve *c, const ec *p)
   return (rc);
 }
 
+static int eccompr(ec_curve *c, const ec *p)
+{
+  /* --- Take the LSB of %$y/x$%, or zero if %$x = 0$% ---
+   *
+   * The negative of a point has %$y' = y + x$%.  Therefore either %$y/x$% or
+   * $%(y + x)/x = y/x + 1$% is odd, and this disambiguates, unless %$x =
+   * 0$%; but in that case we must have %$y^2 = b$% which has exactly one
+   * solution (because squaring is linear in a binary field).
+   */
+
+  int ybit;
+  field *f = c->f;
+  mp *y, *t;
+  if (MP_ZEROP(p->x)) ybit = 0;
+  else {
+    t = F_IN(f, MP_NEW, p->x);
+    y = F_IN(f, MP_NEW, p->y);
+    t = F_INV(f, t, t);
+    t = F_MUL(f, t, y, t);
+    t = F_OUT(f, t, t);
+    ybit = MP_ODDP(t);
+    MP_DROP(y); MP_DROP(t);
+  }
+  return (ybit);
+}
+
 static void ecdestroy(ec_curve *c)
 {
   ecctx_bin *cc = (ecctx_bin *)c;
@@ -380,13 +406,13 @@ ec_curve *ec_binproj(field *f, mp *a, mp *b)
 static const ec_ops ec_binops = {
   "bin",
   ecdestroy, ec_stdsamep, ec_idin, ec_idout, ec_idfix,
-  ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck
+  ecfind, ecneg, ecadd, ec_stdsub, ecdbl, eccheck, eccompr
 };
 
 static const ec_ops ec_binprojops = {
   "binproj",
   ecdestroy, ec_stdsamep, ec_projin, ec_projout, ec_projfix,
-  ecfind, ecprojneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck
+  ecfind, ecprojneg, ecprojadd, ec_stdsub, ecprojdbl, ecprojcheck, eccompr
 };
 
 /*----- Test rig ----------------------------------------------------------*/