%% $OpenXM: OpenXM/src/kxx/openxxx.tex,v 1.7 2000/01/17 22:09:47 takayama Exp $
/*&jp
%\documentclass{jarticle}
\documentstyle{jarticle}
\title{{\bf Open XM の設計と実装} \\
--- Open message eXchange protocol for Mathematics }
\author{ 野呂正行\thanks{富士通研究所
} ,
高山信毅\thanks{神戸大学理学部数学教室}
}
\date{ 2000年, 1月18日}
*/
/*&eg
%\documentclass{article}
\documentstyle{article}
\title{{\bf Design and Implementation of OpenXM} \\
--- Open message eXchange protocol for Mathematics \\
(English Abstract of Japanese Original Document)}
\author{ Masayuki Noro\thanks{Fujitsu Laboratory
} ,
Nobuki Takayama\thanks{Department of Mathematics, Kobe University}
}
\date{ January 18, 2000 }
*/
/*&C
\begin{document}
\maketitle
\def\noroa#1{ }
\def\remove#1{ }
*/
/*&jp
{\tt kxx/openxxx.tex}. {\bf Draft} 1997, 11/20 --- .
この文書は open XM の設計用のメモとしての役目もあるので,
一部のファイル名は開発者のみが参照できる.
*/
//&jp \section{はじめに}
//&eg \section{Introduction} (This part has not been translated)
/*&jp
Open XM は, おなじタイプまたは異なるタイプの数学プロセス間の
メッセージのやりとりの規約である.
開発の動機は, 手作り(または研究的な)数学ソフトの相互乗り入れの実現
および分散計算の実装が
第一であったが, もちろん数学ソフト間だけでなく, ワープロソフトや,
インタラクティブな数学本,
さらには数学デジタル博物館用のソフトがこの規約に従い,
数学ソフトを呼び出すことなどにも利用できる.
当面の目標は openXM 数学ソフトパッケージを作ることである.
これはさまざまな数学ソフトを一つのパッケージとして
簡単に好きな言語より使えるようにするプロジェクトである.
現在 openXM.tar.gz には,
asir, sm1, phc, gnuplot, tigers が入っている.
OpenXM 数学ソフトパッケージプロジェクトに
参加できるように CMO の
規約を拡張していくための規約も定めるものとする.
現在専門的な数学ソフトが多数開発
されているが, 次世代の数学ソフトは他のソフトよりサブルーチンとして
呼び出せる機能をもつべきである.
このように協調機能にすぐれたプログラムを書くための設計の
ガイドライン, プログラム作法のようなものを提案するのも,
このプロジェクトの目的である.
このようなガイドラインにそってプログラムすることにより,
数学アルゴリズム自体に集中できる環境が実現できることを
期待している.
設計の方針として, (1) 単純 (2) 拡張性 (3) 実装の簡便さ (4) 実用性
(5) 高信頼性(robustness),
に重きをおいている.
Open XM はなにも考えずに簡単に接続できるシステムを作ろう,
というまで野心的ではない.
数学的な object は一筋縄ではいかないし, 完全な統一規格をつくるというのは
気が遠くなる仕事である.
そのかわり, 今よりすこしだけこういったデータ交換や分散システム構築の仕事を楽に
したいというのがささやかな第1目標である.
数学的な Object をどのように表現するのか, どう伝えるのかを考えることは
決してつまらない問題ではない.
このような問題は, 新しい数学記号を創造する問題と似ているかもしれない.
我々は, 数字を $0$ を含んだ10進数で表記し,
微分を $dx$ と書き, 写像を $ \longrightarrow $ であらわす.
これらの記号法からどれだけ多くの利益を得ているか, 思いをはせて欲しい.
また, Mathematica や Maple といった巨大な統合ソフトを,
Free Mathematical Softwares としてわれわれ自身の
手でつくっていくための基礎でもある.
%% 変数名をどうするか悩むのにも似てる.
Open XM に準拠したシステム xxx を, open xxx とよぶ.
たとえば, open XM 対応の asir は open asir であり,
open XM 対応の kan/sm1 は open sm1 である.
Open XM は, データ型をきめている部分と,
共通スタック言語を定めている部分にわかれる.
よいたとえかどうか自信がないが,
Open XM を定義する作業は, unicode を定める作業に似ている部分もある.
たとえば, 漢字は東アジアで共通に使用されているが, 国や地方単位で
形がすこしづつ違うものがある.
unicode では, 似た漢字を同じ code におしこんだ.
Open XM でも, システム毎にことなるが似ているデータ型を
同じ型としてあつかう.
たとえば, ``分散多項式'' の意味は, asir と kan/sm1 で異なるが,
Open XM では, 同じ型としてあつかわれる.
ただしこれでは不十分な場合があるので,システム固有のデータ型も扱える
ような仕組みも用意している.
(さっきのたとえでは, こちらは, unicode でなく, ISO の文字符号系に対応するか.)
共通スタック言語は, ごく小数の共通コマンドをのぞき
基本的にシステム毎に固有の関数により実行される.
これにより, open xxx のサーバの実装およびマニュアルの記述は
いちじるしく簡単になる.
システム毎に固有の関数を共通の関数名にするプロジェクトも
考えているが, 共通の関数名は OpenMath のものを利用する予定である.
Open XM は論理的には
OX 層, SM 層, CMO 層にわかれる.
OX Object は, データ, コマンドに大別できる.
データはこのプロジェクトのオリジナルのデータ形式
である CMO (Common Mathematical Object Format) で
送出してもよいし, MP や Open MATH などの形式を用いてもよい.
SM 層は (スタックマシン)サーバを制御するための命令の
あつまりであり, サーバは非同期的に動作させることが可能である.
柔軟性が高いので, IMC などのリモートプロシージャコール系の
プロトコルもエミュレートできる.
*/
//&jp \section{CMO Basic0 の object}
//&eg \section{CMO Basic0 object}
/*&jp
CMO (Common Mathematical Object format) グループ Basic0 の Object は,
ローレベルのデータ型, {\tt int} , {\tt string}
などに対応する object である.
この CMO はすべての OpenXM が実装していると仮定される.
この節では, イントロダクションとして, グループ Basic0 に属する CMObject
(Common Mathematical Object) を形式的な方法をつかわず導入しよう.
*/
/*&eg
Objects in CMO (Common Mathematical Object format) group Basic0
are primitive data such as {\tt int}, {\tt string}.
All OpenXM compliant systems should implement all data types
in the group Basic0.
In this section, as an introduction, we will introduce
CMObject (Common Mathematical Object) of the group Basic0 without
using the Backus-Nauer form.
*/
/*&jp
このグループの正式な名前は,
CMObject/Basic0 である.
以下, {\tt int32} で2の補数表現された
32 bit integer をあらわす
(これはよく使われる計算機での C 言語の int の内部表現).
{\tt byte} で 8 bit データをあらわす.
*/
/*&eg
The canonical name of this group is
CMObject/Basic0.
In the sequel,
{\tt int32} means the signed 32 bit integer expressed by two's complement
(internal expressions of {\tt int} of the language C usually use
this expression).
{\tt byte} means 8 bit data.
*/
//&C
/*&jp
CMObject の TCP/IP 用の実装では,
CMO の object は \\
\begin{tabular}{|c|c|}
\hline
{\tt cmo\_tag}& {\tt cmo\_body} \\
\hline
\end{tabular} \\
なる形をしている.
ここで, {\tt cmo\_tag} は, 正の
{\tt int32} で表現するものと規約する.
*/
/*&eg
In our encoding of the CMO's for TCP/IP,
any CMObject consists of a tag and a body: \\
\begin{tabular}{|c|c|}
\hline
{\tt cmo\_tag}& {\tt cmo\_body} \\
\hline
\end{tabular} \\
{\tt cmo\_tag} should be given by a positive
{\tt int32}.
*/
/*&C
*/
/*&jp
{\tt cmo\_tag} は object のタイプをあらわすタグであり,
以下のように決めている.
*/
//&eg The following is a list of tags of CMObject/Basic0.
/*&C
@../SSkan/plugin/cmotag.h
\begin{verbatim}
#define LARGEID 0x7f000000
#define CMO_ERROR2 (LARGEID+2)
#define CMO_NULL 1
#define CMO_INT32 2
#define CMO_DATUM 3
#define CMO_STRING 4
#define CMO_MATHCAP 5
#define CMO_LIST 17
\end{verbatim}
*/
/*&jp
以下, 各 object の フォーマットを説明する.
サーバ, クライアントはすべての object の CMO 形式をサポートする必要はないが,
{\tt CMO\_ERROR2}, {\tt CMO\_NULL},
{\tt CMO\_INT32}, {\tt CMO\_STRING}, {\tt CMO\_MATHCAP}, {\tt CMO\_LIST}
は最も基本的なデータであり,
また全てのサーバ, クライアントが実装すべき CMO データである.
*/
/*&eg
We will explain each object format.
Servers and clients do not need to implement all CMO's.
However,
{\tt CMO\_ERROR2}, {\tt CMO\_NULL},
{\tt CMO\_INT32}, {\tt CMO\_STRING}, {\tt CMO\_MATHCAP}, {\tt CMO\_LIST}
are primitive data and
all servers and clients have to implement them.
*/
/*&C
\medbreak \noindent
*/
//&jp CMObject Error2 は \\
//&eg CMObject Error2 is of the form \\
/*&C
\begin{tabular}{|c|c|}
\hline
{\tt int32 CMO\_ERROR2} & {\sl CMObject} {\rm ob} \\
\hline
\end{tabular} \\
*/
/*&jp
なる形で表現する.
エラーの時に push する object であり, {\it CMObject} ob の
部分に詳細なエラー情報がはいる.
ob はリストであり, TCP/IP によるストリーム型接続の場合,
最初の成分はエラーを起こした OX メッセージ(後述)
のシリアル番号でないといけない.
シリアル番号は Integer32 で表現する.
*/
/*&eg
It is an object used when a server makes an error.
{\it CMObject} ob carries error informations.
The instance ob is a list and in case of a stream connection like TCP/IP
the first element must be the serial number of the OX message
that caused the error.
The serial number is given by the data type Integer32.
*/
/*&C
\medbreak \noindent
*/
//&jp CMObject Null は \\
//&eg CMObject Null has the format \\
/*&C
\begin{tabular}{|c|c|}
\hline
{\tt int32 CMO\_NULL} \\
\hline
\end{tabular} \\
*/
/*&jp
なる形で表現する.
*/
/*&C
\noindent
*/
//&jp 32 bit integer n は CMObject としては Integer32 と呼ばれ, \\
//&eg 32 bit integer n is called Integer32 as a CMObject and has the format \\
/*&C
\begin{tabular}{|c|c|}
\hline
{\tt int32 CMO\_INT32}& {\tt int32} {\rm n} \\
\hline
\end{tabular} \\
*/
//&jp なる形で表現する.
/*&C
\medbreak \noindent
*/
//&jp 長さ n の バイト列 data は CMObject としては, Datum 型とよばれ \\
//&eg A byte array of the length n is called Datum as a CMObject and has the format \\
/*&C
\begin{tabular}{|c|c|c|c|}
\hline
{\tt int32 CMO\_DATUM}& {\tt int32} {\rm n} & {\tt byte} {\rm data[0]}
& {\tt byte} {\rm data[1]} \\
\hline
$\cdots$ & {\tt byte} {\rm data[n-1]} \\
\cline{1-2}
\end{tabular} \\
*/
//&jp と表現する.
/*&C
\noindent
*/
//&jp 長さ n の 文字列 data は, CMObject としては, Cstring 型とよばれ \\
//&eg String of n bytes is called Cstring as CMObject and has the format \\
/*&C
\begin{tabular}{|c|c|c|c|}
\hline
{\tt int32 CMO\_STRING}& {\tt int32} {\rm n} & {\tt byte} {\rm data[0]}
& {\tt byte} {\rm data[1]} \\
\hline
$\cdots$ & {\tt byte} {\rm data[n-1]} \\
\cline{1-2}
\end{tabular} \\
*/
/*&jp
と表現する. C 言語で普通用いられる, 文字列のおわりの {\tt 0} は文字列
に含めない.
*/
/*&C
\noindent
*/
//&jp CMObject Mathcap は \\
//&eg CMObject Mathcap has the format \\
/*&C
\begin{tabular}{|c|c|}
\hline
{\tt int32 CMO\_MATHCAP} & {\it CMObject} {\rm ob} \\
\hline
\end{tabular} \\
*/
/*&jp
なる形で表現する.
{\tt ob} はリストであり少なくとも3つの要素をもつ.
0 番目の要素は, Integer32 で表した OpenXM protocol version number と,
Cstring で表したシステム名, Server version, CPU type, その他の情報
のリストである.
1 番目の要素は, システム xxx が扱うことの可能な
SM タグを, Integer32 で表現したものを集めたリストである.
3 番目の要素は, システム xxx があつかうことの可能な
データ形式をあつめたリストである.
詳細は mathcap の節で説明する.
*/
/*&eg
ob is a list of which length is more than or equal to three.
The first element is a list of
OpenXM protocol version number in Integer32,
the server name in Cstring,
the server version and CPU type in Cstring,
and extra informations.
The second element is a list of SM tags in Integer 32.
The third element is a list of data type tags which the server or the client
can understand.
The details will be explained in the section on mathcap.
*/
/*&C
\medbreak \noindent
*/
//&jp 長さ m のリストは \\
//&eg A list of the length m has the form \\
/*&C
\begin{tabular}{|c|c|c|c|c|}
\hline
{\tt int32 CMO\_LIST}& {\tt int32} {\rm m} & {\tt CMObject}\, ob[0] & $\cdots$ &
{\tt CMObject}\, ob[$m-1$] \\
\hline
\end{tabular}\\
*/
//&jp で表現する.
//&jp \section{ CMO の形式的表現方法 }
//&eg \section{ A formal expression of CMO }
/*&jp
前の節で CMO の表現方法を形式的に定義せず,
CMO のBasic0 の表現法を説明したが,
ここでは, CMO の Lisp 風表現 (Lisp-like expression)
である
CMOexpression
および前節で説明した CMO の標準 encoding 法をもう一度説明する.
% (タグの省略記法がほしい.)
*/
/*&eg
In the previous setion, we have explained the format of CMO's in the
Basic0 group.
In this section, we will introduce CMOexpression which is like the
bracket expression of Lisp.
We again explain a standard encoding method of CMO,
which we have already explained in the previous section.
*/
/*&jp
まず, CMOexpression を形式的に 拡張 BNF 記法を用いて定義しよう.
タイプライタフォントでかかれた記号は終端記号を意味する.
``:'' は定義を意味する. ``$|$'' は''または''を意味する.
\{ X \} は X の 0 回以上の繰り返しを表す.
[ x ] は X が 0 回または 1 回出現することを表す.
この記法を用いると CMOexpression は次のように定義できる.
*/
/*&eg
Let us define CMOexpression by the extended BNF expression.
Symbols in the type writer fonts mean terminals.
``:'' means a definition.
``$|$'' means ''or''.
\{ X \} is a repetition of X of more than or equal to 0 times.
[ x ] stands for X or nothing.
By using this notation, CMOexpression is defined as follows.
*/
/*&C
\begin{eqnarray*}
\mbox{CMOexpression}
&:& \quad
\mbox{\tt (} \mbox{\tt cmo\_tag} \
\{ \mbox{ expression} \} \mbox{\tt )}\\
\mbox{expression}
&:& \quad \mbox{CMOexpression} \\
& &|\ \mbox{\tt int32} \\
& &|\ \mbox{\tt string} \\
& &|\ \mbox{\tt byte} \\
\end{eqnarray*}
*/
/*&jp
終端記号 {\tt int32} は, 32 bit integer を表す, 10 進または 16 進の数字の
列である.
終端記号 {\tt string} は''文字''の列である.
終端記号 {\tt byte} は 8 bit データを表す, 10 進または 16 進の数字の列である.
*/
/*&jp
Terminal {\tt int32} is signed 32 bit integer.
Terminal {\tt string} is a byte array which usually expresses a string.
Terminal {\tt byte} is 8 bit data.
*/
/*&jp
CMOexpression にあらわれる各要素を区切るために {\tt ,} (コンマ) を用いてもよい.
{\tt cmo\_tag} は {\tt CMO\_} で始まる定数である.
CMOexpression で表現される object を CMObject と呼ぶ.
*/
/*&eg
The comma ({\tt ,}) may be used to separate each element in CMOexpressions.
{\tt cmo\_tag} is a constant that starts with {\tt CMO\_}.
*/
/*&jp
この表記法 CMOexpression を利用して, CMO Basic0 の object を記述
してみよう.
Object 自体の構造を説明するため,
BNF をもうすこし拡張して, 非終端記号, 終端記号名のみならず, 変数の
名前も書くことにする. こうすることにより, object の意味の説明も容易になる
からである. また ``---'' でコメントのはじまりを表すものとする.
*/
/*&eg
Let us describe CMO's in the Basic0 group.
In order to explain the meaning of objects,
we may also put variable names to CMOexpressions.
The start of comments are denoted by ``---''.
*/
/*&jp
たとえば, (CMObject の) 32 bit integer である integer32 を
BNFで定義すれば,
\begin{center}
Integer32 \ : \ ({\tt CMO\_INT32}, {\tt int32})
\end{center}
と書くのが本来の書き方による記法であるが, ここでは,
\begin{eqnarray*}
\mbox{Integer32} \ &:& \ ({\tt CMO\_INT32}, {\sl int32}\ n) \\
& & \ \mbox{--- 32 bit integer $n$ を表す. } \\
\end{eqnarray*}
と書くことを許すことにする.
このように書くことにより, 非終端記号 Integer32 は,
\begin{center}
Integer32 \ : \ ({\tt CMO\_INT32}, {\tt int32})
\end{center}
のように, 終端記号 {\tt CMO\_INT32} と {\tt int32} を成分にもち,
CMObject の
({\tt CMO\_INT32}, {\sl int32}\ n)
は,
32 bit integer $n$ を表現しているんだということが, 1 行でわかる.
*/
/*&eg
(This part has not yet been translated.)
*/
/*&jp
この記法を用いて, 前節で導入した, Basic0 の CMObject を
形式的に定義しよう.
*/
/*&eg
By using this notation, let us define formally CMObjects in the group
Basic0.
*/
/*&C
\bigbreak
\noindent
Group CMObject/Basic0 requires nothing. \\
Error2, Null, Integer32, Datum, Cstring, Mathcap, List $\in$ CMObject/Basic0. \\
Document of CMObject/Basic0 is at {\tt http://www.math.kobe-u.ac.jp/OpenXM}
(in English and Japanese) \\
\begin{eqnarray*}
\mbox{Error2}&:& ({\tt CMO\_ERROR2}, {\sl CMObject}\, \mbox{ob}) \\
\mbox{Null} &:& ({\tt CMO\_NULL}) \\
\mbox{Integer32}
&:& ({\tt CMO\_INT32}, {\sl int32}\ \mbox{n}) \\
\mbox{Datum} &:& ({\tt CMO\_DATUM}, {\sl int32}\, \mbox{n}, {\sl byte}\,
\mbox{data[0]},
\ldots , {\sl byte}\, \mbox{data[n-1]}) \\
\mbox{Cstring}&:& ({\tt CMO\_STRING},{\sl int32}\, \mbox{ n},
{\sl string}\, \mbox{s}) \\
\mbox{Mathcap}&:& ({\tt CMO\_MATHCAP},{\sl CMObject}\, \mbox{ob} ) \\
\mbox{List} &:&
\mbox{({\tt CMO\_LIST}, {\sl int32}\, m, {\sl CMObject}\, ob[0], $\ldots$,
{\sl CMObject}\, ob[m-1])} \\
& & \mbox{--- m is the length of the list.}
\end{eqnarray*}
*/
//&jp Cstring で, {\sl string} s の部分を {\tt byte} に分解すれば,
//&eg In the definition of ``Cstring'', if we decompose ``{\sl string} s'' into bytes, then ``Cstring'' should be defined as
/*&C
\begin{eqnarray*}
\mbox{Cstring}&:& ({\tt CMO\_STRING},{\sl int32}\, \mbox{ n},
{\sl byte}\, \mbox{s[0]},
\ldots, {\sl byte}\ \mbox{s[n-1]})
\end{eqnarray*}
*/
//&jp となる.
/*&jp
また,
``Group CMObject/Basic0 requires nothing''
は, 以下は, グループ CMObject/Basic0 の定義であり,
このグループの CMObject を定義するのに, 要請される CMObject のグループは
ないことを示す.
``Error2, Null, Integer32, Datum, Cstring, Mathcap, List
$\in$ CMObject/Basic0''
は, グループ CMObject/Basic0 には, Error2, Null, Integer32,
Datum, Cstring なるクラスの object が属することを示す.
*/
/*&eg
また,
``Group CMObject/Basic0 requires nothing''
means that there is no super group to define CMO's in the group Basic0.
``Error2, Null, Integer32, Datum, Cstring, Mathcap, List
$\in$ CMObject/Basic0''
means that
Error2, Null, Integer32, Datum, Cstring
are members of the group CMObject/Basic0.
*/
/*&C
*/
/*&jp
では, 実際のデータの表現の例をみてみよう.
たとえば, 32 bit integer の 1234 は,
*/
/*&eg
Let us see examples.
32 bit integer 1234 is expressed as
*/
/*&C
\begin{center}
({\tt CMO\_INT32}, 1234)
\end{center}
*/
/*&jp
とかく.
文字列 ``Hello'' は
*/
/*&eg
The string ``Hello'' is expressed as
*/
/*&C
\begin{center}
({\tt CMO\_STRING}, 5, "Hello")
\end{center}
*/
//&jp と書く.
/*&C
*/
/*&jp
CMOexpression と, CMObject の区別を理解しておくのは重要である.
たとえば
\begin{center}
({\tt CMO\_INT32}, 234, "abc",({\tt CMO\_STRING}))
\end{center}
は CMOexpression ではあるが, CMObject ではない.
これは, 文法的には正しいプログラムだが, なにをやるのかは全く不明な
プログラムと似ている.
さて, Open math 風 (\cite{openmath})
の SGML 表現法も可能であり, その場合は, 上の二つの例は次のように
書く.
\begin{verbatim}
1234
5
"Hello"
\end{verbatim}
*/
/*&C
*/
/*&jp
次に, 標準 encoding 法を説明しよう.
標準 encoding 法では, cmo\_tag を ネットワークバイトオーダーの
32 bit integer {\tt int32} に,
その他のフィールドは, 定義に記述されているデータ型に従い,
byte データ {\tt byte} かまたは
ネットワークバイトオーダーの 32 bit integer {\tt int32} に, 変換する.
*/
/*&eg
Let us explain the standard encoding method.
All {\tt int32} data are encoded into network byte order 32 bit integers
and byte data are encoded as it is.
*/
/*&C
*/
/*&jp
高速の通信方法を用いて
効率を重視する接続の場合には, {\tt int32} を network byte order
に変換する操作がおおきなオーバヘッドとなることが
報告されている.
100Mbps の通信路で 12Mbytes の {\tt CMO\_ZZ} の転送では
約 90\% の時間が network byte order への変換についやされているという
実験データもある.
効率を重視した encoding 法については後述する.
*/
/*&eg
When we are using a high speed network,
the translation from the internal expression of 32 bit integers to
network byte order may become a bottle neck.
There are experimental data which presents that 90 percents of the transmission
time are
for the translation to the network byte order to send {\tt CMO\_ZZ} of size
12M bytes on a 100Mbps network.
In a later section, we will discuss a protocol to avoid the translation.
*/
/*&C
*/
/*&jp
標準 encoding と CMOexpression の間の変換は容易である.
前節で用いたデータの表記法,
たとえば,
*/
/*&eg
The translation between the standard encoding and CMOexpression
is easy.
For example,
*/
/*&C
\begin{center}
\begin{tabular}{|c|c|}
\hline
{\tt int32 CMO\_INT32}& {\tt int32 1234} \\
\hline
\end{tabular}
\end{center}
*/
/*&jp
は, CMOexpression
*/
/*&eg
is the encoding of the CMOexpression
*/
/*&C
\begin{center}
({\tt CMO\_INT32}, 1234)
\end{center}
*/
/*&jp
の 標準 encoding 法による表現である.
*/
//&jp \section{ Open XM の通信モデル}
//&eg \section{ Communication model of Open XM} (This part has not yet been translated)
/*&jp
われわれは, 数学プロセスがメッセージを
交換しながら計算が進行していくというモデルを想定して設計をすすめている.
各プロセスはスタックマシンであり, これを OX スタックマシンとよぶ.
数学プロセスの間の通信路の確保の仕方としては以下のように
いろいろな実現方法を想定している.
\begin{enumerate}
\item ファイルを介して通信する.
\item Library として直接リンクして通信する.
\item TCP/IP ソケットの利用.
\item Remote Procedure call の利用.
\item マルチスレッドの利用.
\item PVM ライブラリの利用.
\item MPI ライブラリの利用.
\end{enumerate}
通信とはプロセス間のメッセージのやりとりである.
メッセージは論理的に次のような構造をもつ:
\begin{center}
\begin{tabular}{|c|c|c|}
\cline{1-2}
{\tt destination} & {\tt origin} & \multicolumn{1}{}{} \\ \hline
{\tt extension}&{\tt ox message\_tag}&{\tt message\_body} \\
\hline
\end{tabular}
\end{center}
このメッセージを, OXobject (Open XM message object) とよぶ.
OXobject はトップレベルのメッセージ object であり,
仕様書では, さまざまなグループに属する object が登場する.
グループ名は, たとえば, OXobject/TCPIP/Basic0 などと書く.
{\tt message\_body} の部分の仕様は, OXobject
の上位に位置する部分であり, SMobject または CMObject がくる.
これらの object はタグをもち, そのタグ定数は {\tt SM\_} または
{\tt CMO\_} ではじまる.
SMobject は, スタックマシンコマンドメッセージ object であり,
やはり, グループ分けされている.
各グループ名は,
SMobject/Basic0, SMobject/Basic1 などと書く.
SMobject の構造は
サーバスタックマシンの節で詳しく説明する.
CMObject についてはすでに Basic0 の CMObject の説明をしたが,
あとで CMObject レベル 1の説明をする.
OXobject の
{\tt ox message\_tag} の定数は {\tt OX\_} で始まる.
\subsection{ OXobject の 表現方法 }
Open XM で各プロセスは
\begin{center}
(OXexpression を理解するスタックマシン) $+$ (xxx 言語で動くエンジン)
\end{center}
なるハイブリッド構成である.
このプロセスを, OX スタックマシンと呼ぶ.
ここでは, OX スタックマシンとやりとりするメッセージである,
OXobject を表現するための OXexpression, および,
スタックマシンの operator に対応する, SMobject を表現するための SMexpression
を定義しよう.
OXobject を スタックマシンコマンド,
SMobject を スタックマシンオペレータともよぶ.
\begin{eqnarray*}
\mbox{OXexpression}
&:& \quad
\mbox{\tt (} \mbox{\tt OX\_tag} \
[\mbox{ expression}] \mbox{\tt )}\\
\mbox{expression}
&:& \quad \mbox{SMexpression} \\
& &|\ \mbox{CMOexpression} \\
\mbox{SMexpression}
&:& \mbox{\tt (} \mbox{\tt SM\_tag} \
\{ \mbox{CMOexpression} \} \mbox{\tt )}\\
\end{eqnarray*}
expression の各要素を区切るために {\tt ,} (コンマ) を用いてもよい.
{\tt OX\_tag} は {\tt OX\_} で始まる定数である.
{\tt SM\_tag} は {\tt SM\_} で始まるスタックマシンオペレータを識別する定数である.
発信元 AAA, 受信先 BBB を書く必要があるときは,
From AAA, To BBB, を OXexpression の前に書く.
必要なければ省略する.
たとえば, あとで説明する, CMO string ``Hello'' を スタックにプッシュする
表現は次のように書く:
\begin{center}
(OX\_DATA, (CMO\_STRING, 5, "Hello"))
\end{center}
あとで説明するように, local 関数 ``hoge'' を実行する スタックマシンコマンドは
次のように表現する:
\begin{center}
(OX\_DATA, (CMO\_STRING, 5, "hoge"))
\end{center}
\begin{center}
(OX\_COMMAND, SM\_executeStringByLocalParser)
\end{center}
標準 encoding 法では, 各 タグを ネットワークバイトオーダーの
32 bit integer で表現する.
\subsection{OXexpression の 標準 encoding と TCP/IP ソケットによる実装法}
通信の実現方法は通信路のとりかたによりかわるが,
論理構造は統一的にあつかわないといけない.
OXexpression はその論理構造を記述している.
ここでは OXexpression の標準 encoding の概略を説明する.
この encoding 法はTCP/IP ソケット用の encoding 法として
現在存在しているサーバに使用されている.
さらにOX スタックマシンの計算状態を制御するための, コントロールメッセージに
ついても説明する.
{\tt destination}, {\tt origin} の部分は, ソケットによる
peer to peer の接続なので省略する.
{\tt extension} フィールドは
{\tt message\_tag} フィールドの次にくる.
{\tt extension} フィールドは OX パケットのシリアル番号がはいる.
シリアル番号は {\tt int32} である.
この番号は, サーバがエラーを起こした場合, エラーをおこした,
OX パケットの番号を戻すのに主に利用される.
以下 {\tt extension} フィールドは, {\tt message\_tag} の
に含まれると理解し {\tt extension} フィールドは省略する.
したがってパケットは
次のように記述する
\begin{center}
\begin{tabular}{|c|c|}
\hline
{\tt ox message\_tag}&{\tt message\_body} \\
\hline
\end{tabular}
\end{center}
が, もっとこまかく見ると,
\begin{center}
\begin{tabular}{|c|c|}
\hline
{\tt ox message\_tag}, \ {\tt packet number}&{\tt message\_body} \\
\hline
\end{tabular}
\end{center}
となっている.
グループ OXobject/TCPIP/Basic0 の
{\tt ox message\_tag} としては次のものが用意されている.
@plugin/oxMessageTag.h
\begin{verbatim}
#define OX_COMMAND 513
#define OX_DATA 514
#define OX_DATA_WITH_LENGTH 521
#define OX_DATA_OPENMATH_XML 523
#define OX_DATA_OPENMATH_BINARY 524
#define OX_DATA_MP 525
#define OX_SYNC_BALL 515
\end{verbatim}
通信路は 2 つ用意する.
1番目の通信路は
\verb+ OX_COMMAND +
および
\verb+ OX_DATA +
がながれる.
2番目の通信路 ({\tt control}と呼ぶ) には,
\verb+ OX_COMMAND + およびそれに続くコントロールコマンド
\verb+ SM_control_* +
またはコントロール関係のデータ, つまり header
\verb+ OX_DATA + ではじまりそれに続く CMO データ
がながれる.
これらをコントロールメッセージおよびコントロールメッセージの結果
メッセージと呼ぶ.
サンプルサーバでは, この 2 つの通信路を, 2 つのポートを用いて
実現している.
\verb+ OX_COMMAND + メッセージは次の形のパケット: \\
\begin{tabular}{|c|c|}
\hline
{\tt OX\_COMMAND} & {\tt int32 function\_id} \\ \hline
{\it message\_tag} & {\it message\_body}
\\ \hline
\end{tabular}, \quad
({\tt OX\_COMMAND}, ({\tt SM\_*}))
\\
\verb+ OX_DATA + メッセージは次の形のパケット: \\
\begin{tabular}{|c|c|}
\hline
{\tt OX\_DATA} & {\tt CMO data} \\ \hline
{\it message\_tag} & {\it message\_body}\\ \hline
\end{tabular}, \quad
({\tt OX\_DATA}, {\sl CMObject} data)
\\
データは CMO を用いて表現する.
コントロールメッセージは次の形のパケット: \\
\begin{tabular}{|c|c|}
\hline
{\tt OX\_COMMAND} & {\tt int32 function\_id} \\ \hline
\end{tabular}, \quad
({\tt OX\_COMMAND},({\tt SM\_control\_*}))
\\
コントロールメッセージは, 計算を中断したい, debug 用の スレッドを起動する,
debug モードを抜けたい, などの用途に利用する.
コントロールメッセージの結果メッセージは次の形のパケット: \\
\begin{tabular}{|c|c|l|}
\hline
{\tt OX\_DATA} & {\tt CMO\_INT32} & {\tt int32 data} \\ \hline
\end{tabular}, \quad
({\tt OX\_DATA}, {\sl Integer32 } n)
\\
{\tt int32 function\_id}
の部分に, サーバスタックマシン の operator に対応する番号がはいる.
グループ SMobject/Basic0 および SMobject/Basic1 に属する
タグとして以下のものがある.
@plugin/oxFunctionId.h
\begin{verbatim}
#define SM_popSerializedLocalObject 258
#define SM_popCMO 262
#define SM_popString 263
#define SM_mathcap 264
#define SM_pops 265
#define SM_setName 266
#define SM_evalName 267
#define SM_executeStringByLocalParser 268
#define SM_executeFunction 269
#define SM_beginBlock 270
#define SM_endBlock 271
#define SM_shutdown 272
#define SM_setMathCap 273
#define SM_executeStringByLocalParserInBatchMode 274
#define SM_getsp 275
#define SM_dupErrors 276
#define SM_control_kill 1024
#define SM_control_reset_connection 1030
\end{verbatim}
たとえば,
\begin{center}
(OX\_COMMAND, SM\_pops)
\end{center}
は
\begin{center}
\begin{tabular}{|c|c|}
\hline
{\tt int32} 513 & {\tt int32} 265 \\
\hline
\end{tabular}
\end{center}
とエンコードされる.
operator の詳細は次の節で説明する.
これらの定数の名前はインプリメントのとき短縮形で表現してもよい.
*/
//&jp \section{ OX スタックマシン }
//&eg \section{ OX stackmachine } (This section has not yet been translated.)
/*&jp
この節では, OX スタックマシン operator の説明
(TCP/IP ソケット上での標準 encoding 法 を用いる),
および, サンプルサーバとリンクする場合または
open XM ライブラリとしてリンクして使用する場合の
ための C の関数の仕様を説明する.
説明の前に, OX サーバスタックマシンの動作の原則を
説明しておく.
サーバスタックマシンは,
{\tt SM\_pop*} 系のスタックマシンコマンドがこないかぎり,
自発的にメッセージを送信することはない.
この原則に基づいて分散計算のプログラミングをおこなう.
イベントドリブンなプログラム法とはちがうことに
注意しよう.
\subsection{サーバスタックマシン }
サンプルサーバである {\tt oxserver00.c}
は以下の仕様の C の関数を用意して,
{\tt nullstackmachine.c } を置き換えれば一応動作するはずである.
\noindent
\subsubsection{サーバスタックマシンのグループ SMobject/Basic0
に属するオペレータ}
\noindent
サーバスタックマシンは最低で1本のスタック
\begin{verbatim}
Object xxx_OperandStack[SIZE];
\end{verbatim}
をもつ.
ここで, {\tt Object} はそのシステム固有の Object 型で構わない.
CMObject は各サーバ固有のローカルオブジェクトに変換して
スタックへプッシュしてよい.
ただし変換, 逆変換を合成したものは恒等写像であることがのぞましい.
CMObject をどのように (local) Object に変換するか,
Object が受け付けるメッセージの定義は,
各システムが独自にきめて文書化しておくものとする.
つまりすべてのメッセージは, private である.
たとえば, {\tt add } のような基本的な メッセージにたいしても,
OX スタックマシンはなにもきめていない.
将来的には open math \cite{openmath} のように
CMObject に対する最大公約数的なメッセージの仕様を
content dictionary (CD) の形で定義したい.
以下, \verb+ xxx_ + は誤解の恐れがないときは省略する.
\verb+ xxx_ + は local サーバシステムに固有の識別子である.
{\tt Asir} の場合は \verb+ Asir_ + を用いる.
{\tt kan/sm1} の場合は \verb+ Sm1_ + を用いる.
関数名, タグ名は長いので省略形を用いてもよい.
以下では次のようにパケットを記述する.
各フィールドは,
\fbox{データ型 \quad データ} なる形式で書く.
たとえば,
{\tt int32 OX\_DATA}
は 32 bit network byte order の数字 {\tt OX\_DATA}
という意味である.
``イタリックで書かれているフィールドは,
定義が別のところでなされているか解釈に誤解のないような自然言語
で説明されている object を表す.''
たとえば,
{\it String commandName}
は, String データ型の local object {\it commandName}
を意味する.
(サーバスタックマシン上の object は, CMO 形式の object
とは限らないことに注意.
CMO 形式で書いてあっても, それはサーバスタックマシンの
local 形式でスタック上にあると解釈して下さい.)
すべてのサーバスタックマシンは
以下の関数を実装していないといけない.
\begin{enumerate}
\item
CMObject/Basic0 の CMO データのうち必須のもの,
{\tt CMO\_ERROR2}, {\tt CMO\_NULL}, {\tt CMO\_INT32},
{\tt CMO\_STRING}, {\tt CMO\_LIST}
がおくられて来た場合
それをスタックに push する.
たとえば, {\tt CMO\_NULL} の場合次のようになる.
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_DATA} & {\tt int32 CMO\_NULL} \\
\hline
\end{tabular}
\\ Stack after the request:
\begin{tabular}{|c|} \hline
{\it NULL} \\
\hline
\end{tabular}
\\ Result: なし.
たとえば, {\tt CMO\_String} の場合次のようになる.
\\ Request:
\begin{tabular}{|c|c|c|c|c|c|} \hline
{\tt int32 OX\_DATA} & {\tt int32 CMO\_String} &{\tt int32} {\rm size}
&{\tt byte} {\rm s1} & $\cdots$ &{\tt byte} {\rm ssize}\\
\hline
\end{tabular}
\\ Stack after the request:
\begin{tabular}{|c|} \hline
{\it String s} \\
\hline
\end{tabular}
\\ Result: なし.
CMO データの受け取りに失敗した時のみ \\
\begin{tabular}{|c|c|c|} \hline
{\tt int32 OX\_DATA} & {\tt int32 CMO\_ERROR2} & {\it CMObject} ob\\
\hline
\end{tabular}
\\
をスタックへ push する.
現在のところ, ob には, \\
\centerline{
[{\sl Integer32} OX パケット番号, {\sl Integer32} エラー番号,
{\sl CMObject} optional 情報]
}
なるリストを入れる (CMO 形式でかいてあるが, これはサーバ独自の形式でよい.
CMO として送出されるときこのような形式でないといけないという意味である.)
\item
\begin{verbatim}
void *xxx_mathCap()
\end{verbatim}
このサーバの mathcap をもどす (termcap のまね).
サーバのタイプ, サーバスタックマシンの能力を知ることができる.
C 言語で実装する場合は, mathCap の構造体をシステム毎にきめるものとし,
この関数はその構造体へのポインタを戻す.
(open sm1 では {\tt struct mathCap} を用いている.
@plugin/mathcap.h)
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_mathcap} \\
\hline
\end{tabular}
\\ Result:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_DATA} & {\sl Mathcap} mathCapOb \\
\hline
\end{tabular}
\item
\begin{verbatim}
xxx_setMathCap(void *m)
\end{verbatim}
受け取った Mathcap {\tt m} を
自分のシステムに設定して, 相手側が理解不能な CMO をおくらないように
する.
C 言語で実装する場合は, mathCap の構造体をシステム毎にきめるものとし,
この関数はその構造体へのポインタを引数とする.
(open sm1 では {\tt struct mathCap} を用いている.
@plugin/mathcap.h)
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_DATA} & {\sl Mathcap} m \\ \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_setMathCap} \\
\hline
\end{tabular}
\\ Result: なし. \\
注意: mathcap は一般にクライアント主体で設定する.
クライアントがサーバに {\tt SM\_mathcap} をおくり,
サーバ側の mathcap を得る.
それを, クライアントはそのサーバに付随した mathcap として
設定する.
次に, クライアントはサーバに自分の mathcap を
{\tt SM\_setMathCap} でおくり, 自分の mathcap を設定させる.
\item
\begin{verbatim}
int xxx_executeStringByLocalParser(char *s)
\end{verbatim}
文字列 $s$ をシステム xxx の文法(サーバスタックマシンの組み込みローカル
言語)にしたがったコマンドとして実行する.
ただし, コマンドの実行の結果の最後に戻り値があるときは,
{\tt OperandStack} に戻り値を push する.
正常終了なら 0 を, 異常終了なら -1 をもどす.
debug モードにはいった場合, -2 を戻す.
エラーの時 Error2 Object
を stack へ push する.\\
{\tt kan/sm1} の場合, サーバスタックマシンの組み込みローカル言語は
{\tt sm1} ポストスクリプト言語である.
サーバスタックマシンと, {\tt sm1} ポストスクリプト言語はスタックを
共有するように実装されている.
実際の計算は
{\tt executeStringByLocalParser} により実行される.
open XM では, 現在のところ関数名の標準化はおこなっていない.
したがって, 実際の計算コマンドの送出は mathcap をみてクライアントが
正しいコマンドを選択する必要がある.
(しかしながら, 共通関数名がないために, 共通仕様のサーバスタックマシンの
実装はきわめて簡単である. 関数名の共通化は将来の課題.) \\
割込みに関しては, -1 を戻すように ハンドラを書く.
executeStringByLocalParser() を再帰的に呼んだときも 割り込みのハンドラが
正しく動作するようにこの関数は書かれるべきである.
この関数を呼び出したのち, signal, setjmp の再設定を呼び出し側でやらないと
いけない. \\
この関数および {\tt popString} の機能を実現すれば, 最低限の
open XM のサーバになれる. 実装では, まずこの二つの関数の機能を
実現すべきである.
\\ Stack before the request:
\\
\begin{tabular}{|c|} \hline
{\it String commandString} \\
\hline
\end{tabular}
\\Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND}& {\tt int32 SM\_executeStringByLocalParser} \\
\hline
\end{tabular}
\\ Result: なし.
\\ 参考: \ 実行前のスタックのデータは,
{\it String commandString} なる local stackmachine の object として
スタック上にあるが, TCP/IP の通信路では, 次のようなデータがまずながれて
{\it commandName} がスタックに push される:
\\
\begin{tabular}{|c|c|c|} \hline
{\tt int32 OX\_DATA} & {\tt int32 CMO\_string} & {\it size and the string commandString} \\
\hline
\end{tabular}
\item
\begin{verbatim}
int xxx_executeStringByLocalParserInBatchMode(char *s)
\end{verbatim}
スタックに副作用がない(スタックにたいしてなんの操作もしない)
ことを除き上とまったく同じ関数である.
エラーの時のみ, Error2 Object をスタックへプッシュする.
\item
\begin{verbatim}
char *xxx_popString(void)
void xxx_popString(ox_stream out)
\end{verbatim}
最初の関数はライブラリとしてリンクして使用する場合の関数である.
{\tt OperandStack} より Object を pop し, それを xxx の出力
規則にしたがい文字列型に変換して戻す.
スタックが空のときは, {\tt (char *)NULL} を戻す.
呼出側の関数は, 戻り値のメモリー領域を操作してはいけない.
また, 再度 サーバスタックマシンが呼ばれたときは, 戻り値のメモリ領域
は変更されているかもしれない.
2 番目の関数は, TCP/IP を用いて通信する場合の関数である.
変換されてでてきた文字列を値として返すのではなく,
{\tt ox\_stream out}
へ CMO のデータとして送信する.
エラーの場合は {\tt CMO\_ERROR2} を戻すべきである.
\\ Stack before the request:
\begin{tabular}{|c|} \hline
{\it Object} \\
\hline
\end{tabular}
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_popString} \\
\hline
\end{tabular}
\\ Result:
\begin{tabular}{|c|c|c|} \hline
{\tt int32 OX\_DATA} & {\tt int32 CMO\_STRING} & {\it size and the string s} \\
\hline
\end{tabular}
\item
\begin{verbatim}
int xxx_getsp(void)
\end{verbatim}
現在のスタックポインタの位置をもどす.
スタート時点での位置は 0 であり, object が push されたばあい,
1 づつ増えるものとする.
\\ Stack before the request:
\begin{tabular}{|c|} \hline
{\it Object} \\
\hline
\end{tabular}
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_getsp} \\
\hline
\end{tabular}
\\ Result:
\begin{tabular}{|c|c|c|} \hline
{\tt int32 OX\_DATA} & {\tt int32 CMO\_INT32} & {\it stack pointer value} \\
\hline
\end{tabular}
\item
\begin{verbatim}
object xxx_dupErrors(void)
\end{verbatim}
スタック上のエラーオブジェクトをリストにして戻す.
スタック自体は変化させない.
\\ Stack before the request:
\begin{tabular}{|c|} \hline
{\it Object} \\
\hline
\end{tabular}
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_dupErrors} \\
\hline
\end{tabular}
\\ Result:
\begin{tabular}{|c|c|c|} \hline
{\tt int32 OX\_DATA} & {\sl CMObject} \ a list of errors\\
\hline
\end{tabular}
\item
\begin{verbatim}
int xxx_start()
\end{verbatim}
xxx の初期化をおこなう.
\end{enumerate}
\noindent
{\bf 例}: \
次は, 標準入力よりの入力を asir に送り評価した結果を表示するプログラム
である.
\begin{verbatim}
#include
main() {
char tmp[1024];
Asir_start();
while (gets(tmp) != NULL) {
if (Asir_executeStringByLocalParser(tmp) != 0) {
printf("%s\n",Asir_popString());
}
}
}
\end{verbatim}
\medbreak
\noindent
{\bf 例}: \
mathcap の問い合わせに対して, {\tt ox\_sm1} は次のように答える.
%%Prog: [(cmoMathCap)] extension ::
\begin{verbatim}
Class.mathcap
[ [199909080 , $Ox_system=ox_sm1.plain$ , $Version=2.990911$ ,
$HOSTTYPE=i386$ ] ,
[262 , 263 , 264 , 265 , 266 , 268 , 269 , 272 , 273 , 275 , 276 ] ,
[[514] , [2130706434 , 1 , 2 , 4 , 5 , 17 , 19 , 20 , 22 , 23 , 24 ,
25 , 26 , 30 , 31 , 60 , 61 , 27 , 33 , 40 , 34 ]]]
\end{verbatim}
mathcap は 3つの要素をもつリストである.
まづ, 最初の要素を見よう.
Ox\_system は open xxx システム名である.
読み込むライブラリがちがっていて, 関数名(または シンボル)の意味がちがうときは
この名前もかえる.
たとえば, open math の basic content dictionary 対応の関数定義マクロを
読みこんだ sm1 は,
ox\_sm1\_basicCD なる名前にする.
HOSTTYPE値は, CPU の種類をあらわし
unix では環境変数\verb+$HOSTTYPE+ の値である.
2 番目の要素は 利用可能な SM コマンドをあつめたリストである.
3 番目のリストは, 処理可能な数学データの形式, およびCMOの場合なら
処理可能なCMOのタグのリストが続く.
上の例では, 514 は {\tt OX\_DATA} をあらわし, 数学データのフォマットは
(サイズ情報なしの) CMO であることを示す.
\medbreak
\noindent
{\bf 例}: \
%%Prog: (ox.sm1) run sm1connectr [(oxWatch) ox.ccc] extension
%%Prog: ox.ccc (122345; ) oxsubmit ;
{\tt message\_body} の実例をあげる. シリアル番号部は除いてある.
\begin{enumerate}
\item {\tt executeStringByLocalParser("12345 ;");}
は次のようなパケットに変換される. 各数字は 16進1バイトをあらわす.
{\tt xx(yy)} のなかの {\tt (yy)} は対応するアスキーコードをあわらす.
\begin{verbatim}
0 0 2 2 0 0 0 4 0 0 0 7
31(1) 32(2) 33(3) 34(4) 35(5) 20 3b(;)
0 0 2 1 0 0 1 c
\end{verbatim}
ここで,
\verb+ 0 0 2 2 0 0 0 4 + は, network byte order で,
順番に {\tt OX\_DATA} それから,
CMO のタグの, {\tt CMO\_STRING} を表す.
\verb+ 0 0 0 7 + は文字数,
最後に 文字列 {\tt 12345 ;} が来る.
ここで, \verb+ 0 0 1 c + は, network byte order で,
{\tt OX\_executeString} を表す.
まとめると次のようになる.
\begin{verbatim}
0 0 2 2 (OX_DATA) 0 0 0 4 (CMO_STRING)
0 0 0 7 (size)
31(1) 32(2) 33(3) 34(4) 35(5) 20 3b(;) (data)
0 0 2 1 (OX_COMMAND)
0 0 1 c (SM_executeStringByLocalParser)
\end{verbatim}
これを OXexpression で表記すると次のようになる.
\begin{center}
(OX\_DATA, (CMO\_STRING, 7, "12345 ;"))
\end{center}
\begin{center}
(OX\_COMMAND, (SM\_executeStringByLocalParser))
\end{center}
\item {\tt popString()} を要請するメッセージ:
\begin{verbatim}
0 0 2 1 (OX_COMMAND)
0 0 1 7 (SM_popString)
\end{verbatim}
OXexpression では
(OX\_COMMAND, (SM\_popString)).
\noindent
これにたいして次の返答メッセージがくる.
\begin{verbatim}
0 0 2 2 (OX_DATA)
0 0 0 4 (CMO_STRING) 0 0 0 5 (size)
31(1) 32(2) 33(3) 34(4) 35(5)
\end{verbatim}
OXexpression でかくと,
(OX\_DATA, (CMO\_STRING, 7, "12345 ;")).
\end{enumerate}
\subsubsection{グループ SMobject/Basic1 に属するオペレータ}
\begin{enumerate}
\item
\begin{verbatim}
void xxx_pops(int n)
\end{verbatim}
operand stack より, {\it n} 個の元
({\it obj1, obj2, $\ldots$, objn}) を pop して捨てる.
\\ Stack before the request: (右が stack のトップである.) \\
\begin{tabular}{|c|c|c|c|c|} \hline
{\it obj1} & {\it obj2} & $\cdots$ & {\it objn} &{\it INT32 n} \\
\hline
\end{tabular}
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_pops } \\
\hline
\end{tabular}
\\ Result: なし.
\item
\begin{verbatim}
int xxx_setName(char *name)
\end{verbatim}
(これは本当に必要な関数??)
{\tt OperandStack} より {\it name} を pop し, つぎに
{\tt OperandStack} より {\it obj} を pop し, それを
現在の名前空間で変数 {\it name} に bind する.
正常終了なら 0 を, 異常終了なら -1 をもどす.
TCP/IP による通信では, 異常終了の時のみ, {\tt CMO\_ERROR2} を
stack へ push する.
\\ Stack before the request: (右が stack の top.)
\begin{tabular}{|c|c|} \hline
{\it obj} & {\it String name} \\
\hline
\end{tabular}
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_setName} \\
\hline
\end{tabular}
\\ Result: なし.
\item
\begin{verbatim}
int xxx_evalName(char *name)
\end{verbatim}
(これは本当に必要な関数??)
現在の名前空間で変数 {\it name} を評価する.
評価の結果 {\it resultObj} をスタックへ戻す.
関数自体は正常終了なら 0 を, 異常終了なら -1 をもどす.
TCP/IP の場合, 異常終了の場合のみ {\tt CMO\_ERROR2} を stack へ push する.
\\ Stack before the request: (右が stack の top.)
\begin{tabular}{|c|} \hline
{\it String name} \\
\hline
\end{tabular}
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_evalName} \\
\hline
\end{tabular}
\\ Stack after the request: (右が stack の top.)
\begin{tabular}{|c|} \hline
{\it resultObj} \\
\hline
\end{tabular}
\\ Result: なし.
\item
\begin{verbatim}
int xxx_executeFunction(char *s, int n)
\end{verbatim}
スタックより {\it n} 個のデータを pop して, サーバのローカル関数
{\it s} を実行する.
エラーのときのみ {\tt CMO\_ERROR2} を stack へ push する.
\\ Stack before the request: (右が stack の top.) \\
\begin{tabular}{|c|c|c|c|c|} \hline
{\it objn} & $\cdots$ & {\it obj1} & {\it INT32 n} & {\it String s} \\
\hline
\end{tabular}
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_executeFunction} \\
\hline
\end{tabular}
\\ Stack after the request:
関数実行の結果.
\\ Result: なし.
\item
\begin{verbatim}
bytes *xxx_popSerializedLocalObject(void)
void popSerializedLocalObject(ox_stream out)
\end{verbatim}
最初の関数はライブラリとしてリンクして使用するための関数である.
スタックより pop した object を local 形式の serialization して
byte 列で戻す.
2 番目の関数は Socket で通信するための同機能の関数であり,
serialization された byte 列を
{\tt ox\_stream out} へ出力する.
この場合,
header
{\tt int32 OX\_DATA}, {\tt int32 CMO\_LOCAL\_OBJECT}
をつけてから, byte 列を送る.
この関数はおもに, homogeneous な分散システムで用いる.
次に, サーバスタックマシンの関数が実行されるまでは,
戻り object の内容は保証されないといけない.
\item
local serialized object, および サポートする CMO object を
{\tt OX\_DATA} として受信した場合, {\tt OperandStack} へ
push する.
受信エラーを起こしたときのみ, {\tt CMO\_ERROR2} を stack へ push する.
\item
\begin{verbatim}
bytes *xxx_popCMO(void)
void xxx_popCMO(ox_stream out)
\end{verbatim}
最初の関数はライブラリとしてリンクして使用するための関数である.
{\tt OperandStack} より object を pop し CMO 形式の
serialized object を byte 列として戻す.
2 番目の関数は Socket で通信するための同機能の関数であり,
{\tt ox\_stream out } へ, そのデータを header
{\tt OX\_DATA} をつけてながす.
この関数はおもに, heterotic な分散システムで用いる.
次に, サーバスタックマシンの関数が実行されるまでは,
戻り object の内容は保証されないといけない.
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 OX\_popCMO} \\
\hline
\end{tabular}
\\ Result:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_DATA} & {\it Serialized CMO} \\
\hline
\end{tabular}
以下で, {\tt ox\_stream} はサンプルサーバの場合,
\begin{verbatim}
typedef FILE2 * ox_stream;
\end{verbatim}
である (cf. {\tt file2.h}). これは処理系によりちがってよい.
{\tt ox\_asir} では, {\tt FILE *} を用いている.
\end{enumerate}
*/
//&jp \section{現在検討中の機能}
//&eg \section{Projects in work in progress} (This part has not been translated.)
/*&jp
\subsection{ OX DATA with Length の構造 }
Digital signature 付の {\tt OX\_DATA} は
ヘッダ {\tt OX\_DATA\_WITH\_LENGTH }で, はじまり, CMO がきて,
それから, 終りのマークおよびデジタル署名がくる.
この形のデータを {\it secured OX DATA} と呼ぶ.
\begin{verbatim}
#define OX_SECURED_DATA 521
\end{verbatim}
\noindent
\begin{tabular}{|c|c|c|c|c|} \hline
{\tt int32 OX\_DATA\_WITH\_LENGTH} & {\tt int32} {\rm serial}
& {\tt int32} {\rm size}
& {\sl CMObject} {\rm o} & {\it tail} \\
\hline
\end{tabular}
{\tt size} フィールドに 値 -1 が入っている場合この情報を無視する.
{\it tail } は次のように定義する.
\\ \noindent
\begin{tabular}{|c|c|c|} \hline
{\tt int32 CMO\_START\_SIGNATURE} & {\tt int32} {\rm size}
& {\it signature} \\
\hline
\end{tabular}
ここで, {\tt size} はバイト列 {\it signature} 部の長さ.
{\it signature} は, Hash 関数を用いた, {\it CMO data}
にたいする, デジタル署名をいれ, 不正な serialized object
を検出する.
Tail の {\tt size} フィールドが 0 の場合, デジタル署名部はない.
クライアント, サーバの実装には次の3つの選択がある.
\begin{enumerate}
\item {\tt OX\_DATA} のみを用いて CMObject を送る (mathcap 付).
\item {\tt OX\_SECURED\_DATA} のみを用いて CMObject を送る.
\item {\tt OX\_DATA} および
{\tt OX\_SECURED\_DATA} を混在して
使用できるようにする.
\item {\tt OX\_DATA} のみを用いてかつ mathcap も用いない(一番高速).
\end{enumerate}
1 の短所は, mathcap の実装が不十分で,
理解できない CMObject をうけとると,
以後の CMObject は理解できなくなる.
1 の長所は, 長さフィールドの計算を
おこなわないため, データを送り出す側に負担がかからないことである.
2 の長所は, mathcap の実装が不十分で,
理解できない CMObject をうけとっても,
長さフィールドを用いて, 通信回線のダウンを
防ぐことができる.
2 の短所は, 長さフィールドの計算を
おこなうため, データを送り出す側に負担がかかることである.
現在のすべてのサンプルサーバは, 1, 4 のみを実装している.
mathcap の交換はセッションの開始時点で必須という訳ではない
ことに注意されたい.
たとえば,
モード 4 で通信して,
それから,
mathcap を交換して,
モード 1 へ移行することも可能なように実装すべきである.
\subsection{サーバスタックマシンはローカルな拡張機能をもってよい}
\begin{verbatim}
#define CMO_PRIVATE 0x7fff0000
\end{verbatim}
{\tt CMO\_PRIVATE} = {\tt OX\_PRIVATE} = {\tt SM\_PRIVATE}
よりはじまる, 0x10000 個の ID は, private 領域として予約されている.
各サーバの開発者間で表現方法につきまだ合意がないような, CMObject,
OXobject, SMobject を表現するために使用する.
\subsection{MathLink や open math などの通信規約の実装}
Open asir, open sm1 と Mathematica の用いている MathLink や
Open Math (\cite{openmath})
プロトコルを変換するための
ライブラリやサーバを用意すれば, {\tt asir} や {\tt kan/sm1} の
内部構造を理解することなしに, これらに準拠したシステムと通信できる.
\subsection{共通スタックマシン言語}
CMO に付随した, たとえば, Integer 32 に対する,
add, sub, mul, などの基本的な計算は {\tt SM\_executeFunction}
で全てのシステムで実行できるように検討している.
スタックマシンの制御構造についても検討している.
*/
//&jp \section{コントロールメッセージ (SMObject/TCPIP/Control)}
//&eg \section{Control message (SMObject/TCPIP/Control)} (This section has not been translated.)
/*&jp
\begin{enumerate}
\item
サーバは {\tt SM\_control\_reset\_connection}
メッセージを受信したら, 現在の計算を中断する.
中断操作は細心の注意をもって行なわないといけない.
サンプルサーバ ({\tt oxmain.c})では, コントロールメッセージの
処理は別のプロセスがおこなっており, SIGUSR1 割り込みをスタックマシンへ
かける.
もしサーバがメッセージの通信中であれば, このコントロールメッセージ
をすぐには実行せず, メッセージ通信を終了するのを待つ.
当然, メッセージを発信中に, このメッセージを送信してもいけない.
(Java 風にいえば, すべての メッセージは synchronized object である.)
また, たとえば file IO なども, 中断をうけてはならない, synchronized な
操作であろう.
クライアントがサーバに controlResetConnection コントロールメッセージを
おくったら, サーバは, 現在の受信バッファをすべてクリアし,
クライアントへ
{\tt OX\_SYNC\_BALL}
を送る.
クライアントは, コントロールメッセージをおくったあと,
待機モードに入り, {\tt OX\_SYNC\_BALL}
をうけとるまですべてのメッセージを読み飛ばす.
クライアントは {\tt OX\_SYNC\_BALL} をうけとったら,
サーバに {\tt OX\_SYNC\_BALL} を送る.
サーバは, 最初の {\tt OX\_SYNC\_BALL} を投げたあと,
待機モードに入り,
{\tt OX\_SYNC\_BALL}
をうけとるまですべてのメッセージを読み飛ばす.
%% 最後に, サーバ
%% はすべての操作が終了したことを通知するため,
%% クライアントに
%% {\tt OX\_SYNC\_BALL} を投げる.
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_control\_reset\_connection} \\
\hline
\end{tabular}
\\ Result:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_DATA} & {\tt CMO\_INT32} {\rm result} \\
\hline
\end{tabular}
@@@
\item
サーバはこのメッセージを受信したらただちにコントロールメッセージへの
返答をおくり, すべてのファイルをクローズして終了する.
\\ Request:
\begin{tabular}{|c|c|} \hline
{\tt int32 OX\_COMMAND} & {\tt int32 SM\_control\_kill} \\
\hline
\end{tabular}
\\ Result:
Empty \\
\end{enumerate}
\medbreak
\noindent
{\bf 例}: (シリアル番号は省略してある.)\
\begin{verbatim}
0 0 2 01 (OX_COMMAND)
0 0 4 06 (SM_control_reset_connection)
\end{verbatim}
Reset に対する返事.
\begin{verbatim}
0 0 2 02 (OX_DATA)
0 0 0 2 (CMO_INT32)
0 0 0 0 ( 0 )
\end{verbatim}
第1のチャンネルでは次の {\tt OX\_SYNC\_BALL} が交換されて同期が
取られる.
\begin{verbatim}
0 0 2 03 (OX_SYNC_BALL)
\end{verbatim}
*/
//&jp \section{TCP/IP でのセッションのスタート}
//&eg \section{How to start a session on TCP/IP} (This section has not yet been translated.)
/*&jp
コントロールプロセス, 計算プロセス
ともに, 起動直後に
1 byte のデータを書き出し flush する.
そのあと, 1 byte のデータを読み込む.
クライアントはコントロールプロセス, 計算プロセス
につながるファイルディスクリプタの両方から
まず 1 byte のデータを読む.
そのあと
1 byte のデータを書き出し flush する.
1 byte のデータは,
{\tt 0}, {\tt 1}, {\tt FF} のどれかであり,
{\tt 0} は以下の通信において {\tt int32} をおくるのに,
network byte order を使用したい,
{\tt 1} は以下の通信において {\tt int32} をおくるのに,
little endian を使用したい,
{\tt FF} は以下の通信において {\tt int32} をおくるのに,
big endian を使用したい,
という意味である.
両者の希望が一致しない場合はつねに {\tt 0} (network byte order)
を使用する.
Network byte order しか実装していないシステムでは,
{\tt 0} をおくればよい.
ただし効率が問題となる通信において, network byte order への変換は
おおきなボトルネックとなることがあることを了解しておくべきである.
\begin{verbatim}
#define OX_BYTE_NETWORK_BYTE_ORDER 0
#define OX_BYTE_LITTLE_ENDIAN 1
#define OX_BYTE_BIG_ENDIAN 0xff
\end{verbatim}
注意: {\tt OpenXM/src/kxx} に含まれる, {\tt ox} (コントロールプロセス,
計算プロセスをたちあげるローンチャ)は, 標準で One Time Password
の機能をもっています.
この機能を OFF にするには {\tt -insecure} option を使用して下さい.
One Time Password は 0 で終了するバイト列であり,
コントロール, 計算双方のプロセスをたちあげるまえに,
{\tt ox} はコントロール, 計算双方のプロセスに対応する,
ふたつのポートに
One Time Password バイト列を送出しています.
{\tt ox} (ソースは {\tt oxmain.c}, {\tt kan96xx/plugin/oxmisc.c})においては
{\tt oxTellMyByteOrder()} が, サーバについての byte order 情報の
送出, 読み込みをやっている.
クライアントについては,
{\tt oxSetByteOrder()} が, byte order 情報の読み込み, 送出をおこなっている.
One time パスワードは安全な通信路で配送される必要があります.
また, 現在の {\rm ox} の実装では, One time パスワードを
サーバ, クライアントに login している人はすべて見ることが
できますので, サーバ, クライアントには悪意のある人はいないと
仮定しないといけません.
One time パスワードを安全に配送し, リモートマシンの {\rm ox}
を立ち上げるには
たとえば
{\tt ssh} を {\tt -f } オプションを用いて使用します.
以下は {\rm sm1} での実装, 動作例です.
ここでは, {\tt yama} の {\tt sm1} より {\tt dc1} の {\tt ox}
を立ち上げています.
{\footnotesize
\begin{verbatim}
yama% sm1
sm1>(ox.sm1) run ;
ox.sm1, --- open sm1 protocol module 10/1,1999 (C) N.Takayama. oxhelp for help
sm1>[(dc1.math.kobe-u.ac.jp) (taka)] sm1connectr-ssh /ox.ccc set ;
Hello from open. serverName is yama.math.kobe-u.ac.jp and portnumber is 0
Done the initialization. port =1024
Hello from open. serverName is yama.math.kobe-u.ac.jp and portnumber is 0
Done the initialization. port =1025
[ 4 , 1025 , 3 , 1024 ]
Executing the command : ssh -f dc1.math.kobe-u.ac.jp -l taka
"/home/taka/OpenXM/bin/oxlog /usr/X11R6/bin/xterm -icon
-e /home/taka/OpenXM/bin/ox -reverse -ox /home/taka/OpenXM/bin/ox_sm1
-host yama.math.kobe-u.ac.jp -data 1025 -control 1024 -pass 518158401 "
[
taka@dc1.math.kobe-u.ac.jp's password:
Trying to accept... Accepted.
Trying to accept... Accepted.
Control port 1024 : Connected.
Stream port 1025 : Connected.
Byte order for control process is network byte order.
Byte order for engine process is network byte order.
\end{verbatim}
}
*/
//&jp \section{ オブジェクトの文字列表現 }
//&eg \section{ String expression of objects}
/*&jp
文字列表現は, システム xxx のマニュアルに記述されている一次元的入出力形式に
したがう.
*/
/*&eg
The string expression of objects of the system xxx is also used
for a string expression for the OX xxx server.
*/
//&jp \section{ 数, 多項式 の CMO 表現 }
//&eg \section{ CMOexpressions for numbers and polynomials }
/*&C
@../SSkan/plugin/cmotag.h
\begin{verbatim}
#define CMO_MONOMIAL32 19
#define CMO_ZZ 20
#define CMO_QQ 21
#define CMO_ZERO 22
#define CMO_DMS_GENERIC 24
#define CMO_DMS_OF_N_VARIABLES 25
#define CMO_RING_BY_NAME 26
#define CMO_DISTRIBUTED_POLYNOMIAL 31
#define CMO_RATIONAL 34
#define CMO_INDETERMINATE 60
#define CMO_TREE 61
#define CMO_LAMBDA 62 /* for function definition */
\end{verbatim}
*/
/*&jp
以下, グループ CMObject/Basic1, CMObject/Tree
および CMObject/DistributedPolynomial
に属する CMObject の形式を説明する.
\noroa{ tagged list を導入すべきか? cf. SSkan/plugin/cmo.txt }
*/
/*&eg
In the sequel, we will explain on the groups
CMObject/Basic1, CMObject/Tree
and CMObject/DistributedPolynomial.
*/
/*&jp
\bigbreak
\noindent
Group CMObject/Basic1 requires CMObject/Basic0. \\
ZZ, QQ, Zero, Rational, Indeterminate,$\in$ CMObject/Basic1. \\
\begin{eqnarray*}
\mbox{Zero} &:& ({\tt CMO\_ZERO}) \\
& & \mbox{ --- ユニバーサルな ゼロを表す. } \\
\mbox{ZZ} &:& ({\tt CMO\_ZZ},{\sl int32}\, {\rm f}, {\sl byte}\, \mbox{a[1]}, \ldots
{\sl byte}\, \mbox{a[m]} ) \\
&:& \mbox{ --- bignum をあらわす. a[i] についてはあとで説明}\\
\mbox{QQ} &:& ({\tt CMO\_QQ}, {\sl ZZ}\, {\rm a}, {\sl ZZ}\, {\rm b}) \\
& & \mbox{ --- 有理数 $a/b$ を表す. } \\
\mbox{Rational} &:& ({\tt CMO\_RATIONAL}, {\sl CMObject}\, {\rm a}, {\sl CMObject}\, {\rm b}) \\
& & \mbox{ --- $a/b$ を表す. } \\
\mbox{Indeterminate} &:& ({\tt CMO\_INDETERMINATE}, {\sl Cstring}\, {\rm v}) \\
& & \mbox{ --- 変数名 $v$ . } \\
\end{eqnarray*}
*/
/*&eg
\bigbreak
\noindent
Group CMObject/Basic1 requires CMObject/Basic0. \\
ZZ, QQ, Zero, Rational, Indeterminate,$\in$ CMObject/Basic1. \\
\begin{eqnarray*}
\mbox{Zero} &:& ({\tt CMO\_ZERO}) \\
& & \mbox{ --- Universal zero } \\
\mbox{ZZ} &:& ({\tt CMO\_ZZ},{\sl int32}\, {\rm f}, {\sl byte}\, \mbox{a[1]}, \ldots
{\sl byte}\, \mbox{a[m]} ) \\
&:& \mbox{ --- bignum. The meaning of a[i] will be explained later.}\\
\mbox{QQ} &:& ({\tt CMO\_QQ}, {\sl ZZ}\, {\rm a}, {\sl ZZ}\, {\rm b}) \\
& & \mbox{ --- Rational number $a/b$. } \\
\mbox{Rational} &:& ({\tt CMO\_RATIONAL}, {\sl CMObject}\, {\rm a}, {\sl CMObject}\, {\rm b}) \\
& & \mbox{ --- Rational expression $a/b$. } \\
\mbox{Indeterminate} &:& ({\tt CMO\_INDETERMINATE}, {\sl Cstring}\, {\rm v}) \\
& & \mbox{ --- Variable name $v$ . } \\
\end{eqnarray*}
*/
/*&C
*/
/*&jp
Indeterminate は変数名をあらわす.
v はバイト列であればなにを用いてもよいが,
システム毎に変数名として用いられるバイト列は制限がある.
各システム xxx は任意の文字列を各システム固有の変数名へ1対1に変換できるように
実装しないといけない.
(これを
{\tt Dx} は {\tt \#dx} と変換するなどの
escape sequence を用いて実現するのは, 無理があるようである.
テーブルを作成する必要があるであろう.)
*/
/*&eg
Indeterminate is a name of a variable.
v may be any sequence of bytes, but each system has its own
restrictions on the names of variables.
Indeterminates of CMO and internal variable names must be translated
in one to one correspondence.
*/
/*&jp
\noindent
Group CMObject/Tree requires CMObject/Basic1. \\
Tree, Lambda $\in$ CMObject/Basic1. \\
\begin{eqnarray*}
\mbox{Tree} &:& ({\tt CMO\_TREE}, {\sl Cstring}\, {\rm name},
{\sl Cstring}\, {\rm cdname}, {\sl List}\, {\rm leaves}) \\
& & \mbox{ --- 名前 name の定数または関数. 関数の評価はおこなわない. } \\
& & \mbox{ --- cdname は空文字列でなければ name の意味が説明されている }\\
& & \mbox{ --- OpenMath CD (content dictionary) の名前. } \\
\mbox{Lambda} &:& ({\tt CMO\_LAMBDA}, {\sl List}\, {\rm args},
{\sl Tree} {\rm body}) \\
& & \mbox{ --- body を args を引数とする関数とする. } \\
& & \mbox{ --- optional な引数が必要なときは, leaves の後へつづける.} \\
\end{eqnarray*}
*/
/*&eg
\noindent
Group CMObject/Tree requires CMObject/Basic1. \\
Tree, Lambda $\in$ CMObject/Basic1. \\
\begin{eqnarray*}
\mbox{Tree} &:& ({\tt CMO\_TREE}, {\sl Cstring}\, {\rm name},
{\sl Cstring}\, {\rm cdname}, {\sl List}\, {\rm leaves}) \\
& & \mbox{ --- A function or a constant of name. Functions are not evaluated. } \\
& & \mbox{ --- cdname may be a null. If it is not null, it is the name of}\\
& & \mbox{ --- the OpenMath CD (content dictionary). } \\
\mbox{Lambda} &:& ({\tt CMO\_LAMBDA}, {\sl List}\, {\rm args},
{\sl Tree} {\rm body}) \\
& & \mbox{ --- a function with the arguments body. } \\
& & \mbox{ --- optional arguments come after leaves.} \\
\end{eqnarray*}
*/
/*&C
*/
/*&jp
数式を処理するシステムでは, Tree 構造が一般にもちいられる.
たとえば, $\sin(x+e)$ は,
{\tt (sin, (plus, x, e))}
なる Tree であらわすのが一般的である.
Tree の表現を スタックマシンのレベルでおこなうとすると,
{\tt ox\_BEGIN\_BLOCK}, {\tt ox\_END\_BLOCK} で評価を抑制するのが
一つの方法である (cf. Postscript の {\tt \{ }, {\tt \} }).
たとえば上の方法では
{\tt x, e, plus, sin } を begin block, end block でかこめばよろしい.
われわれはスタックマシンの実装をなるべく簡単にするという立場をとりたい,
また数学オブジェクトを OX スタックマシンと CMObject を混在して表現したく
ない.
したがって,
Tree 構造は Open Math 風の表現をもちいた CMO を導入することにした.
またこのほうが, われわれの想定するシステム xxx において, Open XM 対応が
はるかに容易である.
なお, Tree は, Open Math では, Symbol, Application のメカニズムに相当する.
*/
/*&eg
In many computer algebra systems, mathematical expressions are usually
expressed in terms of a tree structure.
For example,
$\sin(x+e)$ is expressed as
{\tt (sin, (plus, x, e))}
as a tree.
We can @@@
*/
/*&C
*/
/*&jp
Lambda は関数を定義するための関数である.
Lisp の Lambda 表現と同じ.
\noindent
例: $sin(x+e)$ の表現.
\begin{verbatim}
(CMO_TREE, (CMO_STRING, "sin"), (CMO_STRING, "basic"),
(CMO_LIST,[size=]1,
(CMO_TREE, (CMO_STRING, "plus"), (CMO_STRING, "basic"),
(CMO_LIST,[size=]2, (CMO_INDETERMINATE,"x"),
(CMO_TREE,(CMO_STRING, "e"), 自然対数の底
(CMO_STRING, "basic"))
))
)
)
\end{verbatim}
\noindent
Example:
\begin{verbatim}
sm1> [(plus) (Basic) [(123).. (345)..]] [(class) (tree)] dc ::
Class.tree [ $plus$ , $Basic$ , [ 123 , 345 ] ]
\end{verbatim}
\bigbreak
次に, 分散表現多項式に関係するグループを定義しよう.
\medbreak
\noindent
Group CMObject/DistributedPolynomials requires CMObject/Basic0,
CMObject/Basic1. \\
Monomial, Monomial32, Coefficient, Dpolynomial, DringDefinition,
Generic DMS ring, RingByName, DMS of N variables $\in$
CMObject/DistributedPolynomials. \\
\begin{eqnarray*}
\mbox{Monomial} &:& \mbox{Monomial32}\, |\, \mbox{Zero} \\
\mbox{Monomial32}&:& ({\tt CMO\_MONOMIAL32}, {\sl int32}\, n,
{\sl int32}\, \mbox{e[1]}, \ldots,
{\sl int32}\, \mbox{e[n]}, \\
& & \ \mbox{Coefficient}) \\
& & \mbox{ --- e[i] で, $n$ 変数 monomial
$x^e = x_1^{e_1} \cdots x_n^{e_n}$ の各指数 $e_i$
をあらわす.} \\
\mbox{Coefficient}&:& \mbox{ZZ} | \mbox{Integer32} \\
\mbox{Dpolynomial}&:& \mbox{Zero} \\
& & |\ ({\tt CMO\_DISTRIBUTED\_POLYNOMIAL},{\sl int32} m, \\
& & \ \ \mbox{DringDefinition},
[\mbox{Monomial32}|\mbox{Zero}], \\
& &\ \
\{\mbox{Monomial32}\}) \\
& &\mbox{--- m はモノミアルの個数である.}\\
\mbox{DringDefinition}
&:& \mbox{DMS of N variables} \\
& & |\ \mbox{RingByName} \\
& & |\ \mbox{Generic DMS ring} \\
& & \mbox{ --- 分散表現多項式環の定義. } \\
\mbox{Generic DMS ring}
&:& ({\tt CMO\_DMS\_GENERIC})\ 新版はこちら\\
\mbox{RingByName}&:& ({\tt CMO\_RING\_BY\_NAME}, {\sl Cstring}\ {\rm s}) \\
& & \mbox{ --- 名前 s で, 格納された ring 定義.} \\
\mbox{DMS of N variables}
&:& ({\tt CMO\_DMS\_OF\_N\_VARIABLES}, \\
& & \ ({\tt CMO\_LIST}, {\sl int32}\, \mbox{m},
{\sl Integer32}\, \mbox{n}, {\sl Integer32}\,\mbox{p} \\
& & \ \ [,{\sl object}\,\mbox{s}, {\sl Cstring}\,\mbox{c},
{\sl List}\, \mbox{vlist},
{\sl List}\, \mbox{wvec}, {\sl List}\, \mbox{outord}]) \\
& & \mbox{ --- m はあとに続く要素の数} \\
& & \mbox{ --- n は変数の数, p は 標数} \\
& & \mbox{ --- s は ring の名前} \\
& & \mbox{ --- c は係数環, QQ, ZZ の場合は文字列で QQ, ZZ と書く.} \\
& & \mbox{ --- vlist は Indeterminate のリスト(新版). 多項式環の変数リスト} \\
& & \mbox{ --- wvec は order をきめる weight vector,} \\
& & \mbox{ --- outord は出力するときの変数順序.} \\
\end{eqnarray*}
RingByName や DMS of N variables はなくても, DMS を定義できる.
したがって, これらを実装してないシステムで DMS を扱うものが
あってもかまわない.
以下, 以上の CMObject にたいする,
xxx = asir, kan の振舞いを記述する.
\subsection{ Zero}
CMO では ゼロの表現法がなんとうりもあるが,
どのようなゼロをうけとっても,
システムのゼロに変換できるべきである.
(たとえば, asir は 0 はただ一つ.)
\subsection{ 整数 ZZ }
\begin{verbatim}
#define CMO_ZZ 20
\end{verbatim}
この節ではOpen xxx 規約における任意の大きさの整数(bignum)の扱いについて
説明する.
Open XM 規約における多重精度整数を表すデータ型 CMO\_ZZ は GNU MPライブ
ラリなどを参考にして設計されていて, 符号付き絶対値表現を用いている.
(cf. {\tt kan/sm1} の配布ディレクトリのなかの {\tt plugin/cmo-gmp.c})
CMO\_ZZ は次の形式をとる.\\
\begin{tabular}{|c|c|c|c|c|}
\hline
{\tt int32 CMO\_ZZ} & {\tt int32 $f$} & {\tt int32 $b_0$} & $\cdots$ &
{\tt int32 $b_{n}$} \\
\hline
\end{tabular} \\
$f$ は32bit整数である.
$b_0, \ldots, b_n$ は unsigned int32 である.
$|f|$ は $n+1$ である.
この CMO の符号は $f$ の符号で定める.
前述したように, 32bit整数の負数は 2 の補数表現で表される.
Open xxx 規約では上の CMO は以下の整数を意味する.
\[
\mbox{sgn}(f)\times (b_0 R^{0}+ b_1 R^{1} + \cdots + b_{n-1}R^{n-1} + b_n R^n).
\]
ここで $R = 2^{32}$ である.
{\tt int32} を network byte order で表現しているとすると,
例えば, 整数 $14$ は CMO\_ZZ で表わすと,
\[
\mbox{(CMO\_ZZ, 1, 0, 0, 0, e)},
\]
と表わす.
これはバイト列では
\[
\mbox{\tt 00 00 00 14 00 00 00 01 00 00 00 0e}
\]
となる.
なお ZZ の 0 ( (ZZ) 0 と書く ) は,
{\tt (CMO\_ZZ, 00,00,00,00)}
と表現する.
\subsection{ 分散表現多項式 Dpolynomial }
環とそれに属する多項式は次のような考えかたであつかう.
Generic DMS ring に属する元は,
変数を $n$ 個持つ 適当な係数集合 $K$ を持つ多項式環 $K[x_1, \ldots, x_n]$
の元である.
係数集合 $K$ がなにかは, 実際データを読み込み, Coefficient を見た段階で
わかる.
この環に属する多項式を CMO 形式でうけとった場合, 各サーバはその
サーバの対応する Object に変換しないといけない.
この変換の仕方は, 各サーバ毎にきめる.
Asir の場合は, $K[x_1, \ldots, x_n]$ の元は分散表現多項式に変換される.
\noroa{ でも, order はどうなるの? }
{\tt kan/sm1} の場合は事情は複雑である.
{\tt kan/sm1} は, Generic DMS ring にあたる クラスをもたない.
つまり, Default で存在する, $n$ 変数の分散表現多項式環は存在しないわけである.
したがって, {\tt kan/sm1} では, DMS of N variables が来た場合,
これを CurrentRing の元として読み込む. CurrentRing の変数の数が $n'$
で, $n' < n$ だと新しい多項式環を生成してデータを読み込む.
Order その他の optional 情報はすべて無視する.
DMS の 2 番目のフィールドで,
Ring by Name を用いた場合, 現在の名前空間で変数 yyy に格納された ring object
の元として, この多項式を変換しなさいという意味になる.
{\tt kan/sm1} の場合, 環の定義は ring object として格納されており,
この ring object を 変数 yyy で参照することにより CMO としてうけとった
多項式をこの ring の元として格納できる.
\medbreak \noindent
{\bf Example}:
(すべての数の表記は 16 進表記)
{\footnotesize \begin{verbatim}
Z/11Z [6 variables]
(kxx/cmotest.sm1) run
[(x,y) ring_of_polynomials ( ) elimination_order 11 ] define_ring ;
(3x^2 y). cmo /ff set ;
[(cmoLispLike) 1] extension ;
ff ::
Class.CMO CMO StandardEncoding: size = 52, size/sizeof(int) = 13,
tag=CMO_DISTRIBUTED_POLYNOMIAL
0 0 0 1f 0 0 0 1 0 0 0 18 0 0 0 13 0 0 0 6
0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 2 0 0 0 3
ff omc ::
(CMO_DISTRIBUTED_POLYNOMIAL[1f],[size=]1,(CMO_DMS_GENERIC[18],),
(CMO_MONOMIAL32[13],3*x^2*y),),
\end{verbatim} }
length は, monomial の数$+2$ である.
$ 3 x^2 y$ は 6 変数の多項式環の元としてみなされている.
%%Prog: (3x^2 y). cmosave ===> debug/cmodata1.cmo
%%\\ 反省: 分散多項式の定義で,
%%{\tt CMO\_LIST} でなく, {\tt CMO\_DMS} がはじめにくるべきだったのでは?
%%あたらしい 分散多項式の定義は次のようにすべき:
%% 修正済み. 1999, 9/13
\subsection{再帰表現多項式の定義}
\begin{verbatim}
#define CMO_RECURSIVE_POLYNOMIAL 27
#define CMO_POLYNOMIAL_IN_ONE_VARIABLE 33
\end{verbatim}
Group CMObject/RecursivePolynomial requires CMObject/Basic0, CMObject/Basic1.\\
Polynomial in 1 variable, Coefficient, Name of the main variable,
Recursive Polynomial, Ring definition for recursive polynomials
$\in$ CMObject/RecursivePolynomial \\
\begin{eqnarray*}
\mbox{Polynomial in 1 variable} &:&
\mbox{({\tt CMO\_POLYNOMIAL\_IN\_ONE\_VARIABLE},\, {\sl int32}\, m, } \\
& & \quad \mbox{ Name of the main variable }, \\
& & \quad \mbox{ \{ {\sl int32} e, Coefficient \}} \\
& & \mbox{ --- m はモノミアルの個数. } \\
& & \mbox{ --- e, Coefficieint はモノミアルを表現している. } \\
& & \mbox{ --- 順序の高い順にならべる. 普通は巾の高い順.} \\
& & \mbox{ --- e は 1変数多項式の巾をあらわす. } \\
\mbox{Coefficient} &:& \mbox{ ZZ} \,|\, \mbox{ QQ } \,|\,
\mbox{ integer32 } \,|\,
\mbox{ Polynomial in 1 variable } \\
& & \quad \,|\, \mbox{Tree} \,|\, \mbox{Zero} \,|\,\mbox{Dpolynomial}\\
\mbox{Name of the main variable } &:&
\mbox{ {\sl int32} v } \\
& & \mbox{ --- v は 変数番号 (0 からはじまる) を表す. } \\
\mbox{Recursive Polynomial} &:&
\mbox{ ( {\tt CMO\_RECURSIVE\_POLYNOMIAL}, } \\
& & \quad \mbox{ Ring definition for
recursive polynomials, } \\
& & \quad
\mbox{ Polynomial in 1 variable}\, | \, \mbox{Coefficient} \\
\mbox{Ring definition for recursive polynomials }
& : & \mbox{ {\sl List} v } \\
& & \quad \mbox{ --- v は, 変数名(indeterminate) のリスト. } \\
& & \quad \mbox{ --- 順序の高い順. } \\
\end{eqnarray*}
\bigbreak
\noindent
実例:
\begin{verbatim}
(CMO_RECURSIEVE_POLYNOMIAL, ("x","y"),
(CMO_POLYNOMIAL_IN_ONE_VARIABLE, 2, 0, <--- "x"
3, (CMO_POLYNOMIAL_IN_ONE_VARIABLE, 2, 1, <--- "y"
5, 1234,
0, 17),
1, (CMO_POLYNOMIAL_IN_ONE_VARIABLE, 2, 1, <--- "y"
10, 1,
5, 31)))
\end{verbatim}
これは,
$$ x^3 (1234 y^5 + 17 ) + x^1 (y^10 + 31 y^5) $$
をあらわす.
非可換多項式もこの形式であらわしたいので, 積の順序を上のように
すること. つまり, 主変数かける係数の順番.
\noindent
\begin{verbatim}
sm1
sm1>(x^2-h). [(class) (recursivePolynomial)] dc /ff set ;
sm1>ff ::
Class.recursivePolynomial h * ((-1)) + (x^2 * (1))
\end{verbatim}
int32 と Integer32 の違い.
次にくるデータがかならず int32 とわかっておれば,
int32 を用いる.
次のデータ型がわからないとき Integer32 を用いる.
\subsection{CPU依存の double }
\begin{verbatim}
#define CMO_64BIT_MACHINE_DOUBLE 40
#define CMO_ARRAY_OF_64BIT_MACHINE_DOUBLE 41
#define CMO_128BIT_MACHINE_DOUBLE 42
#define CMO_ARRAY_OF_128BIT_MACHINE_DOUBLE 43
\end{verbatim}
\noindent
Group CMObject/MachineDouble requires CMObject/Basic0.\\
64bit machine double, Array of 64bit machine double
128bit machine double, Array of 128bit machine double
$\in$ CMObject/MachineDouble \\
\begin{eqnarray*}
\mbox{64bit machine double} &:&
\mbox{({\tt CMO\_64BIT\_MACHINE\_DOUBLE}, } \\
& & \quad \mbox{ {\sl byte} s1 , \ldots , {\sl byte}} s8)\\
& & \mbox{ --- s1, $\ldots$, s8 は {\tt double} (64bit). } \\
& & \mbox{ --- この表現はCPU依存である.}\\
&& \mbox{\quad\quad mathcap に CPU 情報を付加しておく.} \\
\mbox{Array of 64bit machine double} &:&
\mbox{({\tt CMO\_ARRAY\_OF\_64BIT\_MACHINE\_DOUBLE}, {\sl int32} m, } \\
& & \quad \mbox{ {\sl byte} s1[1] , \ldots , {\sl byte}}\, s8[1], \ldots , {\sl byte}\, s8[m])\\
& & \mbox{ --- s*[1], $\ldots$ s*[m] は m 個の double (64bit) である. } \\
& & \mbox{ --- この表現はCPU依存である.}\\
& & \mbox{ \quad\quad mathcap に CPU 情報を付加しておく.} \\
\mbox{128bit machine double} &:&
\mbox{({\tt CMO\_128BIT\_MACHINE\_DOUBLE}, } \\
& & \quad \mbox{ {\sl byte} s1 , \ldots , {\sl byte}} s16)\\
& & \mbox{ --- s1, $\ldots$, s16 は {\tt long double} (128bit). } \\
& & \mbox{ --- この表現はCPU依存である.}\\
&& \mbox{\quad\quad mathcap に CPU 情報を付加しておく.} \\
\mbox{Array of 128bit machine double} &:&
\mbox{({\tt CMO\_ARRAY\_OF\_128BIT\_MACHINE\_DOUBLE}, {\sl int32} m, } \\
& & \quad \mbox{ {\sl byte} s1[1] , \ldots , {\sl byte}} s16[1], \ldots , {\sl byte} s16[m])\\
& & \mbox{ --- s*[1], $\ldots$ s*[m] は m 個の long double (128bit) である. } \\
& & \mbox{ --- この表現はCPU依存である.}\\
& & \mbox{ \quad\quad mathcap に CPU 情報を付加しておく.}
\end{eqnarray*}
\bigbreak
次に IEEE 準拠の float および Big float を定義しよう.
\begin{verbatim}
#define CMO_BIGFLOAT 50
#define CMO_IEEE_DOUBLE_FLOAT 51
\end{verbatim}
IEEE 準拠の float については,
IEEE 754 double precision floating-point format
(64 bit) の定義を見よ.
\noindent
Group CMObject/Bigfloat requires CMObject/Basic0, CMObject/Basic1.\\
Bigfloat
$\in$ CMObject/Bigfloat \\
\begin{eqnarray*}
\mbox{Bigfloat} &:&
\mbox{({\tt CMO\_BIGFLOAT}, } \\
& & \quad \mbox{ {\sl ZZ} a , {\sl ZZ} e})\\
& & \mbox{ --- $a \times 2^e$ をあらわす. } \\
\end{eqnarray*}
\section{ OX Local Data }
システム固有の Object の内部表現は,
\begin{verbatim}
#define OX_LOCAL_OBJECT 0x7fcdef30
\end{verbatim}
より増えていく数でタグづけする.
0x200000 の領域をわりふることとする.
タグはシステムごとに割り振る.
\begin{verbatim}
#define OX_LOCAL_OBJECT_ASIR (OX_LOCAL_OBJECT+0)
#define OX_LOCAL_OBJECT_SM1 (OX_LOCAL_OBJECT+1)
\end{verbatim}
これらは, {\tt OX\_DATA} の代わりとして使用できる.
\section{ CMO ERROR2 }
エラー番号 (共通番号)
\begin{verbatim}
#define Broken_cmo 1
#define mathcap_violation 2
\end{verbatim}
\section{メンバの再定義に関する注意}
われわれは,
Coefficient を Group DistributedPolynomials の メンバとして定義した.
これを新しい group のメンバーとして定義を拡張することができる.
たとえば, Coefficient を, 再帰表現多項式のメンバとしても定義できる.
この場合副作用として, DistributedPolynomials のメンバとしての Coeffients
の意味も拡張される.
システムがそのあたらしい DistributedPolynomials をすくなくとも CMO としては
理解できないといけないが, それを実際にそのシステムのローカルな Object に
変換できるかはシステム依存である.
このような再定義をゆるすのは, 一般的な実装法がやはりこのような仕組みだから
である.
mathcap にデータ転送の保護機能はこのような再帰的表現もチェックできないと
いけない.
\section{ 実装, デバッグ, 検証 }
\subsection{ 実装の手順 }
ソフト 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 の開p発が沼津の富士フォーラムでおこなわれていた
ころ, 私が沼津を, 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 Basic0 の機能を
1997, 5 月, 6 月に実現した.
その後, 1997年 7 月に, SMObject/Basic1 の実装,
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 }
Basic0 のスタックマシンのソケットによる実装.
スタックマシンは {\tt nullstackmachine.c} に実装されており,
{\tt oxserver00.c} にリンクしてサーバとなる.
サンプルサーバであり, これに CMO Basic0 仕様の関数を結合すれば,
一応 サーバが動作するはずである.
スタックには,CMO の Basic0 の 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 サーバをすべて書いてみるか?
\section{ どのように協調機能にすぐれた Math Soft を書くのか? }
いくつかの経験的なプログラム作法をメモとしてまとめておく.
\begin{enumerate}
\item 文字列を読み込み, 計算して, また文字列を結果として出力する
プログラムおよび関数は協調機能にすぐれたプログラムの基本である.
グラフィカルインターフェースのみのプログラムは他のソフトと協調
させるのがむずかしい.
\item Output を読むのは人間とは限らない.
Output の読者は, 他のソフトかもしれない.
したがって, Output もやはり, 文法にしたがって出力すべきである.
エラー出力も文法にしたがうべきである.
\end{enumerate}
\subsection{open gnuplot の実装}
書いてない.
\subsection{open phc の実装}
書いてない.
\subsection{open M2 の実装}
書いてない.
この節の補足は,
{\tt this/open/ohp} を見よ (Open XM day, 1999, 7/12 Mon の原稿)
\section{ 新しい CMO の登録 }
\subsection{新しい CMO を作るときの約束}
CMO では, 再帰的なデータ表現をゆるしているので,
Object を増やした場合, もとからある CMO の動作も拡張される.
そのシステムが正しく動作するのか確認する必要がある.
計算することはできなくても, 通信の中断なしに,
データの受渡しをできないといけない.
\subsection{Open XM プロジェクトに参加するには?}
Open XM にパッケージを加えてくれるのは大歓迎です.
takayama@math.kobe-u.ac.jpに連絡下さい.
新しい CMO を必要なら加えて下さい.
加えた場合は
\begin{enumerate}
\item 定義した CMObject の形式的な定義と説明.
\item システム xxx が, この CMObject に関してどのように振舞うかの説明.
\item この CMObject, システム xxx に関する URL.
\end{enumerate}
をおくって下さい.
必要ならディスカッションをおこない, 確定版の仕様を作成し, 確定した段階で
CMO のタグを発行し, この CMObject に関連する URL を
Open XM ホームページ \cite{openxxx} よりリンクします.
\section{Appendix: English translation}
\noindent
(This section has not been updated.)
\subsection{Common Mathematical Object format}
\begin{verbatim}
#define LARGEID 0x7f000000
#define CMO_ERROR2 (LARGEID+2)
#define CMO_NULL 1
#define CMO_INT32 2
#define CMO_DATUM 3
#define CMO_STRING 4
#define CMO_LIST 17
\end{verbatim}
\bigbreak
\noindent
Group CMObject/Basic0 requires nothing. \\
Error2, Null, Integer32, Datum, Cstring, List $\in$ CMObject/Basic0. \\
Document of CMObject/Basic0 is at {\tt http://www.math.kobe-u.ac.jp/openxxx}
(in Japanese) \\
\begin{eqnarray*}
\mbox{Error2}&:& ({\tt CMO\_ERROR2}, {\sl CMObject}\, \mbox{ob}) \\
\mbox{Null} &:& ({\tt CMO\_NULL}) \\
\mbox{Integer32}
&:& ({\tt CMO\_INT32}, {\sl int32}\ \mbox{n}) \\
\mbox{Datum} &:& ({\tt CMO\_DATUM}, {\sl int32}\, \mbox{n}, {\sl byte}\,
\mbox{data[0]},
\ldots , {\sl byte}\, \mbox{data[n-1]}) \\
\mbox{Cstring}&:& ({\tt CMO\_STRING},{\sl int32}\, \mbox{n},
{\sl string}\, \mbox{s}) \\
\mbox{List} &:&
\mbox{({\tt CMO\_LIST}, {\sl int32}\, m, {\sl CMObject}\, ob[1], $\ldots$,
{\sl CMObject}\, ob[m])} \\
& & \mbox{--- m is the length of the list.} \\
\end{eqnarray*}
In the definition of ``Cstring'', if we decompose ``{\sl string} s'' into
bytes, then ``Cstring'' should be defined as
\begin{eqnarray*}
\mbox{Cstring}&:& ({\tt CMO\_STRING},{\sl int32}\, n,
{\sl byte}\, \mbox{s[0]},
\ldots, {\sl byte}\ \mbox{s[n-1]})
\end{eqnarray*}
\noindent
Example:
\begin{center}
({\tt CMO\_INT32}, 1234)
\end{center}
Example:
\begin{center}
({\tt CMO\_STRING}, 5, "Hello")
\end{center}
\begin{verbatim}
#define CMO_MONOMIAL32 19
#define CMO_ZZ 20
#define CMO_QQ 21
#define CMO_ZERO 22
#define CMO_DMS 23 /* Distributed monomial system */
#define CMO_DMS_GENERIC 24
#define CMO_DMS_OF_N_VARIABLES 25
#define CMO_RING_BY_NAME 26
\end{verbatim}
\bigbreak
\noindent
Group CMObject/Basic1 requires CMObject/Basic0. \\
ZZ, QQ, Zero $\in$ CMObject/Basic1. \\
\begin{eqnarray*}
\mbox{Zero} &:& ({\tt CMO\_ZERO}) \\
& & \mbox{ --- universal zero } \\
\mbox{ZZ} &:& ({\tt CMO\_ZZ},{\sl int32}\, f, {\sl byte}\, \mbox{a[1]}, \ldots
{\sl byte}\, \mbox{a[m]} ) \\
&:& \mbox{ --- bignum }\\
\mbox{QQ} &:& ({\tt CMO\_QQ}, {\sl ZZ}\, a, {\sl ZZ}\, b) \\
& & \mbox{ --- rational number $a/b$. } \\
\end{eqnarray*}
\bigbreak
Let us define a group for distributed polynomials.
\medbreak
\noindent
Group CMObject/DistributedPolynomials requires CMObject/Basic0,
CMObject/Basic1. \\
Monomial, Monomial32, Coefficient, Dpolynomial, DringDefinition,
Generic DMS ring, RingByName, DMS of N variables $\in$
CMObject/DistributedPolynomials. \\
\begin{eqnarray*}
\mbox{Monomial} &:& \mbox{Monomial32}\, |\, \mbox{Zero} \\
\mbox{Monomial32}&:& ({\tt CMO\_MONOMIAL32}, {\sl int32}\, n,
{\sl int32}\, \mbox{e[1]}, \ldots,
{\sl int32}\, \mbox{e[n]}, \\
& & \ \mbox{Coefficient}) \\
& & \mbox{ --- e[i] is the exponent $e_i$ of the monomial
$x^e = x_1^{e_1} \cdots x_n^{e_n}$. } \\
\mbox{Coefficient}&:& \mbox{ZZ} | \mbox{Integer32} \\
\mbox{Dpolynomial}&:& \mbox{Zero} \\
& & |\ ({\tt CMO\_LIST},{\sl int32} m, \\
& & \ \ {\tt CMO\_DMS}, \mbox{DringDefinition},
[\mbox{Monomial32}|\mbox{Zero}], \\
& &\ \
\{\mbox{Monomial32}\}) \\
& &\mbox{--- Distributed polynomial is a sum of monomials}\\
& &\mbox{--- m is equal to the number of monomials $+2$.}\\
\mbox{DringDefinition}
&:& \mbox{DMS of N variables} \\
& & |\ \mbox{RingByName} \\
& & |\ \mbox{Generic DMS ring} \\
& & \mbox{ --- definition of the ring of distributed polynomials. } \\
\mbox{Generic DMS ring}
&:& ({\tt CMO\_INT32, CMO\_DMS\_GENERIC}) \\
\mbox{RingByName}&:& ({\tt CMO\_RING\_BY\_NAME}, {\sl Cstring} s) \\
& & \mbox{ --- The ring definition refered by the name ``s''.} \\
\mbox{DMS of N variables}
&:& ({\tt CMO\_DMS\_OF\_N\_VARIABLES}, \\
& & \ ({\tt CMO\_LIST}, {\sl int32}\, \mbox{m},
{\sl Integer32}\, \mbox{n}, {\sl Integer32}\,\mbox{p} \\
& & \ \ [,{\sl Cstring}\,\mbox{s}, {\sl List}\, \mbox{vlist},
{\sl List}\, \mbox{wvec}, {\sl List}\, \mbox{outord}]) \\
& & \mbox{ --- m is the number of elements.} \\
& & \mbox{ --- n is the number of variables, p is the characteristic} \\
& & \mbox{ --- s is the name of the ring, vlist is the list of variables.} \\
& & \mbox{ --- wvec is the weight vector.} \\
& & \mbox{ --- outord is the order of variables to output.} \\
\end{eqnarray*}
\subsection{ Stackmachine commands}
\begin{verbatim}
#define SM_popSerializedLocalObject 258
#define SM_popCMO 262
#define SM_popString 263
#define SM_mathcap 264
#define SM_pops 265
#define SM_setName 266
#define SM_evalName 267
#define SM_executeStringByLocalParser 268
#define SM_executeFunction 269
#define SM_beginBlock 270
#define SM_endBlock 271
#define SM_shutdown 272
#define SM_control_kill 1024
#define SM_control_reset_connection 1030
\end{verbatim}
\subsection{OX messages}
Top level messages are OX messages.
These messages start with one of the following tags.
\begin{verbatim}
#define OX_COMMAND 513 // for stackmachine commands
#define OX_DATA 514 // for CMO
#define OX_SECURED_DATA 521
#define OX_SYNC_BALL 515
\end{verbatim}
\noindent
Example:
\begin{center}
(OX\_COMMAND, SM\_popCMO)
\end{center}
\noindent
Example:
\begin{center}
(OX\_DATA, ({\tt CMO\_STRING}, 5, "Hello"))
\end{center}
*/
/*&jp
\section{ OX サーバに対する C ライブラリインタフェース }
一部のOX サーバでは C のライブラリとしてリンクして使用するもできる.
ライブラリとして使用するための C の関数は
Asir の OX サーバ用クライアント関数に似たインタフェースを持つ.
ライブラリ関数には, CMO を binary encoding して渡す.
ライブラリ関数からは, CMO が binary encoded form で戻る.
*/
/*&eg
\section{ OX servers as a C library}
In some OX servers, one can use the OX server as a C library.
The interface functions of the C library
are similar to Asir OX client functions such as
\verb+ ox_push_cmo() +, \verb+ ox_pop_cmo() +.
CMO should be in the binary encoded form to call these functions.
*/
/*&C
\medbreak
\begin{verbatim}
int xxx_ox_byte_order(int type)
\end{verbatim}
*/
/*&eg
Specify the byte order to send int32 to the OX server xxx.
When type = 0, the network byte order will be used.
In case of error, -1 will be returned.
*/
/*&jp
OX サーバ xxx へ int32 を送るための byte order を type で指定する.
ライブラリではあるが,
type = 0 で, network byte order を使用できないといけない??
失敗した場合, -1 を戻す.
*/
/*&C
\smallskip
\begin{verbatim}
void xxx_ox_push_cmo(void *cmo, int size)
\end{verbatim}
*/
/*&eg
Push the binary encoded CMO {\tt cmo} of the size {\tt size}
onto the stack of the OX server xxx.
*/
/*&jp
Binary encoded された CMO (サイズは size) を, OX サーバ xxx
の stack に push する.
*/
/*&C
\smallskip
\begin{verbatim}
int xxx_ox_pop_cmo(void *cmo, int limit)
\end{verbatim}
*/
/*&eg
Pop a binary encoded CMO from the OX server xxx
and write it at {\tt cmo}.
The return value is the size of the CMO in bytes.
In case of the stack underflow, the return value is 0.
If the size exceeds the {\tt limit}, -1 will be returned
and the CMO is not popped and will not be written to {\tt cmo}.
*/
/*&jp
Binary encoded された CMO (サイズは size) を, OX サーバより
pop して, cmo に書き込む.
戻り値は CMO のサイズを byte で戻す.
Stack underflow の場合の戻り値は 0 である.
ただし, limit より大きいサイズの CMO は書き込まれない.
この場合, 戻り値は -1 となる.
*/
/*&C
\smallskip
\begin{verbatim}
int xxx_ox_peek_cmo_size()
\end{verbatim}
*/
/*&eg
Return the size of the CMO at the top of the stack.
*/
/*&C
\smallskip
\begin{verbatim}
int xxx_ox_peek_cmo_size()
\end{verbatim}
*/
/*&jp
stack の一番上にある CMO のサイズを byte で戻す.
( ライブラリ版特有 )
*/
/*&C
\smallbreak
\begin{verbatim}
ox_push_cmd(), ox_execute_string()
\end{verbatim}
*/
/*&eg
These functions have the same specification with those
in Asir client functions. See Asir document.
Numbers should be given in int 32 and strings should be given
by char *
*/
/*&jp
については, Asir クライアントと同じインタフェース.
数は int32 で, 文字列は char * で.
*/
/*&C
\begin{thebibliography}{99}
\bibitem{openmath} {\tt http://www.openmath.org}
\bibitem{openxxx} {\tt http://www.math.kobe-u.ac.jp/OpenXM/ (under construction)}
\bibitem{openasir-intro} Ohara, Takayama, Noro: Introduction to Open Asir ,
1999, (in Japanese),
Suushiki-Shyori, Vol 7, No 2, 2--17. (ISBN4-87243-086-7, SEG , Tokyo). \\
{\tt http://www.math.kobe-u.ac.jp/OpenXM/}
\end{thebibliography}
*/
/*&C
\bigbreak
\bigbreak
\bigbreak
\small{
\noindent
\rightline{ Masayuki Noro,}
\rightline{ Fujitsu Laboratory, Kawasaki, Japan;}
\rightline{{\tt noro@para.flab.fujitsu.co.jp}}
\vskip .5cm
\noindent
\rightline{ Nobuki Takayama,}
\rightline{Department of Mathematics, Kobe University,
Rokko, Kobe, 657-8501, Japan;}
\rightline{{\tt takayama@math.kobe-u.ac.jp}}
}
\end{document}
*/