/****************************************************************************** Trick Library 'dagger' 乱数生成(RNG)モジュール ヘッダファイル Copyright(C) 2007 Wraith. All rights reserved. Coded by Wraith in Aug 19, 2007. ******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // ■ trickrng.h // http://tricklib.com/cxx/dagger/trickrng.h // // □ 関連ファイル // ありません。このファイルは単体で利用できます。 // // □ ライセンス情報 // http://tricklib.com/license.htm // #ifndef TRICKLIB_RNG_H #define TRICKLIB_RNG_H // // RNG == Random Number Generator // #include /////////////////////////////////////////////////////////////////////////////// // // uint32_t // #if defined(_MSC_VER) namespace tricklib { typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; } #else #include #endif /////////////////////////////////////////////////////////////////////////////// // // secure dice // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) // // windows secure dice // #include "windows.h" #include "wincrypt.h" #if defined(_MSC_VER) #pragma comment(lib, "advapi32.lib") #endif namespace tricklib { class win_secure_dice { public: HCRYPTPROV handle; win_secure_dice() :handle(NULL) { if (!CryptAcquireContext(&handle, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT)) { if (GetLastError() == (DWORD)NTE_BAD_KEYSET) { if (!CryptAcquireContext(&handle, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_NEWKEYSET)) { handle = NULL; } } else { handle = NULL; } } assert(NULL != handle); } ~win_secure_dice() { assert(NULL != handle); if (handle) { CryptReleaseContext(handle, 0); handle = NULL; } } uint32_t roll() { assert(NULL != handle); uint32_t result; CryptGenRandom(handle, sizeof(result), (BYTE*)&result); return result; } }; typedef win_secure_dice secure_dice_type; } #else // // unix secure dice // #include namespace tricklib { class unix_secure_dice { public: FILE *handle; unix_secure_dice(const char *random_filename = "/dev/urandom") :handle(NULL) { assert(NULL != random_filename); handle = fopen(random_filename, "rb"); assert(NULL != handle); } ~unix_secure_dice() { assert(NULL != handle); if (handle) { fclose(handle); handle = NULL; } } uint32_t roll() { assert(NULL != handle); uint32_t result; fread(&result, sizeof(result), 1, handle); return result; } }; typedef unix_secure_dice secure_dice_type; } #endif /////////////////////////////////////////////////////////////////////////////// // // prime spiral // // この prime spiral のアルゴリズムについては以下のページを参照のこと。 // // cf. http://www.trickpalace.net/column/random.htm // namespace tricklib { struct prime_spiral_entropy_pool { enum { prime_a = 7, prime_b = 11, prime_c = 13, prime_d = 17, prime_e = 19, prime_f = 23, prime_g = 29, prime_h = 31, }; enum { master_list_size = prime_a +prime_b +prime_c +prime_d +prime_e +prime_f +prime_g +prime_h, }; union { uint32_t master_list [ prime_a +prime_b +prime_c +prime_d +prime_e +prime_f +prime_g +prime_h ]; struct { uint32_t list_a[prime_a]; uint32_t list_b[prime_b]; uint32_t list_c[prime_c]; uint32_t list_d[prime_d]; uint32_t list_e[prime_e]; uint32_t list_f[prime_f]; uint32_t list_g[prime_g]; uint32_t list_h[prime_h]; }; uint32_t index_mask; }; uint32_t shuffle(uint32_t index) const { assert(0 != master_list[master_list_size -1]); // 偶然最後の要素が 0 になる可能性はわずか 1/2^32 なんで、この assert // に引っかかったとしたらほぼ 100% の確率で、master_list の初期化が // 正しく行われていないです。 const uint32_t i = index_mask ^index; return list_a[i %prime_a] ^ list_b[i %prime_b] ^ list_c[i %prime_c] ^ list_d[i %prime_d] ^ list_e[i %prime_e] ^ list_f[i %prime_f] ^ list_g[i %prime_g] ^ list_h[i %prime_h]; } }; template class prime_spiral_dice_template { public: static const prime_spiral_entropy_pool core; uint32_t index; prime_spiral_dice_template(uint32_t seed = secure_dice_type().roll()) :index(seed) { } uint32_t roll() { return core.shuffle(index++); } }; template const prime_spiral_entropy_pool prime_spiral_dice_template::core = { { // 自前の乱数テーブルを使用したい場合は TRICKLIB_PRIME_SPIRAL_CSV で // 自前の乱数テーブルが格納されているファイルを指定してください。 #if defined(TRICKLIB_PRIME_SPIRAL_CSV) #include TRICKLIB_PRIME_SPIRAL_CSV #else 0x76C05672, 0x36F86B3A, 0x733ED1F6, 0x8CC0F3E0, 0x6B85CF78, 0x74E85131, 0xABB1198B, 0xFDBA37AF, 0x708C5D59, 0xBF10F6DE, 0x13EAA446, 0xFC2441D3, 0x5F39D2B4, 0x8B45596D, 0x4548EF19, 0x71C922EF, 0x1FF69F03, 0xCCAB8D3D, 0x699477BD, 0x96E1C395, 0x5C1DE9EC, 0x65AFD929, 0xE1EC526B, 0xBA8C9727, 0x7AF899A7, 0x84102310, 0x989EAC75, 0x6313F5CC, 0x1D756C57, 0x100FA664, 0xCA179252, 0x7064C987, 0x38C9C832, 0xCFCD0A6A, 0x8E8EE817, 0x476C6117, 0x39D0A31A, 0x04FAB1D7, 0xF5169E21, 0xC69C04AF, 0xF29DA994, 0x3B33085B, 0x8414EC02, 0x0606F44B, 0xB2CBED99, 0xCAC133E0, 0x0FA1948F, 0x3FC8F49F, 0x60B6DF9A, 0xF0E36986, 0xB6463B2A, 0x06713557, 0x8C8576DF, 0x9BA9FD9E, 0x4215BB92, 0x39A92541, 0x92439168, 0xDBED2F27, 0x3FEA4DB8, 0x5DBC70A3, 0xBF5840A9, 0x426655C4, 0xCE607C14, 0x1988E0E4, 0xD3AA0B98, 0x1845CCAE, 0xD1206A30, 0xFA8A6B0D, 0x035EE92B, 0xF5A2E372, 0xD650061C, 0xB15553D6, 0x255F4234, 0xC9B2D551, 0x8B65FBE4, 0xA835DC94, 0x054E8DC1, 0xEE13A812, 0x7EDBF7DE, 0x8BB4637D, 0xD29632F9, 0x51D2B506, 0x759C846F, 0xA5F4E2BA, 0xD67C9C77, 0x5B95DBAF, 0xF8893819, 0x6B282661, 0xC625E4BD, 0x18511502, 0x29F97759, 0x6911EBB8, 0x0680F0D6, 0x4ECC7B26, 0x38938B83, 0xEEF23CE5, 0xA6484DCD, 0x2E19A601, 0xB6CBF9FF, 0x1964A8BC, 0x0E365E51, 0xB06F3CCF, 0xFCD14FD8, 0x9E86A0A6, 0xF72F61E2, 0x5F3DFB60, 0x86BE9C3D, 0xA7F2D45B, 0x1D028693, 0x883BF1EF, 0x1B827B09, 0x4B2276F4, 0xCD43DDBA, 0x3E3036CC, 0xF46C75E4, 0x5CA9756A, 0x473DFA8F, 0xEE18B6D3, 0x5ED4E04F, 0xA0349690, 0x2B011AAC, 0x714CAC57, 0xED79E2CA, 0x5D2E48D4, 0xCBF08D85, 0x399A645C, 0x195A65D2, 0xAC499905, 0xEF0BBF5B, 0xCF5CCF01, 0x809ED064, 0xF404D6B7, 0x127491DC, 0xA5E5C18E, 0x5B35EEDB, 0x21C6977A, 0x81710E2B, 0x4C1394A1, 0x81EBFBD2, 0x2240F094, 0x38B5F17F, 0x1E9D394F, 0x8F4F0E84, 0x8AFED91B, 0x8D993EE4, 0xFD614E66, 0xFC172DE4, 0xCDABA9C3, 0xC7D366DE, 0xD32A400E, #endif } }; typedef prime_spiral_dice_template<> prime_spiral_dice; typedef prime_spiral_dice default_dice_type; #if defined(__BORLANDC__) #pragma warn -8027 #endif class dynamic_prime_spiral_dice :public prime_spiral_entropy_pool, private prime_spiral_dice { // // 動的にエントロピープールを作成するバージョン。 // // 1インスタンスあたりのメモリ消費量が大きく初期化にも時間もかかるが、複数の // インスタンスを作成・利用する場合などにはこちらの利用を推奨。 // public: dynamic_prime_spiral_dice(secure_dice_type &seed_dice = secure_dice_type()) :prime_spiral_dice(seed_dice.roll()) { refresh(seed_dice); } uint32_t roll() { return prime_spiral_entropy_pool::shuffle(prime_spiral_dice::index++); } protected: void refresh(secure_dice_type &seed_dice = secure_dice_type()) { for(int i = 0; i < prime_spiral_entropy_pool::master_list_size; ++i) { prime_spiral_entropy_pool::master_list[i] = seed_dice.roll() ^ prime_spiral_dice::roll(); } } }; #if defined(__BORLANDC__) #pragma warn .8027 #endif } #endif // ndef TRICKLIB_RNG_H /****************************************************************************** □■□■ Wraith the Trickster □■□■ ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ ******************************************************************************/