ついに fx-5800P がPCリンク可能になった

2018/02/10
更新 2021/01/04

fx-5800P と PCのデータリンクを使いこなす CcLinker


アップデート状況
  • CcLinker Dongle の頒布 ⇒ 詳しくはこちら [2019/05/08]
  • CcLinker が Ver 4.0a にアップデートダウンロードはこちら [2019/05/08]
    ※ fx-5800Pと連動して自動化され、さらにWindowsバージョンの違いによる誤動作発生が低減されました


はじめに

小型でバランスのとれた fx-5800P での Casio Basic プログラミングは、当ブログの重要テーマです。しかし致命的な問題として、カバーのヒンジが壊れやすいこと、そしてPCとのデータリンクができない点が挙げられる。これについては "fx-5800P プログラムのバックアップ" で取り上げている。

本来カシオが提供すべきものだと思うのだが、fx-5800P 発売から10年以上経ても、カシオ自身やサードパーティからまだ提供されていなかったが、ついに待ち望んだPCとのデータリンクが実現した

以前から、fx-5800P のデータリンクが検討されてきた。当ブログにおいても、"fx-5800P プログラムのバックアップ" の記事に kikkawa様や AkSd様のコメントで、データ解析ができて、なんとかなるかも知れないというコメントを頂いていた。そして、AkSd様の 関数電卓ファン掲示板 で様々な情報交換がなされ、応援コメントなども集まるようになった。

その中で、takumako様 が CcLinker というデータリンクツールを完成なさった。

takumako様の CcLinkerホームページ

現在は、ファームウェア書き込み済みの以下のような形態で頒布なさっている。
 CcLinkerDongle 

購入方法の詳細は、CcLinker Dongle の頒布 を参照のこと。


CcEditor の紹介

CcLinker で転送したプログラムファイル (CCLファイル) を CcEditor というプログラミングアプリで編集・作成すると fx-5800P の隠し機能が使えてプログラミングの幅が広がる。また、ソースコードにインデントが付けられたり、Getkey のキーコードが簡単に入力できたりと、CcEditor は fx-5800P 専用の優れたプログラミングツールだ。 CcLinker と合わせて CcEditor を使う価値は十分ある。

[2019/05/08 追記]
CcEditor は Ver 2.2 にアップデートされ、さらに使い勝手が改善されている。
CcEditor の簡単な紹介


CcLinker Dongle の導入

NewUSBDongle実際に CcLinker Dongle を入手して使ってみた。左の写真は私が入手した最新のものだ。

[2018/08/07 追記]
できるだけ多くの方に使って頂きたいという作者のtakumako様のお考えから、期間限定を無くして、いつでも有償頒布を受け付けるとのこと。とてもありがたい話だ。

fx-5800P をPCとリンクするには、写真の USBドングルとWindows デスクトップアプリを使う。


実際にWindows 10 で使ってみたので、以下に紹介する。


デバイスドライバーのインストール

先にUSBドングルをPCに奥まできちんと刺し、添付の Windowsデスクトップアプリ - CcLinker を起動すると、自動的にデバイスドライバのインスト-ルが始まる。Windows 10 では、右下にインストールが終了した旨のメッセージが現れる。但し、Windowsアプリのウィンドウは表示されない。

一旦デバイスドライバがインストールされた後 CcLinker アプリを起動するとアプリウィンドウが表示される。


PC保護の警告

Ver 1.6d 以前の CcLinker を初めて起動するとき、Windowsの保護機能が発動してしまう。

PC_Protection.PNG 

自作プログラムでは、最初は間違い無くこれが表示される。CcLinker も危険ではないのに大きなお世話である。気をつけるべきはダウンロード先は作者のオリジナルサイトを使うことだ。おそらく Microsoft がユーザーのPCからインストールプログラムを監視し、そのデータを抽出し、多数決方式でインストール数が少なければ一旦待ったをかける機能だろうと思われる。

ここで、詳細情報 をクリックしたら現れる [実行]をクリックし、アプリを実行すれば次回からこの警告は現れない。
自作プログラムがPC保護機能に引っかかる

[2018/07/31 追記]
CcLinker Ver 1.6e 以降は、この問題を回避するために フリーの圧縮解凍アプリ CGA にて圧縮されたファイル(拡張子がCGA)でも供されている(詳しくはコチラを参照)。

[2019/05/08 追記]
CcLinker Ver 4.0a は zipファイルでの提供もされている。古いバージョンからのアップデートなら zipファイルを入手上書きすれば良く、PC保護機能に引っかかることはない。


CcLinker の起動

最初に USBドングルとfx-5800Pを接続した後、USBドングルをPCに刺す (確実に接続する方法)。
その後 Windowsアプリ CcLinker を起動する。無事に起動すると、CcLinker のウィンドウが表示される。

Pclink_fx-5800P   CcLinkerV4_Booted 

CcLinker Ver 2.0b 以降は [Transmit] ボタンと [Receive] ボタンが廃止され、fx-5800P 上で Transmit や Receive を選択した時に CcLinkerが自動的に連動するようになった。Ver 2.1a で画面の背景に薄い色が付き、見やすくなった。 

もし、ドングルを刺さずに アプリを起動すると、エラーメッセージが表示される。

Boot_Error.PNG 

そこで、メッセージに従って ドングルを刺してから [OK] で、正常起動する。




CcLinker の終了

USBドングルを外す前に、CcLinkerアプリを必ず先に終了させる。
そうでないとエラーになり、結局 CcLinkerを強制終了することになる。



CcLinker の操作
 
CcLinkerアプリには [AC] ボタンしかない。基本操作は 接続した fx-5800P で行い、PC上ではファイルやフォルダの選択操作のみを行うようになっている。

fx-5800P からPCへ特定のプログラムファイルを転送 (PCにバックアップ)

CcLinker は、fx-5800P のプログラムファイルを CCL ファイル (CcLinker独自フォーマットのファイル形式)でバックアップする。

試しに、"fx-5800P【ゲーム】:Hit & Blow" で作ったプログラムのメインルーチンをPCにバックアップしてみる。私の fx-5800P ではメインルーチンのプログラム名を HB に変更している。

fx-5800Pを繋いだUSBドングルをPCに挿入した後 CcLinkerアプリを起動。


Pclink_fx-5800P   CcLinkerV4_Booted  

アプリでは何もせず、fx-5800P で、[MODE] - [▼] - [1] (LINK) - [1] (Transmit] - [2] (Select) と押し、
Select Data で バックアップしたいプログラム (今は "HB") にカーソルを合わせ、[1](SEL) を押し、最後に [0] (TRAN) を押す。
Transmit OK?[EXE] (Yes) を押すと、PCの一時ファイルに一旦バックアップされ、 fx-5800P で Completed! と表示される。

CompleteSaveV4 

そして、バックアップ先を選択するフォルダの選択画面が現れるので、そこでハックアップ先のフォルダを指定する。

SelectSaveFolder   

ファイル名を変更せず、そのまま [開く] ボタンをクリックすると、一時フォルダに一旦転送されたファイルが、指定したフォルダに移動される。


ここで最初に表示されるファイル名は、fx-5800Pに保存されているファイル名のうしろに COMP [ファイルサイズ] の情報が付加されている。この例では、HB COMP 027.cll になっている。ここでファイル名を自由に変更可能で、変更されたファイル名でバックアップできる。

なお、HB COMP 0127 の "COMP 0127" の部分は 必ずしも必要ではなく、消してしまっても問題ない。COMPモードのファイルであることを明示的に示すだけで、0127 はファイルサイズだ。

このファイル選択画面は、いわゆるコモンダイアログになっており、右クリックして現れるメニューから新規にフォルダを作ってからそこへ保存するなど Windows標準の操作ができる。


fx-5800P からPCへ全てのファイルを一気に転送 (PCに全てバックアップ) - Ver 1.7 以降 [2018/08/18]

fx-5800P のプログラムを全て一気にPCに転送できる。

上と同じ要領で、fx-5800P とPC を USBドングルで接続してから、CcLinker アプリを起動する。

CcLinkerアプリでは何もせず、fx-5800P で [MODE] - [▼] - [1] (LINK) - [1] (Transmit) - [1] (All) 、そして [EXE] をキーインする。

すると、「ファイルを選択してください」ダイアログが現れるので、バックアップするフォルダに移動するか、右クリックして新たにフォルダを作り、 [開く(O)]をクリックするか PCの [Enter] キーを押す。これで、電卓内の全てのプログラムがPCへ転送される。

保存先フォルダに同名ファイルがある場合は次のポップアップが現れる。

OverwriteFile  

ここで、[はい(Y)] を押すと、他に同名ファイルがあっても上書きコピーされる。無事に転送が終わると、fx-5800P と CcLinker アプリの両方で Completed! と表示される。

上書き確認は安全のため表示されるが、頻繁に表示され面倒になり、バックアップを中止したい時は、[キャンセル] を押せば、一連の転送そのものをキャンセルできる。

なお、何かエラーが発生したら、エラーメッセージが表示される。エラーメッセージで [OK] をクリック後、CcLinker アプリで [AC] をクリックして一旦バックアップを中止し、バックアップをやり直す。何度か繰り返す必要があるかも知れない。


PCから fx-5800P へ特定のプログラムファイルを転送 (電卓に転送)

CcLinker でバックアップしたCCLファイルを fx-5800P にプログラムファイルとして転送する。

fx-5800P をUSBドングルに繋いだ上で、ドングルをPCに刺し、CcLinkerアプリを起動する。

CcLinkerV4_Booted     

CcLinker アプリでは何もせず、fx-5800P で [MODE] - [▼] - [1] (1:LINK) - [2] (Receive) と押すと、保存するファイルの選択画面が現れる。

SelectResumingFile  

このファイル選択ダイアログで、転送したいファイルを選び [開く] ボタンをクリック。

既に同名ファイルがある場合は、上書きして良いかを確認するメッセージが現れるので、

OverwriteFile   

[はい(Y)][いいえ(N)] をクリックして先に進む。

OverWightBackFile_Disp 

無事に転送されると、fx-5800P と CcLinker の両方で Complete! と表示される。

BackUpAllCOmplete.png 




PCから fx-5800P へ全てのファイルを一気に転送 (電卓に全て転送)  [2018/08/18]

PCにバックアップしたファイルを一気に fx-5800P に転送できる。

fx-5800P で [MODE] - [▼] - [1] (LINK) - [2] (Receive) をキーイン。CcLinker アプリで [Transmit] クリックする。するとTransmit コモンダイアログが開くので、そこでfx-5800P へ転送するファイルのあるバックアップフォルダを開き、転送するファイルを選ぶ。[Ctrl]-[A] で全て選択するか、[SHIFT][Ctrl] を押しながら複数ファイルを選択し、[開く(O)] クリック。これで、選択したファイルが一気に fx-5800P に転送される。

転送が無事に完了した時は、fx-5800P と CcLinkerアプリの両方で Completed! と表示される。

fx-5800P に同名ファイルが有る場合は、見つかる度に以下のポップアップが表示される。

OverWightBackFile 

転送を中止したいときは、fx-5800P で [AC] (Cancel) を押すか、このダイアログで [キャンセル] をクリックする。




fx-5800P プログラムをCCLファイルで公開

当ブログで公開している fx-5800P 用プログラムファイルは、今後 CCLファイルでダウンロードできるようにしてゆく予定だ。

これまでは、プログラムを fx-5800P に手入力するしかなかったが、ダウンロードしたCCLファイルを CcLinker を使って fx-5800P に転送できるので、インターネットを使った fx-5800P のプログラムの流通が容易になる。



CcEditor

Takumako様のホームページ では、CcEditor が公開されている。

これを使うと、fx-5800P の Casio Basic をPC上でコーディングし、CcLinker で扱える CCL ファイルに変換できる。CCL ファイルを変更し、CCLファイルに変換することも可能だ。

それ以上に CcEditor の面白いところは、fx-5800P の Casio Basic で公開されていない機能を使うことが出来る点にある。
  • 表示文字列としてアルファベットの小文字、ギリシャ文字(大文字と小文字)が自由に使える
  • 変数にアルファベット小文字やギリシャ文字(大文字と小文字)が使える
  • 変数に添え字として数字アルファベットギリシャ文字を使える。
"fx-5800P Casio Basic をPCでコーディング - CcEditor" を参照。 

CcLinkerCcEditor を併用すると、fx-5800P の隠し機能として、表示に小文字が使え、使える変数が大幅に増加するので、fx-5800 Casio Basic プログラミングの幅が大きく広がる。



今後、何か分かれば随時追記修正してゆく。



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-5800PCasioBasic、データリンク、CcLinker

リンク集 | ブログ内マップ


関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

グラフ関数電卓 - 高速素因数分解、15桁対応

2020/08/15
追記:2020/08/15
修正:2020/08/17
追記:2020/08/21
追記・修正:2020/10/11
Windowsアプリアップデート&追記修正:2020/12/06
バグフィックス:2021/01/02

以前、fx-5800P の素因数分解の高速化プログラムを紹介しています。
fx-5800P 素因数分解 - 高速化

さらに、これをグラフ関数電卓に移植しました。
 グラフ関数電卓用 FactorG のダウンロード [2021/01/02 バグフィックス]
  バグフィックス:終了時に行列を解放しない点を修正し、不要なWhileEndを削除しました。
このプログラムは、純正Casio Basic用であり、純正Casio Basic は計算精度が得られるのは最大 10桁に制限されているので、プログラムの入力値は最大10桁になっていて、10桁を超えるとエラーを出して終了するようにしています。

その後、この FactorG を fx-CG50 の Python モード(Casio Python) に移植し、さらに15桁対応しました。
Casio Python - 要素数の多いリスト:高速素因数分解(5)

そこで、Casio Basic プログラムも15桁入力対応しようと考えました。純正Casio Basicでは、10桁の精度しかありません。しかし、上位互換であるアドイン版Casio Basic - C.Basic では15桁まで計算精度が得られるので、今回は C.Basic で走らせることを前提にして、純正Casio Basicで作った FactorG プログラムを15桁対応に変更します。


15桁入力に拡張するための条件

15桁入力に拡張するには計算精度が15桁であることが条件で、それを満たすのは、グラフ関数電卓のなかで、Pythonモード (Casio Python) と アドイン版 Casio Basic (C.Basic) が走る下記のモデルが必要です。

Casio Python が走るグラフ関数電卓のモデル
  • fx-CG50 OS3.2 以降
  • fx-9750GIII / fx-9860GIII OS3.4 以降

C.Basic が走るグラフ関数電卓のモデル
  • fx-9860G / fx-9860G SD / fx-9860G Slim (C.Basic for FX)
  • fx-9860GII / fx-9860GII SD (C.Basic for FX)
  • fx-9750GIII / fx-9860GIII (C.Basic for FX)
  • fx-CG20 / fx-CG50 (C.Basic for CG)

15桁入力に拡張した Casio Python スクリプト

以下の記事で紹介しているので、そちらを参照してください。
Casio Python - 要素数の多いリスト:高速素因数分解(5)

スクリプトは下記からダウンロードできます。
FactorG5 - Python スクリプト FactorG5.py (Ver 5.0)

FactorG5_input15 FactorG5_result 


15桁入力に拡張した C.Basic プログラム

今回は、以下のような C.Basic プログラムを作成します。

FactorG2_input15 FactorG2_result2  

そこで、以前作った10桁対応の以下のメインルーチン FACTORG.g3m とサブルーチン WFSUB.g3m を修正する作戦で進めます。そのために、以前作成した 10桁対応の FACTORG をダウンロードしておきます。
10桁対応の FACTORG ファイルのダウンロード [2021/01/02 バグフィックス]
  バグフィックス:終了時に行列解放しない点を修正し、不要なWhileEndを削除しました。

ダウンロードしたファイル FactorG.zip には、FXシリーズ (fx-9860G, fx-9860GII, fx-9750GIII, fx-9860GIII)で使える g1m ファイル、CGシリーズ (fx-CG20, fx-CG50) で使える g3m ファイル、そしてテキストファイルを同梱しています。C.Basic は、テキストファイルを読み込んで実行したり、g3m ファイルや g1m ファイルに変換できます。そこでテキストファイルをメモ帳で編集して 15桁対応に変更し、それを読み込んでからプログラムファイルに変換します。

さらに、15桁精度に対応していない純正Casio Basic で走らせることは考えなくて良いので、純正 Casio Basic に未対応の C.Basic 独自の拡張コマンドを活用してゆきます。

C.Basic については、FXシリーズ用の C.Basic for FX、そして CGシリーズ用の C.Basic for CG があり、それぞれ対応したバージョンをインストールして使えます。fx-9860G 以降の全てのグラフ関数電卓に対応しています。C.Basic については、下記 から必要なダウンロード、必要な説明を参照できます。 
アドイン版 Casio Basic - トップページ

今回は、fx-CG50C.Basic for CG を使います。


15桁入力対応高速素因数分解プログラムへの修正箇所

FACTORG
{1,22}->Dim Mat Z  ◀修正対象
"NUMBER"?->F
If F<1 Or F>=1Exp10 ◀ 修正対象
Then "NUMBER MUST BE >=1 And <1Exp10" ◀修正対象
Stop
IfEnd
If F<>Int (F)
Then "NUMBER MUST BE AN INTEGER" ◀修正対象
Stop
IfEnd
For 1->E To 22  ◀修正対象
0->Mat Z[1,E]
Next
0->Mat Z[1,1]  ◀修正対象
0->Mat Z[1,12]  ◀修正対象
0->E
F->A
Int (Sqrt(A))->C
2->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
3->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
5->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
7->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
11->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
                             ◀追加
While 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
・・・
・・・  ◀このWhileループは全面差替え
・・・
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB":B>C=>Goto 1
WhileEnd

Lbl 1
If A>1
Then Isz E
A->Mat Z[1,E]
1->A
1->Mat Z[1,E+11] ◀修正対象
IfEnd
Int (E/6)->D
E-6*D>0=>Isz D
1->C

Lbl 2
ClrText
Locate 1,1,F    ◀修正対象
Locate 12,1,C  ◀修正対象
Locate 13,1,":" ◀修正対象
Locate 14,1,D  ◀修正対象
6*(C-1)+1->B
Locate 1,2,Mat Z[1,B]    ◀修正対象
Locate 11,2,"^("        ◀修正対象
Locate 13,2,Mat Z[1,B+11] ◀修正対象
Locate 16,2,")"         ◀修正対象
If B+1<=E
Then Locate 1,3,Mat Z[1,B+1] ◀修正対象
Locate 11,3,"^("         ◀修正対象
Locate 13,3,Mat Z[1,B+12]    ◀修正対象
Locate 16,3,")"          ◀修正対象
IfEnd
If B+2<=E
Then Locate 1,4,Mat Z[1,B+2] ◀修正対象
Locate 11,4,"^("         ◀修正対象
Locate 13,4,Mat Z[1,B+13]    ◀修正対象
Locate 16,4,")"          ◀修正対象
IfEnd
If B+3<=E
Then Locate 1,5,Mat Z[1,B+3] ◀修正対象
Locate 11,5,"^("         ◀修正対象
Locate 13,5,Mat Z[1,B+14]    ◀修正対象
Locate 16,5,")"          ◀修正対象
IfEnd
If B+4<=E
Then Locate 1,6,Mat Z[1,B+4] ◀修正対象
Locate 11,6,"^("         ◀修正対象
Locate 13,6,Mat Z[1,B+15]    ◀修正対象
Locate 16,6,")"          ◀修正対象
IfEnd
If B+5<=E
Then Locate 1,7,Mat Z[1,B+5] ◀修正対象
Locate 11,7,"^("         ◀修正対象
Locate 13,7,Mat Z[1,B+16]    ◀修正対象
Locate 16,7,")"          ◀修正対象
IfEnd

While Getkey:WhileEnd     ◀修正対象

Do
Getkey->K            ◀修正対象
LpWhile K=0
While Getkey            ◀修正対象 
WhileEnd             ◀修正対象
0->M
If K=47 Or K=44
Then 1->M
Else If K=27 Or K=37 Or K=31
Then 2->M
Else If K=28 Or K=38 Or K=41
Then 3->M
Else Goto 2
IfEnd:IfEnd
IfEnd

If M=1
Then ClrText
"DONE"
Else If M=2
Then Isz C
C>D=>1->C
Goto 2
Else If M=3
Then C-1->C
C<1=>D->C
Goto 2
IfEnd:IfEnd
IfEnd
ClrMat Z


WFSUB
E+1->E
B->Mat Z[1,E]
Do
D->A
Mat Z[1,E+11]+1->Mat Z[1,E+11] ◀修正対象
A/B->D
LpWhile Frac (D)=0
Int (SqrtA)->C
Return


上でダウンロードした FactorG.zip に同梱してあるテキストファイル FACTORG.txt を編集し、以下の具体的な変更を行います。完成した後、C.Basic 内蔵機能により g3m ファイルに変換して完成させます。


(1) 不要な初期化を削除
For 1->E To 22
0->Mat Z[1,E]
Next
0->Mat Z[1,1]
0->Mat Z[1,12]

0->E
F->A


変数の初期化のうち、For 文で行列 Z を全て 0 に初期化されているので、上記赤文字の初期化は不要です。従って削除します。


(2) 行列の確保領域の拡大に伴う変更
入力桁数を拡大するにともない、見つかる素因数の数も増えるので、素因数を格納する行列をほぼ倍に拡大します。
オレンジ色で示した部分は、以下のようにします。修正部分は赤文字にします。
行列確保の 2142 に変更、1121 に変更します。


FACTORG2
{1,42}->Dim Mat Z
・・・
For 1->E To 42
0->Mat Z[1,E]
Next

・・・
1->Mat Z[1,E+21]


WFSUB2
・・・
Mat Z[1,E+21]+1->Mat Z[1,E+21]
・・・


(3) 入力値の桁数制限を15桁にするための変更
入力値の制限とエラーメッセージを15桁対応にするため、修正文を赤文字にします。

FACTORG2
If F<1 Or F>=1Exp15
Then "NUMBER MUST BE    >=1 And <1Exp15"
Stop
IfEnd
If F<>Int (F)
Then "NUMBER MUST BE    AN INTEGER"


エラーメッセージは、BE のあとのスペースを7個にしすることで、表示した時に改行したようにみせます。


(4) Lbl 2 以下を、入力値と素因数の桁数増加に合わせて変更

C.Basic は計算精度は15桁ですが、設定によっては数値を出力する際に10桁を超えると指数表示になります。C.Basic では Norm の機能が拡張されていて、プログラム冒頭で Norm15 と記述するだけで 15桁までは指数表示されないように設定できます。今回はもう一つの方法として、数値を文字列に変更して Locate で出力する方法で変更してみます。Norm15 の方がスマートでコードがスッキリするかも知れませんが、今回は文字列を使うベタなやり方にしてみます。

以下のサンプルプログラムを見て下さい。

?->F
ToStr(F)->Str 1
log F>=10=>ToStr(Int(F÷E10))+ToStr(F-Int(F÷E10)×E10 )->Str 1
Locate 1,1,Str 1


値を入力させ、それを文字列に変換してLocate で出力するサンプルです。このコードを使います。

画面1行目に入力値と出力ページを出力する部分は、以下のようになります。変更箇所は赤文字で示します。

Lbl 2
ClrText
ToStr(F)->Str 1
log F>=10=>ToStr(Int (F/Exp10))+ToStr(F-Int (F/Exp10)*Exp10)->Str 1

Locate 1,1,Str 1
Locate 18,1,C
Locate 19,1,":"
Locate 20,1,D


このコードの下に、求めた素因数を1ページ分出力するコードが続きます。以下のように修正します。変更箇所は赤文字で示します。

6*(C-1)+1->B
Mat Z[1,B]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,2,Str 1
Locate 16,2,"^("
Locate 18,2,Mat Z[1,B+21]
Locate 21,2,")"
If B+1<=E
Then
Mat Z[1,B+1]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,3,Str 1
Locate 16,3,"^("
Locate 18,3,Mat Z[1,B+22]
Locate 21,3,")"
IfEnd
If B+2<=E
Then
Mat Z[1,B+2]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1

Locate 1,4,Str 1
Locate 16,4,"^("
Locate 18,4,Mat Z[1,B+23]
Locate 21,4,")"
IfEnd
If B+3<=E
Then
Mat Z[1,B+3]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1

Locate 1,5,Str 1
Locate 16,5,"^("
Locate 18,5,Mat Z[1,B+24]
Locate 21,5,")"
IfEnd
If B+4<=E
Then
Mat Z[1,B+4]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,6,Str 1

Locate 16,6,"^("
Locate 18,6,Mat Z[1,B+25]
Locate 21,6,")"
IfEnd
If B+5<=E
Then
Mat Z[1,B+5]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1

Locate 1,7,Str 1
Locate 16,7,"^("
Locate 18,7,Mat Z[1,B+26]
Locate 21,7,")"
IfEnd


(5) 素因数探索コード自体の変更

最初に素数2,3,5,7、11 で割り算して素因数を探索する部分は、さらに素数 13 で割り算するように追加します(赤文字)。

Int (Sqrt(A))->C
2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
3->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
5->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
7->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
11->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
13->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1



さて、これに続くWhile ループでは、以下のように Bに増分 (4, 2, 4, 6, ...) を加えて探索数とし、それで割り算して探索数を得る処理を1行で記述している。
While 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1

・・・
・・・
・・・

以前作っているコードでは、2,3,5,7 のいずれの倍数でもない 13 ~ 222 までの 48 個の探索数を用いている。今回は探索数を増やすため、2, 3, 5, 7, 11 のいずれの倍数でもない 17~2325までの 480 個の探索数に拡張して、さらに高速化を試みます。

但し、探索数の増分の計算そして 480 行の記述をエディタで作成するのは非現実的なので、480個の増分の計算とWhlle ループの中の480行の記述を作成して出力するWindowsアプリを作って、カット&ペーストで一気に作成することにします。

 FactorG2 作成支援 Windowsアプリ - SearchNumCG11 のダウンロード

ダウンロードするファイル SearchNumCB11.zip には、実行ファイル SearchNumCB11.exe と C#のソースファイルを同梱しています。 Visual Studio 2019 Community で作成しました。

実際にタイプして作った肝心のコードは以下です。
(参考) C# では、以下の CalcNum() 関数の実装部分と CalcNum() 関数を呼び出す1行の記述(合計21行)以外は一切コーディングせず、プロパティの設定を行うだけでWindowsアプリを作れることを申し添えておきます。チョット慣れれば、この程度の簡易的なWindowsアプリが簡単かつ迅速に作れるので、大変お勧めです。C#入門講座 など、ご自分に合った入門講座を探してみて下さい。
#foreachループ内の Result.AppendText() は速度低下するけど、この程度なら許せるので許してください。Casio Basic作成支援やCasio Pyton作成支援で作った一連のSearchNumでは、この速度低下に対応したものもあります。詳しくはダウンロードしたソースを見てください。


private void CalcNum()
{
 int prev_num = 13;
 int m = 17;
 int n = 2*3*5*7*11;
 int line = 0;
 String str = "";
 foreach (int num in Enumerable.Range(m,n))
 {
  if ((num % 2) * (num % 3) * (num % 5) * (num % 7) * (num % 11) != 0)
  {
   str = "B+" + (num - prev_num).ToString() + "->B:A/B->D:Frac (D)=0=>Prog \"WFSUB2\":B>C=>Goto 1";
   prev_num = num;
   Result.AppendText(str + "\r\n");
   line++;
  }
 }
 Result.AppendText("\r\n" + line.ToString() + " lines");
 Calc.Enabled = false;
}

整数 num に 17~2326 までの整数を適用し、num が 2, 3, 5, 7, 11 のいずれかの倍数でもない時の num を探索数と識別し、1つ前の num との差 (num - prev_num) を [増分] とし、順次
B+[増分]->B:A/B->D:Frac (D)=0=>Prog "WFSUB2:B>C=>Goto 1
をテキストボックスに出力します。

さっそく SearchNumCB11.exe を起動します。
SearchCB11_input 

[Calculate] ボタンをクリックすると必要な記述が出力されます。
SearchCB11_result 

テキストボックス内は、自由に編集ができます。テキストボックスから必要な部分をカットコピーし、エディタで開いた FACTORG2.txt のなかで該当する While 1WhileEnd の間にペーストします。

例えば、テキストボックスで [Ctrl]+[A] で全てを選択し、[Shift]+[↑] を押してから [Ctrl]+[C] でコピーし、エディタで開いた FACTORG2.txt の 該当部分に [Ctrl]+[V]でペーストします。これで、480行のコードが一気に完成します。

一見回りくどいようですが、タイプミスの抑制と作業全体のタイプ量の大幅な節約、そしてなにより時間の節約になったと思います。


(6) 出力に色を付け、同じコードでモノクロ液晶機種用 g1m ファイルとの互換性を保つ

目標の出力を以下のようにします。
FactorG2_result2 

入力値を、乗数の ^( )で出力するには、red Locateblue Locateとします。
但し、色指定は カラー液晶を搭載した fx-CGシリーズのみで有効となり、モノクロ液晶の fx-9860Gシリーズや fx-9750GIII ではエラーになります。そこで、C.Basic の拡張コマンド System(-1) を使って機種判定を行い、CGシリーズの時は色指定をしたLocateコマンドを実行し、そうでない時は色指定なしの Locate コマンドを実行させれば良いわけです。
System(-1) は、CGシリーズでは 10 以上の整数を返し、それ以外では1桁の整数を返します。

そこで、プログラムの冒頭で機種判断を行うことにします。
0->G:System(-1)>=10=>1->G

このように、変数G を 0 で初期化しておき、CGシリーズの時は 1 になるようにしておきます。

CGシリーズで赤で出力する場合、モノクロ機種で色指定をしないために、
If G:Red Locate 1,1,Str 1
Else Locate 1,1,Str 1:IfEnd


CGシリーズで青で出力する場合、モノクロ機種で色指定をしないために、
If G:Blue Locate 16,2,"^("
Else Locate 16,2,"^(":IfEnd


If G:Blue Locate 21,2,")"
Else Locate 21,2,")":IfEnd


とします。

以上を適用すると Lbl 2 以降は、以下のようになります。修正した部分を赤文字で示します。

Lbl 2
ClrText
ToStr(F)->Str 1
log F>=10=>ToStr(Int (F/Exp10))+ToStr(F-Int (F/Exp10)*Exp10)->Str 1
If G:Red Locate 1,1,Str 1
Else
Locate 1,1,Str 1:IfEnd
Locate 18,1,C
Locate 19,1,":"
Locate 20,1,D
6*(C-1)+1->B
Mat Z[1,B]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,2,Str 1
If G:Blue Locate 16,2,"^("
Else
Locate 16,2,"^(":IfEnd
Locate 18,2,Mat Z[1,B+21]
If G:Blue Locate 21,2,")"
Else
Locate 21,2,")":IfEnd
If B+1<=E
Then
Mat Z[1,B+1]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,3,Str 1
If G:Blue Locate 16,3,"^("
Else
Locate 16,3,"^(":IfEnd
Locate 18,3,Mat Z[1,B+22]
If G:Blue Locate 21,3,")"
Else
Locate 21,3,")":IfEnd
IfEnd
If B+2<=E
Then
Mat Z[1,B+2]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,4,Str 1
If G:Blue Locate 16,4,"^("
Else
Locate 16,4,"^(":IfEnd
Locate 18,4,Mat Z[1,B+23]
If G:Blue Locate 21,4,")"
Else
Locate 21,4,")":IfEnd
IfEnd
If B+3<=E
Then
Mat Z[1,B+3]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,5,Str 1
If G:Blue Locate 16,5,"^("
Else
Locate 16,5,"^(":IfEnd
Locate 18,5,Mat Z[1,B+24]
If G:Blue Locate 21,5,")"
Else
Locate 21,5,")":IfEnd
IfEnd
If B+4<=E
Then
Mat Z[1,B+4]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,6,Str 1
If G:Blue Locate 16,6,"^("
Else
Locate 16,6,"^(":IfEnd
Locate 18,6,Mat Z[1,B+25]
If G:Blue Locate 21,6,")"
Else
Locate 21,6,")":IfEnd
IfEnd
If B+5<=E
Then
Mat Z[1,B+5]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,7,Str 1
If G:Blue Locate 16,7,"^("
Else
Locate 16,7,"^(":IfEnd
Locate 18,7,Mat Z[1,B+26]
If G:Blue Locate 21,7,")"
Else
Locate 21,7,")":IfEnd
IfEnd


以上のようにすると、CGシリーズでもそれ以外でも互換性を保って動作可能になります。


(7) Getkey を Getkey1 に変更する
今回は、C.Basic専用のプログラムに変更するので、純正 Casio BasicGetkey コマンドを C.Basic拡張コマンド Getkey1 に置き換えます。Getkey コマンドは キーが押されるその時に実行されると キーコードを取得する仕様なので、キー取得はループの中に Geteky を記述しなければなりません。キー入力で動作を分岐する動作が連続するとき、同じキーを少し長めに押すと連続して同じキーが押されたと誤判定されることがあり、その際は 
While Getkey:WhileEnd
を記述して、キーが離されないと先に進めない機能(関所の機能)を設ける必要があります。

一方で、C.Basicの拡張コマンド Getkey1 は、キーが押されるまで待つ機能が付加されます。するとキーが離されないと先に進めないようにするループが不要になります。

(6) で検討した結果を出力するコードに続く、結果表示のページを切り替えるためのキー入力コードは以下のようになっています。

While Getkey:WhileEnd

Do
Getkey->K
LpWhile K=0
While Getkey
WhileEnd


Getkey->KGetkey1->K に変更した上で、以下のように変更できます。

Do
Getkey1->K
LpWhile K=0


変更前の以下のコードに含まれる2箇所の While Getkey:WhileEnd を削除します。


(8) g1m ファイルと g3m ファイルに変換する

これまでは、テキストファイルで編集してきました。C.Basic では、テキストファイルから g3m ファイルや g1m ファイルに変換できます。

FACTORG2.txtfx-CG50 に転送します。

次に、C.Basic のファイルリスト画面で FACTORG2.txt を選択
Select_txt_file 

[F6] (▷) を押し、
Coverting_txt_file 

さらに、[F1] (CONVERT) を押し、
Coverte_txt_file 

[F2] (g1m) を押せば、g1m ファイルに変換され、
[F3] (g3m) を押せば、g3m ファイルに変換されます。



15桁対応、高速素因数分解 - FACTORG2.g3m の実行

 ダウンロード:15桁対応・高速素因数分解 FACTORG2 (for C.Basic) 
  [2021/01/02 バグフィックス] バグフィックス:終了時に行列解放しない点を修正しました。

参考のため、以前作った Pythonモード (Casio Python) の FactorG5.py の実行結果と比較します。

search_30445_f  CBResult2_1 

Search_39969_f  CBResult2_2 

seach_47824_f  CBResult2_3 
Case1_14digit  CBResult2_4 

search_90872_f  CBResult2_5 

search_189426_f.png  CBResult2_6 
search_263027_f.png  CBResult2_7 

search_343013_f.png  CBResult2_8 

search_2025804_f.png  CBResult2_9 
search_4349444_f.png  CBResult2_10 


表2- 15桁版高速素因数分解実行時間の違い - Casio Python と C.Basic の比較
    (fx-CG50 OS3.4 使用)
Casio Python
FactorG5.py
C.Basic
FACTORG2.g3m
 WFSUB2.g3m
高速化
入力値実行時間 [秒]実行時間 [秒]時間差 [%]
547,896,321,054,789 8.74.350.6
7,845,162,037,849 11.45.452.6
748,159,026,374,815 13.76.453.3
36,209,518,473,620 15.57.551.6
986,753,421,098,675 
26.011.854.6
96,835,724,130,261 52.724.952.8
748,159,026,396,835 73.134.353.1
96,835,724,136,209 95.344.653.2
748,159,026,336,209 585.0
(9分45秒)
255.8
 (4分15.8秒)
56.3
362,095,184,736,209 1,235.6
(20分35.6秒)
553.3
(9分13.3秒)
55.2

Casio Python よりも C.Basic が2倍程度高速だと分かりました。

現状の Casio Python では、動作中にリアルタイムでキー入力を受け付けることができません。一方、純正 Casio BasicC.Basic ではリアルタイムキー入力が可能なので、プログラミング言語としてはより実用的と言えます。


さらに高速化する [2020/08/15 追記]

さらに高速化するために今回拡張した While ループ内で実行する探索数をさらに増やしてみました。

素数での割り算を2~13に加えて17での割り算を追加し、それに続く Whileループでの素因数探索を 2, 3, 5, 7, 11, 13のいずれの倍数でない整数で割り算するように拡張してみました。すると、このループ内は 5760 行となります。上と同様に新たに専用Windowsアプリを作成し、カット&ペーストで追加し、FACTORG3.g3m を作成しました。

FACTORG3.g3m 作成支援アプリ - SearchNumCB13 ver2.0 のダウンロード 
 ※ [2020/12/06 ver2.0 にアップデート - 処理の大幅な高速化]

これを実行すると以下のように出力されます。
SearchCB13_result

5760行ものコードを追加すると、FACTORG3.g3m のファイルサイズは 210,028 バイト (210Kバイト) になり、上で作った FACTORG2.g3m の10倍程度の大きなファイルです。

幸い fx-CG50 では実行可能で、上で作成した FACTORG2.g3m よりも 7% 程度高速化しました。
15桁対応高速素因数分解プログラム - FACTORG3.zip のダウンロード

現在のところ、C.Basic for CG で動作する FACTORG3.g3m が最速です。
但し、ファイルサイズがあまりにも大きくメモリを無駄食いする割に、7%程度の高速化なので、管理人としては FACTORG2.g3m を推奨したいと思います。

なお、FACTORG3.zip に同梱している FACTORG3.g1m (モノクロ機種用) は、C.Basic for FX ではファイルサイズが大きすぎて実行できないので、上で作った FACTORG2.g1m がモノクロ液晶機種対応としては、最速になります。従って、g1m と g3m で互換性のある FACTORG2 (g1m/g3m互換) をやはり推奨したいと思います。


もう一段高速化を試みる

探索数をさらに拡張した FACTORG4.g3m について
同様に、FACTORG4 作成支援アプリ SearchNumCB17 [2020/12/06 Ver2.0 にアップデート、処理の高速化]  を作って実行させると、なんと 92160 行ものコードを生成します。

SearchCB17_result

この出力をカット&ペーストして、テキストファイル FACTORG4.txt を作成すると 4787 Kバイト (4.8Mバイト) となり、fx-CG50 のストレージメモリの最大容量である 1.6 Mバイトを超えてしまい、メモリ不足で fx-CG50 に転送できません。ここが限界のようです。

最速は、FACTORG3.g3m で、実用的には FACTORG2.g3m で十分だという結論にしておこうと思います。
===== [2020/08/15 追記] 終わり =====


モノクロ機種での FACTORG2.g1m の実行

fx-9750GIII で 15桁対応高速素因数分解 - FACTORG2.g1m を実行してみます。 

CBMResult 

CBMResult_11 CBMResult_12 CBMResult_13 

fx-9750GIIIfx-9860Gシリーズ (fx-9860GIIIfx-9860GII, fx-9860GII SDfx-9860G, fx-9860G SD, fx-9860G Slim) にインストールした C.Basic for FX でも自動機種判定がうまくいって、同様の出力が得られることが確認できました。


今回作成したコード (テキストファイルの表記)

 ダウンロード:15桁対応・高速素因数分解プログラム - FACTORG2 (for C.Basic)

今回紹介したような支援アプリを使わないと到底作成ができないことがよく分かります。


FACTORG2.txt
0->G:System((-)1)>=10=>1->G
{1,42}->Dim Mat Z
"NUMBER"?->F
If F<1 Or F>=1Exp15
Then "NUMBER MUST BE >=1 And <1Exp15"
Stop
IfEnd
If F<>Int (F)
Then "NUMBER MUST BE AN INTEGER"
Stop
IfEnd
For 1->E To 42
0->Mat Z[1,E]
Next
0->E
F->A
Int (Sqrt(A))->C
2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
3->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
5->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
7->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
11->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
13->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
While 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+14->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+10->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+14->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+8->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+6->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+4->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+2->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
B+12->B:A/B->D:Frac (D)=0=>Prog "WFSUB2":B>C=>Goto 1
WhileEnd

Lbl 1
If A>1
Then Isz E
A->Mat Z[1,E]
1->A
1->Mat Z[1,E+21]
IfEnd
Int (E/6)->D
E-6*D>0=>Isz D
1->C

Lbl 2
ClrText
ToStr(F)->Str 1
log F>=10=>ToStr(Int (F/Exp10))+ToStr(F-Int (F/Exp10)*Exp10)->Str 1
If G:Red Locate 1,1,Str 1
Else Locate 1,1,Str 1:IfEnd
Locate 18,1,C
Locate 19,1,":"
Locate 20,1,D
6*(C-1)+1->B
Mat Z[1,B]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,2,Str 1
If G:Blue Locate 16,2,"^("
Else Locate 16,2,"^(":IfEnd
Locate 18,2,Mat Z[1,B+21]
If G:Blue Locate 21,2,")"
Else Locate 21,2,")":IfEnd
If B+1<=E
Then
Mat Z[1,B+1]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,3,Str 1
If G:Blue Locate 16,3,"^("
Else Locate 16,3,"^(":IfEnd
Locate 18,3,Mat Z[1,B+22]
If G:Blue Locate 21,3,")"
Else Locate 21,3,")":IfEnd
IfEnd
If B+2<=E
Then
Mat Z[1,B+2]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,4,Str 1
If G:Blue Locate 16,4,"^("
Else Locate 16,4,"^(":IfEnd
Locate 18,4,Mat Z[1,B+23]
If G:Blue Locate 21,4,")"
Else Locate 21,4,")":IfEnd
IfEnd
If B+3<=E
Then
Mat Z[1,B+3]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,5,Str 1
If G:Blue Locate 16,5,"^("
Else Locate 16,5,"^(":IfEnd
Locate 18,5,Mat Z[1,B+24]
If G:Blue Locate 21,5,")"
Else Locate 21,5,")":IfEnd
IfEnd
If B+4<=E
Then
Mat Z[1,B+4]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,6,Str 1
If G:Blue Locate 16,6,"^("
Else Locate 16,6,"^(":IfEnd
Locate 18,6,Mat Z[1,B+25]
If G:Blue Locate 21,6,")"
Else Locate 21,6,")":IfEnd
IfEnd
If B+5<=E
Then
Mat Z[1,B+5]->z
ToStr(z)->Str 1
log z>=10=>ToStr(Int (z/Exp10))+ToStr(z-Int (z/Exp10)*Exp10)->Str 1
Locate 1,7,Str 1
If G:Blue Locate 16,7,"^("
Else Locate 16,7,"^(":IfEnd
Locate 18,7,Mat Z[1,B+26]
If G:Blue Locate 21,7,")"
Else Locate 21,7,")":IfEnd
IfEnd

Do
Getkey1->K
LpWhile K=0
0->M
If K=47 Or K=44
Then 1->M
Else If K=27 Or K=37 Or K=31
Then 2->M
Else If K=28 Or K=38 Or K=41
Then 3->M
Else Goto 2
IfEnd:IfEnd
IfEnd

If M=1
Then ClrText
"DONE"
Else If M=2
Then Isz C
C>D=>1->C
Goto 2
Else If M=3
Then C-1->C
C<1=>D->C
Goto 2
IfEnd:IfEnd
IfEnd
ClrMat Z


WFSUB.txt
E+1->E
B->Mat Z[1,E]
Do
D->A
Mat Z[1,E+21]+1->Mat Z[1,E+21]
A/B->D
LpWhile Frac (D)=0
Int (SqrtA)->C
Return







応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: プログラム関数電卓、fx-CG50、C.Basic、素因数分解、プログラミング、Casio Basic

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

fx-5800P 素因数分解 - さらなる高速化

2020/12/04
追記修正:2020/12/05
バグフィックス:2021/01/02


fx-5800P 素因数分解 - 高速化 で、Casio Basic プログラムによる素因数分解 の大幅な高速化を紹介していますが、今回はそれをさらに高速化できたので紹介します。

今回は高速化するために、あらゆる使えるものを総動員して fx-5800P Casio Basic プログラムを効率よく作成する、一風変わったアプローチを採用することになりました。


fx-5800P の Casio Basic プログラムをPCで編集

カシオは、fx-5800PのプログラムやデータをPCリンクする手段を提供していませんが、takumako様によりPCリンクするハードウェアとソフトウェア - CcLinker が提供されています。さらに fx-5800P の Casio Basic プログラムをPCで編集するためのエディタ - CcEditor が提供されています。

それぞれの使い方については、以下を参照してください。
 CcLinker - ついに fx-5800P がPCリンク可能になった を参照
 CcEditor - fx-5800P Casio Basic をPCでコーディング - CcEditor を参照


fx-5800P のプログラムをファイルに変換する
今回改造する fx-5800P の Casio Basic プログラム - Factor-F1 を CcLinker でPCに転送します。

FACTOR-F1 のダウンロード [2021/01/02 バグフィックス]
  バグフィックス:終了時に配列変数を解放しない点を修正し、不要な WhileEndを削除しました。
※ ダウンロードした zip ファイルには、fx-5800P で使う2つの ccl ファイルとそれらのテキストファイルを含んでいます。FACTOR-F1.cllWFSUB.ccl を fx-5800P に転送すれば、FACTOR-F1 を走らせられます。


CcLinkerドングルをPCに刺してから、fx-5800P をつなぎ、CcLinker ソフトウェアを起動します。
CcLinker_StartUp 

fx-5800P 素因数分解 - 高速化 で作ったプログラム FACTOR-F1 を fx-5800P から PC へ転送すると、転送したファイルを保存するコモンダイアログが現れます。
CcLinker_DownLoaded

ファイル名を FACTOR-F1.ccl にして、[開く] をクリック。
この場合は、Download フォルダにダウンロードしているので、Download フォルダに FACTOR-F1.ccl が作成されます。

FACTOR-F1 は サブルーチンとして WFSUB を使っています。結論から言えば WFSUB は変更しないので、そのままにしておきます。


FACTOR-F1.ccl を CcEditor で開く
今回編集するプログラムがファイル FACTOR-F1.ccl になったので、それを編集するために CcEditor で開きます。
CcEditor_Loaded

CcEditor で fx-5800P のプログラム FACTOR-F1 が編集できるようになりました。


素因数分解の基本的アルゴリズム

あらゆる整数は、素数の積で表せるので、その素数の積を求めるのが素因数分解です。
ところで、素数とは、1と自分自身以外で割り切れない (1と自分自身以外の約数がない) 整数です。
ちなみに、1は素数ではなく、2,3、5、7,11,13、17、19,23 ... と素数は無限にあります。

与えられた数 (自然数) をそれより小さい自然数 (=探索数) で割って、割り切れるかどうかを調べます、割り切れるかどうかを調べる自然数を探索数と呼ぶことにします。
  • 与えられた数を最小の素数2で割って割り切れたら、2は素因数の1つです。2で割り切れる場合は、何回2で割り切れるかを調べます。そして、2の倍数を探索数から除外します。
  • 2の次に大きな素数は3なので、与えられた数が3で割り切れるかどうかを調べ、割り切れる場合は何回3で割り切れるかどうかを調べます。そして、3の倍数も探索数から除外します。
  • 3の次に大きな素数は5なので、与えられた数が5で割り切れるかどうかを調べます。割り切れる場合は何回5で割り切れるかを調べます、そして探索数から5の倍数も除外します。
こうやって小さい順に素数を探索数として使うのが理想的ですが、素数でなくても問題ありません。いずれにしても、その倍数を使わないようにして探索数を絞り込む方法が "エラストテレスの篩い" と言われているものです。

与えられた数が平方数 (平方根が整数になる数) の場合、その平方根が素数であることもあり、その場合は最大の素因数になります。与えられた数の平方数でなくても、その平方根 より小さく。その平方根に一番近い整数が最大の探索数になります。

プログラムファイルのサイズの上限が限られ、プログラム実行速度が遅い fx-5800P の Casio Basic では、割り算に用いる探索数をどうやって効率よく絞り込むかが、プログラム高速化のポイントになります。


高速素因数分解のアルゴリズム

以前紹介した高速素因数分解のアルゴリズムは、エラストテレスの篩い を効率化したもので、具体的には以下の方法で探索数を絞り込んでいます。

 探索数増分数を48個使って、効率よく探索数を絞り込む方法
a) 素数 2, 3, 5, 7, 11 を探索数として除算を繰り返し、
b) 13以上で 2, 3, 5, 7 のいずれかの倍数でもない探索数は 13~222 までには 210個の整数のうち48個あり、その48個の探索数で除算を繰り返し、
a) b) それぞれの除算の結果から素因数を調べます。13~222までの210個の整数のうち48個まで探索数を絞り込んでいます。詳しくは、前回の記事 を参照してください。

a)
Int(√(A))→C↵
2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
3→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
5→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
7→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
11→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1

探索数 B に 2、3、5、7、11 を適用しています。探索数が与えられた整数 A の平方根より小さく、それに近い整数 C よりも探索数が大きくなれば Goto 1 で探索が終わります。
1回の探索を1行で表現しています。

b)
While 1↵
B+2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+4→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
・・・・・
・・・・・

B+2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+10→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+10→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
WhileEnd↵

この While ループには48行の処理が含まれています。
a) で探索数 B は 11 になっており、増分 2、4、10 などを加えて新たな探索数にして、素因数探索を1行で処理しています。探索数が整数 A よりも小さく、さらに探索数が整数 C よりも大きい場合は、Goto 1 で探索が終わり、While ループを脱出します。ここで、ポイントはこの増分をどうやって求めるかです。48個程度なら手計算やエクセルを使って求められます。



今回は、同じロジックですが、エラストテレスの篩いをさらに効率化、つまり探索数の絞り込みをより効率化し、
探索の無駄をさらに減らすことによる計算の高速化
を試みます。

素数を探索数に用いる部分と、While ループ内の48行の探索部分を以下のように拡張します。

 探索数増分を増やして、素因数探索をさらに効率化する方法
A) 素数 2, 3, 5, 7, 11, 13 を探索数として除算を繰り返し、
B) 17以上で 2, 3, 5, 7, 11 のいずれかの倍数でもない探索数は、17~2326 までには480個あり、その480個の探索数で除算を繰り返し、
A) B) のそれぞれの除算の結果から素因数を調べます。17~2326 までの2310個の整数のうち480個の探索数まで絞りこんでいます。

探索数の取りこぼしを防ぐためには、周期2310の範囲で探索する必要があります。
念のため、探索数を 17~2326 の範囲で探し、それが480個になる説明は以下のようになります。
  • 2, 3, 5, 7, 11 の最小公倍数は 2310
  • 2, 3, 5, 7, 11 のいずれかの倍数でない探索数の増分は 2310 の周期
  • 探索数を17から調べるので、1周期の終わりは 2326
  • 2, 3, 5, 7, 11 のいずれの倍数でない整数の個数:480個
  • これの算出方法は以下の通り;
  •  2 の倍数の個数:2310/2 = 1155
  •  3 の倍数の個数:2310/3 = 770
  •  5 の倍数の個数:2310/5 = 462
  •  7 の倍数の個数:2310/7 = 330
  •  11 の倍数の個数:2310/11 = 210 ⇒ 以上の合計:2927個
  • .
  •  2と3の公倍数の個数:2310/6 = 385
  •  2と5の公倍数の個数:2310/10 = 231
  •  2と7の公倍数の個数:2310/14 = 165
  •  2と11の公倍数の個数:2310/11 = 105
  •  3と5の公倍数の個数:2310/15 = 154
  •  3と7の公倍数の個数:2310/21 = 110
  •  3と11の公倍数の個数:2310/33 = 70
  •  5と7の公倍数の個数:2310/35 = 66
  •  5と11の公倍数の個数:2310/55 = 42
  •  7と11の公倍数の個数:2310/77 = 30 ⇒ 以上の合計:1358個
  • .
  •  2と3と5の公倍数の個数:2310/2/3/5 = 77
  •  2と3と7の公倍数の個数:2310/2/3/7 = 55
  •  2と3と11の公倍数の個数:2310/2/3/11 = 35
  •  2と5と7の公倍数の個数:2310/2/5/7 = 33
  •  2と5と11の公倍数の個数:2310/2/5/11 = 21
  •  2と7と11の公倍数の個数:2310/2/7/11 = 15
  •  3と5と7の公倍数の個数:2310/3/5/7 = 22
  •  3と5と11の公倍数の個数:2310/3/5/11 = 14
  •  3と7と11の公倍数の個数:2310/3/7/11 = 10
  •  5と7と11の公倍数の個数:2310/5/7/11 = 6 ⇒ 以上の合計:288個
  • .
  •  2と3と5と7の公倍数の個数:2310/2/3/5 = 11
  •  2と3と5と11の公倍数の個数:2310/2/3/5/11 = 7
  •  2と3と7と11の公倍数の個数:2310/2/3/7/11 = 5
  •  2と5と7と11の公倍数の個数:2310/2/5/7/11 = 3
  •  3と5と7と11の公倍数の個数:2310/3/5/7/11 = 2 ⇒ 以上の合計:28個
  • .
  •  2と3と5と7と11の公倍数の個数:2310/2/3/5/7/11 = 1個
  • .
  •  以上から 2927 - 1358 + 288 - 28 + 1 = 480個
a)
Int(√(A))→C↵
2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
3→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
5→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
7→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
11→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
13→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1

探索数の素数に 13 を追加します。CcEditor で一番下の赤文字の行を追加します。

b)
While 1↵
B+4→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+4→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
・・・・・
・・・・・
B+12→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+2→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1↵
B+12→B:A÷B→D:Frac(D)=0⇒Prog "WFSUB":B>C⇒Goto 1

WhileEnd↵

この While ループには、480行の素数探索処理が含まれます。この赤文字の部分の特に探索数の増分をどうやって効率よくかつ間違いなく計算し、480行もの入力をどうやって間違いなく効率よく行うのか、そこが問題です。そこで、今回は赤文字の部分を自動的に作成することにしました。


コードの自動作成
さて、手計算やエクセルで480個の探索数増分を計算して、それに基づき480行もの大量の記述を間違いなくタイプして入力するのは、現実的ではなく、あまりにも非効率です。そこで、探索数の増分の計算や、480行のプログラムコード作成を自動化するWindowsアプリを作ります。使えるものは何でも使う作戦です。これにより、カット&ペーストで CcEditor の画面に追記するだけで、480行の追加を簡単かつ確実に行えます。

この480個の探索数の増分を計算し、480行の Casio Basic のコードを自動作成する Windows デスクトップアプリ SearchNum11_10digits.exe を Visual Studio 2019 Community の C# で作りました。少しだけ C# を使ったことがあれは、マウスクリックだけで殆どを自動作成してくれ、全部で20行程度のコーディングを行うだけで、比較的簡単に出来ると思います。

 480行のコードを生成するWindowsデスクトップアプリ
 - SearchNum11_10digits のダウンロード


ダウンロードファイルには、アプリの実行ファイル (SearchNum11_10digits.exe) だけでなくソースコードも同梱していますので、ご興味があればご覧頂くなり、ご自分でビルドしたり改造してお使いください。
※ C# については、以前軽く紹介しています ⇒ プログラム電卓のための Windowsプログラミング

ところで、新しいWindowsアプリは、初めて実行するとき Windowsの保護機能により、まるで危ないソフトのように扱われます。これはこれまで使った人が少ないというだけでも、保護機能が発動するようになっています。自作のWindowsアプリを自分で作って起動しても保護機能が発動してしまいます。この保護機能が発動したときに対処方法について 自作プログラムがPC保護機能に引っかかる にまとめていますので、参考にしてください。

このアプリの重要なコードは以下のようにしています (ご参考まで)。
SearchNum11CB_code

C# を使えば、上記の20行と、この関数を呼び出すための1行、合わせて21行をタイプしてコーディングするだけで、あとはマウスのクリック操作をチョコチョコと行うことで、デスクトップアプリが簡単かつ迅速に作れてしまうのが良いところです。


さて、SearchNum11_10digits.exe を起動したところ:
SearchNum11CB_10digits_starinting

右上の [Calculate] ボタンを押すと、While ループ内のコードがテキストボックスに出力されます。
SearchNum11CB_10digits_result
出力されると [Calculate] ボタンを押せなくしています。

テキストボックスでは、改行したり編集ができます。そこで、これをカットアンドペーストにより、プログラムをエディタで開き、必要なところに貼り付ければ、プログラム修正が簡単にできます。

例えば、上のテキストボックスの中でクリックしてから、[Ctrl]+[A] で全部を選択してから、[↑] キーを押して 最後の行の Goto 1 まで選択した状態にして、[Ctrl]+[C] でコピーしてから、

CcEditor エディタで、

While 1

WhileEnd


の間にカーソルを移動して、[Ctrl]+[V] とすればペーストできます。 


編集したコードを FACTOR-F2.ccl としてPCに保存する

CcEditor で メニューの右にある Project を FACTOR-F1 から FACTOR-F2 に変更します。
CcEditor_FACTOR-F2

[File] - [Ceck] を選択します。
CcEditor_Check

しばらく待つと、コードの種類別に色が付きます。
CcEditor_Checked

関数、コマンド、文字列ごとに異なる色が付きますが、これは fx-5800P Casio Basic の特殊コードの種別に応じて色分けされた結果です。色分けがおかしなところは、文法に合わないコードなので、fx-5800P で実行するとエラーになる可能性が高いわけです。色分けのおかしなところは、よく見て必要ならば修正します。 この色分けは CcEditor の親切機能で、お好みの色分け設定に変更できます。

慣れないとよく分からないかも知れませんが、その場合は次の操作へ進んで下さい。最終的に fx-5800P でエラーが発生したら、その部分を fx-5800P 上で修正するか、CcEditor で修正すれば良いです。

そして、[File] - [Build] を選択して、FACTOR-F2.ccl ファイルを作成 (ビルド) します。
CcEditor_Build

しばらく待つと、cclファイルを作成するかを聞いてくるので、[はい] をクリックします。
CcEditor_ccl

※参考
 CcEditor では、少し待つ間に上の例のようにタイトルバーに (応答なし) と表示されることがあります。これは CcEditor のバグではなくて仕様です。マルチスレッド処理を行わない普通のWindowsアプリでは、アプリがCPUを独占して使う時間が少し長めになると、ウィンドウ表示の更新など内部で行われるマルチタスク処理が止まってしまうので、(応答なし) と表示してしまうのが、この表示の正体です。なのでアプリの処理が終わるまで少し待てば良いことが殆どです。但しアプリのバグで処理が終わらない場合も同じように (応答なし) と表示され、アプリの処理に時間がかかっているだけなのか、バグなのかの区別が付かないのも事実ではあります。

少し待てば、保存するファイル名を決めるコモンダイアログが現れます。
CcEditor_save_ccl

ここでは、ダウンロード先を Download フォルダに指定し、[開く(O)] をクリックします。
[開く(O)] をクリックする前にファイル名を FACTOR-F2.ccl に変更してもOKなので、ここではそのようにします。
CcEditor_save_FACTORF2 

すると、Download フォルダに FACTOR-F2.ccl が作成されます。

FACTOR-F2.ccl のダウンロード [2021/01/02 バグフィックス]
   バグフィックス: 終了時に配列変数が解放されない点を修正し、不要なWhileEndを削除しました。
※ ダウンロードしたzipファイルには、fx-5800P に転送する2つのcclファイルと、それらのテキストファイルを含んでいます。


FACTOR-F2 を fx-5800P に転送して実行する

fx-5800P のプログラムメモリ容量は、最大 28,432 バイトです。一方、今作成した FACTOR-F2.ccl のファイルサイズは、21,456 バイトと結構大きなファイルです。サブプログラム WFSUB.ccl は 147 バイトなので、合計で 21,603 バイト必要となり、容量ギリギリになります。

既に fx-5800P に多くのプログラムがあって、空き容量が足りない時は、FACTOR-F2 を転送できません。そこで、サブプログラム WFSUB 以外のプログラムを CcLinker でPCに待避させた後、WFSUB 以外のプログラムを削除しておき、FACTOR-F2.cclCcLinker で fx-5800P に転送します。

さて、サブプログラム WFSUB は変更せず、そのまま使用します。FACTOR-F2 で、7,849,516,203 (= 3 x 9811 x 88897) を素因数分解し、その実行時間を計ってみます。

FACTOR-F1FACTOR-F2高速化
111秒101秒9.0%


fx-5800P 素因数分解のさらなる高速化が達成できました!


最後に [2020/12/05 追記]

実は先に Pythonモードの Casio Python で素因数分解を高速化したのと同じ手法をfx-5800P のCasio Basic に適用したのが今回の記事です。詳しくは、Casio Python - 要素数の多いリスト:高速素因数分解(5) の表2で示しているように、ループが回る回数が 9.1% 減少し、高速化が 9~10% でした。一方、今回の fx-5800P での高速化が 9.0% であり、これは Casio Python での高速化の結果とほぼ一致しています。従って、素数以外の探索数で計算する While ループの実行回数を削減したことが高速化の主要因要因だといえます。

上で紹介した Casio Python での検討では、素数以外の探索数をさらに拡張して、Whileループの実行回数をさらに減らすことも試していて、さらに高速化できています。ただしプログラムファイル(スクリプトファイル)が恐ろしいほど大きくなってしまうことも判りました。同じことを fx-5800P 用に行っても、できあがるプログラムのファイルサイズが大きすぎて fx-5800P のメモリに収まりません。

今回の fx-5800P で高速化した Casio Basic プログラムファイルは、fx-5800P のメモリ容量ギリギリだったので、これ以上大きなプログラムファイルは実行できません。従って、今回作った FACTOR-F2 は、fx-5800P での最速素因数分解プログラム だと、ここでは言い切ってしまいます。

全く異なるスーパーロジックが、将来見つかるかも知れませんが、そのときが楽しみです!




応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: プログラム関数電卓、fx-5800P、素因数分解、Casio Basic

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

謹賀新年2021年

COW 
 
新年明けまして、おめでとうございます。

昨年は新型コロナ肺炎ウィルスに世界中が振り回されましたが、
今年は少しでも前向きで明るい気持ちを
持ち続けたいと思います。

カシオのプログラム電卓の Python モードが、
今年はさらにバージョンアップされるでしょう!

北米市場で圧倒的なコストパフォーマンスの fx-9750GIII を
今年は国内で販売してもらいたいものです。

fx-5800P の後継モデルはどうなるのでしょうか?

当ブログでは引き続き Casio Basic に光を当て続けながら、
Casio Python を調べてゆきたいと思います。

丑 
令和3年 元旦
Krtyski (やす)



関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

最新記事
検索フォーム
最新コメント
カテゴリ
C# (3)
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

Author:やす (Krtyski)
since Oct 30, 2013


プログラム電卓は、プログラムを作って、使ってナンボ!

プログラム電卓を実際に使って気づいたこと、自作プログラム、電卓での Casio Basic, C.Basic そして Casio Python プログラミングについて書いています。

なお管理人はカシオ計算機の関係者ではありません。いつでもどこでもプログラミングができるプログラム電卓が好きな1ユーザーです。


写真: 「4駆で泥んこ遊び@オックスフォード郊外」

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

ブロとも申請フォーム

この人とブロともになる

QRコード
QR