symm/keccak1600.c (keccak1600_extract): Eliminate intermediate state buffer.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 17 Nov 2018 21:08:11 +0000 (21:08 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 29 Sep 2019 21:03:29 +0000 (22:03 +0100)
Instead, introduce a handy bitmap which identifies which lanes need
complementing and do the whole thing in the loop.

symm/keccak1600.c

index d58bc6f..499ab4f 100644 (file)
@@ -221,6 +221,8 @@ static const lane rcon[24] = {
  * `keccak1600_round' below for the details.
  */
 
+#define COMPL_MASK 0x00121106u
+
 #define STATE_INIT(z) do {                                             \
   lane cmpl = LANE_CMPL;                                               \
   (z)->S[I(1, 0)] = cmpl; (z)->S[I(2, 0)] = cmpl;                      \
@@ -240,6 +242,8 @@ static const lane rcon[24] = {
 #else
 /* A target with fused and/not (`bic', `andc2').  Everything is simple. */
 
+#define COMPL_MASK 0u
+
 #define STATE_INIT(z) do ; while (0)
 #define STATE_OUT(z) do ; while (0)
 
@@ -600,11 +604,14 @@ void keccak1600_mix(keccak1600_state *s, const kludge64 *p, size_t n)
 
 void keccak1600_extract(const keccak1600_state *s, kludge64 *p, size_t n)
 {
+  uint32 m = COMPL_MASK;
   unsigned i;
-  keccak1600_state t;
+  lane t;
 
-  t = *s; STATE_OUT(&t);
-  for (i = 0; i < n; i++) p[i] = FROM_LANE(t.S[i]);
+  for (i = 0; i < n; i++) {
+    t = s->S[i]; if (m&1) NOT_LANE(t, t);
+    *p++ = FROM_LANE(t); m >>= 1;
+  }
 }
 
 /*----- Test rig ----------------------------------------------------------*/