HP 35s でプログラミング - 2
ここ数年、本腰を入れて取り組んでいるリアルタイムスケジューリングの研究分野では、与えられたタスクセットがスケジュール可能か判断するための様々な手法が提案されている。シングルコアでの手法は確立されており、RTA = Response Time Analysis というのがそれである。RTA はマルチコアの場合にも応用が出来、私はマルチと並行してシングルの研究も進めているので RTA が手元の電卓で計算出来るとうれしい。HP 35s がどれほどのパフォーマンスを示してくれるか謎だが、とりあえず実装してみることにした。
が、それに先立ち必要なのは ceil() 関数である。HP 35s には整数部と小数部を取り出す命令があるので、それらを使い愚直に実装してみた:
A001 : LBL A A002 : ENTER A003 : FP A004 : x=0? A005 : GTO A011 A006 : X<>Y A007 : IP A008 : 1 A009 : + A010 : RTN A011 : X<>Y A012 : RTN
この処理は外部プログラムより呼ばれるサブルーチンとして動作する前提であるのと、今後も色々と関数を作るであろうからコンベンションを決めることにした。func( a, b, c ) がある場合、c から逆順にスタックに積んで EXQ (実行、またはサブルーチンの呼び出し) する、というものである。スタックに積む順は古典的なコンパイラの例に倣った。
( 余談ではあるが、C 言語では引数の評価順は仕様として定められていない。関数にジャンプした後、スタックから引数を取り出すことを考えると、引数を逆順にスタックに積むほうが効率が良い。しかしこれでは左から右に読む自然記法と評価順が逆になる。このギャップをスルーするための仕様と思われる。引数をレジスタで渡す場合はこの限りではない)
やってることは簡単で、2行目の ENTER で X レジスタに収められている引数を Y レジスタにもコピーする(後続命令が X レジスタを破壊するためである。3行目 FP で小数部を取り出し、X レジスタに積む。4行目で X レジスタが 0 か判断する。すなわち小数部が 0 なら、11行目へジャンプし、コピーしておいた Y レジスタを X レジスタと交換し、戻る。
小数部、すなわち X レジスタが 0 でない場合、X=0? 命令は後続命令を1行スキップする。6 行目で X レジスタと、引数をコピーしておいた Y レジスタと交換する。 7 行目の IP で整数部を取り出し、1 を足して戻る。
この ceil() 関数は完全ではなく、負の入力に対しては正しく動かないので符号のチェックが必要であるが、実は、HP 35s には「与えられた数値以下の最大整数を取得する」、floor() に相当する命令がある。INTG がそれで、これを ceil() に適用するには符号を置き換えてやれば良い。
B001 : LBL B B002 : +/- B003 : INTG B004 : +/- B005 : RTN
2, 4 行目の +/- は X レジスタの数値の符号を入れ替える命令である。これで ceil() が実装出来た。