From c5b95903146e51d1498e954cbc66c8e3ff391699 Mon Sep 17 00:00:00 2001 From: Loup Vaillant Date: Tue, 30 Jul 2019 00:43:35 +0200 Subject: [PATCH] Hoisted negations out of loops Turns out compilers don't do this naturally, and this leads to observable slow downs in some cases. Also noted that we are relying on 2's complement representation (we already were). We could be more portable by going unsigned, but by this logic the entire field arithmetic should go unsigned. It's possible, but it's not trivial. I've kinda tried it in the past, and failed. Every architecture of interest is 2's complement anyway, so I think this will be good enough. --- src/monocypher.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/monocypher.c b/src/monocypher.c index c44e2ef..777d00d 100644 --- a/src/monocypher.c +++ b/src/monocypher.c @@ -1026,8 +1026,9 @@ static void fe_sub (fe h,const fe f,const fe g){FOR(i,0,10) h[i] = f[i] - g[i];} static void fe_cswap(fe f, fe g, int b) { + i32 mask = -b; // rely on 2's complement: -1 = 0xffffffff FOR (i, 0, 10) { - i32 x = (f[i] ^ g[i]) & -b; + i32 x = (f[i] ^ g[i]) & mask; f[i] = f[i] ^ x; g[i] = g[i] ^ x; } @@ -1035,8 +1036,9 @@ static void fe_cswap(fe f, fe g, int b) static void fe_ccopy(fe f, const fe g, int b) { + i32 mask = -b; // rely on 2's complement: -1 = 0xffffffff FOR (i, 0, 10) { - i32 x = (f[i] ^ g[i]) & -b; + i32 x = (f[i] ^ g[i]) & mask; f[i] = f[i] ^ x; } } -- 2.47.3