Further performance improvements to _ecmult_wnaf

- Initialize 'wnaf' to zeroes using memset
- Add new 'len' arg to speed up smaller scalars (mostly for endo=yes)
pull/11871/head
Peter Dettman 9 years ago
parent 145cc6ea8f
commit 55399c23f7

@ -229,7 +229,7 @@ void bench_ecmult_wnaf(void* arg) {
bench_inv_t *data = (bench_inv_t*)arg; bench_inv_t *data = (bench_inv_t*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_ecmult_wnaf(data->wnaf, &data->scalar_x, WINDOW_A); secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A);
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
} }
} }

@ -213,21 +213,28 @@ static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx) {
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
* - two non-zero entries in wnaf are separated by at least w-1 zeroes. * - two non-zero entries in wnaf are separated by at least w-1 zeroes.
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more * - the number of set values in wnaf is returned. This number is at most 256, and at most one more
* - than the number of bits in the (absolute value) of the input. * than the number of bits in the (absolute value) of the input.
*/ */
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) { static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar_t *a, int w) {
secp256k1_scalar_t s = *a; secp256k1_scalar_t s = *a;
int set_bits = 0; int last_set_bit = -1;
int bit = 0; int bit = 0;
int sign = 1; int sign = 1;
int carry = 0; int carry = 0;
VERIFY_CHECK(wnaf != NULL);
VERIFY_CHECK(0 <= len && len <= 256);
VERIFY_CHECK(a != NULL);
VERIFY_CHECK(2 <= w && w <= 31);
memset(wnaf, 0, len * sizeof(wnaf[0]));
if (secp256k1_scalar_get_bits(&s, 255, 1)) { if (secp256k1_scalar_get_bits(&s, 255, 1)) {
secp256k1_scalar_negate(&s, &s); secp256k1_scalar_negate(&s, &s);
sign = -1; sign = -1;
} }
while (bit < 256) { while (bit < len) {
int now; int now;
int word; int word;
if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) {
@ -236,8 +243,8 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w)
} }
now = w; now = w;
if (now > 256 - bit) { if (now > len - bit) {
now = 256 - bit; now = len - bit;
} }
word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry;
@ -245,14 +252,18 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w)
carry = (word >> (w-1)) & 1; carry = (word >> (w-1)) & 1;
word -= carry << w; word -= carry << w;
while (set_bits < bit) { wnaf[bit] = sign * word;
wnaf[set_bits++] = 0; last_set_bit = bit;
}
wnaf[set_bits++] = sign * word;
bit += now; bit += now;
} }
VERIFY_CHECK(carry == 0); #ifdef VERIFY
return set_bits; CHECK(carry == 0);
while (bit < 256) {
CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
}
#endif
return last_set_bit + 1;
} }
static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) { static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
@ -275,7 +286,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
#else #else
int wnaf_na[256]; int wnaf_na[256];
int bits_na; int bits_na;
int wnaf_ng[257]; int wnaf_ng[256];
int bits_ng; int bits_ng;
#endif #endif
int i; int i;
@ -286,8 +297,8 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na); secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na);
/* build wnaf representation for na_1 and na_lam. */ /* build wnaf representation for na_1 and na_lam. */
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A);
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A);
VERIFY_CHECK(bits_na_1 <= 130); VERIFY_CHECK(bits_na_1 <= 130);
VERIFY_CHECK(bits_na_lam <= 130); VERIFY_CHECK(bits_na_lam <= 130);
bits = bits_na_1; bits = bits_na_1;
@ -296,7 +307,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
} }
#else #else
/* build wnaf representation for na. */ /* build wnaf representation for na. */
bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A);
bits = bits_na; bits = bits_na;
#endif #endif
@ -321,8 +332,8 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
secp256k1_scalar_split_128(&ng_1, &ng_128, ng); secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
/* Build wnaf representation for ng_1 and ng_128 */ /* Build wnaf representation for ng_1 and ng_128 */
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G);
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G);
if (bits_ng_1 > bits) { if (bits_ng_1 > bits) {
bits = bits_ng_1; bits = bits_ng_1;
} }
@ -330,7 +341,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
bits = bits_ng_128; bits = bits_ng_128;
} }
#else #else
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, ng, WINDOW_G); bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G);
if (bits_ng > bits) { if (bits_ng > bits) {
bits = bits_ng; bits = bits_ng;
} }

@ -1374,7 +1374,7 @@ void test_wnaf(const secp256k1_scalar_t *number, int w) {
int bits; int bits;
secp256k1_scalar_set_int(&x, 0); secp256k1_scalar_set_int(&x, 0);
secp256k1_scalar_set_int(&two, 2); secp256k1_scalar_set_int(&two, 2);
bits = secp256k1_ecmult_wnaf(wnaf, number, w); bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w);
CHECK(bits <= 256); CHECK(bits <= 256);
for (i = bits-1; i >= 0; i--) { for (i = bits-1; i >= 0; i--) {
int v = wnaf[i]; int v = wnaf[i];

Loading…
Cancel
Save