/****************************************************************** Random numbers and hashing (c) 1994, 1995 Innobase Oy Created 5/30/1994 Heikki Tuuri *******************************************************************/ #define UT_HASH_RANDOM_MASK 1463735687 #define UT_HASH_RANDOM_MASK2 1653893711 #define UT_RND1 151117737 #define UT_RND2 119785373 #define UT_RND3 85689495 #define UT_RND4 76595339 #define UT_SUM_RND2 98781234 #define UT_SUM_RND3 126792457 #define UT_SUM_RND4 63498502 #define UT_XOR_RND1 187678878 #define UT_XOR_RND2 143537923 extern ulint ut_rnd_ulint_counter; /************************************************************ This is used to set the random number seed. */ UNIV_INLINE void ut_rnd_set_seed( /*============*/ ulint seed) /* in: seed */ { ut_rnd_ulint_counter = seed; } /************************************************************ The following function generates a series of 'random' ulint integers. */ UNIV_INLINE ulint ut_rnd_gen_next_ulint( /*==================*/ /* out: the next 'random' number */ ulint rnd) /* in: the previous random number value */ { ulint n_bits; n_bits = 8 * sizeof(ulint); rnd = UT_RND2 * rnd + UT_SUM_RND3; rnd = UT_XOR_RND1 ^ rnd; rnd = (rnd << 20) + (rnd >> (n_bits - 20)); rnd = UT_RND3 * rnd + UT_SUM_RND4; rnd = UT_XOR_RND2 ^ rnd; rnd = (rnd << 20) + (rnd >> (n_bits - 20)); rnd = UT_RND1 * rnd + UT_SUM_RND2; return(rnd); } /************************************************************ The following function generates 'random' ulint integers which enumerate the value space of ulint integers in a pseudo random fashion. Note that the same integer is repeated always after 2 to power 32 calls to the generator (if ulint is 32-bit). */ UNIV_INLINE ulint ut_rnd_gen_ulint(void) /*==================*/ /* out: the 'random' number */ { ulint rnd; ulint n_bits; n_bits = 8 * sizeof(ulint); ut_rnd_ulint_counter = UT_RND1 * ut_rnd_ulint_counter + UT_RND2; rnd = ut_rnd_gen_next_ulint(ut_rnd_ulint_counter); return(rnd); } /************************************************************ Generates a random integer from a given interval. */ UNIV_INLINE ulint ut_rnd_interval( /*============*/ /* out: the 'random' number */ ulint low, /* in: low limit; can generate also this value */ ulint high) /* in: high limit; can generate also this value */ { ulint rnd; ut_ad(high >= low); if (low == high) { return(low); } rnd = ut_rnd_gen_ulint(); return(low + (rnd % (high - low + 1))); } /************************************************************* Generates a random iboolean value. */ UNIV_INLINE ibool ut_rnd_gen_ibool(void) /*=================*/ /* out: the random value */ { ulint x; x = ut_rnd_gen_ulint(); if (((x >> 20) + (x >> 15)) & 1) { return(TRUE); } return(FALSE); } /*********************************************************** The following function generates a hash value for a ulint integer to a hash table of size table_size, which should be a prime or some random number for the hash table to work reliably. */ UNIV_INLINE ulint ut_hash_ulint( /*=========*/ /* out: hash value */ ulint key, /* in: value to be hashed */ ulint table_size) /* in: hash table size */ { key = key ^ UT_HASH_RANDOM_MASK2; return(key % table_size); } /***************************************************************** Folds a pair of ulints. */ UNIV_INLINE ulint ut_fold_ulint_pair( /*===============*/ /* out: folded value */ ulint n1, /* in: ulint */ ulint n2) /* in: ulint */ { return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1) ^ UT_HASH_RANDOM_MASK) + n2); } /***************************************************************** Folds a dulint. */ UNIV_INLINE ulint ut_fold_dulint( /*===========*/ /* out: folded value */ dulint d) /* in: dulint */ { return(ut_fold_ulint_pair(ut_dulint_get_low(d), ut_dulint_get_high(d))); } /***************************************************************** Folds a character string ending in the null character. */ UNIV_INLINE ulint ut_fold_string( /*===========*/ /* out: folded value */ const char* str) /* in: null-terminated string */ { #ifdef UNIV_DEBUG ulint i = 0; #endif ulint fold = 0; ut_ad(str); while (*str != '\0') { #ifdef UNIV_DEBUG i++; ut_a(i < 100); #endif fold = ut_fold_ulint_pair(fold, (ulint)(*str)); str++; } return(fold); } /***************************************************************** Folds a binary string. */ UNIV_INLINE ulint ut_fold_binary( /*===========*/ /* out: folded value */ const byte* str, /* in: string of bytes */ ulint len) /* in: length */ { ulint i; ulint fold = 0; ut_ad(str); for (i = 0; i < len; i++) { fold = ut_fold_ulint_pair(fold, (ulint)(*str)); str++; } return(fold); }