[Pkg-bitcoin-commits] [libsecp256k1] 13/37: Unroll secp256k1_fe_(get|set)_b32 for 5x52.

Jonas Smedegaard dr at jones.dk
Fri Aug 18 11:27:53 UTC 2017


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository libsecp256k1.

commit aa8499080e2a657113781921096b59a74d7bc0e7
Author: CryptoGuru <bots at cryptoguru.org>
Date:   Mon Jan 9 23:18:57 2017 +0000

    Unroll secp256k1_fe_(get|set)_b32 for 5x52.
    
    field_get_b32: min 0.647us / avg 0.666us / max 0.751us
    field_set_b32: min 0.551us / avg 0.571us / max 0.624us
    
    becomes
    
    field_get_b32: min 0us / avg 0.0000000477us / max 0.000000238us
    field_set_b32: min 0us / avg 0.0000000238us / max 0.000000238us
    
    (Patch from https://bitcointalk.org/index.php?topic=1740973.0
     _get was reversed from the patch because this order appeared
     somewhat faster in testing.)
    
    Signed-off-by: Gregory Maxwell <greg at xiph.org>
---
 src/field_5x52_impl.h | 87 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 66 insertions(+), 21 deletions(-)

diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h
index dd88f38..8e8b286 100644
--- a/src/field_5x52_impl.h
+++ b/src/field_5x52_impl.h
@@ -284,16 +284,40 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
 }
 
 static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
-    int i;
-    r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
-    for (i=0; i<32; i++) {
-        int j;
-        for (j=0; j<2; j++) {
-            int limb = (8*i+4*j)/52;
-            int shift = (8*i+4*j)%52;
-            r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift;
-        }
-    }
+    r->n[0] = (uint64_t)a[31]
+            | ((uint64_t)a[30] << 8)
+            | ((uint64_t)a[29] << 16)
+            | ((uint64_t)a[28] << 24)
+            | ((uint64_t)a[27] << 32)
+            | ((uint64_t)a[26] << 40)
+            | ((uint64_t)(a[25] & 0xF)  << 48);
+    r->n[1] = (uint64_t)((a[25] >> 4) & 0xF)
+            | ((uint64_t)a[24] << 4)
+            | ((uint64_t)a[23] << 12)
+            | ((uint64_t)a[22] << 20)
+            | ((uint64_t)a[21] << 28)
+            | ((uint64_t)a[20] << 36)
+            | ((uint64_t)a[19] << 44);
+    r->n[2] = (uint64_t)a[18]
+            | ((uint64_t)a[17] << 8)
+            | ((uint64_t)a[16] << 16)
+            | ((uint64_t)a[15] << 24)
+            | ((uint64_t)a[14] << 32)
+            | ((uint64_t)a[13] << 40)
+            | ((uint64_t)(a[12] & 0xF) << 48);
+    r->n[3] = (uint64_t)((a[12] >> 4) & 0xF)
+            | ((uint64_t)a[11] << 4)
+            | ((uint64_t)a[10] << 12)
+            | ((uint64_t)a[9]  << 20)
+            | ((uint64_t)a[8]  << 28)
+            | ((uint64_t)a[7]  << 36)
+            | ((uint64_t)a[6]  << 44);
+    r->n[4] = (uint64_t)a[5]
+            | ((uint64_t)a[4] << 8)
+            | ((uint64_t)a[3] << 16)
+            | ((uint64_t)a[2] << 24)
+            | ((uint64_t)a[1] << 32)
+            | ((uint64_t)a[0] << 40);
     if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) {
         return 0;
     }
@@ -307,21 +331,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
 
 /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
 static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
-    int i;
 #ifdef VERIFY
     VERIFY_CHECK(a->normalized);
     secp256k1_fe_verify(a);
 #endif
-    for (i=0; i<32; i++) {
-        int j;
-        int c = 0;
-        for (j=0; j<2; j++) {
-            int limb = (8*i+4*j)/52;
-            int shift = (8*i+4*j)%52;
-            c |= ((a->n[limb] >> shift) & 0xF) << (4 * j);
-        }
-        r[31-i] = c;
-    }
+    r[0] = (a->n[4] >> 40) & 0xFF;
+    r[1] = (a->n[4] >> 32) & 0xFF;
+    r[2] = (a->n[4] >> 24) & 0xFF;
+    r[3] = (a->n[4] >> 16) & 0xFF;
+    r[4] = (a->n[4] >> 8) & 0xFF;
+    r[5] = a->n[4] & 0xFF;
+    r[6] = (a->n[3] >> 44) & 0xFF;
+    r[7] = (a->n[3] >> 36) & 0xFF;
+    r[8] = (a->n[3] >> 28) & 0xFF;
+    r[9] = (a->n[3] >> 20) & 0xFF;
+    r[10] = (a->n[3] >> 12) & 0xFF;
+    r[11] = (a->n[3] >> 4) & 0xFF;
+    r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4);
+    r[13] = (a->n[2] >> 40) & 0xFF;
+    r[14] = (a->n[2] >> 32) & 0xFF;
+    r[15] = (a->n[2] >> 24) & 0xFF;
+    r[16] = (a->n[2] >> 16) & 0xFF;
+    r[17] = (a->n[2] >> 8) & 0xFF;
+    r[18] = a->n[2] & 0xFF;
+    r[19] = (a->n[1] >> 44) & 0xFF;
+    r[20] = (a->n[1] >> 36) & 0xFF;
+    r[21] = (a->n[1] >> 28) & 0xFF;
+    r[22] = (a->n[1] >> 20) & 0xFF;
+    r[23] = (a->n[1] >> 12) & 0xFF;
+    r[24] = (a->n[1] >> 4) & 0xFF;
+    r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4);
+    r[26] = (a->n[0] >> 40) & 0xFF;
+    r[27] = (a->n[0] >> 32) & 0xFF;
+    r[28] = (a->n[0] >> 24) & 0xFF;
+    r[29] = (a->n[0] >> 16) & 0xFF;
+    r[30] = (a->n[0] >> 8) & 0xFF;
+    r[31] = a->n[0] & 0xFF;
 }
 
 SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/libsecp256k1.git



More information about the Pkg-bitcoin-commits mailing list