Add 64-bit integer utilities
This commit is contained in:
parent
119949232a
commit
f7b48c577d
@ -195,6 +195,12 @@ else
|
||||
set_precomp=no
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for __builtin_clzll])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() { __builtin_clzll(1);}]])],
|
||||
[ AC_MSG_RESULT([yes]);AC_DEFINE(HAVE_BUILTIN_CLZLL,1,[Define this symbol if __builtin_clzll is available]) ],
|
||||
[ AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
if test x"$req_asm" = x"auto"; then
|
||||
SECP_64BIT_ASM_CHECK
|
||||
if test x"$has_64bit_asm" = x"yes"; then
|
||||
|
@ -35,4 +35,7 @@ static void secp256k1_rand256_test(unsigned char *b32);
|
||||
/** Generate pseudorandom bytes with long sequences of zero and one bits. */
|
||||
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len);
|
||||
|
||||
/** Generate a pseudorandom 64-bit integer in the range min..max, inclusive. */
|
||||
static int64_t secp256k1_rands64(uint64_t min, uint64_t max);
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille *
|
||||
* Copyright (c) 2013-2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
@ -107,4 +107,21 @@ static void secp256k1_rand256_test(unsigned char *b32) {
|
||||
secp256k1_rand_bytes_test(b32, 32);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int64_t secp256k1_rands64(uint64_t min, uint64_t max) {
|
||||
uint64_t range;
|
||||
uint64_t r;
|
||||
uint64_t clz;
|
||||
VERIFY_CHECK(max >= min);
|
||||
if (max == min) {
|
||||
return min;
|
||||
}
|
||||
range = max - min;
|
||||
clz = secp256k1_clz64_var(range);
|
||||
do {
|
||||
r = ((uint64_t)secp256k1_rand32() << 32) | secp256k1_rand32();
|
||||
r >>= clz;
|
||||
} while (r > range);
|
||||
return min + (int64_t)r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
49
src/tests.c
49
src/tests.c
@ -1,5 +1,5 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Copyright (c) 2013-2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
@ -134,6 +134,52 @@ void random_scalar_order(secp256k1_scalar *num) {
|
||||
} while(1);
|
||||
}
|
||||
|
||||
void run_util_tests(void) {
|
||||
int i;
|
||||
uint64_t r;
|
||||
uint64_t r2;
|
||||
uint64_t r3;
|
||||
int64_t s;
|
||||
CHECK(secp256k1_clz64_var(0) == 64);
|
||||
CHECK(secp256k1_clz64_var(1) == 63);
|
||||
CHECK(secp256k1_clz64_var(2) == 62);
|
||||
CHECK(secp256k1_clz64_var(3) == 62);
|
||||
CHECK(secp256k1_clz64_var(~0ULL) == 0);
|
||||
CHECK(secp256k1_clz64_var((~0ULL) - 1) == 0);
|
||||
CHECK(secp256k1_clz64_var((~0ULL) >> 1) == 1);
|
||||
CHECK(secp256k1_clz64_var((~0ULL) >> 2) == 2);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, INT64_MAX) == 0);
|
||||
CHECK(r == INT64_MAX);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, INT64_MAX - 1) == 0);
|
||||
CHECK(r == INT64_MAX - 1);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, INT64_MIN) == 1);
|
||||
CHECK(r == (uint64_t)INT64_MAX + 1);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, INT64_MIN + 1) == 1);
|
||||
CHECK(r == (uint64_t)INT64_MAX);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, 0) == 0);
|
||||
CHECK(r == 0);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, 1) == 0);
|
||||
CHECK(r == 1);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, -1) == 1);
|
||||
CHECK(r == 1);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, 2) == 0);
|
||||
CHECK(r == 2);
|
||||
CHECK(secp256k1_sign_and_abs64(&r, -2) == 1);
|
||||
CHECK(r == 2);
|
||||
for (i = 0; i < 10; i++) {
|
||||
CHECK(secp256k1_clz64_var((~0ULL) - secp256k1_rand32()) == 0);
|
||||
r = ((uint64_t)secp256k1_rand32() << 32) | secp256k1_rand32();
|
||||
r2 = secp256k1_rands64(0, r);
|
||||
CHECK(r2 <= r);
|
||||
r3 = secp256k1_rands64(r2, r);
|
||||
CHECK((r3 >= r2) && (r3 <= r));
|
||||
r = secp256k1_rands64(0, INT64_MAX);
|
||||
s = (int64_t)r * (secp256k1_rand32()&1?-1:1);
|
||||
CHECK(secp256k1_sign_and_abs64(&r2, s) == (s < 0));
|
||||
CHECK(r2 == r);
|
||||
}
|
||||
}
|
||||
|
||||
void run_context_tests(void) {
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_pubkey zero_pubkey;
|
||||
@ -4463,6 +4509,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
run_rand_bits();
|
||||
run_rand_int();
|
||||
run_util_tests();
|
||||
|
||||
run_sha256_tests();
|
||||
run_hmac_sha256_tests();
|
||||
|
29
src/util.h
29
src/util.h
@ -1,5 +1,5 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Copyright (c) 2013-2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
@ -76,6 +76,33 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Extract the sign of an int64, take the abs and return a uint64, constant time. */
|
||||
SECP256K1_INLINE static int secp256k1_sign_and_abs64(uint64_t *out, int64_t in) {
|
||||
uint64_t mask0, mask1;
|
||||
int ret;
|
||||
ret = in < 0;
|
||||
mask0 = ret + ~((uint64_t)0);
|
||||
mask1 = ~mask0;
|
||||
*out = (uint64_t)in;
|
||||
*out = (*out & mask0) | ((~*out + 1) & mask1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_clz64_var(uint64_t x) {
|
||||
int ret;
|
||||
if (!x) {
|
||||
return 64;
|
||||
}
|
||||
# if defined(HAVE_BUILTIN_CLZLL)
|
||||
ret = __builtin_clzll(x);
|
||||
# else
|
||||
/*FIXME: debruijn fallback. */
|
||||
for (ret = 0; ((x & (1ULL << 63)) == 0); x <<= 1, ret++);
|
||||
# endif
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* Macro for restrict, when available and not in a VERIFY build. */
|
||||
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
||||
# define SECP256K1_RESTRICT
|
||||
|
Loading…
x
Reference in New Issue
Block a user