かなり環境が整ってきた

かなり環境が整ってきた.デスクトップ上にPCを集めて,椅子を動かさなくてもすべての作業をシームレスに実行できるようにした.中央のモニターにはビデオ切り替え機のボタン一つで,3機すべての画面を表示できる.キーボードとマウスはMouth Without Bordersで共有しているので,多少時間の掛かる処理を行うときは,正面のキーボードを使う.

IMG_20220310_134259_BURST001_COVER

快適だ!あと欲しいのは無線HDDだけだ.3TBくらいのHDDが手に入れば,バックアップをすべてこのHDDに移し,負荷を軽くした状態で常時完全スキャンが実施できるようになる.この無線HDDは言ってみれば,クラウドの代用のようなものだ.これができれば,万全と言ってよいのではないかと思う.いま悩んでいるのは,ポットを購入したものかどうか?という些細なことだ.現在はポットの代わりに炊飯器で代替しているが,それほど不便は感じていない.場合によっては,昔のようにヤカンでお湯を沸かすようにしてもいいかな?とも考えている.

IMG_20220220_225526

横書き機能もだいぶ整ってきたが,まだメモリ描画環境に切り替えると描画できなくなるという不具合が残っている.⇒ビットマップ生成の問題というより,再描画の問題なのではないか?そもそも,メモリ描画環境は論理座標系なのか物理座標系なのか?ビットマップにはピクセル単位で描画しているはずだから,当然物理座標系と考えられるが,そうなっているだろうか?少し頭を冷やして考えた方がよい.メモリ描画環境の内容をJPGファイルに保存してみた.下図のようになっている.

image image

つまり,メモリ描画環境ができ損なっているということだろう.これができていなければ話にならない.⇒メモリ描画環境生成時,Refreshに渡す引数のrcBoundsを空にして描画できた↑.ただし,背景は塗りつぶししていないため,真っ黒だ.⇒ようやく描画できるようになった.

image

この論理で正しいということを確認しておこう.通常,座標系は論理座標系と物理座標系に大別されるが,このシステムではそれに加えて第三の座標系とも呼ぶべき「直交座標系」が使われている.通常,論理座標系と物理座標系の変換は,主に座標のスケールと向き,および原点位置に限定され,X軸とY軸の交換までは実施しない.直交変換は図形データが描画プリミティブに渡される直前でXY座標の反転を実施,上位関数からは隠蔽される仕組みになっている.

この仕掛は概ね動作していると言ってよいと思われるが,ビットマップ描画環境では多少話が変わってくる.ビットマップメモリはそれ自体1個の描画デバイスコンテキストだが,書き込みと読み出しの両面で座標変換が必要になる.現行ではこれを以下のように処理している.

  1. メモリビットマップのCImageは物理座標系として扱う
  2. TREEVIEW::BuildBitMapでは,_CDC::LPtoDPで直交座標変換する
  3. TREEVIEW::buildBitMapでは,その逆変換を行って,描画を実行する
  4. ビットマップからスクリーンへの転送 BitBltでは座標変換は行わない

これでよいと思う.

povo 1.0 の20GBを一週間足らずで使い切ってしまった

今月は povo 1.0 の20GBを一週間足らずで使い切ってしまった.通常20日過ぎくらいまでは間に合っていたのだが…しかも,上限オーバーしてからがいきなり遅い.公称では最大1MBでこれまでは少なくとも700KBくらいはあったのだが…特に上りが異常に遅くなっている.常時三台テザリング接続するようにしているのが効いたのだろうか?三台と言っても,ネットにアクセスしている延べ時間はこれまでとほとんど変わらないはずなのだが…テザリングは所内LAN(WiFi)としても使っているので,それまでカウントすればかなりの通信量になるかもしれないが,それは計算には入っていないはず…1日使い放題220円というのは悪くないと思うが,追加1GB550円では手が出ない.

横書き系図をサポートするために座標軸のXY転換を実装しているところだが,なかなか思ったように進まない.90点程度の小さいサンプルは問題なく表示できているが,500点くらいの規模になるとまったく描画できなくなる.上の方の一部だけは正常表示されているが,下の方になるとまったく描画できていない.

VS2017の更新後,検索がまったく効かない状態になった.最初開発環境からインストールしていたが,いつまで経っても終わらないので(povo 1.0の1日使い放題でダウンロードは完了している)VSインストーラを起動して別途更新を実行し,一応完了したように思われたが,フォルダの全文検索がまったく動作」しないようになってしまった.とりあえず,VSのインストーラで「修復」を試みることにする.⇒回復した.再起動したら,カスペルスキーからまた「脅威」の報告.対象はD:\ZELKOVA 2022-03-02\debug\app.publish\ZelkovaTree2022.exeでハッシュを再計算すると,

066B292370D40C40CBD5B36FA2E0E0C98BA52889BF02CA462F6CEDBFB3D482A8

前回とまったく変化していない.ということはカスペルスキーはハッシュ値をまったく無視しているということになる.除外リストへの登録画面では「オブジェクト名」という項目があり,そこにはウィルスの類別コードが入っているので,その項目を空欄にして再登録してみた.

サブ機でWordPressにログインしようとするときの動作もおかしい.メアドとパスワードを入力しただけで弾かれてしまう.カスペルスキーのパスワードマネージャを使わずに手入力すればログインはできる.パスワードマネージャが壊れているのだろうか?入力したとたんに首を左右に振ってイヤイヤのあとボックスの中身が消えてしまう.⇒パスワードにあまり使われない特殊文字が入っているためではないだろうか?パスワードマネージャからパスワードを直接コピーして入力すれば通る.

メモリ描画環境を使わないという設定ですべてのカードが表示できるようになった.ここまで来ればあと一息だ.

デバッグ用ツールの錆落とし

ZView.vbを開いて,COUPLING::GetUserFont:フォントサイズゼロエラーが起きる.これはZELファイルのアイコンをダブルクリックしてオープンしようとするときに出るエラーと同じだ.シューティングはかかり難しい.ZView.vbのオープンはデバッグを開始することには当たらないので,デバッガが作動していないから,ブレークポイントなどを仕掛けても止めることができないため,ほとんど状況が掴めない.

障害はCOUPLING::GetUserFontでScaleFontSizeがゼロを返しているために起きている.このあと,MakeSolidFontを実行したあと,GetUserFontを再帰実行して復帰しているが,ループしてしまう.ScaleFontSizeの値がゼロとなる理由として考えられるのは,PNTPERLOGがゼロであるためと考えられるので,この値に初期値1.0を与えるようにしたところ,今度はMAPPINGのズーム倍率がゼロになるという不良が発生するようになった.前門の虎,後門の狼という状況だ.しばらくデバッグというのをやっていないので,SearchWrongObjectなどデバッグ用ツールの錆落としから始めなくてはならない.

TREEVIEW::mapping.zoom_normalがゼロとなっている理由は,TREEVIEWのコンストラクタで固有データ部をゼロクリアしているためだ.それをやっているのはsetpidだが,この関数は共有関数なので広く使われている.MAPPINGのコンストラクタはzoom_normalなどのメンバー変数を初期化しているが,それを上書きしている.廃棄オブジェクトのリサイクルでも同種の問題があり,TRASHCAN::ReuseWasteから呼び出されるdoCleanではメモリを全クリアする前に維持する必要のある変数を保全するようになっている.operator newではメモリを全クリアしているので,setpidで固有データ部を全クリアする必要はないのではないだろうか?この修正の影響範囲はかなり広いとは思われるが,setpidでメモリ全クリアを実施しないようにしてみよう.

まだ,どこかでクリアしているところがある.ファイルをオープンする前に一旦クローズしているが,そこで実行されるEraseTreeViewでクリアしているのではないか?いや,CleanSlotではそこまでやっていないはずだ.EraseTreeViewのあと,COUPLING::Clean→ TREEVIEW::Clean→ doCleanが実行される.この設計はあまりよくないような気がする.オブジェクトを温存させたままクリーニングするより,一度delete してから作り直した方がわかり易かったのではないか?とりあえず,ここではMAPPINGのコンストラクタでやっている処理をclean(void)としてくくり出し,doCleanから呼び出すことにする.

開発機の完全スキャンが完了したが,まだ5件の脅威が検出されている.

image

これらはとっくの昔に除外リストに登録されているはずなのだが…というか,ハッシュ値を計算しているので除外リストへの登録にはなっていないのだが…ハッシュ値が変化しているとすれば相当な問題だ.ハッシュ値の計算値を記録してみよう.

  1. D:\ZELKOVA 2022-03-08\ZekovaVB\obj\Debug\ZelkovaTree2022.exe 80BFC63F34A43E1A4F0E5B321A2EC3BDED3911AA65984765D06B4E30A00C63AC
  2. D:\ZELKOVA 2022-03-08\debug\app.publish\ZelkovaTree2022.exe 80BFC63F34A43E1A4F0E5B321A2EC3BDED3911AA65984765D06B4E30A00C63AC
  3. D:\ZELKOVA 2022-03-08\debug\ZelkovaTree2022.exe 80BFC63F34A43E1A4F0E5B321A2EC3BDED3911AA65984765D06B4E30A00C63AC
  4. D:\ZELKOVA 2022-03-02\ZekovaVB\obj\Debug\ZelkovaTree2022.exe 066B292370D40C40CBD5B36FA2E0E0C98BA52889BF02CA462F6CEDBFB3D482A8
  5. D:\ZELKOVA 2022-03-02\debug\app.publish\ZelkovaTree2022.exe 066B292370D40C40CBD5B36FA2E0E0C98BA52889BF02CA462F6CEDBFB3D482A8

とりあえず,MAPPINGのズーム倍率がゼロになる問題は解消したものと思われるが,ZView.vbを開いたときのエラーはまだ残っている.

image

ソースコードの修正が動作に反映しない.⇒Program Files (x86)のbabalaboフォルダに入っているOCXを参照している.アプリをアンインストール→リビルドで動作したが,別のエラーが発生している.基準ノード番号がゼロというエラーだが,無視でファイルをオープンできた.

image

ファイルをクローズしたときにもエラーが出たが,その後はオープン・クローズを繰り返しても何も出ないようになった.

image

昔々,OCXを任意のVBアプリに挿入して直ちに動作するような作りを試していたころがあったので,その名残りではないかと思うが,デバッグできないのでどういうフローになっているのか?ほとんど見当もつかない.多分この修正で,ZELファイルのアイコンをクリックして表示されるエラーも解消しているのではないかと思う.しかし,スクロールバーの問題はまったく解決していない.というか,スクロールバーがまったく出なくなってしまった.なぜだろう?

コントロールサイズはOCXのMoveControlイベントで引き渡される.この値が逆転している.現状ではW=1531, H=713となっている.⇒TREEVIEW::GetScrollValueでコントロールサイズを返している.この関数ではGetViewSizeで値を取り出し,LPtoDPで物理単位に変換している.この関数をオーバーライドしてみよう.⇒確かにこの修正は正しいようだ.縦スクロールバーが表示されている.ただし,スクロールバーをドラッグしてもうまくスクロールできない.また,リールを回すとスクロールバー自体が消えてしまう.

LPtoDPは34箇所に出現する.おそらくこれらすべてを書き換える必要があるだろう.⇒とりあえず,引数がtagSIZEであるような箇所だけ修正してみた.これでスクロールバーの操作はリールを含めてできるようになったが,内容は同じだ.つまり,スクロールできていない.これに対処するにはおそらく,引数が矩形の場合と点座標の場合のすべてに対応する必要があるだろう.⇒対処した.完全に動作するようになった.

リール操作中,ZView.vbのMoveControlで停止した.AutoPosition.Yが負値になっている.この値は,OCXからMoveControlイベントで渡されたものだ.FramePositionの呼び出しはモードにより,

  1. SETFRAME_SCROLLCONTROL
  2. SETFRAME_CONTROLSIZE
  3. SETFRAME_MOUSEWHEEL
  4. SETFRAME_SCROLLBAR
  5. SETFRAME_MOVECONTROL

の別があるが,このうちMoveControlSubを実行しているのは,SETFRAME_MOUSEWHEELの場合だけで,それ以外ではInvalidateControl(NULL, false)を実行しているだけだ.しかも,SETFRAME_MOUSEWHEELの場合はInvalidateControlを止めてもスクロール動作になっている.これは前段で実行しているCtrlFramePositionだけで処理をカバーしているということなのではないだろうか?後段を完全に削除しても動作しているので,これでしばらく運用してみることにする.こんな↓感じになった.

image

なかなかいい感じだ.

▲別のもう少し大きいファイルを開いたら,一部を残して画面が真っ黒になってしまった.カードの位置は正しいが,テキストは出ていない.

image

生描画に切り替えたら,PrintImpositionで「印刷用紙が小さ過ぎます」というエラーになった.PrintImpositionを止めたら,画面が真っ黒になる現象は止まったが,ある領域から下は描画されない状態になった.つまり,上記と同じ状態と見られる.いや,メモリ描画環境を使うように設定し直したら,やはり真っ黒になる.⇒COUPLING::SetTitleBoxで「タイトル枠描画パラメータを設定し系図外枠矩形領域を最終決定する」ということをやっているので,見てみよう.

論理座標系では系図枠は11458 x 782になっている.物理座標系では親ウィンドウサイズは999 x 697だ.これを論理座標系に換算すると,1146 x 1149になる.TREEVIEW::BuildBitMapでは,描画領域は論理単位では」11518 x 842でこれをLPtoDPで物理単位に換算して,511 x 6989になる.ビットマップはこのサイズに作られる.buildBitMapではLPtoDPの逆演算DPtoLPが実行されている.draw.Size()という計算で1531 x 6989という矩形のサイズ(横幅は現物に合わせている)が,2523 x 11521になっている.

横書き系図が出力できるようになった

選択枠のドラッグ操作は動作するようになったが,選択枠の中のカードが選択状態にならない.カードをクリックしても選択状態にならない.もう少し調整が必要なようだ.⇒完全に動作するようになった.一覧画面上での操作もチェックしておこう.一覧画面ではクリックによる選択は動作していない.クリックではカード画面上のカードが切り替わるだけで選択状態は変化しない.ダブルクリックするとそのカードが選択状態になる.一覧画面上の操作で選択状態が変化しないという動作が望ましい場合もあるのかもしれないが,ドラッグないしコントロールキー押下による拡張選択もできないというのは少し不便になのではないか?とりあえず,このまま進めよう.

結婚連結線の状態も不良だが,コラッツ木では有配偶者ノードというのは存在しないので,後日対応とする.コラッツ木のサンプルを読んでみよう.⇒読み込みは可能だが,スクロールバーが逆転している.⇒スクロールバーのサイズはフォームが抱えている描画オブジェクトのサイズによって自動的に決定するものではなかったろうか?だとすれば,OCXとVBのインタフェースで整合していないところがあるということになる.この辺りには結構ややこしいやり取りがあったような気がする.

▲ZView.vbを開いて,COUPLING::GetUserFont:フォントサイズゼロエラーが起きる.これはZELファイルのアイコンをダブルクリックしてオープンしようとするときに出るエラーと同じだ.

ドライブ文字とパスの変更

カスペルスキーが完全テストの度に検出してくる「ユーザーに損害を与える目的で悪用される可能性がある正規のソフトウェア」問題が大体見えてきたので,今後は対処できるだろう.今朝も完全スキャンは複数のEXEを摘発してきたが,すべて除外リスト/ハッシュ値の計算で対処した.これで一件落着としたいところだが,それより重大事態が発生している.ThunderBirdのデータがまるごと消えてしまっている.

考えられる要因としては,①カスペルスキーの認証局証明書をThunderBirdに登録したこと,②FakeTC.cm騒動の原因となったアカウントからのメールをフォルダごと外部に移管したことの2つくらいだが,①の手続きは前にも一度やったことがあるので,それが原因であるとは考え辛い.確かに②は少し荒っぽいような気もするが,登録されているすべてのアカウントに影響が出るほど致命的なものとは思われない…

データフォルダの中身は無傷で残っているようなので,リンクを取り直せば復活するのではないかとは思われるが,なぜこんなことになっているのか?その理由が知りたい.アカウントのサーバー設定を開いて確認すると,フォルダは従来通りの場所にリンクされているが,別のアカウントに移ろうとしたら,以下のメッセージが出た.

image

原因はわかった.SDドライブがEになっている.確かに以前にもこのようなことが発生して対処したことがある.つまり,ドライブ名が変化しているためだ.これはドライブのプロパティかなにかで変更できたはずだ.ログが残っているはずだが,見つからなかった.ネットで「ドライブ名の変更」で検索して記事がヒットした.スタートメニュー→ディスクの管理だ.ディスクの管理画面でパーテイションを選択して右クリックで「ドライブ文字とパスの変更」ができる.再起動しないと有効にならないので,完全スキャン中だが再起動.⇒復活した!完全スキャンは停止してまた1%からやり直しだ.

さて,ようやく仕事に戻れる.すでに人名枠と系線は横書き対応になっている.対応が遅れているのは,テキストの表示と選択枠だ.この二つが揃うと大体使えるようになる.テキスト描画にはCDC::TextOutとExtTextOutが使われている.この2つを拡張して_CDCクラスから呼び出すようにしてみよう.⇒一応できたが,うまく動作しない.クリップリージョンまで手当する必要があるようだ.⇒暫定的につねにクリッピングを外すようにして描画できた.

image

縦書きでも横倒しになっているのに,横書きにしても寝たままというのはかなりひねくれている.どこを調整すればよいのか?SetFontOrientationという関数がある.⇒強制的に横書きするように仮修正した.だいぶそれらしくなってきた.

image

下の方にあるドットは兄弟連結点だ.この点が収まると大体描画できたことになる.各種の連結点はDrawJointという関数で描画している.とりあえず,Ellipseという関数をオーバーライドしてみよう.⇒できたようだ.さて,問題は選択枠だ.下図のような状態になっている.

image

選択状態は完全に一致するようになったが,選択枠はまだ同期していない.

image

また,カードをクリックしても応答しない.LButtonDownで渡される座標は物理座標なのでそれを座標変換するとおかしなことになってしまう.SelectFrameXorはDrawFrameRectを使っているが,この関数で直交変換をやっている.

カスペルスキーの「行動原理」が大体飲み込めた

カスペルスキーの「行動原理」が大体飲み込めた.およそ,以下のようなルールで動いているように思われる.

  1. 除外リストに登録されたフォルダ内のEXEはスキャンの対象としない
  2. EXEの入ったフォルダがコピーされた場合には,マークを付けて監視対象とする
  3. 完全スキャンでこのようなマーク付きEXEを発見したときには,削除対象とする
  4. フォルダのリネームは(多分)この監視の対象とはしない ただし,マーク付きのEXEは引き続きトラッキングの対象となる
  5. 削除対象EXEは除外リストに追加するか,ハッシュ値を計算することで監視対象から外れる
  6. 監視対象EXEが実行されるなどの異変が検出されたときには,完全スキャンを停止する(警告が出る場合もあり出ない場合もある)

従って,このような誤検出(ユーザ的見地からはどう見ても過剰反応のように感じる)を防止するためには,開発フォルダのコピー先をあらかじめ除外リストに登録しておく必要がある.また,除外リストの登録項目を無闇に増やさないためには,手操作で(と言っても計算は自動でやってくれるが)ハッシュ値の計算を実行しなくてはならない.

前日の「UDS:Trojan.Win32.FakeTC.cm」に関しては,おそらくカスペルスキーの過剰反応と見て間違いないものと思われるが,念のためこれに関わるすべての添付ファイルを削除した.というか,それも手が掛かり過ぎるので一部を除きThunderBirdの過去のバックアップをまとめて廃棄処分した.オリジナルのメールに残っている添付ファイルは,分離して別の場所に保管するようにしてみたが,警告がどうしても消えないので,そのアカウントのデータをまるごと外部に移管して対処した.

これで一応このところずっと尾を引いていた問題は基本的に解決したのではないかと思うが,なおしばらくは毎日完全スキャンするのを日課とするということにしておく.横書き対応に関してはとりあえず,以下のようなところまでは動いているので,なんとかなるだろう.

image

UDS:Trojan.Win32.FakeTC.cmを検知

作業効率上の観点から,最近になって開発機をネットに常時接続するようにしているが,その代わりカスペルスキーの完全スキャンを毎日実施している.そして,カスペルスキーは毎日のようにと言うより,毎日,数件の削除する必要のあるオブジェクトを検出している.これらはすべてゼルコバの木のEXEで,つい最近バックアップを取ったものだ.開発フォルダそれ自体は「除外リスト」に登録してあるが,バックアップフォルダ名は毎日変わるので登録していない.これらのEXEは「ユーザーに損害を与える目的で悪用される可能性がある正規のソフトウェア」と認定されている.

これらのEXEが何らかの手段で改ざんされているものであるとすれば,それは真の脅威と言えるが,単なるコピーにカスペルスキーが過剰反応している可能性もある.どういうロジックでこのような判定になっているのかがよく飲み込めていないため,「完全スキャンを毎日実施する」ということの中には「カスペルスキーの挙動を観察する」という項目が含まれている.このような警告は通常完全スキャンが完了したあとに「通知センター」に表示されるようになっている.昨日は完全スキャンを開始してほどなく,以下のパネルが表示されたが,そのまま完全スキャンを続行した.

image

今日の始業時にはまだ完全スキャンは完了していなかったが(スリープ中は中断されている?),1時間程度で完了し,「21個のオブジェクトが処理されていません」という結果を報告してきた.内容は以下のようなもので,21個のうち,13個がウィルスとしてマークされている.

image

これらは2006年1月30日にある人物から送られてきたメールに添付されたZIPの中のEXEだ.メールは何度もバックアップを繰り返しているので,これらはすべてそのコピーと考えられる.疑問点はいくつかある.①16年も前のメールの添付ファイルに入っていたEXEが今頃になって初めて検出されたのはなぜか?②メールの送受はサブ機のThunderBirdで行っている.サブ機にもカスペルスキーが常駐しているが,検出されていないのはなぜか?ただし,サブ機では通常の検査しかしていない.

ともかく,まず,サブ機で完全スキャンを実施してその結果を見ることにする.サブ機でウィルスが検出されればよいが,そうでないときはサブ機のファイルと開発機のファイルをバイナリで比較してみる必要が出てくる.もし,不一致があるとすれば,開発機の中のEXEが改ざんされている可能性が出てくる.もし,一致しているのにサブ機の完全スキャンで検出されないとすれば,カスペルスキーの動作そのものがやや疑わしいものになってくる.最近になってカスペルスキーは「個人情報の商用利用の許諾」を求めてきていることから,カスペルスキーに対するわたしの絶対的信頼もやや揺らぎ始めている.

「UDS:Trojan.Win32.FakeTC.cm」をネット検索してみたが,ヒットしない.「FakeTC」で検索したら情報が出てきた.⇒いままで検出されなかったのは,監視条件を厳格化したことが関係しているかもしれない.これまではセキュリティレベルを中間レベルの「最適」に設定していたものを,昨日から最高度の「最大」に切り替えている.サブ機の方も「最大」に設定変更してもう一度走らせることにしよう.

https://www.enigmasoftware.com/faketc-removal/ の記事によると,FakeTCはバックドアトロージャンで活動開始は2011年,セキュリティ関連企業で認知されたのは2015年となっている.FakeTCはアルメニア,ウクライナ,ジョージア,ベラルーシなどで発見されている.開発元はthe Sandworm APT (Advanced Persistent Threat) group (also seen as Quedagh)となっているが,国籍は分からない⇒イランと目されているようだ.このウィルスは主に政府機関や軍事施設に向けたもので,その国のトップレベルの政府要人にSMSメッセージでURLを送りつけ,そのプログラムを自ら実行するように仕向ける.

上記URLはEnigmaSoftという会社のもので,スパイハンターというウィルス駆除ソフトを持っている.15日間の試用版というのもあるので,あとで試してみることにしよう.メールに添付されているEXEはTrueCrypt Format.exeだ.TrueCryptは今でも流通しているフリーソフトで「暗号化された仮想ドライブを作成するツール。仮想ボリュームをドライブとしてマウントするときにパスワードチェックを行うと、以後は自動的に暗号化・復号化をが行われるため、ファイルを利用するたびに暗号化・復号化する必要がない。復号化はメモリ上で行われ、ファイルを残さないので安全。」という内容のものだ.

このメールには発行元のURLとともに「ここが本家です。凄い速度で進化してはいるのですが、根本的な弱点は未解決の様です。 ちなみに、数ヶ月前までは日本語のサイトもあったのですが、現在は跡形もないですね。 」とあり,バグがあることはその当時から知られていたようだ.

FakeTCのオリジナルはこのTrueCryptの弱点を突くものだったようだが,現在生き残っているのはそこから進化して多分TrueCryptとは繋がりのないものになっているのではないかと思う.カスペルスキーはこの「できの悪いTrueCryptのEXE」を潜在的な脅威とみなす判定を行ったのではないだろうか?いずれにしても,これは単純に「削除」でよいと思う.EnigmaSoftのウィルスソフトがこれをどう判定するかを見てみたい気もするが,あとで解約するのも面倒なのでパスしておこう.

ビーナスの腰布がハラリと落ちた歴史的瞬間

自然数を四進数表示すると,フルヌードのビーナス像が現れる.ウソだと思ったら自分の目で確かめてみるとよい.ネット上にはN進数表示のためのツールがごろごろしているから,コラッツ木上の隣り合った数字をいくつか比較してみればホントだってことが分かるだろう.君の目の前にあるのは「整った美の完成型」だ.乱雑でカオス的なコラッツ数列の渦の中にこんな「秘密」が隠されていたなんて信じられるだろうか?

ビーナス裸像

これを見たら夜も寝られなくなる人が続出するかもしれない.実際,昨日からこのブログへのアクセスが急増して一日の訪問者数が100を突破している.ともかく,コラッツ完全木ツールをリリースするまでは全力疾走するしかないね.「コラッツの秘密」が開示される日は近い.

もう少し突っ込んで解析したいのだが,そのためにはゼルコバの木で横書き系図を表示できるようにしたい.それができれば一々PDFに落として,云々の手間が省けるのだが…原理的にはそれほど難しくはないが,かなりの手間が掛かりそうだ.コラッツ三本桜の復活とどちらを先に手掛けたらよいか?コラッツ三本桜の復活は「コラッツ完全木」の完成を意味するが,一度仕事に掛かったらA面・B面の5機能すべてに対応しなくてはならないから,かなりの時間を要することになる.むしろ,思い切ってここでゼルコバの木に横書き系図を導入してしまった方が早いのではないか?ゼルコバの木の座標系は現在,X軸は右から左,Y軸は上から下というオリエンテーションになっているが,横書き対応というのは,X軸とY軸を入れ替えることに相当する.X→Y’,Y→X’とすると,X’は左から右,Y’は上から下に描画されなくてはならない.かなり厄介そうな話だが,やってみよう.

内部の計算は完全に温存されるものとし,座標変換は描画関数で直接実行する.ゼルコバの木系図図面に出力される図形には,①人名枠,②人名枠内のテキスト,③親子連結線,④兄弟連結線,⑤人名枠頭部垂線などがある.描画関数はDrawTreeView.cppとDrawTree.cppに入っているとみてよいだろう.可能ならば,最下位の関数で対応するというのがベストなのだが…切り分けができるだろうか?最下位の関数ということは,WindowsのAPIを直接呼び出している関数ということになる.DrawingObject.cppという未使用のCPPファイルがある.内容は「描画要素オブジェクトクラス」となっているが,これは将来,描画要素をオブジェクトとして扱えるようになったときのためにリザーブしておいたものだ.今回の修正は趣旨はまったく異なるが,とりあえず,ここに修正を要する関数を集めてみることにしよう.まず,使われているWindows APIを特定してみよう.デバイスコンテキストクラスの関数がそれに該当する.ざっと拾い出したところ42個あった.

  1. Arc
  2. BitBlt
  3. DPtoLP
  4. Ellipse
  5. EndDoc
  6. EndPage
  7. ExtTextOut
  8. FillRect ●
  9. FillSolidRect ●
  10. GetClipBox
  11. GetDeviceCaps
  12. GetMapMode
  13. GetSafeHdc
  14. GetTextColor
  15. GetTextFace
  16. GetTextMetrics
  17. GetTextExtent
  18. GetOutputTextExtent
  19. LineTo ●
  20. LPtoDP
  21. MoveTo ●
  22. PatBlt
  23. Polygon
  24. RestoreDC
  25. SaveDC
  26. SelectClipRgn
  27. SelectObject
  28. SetBkColor
  29. SetBkMode
  30. SetMapMode
  31. SetPixel
  32. SetROP2
  33. SetTextAlign
  34. SetTextColor
  35. SetStretchBltMode
  36. SetViewportExt
  37. SetWindowExt
  38. SetWindowOrg
  39. StartDoc
  40. StartPage
  41. StretchBlt
  42. TextOut

ただし,これらの関数でも座標に関わりがないものは対応不要と考えられるので,実際の数はかなり限られていると思う.まず,ともかく矩形と直線の描画に関わるものを対象として修正を試みる.対応が必要な関数は上記リストで●をマークしたFillRect,FillSolidRect,LineTo,MoveToの4関数だけだ.これらはCDCクラスの関数だが,CDCクラスをオーバーライドすることは可能だろうか?⇒できそうだ._CDCという拡張クラスを新設し,以下の関数をDrawingObject.cppに移動した.

  1. Bobject::DrawYlist
  2. Bobject::DrawParentPath
  3. TRIBEBOX::DrawTlist
  4. Bobject::DrawLine
  5. BRect::DrawFrameRect
  6. printtombo
  7. printtombo_yoko
  8. printtombo_tate
  9. Bobject::CallFillRect
  10. TREEVIEW::PaintBackGround
  11. Bobject::FillSolidRect

一応修正は入ったので,走らせてみたが… どうも,これはかなり手強い.画面はほとんど真っ黒で一部描画されている部分もまったく座標変換になっていない…新規ファイルにすると,こんな感じだ.

image

ちょっと頭を冷やして考えなくてはならない… 現行ではデバイスのマッピングモードをMM_ANISOTROPICに設定している.これは座標単位と座標軸の向きを任意に設定できるという便利なものだが,X・Y軸を入れ替えるとしたら,少なくともSetWindowExtExとSetViewportExtExで軸の向きを変更しなくてはならない.ゼルコバの木は画面出力とプリント出力をまったく同じ関数で実行しているので,印刷の方も手当しなくてはならないが,ここのところは暫定的にパスしておくことにしよう.⇒少し状況が変わった.画面にはまだブラックなところが残っているが,人名枠が横書きで表示されている!これはいい傾向だ.

image

おそらく,スケールと軸の向きはこれで正しくなったと思われるが,座標原点の位置が悪いのではないだろうか?SetWindowOrgを呼び出している箇所には修正を入れてみたが,まったく変わらない.なんとか横書きしようとしているのは確かだが…

image

座標がからんでいる関数は上記のリストの中にまだどっさり残っているが,DPtoLP, LPtoDPが動作しないとまずいのではないだろうか?現行では論理座標と物理座標は等スケールになっているはずだが,GetClientRectなどで取得した矩形領域は論理座標系とは反転したものになっているはずだ.CWndの関数もチェックしておく必要がある.座標に関わりがあるのは多分GetClientRectだけだと思う.mmm… だいぶよくなった!

image

▲上下カーソルでカードが移動してしまう.おそらくこれは一覧画面での動作だが,カード画面にフォーカスがあるときは無用な動きだ.

枠線や系線がまったく出ないのはなぜだろう?

コラッツ国の公用語は4進数である

コラッツ国の公用語が4進数であることがわかった.自然数Nの名前を4進数で表記すると,Nの名前の中にはNの親Pの名前と兄弟順位が埋め込まれていることが分かる.簡単な例で見てみよう.下図のボックスには3つの数が入っている.①Nの4進表示(左上),②3N+1の2進表示(右上),③Nの10進表示(下行).

image

上図で奇数17は11, 45, 181, 725, 2901, 11605の6個の子ノードを持っている.これらの数の4進表記を見ると,23, 231, 2311, 23111, 231111, 231111のようになっていて,いずれも23を共通部として持ち,そのあとに1がいくつか並ぶという形式になっている.つまり,

Nの4進表記=共通部+1の並び

という形式になっている.この共通部を親の名前とみなせば,

Nの4進表記=親の名前+兄弟順位

であることは明らかである.「親の名前」はストレートには親ノード17には結びつかないが,バイナリ表記した3N+1にもそれと同様の「共通部」が存在することが見て取れる.今の事例ではこの共通部は「10001」であり,これを4進数に変換すると「101」を得る.これは親の「実名」である.ここで,「親の名前」とはこれまで「コラッツ数」と呼んでいたものにほかならないことは,長子ノードである11の「名前」が「親の名前」そのものであることからも分かる.つまり,長子ノードはある意味で「親の名前」を襲名していると言っても言い過ぎではない.ただし,「親の名前」と「親の実名」は同じではない…

タイトルでは「コラッツ国の公用語は4進数である」としているが,2進数表記,3進数表記も同様の重要性を持つ.つまり,コラッツ国では複数の公用語が併用されていると言うべきだろう.進数表記にはある種の演算が関わっているが,なぜここで問題を「言語」の問題として扱おうとしているのかというと,「言語」には「算術計算」とは異なる「連結(concatenation)」のような操作があるからだ.もちろん,DNAシーケンスなどという発想もその延長上にある.「数」のような抽象物?の中に情報としての記号(具体物)が埋め込まれているというのはかなり重大な発見であるような気がする…

コラッツ木とはすべての自然数が登録された戸籍簿である

コラッツからゼルコバの木にインポートするという操作がある程度滑らかに実施できるようになってきた.ここまでできると,次はインポートしたファイルをPDFに落として,かつ左90°回転させ,文字が正立した図面として保存したい.PDFの回転はChromeでもできるが,保存ができない.ダウンロードはできるが,保存されたファイルを開くと回転が戻ってしまっている.保存という機能もあり,たまたま保存できたケースもあるが,その手順が確立できない.CubePDFに印刷出力するという手もあるが,やはり回転が戻ってしまう.AdobeのAcrobat Reader DCの有料版なら回転までサポートされているが,買取りではなくサブスクリプションで月2千円も掛かるのでは手が出ない.ゼルコバの木でそこまでできるようにする必要はあるのだが,今日明日というわけにもゆかない.⇒いや,できた!多分この手順で間違いないと思う.

  1. コラッツからCSVファイルをエクスポート
  2. ゼルコバの木でファイル→隣接リストをインポート
  3. プリンタにCubePDFを選択,用紙サイズをA0に設定
  4. 拡大縮小倍率を調整して1ページに収まるようにする
  5. CubePDFに印刷出力してPDFファイルに保存
  6. ChromeでPDFファイルを開き,画像を回転させる
  7. 印刷画面を開き,送信先をCubePDFに設定
  8. 詳細設定で用紙サイズをA0,倍率は既定
  9. CubePDFで印刷→PDFに保存

ダメだ.確かに回転は保存されているが,図面の上半分しか入っていない.LibreOfficeでPDFを読み込んで回転まではできる(かなり時間が掛かる).しかし,図形を拡大縮小操作しているうちにフォントが荒っぽくなってしまうという欠陥がある.⇒最初に図形を全選択してからフォントをメイリオに切り替えておくと多少よい結果になる.図面を回転させたあとはページ設定でページサイズを整えたあと(オリエンテーションを横から縦に変えてもよい),ドラッグ移動してページの中に収まるようにすればよい.まぁ,これなら↓なんとか使えるだろう.

image

上図は1-3-4 511コラッツ木で所属の欄に8進数表示のノード番号を表示している.これを見ると,8進で末尾が5なら非コラッツ数であるということが一目瞭然にわかるが,01の並びを見れば第何子であるかわかるはずなので,それも見られるようにしてみたい.このためには8進ではなくむしろ4進表示が適しているのではないだろうか?ちょっとやってみることにしよう.できた!

image

これはかなりわかり易い図だ.兄弟順位がそのものずばり,4進表記したノード番号に現れている.しかも,4進表示すると,これらの兄弟ノードの名前の語幹部はそのものずばり親ノードを示しているように読める.つまり,すべての兄弟が同じ「姓」を持っている.例として5090020693の子ども枠の中を見ると,第1子が12110201023301301で,第2子は12110201023301301-1,第6子は12110201023301301-11111.親の5090020693自体は,5090020693の6番目の子どもで,102331203203-11111という4進名を持っている.長子12110201023301301の名前には2のべき乗数が入っていたはずだが…一昨日の記事から再掲すると,

P=F(S)=(3S+1)/2   c=1の場合:S=…011, …111の場合
    =(3S+1)/4   c=2の場合:S=…001の場合
    =(3S+1)/16  S=5=101の場合

ということになっているので,4進表記すると,c=1というのは,末尾が3,c=2は1,c=4はS=5しかないので,S=11という場合に限られる.末尾が0ないし2なら偶数だから,末尾が1ならば,c=2,3ならc=1.ノード番号全体が11ならc=4ということになる.cの値が決定できれば,あとは3S+1を計算し,それを2^cで割ってやれば親数を得ることができる.もし,3進数で表示されていれば,3N+1がどんな数になるかはすぐ分かるが,それを2のべき乗で割り込んだ結果は子ノードの名前とはかけ離れたものになるのは避けられないだろう.

それにしても,兄弟の氏名がこんなにシンプルな構成だということを想像したことがあったろうか?これはもはやコラッツ問題が完全に解かれたということの証左以外のなにものでもない.子ノードの3S+1という数を計算してそれをバイナリ表示してやれば,この辺りの関係もある程度見えてくるのではないだろうか?それをやってみよう.

この値を生没日付欄に表示してやろうとしたのだが,出てこない.本来日付は内部的には文字列としてしか扱っていないはずなのだが…日付データとしての有効性をどこかでチェックしているのだろう.仕方ないので肩書欄に記入してみた.長くなってしまうが,仕方ない.

image

もはや,これ以上のことを言う必要はないだろう.子どもノードSのノード番号に3S+1という変換を掛けて得た数値はそのものずばり,親ノード番号+右シフトの回数になっている.この兄弟ノードの親ノードである5090020693を4進表記した数字はすべての子どもノードの4進表記の中に埋め込まれている.また,子どもノードSの3S+1のバイナリ表現の中にも完全に親ノード番号が埋め込まれ,それを2^c倍したものになっている.明らかにこれは一種の戸籍システムであり,あるノードのノード番号がわかればそれを順繰りに手繰って,先祖ノードまで遡ることができることは明らかだ.これは家系図を作成するときに本籍地から本人の戸籍→父の戸籍→祖父の戸籍を手繰るのとまったく同じ手順である.4進表記と3N+1の2進表記の間に,3進表記というのを挿入すれば,計算するまでもなく,子ノードのDNAが親ノードのDNAを正確にコピーしたものであることが分かるだろう.この図面はほぼ,コラッツ予想問題の「完全な証明」に相当するものになっていると思う.

親ノード5090020693を2進表記すると,100101111011000111000110101010101のようになる.その子どもの6949574919509の3N+1を2進表記したものは

100101111011000111000110101010101000000000000

のようになる.この末尾の0を取り除くと,100101111011000111000110101010101となって完全に一致する.これは計算の結果そうなったのではなく,もともと埋め込まれていたものであることを示すにはやはり3進数表記を見るのが一番早いと思う.やってみよう.⇒いや,ダメだ.思ったような結果にはならない.当然かもしれないが,3進表記した場合には兄弟ノードのすべてで異なる名前が生成され,共通部を見出すことはできない.これをやるとしたら,長子木を使った方がよいかもしれない.長子ノードの3進表示を左に1シフトして1を加えたものを2ないし4で割ったものが親ノード数になる.従って,親ノードを2ないし4倍したものから1を減じたものを3進表示すれば共通部が見えてくるのではないかと思う.これは長子木が復活したあとで試してみることにしよう.「親ノードを2ないし4倍したものから1を減ずる」のような操作は一種の「計算」ではあるが,2進ないし4進数としてみると,これはDNAの文字並びを壊さない操作になっているので,それと子ノードの3進数が共通部を持つことを示すことができれば,「DNA保存」という文脈の中で説明可能になる.

我々の意図するところは,子ノードが親ノードのDNAを引き継いでいること,そのDNAシーケンスから先祖ノードまでの遺伝子継承関係を手繰ることが可能であることを示すことにある.その目標はすでにほぼ達成されているのではないかと思う.4進表記したときの下位ビットはそのノードの兄弟順位を示すものであり,たとえば,太郎・次郎・三郎などのような一般的な呼称になっている.上位ビットは親の名前だが,暗号化されているため親の実名とは一致しない.しかし,すべての兄弟が同じ親の名前を共有していることは確かだ.親ノード番号を親の実名とすると,子ノードの中に埋め込まれている親の名前は親の戸籍名(暗号化された実名)であると言える.しかし,暗号化された親の実名をデコードするのは難しくない.そして,親の実名もまた,親の親の戸籍名+太郎・次郎などの兄弟順位名から構成されている…結構単純な仕掛けだが,我々が「アドレスコード」と呼ぶものと「ノード番号」が完全に等価であることの実証であると言ってよい.

一言でまとめれば,「自然数の原戸籍簿は4進数によって標記されている」ということになるだろう.4進数のアルファベットは0, 1, 2, 3の4文字である.ここでピンと来たあなたは確かにいい感をしている.人間に限らず,すべての生物のDNAがACGTの4文字から構成されていることはよく知られた事実であり,自然数の4進数表記がDNA配列になっていることはいまさら驚くべきことではないのかもしれない.