OSDN Git Service

Fix warning message on extracting symlink.
[lha/lha.git] / Hacking_of_LHa
index f07bb52..a98a501 100644 (file)
 $Id$
 
 $Id$
 
-               The Hacking of LHa for UNIX (2nd draft)
+               The Hacking of LHa for UNIX (3rd draft)
              -------------------------------------------
 
                                 Koji Arai <arai@users.sourceforge.jp>
 
              -------------------------------------------
 
                                 Koji Arai <arai@users.sourceforge.jp>
 
-Ëܽñ¤Ï¡¢LHa for UNIX 1.14i ¤Î¥½¡¼¥¹¤ò²òÆɤ·¡¢¤½¤Î°µ½Ì¥¢¥ë¥´¥ê¥º¥à¤Î¼Â
-Áõ¤ò³Îǧ¤¹¤ë¤¿¤á¤Î¤â¤Î¤À¡£¤³¤ÎÀ®²Ì¤ÏÊ̤ηÁ¤Ç¤Þ¤È¤á¤Ê¤ª¤µ¤ì»ñÎÁ¤Ë¤Ê¤ë¤«
-¤â¤·¤ì¤Ê¤¤¤·¡¢¤³¤Î¤Þ¤Þ¤Î·Á¤ÇÊݴɤµ¤ì¤ë¤«¤â¤·¤ì¤Ê¤¤¤·¡¢¿·¤¿¤Ë¥½¡¼¥¹¤ò½ñ
-¤­µ¯¤³¤¹¸µ¤Ë¤Ê¤ë¤«¤â¤·¤ì¤Ê¤¤¡£¤È¤Ë¤«¤¯¡¢²Ë¤ÊÀµ·îµÙ¤ß¤òÄÙ¤¹¤¿¤á¤Ë¤ä¤Ã¤Æ
-¤ß¤¿¤À¤±¤Î¤â¤Î¤À¡£(µÙ¤ß¤¬ÌÀ¤±¤ë¤È¤Þ¤¿Ë»¤·¤¯¤Ê¤ë¤Î¤Ç¡¢¤³¤ì°Ê¾å¤Þ¤Ã¤¿¤¯
-²¿¤â¤·¤Ê¤¤¤«¤â¤·¤ì¤Ê¤¤)
-
-Ëܽñ¤Ï¡¢¤Þ¤À̤´°À®¤Ç¤¢¤ë¡£¤Ë¤â¤«¤«¤ï¤é¤º¸ø³«¤¹¤ë¤Î¤Ï¤³¤ì°Ê¾å³¤«¤Ê¤¤¤«
-¤â¤·¤ì¤Ê¤¤¤«¤é¤Ç¤¢¤ë(µ¤¤¬¸þ¤¤¤¿¤é¤Þ¤¿Â³¤­¤ò½ñ¤¯¤À¤í¤¦¡£¤¢¤ë¤¤¤Ï±þ±ç¤Î
-¤ª¼ê»æ¤¬¤¯¤ì¤Ð¤ä¤ëµ¤¤¬½Ð¤ë¤«¤â¤·¤ì¤Ê¤¤)¡£
-
-Ëܽñ¤Ï¥Õ¥ê¡¼¤Ç¤¢¤ë¡£Ê£À½¡¢²þÊÑ¡¢ºÆÇÛÉۤϼ«Í³¤Ç¤¢¤ë¤È¤¤¤¦¤³¤È¤À¡£¤¿¤À¤·
-Ëܽñ¤Ë¤è¤êÀ¸¤¸¤¿¤¢¤é¤æ¤ë»³²¡¢ÉÔÍø±×¤ËÂФ·¤Æ¤Ï°ìÀÚ¤ÎÊݾڤϤʤ¤¡£Ëܽñ¤Ë
-¤Ï±³¤¬¤¢¤ë¤«¤â¤·¤ì¤Ê¤¤¡£¤½¤ì¤ËÂФ·¤Æ±³¤ò¶µ¤¨¤é¤ì¤¿¤ÈÃø¼Ô¤òÈòÆñ¤ò¤·¤Ê¤¤
-¤Ç夭¤¿¤¤¡£¤·¤«¤·´Ö°ã¤¤¤Î»ØŦ¤Ï¹½¤ï¤Ê¤¤(¤¼¤Ò¤ª´ê¤¤¤·¤¿¤¤)¡¢Ãø¼Ô¤Ï°µ½Ì
-½èÍý¤Ë´Ø¤·¤Æ¤Ï̵ÃΤǤ¢¤ë¡£ÍѸì¤Î»È¤¤ÊýÅù¤ÏŬÀڤǤʤ¤¤«¤â¤·¤ì¤Ê¤¤¤Î¤Ç¤³
-¤ÎÊýÌ̤Ǥâ¸æ»ØƳ失¤ì¤Ð¹¬¤¤¤Ç¤¢¤ë¡£
+本書は、LHa for UNIX 1.14i のソースを解読し、その圧縮アルゴリズムの実
+装を確認するためのものだ。この成果は別の形でまとめなおされ資料になるか
+もしれないし、このままの形で保管されるかもしれないし、新たにソースを書
+き起こす元になるかもしれない。とにかく、暇な正月休みを潰すためにやって
+みただけのものだ。(休みが明けるとまた忙しくなるので、これ以上まったく
+何もしないかもしれない)
+
+本書は、まだ未完成である。にもかかわらず公開するのはこれ以上続かないか
+もしれないからである(気が向いたらまた続きを書くだろう。あるいは応援の
+お手紙がくればやる気が出るかもしれない)。
+
+本書はフリーである。複製、改変、再配布は自由であるということだ。ただし
+本書により生じたあらゆる損害、不利益に対しては一切の保証はない。本書に
+は嘘があるかもしれない。それに対して嘘を教えられたと著者を避難をしない
+で頂きたい。しかし間違いの指摘は構わない(ぜひお願いしたい)、著者は圧縮
+処理に関しては無知である。用語の使い方等は適切でないかもしれないのでこ
+の方面でも御指導頂ければ幸いである。
+
+< 目次 >
+
+表記について
+slide 辞書法 (slide.c)
+bit 入出力ルーチン (crcio.c)
+Huffman 法 (huf.c)
+LHA ファイルの構造(まとめ)
+セキュリティバグの考察
 
 ===============================================================================
 
 ===============================================================================
-o É½µ­¤Ë¤Ä¤¤¤Æ
+表記について
 
 
-* ´Ø¿ô¤Ï¡¢¤½¤ÎÄêµÁ¥½¡¼¥¹ file.c ¤È´Ø¿ô̾ func() ¤ò¼¨¤¹¤Î¤Ë
+* 関数は、その定義ソース file.c と関数名 func() を示すのに
      file.c:func()
      file.c:func()
-  ¤È¤¤¤¦µ­½Ò¤ò»È¤¦
+  という記述を使う
 
 
-* ÇÛÎó¤Îź»ú¤Ï¡¢Python¸À¸ì¤Î¥¹¥é¥¤¥¹±é»»»Ò¤Îµ­Ë¡¤Ë½à¤¸¤¿
+* 配列の添字は、Python言語のスライス演算子の記法に準じた
 
 
-    a[m:n] ¤Ï¡¢m <= i < m+n ¤ÎÈϰϤΠa[i] ¤ò°ÕÌ£¤¹¤ë¡£
+    a[m:n] は、m <= i < m+n の範囲の a[i] を意味する。
 
 
-* ÃͤÎÈϰϤϡ¢Ruby¸À¸ì¤ÎÈϰϱ黻»Ò¤Îµ­Ë¡¤Ë½à¤¸¤¿¡£¤³¤ì¤òÇÛÎó¤Î
-  Åº»ú¤Ë»ÈÍѤ¹¤ë¾ì¹ç¤â¤¢¤ë¡£
+* 値の範囲は、Ruby言語の範囲演算子の記法に準じた。これを配列の
+  添字に使用する場合もある。
 
     m <= i <= n   -> i = m..n
     m <= i < n    -> i = m...n
 
 
     m <= i <= n   -> i = m..n
     m <= i < n    -> i = m...n
 
-    a[m..n] ¤Ï¡¢m <= i <= n ¤ÎÈϰϤΠa[i] ¤ò°ÕÌ£¤¹¤ë¡£
+    a[m..n] は、m <= i <= n の範囲の a[i] を意味する。
 
 
-* m ¤Î n ¾è ¤Ï¡¢m^n ¤Çɽ¤¹¡£^ ¤Ï¡¢ÇÓ¾ŪÏÀÍýϤȤ·¤Æ¤âÍøÍѤµ¤ì¤ë¤¬
-  Ê¸Ì®¤«¤éȽÃǤ·¤Æ¤â¤é¤¦¡£
+* m の n 乗 は、m^n で表す。^ は、排他的論理和としても利用されるが
+  文脈から判断してもらう。
 
 
-* v{n} ¤Ï¡¢ÊÑ¿ô v ¤ÎÃͤ¬ n ¤Ç¤¢¤ë¤³¤È¤òɽ¤¹¡£n ¤Ï¡¢¥µ¥ó¥×¥ë¤ÎÃͤǤ¢¤Ã¤¿¤ê
-  Äê¿ô¤ÎÃͤǤ¢¤Ã¤¿¤ê¤¹¤ë¡£
+* v{n} は、変数 v の値が n であることを表す。n は、サンプルの値であったり
+  定数の値であったりする。
 
 
-  v=n ¤ÏÂåÆþʸ
+  v=n は代入文
 
 
-  ÇÛÎó¤ÎÆâÍƤϡ¢
+  配列の内容は、
     ary[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }
     ary[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }
-  ¤Î¤è¤¦¤Ë½ñ¤¯
+  のように書く
 
 
-o ÍѸì¤Ë¤Ä¤¤¤Æ
+o 用語について
 
 
-* Éä¹æ
-        Éä¹æ²½¡¢Éä¹æ¸ì¡¢°µ½Ìʸ
+* 符号
+        符号化、符号語、圧縮文
 
 
-        Éä¹æ¸ì¤Ï¡¢1¤Ä¤Îʸ»ú¤òÉä¹æ²½¤·¤¿·ë²Ì¡£°µ½Ìʸ¤ÏÉä¹æ¸ì¤Îʤӡ£
+        符号語は、1つの文字を符号化した結果。圧縮文は符号語の並び。
 
 
-* Éü¹æ
-        Éü¹æ²½¡¢Éü¹æ¸ì¡¢Éü¹æʸ
+* 復号
+        復号化、復号語、復号文
 
 
-        Éü¹æ¸ì¤Ï¡¢°µ½Ìʸ¤«¤é1¤Ä¤Îʸ»ú¤òÉü¹æ²½¤·¤¿·ë²Ì¡£Éü¹æʸ¤ÏÉü¹æ¸ì¤Îʤӡ£
+        復号語は、圧縮文から1つの文字を復号化した結果。復号文は復号語の並び。
 
 
-* ʿʸ
-        °µ½ÌÁ°¤Îʸ¤ò¼¨¤¹¡£ÂФ·¤ÆÉü¹æʸ¤Ï¡¢Éü¹æ¤·¤¿¸å¤Îʸ¤ò°ÕÌ£¤¹¤ë¡£
+* 平文
+        圧縮前の文を示す。対して復号文は、復号した後の文を意味する。
 
 
-* slide ¼­½ñË¡
+* slide 辞書法
 
 
-* Huffman ˡ
-   Æ°Åª Huffman Ë¡¡¢ÀÅŪ Huffman Ë¡
+* Huffman 
+   動的 Huffman 法、静的 Huffman 法
 
 ===============================================================================
 
 \f
 
 ===============================================================================
 
 \f
-slide ¼­½ñË¡ (slide.c)
+slide 辞書法 (slide.c)
 ----------------------
 
 ----------------------
 
-¤Þ¤º¡¢¹½Â¤¤Ë¤Ä¤¤¤Æ¹Í¤¨¤ë¡£
+まず、構造について考える。
 
 
-slide¼­½ñË¡¤Ï¡¢encoding ¤Ë¤µ¤Þ¤¶¤Þ¤Ê¹©Éפ¬¶Å¤é¤µ¤ì¤ë¤Î¤Ç¤È¤Æ¤âÊ£»¨¤À¤¬¡¢
-ÉáÄÌ decoding ¤Ïñ½ã¤Ç¤¢¤ë¡£decoding ¤ò²òÀϤ¹¤ë¤³¤È¤Ç¤É¤Î¤è¤¦¤Ê°µ½Ìʸ
-¤òºî¤Ã¤Æ¤¤¤ë¤Î¤«¤òÄ´¤Ù¤Æ¤ß¤ë¡£
+slide辞書法は、encoding にさまざまな工夫が凝らされるのでとても複雑だが、
+普通 decoding は単純である。decoding を解析することでどのような圧縮文
+を作っているのかを調べてみる。
 
 
-decoding ¤ò¹Ô¤¦½èÍý¤Ï¡¢slide.c ¤Î decode() ¤Ç¤¢¤ë¡£¤³¤Î½èÍý¤ò¸«¤Æ¤ß¤ë
-¤È»×¤Ã¤¿Ä̤ê´Êñ¤Ë²òÆɤǤ­¤¿(°Ê²¼)
+decoding を行う処理は、slide.c の decode() である。この処理を見てみる
+と思った通り簡単に解読できた(以下)
 
 
-  1. huffman coding ¤Ë¤è¤êÉü¹æ¤·¤¿Ê¸»ú¤ò´Ä¾õ¥Ð¥Ã¥Õ¥¡ dtext ¤Ë½ñ¤­¹þ¤à
-     Ä̾ï¤Îʸ»ú c ¤Ï¡¢c < 256 ¤Çɽ¸½¤µ¤ì¤Æ¤¤¤ë(¤Ä¤Þ¤ê¤½¤Î¤Þ¤Þ)
+  1. huffman coding により復号した文字を環状バッファ dtext に書き込む
+     通常の文字 c は、c < 256 で表現されている(つまりそのまま)
 
 
-  2. Ä̾ï¤Îʸ»ú¤Ç¤Ê¤¤¤â¤Î¤¬¸½¤ì¤¿¤é¡¢¤½¤ì¤ÏŤµ¤Ç¤¢¤ë¡£Ä¹¤µ len ¤Ï¡¢
-     len > 255 ¤Çɽ¸½¤µ¤ì¤Æ¤¤¤ë¡£len ¤«¤é 0xfd(253) ¤ò°ú¤¤¤¿Ãͤ¬
-     ¼ÂºÝ¤ÎŤµ¤òɽ¤¹(-lzs- method ¤Î¾ì¹ç¤Ï¡¢0xfe(254)¤ò°ú¤¯)
-    ¡ÖŤµ¡×¤¬¡¢¸½¤ì¤¿¤é¤½¤Îľ¸å¤Ë¤Ï¡Ö°ÌÃ֡פ¬½ñ¤«¤ì¤Æ¤¤¤ë¤Î¤Ç¤½¤ì¤ò
-     Æɤࡣ¤³¤¦¤·¤Æ¡¢Ä¹¤µ¤È°ÌÃ֤Υڥ¢<len, pt>¤òÆÀ¤ë
+  2. 通常の文字でないものが現れたら、それは長さである。長さ len は、
+     len > 255 で表現されている。len から 0xfd(253) を引いた値が
+     実際の長さを表す(-lzs- method の場合は、0xfe(254)を引く)
+    「長さ」が、現れたらその直後には「位置」が書かれているのでそれを
+     読む。こうして、長さと位置のペア<len, pt>を得る
 
 
-     dtext ¤«¤é pt+1 ¥Ð¥¤¥ÈÁ°¤Î len ¥Ð¥¤¥È¤òÆɤߡ¢dtext ¤ËÄɲäǽñ¤­¹þ¤à
+     dtext から pt+1 バイト前の len バイトを読み、dtext に追加で書き込む
 
 
-   3. dtext ¤¬°ìÇÕ(dicsiz)¤Ë¤Ê¤Ã¤¿¤é¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹
+   3. dtext が一杯(dicsiz)になったらファイルに書き出す
 
 
-¤³¤ì¤Î·«¤êÊÖ¤·¤Ç¤¢¤ë¡£¤Ä¤Þ¤ê¡¢slide ¼­½ñË¡¤Î°µ½Ìʸ¤Ï¡¢Ê¸»ú c ¤È<len,
-pt> ¤ÎʤӤǤ¢¤ë¤³¤È¤¬¤ï¤«¤ë¡£Î㤨¤Ð¡¢Ê¸»úÎó c1 c2 c1 c2 ¤Ï¡¢°Ê²¼¤Î¤è
-¤¦¤Ëɽ¸½¤µ¤ì¤Æ¤¤¤ë¤Ï¤º¤Ç¤¢¤ë¡£(ËÜÅö¤Ï¡¢Ä¹¤µ¤¬ 2 °Ê²¼¤Ç¤Ï°µ½Ì¤¬µ¯¤³¤é¤Ê
-¤¤¤Î¤Çʿʸ¤Î¤Þ¤Þ½ÐÎϤ¹¤ë¡£Ä¹¤µ¤ÏºÇÄã¤Ç¤â 3 ¤ÏɬÍ×)
+これの繰り返しである。つまり、slide 辞書法の圧縮文は、文字 c と<len,
+pt> の並びであることがわかる。例えば、文字列 c1 c2 c1 c2 は、以下のよ
+うに表現されているはずである。(本当は、長さが 2 以下では圧縮が起こらな
+いので平文のまま出力する。長さは最低でも 3 は必要)
 
         +----+----+--------+
         | c1 | c2 | <2, 1> |
         +----+----+--------+
 
 
         +----+----+--------+
         | c1 | c2 | <2, 1> |
         +----+----+--------+
 
-¤Ç¤Ï¡¢¤³¤Î¹½Â¤¤òºîÀ®¤¹¤ë°µ½Ì½èÍý¤Ë¤Ä¤¤¤Æ¹Í¤¨¤ë¡£slide ¼­½ñË¡¤Ç¤Ï¡¢¥Õ¥¡
-¥¤¥ë¤«¤éÆɤ߹þ¤ó¤Àʸ»úÎó token ¤¬¡¢°ÊÁ°¤ËÆɤ߹þ¤ó¤À¼­½ñ¤Ë¸ºß¤¹¤ì¤Ð
-<len, pt> ¤Î¥Ú¥¢¤ò½ÐÎϤ·¡¢Â¸ºß¤·¤Ê¤±¤ì¤Ð token ¤ò¤½¤Î¤Þ¤Þ½ÐÎϤ¹¤ë¡£ÆÉ
-¤ß¹þ¤ó¤À token ¤Ï¡¢¼­½ñ¤ËÄɲä·¡¢¼­½ñ¤Î¸ì¤¬°î¤ì¤¿¤é¸Å¤¤¾ðÊó¤ò¼Î¤Æ¤ë¡£
+ã\81§ã\81¯ã\80\81ã\81\93ã\81®æ§\8bé\80 ã\82\92ä½\9cæ\88\90ã\81\99ã\82\8bå\9c§ç¸®å\87¦ç\90\86ã\81«ã\81¤ã\81\84ã\81¦è\80\83ã\81\88ã\82\8bã\80\82slide è¾\9eæ\9b¸æ³\95ã\81§ã\81¯ã\80\81ã\83\95ã\82¡
+イルから読み込んだ文字列 token が、以前に読み込んだ辞書に存在すれば
+<len, pt> のペアを出力し、存在しなければ token をそのまま出力する。読
+み込んだ token は、辞書に追加し、辞書の語が溢れたら古い情報を捨てる。
 
 
-²¿¤âͽÈ÷Ã챤¬¤Ê¤¤¾õÂ֤ǽñ¤±¤Ð
+何も予備知識がない状態で書けば
 
         while (read_file(&token, tokensiz)) {
           len = search_dict(dict, token, &pt);
 
         while (read_file(&token, tokensiz)) {
           len = search_dict(dict, token, &pt);
@@ -127,32 +136,32 @@ pt> 
           update_dict(dict, token);
         }
 
           update_dict(dict, token);
         }
 
-¤Î¤è¤¦¤Ë¤Ê¤ë¤Ï¤º¡£¤³¤³¤Ç¡¢tokensiz ¤Ï token ¤ÎºÇÂ祵¥¤¥º¤Ç¡¢ºÇĹ°ìÃ×Ĺ
-¤òɽ¤¹¡£¤³¤ÎÃͤ¬Â礭¤±¤ì¤ÐÂ礭¤¤Äø¡¢°µ½Ì¸úΨ¤ÏÎɤ¯¤Ê¤ë¤Ï¤º¤Ç¡¢lha ¤Ç¤Ï¡¢
-¤³¤ì¤Ï MAXMATCH{256}¤Ç¤¢¤ë¡£¤Þ¤¿¡¢dict ¤Ï¼­½ñ¤Ç¤³¤Î¥µ¥¤¥º¤Ï lha ¤Î 
--lh5- ¥á¥½¥Ã¥É¤Ç¤Ï¡¢8192 ¤È¤Ê¤Ã¤Æ¤¤¤ë¡£¤³¤Î¼­½ñ¤âÂ礭¤±¤ì¤ÐÂ礭¤¤ÄøÎÉ
-¤¤¤Ï¤º¤À¡£¤½¤ÎÊý¤¬°ìÃ×ʸ»úÎ󤬸«¤Ä¤«¤ê¤ä¤¹¤¤¡£(¤¿¤À¤·¡¢¼­½ñ¤¬Â礭¤¤¤È
-°ìÃ×°ÌÃÖ¤ò¼¨¤¹¾ðÊó <len, pt> ¤Î¾ðÊóÎ̤¬Áý¤¨¤ë¤Ï¤º¤À¤·¡¢Â®ÅÙ¤âÃÙ¤¯¤Ê¤ë
-¤À¤í¤¦¡£¸å¤Ç¸¡¾Ú¤¹¤ë)
-
-¤Ç¡¢¼ÂºÝ¤Ë¥½¡¼¥¹¤ò¸«¤Æ¤ß¤ë¤È(slide.c:encode())¡¦¡¦¡¦¡¢¤Þ¤Ã¤¿¤¯¤³¤Î¤è¤¦
-¤Ê¹½Â¤¤Ë¤Ï¤Ê¤Ã¤Æ¤Ê¤¤¤è¤¦¤Ë¸«¤¨¤ë¡£²¿¤ä¤é¤ä¤ä¤³¤·¤¤¤³¤È¤Ð¤«¤ê¤Ç¤Þ¤Ã¤¿¤¯
-¤ï¤«¤é¤Ê¤¤¡£¤Ê¤¼¤³¤³¤Þ¤Ç¤ä¤ä¤³¤·¤¤¤Î¤«¤Èµã¤­¤¿¤¯¤Ê¤Ã¤Æ¤¯¤ë¤¬¡¢¤½¤ì¤Ï®
-Å٤Τ¿¤á¤Ç¤¢¤ë(ËÜÅö¡©)¡£¾åµ­¤Î¥³¡¼¥É¤Ç¡¢search_dict() ¤Ï¡¢Ã±¤Ë dict ¤«
-¤é token ¤Ë°ìÃפ¹¤ë°ÌÃÖ¤ò¸¡º÷¤¹¤ë¤À¤±¤ÇÎɤµ¤½¤¦(¼ÂºÝ¤Ë¤½¤ì¤Ç¤âÎɤ¤)¤À
-¤¬¡¢¤³¤ì¤Ç¤Ï¤Þ¤Ã¤¿¤¯Â®ÅÙ¤¬½Ð¤Ê¤¤¡£¤³¤Î¤¢¤¿¤ê¤Î¹©Éפ¬ slide ¼­½ñË¡¤Î¥­
-¥â¤Ç¤¢¤ë¡£
-
-¤½¤¦¤¤¤¦¤ï¤±¤Ç¡¢¤³¤ÎÉôʬ¤òÆɤ߲ò¤¯¤³¤È¤Ë¤¹¤ë¡£¤Ê¤ª¡¢Í½È÷Ãμ±¤È¤·¤Æ lha 
-¤Ç¤Ï¡¢¼­½ñ¤«¤é token ¤òõ¤¹¤Î¤Ë¥Ï¥Ã¥·¥å¤¬»È¤ï¤ì¤Æ¤¤¤ë¤é¤·¤¤¤³¤È¤òµ­¤·
-¤Æ¤ª¤¯¡£
-
-¤³¤³¤Ç¤Ï¼ÂºÝ¤Ë¥Ç¥Ð¥Ã¥¬¤ÇÆ°ºî¤µ¤»¤Ê¤¬¤é²òÆɤ¹¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢¥½¡¼¥¹¤òÆɤà
-¤À¤±¤ÇÍý²ò¤Ç¤­¤ë¤«¤ò»î¤¹¤³¤È¤Ë¤¹¤ë¡£¤Þ¤¿¡¢ËÜʸ¤ÏË¿½ñ(Ææ)¤Î¥Î¥ê¤ò¥Þ¥Í¤Æ
-¤¤¤ë¤È»ØŦ¤¹¤ëÊý¤¬¤¤¤ë¤«¤â¤·¤ì¤Ê¤¤¡¦¡¦¡¦¤¬¤Þ¤Ã¤¿¤¯¤½¤ÎÄ̤ê¤À¡£
-
-¤Þ¤º¡¢¤½¤Î¤â¤Î¤º¤Ð¤ê¤Î encode() (slide.c) ¤ò¸«¤ë¡£°Ê²¼¤¬¤³¤Î´Ø¿ô¤À¤¬
-½èÍý¤ÎÍ×ÅÀ¤À¤±¤ËÃåÌܤ¹¤ë¤¿¤á¤ËÉÔÍפ½¤¦¤ÊÉôʬ¤Ï(¸½»þÅÀ¤Çͽ¬¤Ç)ºï¤Ã¤¿¡£
+のようになるはず。ここで、tokensiz は token の最大サイズで、最長一致長
+を表す。この値が大きければ大きい程、圧縮効率は良くなるはずで、lha では、
+これは MAXMATCH{256}である。また、dict は辞書でこのサイズは lha の 
+-lh5- メソッドでは、8192 となっている。この辞書も大きければ大きい程良
+いはずだ。その方が一致文字列が見つかりやすい。(ただし、辞書が大きいと
+一致位置を示す情報 <len, pt> の情報量が増えるはずだし、速度も遅くなる
+だろう。後で検証する)
+
+で、実際にソースを見てみると(slide.c:encode())・・・、まったくこのよう
+な構造にはなってないように見える。何やらややこしいことばかりでまったく
+わからない。なぜここまでややこしいのかと泣きたくなってくるが、それは速
+度のためである(本当?)。上記のコードで、search_dict() は、単に dict か
+ら token に一致する位置を検索するだけで良さそう(実際にそれでも良い)だ
+ã\81\8cã\80\81ã\81\93ã\82\8cã\81§ã\81¯ã\81¾ã\81£ã\81\9fã\81\8fé\80\9f度ã\81\8cå\87ºã\81ªã\81\84ã\80\82ã\81\93ã\81®ã\81\82ã\81\9fã\82\8aã\81®å·¥å¤«ã\81\8c slide è¾\9eæ\9b¸æ³\95ã\81®ã\82­
+モである。
+
+そういうわけで、この部分を読み解くことにする。なお、予備知識として lha 
+では、辞書から token を探すのにハッシュが使われているらしいことを記し
+ておく。
+
+ここでは実際にデバッガで動作させながら解読するのではなく、ソースを読む
+だけで理解できるかを試すことにする。また、本文は某書(謎)のノリをマネて
+いると指摘する方がいるかもしれない・・・がまったくその通りだ。
+
+まず、そのものずばりの encode() (slide.c) を見る。以下がこの関数だが
+処理の要点だけに着目するために不要そうな部分は(現時点で予測で)削った。
 
 unsigned int
 encode()
 
 unsigned int
 encode()
@@ -211,35 +220,35 @@ encode()
     }
 }
 
     }
 }
 
-¤Þ¤º¡¢¤³¤Î´Ø¿ô¤«¤é³µ´Ñ¤ò¸«¤Æ¤ß¤ë¤È¡¢¥ë¡¼¥×¤ÎÁ°¤Ë½é´ü²½½èÍý¤È¤·¤Æ
-°Ê²¼¤¬¹Ô¤ï¤ì¤Æ¤¤¤ë¡£
+まず、この関数から概観を見てみると、ループの前に初期化処理として
+以下が行われている。
 
 
-(A) init_slide() ½é´ü²½¤¹¤ë
-(B) ¥Õ¥¡¥¤¥ë¤òÆɤ߹þ¤ß text[] ¤Ë³ÊǼ¤¹¤ë¡£
-(C) ¥Ï¥Ã¥·¥åÃÍ hval ¤ò·×»»¤¹¤ë¡£
-(D) insert() ¤¹¤ë (¤­¤Ã¤È¼­½ñ¤Ë token ¤òÄɲ䷤Ƥ¤¤ë¤Î¤À¤í¤¦)
+(A) init_slide() 初期化する
+(B) ファイルを読み込み text[] に格納する。
+(C) ハッシュ値 hval を計算する。
+(D) insert() する (きっと辞書に token を追加しているのだろう)
 
 
-¤½¤·¤Æ¡¢¥ë¡¼¥×½èÍý¤Ç¤Ï°Ê²¼¤Î½èÍý¤¬¹Ô¤ï¤ì¤Æ¤¤¤ë
+そして、ループ処理では以下の処理が行われている
 
 
-(E) lastmatchlen, lastmatchoffset, matchlen ¤ò¹¹¿·¤¹¤ë¡£
-(F) get_next()  (¼¡¤Î token ¤òÆɤࡣ¤¿¤Ö¤ó)
-(G) match_insert()  (¼­½ñ¤ËÄɲ乤롣¤¿¤Ö¤ó)
+(E) lastmatchlen, lastmatchoffset, matchlen を更新する。
+(F) get_next()  (次の token を読む。たぶん)
+(G) match_insert()  (辞書に追加する。たぶん)
 
 
-(H) matchlen > lastmatchlen || lastmatchlen < THRESHOLD ¤Ê¤é
+(H) matchlen > lastmatchlen || lastmatchlen < THRESHOLD なら
 
 
-(H.1) output() ¤¹¤ë¡£(¥Þ¥Ã¥Á¤·¤Ê¤«¤Ã¤¿¤é¤½¤Î¤Þ¤Þ½ÐÎϤ·¤Æ¤¤¤ë¤Î¤À¤í¤¦¡£¤¿¤Ö¤ó)
-(H.2) ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð(¥Þ¥Ã¥Á¤·¤¿¤Ê¤é)¡¢output()¤·¡¢²¿¤«¤¤¤í¤¤¤í¤¹¤ë¡£
+(H.1) output() する。(マッチしなかったらそのまま出力しているのだろう。たぶん)
+(H.2) そうでなければ(マッチしたなら)、output()し、何かいろいろする。
 
 
-¸½»þÅÀ¤Ç¡¢(H.2) ¤ÎÉôʬ¤Ï¤è¤¯²òÆɤǤ­¤Ê¤«¤Ã¤¿¡£²¿¤ä¤éºÆÅÙ get_next() ¤¬
-¸Æ¤Ð¤ì¤Æ¤¤¤¿¤ê¤·¤Æ»×¤Ã¤¿Ä̤ê¤Î½èÍý¥Õ¥í¡¼¤Ë¤Ï¤Ê¤Ã¤Æ¤¤¤Ê¤¤¡£¤À¤¬¡¢¤³¤³¤Ç
-¤Ï¾Ç¤é¤ºÊüÃÖ¤¹¤ë¤³¤È¤Ë¤·¤Æ¡¢¤³¤³¤Þ¤ÇͽÁۤǽñ¤¤¤¿Éôʬ¤ÎºÙÉô¤Ë¿¨¤ì¤ë¤³¤È
-¤Ë¤¹¤ë(ñ¤Ë¤³¤³¤Þ¤Ç¤ÎͽÁÛ¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¤À¤±¤«¤â¤·¤ì¤Ê¤¤¤Î¤À¤«¤é¡¢¤ï¤«
-¤é¤Ê¤¤Éôʬ¤ò̵Íý¤Ë¤ï¤«¤ë¤è¤¦¤Ë´èÄ¥¤ëɬÍפϤʤ«¤í¤¦)
+現時点で、(H.2) の部分はよく解読できなかった。何やら再度 get_next() が
+呼ばれていたりして思った通りの処理フローにはなっていない。だが、ここで
+は焦らず放置することにして、ここまで予想で書いた部分の細部に触れること
+にする(単にここまでの予想が間違っているだけかもしれないのだから、わか
+らない部分を無理にわかるように頑張る必要はなかろう)
 
 
-´Ø¿ô¤ÎºÙÉô¤Ë¿¨¤ì¤ëÁ°¤Ë¥Ç¡¼¥¿¹½Â¤¤Ë¤Ä¤¤¤ÆÄ´¤Ù¤Æ¤ª¤¯¡£¥Ç¡¼¥¿¹½Â¤¤ËÂФ·¤Æ
-¤ÎÍý²ò¤¬¿¼¤Þ¤ì¤Ð¥¢¥ë¥´¥ê¥º¥à¤Î80%¤Ïʬ¤«¤Ã¤¿¤âƱÁ³¤À(¸ØÄ¥)¡£slide.c ¤Ç
-»ÈÍѤµ¤ì¤Æ¤¤¤ë¥Ç¡¼¥¿¹½Â¤¤Ï°Ê²¼¤ÎÄ̤ê¤À¡£(ÉÔÍפ½¤¦¤À¤È»×¤¦¤â¤Î¤Ï½ü¤¤¤Æ
-¤¢¤ë)
+関数の細部に触れる前にデータ構造について調べておく。データ構造に対して
+の理解が深まればアルゴリズムの80%は分かったも同然だ(誇張)。slide.c で
+使用されているデータ構造は以下の通りだ。(不要そうだと思うものは除いて
+ある)
 
 static unsigned int *hash;
 static unsigned int *prev;
 
 static unsigned int *hash;
 static unsigned int *prev;
@@ -252,11 +261,11 @@ static unsigned int matchpos;
 static unsigned int pos;
 static unsigned int remainder;
 
 static unsigned int pos;
 static unsigned int remainder;
 
-too_flag ¤À¤±¡¢static ¤¬¤Ä¤¤¤Æ¤Ê¤¤¤¬¡¢Â¾¤Î¥½¡¼¥¹¤ò grep ¤·¤Æ¤â¤³¤ÎÊÑ¿ô
-¤ò»È¤Ã¤Æ¤¤¤ë²Õ½ê¤Ï¤Ê¤¤¡¢Ã±¤Ë static ¤ÎÉÕ¤±Ëº¤ì¤À¤í¤¦¡£
+too_flag だけ、static がついてないが、他のソースを grep してもこの変数
+を使っている箇所はない、単に static の付け忘れだろう。
 
 
-¤³¤ì¤é¤ÎÊÑ¿ô¤Ï¡¢encode() ¤ÎËÁƬ init_slide() ¤Ç½é´ü²½¤µ¤ì¤Æ¤¤¤ë¡¦¡¦¤Î
-¤«¤È»×¤Ã¤¿¤é°ã¤Ã¤¿¡£slide.c:encode_alloc() ¤Ç¹Ô¤ï¤ì¤Æ¤¤¤ë¡£
+これらの変数は、encode() の冒頭 init_slide() で初期化されている・・の
+かと思ったら違った。slide.c:encode_alloc() で行われている。
 
 int
 encode_alloc(method)
 
 int
 encode_alloc(method)
@@ -295,9 +304,9 @@ encode_alloc(method)
     return method;
 }
 
     return method;
 }
 
-°ú¿ô¤ËÅϤµ¤ì¤¿ method (¤³¤ì¤Ï¡¢lh1, lh5, lh6, lh7 ¤Ê¤É¤ò¼¨¤¹)¤Ë¤è¤Ã¤Æ¡¢
-½é´ü²½¤µ¤ì¤ëÆâÍƤ¬ÊѤï¤ë(encode_alloc()Á°È¾Éôʬ)¡£¤³¤Î¤³¤È¤«¤é³ÆÊÑ¿ô¤Î
-ÍÑÅÓ¤â¤ï¤«¤ë¡£
+引数に渡された method (これは、lh1, lh5, lh6, lh7 などを示す)によって、
+初期化される内容が変わる(encode_alloc()前半部分)。このことから各変数の
+用途もわかる。
 
         method  maxmatch     dicbit
         ----------------------------
 
         method  maxmatch     dicbit
         ----------------------------
@@ -306,36 +315,36 @@ encode_alloc(method)
         -lh6-      256         15
         -lh7-      256         16
 
         -lh6-      256         15
         -lh7-      256         16
 
-¤È¤¤¤¦¤³¤È¤é¤·¤¤¡£dicbit ¤È¤¤¤¦¤Î¤Ï¼­½ñ¥µ¥¤¥º¤Îbit¥µ¥¤¥º¤Ç¡¢¼­½ñ¥µ¥¤¥º
-¤Ï 2^dicbit ¤Çɽ¤µ¤ì¤Æ¤¤¤ë¡£lh5 ¤¬ 8KB(2^13)¡¢lh6 ¤¬ 32KB(2^15)¡¢lh7 
-¤¬ 64KB(2^16) ¤Î¼­½ñ¥µ¥¤¥º¤òÍøÍѤ¹¤ë¤È¸À¤¦¤Î¤ÏͽÈ÷Ãμ±¤Ç¤¢¤ë¡£maxmatch 
-¤È¤¤¤¦¤Î¤Ï¡¢token ¤ÎºÇĹ°ìÃ׍Ǥ¢¤ë¡£¤³¤Î¤³¤È¤âͽÈ÷Ãμ±¤È¤·¤Æ¾ÜºÙ¤Ë¤Ï
-¿¨¤ì¤Ê¤¤¡£(¤È¤³¤í¤Ç¡¢Ëܽñ¤Ç¤ÏÅöÌÌ¡¢lh5, 6, 7 ¤Î¤³¤È¤·¤«¸ÀµÚ¤·¤Ê¤¤)
+ã\81¨ã\81\84ã\81\86ã\81\93ã\81¨ã\82\89ã\81\97ã\81\84ã\80\82dicbit ã\81¨ã\81\84ã\81\86ã\81®ã\81¯è¾\9eæ\9b¸ã\82µã\82¤ã\82ºã\81®bitã\82µã\82¤ã\82ºã\81§ã\80\81è¾\9eæ\9b¸ã\82µã\82¤ã\82º
+は 2^dicbit で表されている。lh5 が 8KB(2^13)、lh6 が 32KB(2^15)、lh7 
+が 64KB(2^16) の辞書サイズを利用すると言うのは予備知識である。maxmatch 
+というのは、token の最長一致長である。このことも予備知識として詳細には
+触れない。(ところで、本書では当面、lh5, 6, 7 のことしか言及しない)
 
 
-encode_set, encode_define ¤È¤¤¤¦¤Î¤¬¤¢¤ë¤¬¡¢method ¤Ë¤è¤Ã¤Æ¡¢Huffman
-coding ¤ÎÊýË¡¤òÊѤ¨¤Æ¤¤¤ë¤³¤È¤Ï¤Á¤ç¤Ã¤È¸«¤ì¤Ð¤¹¤°¤Ë¤ï¤«¤ë¤·¡¢Â礷¤¿¤³
-¤È¤Ç¤Ï¤Ê¤¤¡£°Ê¹ß̵»ë¤¹¤ë¡£
+encode_set, encode_define というのがあるが、method によって、Huffman
+coding の方法を変えていることはちょっと見ればすぐにわかるし、大したこ
+とではない。以降無視する。
 
 
-encode_alloc() ¤Î¸åȾ¤Ç¤Ï¡¢Â¾¤ÎÊÑ¿ô¤Î½é´ü²½(¥Ð¥Ã¥Õ¥¡¤Î³ä¤êÅö¤Æ)¤¬¹Ô¤ï¤ì¤ë¡£
+encode_alloc() の後半では、他の変数の初期化(バッファの割り当て)が行われる。
 
     dicsiz = (((unsigned long)1) << dicbit);
 
 
     dicsiz = (((unsigned long)1) << dicbit);
 
-dicsiz ¤Ï¤½¤Î¤â¤Î¤º¤Ð¤ê¼­½ñ¥µ¥¤¥º¤Ç¤¢¤ë¡£
+dicsiz はそのものずばり辞書サイズである。
 
     txtsiz = dicsiz*2+maxmatch;
 
 
     txtsiz = dicsiz*2+maxmatch;
 
-¸½»þÅÀ¤Ç txtsiz ¤¬²¿¤Ê¤Î¤«¤Ï¤ï¤«¤é¤Ê¤¤¡£
+現時点で txtsiz が何なのかはわからない。
 
     if (hash) return method;
 
 
     if (hash) return method;
 
-hash ¤Ï¤³¤Îľ¸å¤Ç³ä¤êÅö¤Æ¤é¤ì¤ë¡£¤Ä¤Þ¤ê¡¢°ìÅÙ³äÅö¤ò¹Ô¤Ã¤¿¤é¡¢
-encode_alloc() ¤Ï¡¢°Ê¹ß¥á¥â¥ê¤Î³äÅö¤ò¹Ô¤ï¤Ê¤¤¡£¤¿¤À¤½¤ì¤À¤±¤À¡£
+hash はこの直後で割り当てられる。つまり、一度割当を行ったら、
+encode_alloc() は、以降メモリの割当を行わない。ただそれだけだ。
 
     if (alloc_buf() == NULL) exit(207); /* I don't know this 207. */
 
 
     if (alloc_buf() == NULL) exit(207); /* I don't know this 207. */
 
-alloc_buf() ¤Ï¡¢huf.c ¤ÇÄêµÁ¤µ¤ì¤¿´Ø¿ô¡£¤³¤Î¤³¤È¤«¤é Huffman coding ¤Î
-¤¿¤á¤Î¥Ð¥Ã¥Õ¥¡¤ò³ä¤êÅö¤Æ¤Æ¤¤¤ë¤Î¤À¤í¤¦¡£¤³¤³¤Ç¤Ï̵»ë¡£(¤·¤«¤·¡¢207 ¤È
-¤¤¤¦¤Î¤Ï²¿¤Ê¤Î¤À¤í¤¦¡©)
+alloc_buf() は、huf.c で定義された関数。このことから Huffman coding の
+ためのバッファを割り当てているのだろう。ここでは無視。(しかし、207 と
+いうのは何なのだろう?)
 
     hash = (unsigned int*)malloc(HSHSIZ * sizeof(unsigned int));
     prev = (unsigned int*)malloc(DICSIZ * sizeof(unsigned int));
 
     hash = (unsigned int*)malloc(HSHSIZ * sizeof(unsigned int));
     prev = (unsigned int*)malloc(DICSIZ * sizeof(unsigned int));
@@ -345,28 +354,28 @@ alloc_buf() 
     if (hash == NULL || prev == NULL || text == NULL || too_flag == NULL)
         exit(207);
 
     if (hash == NULL || prev == NULL || text == NULL || too_flag == NULL)
         exit(207);
 
-hash ¤Ï¡¢¥Ï¥Ã¥·¥åÍѤβ¿¤«¡¢HSHSIZ ¤Ï¡¢¸ÇÄêÃͤǠ2^15 ¤Ç¤¢¤ë¡£
+hash は、ハッシュ用の何か、HSHSIZ は、固定値で 2^15 である。
 
 
-prev ¤Ï¡¢DICSIZ¤«¤é¼­½ñ¤À¤í¤¦¡£Í×ÁǤη¿¤¬ char ¤Ç¤Ê¤¯ int ¤Ç¤¢¤ë¤³¤È¤Ë
-¤âÃíÌܤ·¤Æ¤ª¤¯¡£DICSIZ ¤Ï dicsiz ¤Ç¤â¹½¤ï¤Ê¤¤¤Ï¤º¡£Ã±¤Ë¡ÖÂç¤Ï¾®¤ò·ó¤Í
-¤ë¡×¤ò¼ÂÁ©¤·¤Æ¤¤¤ë¤À¤±¤Ç¤¢¤í¤¦¡¢TXTSIZ ¤âƱÍͤǤ¢¤ë¡£¤ª¤½¤é¤¯¡¢°ìÅÙ¤Î
-¼Â¹Ô¤ÇÊ£¿ô¤Î°µ½Ì¥á¥½¥Ã¥É¤ò»ÈÍѤ·¤¿¾ì¹ç¡¢¤½¤Î¥á¥½¥Ã¥ÉËè¤ËÎΰè¤ò³ä¤êÅö¤Æ
-¤ë¤è¤ê¤ÏºÇÂç¤ÎÃͤò¤¢¤é¤«¤¸¤á°ìÅÙ¤À¤±³ä¤êÅö¤Æ¤¿Êý¤¬Îɤ¤¤È¹Í¤¨¤¿¤Î¤À¤í¤¦¡£
-¤·¤«¤·¡¢¥½¡¼¥¹¤ò»²¾È¤¹¤ë¤È¤­¤ÏÈË»¨¤Ë¤Ê¤ë¤Î¤Ç°Ê¹ß¡¢
+prev は、DICSIZから辞書だろう。要素の型が char でなく int であることに
+も注目しておく。DICSIZ は dicsiz でも構わないはず。単に「大は小を兼ね
+る」を実践しているだけであろう、TXTSIZ も同様である。おそらく、一度の
+実行で複数の圧縮メソッドを使用した場合、そのメソッド毎に領域を割り当て
+るよりは最大の値をあらかじめ一度だけ割り当てた方が良いと考えたのだろう。
+しかし、ソースを参照するときは繁雑になるので以降、
    DICSIZ == dicsiz
    TXTSIZ == txtsiz
    DICSIZ == dicsiz
    TXTSIZ == txtsiz
-¤Ç¤¢¤ë¤È¤¹¤ë¡£¤³¤ì½ÅÍס£
+であるとする。これ重要。
 
 
-text ¤Ï¡¢¸½»þÅÀ¤Ç¤ÏÉÔÌÀ
+text は、現時点では不明
 
 
-too_flag ¤âÉÔÌÀ
+too_flag も不明
 
 
-¤Ã¤È¤Ê¤ë¡£¤Þ¤À¡¢Îɤ¯Ê¬¤«¤é¤Ê¤¤¤¬¡¢°Ê²¼¤Î¿Þ¤ò½ñ¤¤¤Æ¤ª¤³¤¦¡£¸å¤Ç²¿Å٤⸫
-¤ë¤³¤È¤Ë¤Ê¤ë¤À¤í¤¦¡£¤³¤Î¿Þ¤Ï¥¹¥±¡¼¥ë¤¬ lh7 ¤Î¾ì¹ç¤òÁÛÄꤷ¤Æ¤¤¤ë¤¬¡£¤³
-¤Î¤³¤È¤ÏÂ礷¤¿¤³¤È¤Ç¤Ï¤Ê¤¤¤Ï¤º¤À¡£¤Þ¤¿¡¢too_flag ¤È hash ¤Î¥¹¥±¡¼¥ë¤¬
-°ì½ï¤À¤¬¤³¤ì¤Ï¥µ¥¤¥º(Îΰè¤Î¥Ð¥¤¥È¿ô)¤¬°ì½ï¤Ê¤Î¤Ç¤Ï¤Ê¤¯¡¢Í×ÁÇ¿ô¤¬°ì½ï¤Ç
-¤¢¤ë¤³¤È¤ò¼¨¤·¤Æ¤¤¤ë¡£¤Û¤È¤ó¤É¤Î¾ì¹çÍ×ÁǤη¿¤Î°ã¤¤¤È¤¤¤¦¤Î¤Ï½èÍýÆâÍƤË
-¤È¤Ã¤Æ½ÅÍפʤ³¤È¤Ç¤Ï¤Ê¤¤¤Ï¤º¤À¡£
+っとなる。まだ、良く分からないが、以下の図を書いておこう。後で何度も見
+ることになるだろう。この図はスケールが lh7 の場合を想定しているが。こ
+のことは大したことではないはずだ。また、too_flag と hash のスケールが
+一緒だがこれはサイズ(領域のバイト数)が一緒なのではなく、要素数が一緒で
+あることを示している。ほとんどの場合要素の型の違いというのは処理内容に
+とって重要なことではないはずだ。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -389,7 +398,7 @@ too_flag 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
 
-Àè¤Ë¼¨¤·¤¿ÊÑ¿ô¤ÎÃæ¤Ç¤Þ¤À½é´ü²½¤Ë¤Ï¸½¤ì¤Æ¤¤¤Ê¤¤¤â¤Î¤¬¤¢¤ë¡£Îóµó¤¹¤ë¤È
+先に示した変数の中でまだ初期化には現れていないものがある。列挙すると
 
 static unsigned int hval;
 static int matchlen;
 
 static unsigned int hval;
 static int matchlen;
@@ -397,17 +406,17 @@ static unsigned int matchpos;
 static unsigned int pos;
 static unsigned int remainder;
 
 static unsigned int pos;
 static unsigned int remainder;
 
-¤À¡¢¤¶¤Ã¤È¥½¡¼¥¹¤òį¤á¤ë¤È slide.c:insert() ¤È¤¤¤¦´Ø¿ô¤Ë
+だ、ざっとソースを眺めると slide.c:insert() という関数に
         hash[hval] = pos;
         hash[hval] = pos;
-¤È¤¤¤¦¤Î¤¬¸½¤ì¤Æ¤¤¤ë¤«¤é¡¢hval ¤Ï¡¢hash[] ¤Î°ÌÃÖ¤ò»Ø¤·¡¢hash ¤Ë¤Ï¡¢pos 
-¤ò³ÊǼ¤¹¤ë¤È¿ä¬¤µ¤ì¤ë¡£Æ±ÍͤË
+というのが現れているから、hval は、hash[] の位置を指し、hash には、pos 
+を格納すると推測される。同様に
         prev[pos & (dicsiz - 1)] = hash[hval];
         prev[pos & (dicsiz - 1)] = hash[hval];
-¤È¤¤¤¦¤Î¤â¸½¤ì¤Æ¤¤¤ë¤«¤é pos ¤Ï¡¢prev[] ¤Î°ÌÃÖ¤ò»Ø¤·¡¢prev ¤Ë¤Ï¡¢
-hash[hval] ¤Ä¤Þ¤ê¡¢pos ¤ò³ÊǼ¤·¤Æ¤¤¤ë¤è¤¦¤À¡£¤³¤ì¤Ï¾¯¤·Ææ¤Ê½èÍý¤À¤¬¡¢
-insert() ¤ÎÁ´ËƤÏû¤¤(¤È¤¤¤¦¤«¤³¤ì¤À¤±)¤Ê¤Î¤Ç¡¢¤Á¤ç¤Ã¤È²£Æ»¤Ë¤½¤ì¤Æ¾Ü
-ºÙ¤Ë¸«¤Æ¤ß¤è¤¦¡£(¸½ºß¤Î²òÀϤμñ»Ý¤Ï¡¢ÊÑ¿ô¤ÎÍÑÅӤγµÍפòͽÁÛ¤¹¤ë¤³¤È)
+というのも現れているから pos は、prev[] の位置を指し、prev には、
+hash[hval] つまり、pos を格納しているようだ。これは少し謎な処理だが、
+insert() の全貌は短い(というかこれだけ)なので、ちょっと横道にそれて詳
+細に見てみよう。(現在の解析の趣旨は、変数の用途の概要を予想すること)
 
 
-/* ¸½ºß¤Îʸ»úÎó¤ò¥Á¥§¡¼¥ó¤ËÄɲ乤ë */
+/* 現在の文字列をチェーンに追加する */
 
 static void insert()
 {
 
 static void insert()
 {
@@ -415,40 +424,40 @@ static void insert()
     hash[hval] = pos;
 }
 
     hash[hval] = pos;
 }
 
-¥³¥á¥ó¥È¤Ï¤Þ¤Ã¤¿¤¯°ÕÌ£ÉÔÌÀ¤À¤¬¡¢Ìµ»ë¤·¤Æ½èÍýÆâÍƤËÃåÌܤ¹¤ë¡£prev[] ¤Î
-¥¤¥ó¥Ç¥Ã¥¯¥¹ pos & (dicsiz - 1) ¤Ï¡¢dicsiz ¤¬ 2^n ¤Ç¤¢¤ë¤³¤È¤«¤édicsiz 
-¤Ï¥Ó¥Ã¥È¥Þ¥¹¥¯¤Ç¤¢¤ë¤³¤È¤¬¤ï¤«¤ë¡£Î㤨¤Ð²¾¤Ë dicsiz ¤¬ 2^8 ¤À¤È
-dicsiz - 1 ¤Ï¡¢
+コメントはまったく意味不明だが、無視して処理内容に着目する。prev[] の
+インデックス pos & (dicsiz - 1) は、dicsiz が 2^n であることからdicsiz 
+はビットマスクであることがわかる。例えば仮に dicsiz が 2^8 だと
+dicsiz - 1 は、
 
                8 7 6 5 4 3 2 1 0 bit
       --------------------------
       dicsiz   1 0 0 0 0 0 0 0 0
       dicsiz-1   1 1 1 1 1 1 1 1
 
 
                8 7 6 5 4 3 2 1 0 bit
       --------------------------
       dicsiz   1 0 0 0 0 0 0 0 0
       dicsiz-1   1 1 1 1 1 1 1 1
 
-¤Ç¤¢¤ë¡£¤³¤Î¤¹¤Ù¤Æ 1 ¤¬Î©¤Ã¤¿¥Ó¥Ã¥È¥Þ¥¹¥¯¤È pos ¤ò & ¤¹¤ë¤È¡¢¤É¤Î¤è¤¦
-¤Ê pos ¤ÎÃͤËÂФ·¤Æ¤â pos & (dicsiz - 1) ¤Ï¡¢prev[] ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤ÎÈÏ
-°Ï¤ËǼ¤Þ¤ë¡£¤â¤¦¾¯¤·¸À¤¦¤È pos ¤¬²¾¤Ë¥¤¥ó¥Ç¥Ã¥¯¥¹¤ÎºÇÂçÃÍ+1¤À¤Ã¤¿¾ì¹ç¡¢
-pos & (dicsiz - 1) ¤Ï¡¢0 ¤Ë¤Ê¤ë¡£¤³¤ì¤Ë¤è¤ê¼¡¤ÎͽÁÛ¤¬Î©¤Ä¡£
+である。このすべて 1 が立ったビットマスクと pos を & すると、どのよう
+な pos の値に対しても pos & (dicsiz - 1) は、prev[] のインデックスの範
+囲に納まる。もう少し言うと pos が仮にインデックスの最大値+1だった場合、
+pos & (dicsiz - 1) は、0 になる。これにより次の予想が立つ。
 
 
-  o pos ¤¬¡¢prev[] ¤Î°ÌÃÖ¤ò»Ø¤¹¤Î¤Ç¤Ï¤Ê¤¯¡¢pos & (dicsiz - 1) ¤¬
-    prev[]¤Î°ÌÃÖ¤ò»Ø¤¹¡£(pos ¤Ï¡¢¤³¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤ÎÈϰϤò±Û¤¨¤ë²ÄǽÀ­¤¬¤¢¤ë)
-  o ¤½¤ì¤ËÈ¿¤·¤Æ¡¢prev[] ¤Ï´Ä¾õ¥Ð¥Ã¥Õ¥¡¤é¤·¤¤¤È¤¤¤¦Í½ÁÛ¤¬Î©¤Æ¤Ð¤ä¤Ï¤ê
-    pos ¤Ï¡¢prev ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç¤¢¤ë¡£
+  o pos が、prev[] の位置を指すのではなく、pos & (dicsiz - 1) が
+    prev[]の位置を指す。(pos は、このインデックスの範囲を越える可能性がある)
+  o それに反して、prev[] は環状バッファらしいという予想が立てばやはり
+    pos は、prev のインデックスである。
 
 
-prev ¤¬´Ä¾õ¥Ð¥Ã¥Õ¥¡¤Ç¤¢¤ë¤ÈͽÁÛ¤¬ÉÕ¤±¤ÐÏä¬Áᤤ¡£pos & (dicsiz-1) ¤Ï¡¢
-pos ¤ÈƱµÁ¤À¤È²ò¼á²Äǽ¤À¤«¤é¤Ç¤¢¤ë(prev ¤¬´Ä¾õ¥Ð¥Ã¥Õ¥¡¤Ç¤Ê¤¯Ìµ¸ÂĹ¤Î¥Ð¥Ã
-¥Õ¥¡¤Ç¤¢¤ë¤ÈÁÛÁü¤·¤è¤¦)¤½¤·¤Æ¡¢pos & (dicsiz-1) ¤ò pos ¤ËÃÖ¤­´¹¤¨¤Æ¡¢
-ºÆÅÙ½èÍýÆâÍƤËÃåÌܤ¹¤ë¤È
+prev が環状バッファであると予想が付けば話が早い。pos & (dicsiz-1) は、
+pos と同義だと解釈可能だからである(prev が環状バッファでなく無限長のバッ
+ファであると想像しよう)そして、pos & (dicsiz-1) を pos に置き換えて、
+再度処理内容に着目すると
 
     prev[pos] = hash[hval];
     hash[hval] = pos;
 
 
     prev[pos] = hash[hval];
     hash[hval] = pos;
 
-¤È¤¤¤¦¤³¤È¤«¤é¡¢
-    1. (¤³¤Î´Ø¿ô¤ËÍè¤ëÁ°¤Ë) pos ¤¬¹¹¿·¤µ¤ì¤ë¡£(ͽÁÛ)
-    2. prev[pos] ¤Ë°ÊÁ°¤Î hash[hval] (°ÊÁ°¤Î pos)¤ò³ÊǼ¤¹¤ë
-    3. hash[hval] ¤Ë¿·¤·¤¤ pos ¤ò½ñ¤¯¡£
-¤È¤¤¤Ã¤¿½èÍý¤Ç¤¢¤ë¤³¤È¤¬Í½ÁÛ¤µ¤ì¤ë¡£¥³¥á¥ó¥È¤Î¡Ö¥Á¥§¡¼¥ó¡×¤â¤Ê¤ó¤È¤Ê¤¯
-ǼÆÀ¤Ç¤­¤ë¡£¿·¤¿¤Ê»ö¼Â(¤Þ¤ÀͽÁÛ¤À¤¬)¤¬Ê¬¤«¤Ã¤¿¤Î¤Ç¡¢¿Þ¤Ë½ñ¤­µ­¤½¤¦¡£
+ということから、
+    1. (この関数に来る前に) pos が更新される。(予想)
+    2. prev[pos] に以前の hash[hval] (以前の pos)を格納する
+    3. hash[hval] に新しい pos を書く。
+といった処理であることが予想される。コメントの「チェーン」もなんとなく
+納得できる。新たな事実(まだ予想だが)が分かったので、図に書き記そう。
 
 ----------------------------------------------------------------------------
        0            2^15=32768
 
 ----------------------------------------------------------------------------
        0            2^15=32768
@@ -464,53 +473,53 @@ pos 
        +----+-----+--------------------
             `- ppos      `-pos
 
        +----+-----+--------------------
             `- ppos      `-pos
 
-  * hash ¤Î¼è¤êÆÀ¤ëÃͤϠpos ¤½¤Î°ÌÃ֤Ϡhval
-  * ppos ¤Ï°ÊÁ°¤Î pos ¤ò¼¨¤¹¡£pppos ¤Ï¤µ¤é¤Ë°ÊÁ°¤Î pos ¤ò»Ø¤¹¡£
-  * prev ¤Ï̵¸ÂĹ¤Î¥Ð¥Ã¥Õ¥¡(ËÜÅö¤Ï´Ä¾õ¥Ð¥Ã¥Õ¥¡)
+  * hash の取り得る値は pos その位置は hval
+  * ppos は以前の pos を示す。pppos はさらに以前の pos を指す。
+  * prev ã\81¯ç\84¡é\99\90é\95·ã\81®ã\83\90ã\83\83ã\83\95ã\82¡(æ\9c¬å½\93ã\81¯ç\92°ç\8a¶ã\83\90ã\83\83ã\83\95ã\82¡)
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-¤Þ¤À¡¢²òÀϤǤ­¤Æ¤Ê¤¤ÊÑ¿ô¤¬»Ä¤Ã¤Æ¤¤¤ë¡£
+まだ、解析できてない変数が残っている。
 
 static int matchlen;
 static unsigned int matchpos;
 static unsigned int remainder;
 
 
 static int matchlen;
 static unsigned int matchpos;
 static unsigned int remainder;
 
-¤·¤«¤·¤³¤ì¤é¤Ï¤É¤¦¤Ë¤â¥Ñ¥Ã¤È¸«¤Ç¤Ï¤ï¤«¤é¤Ê¤¤¡£½èÍýÆâÍƤòÄɤ¤¤«¤±¤Ê¤¤¤È
-¤À¤á¤½¤¦¤À¡£»ÅÊý¤Ê¤¤¤Î¤ÇÊÑ¿ô̾¤ÇͽÁÛ¤·¤è¤¦¡£(¹¬¤¤Á°¤ÎÊÑ¿ô̾¤È°ã¤Ã¤Æͽ
-ÁÛ¤·¤ä¤¹¤¤)°Ê²¼
+しかしこれらはどうにもパッと見ではわからない。処理内容を追いかけないと
+だめそうだ。仕方ないので変数名で予想しよう。(幸い前の変数名と違って予
+想しやすい)以下
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
- * matchlen     °ìÃפ·¤¿Ê¸»úÎóĹ
- * matchpos     °ìÃפ·¤¿¼­½ñ¾å¤Î°ÌÃÖ
- * remainder    token ¤Î»Ä¤ê¥µ¥¤¥º
+ * matchlen     一致した文字列長
+ * matchpos     一致した辞書上の位置
+ * remainder    token ã\81®æ®\8bã\82\8aã\82µã\82¤ã\82º
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-¤Ï¤¿¤·¤Æ¡¢Í½ÁۤϤ¢¤Ã¤Æ¤¤¤ë¤Î¤«¡¢º£¤Ï¤Þ¤Àʬ¤«¤é¤Ê¤¤¡£
+はたして、予想はあっているのか、今はまだ分からない。
 
 
-slide.c ¤ò¸«¤ë¸Â¤ê¥Ç¡¼¥¿¹½Â¤¤ÏÌÖÍå¤Ç¤­¤¿¡£·ë¶Éʬ¤«¤Ã¤¿¤Î¤«Ê¬¤«¤é¤Ê¤¤¤Î
-¤«Îɤ¯Ê¬¤«¤é¤Ê¤¤¤¬¾¯¤·¤º¤Ä¤Ç¤âÁ°¿Ê¤Ï¤·¤Æ¤¤¤ë¤Ï¤º¤À¡£¤³¤³¤Ç¡¢ºÆÅÙ 
-encode() ¤Î½èÍý¤òÄɤ¤¤«¤±¤è¤¦¡£º£Å٤ϺÙÉô¤Ë¤âÃåÌܤ¹¤ë¡£
+slide.c を見る限りデータ構造は網羅できた。結局分かったのか分からないの
+か良く分からないが少しずつでも前進はしているはずだ。ここで、再度 
+encode() の処理を追いかけよう。今度は細部にも着目する。
 
 
-Á°¤Ë¡¢encode() ¤Î¥½¡¼¥¹¤Ë¤Ï (A) ¡Á (H) ¤Þ¤Ç¤Îµ­¹æ¤òµ­¤·¤¿¡£¤³¤Î½çÈÖ¤Ë
-²òÀϤò¿Ê¤á¤è¤¦¡£
+前に、encode() のソースには (A) 〜 (H) までの記号を記した。この順番に
+解析を進めよう。
 
     /* (A) */
     init_slide();  
 
 
     /* (A) */
     init_slide();  
 
-¤Þ¤¢¡¢½é´ü²½¤Ç¤¢¤ë¡£ÆâÍƤò¸«¤Æ¤ß¤ë¤È
+まあ、初期化である。内容を見てみると
 
     for (i = 0; i < HSHSIZ; i++) {
         hash[i] = NIL;
         too_flag[i] = 0;
     }
 
 
     for (i = 0; i < HSHSIZ; i++) {
         hash[i] = NIL;
         too_flag[i] = 0;
     }
 
-¤À¤±¤Ç¤¢¤ë¡£NIL ¤È¤¤¤¦¤Î¤Ï¡¢0 ¤Ç¤¢¤ë¤È slide.c ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£ÉáÄÌ
-¤³¤Î¤è¤¦¤Ê½é´üÃͤϡ¢Ä̾ï¤ÎÃͤ¬¼è¤êÆÀ¤Ê¤¤Ãͤò¼¨¤·¤Æ¤¤¤ë¡£NIL ¤¬ 0 ¤Ê¤é 
-hash[] ¤Ë³ÊǼ¤µ¤ì¤ë pos ¤Ï 0 ¤Ë¤Ê¤é¤Ê¤¤²ÄǽÀ­¤¬¤¢¤ë¡£¤Þ¤¢¡¢Í½ÁۤФ«¤ê
-½ñ¤¤¤Æ¤â»ÅÊý¤Ê¤¤¤Î¤Ç¡¢¤³¤Î´Ø¿ô¤Ï½ª¤í¤¦¡£Í¾Ã̤À¤¬¡¢nil ¤Ï null ¤ÈƱ¤¸¤Ç¡£
-¡Ö¤Ê¤¤¡×¤Î°ÕÌ£¤À¤¬¡¢NULL ¤¬C¸À¸ì¤Ç¤Ï¥Ý¥¤¥ó¥¿¤À¤«¤é¡£Ê̤Υޥ¯¥í̾¤Ë¤·¤¿
-¤Î¤«¤âÃΤì¤Ê¤¤¡£¤¤¤º¤ì¤Ë¤·¤Æ¤â¤³¤ÎÄøÅ٤ϥޥ¯¥í¤Ë¤¹¤ëɬÍפâ¤Ê¤«¤í¤¦¤È¤Ï
-»×¤¦¤Î¤Ï¡¢Í¾·×¤Ê¤ªÀ¤Ï䫤⤷¤ì¤Ê¤¤¡£
+だけである。NIL というのは、0 であると slide.c で定義されている。普通
+このような初期値は、通常の値が取り得ない値を示している。NIL が 0 なら 
+hash[] に格納される pos は 0 にならない可能性がある。まあ、予想ばかり
+書いても仕方ないので、この関数は終ろう。余談だが、nil は null と同じで。
+「ない」の意味だが、NULL がC言語ではポインタだから。別のマクロ名にした
+のかも知れない。いずれにしてもこの程度はマクロにする必要もなかろうとは
+思うのは、余計なお世話かもしれない。
 
     /* (B) */
     remainder = fread_crc(&text[dicsiz], txtsiz-dicsiz, infile);
 
     /* (B) */
     remainder = fread_crc(&text[dicsiz], txtsiz-dicsiz, infile);
@@ -521,18 +530,18 @@ hash[] 
 
     if (matchlen > remainder) matchlen = remainder;
 
 
     if (matchlen > remainder) matchlen = remainder;
 
-¥Õ¥¡¥¤¥ë¤òÆɤ߹þ¤ß¡¢³ÆÊÑ¿ô¤Î½é´üÃͤòÀßÄꤷ¤Æ¤¤¤ë¡£ÃíÌܤ¹¤Ù¤­¤Ï¥Õ¥¡¥¤¥ë
-¤òÆɤ߹þ¤ó¤À¥Ð¥Ã¥Õ¥¡¤Î°ÌÃ֤Ǥ¢¤ë¡£fread_crc() ¤Ï¡¢crcio.c ¤ÇÄêµÁ¤µ¤ì¤¿
-ÈÆÍÑ´Ø¿ô¤Ç¡¢CRCÃͤò·×»»¤·¤¿¤ê´Á»ú¥³¡¼¥ÉÊÑ´¹¤ò¤·¤¿¤ê¤ò½ü¤±¤Ð¡¢fread() 
-¤ÈƱ¤¸¤Ç¤¢¤ë¡£¤Ä¤Þ¤ê¡¢¥Õ¥¡¥¤¥ë¤ÏºÇ½é¡¢
+ファイルを読み込み、各変数の初期値を設定している。注目すべきはファイル
+を読み込んだバッファの位置である。fread_crc() は、crcio.c で定義された
+汎用関数で、CRC値を計算したり漢字コード変換をしたりを除けば、fread() 
+と同じである。つまり、ファイルは最初、
 
 
-  &text[dicsiz] ¤Î°ÌÃ֤ˡ¢txtsiz-dicsiz Ê¬¤À¤±Æɤޤì¤ë¡£
+  &text[dicsiz] の位置に、txtsiz-dicsiz 分だけ読まれる。
 
 
-¤³¤È¤ò¼¨¤¹¡£¿Þ¼¨¤·¤è¤¦¡£
+ことを示す。図示しよう。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-< ½é´ü¾õÂÖ >
-                                
+< 初期状態 >
+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
@@ -543,125 +552,125 @@ hash[] 
 
                                    <------ remainder -------------->
 
 
                                    <------ remainder -------------->
 
-                                   |--- ¤³¤Î°ÌÃ֤˺ǽé¤Î  ---------|
-                                        ¥Ç¡¼¥¿¤¬Æɤޤì¤Æ¤¤¤ë
+                                   |--- この位置に最初の  ---------|
+                                        データが読まれている
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-¤Þ¤¹¤Þ¤¹¡¢text[] ¤ÎÍÑÅÓ¤¬ÉÔÌÀ¤À¤¬¡¢slide ¼­½ñË¡¤Îŵ·¿Åª¤ÊÆɤ߹þ¤ß½èÍý
-¤Î¤³¤È¤ò¹Í¤¨¤ë¤È¤¢¤ëÄøÅÙͽÁÛ¤¬¤Ä¤¯(¤½¤ì¤òÀè¤Ë¼¨¤·¤¿Êý¤¬Îɤ¤¤«¡©)¡£¤Þ¤¢¡¢
-¤³¤³¤Ç¤Ï¥Õ¡¼¥ó¤Ã¤ÈÉ¡¤ÇǼÆÀ¤·¤ÆºÑ¤Þ¤½¤¦¡£
+ますます、text[] の用途が不明だが、slide 辞書法の典型的な読み込み処理
+のことを考えるとある程度予想がつく(それを先に示した方が良いか?)。まあ、
+ここではフーンっと鼻で納得して済まそう。
 
 
-fread_crc() ¤Ï¡¢Æɤ߹þ¤ó¤À¥Ð¥Ã¥Õ¥¡Ä¹¤òÊÖ¤¹¡£remainder ¤¬¤½¤ÎÃͤǡ¢´û¤Ë
-¿Þ¼¨¤·¤Æ¤¢¤ë¡£encoded_origsize ¤Ï¡¢¥½¡¼¥¹¤ò¸«¤ë¤È¡¢¸µ¤Î¥Õ¥¡¥¤¥ë¤Î¥µ¥¤
-¥º¤òɽ¤¹¤¿¤á¤À¤±¤ÎÊÑ¿ô¤Î¤è¤¦¤À¡£°Ê¹ß¤Ï̵»ë¤·¤è¤¦¡£
+fread_crc() は、読み込んだバッファ長を返す。remainder がその値で、既に
+å\9b³ç¤ºã\81\97ã\81¦ã\81\82ã\82\8bã\80\82encoded_origsize ã\81¯ã\80\81ã\82½ã\83¼ã\82¹ã\82\92è¦\8bã\82\8bã\81¨ã\80\81å\85\83ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\81®ã\82µã\82¤
+ズを表すためだけの変数のようだ。以降は無視しよう。
 
 
-¤È¤³¤í¤Ç¡¢¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤¬¾®¤µ¤¤¾ì¹ç¿Þ¤ÎÄ̤ê¤Ë¤Ê¤é¤Ê¤¤¤Ã¤È¹Í¤¨¤ë¤«¤âÃÎ
-¤ì¤Ê¤¤¡£¤½¤ÎÄ̤ê¤Ê¤Î¤À¤¬¡¢Îã³°¾ò·ï¤Ï¾¯¤Ê¤¤Êý¤¬¥½¡¼¥¹¤ÏÍý²ò¤·¤ä¤¹¤¤¡£Ã±
-½ã¤Ê¾ì¹ç¤À¤±¤ò¹Í¤¨¤¿Êý¤¬¡¢¤¢¤ì¤³¤ì¹Í¤¨¤ò¤á¤°¤é¤¹É¬Íפ¬¤Ê¤¤¤«¤é¤À¡£¤Ê¤Ë
-¤·¤í´û¤ËÆ°¤¯¥½¡¼¥¹¤ò¸«¤Æ¤¤¤ë¤Î¤À¤«¤é¡¢ºÙ¤«¤¤¤³¤È¤ËÌܤò¤Ä¤Ö¤Ã¤Æ¤â¥¨¥ó¥Ð
-¥°¤¹¤ë¤³¤È¤Ï¤Ê¤¤¤Î¤Ç¤¢¤ë¡£¤½¤¦¤¤¤¦¤ï¤±¤Ç¡¢ÅöÌ̤Ϥ³¤Î¿Þ¤¬Í£°ì¤Î½é´ü¾õÂÖ
-¤Ç¤¢¤ë¤È¹Í¤¨¤ë¡£
+ところで、ファイルサイズが小さい場合図の通りにならないっと考えるかも知
+れない。その通りなのだが、例外条件は少ない方がソースは理解しやすい。単
+純な場合だけを考えた方が、あれこれ考えをめぐらす必要がないからだ。なに
+しろ既に動くソースを見ているのだから、細かいことに目をつぶってもエンバ
+グすることはないのである。そういうわけで、当面はこの図が唯一の初期状態
+であると考える。
 
 
-(B) ¤ÎÉôʬ¤Ï¤â¤¦¾¯¤·ÃíÌܤ¹¤Ù¤­²Õ½ê¤¬¤¢¤ë¡£
+(B) の部分はもう少し注目すべき箇所がある。
 
     matchlen = THRESHOLD - 1;
 
 
     matchlen = THRESHOLD - 1;
 
-matchlen ¤Ï¡¢¡Ö°ìÃפ·¤¿Ê¸»úÎóĹ¡×¤Ç¤¢¤ë¤ÈͽÁÛ¤·¤¿¤¬ THRESHOLD ¤ÎÃͤϠ3
-(¸ÇÄêÃÍ)¤Ç¤¢¤ë¤«¤é¡¢matchlen ¤Î½é´üÃͤϠ2 ¤À¡£¤¤¤­¤Ê¤êͽÁÛ¤¬¤Ï¤º¤ì¤¿µ¤
-¤¬¤¹¤ë¡£Í½ÁÛ¤òΩ¤Æľ¤½¤¦¡£2 ¤È¤¤¤¦Ææ¤Ê¿ôÃͤȠmatch*len* ¤Ë¤Ä¤¤¤Æ¹Í¤¨¤ë
-¤È¡¢ËÁƬ¤Ç <len, pt> ¤Î¥Ú¥¢¤Î len ¤Ï 2 ¤Ç¤¢¤ë¤³¤È¤Ï¤Ê¤¤¤ÈÀâÌÀ¤·¤¿¡£Ìµ
-°ÕÌ£¤À¤«¤é¤Ç¤¢¤ë¤¬¡¢matchlen ¤Î½é´üÃͤϤ³¤Î 2 ¤È´ØÏ¢¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤¡£
-¤½¤³¤Ç¡¢matchlen ¤ÎÍÑÅÓ¤ò°Ê²¼¤Î¤è¤¦¤ËͽÁÛ¤·¤Ê¤ª¤¹¤³¤È¤Ë¤¹¤ë¡£°Ê²¼¤Î¤è
-¤¦¤Ë¥á¥â¤ò¹¹¿·¤·¤è¤¦¡£THRESHOLD(threshold ¤ÏïçÃͤΰÕ)¤â°ì½ï¤ËͽÁÛ¤·¤¿¡£
+matchlen は、「一致した文字列長」であると予想したが THRESHOLD の値は 3
+(固定値)であるから、matchlen の初期値は 2 だ。いきなり予想がはずれた気
+がする。予想を立て直そう。2 という謎な数値と match*len* について考える
+と、冒頭で <len, pt> のペアの len は 2 であることはないと説明した。無
+意味だからであるが、matchlen の初期値はこの 2 と関連するかもしれない。
+そこで、matchlen の用途を以下のように予想しなおすことにする。以下のよ
+うにメモを更新しよう。THRESHOLD(threshold は閾値の意)も一緒に予想した。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-* matchlen      ºÇÄã¸Â°ìÃפ·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤Ä¹¤µ-1
-* THRESHOLD     ºÇÄã¸Â°ìÃפ·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤Ä¹¤µ
+* matchlen      最低限一致しなければならない長さ-1
+* THRESHOLD     最低限一致しなければならない長さ
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-¤¦¡¼¤ó¡¢ËÜÅö¤À¤í¤¦¤«¡©
+うーん、本当だろうか?
 
 
-(B) ¤Î»Ä¤ê¤ÎÉôʬ¤òÊÒÉÕ¤±¤è¤¦
+(B) の残りの部分を片付けよう
 
     pos = dicsiz;
 
     if (matchlen > remainder) matchlen = remainder;
 
 
     pos = dicsiz;
 
     if (matchlen > remainder) matchlen = remainder;
 
-pos ¤¬ dicsiz ¤Ç¤¢¤ë¤³¤È¤«¤é¤É¤¦¤ä¤é¡¢pos ¤Ï¡¢text[] ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤é
-¤·¤¤¡£Á°¤ÎͽÁۤǠpos ¤Ï¡¢prev[] ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç¤â¤¢¤ê¡¢hash[] ¤ÎÃͤÇ
-¤â¤¢¤ë¤ÈͽÁÛ¤·¤¿¤Î¤À¤¬(¤³¤ì¤Ï¤â¤Á¤í¤ó´Ö°ã¤¤¤Ç¤Ï¤Ê¤«¤í¤¦¤¬)¡£¤É¤¦¤ä¤é
-ËÜÅö¤Î°ÕÌ£¤Ï¡¢½èÍý¤¹¤ë¥Æ¥­¥¹¥È¤ÎÀèƬ¤ò¼¨¤·¤Æ¤¤¤ë¤Î¤Ç¤Ï¤Ê¤¤¤«¤È¤â»×¤¨¤ë¡£
-¤Þ¤¢¡¢¤³¤³¤Ç¤Ï̵Æñ¤Ë¡Ötext[] ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹(¤Ç¤â¤¢¤ë)¡×¤È¤À¤±Íý²ò¤·¤è¤¦¡£
-´û¤Ë¿Þ¤Ë¤Ï½ñ¤­¹þ¤ó¤Ç¤¢¤ë¡£
+pos が dicsiz であることからどうやら、pos は、text[] のインデックスら
+しい。前の予想で pos は、prev[] のインデックスでもあり、hash[] の値で
+もあると予想したのだが(これはもちろん間違いではなかろうが)。どうやら
+本当の意味は、処理するテキストの先頭を示しているのではないかとも思える。
+まあ、ここでは無難に「text[] のインデックス(でもある)」とだけ理解しよう。
+既に図には書き込んである。
 
 
-¼¡¤Î if ¤À¤¬¡¢remainder ¤¬ matchlen ¤è¤ê¤â¾®¤µ¤¤¾ì¹ç¤Î¾ò·ï¤À¡£¤Þ¤¿¡¢
-matchlen ¤ÎͽÁÛ¤¬Ê¤¤µ¤ì¤½¤¦¤Êͽ´¶¤¬¤·¤Ê¤¤¤Ç¤â¤Ê¤¤¤¬¡¢¤³¤Î if Ê¸¤Ï*Îã³°
-¾ò·ï*¤Ê¤Î¤Ç̵»ë¤¹¤ë¤³¤È¤Ë¤·¤¿¡£ÅÔ¹ç¤Î°­¤¤¤³¤È¤Ï¸«¤Ê¤¤Êý¤¬Îɤ¤¤Î¤À¡£
+次の if だが、remainder が matchlen よりも小さい場合の条件だ。また、
+matchlen の予想が覆されそうな予感がしないでもないが、この if 文は*例外
+条件*なので無視することにした。都合の悪いことは見ない方が良いのだ。
 
     /* (C) */
     hval = ((((text[dicsiz] << 5) ^ text[dicsiz + 1]) << 5) 
             ^ text[dicsiz + 2]) & (unsigned)(HSHSIZ - 1);
 
 
     /* (C) */
     hval = ((((text[dicsiz] << 5) ^ text[dicsiz + 1]) << 5) 
             ^ text[dicsiz + 2]) & (unsigned)(HSHSIZ - 1);
 
-(C) ¤Ç¤¢¤ë¡£¤³¤ì¤ÏÆñ²ò¤Ç¤¢¤ë¡£Ê£»¨¤Ê¿ô¼°¤Ï¶ì¼ê¤Ç¤¢¤ë¤¬¡¢¤¸¤Ã¤¯¤ê¹Í¤¨¤è
-¤¦¡£¤Þ¤ºµá¤á¤ëÃͤϠhval ¤Ç¤¢¤ë¡£¤³¤ì¤Ï hash[] ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ê¤Î¤À¤¬¡¢
-¤³¤Î¤è¤¦¤ÊÊ£»¨¤Ê¼°¤Çµá¤Þ¤ë¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ê¤ó¤ÆÁÛÁü¤â¤Ä¤«¤Ê¤¤¡£¤Þ¤º¡¢ºÇ½é
-¤Î¥¤¥ó¥¹¥Ô¥ì¡¼¥·¥ç¥ó¤òÂç»ö¤Ë¤¹¤ë¤³¤È¤Ë¤·¤è¤¦¡£ËÁƬ¤Ç¡¢(C) ¤Î½èÍý¤Ï¡Ö¥Ï¥Ã
-¥·¥åÃÍ hval ¤ò·×»»¤¹¤ë¡£¡×¤Ã¤È¶ì¤â¤Ê¤¯Í½ÁÛ¤·¤¿¡£¤½¤·¤Æ¤³¤ì¤Ï´Ö°ã¤¤¤Ç¤Ï
-¤Ê¤¤¤À¤í¤¦(¤­¤Ã¤È)¡£hash[] ¤È¤Î´ØÏ¢¤ò¤³¤³¤Ç¹Í¤¨¤Æ¤â¤ï¤«¤é¤Ê¤¤¤«¤é¡¢¤³
-¤Î¥Ï¥Ã¥·¥åÃͤη׻»¤À¤±¤ò¹Í¤¨¤ë¤³¤È¤Ë¤·¤è¤¦¡£
+(C) である。これは難解である。複雑な数式は苦手であるが、じっくり考えよ
+う。まず求める値は hval である。これは hash[] のインデックスなのだが、
+このような複雑な式で求まるインデックスなんて想像もつかない。まず、最初
+のインスピレーションを大事にすることにしよう。冒頭で、(C) の処理は「ハッ
+シュ値 hval を計算する。」っと苦もなく予想した。そしてこれは間違いでは
+ないだろう(きっと)。hash[] との関連をここで考えてもわからないから、こ
+のハッシュ値の計算だけを考えることにしよう。
 
 
-¼°¤ò¤¸¤Ã¤¯¤ê¸«¤Æ¤ß¤ë¡£¡£¡£¤¸¤Ã¤¯¤ê¸«¤Æ¤ß¤ë¤È°Ê²¼¤Î¤³¤È¤¬¤ï¤«¤ë¡£
+式をじっくり見てみる。。。じっくり見てみると以下のことがわかる。
 
         x(i) = text[dicsiz + i]
 
         x(i) = text[dicsiz + i]
-¤È¤¹¤ë¤È
+とすると
         hval = (( x(0) << 5
                 ^ x(1)      ) << 5
                 ^ x(2)             )
                & (unsigned)(HSHSIZ - 1);
 
         hval = (( x(0) << 5
                 ^ x(1)      ) << 5
                 ^ x(2)             )
                & (unsigned)(HSHSIZ - 1);
 
-¤Ç¤¢¤ë¡£±é»»»Ò << ¤Ï¡¢±é»»»Ò ^ ¤è¤ê¤âÍ¥Àè½ç°Ì¤¬Ä㤤¤Î¤Ç;·×¤Ê³ç¸Ì¤Ï¾Ê
-ά¤·¤¿¡£ºÇ¸å¤Î & (unsigned)(HSHSIZ - 1) ¤Ï¡¢Á°¤Ë¤â»÷¤¿¤è¤¦¤Ê¼°¤¬½Ð¤¿¤¬
-¤³¤ì¤Ï¤¢¤ëÈϰϤοôÃÍ(¤³¤³¤Ç¤Ï¡¢0 ¡Á HSHSIZ{2^15}-1)¤òÃê½Ð¤¹¤ë¤¿¤á¤Î¥Ó¥Ã
-¥È¥Þ¥¹¥¯¤Ç¤¢¤ë¡£¥Ï¥Ã¥·¥å´Ø¿ô¤È¸À¤¦¤Î¤Ï¤¢¤ëÉä¹æ¤ò¤¢¤ë½¸¹ç¤ÎÉä¹æ¤Ë¼ÌÁü¤¹
-¤ë´Ø¿ô¤Ç¤¢¤ë¤«¤é¤³¤Î¤è¤¦¤Ê¥Ó¥Ã¥È¥Þ¥¹¥¯¤ÏÅöÁ³É¬ÍפÀ¤·¡¢Îɤ¯¹Ô¤ï¤ì¤ë»ö¤À
-(ÉáÄ̤Ϡmod ÁÇ¿ô¤ò¹Ô¤¦¤ó¤À¤±¤É)¡£¤Þ¤¿¡¢hval ¤Ï¡¢hash[] ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹
-¤Ê¤Î¤À¤«¤é¡¢¼ÌÁü¤¹¤ë½¸¹ç¤È¤Ï hash[] ¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤À¡£¤ª¤Ã¡¢°Æ³°´Êñ¤Ë
-¤ï¤«¤Ã¤¿¡£x(i) ¤¬ text[dicsiz + i] ¤Ç¡¢¥Ï¥Ã¥·¥å´Ø¿ô¤ÎÊÑ¿ô¤Ï x(0),
-x(1), x(2) ¤À¤«¤é¡¢ÀèƬ¤Î 3 ¥Ð¥¤¥È¤Îʸ»úÎó(ʿʸ)¤Î¥Ï¥Ã¥·¥åÃͤòµá¤á¤Æ¤¤
-¤ë¤ï¤±¤À¡£¤½¤Î¾¤Î·×»»(<< 5 ¤È¤« ^ ¤È¤«) ¤ÏÂ礷¤¿¤³¤È¤Ç¤Ï¤Ê¤¤¡£Ìµ»ë¤·
-¤è¤¦¡£¤Þ¤¿¡¢Â³¤±¤Æ (D) ¤Î½èÍý¤â¸«¤ë¤¬¡¢
+である。演算子 << は、演算子 ^ よりも優先順位が低いので余計な括弧は省
+略した。最後の & (unsigned)(HSHSIZ - 1) は、前にも似たような式が出たが
+これはある範囲の数値(ここでは、0 〜 HSHSIZ{2^15}-1)を抽出するためのビッ
+トマスクである。ハッシュ関数と言うのはある符号をある集合の符号に写像す
+る関数であるからこのようなビットマスクは当然必要だし、良く行われる事だ
+(æ\99®é\80\9aã\81¯ mod ç´ æ\95°ã\82\92è¡\8cã\81\86ã\82\93ã\81 ã\81\91ã\81©)ã\80\82ã\81¾ã\81\9fã\80\81hval ã\81¯ã\80\81hash[] ã\81®ã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹
+なのだから、写像する集合とは hash[] のインデックスだ。おっ、案外簡単に
+わかった。x(i) が text[dicsiz + i] で、ハッシュ関数の変数は x(0),
+x(1), x(2) だから、先頭の 3 バイトの文字列(平文)のハッシュ値を求めてい
+るわけだ。その他の計算(<< 5 とか ^ とか) は大したことではない。無視し
+よう。また、続けて (D) の処理も見るが、
 
     /* (D) */
     insert();
 
 
     /* (D) */
     insert();
 
-insert() ¤Ï¡¢¹¬¤¤²òÆɤº¤ß¤Ç¤¢¤ë pos ¤ò hash[] ¤Ë³ÊǼ¤¹¤ë½èÍý¤À¡£
-ͽÁÛ¤ÎÃʳ¬¤Ç¤Ï¡¢(C) ¤È (D) ¤òÊ̸ĤνèÍý¤È¹Í¤¨¤Æ¤¤¤¿¤Î¤À¤¬¤³¤ì¤Ï
-¤É¤¦¤ä¤é¥»¥Ã¥È¤Ç¤¢¤ë¡£
+insert() は、幸い解読ずみである pos を hash[] に格納する処理だ。
+予想の段階では、(C) と (D) を別個の処理と考えていたのだがこれは
+どうやらセットである。
 
 
-   (C) pos ¤Î°ÌÃ֤Π3 Ê¸»ú¤Î¥Ï¥Ã¥·¥åÃͤò·×»»¤·
-   (D) hash[¥Ï¥Ã¥·¥åÃÍ] = pos ¤ò¹Ô¤¦
+   (C) pos の位置の 3 文字のハッシュ値を計算し
+   (D) hash[ハッシュ値] = pos を行う
 
 
-¤â¤¦¾¯¤·Ãí°Õ¿¼¤¯¸¡Æ¤¤¹¤ë¤È¡Öpos¤Î°ÌÃÖ¤Î3ʸ»ú¡×¤È¡¢µá¤á¤¿¡Ö¥Ï¥Ã¥·¥åÃÍ¡×
-¤ÏÏÀÍýŪ¤Ë¤Ï = ¤Ç¤¢¤ë¡£
+もう少し注意深く検討すると「posの位置の3文字」と、求めた「ハッシュ値」
+は論理的には = である。
 
 
-¤Ä¤Þ¤ê¡¢(C) (D) ¤Î½èÍý¤Ï
+つまり、(C) (D) の処理は
 
 
-  hash[ʸ»úÎó] = °ÌÃÖ
+  hash[文字列] = 位置
 
 
-¤È¤¤¤¦½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤ë¡£¥Ï¥Ã¥·¥åÃͤξ×ÆͤϤ³¤³¤Ç¤Ï¹Í¤¨¤Ê¤¤¡£slide ¼­½ñ
-Ë¡¤Ç¤Ï¡¢¤¢¤ëʸ»úÎó¤ËÂФ·°ÊÁ°¤½¤Îʸ»úÎ󤬸½¤ì¤¿¤«¤É¤¦¤«¤ò¸¡º÷¤·¡¢¤½¤Î°Ì
-ÃÖ¤òµá¤á¤ëɬÍפ¬¤¢¤ë¤Î¤À¤¬¡¢¤³¤ÎºÇ½é¤Î 3 Ê¸»ú¤Ë´Ø¤·¤Æ¤Ï¸½»þÅÀ¤Ç¤½¤ÎÍÑ
-·ï(°ÌÃÖ¤òµá¤á¤ë)¤òËþ¤¿¤¹»ö¤¬¤Ç¤­¤Æ¤¤¤ë¡£¤³¤³¤Þ¤Ç¤Ç¼«¤º¤È encode() ¤ÎÁ´
-ÂÎÁü¤âͽÁÛ¤¬¤Ä¤­¤½¤¦¤Êµ¤¤¬¤¹¤ë¡£
+という処理を行っている。ハッシュ値の衝突はここでは考えない。slide 辞書
+法では、ある文字列に対し以前その文字列が現れたかどうかを検索し、その位
+置を求める必要があるのだが、この最初の 3 文字に関しては現時点でその用
+件(位置を求める)を満たす事ができている。ここまでで自ずと encode() の全
+体像も予想がつきそうな気がする。
 
 
-¾×ÆͤϹͤ¨¤Ê¤¤¤Ã¤È¤·¤¿¤¬¡¢¤Á¤ç¤Ã¤È¹Í¤¨¤¿¤é¤¹¤°¤ï¤«¤Ã¤¿¡£prev[] ¤Ë¤Ï¡¢
-°ÊÁ°¤Î¥Ï¥Ã¥·¥åÃͤǵá¤á¤¿Ê¸»úÎó¤Î°ÌÃÖ¤¬Æþ¤Ã¤Æ¤¤¤ë¡£¤Ä¤Þ¤ê¡¢prev[] ¤Ï¥Ï¥Ã
-¥·¥å¤¬¾×Æͤ·¤¿¤È¤­¤Î¤¿¤á¤Î¥Ð¥Ã¥Õ¥¡¤À¡£¤³¤Î¥Ï¥Ã¥·¥å¤Ï¥Á¥§¡¼¥óË¡¤À¡£
+衝突は考えないっとしたが、ちょっと考えたらすぐわかった。prev[] には、
+以前のハッシュ値で求めた文字列の位置が入っている。つまり、prev[] はハッ
+シュが衝突したときのためのバッファだ。このハッシュはチェーン法だ。
 
 
-Î㤨¤Ð¡¢insert() ¤Ç¡¢
+例えば、insert() で、
     prev[pos] = hash[hval];
     hash[hval] = pos;
     prev[pos] = hash[hval];
     hash[hval] = pos;
-¤Ã¤È½èÍý¤ò¤·¤Æ¤¤¤ë¤Î¤À¤«¤é
+っと処理をしているのだから
 
         hash[hval] = pos1
                       |
 
         hash[hval] = pos1
                       |
@@ -672,47 +681,47 @@ insert() 
                          prev[pos2] = pos3
                                 ...
 
                          prev[pos2] = pos3
                                 ...
 
-¤È¤¤¤Ã¤¿Ãͤ¬Æþ¤ë»ö¤Ë¤Ê¤ë¡£¤¢¤ëʸ»úÎó(¤Î¥Ï¥Ã¥·¥åÃÍ) hval ¤ËÂФ·¤Æ¡¢¤½¤Î
-¼­½ñ¾å¤Î°ÌÃ֤Ϡpos1, pos2, pos3 ¤È¤¤¤¦¸õÊ䤬¤¢¤ë¤ï¤±¤À¡£¼ÂºÝ¤Ë¤É¤Î pos
-¤òÁª¤Ö¤«¤ÏÈæ³Ó¤Ë¤è¤Ã¤Æ¹Ô¤ï¤ì¤ë¤Î¤À¤í¤¦¡£
+といった値が入る事になる。ある文字列(のハッシュ値) hval に対して、その
+辞書上の位置は pos1, pos2, pos3 という候補があるわけだ。実際にどの pos
+を選ぶかは比較によって行われるのだろう。
 
 
-# ¤½¤ì¤Ë¤Ä¤±¤Æ¤â¡¢(C) ¤È (D) ¤ÎÉôʬ¤ò¸«¤ë¤À¤±¤Ç¤â¤³¤Î¥½¡¼¥¹¤¬¤Á¤ç¤Ã¤È
-# ±ø¤¤¤³¤È¤¬¤ï¤«¤ë¡£¤â¤¦¾¯¤·¡¢°ú¿ô¤È¤«Ìá¤êÃͤȤ«¹Í¤¨¤Æ¤¯¤ì¤Æ¤âÎɤ«¤Ã
-# ¤¿¤Ï¤º¤À¡£¥Ï¥Ã¥·¥å´Ø¿ô¤Ë¤·¤Æ¤â¾¯¤Ê¤¯¤È¤â¥Þ¥¯¥í¤°¤é¤¤¤Ë¤Ï¤·¤è¤¦¤è¡£
+# それにつけても、(C) と (D) の部分を見るだけでもこのソースがちょっと
+# 汚いことがわかる。もう少し、引数とか戻り値とか考えてくれても良かっ
+# たはずだ。ハッシュ関数にしても少なくともマクロぐらいにはしようよ。
 
 
-(E) ¡Á (H) ¤Ë°Ü¤í¤¦¤³¤ì¤Ï¥ë¡¼¥×¤ÎÃæ¿È¤Ç¡¢½èÍý¤ÎËÜÂê¤À¡£¤Þ¤º¥ë¡¼¥×¤Îæ
-½Ð¾ò·ï¤ò¸«¤Æ¤ß¤ë¤È
+(E) 〜 (H) に移ろうこれはループの中身で、処理の本題だ。まずループの脱
+出条件を見てみると
 
     while (remainder > 0 && ! unpackable) {
 
 
     while (remainder > 0 && ! unpackable) {
 
-remainder ¤Ï¡¢¥Ð¥Ã¥Õ¥¡¾å¤ËÆɤ߹þ¤ó¤Àʿʸ¤ÎŤµ¤Ç¤¢¤ë¤«¤é¤³¤ì¤¬¤Ê¤¯¤Ê¤ë
-¤Þ¤Ç¥ë¡¼¥×¤¹¤ë¤³¤È¤Ë¤Ê¤ë¡£¤µ¤é¤Ë unpackable ¤È¤¤¤¦¤Î¤Ï¡¢crcio.c ¤Î 
-putcode() ¤Ç¤½¤ÎÃͤòÀßÄꤷ¤Æ¤¤¤ë²Õ½ê¤¬½Ð¤ÆÍè¤ë¤Î¤À¤¬¡¢Éä¹æ²½¤·¤¿½ÐÎÏ¥µ
-¥¤¥º¤¬¸µ¤Î¥µ¥¤¥º¤ò±Û¤¨¤¿¤È¤­¤Ë¿¿¤Ë¤Ê¤ë¡£¤Ä¤Þ¤ê¡¢¤³¤ì°Ê¾å½èÍý¤·¤Æ¤â°µ½Ì
-¤Î°ÕÌ£¤¬¤Ê¤¤¤È¤ï¤«¤Ã¤¿¤é¥ë¡¼¥×¤òÈ´¤±¤ë¤ï¤±¤À¡£
+remainder は、バッファ上に読み込んだ平文の長さであるからこれがなくなる
+までループすることになる。さらに unpackable というのは、crcio.c の 
+putcode() ã\81§ã\81\9dã\81®å\80¤ã\82\92設å®\9aã\81\97ã\81¦ã\81\84ã\82\8bç®\87æ\89\80ã\81\8cå\87ºã\81¦æ\9d¥ã\82\8bã\81®ã\81 ã\81\8cã\80\81符å\8f·å\8c\96ã\81\97ã\81\9få\87ºå\8a\9bã\82µ
+イズが元のサイズを越えたときに真になる。つまり、これ以上処理しても圧縮
+の意味がないとわかったらループを抜けるわけだ。
 
 
-¤Ç¤Ï¡¢(E)¤ò¸«¤è¤¦¡£
+では、(E)を見よう。
 
         /* (E) */
         lastmatchlen = matchlen;  lastmatchoffset = pos - matchpos - 1;
         --matchlen;
 
 
         /* (E) */
         lastmatchlen = matchlen;  lastmatchoffset = pos - matchpos - 1;
         --matchlen;
 
-¤Á¤ç¤Ã¤È¸«¤¿¤À¤±¤Ç¤Ï¤ä¤Ï¤ê¤ï¤«¤é¤Ê¤¤¡£¤³¤ì¤é¤ÎÊÑ¿ô¤Ï¤Þ¤ÀͽÁÛ¤·¤«¤·¤Æ¤Ê
-¤¤¤«¤é¤Ç¤¢¤ë¡£¤¬¡¢¤ï¤«¤ë¤À¤±¤Î¾ðÊó¤Ï½ñ¤­¤·¤ë¤½¤¦¡£
+ちょっと見ただけではやはりわからない。これらの変数はまだ予想しかしてな
+いからである。が、わかるだけの情報は書きしるそう。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-* lastmatchlen    °ÊÁ°¤Î matchlen ¤ÎÃÍ (ÊÑ¿ô̾¤«¤é)
-* lastmatchoffset °ÊÁ°¥Þ¥Ã¥Á¤·¤¿°ÌÃÖ (ÊÑ¿ô̾¤«¤é)
+* lastmatchlen    以前の matchlen の値 (変数名から)
+* lastmatchoffset 以前マッチした位置 (変数名から)
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-°ÊÁ°¤ÎÃͤòlast¡Á¤ËÂàÈò¤·¡¢¿·¤¿¤ÊÃͤòÀßÄꤹ¤ë½àÈ÷¤ò¤·¤Æ¤¤¤ë¤ï¤±¤À¡£¤½¤·
-¤Æ¡¢¡Ö¿·¤¿¤ÊÃͤÎÀßÄê¡×¤Ï¡¢--matchlen ¤ÇÁ᮹Ԥï¤ì¤Æ¤¤¤ë¡£¤·¤«¤·¡¢¡Ö¥Þ¥Ã
-¥Á¤·¤¿Ä¹¤µ¡×¤ò¤Þ¤À²¿¤â¤·¤Æ¤Ê¤¤¤Î¤Ë -1 ¤¹¤ë¤È¤¤¤¦¤Î¤Ï¤¤¤Ã¤¿¤¤¤É¤¦¤¤¤¦¤³
-¤È¤À¤í¤¦¡© matchlen ¤Ï¥ë¡¼¥×¤ÎƬ¤Ç 2 ¤ËÀßÄꤵ¤ì¤Æ¤¤¤ë¡£¤³¤ì¤¬ 1 ¤Ë¤Ê¤Ã
-¤¿¡£ËÜÅö¤Î½é´üÃͤϠ1 ¤Ê¤Î¤«¡©
+以前の値をlast〜に退避し、新たな値を設定する準備をしているわけだ。そし
+て、「新たな値の設定」は、--matchlen で早速行われている。しかし、「マッ
+チした長さ」をまだ何もしてないのに -1 するというのはいったいどういうこ
+とだろう? matchlen はループの頭で 2 に設定されている。これが 1 になっ
+た。本当の初期値は 1 なのか?
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-< ³ÆÊÑ¿ô¤Î½é´üÃÍ >
+< 各変数の初期値 >
 
   matchlen = 1
   matchpos = 0
 
   matchlen = 1
   matchpos = 0
@@ -722,16 +731,16 @@ putcode() 
   lastmatchoffset = dicsiz - 1  (pos - matchpos - 1)
 ----------------------------------------------------------------------------
 
   lastmatchoffset = dicsiz - 1  (pos - matchpos - 1)
 ----------------------------------------------------------------------------
 
-¤³¤Î (E) ¤Ï¤Þ¤¿¸å¤Ç¸«¤ë»ö¤Ë¤Ê¤ë¤À¤í¤¦¡£
+この (E) はまた後で見る事になるだろう。
 
 
-(F) (G) ¤Ç¤¢¤ë¡£¤Þ¤¿¡¢¤½¤Îľ¸å¤Ë¤Ï°ÊÁ°¤Ë¤â¸«¤¿¶­³¦¾ò·ï¤¬¤¢¤ë¡£
+(F) (G) である。また、その直後には以前にも見た境界条件がある。
 
         /* (F) */    /* (G) */
         get_next();  match_insert();
         if (matchlen > remainder) matchlen = remainder;
 
 
         /* (F) */    /* (G) */
         get_next();  match_insert();
         if (matchlen > remainder) matchlen = remainder;
 
-if Ê¸ ¤Ï̵»ë¤·¤Æ´Ø¿ô¤ÎÃæ¿È¤À¤±¤òÄɤ¤¤«¤±¤Æ¤ß¤è¤¦¡£¤Þ¤º¡¢get_next() ¤³
-¤ì¤Ï ¼¡¤Î token ¤ò¼è¤Ã¤Æ¤¯¤ë½èÍý¤À¤ÈͽÁÛ¤·¤Æ¤¢¤ë¡£¤Ï¤¿¤·¤Æ¤É¤¦¤À¤í¤¦¤«¡©
+if 文 は無視して関数の中身だけを追いかけてみよう。まず、get_next() こ
+れは 次の token を取ってくる処理だと予想してある。はたしてどうだろうか?
 
 static void get_next()
 {
 
 static void get_next()
 {
@@ -742,10 +751,10 @@ static void get_next()
     hval = ((hval << 5) ^ text[pos + 2]) & (unsigned)(HSHSIZ - 1);
 }
 
     hval = ((hval << 5) ^ text[pos + 2]) & (unsigned)(HSHSIZ - 1);
 }
 
-remainder ¤ò¾ÃÈñ¤·¡¢pos ¤ò¿Ê¤á¤Æ¤¤¤ë¡£Í½ÁÛÄ̤ê¤À¡£¤Ò¤È¤Þ¤º if ¤Î¾ò·ï¤Ï
-̵»ë¤¹¤ë¤È¡¢Ä¾¸å¤Ç hash Ãͤòµá¤áľ¤·¤Æ¤¤¤ë¡£¤³¤Î¥Ï¥Ã¥·¥å´Ø¿ô¤Ï¡¢°ÊÁ°¤Î¥Ï¥Ã
-¥·¥åÃͤòÍøÍѤ·¤Æ¤¤¤ë¤¬¡¢¤³¤ì¤Ï pos ¤¬°ÊÁ°¤è¤ê + 1 ¤µ¤ì¤Æ¤¤¤ë¤³¤È¤ò¹Í¤¨
-¤ë¤È´ØÏ¢¤¬¸«¤¨¤ÆÍè¤ë¡£°ÊÁ°¤Îhash´Ø¿ô¤ò pos ¤Î´Ø¿ô¤È¤·¤Æ½ñ¤­Ä¾¤¹¤È
+remainder を消費し、pos を進めている。予想通りだ。ひとまず if の条件は
+無視すると、直後で hash 値を求め直している。このハッシュ関数は、以前のハッ
+シュ値を利用しているが、これは pos が以前より + 1 されていることを考え
+ると関連が見えて来る。以前のhash関数を pos の関数として書き直すと
 
         x(pos+i) = text[pos + i]
 
 
         x(pos+i) = text[pos + i]
 
@@ -754,20 +763,20 @@ remainder 
                      ^ x(pos+2)             )
                     & (unsigned)(HSHSIZ - 1);
 
                      ^ x(pos+2)             )
                     & (unsigned)(HSHSIZ - 1);
 
-¤Ç¤¢¤ê¡¢¤Þ¤¿¡¢º£Å٤Υϥå·¥å´Ø¿ô¤Ï¡¢
+であり、また、今度のハッシュ関数は、
 
         hval(pos+1) = ( hval(pos) << 5
                        ^ x(pos+1 + 2)  )
                       & (unsigned)(HSHSIZ - 1);
 
 
         hval(pos+1) = ( hval(pos) << 5
                        ^ x(pos+1 + 2)  )
                       & (unsigned)(HSHSIZ - 1);
 
-¤À¡¢ÈË»¨¤Ê¤Î¤Ç & (HSHSIZE-1) ¤ò³°¤¹¤È¡¢
+だ、繁雑なので & (HSHSIZE-1) を外すと、
 
         hval(pos+1) = (( x(pos+0) << 5
                        ^ x(pos+1)      ) << 5
                        ^ x(pos+2)             ) << 5
                        ^ x(pos+3)
 
 
         hval(pos+1) = (( x(pos+0) << 5
                        ^ x(pos+1)      ) << 5
                        ^ x(pos+2)             ) << 5
                        ^ x(pos+3)
 
-¤Ã¤È¤Ê¤ë¡£¤³¤Î¼¡ get_next() ¤¬¸Æ¤Ó½Ð¤µ¤ì¤ì¤Ð¡¢
+っとなる。この次 get_next() が呼び出されれば、
 
         hval(pos+2) = ((( x(pos+0) << 5
                         ^ x(pos+1)      ) << 5
 
         hval(pos+2) = ((( x(pos+0) << 5
                         ^ x(pos+1)      ) << 5
@@ -775,29 +784,29 @@ remainder 
                         ^ x(pos+3)                    ) << 5
                         ^ x(pos+4)
 
                         ^ x(pos+3)                    ) << 5
                         ^ x(pos+4)
 
-¤Ç¤¢¤ë¡£½ç¤Ë¥Ï¥Ã¥·¥åÃͤòµá¤á¤ëʸ»úÎóŤòÁý¤ä¤·¤Æ¤¤¤ë¡£¤È¤Ë¤«¤¯¡¢
-get_next() ¤Ï¡¢pos ¤ò¿Ê¤á¡¢remainder ¤ò½Ì¤á¡¢¿·¤¿¤Ê(°ÊÁ°¤è¤ê1ʸ»úŤ¤
-ʸ»úÎó¤Î¥Ï¥Ã¥·¥åÃÍ hval ¤òµá¤á¤ë´Ø¿ô¤Î¤è¤¦¤À¡£
+である。順にハッシュ値を求める文字列長を増やしている。とにかく、
+get_next() は、pos を進め、remainder を縮め、新たな(以前より1文字長い
+文字列のハッシュ値 hval を求める関数のようだ。
 
 
-¤·¤«¤·¡¢¤¤¤Ä¤Þ¤Ç¤â hash Ãͤθµ¤È¤Ê¤ëʸ»úÎó¤ò¿­¤Ð¤·¤Æ¤â¤·¤ç¤¦¤¬¤Ê¤¤¤À¤í
-¤¦¡£hval ¤Ï¤É¤³¤«¤Ç¤Þ¤¿¥ê¥»¥Ã¥È¤µ¤ì¤ë¤Ï¤º¤À¡£¤Ã¤È»×¤Ã¤Æ¥½¡¼¥¹¤òõ¤·¤Æ
-¤ß¤¿¤¬¤½¤Î¤è¤¦¤Ê²Õ½ê¤Ï¸«Åö¤¿¤é¤Ê¤¤¡£¤Ê¤¼¤À¤í¤¦¡©¹Í¤¨¤Æ¤ß¤ë¡¦¡¦¡¦ºÇ½é¤Ï
-¤ï¤«¤é¤Ê¤«¤Ã¤¿¤¬¿ô¼°¤ò¤è¤¯¸«¤Æ¤ß¤¿¤é¤ï¤«¤Ã¤¿¡£<< 5 ¤¬¸°¤À¡¢hval(pos+2) 
-¤Î¼°¤ò¸«¤ë¤È x(pos+0) ¤Ï¡¢<< 5 ¤¬¡¢4²ó¤â¹Ô¤ï¤ì¤Æ¤¤¤ë¤Ä¤Þ¤ê¡¢20¥Ó¥Ã¥È¤Î
-¥·¥Õ¥È¤À¡£hval(pos+3) ¤Ê¤é¡¢25¥Ó¥Ã¥È¡¢hval(pos+4) ¤Ê¤é 30 ¥Ó¥Ã¥È¤Î¥·¥Õ
-¥È¤À¡£¤µ¤¹¤¬¤Ë¤³¤ì¤À¤±¥·¥Õ¥È¤¹¤ì¤Ð¡¢x(pos+0)¤Î¾ðÊó¤Ï¾Ã¤¨¤Æ¤â¤¤¤¤¤À¤í¤¦¡£
+しかし、いつまでも hash 値の元となる文字列を伸ばしてもしょうがないだろ
+う。hval はどこかでまたリセットされるはずだ。っと思ってソースを探して
+みたがそのような箇所は見当たらない。なぜだろう?考えてみる・・・最初は
+わからなかったが数式をよく見てみたらわかった。<< 5 が鍵だ、hval(pos+2) 
+の式を見ると x(pos+0) は、<< 5 が、4回も行われているつまり、20ビットの
+シフトだ。hval(pos+3) なら、25ビット、hval(pos+4) なら 30 ビットのシフ
+トだ。さすがにこれだけシフトすれば、x(pos+0)の情報は消えてもいいだろう。
 
 
-¼ÂºÝ¡¢hval ¤Ï²¿Ê¸»úʬ¤Î¾ðÊó¤ò»ý¤Ä¤Î¤À¤í¤¦¡©hval ¤Ï¡¢unsigned int ¤Ç¡¢
-ÉáÄÌ 32 bit ¤Ç¤¢¤ë¤«¤é¡¢6.4 Ê¸»úʬ¤À¤í¤¦¤«¡©¤¤¤ä¡¢¼ÂºÝ¤Ë¤Ï¥Ï¥Ã¥·¥åÃͤÎ
-·×»»»þ¤ËHSHSIZ (15bit) ¤Ç¥Þ¥¹¥¯¤ò¤«¤±¤Æ¤¤¤ë¤«¤é 15 bit ¤Î¾ðÊó¤·¤«»ý¤¿
-¤Ê¤¤¡£¤Ä¤Þ¤ê¡¢3ʸ»ú¤À¡£¥Ó¥Ã¥È·×»»¤Ï¶ì¼ê¤Ê¤Î¤Ç¿Þ¼¨¤·¤Æ³Îǧ¤·¤è¤¦¡£
+実際、hval は何文字分の情報を持つのだろう?hval は、unsigned int で、
+普通 32 bit であるから、6.4 文字分だろうか?いや、実際にはハッシュ値の
+計算時にHSHSIZ (15bit) でマスクをかけているから 15 bit の情報しか持た
+ない。つまり、3文字だ。ビット計算は苦手なので図示して確認しよう。
 
                  15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
           hval  |--|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
 
                  15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
           hval  |--|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
-ºÇ½é¤Î hval(0) ¤Ï¡¢x(0), x(1), x(2) ¤ËÂФ·¤Æ¡¢
+最初の hval(0) は、x(0), x(1), x(2) に対して、
 
                     <---  5 -----> <---  5 -----> <---  5 ----->
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
                     <---  5 -----> <---  5 -----> <---  5 ----->
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
@@ -808,53 +817,53 @@ get_next() 
     x(2)         --                       x  x  x  x  x  x  x  x
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
     x(2)         --                       x  x  x  x  x  x  x  x
                 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
-¤ÎÇÓ¾ŪÏÀÍýϤǤ¢¤ë¡£hval(0) ¤Î»þÅÀ¤Ç x(0) ¤Î¾ðÊó¤Ï 5 ¥Ó¥Ã¥È»Ä¤Ã¤Æ¤¤
-¤ë¤¬ hval(1) ¤Ë¤Ê¤ì¤Ð¾Ã¤¨¤Æ¤·¤Þ¤¦¤Î¤Ï¼«ÌÀ¤Ç¤¢¤ë¡£¤É¤¦¤Ë¤âºÇ½é¤Îʸ»ú¤Ë
-´Ø¤·¤Æ¤Ï 5 ¥Ó¥Ã¥È¤·¤«¾ðÊó¤ò»ÈÍѤ·¤Ê¤¤¤È¸À¤¦¤Î¤¬µ¤»ý°­¤¤¤Î¤À¤¬¡¢15 bit 
-¥µ¥¤¥º¤ÎÊÑ¿ô hval ¤Ë¤Ï¡¢²áµî 3 Ê¸»úʬ¤Î¾ðÊó¤·¤«ÊÝ»ý¤µ¤ì¤Ê¤¤¤Î¤Ï´Ö°ã¤¤
-¤Ê¤¤¡£get_next() ¤Î½èÍý¤ò¸«¤ì¤Ð¡¢°ÌÃÖ pos ¤ËÂФ·¤Æ¡¢hval ¤Ï¾ï¤Ë pos,
-pos+1, pos+2 ¤Î¾ðÊó¤·¤«»ý¤¿¤Ê¤¤¤ï¤±¤À¡£¤³¤ì¤Ï½ÅÍפÀ¡£¥á¥â¤·¤è¤¦
+の排他的論理和である。hval(0) の時点で x(0) の情報は 5 ビット残ってい
+るが hval(1) になれば消えてしまうのは自明である。どうにも最初の文字に
+関しては 5 ビットしか情報を使用しないと言うのが気持悪いのだが、15 bit 
+サイズの変数 hval には、過去 3 文字分の情報しか保持されないのは間違い
+ない。get_next() の処理を見れば、位置 pos に対して、hval は常に pos,
+pos+1, pos+2 の情報しか持たないわけだ。これは重要だ。メモしよう
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
- * hval  hash[]¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¡£¸½ºß°ÌÃÖ pos ¤ËÂФ·¤Æ¡¢
-         text[pos], text[pos+1], text[pos+2] ¤Î¥Ï¥Ã¥·¥åÃͤǡ¢ÏÀÍýŪ¤Ë¤Ï
+ * hval  hash[]のインデックス。現在位置 pos に対して、
+         text[pos], text[pos+1], text[pos+2] のハッシュ値で、論理的には
              hval == text[pos] + text[pos+1] + text[pos+2]
              hval == text[pos] + text[pos+1] + text[pos+2]
-         ¤ÈƱµÁ
+         と同義
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-¤È¤³¤í¤Ç¡¢Á°²ó¡¢hval ¤Î·×»»¤Èinsert() ¤Ï¥»¥Ã¥È¤À¤È¸À¤Ã¤¿¡£º£²ó¤Ï¤É¤¦¤À
-¤í¤¦¡©¼¡¤Î match_insert() ¤ò¸«¤Æ¤ß¤ë¡£
+ところで、前回、hval の計算とinsert() はセットだと言った。今回はどうだ
+ろう?次の match_insert() を見てみる。
 
 static void match_insert()
 {
 
 static void match_insert()
 {
-    ... ¾Êά ...
+    ... 省略 ...
 
     prev[pos & (dicsiz - 1)] = hash[hval];
     hash[hval] = pos;
 }
 
 
     prev[pos & (dicsiz - 1)] = hash[hval];
     hash[hval] = pos;
 }
 
-¡¦¡¦¡¦¶¯Å¨¤Ç¤¢¤Ã¤¿¡£¶¯Å¨¤¹¤®¤¿¤Î¤Çƨ¤²¤Æ¡¢ºÇ¸å¤Î2 ¹Ô¤À¤±¤ËÃåÌܤ·¤¿¡£¤³
-¤ì¤Ï¡¢insert()¤ÈƱ¤¸¤À¡£Í½ÁÛ¤ÏÅö¤¿¤Ã¤Æ¤¤¤ë¡£get_next() ¤Ç hval ¤ò¹¹¿·
-¤·¤¿¸å¤Ï¡¢¤³¤Î match_insert() ¤Ç¡¢prev[] ¤È hash[] ¤ò¹¹¿·¤¹¤ë¤ï¤±¤À¡£
-¤½¤·¤Æ¡¢match_insert() ¤Î¾Êά¤·¤¿Éôʬ¤Ï¡¢¤É¤¦¤ä¤é matchpos, matchlen,
-too_flag ¤ò¹¹¿·¤·¤Æ¤¤¤ë¤À¤±¤Î¤è¤¦¤À¡£¤³¤ì¤¬ËÜÅö¤Ê¤é match_insert()¤Ç¡¢
-insert()¤Î½èÍý¤ò¤»¤º¡¢´Ø¿ô¤òʬ¤±¤ë¤«¤·¤¿Êý¤¬Îɤµ¤½¤¦¤À¡£(¿¿µ¶¤ÎÄø¤Ï¾Ü
-ºÙ¤ò¸«¤Æ¤«¤é¤Ë¤Ê¤ë)
+・・・強敵であった。強敵すぎたので逃げて、最後の2 行だけに着目した。こ
+れは、insert()と同じだ。予想は当たっている。get_next() で hval を更新
+した後は、この match_insert() で、prev[] と hash[] を更新するわけだ。
+そして、match_insert() の省略した部分は、どうやら matchpos, matchlen,
+too_flag を更新しているだけのようだ。これが本当なら match_insert()で、
+insert()の処理をせず、関数を分けるかした方が良さそうだ。(真偽の程は詳
+細を見てからになる)
 
 
-¤ª¤â¤à¤í¤Ë¸å³¤Î½èÍý (H) ¤ò¸«¤ë¤È¡¢
+おもむろに後続の処理 (H) を見ると、
 
         /* (H) */
         if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD) {
 
 
         /* (H) */
         if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD) {
 
-¤³¤ì¤¬¿¿¤Ê¤é¡Ö¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾õÂ֡פÈͽÁÛ¤·¤¿(¤Ê¤¼¤À¤í¡©)¡£¤½¤·¤Æ¡¢
-lastmatchlen ¤Ï½é´ü¾õÂ֤ǤϠ2 ¤Ç¤¢¤ë¡£Í½ÁÛ¤·¤¿¾ò·ï¤ÏµÕ¤«¡© matchlen ¤Þ
-¤ï¤ê¤ÏͽÁۤФ«¤ê¤Ç¿Ê¤á¤¹¤®¤¿¡£¤½¤·¤Æ¤É¤¦¤ä¤é match_insert() ¤òÆɤߤȤ«
-¤Ê¤±¤ì¤Ð¤³¤ÎÀè¤âʬ¤«¤é¤º¤¸¤Þ¤¤¤Ë¤Ê¤ê¤½¤¦¤À¡£
+これが真なら「見つからなかった状態」と予想した(なぜだろ?)。そして、
+lastmatchlen は初期状態では 2 である。予想した条件は逆か? matchlen ま
+わりは予想ばかりで進めすぎた。そしてどうやら match_insert() を読みとか
+なければこの先も分からずじまいになりそうだ。
 
 
-¤³¤Î¤Þ¤Þ match_insert() ¤ò¾ÜºÙ¤Ë²òÀϤ¹¤ë»ö¤Ë¤·¤è¤¦¡£match_insert()
-¤ò¤¹¤Ù¤ÆºÆ·Ç¤¹¤ë¡£
+このまま match_insert() を詳細に解析する事にしよう。match_insert()
+をすべて再掲する。
 
 
-/* ¸½ºß¤Îʸ»úÎó¤ÈºÇĹ°ìÃפ¹¤ëʸ»úÎó¤ò¸¡º÷¤·¡¢¥Á¥§¡¼¥ó¤ËÄɲ乤ë */
+/* 現在の文字列と最長一致する文字列を検索し、チェーンに追加する */
 
 static void match_insert()
 {
 
 static void match_insert()
 {
@@ -907,7 +916,7 @@ static void match_insert()
     hash[hval] = pos;
 }
 
     hash[hval] = pos;
 }
 
-¤Þ¤º¡¢½é´ü²½Éôʬ¤ÎÁ°È¾
+まず、初期化部分の前半
 
     max = maxmatch; /* MAXMATCH; */
     if (matchlen < THRESHOLD - 1) matchlen = THRESHOLD - 1;
 
     max = maxmatch; /* MAXMATCH; */
     if (matchlen < THRESHOLD - 1) matchlen = THRESHOLD - 1;
@@ -915,30 +924,30 @@ static void match_insert()
 
     off = 0;
 
 
     off = 0;
 
-maxmatch ¤Ï¡¢¸ÇÄêÃͤǠ256 ¤À¡¢¤À¤«¤é max ¤â 256
-2¹ÔÌܤΠif Ê¸¤Ï¡¢¤³¤ì¤Þ¤Ç¤·¤Ä¤³¤¤¤¯¤é¤¤¤Ë½Ð¤ÆÍ褿¾ò·ï¤Ë»÷¤Æ¤¤¤ë¤¬¡¢º£
-²ó¤Ï¾ò·ï¤òËþ¤¿¤¹¤é¤·¤¤¡£¤³¤ì¤Þ¤Ç¤Ï¡¢
+maxmatch は、固定値で 256 だ、だから max も 256
+2行目の if 文は、これまでしつこいくらいに出て来た条件に似ているが、今
+回は条件を満たすらしい。これまでは、
 
     if (matchlen > remainder) matchlen = remainder;
 
 
     if (matchlen > remainder) matchlen = remainder;
 
-¤È¤¤¤¦¾ò·ï¤À¤Ã¤¿¡£¤½¤·¤Æº£²ó¤Ï¡¢
+という条件だった。そして今回は、
 
     if (matchlen < THRESHOLD - 1) matchlen = THRESHOLD - 1;
 
 
     if (matchlen < THRESHOLD - 1) matchlen = THRESHOLD - 1;
 
-¤À¤«¤é¡¢Á´ÂÎŪ¤Ë matchlen ¤ÎÃͤϡ¢
+だから、全体的に matchlen の値は、
 
     THRESHOLD-1 <= matchlen <= remainder
 
 
     THRESHOLD-1 <= matchlen <= remainder
 
-¤Ä¤Þ¤ê¡¢
+つまり、
 
 
-              2 <= matchlen <= ¥Ð¥Ã¥Õ¥¡¤Ë»Ä¤Ã¤¿¥Æ¥­¥¹¥ÈĹ
+              2 <= matchlen <= バッファに残ったテキスト長
 
 
-¤ÎÈϰϤËǼ¤á¤é¤ì¤ë¤è¤¦¤À¡£¤³¤³¤Ç¤Ï¡¢matchlen ¤Ï²¼¸ÂÃͤò²¼²ó¤ë¤Î¤Ç2 ¤Ë
-ÀßÄꤵ¤ì¤ë¡£¼¡¤Ë matchpos, off ¤¬½é´ü²½¤µ¤ì¡£°Ê²¼¤Î¿Þ¤Î¾õÂ֤ˤʤ롣
-(pos, remainder ¤Ï¡¢get_next() ¤Ç¹¹¿·¤µ¤ì¤Æ¤¤¤ë¤³¤È¤ËÃí°Õ)
+の範囲に納められるようだ。ここでは、matchlen は下限値を下回るので2 に
+設定される。次に matchpos, off が初期化され。以下の図の状態になる。
+(pos, remainder は、get_next() で更新されていることに注意)
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-                                
+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
@@ -950,43 +959,43 @@ maxmatch 
 
                                      <------ remainder ------------>
 
 
                                      <------ remainder ------------>
 
-                                   |--- ¤³¤Î°ÌÃ֤˺ǽé¤Î  ---------|
-                                        ¥Ç¡¼¥¿¤¬Æɤޤì¤Æ¤¤¤ë
+                                   |--- この位置に最初の  ---------|
+                                        データが読まれている
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-½é´ü²½Éôʬ¤Î¸åȾ
+初期化部分の後半
 
     for (h = hval; too_flag[h] && off < maxmatch - THRESHOLD; ) {
         h = ((h << 5) ^ text[pos + (++off) + 2]) & (unsigned)(HSHSIZ - 1);
     }
     if (off == maxmatch - THRESHOLD) off = 0;
 
 
     for (h = hval; too_flag[h] && off < maxmatch - THRESHOLD; ) {
         h = ((h << 5) ^ text[pos + (++off) + 2]) & (unsigned)(HSHSIZ - 1);
     }
     if (off == maxmatch - THRESHOLD) off = 0;
 
-h ¤Ï¡¢too_flag[] ¤¬º£¤Î¤È¤³¤í¤¹¤Ù¤Æ0¤À¤«¤é hval ¤À¡£(too_flag ¤Ï¡¢h ¤Ä
-¤Þ¤ê hval ¤ò¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ë¼è¤ë¤é¤·¤¤¡£hash[] ¤ÈƱ¤¸¤À¡£ºÆ·Ç¤Ï¤·¤Ê¤¤¤¬
-¥á¥â¤Ë½ñ¤­²Ã¤¨¤Æ¤ª¤³¤¦)
+h は、too_flag[] が今のところすべて0だから hval だ。(too_flag は、h つ
+まり hval をインデックスに取るらしい。hash[] と同じだ。再掲はしないが
+メモに書き加えておこう)
 
 
-off ¤Ï¡¢pos ¤Î°ÌÃÖ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¤Î¤è¤¦¤À(h ¤ò¹¹¿·¤¹¤ë for Ê¸¤ÎÃæ¿È¤«
-¤é)¡£¿Þ¤â¤½¤Î°ÌÃ֤˽ñ¤¤¤¿¡£ºÇ¸å¤Î if Ê¸¤Ï off ¤¬¾å¸Â¤Ë㤷¤¿¾ì¹ç¤Ë0 ¤Ë
-ºÆ½é´ü²½¤·¤Æ¤¤¤ë¡£¤è¤¯¤ï¤«¤é¤Ê¤¤¤Î¤Ç̵»ë¤·¤è¤¦¡£for Ê¸¤ÎÃæ¿È¤«¤éh ¤ä 
-off ¤ÎÍÑÅӤϤɤ¦¤âÀèÆɤߤ·¤¿¥Ï¥Ã¥·¥åÃͤȤ½¤ÎÀèÆɤߤΰÌÃ֤ʤΤǤϤʤ¤¤«
-¤ÈÁÛÁü¤¹¤ë¡£too_flag[] ¤Î¾õÂ֤ˤè¤Ã¤ÆÀèÆɤߤ¹¤Ù¤­Ãͤ¬ÊѤï¤ë¤Î¤À¤í¤¦¤«¡©
+off は、pos の位置からのオフセットのようだ(h を更新する for 文の中身か
+ら)。図もその位置に書いた。最後の if 文は off が上限に達した場合に0 に
+再初期化している。よくわからないので無視しよう。for 文の中身からh や 
+off の用途はどうも先読みしたハッシュ値とその先読みの位置なのではないか
+と想像する。too_flag[] の状態によって先読みすべき値が変わるのだろうか?
 
 
-¤È¤Ë¤«¤¯½èÍý¤ÎËÜÂê¤ËÆþ¤ë»ö¤Ë¤·¤è¤¦¡£¤Þ¤º¡¢¤³¤Î´Ø¿ô¤Ë¸½¤ì¤ë¶É½êÊÑ¿ô¤òÎó
-µó¤·¤Æ¤ª¤³¤¦
+とにかく処理の本題に入る事にしよう。まず、この関数に現れる局所変数を列
+挙しておこう
 
     unsigned int scan_pos, scan_end, len;
     unsigned char *a, *b;
     unsigned int chain, off, h, max;
 
 
     unsigned int scan_pos, scan_end, len;
     unsigned char *a, *b;
     unsigned int chain, off, h, max;
 
-off, h, max ¤Ï¤¹¤Ç¤Ë½Ð¤ÆÍ褿¤Î¤Ç»Ä¤ê¤Ï
+off, h, max はすでに出て来たので残りは
 
   scan_pos, scan_end, len, a, b, chain
 
 
   scan_pos, scan_end, len, a, b, chain
 
-¤À¡¢¤³¤ì¤À¤±¤ÎÊÑ¿ô¤Î°ÕÌ£¤ò²òÆɤ·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÊÑ¿ô¤Ï¾õÂÖ¤òɽ¤¹¤«¤é¡¢
-¤½¤Î¿ô¤¬Â¿¤¤¤È¸À¤¦¤Î¤Ï¤½¤ì¤À¤±Ê£»¨¤Ê½èÍý¤À¤È¤¤¤¦¤³¤È¤À¡£¤á¤²¤ë¡£
+だ、これだけの変数の意味を解読しなくてはならない。変数は状態を表すから、
+その数が多いと言うのはそれだけ複雑な処理だということだ。めげる。
 
 
-¤³¤Î´Ø¿ô¤Î¥á¥¤¥ó¤È¤Ê¤ë¥ë¡¼¥×¤ÎÃæ¤ò¤¶¤Ã¤Èį¤á¤Æ¤ß¤ë¤µ¤é¤ËÆâÉô¤Ë¥ë¡¼¥×¤¬
-¤¢¤ë¡£¤Ò¤È¤Þ¤º¡¢Æó½Å¥ë¡¼¥×¤ÎÃæ¿È¤ò¾Êά¤·¤è¤¦¡£
+この関数のメインとなるループの中をざっと眺めてみるさらに内部にループが
+ある。ひとまず、二重ループの中身を省略しよう。
 
     for (;;) {
         chain = 0;
 
     for (;;) {
         chain = 0;
@@ -995,7 +1004,7 @@ off, h, max 
 
         while (scan_pos > scan_end) {
             chain++;
 
         while (scan_pos > scan_end) {
             chain++;
-            ... ά ...
+            ...  ...
         }
 
         if (chain >= LIMIT)
         }
 
         if (chain >= LIMIT)
@@ -1008,19 +1017,19 @@ off, h, max 
         h = hval;
     }
 
         h = hval;
     }
 
-¤Þ¤º¡¢Á°È¾Éôʬ¤«¤é
+まず、前半部分から
 
         chain = 0;
         scan_pos = hash[h];
         scan_end = (pos > dicsiz) ? pos + off - dicsiz : off;
 
 
         chain = 0;
         scan_pos = hash[h];
         scan_end = (pos > dicsiz) ? pos + off - dicsiz : off;
 
-chain, scan_pos, scan_end ¤Ï¤¹¤Ù¤Æ while ¥ë¡¼¥×¤ËÅϤµ¤ì¤ë¤Ù¤­ÊÑ¿ô¤À¡£
-¤µ¤é¤Ë¡¢while ¤Î¸å¤Ë¤Ï¡¢scan_pos, scan_end ¤Ï¸½¤ì¤Ê¤¤¤«¤é(²¾¤Ë while 
-¥ë¡¼¥×¤¬1¤Ä¤Î´Ø¿ô¤À¤Ã¤¿¤È¤¹¤ë¤È)¤³¤ì¤é¤Ï while ¥ë¡¼¥×Éô¤Î°ú¿ô(ÆþÎÏ)¤À¡£
-¤³¤Î2¤Ä¤ÎÊÑ¿ô¤Ï¤É¤¦¤ä¤ê¤¯¤ê¤·¤è¤¦¤È¤â¡¢while ¥ë¡¼¥×ÉôÆâ¤Î¾õÂÖ¤·¤«É½¤µ
-¤Ê¤¤¤Î¤Ç¡¢¤³¤³¤Ç¤Ï̵»ë¤·¤è¤¦¡£
+chain, scan_pos, scan_end はすべて while ループに渡されるべき変数だ。
+さらに、while の後には、scan_pos, scan_end は現れないから(仮に while 
+ループが1つの関数だったとすると)これらは while ループ部の引数(入力)だ。
+この2つの変数はどうやりくりしようとも、while ループ部内の状態しか表さ
+ないので、ここでは無視しよう。
 
 
-while ¥ë¡¼¥×¤Î¸å¤ò¸«¤Æ¤ß¤ë¤È
+while ループの後を見てみると
 
         if (chain >= LIMIT)
             too_flag[h] = 1;
 
         if (chain >= LIMIT)
             too_flag[h] = 1;
@@ -1031,107 +1040,107 @@ while 
         off = 0;
         h = hval;
 
         off = 0;
         h = hval;
 
-chain ¤¬ LIMIT¤ò±Û¤¨¤¿¾ì¹ç¡¢too_flag[h] = 1 ¤È¤·¤Æ¤¤¤ë¡£chain ¤Ï¡¢¤¶¤Ã
-¤È¸«¤Æ¡¢while ¥ë¡¼¥×¤Î¥«¥¦¥ó¥¿¤é¤·¤¤¤¬¡¢LIMIT ¤Ï 0x100 ¤À¡£¤É¤¦¤Ë¤âÎã
-³°¾ò·ï¤Ã¤Ý¤¤(LIMIT¤È¤¤¤¦Ì¾Á°¤ä¿ôÃͤ¬¤½¤¦»×¤ï¤»¤ë)¤Î¤Ç¤³¤³¤Ç¤Ï̵»ë¤·¤è
-¤¦¡£while ¥ë¡¼¥×¤¬ 256°Ê¾å²ó¤ë²ÄǽÀ­¤¬¤¢¤ëÅÀ¤À¤±¿´¤Ë¤È¤É¤á¤Æ¤ª¤³¤¦¡£
+chain が LIMITを越えた場合、too_flag[h] = 1 としている。chain は、ざっ
+と見て、while ループのカウンタらしいが、LIMIT は 0x100 だ。どうにも例
+外条件っぽい(LIMITという名前や数値がそう思わせる)のでここでは無視しよ
+う。while ループが 256以上回る可能性がある点だけ心にとどめておこう。
 
 
-¼¡¤Î¾ò·ï¤Ç¤Ï¡¢matchlen ¤È off ¤¬¾ò·ïȽÃǤµ¤ì¤Æ¤¤¤ë¡£¤È¤¤¤¦¤³¤È¤Ï¤³¤Î¤É
-¤Á¤é¤«¡¢¤¢¤ë¤¤¤ÏξÊý¤Ï while ¥ë¡¼¥×¤ÎÊÖ¤êÃÍ(½ÐÎÏ)¤À¡£¤¶¤Ã¤È 
-match_insert()Á´ÂΤò¸«¤Æ¤ß¤ë¤È off ¤ÏºÇ½é¤È¤³¤Îľ¸å¤Ç¤·¤«¹¹¿·¤µ¤ì¤Ê¤¤
-¤é¤·¤¤¡£¤Ä¤Þ¤ê¡¢while ¥ë¡¼¥×Éô¤ÎÊÖ¤êÃͤÏmatchlen ¤ÎÊý¤À¡£
-¤³¤Î¾ò·ï¤Ï for () ¥ë¡¼¥×¤Îæ½Ð¾ò·ï¤Ç¤â¤¢¤ë¡£¿´¤Ë¤È¤É¤á¤Æ¡¢¼¡¤Ë¿Ê¤à¡£
+次の条件では、matchlen と off が条件判断されている。ということはこのど
+ちらか、あるいは両方は while ループの返り値(出力)だ。ざっと 
+match_insert()全体を見てみると off は最初とこの直後でしか更新されない
+らしい。つまり、while ループ部の返り値はmatchlen の方だ。
+この条件は for () ループの脱出条件でもある。心にとどめて、次に進む。
 
         max = off + 2;
         off = 0;
         h = hval;
 
 
         max = off + 2;
         off = 0;
         h = hval;
 
-¤Õ¤à¡£¤è¤¯¤ï¤«¤é¤Ê¤¤¡£¤·¤«¤·ÃíÌܤ¹¤Ù¤­ÅÀ¤Ï¤¢¤ë¡£off ¤Ï¤³¤³¤Ç¡¢0 ¤Ë¤Ê¤ë
-¤¬¤³¤ì°Ê¹ß¤Ï off ¤ÎÃͤÏÊѤï¤é¤Ê¤¤¡£¤Ä¤Þ¤ê¡¢off ¤ÏºÇ½é¤Ï²¿¤é¤«¤ÎÃͤǠ
-while ¥ë¡¼¥×Éô¤ËÅϤµ¤ì¤ë¤¬¡¢¤½¤Î¼¡¤«¤é¤Ï¡¢0 ¤À¡£¤³¤Î for ¥ë¡¼¥×¤¬²¿ÅÙ
-²ó¤í¤¦¤È¤â 0 ¤À¡£h ¤âƱ¤¸¤ÇºÇ½é¤Ï²¿¤é¤«¤ÎÃͤò»ý¤Ä¤¬¡¢2²óÌܤΥ롼¥×°Ê¹ß¡¢
-h ¤Ï hval ¤À¡£max ¤Ï¡¢off ¤ò 0 ¤Ë¤¹¤ëľÁ°¤Ë¹¹¿·¤·¤Æ¤¤¤ë¤«¤é¡¢h ¤ä off 
-¤È»ö¤Ê¤ê¡¢3¤Ä¤Î¾õÂÖ¤ò»ý¤Ä¡¢¤¹¤Ê¤ï¤Á¡£maxmatch, off+2, 2 ¤À¡£
+ふむ。よくわからない。しかし注目すべき点はある。off はここで、0 になる
+がこれ以降は off の値は変わらない。つまり、off は最初は何らかの値で 
+while ループ部に渡されるが、その次からは、0 だ。この for ループが何度
+回ろうとも 0 だ。h も同じで最初は何らかの値を持つが、2回目のループ以降、
+h は hval だ。max は、off を 0 にする直前に更新しているから、h や off 
+と事なり、3つの状態を持つ、すなわち。maxmatch, off+2, 2 だ。
 
 
-¤¤¤ä¡¢Ã¦½Ð¾ò·ï¤ò¸«¤Æ¤ß¤ë¤È off == 0 ¤Ê¤é break ¤È¤¢¤ë¡£¤Ä¤Þ¤ê¡¢¤³¤Î 
-for ¥ë¡¼¥×¤Ï¤É¤ó¤Ê¤Ë´èÄ¥¤Ã¤Æ¤â2²ó¤·¤«²ó¤é¤Ê¤¤¤é¤·¤¤¡£¤ä¤Ã¤Ñ¤ê max ¤â 2 
-¤Ä¤Î¾õÂÖ¤·¤«»ý¤¿¤Ê¤¤¤è¤¦¤À¡£
+いや、脱出条件を見てみると off == 0 なら break とある。つまり、この 
+for ループはどんなに頑張っても2回しか回らないらしい。やっぱり max も 2 
+つの状態しか持たないようだ。
 
 
-¤³¤ì¤Ç¡¢1 ²óÌÜ¡¢2²óÌܤˠwhile ¥ë¡¼¥×Éô¤ËÆþ¤ëľÁ°¤Î¾õÂÖ¤¬½ñ¤±¤ë¡£¤³¤Î´Ø
-¿ô match_insert() ¤Ï¡¢while ¥ë¡¼¥×Éô¤ò1²ó¤«2²ó¼Â¹Ô¤¹¤ë½èÍý¤È¸À¤¦¤ï¤±¤À¡£
+これで、1 回目、2回目に while ループ部に入る直前の状態が書ける。この関
+数 match_insert() は、while ループ部を1回か2回実行する処理と言うわけだ。
 
 
-¤³¤³¤Ç̵»ë¤·¤Æ¤¤¤¿¡£while ¥ë¡¼¥×Éô¤ÎÆþÎϤȤʤë scan_pos, scan_end
-¤â¤½¤ì¤¾¤ì¤É¤Î¤è¤¦¤Ê¾õÂ֤ˤʤ뤫½ñ¤¤¤Æ¤ª¤¯
+ここで無視していた。while ループ部の入力となる scan_pos, scan_end
+もそれぞれどのような状態になるか書いておく
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-< 1²óÌÜ >
-   h = ²¿¤«
-   off = ²¿¤«
+< 1回目 >
+   h = 何か
+   off = 何か
    max = maxmatch
 
    scan_pos = hash[h]
    max = maxmatch
 
    scan_pos = hash[h]
-   scan_end = pos + off - dicsiz  (¤¢¤ë¤¤¤Ï¡¢off)
+   scan_end = pos + off - dicsiz  (あるいは、off)
 
    matchlen = 2
    matchpos = pos
 
    matchlen = 2
    matchpos = pos
-< 2²óÌÜ >
+< 2回目 >
    h = hval
    off = 0
    h = hval
    off = 0
-   max = Á°¤Î off + 2
+   max = 前の off + 2
 
    scan_pos = hash[hval]
 
    scan_pos = hash[hval]
-   scan_end = pos - dicsiz  (¤¢¤ë¤¤¤Ï¡¢0)
+   scan_end = pos - dicsiz  (あるいは、0)
 
    matchlen = ?
    matchpos = ?
 ----------------------------------------------------------------------------
 
 
    matchlen = ?
    matchpos = ?
 ----------------------------------------------------------------------------
 
-¾åµ­¤Ï°ìÈ̲½¤·¤¿¾ì¹ç¤À¤¬¡¢º£²ó(½é²ó)¤Î¾ì¹ç¡¢h ¤ä off ¤ÎÃͤϡ¢hval ¤Ç¤¢
-¤ê¡¢0 ¤À¤Ã¤¿¡£2²óÌܥ롼¥×¤Î¤È¤­¤Î¾õÂÖ¤ÈƱ¤¸¤Ç¤¢¤ë¡£2²ó¤Î¥ë¡¼¥×¤Î°ã¤¤¤Ï 
-max ¤ÎÃͤ¬matchpos ¤Ç¤¢¤ë¤« off+2 (¤¹¤Ê¤ï¤Á2)¤Ç¤¢¤ë¤«¤Î°ã¤¤¤·¤«¤Ê¤¤¤è¤¦¤À¡£
+上記は一般化した場合だが、今回(初回)の場合、h や off の値は、hval であ
+り、0 だった。2回目ループのときの状態と同じである。2回のループの違いは 
+max の値がmatchpos であるか off+2 (すなわち2)であるかの違いしかないようだ。
 
 
-¤³¤³¤Ï¡¢¾ò·ï¤ò¾¯¤Ê¤¯¤¹¤ë¤¿¤á¤Ë¤³¤Î¾ì¹ç¤À¤±¤Ë¤·¤Ü¤Ã¤Æ½èÍý¤ò¹Í¤¨¤è¤¦¡£
-while ¥ë¡¼¥×¤Î2²ó¤Î¸Æ¤Ó½Ð¤·¤ò¹Ô¤¦ºÝ¤Î¾õÂ֤ϰʲ¼¤ÎÄ̤ê¤Ë½ñ¤­Ä¾¤»¤ë¡£
+ここは、条件を少なくするためにこの場合だけにしぼって処理を考えよう。
+while ループの2回の呼び出しを行う際の状態は以下の通りに書き直せる。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-< 1²óÌÜ >
+< 1回目 >
    h = hval
    off = 0
    max = maxmatch
 
    scan_pos = hash[hval]
    h = hval
    off = 0
    max = maxmatch
 
    scan_pos = hash[hval]
-   scan_end = pos - dicsiz  (¤¢¤ë¤¤¤Ï¡¢0)
+   scan_end = pos - dicsiz  (あるいは、0)
 
    matchlen = 2
    matchpos = pos
 
    matchlen = 2
    matchpos = pos
-< 2²óÌÜ >
+< 2回目 >
    h = hval
    off = 0
    max = 2
 
    scan_pos = hash[hval]
    h = hval
    off = 0
    max = 2
 
    scan_pos = hash[hval]
-   scan_end = pos - dicsiz  (¤¢¤ë¤¤¤Ï¡¢0)
+   scan_end = pos - dicsiz  (あるいは、0)
 
    matchlen = ?
    matchpos = ?
 ----------------------------------------------------------------------------
 
 
    matchlen = ?
    matchpos = ?
 ----------------------------------------------------------------------------
 
-¤¦¡¼¤ó¡¢¤Þ¤À¡¢¤¹¤Ã¤­¤ê¤·¤Ê¤¤¡£²¿¤¬¤¹¤Ã¤­¤ê¤·¤Ê¤¤¤«¤È¤¤¤¦¤È scan_end ¤Î
-ÃͤÀ¡£¤³¤ì¤¬²¿¤ò°ÕÌ£¤¹¤ë¤Î¤«¤¬¤è¤¯¤ï¤«¤é¤Ê¤¤¡£scan_pos ¤Ï¡¢¤ï¤«¤ë¤Î¤«¡©
-¤È¤¤¤¦¤È¡¢¤ï¤«¤ë¡£hash[hval]¤À¤«¤é¸½ºß¤Îʸ»úÎó¤ÈƱ¤¸Ê¸»úÎó¤Î¼­½ñ¾å¤Î°Ì
-ÃÖ¤À¡£¤µ¤é¤Ë¡¢¸½»þÅÀ¤Ç¤Ï get_next() ¤Ç¡¢hval ¤ò¹¹¿·¤·¤Æ¤«¤é insert() 
-¤ò¹Ô¤Ã¤Æ¤¤¤Ê¤¤¤Î¤Ç¡¢hash[hval] ¤Ë¤Ï²¿¤âÆþ¤Ã¤Æ¤¤¤Ê¤¤¡£¤¹¤Ê¤ï¤Á 0 ¤À¡£
+うーん、まだ、すっきりしない。何がすっきりしないかというと scan_end の
+値だ。これが何を意味するのかがよくわからない。scan_pos は、わかるのか?
+というと、わかる。hash[hval]だから現在の文字列と同じ文字列の辞書上の位
+置だ。さらに、現時点では get_next() で、hval を更新してから insert() 
+を行っていないので、hash[hval] には何も入っていない。すなわち 0 だ。
 
         scan_end = (pos > dicsiz) ? pos + off - dicsiz : off;
 
 
         scan_end = (pos > dicsiz) ? pos + off - dicsiz : off;
 
-¤ò¹Í¤¨¤è¤¦¡£off ¤Ï¡¢0 ¤À¤«¤é
+を考えよう。off は、0 だから
 
         scan_end = (pos > dicsiz) ? pos - dicsiz : 0;
 
 
         scan_end = (pos > dicsiz) ? pos - dicsiz : 0;
 
-¤Ê¤ï¤±¤À¡£¤µ¤é¤Ë¡¢pos¤Ï¸½»þÅÀ¤Ç dicbit+1 ¤Ç¤¢¤ë¤«¤é¡¢1 ¤À¡£¿Þ¤Ë½ñ¤³¤¦¡£
+なわけだ。さらに、posは現時点で dicbit+1 であるから、1 だ。図に書こう。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-                                
+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
@@ -1139,8 +1148,8 @@ while 
        +-------------+-------------+-------------+-------------+---+
        ^ ^                           `-pos(=dicsiz+1)
        | |
        +-------------+-------------+-------------+-------------+---+
        ^ ^                           `-pos(=dicsiz+1)
        | |
-       | scan_end ¤Ï¤³¤ÎÊÕ(1)
-       scan_pos ¤Ï¤³¤ÎÊÕ(0)
+       | scan_end はこの辺(1)
+       scan_pos はこの辺(0)
 
    h = hval
    off = 0
 
    h = hval
    off = 0
@@ -1148,22 +1157,22 @@ while 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤Ä¤¤¤Ë¡¢text[] ¥Ð¥Ã¥Õ¥¡¤Îº¸È¾Ê¬¤Ë»Ø¤·¤«¤«¤ë¡£¤³¤ì¤¬²¿¤Ê¤Î¤«¤Ï¸½»þÅÀ¤Ç
-¤ÏÌÀ³Î¤Ë½ñ¤¤¤Æ¤Ê¤«¤Ã¤¿¤¬Í½ÁÛ¤¹¤ë¤È¤³¤Îº¸È¾Ê¬¤Ï¥º¥Ð¥ê¼­½ñ¤À¡£¸À¤¤ÀڤäÆ
-¤ä¤í¤¦¡£º£¤Þ¤Ç¼­½ñ¤é¤·¤¤(dicsiz¤Î¥µ¥¤¥º¤ò»ý¤Ä)¥Ð¥Ã¥Õ¥¡¤Ï hash[] ¤ä 
-prev[] ¤¬¤¢¤Ã¤¿¤¬¡¢hash[], prev[] ¤ÎÍÑÅӤϤ⤦ÌÀ³Î¤Ç¤¢¤ë¡£¼­½ñ¤È¤Ê¤êÆÀ
-¤ë¥Ð¥Ã¥Õ¥¡¤Ï¤â¤¦¤³¤Î text[] ¤·¤«¤Ê¤¤¤Î¤À¡£
+ついに、text[] バッファの左半分に指しかかる。これが何なのかは現時点で
+は明確に書いてなかったが予想するとこの左半分はズバリ辞書だ。言い切って
+やろう。今まで辞書らしい(dicsizのサイズを持つ)バッファは hash[] や 
+prev[] があったが、hash[], prev[] の用途はもう明確である。辞書となり得
+るバッファはもうこの text[] しかないのだ。
 
 
-¤µ¤é¤Ë¡¢º¸È¾Ê¬¤Ë¸Â¤é¤º¤³¤Î text[] Á´ÂΤ¬¼­½ñ¤Ç¤¢¤í¤¦¤ÈͽÁÛ¤¹¤ë¡£¤³¤ì¤Ï
-¤¿¤À¤Î´ª¤À¤¬ text[] ¤Ï´Ä¾õ¥Ð¥Ã¥Õ¥¡¤Ê¤Î¤Ç¤Ï¤Ê¤«¤í¤¦¤«¤È¹Í¤¨¤Æ¤¤¤ë¡£
+さらに、左半分に限らずこの text[] 全体が辞書であろうと予想する。これは
+ただの勘だが text[] は環状バッファなのではなかろうかと考えている。
 
 
-# ºÇ½é¤ÎÊý¤Ç prev[] ¤¬¼­½ñ¤À¤ÈͽÁÛ¤·¤¿¤¬´Ö°ã¤Ã¤¿Í½ÁÛ¤ò¤·¤Æ¤¤¤¿¤³¤È¤Ë¤³
-# ¤Î»þÅÀ¤Çµ¤¤Å¤¤¤¿¡£prev[] ¤¬¼­½ñ¤ÈƱ¤¸¥µ¥¤¥º¤ò»ý¤ÄÍýͳ¤Ï¤Þ¤À¤è¤¯¤ï¤«
-# ¤é¤Ê¤¤¡£
+# 最初の方で prev[] が辞書だと予想したが間違った予想をしていたことにこ
+# の時点で気づいた。prev[] が辞書と同じサイズを持つ理由はまだよくわか
+# らない。
 
 
-¤³¤Î»þÅÀ¤Ç¤Ï¤Þ¤À scan_pos ¤ä scan_end ¤Î¿¿¤Î°ÕÌ£¤Ï¤ï¤«¤é¤Ê¤¤¡£off ¤Î¤³
-¤È¤ò̵»ë¤·¤Æ¤¤¤ë¤«¤éͽÁÛ¤âΩ¤Á¤Ë¤¯¤¤¤¬¡¢¤Ò¤È¤Þ¤º½é´ü¾õÂÖ¤¬¤É¤¦¤¤¤Ã¤¿¤â
-¤Î¤«¤Ï¤ï¤«¤Ã¤¿¤Î¤Ç¤³¤Î¤Þ¤Þ¡¢while ¥ë¡¼¥×Éô¤ò¸«¤Æ¤ß¤¿¤¤¤È»×¤¦¡£
+この時点ではまだ scan_pos や scan_end の真の意味はわからない。off のこ
+とを無視しているから予想も立ちにくいが、ひとまず初期状態がどういったも
+のかはわかったのでこのまま、while ループ部を見てみたいと思う。
 
         while (scan_pos > scan_end) {
             chain++;
 
         while (scan_pos > scan_end) {
             chain++;
@@ -1184,7 +1193,7 @@ prev[] 
             scan_pos = prev[scan_pos & (dicsiz - 1)];
         }
 
             scan_pos = prev[scan_pos & (dicsiz - 1)];
         }
 
-¤Þ¤º¡¢if Ê¸¤Î¾ò·ï¤òËþ¤¿¤µ¤Ê¤¤¾ì¹ç¤À¤±¤ò¹Í¤¨¤ë¡£
+まず、if 文の条件を満たさない場合だけを考える。
 
         while (scan_pos > scan_end) {
             chain++;
 
         while (scan_pos > scan_end) {
             chain++;
@@ -1196,61 +1205,61 @@ prev[] 
         }
 
 
         }
 
 
-off¤Ï 0 ¤Ê¤Î¤Ç¡¢text[scan_pos + matchlen] != text[pos + matchlen] ¤È¤¤
-¤¦¾ò·ï¤Î¾ì¹ç¤òÁÛÄꤹ¤ë¤ï¤±¤À¤¬¡¢
+offは 0 なので、text[scan_pos + matchlen] != text[pos + matchlen] とい
+う条件の場合を想定するわけだが、
 
 text[scan_pos + matchlen]
 
 
 text[scan_pos + matchlen]
 
-¤È
+と
 
 text[pos + matchlen]
 
 
 text[pos + matchlen]
 
-¤òÈæ¤Ù¤Æ¤¤¤ë
+を比べている
 
 
-text[scan_pos]  ¼­½ñ¾å¤Îʸ»úÎó¤Î*ÀèƬ*
-text[pos]       ¸½ºß¤Îʸ»úÎó¤Î*ÀèƬ*
+text[scan_pos]  辞書上の文字列の*先頭*
+text[pos]       現在の文字列の*先頭*
 
 
-¤òÈæ¤Ù¤Ê¤¤¤Î¤Ï matchlen ¤¬Á°¤ËͽÁÛ¤·¤¿¡ÖºÇÄã¸Â°ìÃפ·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤Ä¹¤µ-1¡×
-¤À¤«¤é¤Ç¤¢¤í¤¦¡£¸½»þÅÀ¤Ç¡¢matchlen ¤¬ 2 ¤À¤«¤é
+を比べないのは matchlen が前に予想した「最低限一致しなければならない長さ-1」
+だからであろう。現時点で、matchlen が 2 だから
 
 text[scan_pos + 0] == text[pos + 0]
 text[scan_pos + 1] == text[pos + 1]
 
 
 text[scan_pos + 0] == text[pos + 0]
 text[scan_pos + 1] == text[pos + 1]
 
-¤Ç¤¢¤Ã¤¿¤È¤·¤Æ¤â¡¢
+であったとしても、
 
 text[scan_pos + 2] != text[pos + 2]
 
 
 text[scan_pos + 2] != text[pos + 2]
 
-¤Ç¤¢¤ì¤Ð¡¢¡ÖºÇÄã¸Â°ìÃפ·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤Ä¹¤µ¡×¤È¤¤¤¦¾ò·ï¤òËþ¤¿¤µ¤Ê¤¤¤Î
-¤Ç¤¢¤ë¡£¤Ê¤Î¤Ç matchlen ¤Î°ÌÃÖ¤«¤éÀè¤ËÈæ³Ó¤·¤Æ̵Â̤ÊÈæ³Ó¤ò¤·¤Ê¤¤¤è¤¦¤Ë
-¤·¤Æ¤¤¤ë¡£¸å¤Ç¤Á¤ã¤ó¤È¤·¤¿Èæ³Ó¤Î½èÍý¤¬½Ð¤ÆÍè¤ë¤À¤í¤¦¡£¤³¤Î¤è¤¦¤Ê½èÍý¤Ï
-½èÍý¤È¤·¤Æ¤Ï¸úΨ¤¬Îɤ¤¤Î¤À¤¬¡¢¤³¤È¥½¡¼¥¹Íý²ò¤È¸À¤¦ÅÀ¤Ç¤Ï¾éŤǤ¢¤ë¡£¤ï
-¤«¤ê¤Ë¤¯¤¤¤Î¤À¡£»ÅÊý¤Ê¤¤¤Î¤À¤±¤É¡£
+であれば、「最低限一致しなければならない長さ」という条件を満たさないの
+である。なので matchlen の位置から先に比較して無駄な比較をしないように
+している。後でちゃんとした比較の処理が出て来るだろう。このような処理は
+処理としては効率が良いのだが、ことソース理解と言う点では冗長である。わ
+かりにくいのだ。仕方ないのだけど。
 
 
-# matchlen ¤Î°ÕÌ£¤ÎͽÁۤϤɤ¦¤ä¤éÅö¤¿¤Ã¤Æ¤¤¤ë¤è¤¦¤À¡£matchlen ¤ÏºÇû°ì
-# Ã×Ĺ¤Ç¡¢minmatchlen ¤Ã¤È̾ÉÕ¤±¤Æ¤âÎɤµ¤½¤¦¤ÊÊÑ¿ô¤À¡£
+# matchlen の意味の予想はどうやら当たっているようだ。matchlen は最短一
+# 致長で、minmatchlen っと名付けても良さそうな変数だ。
 
 
-¤½¤·¤Æ¡¢Èæ³Ó¤Ë¼ºÇÔ¤·¤¿¤é scan_pos ¤ò¹¹¿·¤¹¤ë¡£
+そして、比較に失敗したら scan_pos を更新する。
 
             scan_pos = prev[scan_pos & (dicsiz - 1)];
 
 
             scan_pos = prev[scan_pos & (dicsiz - 1)];
 
-¥Ï¥Ã¥·¥å¤Î¥Á¥§¡¼¥ó¤ò¤¿¤É¤Ã¤Æ¤¤¤ë¡¢¤Ä¤Þ¤ê¼¡¤Î¸õÊä¤ò¼­½ñ¤«¤é¼è¤ê½Ð¤·¤Æ¤¤
-¤ë¤ï¤±¤À¡£¤³¤³¤Þ¤Ç¤Ç¡¢while ¥ë¡¼¥×¤Î½èÍýÆâÍƤÎÁÛÁü¤Ï¤Ä¤¤¤¿¡£¤³¤Î¥ë¡¼¥×
-¤Ï¼­½ñ¤«¤é(ºÇĹ)°ìÃפ¹¤ëʸ»úÎó¤òõ¤·¤Æ¤¤¤ë¤Î¤À¤í¤¦¡£
+ハッシュのチェーンをたどっている、つまり次の候補を辞書から取り出してい
+るわけだ。ここまでで、while ループの処理内容の想像はついた。このループ
+は辞書から(最長)一致する文字列を探しているのだろう。
 
 
-½çÈÖ¤¬Á°¸å¤·¤¿¤¬¡¢while ¥ë¡¼¥×¤Îæ½Ð¾ò·ï¤ò¸«¤Æ¤ß¤ë
+順番が前後したが、while ループの脱出条件を見てみる
 
         while (scan_pos > scan_end) {
 
 
         while (scan_pos > scan_end) {
 
-¤³¤ì¤Ï¤É¤¦¤¤¤¦¤³¤È¤À¤í¤¦¡© scan_pos ¤Ï¡¢¥Ï¥Ã¥·¥å¤Î¥Á¥§¡¼¥ó¤ò¤¿¤É¤Ã¤ÆƱ
-¤¸¥Ï¥Ã¥·¥åÃͤò»ý¤Äʸ»úÎó¤Î°ÌÃÖ¤òõ¤¹¡¢¤³¤ÎÃͤϤÀ¤ó¤À¤ó¤È¾®¤µ¤¯¤Ê¤Ã¤Æ¹Ô
-¤¯¤â¤Î¤Ê¤Î¤À¤í¤¦¤«¡©
-¤½¤ÎÄ̤ê¤Ç¤¢¤ë¡£hash[] ¤Ø¤Î³ÊǼ¤Ï¥Õ¥¡¥¤¥ë¤«¤é¼è¤Ã¤ÆÍ褿ʸ»úÎó¤ò½ç¤Ë³Ê
-Ǽ¤·¤Æ¹Ô¤¯¤Î¤Ç¥Á¥§¡¼¥ó¤Î±ü¤Ë¤Ï¡¢¤è¤êÁ°¤ÎÊý¤Î°ÌÃÖ¤¬½ñ¤«¤ì¤Æ¤¤¤ë¤Ï¤º¤À¡£
-µÕ¤Ë¥Á¥§¡¼¥ó¤ÎÀõ¤¤Éôʬ¤Ë¤Ï¤è¤ê¸½ºß°ÌÃ֤˶ᤤ°ÌÃÖ¤¬½ñ¤«¤ì¤Æ¤¤¤ë¤Î¤À¤í
-¤¦¡£¤Ç¤Ï¡¢¤½¤Î¶­³¦ scan_end ¤Ï¤É¤¦¤ä¤Ã¤Æ¤ï¤«¤ë¤Î¤À¤í¤¦¤«¡©¤³¤ì¤Ï¸å¤Ç¤Þ
-¤¿¸¡¾Ú¤·¤è¤¦¡£
+これはどういうことだろう? scan_pos は、ハッシュのチェーンをたどって同
+じハッシュ値を持つ文字列の位置を探す、この値はだんだんと小さくなって行
+くものなのだろうか?
+その通りである。hash[] への格納はファイルから取って来た文字列を順に格
+納して行くのでチェーンの奥には、より前の方の位置が書かれているはずだ。
+逆にチェーンの浅い部分にはより現在位置に近い位置が書かれているのだろ
+う。では、その境界 scan_end はどうやってわかるのだろうか?これは後でま
+た検証しよう。
 
 
-¤Ç¤Ï¡¢½èÍý¤ÎËܼÁ if Ê¸¤ÎÃæ¤ò¸«¤ë»ö¤Ë¤·¤è¤¦
+では、処理の本質 if 文の中を見る事にしよう
 
             if (text[scan_pos + matchlen - off] == text[pos + matchlen]) {
                 {
 
             if (text[scan_pos + matchlen - off] == text[pos + matchlen]) {
                 {
@@ -1266,22 +1275,22 @@ text[scan_pos + 2] != text[pos + 2]
                 }
             }
 
                 }
             }
 
-ºÇ½é¤Î°ÕÌ£¤â¤Ê¤¯¥Ö¥í¥Ã¥¯¤Ë¤Ê¤Ã¤Æ¤¤¤ëÉôʬ¤ò¸«¤ë¡¢
+最初の意味もなくブロックになっている部分を見る、
 
                 {
                     a = text + scan_pos - off;  b = text + pos;
                     for (len = 0; len < max && *a++ == *b++; len++);
                 }
 
 
                 {
                     a = text + scan_pos - off;  b = text + pos;
                     for (len = 0; len < max && *a++ == *b++; len++);
                 }
 
-¤³¤Î½èÍý¤Ç¤Ï a, b ¤È¤¤¤¦¤¤¤«¤Ë¤â¶É½ê¤Ê̾Á°¤ÎÊÑ¿ô¤¬»È¤ï¤ì¤Æ¤¤¤ë¡£¤³¤ì¤Ï¡¢
-ËÜÅö¤Ë¤³¤Î¥Ö¥í¥Ã¥¯Æâ¤Ç¶É½êŪ¤Ê¤â¤Î¤Î¤è¤¦¤À¡£¤Ê¤é¤ÐÄêµÁ°ÌÃ֤⤳¤Î¥Ö¥í¥Ã
-¥¯Æâ¤Ë¤·¤ÆËÜÅö¤Ë¶É½êŪ¤Ë¤·¤ÆÍߤ·¤«¤Ã¤¿¡£
+この処理では a, b といういかにも局所な名前の変数が使われている。これは、
+本当にこのブロック内で局所的なもののようだ。ならば定義位置もこのブロッ
+ク内にして本当に局所的にして欲しかった。
 
 
-¤µ¤é¤Ë¡¢¤³¤Î½èÍý¤Ïñ¤Ëʸ»úÎó a, b ¤òÈæ³Ó¤·¤Æ¤¤¤ë¤À¤±¤Î¤è¤¦¤À¡£memcmp() 
-¤Ç¤Ï¤Þ¤º¤¤¤Î¤«¤È¸À¤¦¤È¤³¤³¤Çµá¤á¤Æ¤¤¤ë¤â¤Î¤¬¡Ö¤É¤³¤Þ¤Ç°ìÃפ·¤¿¤«(len)¡×
-¤Î¤è¤¦¤Ê¤Î¤Ç¡¢memcmp() ¤Ç¤ÏÌòÉÔ­¤À¡£
+さらに、この処理は単に文字列 a, b を比較しているだけのようだ。memcmp() 
+ではまずいのかと言うとここで求めているものが「どこまで一致したか(len)」
+のようなので、memcmp() では役不足だ。
 
 
-¤½¤Î¼¡¤Î½èÍý¡¢
+その次の処理、
 
                 if (len > matchlen) {
                     matchpos = scan_pos - off;
 
                 if (len > matchlen) {
                     matchpos = scan_pos - off;
@@ -1290,34 +1299,34 @@ text[scan_pos + 2] != text[pos + 2]
                     }
                 }
 
                     }
                 }
 
-¤Ç¡¢matchlen (ºÇÄã°ìÃ×Ĺ)¤è¤êÂ礭¤¤¾ì¹ç¤Ë¾ò·ï¤òËþ¤¿¤¹¡£¾ò·ï¤òËþ¤¿¤µ¤Ê
-¤±¤ì¤Ð¡¢scan_pos ¤ò¹¹¿·¤·¡¢¼¡¤Î¥ë¡¼¥×¤Ë°Ü¤ë¡£¤Ç¤Ï¡¢¾ò·ï¤òËþ¤¿¤¹¾ì¹ç¤ò
-¸«¤Æ¤ß¤è¤¦¡£¤Þ¤ººÇû°ìÃ׍ΰìÃ×¾ò·ï¤òËþ¤¿¤·¤¿¾ì¹ç¡¢matchpos ¤È 
-matchlen ¤ò¹¹¿·¤¹¤ë¡£
+で、matchlen (最低一致長)より大きい場合に条件を満たす。条件を満たさな
+ければ、scan_pos を更新し、次のループに移る。では、条件を満たす場合を
+見てみよう。まず最短一致長の一致条件を満たした場合、matchpos と 
+matchlen を更新する。
 
 
-matchpos ¤Ï¥Þ¥Ã¥Á¤·¤¿°ÌÃÖ¡¢
-matchlen ¤Ï¥Þ¥Ã¥Á¤·¤¿Ä¹¤µ
+matchpos はマッチした位置、
+matchlen はマッチした長さ
 
 
-¤Ç¡¢matchlen ¤¬ max ¤Ê¤éºÇĹ°ìÃ׍Ë㤷¤Æ¤¤¤ë¤Î¤Ç¡¢¤³¤ì°Ê¾åõº÷¤Ï¤·¤Ê
-¤¤¡£matchlen ¤ÏºÇû°ìÃ׍Ǥ¢¤ê¤Ê¤¬¤é¡¢°ìÃ×Ĺ¤Ç¤â¤¢¤ëÊÑ¿ô¤Î¤è¤¦¤À¡£
-(¤É¤¦¤ä¤é°ÊÁ°¤Î2¤Ä¤ÎͽÁۤϤɤÁ¤é¤âÅö¤¿¤Ã¤Æ¤¤¤¿ÌÏÍÍ)
+で、matchlen が max なら最長一致長に達しているので、これ以上探索はしな
+い。matchlen は最短一致長でありながら、一致長でもある変数のようだ。
+(どうやら以前の2つの予想はどちらも当たっていた模様)
 
 
-¤È¤Ë¤«¤¯ while ¥ë¡¼¥×Éô¤Î½ÐÎϤϡ¢¤³¤Î matchpos ¤È matchlen ¤Î¤è¤¦¤À¡£
-Á°¤Ë½ñ¤¤¤¿Ä̤ꤳ¤Î¥ë¡¼¥×¤Ï¡ÖºÇĹ°ìÃ×ʸ»úÎó¤òµá¤á¤ë½èÍý¡×¤À¡£
+とにかく while ループ部の出力は、この matchpos と matchlen のようだ。
+前に書いた通りこのループは「最長一致文字列を求める処理」だ。
 
 
-match_insert() ¤ÎÁ´ÂΤò¤â¤¦°ìÅÙ¸«¤Æ¤ß¤è¤¦¡£¤¿¤À¤·¡¢°Ê²¼¤Î½ñ¤­´¹¤¨¤ò¹Ô¤¦¡£
+match_insert() の全体をもう一度見てみよう。ただし、以下の書き換えを行う。
 
 
-o while ¥ë¡¼¥×Éô¤Ï search_dict(pos, scan_pos, scan_end, max) ¤È¤¤¤¦´Ø¿ô
-  ¤ËÃÖ¤­´¹¤¨¤¿¤â¤Î¤È¤¹¤ë¡£
+o while ループ部は search_dict(pos, scan_pos, scan_end, max) という関数
+  に置き換えたものとする。
 
 
-o ËöÈø¤Î insert() ¤ÈƱÅù¤Î½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤ëÉôʬ¤â insert() ¤Î¸Æ¤Ó½Ð¤·¤Ë
-  ¤¹¤êÂؤ¨¤è¤¦¡£(match_insert() ´Ø¿ô¤ÎÃæ¤Ç insert() ½èÍý¤òËÜÅö¤Ë¹Ô¤¦¤Ù
-  ¤­¤â¤Î¤Ê¤Î¤«¤É¤¦¤«¤¬µ¿Ìä¤À¤¬)
+o 末尾の insert() と同等の処理を行っている部分も insert() の呼び出しに
+  すり替えよう。(match_insert() 関数の中で insert() 処理を本当に行うべ
+  きものなのかどうかが疑問だが)
 
 
-o chain ¤È¤¤¤¦ÊÑ¿ô¤Ë¤«¤«¤ï¤ë½èÍý¤â±£¤·¤¿(search_dictÆâ¤Ç¹Ô¤¦)
+o chain という変数にかかわる処理も隠した(search_dict内で行う)
 
 
-o for ¥ë¡¼¥×¤Ï¡¢2²ó¤·¤«¤Þ¤ï¤é¤Ê¤¤¤Î¤Ç¡¢2 Å٤Πsearch_dict() ¤Î¸Æ¤Ó½Ð¤·
-  ¤Ë½ñ¤­´¹¤¨¤ë
+o for ループは、2回しかまわらないので、2 度の search_dict() の呼び出し
+  に書き換える
 
 static void match_insert()
 {
 
 static void match_insert()
 {
@@ -1347,40 +1356,40 @@ static void match_insert()
     insert();
 }
 
     insert();
 }
 
-¤À¤¤¤Ö¤¹¤Ã¤­¤ê¤·¤¿(¤¬¡¢¤Þ¤ÀÈË»¨¤À)¡£¤Þ¤À¡¢off ¤Ë¤«¤«¤ï¤ëÉôʬ¤¬¤è¤¯Ê¬¤«
-¤é¤Ê¤¤¤¬¡¢¤Ò¤È¤Þ¤ºÎɤ¤¤À¤í¤¦¡£¤³¤Î´Ø¿ô¤Î²òÀϤϤ³¤ì¤Ç½ª¤Ã¤ÆÎɤ¤¤À¤í¤¦¤«¡£
+だいぶすっきりした(が、まだ繁雑だ)。まだ、off にかかわる部分がよく分か
+らないが、ひとまず良いだろう。この関数の解析はこれで終って良いだろうか。
 
 
-¤¤¤ä¡¢Îɤ¯¤Ê¤¤¡£´Î¿´¤Î match_insert() ¤Î½ÐÎϤ¬¤è¤¯¤ï¤«¤é¤Ê¤¤¡£¤³¤Î´Ø¿ô
-¤Ï¡ÖºÇĹ°ìÃ×ʸ»úÎó¤òõ¤·¡¢hash ¤ò¹¹¿·¤¹¤ë½èÍý¡×(¤¯¤É¤¤¤è¤¦¤À¤¬¡¢hash¤ò
-¹¹¿·¤¹¤ë¤Ï;·×¤Ë»×¤¦)¤Ê¤Î¤À¤í¤¦¤¬¡¢ºÇĹ°ìÃ×ʸ»úÎ󤬸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¤È
-¤¤¤¦¤Î¤Ï¤É¤¦È½ÃǤµ¤ì¤ë¤Î¤À¤í¤¦¡©
+いや、良くない。肝心の match_insert() の出力がよくわからない。この関数
+は「最長一致文字列を探し、hash を更新する処理」(くどいようだが、hashを
+更新するは余計に思う)なのだろうが、最長一致文字列が見つからなかったと
+いうのはどう判断されるのだろう?
 
 
-¤Þ¤º¡¢search_dict() ¤Ç¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¡¢matchlen ¤Ï¹¹¿·¤µ¤ì¤Ê¤¤
-(matchpos ¤Ï¡¢pos ¤Ë¤Ê¤ë)¡£¤½¤·¤Æ¡¢¤ª¤½¤é¤¯ 2 ÅÙÌܤΠsearch_dict() ¤Î
-¸Æ¤Ó½Ð¤·¤¬¹Ô¤ï¤ì¤ë¡£¤¬¡¢too_flag[] ¤È¤¤¤¦¤Î¤Ç¡¢È½ÃǤǤ­¤½¤¦¤Êµ¤¤â¤¹¤ë
-¤¬¤³¤ì¤Ï¤à¤·¤í¥Ï¥Ã¥·¥å¤Î¥Á¥§¡¼¥ó¤ò¤¿¤É¤ê¤¹¤®¤ë¤Î¤ò»ß¤á¤ë¤¿¤á¤Î¥Õ¥é¥°¤Ç
-¤¢¤ë¤è¤¦¤Ë»×¤¨¤ë¡£
+まず、search_dict() で見つからなかった場合、matchlen は更新されない
+(matchpos は、pos になる)。そして、おそらく 2 度目の search_dict() の
+呼び出しが行われる。が、too_flag[] というので、判断できそうな気もする
+がこれはむしろハッシュのチェーンをたどりすぎるのを止めるためのフラグで
+あるように思える。
 
 
-2ÅÙÌܤΠsearch_dict()¤Ç¡¢max ¤ÎÃͤ¬ÊѤï¤ë¤Î¤¬¸°¤À¤í¤¦¤«¡©¡£º£²ó¤Î¾ì¹ç¡¢
-max ¤Ï 256 ¤«¤é 2 ¤Ë¤Ê¤ë¡£ºÇĹ°ìÃ×Ĺ¤È¤·¤Æ 2 ¤¬¸Â³¦Ãͤˤʤë¤È¡¢
-search_dict() ¤ÎÆ°ºî¤ÏÊѤï¤ë¤À¤í¤¦¤«¡©¤¤¤ä¡¢¤ä¤Ï¤êÊѤï¤é¤Ê¤¤¡£¤É¤¦¤Ë¤â
-¤³¤Î´Ø¿ô¤À¤±¤Ç¤Ï¸«¤Ä¤«¤Ã¤¿¤«¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¤«¤È¤¤¤¦È½ÃǤϤǤ­¤Ê¤¤¤è¤¦
-¤À¡£(ËÜÅö¤Ï¤ï¤«¤Ã¤Æ¤¤¤ë¤Ï¤º¤Ê¤Î¤Ë¤½¤Î¾ðÊó¤òľÀܳ°¤Ë»ý¤Á½Ð¤·¤Æ¤¤¤Ê¤¤)
+2度目の search_dict()で、max の値が変わるのが鍵だろうか?。今回の場合、
+max は 256 から 2 になる。最長一致長として 2 が限界値になると、
+search_dict() の動作は変わるだろうか?いや、やはり変わらない。どうにも
+この関数だけでは見つかったか見つからなかったかという判断はできないよう
+だ。(本当はわかっているはずなのにその情報を直接外に持ち出していない)
 
 
-µ¤»ý°­¤¤¤¬¤ä¤Ï¤ê¤³¤Î´Ø¿ô¤Î²òÀϤò½ª¤¨¡¢¼¡¤Ë°Ü¤ë»ö¤Ë¤·¤è¤¦¡£
+気持悪いがやはりこの関数の解析を終え、次に移る事にしよう。
 
 
-(H) ¤Ç¤¢¤ë¡£°ÊÁ°¡¢
+(H) である。以前、
 
 
-(H) matchlen > lastmatchlen || lastmatchlen < THRESHOLD ¤Ê¤é
+(H) matchlen > lastmatchlen || lastmatchlen < THRESHOLD なら
 
 
-(H.1) output() ¤¹¤ë¡£(¥Þ¥Ã¥Á¤·¤Ê¤«¤Ã¤¿¤é¤½¤Î¤Þ¤Þ½ÐÎϤ·¤Æ¤¤¤ë¤Î¤À¤í¤¦¡£¤¿¤Ö¤ó)
-(H.2) ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð(¥Þ¥Ã¥Á¤·¤¿¤Ê¤é)¡¢output()¤·¡¢²¿¤«¤¤¤í¤¤¤í¤¹¤ë¡£
+(H.1) output() する。(マッチしなかったらそのまま出力しているのだろう。たぶん)
+(H.2) そうでなければ(マッチしたなら)、output()し、何かいろいろする。
 
 
-¤Ã¤ÈͽÁÛ¤·¤¿Éôʬ¤À¡£º£¤ä match_insert() ¤Ï¡¢²òÀϺѤߤÀ¤«¤é¤³¤ì¤Î¿¿µ¶¤¬
-¤ï¤«¤ë¤«¡©¤È¤¤¤¦¤È¤ä¤Ã¤Ñ¤ê¡¢¤ï¤«¤é¤Ê¤¤¡£¤¿¤À¡¢
+っと予想した部分だ。今や match_insert() は、解析済みだからこれの真偽が
+わかるか?というとやっぱり、わからない。ただ、
         matchlen > lastmatchlen
         matchlen > lastmatchlen
-¤È¤¤¤¦¤Î¤Ï¡¢¼­½ñ¤«¤éʸ»úÎ󤬸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Î¾ò·ï¤Ë¤Ê¤ê¤½¤¦¤À¤«¤é¡¢¤ä¤Ï¤ê
-¤³¤ì¤ÏͽÁÛ¤¬µÕ¤À¤í¤¦¤«¡©¤È¤Ë¤«¤¯¡¢Èæ³ÓŪ´Êñ¤½¤¦¤Ê¡¢(H.1) ¤«¤é¸«¤è¤¦¡£
+というのは、辞書から文字列が見つかった場合の条件になりそうだから、やはり
+これは予想が逆だろうか?とにかく、比較的簡単そうな、(H.1) から見よう。
 
         if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD) {
             /* (H.1) */
 
         if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD) {
             /* (H.1) */
@@ -1388,31 +1397,31 @@ search_dict() 
             count++;
         } else {
 
             count++;
         } else {
 
-¤É¤¦¤â¡¢Ê¸»ú text[pos-1] ¤ò½ÐÎϤ·¤Æ¤¤¤ë¤À¤±¤Î¤è¤¦¤Ë»×¤¨¤ë¡£Ê¸»ú¤Î½ÐÎÏ
-¤Ï¡¢slide ¼­½ñË¡¤Ç¤Ï¡Ö¼­½ñ¤«¤é¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¡×¤ò°ÕÌ£¤¹¤ë¤«¤é¡¢¤ä
-¤Ï¤êºÇ½é¤ÎͽÁۤϤ¢¤Ã¤Æ¤½¤¦¤Ê¤Î¤À¤¬¡¦¡¦¡¦»ÅÊý¤Ê¤¤¤Î¤Ç¡¢output()¤Î½èÍý¤ò
-ÇÁ¤¤¤Æ¸«¤è¤¦¡£¤³¤ì¤Ï¡¢lh5, 6, 7 ¤Î¾ì¹ç¡¢huf.c:output_st1(c, p) ¤Ç¤¢¤ë¡£
-¸½»þÅÀ¤Ç½èÍý¤ÎÆâÍƤò¸«¤Æ¤â¤ï¤±¤¬¤ï¤«¤é¤Ê¤¤¤¬¡¢·ëÏÀ¤«¤é¸À¤¦¤ÈÂè°ì°ú¿ô c 
-¤Ï¡¢Ê¸»ú¤Ç¡¢ÂèÆó°ú¿ô p ¤Ï¡¢°ÌÃ֤Ǥ¢¤ë¡£ËÁƬ¤Î decode ½èÍý¤Ç¡¢Ê¸»ú c ¤Ï
-Ťµ¤â·ó¤Í¤Æ¤¤¤ë¤ÈÀâÌÀºÑ¤ß¤Ê¤Î¤Ç¡¢(¤½¤·¤Æ¡¢text[pos-1] ¤Ë¤Ï¸½»þÅÀ¤Çʸ
-»ú¤½¤Î¤â¤Î¤·¤«½ñ¤«¤ì¤Æ¤¤¤Ê¤¤)¤³¤ì¤Ï¤ä¤Ï¤êʸ»ú¤ò½ÐÎϤ·¤Æ¤¤¤ë½èÍý¤À¡£¤Ä
-¤Þ¤ê¡Ö¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¡×¤Î½èÍý¤À¡£
+どうも、文字 text[pos-1] を出力しているだけのように思える。文字の出力
+は、slide 辞書法では「辞書から見つからなかった場合」を意味するから、や
+はり最初の予想はあってそうなのだが・・・仕方ないので、output()の処理を
+覗いて見よう。これは、lh5, 6, 7 の場合、huf.c:output_st1(c, p) である。
+現時点で処理の内容を見てもわけがわからないが、結論から言うと第一引数 c 
+は、文字で、第二引数 p は、位置である。冒頭の decode 処理で、文字 c は
+長さも兼ねていると説明済みなので、(そして、text[pos-1] には現時点で文
+字そのものしか書かれていない)これはやはり文字を出力している処理だ。つ
+まり「見つからなかった場合」の処理だ。
 
 
-¤Ê¤¼¡¢pos-1 ¤Ê¤Î¤À¤í¤¦¡©³Î¤«¤Ë Huffman coding ¤Ëʸ»ú¤òÅϤ¹¤Î¤Ï¤³¤ì¤¬½é
-¤á¤Æ¤Ç¡¢¸½ºß pos ¤Î°ÌÃ֤ϥХåե¡¤Î1ʸ»ú¿Ê¤ó¤À°ÌÃ֤ˤ¢¤ë¡£pos-1 ¤Ï½ÐÎÏ
-¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤Î¤ÏÅöÁ³¤À¡£¤È¤¤¤¦¤³¤È¤Ï pos ¤Ï¾ï¤Ë¡Ö̤½ÐÎÏʸ»ú¤Î°Ì
-ÃÖ + 1¡×¤Ê¤Î¤«¤â¤·¤ì¤Ê¤¤¡£
+なぜ、pos-1 なのだろう?確かに Huffman coding に文字を渡すのはこれが初
+めてで、現在 pos の位置はバッファの1文字進んだ位置にある。pos-1 は出力
+しなければならないのは当然だ。ということは pos は常に「未出力文字の位
+置 + 1」なのかもしれない。
 
 
-¼¡¤Î count++ ¤ò¸«¤ë¡£count ¤Ï¤É¤¦¤ä¤é¤³¤Î´Ø¿ô¤ÎÊÑ¿ô¤Ç¤Ï¤Ê¤¤¤é¤·¤¤¡¢º¤¤Ã
-¤¿»ö¤Ë¶É½êÊÑ¿ô¤Î̾Á°¤Ã¤Ý¤¤¤¬¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤À¡£¤³¤ì¤Ï¤è¤í¤·¤¯¤Ê¤¤¡£¤Á¤ç¤Ã
-¤È grep ¤·¤¿¤À¤±¤Ç¤Ï¡¢Â¾¤Ë¤É¤³¤Ç¤³¤ÎÊÑ¿ô¤ò»È¤Ã¤Æ¤¤¤ë¤Î¤«¤ï¤«¤é¤Ê¤«¤Ã¤¿¡£
-¤Þ¤¢¡¢º£ 1 Ê¸»ú¤òÅϤ·¤¿½ê¤Ê¤Î¤Ç¡¢ÆþÎÏʸ»ú¿ô¤Ê¤Î¤À¤È²¾Äꤷ¤Æ¤ª¤³¤¦¡£¤³
-¤ÎÊÑ¿ô¤¬ÂçÀª¤Ë±Æ¶Á¤òÍ¿¤¨¤ë»ö¤Ï¤Ê¤¤¤À¤í¤¦¤«¤é¤³¤ì°Ê¾å¤Ï¸«¤Ê¤¤¤È¸À¤¦¤Î¤â
-¥¢¥ê¤À¡£
+次の count++ を見る。count はどうやらこの関数の変数ではないらしい、困っ
+た事に局所変数の名前っぽいがグローバル変数だ。これはよろしくない。ちょっ
+と grep しただけでは、他にどこでこの変数を使っているのかわからなかった。
+まあ、今 1 文字を渡した所なので、入力文字数なのだと仮定しておこう。こ
+の変数が大勢に影響を与える事はないだろうからこれ以上は見ないと言うのも
+アリだ。
 
 
-# ¤½¤Î¸å¡¢dhuf.c:decode_p_dyn() ¤Ç¤Î¤ß count ¤ò»ÈÍѤ·¤Æ¤¤¤ë»ö¤¬¤ï¤«¤Ã¤¿¡£
+# その後、dhuf.c:decode_p_dyn() でのみ count を使用している事がわかった。
 
 
-¼¡¤Ï (H.2) ¤Ç¤¢¤ë¡£¤³¤ì¤¬¤Þ¤¿Æñ²ò¤Ê¤Î¤À¤¬¤æ¤Ã¤¯¤êÊÒÉÕ¤±¤è¤¦¡£
+次は (H.2) である。これがまた難解なのだがゆっくり片付けよう。
 
         } else {
             /* (H.2) */
 
         } else {
             /* (H.2) */
@@ -1430,26 +1439,26 @@ search_dict() 
             if (matchlen > remainder) matchlen = remainder;
         }
 
             if (matchlen > remainder) matchlen = remainder;
         }
 
-¤Þ¤º¡¢output() ¤ËÅϤ·¤Æ¤¤¤ë°ú¿ô¤Ï¡¢¤½¤ì¤¾¤ì¡ÖŤµ¡×¤È¡Ö°ÌÃ֡פǤ¢¤í¤¦
-¤³¤È¤ÏͽÁۺѤߤÀ¡£¤µ¤é¤Ë UCHAR_MAX{255} + 1 - THRESHOLD{3} ¤À¤«¤é
+まず、output() に渡している引数は、それぞれ「長さ」と「位置」であろう
+ことは予想済みだ。さらに UCHAR_MAX{255} + 1 - THRESHOLD{3} だから
 
 
Ťµ  lastmatchlen + 253
°ÌÃÖ  lastmatchoffset & (dicsiz-1)
長さ  lastmatchlen + 253
位置  lastmatchoffset & (dicsiz-1)
 
 
-¤È¤Ê¤Ã¤Æ¤¤¤ë¡£ËÁƬ¤Î decode() ¤Î²òÀϤǡ¢Ä¹¤µ¤Ï 253 ¤ò­¤¹»ö¤Ï³ÎǧºÑ¤ß
-¤À(-lhs- ¤Î¾ì¹ç 254 ¤ò­¤¹¤È¤¤¤¦Æ°ºî¤¬¡¢encoding Éôʬ¤Ç¤Ï¹Í褵¤ì
-¤Æ¤Ê¤¤¤Î¤Ï¡¢-lhs- ¤Î encoding µ¡Ç½¤¬¤Ê¤¤¤«¤é¤À)¡£¤È¤³¤í¤Ç¡¢°ìÃ×Ĺ 
-lastmatchlen ¤Ï 3 °Ê¾å¤Ç½é¤á¤Æ 255 ¤ò±Û¤¨¤ë¤³¤È¤¬¤Ç¤­¤ë¡£°ÊÁ°Í½ÁÛ¤·¤¿¡¢
-THRESHOLD ¤Î°ÕÌ£¡ÖºÇÄã¸Â°ìÃפ·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤Ä¹¤µ¡×¤Ï¤¢¤Ã¤Æ¤¤¤ë¤é¤·¤¤¡£
+となっている。冒頭の decode() の解析で、長さは 253 を足す事は確認済み
+だ(-lhs- の場合 254 を足すという動作が、encoding 部分では考慮され
+てないのは、-lhs- の encoding 機能がないからだ)。ところで、一致長 
+lastmatchlen は 3 以上で初めて 255 を越えることができる。以前予想した、
+THRESHOLD の意味「最低限一致しなければならない長さ」はあっているらしい。
 
 
-¤â¤¦°ìÅÀ¡¢Ãí°Õ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¤Î¤Ï¡¢½ÐÎϤ·¤Æ¤¤¤ë¤Î¤¬ lastmatchlen ¤È 
-lastmatchoffset ¤Ç¤¢¤ë¡£¤³¤ì¤é¤Ï¡¢match_insert() ¤Î¤È¤­¤Ë¤Ï¹¹¿·¤·¤Æ¤¤
-¤Ê¤¤(last¡Á¤Î¹¹¿·¤Ï¼¡¤Î¥ë¡¼¥×¤ÎÀèƬ (E) ¤Ç¹Ô¤ï¤ì¤ë)¡£ÀèÄø (H.1) ¤Î¤È¤­
-¤â½ñ¤­½Ð¤·¤Æ¤¤¤¿¤Î¤Ï¡¢text[pos-1] ¤Ç¤¢¤Ã¤¿¡£pos °ÌÃ֤ϰìÊâÀèÆɤߤ·¤¿°Ì
-ÃÖ¤ò»Ø¤¹¤é¤·¤¤¡£¤³¤Î¤è¤¦¤Ê½èÍý¤ò¹Ô¤¦¾ì¹ç¡¢ºÇ¸å¤ËÄ´À°¤¬É¬ÍפʤϤº¤À(¤Ç
-¤Ê¤¤¤ÈºÇ¸å¤Îʸ»ú¤¬½ÐÎϤµ¤ì¤Ê¤¤)¡£¤½¤ÎÄ´À°¤Ï¤É¤³¤Ç¹Ô¤ï¤ì¤ë¤Î¤À¤í¤¦¡©
+もう一点、注意しなくてはならないのは、出力しているのが lastmatchlen と 
+lastmatchoffset である。これらは、match_insert() のときには更新してい
+ない(last〜の更新は次のループの先頭 (E) で行われる)。先程 (H.1) のとき
+も書き出していたのは、text[pos-1] であった。pos 位置は一歩先読みした位
+置を指すらしい。このような処理を行う場合、最後に調整が必要なはずだ(で
+ないと最後の文字が出力されない)。その調整はどこで行われるのだろう?
 
 
-¤µ¤Æ¡¢¸å³¤Î½èÍý¤À¤¬¡¢<Ťµ¡¢°ÌÃÖ>¤Î¥Ú¥¢¤ò½ÐÎϤ·¤¿¸å¤Ï¡¢
+さて、後続の処理だが、<長さ、位置>のペアを出力した後は、
 
             --lastmatchlen;
 
 
             --lastmatchlen;
 
@@ -1458,51 +1467,51 @@ lastmatchoffset 
                 count++;
             }
 
                 count++;
             }
 
-¤È¤¤¤¦½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤ë¡£get_next() ¤Ï¡¢pos ¤ò¿Ê¤á¤ë½èÍý¡¢insert() ¤Ï¼­
-½ñ¤ËÅÐÏ¿¤¹¤ë½èÍý¤À¤«¤é¡¢¤³¤ì¤Ïʸ»úÎó¤òÆɤßÈô¤Ð¤·¤Æ¤¤¤ë½èÍý¤À¡£³Î¤«¤Ë 
-lastmatchlen Ê¬¤Î¾ðÊó¤Ï½ÐÎϺѤߤÀ¤«¤é¡¢¤³¤ì¤ÏǼÆÀ¤Ç¤¢¤ë¡£lastmatchlen 
-¤ò 1 Í¾Ê¬¤Ë°ú¤¤¤Æ¤¤¤ë¤Î¤¬Ææ¤À¤¬¤³¤ì¤Ï pos ¤¬°ìÊâÀè¤Ë¿Ê¤ó¤Ç¤¤¤ë¤«¤é¤Ç¤¢
-¤í¤¦¤ÈͽÁÛ¤¹¤ë¡£¤Ä¤Þ¤ê¡¢¤³¤Î¸å¤Ï pos ¤Î°ÌÃ֤Ϥޤ¿¡Ö¸½ºß°ÌÃ֡פËÌá¤ë¡£
-¤Ê¤ë¤Û¤É¡¢ÀèÄøÄ´À°¤¬É¬ÍפȽñ¤¤¤¿¤¬¤³¤³¤Ç¹Ô¤ï¤ì¤Æ¤¤¤ë¤é¤·¤¤¡£ºÙÉô¤ÏÉÔÌÀ
-¤À¤¬¾¯¤Ê¤¯¤È¤â¼­½ñ¤Ëʸ»úÎ󤬸«¤Ä¤«¤Ã¤¿¾ì¹ç¤ÏºÇ¸å¤Þ¤Ç½ÐÎϤµ¤ì¤ë¤è¤¦¤À¡£
+という処理を行っている。get_next() は、pos を進める処理、insert() は辞
+書に登録する処理だから、これは文字列を読み飛ばしている処理だ。確かに 
+lastmatchlen 分の情報は出力済みだから、これは納得である。lastmatchlen 
+を 1 余分に引いているのが謎だがこれは pos が一歩先に進んでいるからであ
+ろうと予想する。つまり、この後は pos の位置はまた「現在位置」に戻る。
+なるほど、先程調整が必要と書いたがここで行われているらしい。細部は不明
+だが少なくとも辞書に文字列が見つかった場合は最後まで出力されるようだ。
 
 
-¼¡¤Ë¿Ê¤â¤¦
+次に進もう
 
             get_next();
             matchlen = THRESHOLD - 1;
             match_insert();
             if (matchlen > remainder) matchlen = remainder;
 
 
             get_next();
             matchlen = THRESHOLD - 1;
             match_insert();
             if (matchlen > remainder) matchlen = remainder;
 
-¤»¤Ã¤«¤¯ pos ¤¬¸½ºß¤Î°ÌÃÖ¤ËÌá¤Ã¤¿¤Î¤Ë¡¢get_next() ¤Ç¤Þ¤¿ÀèÆɤߤµ¤ì¤¿¡£
-¤¦¡¼¤à¡£¤½¤·¤Æ¡¢matchlen ¤Ï½é´ü²½¤µ¤ì¤ë¡£°ìÃ×¾ðÊó¤Ï¤¹¤Ç¤Ë½ÐÎϺѤߤÀ¤«
-¤é¤³¤ì¤Ï¤¦¤Ê¤º¤±¤ë¡£¤½¤·¤Æ¡¢match_insert() ¤¬¸Æ¤Ð¤ì¤ë¡£¤³¤Î»þÅÀ¤ÇºÆÅÙ
-¼­½ñ¤¬¸¡º÷¤µ¤ì¤ë¡£pos ¤Ï¤Þ¤¿1ʸ»ú¿Ê¤ó¤Ç¤¤¤ë¤Î¤À¤«¤é¡¢¤³¤ì¤ÏÀèÄø(½é´ü¾õ
-ÂÖ)¤Îmatch_insert() ¤ÈÂ纹¤Ê¤¤½èÍý¤À¡£(¤½¤Îľ¸å¤Îifʸ¤Ï¶­³¦¾ò·ï¤Ê¤Î¤Ç
-̵»ë)
+せっかく pos が現在の位置に戻ったのに、get_next() でまた先読みされた。
+うーむ。そして、matchlen は初期化される。一致情報はすでに出力済みだか
+らこれはうなずける。そして、match_insert() が呼ばれる。この時点で再度
+辞書が検索される。pos はまた1文字進んでいるのだから、これは先程(初期状
+態)のmatch_insert() と大差ない処理だ。(その直後のif文は境界条件なので
+無視)
 
 
-¤½¤¦¤·¤Æ¡¢¤Þ¤¿¼¡¤Î¥ë¡¼¥×¤Ë°Ü¤ë¡£¤³¤Î¤È¤­Â³¤±¤¶¤Þ get_next(),
-match_insert() ¤¬¹Ô¤ï¤ì¤ë¡£¤É¤¦¤ä¤é pos ¤Ï¼¡¤Î¥ë¡¼¥×¤«¤é¤Ï¡¢ 2 Ê¸»úʸ
-Àè¤Ë¿Ê¤ó¤Ç¤·¤Þ¤¦¤è¤¦¤À¡£¤Ê¤¼¤À¤í¤¦¡©
+そうして、また次のループに移る。このとき続けざま get_next(),
+match_insert() が行われる。どうやら pos は次のループからは、 2 文字文
+先に進んでしまうようだ。なぜだろう?
 
 
-# ¸å¤Ç¤ï¤«¤Ã¤¿»ö¤À¤¬¡¢while (--lastmatchlen > 0) ¤Î¥ë¡¼¥×²ó¿ô¤òÆɤߴÖ
-# °ã¤¨¤¿¡£Î㤨¤Ð¡¢lastmatchlen ¤¬ 1 ¤Ê¤é¡¢¤³¤Î while ¥ë¡¼¥×Æâ¤Ç¤Ï 
-# get_next() ¤Ï1²ó¤â¸Æ¤Ð¤ì¤Ê¤¤¡£
+# 後でわかった事だが、while (--lastmatchlen > 0) のループ回数を読み間
+# 違えた。例えば、lastmatchlen が 1 なら、この while ループ内では 
+# get_next() は1回も呼ばれない。
 
 
-¤É¤¦¤Ë¤â¥½¡¼¥¹¤ò¸«¤¿¤À¤±¤Ç²òÆɤ¹¤ë¤Ë¤Ï¡¢¤³¤Î¤¢¤¿¤ê¤¬¸Â³¦¤Î¤è¤¦¤À¡£¤É¤¦
-¤·¤Æ¤âºÙÉô¤¬¤ï¤«¤é¤Ê¤¤¤·¡¢»ö¼Â¤¬¸«¤¨¤Ê¤¤¤«¤éͽÁÛ¤ÎÀѤ߽Ťͤ¬¤¿¤Þ¤Ã¤ÆÉÔ
-°Â¤Ë¤Ê¤ë¡£
+どうにもソースを見ただけで解読するには、このあたりが限界のようだ。どう
+しても細部がわからないし、事実が見えないから予想の積み重ねがたまって不
+安になる。
 
 
-¼Â¤Ï¡¢¤â¤¦¾¯¤·¥Þ¥á¤Ë¿Þ¤òµ¯¤³¤·¤ÆÆɤ߿ʤó¤Ç¹Ô¤±¤Ð¤â¤Ã¤È¤ï¤«¤ë¤³¤È¤¬¤¢¤Ã
-¤¿¤À¤í¤¦¤È»×¤¦¤Î¤À¤¬¡¢¤½¤ì¤ÏÌÌÅݤÀ¤·¡¢´Ö°ã¤¨¤ë²ÄǽÀ­¤¬¤¢¤ë(¤³¤³¤Þ¤Ç¤Ç
-²¿ÅÙ¤«Äˤ¤»×¤¤¤ò¤·¤¿)¡£°Ê¹ß¤Ï¡¢¤¤¤¯¤Ä¤«¤Î¥Ç¡¼¥¿¤ò¼ÂºÝ¤Ë°µ½Ì¤µ¤»¤½¤ÎÆ°
-¤­¤ò¥Ç¥Ð¥Ã¥¬¤ÇÄɤ¦¤³¤È¤Ç¡¢¤³¤ì¤Þ¤Ç¤Î²òÀÏ·ë²Ì¤ò¸¡¾Ú¤·¤Æ¤ß¤è¤¦¡£
+実は、もう少しマメに図を起こして読み進んで行けばもっとわかることがあっ
+ただろうと思うのだが、それは面倒だし、間違える可能性がある(ここまでで
+何度か痛い思いをした)。以降は、いくつかのデータを実際に圧縮させその動
+きをデバッガで追うことで、これまでの解析結果を検証してみよう。
 
 
-¡¦¡¦¡¦¤Ã¤È¡¢¤½¤ÎÁ°¤Ë¡¢¤³¤³¤Þ¤Ç¤Ç¤¹¤Ù¤Æ¤Î´Ø¿ô¤òÌÖÍ夷¤Æ¤·¤Þ¤Ã¤¿¤È»×¤Ã¤Æ
-¤¤¤¿¤Î¤À¤¬¡¢°ì¤Ä˺¤ì¤Æ¤¤¤¿¤â¤Î¤¬¤¢¤Ã¤¿¡£update() ¤À¡£¤³¤Î´Ø¿ô¤Ï¡¢
-get_next() ¤Ç¸Æ¤Ó½Ð¤µ¤ì¤Æ¤¤¤¿¤Î¤À¤¬¡¢°ÊÁ°¤Ï̵»ë¤·¤Æ¤¤¤¿¡£Àè¤Ë¤³¤³¤ò¸«
-¤Æ¤ª¤³¤¦¡£
+・・・っと、その前に、ここまでですべての関数を網羅してしまったと思って
+いたのだが、一つ忘れていたものがあった。update() だ。この関数は、
+get_next() で呼び出されていたのだが、以前は無視していた。先にここを見
+ておこう。
 
 
-¤Þ¤º¡¢get_next() ¤òºÆ·Ç¤¹¤ë¡£
+まず、get_next() を再掲する。
 
 static void get_next()
 {
 
 static void get_next()
 {
@@ -1513,12 +1522,12 @@ static void get_next()
     hval = ((hval << 5) ^ text[pos + 2]) & (unsigned)(HSHSIZ - 1);
 }
 
     hval = ((hval << 5) ^ text[pos + 2]) & (unsigned)(HSHSIZ - 1);
 }
 
-remainder ¤È pos ¤ò¿Ê¤á¤¿¸å¡¢pos ¤¬ txtsiz - maxmatch ¤Ë㤷¤Æ¤·¤Þ¤Ã¤¿
-¾ì¹ç(pos == 2 * 2^dicbit ¤Î¾ì¹ç)¤Ë¸Æ¤Ó½Ð¤µ¤ì¤ë¤è¤¦¤À¡£¤Ä¤Þ¤ê¡¢°Ê²¼¤Î¿Þ
-¤Î¾õÂÖ¤À¡£¤³¤ì¤¬¡¢update() ¤ò¸Æ¤Ó½Ð¤¹»þ¤Î½é´ü¾õÂÖ¤À¡£
+remainder と pos を進めた後、pos が txtsiz - maxmatch に達してしまった
+場合(pos == 2 * 2^dicbit の場合)に呼び出されるようだ。つまり、以下の図
+の状態だ。これが、update() を呼び出す時の初期状態だ。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-                                
+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+-------------+-------------+---+
@@ -1533,7 +1542,7 @@ remainder 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤Ç¤Ï¡¢update() ¤ËÆþ¤ë¡£
+では、update() に入る。
 
 static void update()
 {
 
 static void update()
 {
@@ -1570,18 +1579,18 @@ static void update()
     }
 }
 
     }
 }
 
-ÀèƬ¤Ç¡¢¤Ê¤¼¤« memmove() ¤ò for ¥ë¡¼¥×¤Ç½ñ¤­´¹¤¨¤Æ¤¤¤ë¡£¤Ê¤¼¤³¤Î¤è¤¦¤Ê
-¤³¤È¤ò¹Ô¤Ã¤Æ¤¤¤ë¤Î¤À¤í¤¦¡£for ¥ë¡¼¥×¤ò¸«¤Æ¤ß¤Æ¤â¤ä¤Ã¤Æ¤¤¤ë¤³¤È¤ÏÊѤï¤é
-¤Ê¤¤¡£Ææ¤À¤¬¡¢¤È¤Ë¤«¤¯¡¢text[] ¤Î±¦È¾Ê¬(maxmatch Éôʬ¤â´Þ¤à) ¤òº¸¤Ë°Ü
-¤·¤Æ¤¤¤ë¡£
+先頭で、なぜか memmove() を for ループで書き換えている。なぜこのような
+ことを行っているのだろう。for ループを見てみてもやっていることは変わら
+ない。謎だが、とにかく、text[] の右半分(maxmatch 部分も含む) を左に移
+している。
 
 
-¼¡¤Ë fread_crc() ¤Ç¡¢¿·¤¿¤Ë¥Õ¥¡¥¤¥ë¤òÆɤ߹þ¤à¡£º£ÅÙ¤ÎÆɤ߹þ¤ß°ÌÃÖ¤Ï
-&text[txtsiz - dicsiz] ¤Ç¡¢Ä¹¤µ¤Ï dicsiz ¤Ç¤¢¤ë¡£ÅöÁ³¡¢remainder ¤â¹¹
-¿·¤·¤Æ¤¤¤ë¡£encoded_origsize ¤Ï°ÊÁ°¤ÈƱÍÍ̵»ë¡£pos ¤Ï dicsiz Ê¬¸º¤é¤µ
-¤ì¤Æ¤¤¤ë¡£¤³¤ì¤Ï¤Ä¤Þ¤ê¿Þ¼¨¤¹¤ë¤È¡¢°Ê²¼¤Î¾õÂ֤ˤʤë¤È¸À¤¦»ö¤À
+次に fread_crc() で、新たにファイルを読み込む。今度の読み込み位置は
+&text[txtsiz - dicsiz] で、長さは dicsiz である。当然、remainder も更
+新している。encoded_origsize は以前と同様無視。pos は dicsiz 分減らさ
+れている。これはつまり図示すると、以下の状態になると言う事だ
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-                                
+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+---+---------+-------------+---+
                                 dicsiz=2^dicbit               2*2^dicbit
                                    v                           v   txtsiz
        +-------------+-------------+---+---------+-------------+---+
@@ -1594,21 +1603,21 @@ static void update()
                                    <------------------------------->
                                               remainder
 
                                    <------------------------------->
                                               remainder
 
-       |------- °ÊÁ°¤Î¥Ç¡¼¥¿  ---------|--- ¿·¤·¤¤¥Ç¡¼¥¿  ---------|
+       |------- ä»¥å\89\8dã\81®ã\83\87ã\83¼ã\82¿  ---------|--- æ\96°ã\81\97ã\81\84ã\83\87ã\83¼ã\82¿  ---------|
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-°Ê¹ß¡¢¥Õ¥¡¥¤¥ë¤ÎÆɤ߹þ¤ß¤Ï¾ï¤Ë¤³¤Î update()¤Ç¤·¤«¹Ô¤ï¤ì¤Ê¤¤¡£pos ¤Ï¡¢
-½é´ü¾õÂÖ¤ÈƱ¤¸°ÌÃ֤ʤΤǡ¢½é´ü¾õÂÖ¤¬ºÆ¸½¤µ¤ì¤Æ¤¤¤ë¡£¤³¤³¤Þ¤Ç¤Ç¡¢
-maxmatch ¤ÎÎΰè¤Ï¤Ê¤ó¤À¤í¤¦¤È»×¤¦¤¬¡¢¤ª¤½¤é¤¯ÀèÆɤߤΤ¿¤á¤À¤í¤¦¡£¤½¤ì
-¤é¤·¤¤½èÍý¤Ï¡¢match_insert() ¤ÎËÁƬ¤Ë¤¢¤Ã¤¿(¤¬¡¢¸½»þÅÀ¤Ç¾ÜºÙ¤Ë¤Ï¿¨¤ì¤Æ
-¤¤¤Ê¤¤)¡£
+以降、ファイルの読み込みは常にこの update()でしか行われない。pos は、
+初期状態と同じ位置なので、初期状態が再現されている。ここまでで、
+maxmatch の領域はなんだろうと思うが、おそらく先読みのためだろう。それ
+らしい処理は、match_insert() の冒頭にあった(が、現時点で詳細には触れて
+いない)。
 
 
-# maxmatch Ê¬¤Î;ʬ¤ÊÎΰè¤Ï¡¢pos ¤Î°ÌÃÖ¤«¤éºÇÂç maxmatch Ä¹¤Îʸ»úÎó¾È
-# ¹ç¤ò¹Ô¤¦¤¿¤á¤ËɬÍפÊÎΰ衣ÀèÆɤߤȤϤޤ¿¸«Åö³°¤ì¤Ê¤³¤È¤ò½ñ¤¤¤¿¤â¤Î¤À¡£
-# ¤Á¤ç¤Ã¤È¹Í¤¨¤ì¤Ð¤ï¤«¤ë¤³¤È¤Ê¤Î¤Ë¡¦¡¦
+# maxmatch 分の余分な領域は、pos の位置から最大 maxmatch 長の文字列照
+# 合を行うために必要な領域。先読みとはまた見当外れなことを書いたものだ。
+# ちょっと考えればわかることなのに・・
 
 
-update() ¤Î»Ä¤ê¤ò¸«¤ë¡£
+update() の残りを見る。
 
     for (i = 0; i < HSHSIZ; i++) {
         j = hash[i];
 
     for (i = 0; i < HSHSIZ; i++) {
         j = hash[i];
@@ -1620,40 +1629,40 @@ update() 
         prev[i] = (j > dicsiz) ? j - dicsiz : NIL;
     }
 
         prev[i] = (j > dicsiz) ? j - dicsiz : NIL;
     }
 
-ÆâÍƤϡ¢ÁÛÁü¤¬¤Ä¤¯¤Î¤Ç¾ÜºÙ¤Ï¾Êά¤·¤è¤¦¡£Ã±¤Ë°ÊÁ°¤Î¥Ç¡¼¥¿¤¬°ÜÆ°¤·¤¿¤Î¤Ç¡¢
-¥Ï¥Ã¥·¥åÃͤò¹¹¿·¤·¤Æ¤¤¤ë¤À¤±¤À¡£¤·¤«¤·¡¢¤³¤ì¤Ï¤Ê¤«¤Ê¤«ÌµÂ̤ʽèÍý¤À¡£
+内容は、想像がつくので詳細は省略しよう。単に以前のデータが移動したので、
+ハッシュ値を更新しているだけだ。しかし、これはなかなか無駄な処理だ。
 
 
-°ÊÁ°¡¢text[] ¤Ï´Ä¾õ¥Ð¥Ã¥Õ¥¡¤À¤í¤¦¤ÈͽÁÛ¤·¤¿¤¬Í½ÁÛ¤¬¤Ï¤º¤ì¤¿¤³¤È¤¬¤ï¤«¤Ã
-¤¿¡£´Ä¾õ¥Ð¥Ã¥Õ¥¡¤Ë¤·¤Æ¤¤¤ì¤Ð¡¢¤³¤Î¥Ï¥Ã¥·¥å¤Î½ñ¤­´¹¤¨¤ÏÉÔÍפˤǤ­¤¿¤À¤í
-¤¦¤È»×¤¦¤Î¤À¤¬¡¦¡¦¡¦
-# ¤½¤Î¤«¤ï¤ê¡¢°ÌÃÖ¤ÎÂç¾®Èæ³Ó¤¬ÈË»¨¤Ë¤Ê¤é¤Ê¤¤¤Î¤Ç¡¢¤³¤ì¤Ï¤³¤ì¤ÇÎɤ¤¤Î¤«
-# ¤â¤·¤ì¤Ê¤¤¡£¤É¤Á¤é¤¬Í¥¤ì¤Æ¤¤¤ë¤«¤Ï¼Â¸³¤·¤Æ¤ß¤Ê¤±¤ì¤Ð¤ï¤«¤é¤Ê¤¤¤À¤í¤¦¡£
+以前、text[] は環状バッファだろうと予想したが予想がはずれたことがわかっ
+た。環状バッファにしていれば、このハッシュの書き換えは不要にできただろ
+うと思うのだが・・・
+# そのかわり、位置の大小比較が繁雑にならないので、これはこれで良いのか
+# もしれない。どちらが優れているかは実験してみなければわからないだろう。
 
 
-¤³¤ì¤Ç¡¢°ì±þ¤Ï slide.c ¤òÌÖÍ夹¤ë»ö¤¬¤Ç¤­¤¿¡£¤Þ¤ÀÉÔÌÀ¤ÊÅÀ¤Ï¿¤¤¤¬¡¢¥Ç
-¥Ð¥Ã¥¬¤Ç¼ÂºÝ¤Î½èÍý¤òÄɤ¤¤«¤±¤ì¤Ð¤Þ¤¿¤ï¤«¤ë¤³¤È¤¬¤¢¤ë¤À¤í¤¦¡£
+これで、一応は slide.c を網羅する事ができた。まだ不明な点は多いが、デ
+バッガで実際の処理を追いかければまたわかることがあるだろう。
 
 
-¡¦¡¦¡¦¤·¤Ð¤·¡¢µÙ©¡¦¡¦¡¦
+・・・しばし、休息・・・
 
 
-¤µ¤Æ¡¢¥Ç¥Ð¥Ã¥¬¤Ç¤È°ÊÁ°¤Ï¹Í¤¨¤Æ¤¤¤¿¤Î¤À¤¬¡¢¤¢¤­¤é¤á¤ë¤Î¤Ï¤Þ¤ÀÁᤤ(¸µµ¤
-¤¬½Ð¤¿¤é¤·¤¤)¡¢¤½¤â¤½¤âºÇ½é¤Ë¡Ö¥Ç¥Ð¥Ã¥¬¤ò»È¤ï¤º¤Ë¤É¤³¤Þ¤Ç²òÆɤǤ­¤ë¤«¡×¤Ã
-¤ÈËÁƬ¤Ë½ñ¤¤¤Æ¤¿¤Î¤Ë¤¿¤Ã¤¿2²ó¤ÎÄÌÆɤǤ⤦¤¢¤­¤é¤á¤è¤¦¤È¤·¤Æ¤¤¤¿¡£¤¬¡¢
-¤³¤³¤Þ¤Ç½ñ¤¤¤Æ¤­¤¿Ëܽñ¤ò²¿ÅÙ¤«ÆɤßÊÖ¤·¤¿¤¬¡¢¤Þ¤À¤Þ¤À¸¡Æ¤¤Î;ÃϤϤ¢¤ë¡£
+さて、デバッガでと以前は考えていたのだが、あきらめるのはまだ早い(元気
+が出たらしい)、そもそも最初に「デバッガを使わずにどこまで解読できるか」っ
+と冒頭に書いてたのにたった2回の通読でもうあきらめようとしていた。が、
+ここまで書いてきた本書を何度か読み返したが、まだまだ検討の余地はある。
 
 
-¤Þ¤º¡¢match_insert() ¤Î½èÍý¤Ç¤ï¤«¤é¤Ê¤«¤Ã¤¿Éôʬ¤ò²òÆɤ·¤è¤¦¡£¼Â¤Ï¡¢¤³
-¤ì¤Ë´Ø¤·¤Æ¤Ï¤É¤¦¤·¤Æ¤â¤ï¤«¤é¤ºÇº¤ó¤Ç¤¤¤¿¤È¤³¤í¡¢Lha for UNIX ¤Î¥á¥ó¥Æ
-¥Ê¤Ç¤¢¤ë²¬Ëܤµ¤ó¤Ë¶µ¤¨¤Æ¤â¤é¤¦¤³¤È¤¬¤Ç¤­¤¿(¤¢¤ê¤¬¤È¤¦¤´¤¶¤¤¤Þ¤¹)¤½¤ÎÆâ
-ÍƤò³Îǧ¤·¤Ä¤Ä match_insert() ¤ò¸«¤ë¤³¤È¤Ë¤¹¤ë¡£
+まず、match_insert() の処理でわからなかった部分を解読しよう。実は、こ
+れに関してはどうしてもわからず悩んでいたところ、Lha for UNIX のメンテ
+ナである岡本さんに教えてもらうことができた(ありがとうございます)その内
+容を確認しつつ match_insert() を見ることにする。
 
 
-¤Þ¤º¤Ï¡¢Éü½¬¤À¡£Ä̾ï¤Î¾õÂ֤˴ؤ·¤Æ¤Ï match_insert() ¤Î²òÆɤϺѤó¤Ç¤¤¤ë¡£
-match_insert() ¤Ï¡¢text[pos] ¤«¤é»Ï¤Þ¤ëʸ»úÎó¤ò¼­½ñ¤«¤é¸¡º÷¤·¡¢¸«¤Ä¤«¤Ã
-¤¿°ÌÃ֤ȰìÃ׍ò matchpos, matchlen ¤ËÀßÄꤹ¤ë½èÍý¤À¡£¤½¤·¤Æ¡¢¤Ä¤¤¤Ç¤Ë 
-insert() ¤Ç¡¢text[pos] ¤Î°ÌÃÖ¤ò¥Ï¥Ã¥·¥åÇÛÎó¤Ëµ­Ï¿¤·¡¢¼¡²ó¤Î¸¡º÷¤ËÈ÷¤¨
-¤ë¤³¤È¤â¤·¤Æ¤¤¤ë¡£
+まずは、復習だ。通常の状態に関しては match_insert() の解読は済んでいる。
+match_insert() は、text[pos] から始まる文字列を辞書から検索し、見つかっ
+た位置と一致長を matchpos, matchlen に設定する処理だ。そして、ついでに 
+insert() で、text[pos] の位置をハッシュ配列に記録し、次回の検索に備え
+ることもしている。
 
 
-¤Ç¤Ï¡¢ÉÔÌÀ¤ÊÉôʬ¤Ï¤Ê¤ó¤À¤Ã¤¿¤«¤È¤¤¤¦¤È too_flag[] ¤Þ¤ï¤ê¤Ç¤¢¤ë¡£
-too_flag ¤Î¥Õ¥é¥°¤¬Î©¤Ã¤Æ¤¤¤ë¤È¡£¼­½ñ¸¡º÷¤ÎÍê¤ê¤È¤Ê¤ë¥Ï¥Ã¥·¥åÃͤòÊѹ¹
-¤·¤Æ¤¤¤ë¡£¤³¤ÎÉôʬ¤¬¤Þ¤Ã¤¿¤¯³§Ìܸ¡Æ¤¤¬¤Ä¤«¤Ê¤«¤Ã¤¿¤Î¤À¡£¤³¤ì¤Ë´Ø¤·¤Æ¥½¡¼
-¥¹¤òÆɤ߿ʤá¤è¤¦¡£°Ê²¼¥½¡¼¥¹¤òºÆ·Ç¤¹¤ë¡£
+では、不明な部分はなんだったかというと too_flag[] まわりである。
+too_flag のフラグが立っていると。辞書検索の頼りとなるハッシュ値を変更
+ã\81\97ã\81¦ã\81\84ã\82\8bã\80\82ã\81\93ã\81®é\83¨å\88\86ã\81\8cã\81¾ã\81£ã\81\9fã\81\8fç\9a\86ç\9b®æ¤\9cè¨\8eã\81\8cã\81¤ã\81\8bã\81ªã\81\8bã\81£ã\81\9fã\81®ã\81 ã\80\82ã\81\93ã\82\8cã\81«é\96¢ã\81\97ã\81¦ã\82½ã\83¼
+スを読み進めよう。以下ソースを再掲する。
 
 static void match_insert()
 {
 
 static void match_insert()
 {
@@ -1706,30 +1715,30 @@ static void match_insert()
     hash[hval] = pos;
 }
 
     hash[hval] = pos;
 }
 
-¤Þ¤º¡¢too_flag[] ¤Ï¡¢ºÇ½é¤¹¤Ù¤Æ¤ÎÍ×ÁǤ¬ 0 ¤Ç¤¢¤ë¡£¤½¤·¤Æ¡¢¿·¤¿¤Ë¥Õ¥¡¥¤
-¥ë¤òÆɤà¤È¤­(update())¤â 0 ¤ËºÆ½é´ü²½¤µ¤ì¤ë¤Î¤À¤Ã¤¿¡£¤³¤Î¥Õ¥é¥°¤¬Î©¤Ä
-¾ò·ï¤Ï¤È¤¤¤¦¤È¡¢¤³¤Î match_insert() ¤ÎÃæ¤À¤±¤Ç¤¢¤ë¡£¤½¤Î½èÍý¤Ï
+ã\81¾ã\81\9aã\80\81too_flag[] ã\81¯ã\80\81æ\9c\80å\88\9dã\81\99ã\81¹ã\81¦ã\81®è¦\81ç´ ã\81\8c 0 ã\81§ã\81\82ã\82\8bã\80\82ã\81\9dã\81\97ã\81¦ã\80\81æ\96°ã\81\9fã\81«ã\83\95ã\82¡ã\82¤
+ルを読むとき(update())も 0 に再初期化されるのだった。このフラグが立つ
+条件はというと、この match_insert() の中だけである。その処理は
 
         if (chain >= LIMIT)
             too_flag[h] = 1;
 
 
         if (chain >= LIMIT)
             too_flag[h] = 1;
 
-¤³¤ÎÉôʬ¤À¤±¤À¡£chain ¤¬ LIMIT°Ê¾å¤Ë¤Ê¤Ã¤¿¤é h (¤³¤ì¤Ï¸¡º÷ÂоݤΥϥå·¥å
-ÃͤÀ)¤Ë´Ø¤·¤Æ¡¢¥Õ¥é¥°¤òΩ¤Æ¤ë¡£chain ¤Ï while ¥ë¡¼¥×(¤³¤ì¤Ïʸ»úÎó¤Î¾È
-¹ç¤ò¹Ô¤¦½èÍý)¤Î¥ë¡¼¥×²ó¿ô¤À¡£h ¤Ë´Ø¤·¤Æ¤Î¸¡º÷¤¬ LIMIT{256} °Ê¾å¤Î¾ì¹ç
-¤Ë too_flag[h] ¤Î¥Õ¥é¥°¤¬Î©¤Ã¤Æ¤¤¤ë¡£
+この部分だけだ。chain が LIMIT以上になったら h (これは検索対象のハッシュ
+値だ)に関して、フラグを立てる。chain は while ループ(これは文字列の照
+合を行う処理)のループ回数だ。h に関しての検索が LIMIT{256} 以上の場合
+に too_flag[h] のフラグが立っている。
 
 
-while ¥ë¡¼¥×¤Ï°ìÃ×ʸ»úÎó¤Î°ìÃ׍¬ºÇĹ°ìÃ׍Ë㤹¤ë¤«¡¢¼­½ñ¤òºÇ¸å¤Þ¤Ç
-õº÷¤¹¤ë¤Þ¤Ç¥ë¡¼¥×¤¹¤ë¡£¤Ä¤Þ¤ê¡¢¤¢¤ë¥Ï¥Ã¥·¥å h ¤Ë´Ø¤·¤Æ¤½¤Î¥Á¥§¡¼¥ó¤¬ 
-256 °Ê¾å¤Î¤â¤Î¤Ë´Ø¤·¤Æ¤Ï¡¢too_flag[h] ¤¬ 1 ¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£
+while ループは一致文字列の一致長が最長一致長に達するか、辞書を最後まで
+探索するまでループする。つまり、あるハッシュ h に関してそのチェーンが 
+256 以上のものに関しては、too_flag[h] が 1 になっている。
 
 
-¤Ç¤Ï¡¢¤½¤Î¤è¤¦¤Ê h ¤Ë´Ø¤·¤Æ¡¢match_insert() ¤¬¤É¤Î¤è¤¦¤Ê½èÍý¤Ë¤Ê¤Ã¤Æ¤¤
-¤ë¤«¤ò¸«¤ë¡£¤Þ¤º½é´ü²½Éôʬ
+では、そのような h に関して、match_insert() がどのような処理になってい
+るかを見る。まず初期化部分
 
     max = maxmatch; /* MAXMATCH; */
     if (matchlen < THRESHOLD - 1) matchlen = THRESHOLD - 1;
     matchpos = pos;
 
 
     max = maxmatch; /* MAXMATCH; */
     if (matchlen < THRESHOLD - 1) matchlen = THRESHOLD - 1;
     matchpos = pos;
 
-¤³¤ì¤Ï¡¢¤È¤ê¤¢¤¨¤ºÌµ»ë¡£
+これは、とりあえず無視。
 
     off = 0;
     for (h = hval; too_flag[h] && off < maxmatch - THRESHOLD; ) {
 
     off = 0;
     for (h = hval; too_flag[h] && off < maxmatch - THRESHOLD; ) {
@@ -1737,15 +1746,15 @@ while 
     }
     if (off == maxmatch - THRESHOLD) off = 0;
 
     }
     if (off == maxmatch - THRESHOLD) off = 0;
 
-Ä̾ï off ¤Ï¡¢0 ¤Ê¤Î¤À¤¬¡¢too_flag[h] ¤¬ 1 ¤Ç¤¢¤ë¤â¤Î¤Ë´Ø¤·¤Æ¤ÏÃͤ¬ÊѤï
-¤ë¡£¸¡º÷ÂоݤȤʤëʸ»úÎó text[pos](¤Î¥Ï¥Ã¥·¥åÃÍ) hval ¤Ë´Ø¤·¤Æ¡¢
-too_flag[h] ¤¬Î©¤Ã¤Æ¤¤¤ì¤Ð¡¢(¤³¤Î¥Ï¥Ã¥·¥å¤Î¥Á¥§¡¼¥ó¤¬ 256 °Ê¾å¤Ç¤¢¤ë¤³
-¤È¤¬»öÁ°¤Ë¤ï¤«¤Ã¤Æ¤¤¤ì¤Ð)
+通常 off は、0 なのだが、too_flag[h] が 1 であるものに関しては値が変わ
+る。検索対象となる文字列 text[pos](のハッシュ値) hval に関して、
+too_flag[h] が立っていれば、(このハッシュのチェーンが 256 以上であるこ
+とが事前にわかっていれば)
 
         h = ((h << 5) ^ text[pos + (++off) + 2]) & (unsigned)(HSHSIZ - 1);
 
 
         h = ((h << 5) ^ text[pos + (++off) + 2]) & (unsigned)(HSHSIZ - 1);
 
-¤Ç¡¢¸¡º÷ÂоݤȤʤë¥Ï¥Ã¥·¥åÃͤòÊѹ¹¤·¤Æ¤¤¤ë¡£¤³¤Î¥Ï¥Ã¥·¥åÃͤ¬¼¨¤¹¤Î¤Ï¸µ
-¤Î¸¡º÷ÂоÝʸ»úÎó¤Î 1 Ê¸»úÀè¤À¡£
+で、検索対象となるハッシュ値を変更している。このハッシュ値が示すのは元
+の検索対象文字列の 1 文字先だ。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -1760,20 +1769,20 @@ text   |             |  |  |  |  |  |  |
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¸µ¤Î¸¡º÷ÂоÝʸ»úÎ󤬿ޤΠa ¤À¤È¤¹¤ë¤È¡¢¤³¤ì¤ò¿Þ¤Î b ¤Ë¤·¤Æ¤¤¤ë¡£½é´ü²½
-Éô¤Î¥ë¡¼¥×¤Ï¡¢¤â¤·¤³¤Î b ¤Î¥Ï¥Ã¥·¥å¥Á¥§¡¼¥ó¤Ë´Ø¤·¤Æ too_flag[h] ¤¬¤µ¤é
-¤Ë 1 ¤Ç¤¢¤ë¤Ê¤é¤µ¤é¤Ë Àè¤Îʸ»úÎó¤ò¥Ï¥Ã¥·¥åÃͤȤ¹¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£
-(¤³¤ì¤Ï¸µ¤Î pos ¤Î 2 Ê¸»úÀè¤ò¼¨¤¹¡£¿Þ¤Î c ¤ÎÉôʬ¤À) h ¤Ï¡¢pos+off ¤«¤é
-¤Î3ʸ»ú¤Î¥Ï¥Ã¥·¥åÃͤò¼¨¤¹¤â¤Î¤È¸À¤¦»ö¤À¡£
+元の検索対象文字列が図の a だとすると、これを図の b にしている。初期化
+部のループは、もしこの b のハッシュチェーンに関して too_flag[h] がさら
+に 1 であるならさらに 先の文字列をハッシュ値とするようになっている。
+(これは元の pos の 2 文字先を示す。図の c の部分だ) h は、pos+off から
+の3文字のハッシュ値を示すものと言う事だ。
 
 
-¤¿¤À¤·¡¢h ¤¬¤¢¤Þ¤ê¤Ë¤âÀè¤ÎÊý¤ò¸«¤ë¤è¤¦¤Ê¥Ï¥á¤Ë¤Ê¤ì¤Ð(off ¤¬ maxmatch -
-THRESHOLD) off ¤Ï 0 ¤ËºÆÀßÄꤵ¤ì¤ë¤¬¡¢¤³¤Î¤È¤­ h ¤Ï¤½¤Î¤Þ¤Þ¤À¡£¤³¤Î°Õ
-Ì£¤Ï¤Þ¤À¤ï¤«¤é¤Ê¤¤¤¬¡¢¥Ð¥°¤Ê¤Î¤Ç¤Ï¤Ê¤¤¤«¤ÈÁÛÁü¤·¤Æ¤¤¤ë(h = hval ¤ËºÆÀß
-Äꤹ¤ëɬÍפ¬¤¢¤ë¤À¤í¤¦)
+ただし、h があまりにも先の方を見るようなハメになれば(off が maxmatch -
+THRESHOLD) off は 0 に再設定されるが、このとき h はそのままだ。この意
+味はまだわからないが、バグなのではないかと想像している(h = hval に再設
+定する必要があるだろう)
 
 
-¤Ç¤Ï off = 1 ¤À¤È¤·¤ÆËܽèÍý¤ò¸«¤ë¤³¤È¤Ë¤·¤è¤¦¡£³°Â¦¤Î for ¥ë¡¼¥×¤Ë´Ø¤·
-¤Æ¤Ï¡¢while ¥ë¡¼¥×¤ò2²ó¼Â¹Ô¤¹¤ë¤«¤É¤¦¤«¤À¤±¤Î¤â¤Î¤À¤Ã¤¿¡£¤Ê¤Î¤Ç¡¢ 
-while ¥ë¡¼¥×Éô¤À¤±¤ò¸«¤Æ¤ß¤è¤¦¡£
+では off = 1 だとして本処理を見ることにしよう。外側の for ループに関し
+ては、while ループを2回実行するかどうかだけのものだった。なので、 
+while ループ部だけを見てみよう。
 
         chain = 0;
         scan_pos = hash[h];
 
         chain = 0;
         scan_pos = hash[h];
@@ -1800,12 +1809,12 @@ while 
         if (chain >= LIMIT)
             too_flag[h] = 1;
 
         if (chain >= LIMIT)
             too_flag[h] = 1;
 
-scan_pos, scan_end ¤Ë´Ø¤·¤Æ¤Ï¸¡º÷³«»Ï°ÌÃ֤ȽªÎ»°ÌÃ֤ȸÀ¤¦»ö¤Ç¤â¤¦Îɤ¤
-¤À¤í¤¦¡£¤Ç¡¢ºÇ½é¤Î if ¤Î¾ò·ï¤ËÃåÌܤ¹¤ë¡£
+scan_pos, scan_end に関しては検索開始位置と終了位置と言う事でもう良い
+だろう。で、最初の if の条件に着目する。
 
             if (text[scan_pos + matchlen - off] == text[pos + matchlen]) {
 
 
             if (text[scan_pos + matchlen - off] == text[pos + matchlen]) {
 
-¤³¤ì¤¬¿¿¤È¤Ê¤ë¾õÂÖ¤ò¿Þ¼¨¤·¤è¤¦¡£
+これが真となる状態を図示しよう。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -1819,27 +1828,27 @@ text   |               |  |x'|  |                    |  |  |x |  |  |  |
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤Þ¤º¡¢if ¾ò·ï¤Îº¸ÊÕ
+まず、if 条件の左辺
 
   text[scan_pos + matchlen - off]
 
 
   text[scan_pos + matchlen - off]
 
-matchlen ¤Ï¡¢match_insert() ¤ËÆþ¤ëľÁ°¤Ë 2 ¤Ë½é´ü²½¤µ¤ì¤Æ¤¤¤ë(ºÇ½é¤Ï)
-¤Î¤Ç¡¢¾È¹ç¤¹¤ë¤Î¤Ï¿Þ¤Î x' ¤À¡£
+matchlen は、match_insert() に入る直前に 2 に初期化されている(最初は)
+ので、照合するのは図の x' だ。
 
 
-if ¾ò·ï¤Î±¦ÊÕ
+if 条件の右辺
 
   text[pos + matchlen]
 
 
   text[pos + matchlen]
 
-¤³¤ì¤Ï¡¢¿Þ¤Î x ¤Î°ÌÃÖ¤À¡£x' == x ¤Ê¤é¤ÐËܳÊŪ¤Ë¾È¹ç¤ò³«»Ï¤¹¤ë¡£
+これは、図の x の位置だ。x' == x ならば本格的に照合を開始する。
 
                 {
                     a = text + scan_pos - off;  b = text + pos;
                     for (len = 0; len < max && *a++ == *b++; len++);
                 }
 
 
                 {
                     a = text + scan_pos - off;  b = text + pos;
                     for (len = 0; len < max && *a++ == *b++; len++);
                 }
 
-¤³¤³¤ÇÈæ³Ó¤·¤Æ¤¤¤ë¤Î¤Ï¡¢¿Þ¤Î a ¤È b ¤À¡£b ¤Ï¡¢off ¤¬¤É¤Î¤è¤¦¤Ê¾ì¹ç¤Ç¤â
-ÊѤï¤é¤Ê¤¤¤¬¡¢a ¤Ï¡¢off ¤¬Â礭¤±¤ì¤ÐÂ礭¤¤Äøº¸Â¦¤ò»Ø¤¹¡£off ¤¬Î㤨¤Ð
-3 ¤Ç¤¢¤ë¤È¤­¤Î¾ì¹ç¤â¸«¤Æ¤ß¤è¤¦¡£
+ここで比較しているのは、図の a と b だ。b は、off がどのような場合でも
+変わらないが、a は、off が大きければ大きい程左側を指す。off が例えば
+3 であるときの場合も見てみよう。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -1852,48 +1861,48 @@ text   |             x'|  |  |  |                    |  |  |x |  |  |  |
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-·ë¶ÉÈæ³Ó¤·¤Æ¤¤¤ë¤Î¤Ï¡¢pos ¤«¤é¤Îʸ»úÎó¤Î¥Ï¥Ã¥·¥åÃͤòµá¤á¤¿¾ì¹ç¤È²¿¤âÊÑ
-¤ï¤é¤Ê¤¤¡£off ¤Ç¤¤¤¯¤éÀè¤ò¸«¤è¤¦¤È¤âÈæ³Ó¤¹¤ë¤Î¤Ï pos ¤Î°ÌÃÖ¤À¡£¤Ê¤¼¤³
-¤Î¤è¤¦¤Ê¤³¤È¤ò¤¹¤ë¤Î¤À¤í¤¦¤«¡©¤³¤ì¤ÏºÇ½é¤É¤¦¤·¤Æ¤â¤ï¤«¤é¤Ê¤«¤Ã¤¿¤Î¤À¤¬¡¢
-ÀâÌÀ¤ò¼õ¤±¤ÆǼÆÀ¤·¤¿¡£
+結局比較しているのは、pos からの文字列のハッシュ値を求めた場合と何も変
+わらない。off でいくら先を見ようとも比較するのは pos の位置だ。なぜこ
+のようなことをするのだろうか?これは最初どうしてもわからなかったのだが、
+説明を受けて納得した。
 
 
-¤³¤ì¤Ïñ¤Ë¸úΨ(®ÅÙ)¤Î¤¿¤á¤È¤¤¤¦¤³¤È¤À¡£¤â¤·¡¢¿Þ¤Î b ¤Ë´Ø¤·¤Æ¾È¹çʸ»ú
-Îó¤Î¸õÊ䤬¤¢¤Þ¤ê¤Ë¤â¿¤¤¾ì¹ç(too_flag[h]=1)¡¢¥Ï¥Ã¥·¥å¤Î¥Á¥§¡¼¥ó¤ò²¿ÅÙ
-¤â¤¿¤É¤ë»ö¤Ë¤Ê¤ë¤Î¤Ç¸úΨ¤¬°­¤¤¡£¤·¤«¤·¡¢¼­½ñ¸¡º÷¤Î¥­¡¼¤ò²¿Ê¸»ú¤«¿Ê¤á¤ë
-»ö¤Ç¡¢¤³¤Î²ÄǽÀ­¤ò¸º¤é¤¹»ö¤¬¤Ç¤­¤ë¡£¾¯¤Ê¤¯¤È¤âºÇ°­¤Î 256 ¤è¤ê¤Ï¥Þ¥·¤Ë
-¤Ê¤ë¤è¤¦¤Ê¤â¤Î¤òÁª¤ó¤Ç¤¤¤ë¡£¤½¤¦¤·¤Æ¡¢¤³¤Î while ¥ë¡¼¥×¤Î¥ë¡¼¥×²ó¿ô¤ò
-¸º¤é¤·¤Æ¤¤¤ë¤Î¤À¡£¤É¤¦¤»Ãµ¤·¤¿¤¤¤Î¤ÏºÇĹ°ìÃ×ʸ»úÎó¤Ê¤Î¤ÇÀè¤ÎÊý¤Îʸ»úÎó
-¤¬°ìÃפ·¤Ê¤¤¤ÈÏäˤʤé¤Ê¤¤¤Î¤À¤«¤é¤³¤ì¤Ï¹çÍýŪ¤À¡£
+これは単に効率(速度)のためということだ。もし、図の b に関して照合文字
+列の候補があまりにも多い場合(too_flag[h]=1)、ハッシュのチェーンを何度
+もたどる事になるので効率が悪い。しかし、辞書検索のキーを何文字か進める
+事で、この可能性を減らす事ができる。少なくとも最悪の 256 よりはマシに
+なるようなものを選んでいる。そうして、この while ループのループ回数を
+減らしているのだ。どうせ探したいのは最長一致文字列なので先の方の文字列
+が一致しないと話にならないのだからこれは合理的だ。
 
 
-¤³¤ì¤Ç¡¢³°Â¦¤Î for ¥ë¡¼¥×¤âǼÆÀ¤À¡£¤³¤ì¤Ï while ¥ë¡¼¥×¤ò¤¢¤ë¾ò·ï¤Ç¤ä¤ê
-ľ¤¹½èÍý¤À¤Ã¤¿¡£
+これで、外側の for ループも納得だ。これは while ループをある条件でやり
+直す処理だった。
 
         if (matchlen > off + 2 || off == 0)
             break;
 
 
         if (matchlen > off + 2 || off == 0)
             break;
 
-ºÇĹ°ìÃ׍¬¸«¤Ä¤«¤ë¤«¡¢¤¢¤ë¤¤¤Ï off ¤¬ 0 ¤Ç¤¢¤ì¤Ð¤µ¤Ã¤µ¤È¤³¤Î½èÍý¤Ï½ª
-¤ë¤Î¤À¤¬¡¢¤â¤· off ¤ò¿Ê¤á¤Æ¾È¹ç¤ò¹Ô¤Ã¤Æ¤¤¤¿¤È¤·¤Æ¡¢ºÇĹ°ìÃ×ʸ»úÎ󤬸«
-¤Ä¤«¤é¤Ê¤«¤Ã¤¿¤È¤¹¤ë¤È
+最長一致長が見つかるか、あるいは off が 0 であればさっさとこの処理は終
+るのだが、もし off を進めて照合を行っていたとして、最長一致文字列が見
+つからなかったとすると
 
         max = off + 2;
         off = 0;
         h = hval;
 
 
         max = off + 2;
         off = 0;
         h = hval;
 
-¤È¤¤¤¦¾ò·ï¤Ç¾È¹ç¤ò¤ä¤êľ¤¹¡£¤³¤ì¤Ï¸µ¤Îʸ»úÎó¤Ç¾È¹ç¤ò¤ä¤êľ¤¹¤È¤¤¤¦¤³¤È
-¤À¤«¤é¤Ä¤Þ¤ê¤Ï¡¢ºÇ°­¤Î¥Ï¥Ã¥·¥å¥Á¥§¡¼¥ó¤ò»ÅÊý¤Ê¤¤¤«¤éé¤êľ¤½¤¦¤È¸À¤¦»ö
-¤À¡£¤µ¤é¤Ë¡¢pos ¤«¤é pos+off+3 ¤Þ¤Ç¤Îʸ»úÎ󤬡¢¼­½ñ¤«¤é¸«¤Ä¤«¤é¤Ê¤«¤Ã
-¤¿¤Î¤Ç¡¢ºÇÂç°ìÃ׍ò off + 2 ¤È¤·¤Æ¾ò·ï¤ò´Ë¤á¤Æ¤¤¤ë(¤Ê¤¼¤³¤ì¤¬¾ò·ï¤ò´Ë
-¤á¤ë»ö¤Ë¤Ê¤ë¤«¤È¸À¤¦¤È while ¥ë¡¼¥×¤ÏºÇÂç°ìÃ׍Îʸ»úÎ󤬸«¤Ä¤«¤Ã¤¿¤é
-¤¹¤°¤ËÈ´¤±¤ë¤«¤é¤À)¡£
+という条件で照合をやり直す。これは元の文字列で照合をやり直すということ
+だからつまりは、最悪のハッシュチェーンを仕方ないから辿り直そうと言う事
+だ。さらに、pos から pos+off+3 までの文字列が、辞書から見つからなかっ
+たので、最大一致長を off + 2 として条件を緩めている(なぜこれが条件を緩
+める事になるかと言うと while ループは最大一致長の文字列が見つかったら
+すぐに抜けるからだ)。
 
 
-¤È¤³¤í¤Ç¡¢match_insert() ¤ÎÀè¤Î½èÍý¤Ï°Ê²¼¤Î½ñ¤­´¹¤¨¤ò¹Ô¤¦¤È¤â¤¦¾¯¤·¸«
-¤ä¤¹¤¯¤Ê¤ë¡£(¤È»×¤¦)¡£
+ところで、match_insert() の先の処理は以下の書き換えを行うともう少し見
+やすくなる。(と思う)。
 
 
-o scan_beg ¤È¤¤¤¦ÊÑ¿ô¤òÍÑ°Õ¤·¡¢¤³¤ì¤ò scan_pos - off ¤Ë¤¹¤ë¡£
-o scan_end ¤Ï¡¢pos - dicsiz ¤Ë¤¹¤ë¡£
-o while ¾ò·ï¤ò while (scan_pos != NIL && scan_beg > scan_end) ¤Ë¤¹¤ë¡£
+o scan_beg という変数を用意し、これを scan_pos - off にする。
+o scan_end は、pos - dicsiz にする。
+o while 条件を while (scan_pos != NIL && scan_beg > scan_end) にする。
 
 
-°Ê²¼
+以下
 
         unsigned int scan_pos = hash[h];
         int scan_beg = scan_pos - off;
 
         unsigned int scan_pos = hash[h];
         int scan_beg = scan_pos - off;
@@ -1936,50 +1945,50 @@ text   |      |      x'|  |  |  |                    |  |  |x |  |  |  |
      scan_end
 
          |----|
      scan_end
 
          |----|
-           scan_beg ¤ÎÍ­¸úÈÏ°Ï
+           scan_beg の有効範囲
 
          |----------------- dicsiz ------------------|
 
 ----------------------------------------------------------------------------
 
 
          |----------------- dicsiz ------------------|
 
 ----------------------------------------------------------------------------
 
-scan_beg, scan_end ¤ÎÈϰϤâ¤ï¤«¤ê¤ä¤¹¤¤¤·¡¢hash[h] ¤¬ NIL ¤Î¾ì¹ç¤Î½èÍý
-¤âÌÀ¼¨Åª¤À¡£¤³¤Î½ñ¤­´¹¤¨¤ò¹Ô¤¦¾ì¹ç¡¢scan_beg ¤¬Éé¤ÎÃͤˤʤë²ÄǽÀ­¤¬¤¢
-¤ë¡£¸µ¤â¤È¤Î½èÍý¤Ç¤Ï scan_end Åù¤ÎÊÑ¿ô¤ò unsigned ¤Ë¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¤³¤ì
-¤é¤ò int ¤Ë¤·¤Æ while ¾ò·ï¤ÇÉé¤Î scan_beg ¤ò¤Ï¤¸¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³¤È
-¤ËÃí°Õ¡£¤½¤¦¤¹¤ë¤È¡¢scan_pos != NIL ¤ÏɬÍפʤ¯¤Ê¤ë¤Î¤À¤¬¤ï¤«¤ê¤ä¤¹¤µ¤ò
-Äɵᤷ¤¿¡£
+scan_beg, scan_end の範囲もわかりやすいし、hash[h] が NIL の場合の処理
+も明示的だ。この書き換えを行う場合、scan_beg が負の値になる可能性があ
+る。元もとの処理では scan_end 等の変数を unsigned にしているので、これ
+らを int にして while 条件で負の scan_beg をはじかなければならないこと
+に注意。そうすると、scan_pos != NIL は必要なくなるのだがわかりやすさを
+追求した。
 
 
-¤³¤ì¤Ç match_insert() ¤Î²òÆɤϽª¤ê¤À¡£match_insert() ¤Î½èÍý¤È¤Ï°Ê²¼¤Î
-Ä̤ê¤À¡£
+これで match_insert() の解読は終りだ。match_insert() の処理とは以下の
+通りだ。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-  match_insert() ¤Ï¡¢text[pos] ¤«¤é»Ï¤Þ¤ëʸ»úÎó¤Ë°ìÃפ¹¤ëʸ»úÎó¤ò¼­½ñ
-  ¤«¤é¸¡º÷¤·¡¢¸«¤Ä¤«¤Ã¤¿°ÌÃ֤ȰìÃ׍ò matchpos, matchlen ¤ËÀßÄꤹ¤ë¡£
+  match_insert() は、text[pos] から始まる文字列に一致する文字列を辞書
+  から検索し、見つかった位置と一致長を matchpos, matchlen に設定する。
 
 
-  ¤â¤·¡¢ºÇĹ°ìÃ×ʸ»úÎ󤬸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð matchpos ¤Ï¡¢pos ¤ËÀßÄꤵ¤ì¡¢
-  matchlen ¤Ï¹¹¿·¤µ¤ì¤Ê¤¤¡£(¼Â¤Ï¡¢matchpos = pos ¤Î¾ðÊó¤ÏÆä˻Ȥï¤ì¤Æ¤Ê¤¤)
+  もし、最長一致文字列が見つからなければ matchpos は、pos に設定され、
+  matchlen は更新されない。(実は、matchpos = pos の情報は特に使われてない)
 
 
-  ¸«¤Ä¤«¤Ã¤¿¾ì¹ç¡¢matchlen ¤Ï¸Æ¤Ó½Ð¤·Á°¤Î matchlen ¤è¤ê¤âÂ礭¤¯¤Ê¤ë¡£
-  (¸Æ¤Ó½Ð¤·Á°¤Ç¤Ï matchlen ¤Î°ÕÌ£¤ÏºÇÄã¸Â°ìÃפ·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤Ê¸»úÎó
-  Ä¹¤Ç¡¢¾È¹ç¾ò·ï¤Î°ì¤Ä¤Ë¤Ê¤Ã¤Æ¤¤¤ë)
+  見つかった場合、matchlen は呼び出し前の matchlen よりも大きくなる。
+  (呼び出し前では matchlen の意味は最低限一致しなくてはならない文字列
+  長で、照合条件の一つになっている)
 
 
-  ¤³¤Î´Ø¿ô¤ÎÆþÎϤÏ
+  この関数の入力は
 
       matchlen
       pos
 
 
       matchlen
       pos
 
-  ½ÐÎϤÏ
+  出力は
 
       matchlen
       matchpos
 
 
       matchlen
       matchpos
 
-  ¤È¤¤¤Ã¤¿¤È¤³¤í¡£
+  といったところ。
 
 
-  ¤µ¤é¤Ë¡¢insert() ¤ÈƱÍͤνèÍý¤Ç¡¢pos ¤Î°ÌÃÖ¤ò¥Ï¥Ã¥·¥åÇÛÎó¤Ëµ­Ï¿¤·¡¢
-  ¼¡²ó¤Î¸¡º÷¤ËÈ÷¤¨¤ë¡£¤³¤ì¤Ï¤Ä¤¤¤Ç¤Î½èÍý¡£
+  さらに、insert() と同様の処理で、pos の位置をハッシュ配列に記録し、
+  次回の検索に備える。これはついでの処理。
 ---------------------------------------------------------------------------- 
 
 ---------------------------------------------------------------------------- 
 
-¤³¤ì¤òƧ¤Þ¤¨¤¿¾å¤Ç½èÍýÆâÍƤòºÆÆɤ·¤è¤¦¡£(E) ¡Á (H) ¤À¡£
+これを踏まえた上で処理内容を再読しよう。(E) 〜 (H) だ。
 
         /* (E) */
         lastmatchlen = matchlen;  lastmatchoffset = pos - matchpos - 1;
 
         /* (E) */
         lastmatchlen = matchlen;  lastmatchoffset = pos - matchpos - 1;
@@ -1996,42 +2005,42 @@ scan_beg, scan_end 
             count++;
         } else {
 
             count++;
         } else {
 
-(H) ¤Î¾ò·ï¤È¤Ï²¿¤Ê¤Î¤«¤ò¸«¤ë¡£¤³¤Î¾ò·ï¤¬¿¿¤Ê¤é¡¢Ê¸»úÎó¤ò¤½¤Î¤Þ¤Þ½ÐÎϤ¹
-¤ë¤Î¤À¤¬¡¢ÁÇľ¤Ë slide ¼­½ñË¡¤Î½èÍý¤ò¹Í¤¨¤ì¤Ð¤³¤Î¾ò·ï¤Ï¡Ö¼­½ñ¤«¤é¸«¤Ä
-¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¡×¤È¤Ê¤ë¡£¤¬¡¢¼ÂºÝ¤Ë¤Ï¤â¤¦¾¯¤·Ê£»¨¤À¡£
+(H) の条件とは何なのかを見る。この条件が真なら、文字列をそのまま出力す
+るのだが、素直に slide 辞書法の処理を考えればこの条件は「辞書から見つ
+からなかった場合」となる。が、実際にはもう少し複雑だ。
 
         /* (H) */
         if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD) {
 
 
         /* (H) */
         if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD) {
 
-matchlen ¤Ï¡¢pos ¤Î°ÌÃÖ¤Îʸ»úÎ󤬸«¤Ä¤«¤Ã¤¿¼­½ñ¾å¤ÎŤµ
-lastmatchlen ¤Ï¡¢pos-1 ¤Î°ÌÃÖ¤Îʸ»úÎ󤬸«¤Ä¤«¤Ã¤¿¼­½ñ¾å¤ÎŤµ
+matchlen は、pos の位置の文字列が見つかった辞書上の長さ
+lastmatchlen は、pos-1 の位置の文字列が見つかった辞書上の長さ
 
 
-¤Ç¤¢¤ë¤È¤¹¤ë¤È¡¢¤³¤Î¾ò·ï¤Ï¡¢¡Öpos ¤Î°ÌÃ֤Ǹ«¤Ä¤«¤Ã¤¿Ä¹¤µ¤¬¡¢pos-1 ¤Î°Ì
-Ã֤Ǹ«¤Ä¤«¤Ã¤¿Ä¹¤µ¤è¤ê¤âŤ±¤ì¤Ð¡×¤Ã¤È¤Ê¤ë¡£
+であるとすると、この条件は、「pos の位置で見つかった長さが、pos-1 の位
+置で見つかった長さよりも長ければ」っとなる。
 
 
-¤³¤ì¤Ï¤Ä¤Þ¤ê¡¢pos-1 ¤È pos ¤Î¥Ë²Õ½ê¤Ë´Ø¤·¤Æ¼­½ñ¤ò¸¡º÷¤·¤Æ¡¢¤è¤êŤ¯¥Þ¥Ã
-¥Á¤¹¤ëÊý¤òÁª¤Ü¤¦¤È¤·¤Æ¤¤¤ë¤ï¤±¤À¡£matchlen ¤ÎÊý¤¬Ä¹¤¤¤Ê¤é 1 ¤ÄÁ°
-(pos-1)¤Îʸ»ú¤Ï¤½¤Î¤Þ¤Þ½ÐÎϤ·¡¢¼¡¤Î¥ë¡¼¥×¤Ë°Ü¤ë(¤â¤·¡¢¼¡¤Îʸ»ú¤¬
-¤µ¤é¤ËŤ¯¥Þ¥Ã¥Á¤¹¤ë¤Ê¤é¡£¤Þ¤¿¤½¤Î¤Þ¤Þ½ÐÎϤµ¤ì¤ë)
+これはつまり、pos-1 と pos のニ箇所に関して辞書を検索して、より長くマッ
+チする方を選ぼうとしているわけだ。matchlen の方が長いなら 1 つ前
+(pos-1)の文字はそのまま出力し、次のループに移る(もし、次の文字が
+さらに長くマッチするなら。またそのまま出力される)
 
 
-¤³¤Î¾ò·ï¤Ç¡Ö¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¡×¤È¤¤¤¦¤Î¤Ï¤É¤¦É½¤µ¤ì¤Æ¤¤¤ë¤«¤ò¹Í¤¨¤ë¡£
-¤â¤·¡¢pos ¤Îʸ»úÎ󤬼­½ñ¤Ë¤Ê¤±¤ì¤Ð pos - 1 ¤Îʸ»úÎó¤Ï¡¢¤É¤¦¤¹¤Ù¤­¤«¤È
-¤¤¤¦¤È¡Öpos-1 ¤Îʸ»úÎ󤬸«¤Ä¤«¤Ã¤Æ¤Ê¤±¤ì¤Ð¡£¤½¤Î¤Þ¤Þ½ÐÎÏ¡£¼­½ñ¤Ë¤¢¤Ã¤¿
-¤Ê¤é <lastmatchlen, lastmatchoffset> ¤Î¥Ú¥¢¤ò½ÐÎϡפäȤʤé¤Ê¤±¤ì¤Ð¤Ê
-¤é¤Ê¤¤¡£
+この条件で「見つからなかった場合」というのはどう表されているかを考える。
+もし、pos の文字列が辞書になければ pos - 1 の文字列は、どうすべきかと
+いうと「pos-1 の文字列が見つかってなければ。そのまま出力。辞書にあった
+なら <lastmatchlen, lastmatchoffset> のペアを出力」っとならなければな
+らない。
 
 
-lastmatchlen ¤Ï¡¢½é´ü¾õÂ֤ǤϠTHRESHOLD - 1 ¤Ç¤¢¤Ã¤¿¤Î¤Ç¡¢¸«¤Ä¤«¤é¤Ê¤«¤Ã
-¤¿¤È¤¤¤¦¾ò·ï¤Ï (H) ¤Î±¦Â¦¤Î¾ò·ï lastmatchlen < THRESHOLD ¤Ç¤Þ¤ºÉ½¤µ¤ì
-¤Æ¤¤¤ë¡£
+lastmatchlen は、初期状態では THRESHOLD - 1 であったので、見つからなかっ
+たという条件は (H) の右側の条件 lastmatchlen < THRESHOLD でまず表され
+ている。
 
 
-¤Ç¤Ï¡¢Î㤨¤Ð lastmatchlen ¤¬ 5 ¤Ç¤¢¤Ã¤¿¤È¤·¤è¤¦¡£¤³¤Î¤È¤­ (E) ¤Î½èÍý¤Ç 
-matchlen ¤Ï lastmatchlen - 1 ¤Ä¤Þ¤ê¡¢4 ¤ËÀßÄꤵ¤ì¤ë¡£¤½¤·¤Æ¡¢match_insert()
-¤Ç¼¡¤Îʸ»úÎ󤬤⤷¼­½ñ¤«¤é¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð matchlen ¤Ï¹¹¿·¤µ¤ì¤Ê¤¤¤Î¤Ç
+では、例えば lastmatchlen が 5 であったとしよう。このとき (E) の処理で 
+matchlen は lastmatchlen - 1 つまり、4 に設定される。そして、match_insert()
+で次の文字列がもし辞書から見つからなければ matchlen は更新されないので
   matchlen < lastmatchlen 
   matchlen < lastmatchlen 
-¤È¤Ê¤ë¡£¤³¤Î¤è¤¦¤Ê¾ò·ï(Á°²ó¸«¤Ä¤«¤ê¡¢º£²ó¸«¤Ä¤«¤é¤Ê¤¤)¾ì¹ç¤Ë¸Â¤ê¡¢(H.2)
-¤Î½èÍý¤¬¼Â¹Ô¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£¤Ç¤Ï¡¢(H.2) ¤Î½èÍý¤òÄɤ¤¤«¤±¤è¤¦¡£
+となる。このような条件(前回見つかり、今回見つからない)場合に限り、(H.2)
+の処理が実行されるようになっている。では、(H.2) の処理を追いかけよう。
 
 
-¤Þ¤º¡¢¤³¤Î¾õÂÖ¤ò¿Þ¼¨¤¹¤ë¡£
+まず、この状態を図示する。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -2064,63 +2073,63 @@ text   |               |  |  |  |  |  |              |  |  |  |  |  |  |
             if (matchlen > remainder) matchlen = remainder;
         }
 
             if (matchlen > remainder) matchlen = remainder;
         }
 
-¤Þ¤º¡¢<Ťµ, °ÌÃÖ> ¤Î¥Ú¥¢¤ò½ÐÎϤ¹¤ë¡£¤³¤ì¤Ï¤¤¤¤¤À¤í¤¦¡£½ÐÎϤ¹¤ë¡Ö°ÌÃÖ¡×
-¤Ï0 ¤Ê¤é 1 Ê¸»úÁ°¤òɽ¤¹¤Î¤Ç¡¢¼ÂºÝ¤Î¥ª¥Õ¥»¥Ã¥È pos - 1 - matchpos ¤è¤ê
-¤â 1 ¾®¤µ¤¤ÃͤˤʤäƤ¤¤ë¤³¤È¤ËÃí°Õ¤·¤Æ¤ª¤³¤¦¡£
-
-¤½¤·¤Æ¡¢lastmatchlen ¤Ï 1 °ú¤«¤ì¤ë¡£¤³¤Î¾ì¹çÎ㤨¤Ð 4 ¤Ë¤Ê¤ë¡£¤·¤¿¤¬¤Ã
-¤Æ¡¢¼¡¤Î¥ë¡¼¥×¤Ç¤Ï 3 Ê¸»ú pos ¤¬ÀèÁ÷¤ê¤µ¤ì¤ë(4 ¤Ç¤Ï¤Ê¤¤)¡£pos ¤Ï´û¤Ë 1 
-ʸ»úÀè¤Ë¿Ê¤ó¤Ç¤¤¤ë¤Î¤Ç¡¢ºÇ½é¤Ë 1 °ú¤¯¤Î¤Ï¤³¤Î¤³¤È¤ò¹Íθ¤·¤Æ¤¤¤ë¡£while 
-¥ë¡¼¥×¤¬½ª¤Ã¤¿¸å¤Ïpos ¤Î°ÌÃ֤ϼºݤ˽ÐÎϤ·¤¿Ê¸»úÎó¤ÎºÇ¸å¤Îʸ»ú pos2-1 
-¤ò»Ø¤·¤Æ¤¤¤ë¤³¤È¤Ë¤Ê¤ë¡£
-
-¤½¤·¤Æ¡¢get_next() ¤Ç¤Þ¤¿ 1 Ê¸»úÀè¤ËÁ÷¤ë¡£pos ¤Ï¿Þ¤Î pos2 ¤Î°ÌÃ֤ˤʤ롣
-¤½¤·¤Æ¡¢match_insert() ¤Ç¡¢¤³¤Î°ÌÃÖ¤Îʸ»úÎó¤ò¾È¹ç¤¹¤ë¡£matchlen ¤Ï¡¢
-THRESHOLD - 1 ¤Ë½é´ü²½¤µ¤ì¤ë¤Î¤Ç pos2 ¤Î°ÌÃÖ¤Îʸ»úÎ󤬼­½ñ¤«¤é¸«¤Ä¤«¤é
-¤Ê¤±¤ì¤Ð matchlen ¤Ï¡¢THRESHOLD-1 ¤À¡£¤³¤ì¤Ï½é´ü¾õÂÖ¤ÈƱ¤¸¾õÂÖ¤ò¼¨¤¹¤Î
-¤Ç¡¢¼¡¤Î¥ë¡¼¥×¤Î½èÍý¤âÁÛÁü¤¬¤Ä¤¯((H) ¤Î¾ò·ï¤Î±¦Â¦ lastmatchlen < THRESHOLD
-¤¬Í­¸ú¤Ë¤Ê¤ë)¡£¤Ç¤Ï¡¢¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ï¤È¤¤¤¦¤È¡¢¼¡¤Î¥ë¡¼¥×¤Ç¤µ¤é¤ËÀè 
-pos2+1 ¤Î¾È¹ç·ë²Ì¤ÈÈæ³Ó¤µ¤ì¤ë¤Î¤Ç¤³¤Î½èÍý¤âÁÛÁü¤¬¤Ä¤¯¡£
-
-ºÇ½é¡¢¤É¤¦¤Ë¤â¤³¤Î½èÍýÆâÍƤ¬Íý²ò¤Ç¤­¤Ê¤«¤Ã¤¿¤Î¤À¤¬¡Ö¸½ºß¤Îʸ»úÎó¤È¡¢¼¡
-¤Îʸ»úÎó¤Î¤½¤ì¤¾¤ì¤Ç¼­½ñ¤ò¸¡º÷¤·¡¢¤è¤êŤ¯¸«¤Ä¤«¤Ã¤¿Êý¤ò»È¤¦¡×¤È¤¤¤¦ºÇ
-Ŭ²½¤ò¹Ô¤Ã¤Æ¤¤¤ë»ö¤¬¤ï¤«¤Ã¤Æ¤·¤Þ¤Ã¤¿¸å¤Ï²òÆɤϴÊñ¤À¤Ã¤¿¡£(¼Â¤Ï¤³¤Î»ö
-¼Â¤â¶µ¤¨¤Æ¤â¤é¤Ã¤¿»ö¤À¡£Á´Á³¥À¥á¤¸¤ã¤ó)
-
-¤µ¤Æ¡¢¤³¤ì¤Ç°ìÄ̤ê¤Î²òÀϤϺѤó¤À¤ï¤±¤À¤¬¡¢¤³¤³¤Þ¤Ç¤Î²òÀÏÆâÍƤòÆɤßľ¤·
-¤Æ¤ß¤ë¤È¡¢°Ê²¼¤ÎÅÀ¤¬¤Þ¤À¤Ò¤Ã¤«¤«¤ë¡£
-
-1. ¥Ï¥Ã¥·¥å´Ø¿ô¤ÏºÇŬ¤Ê¤Î¤«¡©ÆäˠHSHSIZ{2^15} ¤ÏºÇŬ¤Ê¤Î¤«¡©
-2. too_flag[] ¤Ï¡¢¼ÂºÝ¤Ë¾È¹ç¤ò¹Ô¤¤¥ë¡¼¥×¤¬LIMIT¤ò±Û¤¨¤¿¾ì¹ç¤Ë
-   ÀßÄꤵ¤ì¤ë¡£¤·¤«¤·¡¢¥Ï¥Ã¥·¥å¤Î¥Á¥§¡¼¥ó¤òºî¤ëºÝ¤Ë¥Á¥§¡¼¥ó¤Î
-   ¸Ä¿ô¤ò¤¢¤é¤«¤¸¤á¿ô¤¨¤Æ¤ª¤±¤Ð°ìÅÙ¤Îõº÷¤¹¤é¤â¹Ô¤ï¤ì¤º¡£¤è¤ê
-   Á᤯½èÍý¤µ¤ì¤Ê¤¤¤À¤í¤¦¤«¡©
-
-¸½¾õ¡¢1, 2 ¤È¤â¼Â»Ü¤·¤Æ¤ß¤¿¤È¤³¤íÆäË®Å٤βþÁ±¤Ï¸«¤é¤ì¤Ê¤«¤Ã¤¿¡£Æäˠ
-1 ¤Ï¡¢Èù̯¤Ê¤È¤³¤í¤¬¤¢¤ê¤Û¤È¤ó¤É¤Î½ñ¤­´¹¤¨¤ÏÀ­Ç½¤ò°­¤¯¤¹¤ë¤À¤±¤À¤Ã¤¿¡£
-¤Ê¤«¤Ê¤«¶½Ì£¿¼¤¤¤â¤Î¤¬¤¢¤ë¡£
-
-¤³¤ì¤Ïº£¸å¤Î²ÝÂê¤È¤·¤Æ¤¤¤º¤ì¤Þ¤¿¸¡¾Ú¤·¤è¤¦¡£¤½¤í¤½¤í slide.c ¤âË°¤­¤Æ
-¤­¤¿¤Î¤Ç¤Ò¤È¤Þ¤º¤Ï¤³¤ì¤Ç½ª¤ê¤Ë¤·¤¿¤¤¡£
+まず、<長さ, 位置> のペアを出力する。これはいいだろう。出力する「位置」
+は0 なら 1 文字前を表すので、実際のオフセット pos - 1 - matchpos より
+も 1 小さい値になっていることに注意しておこう。
+
+そして、lastmatchlen は 1 引かれる。この場合例えば 4 になる。したがっ
+て、次のループでは 3 文字 pos が先送りされる(4 ではない)。pos は既に 1 
+文字先に進んでいるので、最初に 1 引くのはこのことを考慮している。while 
+ループが終った後はpos の位置は実際に出力した文字列の最後の文字 pos2-1 
+を指していることになる。
+
+そして、get_next() でまた 1 文字先に送る。pos は図の pos2 の位置になる。
+そして、match_insert() で、この位置の文字列を照合する。matchlen は、
+THRESHOLD - 1 に初期化されるので pos2 の位置の文字列が辞書から見つから
+なければ matchlen は、THRESHOLD-1 だ。これは初期状態と同じ状態を示すの
+で、次のループの処理も想像がつく((H) の条件の右側 lastmatchlen < THRESHOLD
+が有効になる)。では、見つかった場合はというと、次のループでさらに先 
+pos2+1 の照合結果と比較されるのでこの処理も想像がつく。
+
+æ\9c\80å\88\9dã\80\81ã\81©ã\81\86ã\81«ã\82\82ã\81\93ã\81®å\87¦ç\90\86å\86\85容ã\81\8cç\90\86解ã\81§ã\81\8dã\81ªã\81\8bã\81£ã\81\9fã\81®ã\81 ã\81\8cã\80\8cç\8f¾å\9c¨ã\81®æ\96\87å­\97å\88\97ã\81¨ã\80\81次
+の文字列のそれぞれで辞書を検索し、より長く見つかった方を使う」という最
+適化を行っている事がわかってしまった後は解読は簡単だった。(実はこの事
+実も教えてもらった事だ。全然ダメじゃん)
+
+さて、これで一通りの解析は済んだわけだが、ここまでの解析内容を読み直し
+てみると、以下の点がまだひっかかる。
+
+1. ハッシュ関数は最適なのか?特に HSHSIZ{2^15} は最適なのか?
+2. too_flag[] は、実際に照合を行いループがLIMITを越えた場合に
+   設定される。しかし、ハッシュのチェーンを作る際にチェーンの
+   個数をあらかじめ数えておけば一度の探索すらも行われず。より
+   早く処理されないだろうか?
+
+現状、1, 2 とも実施してみたところ特に速度の改善は見られなかった。特に 
+1 は、微妙なところがありほとんどの書き換えは性能を悪くするだけだった。
+なかなか興味深いものがある。
+
+これは今後の課題としていずれまた検証しよう。そろそろ slide.c も飽きて
+きたのでひとまずはこれで終りにしたい。
 
 \f
 
 \f
-bit Æþ½ÐÎϥ롼¥Á¥ó (crcio.c)
+bit 入出力ルーチン (crcio.c)
 ---------------------------
 
 ---------------------------
 
-¤³¤ì¤«¤é Huffman Ë¡¤Î²òÆɤ˰ܤë¤Î¤À¤¬¡¢¤½¤ÎÁ°½àÈ÷¤È¤·¤Æ bit Æþ½ÐÎϥ롼
-¥Á¥ó¤Î²òÆɤò¹Ô¤¦¡£Huffman Ë¡¤Î¼ÂÁõ¤Ç¤Ïɬ¤º bit Æþ½ÐÎϽèÍý¤¬É¬Íפˤʤ롣
-LHa for UNIX ¤â¤â¤Á¤í¤óÎã³°¤Ç¤Ï¤Ê¤¯¡¢Huffman Ë¡¤Î¼ÂÁõ¤ò²òÆɤ¹¤ë¤Ë¤¢¤¿
-¤ê¤³¤ÎÉôʬ¤Î½èÍýÆâÍƤϤϤ䭤ꤵ¤»¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤¤È¹Í¤¨¤¿¤Î¤À¡£
+ã\81\93ã\82\8cã\81\8bã\82\89 Huffman æ³\95ã\81®è§£èª­ã\81«ç§»ã\82\8bã\81®ã\81 ã\81\8cã\80\81ã\81\9dã\81®å\89\8dæº\96å\82\99ã\81¨ã\81\97ã\81¦ bit å\85¥å\87ºå\8a\9bã\83«ã\83¼
+チンの解読を行う。Huffman 法の実装では必ず bit 入出力処理が必要になる。
+LHa for UNIX ももちろん例外ではなく、Huffman 法の実装を解読するにあた
+りこの部分の処理内容ははっきりさせておいた方が良いと考えたのだ。
 
 
-LHa for UNIX version 1.14i ¤Ç¤Ï bit Æþ½ÐÎϥ롼¥Á¥ó¤Ï crcio.c ¤ÇÄêµÁ¤µ
-¤ì¤Æ¤¤¤ë¡£(¤³¤Î¤è¤¦¤Ê¥Õ¥¡¥¤¥ë̾¤Ë¸ºß¤¹¤ë¤Î¤Ï°Õ³°¤Ê»ö¤À¡£ºÇ¶á¤Î LHa
-for UNIX ¤Ç¤Ï¡¢»ä¤¬ bitio.c ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤òÀߤ±¡¢bit Æþ½ÐÎϥ롼¥Á¥ó¤Ï
-¤½¤³¤ËÀÚ¤ê½Ð¤·¤¿)
+LHa for UNIX version 1.14i では bit 入出力ルーチンは crcio.c で定義さ
+れている。(このようなファイル名に存在するのは意外な事だ。最近の LHa
+for UNIX では、私が bitio.c というファイルを設け、bit 入出力ルーチンは
+そこに切り出した)
 
 
-crcio.c ¤Î¤¦¤Á bit Æþ½ÐÎϥ롼¥Á¥ó¤Ï fillbuf(), getbits(), putcode(),
-putbits(), init_getbits(), init_putbits() ¤Î 6 ´Ø¿ô¤À¡£
+crcio.c のうち bit 入出力ルーチンは fillbuf(), getbits(), putcode(),
+putbits(), init_getbits(), init_putbits() の 6 関数だ。
 
 
-¤Þ¤º¡¢½é´ü²½ÍѤΠinit_getbits(), init_putbits() ¤ò¸«¤è¤¦¡£
+まず、初期化用の init_getbits(), init_putbits() を見よう。
 
 void
 init_getbits( /* void */ )
 
 void
 init_getbits( /* void */ )
@@ -2142,20 +2151,20 @@ init_putbits( /* void */ )
     getc_euc_cache = EOF;
 }
 
     getc_euc_cache = EOF;
 }
 
-¤½¤ì¤¾¤ì bit ÆþÎÏ¡¢bit ½ÐÎϤò¹Ô¤¦¤¿¤á¤Î½é´ü²½½èÍý¤À¡£CHAR_BIT ¤È¤¤¤¦¤Î
-¤Ï 8 ¤Ç¡¢char ·¿¤Î bit ¥µ¥¤¥º¤òɽ¤·¤Æ¤¤¤ë¤é¤·¤¤¡£¾ÜºÙ¤Ï¤ï¤«¤é¤Ê¤¤¤¬½é´ü
-¾õÂ֤ϤȤˤ«¤¯¤³¤ì¤À¡£¤³¤³¤Ç»ÈÍѤµ¤ì¤Æ¤¤¤ëÊÑ¿ô¤Ï¡¢
+それぞれ bit 入力、bit 出力を行うための初期化処理だ。CHAR_BIT というの
+は 8 で、char 型の bit サイズを表しているらしい。詳細はわからないが初期
+状態はとにかくこれだ。ここで使用されている変数は、
 
 static unsigned char subbitbuf, bitcount;
 
 
 static unsigned char subbitbuf, bitcount;
 
-¤¬¡¢crcio.c ¤ÇÄêµÁ¤µ¤ì¤Æ¤ª¤ê¡¢
+が、crcio.c で定義されており、
 
 EXTERN unsigned short bitbuf;
 
 
 EXTERN unsigned short bitbuf;
 
-¤¬¡¢lha.h ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë(EUC ¤Ê¤ó¤¿¤é¤ÏËܼÁ¤Ç¤Ï¤Ê¤¤Ìµ»ë¤·¤è¤¦)¡£¥°¥í¡¼
-¥Ð¥ëÊÑ¿ô¤È¸À¤¦¤Î¤Ï´÷¤à¤Ù¤­¤â¤Î¤À¤¬¡¢¤È¤Ë¤«¤¯»ÈÍѤµ¤ì¤Æ¤¤¤ëÊÑ¿ô¤È½é´üÃÍ
-¤ò³Îǧ¤·¤¿¤Î¤Ç¼¡¤Ë°Ü¤í¤¦¡£init_getbits() ¤Ç¡¢Áá® fillbuf() ¤¬¸Æ¤Ð¤ì¤Æ
-¤¤¤ë¡£¤³¤Î½èÍýÆâÍƤò¸«¤ë¡£
+ã\81\8cã\80\81lha.h ã\81§å®\9a義ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8b(EUC ã\81ªã\82\93ã\81\9fã\82\89ã\81¯æ\9c¬è³ªã\81§ã\81¯ã\81ªã\81\84ç\84¡è¦\96ã\81\97ã\82\88ã\81\86\80\82ã\82°ã\83­ã\83¼
+バル変数と言うのは忌むべきものだが、とにかく使用されている変数と初期値
+を確認したので次に移ろう。init_getbits() で、早速 fillbuf() が呼ばれて
+いる。この処理内容を見る。
 
 void
 fillbuf(n)          /* Shift bitbuf n bits left, read n bits */
 
 void
 fillbuf(n)          /* Shift bitbuf n bits left, read n bits */
@@ -2181,31 +2190,31 @@ fillbuf(n)          /* Shift bitbuf n bits left, read n bits */
     subbitbuf <<= n;
 }
 
     subbitbuf <<= n;
 }
 
-¤Þ¤º¡¢½é´ü¾õÂ֤Ȥ·¤Æ
+まず、初期状態として
 
     bitbuf = 0;
     subbitbuf = 0;
     bitcount = 0;
 
 
     bitbuf = 0;
     subbitbuf = 0;
     bitcount = 0;
 
-¤Ç¤¢¤ê¡¢fillbuf ¤Î°ú¿ô n ¤Ë¤Ï 2 * CHAR_BIT ¤¬Í¿¤¨¤é¤ì¤¿¤Î¤À¤Ã¤¿¡£¤¤¤­
-¤Ê¤ê while ¾ò·ï¤òËþ¤¿¤¹¤Î¤Ç¥ë¡¼¥×Éô¤Î²òÀϤò¹Ô¤ï¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¯¤Ê¤ë¤¬¡¢
-¤Ò¤È¤Þ¤º¤³¤ì¤ò̵»ë¤·¤ÆºÇ¸å¤Î 3 ¹Ô (D) ¤ËÃåÌܤ¹¤ë¡£¾ò·ï¤Ï¾¯¤Ê¤¤Êý¤¬Îɤ¤
-¤Î¤À¡£
+であり、fillbuf の引数 n には 2 * CHAR_BIT が与えられたのだった。いき
+なり while 条件を満たすのでループ部の解析を行わなくてはならなくなるが、
+ひとまずこれを無視して最後の 3 行 (D) に着目する。条件は少ない方が良い
+のだ。
 
     /* (D) */
     bitcount -= n;
     bitbuf = (bitbuf << n) + (subbitbuf >> (CHAR_BIT - n));
     subbitbuf <<= n;
 
 
     /* (D) */
     bitcount -= n;
     bitbuf = (bitbuf << n) + (subbitbuf >> (CHAR_BIT - n));
     subbitbuf <<= n;
 
-bitbuf << n, subbitbuf << n ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ç¡¢bitbuf, subbitbuf ¤ò n ¥Ó¥Ã
-¥Èº¸¤Ë¤º¤é¤¹½èÍý¤Î¤è¤¦¤À¡£¤µ¤é¤Ë bitbuf ¤Ë¤Ï¡¢subbitbuf ¤ò n ¥Ó¥Ã¥È¤º
-¤é¤·¤¿¤È¤­¤Ë°î¤ì¤¿Éôʬ¤ò bitbuf ¤Ë¥»¥Ã¥È¤·¤Æ¤¤¤ë¡£¤Ã¤È¡¢
+bitbuf << n, subbitbuf << n されているので、bitbuf, subbitbuf を n ビッ
+ト左にずらす処理のようだ。さらに bitbuf には、subbitbuf を n ビットず
+らしたときに溢れた部分を bitbuf にセットしている。っと、
 
    (subbitbuf >> (CHAR_BIT - n))
 
 
    (subbitbuf >> (CHAR_BIT - n))
 
-¤ÎÉôʬ¤ò·Ú¤¯ÀâÌÀ¤·¤¿¤¬¡¢¿Þ¼¨¤·¤Æ³Îǧ¤·¤Æ¤ª¤³¤¦¡£
+の部分を軽く説明したが、図示して確認しておこう。
 
 
-subbitbuf ¤Ï unsigned char ¤Ê¤Î¤Ç 8 bit ¤ÎÊÑ¿ô¤À¡£
+subbitbuf は unsigned char なので 8 bit の変数だ。
 
 ----------------------------------------------------------------------------
                7  6  5  4  3  2  1  0
 
 ----------------------------------------------------------------------------
                7  6  5  4  3  2  1  0
@@ -2215,16 +2224,16 @@ subbitbuf 
               <-- n -->
 ----------------------------------------------------------------------------
 
               <-- n -->
 ----------------------------------------------------------------------------
 
-n ¤¬Î㤨¤Ð 3 ¤Î¾ì¹ç¡¢CHAR_BIT - n ¤Ï¡¢5 ¤À¤«¤é subbitbuf ¤ò 5 ¥Ó¥Ã¥È±¦
-¤Ë¤º¤é¤·¤¿Ãͤò¼è¤Ã¤Æ¤¤¤ë¡£¤Ä¤Þ¤ê¡¢¿Þ¤Î 7, 6, 5 ¥Ó¥Ã¥ÈÌܤ¬°ìÈÖ±¦¤ËÍè¤ë
-¤è¤¦¤Ë¤Ê¤Ã¤Æ¤ª¤ê¡¢¤³¤ÎÃͤò bitbuf ¤Ë­¤·¤Æ¤¤¤ë¡£(C¸À¸ì¤Ç¤Ï¡¢unsigned 
-¤ÊÊÑ¿ô¤ò±¦¤Ë¥·¥Õ¥È¤¹¤ë¤È¾å°Ì¥Ó¥Ã¥È¤Ë¤Ï 0 ¤¬Æþ¤ë)
+n が例えば 3 の場合、CHAR_BIT - n は、5 だから subbitbuf を 5 ビット右
+にずらした値を取っている。つまり、図の 7, 6, 5 ビット目が一番右に来る
+ようになっており、この値を bitbuf に足している。(C言語では、unsigned 
+な変数を右にシフトすると上位ビットには 0 が入る)
 
 
-fillbuf() ¤Î¸åȾ 3 ¹Ô(¤¤¤ä¡¢¸åȾ2¹Ô¤«)¤Ï¡£·ë¶É bitbuf ¤È subbitbuf ¤ò
-°ì¤Ä¤Î bitbuf ¤È¤ß¤Ê¤·¤Æ n ¥Ó¥Ã¥Èº¸¤Ë¤º¤é¤·¤Æ¤¤¤ë¤³¤È¤¬¤ï¤«¤ë¡£
+fillbuf() の後半 3 行(いや、後半2行か)は。結局 bitbuf と subbitbuf を
+一つの bitbuf とみなして n ビット左にずらしていることがわかる。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-<¥Ó¥Ã¥È¥Ð¥Ã¥Õ¥¡Á´Âοޠ(ͽÁÛ)>
+<ビットバッファ全体図 (予想)>
 
            7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
            7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -2236,39 +2245,39 @@ fillbuf() 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤Î¤È¤­¡¢ÅöÁ³¿Þ¤Î x, y, z ¤ÎÉôʬ(n = 3 ¤ÏÎã¤È¤·¤Æ¤ÎÃͤÀ)¤¬¶õ¤¯»ö¤Ë¤Ê¤ë¡£
-bitcount ¤È¤¤¤¦ÊÑ¿ô¤¬ n °ú¤«¤ì¤Æ¤¤¤¿¤¬¡¢¤³¤ì¤Ï bit ¥Ð¥Ã¥Õ¥¡Á´ÂΤÎÍ­¸ú
-¤Ê¥Ó¥Ã¥È¿ô¤òɽ¤·¤Æ¤¤¤ë¤Î¤Ç¤Ï¤Ê¤¤¤«¤ÈͽÁÛ¤·¤Æ¤ª¤¯¡£¤¹¤Ê¤ï¤Á¿Þ¤Î¾õÂ֤ʤé
-21 ¤À¡£while ¥ë¡¼¥×¤Ï(´Ø¿ô̾¤«¤é)¤³¤Î¶õ¤­Éôʬ¤òËä¤á¤ë½èÍý¤Ê¤Î¤Ç¤Ï¤Ê¤¤
-¤«¤ÈŬÅö¤ËͽÁۤǤ­¤ë¡£¤Ç¤Ï¡¢while ¥ë¡¼¥×¤ò¸«¤è¤¦¡£¤â¤¦°ìÅÙ½é´üÃͤò³Îǧ
-¤·¡¢ºÇ½é¤Ë¹Ô¤ï¤ì¤ë½èÍýÆâÍƤò¸«¤è¤¦¡£
+このとき、当然図の x, y, z の部分(n = 3 は例としての値だ)が空く事になる。
+bitcount という変数が n 引かれていたが、これは bit バッファ全体の有効
+なビット数を表しているのではないかと予想しておく。すなわち図の状態なら
+21 だ。while ループは(関数名から)この空き部分を埋める処理なのではない
+かと適当に予想できる。では、while ループを見よう。もう一度初期値を確認
+し、最初に行われる処理内容を見よう。
 
 
-ºÇ½é¡¢
+最初、
 
     bitbuf = 0;
     subbitbuf = 0;
     bitcount = 0;
 
 
     bitbuf = 0;
     subbitbuf = 0;
     bitcount = 0;
 
-¤Ç¤¢¤ë¤«¤é¡¢bit¥Ð¥Ã¥Õ¥¡¤Ï¶õ¤Ã¤Ý¤À¡£ÅöÁ³ fillbuf(2 * CHAR_BIT) ¤µ¤ì¤ë¤È
-while ¾ò·ï¤òËþ¤¿¤¹¡£¤­¤Ã¤È 16 bit ¤À¤± bit¥Ð¥Ã¥Õ¥¡¤¬Êä½¼¤µ¤ì¤ë¤Ï¤º(¤Ä
-¤Þ¤ê¡¢bitbuf ¤¤¤Ã¤Ñ¤¤¡¢subbitbuf ¶õ)¤À¡£
+であるから、bitバッファは空っぽだ。当然 fillbuf(2 * CHAR_BIT) されると
+while 条件を満たす。きっと 16 bit だけ bitバッファが補充されるはず(つ
+まり、bitbuf いっぱい、subbitbuf 空)だ。
 
     /* (A) */
     while (n > bitcount) {
         n -= bitcount;
 
 
     /* (A) */
     while (n > bitcount) {
         n -= bitcount;
 
-¤Ç¡¢¥Ó¥Ã¥È¥Ð¥Ã¥Õ¥¡¤¬ÊÝ»ý¤¹¤ë bit ¿ô°Ê¾å¤òÍ׵ᤵ¤ì¤¿¤Î¤Ç¡¢¥ë¡¼¥×¤ËÆþ¤ë¡£
-n -= bitcount ¤Ç¡¢ËÜÅö¤Ë­¤ê¤Ê¤¤Éôʬ¤¬²¿¥Ó¥Ã¥È¤Ê¤Î¤«¤òÆÀ¤Æ¤¤¤ë¡£¤³¤³¤Ç
-¤Ï 16 ¤À¡£¼¡¤Î¹Ô
+で、ビットバッファが保持する bit 数以上を要求されたので、ループに入る。
+n -= bitcount で、本当に足りない部分が何ビットなのかを得ている。ここで
+は 16 だ。次の行
 
         /* (B) */
         bitbuf = (bitbuf << bitcount) + (subbitbuf >> (CHAR_BIT - bitcount));
 
 
         /* (B) */
         bitbuf = (bitbuf << bitcount) + (subbitbuf >> (CHAR_BIT - bitcount));
 
-¤³¤ì¤ÏÀèÄø¤â½Ð¤ÆÍ褿½èÍý¤À¡£¥Ó¥Ã¥È¥Ð¥Ã¥Õ¥¡Á´ÂΤò bitcount Ê¬º¸¤Ë¤º¤é¤·
-¤Æ¤¤¤ë(¤¿¤À¤·¡¢¤Þ¤À subbitbuf ¤Ï¤º¤é¤µ¤ì¤Æ¤¤¤Ê¤¤)¡£¤³¤Î»þÅÀ¤ÇͽÁÛ¤¬¾¯
-¤·Ê¤¤µ¤ì¤¿¡£8 - bitcount ¤Ç subbitbuf ¤ò¤º¤é¤·¤Æ¤¤¤ë¤«¤é bitcount ¤ÏºÇ
-Âç 8 ¤ÎÃͤ·¤«»ý¤¿¤Ê¤¤¤À¤í¤¦¤È¤¤¤¦¤³¤È¤À¡£¤É¤¦¤¤¤¦¤³¤È¤«¡¢¹Í¤¨¤Æ¤ß¤ë¡¦¡¦¡¦
-¹Í¤¨¤Æ¤â¤ï¤«¤é¤Ê¤«¤Ã¤¿¤Î¤Ç¼¡¤Ë¿Ê¤â¤¦¡£
+これは先程も出て来た処理だ。ビットバッファ全体を bitcount 分左にずらし
+ている(ただし、まだ subbitbuf はずらされていない)。この時点で予想が少
+し覆された。8 - bitcount で subbitbuf をずらしているから bitcount は最
+大 8 の値しか持たないだろうということだ。どういうことか、考えてみる・・・
+考えてもわからなかったので次に進もう。
 
         /* (C) */
         if (compsize != 0) {
 
         /* (C) */
         if (compsize != 0) {
@@ -2279,12 +2288,12 @@ n -= bitcount 
             subbitbuf = 0;
         bitcount = CHAR_BIT;
 
             subbitbuf = 0;
         bitcount = CHAR_BIT;
 
-compsize ¤È¤¤¤¦¤Î¤¬½Ð¤ÆÍ褿¤¬¡¢¤³¤ÎÃͤ¬¤É¤¦¤¢¤í¤¦¤È¤â subbitbuf ¤Ï8 ¥Ó¥Ã
-¥ÈËä¤á¤é¤ì¡£bitcount ¤Ï 8 ¤ËÀßÄꤵ¤ì¤Æ¤¤¤ë¡£¤ï¤«¤Ã¤¿ bitcount ¤Ï¡¢
-subbitbuf ¤ËÊÝ»ý¤¹¤ë bit ¿ô¤À¡£¿Þ¤òÄûÀµ¤·¤è¤¦¡£
+compsize というのが出て来たが、この値がどうあろうとも subbitbuf は8 ビッ
+ト埋められ。bitcount は 8 に設定されている。わかった bitcount は、
+subbitbuf に保持する bit 数だ。図を訂正しよう。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-<¥Ó¥Ã¥È¥Ð¥Ã¥Õ¥¡Á´ÂοÞ>
+<ビットバッファ全体図>
 
            7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
            7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -2297,43 +2306,43 @@ subbitbuf 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤Î¿Þ¤òƧ¤Þ¤¨¤Æ¤â¤¦°ìÅÙ½é´ü¾õÂ֤ǤνèÍýÆâÍƤòÄɤ¤¤«¤±¤ë¡£
+この図を踏まえてもう一度初期状態での処理内容を追いかける。
 
 
-¤Þ¤º¡¢(A) ¤Ç¡¢subbitbuf ¤Ï¶õ¤Ê¤Î¤Ç¡¢bitcount ¤Ï 0 ¤À¡£Í׵ᤷ¤¿ bit ¿ô 
-n{16} ¤è¤ê¾®¤µ¤¤¤Î¤Ç¥ë¡¼¥×¤ËÆþ¤ë¡£n ¤Ï 16 ¤Î¤Þ¤Þ¤À¡£
+まず、(A) で、subbitbuf は空なので、bitcount は 0 だ。要求した bit 数 
+n{16} より小さいのでループに入る。n は 16 のままだ。
 
 
-(B) ¤Ç¡¢subbitbuf ¤Ë»Ä¤Ã¤Æ¤¤¤ë bit ¤ò bitbuf ¤Ë¤º¤é¤·¤Æ¤¤¤ë¡£º£¤Ï¤Þ¤À
-¶õ¤Ê¤Î¤Çbitbuf ¤Ï¤³¤³¤Ç¤â¤Þ¤À¶õ¤À¡£
+(B) で、subbitbuf に残っている bit を bitbuf にずらしている。今はまだ
+空なのでbitbuf はここでもまだ空だ。
 
 
-(C) ¤Ç¡¢¥Õ¥¡¥¤¥ë¤«¤é¥Ç¡¼¥¿¤ò8 ¥Ó¥Ã¥ÈÆɤà(compsize ¤Ï¾ï¤Ë0¤Ç¤Ï¤Ê¤¤¤È¹Í¤¨
-¤ë)¡£bitcount ¤Ï 8 ¤Ë¤Ê¤ë¡£¤³¤Î»þÅÀ¤Ç bit¥Ð¥Ã¥Õ¥¡Á´ÂΤϠsubbitbuf ¤À¤±
-Ãͤ¬Æþ¤Ã¤¿¾õÂ֤ˤʤ롣
+(C) で、ファイルからデータを8 ビット読む(compsize は常に0ではないと考え
+る)。bitcount は 8 になる。この時点で bitバッファ全体は subbitbuf だけ
+値が入った状態になる。
 
 
-¼¡¤Î¥ë¡¼¥×¤Ë°Ü¤í¤¦¡£(A) ¤Ç¡¢subbitbuf ¤Ï¤¤¤Ã¤Ñ¤¤¤Ç¤¢¤ë¤¬Í׵ᤷ¤¿ n{16} 
-¤è¤ê¤Ï¾®¤µ¤¤¤Î¤Ç¡¢¤Þ¤À¥ë¡¼¥×¤Ï³¤¯¡£n ¤Ï¤³¤³¤Ç 8 ¤Ë¤Ê¤ë¡£
+次のループに移ろう。(A) で、subbitbuf はいっぱいであるが要求した n{16} 
+よりは小さいので、まだループは続く。n はここで 8 になる。
 
 
-(B) ¤Ç¡¢subbitbuf ¤Ë»Ä¤Ã¤Æ¤¤¤ë bit (8 bit ¤À)¤ò bitbuf ¤Ë¤º¤é¤·¤Æ¤¤¤ë¡£
-º£Å٤Ϡsubbitbuf Á´ÂΤ¬ bitbuf ¤Ë°Ü¤Ã¤Æ¤¤¤ë¤Î¤ÈƱ¤¸¤À¡£(¤Ä¤Þ¤ê¡¢bitbuf
+(B) で、subbitbuf に残っている bit (8 bit だ)を bitbuf にずらしている。
+今度は subbitbuf 全体が bitbuf に移っているのと同じだ。(つまり、bitbuf
 = subbitbuf)
 
 = subbitbuf)
 
-(C) ¤Ç¡¢¤Þ¤¿ subbitbuf ¤Ï 8 bit Êä½¼¤µ¤ì¤ë¡£
+(C) で、また subbitbuf は 8 bit 補充される。
 
 
-(A) ¤Ç¡¢n{8} > bitcount{8} ¤Ïµ¶¤Ê¤Î¤Ç¥ë¡¼¥×¤¬½ª¤ë¡£
+(A) で、n{8} > bitcount{8} は偽なのでループが終る。
 
 
-(D) ¤Ç¡¢subbitbuf ¤Ë»Ä¤Ã¤Æ¤¤¤ë bit ¤Ï¤¹¤Ù¤Æ bitbuf ¤Ë°Ü¤ë¡£bitbuf ¤Ï 16
-bit ¤¤¤Ã¤Ñ¤¤¤Ë¤Ê¤ë¡£bitcount ¤Ï 0 ¤À¡£
+(D) で、subbitbuf に残っている bit はすべて bitbuf に移る。bitbuf は 16
+bit いっぱいになる。bitcount は 0 だ。
 
 
-¤³¤Î½èÍý·ë²Ì¤«¤é fillbuf(n) ¤Ï¡¢bitbuf ¤Ë n ¥Ó¥Ã¥ÈÆɤ߹þ¤à½èÍý¤À¤È¸À¤¨
-¤ë¡£°ú¿ô¤Ë»ØÄê¤Ç¤­¤ë n ¤¬ºÇÂç 16 ¥Ó¥Ã¥È¤Ç¤¢¤ë¤³¤È¤Ë¤âµ¤¤Å¤¤¤ÆÎɤ¤¤À¤í
-¤¦¡£½èÍýÆâÍƤò³Îǧ¤·¤Æ¤ß¤ì¤Ð¤ï¤«¤ë¡£
+この処理結果から fillbuf(n) は、bitbuf に n ビット読み込む処理だと言え
+る。引数に指定できる n が最大 16 ビットであることにも気づいて良いだろ
+う。処理内容を確認してみればわかる。
 
 
-¤³¤³¤Ç¡¢subbitbuf ¤ÎÍÑÅӤ˵¤¤Å¤¤¤¿¡£¥Õ¥¡¥¤¥ë¤«¤é¤ÎÆɤ߹þ¤ß¤¬ 8 ¥Ó¥Ã¥È
-ñ°Ì¤Ç¤·¤«¤Ç¤­¤Ê¤¤¤Î¤Ç¡¢¤½¤ì¤òÊ䤦¤¿¤á¤ÎÊݸÍѥХåե¡¤Ç¤¢¤í¤¦¡£Î㤨¤Ð
-1 ¥Ó¥Ã¥È¤À¤± bitbuf ¤ò fill ¤·¤¿¤±¤ì¤Ð subbitbuf ¤Ë 7 bit »Ä¤·¡¢1 bit
-¤À¤± bitbuf ¤ËÀßÄꤵ¤ì¤ë(³Îǧ¤·¤Æ¤ß¤ì¤Ð¤ï¤«¤ë)
+ここで、subbitbuf の用途に気づいた。ファイルからの読み込みが 8 ビット
+単位でしかできないので、それを補うための保存用バッファであろう。例えば
+1 ビットだけ bitbuf を fill したければ subbitbuf に 7 bit 残し、1 bit
+だけ bitbuf に設定される(確認してみればわかる)
 
 
-fillbuf() ¤¬¤ï¤«¤Ã¤¿¤Î¤Ç¡¢¤½¤ì¤òÍøÍѤ·¤Æ¤¤¤ë getbits() ¤ÎÆâÍƤò³Îǧ¤·
-¤è¤¦¡£
+fillbuf() がわかったので、それを利用している getbits() の内容を確認し
+よう。
 
 unsigned short
 getbits(n)
 
 unsigned short
 getbits(n)
@@ -2348,40 +2357,40 @@ getbits(n)
 
     x = bitbuf >> (2 * CHAR_BIT - n);
 
 
     x = bitbuf >> (2 * CHAR_BIT - n);
 
-¤Ï¡¢3 ÅÙ¤â½Ð¤ÆÍ褿¤Î¤Ç
+は、3 度も出て来たので
 
      buf >> (sizeof(buf)*8 - n)
 
 
      buf >> (sizeof(buf)*8 - n)
 
-¤ò buf ¤Î¾å°Ì n ¥Ó¥Ã¥È¤òÆÀ¤ë¼°¤À¤È¤·¤Æ¥Þ¥¯¥í¤Ë¤·¤Æ¤âÎɤ¤¤À¤í¤¦¡£(¤¬¡¢
-Îɤ¤Ì¾Á°¤¬»×¤¤ÉÕ¤«¤Ê¤¤¤Î¤Ç¤½¤¦¤Ï¤·¤Ê¤¤)¡£¤È¤Ë¤«¤¯¡¢bitbuf ¤Î¾å°Ì n ¥Ó¥Ã¥È
-¤ò²¼°Ì n ¥Ó¥Ã¥È¤È¤·¤Æ x ¤ËÂåÆþ¤·¤Æ¤¤¤ë¡£¤½¤Î¸å¤Ç¡¢
+を buf の上位 n ビットを得る式だとしてマクロにしても良いだろう。(が、
+良い名前が思い付かないのでそうはしない)。とにかく、bitbuf の上位 n ビット
+を下位 n ビットとして x に代入している。その後で、
 
     fillbuf(n);
 
 
     fillbuf(n);
 
-¤·¤Æ¤¤¤ë¡£n bit ¤ò x ¤ËÅϤ·¤¿¤Î¤Ç bitbuf ¤«¤é¾å°Ì n ¥Ó¥Ã¥È¤ò¼Î¤Æ¤Æ¡¢
-¥Ó¥Ã¥ÈÊä½¼¤¹¤ë¡£¤³¤³¤Ç¡¢bitbuf ¤Ï¾ï¤Ë¤¤¤Ã¤Ñ¤¤¤Î¾õÂ֤ˤʤäƤ¤¤ë¤³¤È¤¬
-¤ï¤«¤ë¡£(¥Õ¥¡¥¤¥ë¤ÎËöÈøÉÕ¶á¤Î¾ì¹ç¡¢Àµ³Î¤Ë bitbuf ¤Ë²¿¥Ó¥Ã¥È»Ä¤Ã¤Æ¤¤¤ë
-¤«¤¬È½ÃǤǤ­¤Ê¤¤¤¬¡¢¼ïÌÀ¤«¤·¤ò¤¹¤ë¤È¤³¤Î¤³¤È¤Ï LHa ¤Î½èÍýÆâÍƤˤȤäÆ
-¤Ï¤É¤¦¤Ç¤â¤¤¤¤¤³¤È¤À¡£getbits() ¤Ï decode ½èÍý¤Ç»È¤ï¤ì¤ë¤Î¤À¤¬¡¢decode 
-½èÍý¤Ï²¿¥Ó¥Ã¥È¤Î¾ðÊó¤ò decode ¤¹¤ëɬÍפ¬¤¢¤ë¤«¤ò¾¤Î¾ðÊ󤫤餢¤é¤«¤¸¤á
-ÆÀ¤Æ¤¤¤ë)
+している。n bit を x に渡したので bitbuf から上位 n ビットを捨てて、
+ビット補充する。ここで、bitbuf は常にいっぱいの状態になっていることが
+わかる。(ファイルの末尾付近の場合、正確に bitbuf に何ビット残っている
+かが判断できないが、種明かしをするとこのことは LHa の処理内容にとって
+はどうでもいいことだ。getbits() は decode 処理で使われるのだが、decode 
+処理は何ビットの情報を decode する必要があるかを他の情報からあらかじめ
+得ている)
 
 
-¼¡¤Ë°Ü¤í¤¦º£Å٤Ϡputcode() ¤À¡£put ¤Î¾ì¹ç¤Þ¤º¤Ï¡¢init_putbits() ¤Ç
-½é´ü²½¤¬¹Ô¤ï¤ì¤Æ¤¤¤ë¡£¤½¤ÎÃͤϰʲ¼¤À¡£
+次に移ろう今度は putcode() だ。put の場合まずは、init_putbits() で
+初期化が行われている。その値は以下だ。
 
     bitcount = CHAR_BIT;
     subbitbuf = 0;
     getc_euc_cache = EOF;
 
 
     bitcount = CHAR_BIT;
     subbitbuf = 0;
     getc_euc_cache = EOF;
 
-getc_euc_cache ¤Ï̵»ë¤À¡£bitcount ¤È subbitbuf ¤ÎÃͤ¬ÀßÄꤵ¤ì¡¢bitbuf 
-¤ÏÍøÍѤµ¤ì¤Ê¤¤¡£ÀèÄø¤È¤Ï°ã¤¤ subbitbuf ¤¬¶õ¤Ê¤Î¤Ëbitcount ¤¬ 8 ¤Ê¤Î¤Ç¡¢
-bitcount ¤Î»È¤ï¤ìÊý¤¬Â¿¾¯°Û¤Ê¤ë¤è¤¦¤À¡£get ¤Î¾ì¹ç¤Ï¡¢bitcount ¤Ï¡¢
-subbitbuf ¤ËÊÝ»ý¤¹¤ë bit ¿ô¤À¤Ã¤¿¤¬º£Å٤Ϡsubbitbuf ¤Î¶õ¤­ bit ¿ô¤À¤í
-¤¦¤ÈͽÁÛ¤·¤Æ¤ª¤³¤¦¡£
+getc_euc_cache は無視だ。bitcount と subbitbuf の値が設定され、bitbuf 
+は利用されない。先程とは違い subbitbuf が空なのにbitcount が 8 なので、
+bitcount の使われ方が多少異なるようだ。get の場合は、bitcount は、
+subbitbuf に保持する bit 数だったが今度は subbitbuf の空き bit 数だろ
+うと予想しておこう。
 
 
-¤½¤·¤Æ¡¢putcode(n, x) ¤ò¸«¤ë¡£¼Â¤Ï¥½¡¼¥¹¤ò¸«¤ë¤È¤ï¤«¤ë¤Î¤À¤¬¡¢¤â¤¦°ì¤Ä
-¤Î½ÐÎϥ롼¥Á¥ó putbits() ¤Ï¡¢putcode() ¤Î¸Æ¤Ó½Ð¤·¤Ë½ñ¤­´¹¤¨²Äǽ¤À¡£
-putbits() ¤Ï¡¢
+そして、putcode(n, x) を見る。実はソースを見るとわかるのだが、もう一つ
+の出力ルーチン putbits() は、putcode() の呼び出しに書き換え可能だ。
+putbits() は、
 
 void
 putbits(n, x)           /* Write rightmost n bits of x */
 
 void
 putbits(n, x)           /* Write rightmost n bits of x */
@@ -2392,7 +2401,7 @@ putbits(n, x)           /* Write rightmost n bits of x */
     putcode(n, x);
 }
 
     putcode(n, x);
 }
 
-¤Ã¤È½ñ¤­´¹¤¨¤é¤ì¤ë¤Î¤À¡£¤Ê¤Î¤Ç¡¢putcode() ¤ÎÆâÍƤòÀè¤Ë³Îǧ¤¹¤ë¤ï¤±¤À¡£
+っと書き換えられるのだ。なので、putcode() の内容を先に確認するわけだ。
 
 void
 putcode(n, x)           /* Write rightmost n bits of x */
 
 void
 putcode(n, x)           /* Write rightmost n bits of x */
@@ -2424,42 +2433,42 @@ putcode(n, x)           /* Write rightmost n bits of x */
     bitcount -= n;
 }
 
     bitcount -= n;
 }
 
-½èÍýÆâÍƤ¬ fillbuf() ¤Î¤È¤­¤È»÷¤Æ¤¤¤ë¡£¤Þ¤º¤Ï¡¢ÀèÄø¤ÈƱÍͤˠwhile ¾ò·ï
-¤ò̵»ë¤·¤Æ¹Í¤¨¤Æ¤ß¤ë¡£(D) ¤À¡£
+処理内容が fillbuf() のときと似ている。まずは、先程と同様に while 条件
+を無視して考えてみる。(D) だ。
 
     /* (D) */
     subbitbuf += x >> (USHRT_BIT - bitcount);
     bitcount -= n;
 
 
     /* (D) */
     subbitbuf += x >> (USHRT_BIT - bitcount);
     bitcount -= n;
 
-¤³¤Î¼°¤Ï¤â¤¦ 4 ÅÙÌܤÀ¡£¤Þ¤º¡¢x ¤Î¾å°Ì bitcount ¥Ó¥Ã¥È¤òÆÀ¤Æ¡¢subbitbuf 
-¤Ë­¤·¤Æ¤¤¤ë¡£bitcount ¤Ï¡¢ÀèÄø subbitbuf ¤Î¶õ¤­¤Ç¤¢¤í¤¦¤ÈͽÁÛ¤·¤¿¤¬¡¢
-n °ú¤«¤ì¤Æ¤¤¤ë¤Î¤Ç¡¢Ëä¤á¤¿Ê¬¶õ¤­¤¬¸º¤Ã¤Æ¤¤¤ë¤ï¤±¤À¡£Í½ÁÛ¤ÏÅö¤¿¤Ã¤Æ¤¤¤ë
-¤À¤í¤¦¡£¤³¤Î»þÅÀ¤Ç¤³¤Î´Ø¿ô¤¬ x ¤Î¾å°Ì¥Ó¥Ã¥È¤òÍøÍѤ¹¤ë¤³¤È¤¬¤ï¤«¤ë¡£¥³
-¥á¥ó¥È¤Ë rightmost n bits of x ¤È½ñ¤«¤ì¤Æ¤¤¤ë¤¬ÏǤ蘆¤ì¤Æ¤Ï¤¤¤±¤Ê¤¤¡£
-¿¤¯¤Î¾ì¹ç¡¢¥³¥á¥ó¥È¤Ï¤»¤¤¤¼¤¤¥Ò¥ó¥È¤È¤·¤Æ¤Î¾ðÊó¤Ç¤·¤«¤Ê¤¤¡£¿®ÍѤ·¤Æ¤Ï
-¤¤¤±¤Ê¤¤¤â¤Î¤Ê¤Î¤À¡£(¥³¥á¥ó¥È¤Ï¤¢¤Þ¤ê¥Ç¥Ð¥Ã¥°¤µ¤ì¤Ê¤¤¡£¥³¥á¥ó¥È¤¬¾Ü¤·
-¤±¤ì¤Ð¾Ü¤·¤¤Äø¥³¥á¥ó¥È¤Ï¥¨¥ó¥Ð¥°¤·¤ä¤¹¤¤¡£µ¿¤Ã¤Æ¤«¤«¤í¤¦¡£¤³¤ì¤ÏËܽñ¤Ë
-¤â¸À¤¨¤ë¡£¤¹¤Ù¤Æ¤ò±­¤Î¤ß¤Ë¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¤Î¤À)
+この式はもう 4 度目だ。まず、x の上位 bitcount ビットを得て、subbitbuf 
+に足している。bitcount は、先程 subbitbuf の空きであろうと予想したが、
+n 引かれているので、埋めた分空きが減っているわけだ。予想は当たっている
+ã\81 ã\82\8dã\81\86ã\80\82ã\81\93ã\81®æ\99\82ç\82¹ã\81§ã\81\93ã\81®é\96¢æ\95°ã\81\8c x ã\81®ä¸\8aä½\8dã\83\93ã\83\83ã\83\88ã\82\92å\88©ç\94¨ã\81\99ã\82\8bã\81\93ã\81¨ã\81\8cã\82\8fã\81\8bã\82\8bã\80\82ã\82³
+メントに rightmost n bits of x と書かれているが惑わされてはいけない。
+多くの場合、コメントはせいぜいヒントとしての情報でしかない。信用しては
+いけないものなのだ。(コメントはあまりデバッグされない。コメントが詳し
+ければ詳しい程コメントはエンバグしやすい。疑ってかかろう。これは本書に
+も言える。すべてを鵜のみにしてはいけないのだ)
 
 
-¤Ç¤Ï¡¢½èÍýÆâÍƤ˰ܤ롣¤Þ¤º¤Ï (A)
+では、処理内容に移る。まずは (A)
 
     /* (A) */
     while (n >= bitcount) {
         n -= bitcount;
 
 
     /* (A) */
     while (n >= bitcount) {
         n -= bitcount;
 
-subbitbuf ¤Î¶õ¤­¤¬ n °Ê²¼¤Ç¤¢¤ì¤Ð¥ë¡¼¥×¤ËÆþ¤ë¡£subbitbuf °ì¤Ä¤Ç¤Ïn ¥Ó¥Ã
-¥ÈÁ´Éô¤ÏÏŤ¨¤Ê¤¤¤«¤é¥ë¡¼¥×¤Ç¾®¹ï¤ß¤Ë½èÍý¤·¤è¤¦¤È¤¤¤¦¤³¤È¤À¤í¤¦(¤â¤¦Á´
-ÂΤνèÍýÆâÍƤÎͽÁۤϤĤ¤¤Æ¤¤¤ë)
-n ¤«¤é bitcount °ú¤¤¤Æ¤¤¤ë¤Î¤Ç¡¢n ¥Ó¥Ã¥È¤Î¤¦¤Á¤³¤ì¤«¤é bitcount Ê¬¤Ï
-½èÍý¤µ¤ì¤ë¤³¤È¤ò¤³¤³¤Ç¤µ¤Ã¤µ¤Èµ­Ï¿¤·¤Æ¼¡¤Î¥ë¡¼¥×¤ËÈ÷¤¨¤Æ¤¤¤ë¡£
+subbitbuf の空きが n 以下であればループに入る。subbitbuf 一つではn ビッ
+ト全部は賄えないからループで小刻みに処理しようということだろう(もう全
+体の処理内容の予想はついている)
+n から bitcount 引いているので、n ビットのうちこれから bitcount 分は
+処理されることをここでさっさと記録して次のループに備えている。
 
         /* (B) */
         subbitbuf += x >> (USHRT_BIT - bitcount);
         x <<= bitcount;
 
 
         /* (B) */
         subbitbuf += x >> (USHRT_BIT - bitcount);
         x <<= bitcount;
 
-x ¤Î¾å°Ì bitcount ¥Ó¥Ã¥È¤ò subbitbuf ¤Ë­¤·¤Æ¤¤¤ë¡£subbitbuf ¤Î¶õ¤­¤¬
-¤³¤ì¤ÇËä¤Þ¤Ã¤¿¡£subbitbuf ¤Ï¤â¤¦¤¤¤Ã¤Ñ¤¤¤À¡£x ¤ò bitcount ¥·¥Õ¥È¤¹¤ë¤³
-¤È¤Ç subbitbuf ¤ËÅϤ·¤¿ x ¤Î¾å°Ì¥Ó¥Ã¥È¤ò¼Î¤Æ¤Æ¤¤¤ë¡£
+x の上位 bitcount ビットを subbitbuf に足している。subbitbuf の空きが
+これで埋まった。subbitbuf はもういっぱいだ。x を bitcount シフトするこ
+とで subbitbuf に渡した x の上位ビットを捨てている。
 
         /* (C) */
         if (compsize < origsize) {
 
         /* (C) */
         if (compsize < origsize) {
@@ -2475,173 +2484,174 @@ x 
         subbitbuf = 0;
         bitcount = CHAR_BIT;
 
         subbitbuf = 0;
         bitcount = CHAR_BIT;
 
-compsize ¤Ï̵»ë¤·¤Æ¤âÎɤ¤¡£½èÍý¤ÎËܼÁ¤Ç¤Ï¤Ê¤¤¤«¤é¤À¤¬¡¢¤¹¤°¤Ë¤ï¤«¤ë¤Î¤Ç
-°ì±þÀâÌÀ¤¹¤ë¤È¡¢
+compsize は無視しても良い。処理の本質ではないからだが、すぐにわかるので
+一応説明すると、
         if (compsize < origsize) {
             ...
         else
             unpackable = 1;
         if (compsize < origsize) {
             ...
         else
             unpackable = 1;
-¤Ç¡¢°µ½Ì¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤¬¸µ¤Î¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤ò¾å²ó¤Ã¤¿¤È¤­¤Ë
-½èÍý¤ò½ª¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë(unpackable = 1 ¤·¤Æ¡¢Â¾¤Î²Õ½ê¤Ç¤³¤ÎÊÑ¿ô¤ò´Æ»ë¤¹¤ë¡£
-unpackable == 1 ¤Ê¤é½èÍý¤òÃæÃǤ¹¤ë)
+で、圧縮ファイルサイズが元のファイルサイズを上回ったときに
+処理を終るようになっている(unpackable = 1 して、他の箇所でこの変数を監視する。
+unpackable == 1 なら処理を中断する)
 
 
-¤È¤Ë¤«¤¯ (C) ¤Î»þÅÀ¤Ç¤Ïɬ¤º subbitbuf ¤¬¤¤¤Ã¤Ñ¤¤¤Ë¤Ê¤ë¤Î¤Ç 1 ¥Ð¥¤¥È¤ò
-¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤·¤Æ¤¤¤ë¡£¤½¤Î¸å¡¢subbitbuf = 0, bitcount = 8 ¤È¤·¤Æ 
-subbitbuf ¤ò¶õ¤±¤Æ¼¡¤Î¥ë¡¼¥×¤ËÈ÷¤¨¤Æ¤¤¤ë¡£
+とにかく (C) の時点では必ず subbitbuf がいっぱいになるので 1 バイトを
+ファイルに書き出している。その後、subbitbuf = 0, bitcount = 8 として 
+subbitbuf を空けて次のループに備えている。
 
 
-¤â¤¦¤¤¤¤¤À¤í¤¦¡£putcode() ¤Ï¡¢ÏÀÍýŪ¤Ë¤Ï x ¤Î¤¦¤Á¾å°Ì n ¥Ó¥Ã¥È¤ò½ÐÎϤ¹
-¤ë½èÍý¤À¡£°ú¿ô n ¤Î¾å¸Â¤¬ x ¤ÎºÇÂç¥Ó¥Ã¥È¥µ¥¤¥º 16 ¤Ë¤Ê¤ë¤Î¤ÏÀâÌÀ¤¹¤ë¤Þ
-¤Ç¤â¤Ê¤¤¤À¤í¤¦¡£
+もういいだろう。putcode() は、論理的には x のうち上位 n ビットを出力す
+る処理だ。引数 n の上限が x の最大ビットサイズ 16 になるのは説明するま
+でもないだろう。
 
 
-putcode() ¤Ï¼ÂÁõ¤È¤·¤Æ¡¢subbitbuf ¤È x ¤ò°ì¤Ä¤Ë·Ò¤²¤Æ n bit º¸¤Ë¤º¤é¤·
-¤Æ¤¤¤ë½èÍý¤À¤È¹Í¤¨¤Æ¤âÎɤ¤¡£¤½¤¦¤·¤Æ¡¢subbitbuf ¤¬¤¤¤Ã¤Ñ¤¤¤Ë¤Ê¤Ã¤¿¤é¤½
-¤ÎÅÔÅÙ(1 ¥Ð¥¤¥È¤º¤Ä)¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹¤Î¤À¡£
+putcode() は実装として、subbitbuf と x を一つに繋げて n bit 左にずらし
+ている処理だと考えても良い。そうして、subbitbuf がいっぱいになったらそ
+の都度(1 バイトずつ)ファイルに書き出すのだ。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-<¥Ó¥Ã¥È¥Ð¥Ã¥Õ¥¡Á´ÂοÞ>
+<ビットバッファ全体図>
 
 
-                      <--- º¸¤Ë¤º¤é¤¹
+                      <--- 左にずらす
 
            7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           |* * *          |x y z                          |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
            7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           |* * *          |x y z                          |
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-         /               / <-n->        
+         /               / <-n->
       subbitbuf         x
                  <-------->
                   bitcount
 
 ----------------------------------------------------------------------------
 
       subbitbuf         x
                  <-------->
                   bitcount
 
 ----------------------------------------------------------------------------
 
-putbits() ¤â¸«¤è¤¦¡£ÀèÄø putcode() ¤Î¸Æ¤Ó½Ð¤·¤Ë½ñ¤­´¹¤¨¤¿¥³¡¼¥É¤ò¸«¤ë¤È
-¤¹¤°¤ï¤«¤ë¤¬¡¢
+putbits() も見よう。先程 putcode() の呼び出しに書き換えたコードを見ると
+すぐわかるが、
 
     x <<= USHRT_BIT - n;
     putcode(n, x);
 
 
     x <<= USHRT_BIT - n;
     putcode(n, x);
 
-ºÇ½é¤Î¼°¤Ç¡¢x ¤Î²¼°Ì n ¥Ó¥Ã¥È¤ò x ¤Î¾å°Ì n ¥Ó¥Ã¥È¤Ë¤·¤Æ¤¤¤ë¡£
-¤½¤¦¤·¤Æ¡¢putcode() ¤ò¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¤Î¤Ç¡¢putbits(n, x) ¤Ï¡¢x
-¤Î²¼°Ì n ¥Ó¥Ã¥È¤ò½ÐÎϤ¹¤ë½èÍý¤À¡£
+最初の式で、x の下位 n ビットを x の上位 n ビットにしている。
+そうして、putcode() を呼び出しているので、putbits(n, x) は、x
+の下位 n ビットを出力する処理だ。
 
 
-°Ê¾å¤Ç¥Ó¥Ã¥ÈÆþ½ÐÎϥ롼¥Á¥ó¤Ï½ª¤ê¤À¡£½ÐÎϤ˴ؤ·¤Æ°ì¤ÄÊ᪤·¤Æ¤ª¤¯¤È
-putcode(), putbits() ¤Ç¤ÏºÇ¸å¤ÎºÇ¸å¤Ç subbitbuf ¤Ë¾ðÊ󤬻Ĥ俤ޤޥե¡
-¥¤¥ë¤Ë½ñ¤­½Ð¤µ¤ì¤Ê¤¤¾õÂ֤ˤʤ롣¤³¤ì¤òÅǤ­½Ð¤¹¤¿¤á¤ËÍøÍѼԤÏ
+以上でビット入出力ルーチンは終りだ。出力に関して一つ捕捉しておくと
+putcode(), putbits() ã\81§ã\81¯æ\9c\80å¾\8cã\81®æ\9c\80å¾\8cã\81§ subbitbuf ã\81«æ\83\85å ±ã\81\8cæ®\8bã\81£ã\81\9fã\81¾ã\81¾ã\83\95ã\82¡
+イルに書き出されない状態になる。これを吐き出すために利用者は
 
   putcode(7, 0)
 
 
   putcode(7, 0)
 
-¤ò¹Ô¤¦É¬Íפ¬¤¢¤ë¡£
+を行う必要がある。
 
 
-¤Þ¤È¤á¤è¤¦
+まとめよう
 
 ----------------------------------------------------------------------------
 fillbuf(n)
 
 ----------------------------------------------------------------------------
 fillbuf(n)
-  bitbuf ¤«¤é¾å°Ì n ¥Ó¥Ã¥È¤ò¼Î¤Æ¤Æ¡¢²¼°Ì n ¥Ó¥Ã¥È¤ò¥Õ¥¡¥¤¥ë¤«¤éÆɤ߹þ
-  ¤ßËä¤á¤ë¡£
+  bitbuf から上位 n ビットを捨てて、下位 n ビットをファイルから読み込
+  み埋める。
 
 getbits(n)
 
 getbits(n)
-  bitbuf ¤Î¾å°Ì n ¥Ó¥Ã¥È¤ò²¼°Ì n ¥Ó¥Ã¥È¤È¤·¤ÆÊÖ¤¹¡£bitbuf ¤Ï n ¥Ó¥Ã¥È
-  Êä½¼¤µ¤ì¤ë¡£
+  bitbuf の上位 n ビットを下位 n ビットとして返す。bitbuf は n ビット
+  補充される。
 
 putcode(n, x)
 
 putcode(n, x)
-  x ¤Î¾å°Ì n ¥Ó¥Ã¥È¤ò¥Õ¥¡¥¤¥ë¤Ë½ÐÎϤ¹¤ë¡£ºÇ¸å¤Î½ÐÎÏ»þ¤Ï putcode(7, 0)
-  ¤¹¤ëɬÍפ¬¤¢¤ë¡£
+  x の上位 n ビットをファイルに出力する。最後の出力時は putcode(7, 0)
+  する必要がある。
 
 putbits(n, x)
 
 putbits(n, x)
-  x ¤Î²¼°Ì n ¥Ó¥Ã¥È¤ò¥Õ¥¡¥¤¥ë¤Ë½ÐÎϤ¹¤ë¡£ºÇ¸å¤Î½ÐÎÏ»þ¤Ï putcode(7, 0)
-  ¤¹¤ëɬÍפ¬¤¢¤ë¡£
+  x の下位 n ビットをファイルに出力する。最後の出力時は putcode(7, 0)
+  する必要がある。
 
 init_getbits()
 
 init_getbits()
-  ÆþÎϽèÍý¤Î½é´ü²½
+  入力処理の初期化
 
 init_putbits()
 
 init_putbits()
-  ½ÐÎϽèÍý¤Î½é´ü²½
+  出力処理の初期化
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
 
-Æɤ߹þ¤ß¤Ë´Ø¤·¤Æ¡¢bitbuf ¤Î¥µ¥¤¥º¤¬ 16 ¥Ó¥Ã¥È¤Ç¾ï¤Ë¤½¤Î¾õÂÖ¤¬ÊÝ»ý¤µ¤ì
-¤Æ¤¤¤ë¤Î¤Ï LHa ¤Ë¤È¤Ã¤Æ½ÅÍפʻö¤À¡£decode ½èÍý¤Ç¤ÏľÀÜ bitbuf ¤ò»²¾È¤¹
-¤ë²Õ½ê¤¬¤¢¤ë¡£
+読み込みに関して、bitbuf のサイズが 16 ビットで常にその状態が保持され
+ているのは LHa にとって重要な事だ。decode 処理では直接 bitbuf を参照す
+る箇所がある。
 
 
-Huffman ˡ (huf.c)
+\f
+Huffman 法 (huf.c)
 ------------------
 
 ------------------
 
-LHa for UNIX ¤Ç¤Ï¡¢ÀÅŪ Huffman Ë¡¤È¤·¤Æ¡¢shuf.c¡¢Æ°Åª Huffman Ë¡¤È¤·
-¤Æ dhuf.c ¤¬¤¢¤ë¤é¤·¤¤¤¬¡¢¤³¤ì¤é¤Ë´Ø¤·¤Æ¤Ï¿¨¤ì¤Ê¤¤¡£LHa ¤Ç¤Ï¡¢¤³¤ì¤é¤Ï
-²áµî¤ÎÈǤΥ¢¡¼¥«¥¤¥Ö¤ò²òÅà¤Ç¤­¤ë¤è¤¦¤Ë decode ¤Î¤ß¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¤è¤¦
-¤À¡£¤½¤³¤Ç¡¢¤Þ¤º¤Ï -lh4-, -lh5-, -lh6-, -lh7- ¤ÇÍøÍѤµ¤ì¤Æ¤¤¤ë huf.c 
-¤Î²òÀϤòÃæ¿´¤Ë¹Ô¤¦¤³¤È¤È¤·¤¿¤¤¡£
+LHa for UNIX では、静的 Huffman 法として、shuf.c、動的 Huffman 法とし
+て dhuf.c があるらしいが、これらに関しては触れない。LHa では、これらは
+過去の版のアーカイブを解凍できるように decode のみサポートしているよう
+だ。そこで、まずは -lh4-, -lh5-, -lh6-, -lh7- で利用されている huf.c 
+の解析を中心に行うこととしたい。
 
 
-¤È¤³¤í¤Ç¡¢Ëܽñ¤Ç¤Ï Huffman Ë¡¤¬¤É¤¦¤¤¤Ã¤¿¤â¤Î¤«¤ÏͽÈ÷Ãμ±¤È¤·¤Æ´û¤ËÃΤÃ
-¤Æ¤¤¤ë¤â¤Î¤È¤¹¤ë¤¬¡¢¤¤¤Á¤ª¤¦³µÍפò´Êñ¤ËÀâÌÀ¤·¤Æ¤ª¤³¤¦¡£
+ところで、本書では Huffman 法がどういったものかは予備知識として既に知っ
+ているものとするが、いちおう概要を簡単に説明しておこう。
 
 
-°Ê²¼¤ÎÆâÍƤΥƥ­¥¹¥È¥Õ¥¡¥¤¥ë¤¬¤¢¤Ã¤¿¤È¤¹¤ë¡£
+以下の内容のテキストファイルがあったとする。
 
         abcabcaba
 
 
         abcabcaba
 
-¤³¤Î¥Æ¥­¥¹¥È¤Ï 9 ¥Ð¥¤¥È¤¢¤ë¤ï¤±¤À¤¬¡¢¤³¤Î¥Õ¥¡¥¤¥ë¤Ç»È¤ï¤ì¤Æ¤¤¤ëʸ»ú¤Ï
-¼ïÎष¤«¤Ê¤¤¡¢a, b, c ¤À¡£¤À¤«¤é¤³¤Î¥Õ¥¡¥¤¥ë¤À¤±¤Ë´Ø¤·¤Æ¸À¤¨¤Ð 1 Ê¸»ú
-¤Ï 2 ¥Ó¥Ã¥È¤¢¤ì¤Ðɽ¸½²Äǽ¤Ç¤¢¤ë¡£Î㤨¤Ð³Æʸ»ú¤ËÂФ·¤Æ°Ê²¼¤Î¥Ó¥Ã¥È¤ò
-³ä¤êÅö¤Æ¤¿¤È¤¹¤ë¤È
+このテキストは 9 バイトあるわけだが、このファイルで使われている文字は
+種類しかない、a, b, c だ。だからこのファイルだけに関して言えば 1 文字
+は 2 ビットあれば表現可能である。例えば各文字に対して以下のビットを
+割り当てたとすると
 
 
-        Ê¸»ú   ¥Ó¥Ã¥Èɽ¸½
+        文字   ビット表現
         a      00
         b      01
         c      10
 
         a      00
         b      01
         c      10
 
-Àè¤Î¥Æ¥­¥¹¥È¥Õ¥¡¥¤¥ë¤ÎÆâÍÆ abcabcaba ¤Ï¡¢18¥Ó¥Ã¥È¤¢¤ì¤Ðɽ¸½²Äǽ¤È¤Ê¤ë¡£
+先のテキストファイルの内容 abcabcaba は、18ビットあれば表現可能となる。
 
 
-¤µ¤é¤Ë¡¢½Ð¸½ÉÑÅ٤ι⤤ʸ»ú¤ò¾¯¤Ê¤¤¥Ó¥Ã¥È¿ô¤Çɽ¸½¤·¡¢¤Þ¤ì¤Ë¤·¤«¸½¤ì¤Ê¤¤
-ʸ»ú¤òŤ¤¥Ó¥Ã¥È¿ô¤Çɽ¤¹¤è¤¦¤Ë¤¹¤ì¤Ð¤è¤ê¥Ó¥Ã¥È¿ô¤ò¾¯¤Ê¤¯¤Ç¤­¤ë¡£Î㤨¤Ð
+さらに、出現頻度の高い文字を少ないビット数で表現し、まれにしか現れない
+文字を長いビット数で表すようにすればよりビット数を少なくできる。例えば
 
 
-        Ê¸»ú   ¥Ó¥Ã¥Èɽ¸½
+        文字   ビット表現
         a      0
         b      10
         c      11
 
         a      0
         b      10
         c      11
 
-¤Ç¤¢¤ë¤È¤¹¤ë¤È a ¤Ï 4²ó¡¢b¤Ï3²ó¡¢c¤Ï2²ó¸½¤ì¤ë¤Î¤Ç¡¢Á´ÂΤϠ4 + 2*3 +
-2*2 = 14 ¥Ó¥Ã¥È¤Çɽ¸½¤Ç¤­¤ë¤³¤È¤Ë¤Ê¤ë¡£¤³¤ì¤¬ Huffman Ë¡¤Î°µ½Ì¸¶Íý¤Ç¤¢
-¤ë¡£¤³¤Î¤è¤¦¤Ë Huffman Ë¡¤Ç¤Ïʸ»ú¤ò¥Ó¥Ã¥Èñ°Ì¤Ç°·¤¦¤¿¤á¥Ó¥Ã¥ÈÆþ½ÐÎϥ롼
-¥Á¥ó¤òÀè¤Ë²òÆɤ·¤¿¤ï¤±¤À¡£¤Þ¤¿¡¢Éä¹æ²½¤ÎºÝ¤Ï¤¢¤é¤«¤¸¤á³Æʸ»ú¤Î½Ð¸½ÉÑÅÙ
-¤òµá¤á¤Æ¤ª¤¯É¬Íפ¬¤¢¤ê¡¢Éü¹æ²½¤ÎºÝ¤Ï¤É¤Î¥Ó¥Ã¥ÈÎ󤬤ɤÎʸ»ú¤ËÂбþ¤¹¤ë¤«
-¤ò¤¢¤é¤«¤¸¤áÃΤëɬÍפ¬¤¢¤ë¡£
+であるとすると a は 4回、bは3回、cは2回現れるので、全体は 4 + 2*3 +
+2*2 = 14 ビットで表現できることになる。これが Huffman 法の圧縮原理であ
+ã\82\8bã\80\82ã\81\93ã\81®ã\82\88ã\81\86ã\81« Huffman æ³\95ã\81§ã\81¯æ\96\87å­\97ã\82\92ã\83\93ã\83\83ã\83\88å\8d\98ä½\8dã\81§æ\89±ã\81\86ã\81\9fã\82\81ã\83\93ã\83\83ã\83\88å\85¥å\87ºå\8a\9bã\83«ã\83¼
+チンを先に解読したわけだ。また、符号化の際はあらかじめ各文字の出現頻度
+を求めておく必要があり、復号化の際はどのビット列がどの文字に対応するか
+をあらかじめ知る必要がある。
 
 
-ʸ»úËè¤Ë¥Ó¥Ã¥ÈĹ¤Î¤Ð¤é¤Ä¤­¤¬¤¢¤ë¤è¤¦¤Ê²ÄÊÑĹÉä¹æ¤Ë¤Ï°Ê²¼¤Î¾ò·ï¤¬¤¢¤ë¡£
+文字毎にビット長のばらつきがあるような可変長符号には以下の条件がある。
 
 
-   ¤¢¤ëÉä¹æ¤Î¥Ó¥Ã¥È¥Ñ¥¿¡¼¥ó¤Ï¡¢Â¾¤ÎÉä¹æ¤Î¥Ó¥Ã¥È¥Ñ¥¿¡¼¥ó¤Î³«»Ï¤Ë¤Ï¤Ê¤é
-   ¤Ê¤¤¡£
+   ある符号のビットパターンは、他の符号のビットパターンの開始にはなら
+   ない。
 
 
-¤È¤¤¤¦¤â¤Î¤À¡£¤³¤ì¤ò¡Ö¸ìƬ¾ò·ï¡×¤È¸À¤¦¤é¤·¤¤¡£Î㤨¤Ð¡¢Àè¤ÎÎã¤Ç¤Ï a ¤Ë 
-0 ¤ò³ä¤êÅö¤Æ¤¿¤Î¤Ç¾¤Îʸ»ú¤Ïɬ¤º 1 ¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£¤³¤Î¾ò
-·ï¤òËþ¤¿¤µ¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤Íýͳ¤Ï¤Á¤ç¤Ã¤È¹Í¤¨¤ì¤Ð¤ï¤«¤ë¡£²¾¤Ë°Ê²¼¤Î´Ö°ã¤Ã
-¤¿³äÅö¤ò¹Ô¤Ã¤¿¤È¤¹¤ë¡£
+というものだ。これを「語頭条件」と言うらしい。例えば、先の例では a に 
+0 を割り当てたので他の文字は必ず 1 から始まるようになっている。この条
+件を満たさなければならない理由はちょっと考えればわかる。仮に以下の間違っ
+た割当を行ったとする。
 
 
-        Ê¸»ú   ¥Ó¥Ã¥Èɽ¸½
+        文字   ビット表現
         a      0
         b      10
         c      01
 
         a      0
         b      10
         c      01
 
-¤³¤ì¤À¤È¡¢¥Ó¥Ã¥È¥Ñ¥¿¡¼¥ó 010 ¤¬ ab ¤Ê¤Î¤« ca ¤Ê¤Î¤«Û£Ëæ¤Ë¤Ê¤ë¤Î¤¬¤ï¤«
-¤ë¤À¤í¤¦¡£
+これだと、ビットパターン 010 が ab なのか ca なのか曖昧になるのがわか
+るだろう。
 
 
-ʸ»ú¤ËÂбþ¤¹¤ë¸ìƬ¾ò·ï¤òËþ¤¿¤¹(ºÇŬ¤Ê)¥Ó¥Ã¥ÈÎó¤òµá¤á¤ëÊýË¡¡¢¤½¤ì¤¬¥Ï¥Õ
-¥Þ¥óË¡¤À¡£¥Ï¥Õ¥Þ¥óË¡¤Ç¤Ï¥Ï¥Õ¥Þ¥óÌڤȤ¤¤¦ÌÚ¹½Â¤¤ò¹½ÃÛ¤¹¤ë¤Î¤À¤¬¡¢¤½¤Î¥¢
-¥ë¥´¥ê¥º¥à¤Ï°Ê²¼¤Î¤È¤ª¤ê¤À¡£
+文字に対応する語頭条件を満たす(最適な)ビット列を求める方法、それがハフ
+ã\83\9eã\83³æ³\95ã\81 ã\80\82ã\83\8fã\83\95ã\83\9eã\83³æ³\95ã\81§ã\81¯ã\83\8fã\83\95ã\83\9eã\83³æ\9c¨ã\81¨ã\81\84ã\81\86æ\9c¨æ§\8bé\80 ã\82\92æ§\8bç¯\89ã\81\99ã\82\8bã\81®ã\81 ã\81\8cã\80\81ã\81\9dã\81®ã\82¢
+ルゴリズムは以下のとおりだ。
 
 
-¤Þ¤º¡¢°µ½ÌÂоݤǤ¢¤ë¥Æ¥­¥¹¥È¤Ë´Ø¤·¤Æ³Æʸ»ú¤Î½Ð¸½²ó¿ô¤ò¿ô¤¨¤ë¡£Î㤨¤Ð 
-abcabcaba ¤È¤¤¤¦¥Æ¥­¥¹¥È¤Ç¤Ï¡¢a ¤Ï 4²ó¡¢b¤Ï3²ó¡¢c¤Ï2²ó¤Ê¤Î¤Ç¡¢
+まず、圧縮対象であるテキストに関して各文字の出現回数を数える。例えば 
+abcabcaba というテキストでは、a は 4回、bは3回、cは2回なので、
 
         4    3    2
         |    |    |
         a    b    c
 
 
         4    3    2
         |    |    |
         a    b    c
 
-¤È¤Ê¤ë¡£¼¡¤Ë¡¢½Ð¸½²ó¿ô¤ÎÄ㤤¤â¤ÎƱ»Î¤ò°ì¤Ä¤ÎÀá¤Ë«¤Í¤ë¡£¤³¤ÎÀá¤Ï 3+2=5 
-¤È¤¤¤¦½Ð¸½²ó¿ô¤ò»ý¤Ä¤â¤Î¤È¹Í¤¨¤ë¡£
+となる。次に、出現回数の低いもの同士を一つの節に束ねる。この節は 3+2=5 
+という出現回数を持つものと考える。
 
         4      5
         |     / \
         a    b   c
 
 
         4      5
         |     / \
         a    b   c
 
-°Ê¹ß¤µ¤é¤Ë½Ð¸½²ó¿ô¤ÎÄ㤤¤â¤ÎƱ»Î¤ò°ì¤Ä¤ÎÀá¤Ë«¤Í¤ëÁàºî¤ò·«¤êÊÖ¤¹¡£¤³¤Î
-Îã¤Ç¤Ï¡¢¤â¤¦°ìÅÙ«¤Í¤ì¤Ð½ª¤ê¤À¡£
+以降さらに出現回数の低いもの同士を一つの節に束ねる操作を繰り返す。この
+例では、もう一度束ねれば終りだ。
 
            9
            /\
 
            9
            /\
@@ -2649,28 +2659,28 @@ abcabcaba 
          /  / \
         a  b   c
 
          /  / \
         a  b   c
 
-¤³¤³¤Ç¡¢Ìڤκ¸Â¦¤¬ 0 ±¦Â¦¤¬ 1 ¤Ç¤¢¤ë¤È¤¹¤ë¤È¡£a ¤Ïº¬¤«¤éº¸¤Ë1¤Ä¿Ê¤à¤À
-¤±¤Ê¤Î¤Ç 0¡£b ¤Ï¡¢±¦(1)¢ªº¸(0) ¤Ê¤Î¤Ç¡¢10¡£c ¤Ï±¦(1)¢ª±¦(1) ¤Ê¤Î¤Ç¡¢11 
-¤È¤Ê¤ë¡£¼ÂºÝ¤ÎÉä¹æ²½¤ÎºÝ¤Ïʸ»ú¤«¤é¥Ó¥Ã¥ÈÎó¤òµá¤á¤ë¤Î¤ÇÍÕ¤«¤éº¬¤Ë¤à¤«¤Ã
-¤ÆµÕ½ç¤Ëé¤ë¤³¤È¤Ë¤Ê¤ë¡£¤Þ¤¿¡¢Éü¹æ¤ÎºÝ¤ÏÆþÎϤΥӥåÈÎó¤Ë±è¤Ã¤Æ¤³¤ÎÌÚ¤ò
-º¬¤«¤éé¤ë¤³¤È¤ÇÂбþ¤¹¤ëʸ»ú¤òµá¤á¤ë(¤Ê¤Î¤Ç°µ½Ìʸ¤Ë¤Ï¤³¤ÎÌÚ¹½Â¤¤¬°ì½ï
-¤Ë¾ðÊó¤È¤·¤Æ³ÊǼ¤µ¤ì¤ë¤³¤È¤Ë¤Ê¤ë)¡£
+ここで、木の左側が 0 右側が 1 であるとすると。a は根から左に1つ進むだ
+けなので 0。b は、右(1)→左(0) なので、10。c は右(1)→右(1) なので、11 
+となる。実際の符号化の際は文字からビット列を求めるので葉から根にむかっ
+て逆順に辿ることになる。また、復号の際は入力のビット列に沿ってこの木を
+根から辿ることで対応する文字を求める(なので圧縮文にはこの木構造が一緒
+に情報として格納されることになる)。
 
 
-¤³¤Î¤è¤¦¤Ê¥Ï¥Õ¥Þ¥óÌÚ¤òºîÀ®¤¹¤ë²Õ½ê¤¬¤¢¤ë¤«¤É¤¦¤«¤òõ¤·¤Æ¤ß¤¿¤È¤³¤í 
-maketree.c:make_tree() ¤¬¸«¤Ä¤«¤Ã¤¿¡£¤³¤ì¤Ï¡ÖC¸À¸ì¤Ë¤è¤ëºÇ¿·¥¢¥ë¥´¥ê¥º
-¥à¼­Åµ¡×(±ü¼À²É§Ãø¡¢µ»½ÑɾÏÀ¼Ò)¤ËºÜ¤Ã¤Æ¤¤¤ë¤â¤Î¤È¤Û¤È¤ó¤ÉƱ¤¸¤À¡£¤Ç¤Ï¡¢
-¤³¤Î´Ø¿ô¤Î²òÆɤ«¤é»Ï¤á¤è¤¦(º£²ó¤Î²òÀϤϥܥȥॢ¥Ã¥×¼°¤Ë¹Ô¤¦¤³¤È¤Ë¤·¤è
-¤¦¤È»×¤¦¡£¤È¤¤¤¦¤Î¤â¥Ç¡¼¥¿¹½Â¤¤«¤é¹¶¤á¤è¤¦¤Ë¤â¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤¬¤¿¤¯¤µ¤ó
-½Ð¤ÆÍè¤ë¤·¡¢½èÍý½ç¤ËÄɤäƤâÀµÄ¾¤è¤¯¤ï¤«¤é¤Ê¤«¤Ã¤¿¤«¤é¤À)
+このようなハフマン木を作成する箇所があるかどうかを探してみたところ 
+maketree.c:make_tree() ã\81\8cè¦\8bã\81¤ã\81\8bã\81£ã\81\9fã\80\82ã\81\93ã\82\8cã\81¯ã\80\8cCè¨\80èª\9eã\81«ã\82\88ã\82\8bæ\9c\80æ\96°ã\82¢ã\83«ã\82´ã\83ªã\82º
+ム辞典」(奥村晴彦著、技術評論社)に載っているものとほとんど同じだ。では、
+この関数の解読から始めよう(今回の解析はボトムアップ式に行うことにしよ
+うと思う。というのもデータ構造から攻めようにもグローバル変数がたくさん
+出て来るし、処理順に追っても正直よくわからなかったからだ)
 
 
-¤³¤Î´Ø¿ô¤Î¤¢¤ë¥Õ¥¡¥¤¥ë maketree.c ¤Ç»ÈÍѤ·¤Æ¤¤¤ë¥Ç¡¼¥¿¹½Â¤¤Ï°Ê²¼¤À¡£
+この関数のあるファイル maketree.c で使用しているデータ構造は以下だ。
 
 static short    n, heapsize, heap[NC + 1];
 static unsigned short *freq, *sort;
 static unsigned char *len;
 static unsigned short len_cnt[17];
 
 
 static short    n, heapsize, heap[NC + 1];
 static unsigned short *freq, *sort;
 static unsigned char *len;
 static unsigned short len_cnt[17];
 
-make_tree() ¤Ï°Ê²¼¡£
+make_tree() は以下。
 
 short
 make_tree(nparm, freqparm, lenparm, codeparm)
 
 short
 make_tree(nparm, freqparm, lenparm, codeparm)
@@ -2728,13 +2738,13 @@ make_tree(nparm, freqparm, lenparm, codeparm)
     return k;       /* return root */
 }
 
     return k;       /* return root */
 }
 
-¤³¤Î´Ø¿ô¤Î°ú¿ô¤Ë¡¢nparm, freqparm, lenparm, codeparm ¤È¤¤¤¦¤Î¤¬¤¢¤ë¡£
-¤³¤ì¤¬¤Ê¤ó¤Ê¤Î¤«¤¤¤­¤Ê¤ê¤Ç¤Ï¤ï¤«¤é¤Ê¤¤¤À¤í¤¦¡£¼Â¤Ï»ä¤Ë¤â¤ï¤«¤é¤Ê¤¤¡£º£
-²ó¤Î²òÀϤÇÆüì¤Ê¤Î¤Ï¡¢½èÍýÆâÍƤˤĤ¤¤Æ¤Ï»ä¤Ï(¥¢¥ë¥´¥ê¥º¥à¼­Åµ¤Ç)ÃΤäÆ
-¤¤¤ë¤³¤È¤À¡£¶¯°ú¤Ë̵»ë¤·¤Æ¤â½èÍýÆâÍƤ«¤éÁÛÁü¤¬¤Ä¤¯¤À¤í¤¦¤³¤È¤ò´üÂÔ¤·¤Æ
-¤¤¤ë¡£
+この関数の引数に、nparm, freqparm, lenparm, codeparm というのがある。
+これがなんなのかいきなりではわからないだろう。実は私にもわからない。今
+回の解析で特殊なのは、処理内容については私は(アルゴリズム辞典で)知って
+いることだ。強引に無視しても処理内容から想像がつくだろうことを期待して
+いる。
 
 
-¤È¤ê¤¢¤¨¤º¡¢ËÁƬ¤Î½é´ü²½Éôʬ (A) ¤Ç
+とりあえず、冒頭の初期化部分 (A) で
 
     /* (A) */
     n = nparm;
 
     /* (A) */
     n = nparm;
@@ -2742,8 +2752,8 @@ make_tree(nparm, freqparm, lenparm, codeparm)
     len = lenparm;
     avail = n;
 
     len = lenparm;
     avail = n;
 
-¤È¤·¤Æ¤¤¤ë¡£°ú¿ô¤Ç¼õ¤±¤¿ÆþÎϤò¤³¤Î¥Õ¥¡¥¤¥ë¤Î static ÊÑ¿ô¤Ë¥»¥Ã¥È¤·¡¢Â¾
-¤Î¥ë¡¼¥Á¥ó¤È¥Ç¡¼¥¿¶¦Í­¤·¤Æ¤¤¤ë¤è¤¦¤À¡£avail ¤Ï¸å¤ÇÀâÌÀ¤·¤è¤¦¡£
+としている。引数で受けた入力をこのファイルの static 変数にセットし、他
+のルーチンとデータ共有しているようだ。avail は後で説明しよう。
 
     /* (B) */
     heapsize = 0;
 
     /* (B) */
     heapsize = 0;
@@ -2754,21 +2764,21 @@ make_tree(nparm, freqparm, lenparm, codeparm)
             heap[++heapsize] = i;
     }
 
             heap[++heapsize] = i;
     }
 
-¤³¤³¤Ç¡¢heap[] ¤ò½é´ü²½¤·¤Æ¤¤¤ë¡£heapsize ¤Ï¡¢heap ¤ÎÍ×ÁÇ¿ô¤È¤Ê¤ë¡£¤³
-¤Î½èÍý¤ÏÍ¥ÀèÂÔ¤Á¹ÔÎó heap[] ¤òºî¤ëÉôʬ¤Ê¤Î¤À¤¬¡¢¤Ê¤¼Í¥ÀèÂÔ¤Á¹ÔÎó¤¬É¬Í×
-¤Ê¤Î¤«¤È¤¤¤¦¤ÈÀè¤ÎÀâÌÀ¤Ç Huffman Ë¡¤Î¥¢¥ë¥´¥ê¥º¥à¤Ë½Ð¸½²ó¿ô¤Î¾¯¤Ê¤¤½ç
-¤ËÍÕ¤òÀá¤Ë«¤Í¤ë¤È¤¤¤¦Éôʬ¤¬¤¢¤Ã¤¿¡£Í¥ÀèÂÔ¤Á¹ÔÎó¤Ï¤³¤Î¤¿¤á¤Î¤â¤Î¤À¡£¤È
-¤ê¤¢¤¨¤º¡¢heap[] ¤ÎÍ×ÁǤϰµ½Ì¤¹¤ëʸ»ú¤Ç¤¢¤ë¤È¤¤¤¦¤³¤È¤À¤±¤ò½ñ¤¤¤Æ¤ª¤¯¡£
-¾ÜºÙ¤Ï¤¹¤°¸å¤Ç½Ð¤ë¤À¤í¤¦¡£freq[i] (¤¹¤Ê¤ï¤Á°ú¿ô freqparm) ¤Ï¡¢Ê¸»ú i 
-¤Î½Ð¸½²ó¿ô¤òɽ¤·¤Æ¤¤¤ë¡£¤À¤«¤é¡¢n (nparm)¤Ï¡¢Éä¹æ²½¤¹¤ë¥â¥Ç¥ë¾å¤Îʸ»ú
-¤Î¼ïÎà¤Î¿ô¤òɽ¤·¤Æ¤¤¤ë¤³¤È¤Ë¤Ê¤ë¡£¤¿¤È¤¨¤ÐÄ̾ï¤Î¥Õ¥¡¥¤¥ë¤Ê¤é nparm ¤Ï 
-256 ¤À¤í¤¦¡£¤Þ¤¢¡¢·ë¶É¤Ï freq[] ¤ÎÍ×ÁÇ¿ô¤À¡£
+ここで、heap[] を初期化している。heapsize は、heap の要素数となる。こ
+の処理は優先待ち行列 heap[] を作る部分なのだが、なぜ優先待ち行列が必要
+なのかというと先の説明で Huffman 法のアルゴリズムに出現回数の少ない順
+に葉を節に束ねるという部分があった。優先待ち行列はこのためのものだ。と
+りあえず、heap[] の要素は圧縮する文字であるということだけを書いておく。
+詳細はすぐ後で出るだろう。freq[i] (すなわち引数 freqparm) は、文字 i 
+の出現回数を表している。だから、n (nparm)は、符号化するモデル上の文字
+の種類の数を表していることになる。たとえば通常のファイルなら nparm は 
+256 だろう。まあ、結局は freq[] の要素数だ。
 
 
-    nparm               ºÇÂçÍ×ÁÇ¿ô
-    freqparm[0:nparm]   Åº»ú¤¬Ê¸»ú¤Ç¡¢¤½¤ÎÍ×ÁǤ¬½Ð¸½²ó¿ô
+    nparm               最大要素数
+    freqparm[0:nparm]   添字が文字で、その要素が出現回数
 
 
-Ãí°Õ¤¹¤Ù¤­¤Ê¤Î¤Ï heap[] ¤ÎÍ×ÁǤϠ1 °Ê¹ß¤ò»ÈÍѤ·¤Æ¤¤¤ë¤³¤È¤À¤í¤¦¡£
-heap[0] ¤Ï»È¤ï¤ì¤Ê¤¤¡£
+注意すべきなのは heap[] の要素は 1 以降を使用していることだろう。
+heap[0] は使われない。
 
     /* (C) */
     if (heapsize < 2) {
 
     /* (C) */
     if (heapsize < 2) {
@@ -2776,36 +2786,36 @@ heap[0] 
         return heap[1];
     }
 
         return heap[1];
     }
 
-¤³¤ì¤Ï¡¢heapsize ¤¬ 0 ¤« 1 ¤Î¾ì¹ç¤òɽ¤·¤Æ¤¤¤ë¡£Éä¹æ²½¤¹¤ëʸ»ú¤Î¼ïÎब 
-0 ¤Þ¤¿¤Ï 1 ¤Ä¤·¤«¤Ê¤¤¾ì¹ç¤À¡£heap[1] ¤Ï¡¢(B) ¤Ç 0 ¤Ë½é´ü²½¤·¤Æ¤¤¤¿¤Î¤Ç¡¢
-codeparm[0] = 0 ¤È¤·¤Æ¡¢0 ¤òÊÖ¤·¤Æ¤¤¤ë¡£¤³¤ì¤ÏÆüì¤Ê¾ò·ï¤ò¼¨¤·¤Æ¤¤¤ë¡£
-´Êñ¤ËÁÛÁü¤¬¤Ä¤¯¤³¤È¤À¤¬¡¢½Ð¸½¤¹¤ëʸ»ú¤Î¼ïÎब1¼ïÎष¤«¤Ê¤¤¾ì¹ç¡¢¥Ï¥Õ
-¥Þ¥óÌÚ¤òºî¤ëɬÍפ¬¤Ê¤¤¡£LHa ¤Ç¤Ï¤³¤Î¤è¤¦¤Ê¾ì¹ç¤ËÆüì¤Ê¹½Â¤¤¢¤ë¤¤¤ÏÊýË¡
-¤òÍѤ¤¤Æ¤¤¤ë¤³¤È¤¬ÁÛÁü¤Ç¤­¤ë¡£
+これは、heapsize が 0 か 1 の場合を表している。符号化する文字の種類が 
+0 または 1 つしかない場合だ。heap[1] は、(B) で 0 に初期化していたので、
+codeparm[0] = 0 として、0 を返している。これは特殊な条件を示している。
+簡単に想像がつくことだが、出現する文字の種類が1種類しかない場合、ハフ
+マン木を作る必要がない。LHa ではこのような場合に特殊な構造あるいは方法
+を用いていることが想像できる。
 
     /* (D) */
     for (i = heapsize / 2; i >= 1; i--)
         downheap(i);    /* make priority queue */
 
 
     /* (D) */
     for (i = heapsize / 2; i >= 1; i--)
         downheap(i);    /* make priority queue */
 
-Í¥ÀèÂÔ¤Á¹ÔÎó heap[] ¤ò¹½ÃÛ¤¹¤ë¡£downheap() ¤¬¤Ê¤ó¤Ê¤Î¤«¡¢¤³¤ì¤¬¤É¤¦¤¤¤Ã
-¤¿½èÍý¤Ê¤Î¤«¤Î¾ÜºÙ¤Ï¾Êά¤·¤è¤¦¡£¥¢¥ë¥´¥ê¥º¥à¼­Åµ¤Î¡Ö¥Ò¡¼¥×¥½¡¼¥È¡×¤Î¹à
-¤Ë¾Ü¤·¤¤¤¬¡¢heap[] ¤ÏÌÚ¹½Â¤¤ò¼¨¤·¤Æ¤ª¤ê¡¢¤³¤ÎÌÚ¹½Â¤(2ʬÌÚ)¤Ë¤Ï¡Ö¿Æ¤Ï»Ò
-¤è¤êÍ¥Àè½ç°Ì¤¬Æ±¤¸¤«¹â¤¤¡×¤È¤¤¤¦µ¬Â§¤À¤±¤¬¤¢¤ë¡£¤³¤ÎÌÚ¹½Â¤¤Ï¡¢
+優先待ち行列 heap[] を構築する。downheap() がなんなのか、これがどういっ
+た処理なのかの詳細は省略しよう。アルゴリズム辞典の「ヒープソート」の項
+に詳しいが、heap[] は木構造を示しており、この木構造(2分木)には「親は子
+より優先順位が同じか高い」という規則だけがある。この木構造は、
 
 
-        1. heap[n] ¤Îº¸¤Î»Ò¤Ï heap[2*n]¡¢±¦¤Î»Ò¤Ï heap[2*n + 1]
+        1. heap[n] の左の子は heap[2*n]、右の子は heap[2*n + 1]
 
 
-¤Ç¡¢É½¸½¤µ¤ì¤Æ¤ª¤ê¡¢¤³¤Î¤è¤¦¤ÊȾ½ç½øÌÚ (partial ordered tree) ¤Ë¤Ï¡¢°Ê
-²¼¤ÎÆÃħ¤¬¤¢¤ë
+で、表現されており、このような半順序木 (partial ordered tree) には、以
+下の特徴がある
 
 
-        2. heap[n] ¤Î¿Æ¤Ï heap[n/2]
-        3. heap[1.. heapsize/2] ¤ÏÀá¤Ç¡¢heap[heapsize/2 .. heapsize] ¤ÏÍÕ
+        2. heap[n] の親は heap[n/2]
+        3. heap[1.. heapsize/2] は節で、heap[heapsize/2 .. heapsize] は葉
 
 
-¤³¤Î heap[] ¤¬ºÇ½é¤Ð¤é¤Ð¤é¤ËÍ×ÁǤ¬³ÊǼ¤µ¤ì¤Æ¤¤¤ë¤È¤­¡¢Íդ˶ᤤÀᤫ¤é½ç
-¤Ë downheap() ¤È¤¤¤¦Áàºî¤ò¹Ô¤¦((D)¤Î½èÍý)¤È¡¢¥Ò¡¼¥×¤ò¹½ÃۤǤ­¤ë¤è¤¦¤Ë
-¤Ê¤Ã¤Æ¤¤¤ë¡£downheap(i) ¤Ï¡¢Àá heap[i] ¤È¤½¤Î»Ò heap[2*i], heap[2*i+1] 
-¤ÇÍ×ÁǤòÈæ³Ó¤·¡¢»Ò¤ÎÍ¥Àè½ç°Ì¤ÎÊý¤¬¹â¤±¤ì¤Ð°ÌÃÖ¤ò¸ò´¹¤¹¤ë¡¢¤È¤¤¤¦½èÍý¤ò
-Íդ˸þ¤«¤Ã¤Æ·«¤êÊÖ¤¹´Ø¿ô¤À¡£°Ê²¼¡¢»²¹Í¤Þ¤Ç¤Ë maketree.c:downheap() ¤Î
-ÆâÍƤò¼¨¤¹¡£
+この heap[] が最初ばらばらに要素が格納されているとき、葉に近い節から順
+に downheap() という操作を行う((D)の処理)と、ヒープを構築できるように
+なっている。downheap(i) は、節 heap[i] とその子 heap[2*i], heap[2*i+1] 
+で要素を比較し、子の優先順位の方が高ければ位置を交換する、という処理を
+葉に向かって繰り返す関数だ。以下、参考までに maketree.c:downheap() の
+内容を示す。
 
 static void
 downheap(i)
 
 static void
 downheap(i)
@@ -2826,11 +2836,11 @@ downheap(i)
     heap[i] = k;
 }
 
     heap[i] = k;
 }
 
-¤È¤Ë¤«¤¯ (D) ¤Ë¤è¤ê¡¢ºÇ¤âÍ¥Àè½ç°Ì¤Î¹â¤¤(½Ð¸½²ó¿ô¤Î¾¯¤Ê¤¤)Í×ÁǤ¬ 
-heap[1] ¤ËÍè¤ë¤è¤¦¤Ë¤Ê¤ë¡£¤³¤ÎÍ¥ÀèÂÔ¤Á¹ÔÎó¤Ï¤Ê¤«¤Ê¤«ÌÌÇò¤¤(¤È»ä¤Ï»×¤Ã
-¤¿)¤Î¤Ç¤¤¤í¤¤¤í¤ÈÄ´¤Ù¤Æ¤ß¤ë¤Î¤â¤è¤¤¤À¤í¤¦¡£
+とにかく (D) により、最も優先順位の高い(出現回数の少ない)要素が 
+heap[1] に来るようになる。この優先待ち行列はなかなか面白い(と私は思っ
+た)のでいろいろと調べてみるのもよいだろう。
 
 
-¤µ¤Æ¡¢Â³¤±¤è¤¦ (E) ¤À¡£
+さて、続けよう (E) だ。
 
     /* (E) */
     sort = codeparm;
 
     /* (E) */
     sort = codeparm;
@@ -2851,38 +2861,38 @@ heap[1] 
         right[k] = j;
     } while (heapsize > 1);
 
         right[k] = j;
     } while (heapsize > 1);
 
-ºÇ½é¤Ë¡¢
+最初に、
 
         i = heap[1];    /* take out least-freq entry */
         if (i < n)
             *sort++ = i;
 
 
         i = heap[1];    /* take out least-freq entry */
         if (i < n)
             *sort++ = i;
 
-¤Ç¡¢ºÇ¤â½Ð¸½²ó¿ô¤Î¾¯¤Ê¤¤Ê¸»ú¤ò¼è¤Ã¤ÆÍè¤ë¡£if ¤ÎÉôʬ¤Ï¤Ò¤È¤Þ¤ºÌµ»ë¤·¤è¤¦¡£
+で、最も出現回数の少ない文字を取って来る。if の部分はひとまず無視しよう。
 
         heap[1] = heap[heapsize--];
         downheap(1);
 
 
         heap[1] = heap[heapsize--];
         downheap(1);
 
-¤Ç¡¢heap[] ¤ÎºÇ¸åÈø¤ÎÍ×ÁǤòÀèƬ¤Ë»ý¤Ã¤ÆÍè¤Æ downheap(1) ¤ò¹Ô¤Ã¤Æ¤¤¤ë¡£
-¤³¤¦¤¹¤ë¤È¡¢¥Ò¡¼¥×¤¬ºÆ¹½ÃÛ¤µ¤ì¡Ö¿Æ¤Ï»Ò¤è¤êÍ¥Àè½ç°Ì¤¬Æ±¤¸¤«¹â¤¤¡×¤È¤¤¤¦
-¾ò·ï¤ò¤Þ¤¿Ëþ¤¿¤¹¤è¤¦¤Ë¤Ê¤ë¡£heap[] ¤ÎÍ×ÁǤÏ1¤Ä¸º¤Ã¤Æ¤¤¤ë¡£·ë¶É¡¢¤³¤³¤Þ
-¤Ç¤Î½èÍý¤ÏÏÀÍýŪ¤Ë¤Ï¡ÖÍ¥ÀèÂÔ¤Á¹ÔÎ󤫤éÍ¥ÀèÅ٤ι⤤Í×ÁǤò1¤Ä¼è¤ê½Ð¤¹¡×
-¤È¸À¤¦½èÍý¤À¡£
+で、heap[] の最後尾の要素を先頭に持って来て downheap(1) を行っている。
+こうすると、ヒープが再構築され「親は子より優先順位が同じか高い」という
+条件をまた満たすようになる。heap[] の要素は1つ減っている。結局、ここま
+での処理は論理的には「優先待ち行列から優先度の高い要素を1つ取り出す」
+と言う処理だ。
 
         j = heap[1];    /* next least-freq entry */
         if (j < n)
             *sort++ = j;
 
 
         j = heap[1];    /* next least-freq entry */
         if (j < n)
             *sort++ = j;
 
-³¤±¤Æ¡¢2ÈÖÌܤËÍ¥ÀèÅ٤ι⤤Í×ÁǤò¼è¤ê½Ð¤¹¡£¤Þ¤¿¡¢if ¤Ï̵»ë¤·¤Æ¤ª¤³¤¦¡£
+続けて、2番目に優先度の高い要素を取り出す。また、if は無視しておこう。
 
         k = avail++;    /* generate new node */
         freq[k] = freq[i] + freq[j];
         heap[1] = k;
         downheap(1);    /* put into queue */
 
 
         k = avail++;    /* generate new node */
         freq[k] = freq[i] + freq[j];
         heap[1] = k;
         downheap(1);    /* put into queue */
 
-avail ¤ÏºÇ½é n (nparm)¤À¤Ã¤¿¡£freq[] ¤Ï¡¢Ê¸»ú¤Î½Ð¸½²ó¿ô¤Ê¤Î¤ÇºÇ½éʸ»ú
-¤Î¼ïÎà¿ôʬ(nparm)¤ÎÍ×ÁǤ·¤«¤Ê¤¤¤¬¥Ï¥Õ¥Þ¥óÌÚ¤ÎÀá¤Î½Ð¸½²ó¿ô(¤È¤¤¤¦¤«Í¥Àè
-½ç°Ì)¤ò³ÊǼ¤¹¤ë¤¿¤á¤Ë freq[] ¤Ï¡¢nparm * 2 - 1 ¤Î³ÊǼ°è¤¬É¬ÍפȤʤ뤳
-¤È¤¬¤ï¤«¤ë¡£(ÍÕ¤¬ n ¸Ä¤¢¤ë 2 Ê¬Ìڤˤϡ¢À᤬ n - 1 ¸Ä¤¢¤ë)
+avail は最初 n (nparm)だった。freq[] は、文字の出現回数なので最初文字
+の種類数分(nparm)の要素しかないがハフマン木の節の出現回数(というか優先
+順位)を格納するために freq[] は、nparm * 2 - 1 の格納域が必要となるこ
+とがわかる。(葉が n 個ある 2 分木には、節が n - 1 個ある)
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -2892,11 +2902,11 @@ freq |                       |                       |
      0                       nparm                   nparm * 2 - 1
 
      |-----------------------|-----------------------|
      0                       nparm                   nparm * 2 - 1
 
      |-----------------------|-----------------------|
-      Ê¸»ú(¥Ï¥Õ¥Þ¥óÌÚ¤ÎÍÕ)    ¥Ï¥Õ¥Þ¥óÌÚ¤ÎÀá¤ÎÍ¥Àè½ç°Ì
-      ¤ÎÍ¥Àè½ç°Ì
+      文字(ハフマン木の葉)    ハフマン木の節の優先順位
+      の優先順位
 
 
 
 
-      Îã:
+      :
                  .     ... freq[4]
                 / \
                .   \   ... freq[3]
                  .     ... freq[4]
                 / \
                .   \   ... freq[3]
@@ -2905,31 +2915,31 @@ freq |                       |                       |
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤³¤Þ¤Ç¤Ç¡¢½Ð¸½²ó¿ô¤ÎÄ㤤2¤Ä¤ÎÍ×ÁǤò¼è¤ê½Ð¤·¤½¤Î½Ð¸½²ó¿ô¤ÎϤò 
-freq[k] ¤ËÀßÄꤹ¤ë¤³¤È¤Ë¤Ê¤ë¡£½Ð¸½²ó¿ô¤ÎϤϠheap[] ¤ËºÆÀßÄꤵ¤ì¡¢
-downheap(1) ¤Ç¡¢Í¥ÀèÂÔ¤Á¹ÔÎó¤ò¤Þ¤¿ºÆ¹½ÃÛ¤¹¤ë¡£¤³¤ì¤Ï¡ÖÍÕ¤ò«¤ÍÀá¤òºî¤ë¡×
-¤È¤¤¤¦¥Ï¥Õ¥Þ¥óÌڤι½ÃÛ¥¢¥ë¥´¥ê¥º¥à¤Î¼ÂÁõ¤À¡£¿·¤·¤¯ºîÀ®¤·¤¿À᤬ k ¤Ç¤½
-¤ÎºÇÂçÃͤ¬ºÇ½ªÅª¤Ë avail-1 ¤Ç¤¢¤ë¡£
+ここまでで、出現回数の低い2つの要素を取り出しその出現回数の和を 
+freq[k] に設定することになる。出現回数の和は heap[] に再設定され、
+downheap(1) で、優先待ち行列をまた再構築する。これは「葉を束ね節を作る」
+というハフマン木の構築アルゴリズムの実装だ。新しく作成した節が k でそ
+の最大値が最終的に avail-1 である。
 
 
-ºÇ¸å¤Ë
+最後に
 
         left[k] = i;
         right[k] = j;
 
 
         left[k] = i;
         right[k] = j;
 
-¤Ç¡¢¥Ï¥Õ¥Þ¥óÌÚ¤ò¹½Â¤ left[]¡¢right[] ¤ÇºîÀ®¤¹¤ë¡£
+で、ハフマン木を構造 left[]、right[] で作成する。
 
 
-¤³¤Î (E) ¤òÃê¾ÝÅ٤ι⤤¥³¡¼¥É¤Ç¼¨¤·¤Æ¤ß¤è¤¦¡£¥Ï¥Õ¥Þ¥óÌÚ¤Ï
+この (E) を抽象度の高いコードで示してみよう。ハフマン木は
     struct huffman {
        ...
     } huff;
 
     struct huffman {
        ...
     } huff;
 
-¤Çɽ¤·¡¢¥Ï¥Õ¥Þ¥óÌÚ¤Î1¤Ä¤ÎÀá¤Ï¡¢
+で表し、ハフマン木の1つの節は、
     make_huff(huff, node, left, right)
     make_huff(huff, node, left, right)
-¤ÇºîÀ®¤Ç¤­¤ë¤È¤¹¤ë¡£¤Þ¤¿¡¢Í¥Àè½ç°Ì¤Ä¤­ÂÔ¤Á¹ÔÎó¤ò heap ¤È¤·¡¢heap ¤«¤é
-Í×ÁǤò¼è¤ê½Ð¤¹½èÍý¡¢Í×ÁǤò³ÊǼ¤¹¤ë½èÍý¤ò¤½¤ì¤¾¤ì²¾¤Ë
+で作成できるとする。また、優先順位つき待ち行列を heap とし、heap から
+要素を取り出す処理、要素を格納する処理をそれぞれ仮に
         n = delete_pqueue(heap)
         insert_pqueue(heap, n)
         n = delete_pqueue(heap)
         insert_pqueue(heap, n)
-¤È¤¹¤ë¤È¡¢
+とすると、
 
     /* (E) */
     do {
 
     /* (E) */
     do {
@@ -2944,22 +2954,22 @@ downheap(1) 
         make_huff(&huff, node, left, right);
     } while (heapsize > 1);
 
         make_huff(&huff, node, left, right);
     } while (heapsize > 1);
 
-¤³¤ó¤Ê¤È¤³¤í¤À¤í¤¦¤«¡£¸µ¤Î½èÍý¤Ç¤Ï¥Ò¡¼¥×¤«¤é¤ÎÍ×ÁǤμè¤ê½Ð¤·¤ÈÁÞÆþ¤Ç̵
-Â̤ʽèÍý¤ò̵¤¯¤¹¤¿¤á¤Ë¾¯¤·Ê£»¨¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£(¤½¤·¤Æ¥Ç¡¼¥¿¹½Â¤¤Ë°Í¸¤·
-¤¿½èÍý¤Ë¤Ê¤Ã¤Æ¤¤¤ë)¡£¤É¤Á¤é¤¬¤è¤ê¤¹¤°¤ì¤Æ¤¤¤ë¤«¤ÏÈù̯¤Ê½ê¤À¡£»ä¤Ï¿¾¯
-¤Î½èÍý¤Î̵Â̤âÌܤò¤Ä¤Ö¤Ã¤Æ¤è¤ê¤ï¤«¤ê¤ä¤¹¤¤Êý¤òÍ¥À褹¤ë¤Î¤¬¹¥¤­¤Ê¤Î¤À¤¬¡£
-¤³¤ì¤Ï¤Á¤ç¤Ã¤È¹Í¤¨¤µ¤»¤é¤ì¤ë¤È¤³¤í¤À¡£
+こんなところだろうか。元の処理ではヒープからの要素の取り出しと挿入で無
+駄な処理を無くすために少し複雑になっている。(そしてデータ構造に依存し
+た処理になっている)。どちらがよりすぐれているかは微妙な所だ。私は多少
+の処理の無駄も目をつぶってよりわかりやすい方を優先するのが好きなのだが。
+これはちょっと考えさせられるところだ。
 
 
-¥ë¡¼¥×¤òÈ´¤±¤¿½ê¤Ç k (avail - 1) ¤Ï¡¢¥Ï¥Õ¥Þ¥óÌڤꬤòɽ¤·¤Æ¤¤¤ë¡£
-left[0:avail], right[0:avail] ¤Ç¥Ï¥Õ¥Þ¥óÌÚ¤òɽ¤·¡¢¤½¤Î¤¦¤Á
-left[nparm...avail], right[nparm...avail] ¤¬Àá¤Î»Ò¤ò¼¨¤·¤Æ¤¤¤ë¡£
-left[0...nparm], right[0...nparm] ¤Ï»È¤ï¤ì¤Ê¤¤¤è¤¦¤À¡£
+ループを抜けた所で k (avail - 1) は、ハフマン木の根を表している。
+left[0:avail], right[0:avail] でハフマン木を表し、そのうち
+left[nparm...avail], right[nparm...avail] が節の子を示している。
+left[0...nparm], right[0...nparm] は使われないようだ。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-      Îã:
+      :
                  . -- k (= avail-1)
                 / \
                  . -- k (= avail-1)
                 / \
-   left[k] --  .   \ 
+   left[k] --  .   \
               /\    \
              a  b    c -- right[k]
              |   \
               /\    \
              a  b    c -- right[k]
              |   \
@@ -2968,10 +2978,10 @@ left[0...nparm], right[0...nparm] 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤ì¤Ç¡¢¥Ï¥Õ¥Þ¥óÌڤι½ÃۤϽª¤ê¤Ê¤Î¤À¤¬¡¢¥Ï¥Õ¥Þ¥óË¡¤ÎÉä¹æ²½¤Ç¤Ï¥Ï¥Õ¥Þ¥ó
-ÌÚ¤ÎÍÕ¤«¤éº¬¤Ë¸þ¤«¤Ã¤ÆÌÚ¤òé¤ëɬÍפ¬¤¢¤ë¤Ï¤º¤Ê¤Î¤Ë¡¢left[]¡¢right[] ¤Î
-¹½Â¤¤Ç¤Ïº¬¤«¤éÍդ˸þ¤«¤Ã¤Æ¤·¤«ÌÚ¤òé¤ë¤³¤È¤¬¤Ç¤­¤Ê¤¤¤Ï¤º¤À¡£¤³¤ì¤Ï¤É¤¦
-¤¤¤¦¤³¤È¤À¤í¤¦¡©make_tree() ¤Ç¤Ï¤Þ¤À½èÍý¤¬Â³¤¤¤Æ¤¤¤ë¡£
+これで、ハフマン木の構築は終りなのだが、ハフマン法の符号化ではハフマン
+木の葉から根に向かって木を辿る必要があるはずなのに、left[]、right[] の
+構造では根から葉に向かってしか木を辿ることができないはずだ。これはどう
+いうことだろう?make_tree() ではまだ処理が続いている。
 
     /* (F) */
     sort = codeparm;
 
     /* (F) */
     sort = codeparm;
@@ -2979,13 +2989,13 @@ left[0...nparm], right[0...nparm] 
     make_code(nparm, lenparm, codeparm);
     return k;       /* return root */
 
     make_code(nparm, lenparm, codeparm);
     return k;       /* return root */
 
-¤É¤¦¤ä¤é¡¢ÌÚ¹½Â¤¤Î¾¤Ë¤â¤Ê¤Ë¤ä¤é¹½Â¤¤òºîÀ®¤·¤Æ¤¤¤ë¤è¤¦¤À¡£¤³¤ì¤ÏÀèÄø̵
-»ë¤·¤¿ if Ê¸¤Ë¤â´ØÏ¢¤¹¤ë¡£¤½¤·¤Æ¤³¤ì¤Ï¡Ö¥¢¥ë¥´¥ê¥º¥à¼­Åµ¡×¤Ë¤ÏºÜ¤Ã¤Æ¤¤
-¤Ê¤¤Éôʬ¤À¡£¤É¤¦¤ä¤é LHa ¤Ê¤ê¤Î¹©Éפ¬¤¢¤ë¤è¤¦¤À¡£
+どうやら、木構造の他にもなにやら構造を作成しているようだ。これは先程無
+視した if 文にも関連する。そしてこれは「アルゴリズム辞典」には載ってい
+ない部分だ。どうやら LHa なりの工夫があるようだ。
 
 
-¤Þ¤º¡¢maketree.c:make_len(root) ¤«¤é¸«¤Æ¤ß¤è¤¦¤È»×¤¦¤¬¡¢¤½¤ÎÁ°¤Ë¤³¤Î´Ø
-¿ô¤Ï maketree.c:count_len(root) ¤È¤¤¤¦´Ø¿ô¤ò¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¡£¤³¤Á¤é¤«¤é
-Àè¤Ë¸«¤ë¤³¤È¤Ë¤·¤¿¡£
+まず、maketree.c:make_len(root) から見てみようと思うが、その前にこの関
+数は maketree.c:count_len(root) という関数を呼び出している。こちらから
+先に見ることにした。
 
 static void
 count_len(i)            /* call with i = root */
 
 static void
 count_len(i)            /* call with i = root */
@@ -3003,22 +3013,22 @@ count_len(i)            /* call with i = root */
     }
 }
 
     }
 }
 
-¤³¤Î´Ø¿ô¤ËÅϤµ¤ì¤ë i ¤Ï¡¢ºÇ½é¥Ï¥Õ¥Þ¥óÌڤꬤò»Ø¤¹ÃͤÀ¡£¤³¤Î´Ø¿ô¤ÎÁ´ÂÎ
-¤ò¸«¤ì¤Ð¡¢i ¤¬Àá¤äÍÕ¤ò¼¨¤¹¤³¤È¤Ï¤¹¤°¤ï¤«¤ë¡£ºÇ½é¤Î if Ê¸¤Ë½Ð¤Æ¤¯¤ë n 
-¤Ï²¿¤«¤È¤¤¤¦¤È¤Ê¤ó¤È¤³¤Î¥Õ¥¡¥¤¥ëÆâ¤Î static ÊÑ¿ô¤Ç¡¢make_tree() ¤ÎËÁƬ
-¤Ç nparm ¤Ç½é´ü²½¤·¤Æ¤¤¤¿¡£ÀèÄø¤Ïµ¤¤Ë¤â¤È¤á¤Ê¤«¤Ã¤¿¤Î¤À¤¬¡¢ÊÑ¿ô̾¤ÎÁª
-¤ÓÊý¤¬¤É¤¦¤Ë¤â¤è¤í¤·¤¯¤Ê¤¤¡£¤È¤Ë¤«¤¯ n ¤Ï¡¢nparm ¤Ç¡¢freqparm ¤ÎºÇ½é¤Î
-Í×ÁÇ¿ô¤Ç¡¢Ê¸»ú¤Î¼ïÎà¤Î¿ô¤òɽ¤·¤Æ¤¤¤¿¤â¤Î¤À¡£¤³¤³¤Ç¤Ï¥Ï¥Õ¥Þ¥óÌÚ¤ÎÀá¤äÍÕ
-¤È¤Ê¤ë i ¤ÈÈæ³Ó¤·¤Æ¤¤¤ë¤³¤È¤«¤é¡¢i ¤¬¥Ï¥Õ¥Þ¥óÌÚ¤ÎÀá¤ò¼¨¤¹¤«ÍÕ¤ò¼¨¤¹¤«
-¤ÎȽÃǤ˻ÈÍѤ·¤Æ¤¤¤ë¤é¤·¤¤¡£if Ê¸¤Î¾ò·ï¤¬¿¿¤Î¾ì¹ç(i < n)¡¢i ¤ÏÍդǤ¢¤ë¡£
-µ¶¤Î¾ì¹ç i ¤ÏÀá¤Ç¤¢¤ë¡£µ¶¤Î¾ì¹ç¤Ï¡¢depth ¤ò­¤·¤ÆÆó¤Ä¤Î»Ò¤ËÂФ·¤ÆºÆµ¢
-Ū¤Ë¤³¤Î´Ø¿ô¤ò¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¡£¤Ç¡¢·ë¶É¤³¤Î´Ø¿ô¤¬²¿¤ò¤·¤Æ¤¤¤ë¤«¤È¤¤¤¦¤È¡¢
-Àè¤Û¤É¹½ÃÛ¤·¤¿¥Ï¥Õ¥Þ¥óÌڤ˴ؤ·¤Æ¡¢¤¢¤ë¿¼¤µ¤ÎÍդοô¤ò¿ô¤¨¤Æ¤¤¤ë¤è¤¦¤À¡£
-
-len_cnt[1] ¤Ï¡¢¿¼¤µ 1 (º¬¤Î»Ò)¤ÎÍդοô¤Ç 0 ¡Á 2 ¤ÎÃͤˤʤ롣len_cnt[2] 
-¤Ï¡¢¿¼¤µ 2 (º¬¤Î¹)¤ÎÍդοô¤Ç 0 ¡Á 4 ¤ÎÃͤò»ý¤Ä¤À¤í¤¦¡£¤½¤·¤Æ¡¢¿¼¤µ 16 
-°Ê¾å¤ÎÁؤ˴ؤ·¤Æ¤Ï len_cnt[16] ¤Ë¤¹¤Ù¤Æ·×¾å¤µ¤ì¤ë¤è¤¦¤À¡£¤È¤Ë¤«¤¯¤½¤Î
-¤è¤¦¤Ê½èÍý¤À¤È¤¤¤¦¤³¤È¤Ç¤³¤Î´Ø¿ô¤ò½ª¤¨¡¢make_len() ¤ò¸«¤è¤¦¡£
+この関数に渡される i は、最初ハフマン木の根を指す値だ。この関数の全体
+を見れば、i が節や葉を示すことはすぐわかる。最初の if 文に出てくる n 
+は何かというとなんとこのファイル内の static 変数で、make_tree() の冒頭
+で nparm で初期化していた。先程は気にもとめなかったのだが、変数名の選
+び方がどうにもよろしくない。とにかく n は、nparm で、freqparm の最初の
+要素数で、文字の種類の数を表していたものだ。ここではハフマン木の節や葉
+となる i と比較していることから、i がハフマン木の節を示すか葉を示すか
+の判断に使用しているらしい。if 文の条件が真の場合(i < n)、i は葉である。
+偽の場合 i は節である。偽の場合は、depth を足して二つの子に対して再帰
+的にこの関数を呼び出している。で、結局この関数が何をしているかというと、
+先ほど構築したハフマン木に関して、ある深さの葉の数を数えているようだ。
+
+len_cnt[1] は、深さ 1 (根の子)の葉の数で 0 〜 2 の値になる。len_cnt[2] 
+は、深さ 2 (根の孫)の葉の数で 0 〜 4 の値を持つだろう。そして、深さ 16 
+以上の層に関しては len_cnt[16] にすべて計上されるようだ。とにかくその
+ような処理だということでこの関数を終え、make_len() を見よう。
 
 static void
 make_len(root)
 
 static void
 make_len(root)
@@ -3065,15 +3075,15 @@ make_len(root)
     }
 }
 
     }
 }
 
-¤Á¤ç¤Ã¤ÈÊ£»¨¤À¤¬¤æ¤Ã¤¯¤ê¸«¤Æ¤¤¤³¤¦¡£¤Þ¤º (A) ¤Î½é´ü²½Éôʬ¤ÏÀè¤Û¤É¤Î 
-count_len() ¤ò¸Æ¤Ó½Ð¤¹¤À¤±¤Î¤â¤Î¤Ê¤Î¤Ç¤â¤¦¤è¤¤¤À¤í¤¦¡£
+ちょっと複雑だがゆっくり見ていこう。まず (A) の初期化部分は先ほどの 
+count_len() を呼び出すだけのものなのでもうよいだろう。
 
     /* (A) */
     for (i = 0; i <= 16; i++)
         len_cnt[i] = 0;
     count_len(root);
 
 
     /* (A) */
     for (i = 0; i <= 16; i++)
         len_cnt[i] = 0;
     count_len(root);
 
-¤³¤ì¤Ç¡¢len_cnt[1..16] ¤Ë¤Ï¥Ï¥Õ¥Þ¥óÌڤγÆÁؤÎÍդοô¤¬·×¾å¤µ¤ì¤ë¡£Â³¤¤¤Æ (B)
+これで、len_cnt[1..16] にはハフマン木の各層の葉の数が計上される。続いて (B)
 
     /* (B) */
     cum = 0;
 
     /* (B) */
     cum = 0;
@@ -3084,42 +3094,42 @@ count_len() 
     cum &= 0xffff;
 #endif
 
     cum &= 0xffff;
 #endif
 
-¤³¤ì¤Ï¡¢¤É¤¦¤¤¤¦¤³¤È¤À¤í¤¦¡©len_cnt[] ¤Ï short ¤ÎÇÛÎó¤À¤¬¡¢¤È¤Ë¤«¤¯°Ê
-²¼¤Î¤è¤¦¤Ê·×»»(len_cnt[] ¤ÎÍ×ÁǤò 1 ¥Ó¥Ã¥È¤º¤é¤·¤Ê¤¬¤é­¤¹)¤ò¤·¤Æ¤¤¤ë¡£
-ºÇ¸å¤Ë int ·¿¤Î¥µ¥¤¥º¤¬ 2 ¤Ç¤Ê¤¤¾ì¹ç 0xffff ¤ÇÏÀÍýÀѤò¤·¤Æ¤¤¤ë¤Î¤Ç 2¥Ð
-¥¤¥È¤ÎÉä¹æ¤Ê¤·À°¿ô¤ò·ë²Ì¤È¤·¤ÆÍߤ·¤¤¤é¤·¤¤¡£
+これは、どういうことだろう?len_cnt[] は short の配列だが、とにかく以
+下のような計算(len_cnt[] の要素を 1 ビットずらしながら足す)をしている。
+最後に int 型のサイズが 2 でない場合 0xffff で論理積をしているので 2バ
+イトの符号なし整数を結果として欲しいらしい。
 
 ----------------------------------------------------------------------------
                 f e d c b a 9 8 7 6 5 4 3 2 1 0  bit
 
 ----------------------------------------------------------------------------
                 f e d c b a 9 8 7 6 5 4 3 2 1 0  bit
-  len_cnt[16]  |x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|   (²¼°Ì 16¥Ó¥Ã¥È)
-+ len_cnt[15]  |x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|0|   (²¼°Ì 15¥Ó¥Ã¥È)
-+ len_cnt[14]  |x|x|x|x|x|x|x|x|x|x|x|x|x|x|0|0|   (²¼°Ì 14¥Ó¥Ã¥È)
+  len_cnt[16]  |x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|   (下位 16ビット)
++ len_cnt[15]  |x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|0|   (下位 15ビット)
++ len_cnt[14]  |x|x|x|x|x|x|x|x|x|x|x|x|x|x|0|0|   (下位 14ビット)
 +     :                                                   :
 +     :                                                   :
-+ len_cnt[ 2]  |x|x|0|0|0|0|0|0|0|0|0|0|0|0|0|0|   (²¼°Ì 2 ¥Ó¥Ã¥È)
-+ len_cnt[ 1]  |x|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|   (²¼°Ì 1 ¥Ó¥Ã¥È)
++ len_cnt[ 2]  |x|x|0|0|0|0|0|0|0|0|0|0|0|0|0|0|   (下位 2 ビット)
++ len_cnt[ 1]  |x|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|   (下位 1 ビット)
 & 0xffff       |1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|
 ------------------------------------------------
 = cum           x x x x x x x x x x x x x x x x
 ----------------------------------------------------------------------------
 
 & 0xffff       |1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|
 ------------------------------------------------
 = cum           x x x x x x x x x x x x x x x x
 ----------------------------------------------------------------------------
 
-¤³¤³¤Ç¡¢len_cnt[] ¤Î³ÆÍ×ÁǤÎÃͤ¬³ÆÁؤÎÍդοô¤Ç¤¢¤ë¤³¤È¤ò¹Í¤¨¤ë¤È¡¢³ÆÍ×
-ÁǤǻÈÍѤ¹¤ë¥Ó¥Ã¥È¿ô¤È¤Î´ØÏ¢¤¬¸«¤¨¤ë¡£
+ここで、len_cnt[] の各要素の値が各層の葉の数であることを考えると、各要
+素で使用するビット数との関連が見える。
 
 
-              ¼è¤êÆÀ¤ë
-              ÃͤÎÈÏ°Ï      »ÈÍѥӥåȿô
+              取り得る
+              値の範囲      使用ビット数
  -----------------------------------------
  -----------------------------------------
- len_cnt[16]  0.. 2^16°Ê¾å  17¥Ó¥Ã¥È°Ê¾å
- len_cnt[15]  0.. 2^15      16¥Ó¥Ã¥È
- len_cnt[14]  0.. 2^14      15¥Ó¥Ã¥È
-     :                  
- len_cnt[ 3]  0.. 2^3        4 ¥Ó¥Ã¥È
- len_cnt[ 2]  0.. 2^2        3 ¥Ó¥Ã¥È
- len_cnt[ 1]  0.. 2^1        2 ¥Ó¥Ã¥È
-
-Àè¤Î·×»»¼°¤Ç¤Ï len_cnt[] ¤Î³ÆÍ×ÁǤǻÈÍѤ·ÆÀ¤ë¥Ó¥Ã¥È¿ô¤«¤é 1 °ú¤¤¤¿¥Ó¥Ã
-¥È¿ô¤¬·×»»¤Ë»ÈÍѤµ¤ì¤Æ¤¤¤ë¡£Î㤨¤Ðº¬¤Î»Ò¤¬¤¹¤Ù¤ÆÍդʤé len_cnt[1] ¤Ï¡¢
-2 ¤Ë¤Ê¤ê¡¢2¿Ê¤Ç¡¢00000000 00000010 ¤À¤¬¡¢cum ¤Î·×»»¤Ë¤Ï¤³¤Î²¼°Ì 1 ¥Ó¥Ã
-¥È¤·¤«»ÈÍѤµ¤ì¤Ê¤¤¡£
+ len_cnt[16]  0.. 2^16以上  17ビット以上
+ len_cnt[15]  0.. 2^15      16ビット
+ len_cnt[14]  0.. 2^14      15ビット
+     :
+ len_cnt[ 3]  0.. 2^3        4 ビット
+ len_cnt[ 2]  0.. 2^2        3 ビット
+ len_cnt[ 1]  0.. 2^1        2 ビット
+
+先の計算式では len_cnt[] の各要素で使用し得るビット数から 1 引いたビッ
+ト数が計算に使用されている。例えば根の子がすべて葉なら len_cnt[1] は、
+2 になり、2進で、00000000 00000010 だが、cum の計算にはこの下位 1 ビッ
+トしか使用されない。
 
        /\
       a  b     .. len_cnt[1] = 00000000 00000010
 
        /\
       a  b     .. len_cnt[1] = 00000000 00000010
@@ -3127,8 +3137,8 @@ count_len() 
                                                v
                                          cum = x0000000 00000000
 
                                                v
                                          cum = x0000000 00000000
 
-º¬¤Î¹¤¬¤¹¤Ù¤ÆÍդʤé len_cnt[2] ¤Ï¡¢4 ¤Ë¤Ê¤ê¡¢2¿Ê¤Ç¡¢00000000 00000100 
-¤À¤¬¡¢cum ¤Î·×»»¤Ë¤Ï¤³¤Î²¼°Ì 2 ¥Ó¥Ã¥È¤·¤«»ÈÍѤµ¤ì¤Ê¤¤¡£
+根の孫がすべて葉なら len_cnt[2] は、4 になり、2進で、00000000 00000100 
+だが、cum の計算にはこの下位 2 ビットしか使用されない。
 
        / \     .. len_cnt[1] = 00000000 00000000
       /\ /\
 
        / \     .. len_cnt[1] = 00000000 00000000
       /\ /\
@@ -3137,10 +3147,10 @@ count_len() 
                                                vv
                                          cum = xx000000 00000000
 
                                                vv
                                          cum = xx000000 00000000
 
-¤³¤Î¤è¤¦¤Ë¤¢¤ëÁؤΤ¹¤Ù¤Æ¤¬ÍդǤ¢¤ë¤è¤¦¤Ê¥Ð¥é¥ó¥¹¤Î¤è¤¤¥Ï¥Õ¥Þ¥óÌÚ¤Ë
-ÂФ·¤Æ¤ÏÀè¤Î·×»»·ë²Ì cum ¤Ï 0 ¤Ë¤Ê¤ë¤é¤·¤¤¡£
+このようにある層のすべてが葉であるようなバランスのよいハフマン木に
+対しては先の計算結果 cum は 0 になるらしい。
 
 
-¤Þ¤¿¡¢
+また、
        /\
       a /\     .. len_cnt[1] = 00000000 00000001
         b c    .. len_cnt[2] =  00000000 00000010
        /\
       a /\     .. len_cnt[1] = 00000000 00000001
         b c    .. len_cnt[2] =  00000000 00000010
@@ -3148,7 +3158,7 @@ count_len() 
                                                vv
                                          cum = xx000000 00000000
 
                                                vv
                                          cum = xx000000 00000000
 
-¤Î¤è¤¦¤ÊÌÚ¤ËÂФ·¤Æ¤â·×»»·ë²Ì¤Ï¥ª¡¼¥Ð¡¼¥Õ¥í¡¼¤µ¤ì cum ¤Ï 0 ¤Ë¤Ê¤ë¡£
+のような木に対しても計算結果はオーバーフローされ cum は 0 になる。
 
        /\
       a /\       .. len_cnt[1] = 00000000 00000001
 
        /\
       a /\       .. len_cnt[1] = 00000000 00000001
@@ -3158,8 +3168,8 @@ count_len() 
                                                  vvv
                                            cum = xxx00000 00000000
 
                                                  vvv
                                            cum = xxx00000 00000000
 
-¤âƱÍͤˠcum ¤Ï 0 ¤À¡£·ë¶É cum ¤¬ 0 ¤Ë¤Ê¤é¤Ê¤¤ÌڤȤϤ¢¤ëÀ᤬ 1 ¤Ä¤ÎÍÕ
-¤·¤«¤â¤¿¤Ê¤¤¤è¤¦¤Ê¾ì¹ç¤Ç¤¢¤ë¤é¤·¤¤¡£
+も同様に cum は 0 だ。結局 cum が 0 にならない木とはある節が 1 つの葉
+しかもたないような場合であるらしい。
 
        /\
       a /\       .. len_cnt[1] = 00000000 00000001
 
        /\
       a /\       .. len_cnt[1] = 00000000 00000001
@@ -3169,12 +3179,12 @@ count_len() 
                                                  vvv
                                            cum = 11100000 00000000
 
                                                  vvv
                                            cum = 11100000 00000000
 
-¤½¤·¤Æ¡¢¥Ï¥Õ¥Þ¥óÌڤκî¤êÊý¤«¤é¤³¤Î¤è¤¦¤Ê¤³¤È¤Ïµ¯¤³¤ê¤¨¤Ê¤¤¤Î¤Ç¤Ï¤Ê¤¤¤«
-¤È»×¤¨¤ë¡£
+そして、ハフマン木の作り方からこのようなことは起こりえないのではないか
+と思える。
 
 
-(C) ¤Ç¤Ï¡¢if (cum) ¤Ç¡¢¤³¤Îµ¯¤³¤ê¤¨¤Ê¤¤¥Ï¥Õ¥Þ¥óÌڤξì¹ç¤Ë¤Ê¤Ë¤«½èÍý¤ò
-¹Ô¤Ã¤Æ¤¤¤ë¡£¤Þ¤Ã¤¿¤¯Ææ¤Ç¤¢¤ë¤¬¡¢¤Þ¤º¡¢¤³¤Î (C) ¤òÆüì¾ò·ï¤È¤ß¤Ê¤·¤ÆÀè
-¤Ë (D) ¤ÎÊý¤ò¸«¤ë¤³¤È¤Ë¤·¤è¤¦¡£
+(C) では、if (cum) で、この起こりえないハフマン木の場合になにか処理を
+行っている。まったく謎であるが、まず、この (C) を特殊条件とみなして先
+に (D) の方を見ることにしよう。
 
     /* (D) */
     /* make len */
 
     /* (D) */
     /* make len */
@@ -3186,31 +3196,31 @@ count_len() 
         }
     }
 
         }
     }
 
-sort ¤Ï²¿¤«¤È¤¤¤¦¤È¡¢make_tree() ¤Î°ú¿ô¤ËÅϤµ¤ì¤¿ codeparm ¤ò»Ø¤·¤Æ¤¤
-¤ë¡£¤³¤ÎÇÛÎó¤ÎÃæ¤Ë¤Ï(¥Ï¥Õ¥Þ¥óÌÚ¤ò¹½ÃÛ¤¹¤ëºÝ¤ËÀßÄꤵ¤ì¤Æ¤¤¤¿¤Î¤À¤¬)¡¢½Ð
-¸½ÉÑÅÙ¤ÎÄ㤤½ç¤Çʿʸ¤Îʸ»ú¥³¡¼¥É¤¬Æþ¤Ã¤Æ¤¤¤ë¡£make_tree() ¤Ç¡¢sort ¤Ë
-ÃͤòÀßÄꤹ¤ëºÝ¡¢
+sort は何かというと、make_tree() の引数に渡された codeparm を指してい
+る。この配列の中には(ハフマン木を構築する際に設定されていたのだが)、出
+現頻度の低い順で平文の文字コードが入っている。make_tree() で、sort に
+値を設定する際、
 
         if (j < n)
             *sort++ = j;
 
 
         if (j < n)
             *sort++ = j;
 
-¤Î¤è¤¦¤Ë¾ò·ïȽÃǤ¬¤¢¤Ã¤¿¤Î¤Ç¡¢sort[] ¤Ë¤Ï¥Ï¥Õ¥Þ¥óÌÚ¤ÎÀá¤ÏÆþ¤Ã¤Æ¤¤¤Ê¤¤¡£
-¤½¤·¤Æ¥Ï¥Õ¥Þ¥óÌڤϤ½¤Î¹½ÃۤλÅÊý¤«¤é½Ð¸½ÉÑÅÙ¤ÎÄ㤤ʸ»ú¤ÏÌڤΤè¤ê¿¼¤¤¾ì
-½ê¤Ë°ÌÃ֤Ť±¤é¤ì¤Æ¤¤¤ë¡£¤³¤ì¤é¤Î¤³¤È¤«¤é make_len()¤Çµá¤á¤è¤¦¤È¤·¤Æ¤¤
-¤ë¤â¤Î¤¬²¿¤Ê¤Î¤«¤¬¤ï¤«¤ë¡£make_len() ¤Ï¡¢
-    len[ʸ»ú] = ¥Ï¥Õ¥Þ¥óÌڤο¼¤µ
-¤È¤¤¤Ã¤¿Âбþɽ¤òºîÀ®¤¹¤ë½èÍý¤À¡£¤µ¤é¤Ë¸À¤¦¤È¥Ï¥Õ¥Þ¥óÌڤο¼¤µ¤Ïʸ»ú¤òÉä
-¹æ²½¤·¤¿·ë²Ì¤Î¥Ó¥Ã¥È¿ô¤òɽ¤¹¤³¤È¤«¤é
-    lenparm[ʸ»ú] = Éä¹æ¸ì¤Î¥Ó¥Ã¥È¿ô
-¤È¤¤¤Ã¤¿Âбþɽ¤òºîÀ®¤¹¤ë½èÍý¤Ç¤¢¤ë¤È¸À¤Ã¤¿Êý¤¬Àµ²ò¤À¤í¤¦¡£
-len[] ¤Ï¡¢make_tree() ¤ÎËÁƬ¤Ç¡¢lenparm ¤ò»Ø¤¹¤è¤¦¤ËÀßÄꤵ¤ì¤¿ÊÑ¿ô¤Ê¤Î
-¤Ç¡¢¤½¤Î¤è¤¦¤ËÃÖ¤­´¹¤¨¤Æ¤ª¤¤¤¿¡£
-
-¤Ç¤Ï¡¢Ææ¤Î (C) ¤ò¸«¤è¤¦¡£¤½¤ÎÁ°¤Ë cum != 0 ¤Ïµ¯¤³¤ê¤¨¤Ê¤¤¤È½ñ¤¤¤¿¤¬¤è
-¤¯¹Í¤¨¤¿¤é len_cnt[16] ¤À¤±¤Ï¿¼¤µ16°Ê¾å¤ÎÍÕ¤¹¤Ù¤Æ¤Î¿ô¤ò·×¾å¤·¤Æ¤¤¤ë¤¿
-¤á¡¢¤É¤Î¤è¤¦¤ÊÃͤ⤢¤êÆÀ¤ë¡£¤Ä¤Þ¤ê¡¢¤³¤Î (C) ¤Î½èÍý¤Ï¥Ï¥Õ¥Þ¥óÌÚ¤¬¿¼¤µ 
-17 °Ê¾å¤Ë¤Ê¤Ã¤¿¤È¤­¤Ë½èÍý¤µ¤ì¤ë¤â¤Î¤À¤È¸À¤¨¤½¤¦¤À¡£»×¤¤Àڤäƿ޼¨¤·¤è
-¤¦Î㤨¤Ð¤³¤ó¤ÊÌڤϡ¢(C)¤Î½èÍýÂоݤȤʤ롣
+のように条件判断があったので、sort[] にはハフマン木の節は入っていない。
+そしてハフマン木はその構築の仕方から出現頻度の低い文字は木のより深い場
+所に位置づけられている。これらのことから make_len()で求めようとしてい
+るものが何なのかがわかる。make_len() は、
+    len[文字] = ハフマン木の深さ
+といった対応表を作成する処理だ。さらに言うとハフマン木の深さは文字を符
+号化した結果のビット数を表すことから
+    lenparm[文字] = 符号語のビット数
+といった対応表を作成する処理であると言った方が正解だろう。
+len[] は、make_tree() の冒頭で、lenparm を指すように設定された変数なの
+で、そのように置き換えておいた。
+
+では、謎の (C) を見よう。その前に cum != 0 は起こりえないと書いたがよ
+く考えたら len_cnt[16] だけは深さ16以上の葉すべての数を計上しているた
+め、どのような値もあり得る。つまり、この (C) の処理はハフマン木が深さ 
+17 以上になったときに処理されるものだと言えそうだ。思い切って図示しよ
+う例えばこんな木は、(C)の処理対象となる。
 
        /\
       a /\       .. len_cnt[ 1] = 0000000000000001
 
        /\
       a /\       .. len_cnt[ 1] = 0000000000000001
@@ -3233,23 +3243,23 @@ len[] 
                                                  vvvvvvvvvvvvvvvv
                                            cum = 0000000000000001
 
                                                  vvvvvvvvvvvvvvvv
                                            cum = 0000000000000001
 
-¤³¤Î¤è¤¦¤ÊÌÚ¤ÏÎ㤨¤Ð³Æʸ»ú¤¬°Ê²¼¤Î½Ð¸½ÉÑÅ٤Ȥʤë¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë¤Èµ¯
-¤³¤ë(¼ÂºÝ¤Ë¤Ï¡¢LHA ¤Î¾ì¹ç¡¢slide ¼­½ñË¡¤Î½èÍý¤â¤¢¤ë¤Î¤Ç¤³¤ì¤Û¤Éñ½ã¤Ç
-¤Ï¤Ê¤¤)¡£
+このような木は例えば各文字が以下の出現頻度となるファイルを作成すると起
+こる(実際には、LHA の場合、slide 辞書法の処理もあるのでこれほど単純で
+はない)。
 
 
-        Ê¸»ú    ÉÑÅÙ        Ê¸»ú    ÉÑÅÙ
+        文字    頻度        文字    頻度
         ------------        ------------
         r          1        i        256
         q          1        h        512
         p          2        g       1024
         o          4        f       2048
         n          8        e       4096
         ------------        ------------
         r          1        i        256
         q          1        h        512
         p          2        g       1024
         o          4        f       2048
         n          8        e       4096
-        m         16        d       8129
+        m         16        d       8192
         l         32        c      16384
         k         64        b      32768
         l         32        c      16384
         k         64        b      32768
-        j        128        a      65535
+        j        128        a      65536
 
 
-¤È¤³¤í¤Ç¡¢cum ¤ÎÃͤϲ¿¤Ê¤Î¤«¤È¤¤¤¦¤È¡¢
+ところで、cum の値は何なのかというと、
 
                                                         :
                                .. len_cnt[15] = 0000000000000001
 
                                                         :
                                .. len_cnt[15] = 0000000000000001
@@ -3258,7 +3268,7 @@ len[] 
                        r  s                      vvvvvvvvvvvvvvvv
                                            cum = 0000000000000010
 
                        r  s                      vvvvvvvvvvvvvvvv
                                            cum = 0000000000000010
 
-¤³¤Î¾ì¹ç¤Ï cum = 2 ¤À¡£
+この場合は cum = 2 だ。
                                                         :
                                .. len_cnt[15] = 0000000000000001
                      p /\       .. len_cnt[16] = 0000000000000101
                                                         :
                                .. len_cnt[15] = 0000000000000001
                      p /\       .. len_cnt[16] = 0000000000000101
@@ -3266,10 +3276,10 @@ len[] 
                        r /\                      vvvvvvvvvvvvvvvv
                         s  t               cum = 0000000000000011
 
                        r /\                      vvvvvvvvvvvvvvvv
                         s  t               cum = 0000000000000011
 
-¤³¤Î¾ì¹ç¤Ï cum = 3 ¤À¡£¾¯¤Ê¤¯¤È¤â¤³¤ÎÎã¤Ç¤Ï¿¼¤µ 16 °Ê¾å¤ÎÍդοô - 2¤Ë
-¤Ê¤ë¤é¤·¤¤(¤½¤¦¤«¡¢11111111 11111110 = -2 ¤ò­¤·¤Æ¤¤¤ë¤Î¤À¤«¤éÅöÁ³¤À)¡£
+この場合は cum = 3 だ。少なくともこの例では深さ 16 以上の葉の数 - 2に
+なるらしい(そうか、11111111 11111110 = -2 を足しているのだから当然だ)。
 
 
-¤Ç¤Ï¡¢º£ÅÙ¤³¤½ (C) ¤ò¸«¤ë¡£
+では、今度こそ (C) を見る。
 
     /* (C) */
     /* adjust len */
 
     /* (C) */
     /* adjust len */
@@ -3287,24 +3297,24 @@ len[] 
         } while (--cum);
     }
 
         } while (--cum);
     }
 
-¤Ç¤¢¤ë¡£¤¤¤­¤Ê¤ê fprintf() ¤·¤Æ¤¤¤ë¤È¤³¤í¤¬¤¹¤´¤¤¡£¥Ç¥Ð¥Ã¥°ÍѤνÐÎϤ¬
-»Ä¤Ã¤Æ¤¤¤ë¤Î¤À¤í¤¦¡£LHa for UNIX ¤Ç 17 ¤È¤¤¤¦½ÐÎϤò¸«¤¿¤³¤È¤¬¤¢¤ë¿Í¤Ï
-¶µ¤¨¤ÆÍߤ·¤¤¡£
+である。いきなり fprintf() しているところがすごい。デバッグ用の出力が
+残っているのだろう。LHa for UNIX で 17 という出力を見たことがある人は
+教えて欲しい。
 
 
-¤Ç¡¦¡¦¡¦¡¢·ë¶É¤³¤Î (C) ¤ÎÉôʬ¤Ï¸«¤Æ¤â¤è¤¯¤ï¤«¤é¤Ê¤«¤Ã¤¿¡£¤³¤³¤Þ¤Ç½ñ¤¤
-¤Æ¤ª¤¤¤Æ¤Ê¤ó¤À¤¬¡¢µ¤»ý¤Á¤è¤¯Ìµ»ë¤¹¤ë¤³¤È¤Ë¤·¤¿¡£
+で・・・、結局この (C) の部分は見てもよくわからなかった。ここまで書い
+ておいてなんだが、気持ちよく無視することにした。
 
 
-¤Ç¤Ï¡¢make_tree() ¤«¤é¸Æ¤Ó½Ð¤µ¤ì¤ëºÇ¸å¤Î´Ø¿ô¡¢maketree.c:make_code() 
-¤ò¸«¤è¤¦¡£make_code() ¤Ï¡¢make_tree() ¤Î(F) ¤ÎÉôʬ¤Ç°Ê²¼¤Î¤è¤¦¤Ë¸Æ¤Ð¤ì
-¤Æ¤¤¤¿¡£
+では、make_tree() から呼び出される最後の関数、maketree.c:make_code() 
+を見よう。make_code() は、make_tree() の(F) の部分で以下のように呼ばれ
+ていた。
 
     make_code(nparm, lenparm, codeparm);
 
 
     make_code(nparm, lenparm, codeparm);
 
-¤³¤Î°ú¿ô¤Î¤¦¤Á¡¢lenparm[] ¤ÏÀè¤Û¤É¤Î make_len[] ¤ÇÃͤ¬ºî¤é¤ì¤¿¤â¤Î¤À¤¬¡¢
-    lenparm[ʸ»ú] = Éä¹æ¸ì¤Î¥Ó¥Ã¥È¿ô
-¤È¤¤¤¦Âбþɽ¤À¤Ã¤¿¡£codeparm[] ¤Ï¡¢Àè¤Û¤É¤â½Ð¤¿¤¬ make_tree() ¤ÎÃæ¤ÇÀß
-Äꤵ¤ì¤Æ¤¤¤ë¤â¤Î¤À¤Ã¤¿¡£½Ð¸½ÉÑÅÙ¤ÎÄ㤤½ç¤Çʿʸ¤Îʸ»ú¥³¡¼¥É¤¬Æþ¤Ã¤¿ÇÛÎó
-¤À¡£
+この引数のうち、lenparm[] は先ほどの make_len[] で値が作られたものだが、
+    lenparm[文字] = 符号語のビット数
+という対応表だった。codeparm[] は、先ほども出たが make_tree() の中で設
+定されているものだった。出現頻度の低い順で平文の文字コードが入った配列
+だ。
 
 void
 make_code(n, len, code)
 
 void
 make_code(n, len, code)
@@ -3331,23 +3341,23 @@ make_code(n, len, code)
     }
 }
 
     }
 }
 
-# ¸å¤Çµ¤¤¬¤Ä¤¤¤¿¤³¤È¤À¤¬¡¢¤¢¤é¤«¤¸¤áÀßÄꤷ¤Æ¤¤¤¿ codeparm[] ¤ÎÆâÍƤϤ³
-# ¤³¤Ç¤Ï»ÈÍѤµ¤ì¤Ê¤¤¡£¤Ä¤Þ¤ê¡¢codeparm[] ¤ÏÀèÄø¤Ï¥ï¡¼¥¯ÍѤΥХåե¡¤È
-# ¤·¤ÆÍøÍѤµ¤ì¤Æ¤¤¤¿¤¬¡¢¤³¤³¤Ç¤Î codeparm[] ¤Ï½èÍý·ë²Ì¤òɽ¤¹¤È¤¤¤¦Æó¤Ä
-# ¤ÎÌò³ä¤¬¤¢¤ë
+# 後で気がついたことだが、あらかじめ設定していた codeparm[] の内容はこ
+# こでは使用されない。つまり、codeparm[] は先程はワーク用のバッファと
+# して利用されていたが、ここでの codeparm[] は処理結果を表すという二つ
+# の役割がある。これは、領域を節約するための変数の使い回しだ。
 
 
-ºÇ½é¤Î for Ê¸¤Ç¤Ï¡¢ÊÑ¿ô i ¤ËÂФ·¤Æ¡¢weight[i] ¤¬²¼¤Î¤è¤¦¤ËÀßÄꤵ¤ì¤ë
+最初の for 文では、変数 i に対して、weight[i] が下のように設定される
 
   weight[i=1..16] = 2^(16-i)
 
 
   weight[i=1..16] = 2^(16-i)
 
-¤½¤·¤Æ¡¢start[i] ¤Ï¡¢
+そして、start[i] は、
 
   start[1] = 0
   start[n] = start[n-1] + weight[n-1] * len_cnt[n-1]   (n > 1)
 
 
   start[1] = 0
   start[n] = start[n-1] + weight[n-1] * len_cnt[n-1]   (n > 1)
 
-¤È¤¤¤¦Á²²½¼°¤À¡£starr[] ¤Îź»ú i ¤Ï¡¢len_cnt[i](¿¼¤µ i ¤ÎÍդοô)¤Îź»ú
-¤Ç¤â¤¢¤ë¤³¤È¤«¤é¡¢¥Ï¥Õ¥Þ¥óÌڤο¼¤µ¤òɽ¤·¤Æ¤¤¤ë¡£start ¤¬¼ÂºÝ¤Ë¤É¤Î¤è¤¦
-¤ÊÃͤò¼è¤ë¤«¤È¸À¤¦¤È¡¢Î㤨¤Ð len_cnt[i] ¤Î³ÆÍ×ÁǤ¬ Li ¤Ç¤¢¤Ã¤¿¾ì¹ç¡¢
+という漸化式だ。start[] の添字 i は、len_cnt[i](深さ i の葉の数)の添字
+でもあることから、ハフマン木の深さを表している。start が実際にどのよう
+な値を取るかと言うと、例えば len_cnt[i] の各要素が Li であった場合、
 
      i     len_cnt[i]   weight[i]   start[i]
  --------------------------------------------
 
      i     len_cnt[i]   weight[i]   start[i]
  --------------------------------------------
@@ -3356,7 +3366,7 @@ make_code(n, len, code)
      3         L3        2^13      2^15 * L1 + 2^14 * L2
      4         L4        2^12      2^15 * L1 + 2^14 * L2 + 2^13 * L3
 
      3         L3        2^13      2^15 * L1 + 2^14 * L2
      4         L4        2^12      2^15 * L1 + 2^14 * L2 + 2^13 * L3
 
-¤³¤ó¤Ê´¶¤¸¤À¡£¤³¤ì¤Ï¤¤¤Ã¤¿¤¤²¿¤À¤í¤¦¤«¡©Â³¤¯ for Ê¸¤ò¸«¤Æ¤ß¤è¤¦¡£
+こんな感じだ。これはいったい何だろうか?続く for 文を見てみよう。
 
     for (i = 0; i < n; i++) {
         j = len[i];
 
     for (i = 0; i < n; i++) {
         j = len[i];
@@ -3364,9 +3374,9 @@ make_code(n, len, code)
         start[j] += weight[j];
     }
 
         start[j] += weight[j];
     }
 
-¤³¤³¤Ç¤Î i ¤Ï¡¢0...n ¤ÎÈϰϤǤ¢¤ë¤³¤È¤«¤éʿʸ¤Îʸ»ú¤ò¼¨¤¹¡£Ê¶¤é¤ï¤·¤¤
-¤Î¤Ç¡¢i ¤Ï¡¢c ¤Ë½ñ¤­´¹¤¨¡¢j ¤ò i ¤Ë¤·¤è¤¦¡£(¤³¤ì¤Ç¡¢i ¤ÏÁ°¤Î for Ê¸¤Î 
-i ¤ÈƱ¤¸°ÕÌ£¤Ë¤Ê¤ë)
+ここでの i は、0...n の範囲であることから平文の文字を示す。紛らわしい
+ので、i は、c に書き換え、j を i にしよう。(これで、i は前の for 文の 
+i と同じ意味になる)
 
     int c;
 
 
     int c;
 
@@ -3376,10 +3386,10 @@ i 
         start[i] += weight[i];
     }
 
         start[i] += weight[i];
     }
 
-i = len[c] ¤Ïʸ»ú c ¤Î¥Ó¥Ã¥ÈĹ¤Ç¡¢¥Ï¥Õ¥Þ¥óÌڤο¼¤µ¤ò¼¨¤¹¡£
-code[c] ¤Ë¤Ï¡¢start[i] ¤¬ÀßÄꤵ¤ì¤ë¤¬¡¢°ìÅÙ start[i] ¤¬»²¾È¤µ¤ì¤ë¤È
-start[i] ¤Ï¡¢weight[i] ¤ò­¤·¤¿Ãͤ¬¼¡²ó»È¤ï¤ì¤ë¡£Î㤨¤Ð¡¢¤¢¤ëʸ»ú
-a, b, c ¤¬¤½¤ì¤¾¤ì°Ê²¼¤Î¥Ï¥Õ¥Þ¥óÌÚ¤Çɽ¸½¤µ¤ì¤¿¤È¤¹¤ë¡£
+i = len[c] は文字 c のビット長で、ハフマン木の深さを示す。
+code[c] には、start[i] が設定されるが、一度 start[i] が参照されると
+start[i] は、weight[i] を足した値が次回使われる。例えば、ある文字
+a, b, c がそれぞれ以下のハフマン木で表現されたとする。
 
        /\               a: 0
       a /\              b: 10
 
        /\               a: 0
       a /\              b: 10
@@ -3397,7 +3407,7 @@ a, b, c 
   b     2     2         2            2^14      2^15
   c     2     2         2            2^14      2^15 + 2^14
 
   b     2     2         2            2^14      2^15
   c     2     2         2            2^14      2^15 + 2^14
 
-¤³¤ó¤Ê´¶¤¸¤Ë¤Ê¤ë¡£Ê̤ΥϥեޥóÌڤξì¹ç¤â¸«¤Æ¤ß¤è¤¦¡£
+こんな感じになる。別のハフマン木の場合も見てみよう。
 
         /\                a: 00
       /\  /\              b: 01
 
         /\                a: 00
       /\  /\              b: 01
@@ -3417,8 +3427,8 @@ a, b, c 
   c     2     2         4            2^14      2^14 * 2
   d     2     2         4            2^14      2^14 * 3
 
   c     2     2         4            2^14      2^14 * 2
   d     2     2         4            2^14      2^14 * 3
 
-¤³¤ì¤Ç¡¢¥Ô¥ó¥ÈÍè¤ë¤ÈÀ¨¤¤¤Î¤À¤¬ code[c] ¤Ë¤Ïʸ»ú c ¤ËÂбþ¤¹¤ëÉä¹æ²½¤·¤¿
-¥Ó¥Ã¥ÈÎó¤¬ÀßÄꤵ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤³¤È¤Ëµ¤¤Å¤¯¤À¤í¤¦¤«¡©¤Ä¤Þ¤ê¤Ï¡¢
+これで、ピント来ると凄いのだが code[c] には文字 c に対応する符号化した
+ビット列が設定されるようになっていることに気づくだろうか?つまりは、
 
   c  len[c]   i     len_cnt[i]   weight[i]   code[c]
  -----------------------------------------------------------
 
   c  len[c]   i     len_cnt[i]   weight[i]   code[c]
  -----------------------------------------------------------
@@ -3426,33 +3436,33 @@ a, b, c 
   b     2     2         4            2^14  01000000 00000000
   c     2     2         4            2^14  10000000 00000000
   d     2     2         4            2^14  11000000 00000000
   b     2     2         4            2^14  01000000 00000000
   c     2     2         4            2^14  10000000 00000000
   d     2     2         4            2^14  11000000 00000000
-                                           ^^ <- ¥Ï¥Õ¥Þ¥óÉä¹æ
-
-¤À¡£°Ê¹ß¡¢code[] (¼ÂºÝ¤Ë¤Ï codeparm) ¤òÍøÍѤ¹¤ë¤³¤È¤Çɽ°ú¤­¤Çʸ»ú c ¤Ë
-Âбþ¤¹¤ë¥Ï¥Õ¥Þ¥óÉä¹æ¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë(code[c]¤Î¤¦¤Á¾å
-°Ì len[c] ¥Ó¥Ã¥È¤À¤±¤ò¸«¤ë)¡£Éä¹æ²½¤ÎºÝ¤ËÌÚ¤òé¤ëɬÍפϤʤ¯¡¢¹â®¤ÊÉä¹æ
-²½¤¬²Äǽ¤Ë¤Ê¤ë(¤È´üÂÔ¤µ¤ì¤ë¡£¤É¤ÎÄøÅÙ¸ú²Ì¤¬¤¢¤ë¤«¤Ï¤¤¤º¤ì¸¡¾Ú¤·¤Æ¤ß¤¿
-¤¤¡£¤½¤¦¤¤¤¨¤Ð¡¢ÍÕ¤«¤éº¬¤Ë¸þ¤«¤Ã¤ÆÌÚ¤òé¤ë¤¿¤á¤Î¾ðÊó¤¬É¬Íפʤ«¤Ã¤¿¤³¤È
-¤â¤³¤ì¤Ç¤ï¤«¤Ã¤¿)¡£
-
-·ë¶É make_tree(nparm, freqparm, lenparm, codeparm) ¤Ï¡¢lenparm[c] ¤È 
-codeparm[c] ¤òºîÀ®¤¹¤ë´Ø¿ô¤À¤Ã¤¿¤ï¤±¤À(¥Ï¥Õ¥Þ¥óɽ¤È¤Ç¤â¸À¤¦¤Î¤À¤í¤¦
-¤«¡©)¡£¼Â¤Ï¡¢¤³¤Î¤³¤È¤Ï make_tree() ¤ò¸Æ¤Ó½Ð¤·¡¢ codeparm ¤ò»ÈÍѤ·¤Æ¤¤
-¤ë²Õ½ê(huf.c)¤ò¸«¤ë¤Þ¤Ç¤Þ¤ë¤Ç¤ï¤«¤é¤Ê¤«¤Ã¤¿¡£¤·¤«¤â¡¢¤Þ¤À¤Á¤ã¤ó¤ÈÍý²ò
-¤·¤¿¤ï¤±¤Ç¤Ï¤Ê¤¤¡£
-
-¤Õ¤È»×¤Ã¤¿¤Î¤À¤¬¡¢¾åµ­¤ÎɽºîÀ®¤Ïʸ»ú¥³¡¼¥É½ç¤Ë°Í¸¤·¤Æ¤¤¤ë(¥³¡¼¥É¤Î¼ã
-¤¤Êý¤¬º¸¤Î»Ò¤Ë¤Ê¤ë)¤¬¡¢ÌÚ¤òºîÀ®¤¹¤ë¾ì¹ç¤Ï¤½¤Î¤è¤¦¤Ê¤³¤È¤Ï¤Ê¤«¤Ã¤¿¤Ï¤º
-¤À¡£¥Ï¥Õ¥Þ¥óÌÚ¤òé¤Ã¤¿¾ì¹ç¤Èɽ¤ò»²¾È¤·¤¿¾ì¹ç¤È¤Ç¤ÏÆÀ¤é¤ì¤ëÉä¹æ¸ì¤Ï°Û¤Ê
-¤ë¤Î¤Ç¤Ï¤Ê¤¤¤À¤í¤¦¤«¡©¤È¤¤¤¦¤³¤È¤Ï°µ½Ìʸ¤ËËä¤á¹þ¤Þ¤ì¤ë¤Î¤ÏÌڤǤϤʤ¯¤³
-¤Îɽ¤ÎÊý¤À¤È¤¤¤¦¤³¤È¤âÁÛÁü¤¬¤Ä¤¯¡£Ìڤι½Â¤¤òɽ¤¹ left[]¡¢right[] ¤Ï¥°
-¥í¡¼¥Ð¥ëÊÑ¿ô¤À¤¬¡¢¼ÂºÝ¤Ë¤Ï make_tree() Æâ¤Ç¤·¤«»È¤ï¤ì¤Ê¤¤¤Î¤«¤âÃΤì¤Ê
-¤¤(¾¯¤Ê¤¯¤È¤âÉä¹æ²½¤Ë´Ø¤·¤Æ¤Ï¤½¤Î¤è¤¦¤À¡£huf.c ¤òį¤á¤ë¤È¤É¤¦¤ä¤éÉü¹æ
-»þ¤Ï left[]¡¢right[]¤Ï»È¤ï¤ì¤ë¤é¤·¤¤)¡£
-
-¤µ¤é¤Ë¤Õ¤È»×¤¤ÉÕ¤¤¤¿¡£Ææ¤Î (C) ¤Î¥³¡¼¥É¤À¤¬ ¿¼¤µ 17 °Ê¾å¤ÎÌÚ¤¬ºîÀ®¤µ¤ì
-¤¿¾ì¹ç¤ËÌÚ¤òºÆ¹½ÃÛ¤¹¤ë½èÍý¤À¤È¤¤¤¦¤³¤È¤¬¤ï¤«¤Ã¤¿¡£ºÇ½é¡¢len_cnt[] (¤¢
-¤ë¿¼¤µ¤ÎÍդοô) ¤À¤±¤¬¡¢Áàºî¤µ¤ì¤Æ¤¤¤¿¤«¤é¤è¤¯¤ï¤«¤é¤Ê¤«¤Ã¤¿¤Î¤À¡¢
+                                           ^^ <- ハフマン符号
+
+だ。以降、code[] (実際には codeparm) を利用することで表引きで文字 c に
+対応するハフマン符号を得ることができるようになっている(code[c]のうち上
+位 len[c] ビットだけを見る)。符号化の際に木を辿る必要はなく、高速な符号
+化が可能になる(と期待される。どの程度効果があるかはいずれ検証してみた
+い。そういえば、葉から根に向かって木を辿るための情報が必要なかったこと
+もこれでわかった)。
+
+結局 make_tree(nparm, freqparm, lenparm, codeparm) は、lenparm[c] と 
+codeparm[c] を作成する関数だったわけだ(ハフマン表とでも言うのだろう
+か?)。実は、このことは make_tree() を呼び出し、 codeparm を使用してい
+る箇所(huf.c)を見るまでまるでわからなかった。しかも、まだちゃんと理解
+したわけではない。
+
+ふと思ったのだが、上記の表作成は文字コード順に依存している(コードの若
+い方が左の子になる)が、木を作成する場合はそのようなことはなかったはず
+だ。ハフマン木を辿った場合と表を参照した場合とでは得られる符号語は異な
+るのではないだろうか?ということは圧縮文に埋め込まれるのは木ではなくこ
+ã\81®è¡¨ã\81®æ\96¹ã\81 ã\81¨ã\81\84ã\81\86ã\81\93ã\81¨ã\82\82æ\83³å\83\8fã\81\8cã\81¤ã\81\8fã\80\82æ\9c¨ã\81®æ§\8bé\80 ã\82\92表ã\81\99 left[]ã\80\81right[] ã\81¯ã\82°
+ローバル変数だが、実際には make_tree() 内でしか使われないのかも知れな
+い(少なくとも符号化に関してはそのようだ。huf.c を眺めるとどうやら復号
+時は left[]、right[]は使われるらしい)。
+
+さらにふと思い付いた。謎の (C) のコードだが 深さ 17 以上の木が作成され
+た場合に木を再構築する処理だということがわかった。最初、len_cnt[] (あ
+る深さの葉の数) だけが、操作されていたからよくわからなかったのだ、
 
     /* (C) */
     /* adjust len */
 
     /* (C) */
     /* adjust len */
@@ -3470,8 +3480,8 @@ codeparm[c] 
         } while (--cum);
     }
 
         } while (--cum);
     }
 
-¿¼¤µ n ¤ÎÍդοô¤ò 1 ¤Ä¸º¤é¤·¤Æ¡¢¤½¤Î²¼¤ÎÍդοô¤ò 2 Â­¤·¤Æ¤¤¤ë¡£
-¤³¤ì¤¬¡¢cum ¤Î¿ô¤À¤±·«¤êÊÖ¤µ¤ì¤ë¡£Î㤨¤Ð¡¢Á°¤Ë¤â½Ð¤¿
+深さ i の葉の数を 1 つ減らして、その下の葉の数を 2 足している。
+これが、cum の数だけ繰り返される。例えば、前にも出た
 
                                                      :
                    n /\       .. len_cnt[14] = 0000000000000001
 
                                                      :
                    n /\       .. len_cnt[14] = 0000000000000001
@@ -3481,7 +3491,7 @@ codeparm[c] 
                                                  vvvvvvvvvvvvvvvv
                                            cum = 0000000000000001
 
                                                  vvvvvvvvvvvvvvvv
                                            cum = 0000000000000001
 
-¤ÎÎã¤Ç¤Ï¡¢ºÇ½é¤Ë len_cnt[16] ¤«¤é cum {1} ¤¬°ú¤«¤ì¡¢
+の例では、最初に len_cnt[16] から cum {1} が引かれ、
 
                                                      :
                    n /\       .. len_cnt[14] = 0000000000000001
 
                                                      :
                    n /\       .. len_cnt[14] = 0000000000000001
@@ -3489,7 +3499,7 @@ codeparm[c] 
                      p /       .. len_cnt[16] = 0000000000000010
                       q
 
                      p /       .. len_cnt[16] = 0000000000000010
                       q
 
-³¤¤¤Æ¡¢¿¼¤µ 15 ¤è¤ê¾å¤ÎÍդΤ¢¤ëÀᤫ¤é 1 ¤Ä»Ò¤ò¼è¤ê¡¢
+続いて、深さ 15 より上の葉のある節から 1 つ子を取り、
 
                                                      :
                    n /\       .. len_cnt[14] = 0000000000000001
 
                                                      :
                    n /\       .. len_cnt[14] = 0000000000000001
@@ -3497,7 +3507,7 @@ codeparm[c] 
                      p /        .. len_cnt[16] = 0000000000000010
                       q
 
                      p /        .. len_cnt[16] = 0000000000000010
                       q
 
-²¼¤ÎÍդοô(¤³¤ÎÎã¤Ç¤Ï¡¢len_cnt[16])¤ò 2 Â­¤·¤Æ¤¤¤ë¡£
+下の葉の数(この例では、len_cnt[16])を 2 足している。
 
                 /   \
               n    /  \       .. len_cnt[14] = 0000000000000001
 
                 /   \
               n    /  \       .. len_cnt[14] = 0000000000000001
@@ -3505,27 +3515,27 @@ codeparm[c] 
                 o  r  p /       .. len_cnt[16] = 0000000000000100
                        q
 
                 o  r  p /       .. len_cnt[16] = 0000000000000100
                        q
 
-cum ¤Ï¡¢¤³¤ÎÎã¤Ç¤Ï 0 ¤Ë¤Ê¤ë¤Î¤Ç¡¢¤³¤ì¤ÇÌÚ¤ÎÊ¿³ê²½¤Ï½ª¤ë¡£¥Æ¥­¥¹¥È¤À¤È
-¤Á¤ç¤Ã¤È¸«¤Ë¤¯¤¤¤¬¡¢¤½¤¦¤¤¤¦½èÍý¤È¤¤¤¦¤³¤È¤Ç´Ö°ã¤¤¤Ê¤¤¤À¤í¤¦¡£
-lenparm[] ¤ÎÃͤϤ³¤Î¸å¤Î (D) ¤Ç¡¢¤³¤ÎÌÚ¤ò¸µ¤Ë·×»»¤µ¤ì¤Æ¤¤¤ë¡£
+cum は、この例では 0 になるので、これで木の平滑化は終る。テキストだと
+ちょっと見にくいが、そういう処理ということで間違いないだろう。
+lenparm[] の値はこの後の (D) で、この木を元に計算されている。
 
 
-¤È¤³¤í¤Ç¡¢ËÜÅö¤Î½ê¤Ï°Ê²¼¤Î¤è¤¦¤Êʸ»ú¤ÎÂбþ¤Ë¤Ê¤ë(ɽ¤òºîÀ®¤¹¤ë¤È¤­¤Ëʸ
-»ú¥³¡¼¥É½ç¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¿¤á)¤Î¤À¤¬¡¢·ë²ÌŪ¤Ë¸µ¤ÎÌÚ¤«¤é p ¤ò´Þ¤àÀá¤ò¼è¤ê
-½ü¤­ o ¤Î°ÌÃÖ¤ËÁÞÆþ¤¹¤ë½èÍý¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£¤Ê¤ó¤À¤«ÌÌÇò¤¤¡£
+ところで、本当の所は以下のような文字の対応になる(表を作成するときに文
+字コード順になっているため)のだが、結果的に元の木から p を含む節を取り
+除き o の位置に挿入する処理になっている。なんだか面白い。
 
                 /   \
               n    /  \       .. len_cnt[14] = 0000000000000001
                  /\    /\      .. len_cnt[15] = 0000000000000000
                 o  p  q  r      .. len_cnt[16] = 0000000000000100
 
 
                 /   \
               n    /  \       .. len_cnt[14] = 0000000000000001
                  /\    /\      .. len_cnt[15] = 0000000000000000
                 o  p  q  r      .. len_cnt[16] = 0000000000000100
 
-ʸ»ú¤«¤é Huffman Éä¹æ¤¬ÆÀ¤é¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¤Î¤Ç¡¢°µ½Ì½èÍý¤ò¹Ô¤¦Æ»¶ñ¤Ï
-·¤Ã¤¿¡£¤¤¤è¤¤¤è Huffman Ë¡¤Ë¤è¤ë°µ½Ì½èÍýÁ´ÈÌ (huf.c) ¤ò¸«¤ë¤³¤È¤Ë¤·¤è
-¤¦¡£
+文字から Huffman 符号が得られるようになったので、圧縮処理を行う道具は
+揃った。いよいよ Huffman 法による圧縮処理全般 (huf.c) を見ることにしよ
+う。
 
 
-¤Þ¤º huf.c ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥Ç¡¼¥¿¹½Â¤¤«¤é³Îǧ¤·¤è¤¦¡£¥Ç¡¼¥¿¹½Â¤¤¬¤ï¤«¤Ã
-¤Æ¤·¤Þ¤¨¤Ð¥¢¥ë¥´¥ê¥º¥à¤Î 90% ¤Ï¤ï¤«¤Ã¤¿¤âƱÁ³¤À(¸ØÄ¥)¡£
+まず huf.c で定義されているデータ構造から確認しよう。データ構造がわかっ
+てしまえばアルゴリズムの 90% はわかったも同然だ(誇張)。
 
 
-huf.c ¤Ë¤Ï°Ê²¼¤ÎÊÑ¿ô¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£
+huf.c には以下の変数が定義されている。
 
 unsigned short  left[2 * NC - 1], right[2 * NC - 1];
 unsigned char   c_len[NC], pt_len[NPT];
 
 unsigned short  left[2 * NC - 1], right[2 * NC - 1];
 unsigned char   c_len[NC], pt_len[NPT];
@@ -3539,7 +3549,7 @@ static unsigned short output_pos, output_mask;
 static          int   pbit;
 static          int   np;
 
 static          int   pbit;
 static          int   np;
 
-»ÈÍѤµ¤ì¤Æ¤¤¤ëÄê¿ô¤â³Îǧ¤¹¤ë lha_macro.h ¤À¡£
+使用されている定数も確認する lha_macro.h だ。
 
 #define NP          (MAX_DICBIT + 1)
 #define NT          (USHRT_BIT + 3)
 
 #define NP          (MAX_DICBIT + 1)
 #define NT          (USHRT_BIT + 3)
@@ -3550,37 +3560,41 @@ static          int   np;
 #define NPT         0x80
 #define CBIT                9   /* $\lfloor \log_2 NC \rfloor + 1$ */
 
 #define NPT         0x80
 #define CBIT                9   /* $\lfloor \log_2 NC \rfloor + 1$ */
 
-¤¿¤¯¤µ¤ó¤¢¤ë¡£¤¿¤¯¤µ¤ó¤¢¤ê¤¹¤®¤Æ¤¯¤¸¤±¤½¤¦¤À¤¬(»ö¼Â¡¢¤¯¤¸¤±¤¿)¡¢¸½»þÅÀ
-¤Ç¤ï¤«¤ëÊÑ¿ô¤â¤¢¤ë¡£left[] ¤ä right[] ¤Ï Huffman ÌÚ¤ò¹½ÃÛ¤¹¤ë¤Î¤Ë»ÈÍÑ
-¤·¤¿ÊÑ¿ô¤À¤Ã¤¿¡£¤½¤³¤«¤é NC ¤Ïʸ»ú¼ï¤ÎºÇÂç¿ô¤Ç¤¢¤ë¤³¤È¤¬¤ï¤«¤ë¡£NC ¤Ë 
-MAXMATCH{256} Åù¤ÎÃͤ¬»ÈÍѤµ¤ì¤Æ¤¤¤ë¤Î¤ÏÆæ¤À¤¬¡¢¸½»þÅÀ¤Ç¤Ï̵»ë¤·¤Æ¤ª¤³
-¤¦¡£
+たくさんある。たくさんありすぎてくじけそうだが(事実、くじけた)、現時点
+でわかる変数もある。left[] や right[] は Huffman 木を構築するのに使用
+した変数だった。そこから NC は文字種の最大数であることがわかる。NC に 
+MAXMATCH{256} 等の値が使用されているのは謎だが、現時点では無視しておこ
+う。
 
 
-c_freq[] ¤ä c_len[], p_freq[], pt_len[] ¤â make_tree() ¤Ç½Ð¤ÆÍ褿ÊÑ¿ô
-̾¤Ë»÷¤Æ¤¤¤ë¡£¤ª¤½¤é¤¯ make_tree() ¤ËÅϤ¹ÊÑ¿ô¤À¤í¤¦¡£³Îǧ¤·¤Æ¤ß¤¿¤È¤³
-¤í huf.c ¤«¤é make_tree() ¤Î¸Æ¤Ó½Ð¤·¤ò¹Ô¤Ã¤Æ¤¤¤ëÉôʬ¤òÈ´¤­½Ð¤¹¤È¡¢
+c_freq[] や c_len[], p_freq[], pt_len[] も make_tree() で出て来た変数
+名に似ている。おそらく make_tree() に渡す変数だろう。確認してみたとこ
+ろ huf.c から make_tree() の呼び出しを行っている部分を抜き出すと、
 
     root = make_tree(NC, c_freq, c_len, c_code);
     root = make_tree(NT, t_freq, pt_len, pt_code);
     root = make_tree(np, p_freq, pt_len, pt_code);
 
 
     root = make_tree(NC, c_freq, c_len, c_code);
     root = make_tree(NT, t_freq, pt_len, pt_code);
     root = make_tree(np, p_freq, pt_len, pt_code);
 
-¤Î 3 ²Õ½ê¤¬½Ð¤ÆÍ褿¡£¤Ä¤Þ¤ê¡¢
+の 3 箇所が出て来た。つまり、
 
 
-   Ê¸»ú¼ï¤Î¿ô  Ê¸»ú¤Î½Ð¸½²ó¿ô   Éä¹æ²½¤·¤¿Ê¸»ú  Ê¸»ú¤ËÂбþ¤¹¤ë
-                                ¤Î bit Ä¹       Huffman Éä¹æɽ
+   文字種の数  文字の出現回数   符号化した文字  文字に対応する
+                                の bit 長       Huffman 符号表
    -----------------------------------------------------------
      NC         c_freq          c_len           c_code
      NT         t_freq          pt_len          pt_code
      np         p_freq          pt_len          pt_code
 
    -----------------------------------------------------------
      NC         c_freq          c_len           c_code
      NT         t_freq          pt_len          pt_code
      np         p_freq          pt_len          pt_code
 
-¤È¤¤¤¦´Ø·¸¤Î¤è¤¦¤À¡£¤É¤¦¤ä¤é c_code¡¢pt_code ¤È¤¤¤¦ 2 ¼ïÎà¤Î
-Huffman Éä¹æɽ¤ò»ÈÍѤ¹¤ë¤é¤·¤¤¡£
+という関係のようだ。どうやら c_code、pt_code という 2 種類の
+Huffman 符号表を使用するらしい。
 
 
-¤½¤Î¾¤ÎÊÑ¿ô¤Ë´Ø¤·¤Æ¤âͽÁÛ¤òΩ¤Æ¤¿¤¤½ê¤À¤¬¡¢¤â¤¦¤¯¤¸¤±¤¿¤Î¤Ç¡¢½èÍýÆâÍÆ
-¤«¤é¹¶¤á¤ë¤³¤È¤Ë¤·¤¿¡£
+# あとでわかることだが実際は 3 種類の Huffman 符号表を作っており
+# pt_code は変数が使い回しされている。変数の使用領域を減らし
+# たかったのだろう。
 
 
-slide ¼­½ñË¡¤Î²òÆɤǠHuffman Ë¡¤Ë´ØÏ¢¤·¤¿½èÍý¤Î¸Æ¤Ó½Ð¤·¤¬¤¤¤¯¤Ä¤«¤¢¤Ã
-¤¿¡£
+その他の変数に関しても予想を立てたい所だが、もうくじけたので、処理内容
+から攻めることにした。
+
+slide 辞書法の解読で Huffman 法に関連した処理の呼び出しがいくつかあっ
+た。
 
     /* initialize */
     alloc_buf()
 
     /* initialize */
     alloc_buf()
@@ -3595,8 +3609,8 @@ slide 
     decode_set.decode_c()
     decode_set.decode_p()
 
     decode_set.decode_c()
     decode_set.decode_p()
 
-°Ê¾å¤À¡£lh4, 5, 6, 7 ¤Ç¤Ï¡¢¾åµ­¤Î¤½¤ì¤¾¤ì¤Ï¡¢huf.c ¤Î°Ê²¼¤Î´Ø¿ô¤Î¸Æ¤Ó
-½Ð¤·¤ËÂбþ¤·¤Æ¤¤¤ë¡£¤³¤ì¤Ï¡¢slide.c ¤ÎËÁƬÉôʬ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£
+以上だ。lh4, 5, 6, 7 では、上記のそれぞれは、huf.c の以下の関数の呼び
+出しに対応している。これは、slide.c の冒頭部分で定義されている。
 
     /* encoder */
     encode_start() -> encode_start_st1()
 
     /* encoder */
     encode_start() -> encode_start_st1()
@@ -3608,9 +3622,9 @@ slide 
     decode_c()     -> decode_c_st1()
     decode_p()     -> decode_p_st1()
 
     decode_c()     -> decode_c_st1()
     decode_p()     -> decode_p_st1()
 
-¤³¤Î¤¦¤Á¤Î°µ½Ì½èÍý¤Ë¤¢¤¿¤ëÉôʬ encode_start_st1(), output_st1(),
-encode_end_st1() ¤ò¸«¤Æ¤¤¤³¤¦¡£¤Þ¤º¤Ï¡¢½é´ü²½½èÍý¤Ç¤¢¤ë 
-encode_start_st1() ¤«¤é¡¢
+このうちの圧縮処理にあたる部分 encode_start_st1(), output_st1(),
+encode_end_st1() を見ていこう。まずは、初期化処理である 
+encode_start_st1() から、
 
 void
 encode_start_st1( /* void */ )
 
 void
 encode_start_st1( /* void */ )
@@ -3637,9 +3651,9 @@ encode_start_st1( /* void */ )
     buf[0] = 0;
 }
 
     buf[0] = 0;
 }
 
-dicbit (¤³¤ì¤Ï¼­½ñ¤Î bit ¥µ¥¤¥º¤À¤Ã¤¿)¤Ë¤è¤Ã¤Æ¡¢np, pbit ¤ÎÃͤ¬ÊѤï¤ë¡£
-dicbit ¤Î°ã¤¤¤È¤¤¤¦¤Î¤Ï LHa ¤Î encoding ¥á¥½¥Ã¥É¤Î°ã¤¤¤À¡£¤½¤ì¤¾¤ì°Ê²¼
-¤ÎÂбþ¤Ë¤Ê¤ë¡£
+dicbit (これは辞書の bit サイズだった)によって、np, pbit の値が変わる。
+dicbit の違いというのは LHa の encoding メソッドの違いだ。それぞれ以下
+の対応になる。
 
     method  dicbit  np  pbit
    --------------------------
 
     method  dicbit  np  pbit
    --------------------------
@@ -3648,27 +3662,27 @@ dicbit 
     -lh6-   15      16  5
     -lh7-   16      17  5
 
     -lh6-   15      16  5
     -lh7-   16      17  5
 
-np ¤È¤¤¤¦¤Î¤Ï¡¢ÀèÄø make_tree() ¤ò¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë²Õ½ê¤ÎÀö¤¤½Ð¤·¤Ç¸«¤«¤±
-¤¿ÊÑ¿ô¤À¤Ã¤¿¡£¤Þ¤À¡¢¤³¤Î´ØÏ¢¤Ï¤è¤¯¤ï¤«¤é¤Ê¤¤¡£
+np というのは、先程 make_tree() を呼び出している箇所の洗い出しで見かけ
+た変数だった。まだ、この関連はよくわからない。
 
 
-½èÍý¤Î¸åȾ¤Ç¤Ï¡¢Ê¸»ú¤Î½Ð¸½ÉÑÅÙ¤òɽ¤¹ c_freq[]¡¢p_freq[] ¤Î½é´ü²½¤ò
-¹Ô¤Ã¤Æ¤¤¤ë¡£¤µ¤é¤Ë
+処理の後半では、文字の出現頻度を表す c_freq[]、p_freq[] の初期化を
+行っている。さらに
 
     output_pos
     output_mask
     buf[]
 
 
     output_pos
     output_mask
     buf[]
 
-¤È¤¤¤¦½é½Ð¤ÎÊÑ¿ô¤â 0 ¤Ë½é´ü²½¤·¤Æ¤¤¤ë¡£(buf ¤Ï¡¢buf[0] ¤Î¤ß½é´ü²½¤·¤Æ
-¤¤¤ë) init_putbits() ¤Î¸Æ¤Ó½Ð¤·¤Ï bit ½ÐÎϥ롼¥Á¥ó¤Î½é´ü²½½èÍý¤À¤Ã¤¿¡£
-°Ê¹ß¡¢putbits(), putcode() ¤ò»ÈÍѤǤ­¤ë¡£
+という初出の変数も 0 に初期化している。(buf は、buf[0] のみ初期化して
+いる) init_putbits() の呼び出しは bit 出力ルーチンの初期化処理だった。
+以降、putbits(), putcode() を使用できる。
 
 
-¼¡¤Ë output_st1(c, p) ¤ò¸«¤ë¡£slide.c ¤Ç¤³¤Î´Ø¿ô¤Ï°Ê²¼¤Î¤è¤¦¤Ë»ÈÍѤµ¤ì
-¤Æ¤¤¤¿¡£
+次に output_st1(c, p) を見る。slide.c でこの関数は以下のように使用され
+ていた。
 
 
-        output_st1(c, 0)        Ê¸»ú c ¤ò½ÐÎÏ
-        output_st1(len, off)    <len, off> ¤Î¥Ú¥¢¤ò½ÐÎÏ
+        output_st1(c, 0)        文字 c を出力
+        output_st1(len, off)    <len, off> のペアを出力
 
 
-¤³¤Î¤³¤È¤òƧ¤Þ¤¨¤¿¾å¤Ç¡¢½èÍýÆâÍƤò¸«¤Æ¤ß¤è¤¦¡£
+このことを踏まえた上で、処理内容を見てみよう。
 
 void
 output_st1(c, p)
 
 void
 output_st1(c, p)
@@ -3707,14 +3721,14 @@ output_st1(c, p)
     }
 }
 
     }
 }
 
-(A) ¤Ï¡¢output_mask ¤ÎÃͤ˱þ¤¸¤Æ½èÍý¤ò¹Ô¤¦¤è¤¦¤À¡£½é´ü²½¤Ç output_mask 
-¤Ï 0 ¤À¤«¤é (A) ¤Î½èÍý¤ÏºÇ½é¤«¤é¼Â¹Ô¤µ¤ì¤ë¤¬¡¢¤Ò¤È¤Þ¤ºÌµ»ë¤·¤è¤¦¡£
+(A) は、output_mask の値に応じて処理を行うようだ。初期化で output_mask 
+は 0 だから (A) の処理は最初から実行されるが、ひとまず無視しよう。
 
 
-(B) ¤Ï¡¢buf ¤Ë°ú¿ô¤ÇÅϤµ¤ì¤¿Ê¸»ú c ¤ò³ÊǼ¤·¡¢c_freq[c] ¤ÎÃÍ(ʸ»ú¤Î½Ð¸½
-ÉÑÅÙ)¤ò­¤·¤Æ¤¤¤ë¡£¤É¤¦¤ä¤é´ðËܤÏÅϤµ¤ì¤¿Ê¸»ú c ¤ò±ä¡¹¤È buf ¤Ë³ÊǼ¤·¡¢
-¸å¤Ç°µ½Ì¤ò¹Ô¤¦(¤ª¤½¤é¤¯ (A) ¤À¤í¤¦)¤è¤¦¤À¡£
+(B) は、buf に引数で渡された文字 c を格納し、c_freq[c] の値(文字の出現
+頻度)を足している。どうやら基本は渡された文字 c を延々と buf に格納し、
+後で圧縮を行う(おそらく (A) だろう)ようだ。
 
 
-¤³¤Î buf ¤Î¥µ¥¤¥º¤Ï¤È¸À¤¦¤È¡¢¤³¤ì¤Ï alloc_buf() ¤Ç³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤¿¡£
+この buf のサイズはと言うと、これは alloc_buf() で割り当てられていた。
 
 unsigned char  *
 alloc_buf( /* void */ )
 
 unsigned char  *
 alloc_buf( /* void */ )
@@ -3728,15 +3742,15 @@ alloc_buf( /* void */ )
     return buf;
 }
 
     return buf;
 }
 
-bufsiz ¤¬ buf ¤Î¥µ¥¤¥º¤é¤·¤¤¡£¤³¤ì¤Ï¤Ç¤­¤ë¤À¤±Â礭¤¯¼è¤ë¤è¤¦¤Ë¤·¤Æ¤¤¤ë
-¤¬¡¢Â礭¤¯¼è¤ì¤Ê¤±¤ì¤Ð¤½¤ì¤Ï¤½¤ì¤ÇÎɤ¤¤è¤¦¤À¡£
+bufsiz が buf のサイズらしい。これはできるだけ大きく取るようにしている
+が、大きく取れなければそれはそれで良いようだ。
 
 
-¤µ¤é¤Ë¡¢(C) ¤Î½èÍý¤ò¹Ô¤¦¤«¤É¤¦¤«¤Ï¡¢c >= (1 << CHAR_BIT) ¤È¤¤¤¦¾ò·ï¤Ç
-ȽÃǤµ¤ì¤Æ¤¤¤ë¡£¤³¤Î¾ò·ï¤¬¿¿¤È¤Ê¤ë¾ì¹ç¤Ï²¿¤«¤È¸À¤¦¤È c ¤¬¡ÖŤµ¡×¤òɽ
-¤¹¾ì¹ç¤À¡£¤³¤Î¤È¤­°ú¿ô p ¤Ç¡Ö°ÌÃ֡פ¬ÅϤµ¤ì¤Æ¤¤¤ë¤Î¤Ç¤³¤ì¤â buf ¤Ë¥»¥Ã
-¥È¤·¤Æ¤¤¤ë¡£¤½¤Î¶ñÂÎŪÆâÍƤϤȤ¤¤¦¤È¡¢²¿¤ä¤é cpos ¤È¤¤¤¦¤³¤Î´Ø¿ôÆâ¤Ç 
-static ¤ÊÊÑ¿ô¤¬»ÈÍѤµ¤ì¤Æ¤¤¤ë¡£¤è¤¯¤ï¤«¤é¤Ê¤¤¤¬Ê¸»ú c ¤ä <len,off> ¤Î
-¥Ú¥¢¤Ï¡¢buf ¾å¤Ç°Ê²¼¤Î¤è¤¦¤Ëɽ¤µ¤ì¤ë¤é¤·¤¤¡£
+さらに、(C) の処理を行うかどうかは、c >= (1 << CHAR_BIT) という条件で
+判断されている。この条件が真となる場合は何かと言うと c が「長さ」を表
+す場合だ。このとき引数 p で「位置」が渡されているのでこれも buf にセッ
+トしている。その具体的内容はというと、何やら cpos というこの関数内で 
+static な変数が使用されている。よくわからないが文字 c や <len,off> の
+ペアは、buf 上で以下のように表されるらしい。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -3744,7 +3758,7 @@ output_st1(c1, 0)
 output_st1(c2, 0)
 output_st1(len, off)
 
 output_st1(c2, 0)
 output_st1(len, off)
 
-¤È¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Î buf ¤Î¾õÂÖ
+と呼び出した場合の buf の状態
 
     +-----+-----+-----+-----+-----+
 buf | c1  | c2  | len |    off    |
 
     +-----+-----+-----+-----+-----+
 buf | c1  | c2  | len |    off    |
@@ -3752,7 +3766,7 @@ buf | c1  | c2  | len |    off    |
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-(C) ¤Î½èÍý¤ÎºÇ¸å¤ÎÉôʬ
+(C) の処理の最後の部分
 
         c = 0;
         while (p) {
 
         c = 0;
         while (p) {
@@ -3761,25 +3775,25 @@ buf | c1  | c2  | len |    off    |
         }
         p_freq[c]++;
 
         }
         p_freq[c]++;
 
-¤Ï¡¢½Ð¸½ÉÑÅÙ p_freq[] ¤òµá¤á¤ë½èÍý¤À¤¬¡¢p_freq ¤Ï¡¢off Ãͤνи½ÉÑÅÙ¤ò
-ɽ¤·¤Æ¤¤¤ë¤é¤·¤¤¡£¤³¤³¤Ç¤Î c ¤Ï¡¢p (off) ¤Î bit Ä¹¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£off ¤Î
-ÃͤÏÂ礭¤¤(¼­½ñ¥µ¥¤¥º¤À¤«¤éºÇÂç(lh7)¤Ç¡¢64KB)¤Î¤Ç¡¢Âå¤ï¤ê¤Ë bit Ä¹¤òÍø
-ÍѤ·¤Æ¤¤¤ë¤È¤¤¤Ã¤¿¤È¤³¤í¤«¡£¤½¤¦¤¤¤¨¤Ð¡¢np ¤È¤¤¤¦ÊÑ¿ô¤¬¤¢¤ê¡¢
-make_tree() ¤ÎÂè°ì°ú¿ô¤ËÅϤµ¤ì¤ë¤³¤È¤«¤é¡¢¤³¤ì¤Ï¡¢p_freq[] ¤ÎÍ×ÁÇ¿ô¤ò
-ɽ¤¹¡£p_freq[] ¤ÎÍ×ÁÇ¿ô¤È¤Ï¡¢<off> ¤Î bit Ä¹¤ÎºÇÂçÃÍ+1¤Ê¤Î¤Ç¡¢lh7 ¤Ç¡¢
-64KB¡£¤Ä¤Þ¤ê 16 bit + 1 ¤¬ np ¤Ë¤Ê¤ë¡£
+は、出現頻度 p_freq[] を求める処理だが、p_freq は、off 値の出現頻度を
+表しているらしい。ここでの c は、p (off) の bit 長になっている。off の
+値は大きい(辞書サイズだから最大(lh7)で、64KB)ので、代わりに bit 長を利
+用しているといったところか。そういえば、np という変数があり、
+make_tree() の第一引数に渡されることから、これは、p_freq[] の要素数を
+表す。p_freq[] の要素数とは、<off> の bit 長の最大値+1なので、lh7 で、
+64KB。つまり 16 bit + 1 が np になる。
 
 
-¤Ä¤¤¤Ç¤Ë¸À¤¦¤È¡¢¡ÖŤµ¡×¤Ï¤½¤Î¤Þ¤Þ c_freq[] ¤ÇÉÑÅÙ¤¬·×¾å¤µ¤ì¤Æ¤¤¤¿¡£Æ±
-¤¸¤¯ make_tree() ¤ÎÂè°ì°ú¿ô¤ËÅϤµ¤ì¤ë NC ¤ÎÃͤ¬
+ついでに言うと、「長さ」はそのまま c_freq[] で頻度が計上されていた。同
+じく make_tree() の第一引数に渡される NC の値が
 
 #define NC          (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
 
 
 #define NC          (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
 
-¤Ê¤Î¤Ï¡¢¤½¤¦¤¤¤¦¤³¤È¤À(Ťµ¤ò¹Í¤¨¤Ê¤±¤ì¤Ðʸ»ú¤ÎºÇÂçÃÍ{255}+1¤È¤Ê¤ë¤È¤³
-¤í¤À¤¬¡¢Ä¹¤µ¤ÎºÇÂçÃͤ¬¡¢256 + MAXMATCH - THRESHOLD ¤À¤«¤é¾å¤Î¼°¤Ë¤Ê¤Ã
-¤Æ¤¤¤ë¤Î¤À¤í¤¦¤È»×¤¦¡£¤Á¤ç¤Ã¤È¤ï¤«¤ê¤Ë¤¯¤¤¤¬)
+なのは、そういうことだ(長さを考えなければ文字の最大値{255}+1となるとこ
+ろだが、長さの最大値が、256 + MAXMATCH - THRESHOLD だから上の式になっ
+ているのだろうと思う。ちょっとわかりにくいが)
 
 
-¤³¤³¤Þ¤Ç¤Ç¡¢°µ½Ì¤ò¹Ô¤¦½èÍý¤Ï¸½¤ï¤ì¤Ê¤«¤Ã¤¿¡£¤ä¤Ï¤ê (A) ¤ÎÉôʬ¤¬°µ½Ì½è
-Íý¤À¡£
+ここまでで、圧縮を行う処理は現われなかった。やはり (A) の部分が圧縮処
+理だ。
 
     /* (A) */
     output_mask >>= 1;
 
     /* (A) */
     output_mask >>= 1;
@@ -3795,20 +3809,20 @@ make_tree() 
         buf[cpos] = 0;
     }
 
         buf[cpos] = 0;
     }
 
-ºÇ½é¡¢output_mask ¤Ï¡¢0 ¤Ê¤Î¤Ç if ¾ò·ï¤òËþ¤¿¤¹¡£¤½¤·¤Æ¡¢output_mask ¤Ï¡¢
-(1 << (CHAR_BIT - 1)) ¤Ä¤Þ¤ê¡¢128 ¤Ë¤Ê¤ë¡£(A) ¤ÎËÁƬ¤Ç¡¢>>= 1 ¤·¤Æ¤¤¤ë
-¤Î¤Ç¡¢output_mask ¤Ï¡¢128, 64, 32, ..., 1, 128 ¤È¤¤¤¦Ãͤò¼è¤ë¤é¤·¤¤¡£¤½
-¤·¤Æ¡¢ËÜÅö¤Î½é´üÃͤϠ128 ¤À¡£
+最初、output_mask は、0 なので if 条件を満たす。そして、output_mask は、
+(1 << (CHAR_BIT - 1)) つまり、128 になる。(A) の冒頭で、>>= 1 している
+ので、output_mask は、128, 64, 32, ..., 1, 128 という値を取るらしい。そ
+して、本当の初期値は 128 だ。
 
 
-¼¡¤Î¾ò·ï
+次の条件
 
   output_pos >= bufsiz - 3 * CHAR_BIT
 
 
   output_pos >= bufsiz - 3 * CHAR_BIT
 
-¤È¤¤¤¦¤Î¤Ï¡¢buf ¤¬ bufsiz - 24 ¤è¤ê¤âÂ礭¤¯¤Ê¤Ã¤¿¤È¤­¤ÎÃͤÀ¡£¤Ò¤È¤Þ¤º
-̵»ë¤·¤è¤¦¡£¤½¤·¤Æ¡¢cpos = output_pos++ ¤È¤·¤Æ¡¢buf[cpos] = 0 ¤Ë¥»¥Ã¥È
-¤µ¤ì¤Æ¤¤¤ë¡£¤É¤¦¤ä¤é¡¢Àè¤Ë¤³¤Á¤é¤ò¸«¤ë¤Ù¤­¤À¤Ã¤¿¤è¤¦¤À¡£cpos ¤ÎÃÍ
-¤È output_pos++ ¤¬ (A) ¤Ç¹Ô¤ï¤ì¤Æ¤¤¤ë¤³¤È¤òƧ¤Þ¤¨¤Æ¤â¤¦°ìÅÙ (B)¡¢(C)
-¤Î½èÍý¤ò¸«¤ë¤È¡¢buf ¤Ï°Ê²¼¤Î¤è¤¦¤Ë»ÈÍѤµ¤ì¤Æ¤¤¤ë¤é¤·¤¤¡£
+というのは、buf が bufsiz - 24 よりも大きくなったときの値だ。ひとまず
+無視しよう。そして、cpos = output_pos++ として、buf[cpos] = 0 にセット
+されている。どうやら、先にこちらを見るべきだったようだ。cpos の値
+と output_pos++ が (A) で行われていることを踏まえてもう一度 (B)、(C)
+の処理を見ると、buf は以下のように使用されているらしい。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -3816,7 +3830,7 @@ output_st1(c1, 0)
 output_st1(c2, 0)
 output_st1(len, off)
 
 output_st1(c2, 0)
 output_st1(len, off)
 
-¤È¸Æ¤Ó½Ð¤·¤¿¾ì¹ç¤Î buf ¤Î¾õÂÖ
+と呼び出した場合の buf の状態
 
 
     +-----+-----+-----+-----+-----+-----+--
 
 
     +-----+-----+-----+-----+-----+-----+--
@@ -3826,18 +3840,18 @@ buf |  32 | c1  | c2  | len |    off    |  ...
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-<len, off> ¤Î¥Ú¥¢¤ò½ÐÎϤ¹¤ë¤È¤­ buf[cpos] ¤Ë¤Ï°Ê²¼¤Î¤è¤¦¤ÊÃͤ¬ÀßÄꤵ¤ì
-¤Æ¤¤¤¿¤³¤È¤â¿Þ¤Ë½ñ¤¤¤Æ¤¢¤ë¡£
+<len, off> のペアを出力するとき buf[cpos] には以下のような値が設定され
+ていたことも図に書いてある。
 
         buf[cpos] |= output_mask;
 
 
         buf[cpos] |= output_mask;
 
-¤â¤¦¾¯¤·Ãí°Õ¿¼¤¯¤³¤Î¤¢¤¿¤ê¤ò¹Í¤¨¤è¤¦¡£output_mask ¤Ï¡¢¤³¤Î´Ø¿ô¤¬¸Æ¤Ð¤ì
-¤ë¤¿¤Ó¤Ë 128, 64, 32, ..., 1, 128, 64, ... ¤È¤¤¤¦Ãͤˤʤ롣¤½¤·¤Æ¡¢buf 
-¤Ï¡¢¸Æ¤Ð¤ì¤ë¤¿¤Ó¤Ë c (1¥Ð¥¤¥È)¡¢¤¢¤ë¤¤¤Ï <len, off> (3¥Ð¥¤¥È)¤ÎÃͤ¬Àß
-Äꤵ¤ì¤ë¤¬¡¢output_mask ¤¬ 128 ¤Ë¤Ê¤Ã¤¿¤È¤­¤Ï¡¢Í¾Ê¬¤Ë 1 ¥Ð¥¤¥È¶õ¤­¤¬¤Ç
-¤­¤ë(¤³¤ì¤Ï¡¢buf[cpos]¤Ç¼¨¤µ¤ì¤ë)¡£¤³¤Î¶õ¤­¤Ë¤Ï <len,off> ¤¬ÀßÄꤵ¤ì¤ë
-¤¿¤Ó¤Ë¤½¤Î»þÅÀ¤Î output_mask Ãͤ¬ÀßÄꤵ¤ì¤ë¤è¤¦¤À¡£(A) ¤¬¸Æ¤Ð¤ì¤ë¤È¤­
-¤È¸À¤¦¤Î¤Ï¡¢°ìÈֺǽé¤Î output_mask = 0 ¤Î¾ì¹ç¤ò½ü¤±¤Ð¡¢
+もう少し注意深くこのあたりを考えよう。output_mask は、この関数が呼ばれ
+るたびに 128, 64, 32, ..., 1, 128, 64, ... という値になる。そして、buf 
+は、呼ばれるたびに c (1バイト)、あるいは <len, off> (3バイト)の値が設
+定されるが、output_mask が 128 になったときは、余分に 1 バイト空きがで
+きる(これは、buf[cpos]で示される)。この空きには <len,off> が設定される
+たびにその時点の output_mask 値が設定されるようだ。(A) が呼ばれるとき
+と言うのは、一番最初の output_mask = 0 の場合を除けば、
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
@@ -3852,10 +3866,11 @@ buf     | 40 | c1 | c2 |len |   off   | c4 |len |   off   | c6 | c7 | c8 |
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤Î¤è¤¦¤Ê¾õÂ֤ˤʤ俤Ȥ­¤È¤¤¤¦¤³¤È¤À¡£¤µ¤é¤Ë¡¢buf[cpos] ¤Ë¤Ï¡¢
-<len,off> ¤¬³ÊǼ¤µ¤ì¤Æ¤¤¤ë°ÌÃÖ¤òɽ¤·¤Æ¤¤¤ë¡£¤³¤Î¾õÂÖ¤ò 1 ¥Ö¥í¥Ã¥¯¤È¤·
-¤Æ¤³¤Î¥Ö¥í¥Ã¥¯Ã±°Ì¤Ë¾ðÊ󤬠buf ¤Ë³ÊǼ¤µ¤ì¡¢buf ¤¬¤¤¤Ã¤Ñ¤¤¤Ë¤Ê¤Ã¤¿¤é 
-(A) ¤Î½èÍý¤Î̵»ë¤·¤¿if Ê¸¤ÎÃæ¿È¤Ç
+このような状態になったときということだ。さらに、buf[cpos] には、
+<len,off> が格納されている位置を表している。この状態を 1 セグメントと呼
+ぶことにしよう。そしてこのセグメント単位に情報が buf に格納され、buf が
+いっぱいになったらこのセグメントの集まりを 1 ブロックとして (A) の処理
+の無視したif 文の中身で
 
         if (output_pos >= bufsiz - 3 * CHAR_BIT) {
             send_block();
 
         if (output_pos >= bufsiz - 3 * CHAR_BIT) {
             send_block();
@@ -3864,30 +3879,34 @@ buf     | 40 | c1 | c2 |len |   off   | c4 |len |   off   | c6 | c7 | c8 |
             output_pos = 0;
         }
 
             output_pos = 0;
         }
 
-¤Î¤è¤¦¤Ë send_block() ¤¬¸Æ¤Ð¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤è¤¦¤À¡£¤³¤Î if ¤Î¾ò·ï
-¤Ç¡¢3 * CHAR_BIT ¤È¤¤¤¦¤Î¤Ï <len, off> ¤Î³ÊǼ¥Ð¥¤¥È¿ô¤ò¼¨¤·¤Æ¤¤¤ë¡£
-(¤È»×¤Ã¤¿¤¬¡¢3 * CHAR_BIT ¤Ç¤Ï¥Ó¥Ã¥È¿ô¤À¡£°ìÊý¡¢bufsiz ¤Ï¥Ð¥¤¥È¿ô¤À¡£
-·×»»¤Ë»ÈÍѤ·¤Æ¤¤¤ëñ°Ì¤¬°ã¤¦¡£²¿¤ä¤é¥Ð¥°¤Ã¤Ý¤¤Ê·°Ïµ¤¤¬¤¢¤ë¤¬¡¢¥Ð¥°¤À¤È
-¤·¤Æ¤â¥Ð¥Ã¥Õ¥¡¤ò¤Á¤ç¤Ã¤È¤À¤±ÌµÂ̤ˤ·¤Æ¤¤¤ë¤À¤±¤Ê¤Î¤ÇÂ礷¤¿¤³¤È¤Ï¤Ê¤¤¤Î
-¤À¤í¤¦)
-
-# ¤É¤¦¤ä¤é¥Ð¥°¤Ç¤Ï¤Ê¤¤¤é¤·¤¤¡£3 * CHAR_BIT ¤È¤¤¤¦¤Î¤Ï¡¢1¥Ö¥í¥Ã¥¯¤¬
-# CHAR_BIT ¤Î¥¹¥í¥Ã¥È(8 ¤Ä¤Î¥¹¥í¥Ã¥È)¤ò»ý¤Á¡¢1 ¥Ö¥í¥Ã¥¯¤¬¤¹¤Ù¤Æ
-# <len,off> (3 bytes)¤Î¾ì¹ç¡¢ºÇÂç 3 bytes * 8 ¤È¤Ê¤ë¤³¤È¤ò¼¨¤·¤Æ¤¤¤ë¤è
-# ¤¦¤À¡£
-# CHAR_BIT ¤Ï¡¢buf[cpos] ¤Î¥Ó¥Ã¥È¿ô¤òɽ¤·¤Æ¤¤¤ë¡£
+のように send_block() が呼ばれるようになっているようだ。この if の条件
+で、3 * CHAR_BIT というのは <len, off> の格納バイト数を示している。
+(と思ったが、3 * CHAR_BIT ではビット数だ。一方、bufsiz はバイト数だ。
+計算に使用している単位が違う。何やらバグっぽい雰囲気があるが、バグだと
+してもバッファをちょっとだけ無駄にしているだけなので大したことはないの
+だろう)
+
+# どうやらバグではないらしい。3 * CHAR_BIT というのは、1 セグメントが
+# CHAR_BIT のスロット(8 つのスロット)を持ち、1 セグメント内のスロットが
+# すべて <len,off> (3 bytes)の場合、最大 3 bytes * 8 となることを示して
+# いるようだ。
+# CHAR_BIT は、buf[cpos] のビット数を表している。
 #
 #
-# ¼ÂºÝ¤Î¤È¤³¤í1¥Ö¥í¥Ã¥¯¤Ï¡¢buf[cpos]¤Î1 byte¤¬ÀèƬ¤ËɬÍפʤΤǺÇÂ祵¥¤¥º¤Ï
+# 実際のところ 1 セグメントは、buf[cpos] の領域 1 byte が先頭に必要なの
+# で最大サイズは
 #       3 * CHAR_BIT + 1
 #       3 * CHAR_BIT + 1
-# ¤È¤Ê¤ë¡£¤½¤¦¤¤¤¦°ÕÌ£¤Ç¤Ï¡¢
-#       if (output_pos > bufsiz - (3 * CHAR_BIT + 1)) {
-# ¤ÎÊý¤¬¤ï¤«¤ê¤ä¤¹¤¤¤è¤¦¤Ë»×¤¦¡£
+# となる。そういう意味では、
+#       if (buf の残りサイズ < 最大サイズ) {
+# という形式。つまり、
+#       if (bufsiz - output_pos < 3 * CHAR_BIT + 1) {
+# の方がわかりやすいように思う。
 
 
-output_pos = 0 ¤È¤·¤Æ¤¤¤ë¤³¤È¤«¤é¤³¤Î»þÅÀ¤Î buf ¤ÎÃæ¿È¤¬¤¹¤Ù¤Æ 
-send_block() ¤Ç°µ½Ì¤µ¤ì¥Õ¥¡¥¤¥ë¤Ë½ÐÎϤµ¤ì¤ë¤À¤í¤¦¤³¤È¤¬ÁÛÁü¤Ç¤­¤ë¡£
+output_pos = 0 としていることからこの時点の buf の中身(セグメントの集ま
+り=1 ブロック)がすべて send_block() で圧縮されファイルに出力されるだろ
+うことが想像できる。
 
 
-¤³¤Î 1 ¥Ö¥í¥Ã¥¯¤ËËþ¤¿¤Ê¤¤¾õÂ֤ǥե¡¥¤¥ë¤Î½ª¤ê¤¬Í褿¾ì¹ç¡¢¸å½èÍý 
-encode_end_st1() ¤Ç send_block() ¤¬¸Æ¤Ð¤ì¤ë¤Ç¤¢¤í¤¦¤³¤È¤âÁÛÁü¤Ç¤­¤ë¡£
+この 1 ブロックに満たない状態でファイルの終りが来た場合、後処理 
+encode_end_st1() で send_block() が呼ばれるであろうことも想像できる。
 
 encode_end_st1( /* void */ )
 {
 
 encode_end_st1( /* void */ )
 {
@@ -3897,12 +3916,12 @@ encode_end_st1( /* void */ )
     }
 }
 
     }
 }
 
-»×¤Ã¤¿Ä̤ê¤Ç¤¢¤ë¡£putbits(7, 0) ¤È¤¤¤¦¤Ï¡¢bitbuf ¤Ë»Ä¤Ã¤¿ bit ¤òÅǤ­½Ð¤¹
-¤¿¤á¤Ç¤¢¤ë¤³¤È¤Ï¡¢bit Æþ½ÐÎϥ롼¥Á¥ó¤Î²òÆɤdzÎǧºÑ¤ß¤À¡£
+思った通りである。putbits(7, 0) というは、bitbuf に残った bit を吐き出す
+ためであることは、bit 入出力ルーチンの解読で確認済みだ。
 
 
-¤½¤¦¤¤¤¦¤ï¤±¤Ç¡¢send_block() ¤¬°µ½Ì¤Î¥á¥¤¥ó¥ë¡¼¥Á¥ó¤Ç¤¢¤ë¡£
-send_block() ¤ÎÆþÎϤȤÏÀè¤Ë¼¨¤·¤¿¿Þ¤Î¾õÂ֤Πbuf ¤À¡£huf.c:send_block() 
-¤ò¸«¤Æ¤ß¤è¤¦¡£
+そういうわけで、send_block() が圧縮のメインルーチンである。
+send_block() の入力とは先に示した図の状態の buf だ。huf.c:send_block() 
+を見てみよう。
 
 static void
 send_block( /* void */ )
 
 static void
 send_block( /* void */ )
@@ -3964,23 +3983,23 @@ send_block( /* void */ )
         p_freq[i] = 0;
 }
 
         p_freq[i] = 0;
 }
 
-¤Ê¤«¤Ê¤«Â礭¤Ê´Ø¿ô¤Ç¤¢¤ë¤¬¡¢¤½¤ì¤Û¤ÉÆñ¤·¤¤¤³¤È¤Ï¤Ê¤¤¡£¤Þ¤º¡¢(A)
+なかなか大きな関数であるが、それほど難しいことはない。まず、(A)
 
     /* (A) */
     root = make_tree(NC, c_freq, c_len, c_code);
     size = c_freq[root];
     putbits(16, size);
 
 
     /* (A) */
     root = make_tree(NC, c_freq, c_len, c_code);
     size = c_freq[root];
     putbits(16, size);
 
-make_tree() ¤Ç Huffman É½ c_len[], c_code[] ¤ò¹½ÃÛ¤¹¤ë¡£Ìá¤êÃͤΠroot 
-¤Ï¡¢Huffman Ìڤꬤò¼¨¤·¡¢c_freq[root] ¤Ï¡¢Ê¸»ú¤Î½Ð¸½²ó¿ô¤ÎÁíϤǤ¢¤ë
-¤«¤é¡¢size ¤Ï¡¢Ê¿Ê¸¤ÎÁí¥Ð¥¤¥È¿ô¤À(size ¤Ë <off> ¤Îʬ¤Î¥µ¥¤¥º¤Ï´Þ¤Þ¤ì¤Ê
-¤¤¡£c_freq[] ¤¬¡¢<off> ¤Î½Ð¸½ÉÑÅÙ¤ò¿ô¤¨¤Ê¤«¤Ã¤¿¤«¤é)¡£¥Õ¥¡¥¤¥ë¤Ë¤Ï¡¢¤³
-¤Î size ¤¬¤Þ¤º½ñ¤­½Ð¤µ¤ì¤Æ¤¤¤ë(¤½¤¦¤¤¤¨¤Ð¡¢¤³¤Î bit Æþ½ÐÎϥ롼¥Á¥ó¤ò»È
-ÍѤ¹¤ë¤È¥Ð¥¤¥È¥ª¡¼¥À¡¼¤Ë´Ø¤·¤Æ¹Íθ¤¹¤ëɬÍפ¬¤Ê¤¯¤Ê¤ë)¡£
+make_tree() で Huffman 表 c_len[], c_code[] を構築する。戻り値の root 
+は、Huffman 木の根を示し、c_freq[root] は、文字の出現回数の総和である
+から、size は、平文の総バイト数だ(size に <off> の分のサイズは含まれな
+い。c_freq[] が、<off> の出現頻度を数えなかったから)。ファイルには、こ
+の size がまず書き出されている(そういえば、この bit 入出力ルーチンを使
+用するとバイトオーダーに関して考慮する必要がなくなる)。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-      16bit  
+      16bit
    |---------|
    +----+----+
    |  size   |
    |---------|
    +----+----+
    |  size   |
@@ -3988,7 +4007,7 @@ make_tree() 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-³¤¤¤Æ¡¢(B)
+続いて、(B)
 
     if (root >= NC) {
         count_t_freq();
 
     if (root >= NC) {
         count_t_freq();
@@ -4007,20 +4026,20 @@ make_tree() 
         putbits(CBIT, root);
     }
 
         putbits(CBIT, root);
     }
 
-root ¤¬ NC ¤è¤ê¤âÂ礭¤¤¾ì¹ç¤òȽÃǤ·¤Æ¤¤¤ë¤¬¡¢¥Ï¥Õ¥Þ¥óÌڤꬤÏɬ¤º NC ¤è
-¤ê¤âÂ礭¤¤(make_tree() ¤Î avail ¤Î½é´üÃͤò³Îǧ¤·¤è¤¦)¡£¤Ç¤Ï¡¢¤³¤Î
-¾ò·ï¤òËþ¤¿¤µ¤Ê¤¤¾ì¹ç¤È¸À¤¦¤Î¤Ï²¿¤«¤È¸À¤¦¤È¡¢Æ±¤¸¤¯ make_tree() ¤ò³Îǧ¤¹¤ë¤È¡¢
+root が NC よりも大きい場合を判断しているが、ハフマン木の根は必ず NC よ
+りも大きい(make_tree() の avail の初期値を確認しよう)。では、この
+条件を満たさない場合と言うのは何かと言うと、同じく make_tree() を確認すると、
 
     if (heapsize < 2) {
         codeparm[heap[1]] = 0;
         return heap[1];
     }
 
 
     if (heapsize < 2) {
         codeparm[heap[1]] = 0;
         return heap[1];
     }
 
-¤È¤¤¤¦Îã³°¾ò·ï¤¬¤¢¤Ã¤¿¡£¤³¤ì¤Ï¡¢°µ½Ì¤¹¤ëʸ»ú¤¬¤Ê¤¤¡¢¤¢¤ë¤¤¤Ï1¼ïÎष¤«
-¤Ê¤¤¾ì¹ç¤Î½èÍý¤À¡£°µ½Ì¤¹¤ëʸ»ú¤¬¤Ê¤¤¾ì¹ç¤Ë send_block() ¤¬¸Æ¤Ð¤ì¤ë¤³¤È
-¤Ï¤Ê¤¤¤À¤í¤¦¤«¤é¡¢(B) ¤Î½èÍý¤Î else ¤Ï 1 ¥Ö¥í¥Ã¥¯Ãæ¤Ë°µ½Ì¤¹¤ëʸ»ú¤¬ 1 
-¼ïÎष¤«¤Ê¤¤¾ì¹ç¤Î½èÍý¤Ç¤¢¤ë(¤³¤Î 1 ¼ïÎà¤Îʸ»ú¤È¤Ï¡¢make_tree() ¤ÎÌá¤ê
-ÃÍ root ¤À)¡£¤³¤Î¤È¤­°Ê²¼¤Î¤è¤¦¤Ê½ÐÎϤˤʤ롣(TBIT{5}, CBIT{9} ¤Ç¤¢¤ë)
+という例外条件があった。これは、圧縮する文字がない、あるいは 1 種類しか
+ない場合の処理だ。圧縮する文字がない場合に send_block() が呼ばれること
+はないだろうから、(B) の処理の else は 1 ブロック中に圧縮する文字が 1 
+種類しかない場合の処理である(この 1 種類の文字とは、make_tree() の戻り
+値 root だ)。このとき以下のような出力になる。(TBIT{5}, CBIT{9} である)
 
 ----------------------------------------------------------------------------
       TBIT    CBIT
 
 ----------------------------------------------------------------------------
       TBIT    CBIT
@@ -4032,11 +4051,11 @@ root 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤ì¤¬¡¢1¥Ö¥í¥Ã¥¯¤Ë1¼ïÎष¤«Ê¸»ú¤¬¤Ê¤¤¾ì¹ç¤Î½ÐÎϤÀ(off¤Î¾ðÊó¤Ï¤Þ¤À´Þ¤Þ
-¤Ê¤¤)¡£(B)¤Î if ¤¬¿¿¤Î¤È¤­¤¬¤É¤¦¤Ê¤ë¤«¤ÏÊ£»¨¤½¤¦¤Ê¤Î¤Ç¸å¤Ç¸«¤ë¤³¤È¤Ë¤·
-¤è¤¦¡£
+これが、1 ブロックに 1 種類しか文字がない場合の出力だ(off の情報はまだ
+含まない)。(B)の if が真のときがどうなるかは複雑そうなので後で見ること
+にしよう。
 
 
-³¤¤¤Æ (C)
+続いて (C)
 
     root = make_tree(np, p_freq, pt_len, pt_code);
     if (root >= np) {
 
     root = make_tree(np, p_freq, pt_len, pt_code);
     if (root >= np) {
@@ -4047,28 +4066,28 @@ root 
         putbits(pbit, root);
     }
 
         putbits(pbit, root);
     }
 
-p_freq[] ¤ò¸«¤Æ¤¤¤ë¤³¤È¤«¤éº£Å٤Ϡ<off> ¤Î¾ðÊó¤Î Huffman ÌÚ¤ò¹½ÃÛ¤·¤Æ
-¤¤¤ë¤³¤È¤¬¤ï¤«¤ë¡£ÀèÄø¤ÈƱÍͤˡ¢<off> ¤ÎÃͤ¬¤¹¤Ù¤ÆƱ¤¸¾ì¹ç¤Ï¡¢else ¤Î
-¾ò·ï¤Ë¤Ê¤ê¡¢°Ê²¼¤Î½ÐÎϤ¬¹Ô¤ï¤ì¤ë¡£(np ¤ÎÃͤϡ¢-lh7- ¤Î¾ì¹ç¤Ç¡¢17 ¤À)
+p_freq[] を見ていることから今度は <off> の情報の Huffman 木を構築して
+いることがわかる。先程と同様に、<off> の値がすべて同じ場合は、else の
+条件になり、以下の出力が行われる。(pbit の値は、-lh7- の場合で、5 だ)
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-              
-      np bit    np bit              method  np
+
+       pbit     pbit                method  pbit
    |---------|---------|            ----------
    |---------|---------|            ----------
-   +----+----+---------+            -lh4-   14
-   |     0   |  root   |            -lh5-   14
-   +----+----+---------+            -lh6-   16
-                                    -lh7-   17
+   +----+----+---------+            -lh4-   4
+   |     0   |  root   |            -lh5-   4
+   +----+----+---------+            -lh6-   5
+                                    -lh7-   5
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤³¤Þ¤Ç¤Ë½ÐÎϤ·¤¿¾ðÊ󤬲¿¤ò¼¨¤¹¤«¤ï¤«¤ë¤À¤í¤¦¤«¡©Huffman Ë¡¤ÎÉä¹æ²½½è
-Íý¤Ïʸ»ú¤ò bit Îó¤ËÊÑ´¹¤¹¤ë¡£¤³¤ì¤òÉü¹æ¤¹¤ë¾ì¹ç¤Ï bit Îó¤ËÂбþ¤¹¤ëʸ»ú
-¤òÃΤëɬÍפ¬¤¢¤ë¡£¤¹¤Ê¤ï¤Á Huffman ÌڤǤ¢¤ë(¼ÂºÝ¤Ë¤Ï Huffman É½)¡£¿Þ¼¨
-¤·¤¿¤Î¤Ï¡¢Huffman ÌÚ¤ò¹½ÃÛ¤¹¤ëɬÍפ¬¤Ê¤¤(¹½ÃۤǤ­¤Ê¤¤)¾ì¹ç¤Î¾ðÊó¤Ë¤Ê¤ë
-¤¬¡¢¸½ºß²òÆɤòÈô¤Ð¤·¤Æ¤¤¤ë½èÍý¤Ï Huffman É½¤ò¥Õ¥¡¥¤¥ë¤Ë½ÐÎϤ·¤Æ¤¤¤ë²Õ
-½ê¤Ç¤¢¤ë¤³¤È¤ÏÍưפËÁÛÁü¤¬¤Ä¤¯¡£¤È¤¤¤¦¤³¤È¤Ï»Ä¤ê¤Î (D) ¤¬ËÜÅö¤Î°µ½Ìʸ
-¤ò½ÐÎϤ¹¤ë²Õ½ê¤À¡£
+ここまでに出力した情報が何を示すかわかるだろうか?Huffman 法の符号化処
+理は文字を bit 列に変換する。これを復号する場合は bit 列に対応する文字
+を知る必要がある。すなわち Huffman 木である(実際には Huffman 表)。図示
+したのは、Huffman 木を構築する必要がない(構築できない)場合の情報になる
+が、現在解読を飛ばしている処理は Huffman 表をファイルに出力している箇
+所であることは容易に想像がつく。ということは残りの (D) が本当の圧縮文
+を出力する箇所だ。
 
     /* (D) */
     pos = 0;
 
     /* (D) */
     pos = 0;
@@ -4088,20 +4107,20 @@ p_freq[] 
             return;
     }
 
             return;
     }
 
-size ¿ôʬ¥ë¡¼¥×¤·¤Æ¤¤¤ë¡£size ¤Ï¡¢<off> ¤ò½ü¤¤¤¿ buf ¤Îʸ»ú¿ô¤ò¼¨¤·¤Æ
-¤¤¤ë¤ÈÁ°¤Ë½ñ¤¤¤¿¤¬¡¢¤É¤¦¤ä¤é <len, off> ¤ò 1 Ê¸»ú¤È¿ô¤¨¤¿¤È¤­¤Î buf ¤Î
-ʸ»ú¿ô¤ò¼¨¤·¤Æ¤¤¤ë¤È¹Í¤¨¤¿Êý¤¬Îɤµ¤½¤¦¤À¡£
+size 数分ループしている。size は、<off> を除いた buf の文字数を示して
+いると前に書いたが、どうやら <len, off> を 1 文字と数えたときの buf の
+文字数を示していると考えた方が良さそうだ。
 
 
-ºÇ½é¤Î if ¤Ç¡¢
+最初の if で、
 
         if (i % CHAR_BIT == 0)
             flags = buf[pos++];
         else
             flags <<= 1;
 
 
         if (i % CHAR_BIT == 0)
             flags = buf[pos++];
         else
             flags <<= 1;
 
-¤³¤ì¤¬¿¿¤Ë¤Ê¤ë¾ò·ï¤Ï buf[pos] ¤¬ buf[cpos] ¤Ç¤¢¤ë¾ì¹ç¤À(output_mask ¤¬ 
-128, 64, ..., 1 ¤È 8 ¤Ä¤ÎÃͤò½ä²ó¤·¤Æ¤¤¤¿¤³¤È¤ò»×¤¤½Ð¤½¤¦)¡£
-flags ¤Ï¡¢<len, off> ¤Î buf ¾å¤Î°ÌÃÖ¤ò¼¨¤¹ bit ¥Þ¥¹¥¯¤Ë¤Ê¤ë¡£
+これが真になる条件は buf[pos] が buf[cpos] である場合だ(output_mask が 
+128, 64, ..., 1 と 8 つの値を巡回していたことを思い出そう)。
+flags は、<len, off> の buf 上の位置を示す bit マスクになる。
 
         if (flags & (1 << (CHAR_BIT - 1))) {
             encode_c(buf[pos++] + (1 << CHAR_BIT));
 
         if (flags & (1 << (CHAR_BIT - 1))) {
             encode_c(buf[pos++] + (1 << CHAR_BIT));
@@ -4111,24 +4130,24 @@ flags 
         } else
             encode_c(buf[pos++]);
 
         } else
             encode_c(buf[pos++]);
 
-flags ¤¬¡¢127 ¤Ç¤¢¤ë¤È¤­ buf[pos] ¤Ï¡¢<len, off> ¤ò»Ø¤·¡¢
+flags の 7 ビット目(128)が立っているとき buf[pos] は、<len, off> を指し、
 
   encode_c(len + 256)
   encode_p(off)
 
 
   encode_c(len + 256)
   encode_p(off)
 
-¤Ç¡¢°µ½Ì¤ò¹Ô¤¦¤è¤¦¤À¡£len ¤Ë 256 ¤ò­¤·¤Æ¤¤¤ë¤Î¤Ï¡¢buf[] ¤Ë len ¤ò³ÊǼ
-¤¹¤ë¤È¤­(output_st1() ¤Î (B) ¤Î½èÍý)¤Ë
+で、圧縮を行うようだ。len に 256 を足しているのは、buf[] に len を格納
+するとき(output_st1() の (B) の処理)に
 
     buf[output_pos++] = (unsigned char) c;
 
 
     buf[output_pos++] = (unsigned char) c;
 
-¤Î¤è¤¦¤ËºÇ¾å°Ì bit ¤ò¼Î¤Æ¤Æ¤¤¤¿¤«¤é¤À¡£len ¤Ï¾ï¤Ë 256 °Ê¾å¤Ê¤Î¤Ç¡¢256 
-¤ò­¤¹¤³¤È¤Ç¸µ¤Î len ¤ÎÃͤò°µ½Ì¥ë¡¼¥Á¥ó¤ËÅϤ·¤Æ¤¤¤ë¡£
+のように最上位 bit を捨てていたからだ。len は常に 256 以上なので、256 
+を足すことで元の len の値を圧縮ルーチンに渡している。
 
 
-Ä̾ï¤Îʸ»ú¤Ï
+通常の文字は
 
   encode_c(buf[pos])
 
 
   encode_c(buf[pos])
 
-¤Ç°µ½Ì¤µ¤ì¤Æ¤¤¤ë¡£encode_c() ¤Î½èÍýÆâÍƤϴÊñ¤Ê¤Î¤Ç¸«¤Æ¤ß¤è¤¦¡£
+で圧縮されている。encode_c() の処理内容は簡単なので見てみよう。
 
 static void
 encode_c(c)
 
 static void
 encode_c(c)
@@ -4137,10 +4156,10 @@ encode_c(c)
     putcode(c_len[c], c_code[c]);
 }
 
     putcode(c_len[c], c_code[c]);
 }
 
-c_len[], c_code[] ¤¬Ê¸»ú c ¤ËÂбþ¤¹¤ë Huffman Éä¹æ¤Î bit Ä¹¤ÈÉä¹æ¤ò¼¨
-¤·¤Æ¤¤¤ë¤Î¤Ç¡¢¤½¤ì¤ò¤½¤Î¤Þ¤Þ½ÐÎϤ·¤Æ¤¤¤ë¡£´Êñ¤À¡£
+c_len[], c_code[] が文字 c に対応する Huffman 符号の bit 長と符号を示
+しているので、それをそのまま出力している。簡単だ。
 
 
-encode_p() ¤Ï¤â¤¦¾¯¤·Ê£»¨¤À¡£
+encode_p() はもう少し複雑だ。
 
 static void
 encode_p(p)
 
 static void
 encode_p(p)
@@ -4159,12 +4178,12 @@ encode_p(p)
         putbits(c - 1, p);
 }
 
         putbits(c - 1, p);
 }
 
-ºÇ½é¤Î while Ê¸¤Ç¡¢<off> ¤Î bit Ä¹¤òµá¤á¡¢¤½¤Î bit Ä¹¤Î¾ðÊó¤ò
-Huffman Éä¹æ²½¤·¤Æ¤¤¤ë¡£¤½¤Î¸å¡¢putbits() ¤Ç¡¢É¬Í× bit ¿ô¤À¤±
-½ÐÎϤ¹¤ë¡£¤Ä¤Þ¤ê¡¢<off> ¤Ï°Ê²¼¤Î¤è¤¦¤ËÉä¹æ²½¤µ¤ì¤ë¡£
+最初の while 文で、<off> の bit 長を求め、その bit 長の情報を
+Huffman 符号化している。その後、putbits() で、必要 bit 数だけ
+出力する。つまり、<off> は以下のように符号化される。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-off = 64 ¤Î°µ½Ì
+off = 64 の圧縮
 
      |---- 16 bit -------|
      +----+----+----+----+
 
      |---- 16 bit -------|
      +----+----+----+----+
@@ -4172,21 +4191,21 @@ off  |0000 0000 0100 0000|
      +----+----+----+----+
                  |-7 bit-|
 
      +----+----+----+----+
                  |-7 bit-|
 
-¤³¤Î°µ½Ìʸ¤Ï°Ê²¼(Ťµ¤¬ 7 bit ¤Ç¤¢¤ë¤È¤¤¤¦¾ðÊó(HuffmanÉä¹æ²½)¤ÈÃͤΥڥ¢)
+ã\81\93ã\81®å\9c§ç¸®æ\96\87ã\81¯ä»¥ä¸\8b\95·ã\81\95ã\81\8c 7 bit ã\81§ã\81\82ã\82\8bã\81¨ã\81\84ã\81\86æ\83\85å ±(Huffman符å\8f·å\8c\96\81¨å\80¤ã\81®ã\83\9aã\82¢)
 
                        |-6 bit-|
      +-----------------+-------+
 
                        |-6 bit-|
      +-----------------+-------+
-     | 7 ¤ÎHuffmanÉä¹æ |00 0000|
+     | 7 のHuffman符号 |00 0000|
      +-----------------+-------+
 
 ----------------------------------------------------------------------------
 
      +-----------------+-------+
 
 ----------------------------------------------------------------------------
 
-¤³¤³¤Ç¡¢Ãͤò 6 bit ¤·¤«½ÐÎϤ·¤Ê¤¤(putbits() ¤Ç c-1 ¤òÅϤ·¤Æ¤¤¤ë)¤Î¤Ï¡¢
-7 bit Ìܤ¬ 1 ¤Ç¤¢¤ë¤³¤È¤¬¼«ÌÀ¤À¤«¤é¤Ç¤¢¤ë¡£¾ï¤Ë off != 0 ¤À¤«¤é¡¢½ñ¤­
-½Ð¤¹¾ðÊó¤ò 1 bit ºï¸º¤Ç¤­¤ë¤ï¤±¤À¡£¤·¤¿¤¬¤Ã¤Æ¡¢off=1 ¤Î¤È¤­¤Ï bit Ä¹¤¬ 
-1 ¤È¤¤¤¦¾ðÊó¤·¤«½ñ¤­½Ð¤µ¤Ê¤¤¡£
+ここで、値を 6 bit しか出力しない(putbits() で c-1 を渡している)のは、
+7 bit 目が 1 であることが自明だからである。最初にビット長を出力している
+ので、値の情報は1 bit 削減できるわけだ。したがって、off=1 のときは bit
+長が 1 という情報しか書き出さない。
 
 
-ºÇ¸å¤Î (E) ¤ÏÉÑÅÙɽ¤ò¥¯¥ê¥¢¤·¤Æ¤¤¤ë¤À¤±¤À¡£
+最後の (E) は頻度表をクリアしているだけだ。
 
     /* (E) */
     for (i = 0; i < NC; i++)
 
     /* (E) */
     for (i = 0; i < NC; i++)
@@ -4194,8 +4213,50 @@ off  |0000 0000 0100 0000|
     for (i = 0; i < np; i++)
         p_freq[i] = 0;
 
     for (i = 0; i < np; i++)
         p_freq[i] = 0;
 
-°Ê¾å¤Ç¡¢°µ½Ì½èÍýÁ´ÂΤγµÍפ¬¤ï¤«¤Ã¤¿¡£¸å¤Ï̵»ë¤·¤Æ¤¤¤¿ Huffman É½¤ò½Ð
-ÎϤ¹¤ë²Õ½ê¤À¤±¤À¡£
+ここで、頻度表をクリアしているということは文字や位置の出現回数は 1 ブロック
+単位でしか計上しないことを表す。
+
+# 一方、c_freq や p_freq は unsigned short であるから(16 bit だとし
+# て)65535 までしか数えられない。さらに、{c,p}_freq には Huffman 木の構
+# 築の過程で出現回数の総和がセットされる場合があることから 1 ブロックに
+# は 65535 文字 + 65535 個の位置までしか格納できない。
+# いや、位置は必ず長さとセットであることから。位置の出現回数は文字の出
+# 現回数(これは長さの出現回数を含む)に含まれるため 65535 スロットまでし
+# か buf を持てないことになる。これは blocksize (16 bit)とも一致する。
+#
+# buf の領域確保は以下のようになっていた。
+#
+#    unsigned char  *
+#    alloc_buf( /* void */ )
+#    {
+#       bufsiz = 16 * 1024 *2;  /* 65408U; */ /* t.okamoto */
+#       while ((buf = (unsigned char *) malloc(bufsiz)) == NULL) {
+#           bufsiz = (bufsiz / 10) * 9;
+#           if (bufsiz < 4 * 1024)
+#               break;
+#       }
+#       return buf;
+#    }
+#
+# これから、bufsiz は、16 * 1024 *2 = 2^4 * 2^10 * 2 = 2^15 である。
+# 1 セグメントの最小サイズがバイト数で(1*CHAR_BIT+1)であるから
+# この領域に格納できる最大セグメント数は、
+#   2^15 / (1*CHAR_BIT+1)
+# であり、1 セグメントは 8 スロットあるから、最大スロット数は
+#     8 * 2^15 / (1*CHAR_BIT+1)
+#   = 2^18 / 9
+#   = 29127.1111111111
+# となる。これは、頻度表の上限(スロット数の上限)
+#   65535=2^16-1
+# よりも小さいので問題はないことになる。
+#
+# なお、1 ブロックのサイズはこのバッファサイズにより決まるわけだが 1 ブ
+# ロックのサイズが大きければ大きいほどよいというわけではない。むしろ、
+# 文字の出現確率の変動に追随するためには小さい方がよいのだがそうすると
+# Huffman 木の格納回数が増えるので簡単には最適値は決まらない。
+
+以上で、圧縮処理全体の概要がわかった。後は無視していた Huffman 表を出
+力する箇所だけだ。
 
     /* (B) */
     if (root >= NC) {
 
     /* (B) */
     if (root >= NC) {
@@ -4209,11 +4270,11 @@ off  |0000 0000 0100 0000|
         }
         write_c_len();
 
         }
         write_c_len();
 
-¤³¤³¤Ç¤Ï¡¢c_len[], c_code[] ¤È¤¤¤¦ Huffman É½¤ò½ÐÎϤ¹¤ë¤À¤±¤Î¤Ï¤º¤À¤¬¡¢
-¤µ¤é¤Ë Huffman É½ pt_len[], pt_code[] ¤Î¹½ÃÛ¤ò¹Ô¤Ã¤Æ¤¤¤ë¡£¤³¤ì¤Ï¡¢
-<off> ¤Î bit Ä¹¤Î Huffman Éä¹æɽ¤Ç¤â¤¢¤Ã¤¿ÊÑ¿ô¤À¤¬¡¢Ã±¤ËÊÑ¿ô¤ò»È¤¤²ó¤·
-¤Æ¤¤¤ë¤À¤±¤À¡£¤³¤³¤Ç¤Î pt_len[], pt_code[] ¤¬²¿¤ÎÉä¹æɽ¤«¤Ï¡¢
-count_t_freq() ¤ò¸«¤ëɬÍפ¬¤¢¤ë¡£
+ここでは、c_len[], c_code[] という Huffman 表を出力するだけのはずだが、
+さらに Huffman 表 pt_len[], pt_code[] の構築を行っている。これは、
+<off> の bit 長の Huffman 符号表でもあった変数だが、単に変数を使い回し
+ているだけだ。ここでの pt_len[], pt_code[] が何の符号表かは、
+count_t_freq() を見る必要がある。
 
 static void
 count_t_freq(/*void*/)
 
 static void
 count_t_freq(/*void*/)
@@ -4249,13 +4310,13 @@ count_t_freq(/*void*/)
     }
 }
 
     }
 }
 
-ºÇ½é¤ËÉÑÅÙɽ t_freq[] ¤ò½é´ü²½¤¹¤ë¡£Â³¤¤¤Æ¡¢
+最初に頻度表 t_freq[] を初期化する。続いて、
 
     n = NC;
     while (n > 0 && c_len[n - 1] == 0)
         n--;
 
 
     n = NC;
     while (n > 0 && c_len[n - 1] == 0)
         n--;
 
-¤Ç¡¢c_len[n] != 0 ¤Ç¤¢¤ëºÇÂç¤Î n ¤òµá¤á¤Æ¤¤¤ë¡£
+で、c_len[n] != 0 である最大の n を求めている。
 
     i = 0;
     while (i < n) {
 
     i = 0;
     while (i < n) {
@@ -4280,26 +4341,26 @@ count_t_freq(/*void*/)
             t_freq[k + 2]++;
     }
 
             t_freq[k + 2]++;
     }
 
-c_len[i] ¤Ï¡¢Ê¸»ú i ¤Î Huffman Éä¹æ¤Ç¤Î bit Ä¹¤Ç¤¢¤Ã¤¿¡£¤³¤Î
-c_len[i] ¤ÎÃͤò°Ê²¼¤Î¾ì¹çʬ¤±¤Ç t_freq[] ¤ËÉÑÅÙ·×»»¤·¤Æ¤¤¤ë¡£
-count ¤Ï¡¢c_len[i] ¤¬Ï¢Â³¤Ç²¿²ó 0 ¤Ç¤¢¤ë¤«¤Î¿ô¤À¡£
+c_len[i] は、文字 i の Huffman 符号での bit 長であった。この
+c_len[i] の値を以下の場合分けで t_freq[] に頻度計算している。
+count は、c_len[i] が連続で何回 0 であるかの数だ。
 
   c_len[i]    count     t_freq[]
   -------------------------------------------
 
   c_len[i]    count     t_freq[]
   -------------------------------------------
-     0        0 .. 2    t_freq[0] += count
+     0        1 .. 2    t_freq[0] += count
      0        3 ..18    t_freq[1]++
      0        19        t_freq[0]++, t_freq[1]++
      0        3 ..18    t_freq[1]++
      0        19        t_freq[0]++, t_freq[1]++
-     0        20°Ê¾å    t_freq[2]++
-   0°Ê³°                t_freq[c_len[i]+2]++;
+     0        20以上    t_freq[2]++
+   0以外                t_freq[c_len[i]+2]++;
 
 
-¤³¤ì¤¬¤É¤¦¤¤¤¦Íý¶þ¤Ç¤¢¤ë¤«¤Ï¤è¤¯¤ï¤«¤é¤Ê¤¤¤¬¡¢¤È¤Ë¤«¤¯ÉÑÅÙ·×»»¤ò¹Ô¤¦¾ì
-¹ç¤Ë t_freq[0], t_freq[1], t_freq[2] ¤òÆÃÊÌ°·¤¤¤·¤Æ¤¤¤ë¡£¤½¤·¤Æ¡¢ÉÑÅÙ
-·×»»¤ÎÂоݤ¬ c_len[] ¤Ç¤¢¤ë¤³¤È¤«¤é (B) ¤Î½èÍý¤Ï¡¢c_len[] ¤Ë´Ø¤·¤Æ 
-Huffman Éä¹æ²½¤ò¹Ô¤¦½èÍý¤Î¤è¤¦¤À¡£
+これがどういう理屈であるかはよくわからないが、とにかく頻度計算を行う場
+合に t_freq[0], t_freq[1], t_freq[2] を特別扱いしている。そして、頻度
+計算の対象が c_len[] であることから (B) の処理は、c_len[] に関して 
+Huffman 符号化を行う処理のようだ。
 
 
-¤½¤¦¤·¤Æ¡¢make_tree() ¤Ç¡¢t_freq[] ¤Ë´Ø¤·¤Æ Huffman Éä¹æɽ¤òºîÀ®¤·¡¢
-write_pt_len() ¤Ç¡¢¤³¤ÎÉä¹æɽ(ʸ»ú¤Î Huffman Éä¹æ¤Î¥Ó¥Ã¥ÈĹ c_len ¤Î 
-Huffman Éä¹æ¤Î¥Ó¥Ã¥ÈĹ) pt_len[] ¤ò½ÐÎϤ¹¤ë¡£
+そうして、make_tree() で、t_freq[] に関して Huffman 符号表を作成し、
+write_pt_len() で、この符号表(文字の Huffman 符号のビット長 c_len の 
+Huffman 符号のビット長) pt_len[] を出力する。
 
 static void
 write_pt_len(n, nbit, i_special)
 
 static void
 write_pt_len(n, nbit, i_special)
@@ -4327,51 +4388,53 @@ write_pt_len(n, nbit, i_special)
     }
 }
 
     }
 }
 
-ºÇ½é¤Ë pt_len[] ¤ÎÍ×ÁÇ¿ô¤ò nbit ½ÐÎϤ·¡¢Â³¤±¤ÆÉä¹æ bit Ä¹ pt_len[] ¤Î
-Í×ÁǤò½ÐÎϤ·¤Æ¤¤¤ë¡£nbit ¤Ï¡¢n ¤ò³ÊǼ¤¹¤ë¤Î¤ËɬÍפʠbit ¿ô¤òɽ¤·¤Æ¤¤¤ë
-¤è¤¦¤À¡£¤³¤³¤Ç¤Ï¡¢n (NT{19}) ¤ò½ÐÎϤ¹¤ë¤Î¤Ë TBIT{5} bit É¬ÍפǤ¢¤ë¤È¤¤
-¤¦¤³¤È¤À¡£
+最初に pt_len[] の要素数を nbit 出力し、続けて符号 bit 長 pt_len[] の
+要素を出力している。nbit は、n を格納するのに必要な bit 数を表している
+ようだ。ここでは、n (NT{19}) を出力するのに TBIT{5} bit 必要であるとい
+うことだ。
 
 
-pt_len[] ¤ò½ÐÎϤ¹¤ë¤È¤­¤Ï¡¢¤½¤ÎÃͤ¬ 6 ¤è¤êÂ礭¤¤¤«¤É¤¦¤«¤Ç·Á¼°¤òÊѤ¨¤Æ
-½ÐÎϤ·¤Æ¤¤¤ë¡£6 °Ê²¼¤Ç¤¢¤ì¤Ð¤½¤Î¤Þ¤Þ 3 bit ¤Ç½ÐÎϤ·¡¢7 bit °Ê¾å¤Ç¤¢¤ì
-¤Ð¡¢bit ¿ô¤Çɽ¸½¤¹¤ë¤é¤·¤¤¡£Î㤨¤Ð pt_len[i] == 7 ¤Ê¤é¡¢1110 ¤È¤Ê¤ë¡£
-ºÇ½é¤Î 3 bit ¤Ïɬ¤º 1 ¤Ë¤Ê¤ê¡¢ºÇ½é¤Î·Á¼°¤È¶èÊ̤¬¤Ä¤¯¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£
+pt_len[] を出力するときは、その値が 6 より大きいかどうかで形式を変えて
+出力している。6 以下であればそのまま 3 bit で出力し、7 bit 以上であれ
+ば、bit 数で表現するらしい。例えば pt_len[i] == 7 なら、1110 となる。
+最初の 3 bit は必ず 1 になり、最初の形式と区別がつくようになっている。
 
 
-¤µ¤é¤Ë¡¢i_special ÈÖÌܤΠpt_len[i] ¤ò½ÐÎϸå¤Ï¡¢i_special ... 6 ¤ÎÈÏ°Ï
-¤Ç pt_len[i] == 0 ¤¬Â³¤¯¤³¤È¤ò 2 bit ¤Ç¡¢É½¸½¤·¤Æ¤¤¤ë¡£i_special ¤Ï
-write_pt_len() ¤Î 3 ÈÖÌܤΰú¿ô¤Ç¡¢º£²ó¤Î¾ì¹ç¤Ï 3 ¤À¡£Î㤨¤Ð 
-pt_len[3..5] ¤¬¤¹¤Ù¤Æ 0 ¤Ê¤é pt_len[3] ¤ò½ÐÎϸ塢i - 3 (= 3) ¤ò 2 bit 
-½ÐÎϤ¹¤ë¡£¤Ä¤Þ¤ê¡¢11 ¤¬½ÐÎϤµ¤ì¤ë¡£¤³¤Î¤è¤¦¤Ê¤³¤È¤ò¤·¤Æ¤¤¤ë°ÕÌ£¤Ï¤³¤ì
-¤Þ¤¿¤è¤¯¤ï¤«¤é¤Ê¤¤¡£¤Á¤ç¤Ã¤ÈÊ£»¨¤Ê¤Î¤Ç¿Þ¼¨¤·¤Æ¤ß¤¿¡£
+さらに、i_special 番目の pt_len[i] を出力した後は、i_special ... 6 の範
+囲で pt_len[i] == 0 が続くことを 2 bit で、表現している。i_special は
+write_pt_len() の 3 番目の引数で、今回の場合は 3 だ。例えば
+pt_len[3..5] がすべて 0 なら pt_len[3..5] を出力せずに、i - 3 (= 3) を
+2 bit 出力する。つまり、11 が出力される。このようなことをしている意味は
+これまたよくわからない。ちょっと複雑なので図示してみた。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-< pt_len[] ¤Î½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥È >
+< pt_len[] の出力フォーマット >
 
              0       TBIT{5}
              +-------+-----------+-----------+--   --+-----------+
              |   n   | pt_len[0] | pt_len[1] | ...    pt_len[n-1]|
              +-------+-----------+-----------+--   --+-----------+
 
 
              0       TBIT{5}
              +-------+-----------+-----------+--   --+-----------+
              |   n   | pt_len[0] | pt_len[1] | ...    pt_len[n-1]|
              +-------+-----------+-----------+--   --+-----------+
 
-pt_len[i] <= 6 ¤Î¾ì¹ç
+pt_len[i] <= 6 の場合
 
               0     3bit
               +-----+
     pt_len[i] | | | |
               +-----+
 
 
               0     3bit
               +-----+
     pt_len[i] | | | |
               +-----+
 
-pt_len[i] >= 7 ¤Î¾ì¹ç
+pt_len[i] >= 7 の場合
 
               0             pt_len[i] - 3
               +----------------+
     pt_len[i] |1 1 1 1 ... 1 0 |
               +----------------+
 
 
               0             pt_len[i] - 3
               +----------------+
     pt_len[i] |1 1 1 1 ... 1 0 |
               +----------------+
 
-pt_len[i_special] ¤Îľ¸å¤Ï 2 bit ¤Î¾ðÊó¤¬Éղ䵤ì¤ë¡£¤³¤ÎÃͤò x ¤È¤¹¤ë
-¤È¡¢pt_len[i_special .. x + 3] ¤ÎÈϰϤǠ0 ¤¬Â³¤¯¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
+pt_len[i_special-1] の直後は 2 bit の情報が付加される。この値を x とする
+と、pt_len[i_special .. x + 2] の範囲で 0 が続くことを意味する。x が 0
+なら pt_len[i_special] は 0 ではない。
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-ºÇ¸å¤Ë¡¢write_c_len() ¤Ç¡¢Éä¹æɽ c_len[] ¤È pt_code[] ¤ò½ÐÎϤ¹¤ë¡£
+最後に、write_c_len() で、Huffman 符号のビット長 c_len[] (の Huffman 符
+号表 pt_code[]) を出力する。
 
 static void
 write_c_len(/*void*/)
 
 static void
 write_c_len(/*void*/)
@@ -4414,30 +4477,30 @@ write_c_len(/*void*/)
     }
 }
 
     }
 }
 
-Á°¤Ë¡¢ÉÑÅÙ¤ò¿ô¤¨¤¿¤È¤­¤ÈƱÍͤξò·ï¤Ç½ÐÎÏ·Á¼°¤¬ÊѤï¤Ã¤Æ¤¤¤ë¡£½èÍýÆâÍƤÏ
-´Êñ¤Ê¤Î¤Ç¡¢°Ê²¼¤Î¿Þ¤ò¼¨¤¹¤À¤±¤Ë¤¹¤ë(Íý¶þ¤Ï¤è¤¯¤ï¤«¤é¤Ê¤¤)¡£
+前に、頻度を数えたときと同様の条件で出力形式が変わっている。処理内容は
+簡単なので、以下の図を示すだけにする(理屈はよくわからない)。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-< c_len[] ¤Î½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥È >
+< c_len[] の出力フォーマット >
 
              0       CBIT{9}
              +-------+-----------+-----------+--   --+-----------+
              |   n   |  c_len[0] |  c_len[1] | ...     c_len[n-1]|
              +-------+-----------+-----------+--   --+-----------+
 
 
              0       CBIT{9}
              +-------+-----------+-----------+--   --+-----------+
              |   n   |  c_len[0] |  c_len[1] | ...     c_len[n-1]|
              +-------+-----------+-----------+--   --+-----------+
 
-c_len[i] == 0 ¤Î¾ì¹ç
+c_len[i] == 0 の場合
 
 
- 0 ¤¬Â³¤¯¿ô¤ò count ¤È¤¹¤ë¤È¡¢
+ 0 が続く数を count とすると、
 
 
- count == 0..2 ¤Î¾ì¹ç
+ count == 1..2 の場合
 
 
-                pt_len[0]  
-              <----------> 
+                pt_len[0]
+              <---------->
              +------------+
              | pt_code[0] |
              +------------+
 
              +------------+
              | pt_code[0] |
              +------------+
 
- count == 3..18 ¤Î¾ì¹ç
+ count == 3..18 の場合
 
                pt_len[1]    4 bit
               <----------> <------>
 
                pt_len[1]    4 bit
               <----------> <------>
@@ -4445,7 +4508,7 @@ c_len[i] == 0 
              | pt_code[1] |count-3|
              +------------+-------+
 
              | pt_code[1] |count-3|
              +------------+-------+
 
- count == 19 ¤Î¾ì¹ç
+ count == 19 の場合
 
                 pt_len[0]   pt_len[1]    4 bit
               <----------> <----------> <------>
 
                 pt_len[0]   pt_len[1]    4 bit
               <----------> <----------> <------>
@@ -4453,7 +4516,7 @@ c_len[i] == 0 
              | pt_code[0] | pt_code[1] |count-3|
              +------------+------------+-------+
 
              | pt_code[0] | pt_code[1] |count-3|
              +------------+------------+-------+
 
-  count >= 20 ¤Î¾ì¹ç
+  count >= 20 の場合
 
                 pt_len[2]    CBIT{9}
               <----------> <------>
 
                 pt_len[2]    CBIT{9}
               <----------> <------>
@@ -4461,7 +4524,7 @@ c_len[i] == 0 
              | pt_code[2] |count-20|
              +------------+--------+
 
              | pt_code[2] |count-20|
              +------------+--------+
 
-c_len[i] != 0 ¤Î¾ì¹ç
+c_len[i] != 0 の場合
 
               pt_len[c_len[i]+2]
              +-------------------+
 
               pt_len[c_len[i]+2]
              +-------------------+
@@ -4470,28 +4533,33 @@ c_len[i] != 0 
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤³¤¦¤·¤Æ¡¢Ê¸»ú¤Î Huffman Éä¹æɽ¤Ï¡¢pt_len[] ¤È pt_code[](pt_code[] ¤Ï
-¤Ä¤Þ¤ê c_len[] ¤Î Huffman Éä¹æ)¤ò½ÐÎϤ¹¤ë¤³¤È¤Çɽ¸½¤µ¤ì¤ë¡£c_code[] ¤¬
-½ÐÎϤµ¤ì¤Æ¤Ê¤¤¤È»×¤¦¤«¤â¤·¤ì¤Ê¤¤¤¬¡¢¤ª¤½¤é¤¯¡¢decode ½èÍý¤¬ c_len[] ¤ÎÃÍ
-¤«¤é·×»»¤·¤Æµá¤á¤Æ¤¤¤ë¤Î¤Ç¤Ï¤Ê¤¤¤«¤È»×¤ï¤ì¤ë¡£¤³¤ì¤Ï decode ½èÍý¤Î²òÆÉ
-¤ÇÌÀ¤é¤«¤Ë¤Ê¤ë¤À¤í¤¦¡£
+こうして、文字の Huffman 符号表は、pt_len[] と pt_code[](pt_code[] は
+つまり c_len[] の Huffman 符号)を出力することで表現される。c_code[] が
+出力されてないと思うかもしれないが、おそらく、decode 処理が c_len[] の値
+から計算して求めているのではないかと思われる。これは decode 処理の解読
+で明らかになるだろう。
 
 
-¤³¤Î¸å¡¢send_block() ¤Ï¡¢(C) ¤Ç¡¢<off> ¤Î Huffman Éä¹æɽ¤ò½ÐÎϤ¹¤ë¤Î¤À
-¤¬¡¢
+# 少し変なことを書いている。pt_code[] の出力は、c_len[] の Huffman 符号
+# を出力しているのであり、Huffman 木の情報として出力しているわけではな
+# い。つまり、c_code[] が出力されていないのと同様に pt_code[] も出力は
+# していない。
+
+この後、send_block() は、(C) で、<off> の Huffman 符号表を出力するのだ
+が、
 
         write_pt_len(np, pbit, -1);
 
 
         write_pt_len(np, pbit, -1);
 
-¤³¤ì¤Ï¡¢Àè¤Î pt_len[] ¤Î½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥È¤ÈƱ¤¸¤Ê¤Î¤Ç¾ÜºÙ¤Ï¤Ï¤·¤ç¤í¤¦¡£
-¤¿¤À¤·¡¢º£Å٤Πpt_len[] ¤Î½ÐÎϤǤϠwrite_pt_len() ¤ÎÂè»°°ú¿ô i_special 
-¤¬ -1 ¤Ç»ØÄꤵ¤ì¤Æ¤¤¤Æ¡¢i_special ÈÖÌܤΠpt_len[i_special..6] ¤Ë´Ø¤·¤Æ
-ÆÃÊÌ°·¤¤¤¬¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤ë¤È¤³¤í¤¬°Û¤Ê¤ë¡£
+これは、先の pt_len[] の出力フォーマットと同じなので詳細ははしょろう。
+ただし、今度の pt_len[] の出力では write_pt_len() の第三引数 i_special 
+が -1 で指定されていて、i_special 番目の pt_len[i_special..5] に関して
+特別扱いがなくなっているところが異なる。
 
 
-np ¤ä pbit ¤Î°ÕÌ£¤â¤³¤Î»þÅÀ¤Ç¤ï¤«¤ë¤Î¤Ç°ì±þÀâÌÀ¤·¤Æ¤ª¤¯¡£np, pbit ¤½¤·
-¤Æ¡¢LHA ¤Î°µ½Ì method ¤È¤Î´Ø·¸¤Ï°Ê²¼¤Îɽ¤ÎÄ̤ê¤Ê¤Î¤À¤¬¡¢np ¤Ï¡¢<off>¤Î
-ºÇÂçbitĹ+1 ¤À¡£<off> ¤ÎºÇÂçbitĹ¤Ï¤¹¤Ê¤ï¤Á dicbit ¤Ê¤Î¤Ç¡¢np ¤Ï¡¢
-dicbit + 1 ¤Ç¤¢¤ë¡£-lh4- ¤Î¤È¤­¤Ëdicbit + 2 ¤Ê¤Î¤¬ÉԻ׵ĤÀ¤¬¡¢¤³¤ì¤ÏÎò
-»ËŪ¤ÊÍýͳ¤À¤í¤¦¤È»×¤ï¤ì¤ë¡£pbit ¤Ï¡¢ÃÍ np ¤ò½ÐÎϤ¹¤ë¤Î¤ËɬÍפʠbit ¿ô
-¤Ê¤Î¤Çɽ¤ÎÄ̤ê¤Ë¤Ê¤ë¡£
+np や pbit の意味もこの時点でわかるので一応説明しておく。np, pbit そし
+て、LHA の圧縮 method との関係は以下の表の通りなのだが、np は、<off> の
+最大 bit 長 + 1 だ。<off> の最大 bit 長はすなわち dicbit なので、np は、
+dicbit + 1 である。-lh4- のときに dicbit + 2 なのが不思議だが、これは歴
+史的な理由だろうと思われる。pbit は、値 np を出力するのに必要な bit 数
+なので表の通りになる。
 
     method  dicbit  np  pbit
    --------------------------
 
     method  dicbit  np  pbit
    --------------------------
@@ -4500,11 +4568,11 @@ dicbit + 1 
     -lh6-   15      16  5
     -lh7-   16      17  5
 
     -lh6-   15      16  5
     -lh7-   16      17  5
 
-¤Þ¤È¤á¤ë¤È LHA ¤Ë¤ª¤±¤ë°µ½Ì¥Õ¥¡¥¤¥ë¤Î¹½Â¤¤Ï°Ê²¼¤ÎϢ³¤Ç¤¢¤ë¤È¸À¤¨¤ë¤è
-¤¦¤À¡£
+まとめると LHA における圧縮ファイルの構造は以下の連続であると言えるよ
+うだ。
 
 ----------------------------------------------------------------------------
 
 ----------------------------------------------------------------------------
-< LHA ¥Õ¥¡¥¤¥ë¤Î¹½Â¤(1 ¥Ö¥í¥Ã¥¯Ê¬) >
+< LHA ファイルの構造(1 ブロック分) >
 
     +-----------+
     | blocksize |
 
     +-----------+
     | blocksize |
@@ -4512,48 +4580,48 @@ dicbit + 1 
        16bit
 
     +-----+--------------------+
        16bit
 
     +-----+--------------------+
-    | len |      pt_len        | c_len¤Î¥Ï¥Õ¥Þ¥óÉä¹æɽ
+    | len |      pt_len        | c_lenのハフマン符号表
     +-----+--------------------+
       5bit        ?? bit
       TBIT
 
     +-------+------------------+
     +-----+--------------------+
       5bit        ?? bit
       TBIT
 
     +-------+------------------+
-    |  len  |     c_len        | Ê¸»ú¤ÈŤµ¤Î¥Ï¥Õ¥Þ¥óÉä¹æɽ
+    |  len  |     c_len        | 文字と長さのハフマン符号表
     +-------+------------------+
       9bit        ?? bit
       CBIT
 
     +---------+--------------------+
     +-------+------------------+
       9bit        ?? bit
       CBIT
 
     +---------+--------------------+
-    |   len   |   pt_len           | °ÌÃ֤ΥϥեޥóÉä¹æɽ
+    |   len   |   pt_len           | 位置のハフマン符号表
     +---------+--------------------+
      pbit         ?? bit
                                (pbit=4bit(lh4,5) or 5bit(lh6,7))
 
     +---------------------+
     +---------+--------------------+
      pbit         ?? bit
                                (pbit=4bit(lh4,5) or 5bit(lh6,7))
 
     +---------------------+
-    |  °µ½Ìʸ             |
+    |  圧縮文             |
     +---------------------+
 
 ----------------------------------------------------------------------------
 
     +---------------------+
 
 ----------------------------------------------------------------------------
 
-¤³¤³¤Þ¤Ç¤Î²òÆɤǤϺÙÉô¤ò¤«¤Ê¤ê¤Ï¤·¤ç¤Ã¤¿¤¬¡¢decode ½èÍý¤ò¸«¤ì¤Ð¤ï¤«¤ë
-¤³¤È¤â¤¢¤ë¤Ç¤¢¤í¤¦¤³¤È¤ò´üÂÔ¤·¤Æ¤¤¤ë¡£°Ê¹ß¡¢decode ½èÍý¤ÎÆâÍƤò½èÍý¤Î
-ή¤ì¤òÄɤ¦¤³¤È¤Ç³Îǧ¤·¤è¤¦¡£
+ここまでの解読では細部をかなりはしょったが、decode 処理を見ればわかる
+こともあるであろうことを期待している。以降、decode 処理の内容を処理の
+流れを追うことで確認しよう。
 
 
-¤Ç¤Ï¡¢¤¤¤è¤¤¤è decode ½èÍý¤Î²òÆɤËÆþ¤ë¡£¤³¤ì¤¬½ª¤ì¤Ð LHA ¤Î½èÍý¤ÎÁ´ËÆ
-¤ò°ì±þ¤ÏÌÖÍ夷¤¿¤³¤È¤Ë¤Ê¤ë¤Î¤Ç¡¢µ¤¹ç¤¤¤òÆþ¤ì¤Æ¿Ê¤á¤è¤¦¡£
+では、いよいよ decode 処理の解読に入る。これが終れば LHA の処理の全貌
+を一応は網羅したことになるので、気合いを入れて進めよう。
 
 
-decode ½èÍý¤Ï°Ê²¼¤Î´Ø¿ô¤«¤éÀ®¤Ã¤Æ¤¤¤ë¡£¤³¤ì¤é¤Ï¡¢slide.c ¤Î decode ´Ø
-¿ô¤«¤é¸Æ¤Ð¤ì¤Æ¤¤¤ë¡£
+decode 処理は以下の関数から成っている。これらは、slide.c の decode 関
+数から呼ばれている。
 
 
-huf.c:decode_c_st1()          /* Ê¸»ú¡¢Ä¹¤µ¤Î decode ½èÍý */
-huf.c:decode_p_st1()          /* °ÌÃ֤Πdecode ½èÍý */
-huf.c:decode_start_st1()      /* decode ½èÍý¤Î½é´ü²½ */
+huf.c:decode_c_st1()          /* 文字、長さの decode 処理 */
+huf.c:decode_p_st1()          /* 位置の decode 処理 */
+huf.c:decode_start_st1()      /* decode 処理の初期化 */
 
 
-                        (¼ÂºÝ¤Ë¤Ï¡¢struct decode_option ¤Î decode_c,
-                        decode_p, decode_start ¤ò²ð¤·¤Æ¸Æ¤Ð¤ì¤ë)
+                        (実際には、struct decode_option の decode_c,
+                        decode_p, decode_start を介して呼ばれる)
 
 
-decode_start_st1() ¤Ï¡¢°Ê²¼¤ÎÄ̤ê¤À¡£¤³¤ì¤Ï encode_start_st1() ¤Î¤È¤­
-¤ÈÆÃÊÌÊѤï¤ë½ê¤Ï¤Ê¤¤¡£ÆäËÀâÌÀ¤ÎɬÍפϤʤ¤¤À¤í¤¦¡£
+decode_start_st1() は、以下の通りだ。これは encode_start_st1() のとき
+と特別変わる所はない。特に説明の必要はないだろう。
 
 void
 decode_start_st1( /* void */ )
 
 void
 decode_start_st1( /* void */ )
@@ -4574,7 +4642,7 @@ decode_start_st1( /* void */ )
     blocksize = 0;
 }
 
     blocksize = 0;
 }
 
-¤Ç¤Ï¡¢decode_c_st1() ¤ò¸«¤è¤¦¡£
+では、decode_c_st1() を見よう。
 
 unsigned short
 decode_c_st1( /*void*/ )
 
 unsigned short
 decode_c_st1( /*void*/ )
@@ -4606,7 +4674,7 @@ decode_c_st1( /*void*/ )
     return j;
 }
 
     return j;
 }
 
-blocksize == 0 ¤Î¾ì¹ç¤Ë
+blocksize == 0 の場合に
 
     if (blocksize == 0) {
         blocksize = getbits(16);
 
     if (blocksize == 0) {
         blocksize = getbits(16);
@@ -4615,19 +4683,18 @@ blocksize == 0 
         read_pt_len(np, pbit, -1);
     }
 
         read_pt_len(np, pbit, -1);
     }
 
-¤È¡¢¤¤¤í¤¤¤í¤È¤ä¤Ã¤Æ¤¤¤ë¤¬¤³¤ÎÉôʬ¤Ï¤¹¤°ÁÛÁü¤¬¤Ä¤¯¡£< LHA ¥Õ¥¡¥¤¥ë¤Î¹½
-¤ > ¤Î¥Ï¥Õ¥Þ¥óÉä¹æɽ¤òÆɤ߹þ¤ó¤Ç¤¤¤ë¤Î¤À¤í¤¦¡£¤½¤¦¤·¤Æ¡¢°ìÅÙÆɤ߹þ¤ó
-¤À¸å¤Ï¸å³¤Î½èÍý¤Ç 1 ¥Ö¥í¥Ã¥¯Ê¬(blocksize Ê¬)´°Î»¤¹¤ë¤Þ¤Ç decode ¤ò¹Ô
-¤¦¤À¤±¤À¡£
+と、いろいろとやっているがこの部分はすぐ想像がつく。< LHA ファイルの構
+造 > のハフマン符号表を読み込んでいるのだろう。そうして、一度読み込んだ
+後は後続の処理で blocksize 分読み込むまで decode を行うだけだ。
 
     blocksize--;
     j = c_table[bitbuf >> 4];
 
 
     blocksize--;
     j = c_table[bitbuf >> 4];
 
-decode ½èÍý¤Ï¥Ï¥Õ¥Þ¥óÉä¹æɽ¤òɽ°ú¤­¤¹¤ë¤À¤±¤Ê¤Î¤Çñ½ã¤À¡£bitbuf >> 4 
-¤Ï¡¢bitbuf >> (16 - 12) ¤ÈÆɤßÊѤ¨¤¿Êý¤¬¤ï¤«¤ê¤ä¤¹¤¤¡£¤³¤ì¤Ï°ÊÁ°²¿ÅÙ¤â
-½Ð¤¿·Á¤À¤¬ bitbuf ¤Î¾å°Ì 12 bit ¤ò¼è¤ê½Ð¤·¤Æ¤¤¤ë¡£¤½¤¦¤·¤Æ¤½¤ÎÃÍ(¥Ï¥Õ
-¥Þ¥óÉä¹æ)¤ò¸µ¤Ëɽ°ú¤­¤·¤¿·ë²Ì j ¤¬Éü¹æ¤·¤¿Ê¸»ú¤È¤Ê¤ë¡£¤Ê¤¼ 12 bit ¤Ê¤Î¤«
-¤Ï¤è¤¯¤ï¤«¤é¤Ê¤¤¸å¤Ç¹Í¤¨¤è¤¦¡£¤³¤Î¸å¤ÎÉôʬ¤Ç¡¢
+decode 処理はハフマン符号表を表引きするだけなので単純だ。bitbuf >> 4 
+は、bitbuf >> (16 - 12) と読み変えた方がわかりやすい。これは以前何度も
+出た形だが bitbuf の上位 12 bit を取り出している。そうしてその値(ハフ
+マン符号)を元に表引きした結果 j が復号した文字となる。なぜ 12 bit なのか
+はよくわからない後で考えよう。この後の部分で、
 
     if (j < NC)
         fillbuf(c_len[j]);
 
     if (j < NC)
         fillbuf(c_len[j]);
@@ -4645,43 +4712,43 @@ decode 
     }
     return j;
 
     }
     return j;
 
-j < NC ¤Î¾ì¹ç¤Ï c_len[j] ¤Ç¥Ï¥Õ¥Þ¥óÉä¹æ¤Î¥Ó¥Ã¥ÈĹʬ¤ò fillbuf() ¤·¤Æ¤¤
-¤ë¡£¤Ä¤Þ¤êÀèÄøɽ°ú¤­¤·¤¿ 12 bit ¤Î¤¦¤Á c_len[j] bit ¤¬ËÜÅö¤Î¥Ï¥Õ¥Þ¥óÉä
-¹æ¤Ê¤Î¤À¤¬¡¢É½°ú¤­¤ÎºÝ¤Ë¼ÂºÝ¤Î¥Ó¥Ã¥ÈŤòµ¤¤Ë¤¹¤ëɬÍפ¬¤Ê¤¤¤Î¤¬ÆÃħŪ¤À¡£
+j < NC の場合は c_len[j] でハフマン符号のビット長分を fillbuf() してい
+る。つまり先程表引きした 12 bit のうち c_len[j] bit が本当のハフマン符
+号なのだが、表引きの際に実際のビット長を気にする必要がないのが特徴的だ。
 
 
-else ¤ÎÉôʬ¤Ï¡¢j ¤òµá¤áľ¤·¤Æ¤¤¤ë¤³¤È¤«¤é¡¢¤É¤¦¤ä¤éÉä¹æɽ¤«¤é¤Îɽ°ú¤­
-¤Ç¤ÏÉü¹æ¤Ç¤­¤Ê¤¤¾ì¹ç¤òɽ¤·¤Æ¤¤¤ë¤é¤·¤¤¡£¤³¤Î¾ì¹ç¡¢É½°ú¤­¤Ë»ÈÍѤ·¤¿ 12
-bit ¤ò¼Î¤Æ(fillbuf(12))¡¢¥Ï¥Õ¥Þ¥óÌÚ(left[], right[])¤òé¤ë»ö¤Ç¡¢Éü¹æ¤ò
-¹Ô¤Ã¤Æ¤¤¤ë¡£¤³¤Î¸å¡¢fillbuf(c_len[j] - 12) ¤·¤Æ¤¤¤ë¤³¤È¤«¤é¡¢Éä¹æĹ¤Ï 
-12 bit °Ê¾å¤¢¤ë¤Î¤À¤í¤¦¡£
+else の部分は、j を求め直していることから、どうやら符号表からの表引き
+では復号できない場合を表しているらしい。この場合、表引きに使用した 12
+bit を捨て(fillbuf(12))、ハフマン木(left[], right[])を辿る事で、復号を
+行っている。この後、fillbuf(c_len[j] - 12) していることから、符号長は 
+12 bit 以上あるのだろう。
 
 
-decode_c_st1() ¤¬ decode ¤¹¤ë°µ½Ìʸ¤Î¹½Â¤¤Ï¿Þ¤Çɽ¤¹¤È°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë
+decode_c_st1() が decode する圧縮文の構造は図で表すと以下のようになる
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-j < NC ¤Î¾ì¹ç (c_len[j] < 12 ¤Î¾ì¹ç)
+j < NC の場合 (c_len[j] < 12 の場合)
 
          <-  c_len[j] ->
          <----- 12 ------->
         +--------------+----------
 
          <-  c_len[j] ->
          <----- 12 ------->
         +--------------+----------
-°µ½Ìʸ  | ¥Ï¥Õ¥Þ¥óÉä¹æ |
+圧縮文  | ハフマン符号 |
         +--------------+----------
 
         +--------------+----------
 
-j >= NC ¤Î¾ì¹ç (c_len[j] > 12 ¤Î¾ì¹ç)
+j >= NC の場合 (c_len[j] > 12 の場合)
 
          <------------ c_len[j] --------->
          <------ 12 ------>
         +------------------+--------------+--------
 
          <------------ c_len[j] --------->
          <------ 12 ------>
         +------------------+--------------+--------
-°µ½Ìʸ  |    root          | ¥Ï¥Õ¥Þ¥óÉä¹æ |
+圧縮文  |    root          | ハフマン符号 |
         +------------------+--------------+--------
 
         +------------------+--------------+--------
 
-            root: ¥Ï¥Õ¥Þ¥óÌڤκ¬
+            root: ハフマン木の根
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-¤Ï¤¿¤·¤Æ¡¢°µ½Ì½èÍý¤Î¤È¤­¤Ë¤³¤Î¤è¤¦¤Ê¹½Â¤¤òºî¤Ã¤¿³Ð¤¨¤Ï¤Ê¤¤¤Î¤À¤¬¤É¤¦¤¤
-¤¦¤³¤È¤À¤í¤¦¡©²ÝÂê¤ò»Ä¤·¤Ä¤Äº£Å٤Ϡdecode_p_st1() (°ÌÃÖ¤ÎÉü¹æ½èÍý)¤ò¸«
-¤ë¡£
+はたして、圧縮処理のときにこのような構造を作った覚えはないのだがどうい
+うことだろう?課題を残しつつ今度は decode_p_st1() (位置の復号処理)を見
+る。
 
 unsigned short
 decode_p_st1( /* void */ )
 
 unsigned short
 decode_p_st1( /* void */ )
@@ -4708,53 +4775,53 @@ decode_p_st1( /* void */ )
     return j;
 }
 
     return j;
 }
 
-ÀèÄø¤ÈƱ¤¸¤À¡£º£Å٤ϡ¢bitbuf ¤Î¤¦¤Á 8 bit ¤ò»ÈÍѤ·¤Æɽ°ú¤­¤ò¹Ô¤¤¡¢
-j < np ¤Ê¤é pt_len[j] ¤òµÍ¤á¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥Ï¥Õ¥Þ¥óÌÚ¤òé¤Ã¤Æ¤¤¤ë¡£
-Éü¹æ¤·¤¿ j ¤Ï°ÌÃÖ¤òɽ¤¹ÃͤΠbit Ä¹¤Ê¤Î¤ÇºÇ¸å¤Ë
+先程と同じだ。今度は、bitbuf のうち 8 bit を使用して表引きを行い、
+j < np なら pt_len[j] を詰め、そうでなければハフマン木を辿っている。
+復号した j は位置を表す値の bit 長なので最後に
 
         j = (1 << (j - 1)) + getbits(j - 1);
 
 
         j = (1 << (j - 1)) + getbits(j - 1);
 
-¤Ç¡¢ËÜÅö¤Î°ÌÃÖ¤ÎÃͤòÆɤó¤Ç¤¤¤ë(encode_p() ¤¬¤½¤¦¤¤¤¦½èÍý¤À¤Ã¤¿»ö¤ò»×¤¤
-½Ð¤½¤¦)¡£
+で、本当の位置の値を読んでいる(encode_p() がそういう処理だった事を思い
+出そう)。
 
 
-decode_p_st1() ¤¬ decode ¤¹¤ë°µ½Ìʸ¤Î¹½Â¤¤Ï¿Þ¤Çɽ¤¹¤È°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë
+decode_p_st1() が decode する圧縮文の構造は図で表すと以下のようになる
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-j < np ¤Î¾ì¹ç (pt_len[j] < 8 ¤Î¾ì¹ç)
+j < np の場合 (pt_len[j] < 8 の場合)
 
          <- pt_len[j] ->
          <------ 8 ------->
         +--------------+----------
 
          <- pt_len[j] ->
          <------ 8 ------->
         +--------------+----------
-°µ½Ìʸ  | ¥Ï¥Õ¥Þ¥óÉä¹æ |
+圧縮文  | ハフマン符号 |
         +--------------+----------
 
         +--------------+----------
 
-j >= np ¤Î¾ì¹ç (pt_len[j] > 8 ¤Î¾ì¹ç)
+j >= np の場合 (pt_len[j] > 8 の場合)
 
          <----------- pt_len[j] --------->
          <------ 8 ------->
         +------------------+--------------+----------+----------
 
          <----------- pt_len[j] --------->
          <------ 8 ------->
         +------------------+--------------+----------+----------
-°µ½Ìʸ  |      root        | ¥Ï¥Õ¥Þ¥óÉä¹æ | °ÌÃÖ¤ÎÃÍ |
+圧縮文  |      root        | ハフマン符号 | 位置の値 |
         +------------------+--------------+----------+----------
 
         +------------------+--------------+----------+----------
 
-            root: ¥Ï¥Õ¥Þ¥óÌڤκ¬
+            root: ハフマン木の根
 
 ----------------------------------------------------------------------------
 
 
 ----------------------------------------------------------------------------
 
-°Ê¾å¤¬¡¢decode ½èÍý¤Î³µÍפÀ¡£¤³¤³¤Þ¤Ç¤Î½èÍý¤ÏÊ̤ˤɤ¦¤È¤¤¤¦»ö¤â¤Ê¤¤¤À
-¤í¤¦¡£decode ½èÍý¤Î¥­¥â¤Ï¡¢°µ½Ìʸ¤ËËä¤á¹þ¤ó¤À¥Ï¥Õ¥Þ¥óÉä¹æɽ¤ÎÆɤ߹þ¤ß
-¤Ë¤¢¤ë¡£blocksize == 0 ¤Î¤È¤­¤Ë¡¢decode_c_st1() ¤Ç¸Æ¤Ð¤ì¤ë 
-read_pt_len(), read_c_len() ¤À¡£¤³¤ì¤Ë¤è¤ê¡¢decode ½èÍý¤Ç»ÈÍѤ¹¤ë¥Æ¡¼¥Ö¥ë
+以上が、decode 処理の概要だ。ここまでの処理は別にどうという事もないだ
+ろう。decode 処理のキモは、圧縮文に埋め込んだハフマン符号表の読み込み
+にある。blocksize == 0 のときに、decode_c_st1() で呼ばれる 
+read_pt_len(), read_c_len() だ。これにより、decode 処理で使用するテーブル
 
 
-c_table[]       ¥Ï¥Õ¥Þ¥óÉä¹æ -> Ê¸»ú¤ÎÊÑ´¹¥Æ¡¼¥Ö¥ë
-c_len[]         ¥Ï¥Õ¥Þ¥óÉä¹æ -> ¥Ï¥Õ¥Þ¥óÉä¹æ¤Î¥Ó¥Ã¥ÈŤÎÂбþ
-pt_table[]      ¥Ï¥Õ¥Þ¥óÉä¹æ -> °ÌÃ֤ΥӥåÈŤÎÊÑ´¹¥Æ¡¼¥Ö¥ë
-pt_len[]        ¥Ï¥Õ¥Þ¥óÉä¹æ -> ¥Ï¥Õ¥Þ¥óÉä¹æ¤Î¥Ó¥Ã¥ÈŤÎÂбþ
-left[]          ¥Ï¥Õ¥Þ¥óÌÚ(º¸¤Î¥Î¡¼¥É)
-right[]         ¥Ï¥Õ¥Þ¥óÌÚ(±¦¤Î¥Î¡¼¥É)
+c_table[]       ハフマン符号 -> 文字の変換テーブル
+c_len[]         ハフマン符号 -> ハフマン符号のビット長の対応
+pt_table[]      ハフマン符号 -> 位置のビット長の変換テーブル
+pt_len[]        ハフマン符号 -> ハフマン符号のビット長の対応
+left[]          ハフマン木(左のノード)
+right[]         ハフマン木(右のノード)
 
 
-¤¬¹½ÃÛ¤µ¤ì¤ë¡£¤³¤ÎÉôʬ¤ÎÊý¤¬ decode ½èÍýËÜÂΤè¤ê¤ä¤ä¤³¤·¤½¤¦¤À¡£
-¤Ç¤Ï¡¢¤³¤ì¤é¤ò¸«¤Æ¹Ô¤³¤¦¡£
+が構築される。この部分の方が decode 処理本体よりややこしそうだ。
+では、これらを見て行こう。
 
     if (blocksize == 0) {
         blocksize = getbits(16);
 
     if (blocksize == 0) {
         blocksize = getbits(16);
@@ -4763,7 +4830,7 @@ right[]         
         read_pt_len(np, pbit, -1);
     }
 
         read_pt_len(np, pbit, -1);
     }
 
-ºÇ½é¤Ï¡¢read_pt_len(NT, TBIT, 3) ¤«¤é
+最初は、read_pt_len(NT, TBIT, 3) から
 
 static void
 read_pt_len(nn, nbit, i_special)
 
 static void
 read_pt_len(nn, nbit, i_special)
@@ -4806,8 +4873,8 @@ read_pt_len(nn, nbit, i_special)
     }
 }
 
     }
 }
 
-¼ÂºÝ¡¢Â礷¤¿»ö¤Ï¤Ê¤¤¡£< pt_len[] ¤Î½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥È > ¤Ë¤·¤¿¤¬¤Ã¤Æ¡¢
-pt_len[] ¤òÆɤßľ¤·¤Æ¤¤¤ë¤À¤±¤À¡£read_c_len() ¤â¸«¤è¤¦¡£
+実際、大した事はない。< pt_len[] の出力フォーマット > にしたがって、
+pt_len[] を読み直しているだけだ。read_c_len() も見よう。
 
 static void
 read_c_len( /* void */ )
 
 static void
 read_c_len( /* void */ )
@@ -4855,18 +4922,23 @@ read_c_len( /* void */ )
     }
 }
 
     }
 }
 
-¤³¤Á¤é¤â¡¢< c_len[] ¤Î½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥È > ¤Ë¤·¤¿¤¬¤Ã¤Æ¡¢c_len[] ¤òÆɤß
-ľ¤·¤Æ¤¤¤ë¤À¤±¤À¡£·ë¶É¥­¥â¤È¤Ê¤ë¤Î¤Ï¡¢make_table() ¤Ë¤¢¤ë¤é¤·¤¤¡£¤³¤Î
-´Ø¿ô¤Ë¤è¤ê¡¢Æɤ߹þ¤ó¤À pt_len[], c_len[] ¤«¤é pt_table[], c_table[]
-(¤½¤·¤Æ¡¢¥Ï¥Õ¥Þ¥óÌÚ left[], right[])¤ò¹½ÃÛ¤·¤Æ¤¤¤ë¤Î¤À¤í¤¦¡£
+こちらも、< c_len[] の出力フォーマット > にしたがって、c_len[] を読み
+直しているだけだ。
+# このあたりになると解析がかなり雑になっている(当時疲れていたのだろう)。
+# 最終的には後述の「LHA ファイルの構造(まとめ)」にて、再度検討しなおし
+# ているのでそちらを見て欲しい。不明だった部分もここですべて明らかにし
+# ている。
+結局キモとなるのは、make_table() にあるらしい。この関数により、読み込ん
+だ pt_len[], c_len[] から pt_table[], c_table[] (そして、ハフマン木
+left[], right[])を構築しているのだろう。
 
 
-·ë¶É¡¢decode ½èÍý read_c_len(), read_pt_len() ¤òÆɤó¤Ç¤â¤Ê¤¼¤³¤Î¤è¤¦¤Ê
-Éä¹æ²½¤ò¹Ô¤Ã¤Æ¤¤¤ë¤Î¤«¤è¤¯¤ï¤«¤é¤Ê¤«¤Ã¤¿¡£²¿¤«Åý·×Ū¤Êº¬µò¤Ç¤â¤¢¤ë¤Î¤À
-¤í¤¦¤«¡©¤½¤ì¤È¤â LHA ¤Ë¤È¤Ã¤ÆÎò»ËŪ¤Ê»ö¾ð¤Ç¤â¤¢¤ë¤Î¤«¡©¤³¤ì¤Ë´Ø¤·¤Æ¤Ï
-ÊÌÅÓ¸¡¾Ú¤ÎɬÍפ¬¤¢¤ë¤À¤í¤¦¡£
+結局、decode 処理 read_c_len(), read_pt_len() を読んでもなぜこのような
+符号化を行っているのかよくわからなかった。何か統計的な根拠でもあるのだ
+ろうか?それとも LHA にとって歴史的な事情でもあるのか?これに関しては
+別途検証の必要があるだろう。
 
 
-¤Ç¤Ï¡¢ºÇ¸å¤Î´Ø¿ô make_table() ¤ò²òÆɤ·¤è¤¦¡£¤³¤ì¤Ï¡¢maketbl.c ¤ÇÄêµÁ¤µ
-¤ì¤Æ¤¤¤ë¡£
+では、最後の関数 make_table() を解読しよう。これは、maketbl.c で定義さ
+れている。
 
 void
 make_table(nchar, bitlen, tablebits, table)
 
 void
 make_table(nchar, bitlen, tablebits, table)
@@ -4958,7 +5030,7 @@ make_table(nchar, bitlen, tablebits, table)
     }
 }
 
     }
 }
 
-½ç¤Ë¸«¤Æ¹Ô¤³¤¦¡£
+順に見て行こう。
 
     /* (A) */
     avail = nchar;
 
     /* (A) */
     avail = nchar;
@@ -4969,18 +5041,18 @@ make_table(nchar, bitlen, tablebits, table)
         weight[i] = 1 << (16 - i);
     }
 
         weight[i] = 1 << (16 - i);
     }
 
-avail ¤Ï¤ª¤½¤é¤¯ maketree.c:make_tree() ¤Ç¤½¤¦¤Ç¤¢¤Ã¤¿¤è¤¦¤Ë¡¢ÌÚ¤ÎÀá¤Î
-½é´üÃͤÀ¤í¤¦¤ÈͽÁÛ¤·¤Æ¤ª¤¯¡£count[], weight[] ¤â¡¢maketree.c ¤Ç¤Î 
-len_cnt[] weight[] ¤ÈƱµÁ¤À¤í¤¦(¤¹¤Ê¤ï¤Á¡¢count[i] ¤Ï¡¢Ìڤο¼¤µ i ÈÖÌÜ
-¤ÎÍդοô¡¢weight[i] ¤Ï½Å¤ß)
+avail はおそらく maketree.c:make_tree() でそうであったように、木の節の
+初期値だろうと予想しておく。count[], weight[] も、maketree.c での 
+len_cnt[] weight[] と同義だろう(すなわち、count[i] は、木の深さ i 番目
+の葉の数、weight[i] は重み)
 
     /* (B) */
     /* count */
     for (i = 0; i < nchar; i++)
         count[bitlen[i]]++;
 
 
     /* (B) */
     /* count */
     for (i = 0; i < nchar; i++)
         count[bitlen[i]]++;
 
-count[] ¤òµá¤á¤Æ¤¤¤ë¡£bitlen[i] ¤Ï¡¢Ê¸»ú i ¤Î¥Ï¥Õ¥Þ¥óÉä¹æ¤Ç¤Î bit Ä¹¤Ç
-¤¢¤Ã¤¿¡£¤ä¤Ï¤ê count[] ¤ÏͽÁÛÄ̤ê¤À¡£
+count[] を求めている。bitlen[i] は、文字 i のハフマン符号での bit 長で
+あった。やはり count[] は予想通りだ。
 
     /* (C) */
     /* calculate first code */
 
     /* (C) */
     /* calculate first code */
@@ -4992,9 +5064,9 @@ count[] 
     if ((total & 0xffff) != 0)
         error("make_table()", "Bad table (5)\n");
 
     if ((total & 0xffff) != 0)
         error("make_table()", "Bad table (5)\n");
 
-¤³¤ì¤Ï¡¢maketree.c:make_code() ¤ÎÁ°È¾Éôʬ¤È¤Þ¤Ã¤¿¤¯Æ±¤¸¤À¡£¤³¤ì¤Ë¤è¤ê¡¢
-¿¼¤µ i ¤ËÂФ·¤Æ¡¢°Ê²¼¤ÎÂбþɽ¤¬¤Ç¤­¤ë(¤³¤ì¤ÏÁ°¤Ë¤â½ñ¤¤¤¿¡£Li ¤Ï¡¢
-count[i] ¤ÎÃͤòɽ¤·¤Æ¤¤¤ë)¡£
+これは、maketree.c:make_code() の前半部分とまったく同じだ。これにより、
+深さ i に対して、以下の対応表ができる(これは前にも書いた。Li は、
+count[i] の値を表している)。
 
      i     count[i]   weight[i]   start[i]
  --------------------------------------------
 
      i     count[i]   weight[i]   start[i]
  --------------------------------------------
@@ -5003,9 +5075,9 @@ count[i] 
      3         L3        2^13      2^15 * L1 + 2^14 * L2
      4         L4        2^12      2^15 * L1 + 2^14 * L2 + 2^13 * L3
 
      3         L3        2^13      2^15 * L1 + 2^14 * L2
      4         L4        2^12      2^15 * L1 + 2^14 * L2 + 2^13 * L3
 
-¤³¤ì¤¬²¿¤òɽ¤¹¤«¤È¸À¤¦¤È¿¼¤µ i ¤ÎÉä¹æ(¤Ä¤Þ¤ê bit Ä¹ i ¤ÎÉä¹æ)¤Ï¡¢
-start[i] ¤«¤é start[i+1]-1 ¤ÎÈϰϤÎÃͤò»ý¤Ä¤È¸À¤¦»ö¤ò°ÕÌ£¤¹¤ë¡£ºÆÅÙ¡¢
-Îã¤Ç¼¨¤½¤¦¡£
+これが何を表すかと言うと深さ i の符号(つまり bit 長 i の符号)は、
+start[i] から start[i+1]-1 の範囲の値を持つと言う事を意味する。再度、
+例で示そう。
 
        /\               a: 0
       a /\              b: 10
 
        /\               a: 0
       a /\              b: 10
@@ -5017,10 +5089,10 @@ start[i] 
      2         2        2^14      2^15
      3         0        2^13      2^15 + 2^14 * 2
 
      2         2        2^14      2^15
      3         0        2^13      2^15 + 2^14 * 2
 
-¤³¤ì¤è¤ê¡¢¿¼¤µ 1 ¤ÎÍÕ a ¤Ï¡¢start[1] .. start[2]-1 ¤Ä¤Þ¤ê¡¢
-00000000 00000000 .. 01111111 11111111 ¤ÎÈϰϤÎÉä¹æ¤È¤Ê¤ë¡£
-¿¼¤µ 2 ¤ÎÍÕ b, c ¤Ï¡¢start[2] .. start[3]-1 ¤Ä¤Þ¤ê¡¢
-10000000 00000000 ... 11111111 11111111 ¤È¤Ê¤ë¡£
+これより、深さ 1 の葉 a は、start[1] .. start[2]-1 つまり、
+00000000 00000000 .. 01111111 11111111 の範囲の符号となる。
+深さ 2 の葉 b, c は、start[2] .. start[3]-1 つまり、
+10000000 00000000 ... 11111111 11111111 となる。
 
     /* (D) */
     /* shift data for make table. */
 
     /* (D) */
     /* shift data for make table. */
@@ -5030,106 +5102,2040 @@ start[i] 
         weight[i] >>= m;
     }
 
         weight[i] >>= m;
     }
 
-Íýͳ¤Ï¤ï¤«¤é¤Ê¤¤¤¬¡¢ºîÀ®¤¹¤ë¥Æ¡¼¥Ö¥ë¤ò°ú¿ô¤ÇÅϤµ¤ì¤¿ bit ¿ô¤Î¥Æ¡¼¥Ö¥ë
-¤Ë¤Ê¤ë¤è¤¦¼ÌÁü¤·¤Æ¤¤¤ë¡£¤Ä¤Þ¤ê¡¢ÃͤÎÈϰϤνé´üÃÍ start[] ¤È weight[]
-¤ò 16 - tablebits ¤Ç¥·¥Õ¥È¤¹¤ë¤³¤È¤Ç¡¢
+理由はわからないが、作成するテーブルを引数で渡された bit 数のテーブル
+になるよう写像している。つまり、値の範囲の初期値 start[] と weight[]
+を 16 - tablebits でシフトすることで、
 
          01111111 11111111
 
 
          01111111 11111111
 
-¤È¤¤¤¦¥Æ¡¼¥Ö¥ë¤ÎÃͤÏ(tablebits ¤¬ 12 ¤Ç¤¢¤ë¤È¤¹¤ë¤È)¡¢
+というテーブルの値は(tablebits が 12 であるとすると)、
 
          00000111 11111111
 
          00000111 11111111
+         <--> (16 - tablebits{12}) = 4 bit シフト
 
 
-¤ÎÃͤˤ¹¤ë¡£encode ¤¹¤ë¤È¤­¤Ï¡¢16 bit ¤Î¥Æ¡¼¥Ö¥ë¤ò¤½¤Î¤Þ¤Þ»ÈÍѤ·¤Æ¤¤¤¿
-¤Ë¤â´Ø¤ï¤é¤º decode ¤Î¤È¤­¤Ë¤Ï¥Æ¡¼¥Ö¥ë¤Î bit ¿ô¤ò¸º¤é¤·¤Æ¤¤¤ë¤Î¤À¡£¤Þ¤Ã
-¤¿¤¯Íýͳ¤¬¤ï¤«¤é¤Ê¤¤¡£
+の値にする。encode するときは、16 bit のテーブルをそのまま使用していた
+にも関わらず decode のときにはテーブルの bit 数を減らしているのだ。まっ
+たく理由がわからない。
 
 
-ÅöÁ³¡¢encode ¤Ç»ÈÍѤ·¤Æ¤¤¤¿¤È¤­¤Î¥Æ¡¼¥Ö¥ë¤è¤ê¾ðÊóÎ̤¬¸º¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢
-¤¹¤Ù¤Æ¤ò¥Æ¡¼¥Ö¥ë»²¾È¤Ç decode ¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Ê¤¤¡£¤½¤³¤Ç¡¢Â­¤ê¤Ê¤¤Éôʬ
-¤Ï¸å¤Î½èÍý¤ÇÌÚ¤òºî¤ë¤³¤È¤ÇÊä¤Ã¤Æ¤¤¤ë¤è¤¦¤À¡£
+当然、encode で使用していたときのテーブルより情報量が減っているので、
+すべてをテーブル参照で decode することはできない。そこで、足りない部分
+は後の処理で木を作ることで補っているようだ。
 
 
-bit ¿ô¤ò¸º¤é¤¹Íýͳ¤ò¹Í¤¨¤Æ¤ß¤ë¡£É½°ú¤­¤Î¹Í¤¨Êý¤Ï¡¢
+bit 数を減らす理由を考えてみる。まず表引きの考え方は、
 
        /\               a: 0
       a /\              b: 10
         b c             c: 11
 
 
        /\               a: 0
       a /\              b: 10
         b c             c: 11
 
-¤È¤¤¤¦ Huffman ÌڤˤĤ¤¤Æ¡¢
+という Huffman 木について、
 
      00: c_table[00] = a
      01: c_table[01] = a
      10: c_table[10] = b
      11: c_table[11] = c
 
 
      00: c_table[00] = a
      01: c_table[01] = a
      10: c_table[10] = b
      11: c_table[11] = c
 
-¤È¤¤¤¦¥Æ¡¼¥Ö¥ë¤òºîÀ®¤¹¤ë¤³¤È¤Ç Huffman Éä¹æ²½¤·¤¿¥Ó¥Ã¥ÈÎ󤫤éÉü¹æ¸ì¤ò
-ÆÀ¤ë¡£
+というテーブル、つまり
+
+         c_table[Huffman符号]=復号語
 
 
-HuffmanÉä¹æ¤«¤éʸ»ú¤òÆÀ¤ëɬÍפ¬¤¢¤ë¤Î¤Ç¡¢c_table[]¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ë¤Ï¡¢
-HuffmanÉä¹æ¤¬¼è¤ê¤¦¤ëºÇÂçÃͤò»ØÄê¤Ç¤­¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£16bit ¤ÎHuffman
-Éä¹æ¤ÎºÇÂçÃͤϠ65535 ¤Ç¤¢¤ë¤«¤é
+を作成することで Huffman 符号化したビット列から復号語を得られるようにす
+る。そして、Huffman 符号から文字を得る必要があるので、c_table[] のイン
+デックスには、Huffman 符号が取りうる最大値を指定できなければならない。
+16 bit のHuffman 符号の最大値は 65535 であるから表引きに必要な変数は、
 
 
-  unsigned short c_table[65535+1]; (unsigned short > NC-1)
+  unsigned short c_table[65535+1]; (unsigned short >= NC-1)
 
 
-¤È¤Ê¤ë¡£¤ª¤½¤é¤¯É½¤Î bit ¿ô¤ò¸º¤é¤·¤Æ¤¤¤ë¤Î¤Ï¤³¤ÎÂ礭¤Ê¥Æ¡¼¥Ö¥ë¤òºî¤ê¤¿
-¤¯¤Ê¤¤¤«¤é¤Ç¤Ï¤Ê¤¤¤«¤È»×¤ï¤ì¤ë¡£c_table[] ¤ÎÍ×ÁÇ¿ô¤òºÇÄã¸ÂɬÍפʿô¤ËÍÞ
-¤¨¤è¤¦¤È¤¹¤ë¤È°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¤¬¡¢
+となる。おそらく表の bit 数を減らしているのはこの大きなテーブルを作りた
+くないからではないかと思われる。c_table[] の要素数を最低限必要な数に抑
+えようとすると以下のようになるが、
 
       0: c_table[ 0=0] = a
      10: c_table[10=2] = b
      11: c_table[11=3] = c
 
 
       0: c_table[ 0=0] = a
      10: c_table[10=2] = b
      11: c_table[11=3] = c
 
-¤³¤ÎÎã¤Î¾ì¹ç¡¢c_table[1] ¤¬¶õ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¡¼¥Ö¥ë¤òºîÀ®¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê
-¤¤¡£¥Ï¥Ã¥·¥åɽ¤òºî¤ì¤Ð²Äǽ¤À¤¬¤½¤¦¤Ï¤»¤º¡¢c_table[] ¤ÎÍ×ÁÇ¿ô¤ò¸º¤é¤·¡¢
-ɽ°ú¤­¤Çɽ¤»¤Ê¤¤Éôʬ¤ÏÌÚ¤ÇÊä¤Ã¤Æ¤¤¤ë¤È¤¤¤¦¤³¤È¤À¡£
+この例の場合、c_table[1] が空であるようなテーブルを作成しなければならな
+い。ハッシュ表を作れば可能だがそうはせず、c_table[] の要素数を減らし、
+表引きで表せない部分は木で補っているということだ。
 
 
-¼ÂºÝ¤Î c_table[] ¤ÎÄêµÁ¤Ï¡¢
+実際の c_table[] の定義は、
 
   unsigned short c_table[4095+1];
 
 
   unsigned short c_table[4095+1];
 
-¤È¤Ê¤Ã¤Æ¤ª¤ê¡¢12 ¥Ó¥Ã¥È(2^12=4096)¤ÎHuffmanÉä¹æ¤Ë¤Ä¤¤¤Æɽ°ú¤­¤¬²Äǽ¤È¤Ê¤Ã
-¤Æ¤¤¤ë¡£¤½¤·¤Æ¡¢Éü¹æ¸ì¤Ï¡¢0...NC ¤ÎÈϰϤǤ¢¤ë¤«¤é¡¢
-    c_table[¥Ó¥Ã¥ÈÎó] < NC
-¤Î¾ì¹ç¤Ï¡¢¤½¤Î¤Þ¤Þɽ°ú¤­¤Ç
-    c_table[¥Ó¥Ã¥ÈÎó] >= NC
-¤Î¾ì¹ç¤Ï¡¢ÌڤΥ롼¥È¥Î¡¼¥É¤ò¼¨¤·¡¢¤½¤ÎÃͤ«¤éÌÚ¤òé¤Ã¤ÆÉü¹æ¤Ç¤­¤ë¤è¤¦¤Ë
-¤Ê¤Ã¤Æ¤¤¤ë¡£¿Þ¼¨¤¹¤ë¤È
+となっており、12 ビット(2^12=4096)の Huffman 符号について表引きが可能と
+なっている。そして、復号語は、0...NC の範囲であるから、
+    c_table[ビット列] < NC
+の場合は、そのまま表引きで
+    c_table[ビット列] >= NC
+の場合は、木のルートノードを示し、その値から木を辿って復号できるように
+なっている。図示すると
 
 ----------------------------------------------------------------------------
        .
       / \
 
 ----------------------------------------------------------------------------
        .
       / \
-     a   .           ... ³¬ÁØ:1   `.
+     a   .           ... 階層:1   `.
         / \                        |
         / \                        |
-        b            ... ³¬ÁØ:2    `> É½°ú¤­
+        b            ... 階層:2    `> 表引き
                            :       '
                            :       |
                            :       '
                            :       |
-            .        ... ³¬ÁØ:11   |
+            .        ... 階層:11   |
            / \                     |
            / \                     |
-          x   x      ... ³¬ÁØ:12  .' <- É½°ú¤­¤Î·ë²Ì x ¤¬(>=NC)¤Î¾ì¹ç¡¢
-             / \                        Ìڤγ¤­¤¬¤¢¤ë¤³¤È¤ò¼¨¤¹
-            .   .    ... ³¬ÁØ:13  `.
+          x   y      ... 階層:12  .' <- 表引きの結果 y が(>=NC)の場合、
+             / \                        木の続きがあることを示す
+            z   .    ... 階層:13  `.
                                    |
                                    |
-                           :        >   left[]/right[]¤Çɽ¸½ (³¬ÁØ12¤¬root)
-                     ... ³¬ÁØ:16  .'
+                           :        >   left[]/right[]で表現 (階層12がroot)
+                     ... 階層:16  .'
+----------------------------------------------------------------------------
+
+階層 12 より下(13 以上の bit 数の Huffman 符号)の Huffman 木について
+left[], right[] で表しているようだ。
+
+上の例で、13 ビットの Huffman 符号で符号化される復号語 z については、
+y にその木のルートノードの値(y > NC)が割り当てられる。
+
+図から明らかだが、復号語そのものを指す 12 bit の符号(たとえば x)と、木
+のルートノードを指す 12 bit の符号(たとえば y)が同じ符号となることはな
+い。これは Huffman 符号が語頭条件を満たすからである。
+
+では、y に割り当てる値はどのように決まるかというとおそらく NC 以上の数
+値を連番か何かで割り当てているのではないかと思われる。これについてはこ
+れ以降で確認する。
+
+なお、階層が深い Huffman 木とは、bit 長が長い符号であり、bit 長が長いと
+いうことは出現頻度が低いはずであるから、left[], right[] で木を辿る回数
+は少ないはずである。これは理にかなっている。
+
+あと、この木に必要なサイズはいくつであるかという点が気になる。これは、
+階層 13 以上のノードの数となるが、階層 n の二分木のノード(ここでは、葉
+および節をノードと呼ぶことにしている。