メインページ | アルファベット順一覧 | 構成 | ファイル一覧 | 構成メンバ | ファイルメンバ | 関連ページ

# dkcSemiRealRandom.c

説明を見る。

    00001
    00010 #include "dkcSemiRealRandom.h"
    00011 #include "dkcOS.h"
    00012 #include "dkcStdio.h"
    00013
    00014 #ifdef _MSC_VER
    00015 #   pragma warning(disable:4055)
    00016 #endif
    00017
    00018
    00019
    00020 #define dkcdSRR_PATH_SIZE (sizeof(wchar_t) * dkcdMAXPATH_BUFFER)
    00021
    00022 typedef
    00023 DWORD (WINAPI *GetTempPathA_FT)(
    00024     DWORD nBufferLength,
    00025     LPSTR lpBuffer
    00026     );
    00027
    00028 typedef
    00029 DWORD (WINAPI *GetTempPathW_FT)(
    00030     DWORD nBufferLength,
    00031     LPWSTR lpBuffer
    00032     );
    00033
    00034
    00035 typedef
    00036 UINT (WINAPI *GetTempFileNameA_FT)(
    00037     LPCSTR lpPathName,
    00038     LPCSTR lpPrefixString,
    00039     UINT uUnique,
    00040     LPSTR lpTempFileName
    00041     );
    00042
    00043 typedef
    00044 UINT (WINAPI *GetTempFileNameW_FT)(
    00045     LPCWSTR lpPathName,
    00046     LPCWSTR lpPrefixString,
    00047     UINT uUnique,
    00048     LPWSTR lpTempFileName
    00049     );
    00050
    00051
    00052 static DKC_INLINE int load_dll(DKC_SEMI_REAL_RANDOM *p,BOOL isNT){
    00053     DKC_DLL *pdll = dkcLoadLibrary("kernel32.dll");
    00054     if(NULL==pdll)
    00055         return edk_FAILED;
    00056
    00057     if(isNT){
    00058         p->fpGetTempFileName =  dkcGetProcAddress(pdll,"GetTempFileNameW");
    00059         p->fpGetTempPath =          dkcGetProcAddress(pdll,"GetTempPathW");
    00060     }else{
    00061         p->fpGetTempFileName = dkcGetProcAddress(pdll,"GetTempFileNameA");
    00062         p->fpGetTempPath =          dkcGetProcAddress(pdll,"GetTempPathA");
    00063     }
    00064     //p->fpQueryPerformanceCounter = dkcGetProcAddress(pdll,"QueryPerformanceCounter");
    00065     dkcmFORCE_NOT_ASSERT(
    00066         p->fpGetTempFileName == NULL ||
    00067         p->fpGetTempPath == NULL
    00068     );
    00069
    00070     p->pDLL = pdll;
    00071     return edk_SUCCEEDED;
    00072 }
    00073
    00074 DKC_SEMI_REAL_RANDOM *WINAPI dkcAllocSemiRealRandomWin32()
    00075 {
    00076     DKC_SEMI_REAL_RANDOM *ptr;
    00077     DKC_GENERIC_FILESYSTEM *pfs;
    00078     BOOL isNT = dkcIsOSNT();
    00079     if(isNT)
    00080     {//Windows NT
    00081         pfs = dkcAlloc_UNICODE_FileSystem();
    00082     }else{
    00083         pfs = dkcAlloc_SJIS_FileSystem();
    00084     }
    00085
    00086     ptr = dkcAllocSemiRealRandomFromGFS(pfs);
    00087     if(NULL==ptr){
    00088         dkcFreeGenericFileSystem(&pfs);
    00089         return NULL;
    00090     }
    00091     //余分に確保しておく･･･
    00092     ptr->pPath = dkcAllocate(dkcdSRR_PATH_SIZE);
    00093     if(NULL==ptr->pPath){
    00094         goto End;
    00095     }
    00096
    00097     if(DKUTIL_FAILED(load_dll(ptr,isNT))){
    00098         goto End;
    00099     }
    00100
    00101     ptr->mIsNT = isNT;
    00102     //successful
    00103     return ptr;
    00104 End:
    00105     dkcFreeSemiRealRandom(&ptr);
    00106     return NULL;
    00107
    00108     /*
    00109     DKC_SEMI_REAL_RANDOM *ptr;
    00110     pfs = dkcAlloc_SJIS_FileSystem();
    00111
    00112     ptr = dkcAllocSemiRealRandomFromGFS(pfs);
    00113     if(NULL==ptr){
    00114         dkcFreeGenericFileSystem(&pfs);
    00115         return NULL;
    00116     }
    00117     //successful
    00118     return ptr;*/
    00119 }
    00120
    00121
    00122 DKC_SEMI_REAL_RANDOM *WINAPI dkcAllocSemiRealRandomFromGFS(DKC_GENERIC_FILESYSTEM *pa)
    00123 {
    00124     DKC_SEMI_REAL_RANDOM *p;
    00125     if(NULL==pa){
    00126         return NULL;
    00127     }
    00128     p = dkcAllocate(sizeof(DKC_SEMI_REAL_RANDOM));
    00129     if(NULL==p){
    00130         return NULL;
    00131     }
    00132     p->mpObj = pa;
    00133     return p;
    00134 }
    00135
    00136
    00137 int WINAPI dkcFreeSemiRealRandom(DKC_SEMI_REAL_RANDOM **pp)
    00138 {
    00139     DKC_SEMI_REAL_RANDOM *p = *pp;
    00140     if(NULL==pp || NULL==p)
    00141         return edk_FAILED;
    00142
    00143     dkcFreeGenericFileSystem(&(p->mpObj));
    00144     return dkcFree(pp);
    00145 }
    00146
    00147 static DKC_INLINE int process(DKC_GENERIC_FILESYSTEM *gfs,const void *filename){
    00148     size_t ws;
    00149     char buff[1];
    00150     int r = dkcGenericFileSystemOpen(gfs,edkcBinaryMode | edkcWriteMode,filename);
    00151     if(DKUTIL_FAILED(r))    return r;
    00152
    00153     dkcGenericFileSystemWrite(gfs,buff,sizeof(buff),&ws);
    00154
    00155     dkcGenericFileSystemClose(gfs);
    00156
    00157     dkcGenericFileSystemDeleteFile(gfs,filename);
    00158     return edk_SUCCEEDED;
    00159 }
    00160
    00161 static BOOL generate(DKC_SEMI_REAL_RANDOM *ptr,uint32 *value32){
    00162 #ifdef WIN32
    00163     DKC_INT64_STRUCT hd;
    00164     uint32 temp;
    00165     QueryPerformanceCounter(&hd);
    00166     temp = hd.u.LowPart;
    00167
    00168     if(DKUTIL_FAILED(process(ptr->mpObj,ptr->pPath))){
    00169         return FALSE;
    00170     }
    00171
    00172     QueryPerformanceCounter(&hd);
    00173     *value32 = (hd.LowPart ^ temp);
    00174     return TRUE;
    00175 #else
    00176
    00177
    00178 #endif
    00179 }
    00180
    00182 static uint32 test(DKC_SEMI_REAL_RANDOM *ptr,size_t test_count,size_t min_,size_t max_)
    00183 {
    00184     uint8 bits[dkcdSEMI_REAL_RANDOM_BITS];
    00185     uint8 prior_bits[dkcdSEMI_REAL_RANDOM_BITS];
    00186     uint32 various[dkcdSEMI_REAL_RANDOM_BITS];
    00187     uint32 val;
    00188     int randRshift,randLshift;
    00189     int i;
    00190     size_t j;
    00191
    00192     memset(various,0,sizeof(uint32) * dkcdSEMI_REAL_RANDOM_BITS);
    00193
    00194     for(j=0;j<test_count;j++)
    00195     {
    00196         if(FALSE==generate(ptr,&val))
    00197             return 0xFFFFFFFF;
    00198
    00199         for(i=0;i<dkcdSEMI_REAL_RANDOM_BITS;i++)
    00200         {
    00201             bits[i]=(uint8)(val & 1);
    00202             val = val >> 1;
    00203             various[i] += ( bits[i] != prior_bits[i] );
    00204             prior_bits[i]=bits[i];
    00205         }
    00206     }
    00207
    00208     randRshift=255;
    00209     randLshift=-1;
    00210     for(i=0;i<dkcdSEMI_REAL_RANDOM_BITS;i++)
    00211     {
    00212         if((various[i]>=min_)&&(various[i]<=max_))
    00213         {
    00214             if(i < randRshift)
    00215                 randRshift=i;
    00216
    00217             if(i >= randLshift)
    00218                 randLshift=i-randRshift+1;
    00219         }
    00220         else break;
    00221     }
    00222     if(randRshift==255) return 0xFFFFFFFF;
    00223     if(randLshift<=0)       return 0xFFFFFFFF;
    00224
    00225     ptr->mLeftShift = randLshift;
    00226     ptr->mRightShift = randRshift;
    00227
    00228     return (uint32)randLshift;
    00229 }
    00230
    00231 int WINAPI dkcSemiRealRandomInit(DKC_SEMI_REAL_RANDOM *ptr)
    00232 {
    00233 #ifdef WIN32
    00234
    00235     GetTempPathA_FT pGTPA;
    00236     //char *pstr;
    00237
    00238     GetTempPathW_FT pGTPW;
    00239     //wchar_t *pwstr;
    00240
    00241     if(ptr->mIsNT){
    00242         pGTPW = (GetTempPathW_FT)ptr->fpGetTempPath;
    00243         dkcmFORCE_NOT_ASSERT(dkcdMAXPATH < pGTPW(0,ptr->pPath));
    00244
    00245         if(pGTPW(dkcdMAXPATH,ptr->pPath)==0)
    00246              return edk_FAILED; //テンポラリファイルフォルダを取得
    00247
    00248         //仮のテンポラリファイル。ちゃんとやるならGetTempFileNameで。
    00249         if(DKUTIL_FAILED(dkc_wcscat2(ptr->pPath,dkcdSRR_PATH_SIZE,dkcdSRR_TEMP_FILE_NAME_W)))
    00250         {
    00251             return edk_FAILED;
    00252         }
    00253
    00254     }else{//Win9x
    00255         pGTPA = (GetTempPathA_FT)ptr->fpGetTempPath;
    00256         dkcmFORCE_NOT_ASSERT(dkcdMAXPATH < pGTPA(0,ptr->pPath));
    00257
    00258         if(pGTPA(dkcdMAXPATH,ptr->pPath)==0)
    00259              return edk_FAILED; //テンポラリファイルフォルダを取得
    00260
    00261         //仮のテンポラリファイル。ちゃんとやるならGetTempFileNameで。
    00262         if(DKUTIL_FAILED(dkc_strcat2(ptr->pPath,dkcdSRR_PATH_SIZE,dkcdSRR_TEMP_FILE_NAME)))
    00263         {
    00264             return edk_FAILED;
    00265         }
    00266     }
    00267     {
    00268         int i;
    00269         for(i=0;i<dkcdSEMI_REAL_RANDOM_TRIAL_AND_ERROR_LIMIT;)//64回も行って成功しないは無いだろう･･･
    00270         {
    00271             if(0xFFFFFFFF==test(ptr,128,40,60)){
    00272                 i++;
    00273             }else{
    00274                 break;
    00275             }
    00276         }
    00277         if(!(i<64))
    00278         {
    00279             return edk_FAILED;
    00280         }
    00281     }
    00282
    00283     return edk_SUCCEEDED;
    00284 #else
    00285
    00286
    00287 #endif
    00288
    00289 }
    00290
    00291
    00292
    00293 BOOL WINAPI dkcSemiRealRandomGet32(DKC_SEMI_REAL_RANDOM *ptr,uint32 *value32)
    00294 {
    00295     uint32 tmp=0;
    00296     uint32 val;
    00297     int totalbit=0;
    00298     size_t i,j;
    00299     for(j=0;j<dkcdSEMI_REAL_RANDOM_TRIAL_AND_ERROR_LIMIT;j++)
    00300     {
    00301         if(FALSE==generate(ptr,&val))
    00302             return FALSE;
    00303
    00304         val = val >> ptr->mRightShift;
    00305         for(i=0;i<ptr->mLeftShift;i++)
    00306         {
    00307             tmp+=val & 1;
    00308             val=val >> 1;
    00309             totalbit++;
    00310             if(totalbit>=32){
    00311                 *value32 = tmp;
    00312                 goto End;
    00313             }
    00314             tmp=tmp<<1;
    00315         }
    00316     }
    00317
    00318 End:
    00319     if(!(j<dkcdSEMI_REAL_RANDOM_TRIAL_AND_ERROR_LIMIT))
    00320     {
    00321         return FALSE;
    00322     }
    00323     return TRUE;
    00324 }
    00325
    00326 uint8 WINAPI dkcSemiRealRandomGet1(DKC_SEMI_REAL_RANDOM *ptr)
    00327 {
    00328 #ifdef WIN32
    00329     uint32 val;
    00330     generate(ptr,&val);
    00331     return (uint8) ( (val >> ptr->mRightShift ) & 1) ;
    00332
    00333 #else
    00334
    00335
    00336 #endif
    00337
    00338
    00339
    00340 }
    00341
    00342
    00343
    00344 #ifdef _MSC_VER
    00345 #   pragma warning(default:4055)
    00346 #endif
    00347