2006年声優言及数(8)最大値のマッチング

これは簡単。前回bit_pattern()で取得したビットパターンのマッチングをすればいいだけ。列挙したビットパターンに対応する数字を加えて、Cのコードに入れるだけ。ハードコーディング万歳。列挙したビットパターンを対応する数字に変換するには、デバッグも含めてhex->binの変換を実行してチェックすることにします。

use strict;
while(<>){
  print "pattern: $_";
  s/.*\{//;
  s/, \}.*//;
  s/0x//g;
  my @l = map {
    my $str =  unpack("B32", pack("H*", $_));
    $str =~ s/0/ /g;
    $str =~ s/1/\*/g;
    $str;
  } split(/, /);
  print join("\n", @l), "\n";
}

"unpack("B32", pack("H*", $_));"はhex -> 32bit binaryに変換する一番簡単な方法。いちいちビットシフトなんてLLでやることじゃないよね。他のLLにこういうAPIがあるのかは知らないけど・・・。

肝心のパターンマッチ処理はこんな感じ。フラグを使わない手抜きマッチング。bit_patternsの最後には、対応するカウントが入ってます。この配列はint型なので、整数になるように10倍した値を入れてます。1ビットシフト*1とかにしたほうがCPUにはやさしいのかも・・・?

#define BIT_PATTERNS_NUM 10
void get_count_max(graph_area *g)
{
     int bit_patterns[BIT_PATTERNS_NUM][COUNTER_HEIGHT+1] = {
          {0x00000080, 0x00000180, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x000001c0, 10},
          {0x000403c0, 0x000c0200, 0x00040380, 0x00040040, 0x00040040, 0x00043240, 0x000e3180, 15},
          {0x000c0780, 0x00120400, 0x00020700, 0x00040080, 0x00080080, 0x00106480, 0x001e6300, 25},
          {0x000f0000, 0x00080000, 0x000e0000, 0x00010000, 0x00010000, 0x00090000, 0x00060000, 50},
          {0x00086000, 0x00189000, 0x0008b000, 0x0008d000, 0x00089000, 0x00089000, 0x001c6000, 100},
          {0x000cf000, 0x00128000, 0x0002e000, 0x00041000, 0x00081000, 0x00109000, 0x001e6000, 250},
          {0x000f3000, 0x00084800, 0x000e5800, 0x00016800, 0x00014800, 0x00094800, 0x00063000, 500},
          {0x000cf300, 0x00128480, 0x0002e580, 0x00041680, 0x00081480, 0x00109480, 0x001e6300, 2500},
          {0x00086300, 0x00189480, 0x0008b580, 0x0008d680, 0x00089480, 0x00089480, 0x001c6300, 1000},
          {0x000f3180, 0x00084a40, 0x000e5ac0, 0x00016b40, 0x00014a40, 0x00094a40, 0x00063180, 5000},
     };
     int i, j;
     g->count_max = -1.0; /* default value */
     for(i=0; i<BIT_PATTERNS_NUM; i++){
          for(j=0; j<COUNTER_HEIGHT; j++){
               if(g->bit_pattern[j] != bit_patterns[i][j])
                    break;
          }
          if(j == COUNTER_HEIGHT){
               g->count_max = (double)bit_patterns[i][COUNTER_HEIGHT]/10.0;
               break;
          }
     }
     printf("count_max: %.1f\n", g->count_max);
     if(g->count_max == -1.0){
          fprintf(stderr, "error: not mathced count.\n");
          destruct_graph(g);
          exit(EXIT_FAILURE);
     }
}

*1:小数は0.5しかないので