FC2カウンター FPGAの部屋 XORShiftを試してみた3(ビットごとの自己相関を取ってみた)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

XORShiftを試してみた3(ビットごとの自己相関を取ってみた)

XORShiftを試してみた1(XORShift.vhd)”と”XORShiftを試してみた2(M系列、m_seq_32.vh)”で、2,000個の擬似乱数列を取得できたので、それのビットごとの自己相関を取ってみた。
自己相関としては、位相をずらした数列を掛け算して累算(積分)だと思うが、今回はビットごとのランダム性を見たかったので、EXNORして1のビットの数を数えて、1000個分累算してみた。それを1個ずつずらして、1000回行った。
そのためにVisual Studio 2012 Express 無料版をインストールして、Cプログラムを作成した。これが苦労してしまった。いつの間にか、strcpy などは使えなくなっていて、(プロジェクトのプロパティで大丈夫になるのかもしれないが。。。)strcpy_s などを使用する必要があった。しかも、argv も **wchar_t 型になっていて、ワイド文字列からマルチバイト文字列への変換が必要で、かなり時間がかかってしまった。
#いろいろな制限がきつくなりますね。。。

下に、autocorrelation.c を示す。(2012/04/26 修正:累算(積分)幅を変更できるようにCプログラムを変更しました)

// autocorrelation.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <cstring>

#include "stdafx.h"

// 1 になっているビットを数える
int count_bit(unsigned int val){
    int count=0;

    for (int i=0; i<(sizeof(val)*8); i++){
        if (val & 1)
            count++;
        val >>= 1;
    }
    return count;
}

int _tmain(int argc, _TCHAR* argv[])
{
    unsigned int data[2050];
    FILE *wfp, *rfp;
    int i, j, k;
    int retval;
    unsigned int xnor_val;
    int sum;
    char readfile[100], writefile[100], width_num_s[50];
    size_t r_ret_val, w_ret_val, wid_ret_val;
    int width_num;

    if (argc < 3){
        fprintf(stderr, "Usage : autocorrelation  \"width_num\" \"input data file name\" <output file name>\n");
        exit(1);
    } else {
        wcstombs_s(&wid_ret_val, width_num_s, argv[1], sizeof(width_num_s));
        wcstombs_s(&r_ret_val, readfile, argv[2], sizeof(readfile));

        if (argc == 3) // width_num + read file
            strcpy_s(writefile, sizeof(writefile), "autocorre.txt");
        else
            wcstombs_s(&w_ret_val, writefile, argv[3], sizeof(writefile));
    }

    if (fopen_s(&rfp, readfile, "r") != 0){ // 自己相関を取るデータファイルをオープン
        fprintf(stderr, "%s read file open error!\n", readfile);
        exit(1);
    }

    if (fopen_s(&wfp, writefile, "w") != 0){ // 自己相関をとった結果を格納するログファイルをオープン
        fprintf(stderr, "%s write file open error!\n", writefile);
        exit(1);
    }

    sscanf_s(width_num_s, "%d", &width_num, sizeof(int));

    for (i=0; i<2000; i++){ // データの読み込み
        retval = fscanf_s(rfp, "%x\n", &data[i]);
        if (retval == EOF){
            fprintf(stderr, "data read error!\n");
            exit(1);
        }
    }
    fclose(rfp);

    // 最初にwidth_num個(data[0]~data[999])のデータの自分自身とのXNORを取り、1になる数を調べる。この値は32 x width_num 個のはず。
    // 次に、最初にwidth_num個(data[0]~data[width_num-1])と位置を1つずらしたwidth_num個(data[1]~data[width_num])のXNORを取り、1になる数を調べる。
    // これを1000回行う
    for (i=0; i<1000; i++){
        sum = 0;
        for (j=0, k=i; j<width_num; j++, k++){
            xnor_val = ~(data[j] ^ data[k]);
            sum += count_bit(xnor_val);
        }
        fprintf(wfp, "%d\n", sum);
    }
    fclose(wfp);

    return 0;
}



これで、XORShit とM系列の自己相関を取ってみた。
最初にXORShift の自己相関の一部を下に示す。(1000個累算しています)

32000
16123
15910
16084
15946
16009
16083
16089
16003
16016
15959
16042
15934
16067
15982
16091


次に、32ビット長のM系列の自己相関の一部を下に示す。(1000個累算しています)

32000
15606
16306
16102
16306
15980
16337
15816
16480
16831
15360
16765
14963
15764
15700
15600
17163
17070


下に、XORShift の自己相関を1000個累算した時のグラフを示す。
XORShift_3_120426.png

下に、32ビット長のM系列の自己相関を1000個累算した時のグラフを示す。
XORShift_4_120426.png

どうだろうか?32ビット長のM系列に比べて、XORShiftがなだらかなのがわかると思う。積分するといい具合に平均化されている。

下に、XORShift の自己相関を500個累算した時のグラフを示す。
XORShift_5_120426.png

下に、32ビット長のM系列の自己相関を500個累算した時のグラフを示す。
XORShift_6_120426.png

これも同様な傾向がある。

下に、XORShift の自己相関を1個累算した時のグラフを示す。
XORShift_7_120426.png

下に、32ビット長のM系列の自己相関を1個累算した時のグラフを示す。
XORShift_8_120426.png


これは同様にグラフが暴れている。
  1. 2013年04月26日 05:52 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/2450-c9894767
この記事にトラックバックする(FC2ブログユーザー)