%% $OpenXM: OpenXM/doc/OpenXM-specs/implementation.tex,v 1.4 2020/03/14 01:21:56 takayama Exp $
//&jp \section{ 実装, デバッグ, 検証 }

//&jp \subsection{ 実装の手順 }

/*&jp
ソフト xxx を, open XM 対応にするのには以下のような
手順をふむと開発が容易であろう.
\begin{enumerate}
\item[Step 1.]
{\tt executeStringByLocalParser}
および {\tt popString} の機能を実現して,
xxx をライブラリとしてまとめ, 他のソフトとリンクして
使用できるかテストする.
C での実現の場合 割り込みの取扱に注意を要する.
これだけの実現でも, サンプルサーバ
({\tt nullserver00.c}) とリンクすれば,
open XM 対応のクライアントと通信できる.
クライアント側では, このシステムに対応した機能呼び出し
プログラムを書く.
\item[Step 2.]
次に, CMO を可能な限り実装する.
open sm1 や open asir で, CMO 形式のデータを
作成して, 読み込めるかテストする.
\item[Step 2'.]
{\tt kan/sm1} の plugin として組み込むとサーバの開発が楽かもしれない.
{\tt kan/sm1} のソースファイルのディレクトリ {\tt plugin} を見よ.
\item[Step 3.]
CMO の stream への転送, stream よりの転送は,
巨大データの送信受信にきわめて大切である.
これを実装しサンプルサーバとリンクする.
\end{enumerate}


\subsection{歴史}
kan -- asir 間でも以上のように開発がすすんだ.

Risa/Asir の開発が沼津の富士フォーラムでおこなわれていた
ころ, 私が沼津を, 1996年, 1月19日に訪問し,
{\tt Asir\_executeString()}
の機能を野呂さんに書いてもらって, kan より asir を文字列で呼び出す
機能およびその逆を実現したのがことの発端である. 
たとえば, asir より kan/sm1 の機能を呼び出すには,
\begin{verbatim}
F = x; G = y;
Ans = kan("(%p).  (%p).  mul toString",F,G)
\end{verbatim}
と入力すればよい.
{\tt x} と {\tt y} の積が kan で解釈実行されて, 結果を
もどす.
このレベルの結合では kan/sm1 は, 内蔵インタプリタ付の
ライブラリとして利用できてずいぶん便利である.
この関数 {\tt kan} は {\tt builtin/parif.c} に組み込んだ.
{\tt asir} は {\tt pari} の関数を組み込んでいるが, この組み込みの
メカニズムを利用すると容易にリンクできた.
参照: {\tt  noro/src/Old1/parif.c}.

次に, CMO Primitive の機能を
1997, 5 月, 6 月に実現した.
その後, 1997年 7 月に, SMObject/Basic の実装,
1997年 7 月には, 野呂がイタリアの CoCoA のワークショップにおいて,
大阿久の b-function を stratification 込みで計算する計算プログラムを
asir, kan を連係してデモした. このときは, {\tt Sm1\_executeStringByLocalParser}
関数を用いて, ライブラリとしてリンクしてつかった.
1997 年 11 月に TCP/IP による, サーバスタックマシン間の通信の
実装をおこなっている.
通信の実装テストのために, Java および C で null server , null client
を作成した. 以下, これにつき述べる.


\subsection{ サンプルサーバ, クライアント }

Open XM では, 現在のところ,
サンプルサーバとして  {\tt oxserver00.c} を提供している.
このサーバをもとにして, {\tt asir} および {\tt kan/sm1} 
の open XM サーバを試験中である ({\tt ox\_asir}, {\tt ox\_sm1}).
{\tt ox\_sm1} では, {\tt sm1stackmachine.c} が
open XM スタックマシンを実現している.
サンプルクライアントは, ネットワークにデータを送出および
受信する機能のみをもつ,  {\tt testclient.c} を提供
している. 
{\tt asir} および {\tt kan/sm1} には本格的な
クライアント機能(open XM サーバを呼び出す
機能)を組み込んである.
サーバを起動するプログラムは, {\tt kan/sm1} グループでは,
{\tt ox} なる名前で, {\tt asir} グループでは,
{\tt ox\_lauch} なる名前であるが, 機能は同じである.
{\tt ox} のソースは {\tt oxmain.c} である.

\subsubsection{OpenXM/src/ox\_toolkit にあるサンプル実装}
このディレクトリの解説文書を見よ.

\subsubsection{ ox\_null }

Primitive のスタックマシンのソケットによる実装. 
スタックマシンは {\tt nullstackmachine.c} に実装されており,
{\tt oxserver00.c} にリンクしてサーバとなる.
サンプルサーバであり, これに CMO Primitive 仕様の関数を結合すれば,
一応 サーバが動作するはずである.
スタックには,CMO の Primitive の object へのポインタがそのまま push される.
コントロール機能なし. 1997/11/29 版よりコントロール機能追加.
@Old/nullserver00.c.19971122c,
@Old/mytcpip.c.19971122c

現在はこのサーバはメンテナンスされていない
(object 関係の関数を追加しないとコンパイルできない.)

\subsubsection{ testclient }


Java による実装:
@Old/client.java.19971122c
これも現在はふるい.
OX パケットのシリアル番号に対応していない.
ちかいうちに改訂する予定.
{\tt executeString} および {\tt popString} を要請する能力しか持たない.
受信は スレッド {\tt listner} がおこなっている.
受信は byte データを表示するのみである.
スレッドの優先度をうまくバランスとらないと, 受信データがあるのに
表示しなかったりする.

C による {\tt testclient}
同じような機能をもつプログラムの実装もある.
{\footnotesize \begin{verbatim}
./ox -ox ox_sm1 -host localhost -data 1300 -control 1200  (サーバの立ち上げ)
./testclient     (testclient の立ち上げ)
\end{verbatim}}
これも現在はふるい.

田村 ({\tt tamura@math.kobe-u.ac.jp}) による Java への新しい実装がある
(1999, 3月, 神戸大学修士論文).

\subsubsection{ {\tt ox} }
{\tt ox} は ox サーバをたちあげるためのプログラムである.
クライアントよりサーバへ接続するには二つの方法がある.
一つは {\tt ox} で データとコントロール用の二つの
ポート番号を明示的に起動し, クライアントがこのポートへつなぎに
いく方法である.
もう一つは, クライアント側でまず, 空いているポートを二つ
さがし, それから {\tt ox} を {\tt -reverse} で起動して
サーバ側がクライアントにつなぎにくる方法である.
この場合, {\tt ox} はたとえば次のように起動される.
{\footnotesize \begin{verbatim}
/home/nobuki/kxx/ox -reverse -ox /home/nobuki/kxx/ox_sm1 
-data 1172 -control 1169 -pass 1045223078 
\end{verbatim} }

{\tt ox} は, 子どもプロセスとして, {\tt ox\_asir}, {\tt ox\_sm1}
などを起動するのであるが,
これらのプロセスは
3 よりOX データ, コマンドを読み込み, 4 へ OX データを書き出す.
現在の実装では 3 と 4 は dup して同一視してしまっている.
{\tt ox} はTCP/IP のデータ転送のポートを, 3, 4 へわりあてて,
子どもプロセスを起動する.
{\footnotesize \begin{verbatim}
close(fdControl);   /* close(0); dup(fdStream); */
dup2(fdStream,3);
dup2(fdStream,4);  
\end{verbatim}}


\subsubsection{ {\tt ox\_asir} phrase book}

[ この節の記述は古い]
CMObject と asir の object は次の規則にしたがって変換される.
なお asir の object のタグをみるには関数 {\tt type} を用いる.
\begin{enumerate}
\item Null :  0 として使用される.
\item Integer32 : 内部的にのみ使用される. 送出は, ZZ に変換される.
  -1 は (unsigned int) -1 に変換されてから, ZZ に変換されるので,
  正の数となる.
\item Cstring : 文字列 (type = 7) に変換される.
\item ZZ : 数 (type = 1 ) に変換される.
\item QQ : 数 (type = 1 ) に変換される.
\item List : リスト (type = 4) に変換される.
\item Dpolynomial : 分散表現多項式 (type = 9) に変換される.
order はうけとったモノミアルのリストと同じ order である.
\item RecursivePolynomial : 再帰表現多項式に変換される.
内部順序に自動変換される.
\item Indeterminate : 不定元に変換される.
\end{enumerate}
記述のない CMObject に関しては, 利用できない (cf. mathcap ).

\noindent
問題点: 0 の扱いの仕様がまださだまっていない.
Null が数 (type = 1) の 0 に変換される版もある.

\medbreak
\noindent
例: 
分散表現多項式の $x^2-1$ の因数分解を asir にやってもらう 
OXexpression の列をあげる.
{\footnotesize
\begin{verbatim}
(OX_DATA, (CMO_LIST, 4, CMO_DMS,CMO_DMS_GENERIC,
(CMO_MONOMIAL32,1,2,(CMO_ZZ,1)),
(CMO_MONOMIAL32,1,0,(CMO_ZZ,-1)))),
(OX_DATA, (CMO_INT32,1))
(OX_DATA, (CMO_STRING,"ox_dtop"))
(OX_COMMAND,(SM_executeString))

(OX_DATA, (CMO_INT32,1))
(OX_DATA, (CMO_STRING,"fctr"))
(OX_COMMAND,(SM_executeString))


(OX_DATA, (CMO_INT32,1))
(OX_DATA, (CMO_STRING,"ox_ptod"))
(OX_COMMAND,(SM_executeString))

(OX_COMMAND,(SM_popCMO))
\end{verbatim}}

ここで, ZZ の元を普通の整数表記であらわした.
{\tt dtop1} および {\tt ptod1} はそれぞれ, 分散表現多項式を, Asir の再帰表現
多項式に, 逆に, Asir の再帰表現多項式を, 分散表現多項式に変換する,
ユーザ定義の 1 引数関数である. %% kxx/oxasir.sm1
これらの関数は Asir の リストにも作用させることが可能であり, その場合は
要素としてでてくる,  分散表現多項式 または Asir の再帰表現多項式
を必要な形に変換する.
{\tt fctr} は因数分解をする組み込み関数である.

{\tt kxx/oxasir.asir} のソース.
{\footnotesize \begin{verbatim}
OxVlist = [x,y,z]$

def ox_ptod(F) {
extern OxVlist;
if (type(F) == 4) return(map(ox_ptod,F));
else if (type(F) == 2) return(dp_ptod(F,OxVlist));
else return(F);
}

def ox_dtop(F) {
extern OxVlist;
if (type(F) == 4) return(map(ox_dtop,F));
else if (type(F) == 9) return(dp_dtop(F,OxVlist));
else return(F);
}

end$
\end{verbatim}}

\subsubsection{ {\tt ox\_sm1} phrase book }

[ この節の記述は古い]
CMObject と kan/sm1 の object は次の規則にしたがい変換される.
なお, kan/sm1 の object のタグをみるには, {\tt tag} または {\tt etag}
を用いる.
\begin{enumerate}
%% \item Error : Error (etag = 257) に変換される.
\item Error2 : Error (etag = 257) に変換される.
\item Null : null (tag = 0) に変換される.
\item Integer32 : integer (tag = 1) に変換される.
\item Cstring : 文字列 (type = 5) に変換される.
\item ZZ : universalNumber (type = 15 ) に変換される.
\item QQ : rational (tag = 16 ) に変換される.
\item List : array (tag = 6) に変換される.
\item Dpolynomial : 多項式 (tag = 9) に変換される.
\end{enumerate}


\noroa{ {\tt SS475/memo1.txt} も見よ.}

注意: {\tt ReverseOutputOrder = 1} (標準)
のとき, {\tt xn, ..., x0, dn, ..., d0} の順番で
({\tt show\_ring} の形式) Dpolynomial に変換される
(印刷形式だと,
{\tt xn} は {\tt e}, {\tt d0} は {\tt h},
{\tt x0} は {\tt E}, {\tt dn} は {\tt H}).
たとえば,
{\tt ox\_send\_cmo(id,<<1,0,0,0,0,0>>)}  は,
{\tt x2} に変換される.
{\tt ox\_send\_cmo(id,<<0,0,1,0,0,0>>)}  は,
{\tt x0} に変換される.

{\tt OxVersion} 変数で openXM のプロトコルの version を表す.

\subsubsection{ {\tt ox\_sm1} を用いたクライアントのテスト方法 }
まだかいてない.

\subsubsection{ {\tt Asir} を用いたサーバのテスト方法 }

\subsection{ 最小の TCP/IP クライアントの例 }

Java または M2 によるソースコードを掲載の予定.

\subsection{ クライアント asir, sm1 }

sm1 については, ox.sm1 , oxasir.sm1 がクライアントパッケージ.
{\tt ox}, {\tt ox\_asir}, {\tt ox\_sm1} の存在するパス,
および sm1 より呼び出すための asir の関数定義である
{\tt oxasir.asir} のあるパスを
これらのパッケージに書き込んでおく必要がある.

{\tt ox\_asir} は, {\tt asir} なる名前でよばれると
asir として動作し, {\tt ox\_asir} なる名前でよばれると,
open XM サーバとして動作する.
{\tt /usr/local/lib/asir} または
{\tt ASIR\_LIBDIR} へ {\tt ox\_asir} 実体をおき,
{\tt ox\_launch} をおなじディレクトリへ {\tt ox\_asir} へのシンボリックリンク
として作成する.
コマンドサーチパスにあるディレクトリへ {\tt asir} を {\tt ox\_asir}
へのシンボリックリンクとして作成する.
{\footnotesize
\begin{verbatim}

This is Asir, Version 990413.
Copyright (C) FUJITSU LABORATORIES LIMITED.
3 March 1994. All rights reserved.
0
[324] ox_launch(0,"/usr/local/lib/asir/ox_asir");
1      <=== これがサーバの番号.
[326] ox_execute_string(1,"fctr(x^10-1);");
0
[327] ox_pop_local(1);
[[1,1],[x-1,1],[x+1,1],[x^4+x^3+x^2+x+1,1],[x^4-x^3+x^2-x+1,1]]
[328] ox_execute_string(1,"dp_ptod((x+y)^5,[x,y]);");
0
[329] ox_pop_cmo(1);
(1)*<<5,0>>+(5)*<<4,1>>+(10)*<<3,2>>+(10)*<<2,3>>+(5)*<<1,4>>+(1)*<<0,5>>
[330] ox_rpc(1,"fctr",x^10-y^10);
0
[331] ox_pop_local(1);
[[1,1],[x^4-y*x^3+y^2*x^2-y^3*x+y^4,1],[x^4+y*x^3+y^2*x^2+y^3*x+y^4,1],[x+y,1],[x-y,1]]
[332] ox_rpc(1,"fctr",x^1000-y^1000);   ox_cmo_rpc もあり.
0
[333] ox_flush(1);
1
[334] ox_pop_local(1);
0

ox_sync(1);   --- sync ball を送る.

\end{verbatim}}

\subsection{開発中のサーバ, クランアント}

Mathematica サーバ, クライアント : 小原.
Java クライアント, Open Math proxy : 田村.
Gnuplot サーバ, Macaulay 2 クライアント, サーバ,
その他小さいソフト (Toric GB, Grobner fan)のサーバ,
Algebraic equation solver by numerical method: 高山.
Open Asir マニュアル, サンプル: 小原, 高山.

数学的におもしろい問題を実際にあつかってみないと
わからない問題点もおおくあると思う.
現在, ${\cal A}$-超幾何関数の解のグラフ表示,
パラメータ付積分のグラフ表示のソフトをかくことで
さらに問題点をさぐることを
計画している.
グレブナdeformation による多項式解, 有理解の導出(線形および非線形方程式,
非線形微分方程式から出発すると代数方程式を解く問題になる)
は OpenXM 的なプログラムのおもしろい練習問題.
Java の並列計算記述能力をつかって ox サーバを使うのもおもしろい.

世界中の人につかってもらえる規格にするには
まだまだ実験と経験をかさねないといけない.
Free Mathematical Software Initiative を作るべきだろう.

\subsection{ Change log }
\begin{enumerate}
\item 1997/11/20 : この document の最初の version が生まれた.
  kxx/openxxx.tex なる名前であった.
\item 1999/07 : {\tt CMO\_ZZ} の形式を変えた.
\item 1999/09/7, 9/8 : 分散表現多項式, Mathcap, RecursivePolynomial,
の形式を変えた. asir, sm1 に実装した. エラー処理のために,
dupErrors, getsp を SM コマンドに加えた.
\end{enumerate}

\subsection{ }
Java で sm1 サーバをすべて書いてみるか?
*/
