mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-12 11:19:08 -05:00
Merge pull request #271
55399c2 Further performance improvements to _ecmult_wnaf (Peter Dettman)
145cc6e
Improve performance of _ecmult_wnaf (Peter Dettman)
This commit is contained in:
commit
bdf0e0c268
3 changed files with 41 additions and 27 deletions
|
@ -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,43 +213,57 @@ 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;
|
||||||
|
|
||||||
|
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) == 0) {
|
if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) {
|
||||||
bit++;
|
bit++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
while (set_bits < bit) {
|
|
||||||
wnaf[set_bits++] = 0;
|
|
||||||
}
|
|
||||||
now = w;
|
now = w;
|
||||||
if (bit + now > 256) {
|
if (now > len - bit) {
|
||||||
now = 256 - bit;
|
now = len - bit;
|
||||||
}
|
|
||||||
word = secp256k1_scalar_get_bits_var(&s, bit, now);
|
|
||||||
if (word & (1 << (w-1))) {
|
|
||||||
secp256k1_scalar_add_bit(&s, bit + w);
|
|
||||||
wnaf[set_bits++] = sign * (word - (1 << w));
|
|
||||||
} else {
|
|
||||||
wnaf[set_bits++] = sign * word;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry;
|
||||||
|
|
||||||
|
carry = (word >> (w-1)) & 1;
|
||||||
|
word -= carry << w;
|
||||||
|
|
||||||
|
wnaf[bit] = sign * word;
|
||||||
|
last_set_bit = bit;
|
||||||
|
|
||||||
bit += now;
|
bit += now;
|
||||||
}
|
}
|
||||||
return set_bits;
|
#ifdef VERIFY
|
||||||
|
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) {
|
||||||
|
@ -272,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;
|
||||||
|
@ -283,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;
|
||||||
|
@ -293,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
|
||||||
|
|
||||||
|
@ -318,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;
|
||||||
}
|
}
|
||||||
|
@ -327,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…
Add table
Reference in a new issue