連載:有限状態機およびビットビー(Viterbi)デコーダ(三)


現在,汎用的なステートマシンコーデックと,順方向コード,フィードバックコードに対する具体的なステータスジェネレータがある.テストしてみます.
ファイルは一つだけcpp
まずC++の異なるコンパイラを埋め合わせるために、補助コードを作ります.
#include <stdio.h>
#include <memory>
#include "lsm_viterbi.h"
#include "front_conv_lsmaker.h"
#include "feedback_conv_lsmaker.h"
#include <time.h>
#include <stdlib.h>
using namespace LSMVIT;
using namespace std;
#if defined (_MSC_VER)
#if _MSC_VER <=1600
using namespace std::tr1::placeholders;
#else
using namespace std::placeholders;
#endif
#else
using namespace std::placeholders;
#endif
int bitweight[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
//         
void outputArray(const char * name,int array[], int nLen,int nMaxBytes);

このプログラムは、VS 2010以上、またはGCC 4.6以上(C++0 xまたはC++11スイッチをオンにする)でコンパイル運転することができる.
一度に異なる形式のプレゼンテーションに適したために、テンプレート関数を書いてプレゼンテーションします.
/** \brief          
 *           
 * \param pName const char*      
 * \param pins[][n] int   (  )  ,k*n
 * \param errRate double    , 0~1
 * \param const int * nDelMask = nullptr     ,    1        , codelen  
 * \param const int (* nFeedbackPins)[k] = nullptr       ,k*k,  nullptr       
 * \return void
 *
 */
template <int n, int k, int m, int L /*    */ , int codelen /*      */ >
void demo(
                const char * pName,
                const int pins[/*k*/][n],
                double errRate,
                bool outputViz = false,
                const int * nDelMask = nullptr,/*       codelen*/
                const int (* nFeedbackPins)[k] = nullptr/*       */
                )
{
	puts ("------------------------");
	puts (pName);
	puts ("------------------------");
	putchar ('
'); // const int nRegStatus = (1<<(m*k)),nInStatus = 1<<k; typedef lsm_codec<nRegStatus,nInStatus,n,L> t_lcm_codec; // shared_ptr<t_lcm_codec> pcodec (new t_lcm_codec); // if (nFeedbackPins==nullptr) { // typedef fconv_lsmaker<n,k,m> t_fcmaker; t_fcmaker fc_maker(pins); pcodec->init_status(bind(&t_fcmaker::cb_status,&fc_maker,_1,_2,_3,_4)); } else { // typedef feedback_lsmaker<n,k,m> t_bcmaker; t_bcmaker bc_maker(pins,nFeedbackPins); pcodec->init_status(bind(&t_bcmaker::cb_status,&bc_maker,_1,_2,_3,_4)); } if (outputViz==true) { // , GraphviZ string filename = pName; filename += ".txt"; string strGraph = pcodec->make_graph(); FILE * file = fopen(filename.c_str(),"wb"); if (file) { fwrite(strGraph.c_str(),strGraph.size(),1,file); fclose(file); } } // const int buflen = codelen; int nInputData[buflen], nOutputCode[buflen], nErrorBit[buflen]; int nRecievedCode[buflen], nDecodedData[buflen],nErrGraph[buflen]; // , 0 for (int i=0;i<buflen;i++) nInputData[i] = (i<buflen-m)?rand() % (1<<k):0; outputArray(" ",nInputData,buflen,1); // int nInitStatus = rand() % (nRegStatus); printf (" = %d
",nInitStatus); pcodec->encode(nInputData,buflen,nOutputCode,nInitStatus); outputArray(" ",nOutputCode,buflen,n/4 + n%4==0?0:1); // , 。 int rawerr = 0; for (int i=0;i<buflen;i++) { nErrorBit[i] = 0; for (int j = 0;j<n;j++) nErrorBit[i] |=(i>=m && i<=buflen - m)? (rand() % 100 / 100.0 < errRate ? (1<<j):0):0; for(int j=0;j<n/4+1;j++) rawerr += bitweight[(nErrorBit[i]>>(j*4))&0x0f]; } outputArray(" ",nErrorBit,buflen,n/4 + n%4==0?0:1); printf("
%d , %d bit
",n*buflen,rawerr); printf("
"); // , XOR for (int i=0;i<buflen;i++) nRecievedCode[i] = nOutputCode[i] ^ nErrorBit[i]; outputArray(" ",nRecievedCode,buflen,n/4 + n%4==0?0:1); // , if (nDelMask != nullptr) { for (int i=0;i<buflen;i++) nRecievedCode[i] += (nDelMask[i] << n); outputArray(" ",nRecievedCode,buflen,(2*n/4 + (2*n)%4==0?0:1)); } // pcodec->decode(nRecievedCode, buflen, true); int nPoped = pcodec->pop_data(nDecodedData,buflen); outputArray(" ",nDecodedData,nPoped,n/4 + n%4==0?0:1); int err = 0; for (int i=0;i<nPoped;i++) { nErrGraph[i] = (nDecodedData[i]^nInputData[i]); for(int j=0;j<n/4+1;j++) err += bitweight[(nErrGraph[i]>>(j*4))&0x0f]; } printf(" %d bit
",err); if (err) outputArray(" ",nErrGraph,nPoped,n/4 + n%4==0?0:1); putchar('
'); putchar('
'); }

これでメインは簡単です
int main (int argc, char * argv[])
{
	srand((unsigned int)time(0));
	const int datalen = 256;
	/*
	2,1,3  
	-[]-[]-[]-+
	1  0  1  1
	1  1  1  1
	*/
    	int nPins213 [1][2] = {{13,17}};
    	demo<2,1,3,32,datalen>("213   ",nPins213,1e-3,true);
	/*
	4 , 1 , 6  ,     
	-[]-[]-[]-[]-[]-[]-+
        1  0  1  1  0  1   1 -> 0
	1  1  0  1  0  0   1 -> 1
	1  1  0  0  1  1   1 -> 2
	1  1  1  1  0  0   1 -> 3
	*/
	int pins416 [1][4] = {{133,151,147,171}};
	demo<4,1,6,64,datalen>("416   ",pins416,1e-1);

	/*
	3 , 2 , 4    ,       
    	0-[]-[]-[]-[]-+    1-[]-[]-[]-[]-+
	 1  0  0  0  0      0  0  0  0  0
	 1  0  0  1  1      1  1  1  0  1
	 0  0  0  0  0      1  0  0  0  0
	     ,       ,         :
    	 0-[]-[]-[]-[]-+    1-[]-[]-[]-[]-+
     	 0  1  1  0  1      0  1  0  0  1
     	 0  1  0  1  1      0  1  1  1  1
    	*/
	int pins324 [2][3] = {{20,23,0},{0,35,20}};
	int feedbackpin[2][2] = {{15, 13},{11,17}};
    	demo<3,2,4,64,datalen>("324          ",pins324,1e-4,false,nullptr,feedbackpin);

 	/*
 		3/4 2 , 1 , 6   
 	*/
	int pins216 [1][2] = {{133,171}};
	int nDelMask [datalen];
	for (int i=0;i<datalen;i++)
		nDelMask[i] = (i%3);
	demo<2,1,6,50,datalen>("216     ",pins216,1e-4,false,nDelMask);
	return 0;
}

出力結果の関数
void outputArray(const char * name,int array[], int nLen,int nMaxBytes)
{
	printf ("
%s:
",name); int pc = 0; int ps = 80 / (nMaxBytes * 8+1); char pMask[] = "0123456789ABCDEF"; for (int i=0;i<nLen;i++) { if (array[i]==0) { for (int j=1;j<nMaxBytes;j++) putchar (' '); putchar ('0'); } else for (int j=0;j<nMaxBytes;j++) putchar (pMask[(array[i]>>(4*(nMaxBytes - 1 - j))) & 0x0f]); if ((i+1)%8==0) { pc ++; if (pc >= ps) { pc = 0; putchar ('
' ); } else putchar (' ' ); } } putchar ('
' ); }

 
さあ、運転してもいいですよ.
 
------------------------
416   
------------------------


  :
01001111 10100001 01011011 11011110 00101010 11001100 01110010 11001010
10111011 01010001 11001110 11000100 11101000 00000000 01100001 11011111
00000100 10011010 11100101 10011110 01100010 10101010 00111000 10110111
10000011 00010000 11100100 11100100 10000000 00000011 00111101 10000000

   = 63

   :
4CDE75B3 EBCDE8D5 86A4F318 99E3269E CA829A40 BF3EF0BB F7DE36A0 3ACEFF35
40BFC96D 9E7EF472 2E36AF4C 9D910726 2ABC92E8 DAF00000 0F8E4F8A 7139D691
B3A75079 253DA448 E0C99A03 ACEF0431 C5FBBF72 9A40B0B0 4722E365 8295C189
9ECA7508 E4F726D2 57136A0C DABC6A0C D5322AF0 000000F8 E4004313 291085F0


    :
00000080 00802880 00021000 00080438 08002228 10000070 12100640 45603000
00200000 00010034 52088002 04004010 20001800 0C682444 088012A0 00986000
10401082 00000300 20000000 01800000 01000400 00000001 21010802 20210008
35000005 9602C04A 01080010 E0000400 0A102080 00880940 00800C00 00000000


  1024    ,  129 bit     


       :
4CDE7533 EB4DC055 86A6E318 99EB22A6 C282B868 AF3EF0CB E5CE30E0 7FAECF35
409FC96D 9E7FF446 7C3E2F4E 99914736 0ABC8AE8 D6982444 070E5D2A 71A1B691
A3E740FB 253DA748 C0C99A03 AD6F0431 C4FBBB72 9A40B0B1 6623EB67 A2B4C181
ABCA750D 72F5E698 561B6A1C 3ABC6E0C DF220A70 008809B8 E4804F13 291085F0


    :
01001111 10100001 01011011 11011110 00101010 11001100 01110010 11001010
10111011 01010001 11001110 11000100 11101000 00000000 01100001 11011111
00000100 10011010 11100101 10011110 01100010 10101010 00111000 10110111
10000011 00010000 11100100 11100100 10000000 00000011 00111101 10000000

      0 bit