Add 64-bit integer utilities
This commit is contained in:
parent
e34ceb333b
commit
efc61dc0ca
@ -195,6 +195,12 @@ else
|
|||||||
set_precomp=no
|
set_precomp=no
|
||||||
fi
|
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
|
if test x"$req_asm" = x"auto"; then
|
||||||
SECP_64BIT_ASM_CHECK
|
SECP_64BIT_ASM_CHECK
|
||||||
if test x"$has_64bit_asm" = x"yes"; then
|
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. */
|
/** Generate pseudorandom bytes with long sequences of zero and one bits. */
|
||||||
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len);
|
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 /* SECP256K1_TESTRAND_H */
|
#endif /* SECP256K1_TESTRAND_H */
|
||||||
|
@ -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 *
|
* Distributed under the MIT software license, see the accompanying *
|
||||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
* 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_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 /* SECP256K1_TESTRAND_IMPL_H */
|
#endif /* SECP256K1_TESTRAND_IMPL_H */
|
||||||
|
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 *
|
* Distributed under the MIT software license, see the accompanying *
|
||||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
@ -137,6 +137,52 @@ void random_scalar_order(secp256k1_scalar *num) {
|
|||||||
} while(1);
|
} 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) {
|
void run_context_tests(void) {
|
||||||
secp256k1_pubkey pubkey;
|
secp256k1_pubkey pubkey;
|
||||||
secp256k1_pubkey zero_pubkey;
|
secp256k1_pubkey zero_pubkey;
|
||||||
@ -5021,6 +5067,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
run_rand_bits();
|
run_rand_bits();
|
||||||
run_rand_int();
|
run_rand_int();
|
||||||
|
run_util_tests();
|
||||||
|
|
||||||
run_sha256_tests();
|
run_sha256_tests();
|
||||||
run_hmac_sha256_tests();
|
run_hmac_sha256_tests();
|
||||||
|
28
src/util.h
28
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 *
|
* Distributed under the MIT software license, see the accompanying *
|
||||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
@ -84,6 +84,32 @@ static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void
|
|||||||
return ret;
|
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. */
|
/* Macro for restrict, when available and not in a VERIFY build. */
|
||||||
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
||||||
# define SECP256K1_RESTRICT
|
# define SECP256K1_RESTRICT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user