Add 64-bit integer utilities
This commit is contained in:
		
							parent
							
								
									e541a90ef6
								
							
						
					
					
						commit
						e1fb4af90b
					
				| @ -230,6 +230,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 /* 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   * | ||||
|  * 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 /* 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   * | ||||
|  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 | ||||
|  **********************************************************************/ | ||||
| @ -140,6 +140,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(int use_prealloc) { | ||||
|     secp256k1_pubkey pubkey; | ||||
|     secp256k1_pubkey zero_pubkey; | ||||
| @ -5223,6 +5269,7 @@ int main(int argc, char **argv) { | ||||
| 
 | ||||
|     run_rand_bits(); | ||||
|     run_rand_int(); | ||||
|     run_util_tests(); | ||||
| 
 | ||||
|     run_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   * | ||||
|  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 | ||||
|  **********************************************************************/ | ||||
| @ -125,6 +125,32 @@ static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_siz | ||||
|     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