大体止まらないで走れるようになった

N=268435472,K=6のとき,#2でcycle=2,4,2になるという事例を考えてみよう.この値はn^の設定に関わらず一定だ.べきn^を変えるとstripeは変化するが,cycleは変化しない.これはcycleがマトリックスの行でstripeがマトリックスの列なのだから当然だろう.べきを2に固定してnを変化させると,Rと#が変化し連動してcycleが変化する.これも当然の動作ではあるが… Rと行が一致しない場合をカラー表示すると,

  • N=268435472 R=4 → 2,4,2,4
  • N=268435473 R=3 → 3,3,3,3
  • N=268435474 R=4 → 4,4,4,4
  • N=268435475 R=1 → 5,1,5,1
  • N=268435476 R=0 → 0,0,0,0
  • N=268435477 R=1 → 1,1,1,1
  • N=268435478 R=4 → 2,4,2,4
  • N=268435479 R=3 → 3,3,3,3
  • N=268435480 R=4 → 4,4,4,4
  • N=268435481 R=1 → 5,1,5,1
  • N=268435482 R=0 → 0,0,0,0

のようになり,R=1と4が特殊な事例になっている.R=2と5はこの系列には現れない.剰余数列には周期性があり,長さ6の周期{4,3,4,1,0,1}を繰り返している.この周期列は縦周期列に現れるものとまったく同じだ.つまり,べき=2, 4, 6の縦数列にこのパターンが現れている.これもある意味で当然だ.縦周期というのはそのようなものとして定義されているのだから.マトリックスはKによって一意に決定される.また,n^e mod K= R の値はeの値に依らず一定である.

それでは,ある値nとeを指定したときの cycle がマトリックスのどの行に該当するのかを決定するパラメータを何と見ればよいのだろう.上のリストで見ると 1,1,1,1 のcycleは268435477に対応している.これはKに依存した値と思われるので,Kの剰余を取ってみよう.確かにR=1となっている.しかし,R=1だからと言って1,1,1,1になる訳ではない.268435476と268435482の間にはR=1が2つあり,その一つは5,1,5,1だ.基準はN=1であり,6の周期で変化しているのだから,N=1とN=268435472の剰余的な距離が分かればよい.N=1 → R=1のはずだから,N=268435472→R=4との差分を見ればよいはずだ.

いや,上ではR の値はeの値に依らず一定としているが,間違っている.たとえば,N=268435472^2 mod 6≡4だが,268435472^3 mod 6≡2だ.実際,マトリックスの第2行を見ると,2,4,2,4の数列になっている.しかし,e=2でR=4となるのは2だけではない.4も同様にR=4となっているが,この行は4,4,4,4という数列を生成する.言い換えると,Rとeだけではcycleは決定できない.決め手はなんだろう?ψは不定になっているが,ψを決定しても決め手にはならないだろう.ψは存在すれば#に一致するはずだが,e=2でも3でも#の値は2で変わらない.268435472^1のRを見ると,R=2だ.N=1ならR=1だから,その差は1.つまり,N=2≡268435472 mod Kと言える.

べき乗する前のNの剰余を見ておけばよいのではないだろうか?この剰余をNrとすると,確かにNrはマトリックスの行を指定しているように思われる.N^e mod K ≡ R の剰余Rはeの値によって変化するが,Nrの値はeに依らず(当然だが)不変である.いまNをnと表記しているので,この数字はnRとラベル付けしておこう.これでマトリックスとの対応が疑問の余地なく一致するようになった.つまり,マトリックス上の行はnRで一意に決定され,マトリックス上の列はe=n^で決定できる.⇒完璧だ.もはや疑問の余地はない.

このツールには5個の検定が含まれているが,検定範囲を指定するのではなく,検定の回数を指定するという方式に変えておくことにする.この方が設定し易いのではないかと思う.

SeedTestの1回分でInvertFuncが三度呼び出されているのはなぜか?①SeedTestClickからの呼び出し,②ValueChanged x 2 .SeedTestClickの中では明示的にValueChangedを実行しているのでInvertFuncの実行が重複してしまう.①passflagが立っているときは,UpDown.ValueChangedでValueChangeProをパスするようにした.

MatrixTest中にnRがまったく更新されないのはなぜか?この値はDispModPowで更新している.DispModPowはValueChangedから呼ばれているのだが…BuildMatrixでは基本的に画面の更新を行っていない.その後にTestMatrixが実行されるが,これはテーブル全体のテストでNの書き換えなどは行われない.⇒TestMatrixではResidueFuncProの中でNの書き換えを実施している.TestMatrixでResidueFuncProを実行したあと,DispModPowを呼び出すようにした.これでnRは更新されるようになったが,nの素因数列は止まったままだ.これはDispParametorで出している.これが入ると少し重くなるとは思うが…

PrimeTestでPowerResidueFuncが逆数モードで2回呼び出されている.ValueChangedから実行されている.passflagは立っているのだが,実行されている.passflagは整数なので0と比較するようにして動作するようになった.

PrimeTestでNを268435400に設定してInverteFuncの処理範囲に入るようにしたが,UやnUがまったく表示されていない.エラーも出ていないように見えるのだが… 同じ設定でInvertTestを実行したら,ハングしてしまった.⇒DispInvertで相当手間取っている.ValueChangedから呼び出しているDispInvertFuncはInvertTestとDispInvertを含んでいるので,そっくりこの処理を呼び出すだけでよいと思われるが,大きいNはほとんど処理しきれないというのが実情だ.しかし,DispInvertFuncではそこまで時間が掛かっていない.Uが出るためにはかなりNが小さくないと処理できないようだ.処理可能なnの最大値は268435455だ.

しかし,InvertTestでは,n=268435400 B=10でハングしてしまう.なぜだろう?ToBCDで手間取っているようだ.しかし,この関数はDispInvert→ConvertNum2String→ToBCDで,DispInvertはDispInvertFuncに含まれているはずなのだが… おかしい.Uが出なくなってしまった.N=2684354は十分小さい数のはずなのだが… もっと小さい数にすれば出る.MakeRecursionUnitで桁数オーバーでアボートが起きている.⇒DispInvertFuncならUやnUは表示されないが,処理は進む.おそらく,DispInvertFuncで使っているルーチンは途中で打ち切るようにできているのだろう.⇒MakeRecursionUnitがUを返してこない場合にはConvertNum2Stringは実行されない.つまり,土壷にはまらないようになっている.これは差し替えでよいだろう.

n=268435455のとき,digitは1342176になっている.MaxOutputは30000なのでそれよりもだいぶ大きい.QTのサイズは2684392あるのでUの計算はできるはずだ.⇒計算自体は単純な計算なので実行は可能だが,Uは生値なので途方もない大きさになる.やはり,ある限度で打ち切った方が現実的なのではないか?桁数で30000というのはそれだけでも無茶無茶大きな数字だ.やはり,これは打ち切るのが正解としておこう.1/nの循環節までは出せるのでこれで満足するしかないと思う.

InvertTestではBをB+50まで変化させているが,特定のBでやけに重くなるのはなぜだろう?重くなるBには 42, 46, 57がある.おそらくこれらは何らかの理由で循環節が長くなっているのだろう.n=2684354のとき,B=42で fixed=1 keta=27962だ.この桁数は上限を超えていないので,nU,RPも出力されているが,Uが空欄になっている.なぜだろう?B=43 では,fixed=0 keta=1342176でアボートしている.B=42が遅いのではなく,打ち切りになっていないために見かけ上遅くなっているというだけだ.46, 57の場合も同じだ.ダンプしてみたが表示しようもないほど大きな数だ.

U=30979015254076365607484929108097110855736447
23737560540653941886057714834360774845095407791
71918951268321512524684829108915145925588584343
70873530921047046611821998461775454883886861647
25702974448815854451091871481243706996114903023
35610469271871095106330135472657551521990096397
75521223776067953620107407306115688619234917853
24243166297078829776098227164689…これが延々と続く…

ともかく,Uという数は手に負えないほど大きくなるということが分かった.⇒テキストボックスに入り切る範囲で打ち切ることで描画できるようになった.これ以上のことはできない.これで処理できる場合には限界まで表示できるようになった.1/nもたとえば,B=47の場合,1342176桁もあるのだから,どこかで打ち切っているのだろう.

MatrixTestのとき,(n, B)と(φ(n), @)が更新されない.現行では,(n, B)はDispInvertFuncでしか更新されていない.というか,MatrixTestはBとはまったく関わりのないテストになっているはずだから,更新されないというのが正しいのではないか?この2つはBの枠内に移してしまおう.⇒これで剰余演算と逆数演算が完全に分離できた.

ResidueTestで画面の更新が止まったあと,かなりの時間砂時計のままになる.なぜか?おそらく,最後の辺りで桁数の大きな処理が入っているためだろう.27962桁というのが,n={2684354}, B=42で起きている.例のB=42, 46, 57だ.この桁数上限はもう少し小さい方がよい.10000桁まで減らしてみたら,だいぶ楽になった.これでよい.

PrimeTestはBを変化させるテストになっているが,なにも更新されない.なぜか?仮にUなどが上限で描画できなかったとしても,1/nは変化してもよいのではないだろうか?DispInvertFuncもDispInvertも実行されていないためだ.⇒DispInvertFuncを実行するようにした.

n=2684351, n^2=2, K=2, B=42のとき,DispInvertFuncの下記の位置でエラーが発生した.

extBox13.Text=U.ToString.Substring(0, TextBox13.MaxLength)

現行ではTextBox13.MaxLength=32767だが,U.ToStringの長さがそれよりも短いときにはエラーが発生する.⇒対処した.

▲BuildMatrixでパラメータを書き換えるのはまずい.MatrixTestは別としても,BuildMatrixでは画面を変化させない方がよい.TestMatrixをパスしてもよいのではないか?

stripeの横にn^e mod K を表示する.正しくは,n^e mod (K-1)ではないか?⇒そのようだ.eRはstripeの列番号に相当し,nRはcycleの行番号に対応する.これで完全にストーリーが完結した.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA