os muldif
大島 利雄

August 28, 2024

目次
1

List of Functions
1.1 Functions related to diﬀerential operators . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1.1
Fundamental functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1.2
Fractional calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1.3
Some operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Useful functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.1
Extended function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.2
Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.3
Polynomials and rational functions . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.4
Functions with real/complex variables . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.5
Lists and vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.6
Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.7
Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.8
Permutations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.9
TEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.10Lines and curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.11
Drawing curves and graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.12
Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.13
Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5
5
5
6
8
9
9
11
13
15
16
19
20
21
22
23
24
25
26

2

Risa/Asir
2.1 Risa および Asir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Asir の特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 コマンドラインオプション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4 環境変数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.5 起動から終了まで . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6 割り込み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7 エラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.8 計算結果，特殊な数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9 型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9.1
Asir で使用可能な型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9.2
数の型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9.3
不定元の型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10 ユーザ言語 Asir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.1
文法（C 言語との違い） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.2
ユーザ定義函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27
27
27
28
28
28
29
30
30
31
31
33
34
35
35
36

1

2.10.3
変数および不定元 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.4
引数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.5
コメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.6
文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.7
return 文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.8
if 文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.9ループ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.10構造体定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.11さまざまな式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.12
プリプロセッサ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.13
オプション指定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.11 モジュール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.12 デバッガ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.12.1
デバッガとは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.12.2
コマンドの解説 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.12.3
デバッガの使用例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.12.4
デバッガの初期化ファイルの例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.12.5
文法の詳細 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.13 有限体における演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.13.1
有限体の表現および演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.13.2有限体上での 1 変数多項式環の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.13.3
小標数有限体上での多項式環の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.13.4有限体上の楕円曲線に関する演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14 代数的数に関する演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14.1
代数的数の表現 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14.2分散多項式による代数的数の表現 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14.3代数的数の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14.4代数体上での 1 変数多項式の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14.4.1
GCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14.4.2
無平方分解，因数分解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
最小分解体 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14.4.3
2.15 グレブナー基底の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.1
分散表現多項式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.2
ファイルの読み込み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.3
基本的な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.4計算および表示の制御 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.5
項順序の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.6Weight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.7
有理式を係数とするグレブナ基底 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.8基底変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15.9Weyl 代数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16 分散計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16.1OpenXM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16.2
Mathcap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16.3
スタックマシンコマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16.4デバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16.4.1
エラーオブジェクト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16.4.2
リセット . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16.4.3
デバッグ用ポップアウトウインドウ . . . . . . . . . . . . . . . . . . . . . . . . .

2

37
38
38
39
39
40
40
41
41
42
43
45
47
47
47
49
50
50
53
53
54
54
54
55
55
56
57
58
58
59
59
60
60
60
60
61
63
64
65
65
66
66
66
67
67
68
68
69
69

2.17 Asir-Contrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.17.1
はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.17.2
Asir/Contrib のロード方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.17.3Asir Contrib の函数名について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.17.4
Windows 版 Asir-Contrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.18 Risa/Asir と os muldif.rr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.18.1
os muldif.rr のインストール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3

69
69
69
70
70
71
72

Functions74
3.1 Functions related to diﬀerential operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.1.1
Fundamental functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.1.2
Fractional calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
3.1.3
Some operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
3.2 Useful functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
3.2.1
Extended function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
3.2.2
Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
3.2.3
Polynomials and rational functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
3.2.4
Functions with real/complex variables . . . . . . . . . . . . . . . . . . . . . . . . . . 227
3.2.5
Lists and vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
3.2.6
Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
3.2.7
Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
3.2.8
Permutations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
3.2.9
TEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
3.2.10Lines and curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
3.2.11
Drawing curves and graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
3.2.12
Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
3.2.12.1
表の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
3.2.12.2
表や行列の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
3.2.12.3函数値の数表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
3.2.12.4
点数分布表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
3.2.12.5
Table of score distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
3.2.12.6
計算尺 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
3.2.13
Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
3.2.14
補足 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
3.2.14.1
行列の入力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
3.2.14.2
平面図形 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
3.2.14.3
リスト形式函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
3.2.14.4
実数値／複素数値函数の解析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
3.2.14.5
表形式データ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
3.2.14.6
有限集合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
3.2.14.7
次のベクトルやリスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
3.3 Functions in the original library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
3.3.1
数の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
3.3.2
多項式，有理式の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
3.3.3
リスト，ベクトル，配列の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
3.3.4
行列の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
3.3.5
文字列に関する演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
3.3.6
構造体に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
3.3.7
入出力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438

3

3.3.8型や函数，モジュールに関わる函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
3.3.9数値函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
3.3.10
描画函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
3.3.11
有限体に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
3.3.12
代数的数に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
3.3.13
グレブナー基底に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
3.3.14
分散計算に関する関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
3.3.15
その他の函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
3.4 Functions in the contributed library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
3.4.1
基礎 (標準函数) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
3.4.2
数（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 492
3.4.3
行列（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
3.4.4
表示（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4953.4.5多項式（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
3.4.6
グラフィックライブラリ（2 次元） . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501
3.4.7
OpenXM-Conrib 一般函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
3.4.8
OXShell の関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
3.4.9
OpenMath 函数 (1999 版) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
3.4.10Diﬀerential equations (by Okutani) . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
3.4.11
D-module (by Okutani) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506
3.4.12DSOLV 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
3.4.13
GNUPLOT 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
3.4.14p Fq に関するコホモロジー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
3.4.15
PHC 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
3.4.16
Plucker 関係式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
3.4.17
SM1 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
3.4.18
TIGERS 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
3.4.19Mathematica 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
3.4.20
便利な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 528
3.4.21
その他 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
索引

531

4

os_muldif.rr for Risa/Asir
A library for computing (ordinary/partial) diﬀerential operators
by Toshio Oshima

1 List of Functions
1.1 Functions related to diﬀerential operators
以下の関数はモジュール化されているので，先頭に os_md. を付加して，os_md.muldo() のように呼び出す．

1.1.1 Fundamental functions
1. muldo(p1 ,p2 ,[x,∂x ]|lim=n) または muldo(p1 ,p2 ,x|lim=n)muldo(p1 ,p2 ,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]|lim=n):: 有理函数（初等函数でもよい）係数の常（または偏）微分作用素（の行列）の積 (⇐ [∂x , x] = 1)
2. caldo([p1 ,p2 ,. . .],[x,∂x ]|mono=f ) or caldo([p1 ,p2 ,. . .],[[x1 ,∂x1 ],. . .]|mono=f ):: 微分作用素の積の和を計算する
3. muledo(p1 ,p2 ,[x,∂x ]) or muledo(p1 ,p2 ,x):: Euler 型常微分作用素（の行列）の積 (⇐ [∂x , x] = x)
4. transpdo(p,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .],[[y1 ,∂y1 ],[y2 ,∂y2 ],. . .]|ex=1,inv=f )P:: 微分作用素の変換（xi 7→ yi = yi (x), ∂xj 7→ ∂yj = cj (x) + ν ajν (x)∂xν ）5. translpdo(p,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .],mat)P:: 微分作用素の線形座標変換（xi 7→ j (mat)ij xj ）6. transppow([[x1 ,∂x1 ],. . .,[xn ,∂xn ]],m):: ベキ函数による座標変換での変換公式
7. appldo(p,r,[x,∂x ]|Pfaff=1) or appldo(p,r,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]):: 微分作用素（の行列）の有理式，初等函数（の行列），Pfaﬀ 系への作用の計算
8. adj(p,[x,∂x ]) または adj(p,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]):: 微分作用素（の行列） p の formal adjoint
9. psymbol(p,,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]):: principal symbol of diﬀerential operator
10. sftpexp(p,[x,∂x ],q,r) or sftpexp(p,[[x1 ,∂x1 ],. . .],q,r]):: 微分作用素 p を q −r ◦ p ◦ q r と変換する
11. appledo(p,r,[x,∂x ]):: Euler 型常微分作用素の有理式への作用の計算
12. divdo(p1 ,p2 ,[x,∂x ]|rev=1):: 常微分作用素の割り算
13. mygcd(p1 ,p2 ,[x, ∂x ]|rev=1,dviout=n) or mygcd(p1 ,p2 ,[x]|rev=1,dviout=n)
mygcd(p1 ,p2 ,x|dviout=n), mygcd(p1 ,p2 ,0|dviout=n):: 有理函数係数の常微分作用素（または x の多項式，または正整数）p1 と p2 の GCD（最大公約元）
14. mylcm(p1 ,p2 ,[x, ∂x ]|rev=1) or mylcm(p1 ,p2 ,[x]|rev=1)
mylcm(p1 ,p2 ,x), mylcm(p1 ,p2 ,0):: 有理函数係数の常微分作用素（または x の多項式，または正整数）p1 と p2 の LCM（最小公倍元）
15. m1div(m,n,[x,∂x ]) or m1div(m,n,[x]) or m1div(m,n,x):: 有理函数係数の常微分作用素（or x の多項式）の正方行列 m と有理式（or x を含まない有理式）の正方行列 n に対し，m = R[1](∂x −n)+R[0]（or m = R[1](x−n)+R[0]）となるリスト R = [R[0], R[1]]を返す．

16. qdo(p1 ,p2 ,[x,∂x ]):: 常微分方程式 p1 u = 0 に対し q1 p2 u = 0 となる微分作用素 q1 と q2 p2 u = u となる微分作用素 q2 の5

リスト [q1 , q2 ] を返す
17. mdivisor(m,[x,∂]|trans=1,step=1,dviout=t)
mdivisor(m,x|trans=1,step=1,dviout=t), mdivisor(m,0|trans=1,step=1,dviout=t):: 有理函数係数の常微分作用素/1 変数多項式や整数の行列の単因子を得る
18. sqrtdo(p,[x,∂x ]) ?
√:: x 7→ 1/x で（x のべき倍を除いて）不変な微分作用素 p に対する変数変換 x 7→ y = x + x2 − 1
19. toeul(p,[x,∂x ],n):: （Fuchs 型）常微分作用素を x = n で Euler 型に変換
20. fromeul(p,[x,px ],n):: Euler 型常微分作用素を元に戻す（toeul(p, [x, ∂x ], n) の逆変換）
21. expat(p,[x,∂x ],n):: 確定特異点型常微分作用素の x = n での特性指数を求める
22. sftexp(p,[x,∂x ],n,r):: 常微分作用素 p を (x − n)−r ◦ p ◦ (x − n)r に変換する
23. fractrans(p,[x,∂x ],n0 ,n1 ,n2 ):: 常微分作用素 p に x の一次分数変換 (n0 , n1 , n2 ) 7→ (0, 1, ∞) を行う
24. chkexp(p,[x, ∂x ],n,r,m):: j = 0, . . . , m − 1 の全てに対し，確定特異点型常微分作用素 p の解 uj で (x − n)−(r+j) uj が x = nで正則でそこでの値が 1 となるものの存在条件
25. soldif(p,[x, ∂x ],n,q,m)P∞:: 常微分作用素 p の x = n の近傍での z q (1 + j=1 cj z j ) の形の形式解に対し，長さ m + 1 のベク
トル [1 c1 c2 · · · cm ] を返す（z = x − n）．
26. okuboetos(p, [x, ∂x ]| diag=[c1 , c2 , . . . ]):: 単独 Okubo 型方程式 pu = 0 を Okubo 型の 1 階のシステムに変換する
27. stoe(p,[x, dx],m):: 1 階の線型常微分方程式系を単独高階に直す
28. etos(p,[x, dx],m):: 単独高階線型常微分方程式を 1 階系に直す
29. dform(ℓ, x|dif=1)
P
P:: 変数 x[0], x[1], . . . の 1 次微分形式ℓ[i][0]d(ℓ[i][1]), または 2 次微分形式ℓ[i][0]d(ℓ[i][1]) ∧d(ℓ[i][2]) の計算．dif=1 は 1 次微分形式の外微分の計算．
30. solpokubo(p,[x, ∂x ],n):: 単独 Okubo 型常微分作用素 p の n 次の固有多項式と固有値を求める
31. getSSE(p,[x,y,. . . ]|get=s):: Get singularities, rank,... of holonomic systems deﬁned by the ideal p etc.

1.1.2 Fractional calculus
この項は，[O3]，[O5], [O7], [O9], [O10] などの主要結果（基本的部分は [O2] で解説）を Risa/Asir 上で実現したものとなっている．

32. laplace(p,[x, ∂x ]) or laplace(p,[[x1 , ∂x1 ],[x2 , ∂x2 ], . . . ]):: 微分作用素 p の（部分）Laplace 変換
33. laplace1(p,[x, ∂x ]) or laplace1(p,[[x1 , ∂x1 ],[x2 , ∂x2 ], . . . ]):: 微分作用素 p の（部分）逆 Laplace 変換
34. mc(p,[x, ∂x ],r):: 常微分作用素 p の middle convolution mcr (p)35. mce(p,[x, ∂x ],n,r):: 常微分作用素 p を (∂x − n)−r ◦ p ◦ (∂x − n)r と変換
36. rede(p,[x, ∂x ]) or rede(p,[[x1 , ∂x1 ],[x2 , ∂x2 ], . . . ]):: 部分作用素 p の reduced representative を返す

6

37. ad(p,[x, ∂x ],f ):: 常微分作用素 p の ∂x を ∂x − f に置き換える変換
38. add(p,[x, ∂x ],f ):: 常微分作用素 p の ∂x を ∂x − f に置き換える addition，すなわち rede(ad())
39. vadd(p,[x, ∂x ],[[c0 , r0 ],[c1 , r1 ], . . . ])P
rj x j:: Versal addition add(p,[x, ∂x ], j≥0 ∏j (1−c
)
ν x)
ν=0
40. addl(p,[x, ∂x ],f ):: 常微分作用素の addition の Laplace 変換 laplace1(add(laplace()))
41. cotr(p,[x, ∂x ],f ):: 常微分作用素 p の x 7→ f (x) による座標変換
42. rcotr(p,[x, ∂x ],f ):: 常微分作用素 p の x 7→ f (x) による座標変換の reduced representative
43. s2sp(p|num=1,std=k,short=1):: スペクトル型を表す文字列と “数のリストのリスト”との変換
44. s2csp(p|n=f ):: 不分岐合流スペクトル型を表す文字列と “数のリストによる表現”との変換
45. chkspt(m|mat=1,dumb=1) または chkspt(m|opt=t,dumb=1) または fspt(m,t):: 分割の組 m（スペクトルタイプ）または generalized Riemann scheme（GRS）をチェックして[pts, ord, idx, f uchs, rod, redsp, f spt] を返す
opt="sp", "basic", "construct", "strip", "short", "long", "sort", "idx"
46. spgen(n|eq=1,str=1,std=f ,pt=[k, ℓ],sp=m,basic=1):: 階数 n 以下の rigid な分割の組（あるいは与えられたものの軌道）を得る
n が 0 や負のときは，rigidity index が n の basic なものを得る．
47. sproot(p,t|dviout=1,only=k,sym=t,null=1):: スペクトル型を与えて構成やルートの情報を示す．t="base", "length", "type", "part", "pair","pairs", sp
48. spbasic(n,d|str=1,pt=[k,ℓ]):: d 階で rigidity index が n の fundamental スペクトル型のリストを返す
49. sp2grs(m,a,ℓ|mat=1):: spectral type から generalized Riemann scheme を生成する
50. ssubgrs (m, ℓ):: Generalized Riemann scheme m の ℓ に対する特性指数和51. mcgrs(m,[r1 , r2 , . . . , rn ]|mat=1,slm=[[k1 ,k2 ,. . .],m0 ]):: middle convolution と addition を順に generalized Riemann scheme や留数行列の和に施す
52. mcop(p,[r1 , r2 , . . . , rn ],[x, x1 , x2 , . . . ]):: middle convolution と addition を (偏）微分作用素 p に順に施していく
53. redgrs(m|mat=1):: 常微分作用素の generalized Riemann scheme の 1-step reduction
54. getbygrs(m,t|perm=ℓ,var=v,pt=[p1 , . . . ],mat=1) or
getbygrs(m,[t,s1 , s2 , . . . ]|perm=ℓ,var=v,pt=[p1 , . . . ],mat=1) :: generalized Riemann scheme(GRS) で定義される Fuchs 型常微分方程式の解析（GRS は短縮形またはスペクトルタイプでもよい）
t ="reduction", "construct", "connection", "operator", "series", "TeX", "Fuchs","basic", "", "All", "irreducible", "recurrence"s ="TeX", "dviout", "keep", "simplify", "short", "general", "operator","irreducible", "sft", "top0", "x1", "x2"ℓ は特異点の置換または互換（cf. mperm()），var は exponents の変数（cf. sp2grs()）, p1 , . . . は特異点の位置（∞ は除く）．
55. spslm(m,[k1 ,k2 ,. . .]):: rigid な常微分方程式の解の半局所モノドロミーを求める

7

56. shiftop(ℓ, s|zero=1,raw=k,all=t,dviout=1):: rigid なスペクトル型 ℓ と shift s から shift 作用素を求める
57. shiftPfaff(a,b,g,x,[µ1 ,µ2 ]):: Pfaﬀ 系の隣接関係式の middle convolution による変換
58. conf1sp(m|x2= ± 1,conf=0):: スペクトル型 m の微分作用素の Poincare rank 1 の合流過程を示す
59. pf2kz(m|all=1):: n 変数の Pfaﬀ 系 m を n + 2 変数の KZ 方程式に変換
60. confexp([[c0 ,f0 ],[c1 ,f1 ],...,[cm , fm ]]) confexp([[f1 ,. . .,fn ],[c1 ,. . .,cm ]]|sym=k]):: 特性指数の合流を返す
61. mcvm(n|var=x,z=1,get=g) mcvm([n1 ,n2 , . . .]|var=[a,b, . . . ],z=1,get=g)mcvm([r,k,i,j]|e=1,var=[a,b, . . . ]):: versal unfolding の middle convolution
62. anal2sp(m,l):: 同時スペクトル m の解析
63. mc2grs(g,r|top=0,dviout=k,div=ℓ,fig=s):: P1 内の 5 点の配置に対する KZ 型方程式の同時スペクトル g の変換
64. newKZmat(k,l|raw=f ,base=1,ext=1):: convolution of residue matrices of KZ equation
65. midKZ(l,b|raw=1,skip=m,kill=f ,dviout=1):: KZ 方程式の留数行列の middle convolution の対角化
66. mcfamily(i,j,[m1 , . . .],ℓ|mult=1,max=1,fix=[p1 , . . .],verb=1)h可換集合族の middle convolution
67. mcset(x,k,ℓ):: 集合の middle convolution
68. m2mc(ℓ,[a0 ,ay ,a1 ,c]|swap=1,small=1,simplify=0,MC=1)m2mc(ℓ,s|small=1,simplify=0,int=0,swap=t)d(x−y)d(x−1)d(y−1)dy:: Pfaﬀ 形式 du = (A0 dx
x +Ay x−y +A1 x−1 +B0 y +B1 y−1 )u の x 変数での addition+middle
convolution を求める（ℓ = [A0 , Ay , A1 , B0 , B1 ]）．
ℓ がスペクトル型や Riemann scheme のとき，上の後者では s ="GRC", "GRSC", "extend", "Pfaff","sp", "pairs", "irreducible", "All", "swap"
69. mcmgrs(g,r|dviout=k):: P1 内の 5 点以上の点配置に対する KZ 型方程式の同時スペクトル g の変換
70. mmc(l,[µ,a1 ,...,an ]|full=1,homog=1,mult=f ):: Schlesinger 型常微分方程式および KZ 型方程式の addition+middle convolution
71. kzext([a1 , a2 , . . . , am ]|perm=σ):: KZ 方程式の全留数行列を返す
72. linfrac01(ℓ|over=1):: x = 0, 1, ∞, y, z, . . . の一次分数変換のリスト（ℓ = [x, y] etc.）
73. lft01(ℓ, t|tr=τ ):: ℓ = [x,y] または ℓ = [x,y1 ,y2 ,. . .,yq ] に対する特殊一次分数変換
1.1.3 Some operators
74. okubo3e([p0,1 , . . . , p0,m ],[p1,1 , . . . , p1,n ],[p2,1 , . . . , p2,m+n |opt=1]):: 0, 1, ∞ に確定特異点を持つ m + n 階の単独 Okubo 型微分作用素を求める
75. fuchs3e([p0,1 , . . . , p0,n ],[p1,1 , . . . , p1,n ],[p2,1 , . . . , p2,n ]):: 0, 1, ∞ に確定特異点を持つ n 階の Fuchs 型微分作用素を求める
76. ghg([p1,1 , p1,2 , ..., p1,m ],[p2,1 , p2,2 , ..., p2,n ]):: 一般超幾何函数 m Fn (p1 ; p2 ; x)（cf. seriesHG()）の満たす微分作用素

877. ghg2([a1 , a2 , . . . , b],[a01 , a02 , . . . , b0 ]|raw=1,all=1,symbol=1,var=v):: 多変数の一般化超幾何級数の微分方程式
78. even4e([p1,1 , p1,2 , p1,3 , p1,4 ],[p2,1 , p2,2 ]):: 4 階 even family (Rigid)
79. odd5e([p1,1 , p1,2 , p1,3 , p1,4 , p1,5 ],[p2,1 , p2,2 ]):: 5 階 odd family (Rigid)
80. rigid211([p0,1 , p0,2 ],[p1,1 , p1,2 ],[q0 , q1 ]):: Type 211,211,211
81. extra6e([p1,1 , p1,2 , p1,3 , p1,4 , p1,5 , p1,6 ],[p2,1 , p2,2 ]):: Extra case (Rigid)
82. eofamily([p0,1 , p0,2 ],[p1,1 ],[p2,1 , . . . , p2,n ]):: Even/odd family (obsolete)
83. ev4s(p1 ,p2 ,p3 ,p4 ,p5 ):: Heckman-Opdam 超幾何の (BC2 , BC1 ) 型制限常微分 (Rigid)
84. b2e(p1 ,p2 ,p3 ,p4 ,p5 ):: Heckman-Opdam 超幾何の (BC2 , A1 ) 型制限常微分 (Non Rigid)
85. heun([a, b, c, d, e],p,r|):: Heun の微分方程式を与える．r はアクセサリパラメータ

1.2 Useful functions
以下の函数は module 化され，函数名の先頭に os_md. をつけて os_md.chkfun() のように呼び出す．

1.2.1 Extended function
86. myhelp(h):: os_muldif.rr のマニュアルを表示する
87. chkfun(f ,s):: 函数 f （= 文字列）が定義済みかどうか調べ，未定義なら load(s) を実行
88. isMs():: Microsoft Windows 環境かどうか調べる
89. isyes(p|set=ℓ):: 1 か 0 を返す函数を定義し，それを使う
90. isall(f ,m):: m の要素に p 対して f (p) が 0 となるものが存在すると 0，そうでなければ 1 を返す
91. ptype(p,ℓ):: ℓ は変数，または変数のリストで，それのみを変数とみなした type() を返す
92. getline(Id|Max=m,CR=[r1 ,r2 ,..],LF=[l1 ,l2 ,...]):: get line() の拡張版
93. keyin(s):: s を表示し，1 行のキー入力を待って，それを文字列として返す
94. showbyshell(s):: shell でコマンド s を実行した標準出力の結果を Risa/Asir で表示
95. getbyshell(s):: shell でコマンド s を実行した標準出力の結果をファイルとして得る
96. fcat(f ,s|exe=1):: ファイル f に s を書き出す
97. makev([ℓ1 ,ℓ2 , . . . ]|num=1):: ℓ1 , ℓ2 . . . を合わせて一つの変数名を作る
98. shortv(p,[v1 ,v2 , . . .]|top=w)
9

:: p の添字番号つき不定元 v1 , . . . を一文字の w 以下の変数名に変える
99. makenewv(ℓ|var=v,num=n):: ℓ に使われていない新しい不定元を生成する
100. isvar(p):: p が変数かどうか調べる
101. varargs(p|all=t):: 式 p に含まれる初等函数の函数子とその変数に現れる不定元のリストを返す
102. pfargs(p,x|level=t):: 式 p に現れる x 変数を含んだ初等函数と引数のリストを返す
103. isdif(p):: p が微分作用素と推測されるときはその変数と微分の組のリストを返し，そうでなければ 0 を返す
104. mysubst(r,[v1 ,r1 ]|inv=1) mysubst(r,[[v1 ,r1 ], . . . ]|inv=1)
mysubst(r,[ℓ1 ,ℓ2 ]|lpair=1,inv=1):: subst(r,v1 ,r1 , . . . ) と同等．r が複雑で r1 が有理式のときに特に有効．
105. myswap(p,[x1 ,x2 ,. . .,xn ]):: 有理式またはそのリストなどの不定元の巡回置換 (x1 , x2 , . . . , xn )106. substnum(l,s,t|depth=d):: リストまたはベクトルの成分の置き換え
107. mulsubst(r,[[p1,0 , p1,1 ],[p2,0 , p2,1 ], . . . ]|inv=1)
mulsubst(r,[ℓ0 ,ℓ1 ,...]|lpair=1,generate=k,short=1)
mulsubst(r,[ℓ0 ,ℓ1 ]|conj=f ) mulsubst(r,[ℓ0 ,ℓ1 ]|dform=1):: 有理式またはそのリスト，ベクトル，行列 r に複数同時の代入，有理変換の合成, Pfaﬀ 形式の有理変換108. fmult(f ,m,ℓ,n| · · · ):: mi 7→ mi+1 = f (mi ,ℓ[i],n[0], n[1], . . . | · · · ) という変換（m0 = m）の最終結果 mlength(l) を返す
109. mtransbys(f ,m,ℓ| · · · ):: スカラーに関する変換 f () をリスト，ベクトルまたは行列 m に拡張する
110. mmulbys(f ,m,n,ℓ| · · · ):: 和が定義された objects の 2 つに対して 1 つの object を与える演算 f を，objects を成分とするベクトルまたは行列 m と n の演算に拡張する
111. cmpsimple(p,q|comp=t):: 式 p と q の簡単さを比較
112. simplify(p,ℓ,t|var=[x1 , x2 , . . . ]):: ℓ の一次関係式を使って p を簡単化
113. getel(m,i):: m がリスト，ベクトル，行列で i が非負整数なら m[i] を返す
114. evalred(r|opt=[[s1 ,t1 ],[s2 ,t2 ]...]):: sin(0), cos(0), exp(0) などを 0, 1, 1 などの整数に置き換える
115. evals(r|del=s,raw=1):: 文字列あるいは函数を評価する．
116. myeval([r,[x1 ,f1 ,v1 ],[x2 ,f2 ,v2 ],. . .]):: os_md.myeval(subst([r,[x2 ,f2 ,v2 ],. . .],x1 ,f1 (os_md.myeval(v1 )))) を返す
os_myeval([r])=map(eval(r))
117. mydeval([r,[x1 ,f1 ,v1 ],[x2 ,f2 ,v2 ],. . .]):: os_md.mydeval(subst([r,[x2 ,f2 ,v2 ],. . .],x1 ,f1 (os_md.mydeval(v1 )))) を返す
os_md.mydeval([r])=map(deval(r))
118. myval([r,[x1 ,f1 ,v1 ],[x2 ,f2 ,v2 ],. . .]):: myeval() と同様な函数であるが，可能な限り正確な値を返す
119. f2df(f |opt=n)10

:: 函数 f から sin などの函数子を除いて myeval() や mydeval() の引数のリスト形式函数に変換
120. todf(f ,[v1 ,. . .,vn ]) todf([f ,[ops]],[v1 ,. . .,vn ]):: 函数子 f で変数が v1 , . . . , vn のリスト形式函数を得る（n は f の引数の数）
121. df2big(f |inv=1):: リスト形式函数 f を倍精度浮動小数点計算から bigfloat 計算へ変更する
122. compdf(f ,x,g) compdf(f ,[x1 ,x2 , . . .],[g1 ,g2 , . . .]):: リスト形式函数 f の変数 x にリスト形式函数 g を代入したリスト形式函数を返す
123. cutf(f ,x,[[x1 ,v1 ],[x2 ,v2 ],...,[xn ,vn ]]) cutf(f ,x,[t,[x1 ,v1 ],...,[xn ,vn ]]):: 函数 f の変数が特定の範囲のとき函数値の変更を行い，その値またはリスト形式函数を返す
124. periodicf(f ,[a,b],x) periodicf(ltov([g1 ,g2 ,...,gn ]),c,x):: x を変数とする函数 f |[a,b) を周期関数に拡張した函数にする
125. cmpf([f ,[a,b]]|exp=c)
cmpf(x):: 積分区間をコンパクト閉区間 [0, 1] に直した函数にする
126. myfeval(f ,x) (f ,a) myfeval(f ,[x,a]) myfeval(f ,[[x1 ,a1 ],. . .])127. myfdeval(f ,a) myfdeval(f ,[x,a]) myfdeval(f ,[[x1 ,a1 ],. . .]):: myeval() や mydeval() の引数のリスト形式函数 f の変数に a を代入して値を得る
128. myf2eval(f ,x,y)129. myf2deval(f ,x,y):: myeval() や mydeval() の引数のリスト形式 2 変数函数 f に代入して値を得る
130. myf3eval(f ,x,y,z)131. myf3deval(f ,x,y,z):: myeval() や mydeval() の引数のリスト形式 3 変数函数 f に代入して値を得る
132. execproc(ℓ|all=1,var=k):: リスト形式手続きの実行
133. fsum(f ,[m,n,d]|df=1,subst=1) fsum(f ,[x,m,n,d]|df=1,subst=1)
P[ m−n ]:: 一般項が f (x) で与えられる級数の和 k=0d f (m + kd) を返す
134. fint(f ,n,[t1 ,t2 ]]|cpx=1,exp=c,int=k,prec=v,Acc=1) fint(f ,n,ℓ|· · · ):: 複素積分を含む数値積分
135. fimag(f ,x|inv=g):: 複素変数の指数関数を実変数の関数に変換
136. trig2exp(f ,x|inv=g):: 三角関数と指数関数の変換と簡単化
137. isshortneg(f ):: f と −f を表現する文字列の長さの比較
138. fshorter(f ,x):: x の三角関数の簡単化
139. fzero(f ,[x,x1 ,x2 ]|mesh=m,dev=d,zero=1,trans=1,cont=1):: 実数値函数 f の零点を求める
140. fmmx(f ,[x,x1 ,x2 ]|mesh=m,dev=d,mmx=1,zero=1,trans=1,cont=1,dif=1):: 実数値函数 f の極値を求める
141. flim(f ,v|prec=c,init=t):: 変数 x の実数値関数 f の極限値を求める
142. fcont(f ,[x,x1 ,x2 ]|mesh=m,dev=d,zero=1,trans=1,dif=1) ?
:: 実数値函数 f の不連続点や滑らかでない点を求める
143. fresidue(p,q|cond=[f1 ,f2 ,. . .],sum=1):: 多項式 q を分母とする有理式 p/q の特異点と留数の組のリスト（z が変数で，p は正則函数）
1.2.2 Numbers
144. abs(p) abs([p,prec])11

:: 整数または実数または複素数 p の絶対値を返す
145. sgn(n|val=1):: 数 n または置換 n の符号を返す
146. calc(p, [s, q]) calc(p, s):: 数や有理式などあるいはそれらを成分とするリストやベクトルの成分に対して演算を施す
147. isint(p):: p が整数かどうか調べる
148. israt(p):: p が有理数かどうか調べる
149. iscrat(p):: p が数でその実部と虚部が共に有理数かどうか調べる
150. isalpha(n):: 整数 n がアルファベットの文字コードかどうか調べる
151. isnum(n):: 整数 n が数字 0〜9 の文字コードかどうか調べる
152. isalphanum(n):: 整数 n がアルファベットまたは数字の文字コードかどうか調べる
153. isdecimal(s):: 文字列 s が整数または小数を表しているかどうか調べる
154. catalan(n):: Catalan 数などの場合の数を返す
155. getCatalan(k,n|opt=1,to=f ):: Catalan 数と許容 01 列，トーナメント表，凸多角形の三角形分割，番号付け，などの間の変換
156. symtournament(n|to=t,verb=1):: トーナメント戦（2 分木）の場合の数, タイプ
157. numtournament(n):: トーナメント戦にかかわる場合の数のリスト
158. tobig(n):: 0 以外の有理数を bigfloat に変換する
159. nthmodp(a,n,p):: an mod p を返す（a は整数で n, p は自然数）
160. issquaremodp(a,p|power=n):: 平方剰余を調べる（ルジャンドルの平方剰余記号 ( ap )，n は平方を一般べきに）
161. rootmodp(a,p|power=n):: p を法として a の平方根（一般には n 乗根）を求める
162. primroot(p|all=1,ind=a):: 奇素数またはそのべき p の原始根やそれを底とする指数をもとめる
163. rabin(p,q):: p に対し q を底とするミラー・ラビンの素数判定を行う（素数，擬素数なら 1 を返す）
164. cfrac(x,n|neg=1):: 有理数あるいは実数を連分数展開する（n は項数）165. cfrac2n(l|loop=m,,ex=1,q=f ,reg=1):: （循環）連分数を通常の形（含 q-変形）に直す.
166. sqrtrat(r):: 有理数（または実部と虚部が有理数の複素数）の平方根を得る
167. sqrt2rat(r|mult=1):: 平方根や虚数を含んだ分数の有理化
168. sint(r,p|str=t,sqrt=1,zero=0):: 実数 r または複素数，リストや行列（ネスト対応）などの成分の実数を小数点以下 p 桁に丸める12

169. frac2n(n|big=1):: 分数を実数になおす（r は複素数，有理式やそのリストや行列などでもよい）
1.2.3 Polynomials and rational functions
170. radd(p,q):: 有理式（の行列）p と q の和を既約有理式（の行列）の形で計算する
171. rmul(p,q):: 有理式（の行列）p と q の積を既約有理式（の行列）の形で計算する
172. mulpolyMod(p,q,x,n):: x の多項式 p と q の積を xn+1 以上の項を無視して計算する
173. polbyroot([p1 , p2 , ..., pn ],x) polbyroot([m,n],x|var=v):: 多項式を根で与える
174. polbyvalue([[a1 , b1 ],...,[an , bn ]],x):: x の n − 1 次多項式を n 個の点 x = ai での値 bi で与える
175. pgen([[x1 , n1 ],[x2 , n2 ]...],a|sum=n,shift=m,sep=1,num=1):: 係数が a∗ で xi が ni 次，全体で n 次以下の x1 , . . . の一般多項式を作る
176. rpdiv(p,q,x):: x の多項式の割り算
177. res0(p,q,x|var=[x1 , x2 , . . .],opt=f ,dbg=d):: 1 変数多項式の共通解の存在条件と解，割り算
178. sgnstrum([p1 , p2 , . . .],t|):: 多項式の strum 列の t での符号変化の個数を返す
179. polstrum(p|num=[t1 ,t2 ],mul=1):: 多項式の strum 列や，(t1 , t2 ] にある根の個数を返す
180. polrealroots(p|in=[a,b],step=[n1 ,n2 ],nt=k):: 多項式の実根を求める
181. polroots(p,x|comp=t,err=r,lim=ℓ):: 変数 x の 1 変数多項式の根，多変数多項式の共通根（実根・虚根）の（近似）値を返す
182. easierpol(p,x) または easierpol(p,[x1 , x2 , . . . ]):: 有理式係数の x の多項式の係数に x を含まない有理式をかけて，係数の最大公約元が 1 の整数係数の多項式に変換

183. getroot(p,x|mult=1,cpx=1):: 多項式の根を有理式または有理数の平方根の範囲で求める
184. fctri(p):: 実部と虚部が有理数係数の１変数多項式を，その範囲で既約分解する
185. polinsym(p,[x1 , . . . , xn ],s):: (x1 , . . . , xn ) の対称有理式を基本対称式で表す
186. polinvsym(p,[x1 , . . . , xn ],s):: polinsym(p,[x1 , . . . , xn ],s) の逆函数
187. pol2sft(p,x|sft=t):: shifted power 多項式を与える
188. polinsft(p,x):: shifted power 多項式に直す（pol2sft() の逆変換）
189. sftpow(p,n)
190. sftpowext(p,n,s)
Qn:: p の s shifted n power ν=1 (p + (ν − 1)s) を返す
191. binom(p,n):: p(p − 1)(p − 2) · · · (p − n + 1)/n! を返す
192. expower(p,r,n)13

:: (1 + p)r の展開を pn まで求める
193. orthpoly(n|pol="type")
orthpoly([n,a, . . .]|pol="type"):: 変数 x の n 次直交多項式を返す
194. schurpoly ([m1 ,m2 , . . .]|var=v):: m1 ≥ m2 ≥ · · · ≥ mn ≥ 0 のウェイトの Schur 多項式を返す
195. seriesMc(f ,k,v|evalopt=[[s1 ,t1 ],[s2 ,t2 ]...]):: 函数 f の変数または変数のリスト v に対する k 次の項までの Maclaurin 展開を求める
196. solveEq([f1 , f2 , . . . ],[x1 , x2 , . . . ]|h=1,inv=1):: 連立代数方程式を解く，双有理変換の逆変換を求める．
197. baseODE([f1 , f2 , . . . ]|f=y,to=x,var=v,vl=h,ord=d,in=1,TeX=t,pages=p,dbg=d,step=k):: 一階常微分方程式系の単独化, 双有理変換
198. taylorODE(d|series=h,taylor=[s,t],runge=m,f=f ,c1=1,list=1,dif=1,lim=[h,n]):: dy/dx = f (x, y) の解の Taylor 展開と Runge-Kutta 法の解析
199. pTaylor([f1 ,f2 , . . .],[x1 ,x2 , . . .],m|raw=1,time=t):: 常微分方程式 x0i = fi (x) (i = 1, 2, . . .) の m 次までのベキ級数解を返す
200. seriesHG([a1 ,a2 ,. . .],[b1 ,b2 ,. . .],p,k)seriesHG([[a1 ,. . .],[b1 ,. . .],[c1 ,. . .]],[[d1 ,. . .],[e1 ,. . .],[f1 ,. . .]],[x,y],k):: 一般超幾何級数 m Fn (a1 , a2 , . . . , am ; b1 , b2 , . . . , bn ; p) の pk 次の項まで求めるP(a1 )i+j ···(b1 )i ···(c1 )j ··· xi y j
または 2 変数の級数
0≤i+j≤k (d1 )i+j ···(e1 )i ···(f1 )j ··· i!j! を返す．
201. isfctr(r):: 係数が有理数の有理式かどうかを返す
202. fctrtos(r|var=ℓ,rev=1,dic=1,TeX=f ,dviout=1,lim=n,small=1,pages=1,add=s):: 有理式を因数分解した形の文字列に変換する
203. tohomog(r,[x1 , x2 , . . . ],y):: (x1 , x2 , . . .) の有理式に変数 y を導入して (y, x1 , x2 , . . .) の斉次式にする
204. substblock(p,x,q,y):: x の多項式 p, q に対し，y = q とおいて p を x の次数が mydeg(q,x) 未満の (x, y) の多項式に直す
205. invf([p1 , . . . , pn ],[x1 , . . . , xn ],[y1 , . . . , yn ]):: yj = pj (x) (j = 1, . . . , n) を xj = qj (y) (j = 1, . . . , n) と解く
206. mydeg(p,x|opt=1), mydeg(p,[x,y]|opt=1):: deg(p,x) の拡張（x は 1 次，y は −1 次）．p は行列や配列で係数は有理式でよい．
207. mymindeg(p,x|opt=1):: p がスカラーのときは mindeg(p,x) と同じ．係数は有理式でよいが，p が行列などのスカラーでな
いときは 0 以外の成分の最小次数を返す．
208. iscoef(p,f ):: p の係数の全てが f (∗) 6= 0 を満たすかどうかチェックする
209. mycoef(p,n,x):: coef(p,n,x) と同じ．n, x は同じ長さのリストでもよい．p は行列や配列で係数は有理式でよい．
210. pcoef(p,m,q)
pcoef(p,m,[[x1 , .., xn ],[m1 , . . . , mn ]]):: 多項式 pm を展開したときの単項式 q に対する係数を返す
211. pmaj(p|var=t):: 多項式を単項式で表した係数を，全てその絶対値で置き換えた多項式を返す
212. pfctr(p,x):: x の多項式または有理式 p の因数分解
213. cterm(p|var=[x,y, . . . ]):: 多項式の定数項を返す．変数を指定可能．
214. terms(p,[x,y, . . . ]|rev=1,dic=1):: 多項式の存在する項の次数とべき指数のリストを返す

14

215. pterm(p,[x1 ,x2 , . . . ],[m1 ,m2 , . . . ]):: 多項式の指定した変数が指定した次数となる項を返す
216. pweight(p,[x1 ,x2 , . . . ],[m1 ,m2 , . . . ]):: 多項式の変数に重みをつけて斉次式の成分に分解する
217. polcut (p,n,[x, y, . . . ]|top=m):: 変数のリスト [x, y, . . . ] の多項式 p から次数が（m 以上）n 以下でない項を削除
218. mydiff(p,x):: diff(p,x) と同じ．p は行列や配列で係数は有理式でよい．x もリストでよい．
219. myediff(p,x):: ediff(p,x) と同じ．p は行列や配列で係数は有理式でよい．
220. mypdiff(p,[x1 ,f1 ,x2 ,f2 ,...]):: 合成関数の微分．
221. difflog(L|var=x):: 対数微分を返す
222. ptol(p,x|opt=0):: x の多項式 p の係数のリストを返す
223. pfrac(p,x|root=2,dviout=1,TeX=1):: x の有理式 p（の行列）を部分分数展開し，分子，分母（多項式とべき）の組のリストを返す
224. lpgcd([p1 , p2 , . . . ]):: 多項式 p1 , p2 , . . . の共通因子を返す
225. jacobian([f1 , . . . , fm ],[x1 , . . . , xn ]|mat=1):: 関数の組 (f1 , . . . , fm ) の変数 (x1 , . . . , xn ) についてのヤコビアン (m = n) またはヤコビ行列を返す
226. hessian([f ,[x1 , . . . , xn ]|mat=1):: 関数の組 f の変数 (x1 , . . . , xn ) についてのヘシアンまたはヘッセ行列を返す．
227. wronskian[f1 , . . . , fn ],x|mat=1):: 関数の組 (f1 , . . . , fn ) の変数 x についてのロンスキアンまたはロンスキー行列を返す．
228. prehombf(p,q|mem=±1):: 概均質ベクトル空間の相対不変式 p の b 函数を得る．q は双対多項式.
229. intpoly(p,x|exp=c,cos=c,sin=c):: 変数 x の多項式 p（またはそれと指数関数, 対数関数や三角関数の積）や有理式の原始函数を返す
230. integrate(f ,x|dumb=k,dviout=p,log=1,frac=t,I=[a,b]):: 関数 f を変数 x について不定積分する
231. rungeKutta(f ,n,[a,b],y,y0 |mul=k,prec=1,single=1,val=1):: Runge-Kutta 法で常微分方程式 y 0 = f (x, y) の数値解を求める（f は連立も可）
232. pwTaylor(f ,n,[a,b],x,x0 ,m|mul=k,prec=p,val=1,err=e,view=[[c0 ,c1 ,d0 ,d1 ],c,u],Inf=s):: 区分的な Taylor 展開で常微分方程式 x0 = f (t, x) の数値解を求める（f は連立も可）
233. powsum(n):: 1n + 2n + · · · + mn の m を x で置き換えた n + 1 次多項式を返す
234. bernoulli(n):: n 次の Bernoulli 多項式 Bn (x) を返す
1.2.4 Functions with real/complex variables
以下の数値函数では変数（引数）を不定変数にすると対応するリスト形式函数を返す．

235. frac(x):: 実数 x の小数部分236. erfc(x) erfc([x,prec]) R
2∞:: 相補誤差函数 erfc(x) = √2π x e−t dt
237. fouriers([a0 ,a1 ,. . .,am ],[b1 ,b2 ,. . .,bn ],z|cpx=1,sum=f ,y=t,const=c)fouriers([f ,m],[g,n],z|cpx=1,sum=f ,y=t,const=c)

15

:: 有限 Fourier 級数 a0 + a1 cos z + a2 cos 2z + · · · + am cos mz + b1 sin x + b2 sin 2z + · · · + bn sin nz
238. myexp(z):: 指数関数 exp(z)239. mysin(z):: 三角関数 sin(z)240. mycos(z):: 三角関数 cos(z)241. mytan(z):: 三角関数 tan(z)242. myasin(z):: 逆三角関数 asin(z)243. myacos(z):: 逆三角関数 acos(z)244. myatan(z):: 逆三角関数 atan(z)245. mylog(z):: 対数函数 log(z)246. nlog(z):: log10 (z)247. dlog10(x):: log10 (|x|)
248. mypow(z,w):: 巾関数 z w
249. myarg(z):: 偏角 arg(z)250. sqrt(z) sqrt([z,prec]):: z の平方根を与える
251. arg(z) arg([z,prec]):: z の偏角252. gamma(z) gamma([z,prec]):: ガンマ函数 Γ(z)253. digamma(z) digamma([z,prec])′(z):: ディガンマ函数 ψ(z) = ΓΓ(z)254. lngamma(z) lngamma([z,prec]):: log(Γ(z))
255. dilog(z)P∞ k:: ダイログ函数 Li2 (z) = k=1 zk2
256. zeta(s) zeta([s,prec]):: zeta 函数 ζ(s)257. eta(τ ) eta([τ ,prec])πiτ Q∞:: Dedekind の Eta 函数 η(τ ) = e 12 m=1 (1 − e2πimτ )258. jell(τ ) jell([τ ,prec]):: Elliptic j-invariant j(τ )1.2.5 Lists and vectors
259. lcut(l,m,n):: リスト l の部分リストを返す
260. llsize([m1 , m2 , . . .]):: リスト mj のリストに対し，成分 mj の個数と mj の要素の最大個数を返す

16

261. findin(m,[ℓ0 , ℓ1 , . . . ]):: m に等しい要素を ℓ0 , ℓ1 , . . . から探す
262. lxor(m,[ℓ0 , ℓ1 , . . . ]):: m に等しい要素を除くが，それがなければ m を加える
263. countin(s,m,[ℓ0 , ℓ1 , . . . ]|step=k):: s 以上 m 以下の {ℓ0 , ℓ1 , . . .} の要素の個数，間隔 m での個数分布表を返す
264. lcount(ℓ):: リストの要素の重複度と要素の組のリストにする
265. delopt(ℓ,s|inv=1) delopt(ℓ,[s1 ,s2 ,. . .]|inv=f ):: オプションリスト（リストのリスト）からオプション s（複数指定可）を削除，抽出，付加．
266. mycat([ℓ1 , . . . , ℓm ]|delim=s)267. mycat0([ℓ1 , . . . , ℓm ],t|delim=s):: ℓ1 , . . . , ℓm を表示する
268. vtozv(v):: 有理式のベクトルをスカラー倍して単純化する
269. l2p(l,v|size=s):: 係数のリスト l を与えて v の多項式を返す．またその逆変換を返す．
270. mulseries(v1 ,v2 ):: ２つのベクトルをべき級数とみなして，その積のベクトルを返す
271. pluspower(p,x,r,m):: (1 + p)r の x に関するべき級数展開を第 m 項まで求める
272. average(ℓ|sint=k)
average([ℓ1 ,ℓ2 ]|opt="co",sint=k):: 実数のリストに対し，平均値や標準偏差や相関係数を求める
273. regress(ℓ|sint=k):: 実数の組のリストに対し，回帰直線を求める
274. vprod(v1 ,v2 )275. dvprod(v1 ,v2 ):: 2 つのベクトル（リストでもよい）の内積を返す
276. llbase(v,ℓ):: 変数 ℓ[0], ℓ[1], . . . の一次方程式のベクトル v の標準変換を行う（例は lsol() の項を参照）
277. lsol(v,l):: 変数 ℓ[0], ℓ[1], . . . に関する連立一次方程式を解く
278. lnsol(v,l):: 変数 ℓ[0], ℓ[1], . . . に関する連立一次方程式の有理数解を求める
279. lchange(ℓ,k,v|flat=1):: （多重）リスト ℓ の k で指定した位置の成分を v に置き換える
280. lsum([m1 , m2 , . . .]):: m1 , m2 , . . . の和を返す
281. lextn([m1 ,m2 , . . .]|uniq=1):: 整数のリストの区間表現を展開して返す
282. llextn([ℓ1 ,ℓ2 , . . .]):: 整数の区間表現のリストを整数のリストのリストに283. lmax([m1 , m2 , . . .]):: m1 , m2 , . . . の中の最大のものを返す
284. lmin([m1 , m2 , . . .]):: m1 , m2 , . . . の中の最小のものを返す
285. lmaxsub([ℓ1 ,ℓ2 , . . .]|min=1]):: 包含関係で極大（極小）のリスト ℓi の全体を返す
286. lgcd([m1 , m2 , . . .]|poly=1])17

:: m1 , m2 , . . . の最大公約数（元）を返す
287. llcm([m1 , m2 , . . .]|poly=1,poly=[x1 , x2 , . . .],dn=1]):: m1 , m2 , . . . の最小公倍数（元）を返す
288. ldev(ℓ,s):: リスト s の整数倍をリスト ℓ に加えて，成分の絶対値を最小にする
289. qsortn(ℓ):: 大きい順のクイックソート
290. rsort(ℓ,s,k):: ネストされたリスト ℓ のリカーシブソート
291. isort(ℓ,f ):: ℓ のインデックスソート
292. llselect(ℓ,n,k|eq=1,val=1):: 表形式のリストを成分の条件で分割する
293. llget(ℓ,[a1 ,a2 ,. . .],[b1 ,b2 ,. . .]|flat=1):: 表形式のリストから行や列を抽出
294. sort2([m1 ,m2 ]):: 2 成分のリストまたはベクトルの成分を小さい順に並び替える
295. lsort(ℓ1 ,ℓ2 ,t|c1=[c1,0 ,c1,1 , . . . ],c2=[c2,0 ,c2,1 , . . . ]):: リスト ℓ1 に対し，ℓ2 との合併，共通部分，または ℓ2 や共通部分を除く
その他，表形式データの操作

t = "cup", "setminus", "cap", "reduce", "sum", "subst"
296. issub(ℓ1 , ℓ2 ):: 部分リストかどうかのチェック
297. isdisjopint(ℓ1 ,ℓ2 )298. isdisjopintfamily([ℓ1 ,ℓ2 , . . .]):: 互いに共通部分がないかどうかのチェック
299. iscommuteset(ℓ1 ,ℓ2 )300. iscommutefamily([ℓ1 ,ℓ2 , . . .]):: 交換可能かどうかのチェック
301. llsymred([ℓ1 ,ℓ2 , . . .],[m1 ,m2 , . . .]|sort=f ,depth=d):: リストのリスト（集合族）を集めたリストから対称性で最小なもののみを残す
302. llord([ℓ1 ,ℓ2 , . . .]|verb=f ):: リストの包含関係の解析
303. btree(p,v|opt=s,add=m):: 二分木の作成と要素 p を二分木 v に追加するなどの二分木の操作
304. spantree(f ,l,s|optimize=,comp=,unit=u,limit=m,fopt=op):: l の要素を使う函数 f による変換で s の要素から生成される二本木を作る
305. msort(ℓ,s):: ベクトルやリストの成分を（多重）キー s に従ってソートする
306. l2min(l,p|check=1,cmp=f ):: リスト ℓ を成分の入れ替えで最小なものに変更する
307. partspt(l,m|opt=f ):: 一つの整数の 2 種の分割に対して細分関係を調べる
308. lpair(ℓ1 ,ℓ2 ):: 2 つのリストまたはベクトルを pair のリストに変換する
309. addIL([a,b],[[a1 ,b1 ],[a2 ,b2 ],. . .]|in=t):: 有限区間の合併集合と有限区間の和集合の計算
310. lext2(m):: 2 次の外積の基底の並べ替え

18311. vnext(v):: ベクトルの成分を並べ替え，辞書式順序で次のベクトルに変換する
312. vgen(v,w,m|opt=0):: 成分の和が m の非負整数成分のベクトル w を順に生成する
313. paracmpl(l,t|lim=1,low=1,para=[v1 , v2 , . . .]):: 有理的に t に依存したリスト l の成分（たとえば有理式）で張られる空間の正則完備化
1.2.6 Matrices
314. dupmat(m):: 成分が有理式の行列またはベクトル m の複製を作る
315. m2v(m):: 行列 m の成分を 1 行目から順に並べてベクトルに変換する
316. m2l(m|flat=1):: 有理式，ベクトルあるいは行列 m の成分を順に並べてリストにする
317. m2lv(m):: 行列 m の行ベクトルを並べてリストにする
318. m2ll(m):: 行列 m を行ベクトルをリストにかえたものを成分とするリストにする
319. lv2m(ℓ|fill=n):: 行ベクトル（行成分のリストでも可）のリスト ℓ から行列を作る
320. s2m(s):: 文字列での有理数成分の行列表現や，列のリストから行列を作る．必要最低サイズの行列になる
321. c2m(l,v|pow=t):: 基底の変換から係数行列を作る
322. mperm(m,[σ0 ,σ1 . . . ],[τ0 ,τ1 , . . . ]|mult=1)
mperm(m,[[σ0 ,σ1 ]],[[τ0 ,τ
 1 ]]|mult=1), mperm(m,[σ,[m1 ]],[τ ,[m2 ]]|mult=1):: 行列 m から小行列 mσi τj を作る，または置換行列（または互換）で変換する
323. mtranspose(m):: 行列 m の転置行列を求める（m はリストのリストでもよい）
324. madjust(m,w|null=n):: 行列 m の列数を w に調整する
325. mpower(m,n):: 行列 m の n 乗を求める
326. mtoupper(m,n|opt= t,step=1,dviout=1,pages=1,tab=k,lim=w):: 行列 m に対し，行基本変形を行って，行の先頭からの 0 の成分の個数が下の行の方へ狭義単調増加となるようにする．最後の n 列は無視．
327. mytrace(m):: 行列の trace を返す．
328. mydet(m):: det(m) と同じ．ただし成分は有理式でもよい．
329. mydet2(m):: det(m) と同じ．ただし成分は有理式でもよい．
330. permanent(m):: 正方行列の permanent を返す
331. myrank(m):: 行列 m の rank を求める（例は mtoupper() の項）
332. mykernel(m|opt=1):: 行列 m の転置行列の kernel の基底を求める
333. myimage(m|opt=1)

19

:: 行列 m の転置行列の像の基底を求める
334. mymod(v,[v1 , . . . , vk ]| opt=ℓ):: ベクトル v1 , . . . , vk で張られる空間の商空間への v の射影を求める（例は myimage() の項）
335. mmod(m,[v1 , . . . , vk ]| opt=1):: ベクトル v1 , . . . , vk で張られる空間の商空間への線形写像 m の射影
336. myinv(m):: 正方行列 m の逆行列を求める
337. madj(g,m):: 行列 gmg −1 を計算する．m は行列のリストか行列のベクトルでもよい．
338. diagm(m,a):: 対角行列を作成する
339. mgen(m,n,a,s|sep=1):: size m × n の一般行列を作成する
340. unim(s|abs=m,num=n,both=1,int=1,rank=r,conj=1,res=1,wt=w,dviout=t,lim=w):: 行列式 1 でサイズ s の整数行列をランダムに生成する，行列 s をランダムに変換する
341. newbmat(m,n,[[r00 , r01 , . . . ],[r10 , . . . ], . . . ]|null=t):: ブロック行列を作成する
342. meigen(m|mult=1,vec=1,TeX=1,sep=s):: 行列 m の固有値, 固有ベクトルを返す
343. mdsimplify(m|show=1,type=ℓ):: 有理式正方行列 m，またはそのリストやベクトルを対角行列で簡単化
344. mext2(m):: 線型変換の外積を与える
345. transm(m|dviout=1):: 行列 m の基本変形をインタラクティブに行う
1.2.7 Strings
346. str char(s,n,t):: 文字列 s の n 文字以降に文字列 t の先頭文字が最初に現れる場所を返す（str chr() の拡張）
347. str pair(s,n,t1 ,t2 |inv=1):: 文字列 s の n 文字以降で，文字（列）t2 の出現回数が t1 の出現回数を超える最初の位置を返す
348. str str(s,t|top=n,end=m,sjis=1):: 文字列 s に部分文字列 t が最初に現れる場所を返す
349. str cut(s,m,n):: 文字列 s の先頭から m 文字をスキップして，それ以降 n − m + 1 文字を返す
350. str subst(s,s0 ,s1 |sjis=1,raw=1) または
str_subst(s,[s00 , s01 , . . . ],[s10 , s11 , . . . ]|inv=1,sjis=1,raw=1)
str_subst(s,[[s00 , s10 ],[s01 , s11 ], . . . ],0|sjis=1):: 文字列 s に含まれる部分文字列 s0 を s1 で全て先頭から順に置き換える
351. str times(s,n):: 文字列 s（またはリスト）を n 回繰り返した文字列（またはリスト）を返す
352. str addc(s,c,n|tail=1):: 文字列 s に文字 c を差し込んで長さ n にする
353. str insert(s,u,[t,e]|transpose=1):: 文字列 s のリストの間に u の成分の（文字列の）リストを順に入れた差し込み文にする
354. strip(s,t1 ,t2 ):: 文字列の外側の括弧を外す
355. n2a(n|m=m,s=s,opt=[ab],verb=1):: 自然数を一文字に縮める20

356. s2os(s):: 文字列を入力可能な文字列に変換
357. i2hex(i|cap=1,num=1,min=m):: 非負整数 i の 16 進表示
358. sjis2jis(l):: 文字コードの整数のリストの先頭 2 つを ShiftJIS から JIS に変換
359. jis2sjis(l):: 文字コードの数字のリストの先頭 2 つを JIS から ShiftJIS に変換
360. s2euc(s):: ShiftJIS または JIS 文字列を EUC 文字列に変換
361. s2sjis(s):: EUC または JIS 文字列を ShiftJIS 文字列に変換
362. str tb([s0 , s1 , . . . ],tb) または str_tb(0,tb):: テキスト用バッファを作成（tb = 0）し，そこ（戻り値 tb）に文字列 s0 , . . . を順に追加する．最初の引数を 0 として文字列を取り出す．
363. l2os(l):: リストを入力可能な文字列に変換
364. r2os(l):: 数式を eval str() で入力可能な文字列に変換
365. evalcoord(s):: 文字列 s から括弧で囲まれた座標を抽出
366. evalsint(s):: 文字列 s に含まれる整数とそれ以外を分離
367. readTikZ(s):: 単純な TikZ のソースを描画実行形式に変換
368. r2ma(s):: Mathematica の形式の数式に変換
369. evalma(s|inv=1):: Mathematica の数式を読み込む
370. readcsv(s|eval=[n1 , n2 , . . . ],eval=n,sp=1,col=c,null=t,eq=1):: CSV 形式のデータをリスト形式で読み込む
371. tocsv(l|null=n,exe=f ):: リストのリストまたは行列を CSV 形式のデータに変換
1.2.8 Permutations
372. ldict(n,m |opt=t):: {0, 1, 2, . . . , m − 1} を並べ替えて辞書式順序で n + 1 番目のリストを返す
373. ndict(ℓ |opt=t):: {ℓ0 , ℓ1 , . . . , ℓm−1 } の並べ替えのリスト ℓ が何番目かを返す（最初は 0 番）
374. nextsub([a0 , . . . , am−1 ],n):: {0, . . . , n − 1} の m 個の部分集合を並べたとき，{a0 , . . . , am−1 } の次の部分集合を返す．最後を与えた時は 0 を返す．
375. nextpart(ℓ|max=m):: 自然数の分割のリスト ℓ に対し，辞書式順序で次に大きなものを返す
376. nextshort(ℓ, ):: 自然数の分割のリスト ℓ に対し，より分割の個数が少なくて辞書式順序で次に大きなものを返す
377. transpart(ℓ):: 自然数の分割のリスト（Young 図式に対応）ℓ に対し，その双対を返す（例は nextpart() を参照）
378. trpos(a,b,n)21

:: 互換 (a, b) にあたる n 次置換群の元を返す
379. sprod(s,t):: 置換群の積を返す
380. sadj(s,t):: 置換群の共役変換を返す
381. sinv(s):: 置換 s の逆元を返す
382. slen(s):: 置換 s の長さを返す
383. sexps(s):: 置換 s を隣接互換の積で表す
384. sord(s,t):: 置換を Bruhat order で比較する
1.2.9 TEX
385. my tex form(p|subst=[t0 , t1 ],frac=f ,root=r,ket=k):: print tex form(p) の戻り値から文字列置換や不要部分削除を行い，読みやすいソースに変換
386. show(p|opt=ℓ,raw=1):: p を dviout で適切に表示する
387. dviout(p|clear=1,keep=1,delete=t,fctr=1,mult=1,subst=[s0, s1],eq=k,title=s):: p を dviout で表示する
388. dviout0(ℓ) or dviout0([ℓ1 , ℓ2 , . . . ]) or dviout0(ℓ|opt=s):: TEX での表示のための内容削除などの基本操作
389. verb tex form(p):: p を LATEX で表現可能な文字列にする
390. monotos(p):: 有理式を文字列に変換．単項式以外では ( と ) で囲む
391. monototex(p|minus=1):: 有理式を TEX の文字列に変換．単項式以外では ( と ) で囲む
392. rtotex(p):: 数式を TEX の文字列に変換．1 文字を越えるときは { と } で囲む
393. texsp(s):: TEX の文字列 s の最後が TEX のキーワードのとき，s の末尾に空白をつける．
394. texbegin(t,s|opt=u):: TEX の \begin{t}[u] s \end{t} というソースを出力する
395. texcr(k):: 127 以下の非負整数 k に応じて TEX における数式の改行の文字列を返す
396. texket(s|all=t):: TEX のソース s における括弧のサイズを可変にする
397. eqs2tex(p,[var,dic,pages,cont]|dviout=1):: 長い数式 p を TEX の複数行の display style に変換
398. ltotex(l|opt=s,pre="string",cr="cr",small=1,lim=ℓ,var=v):: リストまたはベクトルを s = "spt" のとき重複度つきのリストとみて\left\{... または s = "GRS"のとき \begin{Bmatrix} · · · の形の Riemann scheme とみて TEX の文字列に変換など
399. mtotex(m|small=1,2, null=1,2, sp=1,2, idx=0,1, mat=s,var=ℓ, pfrac=v,raw=1,lim=n):: 行列またはベクトルを TEX の文字列に変換するが，成分が有理式のときは因数分解した形にする
400. divmattex(s,l):: 行列の TEX のソース s の分割や列の並べ替えを行う
401. smallmattex(s)22

:: TEX のソースで ( ) や { } で囲まれた行列を小サイズに変換する
402. texlen(s):: LATEX の数式の横幅を推測して文字数で返す
403. texlim(s, n|del=s0 ,cut=s1 ):: 長い TEX の数式を，複数行に分割する
1.2.10 Lines and curves404. ladd(u,v,t)ladd(u,v,[t2 ])ladd(u,v,[t1 ,t2 ]):: ベクトルまたはリストの成分の和（t = 1）や差（t = −1）を成分とするリストを返す
405. lsub([u,v]):: ベクトルまたはリスト u, v に対して，u − v を返す
406. dnorm(v|max=f ):: ベクトルまたはリストのノルム，または 2 点間の距離を返す
407. dext(u,v)，([u1 ,u2 ],[v1 ,v2 ]):: 2 次元ベクトルまたはリストの外積を返す
408. darg([p,q]) darg([p1 ,p2 ],[q1 , q2 ])
→
−
→ −−→
pq = (x, y) の偏角 θ，または −p−
1 p2 と q1 q2 のなす角に応じた数を返す
409. dwinding([p,[q1 , . . . , qn ])点 p に対して，点 q1 , . . . , qn , q1 を順に繋ぐ折れ線の回転数を返す
410. mrot(θ|deg=1) mrot([θz0 ,θy ,θz ]|deg=1,conj=1):: 角度 θ の回転行列，または 3 次元の回転行列を返す
411. dvangle(v1 ,v2 ) dvangle([u1 , u2 , u3 ],0):: ベクトルまたはリストの鋏む角度の余弦を返す
412. ptaffine(m,ℓ|org=v,shift=w,arg=θ,deg=θ,proc=1):: 実数の組（座標）のリストを結合する，またはアフィン変換（こちらは描画実行形式も可）を施す
413. ptpolygon(n,r|org=p,scale=t,arg=θ,deg=θ):: 半径 r の円に内接する正 n 多角形の頂点の平面座標
414. ptlattice(m,n,v1 ,v2 |org=p,scale=t,cond=[f1 ,f2 , . . .],line=1):: org を始点として v1 方向に m 個まで，v2 方向に n 個までの合計 m × n 個の格子点の座標415. ptcopy(ℓ,v):: 座標のリスト ℓ を移動方向のリスト v に従って複製コピーする
416. ptcommon([s1 ,s2 ],[t1 ,t2 ]|in=k):: 直線や線分や円に対して共通点，接点や垂線の足，内分点，方向転換進行点，角度などを求める
417. pt5center(p,q,r|opt=f ):: p, q, r を頂点とする三角形の五心, 円や直線に接する円
418. ptinversion(p|org=[a,b],sc=r):: 点 p または円 p の反転
419. ptcontain(p,[t1 ,t2 ,t3 ]):: 点 p あるいは線分 p = [p1 ,p2 ] と三角形 t1 , t2 ，t3 の共通部分を返す
420. pg2tg(n|all=f ,bis=1):: 正 n 多角形の対角線による三角形分割のリストを返す
421. pgpart(p,f ):: 正 n 多角形の対角線による三角形分割の種々の変換
422. xypg2tg(p|pg=n,skip=s,r=r,org=b,rot=c,opt=t,proc=f ,line=ℓ,every=e,V=v,dviout=d):: （複数の）正多角形の三角形分割などの表示
423. istournament(ℓ|verb=1):: トーナメント戦のチェック
424. xytournament(l,[w,h]|dviout=t,teams=s,top=0,winner=m,win=1,rev=1,verb=f ):: トーナメント戦の図の描画

23425. ptconvex([p1 , p2 , . . .]|opt=1):: すべての点 p1 , p2 , . . . の凸包，あるいはすべての点を繋ぐ多角形を返す
426. ptwindow(ℓ,[x1 ,x2 ],[y1 ,y2 ]|scale=t):: 平面座標 (x, y) のリストで x1 ≤ x ≤ x2 ，y1 ≤ y ≤ y2 を満たさないものを 0 に変える
427. ptbbox([[x1 ,y1 ,. . .],[x2 ,y2 ,. . .],. . .]|box=b)
(1)
(1)
(1)
(1)
(2)
(2)
ptbbox([[[xmin ,xmax ],[ymin ,ymax ],. . .],[[xmin ,xmaxS ],. . .],. . .]|box=1):: 座標 (x, y, . . .) や箱のリストを囲む箱 [[xmin ,xmax ],[ymin ,ymax ],. . .] を返す
(1)
(1)
(1)
(1)
(2)
(2)
(2)
(2)
428. iscombox([[xmin ,xmax ],[ymin ,ymax ],. . .], [[xmin ,xmax ],[ymin ,ymax ],. . .]):: 2 つの箱（区間の直積）の共通部分の有無を返す
429. lninbox([p1 ,p2 ],[[xmin ,xmax ],[ymin ,ymax ]]|in=1):: 平面内の 2 点 p1 と p2 を結ぶ直線（または線分）の箱内の部分（2 点を結ぶ線分）を返す
430. scale(ℓ|scale=[c1 , . . .],f=f ,shift=[s1 ,s2 ],TeX=1,mes=[t,[a1 ,b1 ,w1 ], . . .],line=[a,b],
mes2=[[x1 ,[t1,0 ,t1,1 ,c1 ],t1 ,s1 ],. . .],prec=0,col=s,inv=1,vert=1):: 目盛や対数（函数）尺の作成
431. tobezier(ℓ|inv=[a,b,t],div=k):: 点のリスト ℓ で定まる Bézier 曲線のパラメータ表示とその逆変換と分割
432. lbezier(l|inv=t):: 区分 Bézier 曲線のデータ変換
433. velbezier(f ,[a,b,t]):: Bézier 曲線の最大速度ベクトル434. ptbezier(l,[n, t]) ptbezier(l,s):: （複合）Bézier 曲線上の点と速度ベクトルを求める
435. areabezier(l|rev=1,pt=[p1 ,p2 , . . .],para=1,prec=v,int=k,exp=c,Acc=1,cpx=1):: Bézier 曲線を用いた領域の面積・数値積分の計算
436. ptcombezier(ℓ1 ,ℓ2 ,m):: 点のリスト ℓ1 , ℓ2 で定まる 2 つの Bézier 曲線の交点を求める
437. ptcombz(b1 ,b2 ,m|red=t,prec=k):: 区分 Bézier 曲線 b1 , b2 の交点を求める
1.2.11 Drawing curves and graphs
438. openGlib([w,h]|null=1):: グラフィックライブラリ（glib）のウインドウを開く
439. trcolor(s):: 色を文字列からコードへ変換
色は，red, green, blue, yellow, cyan, magenta, black, white, gray が可能
440. mcolor([c0 ,. . .,cm ],k|disc=1):: 中間色のコードを返す
441. xyproc(f |dviout=1,opt=s,env=t):: XY-pic/TikZ や指定した環境の開始（f = 1）と終了（f = 0）や表示
442. xypos([x,y,s]) xypos([x,y,s,t]) xypos([x,y,s,t,u]) xypos([x,y]):: XY-pic/TikZ での座標 (x, y) や式 s などの文字出力．t はラベルの文字，u はオプション文字列．
443. xyput([x,y,s]|scale=r) xyput([x,y,s,t]) xyput([x,y,s,t,u]):: XY-pic/TikZ での座標 (x, y) や式 s などの文字出力．t はラベルの文字，u はオプション文字列．
444. xyline([x1 ,y1 ,s1 ],[x2 ,y2 ,s2 ]|opt=t) xyline([x1 ,y1 ],[x1 , y2 ]|opt=t):: XY-pic/TikZ で (x1 , y1 ) と (x2 , y2 ) を線で結ぶ（引数はベクトルでもよい）
445. xyarrow([x1 ,y1 ,s1 ],[x2 ,y2 ,s2 ]|opt=t,cmd=s):: XY-pic/TikZ で (x1 , y1 ) と (x2 , y2 ) を矢印等で結ぶ（引数はベクトルでもよい）
446. xyarrows([f1 ,f2 ],[v1 ,v2 ],[[x1 ,x2 ,m],[y1 ,y2 ,n]]|scale=r,abs=v):: XY-pic/TikZ で複数の矢印を描く

24

447. xybox([[x1 ,y1 ],[x2 ,y2 ],[x3 ,y3 ]]|opt=t,color=s...) xybox([[x1 ,y1 ],[x2 ,y2 ]]|opt=t,color=s,...):: XY-pic/TikZ で (x1 , y1 ) と (x2 , y2 ) を対角点とし，(x3 , y3 ) を頂点とする平行四辺形（あるいは水平な辺をもつ長方形）を描く

448. xycirc([x,y,s],r|opt=t,arg=[θ1 ,θ2 ],deg=[θ1 ,θ2 ],close=1):: XY-pic/TikZ で (x, y) 中心の半径 r mm/cm の円を描く
449. xybezier([[x1 ,y1 ], . . . ,[xn , yn ]]|verb=k,opt=t,cmd=s,relative=1):: XY-pic/TikZ で区分 Bézier 曲線（複合 Bézier 曲線）を描く
450. draw bezier(id,idx,b|col=c,opt=s,init=1):: キャンバス上に区分 Bézier 曲線を描く
451. xylines([[x1 ,y1 ,s1 ],[x2 ,y2 ,s2 ],. . .]|opt=t,close=1,curve=1,ratio=c,verb=1,scale=r,
Acc=1,dviout=1,proc=p):: XY-pic/TikZ で sj を (xj , xj ) に置き，(x1 , y1 ), (x2 , y2 ), . . . を（Bézier 曲）線で結ぶ
452. xyang(r,p0 ,p1 ,p2 |opt=t,scale=r,prec=1,ar=1,dviout=1,proc=1):: XY-pic/TikZ で角 ∠p1 p0 p2 の記号や円弧や扇形や矢印を描く
453. xyoval(p,r,q|opt=t,arg=[t1 ,t2 ,t3 ],deg=[t1 ,t2 ,t3 ],scale=r,ar=1,prec=1,dviout=1,
proc=1):: XY-pic/TikZ で p を中心として，軸の長さが r と qr の楕円またはその弧や扇形を描く
454. xygrid([x,tx ,ux ,mx ,sx ],[y,ty ,uy ,my ,sy ]|raw=r,shift=[sx ,sy ]):: （対数）方眼紙の描画
455. xycircuit(p,s|scale=r,opt=t,at=k,rev=1):: 電気回路を描く
456. xypoch(w,h,r1 ,r2 |ar=r):: Pochhammer の cycle を描く
457. xyplot([[a1 ,b1 ],[a2 ,b2 ],. . .],[x0 ,x1 ],[y0 ,y1 ]|opt=t,ax=[x0 ,y0 ,s,t,u],axopt=[w,h,o,z],
scale=r,to=[W ,H],dviout=1,view=v,raw=1):: 与えられた点のリストをプロットして順につなぐ
458. xyaxis([x0 ,y0 ,s,t,u],[x1 ,x2 ],[y1 ,y2 ]|scale=r,opt=t,axopt=[h,w,o,z],view=1):: 座標軸の描画
459. xygraph(f ,n,[t1 , t2 ],[x1 ,x2 ],[y1 , y2 ]|opt=t,rev=1,ax=[x0 ,y0 ,s,t,u],axopt=[h,w,o,z],
scale=r,ratio=c,raw=1,org=[x0 ,y0 ],pt=[p1 ,p2 ,...],verb=1,para=1,prec=v,shift=[u,v],
Acc=1,dviout=t,proc=p):: 変域の n 等分点での値で関数のグラフを描く（t1 ≤ x ≤ t2 ，(x1 , y1 )–(x2 , y2 ) は表示窓の範囲）
460. xy2graph(f ,n,[x1 ,x2 ],[y1 , y2 ],[h1 ,h2 ],α,β|opt=t,scale=r,view=h,raw=1,trans=1,
ax=[z1 ,z2 ,t],dev=m,acc=k,org=[x0 ,y0 ,z0 ],pt=[p1 ,p2 ,...],prec=v,title=s,dviout=k,
ext=[a,b],shift=[u,v],cl=1,proc=p):: x, y 変数の区間を n 等分して曲面 z = f (x, y) の 3D グラフを描く
461. xy2curve([f1 , f2 , f3 ],n,[t1 ,t2 ],[y1 ,y2 ],[z1 , z2 ],α,β|scale=r,gap=g,opt=s,eq=q,raw=w,
dviout=d):: 空間曲線の隠線処理つき描画
462. execdraw(ℓ,t|shift=[u,v],ext=[a,b],cl=1):: 描画実行形式 ℓ を出力形態 t に従って実行する
1.2.12 Applications
463. powprimroot(p,n|all=1,exp=1,log=f ):: p 以上の素数 n 個とその原始根のリストを作る
464. distpoint(l|div=5,opt=s,title=t,size=ℓ):: 100 点満点の点数表のデータ l を元に点数分布などを表にする
465. seriesTaylor(f ,k,v|evalopt=opt,small=1,frac=0,dviout=n):: 函数 f の変数または変数のリスト v に対する k 次の項までの Taylor 展開を求める

25

1.2.13 Environments
466. Canvas:: Risa/Asir の描画キャンバスのデフォルトサイズ
467. AMSTeX:: この値が 1 は AMSLATEX を意味する
468. TeXEq:: デフォルトの LATEX の数式環境の指定（dviout0(3) で値が分かる）
469. TeXLim:: LATEX で長い数式を行分割する際の 1 行の許容最大横幅文字数のデフォルト値
470. TeXPages:: TEX の display style で改ページを許す行数の閾値（cf. fctrtos()）
471. TikZ:: グラフ表示に XY-pic を使うか TikZ を使うかを指定
472. XYPrec:: グラフ表示の時の座標の小数点以下の丸め桁数
473. XYcm:: Unit is cm even in XY-pic での単位を cm で表して，TikZ に合わせる
474. XYLim:: XY-pic や TikZ での曲線描画で順に指定する点での改行の間隔
475. DVIOUTH:: myhelp() で指定した函数の解説を示すためのプログラムの指定
476. DIROUT:: 数式を LATEX に変換したソースが格納されるディレクトリ（書き込み可能なことが要請される）
477. DVIOUTA:: LATEX の AMSTEX 環境で risaout.tex を変換して表示するプログラムのパス名
478. DVIOUTB:: LATEX の AMSTEX 環境で risaout10.tex （または risaout10.tex）を変換して表示するプロ
グラムのパス名で，DVIOUTA と交換できる（cf. dviout0(), risatex.bat）479. DVIOUTL:: LATEX 環境で riasout0.tex を変換して表示するプログラムのパス名
480. .muldif:: os_muldif.rr をロードしたときに読み込まれるファイル
481. risatex.bat:: os_muldif.rr が出力する LATEX のソースファイルを変換して表示するプログラム

26

2 Risa/Asir
Risa/Asir はオープンソースの計算機代数 (数式処理) システムです.
神戸版は OpenXM コミッターによって開発されています. オリジナルの Risa/Asir は富士通研究所で開発されました.
現在の神戸版は Windows 用（32bit, 64bit），UNIX 用，MAC OS X 用が存在し
http://www.math.kobe-u.ac.jp/Asir/asir-ja.html
からダウンロードできます．
Risa/Asir の著作権, ライセンス同意事項についてはこちらを御覧ください. 要約すると「非商用の場合,
配布, 改変は自由」という形で提供されています．
以下の §2.1 – §2.16 および 3. Some function in the original library は，Risa/Asir の Help ファ
イル（chm 形式）の一部を，若干の改変をほどこして取り込んだもので，myhelp() によって os_muldif.rrに含まれる函数とともに Risa/Asir から参照することが出来ます．

2.1 Risa および Asir
Risa の構成は次の通りである.
• 基本演算部
これは, Risa の内部形式に変換されたオブジェクト (数, 多項式など) の間の演算を実行する部分であり, UNIX の ‘libc.a’ などと同様の, ライブラリとして存在する. エンジンは, C および アセンブラで記述され, 後述する言語インタフェース Asir の基本演算部として用いられている.
• メモリ管理部
Risa では, メモリ管理部として, [Boehm-Weiser] によるフリーソフトウェア (gc-6.1alpha5) を用いている. これはガーベジコレクション (以下 GC と呼ぶ) を自動的に行うメモリ割り当て機構を持ち,
Risa の各部分はすべてこれにより必要なメモリを得ている.
• AsirAsir は, Risa の計算エンジンの言語インタフェースである. Risa では, 比較的容易にユーザ用の言語
インタフェースを作ることができる. Asir はその一つの例として作ったもので, C 言語に近い文法をもつ. また, C のデバッガとして広く用いられている dbx 風のデバッガも備えている.

2.2 Asir の特徴
Asir は, 前述の通り, 計算エンジンの言語インタフェースである. 通常 Asir という名前の実行可能ファイ
ルとして提供される. 現在サポートされている機能は概ね次の通りである.
• C 言語風のユーザ言語• 数, 多項式, 有理式の加減乗 (除)• ベクトル, 行列の演算• 最小限のリスト処理• 組み込み函数 (因数分解, GCD, グレブナ基底など)• ユーザ定義函数によるツール (代数体上の因数分解など)• dbx 風のデバッガ• 陰函数の描画• PARI (see section pari()) による初等超越函数を含む式の評価• UNIX 上での分散計算機能 (OpenXM)

27

2.3 コマンドラインオプション
コマンドラインオプションは次の通り.

-heap number Risa/Asir では, 4KB のブロックをメモリ割り当ての単位として用いている. デフォルトでは, 初期 heap として, 16 ブロック (64KB) 割り当てるが, それを変更する場合, -heap を用いる. 単
位はブロックである. heap の大きさは, heap() 函数で調べることができる (単位はバイト).
-adj number この値が大きいほど, 使用メモリ量は大きくなるが, GC 時間が少なくなる. number として 1以上の整数が指定できる. デフォルトでは 3 である. この値が 1 以下になると GC をしない設定になるので要注意である. heap をなるべく伸ばさずに, GC を主体にしてメモリ管理したい場合には, この値を大きく (例えば 8) 設定する.
-norc 初期化ファイル ‘$HOME/.asirrc’ を読まない.
-quiet 起動時の著作権表示を行わない.
-f ﬁle 標準入力の代わりに, ﬁle から入力を読み込んで実行する. エラーの際にはただちに終了する.
-paristack number PARI (see section pari()) 専用の領域の大きさを指定する. 単位はバイト. デフォルトでは 1 MB.
-maxheap number heap 領域の上限を指定する. 単位はバイト. デフォルトでは無制限. UNIX の場合, 実際には limit コマンドで表示される data size の値に制限されているため, -maxheap の指定がなくても一定量以上に heap を獲得できない場合があるので注意.)

2.4 環境変数
Asir の実行に関するいくつかの環境変数が存在する. UNIX 上では環境変数は shell のコマンドラインから直接設定するか, shell の rc ファイルで設定する. Windows NT では, [設定]→[システム]→[環境] で設定
する. Windows 95/98 では, ‘c:\autoexec.bat’ に書いて reboot する.
ASIR LIBDIR Asir のライブラリディレクトリ, すなわちユーザ言語で書かれたファイルなどがおかれる
ディレクトリ. 指定がない場合 UNIX 版では ‘/usr/local/lib/asir’, Windows 版では Asir メイ
ンディレクトリの下の ‘lib’ ディレクトリが用いられる. この環境変数は ASIRLOADPATH に統合され廃止される予定.
ASIR CONTRIB DIR Asir の asir-contrib デ ィ レ ク ト リ, す な わ ち OpenXM/asir-contrib プ ロ ジ ェ
ク ト で 書 か れ た パ ッ ケ ー ジ や デ ー タ な ど が お か れ る デ ィ レ ク ト リ. 指 定 が な い 場 合 UNIX 版
で は ‘/usr/local/lib/asir-contrib’, Windows 版 で は Asir メ イ ン デ ィ レ ク ト リ の 下 の‘lib-asir-contrib’ ディレクトリが用いられる. この環境変数は ASIRLOADPATH に統合され廃止される予定.
ASIRLOADPATH ロードされるファイルがあるディレクトリを UNIX の場合 ’:’, Windows の場合 ’;’
で区切って並べる. ディレクトリは左から順にサーチされる. この指定がない場合, および指定されたファイルが ASIRLOADPATH になかった場合, ライブラリディレクトリもサーチされる.
HOME -norc オプションつきで起動しない場合, ‘$HOME/.asirrc’ があれば, 予めこのファイルを実行
する. HOME が設定されていない場合, UNIX 版ではなにも読まないが, Windows 版では Asir メイ
ンディレクトリ (get rootdir() で返されるディレクトリ) の ‘.asirrc’ を探し, あればそれを実行する.

2.5 起動から終了まで
Asir を起動すると,[0]28

なるプロンプトが表示され, セッションが開始する. ‘$HOME/.asirrc’ (Windows 版の場合, HOME 設定されていない場合には get rootdir() で返されるディレクトリにある ‘.asirrc’) が存在している場合, このファイルを Asir ユーザ言語でかかれたファイルと見なし, 解釈実行する.
プロンプトは入力の番号を表す. セッションは, end; または quit; を入力することにより終了する. 入力
は, ‘;’ または ‘$’ までを一区切りとして評価される. ‘;’ のとき結果は表示され, ‘$’ のとき表示されない.

% asir[0] A;
0[1] A=(x+y)^5;x^5+5*y*x^4+10*y^2*x^3+10*y^3*x^2+5*y^4*x+y^5[2] A;
x^5+5*y*x^4+10*y^2*x^3+10*y^3*x^2+5*y^4*x+y^5[3] a=(x+y)^5;
evalpv : invalid assignment
return to toplevel[3] a;
a[4] fctr(A);[[1,1],[x+y,5]][5] quit;%
この例では, A, a, x, y なる文字が使用されている. A はプログラムにおける変数で, a, x, y は数学的な意味
での不定元である. 一般にプログラム変数は大文字で始まり, 不定元は小文字で始まる. この例でわかるように, プログラム変数は, 数, 式などを格納しておくためのものであり, C 言語などにおける変数に対応する. 一方, 不定元はそれ自身で値を持つことはできず, 従って, 不定元に対する代入は許されない. 後に示すが, 不定元に対する代入は, 組み込み函数 subst() により明示的に行われる.

2.6 割り込み
計算を実行中に割り込みをかけたい場合, 割り込みキャラクタ (通常は C-c, Windows, DOS 版では C-x を入力する.

@ (x+y)^1000;
C-cinterrupt ?(q/t/c/d/u/w/?)
各選択肢の意味は次の通り.

q
t
c
d
u
w
?

Asir を終了する. (確認あり)
トップレベルに戻る. (確認あり)
実行を継続する.
デバッグモードに入る. デバッガに関しては See section デバッガ.
register_handler() (see section ox_reset, ox_intr, register_handler) で登録された関数を実行後トップレベルに戻る. (確認あり)
中断点までの函数の呼び出し列を表示する.
各選択肢の意味を説明する

29

2.7 エラー処理
組み込み函数に不正な型の引数を渡した場合などには実行が中断されるが, ユーザ函数の中でエラーが起きた場合にはトップレベルに戻る前に自動的にデバッグモードに入る. この状態でエラーの場所, 直前の引数の値などを調べることができる. 表示されるエラーメッセージはさまざまであり, 内部の函数名に引き続いてメッセージが表示される. これは, 呼び出された組み込み函数と必ずしも対応はしない.
その他, さまざまな原因により内部演算函数においてエラーが生ずることがある. UNIX 版の場合, これは次のいずれかの internal error として報告され, 通常のエラーと同様に扱って, デバッグモードに入る.

SEGV
BUS ERROR 組み込み函数によっては, 引数の型を厳密にチェックせずに演算ルーチンに引き渡してしまうものも存在している. このような状況において, 不正なポインタ, あるいは NULL ポインタによるアクセス違反があった場合, これらのエラーとなる.
BROKEN PIPE プロセス間通信において, 相手先のプロセスとの間のストリームが既に存在していない場合(例えば既に相手先のプロセスが終了している場合など) に, そのストリームに入出力しようとした場合にこのエラーとなる. これらは実際には, 組み込み函数の入口において, 引数を完全にチェックすることにより大部分は防げるが, 手間が多くかかることと, 場合によっては効率を落すことにもなるため, あえて引数チェックはユーザ任せにしてある.

2.8 計算結果，特殊な数@ はエスケープ文字として使用される. 現在次のような規定がある.
@n n 番目の計算結果.
@@ 直前の計算結果.
@i
虚数単位.
@pi 円周率.
@e
自然対数の底.
@2 元体 GF(2) 上の一変数多項式の変数 (不定元)@>, @<, @>=, @<=, @==, @&&, @|| quantiﬁer elimination における, 一階述語論理演算子[0] fctr(x^10-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]][1] @@[3];[x^4+x^3+x^2+x+1,1][2] eval(sin(@pi/2));
1.000000000000000000000000000000000000000000000000000000000[3] eval(log(@e),20);
0.99999999999999999999999999998[4] @0[4][0];x^4-x^3+x^2-x+1[5] (1+@i)^5;(-4-4*@i)[6] eval(exp(@pi*@i));-1.0000000000000000000000000000[7] (@+1)^9;(@^9+@^8+@+1)30

トップレベルで計算された値はこのようにヒストリとして取り出し可能であるが, このことは, ガベージコレ
クタにとっては負担をもたらす可能性がある. 特に, 大きな式をトップレベルで計算した場合, その後の GC
時間が急速に増大する可能性がある. このような場合, delete history() が有効である.

2.9 型
2.9.1 Asir で使用可能な型
Asir においては, 可読な形式で入力されたさまざまな対象は, パーザにより中間言語に変換され, インタ
プリタにより Risa の計算エンジンを呼び出しながら内部形式に変換される. 変換された対象は, 次のいずれかの型を持つ. 各番号は, 組み込み函数 type() により返される値に対応している. 各例は, Asir のプロンプ
トに対する入力が可能な形式のいくつかを示す.
00

実際には 0 を識別子にもつ対象は存在しない. 0 は, C における 0 ポインタにより表現されている. しかし, 便宜上 Asir の type(0) は値 0 を返す.

1数

1

0x0d

2/3

14.5

3+2*@i数は（0x0d は 16 進数，@i は虚数単位）, さらにいくつかの型に分けられる. これについては下で述
べる.
2 多項式 (数でない) x afo (2.3*x+y)^10多項式は, 全て展開され, その時点における変数順序に従って, 再帰的に 1 変数多項式として降冪の順に整理される. (See section 分散表現多項式)．この時, その多項式に現れる順序最大の変数を 主変数と呼ぶ.
3 有理式 (多項式でない) (x+1)/(y^2-y-x) x/x
有理式は, 分母分子が約分可能でも, 明示的に red() が呼ばれない限り約分は行われない. これは, 多
項式の GCD 演算が極めて重い演算であるためで, 有理式の演算は注意が必要である.
4 リスト [] [1,2,[3,4],[x,y]]
リストは読み出し専用である. [] は空リストを意味する. リストに対する操作としては, car(), cdr(),cons() などによる操作の他に, 読み出し専用の配列とみなして, [index] を必要なだけつけることにより要素の取り出しを行うことができる. 例えば[0] L = [[1,2,3],[4,[5,6]],7]$[1] L[1][1];[5,6]
注意すべきことは, リスト, 配列 (行列, ベクトル) 共に, インデックスは 0 から始まることと, リストの要素の取り出しをインデックスで行うことは, 結局は先頭からポインタをたどることに相当するため,配列に対する操作に比較して大きなリストでは時間がかかる場合があるということである.
5 ベクトル newvect(3) newvect(2,[a,1])ベクトルは, newvect() で明示的に生成する必要がある. 前者の例では 2 成分の 0 ベクトルが生成され, 後者では, 第 0 成分が a, 第 1 成分が 1 のベクトルが生成される. 初期化のための 第 2 引数は, 第1 引数以下の長さのリストを受け付ける. リストの要素は左から用いられ, 足りない分は 0 が補われる.
成分は [index] により取り出せる. 実際には, 各成分に, ベクトル, 行列, リストを含む任意の型の対象を代入できるので, 多次元配列をベクトルで表現することができる.

[0] A3 = newvect(3);[ 0 0 0 ][1] for (I=0;I<3;I++)A3[I] = newvect(3);[2] for (I=0;I<3;I++)for(J=0;J<3;J++)A3[I][J]=newvect(3);[3] A3;[ [ [ 0 0 0 ] [ 0 0 0 ] [ 0 0 0 ] ][ [ 0 0 0 ] [ 0 0 0 ] [ 0 0 0 ] ]31

[ [ 0 0 0 ] [ 0 0 0 ] [ 0 0 0 ] ] ][4] A3[0];[ [ 0 0 0 ] [ 0 0 0 ] [ 0 0 0 ] ][5] A3[0][0];[ 0 0 0 ]6 行列 newmat(2,2) newmat(2,3,[[x,y],[z]])行列の生成も newmat() により明示的に行われる. 初期化も, 引数がリストのリストとなることを除いてはベクトルと同様で, リストの各要素 (これはまたリストである) は, 各行の初期化に使われ, 足りない部分には 0 が埋められる. 行列も, 各要素には任意の対象を代入できる. 行列の各行は, ベクトルとして取り出すことができる.
[0] M=newmat(2,3);[ 0 0 0 ][ 0 0 0 ][1] M[1];[ 0 0 0 ][2] type(@@);
5
7 文字列 ""

"afo"

文字列は, 主にファイル名などに用いられる. 文字列に対しては加算のみが定義されていて, 結果は 2
つの文字列の結合である.

[0] "afo"+"take";afotake8 構造体 newstruct(afo)Asir における構造体は, C における構造体を簡易化したものである. 固定長配列の各成分を名前でアクセスできるオブジェクトで, 構造体定義毎に名前をつける.
9 分散表現多項式 2*<<0,1,2,3>>-3*<<1,2,3,4>>
これは, ほとんどグレブナ基底専用の型で, 通常の計算でこの型が必要となることはまずないが, グレブ
ナ基底計算パッケージ自体がユーザ言語で書かれているため, ユーザが操作できるよう独立した型として Asir で使用できるようにしてある. これについては See section グレブナ基底の計算.
10 符号なしマシン 32bit 整数
11 エラーオブジェクト
以上二つは, Open XM において用いられる特殊オブジェクトである.
12 GF(2) 上の行列
現在, 標数 2 の有限体における基底変換のためのオブジェクトとして用いられる.
13 MATHCAP オブジェクト
Open XM において, 実装されている機能を送受信するためのオブジェクトである.
14 ﬁrst order formulaquantiﬁer elimination で用いられる一階述語論理式.
15 matrix over GF (p)小標数有限体上の行列.
16 byte array
符号なし byte の配列−1 VOID オブジェクト型識別子 −1 をもつオブジェクトは関数の戻り値などが無効であることを示す.

32

2.9.2数の型

0 有理数
有理数は, 任意多倍長整数 (bignum) により実現されている. 有理数は常に既約分数で表現される.
1 倍精度浮動小数
マシンの提供する倍精度浮動小数である. Asir の起動時には, 通常の形式で入力された浮動小数はこの型に変換される. ただし, ctrl() により bigfloat が選択されている場合には bigﬂoat に変換される.

[0] 1.2;
1.2[1] 1.2e-1000;
0[2] ctrl("bigfloat",1);
1[3] 1.2e-1000;
1.20000000000000000513 E-1000
倍精度浮動小数と有理数の演算は, 有理数が浮動小数に変換されて, 浮動小数として演算される.
2 代数的数 See section 代数的数に関する演算.
3 bigﬂoat
bigﬂoat は, Asir では PARI ライブラリにより実現されている. PARI においては, bigﬂoat は, 仮数部
のみ任意多倍長で, 指数部は 1 ワード以内の整数に限られている. ctrl() で bigﬂoat を選択することにより, 以後の浮動小数の入力は bigﬂoat として扱われる. 精度はデフォルトでは 10 進 9 桁程度であるが, setprec() により指定可能である.

[0] ctrl("bigfloat",1);1[1] eval(2^(1/2));
1.414213562373095048763788073031[2] setprec(100);9[3] eval(2^(1/2));
1.41421356237309504880168872420969807856967187537694807317...
eval() は, 引数に含まれる函数値を可能な限り数値化する函数である. setprec() で指定された桁数
は, 結果の精度を保証するものではなく, PARI 内部で用いられる表現のサイズを示すことに注意すべきである. (See section eval(), deval(), pari().)
4 複素数
複素数は, 有理数, 倍精度浮動小数, bigﬂoat を実部, 虚部として a+b*@i (@i は虚数単位) として与えられる数である. 実部, 虚部はそれぞれ real(), imag() で取り出せる.
5 小標数の有限素体の元
ここで言う小標数とは, 標数が 227 未満のもののことである. このような有限体は, 現在のところグレ
ブナ基底計算において内部的に用いられ, 有限体係数の分散表現多項式の係数を取り出すことで得られる. それ自身は属する有限体に関する情報は持たず, setmode() で設定されている素数 p を用いてGF (p) 上での演算が適用される.
6 大標数の有限素体の元標数として任意の素数がとれる. この型の数は, 整数に対し simp ff を適用することにより得られる.

33

7 標数 2 の有限体の元
標数 2 の任意の有限体の元を表現する. 標数 2 の有限体 F は, 拡大次数 [F :GF (2)] を n とすれば,
GF (2) 上既約な n 次多項式 f (t) により F = GF (2)[t]/(f (t)) とあらわされる. さらに, GF (2)[t] の
元 g は, f (t) も含めて自然な仕方でビット列とみなされるため, 形式上は, F の元 g mod f は, g, fをあらわす 2 つのビット列で表現することができる. F の元を入力するいくつかの方法が用意されている.
@@ はその後ろに数字, 文字を伴って, ヒストリや特殊な数をあらわすが, 単独で現れた場合には,
F = GF (2)[t]/(f (t)) における t mod f をあらわす. よって, @ の多項式として F の元を入力できる. (@^10+@+1 など)
ptogf2n 任意変数の 1 変数多項式を, ptogf2n() により対応する F の元に変換する.
ntogf2n 任意の自然数を, 自然な仕方で F の元とみなす. 自然数としては, 10 進, 16 進 (0x で始まる), 2 進 (0b で始まる) で入力が可能である.
その他 多項式の係数を丸ごと F の元に変換するような場合, simp ff() により変換できる.
8 位数 pn の有限体の元位数が pn (p は任意の素数, n は正整数) は, 標数 p および GF (p) 上既約な n 次多項式 m(x) を
setmod ff により指定することにより設定する. この体の元は m(x) を法とする GF (p) 上の多項式として表現される.
9 位数 pn の有限体の元(小位数) 位数が pn の有限体 (pn が 229 以下, p が 214 以上なら n は 1) は, 標数 p および拡大次数n を setmod ff() により指定することにより設定する. この体の 0 でない元は, p が 214 未満の場合,
GF (pn ) の乗法群の生成元を固定することにより, この元のべきとして表される. これにより, この体の0 でない元は, このべき指数として表現される. p が 214 以上の場合は通常の剰余による表現となるが,共通のプログラムで双方の場合を扱えるようにこのような仕様となっている.
10 位数 pn の小位数有限体の代数拡大の元
前項の, 位数が pn の小位数有限体の m 次拡大の元である. 標数 p および拡大次数 n, m を
setmod ff() により指定することにより設定する. 基礎体上の m 次既約多項式が自動生成され, その代数拡大の生成元の定義多項式として用いられる. 生成元は @s である.
11 分散表現の代数的数
See section 代数的数に関する演算. 小標数有限素体以外の有限体は setmod ff() で設定する. 有限体の元どうしの演算では, 一方が有理数の場合には, その有理数は自動的に現在設定されている有限体の元に変換され, 演算が行われる.
不定元の型
多項式の変数となり得る対象を不定元とよぶ. Asir では, 英小文字で始まり, 任意個のアルファベット, 数
字, ‘ ’ からなる文字列を不定元として扱うが, その他にもシステムにより不定元として扱われるものがいく
つかある. Asir の内部形式としては, これらは全て多項式としての型を持つが, 数と同様, 不定元の型により区別される.

2.9.3

0 一般不定元
英小文字で始まる文字列. 多項式の変数として最も普通に用いられる.

[0] [vtype(a),vtype(aA_12)];[0,0]
1 未定係数 uc() は, ‘_’ で始まる文字列を名前とする不定元を生成する. これらは, ユーザが入力できないというだけで, 一般不定元と変わらないが, ユーザが入力した不定元と衝突しないという性質を利用して未定係数の自動生成などに用いることができる.
[1] U=uc();_034

[2] vtype(U);12 函数形式
組み込み函数, ユーザ函数の呼び出しは, 評価されて何らかの Asir の内部形式に変換されるが, sin(x),cos(x+1) などは, 評価後もそのままの形で存在する. これは函数形式と呼ばれ, それ自身が 1 つの不定元として扱われる. またやや特殊な例として, 円周率 @pi や自然対数の底 @e も函数形式として扱われる.

[3] V=sin(x);sin(x)[4] vtype(V);2[5] vars(V^2+V+1);[sin(x)]3 函数子函数呼び出しは, fname(args) という形で行なわれるが, fname の部分を函数子と呼ぶ. 函数子には, 函数の種類により組み込み函数子, ユーザ定義函数子, 初等函数子などがあるが, 函数子は単独で不定元として機能する.

[6] vtype(sin);32.10 ユーザ言語 Asir
Asir の組み込み函数は, 因数分解, GCD などの計算を行うもの, ファイル入出力を行うもの, あるいは数式の一部を取り出すものなどさまざまなものが用意されているが, ユーザが実際に行いたいことを実行させるためには一般にはユーザ言語によるプログラムを書く必要がある. ユーザ言語も Asir と呼ばれる. 以下では,
ユーザ言語の文法規則および実際のユーザ言語プログラムを例としたプログラムの書き方について述べる.
2.10.1 文法（C 言語との違い）
Asir の文法は C 言語に準拠している. おもな相違点は次の通りである. 以下で, 変数とは Asir におけるプ
ログラム用の変数, すなわち大文字で始まる文字列を意味することとする.
• 変数の型がない.
既に説明したとおり, Asir で扱われる対象自身は全て何らかの型を持っている. しかし, プログラム変数自体は, どのような対象でも代入できるという意味で型がないのである.

[0] A = 1;
1
[1] type(A);1[2] A = [1,2,3];[1,2,3][3] type(A);4• 函数内の変数は, デフォルトでは仮引数をこめてすべて局所変数. ただし, extern 宣言された変数は,トップレベルにおける大域変数となる. すなわち, 変数のスコープは大域変数と局所変数の 2 種類に単35

純化されている. トップレベル, すなわちプロンプトに対して入力された変数は全て大域変数として登録される. また函数内では次のいずれかとなる. 函数が定義されるファイルにおいて, その函数定義以前に, ある変数が extern 宣言されている場合, 函数内のその変数も大域変数として扱われる. extern
宣言されていない変数はその函数に局所的となる.

% cat afo
def afo() { return A;}
extern A$
def bfo() { return A;}
end$% asir[0] load("afo")$[5] A = 1;
1
[6] afo();
0[7] bfo();
1• プログラム変数は大文字で始まり, 不定元, 函数は小文字で始まる.
この点は, 既存の数式処理システムのほとんどと異なる点である. Asir がこの仕様を採用したのは,ユーザが不定元のつもりで使用した変数になんらかの値が代入されていた場合に混乱を招く, という,
既存のシステムにありがちな状況を避けるためである.
• switch 文, goto がない.
goto がないため, 多重ループを一度に抜けるのがやや複雑になる場合がある.
• コンマ式は, for(A;B;C) または, while(A) の A, B, C にのみ使うことができる.
これは, リストを正式なオブジェクトとして加えたことによる.
以上は制限であるが, 拡張としては次の点が挙げられる.

• 有理式に対する計算を, 通常の C における計算と同様にできる.
• リストが扱える. 構造体を用いるまでもない要素の集合体を, リストで表すことができ, C で直接書く場合に比較してプログラムが短く, 読みやすく書ける.
• ユーザ定義函数における一行ヘルプ. Emacs-Lisp に類似した機能である. 詳しくは, See section ユー
ザ定義函数 を見よ.
• ユーザ定義函数におけるオプション指定. これに関しては, See section オプション指定.
Asir では次の語句がキーワードとして定められている.
• C 言 語 に 由 来: break, continue, do, else, extern, for, if, return, static, struct,
while• C 言語からの拡張: def, endmodule, function, global, local, localf, module• 函数: car, cdr, getopt, newstruct, map, pari, quote, recmap, timer
ユーザ定義函数
ユーザによる函数の定義は ‘def’ 文で行う. 文法エラーは読み込み時にある程度チェックされ, おおよその場所が表示される. 既に (引数の個数に関係なく) 同名の函数が定義されている場合には, その函数は再定義される. ctrl() 函数により verbose フラグが on になっている場合,

2.10.2

afo() redefined.

36

というメッセージが表示される. ある函数の定義において, まだ未定義の函数を呼び出していても, 定義時にはエラーにならない. 実行時に未定義の函数を呼び出そうとした場合にエラーとなる.

deff(X) {
if ( !X )return 1;
else
return X * f(X-1);}
def c(N){A = newvect(N+1); A[0] = B = newvect(1); B[0] = 1;
for ( K = 1; K <= N; K++ ) {A[K] = B = newvect(K+1); B[0] = B[K] = 1;
for ( P = A[K-1], J = 1; J < K; J++ )B[J] = P[J-1]+P[J];}return A;}
def add(A,B)"add two numbers."{
return A+B;}
2 つ目の例では, 長さ N + 1 のベクトル (A とする) が返される. A[I] は長さ I+1 の配列であり, そのそれぞれの要素がを要素とする配列である.
3 つ目の例では, 引数並びのあとに文字列が置かれているが、これは Emacs-Lisp の関数定義に類似の機能
で、ヘルプ用の文字列である。この例の場合、help(add) によってこの文字列が出力される。
参照 section help.
以下では, C によるプログラミングの経験がない人のために, Asir 言語によるプログラムの書き方を解説する.
変数および不定元
既に述べた通り, Asir においてはプログラム変数と不定元を明確に区別している.

2.10.3
変数

大文字で始まり, アルファベット, 数字, ‘_’ からなる文字列 変数あるいはプログラム変数とは, Asirのさまざまな型の内部形式を格納するための箱であり, 格納された内部形式が, この変数の値である. 変数が式の要素として評価される時は, そこに収められた値に置き換えられる. すなわち, 内部形式の中にはプログラム変数は現れない. 変数は全て 0 で初期化されている.

[0] X^2+X+1;
1[1] X=2;
2[2] X^2+X+1;
37

7
不定元 小文字で始まり, アルファベット, 数字, ‘_’ からなる文字列, またはシングルクオートで囲まれた文
字列, もしくは函数形式. 不定元とは, 多項式環を構成する際に添加される変数をいう. Asir においては, 不定元は値をもたない超越的な元であり, 不定元への値の代入は許されない.

[3] X=x;x[4] X^2+X+1;x^2+x+1[5] A=’Dx’*(x-1)+x*y-y;(y+Dx)*x-y-Dx[6] function foo(x,y);[7] B=foo(x,y)*x^2-1;
foo(x,y)*x^2-1
2.10.4 引数
def sum(N) {for ( I = 1, S = 0; I <= N; I++ )S += I;
return S;}
これは, 1 から N までの自然数の和を求める函数 sum() の定義である. この例における sum(N) の N が引数である. この例は, 1 引数函数の例であるが, 一般に引数の個数は任意であり, 必要なだけの個数を ‘,’ で区切って指定することができる. 引数は値が渡される. すなわち, 引数を受けとった側が, その引数の値を変更しても, 渡した側の変数は変化しない. ただし, 例外がある. それは, ベクトル, 行列を引数に渡した場合である.
この場合も, 渡された変数そのものを書き替えることは, その函数に局所的な操作であるが, 要素を書き換えた
場合, それは, 呼び出し側のベクトル, 行列の要素を書き換えることになる.

def clear_vector(M) {/* M is expected to be a vector */L = size(M)[0];for ( I = 0; I < L; I++ )M[I] = 0;}
この函数は, 引数のベクトルを 0 ベクトルに初期化するための函数である. また, ベクトルを引数に渡すことにより, 複数の結果を引数のベクトルに収納して返すことができる. 実際には, このような場合には, 結果をリストにして返すこともできる. 状況に応じて使いわけすることが望ましい.

2.10.5 コメント
C と同様 ‘/*’ と ‘*/’ で囲まれた部分はコメントとして扱われる.
/** This is a comment.
*/38

def afo(X) {コメントは複数行に渡っても構わないが, 入れ子にすることはできない. ‘/*’ がいくつあっても最初のもののみが有効となり, 最初に現れた ‘*/’ でコメントは終了したと見なされる. プログラムなどで, コメントを含む可能性がある部分をコメントアウトした場合には, #if 0, #endif を使えばよい. (See section プリプロセッ
サ.)

#if 0
def bfo(X) {/* empty */}#endif
2.10.6 文Asir のユーザ函数は,
def 名前 (引数, 引数,..., 引数) {
文
文

...
文

}
という形で定義される. このように, 文は函数の基本的構成要素であり, プログラムを書くためには, 文がどのようなものであるか知らなければならない. 最も単純な文として, 単文がある. これは,S = sum(N);のように, 式に終端記号 (‘;’ または \tt ‘$’) をつけたものである. この単文及び類似の return 文, break
文などが文の最小構成単位となる. if 文や for 文の定義 (section 文法の詳細) を見ればわかる通り, それらの本体は, 単なる一つの文として定義されている. 通常は, 本体には複数の文が書けることが必要となる. このような場合, ‘{’ と ‘}’ で文の並びを括って, 一つの文として扱うことができる. これを複文と呼ぶ.

if ( I == 0 ) {J = 1;
K = 2;
L = 3;}‘}’ の後ろには終端記号は必要ない. なぜなら, ‘’ 文並び ‘’ が既に文となっていて, if 文の要請を満たしているからである.
2.10.7 return 文
return 文は,return 式;
return;の 2 つの形式がある. いずれも函数から抜けるための文である. 前者は函数の値として 式 を返す. 後者では, 函数の値として何が返されるかはわからない.

39

2.10.8 if 文
if 文にはif ( 式 )文

if ( 式 )
及び

文

else
文
の 2 種類がある. これらの動作は明らかであるが, 文の位置に if 文が来た場合に注意を要する. 次の例を考えてみよう.

if ( 式 )if ( 式 ) 文
else文
この場合, 字下げからは, else 以下は, 最初の if に対応するように見えるが, パーザは, 自動的に 2 番目のif に対応すると判断する. すなわち, 2 種類の if 文を許したために, 文法に曖昧性が現れ, それを解消するた
めに,else 以下は, 最も近い if に対応するという規則が適用されるのである. 従って, この例は,if ( 式 ) {if ( 式 ) 文 else 文}という意味となる. 字下げに対応させるためには,if ( 式 ) {if ( 式 ) 文} else文としなければならない.
関数の中でなく, top level で if 文を用いるときは $ または ; で終了する必要がある. これらがないと次の文がよみとばされる.
ループ
ループを構成する文は, while 文, for 文, do 文の 3 種類がある.

2.10.9• while 文
形式は,while ( 式 ) 文
で, これは, 式 を評価して, その値が 0 でない限り 文 を実行するという意味となる. たとえば 式 が 1ならば, 単純な無限ループとなる.
• for 文
形式は,for ( 式並び-1; 式; 式並び-2 ) 文
で, これは式並び −1 (を単文並びにしたもの)

40

while ( 式 ) {文
式並び$-2$ (を単文並びにしたもの)}と等価である.

• do 文do {文} while ( 式 )は, 先に 文を実行してから条件式による判定を行う所が while 文と異なっている. ループを抜け出す手段として, break 文及び return 文がある. また, ループの制御をある位置に移す手段として continue
文がある.

• breakbreak 文は, それを囲むループを一つだけ抜ける.
• return
return 文は, 一般に函数から抜けるための文であり, ループの中からでも有効である.
• continue
continue 文は, ループの本体の文の末端に制御を移す. 例えば for 文では, 最後の式並びの実行を行い, while 文では条件式の判定に移る.
構造体定義
構造体とは, 各成分の要素が名前でアクセスできる固定長配列と思ってよい. 各構造体は名前で区別される.
構造体は, struct 文により宣言される. 構造体が宣言されるとき, asir は内部で構造体のそれぞれの型に固有の識別番号をつける. この番号は, 組み込み関数 str type() により取得できる. ある型の構造体は, 組み込み関数 newstruct() により生成される. 構造体の各メンバは, 演算子 -> によりアクセスする. メンバが構造体の場合, -> による指定は入れ子にできる.

2.10.10[1] struct rat {num,denom};
0[2] A = newstruct(rat);{0,0}[3] A->num = 1;
1
[4] A->den = 2;
2
[5] A;{1,2}[6] struct_type(A);1
さまざまな式
主な式の構成要素としては, 次のようなものがある.

2.10.11• 加減乗除, 冪
冪は, ‘^’ により表す. 除算 ‘/’ は, 体としての演算に用いる. 例えば, 2/3 は有理数の 2/3 を表す. 整41

数除算, 多項式除算 (剰余を含む演算) には別途組み込み函数が用意されている.

x+1

A^2*B*afo X/3• インデックスつきの変数
ベクトル, 行列, リストの要素はインデックスを用いることにより取り出せる. インデックスは 0 から始まることに注意する. 取り出した要素がベクトル, 行列, リストなら, さらにインデックスをつけることも有効である.
V[0] M[1][2]• 比較演算等しい (‘==’), 等しくない (‘!=’), 大小 (‘>’, ‘<’, ‘>=’, ‘<=’) の 2 項演算がある. 真ならば有理数の 1, 偽ならば 0 を値に持つ.
• 論理式
論理積 (‘&&’), 論理和 (‘||’) の 2 項演算と, 否定 (‘!’) が用意されている. 値はやはり 1, 0 である.
• 代入
通常の代入は ‘=’ で行う. このほか, 算術演算子と組み合わせて特殊な代入を行うこともできる (‘+=’,‘-=’, ‘*=’, ‘/=’, ‘^=’)A = 2

A *= 3 (これは A = A*3 と同じ; その他の演算子も同様)• 函数呼び出し
函数呼び出しも式の一種である.
• ‘++’, ‘--’これらは, 変数の前後について, それぞれ次のような操作, 値を表す.

A++
A-++A
--A

値は元の A の値, A = A+1
値は元の A の値, A = A-1
A = A+1, 値は変化後の値
A = A-1, 値は変化後の値

2.10.12 プリプロセッサ
Asir のユーザ言語は C 言語を模したものである. C の特徴として, プリプロセッサ cpp によるマクロ展
開, ファイルのインクルードがあるが, Asir においてもユーザ言語ファイルの読み込みの際 cpp を通してから読み込むこととした. これによりユーザ言語ファイル中で #include, #define, #if などが使える.
• #include
UNIX では インクルードファイルは, Asir のライブラリディレクトリ (環境変数 ASIR_LIBDIR で指定されたディレクトリ) と #include が書かれているファイルと同じディレクトリをサーチする. UNIX以外では cpp に特に引数を渡さないため, #include が書かれているファイルと同じディレクトリのみをサーチする.
• #define
これは, C におけるのと全く同様に用いることができる.
• #if/*, */ によるコメントは入れ子にできないので, プログラムの大きな部分をコメントアウトする際に,#if 0, #endif を使うと便利である.
次の例は, ‘defs.h’ にあるマクロ定義である.

#define ZERO 0#define NUM 1

42

#define POLY 2#define RAT 3#define LIST 4#define VECT 5#define MAT 6#define STR 7#define N_Q 0#define N_R 1#define N_A 2#define N_B 3#define N_C 4#define V_IND 0#define V_UC 1#define V_PF 2#define V_SR 3#define isnum(a) (type(a)==NUM)#define ispoly(a) (type(a)==POLY)#define israt(a) (type(a)==RAT)#define islist(a) (type(a)==LIST)#define isvect(a) (type(a)==VECT)#define ismat(a) (type(a)==MAT)#define isstr(a) (type(a)==STR)#define FIRST(L) (car(L))#define SECOND(L) (car(cdr(L)))#define THIRD(L) (car(cdr(cdr(L))))#define FOURTH(L) (car(cdr(cdr(cdr(L)))))#define DEG(a) deg(a,var(a))#define LCOEF(a) coef(a,deg(a,var(a)))#define LTERM(a) coef(a,deg(a,var(a)))*var(a)^deg(a,var(a))#define TT(a) car(car(a))#define TS(a) car(cdr(car(a)))#define MAX(a,b) ((a)>(b)?(a):(b))
C のプリプロセッサを流用しているため, プリプロセッサは $ を正しく処理できない. たとえば LIST が定義されていても LIST$は置換されない. $ の前に空白をおいて LIST $ と書かないといけない.
オプション指定
ユーザ定義関数が N 変数で宣言された場合, その関数は, N 変数での呼び出しのみが許される.

2.10.13[0] def factor(A) { return fctr(A); }[1] factor(x^5-1,3);
evalf : argument mismatch in factor()
return to toplevel
不定個引数の関数をユーザ言語で記述したい場合, リスト, 配列を用いることで可能となるが, 次のようなよ
り分かりやすい方法も可能である.

43

% cat factor
def factor(F){Mod = getopt(mod);
ModType = type(Mod);if ( ModType == -1 ) /* ’mod’ is not specified. */return fctr(F);else if ( ModType == 0 ) /* ’mod’ is a number */return modfctr(F,Mod);}[0] load("factor")$[1] factor(x^5-1);[[1,1],[x-1,1],[x^4+x^3+x^2+x+1,1]][2] factor(x^5-1|mod=11);[[1,1],[x+6,1],[x+2,1],[x+10,1],[x+7,1],[x+8,1]]
2 番目の factor() の呼び出しにおいて, 関数定義の際に宣言された引数 x^5-1 の後ろに mod=11 が置かれている. これは, 関数実行時に, mod という keyword に対して 11 という値を割り当てることを指定している.
これをオプション指定と呼ぶことにする. この値は getopt(mod) で取り出すことができる. 1 番目の呼び出
しのように mod に対するオプション指定がない場合には, getopt(mod) は型識別子 −1 のオブジェクトを返す. これにより, 指定がない場合の動作を if 文により記述できる. ‘|’ の後ろには, 任意個のオプションを,‘,’ で区切って指定することができる.
[100] xxx(1,2,x^2-1,[1,2,3]|proc=1,index=5);
さらに, オプションを key1=value1,key2=value2,... のように ‘,’ で区切って渡す代わりに, 特別なキー
ワード option_list とオプションリスト [["key1",value1],["key2",value2],...] を用いて渡すことも可能である.

[101] dp_gr_main([x^2+y^2-1,x*y-1]|option_list=[["v",[x,y]],["order",[[x,5,y,1]]]]);
特に, 引数なしの getopt() はオプションリストを返すので, オプションをとる関数から, オプションをとる関数を呼び出すときには有用である.

% cat foo.rr
def foo(F){OPTS=getopt();
return factor(F|option_list=OPTS);}[3] load("foo.rr")$[4] foo(x^5-1|mod=11);[[1,1],[x+6,1],[x+2,1],[x+10,1],[x+7,1],[x+8,1]]44

2.11 モジュール
ライブラリで定義されている関数, 変数をカプセル化する仕組みがモジュール (module) である. はじめにモジュールを用いたプログラムの例をあげよう.

module stack;static Sp $Sp = 0$static Ssize$
Ssize = 100$
static Stack $Stack = newvect(Ssize)$
localf push $localf pop $def push(A) {if (Sp >= Ssize) {print("Warning: Stack overflow\nDiscard the top"); pop();}Stack[Sp] = A;Sp++;}
def pop() {local A;
if (Sp <= 0) {print("Stack underflow"); return 0;}Sp--;
A = Stack[Sp];return A;}
endmodule;
def demo() {stack.push(1);stack.push(2);print(stack.pop());
print(stack.pop());}
モジュールは module モジュール名 〜 endmodule で囲む. モジュールは入れ子にはできない. モジュールの中だけで使う大域変数は static で宣言する. この変数はモジュールの外からは参照もできないし変更もできない. モジュールの外の大域変数は extern で宣言する.
モジュール内部で定義する関数は localf を用いて宣言しないといけない. 上の例では push と pop を宣言している. この宣言は必須である.
モ ジ ュ ー ル moduleName で 定 義 さ れ た 関 数 functionName を モ ジ ュ ー ル の 外 か ら 呼 ぶ に は
moduleName.functionName(引 数 1, 引 数 2, ... ) な る 形 式 で よ ぶ. モ ジ ュ ー ル の 中 か ら は, 関 数 名のみでよい. 次の例では, モジュールの外からモジュール stack で定義された関数 push, pop を呼んでいる.

45

stack.push(2);print( stack.pop() );2モジュールで用いる関数名は局所的である. つまりモジュールの外や別のモジュールで定義されている関数名と同じ名前が利用できる.
モジュール機能は大規模ライブラリの開発を想定している. ライブラリを必要に応じて分割ロードするには,関数 module definedp() を用いるのが便利である. デマンドロードはたとえば次のように行なえば良い.

if (!module_definedp("stack")) load("stack.rr") $asir では局所変数の宣言は不要であった. しかしモジュール stack の例を見れば分かるように, local A;
なる形式で局所変数を宣言できる. キーワード local を用いると, 宣言機能が有効となる. 宣言機能を有効にすると, 宣言されてない変数はロードの段階でエラーを起こす. 変数名のタイプミスによる予期しないトラブ
ルを防ぐには, 宣言機能を有効にしてプログラムするのがよい.
モジュール内の関数をそのモジュールが定義される前に呼び出すような関数を書くときには, その関数の前でモジュールを次のようにプロトタイプ宣言しておく必要がある.
/* Prototype declaration of the module stack */module stack;localf push $localf pop $endmodule;
def demo() {print("----------------");
stack.push(1);print(stack.pop());
print("---------------");}
module stack;/* The body of the module stack */endmodule;
モジュールの中からトップレベルで定義されている関数を呼ぶには, 下の例のように :: を用いる.

def afo() {S = "afo, afo";
return S;}
module abc;
localf foo,afo $def foo() {G = ::afo();return G;}
46

def afo() {return "afo, afo in abc";}
endmodule;
end$[1200] abc.foo();afo, afo[1201] abc.afo();afo, afo in abc

2.12 デバッガ

2.12.1 デバッガとはC 言語で書かれたプログラムのためのデバッガ dbx は, ソースレベルでのブレークポイントの設定, ステッ
プ実行, 変数の参照などが可能な強力なデバッガである. Asir では, dbx 風のデバッガを用意している. デバッグモードに入るには, トップレベルで debug; と入力する.
[10] debug;(debug)その他, 次の方法, あるいは状況でデバッグモードに入る.

• 実行中ブレークポイントに達した場合• 割り込みで ‘d’ を選択した場合• 実行中エラーを起こした場合 この場合, 実行の継続は不可能であるが, 直接のエラーの原因となった• ユーザ定義函数の文を表示してデバッグモードに入るため, エラー時における変数の値を参照でき, デバッグに役立たせることができる.
• error() が呼び出された場合コマンドの解説
コマンドは dbx のコマンドの内必要最小限のものを採用した. 更に, gdb のコマンドからもいくつか便利なものを採用した. 実際の機能は dbx とほぼ同様であるが, step, next は, 次の行ではなく次の文を実行する.
従って, 1 行に複数の文がある場合は, その文の数だけ next を実行しなければ次の行に進めない. また, dbxと同様 ‘.dbxinit’ を読み込むので, dbx と同じ alias を使うことができる.

2.12.2step
次の文を実行する. 次の文が函数を含むとき, その函数に入る.

next
次の文を実行する.

ﬁnish
現在実行中の函数の実行が終了した時点で再びデバッグモードに入る. 誤って step を実行した場合に有効である.

contquit
デバッグモードから抜け, 実行を継続する.

up [n]
47

スタックフレームを 1 段 (引数 n がある時は n 段) 上がる. これにより, そのスタックフレームに属す
る変数の値の参照, 変更ができる.

down [n]スタックフレームを 1 段 (引数 n がある時は n 段) 下がる.

frame [n]引数がないとき, 現在実行中の函数を表示する. 引数があるとき, スタックフレームを番号 n のものに設定する. ここでスタックフレームの番号とは where により表示される呼び出し列において, 先頭に表示される番号のことである.

list [startline]
list function
現在行, または startline, または function の先頭から 10 行ソースファイルを表示する.
print expr
expr を表示する.
func function
対象函数を function に設定する.
stop at sourceline [if cond]stop in function
sourceline 行目, または function の先頭にブレークポイントを設定する. ブレークポイントは, 函数が再定義された場合自動的に取り消される. if が続く場合, cond が評価され, それが 0 でない場合に実行が中断し, デバッグモードに入る.
trace expr at sourceline [if cond]
trace expr in function
stop と同様であるが, trace では単に expr を表示するのみで, デバッグモードには入らない.
delete n
ブレークポイント n を取り消す.
statusブレークポイントの一覧を表示する.
where
現在の停止点までの呼び出し列を表示する.
alias alias command
command に alias の別名を与える.

print の引数として, トップレベルにおけるほとんどすべての式がとれる. 通常は, 変数の内容の表示が主であるが, 必要に応じて次のような使い方ができる.
• 変数の書き換え

実行中のブレークポイントにおいて, 変数の値を変更して実行を継続させたい場合,
次のような操作を行えばよい.

(debug) print A
A = 2(debug) print A=1
A=1 = 1(debug) print A
A = 1• 函数の呼び出し

函数呼び出しも式であるから, print の引数としてとれる.

(debug) print length(List)
length(List) = 14
この例では, 変数 List に格納されているリストの長さを length() により調べている.

48

(debug) print ctrl("cputime",1)ctrl("cputime",1) = 1
この例は, 計算開始時に CPU 時間の表示の指定をし忘れた場合などに, 計算途中でデバッグモードから指定を行えることを示している. また, 止むを得ず計算を中断しなければならない場合, デバッグモードから bsave() などのコマンドにより途中結果をファイルに保存することもできる.

(debug) print bsave(A,"savefile")
bsave(A,"savefile") = 1
デバッグモードからの函数呼び出しで注意すべきことは, print の引数がユーザ定義函数の呼び出しを含む場合, その函数呼び出しでエラーが起こった場合に元の函数の実行継続が不可能になる場合があるということである.
デバッガの使用例
ここでは, 階乗を再帰的に計算させるユーザ定義函数を例として, デバッガの実際の使用法を示す.

2.12.3% asir[0] load("fac")$[3] debug$(debug) list factorial
1
def factorial(X) {2
if ( !X )3
return 1;
4else
5
return X * factorial(X - 1);
6
}
7
end$
(debug) stop at 5<-- ブレークポイントの設定(0) stop at "./fac":5(debug) quit<-- デバッグモードを抜ける[4] factorial(6);<-- factorial(6) の呼び出し
stopped in factorial at line 5 in file "./fac"5
return X * factorial(X - 1);(debug) where<-- ブレークポイントまでの呼び出し列の表示
factorial(), line 5 in "./fac"(debug) print X<-- X の値の表示
X = 6(debug) step<-- ステップ実行 (函数に入る)
stopped in factorial at line 2 in file "./fac"
2 if ( !X )(debug) where
factorial(), line 2 in "./fac"factorial(), line 5 in "./fac"(debug) print X
X = 5(debug) delete 0<-- ブレークポイント 0 の消去
49

(debug) cont720[5] quit;<-- 実行継続<-- 結果 = 6!

デバッガの初期化ファイルの例
前に述べた通り, Asir は, 起動時に ‘$HOME/.dbxinit’ を読み込む. このファイルは, dbx のさまざまな
初期設定用のコマンドを記述しておくファイルであるが, Asir は, alias 行のみを認識する. 例えば,

2.12.4% cat ~/.dbxinit
alias n next
alias c contalias p print
alias s step
alias d delete
alias r run
alias l list
alias q quit
なる設定により, print, cont など, デバッグモードにおいて頻繁に用いられるコマンドが, それぞれ p, c な
ど, 短い文字列で代用できる. また, デバッグモードにおいて, alias コマンドにより alias の追加ができる.

lex_hensel(La,[a,b,c],0,[a,b,c],0);
stopped in gennf at line 226 in file "/home/usr3/noro/asir/gr"
226
N = length(V); Len = length(G); dp_ord(O); PS = newvect(Len);(debug) p V
V = [a,b,c](debug) c...
2.12.5 文法の詳細<式>:‘(’<式>‘)’<式> <二項演算子> <式>‘+’ <式>‘-’ <式><左辺値><左辺値> <代入演算子> <式><左辺値> ‘++’<左辺値> ‘--’‘++’ <左辺値>‘--’ <左辺値>‘!’ <式><式> ‘?’ <式> ‘:’ <式><函数> ‘(’ <式並び> ‘)’<函数> ‘(’ <式並び> ‘|’ <オプション並び> ‘)’50

<文字列><指数ベクトル>
<アトム>
<リスト>
(See section さまざまな式.)<左辺値>:<変数> [‘[’<式>‘]’]*<二項演算子>:‘+’ ‘-’ ‘*’ ‘/’ ‘%’ ‘^’(冪)‘==’ ‘!=’ ‘<’ ‘>’ ‘<=’ ‘>=’ ‘&&’ ‘||’
<代入演算子>:‘=’ ‘+=’ ‘-=’ ‘*=’ ‘/=’ ‘%=’ ‘^=’<式並び>:<空><式> [‘,’ <式>]*<オプション>:alphabet で始まる文字列 ‘=’ <式><オプション並び>:<オプション><オプション> [‘,’ <オプション>]*<リスト>:‘[’ <式並び> ‘]’<変数>:
大文字で始まる文字列 (X,Y,Japan など)(See section 変数と不定元.)<函数>:
小文字で始まる文字列 (fctr,gcd など)<アトム>:<不定元><数><不定元>:
小文字で始まる文字列 (a,bCD,c1_2 など)

51

(See section 変数と不定元.)
<数>:
<有理数>
<浮動小数><代数的数><複素数>(See section 数の型.)<有理数>:
0, 1, -2, 3/4<浮動小数>:
0.0, 1.2e10<代数的数>:
newalg(x^2+1), alg(0)^2+1(See 代数的数に関する演算)<複素数>:
1+@i, 2.3*@i<文字列>:‘"’ で囲まれた文字列<指数ベクトル>:‘<<’ <式並び> ‘>>’(See グレブナ基底の計算)<文>:<式> <終端><複文>‘break’ <終端>‘continue’ <終端>
‘return’ <終端>
‘return’ <式> <終端>‘if’ ‘(’ <式並び> ‘)’ <文>‘if’ ‘(’ <式並び> ‘)’ <文> ‘else’ <文>‘for’ ‘(’ <式並び> ‘;’ <式並び> ‘;’ <式並び> ‘)’ <文>‘do’ <文> ‘while’ ‘(’ <式並び> ‘)’ <終端>‘while’ ‘(’ <式並び> ‘)’ <文>‘def’ <函数> ‘(’ <式並び> ‘)’ ‘{’ <変数宣言> <文並び> ‘}’‘end(quit)’ <終端>
(See section 文.)
52

<終端>:‘;’ ‘$’<変数宣言>:[‘extern’ <変数> [‘,’ <変数>]* <終端>]*<複文>:‘{’ <文並び> ‘}’<文並び>:[<文>]*

2.13 有限体における演算
2.13.1 有限体の表現および演算
Asir においては, 有限体は, 正標数素体 GF (p), 標数 2 の有限体 GF (2n ), GF (p) の n 次拡大 GF (pn ) が定義できる. これらは全て, setmod ff() により定義される.
[0] P=pari(nextprime,2^50);
1125899906842679[1] setmod_ff(P);1125899906842679[2] field_type_ff();
1[3] load("fff");
1[4] F=defpoly_mod2(50);x^50+x^4+x^3+x^2+1[5] setmod_ff(F);x^50+x^4+x^3+x^2+1[6] field_type_ff();
2[7] setmod_ff(x^3+x+1,1125899906842679);[1*x^3+1*x+1,1125899906842679][8] field_type_ff();
3[9] setmod_ff(3,5);[3,x^5+2*x+1,x][10] field_type_ff();
4
setmod ff() は, さまざまなタイプの有限体を基礎体としてセットする. 引数が正整数 p の場合 GF (p), n次多項式 f (x) の場合, f (x) mod 2 を定義多項式とする GF (2n ) をそれぞれ基礎体としてセットする. また,
有限素体の有限次拡大も定義できる. 詳しくは 数の型を参照. setmod ff() においては引数の既約チェックは行わず, 呼び出し側が責任を持つ.
基礎体とは, あくまで有限体の元として宣言あるいは定義されたオブジェクトが, セットされた基礎体の演53

算に従うという意味である. 即ち, 有理数どうしの演算の結果は有理数となる. 但し, 四則演算において一方のオペランドが有限体の元の場合には, 他の元も自動的に同じ有限体の元と見なされ, 演算結果も同様になる.
0 でない有限体の元は, 数オブジェクトであり, 識別子の値は 1 である. さらに, 0 でない有限体の元の数識
別子は, GF (p) の場合 6, GF (2n ) の場合 7 となる.
有限体の元の入力方法は, 有限体の種類により様々である. GF (p) の場合, simp ff() による.

[0] P=pari(nextprime,2^50);
1125899906842679[1] setmod_ff(P);1125899906842679[2] A=simp_ff(2^100);3025[3] ntype(@@);
6
また, GF (2n ) の場合いくつかの方法がある.

[0] setmod_ff(x^50+x^4+x^3+x^2+1);x^50+x^4+x^3+x^2+1[1] A=@;(@)[2] ptogf2n(x^50+1);(@^50+1)[3] simp_ff(@@);(@^4+@^3+@^2)[4] ntogf2n(2^10-1);(@^9+@^8+@^7+@^6+@^5+@^4+@^3+@^2+@+1)
有限体の元は数であり, 体演算が可能である. @ は GF (2n ) の, GF (2) 上の生成元である. 詳しくは 数の型を参照.

2.13.2 有限体上での 1 変数多項式環の演算fff では, 有限体上の 1 変数多項式に対し, 無平方分解, DDF, 因数分解, 多項式の既約判定などの関数が定義されている.
いずれも, 結果は [因子, 重複度] のリストとなるが, 因子は monic となり, 入力多項式の主係数は捨てられる. 無平方分解は, 多項式とその微分との GCD の計算から始まるもっとも一般的なアルゴリズムを採用している.
有限体上での因数分解は, DDF の後, 次数別因子の分解の際に, Berlekamp アルゴリズムで零空間を求め,
基底ベクトルの最小多項式を求め, その根を Cantor-Zassenhaus アルゴリズムにより求める, という方法を実装している.
小標数有限体上での多項式環の演算小標数有限体係数の多項式に限り, 多変数多項式の因数分解が組み込み関数として実装されている. 関数はsffctr() である. また, modfctr() も, 有限素体上で多変数多項式の因数分解を行うが, 実際には, 内部で十分大きな拡大体を設定し, sffctr() を呼び出して, 最終的に素体上の因子を構成する, という方法で計算している.

2.13.3有限体上の楕円曲線に関する演算有限体上の楕円曲線に関するいくつかの基本的な演算が, 組み込み関数として提供されている.

2.13.454

楕円曲線の指定は, 長さ 2 のベクトル [a b] で行う. a, b は有限体の元で, setmod ff() で定義されている有限体が素体の場合, y 2 = x3 + ax + b, 標数 2 の体の場合 y 2 + xy = x3 + ax2 + b を表す.
楕円曲線上の点は, 無限遠点も込めて加法群をなす. この演算に関して, 加算 (ecm add ff()), 減算(ecm sub ff()) および逆元計算のための関数 (ecm chsgn ff()) が提供されている. 注意すべきは, 演算の対象となる点の表現が,無限遠点は 0. それ以外の点は, 長さ 3 のベクトル [x y z]. ただし, z は 0 でない. という点である. [xy z] は斉次座標による表現であり, アフィン座標では [x/z y/z] なる点を表す. よって, アフィン座標 [xy] で表現された点を演算対象とするには，[x y 1] なるベクトルを生成する必要がある. 演算結果も斉次座標で得られるが, z 座標が 1 とは限らないため, アフィン座標を求めるためには x, y 座標を z 座標で割る必要がある.

2.14 代数的数に関する演算
2.14.1 代数的数の表現
Asir においては, 代数体という対象は定義されない. 独立した対象として定義されるのは, 代数的数である.
代数体は, 有理数体に, 代数的数を有限個 順次添加した体として仮想的に定義される. 新たな代数的数は, 有理数および これまで定義された代数的数の多項式を係数とする 1 変数多項式を定義多項式として定義される.
以下, ある定義多項式の根として定義された代数的数を, root と呼ぶことにする.
[0] A0=newalg(x^2+1);(#0)[1] A1=newalg(x^3+A0*x+A0);(#1)[2] [type(A0),ntype(A0)];[1,2]
この例では, A0 は x2 + 1 = 0 の根, A1 は, その A0 を係数に含む x3 + A0 ∗ x + A0 = 0 の根として定義されている. newalg() の引数すなわち定義多項式には次のような制限がある.

1. 定義多項式は 1 変数多項式でなければならない.
2. newalg() の引数である定義多項式は, 代数的数を含む式の簡単化のために用いられる. この簡単化は,組み込み函数 srem() に相当する内部ルーチンを用いて行われる. このため, 定義多項式の主係数は,有理数になっている必要がある. 定義多項式の係数は すでに定義されている root の有理数係数多項式でなければならない.
3. 定義多項式は, その係数に含まれる全ての root を有理数に添加した体上で既約でなければならない.
newalg() が行う引数チェックは, 1 および 2 のみである. 特に, 引数の定義多項式の既約性は全くチェックされない. これは既約性のチェックが多大な計算量を必要とするためで, この点に関しては, ユーザの責任に任されている. 一旦 newalg() によって定義された代数的数は, 数としての識別子を持ち, また, 数の中では代数的数としての識別子を持つ. (type(), vtype() 参照.) さらに, 有理数と, root の有理式も同様に代数的数となる.
[87] N=(A0^2+A1)/(A1^2-A0-1);((#1+#0^2)/(#1^2-#0-1))[88] [type(N),ntype(N)];[1,2]
例からわかるように, root は #n と表示される. しかし, ユーザはこの形では入力できない. root は 変数に格納して用いるか, あるいは alg(n) により取り出す. また, 効率は落ちるが, 全く同じ引数 (変数は異なっていてもよい) により newalg() を呼べば, 新しい代数的数は定義されずに既に定義された ものが得られる.

55

[90] alg(0);(#0)[91] newalg(t^2+1);(#0)
root の定義多項式は, defpoly() により取り出せる.
[96] defpoly(A0);t#0^2+1[97] defpoly(A1);t#1^3+t#0*t#1+t#0
ここで現れた, t#0, t#1 はそれぞれ #0, #1 に対応する不定元である. これらもユーザが入力することはできない. var() で取り出すか, あるいは algv(n) により取り出す.

[98] var(@);
t#1[99] algv(0);
t#0
[100]
分散多項式による代数的数の表現
前節で述べたように, root を含む代数的数に対する簡単化はユーザの判断で行う必要がある. これに対し,
ここで解説するもう一つの代数的数の表現については, 加減乗除, ベキなどを行ったあと自動的に簡単化が行われる. この表現は, 逐次拡大の場合に特に効率よく計算が行われるよう設計されており, グレブナー基底関係の関数における係数体として用いることができる. この表現は 内部的には, DAlg と呼ばれるオブジェクトとして定義されている. DAlg は分数式の形で保持される. 分母は整数, 分子は整数係数の分散多項式である.
DAlg は，set field() によりあらかじめ設定された代数体の元として生成される. 生成方法は, newalg()
で生成された代数的数を含む数から algtodalg() で変換する, あるいは分散多項式から直接 dptodalg() で変換する，の 2 通りある. 一旦 DAlg 形式に変換されれば, 演算後に自動的に簡単化される.

2.14.2[0] A=newalg(x^2+1);(#0)[1] B=newalg(x^3+A*x+A);(#1)[2] set_field([B,A]);
0[3] C=algtodalg(A+B);((1)*<<1,0>>+(1)*<<0,1>>)[4] C^5;((-11)*<<2,1>>+(5)*<<2,0>>+(10)*<<1,1>>+(9)*<<1,0>>+(11)*<<0,1>>+(-1)*<<0,0>>)[5] 1/C;((2)*<<2,1>>+(-1)*<<2,0>>+(1)*<<1,1>>+(2)*<<1,0>>+(-3)*<<0,1>>+(-1)*<<0,0>>)/5
この例では, Q(a, b) (a2 + 1 = 0, b3 + ab + b = 0) において, (a + b)5 および 1/(a + b) を計算 (簡単化) している．分子である分散多項式の表示は, 分散多項式の表示をそのまま流用している．

56

代数的数の演算
前節で, 代数的数の表現, 定義について述べた. ここでは, 代数的数を用いた演算について述べる. 代数的数に関しては, 組み込み函数として提供されている機能はごく少数で, 大部分はユーザ定義函数により実現されている. ファイル は, sp で, gr と同様 Asir の標準ライブラリディレクトリにおかれている.

2.14.3[0] load("gr")$[1] load("sp")$あるいは, 常に用いるならば, $HOME/.asirrc に書いておくのもよい. root はその他の数と同様, 四則演算が可能となる. しかし, 定義多 項式による簡単化は自動的には行われないので, ユーザの判断で適宜行わなけ
ればならない. 特に, 分母が 0 になる場合に致命的なエラーとなるため, 実際に分母を持つ代数的数を生成する場合には細心の注意が必要となる. 代数的数の, 定義多項式による簡単化は, simpalg() で行う.

[49] T=A0^2+1;(#0^2+1)[50] simpalg(T);0simpalg() は有理式の形をした代数的数を, 多項式の形に簡単化する.
[39] A0=newalg(x^2+1);(#0)[40] T=(A0^2+A0+1)/(A0+3);((#0^2+#0+1)/(#0+3))[41] simpalg(T);(3/10*#0+1/10)[42] T=1/(A0^2+1);((1)/(#0^2+1))[43] simpalg(T);div : division by 0
stopped in invalgp at line 258 in file "/usr/local/lib/asir/sp"
258
return 1/A;
(debug)
この例では, 分母が 0 の代数的数を簡単化しようとして 0 による除算が生じ たため, ユーザ定義函数である simpalg() の中でデバッガが呼ばれたことを示す. simpalg() は, 代数的数を係数とする多項式の各係数を簡単化できる.

[43] simpalg(1/A0*x+1/(A0+1));(-#0)*x+(-1/2*#0+1/2)
代数的数を係数とする多項式の基本演算は, 適宜 simpalg() を呼ぶことを 除けば通常の場合と同様である
が, 因数分解などで頻繁に用いられるノルムの計算などにおいては, root を不定元に置き換える必要が出てくる. この場合, algptorat() を用いる.

[83] A0=newalg(x^2+1);(#0)[84] A1=newalg(x^3+A0*x+A0);

57

(#1)
[85] T=(2*A0+A1*A0+A1^2)*x+(1+A1)/(2+A0);(#1^2+#0*#1+2*#0)*x+((#1+1)/(#0+2))[86] S=algptorat(T);(((t#0+2)*t#1^2+(t#0^2+2*t#0)*t#1+2*t#0^2+4*t#0)*x+t#1+1)/(t#0+2)[87] algptorat(coef(T,1));t#1^2+t#0*t#1+2*t#0
このように, algptorat() は, 多項式, 数に含まれる root を, 対応する不定元, すなわち #n に対する t#nに置き換える. 既に述べたように, この不定元はユーザが入力することはできない. これは, ユーザの入力した不定元と, root に対応する不定元が一致しないようにするためである. 逆に, root に対応する不定元を, 対応
する root に置き換えるためには rattoalgp() を用いる.

[88] rattoalgp(S,[alg(0)]);(((#0+2)/(#0+2))*t#1^2+((#0^2+2*#0)/(#0+2))*t#1+((2*#0^2+4*#0)/(#0+2)))*x+((1)/(#0+2))*t#1+((1)/(#0+2))[89] rattoalgp(S,[alg(0),alg(1)]);(((#0^3+6*#0^2+12*#0+8)*#1^2+(#0^4+6*#0^3+12*#0^2+8*#0)*#1+2*#0^4+12*#0^3+24*#0^2+16*#0)/(#0^3+6*#0^2+12*#0+8))*x+(((#0+2)*#1+#0+2)/(#0^2+4*#0+4))[90] rattoalgp(S,[alg(1),alg(0)]);(((#0+2)*#1^2+(#0^2+2*#0)*#1+2*#0^2+4*#0)/(#0+2))*x+((#1+1)/(#0+2))[91] simpalg(@89);(#1^2+#0*#1+2*#0)*x+((-1/5*#0+2/5)*#1-1/5*#0+2/5)[92] simpalg(@90);(#1^2+#0*#1+2*#0)*x+((-1/5*#0+2/5)*#1-1/5*#0+2/5)
rattoalgp() は, 置換の対象となる root のリストを第 2 引数 にとり, 左から順に, 対応する不定元を置き換えて行く. この例は, 置換する順序を換えると簡単化を行わないことにより結果が一見異なるが, 簡単化により実は一致することを示している. algptorat(), rattoalgp() は, ユーザが独自の簡単化を行いたい場合などにも用いることができる.
2.14.4 代数体上での 1 変数多項式の演算
sp では, 1 変数多項式に限り, GCD, 因数分解およびそれらの応用として最小分解体を求める函数を提供している.
2.14.4.1

GCD

代数体上での GCD は cr gcda() により計算される. この函数はモジュラ演算および中国剰余定理により
代数体上の GCD を 計算するもので, 逐次拡大に対しても有効である.

[63] A=newalg(t^9-15*t^6-87*t^3-125);(#0)[64] B=newalg(75*s^2+(10*A^7-175*A^4-470*A)*s+3*A^8-45*A^5-261*A^2);(#1)[65] P1=75*x^2+(150*B+10*A^7-175*A^4-395*A)*x+(75*B^2+(10*A^7-175*A^4-395*A)*B+13*A^8-220*A^5-581*A^2)$

58

[66] P2=x^2+A*x+A^2$[67] cr_gcda(P1,P2);
27*x+((#0^6-19*#0^3-65)*#1-#0^7+19*#0^4+38*#0)
2.14.4.2

無平方分解，因数分解

無平方分解は, 多項式とその微分との GCD の計算から始まるもっとも一般的なアルゴリズムを採用している. 函数は asq() である.

[116] A=newalg(x^2+x+1);(#4)[117] T=simpalg((x+A+1)*(x^2-2*A-3)^2*(x^3-x-A)^2);x^11+(#4+1)*x^10+(-4*#4-8)*x^9+(-10*#4-4)*x^8+(16*#4+20)*x^7+(24*#4-6)*x^6+(-29*#4-31)*x^5+(-15*#4+28)*x^4+(38*#4+29)*x^3+(#4-23)*x^2+(-21*#4-7)*x+(3*#4+8)[118] asq(T);[[x^5+(-2*#4-4)*x^3+(-#4)*x^2+(2*#4+3)*x+(#4-2),2],[x+(#4+1),1]]
結果は通常と同様に, [因子, 重複度] のリストとなるが, 全ての因子の積は, もとの多項式と定数倍の差はあり得る. これは, 因子を整数係数にし て見やすくするためで, 因数分解でも同様である. 代数体上での因数分
解は, Trager によるノルム法を改良したもので, 特にある多項式に対し, その根を添加した体上でその多項式
自身を因数分解する場合に特に有効である.

[119] af(T,[A]);[[x^3-x+(-#4),2],[x^2+(-2*#4-3),2],[x+(#4+1),1]]
引数は 2 つで, 第 2 引数は, root のリストである. 因数分解は有理数体に, それらの root を添加した体上で行われる. root の順序には制限がある. すなわち, 後で定義されたものほど前の方にこなければならない. 並
べ換えは, 自動的には行われない. ユーザの責任となる. ノルムを用いた因数分解においては, ノルムの計算と整数係数 1 変数多項式の因数分解の効率が, 全体の効率を左右する. このうち, 特に高次の多項式の場合に後者において組合せ爆発により計算不能になる場合がしばしば生ずる.

[120] B=newalg(x^2-2*A-3);(#5)[121] af(T,[B,A]);[[x+(#5),2],[x^3-x+(-#4),2],[x+(-#5),2],[x+(#4+1),1]]
2.14.4.3

最小分解体

やや特殊な演算ではあるが, 前節の因数分解を反復適用することにより, 多項式の最小分解体を求めることができる. 函数は sp() である.

[103] sp(x^5-2);[[x+(-#1),2*x+(#0^3*#1^3+#0^4*#1^2+2*#1+2*#0),2*x+(-#0^4*#1^2),
2*x+(-#0^3*#1^3),x+(-#0)],[[(#1),t#1^4+t#0*t#1^3+t#0^2*t#1^2+t#0^3*t#1+t#0^4],[(#0),t#0^5-2]]]
sp() は 1 引数で, 結果は [1 次因子のリスト, [[root, algptorat(定義多項式)] のリスト] なるリストである. 第 2 要素の [root,algptorat(定義多項式)] のリストは, 右から順に, 最小分解体が得られるまで添加していった root を示す. その定義多項式は, その直前までの root を添加した体上で既約であることが保証
59

されている. 結果の第 1 要素である 1 次因子のリストは, 第 2 要素の root を全て添加した体上での, sp()の引数の多項式の全ての因子を表す. その体は 最小分解体となっているので, 因子は全て 1 次となるわけである. af() と同様, 全ての因子の積は, もとの多項式と定数倍の差はあり得る.

2.15 グレブナー基底の計算
分散表現多項式
分散表現多項式とは, 多項式の内部形式の一つである. 通常の多項式 (type が 2) は, 再帰表現と呼ばれる形式で表現されている. すなわち, 特定の変数を主変数とする 1 変数多項式で, その他の変数は, その 1 変数多項式の係数に, 主変数を含まない多項式として現れる. この係数が, また, ある変数を主変数とする多項式となっていることから再帰表現と呼ばれる. これに対し, 多項式を, 変数の冪積と係数の積の和として表現したものを分散表現と呼ぶ. グレブナ基底計算においては, 単項式に注目して操作を行うため多項式が分散表現されている方がより効率のよい演算が可能になる. このため, 分散表現多項式が, 識別子 9 の型として Asir のトップレベルから利用可能となっている. ここで, 後の説明のために, いくつかの言葉を定義しておく.

2.15.1

項 (term)
変数の冪積. すなわち, 係数 1 の単項式のこと, Asir においては,<<0,1,2,3,4>>という形で表示され, また, この形で入力可能である. この例は, 5 変数の項 を示す. 各変数を a, b, c,d, e とすると この項は b*c^2*d^3*e^4 を表す.
項順序 (term order)
分散表現多項式における項は, 次の性質を満たす全順序により整列される.
1. 任意の項 t に対し t > 1
2. t, s, u を項とする時, t > s ならば tu > su
この性質を満たす全順序を項順序と呼ぶ. この順序は変数順序 (変数のリスト) と項順序型 (数, リスト
または行列) により指定される.
単項式 (monomial)
項と係数の積.
2*<<0,1,2,3,4>>という形で表示され, また, この形で入力可能である.
頭単項式 (head monomial)
頭項 (head term)
頭係数 (head coeﬃcient)
分散表現多項式における各単項式は, 項順序により整列される. この時順 序最大の単項式を頭単項式,
それに現れる項, 係数をそれぞれ頭項, 頭係数 と呼ぶ.
ファイルの読み込み
グレブナ基底を計算するための基本的な函数は dp gr main() および dp gr mod main(), dp gr f main()
なる 3 つの組み込み函数であるが, 通常は, パラメタ 設定などを行ったのちこれらを呼び出すユーザ函数を用いるのが便利である. これらのユーザ函数は, ファイル gr を load() により読み込むことにより使用可能となる. gr は, Asir の標準 ライブラリディレクトリに置かれている.

2.15.2[0] load("gr")$
2.15.3 基本的な関数
gr では数多くの函数が定義されているが, 直接グレブナ基底を計算するためのトップレベルは次の 3 つである. 以下で, plist は多項式のリスト, vlist は変数 (不定元) のリスト, order は変数順序型, p は 227 未満の素数である.

60

gr(plist,vlist,order)[Gebaue-Moeller] による useless pair elimination criteria, sugar strategy および [Traverso] によるtrace-lifting を用いた Buchberger アル ゴリズムによる有理数係数グレブナ基底計算函数. 一般にはこの函数を用いる.
hgr(plist,vlist,order)
入力多項式を斉次化した後 gr() のグレブナ基底候補生成部により候補生成し, 非斉次化, interreduce
したものを gr() のグレブナ基底チェック部でチェックする. 0 次元システム (解の個数が有限個の方
程式系) の場合, sugar strategy が係数膨張を引き起こす場合がある. このような場合, strategy を斉次化による strategy に置き換えることにより係数膨張を抑制することができる場合が多い.
gr mod(plist,vlist,order,p)[Gebaue-Moeller] による useless pair elimination criteria, sugar strategy および Buchberger アルゴ
リズムによる GF(p) 係数グレブナ基底計算函数.
計算および表示の制御
グレブナ基底の計算において, さまざまなパラメタ設定を行うことにより計算, 表示を制御することができる. これらは, 組み込み函数 dp gr flags() により設定参照することができる. 無引数で dp gr flags() を実行すると, 現在設定されているパラメタが, 名前と値のリストで返される.

2.15.4[100] dp_gr_flags();[Demand,0,NoSugar,0,NoCriB,0,NoGC,0,NoMC,0,NoRA,0,NoGCD,0,Top,0,
ShowMag,1,Print,1,Stat,0,Reverse,0,InterReduce,0,Multiple,0][101]
以下で, 各パラメタの意味を説明する. on の場合とは, パラメタが 0 でない場合を いう. これらのパラメタの初期値は全て 0 (oﬀ) である.

NoSugar on の場合, sugar strategy の代わりに Buchberger の normal strategy が用 いられる.
NoCriB on の場合, 不必要対検出規準のうち, 規準 B を適用しない.
NoGC on の場合, 結果がグレブナ基底になっているかどうかのチェックを行わない.
NoMC on の場合, 結果が入力イデアルと同等のイデアルであるかどうかのチェック を行わない.
NoRA on の場合, 結果を reduced グレブナ基底にするための interreduce を行わない.
NoGCD on の場合, 有理式係数のグレブナ基底計算において, 生成された多項式の, 係数の content をとらない.
Top on の場合, normal form 計算において頭項消去のみを行う.
Reverse on の場合, normal form 計算の際の reducer を, 新しく生成されたものを優先して選ぶ.
Print on の場合, グレブナ基底計算の途中におけるさまざまな情報を表示する.
PrintShort on で、Print が oﬀ の場合, グレブナ基底計算の途中の情報を短縮形で表示する.
Stat on で Print が oﬀ ならば, Print が on のとき表示されるデータの内, 集計データのみが表示される.
ShowMag on で Print が on ならば, 生成が生成される毎に, その多項式の係数のビット長の和を表示し, 最後に, それらの和の最大値を表示する.
Content
Multiple 0 でない有理数の時, 有理数上の正規形計算において, 係数のビット長の和が Content 倍になるごとに係数全体の GCD が計算され, その GCD で 割った多項式を簡約する. Content が 1 ならば, 簡約
するごとに GCD 計算が行われ一般には効率が悪くなるが, Content を 2 程度とすると, 巨大な整数が係数に現れる場合, 効率が良くなる場合がある. backward compatibility のため、Multiple で整数値を指定できる.
Demand 正当なディレクトリ名 (文字列) を値に持つとき, 生成された多項式はメモリ 中におかれず, そのディレクトリ中にバイナリデータとして置かれ, その多項 式を用いる normal form 計算の際, 自動的にメモリ中にロードされる. 各多 項式は, 内部でのインデックスをファイル名に持つファイルに格納される. ここで指定されたディレクトリに書かれたファイルは自動的には消去されない ため, ユーザが責61

任を持って消去する必要がある. Print が 0 でない場合次のようなデータが表示される.

[93] gr(cyclic(4),[c0,c1,c2,c3],0)$
mod= 99999989, eval = [](0)(0)<<0,2,0,0>>(2,3),nb=2,nab=5,rp=2,sugar=2,mag=4(0)(0)<<0,1,2,0>>(1,2),nb=3,nab=6,rp=2,sugar=3,mag=4(0)(0)<<0,1,1,2>>(0,1),nb=4,nab=7,rp=3,sugar=4,mag=6.
(0)(0)<<0,0,3,2>>(5,6),nb=5,nab=8,rp=2,sugar=5,mag=4(0)(0)<<0,1,0,4>>(4,6),nb=6,nab=9,rp=3,sugar=5,mag=4(0)(0)<<0,0,2,4>>(6,8),nb=7,nab=10,rp=4,sugar=6,mag=6....gb done
reduceall.......
membercheck(0,0)(0,0)(0,0)(0,0)
gbcheck total 8 pairs........
UP=(0,0)SP=(0,0)SPM=(0,0)NF=(0,0)NFM=(0.010002,0)ZNFM=(0.010002,0)
PZ=(0,0)NP=(0,0)MP=(0,0)RA=(0,0)MC=(0,0)GC=(0,0)T=40,B=0 M=8 F=6
D=12 ZR=5 NZR=6 Max_mag=6[94]
最初に表示される mod, eval は, trace-lifting で用いられる法 である. mod は素数, eval は有理式係数の場合に用いられる 数のリストである. 計算途中で多項式が生成される毎に次の形のデータが表示される.

(TNF)(TCONT)HT(INDEX),nb=NB,nab=NAB,rp=RP,sugar=S,mag=M
それらの意味は次の通り.
TNF normal form 計算時間 (秒)TCONT content 計算時間 (秒)HT 生成された多項式の頭項INDEX S-多項式を構成する多項式のインデックスのペア
NB 現在の, 冗長性を除いた基底の数
NAB 現在までに生成された基底の数
RP 残りのペアの数S生成された多項式の sugar の値
M生成された多項式の係数のビット長の和 (ShowMag が on の時に表示される. )最後に, 集計データが表示される. 意味は次の通り. (時間の表示において, 数字が 2 つあるものは, 計算時間と GC 時間のペアである.)

UP ペアのリストの操作にかかった時間
SP
有理数上の S-多項式計算時間
SPM 有限体上の S-多項式計算時間
N
有理数上の normal form 計算時間
NFM 有限体上の normal form 計算時間
ZNFM NFM の内, 0 への reduction にかかった時間
PZ
content 計算時間
NP 有理数係数多項式の係数に対する剰余演算の計算時間

62

MP S-多項式を生成するペアの選択にかかった時間
RA interreduce 計算時間
MC trace-lifting における, 入力多項式のメンバシップ計算時間
GC 結果のグレブナ基底候補のグレブナ基底チェック時間
T
生成されたペアの数
B, M, F, D 各 criterion により除かれたペアの数
ZR
0 に reduce されたペアの数
NZR 0 でない多項式に reduce されたペアの数
Max mag 生成された多項式の, 係数のビット長の和の最大値
項順序の設定項は内部では, 各変数に関する指数を成分とする整数ベクトルとして表現される. 多項式を分散表現多項式に変換する際, 各変数がどの成分に対応するかを指定するのが, 変数リストである. さらに, それら整数ベクトルの全順序を 指定するのが項順序の型である. 項順序型は, 数, 数のリストあるいは 行列で表現される. 基本
的な項順序型として次の 3 つがある.

2.15.50 (DegRevLex; 全次数逆辞書式順序)
一般に, この順序によるグレブナ基底計算が最も高速である. ただし, 方程式を解くという目的に用いることは, 一般にはできない. この順序によるグレブナ基底は, 解の個数の計算, イデアルのメンバシップ
や, 他の変数順序への基底変換のためのソースとして用いられる.
1 (DegLex; 全次数辞書式順序)
この順序も, 辞書式順序に比べて高速にグレブナ基底を求めることができるが, DegRevLex と同様直接
その結果を用いることは困難である. しかし, 辞書式順序のグレブナ基底を求める際に, 斉次化後にこの順序でグレブナ基底 を求めている.
2 (Lex; 辞書式順序)
この順序によるグレブナ基底は, 方程式を解く場合に最適の形の基底を与えるが 計算時間がかかり過ぎるのが難点である. 特に, 解が有限個の場合, 結果の 係数が極めて長大な多倍長数になる場合が多い.
この場合, gr(), hgr() による計算が極めて有効になる場合が多い.
こ れ ら を 組 み 合 わ せ て リ ス ト で 指 定 す る こ と に よ り, 様 々 な 消 去 順 序 が 指 定 で き る . こ れ は ,[[O1,L1],[O2,L2],...] で指定される. Oi は 0, 1, 2 のいずれかで, Li は変数の個数を表す. この指定
は, 変数を先頭から L1, L2, ... 個 ずつの組に分け, それぞれの変数に関し, 順に O1, O2, ... の項順序型で大小が決定するまで比較することを意味する. この型の順序は一般に消去順序と呼ばれる. さらに, 行列により項順序を指定することができる. 一般に, n 行 m 列の実数行列 M が次の性質を持つとする.

1. 長さ m の整数ベクトル v に対し M v = 0 と v = 0 は同値.
2. 非負成分を持つ長さ m の 0 でない整数ベクトル v に対し, M v の 0 でない最初の成分は非負.
この時, 2 つのベクトル t, s に対し, t > s を, M (t − s) の 0 でない最初の成分が非負, で定義することにより項順序が定義できる. 項順序型は, gr() などの引数として指定される他, 組み込み函数 dp ord() で指定され, さまざまな函数の実行の際に参照される. これらの順序の具体的な定義およびグレブナ基底に関する更に詳しい解説は [Becker-Weispfenning] などを参照のこと. 項順序型の設定の他に, 変数の順序自体も計算時間に大きな影響を与える.

[90] B=[x^10-t,x^8-z,x^31-x^6-x-y]$[91] gr(B,[x,y,z,t],2);[x^2-2*y^7+(-41*t^2-13*t-1)*y^2+(2*t^17-12*t^14+42*t^12+30*t^11-168*t^9-40*t^8+70*t^7+252*t^6+30*t^5-140*t^4-168*t^3+2*t^2-12*t+16)*z^2*y+(-12*t^16+72*t^13-28*t^11-180*t^10+112*t^8+240*t^7+28*t^6-127*t^5-167*t^4-55*t^3+30*t^2+58*t-15)*z^4,63

(y+t^2*z^2)*x+y^7+(20*t^2+6*t+1)*y^2+(-t^17+6*t^14-21*t^12-15*t^11+84*t^9+20*t^8-35*t^7-126*t^6-15*t^5+70*t^4+84*t^3-t^2+5*t-9)*z^2*y+(6*t^16-36*t^13+14*t^11+90*t^10-56*t^8-120*t^7-14*t^6+64*t^5+84*t^4+27*t^3-16*t^2-30*t+7)*z^4,(t^3-1)*x-y^6+(-6*t^13+24*t^10-20*t^8-36*t^7+40*t^5+24*t^4-6*t^3-20*t^2-6*t-1)*y+(t^17-6*t^14+9*t^12+15*t^11-36*t^9-20*t^8-5*t^7+54*t^6+15*t^5+10*t^4-36*t^3-11*t^2-5*t+9)*z^2,-y^8-8*t*y^3+16*z^2*y^2+(-8*t^16+48*t^13-56*t^11-120*t^10+224*t^8+160*t^7-56*t^6-336*t^5-112*t^4+112*t^3+224*t^2+24*t-56)*z^4*y+(t^24-8*t^21+20*t^19+28*t^18-120*t^16-56*t^15+14*t^14+300*t^13+70*t^12-56*t^11-400*t^10-84*t^9+84*t^8+268*t^7+84*t^6-56*t^5-63*t^4-36*t^3+46*t^2-12*t+1)*z,2*t*y^5+z*y^2+(-2*t^11+8*t^8-20*t^6-12*t^5+40*t^3+8*t^2-10*t-20)*z^3*y+8*t^14-32*t^11+48*t^8-t^7-32*t^5-6*t^4+9*t^2-t,-z*y^3+(t^7-2*t^4+3*t^2+t)*y+(-2*t^6+4*t^3+2*t-2)*z^2,
2*t^2*y^3+z^2*y^2+(-2*t^5+4*t^2-6)*z^4*y+(4*t^8-t^7-8*t^5+2*t^4-4*t^3+5*t^2-t)*z,z^3*y^2+2*t^3*y+(-t^7+2*t^4+t^2-t)*z^2,-t*z*y^2-2*z^3*y+t^8-2*t^5-t^3+t^2,-t^3*y^2-2*t^2*z^2*y+(t^6-2*t^3-t+1)*z^4,z^5-t^4][93] gr(B,[t,z,y,x],2);[x^10-t,x^8-z,x^31-x^6-x-y]
変数順序 [x,y,z,t] におけるグレブナ基底は, 基底の数も多く, それぞれの式も大きい. しかし, 順序[t,z,y,x] のもとでは, B がすでに グレブナ基底となっている. 大雑把にいえば, 辞書式順序でグレブナ基底を求める ことは, 左側の (順序の高い) 変数を, 右側の (順序の低い) 変数で書き表すことであり, この例の場合は, t, z, y が既に x で表されていることからこのような極端な結果となったわけである. 実際に現れる計算においては, このように選ぶべき変数順序が明らかであることは少なく, 試行錯誤が必要な場合もある

2.15.6 Weight
前節で紹介した項順序は, 各変数に weight (重み) を設定することで より一般的なものとなる.

[0] dp_td(<<1,1,1>>);
3[1] dp_set_weight([1,2,3])$[2] dp_td(<<1,1,1>>);6単項式の全次数を計算する際, デフォルトでは 各変数の指数の和を全次数とする. これは各変数の weightを 1 と考えていることに相当する. この例では, 第一, 第二, 第三変数の weight をそれぞれ 1,2,3 と指定している. このため, <<1,1,1>> の全次数 (以下ではこれを単項式の weight と呼ぶ) が 1*1+1*2+1*3=6 となる.
weight を設定することで, 同じ項順序型のもとで異なる項順序が定義できる. 例えば, weight をうまく設定することで, 多項式を weighted homogeneous にすることができる場合がある. 各変数に対する weight をまとめたものを weight vector と呼ぶ. すべての成分が正であり, グレブナ基底計算において, 全次数の代わりに用いられるものを特に sugar weight と呼ぶことにする. sugar strategy において, 全次数の代わりに使われるからである. 一方で, 各成分が必ずしも正とは限らない weight vector は, sugar weight として設定することはできないが, 項順序の一般化には 有用である. これらは, 行列による項順序の設定にすでに現れている. すな
わち, 項順序を定義する行列の各行が, 一つの weight vector と見なされる. また, ブロック順序は, 各ブロッ64

クの 変数に対応する成分のみ 1 で他は 0 の weight vector による比較を最初に行ってから, 各ブロック毎の
tie breaking を行うことに相当する. weight vector の設定は dp set weight() で行うことができるが, 項順序を指定する際の他のパラメタ (項順序型, 変数順序) と まとめて設定できることが望ましい. このため, 次のような形でも 項順序が指定できる.

[64] B=[x+y+z-6,x*y+y*z+z*x-11,x*y*z-6]$[65] dp_gr_main(B|v=[x,y,z],sugarweight=[3,2,1],order=0);[z^3-6*z^2+11*z-6,x+y+z-6,-y^2+(-z+6)*y-z^2+6*z-11][66] dp_gr_main(B|v=[y,z,x],order=[[1,1,0],[0,1,0],[0,0,1]]);[x^3-6*x^2+11*x-6,x+y+z-6,-x^2+(-y+6)*x-y^2+6*y-11][67] dp_gr_main(B|v=[y,z,x],order=[[x,1,y,2,z,3]]);[x+y+z-6,x^3-6*x^2+11*x-6,-x^2+(-y+6)*x-y^2+6*y-11]
いずれの例においても, 項順序は option として指定されている. 最初の例では v により変数順序を,
sugarweight により sugar weight vector を, order により項順序型を指定している. 二つ目の例におけるorder の指定は matrix order と同様である. すなわち, 指定された weight vector を左から順に使って weightの比較を行う. 三つ目の例も同様であるが, ここでは weight vector の要素を 変数毎に指定している. 指定がないものは 0 となる. 三つ目の例では, order による指定では項順序が決定しない. この場合には, tie breakerとして全次数逆辞書式順序が自動的に設定される. この指定方法は, dp gr main(), dp gr mod main() などの組み込み関数でのみ可能であり, gr() などのユーザ定義関数では未対応である.

2.15.7 有理式を係数とするグレブナ基底
gr() などのトップレベル函数は, いずれも, 入力多項式リストに現れる変数 (不定元) と, 変数リストに現れる変数を比較して, 変数リストにない変数が入力多項式に現れている場合には, 自動的に, その変数を, 係数体の元として扱う.
[64] gr([a*x+b*y-c,d*x+e*y-f],[x,y],2);[(-e*a+d*b)*x-f*b+e*c,(-e*a+d*b)*y+f*a-d*c]
この例では, a, b, c, d が係数体の元として扱われる. すなわち, 有理函数体 F = Q(a,b,c,d) 上の 2 変数多項式環 F[x,y] におけるグレブナ基底を求めることになる. 注意すべきことは, 係数が体として扱われていることである. すなわち, 係数の間に多項式 としての共通因子があった場合には, 結果からその因子は除かれているため, 有理数体上の多項式環上の問題として考えた場合の結果とは一般には異なる. また, 主として計
算効率上の問題のため, 分散表現多項式の係数として実際に許されるのは多項式までである すなわち, 分母を持つ有理式は分散表現多項式の係数としては許されない.
基底変換
辞書式順序のグレブナ基底を求める場合, 直接 gr() などを起動するより, 一旦他の順序 (例えば全次数逆辞
書式順序) のグレブナ基底を計算して, それを入力として辞書式順序のグレブナ基底を計算する方が効率がよ
い場合がある. また, 入力が何らかの順序でのグレブナ基底になっている場合, 基底変換と呼ばれる方法により, Buchberger アルゴリズムによらずに効率良く辞書式順序のグレブナ基底が計算できる場合がある. このような目的のための函数が, ユーザ定義函数として gr にいくつか定義されている. 以下の 2 つの函数は, 変数
順序 vlist1, 項順序型 order で既にグレブナ基底となっている多項式リスト gbase を, 変数順序 vlist2 における辞書式順序のグレブナ基底に変換する函数である.

2.15.8tolex(gbase,vlist1,order,vlist2)
この函数は, gbase が有理数体上のシステムの場合にのみ使用可能である. この函数は, 辞書式順序のグレブ
ナ基底を, 有限体上で計算されたグレブナ基底を雛型として, 未定係数法および Hensel 構成により求めるものである.
tolex tl(gbase,vlist1, order,vlist2,homo)
この函数は, 辞書式順序のグレブナ基底を Buchberger アルゴリズムにより求 めるものであるが, 入力
65

がある順序におけるグレブナ基底である場合の trace-lifting におけるグレブナ基底候補の頭項, 頭係数の性質を利用して, 最終的なグレブナ基底チェック, イデアルメンバシップチェックを省略しているため, 単にBuchberger アルゴリズムを繰り返すより効率よく計算できる. 更に, 入力が 0 次元システムの場合, 自動的に
もう 1 つの中間的な項順序を 経由して辞書式順序のグレブナ基底を計算する. 多くの場合, この方法は, 直接
辞書式順序の計算を行うより効率がよい. (もちろん例外あり. ) 引数 homo が 0 でない時, hgr() と同様に斉次化を経由して 計算を行う. その他, 0 次元システムに対し, 与えられた多項式の最小多項式を求める函数,
0 次元システムの解を, よりコンパクトに表現するための函数などが gr() で定義されている. これらについては個々の函数の説明を参照のこと.

2.15.9 Weyl 代数
これまでは, 通常の可換な多項式環におけるグレブナ基底計算について述べてきたが, グレブナ基底の理論
は, ある条件を満たす非可換な環にも拡張できる. このような環の中で, 応用上も重要な, Weyl 代数, すな
わち多項式環上の微分作用素環の演算およびグレブナ基底計算が Risa/Asir に実装されている. 体 K 上の n 次元 Weyl 代数 D=K<x1,...,xn,D1,...,Dn> は xi*xj-xj*xi=0, Di*Dj-Dj*Di=0, Di*xj-xj*Di=0(i!=j), Di*xi-xi*Di=1 という基本関係を持つ環である. D は 多項式環 K[x1,...,xn] を係数とする微分作用素環で, Di は xi による微分を表す. 交換関係により, D の元は, x1^i1*...*xn^in*D1^j1*...*Dn^jn
なる単項式の K 線形結合として書き表すことができる. Risa/Asir においては, この単項式を, 可換な多項式と同様に<<i1,...,in,j1,...,jn>> で表す. すなわち, D の元も 分散表現多項式として表される. 加減算
は, 可換の場合と同様に, +, - により実行できるが, 乗算は, 非可換性を考慮して dp weyl mul() という関数
により実行する.
[0] A=<<1,2,2,1>>;(1)*<<1,2,2,1>>[1] B=<<2,1,1,2>>;(1)*<<2,1,1,2>>[2] A*B;(1)*<<3,3,3,3>>[3] dp_weyl_mul(A,B);(1)*<<3,3,3,3>>+(1)*<<3,2,3,2>>+(4)*<<2,3,2,3>>+(4)*<<2,2,2,2>>+(2)*<<1,3,1,3>>+(2)*<<1,2,1,2>>
グレブナ基底計算についても, Weyl 代数専用の関数として, 次の関数が用意してある. dp weyl gr main(),dp weyl gr mod main(), dp weyl gr f main(), dp weyl f4 main(), dp weyl f4 mod main(). また, 応用として, global b 関数の計算が実装されている.

2.16 分散計算
2.16.1 OpenXM
Asir は, 分散計算における通信プロトコルとして, OpenXM (Open message eXchange for Mathematics) プ
ロトコルを採用している. OpenXM プロジェクトについては, http://www.math.sci.kobe-u.ac.jp/OpenXM/
を参照してほしい. OpenXM プロトコルは, 主として数学オブジェクトをプロセス間でやりとりする ための規約である. OpenXM においては
1. client が server に対して計算実行依頼のメッセージを送る.
2. server が計算を実行する.
3. client が server に結果送付依頼のメッセージを送る.
4. server は結果を返し, client は結果を受け取るという形で分散計算が行われる. server はスタックマシンである. すなわち, client から送られたデータオ
ブジェクトは, 指定がない限り server のスタッ クに積まれ, コマンドが送られた時に, 必要なだけスタック

66

からデータを取り出して, 関数呼び出しの引数とする. OpenXM において特徴的なことは, 計算結果は単にserver のスタックに 積まれるだけで, client からの依頼がない限り, 通信路にデータは流れない という点である. プロトコルには, オブジェクトの共通フォーマットを規定する CMO (Common Mathematical Object
format), プロセスに対する 動作を指定する SM (Stack Machine command) が含まれる. これらは, データを送る際に, データの種類を指定する ための OX expression としてラッピングされる. OpenXM による分散計算を行う場合には, まず, server を立ち上げて, 通信を成立させる必要がある. このために, ox launch(),ox launch nox(), ox launch generic() などの関数が用意されている. さらに, 通信の成立した server に対して 以下のような操作が関数として用意されている.

ox push cmo()
データを server のスタックに積む

ox pop cmo()
データを server のスタックから取り出す.

ox cmo rpc()
server の関数を呼び出し, 結果をスタックに積む.
ox execute string()
server 固有のユーザ言語 (Asir なら Asir 言語) で書かれた文字列を server が実行し, 結果をスタッ
クに積む.
ox push cmd()
SM コマンドの送信.
ox get()
既に通信路にあるデータの取り出し.
2.16.2 Mathcap
server, client ともに, OpenXM で規定されている全ての CMO フォー マット, SM コマンドを実装しているとは限らない. 相手の知らないデータ, コマンドを送った場合, 現状では結果は予想できない. このため,
OpenXM では, あらかじめ互いのサポートする CMO, SM のリストを交換しあって, 相手の知らないデータを送らないようにする仕組みを提唱している. このための データが Mathcap である. Mathcap は CMO としてはリストであり, その要素は 32 bit 整数または文字列である. 現在の規定では,Mathcap は 長さが 3 のリスト
で, [[version 番号, server 名],SMtaglist,[[OXtag,CMOtaglist], [OXtag,CMOtaglist],...]] という形をしている. [OXtag,CMOtaglist] は, OXtag で示されるカテゴリのデータに対して, どのような CMOが使用可 能かを示すものである. この指定を複数許すことにより, 例えば ox asir のように, CMO データ以外に, Asir 固有のデータ形式 により, CMO より多くの種類のデータ送受信を行えることを示せる. データ送信の際に, 相手プロセスの Mathcap が既に登録されている場合, Mathcap によるチェックを行うか否かは, ctrl
コマンドの ox check スイッチにより決まる. このスイッチの初期値は 1 で, チェックを行うことを意味する.
ctrl("ox check",0) によりチェックを行わないようにできる.
2.16.3

スタックマシンコマンド

スタックマシンコマンドは, スタックマシンである server に何らかの操作を行 わせるために用意されている. いくつかのコマンドは, よく用いられる形で, 他のコマンド, データとともに, Asir の組み込み関数により送られるが, ユー ザが明示的にあるコマンドを送る必要がしばしば生ずる. スタックマシンコマンドは 32 bit
以下の整数であり, ox_push_cmd() コマンドで送信できる. 以下で, 代表的なスタックマシンコマンドについて解説する. SM_xxx=yyy で, SM_xxx が mnemonic, yyy が値である. 以下で, スタックからデータを取り出すとは, スタックの一番上からデータを 取り除くことを言う.

SM popSerializedLocalObject=258
server が ox\_asir の場合に, 必ずしも CMO で定義されていないオブジェクトをスタックから取り出
し, 通信路に流す.
SM popCMO=262
CMO オブジェクトをスタックから取り出し, 通信路に流す.
67

SM popString=263
スタックからデータを取り出し, 可読形式の文字列に変換して通信路に流す.
SM mathcap=264
server の mathcap をスタックに積む.
SM pops=265
スタックから取り出したデータを個数として, その個数分スタックから データを取り除く.
SM setName=266
スタックからデータを変数名として取り出し, 次に取り出したデータをその 変数に割り当てる. この割り当ては, server 固有の処理として行われる.
SM evalName=267
スタックから取り出したデータを変数名として, その値をスタックに載せる.
SM executeStringByLocalParser=268
スタックから取り出したデータを, server 固有の parser, evaluator で 処理し, 結果をスタックに載せる.
SM executeFunction=269
スタックから, 関数名, 引数の個数, 個数分の引数を取り出し, 関数を呼び出し結果をスタックに載せる.
SM beginBlock=270
データブロックのはじまり.
SM endBlock=271
データブロックの終り.
SM shutdown=272
server との交信を切断し, server を終了させる.
SM setMathcap=273
スタックのデータを client の mathcap として, server に登録を要求する.
SM getsp=275
現在スタックに積まれているデータの数をスタックに載せる.
SM dupErrors=276
現在スタックに積まれているオブジェクトの内, エラーオブジェクトのみをリストにして, スタックに載せる.
SM nop=300
なにもしない.
デバッグ
デバッグ分散計算においては, 一般にデバッグが困難となる. ox_asir においては, デバッグのためのいく
つかの機能を提供している.

2.16.42.16.4.1

エラーオブジェクト

OpenXM server が実行中にエラーを起こした場合, 結果のかわりに CMO エラーオブジェクトをスタックに積む. エラーオブジェクトは, 対応する SM コマンドのシリアル番号と, エラーメッセージからなり, それによってどの SM コマンドがどのようなエラーを起こしたがある程度判明する.
[340] ox_launch();0[341] ox_rpc(0,"fctr",1.2*x);0[342] ox_pop_cmo(0);error([8,fctrp : invalid argument])

682.16.4.2

リセット

ox reset() は現在実行中の server をリセットして, コマンド受け付け状態に戻す. この機能は, 通常のAsir セッションにおけるキーボード割り込みとほぼ同様に, OpenXM server をリセットできる. また, 何らかの原因で, 通信路のデータが載ったままの状態で ox rpc() などを実行すると, ox pop cmo() など, スタックからの取り出しと, 実際に読まれるデータの対応が不正になる. そのような場合にも有効である.
2.16.4.3

デバッグ用ポップアウトウインドウ

server には, client におけるキーボードに相当する入力機能がないため, server 側で動作しているユーザ言
語プログラムのデバッグが困難になる. この ため, server 側でのユーザ言語プログラム実行中のエラーおよび, client からの ox_rpc(id,"debug") 実行により, server にデバッグコマンド を入力するための小さなウィ
ンドウがポップアップする. このウィンドウからの入力に対する出力は, log 用の xterm に表示される. このウィンドウを閉じるには, quit を入力すればよい.

2.17 Asir-Contrib
はじめに
数 式 処 理 シ ス テ ム asir は OpenXM プ ロ ト コ ル (Open message eXchange for Mathematics,
http://www.openxm.org) をサポートしたサーバを コンポーネントとして利用できる. これらのサーバを呼
ぶためのインタフェース関数はファイル ‘OpenXM/rc/asirrc’ をロードすることによりシステムに読み込まれる. Risa/Asir (OpenXM 配布版) では起動時に自動的にこのファイルが読まれる. Risa/Asir (OpenXM 配布版) は, このマニュアルでは OpenXM/Risa/Asir と呼ぶ. このマニュアルでは asir 用のこれらの関数 お
よびユーザ言語で書かれた数学関数およびユーティリティ関数を説明する.
HEAD branch に同期した最新版の asir-contrib マニュアルは
http://www.math.kobe-u.ac.jp/OpenXM/Current/doc/index-doc-ja.html を参照.
OpenXM プロトコルの技術的詳細については, ‘$(OpenXM HOME)/doc/OpenXM-specs’ にあるファイル
openxm-jp.tex’ を見て下さい.
それでは, あなたの計算機上で数学をお楽しみ下さい.

2.17.1

List of contributors:• Maekawa, Masahide (Oct., 1999 – : CVS server)• Noro, Masayuki (Jan., 1996 – : OpenXM Protocol OXRFC-100, asir2000)• Ohara, Katsuyoshi (Jan., 1998 – : ox math, oxc OXRFC-101)• Takayama, Nobuki (Jan., 1996 – : OpenXM Protocol OXRFC-100, kan/sm1, asir-contrib)• Tamura, Yasushi (Nov., 1998 – : OpenMath proxy, tfb)
• Fujimoto, Mitsushi (Windows)• Iwane, Hidenao (Knapsack factorizer)• Nakayama, Hiromasa (Gaussian elimination)• Okutani, Yukio (Oct., 1999 – Feb., 2000 : matrix, diﬀ, ...)
• Stillman, Mike (Macaulay 2 client and server)• Tsai, Harrison (Macaulay 2 client and server)
この Contrib パッケージの 著作権については, OpenXM/Copyright を見て下さい.
有用だと思いますが無保証です.

2.17.2 Asir/Contrib のロード方法‘OpenXM/rc/asirrc’ を ロ ー ド す る こ と に よ り Asir/Contrib の 主 な 関 数 が 利 用 可 能 と な る.
OpenXM/Risa/Asir で は ASIR CONFIG 環 境 変 数 に よ り こ の フ ァ イ ル を 起 動 時 に 読 み 込 ん で い る.
‘names.rr’ が Asir/Contrib のトップレベルのファイルである. このファイルよりその他のファイルが読69

み込まれている. 一部のパッケージは ‘names.rr’ からは読み込まれないので, 明示的に読み込む必要がある.

A sample of ‘asirrc’ to use Asir/Contrib.
load("gr")$load("primdec")$load("katsura")$load("bfct")$load("names.rr")$load("oxrfc103.rr")$
User_asirrc=which(getenv("HOME")+"/.asirrc")$
if (type(User_asirrc)!=0) {if (!ctrl("quiet_mode")) print("Loading ~/.asirrc")$load(User_asirrc)$}else{ }$end$

2.17.3 Asir Contrib の函数名について
Asir Contrib には(1) 標準的な名前で定義された数学函数 (names.rr または longname)(2) Asir 標準函数以外の有用なライブラリ函数(3) OpenXM サーバを asir から呼ぶための函数が含まれている.
Asir Contrib の函数名はモジュール化されているかまたは次の形をしている: カテゴリ名 函数名OpenXM サ ー バ を 呼 び 出 す 函 数 名 は か な ら ず, OpenXM サ ー バ 名 函 数 名 と い う 形 を し て い る. たと え ば sm1.hilbert は OpenXM サ ー バ sm1 の Hilbert 函 数 の 計 算 函 数 を 呼 び 出 す 函 数 で ある. 一 方 poly hilbert polynomial は Asir Contrib の Hilbert 函 数 を 計 算 す る た め の (1) に属 す る 標 準 的 な 函 数 名 で あ る. 標 準 函 数 poly hilbert polynomial() は, 現 在 sm1.hilbert を
呼 び 出 し て Hilbert 函 数 を 計 算 し て い る が, こ れ は 将 来 変 更 さ れ る か も し れ な い.
た と え ば,Asir 言 語 で 記 述 さ れ た 有 用 な ラ イ ブ ラ リ 函 数 集 commutativeRing.rr が 開 発 さ れ て Hilbert 函
数 の 計 算 函 数 commutativeRing hilbert polynomial() が 含 ま れ る よ う に な っ た ら, 標 準 函 数
poly hilbert polynomial() は, commutativeRing hilbert polynomial() を呼び出して Hilbert 函数を計算するようになるかもしれない. したがって, ユーザプログラムは標準数学函数名を用いるのが望ましい.
標準数学函数名は, OpenXM project において, 全てのプロジェクトで共通の仕様を持つように努力している.
たとえば, kan/k0 も Asir Contrib と同様の標準数学函数名を持つ予定である. 現在実験的に数学函数のカ
テゴリ complex 複体 (複素数でない) のマニュアルを kan/k0, asir/contrib で共通化を試みている.
§3.4 において, 標準数学函数の解説をおこない, それからライブラリ函数および OpenXM サーバのインタ
フェースの説明を行う.
2.17.4 Windows 版 Asir-Contrib
Windows でも不完全ながら asir-contrib が動作する. 現在, 外部コンポーネント sm1 および, 外部コン
ポーネントを利用しない asir-contrib の関数が動作する. Cygwin 環境では外部コンポーネント sm1, phcが動作する. その他の外部コンポーネントは動作しない.
次の関数は Windows では動作しない. Windows での cygwin 環境では動作する場合がある.
gnuplot.*om.*mathematica.*70phc.*
print_dvi_form
print_gif_form
print_open_math_xml_form
print_png_form
print_xdvi_form
print_xv_form
tigers_xv_form

2.18 Risa/Asir と os muldif.rr
Risa/Asir は有理関数の計算を行う場合に注意が必要で，特に有理関数係数の多項式や微分作用素，成分が有理関数の行列の演算が，そのままでは思い通りにならないことがある．いくつかの例を挙げてみよう．
[0] 2/x-1/x+1/x-1/x;(x^3)/(x^4)[1] x/(x+y)+y/(x+y);(x^2+2*y*x+y^2)/(x^2+2*y*x+y^2)[2] x/y*y/x;(y*x)/(y*x)[3] 1/(1/x);(x)/(1)[4] deg((a/b)*x^2,x);0[5] diff((1/a)*x+1/b,x);(b^2*a)/(b^2*a^2)[6] diff((x+1)^(-3),x);(-3*x^2-6*x-3)/(x^6+6*x^5+15*x^4+20*x^3+15*x^2+6*x+1)[7] A = newmat(2,2,[[a,0],[0,1/a]]);[ a 0 ][ 0 (1)/(a) ][8] det(A);internal error (SEGV)
return to toplevel[9] coef(x+1/a,1,x);0
このような場合も、より望まれる形で結果が得られるように作ったライブラリが os_muldif.rr [O6] である．
以下，現状の関数の解説があるが，流動的かつ暫定的なものである．

• Risa/Asir の サ ー チ パ ス（ 標 準 的 に は ，RisaAsir—の ラ イ ブ ラ リ の あ る./lib/の 下 の./lib/asir-contrib で ，names.rr な ど が イ ン ス ト ー ル さ れ て い る 場 所 に 置 く ．そ の 場 所 は
Risa/Asir を起動して which("names.rr") とすれば表示される）に os_muldif.rr を入れると
Risa/Asir において load("os_muldif.rr")$ とすることにより，os_muldif.rr の中の函数が使用できるようになる．

71

• デフォルトではモジュール化して読み込まれるので，函数名の先頭に os_md. をつけて呼び出さなくてはなくてはならない．

• load("names.rr") も実行しておけば（最近の Risa/Asir のパッケージでは動時に読み込まれていることがあり，そのときはこれは不要），数式や結果を読みやすい TEX のソースで出力可能できる．さらに MS Windows においては，dviout にパスを通しておけば，dviout で表示することが出来る．他のシステムでも簡単な変更で，TEX のプレビュ機能を使って結果が表示可能になる．
• chkfun(1,0) によって Version 番号が分かる（0 から始まるものは暫定版）．
• 使用例が書いていないものは未テストなので，正しく動作しない可能性が高い．
• また？の印が付いているものも同様である．
• 不具合は知らせていただけと有り難い．
こ の ラ イ ブ ラ リ の 特 徴 的 な 関 数 と し て は ，dviout()，show(), ltotex(), fctrtos(), mtotex(),myhelp(), xy2graph(), mtoupper(), mdivisor(), getbygrs(), shiftop(), m2mc()，mc2grs(),
scale() などがある．

2.18.1 os muldif.rr のインストール• get rootdir() で示される Risa/Asir のライブラリがインストールされたディレクトリの下の（Risa/Asir のライブラリ・サーチパス）lib\asir-contrib に os_muldif.rr を入れる*1 ．
Risa/Asir から[0] load("os_muldif.rr")$
Loaded muldif Ver. 00140330 (Toshio Oshima)
として読み込むと，os_muldif.rr で定義された函数が使えるようになる．
• デフォルトではモジュール化して読み込まれるので，以下に説明される函数名の先頭に os_md. をつけて呼び出さなくてはなくてはならない．
以下では，例を除いて先頭の os_md. が全て省略されているので注意．
• Risa/Asir の起動時に自動的に読み込むには，get rootdir() にある .asirrc にimport("os_muldif.rr")$の 1 行を追加しておけばよい．そのときの .asirrc は例えば以下のようである．

import("contrib-setord.rr")$
import("gr")$
import("primdec")$
import("katsura")$import("bfct")$
import("names.rr")$
import("oxrfc103.rr")$
import("os_muldif.rr")$end$• os_muldif.rr の冒頭の
#define USEMODULE 1を#undef USEMODULE*1 names.rr などが置かれている場所なので，Risa/Asir のコマンドラインから which("names.rr") などとすれば，そのディレクトリが分かる．

72

と書き換えると，モジュール化されずに読み込まれるので，函数の先頭に os_md. をつける必要はなくなる．しかしながら，他の函数とのバッティングが起こる可能性が生じるので，それは推奨されない．

• よく使う関数のみ os_md. を略した形や簡単な名前にするには，その関数を呼び出す新たな関数を再定義しておくとよい．たとえばdef cat(X){return os_md.mycat(X|option_list=getopt());}
def myhelp(X){return os_md.myhelp(X|option_list=getopt());}
def show(X){return os_md.show(X|option_list=getopt());}
・・・

cat("mydef:\n cat, myhelp, show,...")$というような内容を mydef.rr というファイルに書いてライブラリに入れて.asirrc に以下の一行を加えておけばよい．

import("mydef.rr")$• TEX を利用して数式を綺麗に表示するには，OS や動作環境に依存するプレビューアの指示などの設定が必要となる．これについては risatex.bat の項の前後を参照してください．
• myhelp("fn") によって函数 fn の説明を表示させる機能の有効化については，DVIOUTH の項を参照してください．また，os_muldif.dvi と os_muldif.pdf は get rootdir()/help に入れてください．
こうすれば dviout にパスが通っていると，DVIOUTH の設定は不要です．

73

3 Functions
3.1 Functions related to diﬀerential operators
以下の関数はモジュール化されているので，先頭に os_md. を付加して，os_md.muldo() のように呼び出す．

3.1.1 Fundamental functions
1. muldo(p1 ,p2 ,[x,∂x ]|lim=n) または muldo(p1 ,p2 ,x|lim=n)muldo(p1 ,p2 ,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]|lim=n) または muldo(p1 ,p2 ,[[x1 ],x2 ,. . .]|lim=n):: 有理函数（初等函数でもよい）係数の常（または偏）微分作用素の積 (⇐ [∂x , x] = 1)
• 有理函数は多項式の商で表される．多項式の係数は普通は有理数とするが，実部と虚部が有理数の複素数でもよい（cf. 数の型）．
• ∂x が標準的な dx のときは，[x,∂x ] の代わりに x としてよい．
これは以下の函数でも同様とする．

• 偏微分作用素のときは，3 番目の引数が [[x],[y,v],z] などでもよい．これは d を付加して[[x,dx],[y,v],[z,dz]] と解釈される．ただしリストの最初はリストでなくてはならない．すなわち [[x,dx],[y,dy]] は [[x],y] と書いてもよいが，[x,y] は常微分作用素と解釈される．
以下の函数で微分作用素とある場合は，同様な省略が可能である．

• p2 はベクトルまたは行列でもよい．このときは p1 は行列でもよい．
• x や xi が 0 のときは，単なる積を返す．
• exp(∂) などの無限階微分作用素や ∂ −1 などの擬微分作用素も計算可能（ただし，appldo() など
では不可，また計算が有限回で終わらないこともあり，そのときは途中で打ち切る）．
• Leibniz 公式での積の計算で，各変数の微分の回数が 100 回以上になるとそこで打ち切るのがデフォルトであるが lim=n のオプションで変更可能（これは p1 , p2 がスカラーのときのみ有効）．
たとえば，muldo(dx^(-1),1/x,x) や muldo(exp(dx),1/x,x) は有限回で計算が終わらない．
∂∂[dx, x] = 1, [dy, y] = 1 という交換関係のとき（⇐ dx = ∂x
, dy = ∂y)[0] os_md.muldo((1+x)*dx+1, (1-x)*dx+1, [x,dx]);(-x^2+1)*dx^2+(-x+1)*dx+1[1] os_md.muldo(x*dx+1/(x-a),a*dx+1/x,x);((a*x^3-a^2*x^2)*dx^2+x^2*dx-x+a+1)/(x^2-a*x)[2] os_md.muldo((a+y)*dy, (b-y)*dy, y);(-y^2+(-a+b)*y+b*a)*dy^2+(-y-a)*dy[3] os_md.muldo((a+y)*dy, (b-y)*dy, [0,dy]);(-y^2+(-a+b)*y+b*a)*dy^2[4] os_md.muldo(dx+dy, x*dx+y*dy, [[x],y]);x*dx^2+((x+y)*dy+1)*dx+y*dy^2+dy[5] os_md.muldo(dx+dy,sin(x+y),[[x],y]);sin(x+y)*dy+sin(x+y)*dx+2*cos(x+y)[6] os_md.muldo(exp(dx),(x-1)^4,x);exp(dx)*x^4[7] subst(@@,exp(dx),1);x^4[8] os_md.muldo(x*dx^(-1),dx/x,x);Over 100 derivations!

74

(x^100*dx^{100}+x^99*dx^99+2*x^98*dx^98+.........)/(x^100*dx^100)[9] os_md.muldo(dx^(-1),dx/x,x|lim=5);Over 5 derivations!
(x^5*dx^5+x^4*dx^4+2*x^3*dx^3+6*x^2*dx^2+24*x*dx+120)/(x^5*dx^5)[10] os_md.muldo(x*exp(dx),1/x,x|lim=5);Over 5 derivations!
(exp(dx)*x^5-exp(dx)*x^4+exp(dx)*x^3-exp(dx)*x^2+exp(dx)*x-exp(dx))/(x^5)[11] deval(os_md.muldo(exp(dx),exp(x),x]);Over 100 derivations!
2.71828*exp(1*dx)*exp(1*x)
[0] は



d
d2
d
d
+ 1 ◦ (1 − x) dx+ 1 = (1 − x2 ) dx
(1 + x) dx
2 + (1 − x) dx + 1を意味する．なお，[6], [8], [9], [10], [11] の結果は，微分と函数とが可換と考えて割り算をして並べ直したものが通常の表記での結果となる．すなわち
[6] は
d

d

2

3

4 dx
1
d
d
1 d
e dx ◦ (x−1)= x4 (1 + dx
+ 21 dx
4 = x e2 + 3! dx3 + · · · )

[8] は
d
x dx

−1

d
d −1
d −2
◦ x1 dx= 1 + x1 ( dx
) + x22 ( dx
) + ···[10] は

2

d

3

d
1 d
1 d
xe dx ◦ x1 = (1 − x1 + x12 − x13 + x14 − x15 )(1 + dx
+ 2!
dx2 + 3! dx3 + · · · )と解釈する．[11] は，実際はdde dx ◦ ex = ex+1 e dx
である.
2. caldo([p1 ,p2 ,. . .],[x,∂x ]|mono=f ) or caldo([p1 ,p2 ,. . .],[[x1 ,∂x1 ],. . .]|mono=f ):: 微分作用素の積の和を計算する
p1 + p2 + · · · を返す. pj は微分作用素でなくてリスト [pj,1 , . . .] でもよい. その場合は• pj = pj,1 pj,2 · · · という微分作用素の積を表す.
m• pj,ν が，[qj,ν , mj,ν ] となっていた場合は pj,ν = qj,νj,ν とする. mj,ν は非負整数でなければならない.
• pj,ν が，[qj,ν ,[mj,ν,1 , . . .]] となっていた場合は, pj,ν = (qj,ν + sj,ν,1 )(qj,ν + sj,ν,2 ) · · · とする.
• momo=1 : [p1 ] を計算するときは，momo=1 を指定して引数を p1 としてもよい．
• momo=2 : p1,1 を計算するときは，momo=2 を指定して引数を p1,1 としてもよい．

[0] os_md.caldo([[dx-x,[dx+x,2]],y],x);dx^3+x*dx^2+(-x^2+3)*dx-x^3+x+y
3. muledo(p1 ,p2 ,[x,∂x ]) or muledo(p1 ,p2 ,x):: Euler 型常微分作用素の積 (⇐ [∂x , x] = x)p2 は行列またはベクトルでもよい．このとき，p1 は行列でもよい．
d[dx, x] = x という交換関係のとき（⇐ dx = x dx)[0] os_md.muledo((1+x)*dx+1, (1-x)*dx+1, x);(-x^2+1)*dx^2+(-x+1)*dx+1
4. transpdo(p,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .],[[y1 ,∂y1 ],[y2 ,∂y2 ],. . .]|ex=1,inv=f )P:: 微分作用素の変換（xi 7→ yi = yi (x), ∂xj 7→ ∂yj = cj (x) + ν ajν (x)∂xν ）75

• yi , ∂yj は (x1 , . . . , xn ) の有理式および有理式係数の微分作用素• [xi , ∂xi ] の方は xi の形の省略形も可（⇐ ∂xi = dxi ）• 引数のリストの 2 番目が 3 番目より長い場合，残りは恒等変換とみなす．
• p は微分作用素のリスト，ベクトル，行列でもよい．
• 双有理変換のときは，第 2 引数は第 1 引数と同じ長さにとって，[y1 ,y2 , . . .] とのみ指定すればよい．∂y1 , ∂y2 , . . . は自動計算される．このとき– inv=1 : 逆変換を表す– inv=2 : [∂y1 ,∂y2 ,...] を返す．
– inv=3 : 逆変換の [∂y1 ,∂y2 ,...] を返す．
• 3 番目の引数が整数成分の可逆行列 m，あるいは，それが行ベクトルのリストのリストのときは，
transppow() で定まる座標変換と見なす．
[0] os_md.transpdo(x^2*dx^2,x,[[1/x,-x^2*dx]]);x^2*dx^2+2*x*dx[1] os_md.transpdo(x*dx+y*dy,[[x],y],[x+y,x-y]);os_md.transpdo(x*dx+y*dy,[[x],y],[[x+y,(dx+dy)/2],[x-y,(dx-dy)/2]]);y*dy+x*dx[2] os_md.transpdo(4*dx^2,[[x,dx],[y,dy]],[x+y,x-y]);dy^2+2*dx*dy+dx^2[3] os_md.transpdo(x*dx+y*dy,[[x],y],[x+y,x-y]|inv=2);[1/2*dy+1/2*dx,-1/2*dy+1/2*dx][4] os_md.transpdo(x*dx,x,[1/x]);-x*dx[5] os_md.transpdo(x*dx,x,[-dx+1/x,x]|ex=1);-x*dx• 上の [0], [1] などでは，[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .] について省略形を用いている（cf. muldo()）．
• [0] や [1] では，x 7→ x1 や (x, y) 7→ (x + y, x − y) という座標変換による微分作用素の変換を求
d
d
∂
∂
∂
∂ 1 ∂
∂
めている．このとき，対応する変換 dx
7→ − x12 dx
や ( ∂x, ∂y) 7→ ( 12 ∂x+ 12 ∂y, 2 ∂x − 12 ∂y) も指定しているが，[2] のように省略してよい．
dd• 座標変換ではないが (x, dx) 7→ (x, dx+ c) のような微分作用素環の同型変換となるものでもよい．
• ex=1 : (xi , ∂xi ) 7→ (Si (x, ∂), Ti (x, ∂)) という微分作用素環の準同型写像による変換を計算する．
すなわち [Ti (x, ∂), Sj (x, ∂)] = δi,j であって，p は (x, ∂) について多項式である必要がある．
dd[5] は，(x, dx) 7→ (− dx+ x1 , x) という変換を考えている．
5. translpdo(p,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .],mat)P:: 微分作用素の線形座標変換（xi 7→ j (mat)ij xj ）[xi ,∂xi ] は xi の形の省略形も可（⇐ ∂xi = dxi ）．
[0] M=mat([1,1],[1,-1]);[ 1 1 ]
[ 1 -1 ][1] os_md.translpdo(4*dx^2,[[x,dx],[y,dy]],M);dy^2+2*dx*dy+dx^2
6. transppow([[x1 ,∂x1 ],. . .,[xn ,∂xn ]],m):: ベキ函数による座標変換での変換公式
xi 7→

n
Y

m

xj i,jj=1

76(j = 1, . . . , n)という座標変換による [[x1 ,∂x1 ],. . .,[xn ,∂xn ]] の変換結果を返す．m はサイズ n の整数成分の可逆行列．行ベクトルのリストのリストで与えてもよい．

[0] os_md.transppow([x,y],[[1,1],[0,-1]]);[[x,(y*dy+x*dx)/(x)],[(x)/(y),(-y^2*dy)/(x)]][1] os_md.transppow([x,y],[[1,1],[0,1]]);[[x,(-y*dy+x*dx)/(x)],[y*x,(dy)/(x)]]7. appldo(p,r,[x,∂x ]|Pfaff=1) or appldo(p,r,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]):: 微分作用素（の行列）の有理式，初等函数（の行列），Pfaﬀ 系への作用の計算
r はベクトルまたは行列でもよい．この場合は p は行列でもよい．
d• Pfaff=1 : dudx = r(x)u に対し p(x, dx )u = s(x)u となる s(x) を求める (p, r は行列またはス
カラー)[0] os_md.appldo(x*dx^2-2*dx, a*x^3+b*x^2, x);-2*b*x[1] os_md.appldo(x*dx^2+2*dx, x+y/x, x);2[2] V=newvect(2,[x/y,y/x]);[ (x)/(y) (y)/(x) ][3] os_md.appldo(x*dx+1,V,x);[ (2*x)/(y) 0 ][4] P=newmat(2,2,[[x*dx+1,x/y],[0,x*dx]]);[ x*dx+1 (x)/(y) ][ 0 x*dx ][5] os_md.appldo(P,V,x);[ (2*x+y)/(y) (-y)/(x) ][6] os_md.appldo(ddx,P,dx);[ x 0 ]
[ 0 x ]
[7] A=newmat(2,2,[[cos(x+y),-sin(x+y)],[sin(x+y),cos(x+y)]]);[ cos(x+y) -sin(x+y) ][ sin(x+y) cos(x+y) ][8] os_md.appldo(dx^2,A,x);[ -cos(x+y) sin(x+y) ][ -sin(x+y) -cos(x+y) ][9] V=[lambda1,lambda2];C0=newmat(2,2,[V,V]);[10] C=os_md.diagm(2,[1/x,1/(x-1)])*(C0+os_md.diagm(2,[mu]));[11] P=os_md.diagm(2,[1,dx])*C0;[12] U=os_md.appldo(P,C,[x,dx]|Pfaff=1);[13] V=os_md.myinv(U); λ −1u0
x 1 (1 − x)λ2
u0 = ∂ −µ xλ1 (1 − x)λ2 （Gauss の超幾何）, u =に対し, v = ∂ −µ−1∂u0xλ1 (1 − x)λ2 −1
u = U v, v = V u となる有理関数の行列 U , V を上で求めた．
8. adj(p,[x,∂x ]) または adj(p,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]):: 微分作用素（の行列） p の formal adjoint77

[0] os_md.adj(x*dx^2+x^3*dx+1,x);x*dx^2+(-x^3+2)*dx-3*x^2+1
9. psymbol(p,,[[x1 ,∂x1 ],[x2 ,∂x2 ],. . .]):: principal symbol of diﬀerential operator
微分作用素 p の主表象を返す（cf. ghg2()）．
10. sftpexp(p,[x,∂x ],q,r) or sftpexp(p,[[x1 ,∂x1 ],. . .],q,r]):: 微分作用素 p を q −r ◦ p ◦ q r と変換する
q, r は有理式．ただし，r は（xν を含まない）パラメータ．
[0] os_md.sftpexp(dx*dy,[[x,dx],[y,dy]],exp(x-y),a);(dx+a)*dy-a*dx-a^2[1] os_md.sftpexp(dx*dy,[[x,dx],[y,dy]],x-y,a);((x^2-2*y*x+y^2)*dx+a*x-a*y)*dy+(-a*x+a*y)*dx-a^2+a[2] os_md.show(@@);(x − y)2 ∂x ∂y − a(x − y)∂x + a(x − y)∂y − a(a − 1)
11. appledo(p,r,[x,∂x ]):: Euler 型常微分作用素の有理式への作用の計算[0] os_md.appledo(dx^2,x^2+y/x,x);(4*x^3+y)/(x)12. divdo(p1 ,p2 ,[x,∂x ]|rev=1):: 常微分作用素の割り算• 戻り値 [q, r, m]⇒ m ∗ p1 = q ∗ p2 + r (ord m = 0, ord r < ord p2 )• rev=1 と指定すると
p1 ∗ m = p2 ∗ q + r (ord m = 0, ord r < ord p2 )[0] R=os_md.divdo(dx^2, x*dx+1, x);[x*dx-2,2,x^2][1] os_md.muldo(R[0],x*dx+1,x)+R[1];x^2*dx^2[2] R=os_md.divdo(dx^2,x*dx+1,x|rev=1);[x*dx+2,0,x^2][3] os_md.muldo(x*dx+1,R[0],x)+R[1];x^2*dx^2+4*x*dx+2[4] os_md.muldo(dx^2,R[2],x);x^2*dx^2+4*x*dx+2
13. mygcd(p1 ,p2 ,[x, ∂x ]|rev=1,dviout=n) or mygcd(p1 ,p2 ,[x]|rev=1,dviout=n)
mygcd(p1 ,p2 ,x|dviout=n), mygcd(p1 ,p2 ,0|dviout=n):: 有理函数係数の常微分作用素（または x の多項式，または正整数）p1 と p2 の GCD（最大公約元）• 戻り値を R とおくと GCD は R[0] = R[1]∗ p1 + R[2] ∗p2 となる．
R[1] R[2]R[3] ∗ p1 + R[4] ∗ p2 = 0 が成立し，行列は可逆．
R[3] R[4]
また R[3] ∗ p1 = −R[4] ∗ p2 が LCM となる．
• rev=1 を指定すると，上で積の順序が全て逆になる.
• ユークリッドの互除法による計算であるが，p1 と p2 の大きさが同じ場合は p1 を p2 で割ることか78

ら始める．

• dviout=0 : ユークリッド互除法での各ステップでのデータがリストのリストで返される．
整数のときは，リストの最初は，最初の整数の組，その後は商と余りの組のリストが，余りが 0 になるまで続く．
多項式と常微分作用素の時は，最初の式の組，その後は商と余りとスカラー倍の 3 つのデータの組（divdo() の返す値）が続くリスト．
• dviout=1 : ユークリッドの互除法の割り算が TEX を使って示される．
• dviout=2 : ユークリッドの互除法が行列の形で TEX を使って示される．
• dviout=-1,-2 : 上の TEX のソースが返される．

[0] P = os_md.muldo(x*dx+1,x*dx+1,x);x^2*dx^2+3*x*dx+1[1] Q = os_md.muldo(dx-1,x*dx+1,x);x*dx^2+(-x+2)*dx-1[2] os_md.mygcd(P,Q,[x]);[x*dx+1,(1)/(x+1),(-x)/(x+1),((-x-1)*dx+x+2)/(x+1),((x^2+x)*dx+x+2)/(x+1)][3] os_md.mygcd(P,Q,[dx]);[1,0,(1)/(x*dx^2+(-x+2)*dx-1),1,(-x^2*dx^2-3*x*dx-1)/(x*dx^2+(-x+2)*dx-1)][4] os_md.mygcd(234,111,0);[3,-9,19,37,-78][5] os_md.mygcd(234,111,0|dviout=0);[[234,111],[2,12],[9,3],[4,0]][6] os_md.mygcd(234,111,0|dviout=1);
234 = 2 × 111 + 12
111 = 9 × 12 + 3
12 = 4 × 3[7] os_md.mygcd(234,111,0|dviout=-1);
234&=2\times111+12\allowdisplaybreaks\\
111&=9\times12+3\allowdisplaybreaks\\
12&=4\times3[8] os_md.mygcd(234,111,0|dviout=2)$


234
111




=



2 1
1 0





  
 
9 1
12
19 2
12
=
1 0
3
9 1
3

  
 

4 1
3
78 19
3
19 2
=
,
=
1 0
0
37 9
0
9 1
  


3
−9 19
234
=
0
37 −78
111
=

2 1
1 0



111
12

[9] os_md.mygcd(P,Q,[x,dx]|dviout=2)$x2 ∂ 2 + 3x∂ + 1 = (x)(x∂ 2 − (x − 2)∂ − 1) + (x(x + 1)∂ + (x + 1))(x2 + 2x + 1)(x∂ 2 − (x − 2)∂ − 1) = ((x + 1)∂ − (x + 2))(x(x + 1)∂ + (x + 1))79[10] os_md.mygcd(P,Q,[x,dx]|dviout=2);




x 1
x∂ 2 − (x − 2)∂ − 1
1 0
x(x + 1)∂ + (x + 1)


 1

x+2
1
x 1
x(x + 1)∂ + (x + 1)
x+1 ∂ − (x+1)2
=
1 0
0
1
0
!

1
x
x
x(x + 1)∂ + (x + 1)
x+1 ∂ + (x+1)2
=
1
x+2
0
1
x+1 ∂ − (x+1)2x∂ + 1 xx∂ + 1
=
,
∂−1 1
0
!



1
x
− (x+1)2x∂ + 1x2 ∂ 2 + 3x∂ + 1(x+1)2
=
1
x+2
x
x+2
0
x∂ 2 − (x − 2)∂ − 1− x+1∂ + (x+1)2
x+1 ∂ + (x+1)2

x2 ∂ 2 + 3x∂ + 1
x∂ 2 − (x − 2)∂ − 1





=

14. mylcm(p1 ,p2 ,[x, ∂x ]|rev=1) or mylcm(p1 ,p2 ,[x]|rev=1)
mylcm(p1 ,p2 ,x), mylcm(p1 ,p2 ,0):: 有理函数係数の常微分作用素（または x の多項式，または正整数）p1 と p2 の LCM（最小公倍元）[0] P=os_md.mylcm((2-x)*dx-1,x*dx+1,[x,dx]);(x^2-2*x)*dx^2+(4*x-4)*dx+2[1] os_md.appldo(P,a/x+b/(2-x),[x,dx]);0[2] Q=os_md.mylcm((2-x)*dx-1,x*dx+1,x);(x^2-2*x)*dx^2+(2*x-2)*dx+1[3] fctr(Q);[[1,1],[x*dx+1,1],[(x-2)*dx+1,1]]
15. m1div(m,n,[x,∂x ]) or m1div(m,n,[x]) or m1div(m,n,x):: 有理函数係数の常微分作用素（or x の多項式）の正方行列 m と有理式（or x を含まない有理式）の正方行列 n に対し，m = R[1](∂x −n)+R[0]（or m = R[1](x−n)+R[0]）となるリスト R = [R[0], R[1]]を返す．R[0] は微分（or x）を含まない．
16. qdo(p1 ,p2 ,[x,∂x ]):: 常微分方程式 p1 u = 0 に対し q1 p2 u = 0 となる微分作用素 q1 と q2 p2 u = u となる微分作用素 q2 の
リスト [q1 , q2 ] を返す
q1 , q2 は以下の以下の性質をもつ．
qp2 u = 0 ⇒ ∃r such that q = rq1
qp2 u = u ⇒ ∃r such that q = q2 + rq1 and ord q２ ≤ ord q[0] P=os_md.ghg([a,b],[c]);(-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-b*a[1] os_md.qdo(P,dx,x);[(x^2-x)*dx^2+((a+b+3)*x-c-1)*dx+(b+1)*a+b+1,((-x^2+x)*dx+(-a-b-1)*x+c)/(b*a)]
17. mdivisor(m,[x,∂]|trans=1,step=1,dviout=t)
mdivisor(m,x|trans=1,step=1,dviout=t), mdivisor(m,0|trans=1,step=1,dviout=t):: 有理函数係数の常微分作用素/1 変数多項式や整数の行列の単因子を得る• 有理函数係数の常微分作用素の行列の場合は [O3, Lemma 1.10] に基づく．
• step=1 : 行と列の基本変形の途中過程を示す• trans=1 : 単因子，左からかける行変形行列，右からかける列変形行列の 3 成分のリストを返す.
trans=2 : 上の 3 成分の後に，行変形行列の逆行列，列変形行列の逆行列を加えた 5 成分のリスト
80

を返す.
• m が可逆 ⇔ 単因子が [1, 1, . . .]. この場合は trans=1 を指定したときの戻り値を R とおくと，
R[1] が逆行列，R[2] は単位行列となる.
• dviout=1 : 基本変形の途中過程を TEX で表示．
• dviout=-1 : dviout=1 の TEX のソースを返すが，表示はしない．
• dviout=2 : 基本変形の途中過程を TEX で表示．左右からかける行列も表示．
• dviout=-2 : dviout=2 の TEX のソースを返すが，表示はしない．
• dviout=3 : 基本変形の結果と変換行列とその逆行列を表示（trans=2 の情報）．
• dviout=-3 : dviout=3 の TEX のソースを返すが，表示はしない．
• unim() によって単因子計算や対角化の演習のための正方整数行列の生成ができる．

[0] A=os_md.s2m("12-1,2-22,-121");[ 1 2 -1 ][ 2 -2 2 ][ -1 2 1 ][1] os_md.mdivisor(os_md.mgen(3,0,[x],0)-A,x);[1,x-2,x^2+2*x-8][2] os_md.mdivisor(os_md.mgen(3,0,[x],0)-A,x|step=1);
1: start[ x-1 -2 1 ][ -2 x+2 -2 ][ 1 -2 x-1 ]1: (1,2) -> (1,1)[ -2 x-1 1 ][ x+2 -2 -2 ][ -2 1 x-1 ]1: unit[ 1 -1/2*x+1/2 -1/2 ][ 0 1/2*x^2+1/2*x-3 1/2*x-1 ][ 0 -x+2 x-2 ]2: start[ 1/2*x^2+1/2*x-3 1/2*x-1 ][ -x+2 x-2 ]2: (1,2) -> (1,1)[ 1/2*x-1 1/2*x^2+1/2*x-3 ][ x-2 -x+2 ][ 2 0 ]*
[ -4 2 ]2: line 1 & 2[ x-2 x^2+x-6 ][ 0 -2*x^2-4*x+16 ]*[ 1 -x-3 ][ 0 1 ]
2: column 1 & 2[ x-2 0 ]81

[ 0 -2*x^2-4*x+16 ]3: start[ -2*x-8 ][1,x-2,x^2+2*x-8][3] os_md.mdivisor(os_md.mgen(2,0,[dx],0),[x,dx]|step=1);
1: start[ dx 0 ][ 0 dx ]1: column 1 += col2*x[ dx 0 ][ x*dx+1 dx ][ -x 1 ]*[ x*dx+2 -dx ]1: line 1 & 2[ 1 dx ][ 0 -dx^2 ]1: unit[ 1 dx ][ 0 -dx^2 ]2: start[ -dx^2 ][[1,dx^2],[4] os_md.mdivisor(os_md.mgen(2,0,[dx],0),[x,dx]|trans=2);[[1,dx^2],[ -x 1 ][ -x*dx-2 dx ],[ 1 -dx ][ x -x*dx+1 ],[ dx -1 ][ x*dx+1 -x ],[ -x*dx dx ][ -x 1 ]][5] os_md.mdivisor(os_md.mgen(2,0,[dx],0),[x,dx]|dviout=2);
∂ 0 1 0
 0 ∂ 0 1
1 0

0 1
C1 + = C2 × (x)


∂
0 1 0
x∂ + 1 ∂ 0 1
→

1
0
x
1

 
−x
1
L1
x∂ + 2 −∂
L2


1
∂
−x
1
2
 0 −∂x∂ + 2 −∂ 
→

1
0
x
1
Cj − = C1 × ◦ (j > 1)

82




1
0
−x
1
2
0
−∂
x∂ + 2 −∂ 
→

1
−∂
x −x∂ + 1
L2 ← (−1) × L2


1
0
−x
1
2
0
∂
−x∂ − 2 ∂ 
→

1
−∂
x −x∂ + 1
As a result,

 


1 0
−x
1
∂ 0
1
=
−x∂ − 2 ∂
0 ∂
x
0 ∂2

−1 

−x
1
∂
−1
=
,
−x∂ − 2 ∂x∂ + 1 −x

−1 

1
−∂
−x∂ ∂
=
.
x −x∂ + 1
−x 1


−∂
,
−x∂ + 1

上の dviout=2 のオプションの結果から分かるように，以下のアルゴリズムで計算を行う．なお，以下にある行列 C は mygcd() によって求めている．
行列 A の成分はユークリッド環 R で、以下のいずれかとします．
(1) 整数環(2) 有理函数係数の１変数多項式環(3) 有理函数係数の常微分作用素環
アルゴリズムは以下の通り（a）A が零行列なら [0] を返す（b）A の零でない最小の (i, j) 成分を，行の交換，列の交換で (1, 1) 成分に移す（(i, j) は辞書式順序で最小なもの）．ここで最小とは，(1) 絶対値, (2) 次数, (3) 階数 が基準（c）A の 1 列目の 2 行目以下に零でない成分があれば，(1, 1) 成分とその最初の零でない成分を並べた
サイズ 2 の列ベクトルに適当な GL(2, R) の元 C を左からかけて，ベクトルの第 2 成分を零にするものを求める（← ユークリッドの互除法）．SL(2, R) でなくて GL(2, R) にしたのは，変換後の第 1 成分の係数が (2), (3) の時に多項式となるようにするため．1 行目と対応する行に左からC をかけて行変形する．そのあと (b) へ．
（d）A の 1 列目が第 1 成分を除いて零のとき．第 1 行の第 2 成分以降で零でないものがあれば，3.
と同様にサイズ 2 の行ベクトルとそれに右からかける GL(2, R) の元 C を求めて列変形を行い，(b) へ．
- 以下，(1, 1) 成分を除いて A の 1 行目と 1 列目の成分が全て 0 とする （e）A の行または列のサイズが 1 のとき，[(1, 1) 成分] を返す．
– 以下はそれ以外 –（f）A の (1, 1) 成分が可逆のとき，それを 1 と置き直して，以下の (g) ii) と同様なことを行う．
— (1) または (2) のとき —（g）(1, 1) 成分で割り切れない成分があるかどうか調べる.
i) 割り切れない成分をもつ列があれば，その列を 1 列目に加え，その成分が 2 行目でなければ 2
行目と行を交換．その後 (b) へii) すべて割り切れれば，1 行目と 1 列目を除いた行列を (1, 1) 成分で割ってできる，行と列のサ
イズが 1 ずつ小さな行列，を引数として，この函数を呼び，戻り値の各成分を (1, 1) 成分倍したリストに (1, 1) 成分を追加したリストを返す．
— (3) のとき —（h）零でない (1, 1) 成分以外の (i, j) 成分を選んで（辞書式順序で最小な (i, j) を選ぶ）それを P とし，P xk と (1, 1) 成分の作る左イデアルが (1, 1) 成分の作る左イデアルに入らない k を求める（kは (i, j) 成分の階数以下の非負整数となる）．なお x は微分との交換子が恒等写像となるかけ算作

83

用素．j 列目に xk を右からかけたものを 1 列目に加えて (b) へ．

step=1 を指定したときの表示される行列の上のコメントの意味は以下の通り．
• 最初の数字は，mdivisor() が呼ばれたネスティングの深さで，1 段深まると行列サイズが 1 減る
（cf. (f), (g) ii)）．
• start : この函数が呼び出されたときの行列．
• (a,b) -> (1,1) : a 行目と 1 行目，b 列目と 1 列目を交換して，(a,b) 成分を (1,1) に移動する（cf. (b)）.
• line 1 & a : 1 行目と a 行目に左から GL(2, R) をかけて (a,1) 成分を 0 にする（cf. (c)）．
• column 1 & b : 1 列目と b 列目に右から GL(2, R) をかけて (1,b) 成分を 0 にする（cf. (d)）．
• unit : (1,1) 成分が可逆元のときの処理（cf. (f)）.
• column 1 += col b, line 2<->a : 1 列目に b 列目を加えて，2 行目と a 行目を交換（cf. (g)i)）．
• column 1 += col b*x^k : b 列目に右から x^k をかけたものを 1 列目に加える（ cf. (h)）.
1 2
一方，TEX においては，i 行目を Li と表し, j 列目を Cj と表して，たとえばを 3 行目と 5 行
3 4目にかけるのは



1
3

 
2
L3
4
L5

と表す.

[6] os_md.mdivisor(mat([3,5,7],[5,3,3]),0|dviout=2)
3 5 7 1 0
5 3 3 0 1
1 0 00 1 0
0 0 1
 

L1
2 −1
L2
−5 3


1
7
11
2 −1
0 −16 −26 −5 3 


0
0
→ 1


0
1
0
0
0
1
Cj − = C1 × ◦ (j > 1)


1
0
0
2 −1
0 −16 −26 −5 3 → 1 −7 −11


0
1
0
0
0
1


−5 −13(C2 C3)
3
8


1 0
0
2 −1
0 2
0
−5 3 
3→ 1 2
0 −5 −13
0 3
8
As a result,

 

1 0 0
2 −1
3 5
=
0 2 0
−5 3
5 3
84

7
3

 1
0
0

2
−5
3

!
3
−13 ,
8



2
−5
1
0
0

−1 

−1
3 1
=
,
3
5 2
!−1
2
3
1 7
−5 −13= 0 −8
3
8
0 3

!
11
−13 .
5

[7] os_md.mdivisor(mat([dx,0,0],[0,dx,0],[0,0,dx]),[x,dx]|dviout=3)
!
!
1 0 0
∂ 0 0
0 1 0 = P 0 ∂ 0 Q,
0 0 ∂0 0 ∂3

 
−1
1 2
−x
1
0
∂
−x2 ∂ 2 − 4x∂ − 2
2 x ∂ + 2x
− 12 x2 ∂ − 2x  = x∂ + 1 −x3 ∂ 2 − 4x2 ∂ − 2x 12 x3 ∂ + 2x2  ,P =  − 12 x∂ − 1 21 ∂−1
−x∂ 2 − 3∂ ∂ 2 −x2 ∂ 2 − 6x∂ − 6
0
∂
2



−1
1 2 3
2
2
−x∂
∂
0
1 −x ∂ − 2x
2 x ∂ + x∂ − ∂Q = x −x3 ∂ − x2 12 x3 ∂ 3 + 12 x2 ∂ 2 − x∂ + 1 = − 12 x∂ 2 − ∂ 12 ∂ 2 − 12 x2 ∂ 2 − 2x∂  .
−x
1
−x2
0
1
− 12 ∂ 2[8] A=mat([2,-2,-2],[0,1,-1],[0,0,2])$[9] os_md.mdivisor(os_md.mgen(3,0,[x],0)-A,x|dviout=2)$
x − 22
2
1 0 0
0
x
−
1
1
0
1 0

 0
0
x
−
2
0
0
1


 1

0
0


0
1
0
0
0
1
C1 ↔ C2
 2
x−2
2
1 0 0
01
0 1 0
x − 1
 0
0
x
−
2
0
0 1

→
 0

1
0


1
0
0
0
0
1
1
L1 ← ( ) × L1
 2

1
1
1
1
0 0
2 (x − 2)2x − 10
10 1 0 00x − 2 0 0 1
→

1
0
 0

 1

0
0
0
0
1
Li − = ◦ × L1 (i > 1)


1
1
1
1
0 0
2 (x − 2)20 − 1 (x − 2)(x − 1) −(x − 2) − 1 (x − 1) 1 0
2
2



0
x−2
0
0 1
→ 0

1
0
0

1

0
0
0
0
1
Cj − = C1 × ◦ (j > 1)

85



1
1
0
0
0 0
2
0 − 21 (x − 2)(x − 1) −(x − 2) − 12 (x − 1) 1 0


0
0
x−2
0
0 1
→

1
0
0

1

1
− 2 (x − 2)−1
001
L2 ↔ L3, C2 ↔ C3


1
0 0
1
0
0
2
0
x−2
0
0
0 1


0 −(x − 2) − 21 (x − 2)(x − 1) − 12 (x − 1) 1 0
→

0
1
0

1

−1
− 12 (x − 2)
0
1
0

 
1 0
L2
1 1
L3


1
1
0
0
0 0
2
0 x − 2
0
0
0 1


0
0
− 12 (x − 2)(x − 1) − 12 (x − 1) 1 1
→

0
1

0

1
−1
− 12 (x − 2)0
10L3 ← (−2) × L3


1
1
0
0
0
0
2
0 x − 2
0
0
0
1


0
(x − 2)(x − 1) x − 1 −2 −2
0
→

0
1
0

1
1

−1
− 2 (x − 2)0
10
As a result,

!  1
1
0
0
x−2
0
0
2
0 x−2
0
0
= 0
0
1
0
0
(x − 2)(x − 1)0
x − 1 −2 −2

−1 

1
2
0
0
0
0
2
 0
0
1  = x − 1 −1 − 12  ,x − 1 −2 −2
0
1
0

−1 

1
0 0
1
(x − 2) 1 1
2
1 −1 − 1 (x − 2) = 
00 1 .
2
0 1
0
1
0 0

2
x−1
0

!
0
2
1
1
x−2
0

0
−1
1


1
− 21 (x − 2)
0

18. sqrtdo(p,[x,∂x ]) ?
√:: x 7→ 1/x で（x のべき倍を除いて）不変な微分作用素 p に対する変数変換 x 7→ y = x + x2 − 1
x = 21 (y + y −1 ) に注意
19. toeul(p,[x,∂x ],n):: （Fuchs 型）常微分作用素を x = n で Euler 型に変換
変数変換 x 7→ x + n のあと x∂x を ∂x で置き換え，多項式係数にする.
ただし，n が文字列 "infty" のときは，変数変換 x 7→ 1/x のあと x∂x を ∂x で置き換える.
最後に x の巾を掛けて x = 0 で消えない作用素に調整する．
[0] os_md.toeul(os_md.ghg([a,b],[c]), x, 0);(-x+1)*dx^2+((-a-b)*x+c-1)*dx-b*a*x[1] os_md.toeul(os_md.ghg([a,b],[c]), x, "infty");86

(x-1)*dx^2+((-c+1)*x+a+b)*dx-b*a
20. fromeul(p,[x,px ],n):: Euler 型常微分作用素を元に戻す（toeul(p, [x, ∂x ], n) の逆変換）
最後に x − n の巾をかけて x = n で消えない多項式係数とする．
[0] os_md.fromeul(dx,x,1);dx[1] os_md.fromeul(dx-a,x,1);(x-1)*dx-a
21. expat(p,[x,∂x ],n):: 確定特異点型常微分作用素の x = n での特性指数を求める• n は文字列 “infty” でもよい（n = ∞ に対応）．
• Fuchs 型常微分作用素で n が文字列 “?” のときは，全ての特異点とそこでの特性指数とを求める．
• 以下，例で現れる ghg() については，(76) を参照[0] os_md.expat(os_md.ghg([a,b,c],[d,e]), x, 0);[-d+1,-e+1,0][1] os_md.expat(os_md.ghg([a,b,c],[d,e]), x, 1);[-a-b-c+d+e,1,0][2] os_md.expat(os_md.ghg([a,b,c],[d,e]), x, 2);[1,2,0][3] os_md.expat(os_md.ghg([a,b,c],[d,e]), x, "infty");[a,b,c][4] os_md.expat(os_md.ghg([a,b,c],[d,e]), x, "?");[[0,[-d+1,-e+1,0]],[1,[-a-b-c+d+e,1,0]],[infty,[a,b,c]]]22. sftexp(p,[x,∂x ],n,r):: 常微分作用素 p を (x − n)−r ◦ p ◦ (x − n)r に変換する
ただし，[∂x , r] = 0 とする（以下同様）．
[0] P=os_md.ghg([a,b],[c]);(-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-b*a[1] os_md.sftexp(P,x,0,1-c);(-x^2+x)*dx^2+((-a-b+2*c-3)*x-c+2)*dx+(-b+c-1)*a+(c-1)*b-c^2+2*c-1[2] Q=os_md.sftexp(P,x,"infty",b);(-x^3+x^2)*dx^2+((-a+b-1)*x^2+(-2*b+c)*x)*dx+b^2+(-c+1)*b[3] os_md.expat(Q,x,"infty");[a-b,0]23. fractrans(p,[x,∂x ],n0 ,n1 ,n2 ):: 常微分作用素 p に x の一次分数変換 (n0 , n1 , n2 ) 7→ (0, 1, ∞) を行う[0] os_md.fractrans(os_md.ghg([a,b],[c]),x,1,0,"infty");(-x^2+x)*dx^2+((-a-b-1)*x+a+b-c+1)*dx-b*a[1] P=os_md.fractrans(os_md.ghg([a,b],[c]),x,"infty",1,0);(x^3-x^2)*dx^2+((-c+2)*x^2+(a+b-1)*x)*dx-b*a[2] os_md.expat(P,x,1);[-a-b+c,0]87

[3] os_md.expat(P,x,0);[a,b]
24. chkexp(p,[x, ∂x ],n,r,m):: j = 0, . . . , m − 1 の全てに対し，確定特異点型常微分作用素 p の解 uj で (x − n)−(r+j) uj が x = nで正則でそこでの値が 1 となるものが存在する条件を求める．
[0] os_md.chkexp(os_md.ghg([a,b],[c]),x,0,0,1);[][1] os_md.chkexp(os_md.ghg([a,b],[c]),x,"infty",0,2);[a+b-1,-b*a][2] os_md.chkexp(os_md.ghg([a,b],[c]),x,"infty",0,1);[-b*a]
25. soldif(p,[x, ∂x ],n,q,m)P∞:: 常微分作用素 p の x = n の近傍での z q (1 + j=1 cj z j ) の形の形式解に対し，長さ m + 1 のベク
トル [1 c1 c2 · · · cm ] を返す（z = x − n）．
z j log z の項が現れる解も構成される．？
n ="infty" のときは，x = ∞, z = 1/x とする．
[0] R=os_md.soldif(os_md.ghg([a,b],[c]),x,"infty",a,4);[ 1 (a^2+(-c+1)*a)/(a-b+1) (1/2*a^4+(-c+2)*a^3+(1/2*c^2-5/2*c+...
[1] fctr(dn(R[4]));[[1,1],[a-b+1,1],[a-b+2,1],[a-b+3,1],[a-b+4,1]][2] fctr(nm(R[4]));[[1/24,1],[a,1],[a+1,1],[a+2,1],[a+3,1],[a-c+1,1],[a-c+2,1],[a-c+3,1],[a-c+4,1]]
26. okuboetos(p, [x, ∂x ]| diag=[c1 , c2 , . . . ]):: 単独 Okubo 型方程式 pu = 0 を Okubo 型の 1 階のシステムに変換する
m 階の多項式係数の常微分方程式 pu = 0 は，p の n 階微分の係数が n 次以下の多項式ならば Okubo
型（n = 0, . . . , m）．
• 戻り値は [[a0 , . . . , am−1 ], B, T ]• オプション diag=[c0 , c1 , . . . ] によって，[a0 , . . . , am−1 ] の順序を変えたものを指定することができる．
• 単独 Fuchs 型のとき，p 7→ p ∗ ∂x + p0 の変換を何度か施すと Okubo 型になる

(x − ai )u0i =m−1XBij uj

j=0

ui =

m−1
X

Ti,j u(j) .

j=0[0] P = os_md.ghg([a,b],[c]);(-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-b*a[1] R = os_md.okuboetos(P,x)$[2] R[0];[ 0 1 ]
[3] R[1];88(i = 0, . . . , m − 1),[ -c+1 1 ][ (-b+c-1)*a+(c-1)*b-c^2+2*c-1 -a-b+c-1 ][4] R[2];[ 1 0 ]
[ c-1 x ][5] det(R[1]);b*a[6] os_md.fctrtos(R[1][1][0]);-(b-c+1)*(a-c+1)[7] R = os_md.okuboetos(P,x|diag=[1,0])$[8] R[0];[ 1 0 ]
[9] R[1];[ -a-b+c 1 ][ (-b+c)*a+c*b-c^2 -c ][10] R[2];[ 1 0 ]
[ a+b-c x-1 ]]以上から

u = F (a, b, c; x),
 

u0
u
=
,
u1
(c − 1)u + xu0
 0  
u0
1−c
=
x−1
−(b − c + 1)(a − c + 1)
u01




x

 
u0
1
.
−a − b + c − 1
u1

特に


  
v0
u
,
=
x
c−1
0
v1
a−c+1 u + a−c+1 u 0 
 
v0
v0
1−c
a−c+1
=
,
x−1
−(b − c + 1) −a − b + c − 1
v10
v1




1−c a−c+10000−b + c − 1 −a − b + c − 1
dv
=
v+
v
dx
x
x−1
v=



x

27. stoe(p,[x, dx],m):: 1 階の線型常微分方程式系を単独高階に直す
P• 方程式系 u0i = j≥0 pij (x)uj の um の満たす方程式を返す．p は有理式を成分とする正方行列．
• m がリスト [m1 , m2 ] のときは，um1 を um2 を用いて表す (um2 に施す微分作用素）．
• m が負数のときは，[−m, 0] を表す．
• 非線形の場合は baseODE()．
[0] A=newmat(2,2,[[(-c+1)/(x),(a-c+1)/(x)],[(-b+c-1)/(x-1),(-a-b+c-1)/(x-1)]]);[ (-c+1)/(x) (a-c+1)/(x) ][ (-b+c-1)/(x-1) (-a-b+c-1)/(x-1) ][1] os_md.stoe(A,x,0);(x^2-x)*dx^2+((a+b+1)*x-c)*dx+b*a89

[2] T=os_md.mgen(4,0,[x,x-1,x,x-1],0);[ x 0 0 0 ][ 0 x-1 0 0 ][ 0 0 x 0 ][ 0 0 0 x-1 ][3] A=newmat(4,4,[[a1,1],[a21,a2,1],[a31,a32,a3,1],[a41,a42,a43,a4]]);[ a1 1 0 0 ][ a21 a2 1 0 ][ a31 a32 a3 1 ][ a41 a42 a43 a4 ][4] C=os_md.myinv(T)*A;[ (a1)/(x) (1)/(x) 0 0 ][ (a21)/(x-1) (a2)/(x-1) (1)/(x-1) 0 ][ (a31)/(x) (a32)/(x) (a3)/(x) (1)/(x) ][ (a41)/(x-1) (a42)/(x-1) (a43)/(x-1) (a4)/(x-1) ][5] P=os_md.stoe(C,x,0)$[6] os_md.expat(P,x,"?");[[0,[a3+1,a1,1,0]],[1,[a4+2,a2+1,1,0]],[infty,[dx^4+(a4+a3+a1+a2)*dx^3+(-a21-a32-a43+(a3+a1+a2)*a4+(a1+a2)*a3+a2*a1)*dx^2+((-a4-a3)*a21+(-a4-a1)*a32+(-a1-a2)*a43+a31+a42+((a1+a2)*a3+a2*a1)*a4+
a2*a1*a3)*dx+(a43-a3*a4)*a21-a1*a4*a32-a41-a2*a1*a43+a4*a31+a1*a42+a2*a1*a3*a4]]][7] os_md.mperm(A,[0,2,1,3],1);[ a1 0 1 0 ][ a31 a3 a32 1 ][ a21 1 a2 0 ][ a41 a43 a42 a4 ][8] Q=E[2][1][0]-os_md.polbyroot([1,4],dx|var=a);(-a21-a32-a43)*dx^2+((-a4-a3)*a21+(-a4-a1)*a32+(-a1-a2)*a43+a31+a42)*dx+(a43-a3*a4)*a21-a1*a4*a32-a41-a2*a1*a43+a4*a31+a1*a42
28. etos(p,[x, dx],m):: 単独高階線型常微分方程式を 1 階系に直す
n 階の方程式 P u = 0 を一階系 ũ0 = Aũ に変換し，行列 A を返す．
P
• m は有理式成分の行列で，成分を mij とするとき，一階系の i 番目の成分を ui =mij u(j) とする．

• m = 1 のときは，m は単位行列と見なす．
• m が長さ n のリストの時，成分がそれで与えられる対角行列を m とみなす．
[0] P=(-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-a*b$[1] M=os_md.etos(P,x,[1,x]);[ 0 1 ][ (-b*a)/(x-1) ((-a-b-1)*x+c)/(x^2-x) ][2] os_md.pfrac(M,x|dviout=1);

 

0 1
0
0
0 0
−ba −(a + b − c + 1)
+
x
x−1
90

29. dform(ℓ, x|dif=1)
P
P:: 変数 x[0], x[1], . . . の 1 次微分形式ℓ[i][0]d(ℓ[i][1]), または 2 次微分形式ℓ[i][0]d(ℓ[i][1]) ∧d(ℓ[i][2]) の計算．dif=1 は 1 次微分形式の外微分の計算．
• ℓ[i][j] は行列でもよい• dif=1 は，1 次形式の外微分を計算する[0] os_md.dform([[a*y,x/y],[b*x,y/x]],[x,y]);[(a*x-b*y)/(x),x],[(-a*x+b*y)/(y),y]][1] os_md.dform([[a*y,x/y,x],[b*x,y/x,y]],[x,y]);[[(a*x^2-b*y^2)/(y*x),x,y]][2] os_md.dform([[x-y,y],[x-y+1,x]],[x,y]|dif=1);[[2,x,y]]上の計算は，以下を意味する．
−ax+byay · d( xy ) + bx · d( xy ) = ax−bydy
x dx +
y−byax · d( xy ) ∧ dx + bx · d( xy ) ∧ dy = ax xy
dx ∧ dyd (x − y)dy + (x − y − 1)dx = 2dx ∧ dy2

2

30. solpokubo(p,[x, ∂x ],n):: 単独 Okubo 型常微分作用素 p の n 次の固有多項式と固有値を求める
Okubo 型常微分作用素とは，k 階微分の係数が k 次以下の多項式で，最高階は階数と次数が等しい作
用素[0] P=x*(1-x)*dx^2+(c-a*x)*dx;(-x^2+x)*dx^2+(-a*x+c)*dx[1] os_md.solpokuboe(P,[x,dx],1);[a*x-c,-a][2] os_md.solpokuboe(P,[x,dx],2);[(a^2+3*a+2)*x^2+((-2*c-2)*a-2*c-2)*x+c^2+c,-2*a-2][3] os_md.fctrtos(@@[0]|var=x);(a+1)*(a+2)*x^2-2*(c+1)*(a+1)*x+c*(c+1)
31. getSSE(p,[x,y,. . . ]|get=s):: Get singularities, rank,... of holonomic systems deﬁned by the ideal p etc.
• p is an ideal of a Weyl algebra given by a list
• Singurarities of the equation• get="rank" : rank of the equation if it is holonomic• get="gr" : Groebner base• get="top" : top terms of the Groebner base• get=symbol : symbol ideal• get="base" : base of the quotiend by the ideal[0] F2=os_md.ghg2([a,b,c],[[0,d],[0,e],[]]); /* Appell’s F_2 */[(-y*x*dx-a*y)*dy+(-x^2+x)*dx^2+((-a-c-1)*x-d+1)*dx-c*a,(-y^2+y)*dy^2+(-y*x*dx+(-b-c-1)*y-e+1)*dy-b*x*dx-c*b][1] os_md.getSSE(F2,[x,y]);[y,y-1,x,x-1,x+y-1]/* singularities */[2] os_md.getSSE(F2,[x,y]|get="rank");91

4[3] os_md.getSSE(F2,[x,y]|get="base");[dy^2,dx,dy,1][4] os_md.getSSE(F2,[x,y]|get="top");[dx*dy,dx^2,dy^3][5] os_md.getSSE(F2,[x,y]|get="symbol");[(-y^2+y)*dy^2-y*x*dx*dy,(-y^2+y)*dy^2+(x^2-x)*dx^2,((y^2-y)*x+y^3-2*y^2+y)*dy^3,(y^2-y)*dy^3+(-y^2+y)*dx*dy^2][13366] os_md.getSSE(F2,[x,y]|get="gr");[(-y^2+y)*dy^2+(-y*x*dx+(-b-c-1)*y-e+1)*dy-b*x*dx-c*b,...
[6] F21=os_md.ghg2([[a,aa],[b,bb],[c,cc]],[[0,d,dd],[0,e,ee],[f]])$[7] os_md.getSSE(F21,[x,y]);[y,y-1,x,x-1,x+y,x+y-1][8] os_md.getSSE(F21,[x,y]|get="rank");
14[9] os_md.getSSE(os_md.ghg2([1,1,2],[2,2,1]|symbol=1),[x,y]);[y,y-1,x,x-1,x+y,x+y-1][10] os_md.getSSE(os_md.ghg2([2,2,1],[1,1,2]|symbol=1),[x,y]);[y,y-1,x,x-1,x+y,(y-1)*x-y][11] os_md.getSSE(os_md.ghg2([0,0,2],[2,2,0]|symbol=1),[x,y]);[y,x,x^2+(-2*y-2)*x+y^2-2*y+1][12] os_md.getSSE(os_md.ghg2([1,1,2],[3,3,0]|symbol=1),[x,y]);[y,y-1,x,x-1,x^2+(-2*y-2)*x+y^2-2*y+1][13] os_md.getSSE(os_md.ghg2([1,1,3],[3,3,1]|symbol=1),[x,y]);[y,y-1,x,x-1,x-y,x^2+(-2*y-2)*x+y^2-2*y+1][14] os_md.getSSE(os_md.ghg2([2,2,4],[4,4,2]|symbol=1),[x,y]);[y,y-1,x,x-1,x-y,x^2+(-2*y-2)*x+y^2-2*y+1][15] os_md.getSSE(os_md.ghg2([2,2,4],[4,4,2]|symbol=1),[x,y]|get="rank");
28[16] os_md.getSSE(os_md.ghg2([0,0,3],[3,3,0]|symbol=1),[x,y]);[y,x,x^3+(3*y-3)*x^2+(3*y^2+21*y+3)*x+y^3-3*y^2+3*y-1][17] os_md.getSSE(os_md.ghg2([1,1,4],[4,4,1]|symbol=1),[x,y]);[y,y-1,x,x-1,x+y,x^3+(3*y-3)*x^2+(3*y^2+21*y+3)*x+y^3-3*y^2+3*y-1][18] os_md.getSSE(os_md.ghg2([0,0,4],[4,4,0]|symbol=1),[x,y]);[y,x,x^4+(-4*y-4)*x^3+(6*y^2-124*y+6)*x^2+(-4*y^3-124*y^2-124*y-4)*x+y^4-4*y^3+6*y^2-4*y+1][19] os_md.getSSE(os_md.ghg2([1,1,1,1],[2,2,2,0]|symbol=1),[x,y,z]);[z,z-1,y,y-1,y+z-1,x,x-1,x+z-1,x+y-1,x+y+z-1][20] os_md.getSSE(os_md.ghg2([1,1,1,2],[2,2,2,1]|symbol=1),[x,y,z]);[z,z-1,y,y-1,y+z,y+z-1,x,x-1,x+z,x+z-1,x+y,x+y-1,x+y+z,x+y+z-1][21] os_md.getSSE(os_md.ghg2([1,1,1,2],[2,2,2,1]|symbol=1),[x,y,z]|get="rank");
15

92

3.1.2 Fractional calculus
この項は，[O3]，[O5], [O7], [O9], [O10] などの主要結果（基本的部分は [O2] で解説）を Risa/Asir 上で実現したものとなっている．

32. laplace(p,[x, ∂x ])laplace(p,[[x1 , ∂x1 ],[x2 , ∂x2 ], . . . ]):: 微分作用素 p の（部分）Laplace 変換 (x, ∂x ) 7→ (−∂x , x)[0] os_md.laplace(x^2*dx+1,x);x*dx^2+2*dx+1
33. laplace1(p,[x, ∂x ])laplace1(p,[[x1 , ∂x1 ],[x2 , ∂x2 ], . . . ]):: 微分作用素 p の（部分）逆 Laplace 変換(x, ∂x ) 7→ (∂x , −x)[0] os_md.laplace1(x^2*dx+1,x);-x*dx^2-2*dx+1
34. mc(p,[x, ∂x ],r):: 常微分作用素 p の middle convolution mcr (p)[0] P=os_md.mc(x*(1-x)*dx-a-b*x,x,r);(x^2-x)*dx^2+((-2*r+b+2)*x+r+a-1)*dx+r^2+(-b-1)*r+b[1] os_md.expat(P,x,"?");[[0,[r+a,0]],[1,[r-a-b,0]],[infty,[-r+b,-r+1]]]
35. mce(p,[x, ∂x ],n,r):: 常微分作用素 p を (∂x − n)−r ◦ p ◦ (∂x − n)r と変換して常微分作用素に戻す.
ただし n は，∂x と可換とする．n = 0 のときは middle convolution mcr (p)．
36. rede(p,[x, ∂x ])rede(p,[[x1 , ∂x1 ],[x2 , ∂x2 ], . . . ]):: 部分作用素 p の reduced representative を返す[0] os_md.rede(x*(y^2-1)*dx+(y+1)/x*dy,[[x],y]);dy+(y-1)*x^2*dx
37. ad(p,[x, ∂x ],f ):: 常微分作用素 p の ∂x を ∂x − f に置き換える変換
38. add(p,[x, ∂x ],f ):: 常微分作用素 p の ∂x を ∂x − f に置き換える addition，すなわち rede(ad())[0] os_md.add(dx^2+x,x,1/x^2);
x^4*dx^2-2*x^2*dx+x^5+2*x+1
39. vadd(p,[x, ∂x ],[[c0 , r0 ],[c1 , r1 ], . . . ])P
rj x j:: Versal addition add(p,[x, ∂x ], j≥0 ∏j (1−c
)
ν x)
ν=0
40. addl(p,[x, ∂x ],f ):: 常微分作用素の addition の Laplace 変換 laplace1(add(laplace()))[0] os_md.add(x,x,a/(x-c));-x*dx+c*x-a-1

9341. cotr(p,[x, ∂x ],f ):: 常微分作用素 p の x 7→ f (x) による座標変換
42. rcotr(p,[x, ∂x ],f ):: 常微分作用素 p の x 7→ f (x) による座標変換の reduced representative
43. s2sp(p|num=1,std=k,short=1):: スペクトル型を表す文字列と “数のリストのリスト”との変換• 10, 11, 12, . . . , 35 は，a,b,c,...,z で表す．負の数や ^ や分数も有効．
• ^ は（べき乗ではなく）同じ数の繰り返しを表す.
• 10 以上の数を ( ) で括って表してもよいが，括弧のネスティングは不可．
• num=1 を指定すると，a,b,c,... は戻り値に使わずに括弧で括って表す．
• 引数においては，36, 37, . . . , 60 を A, B, . . . , Z と表してもよい．
• 有理数以外は< >で囲った文字列に変換される．
• std=k を指定すると戻り値を, 各特異点での重複度を大きい順にして
k = 1 の時は各特異点を重複度の辞書式順序を小さい順に
k = −1 のときは各特異点を重複度の辞書式順序を大きい順に並べたスペクトル型とする．

• short=1 を指定すると，同じ重複度が 4 個以上続くときに ^* を使う短縮形の文字列に変換する．
このとき std=k のオプションも同次指定可能．
[0] os_md.s2sp("121,22,211");[[1,2,1],[2,2],[2,1,1]][1] os_md.s2sp(@@);
121,22,211[2] os_md.s2sp("5^2,541,1^a");[[5,5],[5,4,1],[1,1,1,1,1,1,1,1,1,1]][3] os_md.s2sp("2-3a,1^9");[[2,-3,10],[1,1,1,1,1,1,1,1,1]][4] newmat(4,4,os_md.s2sp("1,01,001,0001"));[ 1 0 0 0 ][ 0 1 0 0 ][ 0 0 1 0 ][ 0 0 0 1 ][5] S=os_md.s2sp("1(-15)a-b,fg-7/(80)");[[1,-15,10,-11],[15,16,-7/80]][6] os_md.s2sp(S);1(-15)a(-11),fg(-7/80)[7] os_md.s2sp(S|num=1);
1(-15)(10)(-11),(15)(16)(-7/80)[8] os_md.s2sp([[1,2],[a-b,2.5]]);12,<a-b><2.5>[9] os_md.s2sp(@@);[[1,2],[a-b,2.5]][10] os_md.s2sp(os_md.s2sp("32,2111,41,23"|std=1));
2111,32,32,41[11] os_md.s2sp(os_md.s2sp("32,2111,41,23"|std=-1));
41,32,32,2111

94

[12] os_md.s2sp("111111,33,222"|short=1,std=-1);
33,222,1^6
44. s2csp(p|n=f ):: 不分岐合流スペクトル型を表す文字列と “数のリストによる表現”との変換• 合流スペクトル型は，各特異点での不確定特異点型のリスト• 不確定特異点型は，不確定度に応じた重複度とその中身のリスト（リカーシブに定義される）• 不分岐合流スペクトル型は versal unfolding を使って文字列で表す（cf. [O10]）.
• n = 1 では，括弧で囲む表記による文字列入出力もサポート（cf. [Hiroe-Kawakami-Nakamura-Sakai]）．
• n = −1 では，括弧で囲む上の表記をリストにした入出力をサポート．
[0] L=os_md.s2csp("111,21,111");[[1,1,1],[2,1],[1,1,1]][1] os_md.s2csp(L);111,21,111[2] L=os_md.s2csp("111|21,111");[[[2,[1,1]],[1,[1]]],[1,1,1]][3] os_md.s2csp(L);111|21,111[4] os_md.s2csp(L|n=1);(1 1) (1),1 1 1[5] L=os_md.s2csp("111|111,21");[[[1,[1]],[1,[1]],[1,[1]]],[2,1]][6] os_md.s2csp(L);
111|111,21[7] os_md.s2csp(L|n=1);(1) (1) (1),2 1[8] L=os_md.s2csp("111|111|21");[[[2,[[1,[1]],[1,[1]]]],[1,[[1,[1]]]]]][9] os_md.s2csp(L);
111|111|21[10] os_md.s2csp(L|n=1);((1) (1)) ((1))[11] os_md.s2csp("((1)(1))((1))"|n=1);
111|111|21[12] os_md.s2csp("(1)(1)(1),21"|n=-1);[[[1],[1],[1]],[2,1]][13] os_md.s2csp( [[[1],[1],[1]],[2,1]]|n=-1);(1) (1) (1),2 1
45. chkspt(m|mat=1,dumb=1) または chkspt(m|opt=t,dumb=1) または fspt(m,t):: 分割の組 m（スペクトルタイプ）または generalized Riemann scheme（GRS）をチェックして[pts, ord, idx, f uchs, rod, redsp, f spt] を返す
pts
特異点の数（分割の組の数）
ord
階数
idx
rigidity index
f uchs Fuchs の関係式

95

rod
reduction での階数減
redsp reduction exponents のリスト
f spt
対応する basic なスペクトルタイプ
m は Kac-Moody ルート系のルート束の元で指定してもよい（cf. sproot()）.
m = [n, [n0,1 , n0,2 , . . . ], [n1,1 , n1,2 , . . . ] . . . , ],mj,ν = nj,ν−1 − mj,ν(j ≥ 0, ν ≥ 1)

• mat=1 : Schleginger 型を意味する.
• dumb=1 : エラー表示抑制を意味する．
• 戻り値 −1 は分割が不正，0 は実現不可能，を意味する．
以下順に t = 0, 1, . . . であり fspt(m,t) としてもよいが，文字列により opt を指定した場合 chkspt()
のみ可能で• opt="sp" or 0: 与えられた GRS のスペクトルタイプを返す．
• opt="basic" or 1: chkspt(m) の戻り値のリストの 7 番目の f spt のみを返す．realizable でな
いときは 0 を返す．
• opt="construct" or 2: basic なスペクトルタイプからの構成を示す．realizable でないときは 0を返す．

• opt="strip" or 3: generalized Riemann scheme またはスペクトルタイプから重複度 0 の項を削る．

• opt="short" or 4: GRS を短縮形に• opt="long" or 5: GRS を短縮形から戻す• opt="sort" or 6: スペクトル型を各点でソートして返す• opt="root" or 7: Kac-Moody Weyl 群での構成を示す．
戻り値のリストは 3 成分で，最初は base，次は与えたもの，最後が鏡映のリスト．鏡映は 3 成分
で最初が内積の値，次とその次で，枝の番号と頂点からの番号．

• opt="idx" : Index of rigidity を返す（数字による指定は不可）• opt="kac" : Kac-Moody ルート系のルート束の元を返す
短縮形とは，重複度が 1 の exponent は，重複度込みのリストから exponent のみ短くしたもの．
[0] os_md.chkspt([[1,2,1],[2,2],[1,1,1,1]]);[3,4,2,0,1,[ 1 0 0 ],[[1],[1],[1]]]][1] os_md.chkspt("121,22,1111");[3,4,2,0,1,[ 1 0 0 ],[[1],[1],[1]]]][2] M=os_md.sp2grs([[1,1,1,1],[2,1,1],[2,2]],[a,b,c],[1,1]);[[[1,-2*c1-2*c0-b1-2*b0-a1-b2-a3-a2+3],[1,a1],[1,a2],[1,a3]],[[2,b0],[1,b1],[1,b2]],[[2,c0],[2,c1]]][3] os_md.sp2grs([[1,1,1,1],[2,1,1],[2,2]],[a,b,c],[1,1]|mat=1);[[[1,-2*c1-2*c0-b1-2*b0-a1-b2-a3-a2],[1,a1],[1,a2],[1,a3]],[[2,b0],[1,b1],[1,b2]],[[2,c0],[2,c1]]][4] os_md.chkspt(M|opt="sp");[[1,1,1,1],[2,1,1],[2,2]][5] os_md.chkspt(M|opt="basic");[[1],[1],[1]][6] os_md.chkspt(M|opt="construct");[[[1],[1],[1]],[[1,1],[1,1],[1,1]],96[[1,1,1],[1,1,1],[2,1]],[[1,1,1,1],[2,1,1],[2,2]]][7] os_md.chkspt(M|opt="short");[[-2*c1-2*c0-b2-b1-2*b0-a2-a1-a3+3,a1,a2,a3],[[2,b0],b1,b2],[[2,c0],[2,c1]]][8] os_md.chkspt([[0,1,2,1],[2,0,2,0],[1,1,1,1]]|opt="strip");[[2,1,1],[2,2],[1,1,1,1]][9] os_md.chkspt([[0,1,2,1],[2,0,2,0],[1,1,1,1]]|opt="sort");[[2,1,1,0],[2,2,0,0],[1,1,1,1]][10] os_md.chkspt("21,21,21,21"|opt="root");[[[1],[1],[1],[1]],[[2,1],[2,1],[2,1],[2,1]],[[1,3,1],[1,2,1],[1,1,1],[1,0,1],[2,0,0]]][11] os_md.chkspt("21,21,21,111");[4,3,0,0,1,[ 0 0 0 0 ],[[1,1],[1,1],[1,1],[1,1]]][12] os_md.chkspt([[3,2],[2,2,1],[1,1,1,1]]);
illegal partitions-1[13] os_md.chkspt("31,31,31,22");
not realizable
0[14] os_md.chkspt("43,322,1^7");[3,7,0,0,1,[ 0 0 0 ],[[3,3],[2,2,2],[1,1,1,1,1,1]]][15] os_md.chkspt("21,21,21,111");[4,3,0,0,1,[ 0 0 0 0 ],[[1,1],[1,1],[1,1],[1,1]]][16] os_md.chkspt([[2*m,2*m],[m,m,m,m],[m,m,m,m-1,1]]|opt="idx");-2*m+2[17] os_md.chkspt([[2*m,2*m],[m,m,m,m],[m,m,m,m-1,1]]);[3,4*m,-2*m+2,0,-1,[ 0 0 3 ],[[2*m,2*m],[m,m,m,m],[m-1,m,m,m,1]]]46. spgen(n|eq=1,str=1,std=f ,pt=[k, ℓ],sp=m,basic=1):: 階数 n 以下の rigid な分割の組（あるいは与えられたものの軌道）を得る
n が 0 や負のときは，rigidity index が n の basic なものを得る．
• eq=1 : 階数が丁度 n のもの（n > 1 のとき）
• str=1 : 文字列で得る• pt=[k, ℓ] : 分割が k 組以上 ℓ 組以下のもの. k = ℓ のときは，pt=k と指定してよい．
• sp=m : スペクトル型が m のものから階数増加の方向で得られるもの
さらにここで basic=1 を指定すると，階数増加の方向に限らないもの• std=f : 各特異点の重複度は大きい順に，特異点間では f = 1（resp. −1）のとき，小さい（resp. 大きい）順に並べる．

[0] os_md.spgen(4|eq=1,pt=4);[[[2,2],[2,2],[2,2],[3,1]],[[2,2],[3,1],[3,1],[2,1,1]]][1] ltov(os_md.spgen(4|eq=1,pt=4,str=1));[ 22,22,22,31 22,31,31,211 ][2] ltov(os_md.spgen(4|eq=1,pt=4,str=1,std=-1));

97

[ 31,22,22,22 31,31,22,211 ][3] ltov(os_md.msort(os_md.spgen(4|eq=1,pt=4,str=1,std=-1),[-1,0]));[ 31,31,22,211 31,22,22,22 ][4] ltov(os_md.spgen(-2|pt=4,str=1));[ 21,21,111,111 22,22,22,211 31,22,22,1111 ][5][0] 階数が 4 で特異点が 4 個の rigid なスペクトル型のリストを得る[1] 同じスペクトル型を文字列形式で得る[2] 同じスペクトル型を文字列形式で得て大きい方からの辞書式順序で得る[3] スペクトル型の組を大きい方からの辞書式順序で得る[4] rigid 指数が −2 で特異点数 4 のスペクトル型を文字列形式で得る[5] スペクトル型が ”11,11,11,11” の軌道に属する階数 4 のものを文字列形式で得るプログラムの例は/* 8 階で特異点が 4 個のリジッドなスペクトル型を辞書式順序の大きい順に並べたリストを得る（文字列で）*/[6] Rank=8; /* give rank */[7] G=os_md.spgen(Rank|eq=1,pt=4); /* get spectral types */[8] for(L=[];G!=[];G=cdr(G))
L=cons(os_md.s2sp(os_md.s2sp(car(G)|std=-1)),L);[9] L=msort(L,[-1,0]);47. sproot(p,t|dviout=1,only=k,sym=t,null=1):: スペクトル型を与えて構成やルートの情報を示す．t="base", "length", "type", "part", "pair","pairs", sp• length : basic に変換する Weyl 群の長さ（= #∆(m)）• base：chksp(p|opt="root") と同じ．単純鏡映での最短積• type：上に対応する型（= [∆(m)]，cf. [O3, (7.40)])．
• height：root の高さ（単純ルートの一次結合で表示したときの係数の和．cf. [O3, (7.35)]）• part：上の Weyl 群の元で正負が変わるルート（= ∆(m)：既約条件に対応．cf. [O3, (7.30)]）の情報を得る．最初が対応する basic なルート，2 項目が与えられたルート，3 項目が求めるルート
および与えられたルートとの内積の組のリスト．

• pair, pairs：既約分解に対応するルートの分解
dviout=1 と only=k が指定可能．ルートは対応する分割で示す．
iand(k, 1) = 1 : 分割の相手が分割に対応するもの
iand(k, 2) = 2 : 分割の相手の位数が 0 のルートとなるもの
iand(k, 4) = 4 : 分割の相手が負ルートとなるもの
sym=1 : 対称性で移るものは同一視する
sym=2 : 上と同様であるが，各特異点での対称性のみで同一視
null=1 : 該当のものがなければ出力しない• sp : スペクトル型を与えた場合は，対応するルートの内積を与える[0] os_md.sproot("11,11,11","height");
5[1] os_md.sproot("11,11,11","length");4[2] os_md.sproot("11,11,11","type");[[4,1]][3] os_md.sproot("11,11,11","base");98[[[1],[1],[1]],[[1,1],[1,1],[1,1]],[[1,2,1],[1,1,1],[1,0,1],[1,0,0]]][4] os_md.sproot("11,11,11","part");[[[1],[1],[1]],[[1,1],[1,1],[1,1]],[[1,[[1,0],[1,0],[0,1]]],[1,[[1,0],[0,1],[1,0]]],[1,[[0,1],[1,0],[1,0]]],[1,[[1,0],[1,0],[1,0]]]]][4] os_md.sproot("11,11,11","11,11,11");2[5] os_md.sproot("11,11,11","10,10,10");1[6] os_md.sproot("31,31,22,211","length");8[7] os_md.sproot("31,31,22,211","type");[[6,1],[2,2]][8] os_md.sproot("31,31,22,211","height");
11[9] os_md.sproot("31,31,22,211","pairs"|dviout=1);
31, 31, 22, 211 = 10, 10, 01, 001 ⊕ 21, 21, 21, 210= 20, 11, 11, 110 ⊕ 11, 20, 11, 101= 11, 20, 11, 110 ⊕ 20, 11, 11, 101= 10, 10, 01, 010 ⊕ 21, 21, 21, 201= 10, 10, 10, 001 ⊕ 21, 21, 12, 210= 10, 10, 10, 010 ⊕ 21, 21, 12, 201= 2(10, 10, 01, 100) ⊕ 11, 11, 20, 011= 2(10, 10, 10, 100) ⊕ 11, 11, 02, 011
上の右辺の最初の項は ∆(m) に属する実正ルートとなる．また，"pair" のときは，上の最後の 2 行が異なり，20, 20, 20, 200 ⊕ 11, 11, 02, 011 などとなる．

[10] os_md.sproot("31,31,22,211","pairs"|dviout=1,sym=1);[11] os_md.sproot("31,31,22,211","pairs"|dviout=1,sym=2);
31, 31, 22, 211 = 20, 11, 11, 110 ⊕ 11, 20, 11, 101= 10, 10, 10, 010 ⊕ 21, 21, 12, 201= 2(10, 10, 10, 100) ⊕ 11, 11, 02, 011
31, 31, 22, 211 = 20, 11, 11, 110 ⊕ 11, 20, 11, 101= 11, 20, 11, 110 ⊕ 20, 11, 11, 101= 10, 10, 10, 010 ⊕ 21, 21, 12, 201= 2(10, 10, 10, 100) ⊕ 11, 11, 02, 011[O2, 第 8 章] や [O3, Chapter 7] にスペクトル型 m = (mj,ν ) と Kac-Moody ルート系のルート α との99

対応が解説されている．

αm = nα0 +X X Xj≥0 i≥1= nα0 +

XXmj,ν αj,i , n = mj,1 + mj,2 + · · · （j に依らない）

ν>inj,ν αj,ν

j≥0 ν≥1

mj,ν = nj,ν−1 − nj,ν (j = 0, 1, . . . , ν = 1, 2, . . . , nj,0 = n)"11,11,11" ↔ α = 2α0 + α0,1 + α1,1 + α2,1"21,21,21,21" ↔ α = 2α0 + α0,1 + α1,1 + α2,1 + α3,1"31,31,22,211" ↔ α = 4α0 + α0,1 + α1,1 + 2α2,1 + 2α3,1 + α3,2(α|α) = 2(α ∈ Π := {α0 , αj,ν | j ≥ 0, ν > 0})(α0 |αj,ν ) = −δν,10(i 6= j or |µ − ν| > 1)
(αi,µ |αj,ν ) =−1 (i = j and |µ − ν| = 1)sα : x 7→ x − (x|α)αα0(α ∈ Π)

α0,1

α0,2

α1,1

α1,2

α2,1

α2,2

α3,1

α3,2

···
···
···
···

Gauss の超幾何に対応する"11,11,11"のときは−1
αm = 2α0 + α0,1 + α1,1 + α1,2 = sα0 sα2,1 sα1,1 sα0,1 (α0 ) = wm
(α0 ),
wm = sα0,1 sα1,1 sα2,1 sα0 ,∆(m) = {α0 + α0,1 , α0 + α1,1 , α0 + α2,1 , α0 },[∆(m)] := {(α|αm ) | α ∈ ∆(m)} = {1, 1, 1, 1}↔ 4 = 1 + 1 + 1 + 1 : 14
であって，height は 2 + 1 + 1 + 1 = 5 で，rigid な場合は [∆(m)] は (height で与えられる数 −1) という自然数の分割となるが，今の場合は 4 = 1 + 1 + 1 + 1 である．また base で与えられた 3 番目の項のリスト[[1,2,1],[1,1,1],[1,0,1],[1,0,0]]
は，3 つの数字の 2 項目と 3 項目によって−1wm= sα2,1 sα1,1 sα0,1 sα0を意味し，最初の数字は対応する鏡映による height の変化の数を示している．
なお，一般に wm = sαi0 sαi1 · · · sαiK のときは∆(m) = {sαi0 · · · sαiν−1 (αiν ) | ν = 0, . . . , K}であり，m が rigid なときは wm αm = α0 となる長さ (= K) 最小の Weyl 群 (鏡映 sα (α ∈ Π) で生成される群) の元．なお mj,ν は mj,1 ≥ mj,2 ≥ · · · となるように正規化して考えるので，i0 = 0 である．

/* 8 階で特異点が 4 個以上に対応するリジッドなスペクトル型の分解で，Type 2 と Type 3 のものを全て得る */[12] Rank=8; /* give rank */[13] G=os_md.spgen(Rank|eq=1,str=1,pt=[4,100]); /* get spectral types */[14] for(T=G;T!=[];T=cdr(T))
if((os_md.sproot(car(T),"pairs"|only=6))!=[]) /* only type 2, 3 */os_md.sproot(os_md.s2sp(car(T)|std=-1), /* in standard order */pairs"|only=6,dviout=1);100

48. spbasic(n,d|str=1,pt=[k,ℓ]):: d 階で rigidity index が n の fundamental スペクトル型のリストを返す• n は 0 または負の偶数• d = 0 のときは全ての階数のものを返す．
• オプション pt=[k,ℓ] は，分割（特異点）の数が k 以上 ℓ 以下を意味する. pt=k は pt=[k,k] を
意味する.
恒等式
p−1
X



(ord m − mj,1 ) − 2ord m ord m +

nj
p−1X
X


(mj,1 − mj,ν )mj,ν = −idx m

j=0 ν=1

j=0

において，mj,1 ≥ mj,2 ≥ · · · かつ m1 ≥ m2 ≥ · · · で，左辺の第 1 項目が非負なものが求めるもの．
辞書式順序で大きい順に求める. なお，

0≤

p−1
X


(ord m − mj,1 ) − 2ord m ord m ≤ |idx m|

j=0に注意．特に ord m > |idx m| のときは

p−1P

(ord m − mj,1 ) = 2ord m.

j=0

さらに以下に注意

p ≤ 12 |idx m| + 4, ord m ≤ 3|idx m| + 6, ord m ≤ |idx m| + 2 (p > 3).
特に，ord m > |idx m| + 2 の時は，p = 3 で m0,1 + m1,1 + m2,1 = ord m.
そこで

1
L=
Si(p) =

2 |idx m| + 4

3
p−1
X

(ord m ≤ idx m + 2),
(ord m > idx m + 2)

(ord m − mj,1 ) − 2idx m, Sv(p) =

nj
p−1X
X

(mj,1 − mj,ν )mj,ν

j=0 ν=1

j=0とおき，条件p < L,

Si(p) ≥ 0,

Sv(p) ≤ |idx m|,

Si(p) · ord m + Sv(p) = |idx m|をチェックして満たすものをすべて求める（詳しくは [Osp]）．

rigidity index

0−2

計算時間 (sec)
総個数
3 点特異点
4 点特異点

4
3
1

13
9
3

−4
0.02
37
25
9

−6
0.05
69
46
17

−8
0.09
113
73
29

−10
0.19
198
127
50

−12
0.33
291
182
76

−14
0.58
415
249
115

−16
1.03
647
395
172

−18
1.70
884
522
243

[0] os_md.spbasic(-2,0);[[[1,1],[1,1],[1,1],[1,1],[1,1]],[[2,1],[2,1],[1,1,1],[1,1,1]],...
[1] tstart$os_md.mycat(length(os_md.spbasic(-10,0)))$tstop$
198[2] 0.1875sec + gc : 0.1875sec(0.188sec)

101

−20
2.67
1186
680
345

−22
4.25
1682
963
478

上は，Let’s Note CF-SZ5 (i7-6500U), 2016 による．
与えられた rigidity index をもつ fundamental スペクトル型の表を作るには，以下のようにすればよい.

[0] Idx=-4; Column=4; /* Put the rigidity index */[1] Ord=6-3*Idx; Sp="\\,\\ ";V=newvect(Ord+1);V[0]=V[1]=[];[2] for(I=2;I<=Ord;I++) V[I]=os_md.spbasic(Idx,I|str=1);
for(R=[],I=0;I<10;I++){T=Sp+rtostr(I)+":\\,";
for(TL=V[I];TL!=[];TL=cdr(TL)) R=cons(T+car(TL),R);};
for(I=10;I<=Ord;I++){T=rtostr(I)+":\\,";
for(TL=V[I];TL!=[];TL=cdr(TL)) R=cons(T+car(TL),R);};[3] R=reverse(R);Title="idx=$"+rtostr(Idx)+"$\\ (Pidx="+rtostr((2-Idx)/2)+"),\\ "+rtostr(length(R))+" basic tuples";[4] S=os_md.ltotex([R]|opt="tab",width=Column, align="l",title=Title);
dviout(S);特異点の数で並べるには上の [2] を，以下のようにする.

[2] for(I=2;I<=Ord;I++) V[I]=os_md.spbasic(Idx,I);
for(S=[],I=2;I<=Ord;I++)
for(TL=V[I];TL!=[];TL=cdr(TL)) S=cons([length(car(TL)),I,car(TL)],S);
S=qsort(S);for(R=[],TS=S;TS!=[];TS=cdr(TS)){N=(P=car(TS))[1];if(N<10) T= Sp+rtostr(N)+":\\,";
else T=rtostr(N)+":\\,";
R=cons(T+os_md.s2sp(P[2]),R);}
49. sp2grs(m,a,ℓ|mat=1):: spectral type から generalized Riemann scheme を生成する• 逆の変換は，chkspt() で opt="sp"を指定したもの．
• i + 1 番目の特異点の j + 1 番目のスペクトルパラメータは a が変数の時 aij で、リストの時 a[i]jで表される．a や a[i] は文字列でもよい．
• ℓ が [ℓ1 , ℓ2 ] というリストの時，ℓ1 番目の特異点における ℓ2 番目の exponent は，Fuchs の関係式を満たすように決められる．その exponent が 0 のときは，別の exponent で調整される.
• ℓ が正整数 k のとき，aij は aij +k または，a[i]j +k となる．前者と併用するときは，ℓ = [ℓ1 , ℓ2 , k]というリストにする．

• ℓ が負整数 −1 − k のときは，標準的にいくつかの exponents を 0 とし，上の k シフトを行う．
• mat=1 は，Schleginger 型を意味する（Fuchs の関係式が異なる）.
[0] os_md.sp2grs([[1,1],[1,1],[1,1]],a,0);[[[1,a00],[1,a01]],[[1,a10],[1,a11]],[[1,a20],[1,a21]]][1] M=os_md.sp2grs("111,111,21",[a,b,c],[3,2]);[[[1,a0],[1,a1],[1,a2]],[[1,b0],[1,b1],[1,b2]],[[2,c0],[1,-b1-b2-a2-a1-2*c0-b0-a0+2]]][2] os_md.sp2grs([[1,1,1],[1,1,1],[2,1]],[a,b,c],[3,2,-2]);102[[[1,a1],[1,a2],[1,a3]],[[1,b1],[1,b2],[1,0]],[[2,0],[1,-b1-b2-a3-a2-a1+2]]][3] subst(M,b0,0,b1,1-b1,b2,1-b2,c0,0);[[[1,a0],[1,a1],[1,a2]],[[1,0],[1,-b1+1],[1,-b2+1]],[[2,0],[1,b1+b2-a2-a1-a0]]][4] os_md.sp2grs([[1,1],[1,1],[1,1]],a,1);[[[1,a01],[1,a02]],[[1,a11],[1,a12]],[[1,a21],[1,a22]]][5] os_md.ssubgrs(M,"110,110,11");-b2-a2-c0+2[6] os_md.ssubgrs(M,[[1,1,0],[1,1,0],[1,1]]);-b2-a2-c0+2
50. ssubgrs (m, ℓ):: Generalized Riemann scheme m の ℓ に対する特性指数和[0] GRS=os_md.sp2grs("111,111,21",[a,b,c],[1,3,-2]);[[[1,a1],[1,a2],[1,-c-b1-b2-a2-a1+2]],[[1,b1],[1,b2],[1,0]],[[2,0],[1,c]]][1] os_md.ssubgrs(GRS,"010,100,10");b1+a2[2] os_md.ssubgrs(GRS,"011,110,11");-a1+2
51. mcgrs(m,[r1 , r2 , . . . , rn ]|mat=1,slm=[[k1 ,k2 ,. . .],m0 ]):: middle convolution と addition を順に generalized Riemann scheme や留数行列の和に施す• rj がスカラーの時は mcrj を，rj がリスト [rj,1 , . . . , rj,n ] のときは addition を意味する. また[rj,0 , rj,1 , . . . , rj,n ] のときは，まず middle convolution mcrj,0 を施し，そのあと [rj,1 , . . . , rj,n ] に対応する addition を施す．施す順序は，最初が rn ，次に rn−1 という順で，最後が r1 .
• Schlesinger 型のときは，mat=1 を指定する.
さらに sm1=の指定により，k1 , k2 , . . . 番目の留数行列の和のスペクトル型 m0 の変換を得る. これにより，半局所モノドロミーや合流で得られる不確定特異点での局所モノドロミーが計算できる（cf. [O7]）.

[1] M0=[[1,0]]$M=[M0,M0,M0,M0]$S=[m,[a,b,c]]$[2] os_md.mcgrs(M,S);[[[2,-m+1],[1,-a-b-c-m]],[[2,0],[1,a+m]],[[2,0],[1,b+m]],[[2,0],[1,c+m]]][3] os_md.mcgrs(M,S|mat=1);[[[2,-m],[1,-a-b-c-m]],[[2,0],[1,a+m]],[[2,0],[1,b+m]],[[2,0],[1,c+m]]][4] os_md.mcgrs(M,S|mat=1,slm=[[0,1],M0]);[[[[2,-m],[1,-a-b-c-m]],[[2,0],[1,a+m]],[[2,0],[1,b+m]],[[2,0],[1,c+m]]],[[1,0],[1,-m],[1,-b-c-m]]]
52. mcop(p,[r1 , r2 , . . . , rn ],[x, x1 , x2 , . . . ]):: middle convolution と addition を (偏）微分作用素 p に順に施していく• [x, x1 , x2 , . . .] によって，x は変数，x1 , x2 , . . . は有限の特異点の位置を示す．
• [r1 , r2 , . . .] において，rj = [rj,0 , rj,1 , . . .] は middle convolution と additions を表す．
– まず middle convolution mcrj,0 を施し，その後 x = xν における additions（関数 u の(x − xν )rj,ν u へのゲージ変換に対応）を行う（ν = 1, 2, . . .）．
– p に対して rj に対応する変換を，r1 , r2 , . . . の順に行う．
103

[0] R=os_md.getbygrs("21,21,21,21","construct")$[1] R[0][1];[[[1,b+c+d+a1+2*a0-2]],[[1,0]],[[1,0]],[[1,0]]][2] S=os_md.lsol(os_md.getbygrs("21,21,21,21","Fuchs"),a1);-b-c-d-2*a0+2[3] R=subst(R,a1,S,a0,a);[[0,[[[1,0]],[[1,0]],[[1,0]],[[1,0]]]],[[0,a+b-1,a+c-1,a+d-1],[[[1,-3*a-b-c-d+3]],[[1,a+b-1]],[[1,a+c-1]],[[1,a+d-1]]]],[[-a+1,0,0,0],[[[2,a],[1,-2*a-b-c-d+2]],[[2,0],[1,b]],[[2,0],[1,c]],[[2,0],[1,d]]]]][4] RR=[R[1][0],R[2][0]];[[0,a+b-1,a+c-1,a+d-1],[-a+1,0,0,0]][5] os_md.mcop(dy,RR,[x,0,1,y]);((-x+y)*dx-a)*dy+(-a-d+1)*dx[6] os_md.show(@@)$−(x − y)∂x ∂y − (a + d − 1)∂x − a∂y53. redgrs(m|mat=1):: 常微分作用素の generalized Riemann scheme の 1-step reduction
結果のデータ [redsp, m0 ] を返す．
reduction 出来ないときは非負整数（basic, 0 は rigid) または負の値（非存在）を返す．
54. getbygrs(m,t|perm=ℓ,var=v,pt=[p1 , . . . ],mat=1) or
getbygrs(m,[t,s1 , s2 , . . . ]|perm=ℓ,var=v,pt=[p1 , . . . ],mat=1) :: generalized Riemann scheme(GRS) で定義される Fuchs 型常微分方程式の解析（GRS は短縮形またはスペクトルタイプでもよい）• mat=1 は，Schleginger 型を意味する.
• getbygrs(0,0) で渡されるパラメータが示される．
• m の要素の数を p + 1 個とすると，それは p + 1 個の特異点に対応する．それを順に x0 = ∞, x1 =0, x2 = 1, x3 , . . . , xp とする.
• Fuchs 型 方 程 式 の 特 異 点 x = xj に お け る generalized exponents（ 一 般 特 性 指 数 ）が{[λ0 ](n0 ) , . . . , [λk ](nk ) } であるとは exponents が重複度を込めて {λj + ν ; 0 ≤ ν < nj , j =0, . . . , k} であって，{λ0 , . . . , λk } に互いに差が整数となる要素が含まれない場合（そうでない場
合の定義は略すが，たとえば λj が全て等しいなら対応する局所モノドロミー群の Jordan ブロックへの分解サイズが，n = n0 + · · · + nk の分割の双対分割に対応すること），x = xj での局所モ
ノドロミー群が半単純（対角化可能）となるとき，すなわち (x − xj )λj +ν ϕj,ν (x)（0 ≤ ν < nν ）という形の局所解が存在することをいう（ϕj,ν (x) は，x = xj で正則で，ϕj,ν (xj ) = 1)．
• 各特異点での generalized exponents を並べて表にしたものを generalized Riemann scheme(GRS) という（cf. [O2, 第 5 章]，[O3, Deﬁnition 4.6]）:


x =∞
xj










m[0][0][1] (m[0][0][0]) m[j][0][1] (m[j][0][0])














 m[0][1][1] (m[0][1][0]) m[j][1][1] (m[j][1][0])

..
..

.
.
; x










m[0][i][1]m[j][i][1](m[0][i][0])(m[j][i][0])






.
.


..
..
• perm=[[i, j]] : i 番目の特異点と j 番目の特異点の入れ替え• perm=[j0 , . . . , jp ] : 特異点の並べ替え（xj0 の特性指数が ∞ に移る）．
• var=v : exponents の変数の指定．sp2grs() の第２変数の指定にあたる．
• pt=[p1 , p2 , . . . ] : 特異点の位置を ∞, p1 , p2 , . . . とする．
104

• Generalize Riemann scheme m の特性指数の一つを指定せずに，それを "?" で表してもよい．その特性指数は Fuchs の関係式から決定される．
• m がスペクトル型（分割の組）のとき，対応する GRS に変換される．このとき，s = "general"を指定できる（指定しないと，いくつかの exponents が 0 として，Okubo 型またはそれに近いものにする）．

R = getbygrs(m,t) とする．
オプション・パラメータ s は一つの文字列，あるいは，複数の文字列を指定する．"TeX", "dviout","keep" は，以下のどの機能においても指定できる．
• t ="reduction" or 0 : basic な方程式への reductions ="TeX" を指定したときは，さらに "top0" も指定可能
R[i][0] : i 番目の reduction の xj での exponents の位置 R[i][0][ν]（ν = 0, . . . , p, i = 1, . . .）R[i][0][ν] (ν = 1, . . . , p) に対応する addition を行い，R[i][0][0] に対する middle convolution を行う．

R[i][1] : 上の reduction の結果の GRS
R[0][1] : 元の GRS• t ="construct" or 1 : 方程式の構成法と解の積分表示
0R[0][1]: reduction された basic
 な方程式の GRS (m とおく）．
Qp
R[i][0][ν]RAd ν=1 (x − xν )◦ mcR[i][0][0] によって GRS が R[i − 1][1] から R[i][1] に変わり
（i = 1, 2, . . .），m0 から m への変換が分かる．
s ="short" を指定可能
s ="TeX" を指定すると，解の積分表示が得られる（局所モノドロミーの固有値の重複度が 1 の局
所解）

• t ="connection" or 2 : 接続公式を求める
s ="simplify" を指定可能
特異点が p + 1 点のときは，特異点の位置が x0 = ∞, x1 = 0, x2 = 1, x3 , x4 , . . . , xp とする上記
GRS であって，x = 0 と 1 での最後の exponent の重複度が共に 1 であるとき，対応する正規化
した局所解の 0 から 1 への接続係数はQ
Γ(R[0][ν]) Y
R[2][j]c B Qν
(1 − x−1j )ν Γ(R[1][ν])j≥3で与えられる．cB は対応する basic 方程式の接続係数であるが，rigid なとき（すなわちアクセサ
R[2][j]リ・パラメータの無いとき）は cB = 1 となる．特異点が 3 点のときは、(1 − x−1の項はな
j )いことに注意．
• t ="operator" or 3 : 方程式を求める
s ="simplify" を指定可能．
dを表す．
結果は，x が変数 x，dx が dx
id
アクセサリ・パラメータは ri_j と表され，それは帰着 basic 方程式の xj dx
i の係数にあたる．
この計算は、他の計算に比べて重いので注意．
• t ="series" or 4 : x = 0 での最後の exponent（重複度が 1 の必要あり）に対応する局所解のベ
キ級数表示を求める．

R = [R0 , R1 , R2 ]R0 = [[R00 , [R01 , T1 ], [R02 , T2 ], . . .], [P1 , Q1 ], [P2 , Q2 ], . . .]R1 = [[R100 , P101 , P102 , . . .], [R110 , P111 , P112 , . . .], . . .]R2 = [[R200 , P201 , P202 , . . .], [R210 , P211 , P212 , . . .], . . .]105

0 ≤ P1 < P 2 < P 3 < · · ·X

Cn0 xR00 +n0

nP1 ,nP2 ,...

·

Y
j≥1

1−

Q

Y
j≥0, P j6=0

 x  nP jxQj

x R0j j≥0 (R1j0 )nP1j1 +nP1j2 +···Q,xTj
j≥0 (R2j0 )nP2j1 +nP2j2 +···

x1 = x2 = 1,P1 6= 0 ⇒ n0 = 0 and C0 = 1.
• t = "TeX" or 5 : GRS を LATEX で表示
s = "top0" を指定すると，GRS で ∞ を最後に表示する．
• t = "Fuchs" or 6 : Fuchs の関係式を得る• t = "All" or 7 : s に"dviout"を指定したときのみ有効で，dviout での関連する結果の表示．sに"irreducible"を指定すると既約性の判定条件の非表示，"operator"を指定すると方程式の表示も行う．

• t = "basic" or 8 : 帰着される basic な GRS を得る
s ="short" を指定可能• t = "" or 9 : GRS を短縮形でない形式で示す
s ="short" を指定すると，短縮形で示す• t = "irreducible" or 10 : 既約条件を求める
s = "simplify を指定可能
リストの各 liner form が整数値とならないことが既約性の必要十分条件．rigid でないならば，さらに帰着された方程式の既約条件も課される．

• t = "recurrence" or 11 : 3 項間漸化式を示す∞, 0, 1 の最後の exponents の重複度がすべて 1 で rigid のときのみ可．
原点の規格化された局所解について上の exponents をシフトしたもの．
s は文字列または文字列のリスト．文字列は• "simplify" : Fuchs の関係式を使って結果を簡単にする• "TeX" : LATEX の数式で出力する• "dviout" : dviout で表示する
このときオプション・パラメータ title= で文字列を指定できる• "keep" : 上と同様だが，表示はしない• "short" : GRS を短縮形で表示• "general" : スペクトルタイプを与えたとき，exponents を完全に generic にとる• "x1" : 特異点を，∞, x1 , x2 , . . . とする（GRS の TEX 表示、および作用素を得るときのみ有効）• "x2" : 特異点を，∞, 0, x2 , . . . とする（GRS の TEX 表示、および作用素を得るときのみ有効）• "top0" : GRS の TEX での表示で，∞ を最後とする• "sht" : 自動生成される exponents の番号を 1（デフォルトは 0）から始める[1] M=os_md.sp2grs([[1,1,1],[1,1,1],[2,1]],[a,b,c],[3,2]);[[[1,a0],[1,a1],[1,a2]],[[1,b0],[1,b1],[1,b2]],[[2,c0],[1,-2*c0-b2-b1-b0-a2-a1-a0+2]]][2] os_md.getbygrs(M,"reduction");[[0,[ [[1,a0],[1,a1],[1,a2]],[[1,b0],[1,b1],[1,b2]],[[2,c0],[1,-2*c0-b2-b1-b0-a2-a1-a0+2]]
106

]
],
[[ 0 0 0 ],[ [[0,-c0-b0-a0+2],[1,a1-a0+1],[1,a2-a0+1]],[[0,0],[1,c0+b1+a0-1],[1,c0+b2+a0-1]],[[1,0],[1,-2*c0-b2-b1-a2-a1+1]]]],[[ 1 1 0 ],[ [[0,-c0-b0-a1+2],[0,-c0-b1-a1+2],[1,a2-a1+1]],[[0,a1-a0],[0,0],[1,c0+b2+a1-1]],[[0,0],[1,-c0-b2-a2]]]]][3] os_md.getbygrs(M,"construct");[[[0,[ [[1,0]],[[1,0]],[[1,0]]]][[0,c0+b2+a1-1,-c0-b2-a2][ [[1,a2-a1+1]],[[1,c0+b2+a1-1]],[[1,-c0-b2-a2]]]],[[-c0-b1-a1+1,c0+b1+a0-1,0],[ [[1,a1-a0+1],[1,a2-a0+1]],[[1,c0+b1+a0-1],[1,c0+b2+a0-1]],[[1,0],[1,-2*c0-b2-b1-a2-a1+1]]]],[[-c0-b0-a0+1,b0,c0],[ [[1,a0],[1,a1],[1,a2]],[[1,b0],[1,b1],[1,b2]],[[2,c0],[1,-2*c0-b2-b1-b0-a2-a1-a0+2]]]]][4] os_md.getbygrs(M,"connection");[[3*c0+b2+b1+b0+a2+a1+a0-2,b2-b1+1,b2-b0+1],107

[c0+b2+a2,c0+b2+a1,c0+b2+a0],[ 0 2*c0+b2+b1+b0+a1+a0-2 -b2-a2 ]][5] os_md.getbygrs(M,["construct","TeX"])$x^{b_{0}}(1-x)^{c_0}\int_c^x(x-s_0)^{c_0+b_0+a_0}ds_0s_0^{c_0+b_1+a_0-1}\int_c^{s_0}(s_0-s_1)^{c_0+b_1+a_1}
s_1^{c_0+b_2+a_1-1}(1-s_1)^{-c_0-b_2-a_2}ds_1[6] M0=subst(M,b2,0,c0,0,b1,1-b1,b0,1-b0);[[[1,a0],[1,a1],[1,a2]],[[1,-b0+1],[1,-b1+1],[1,0]],[[2,0],[1,b1+b0-a2-a1-a0]]][7] os_md.getbygrs(M0,"connection");[[b1,-b1-b0+a2+a1+a0,b0],[a2,a1,a0],[ 0 -b1-b0+a1+a0 -a2 ]][8] P=os_md.getbygrs(M0,"operator");(x^3-x^2)*dx^3+((a1+a0+a2+3)*x^2+(-b1-b0-1)*x)*dx^2+(((a0+a2+1)*a1+(a2+1)*a0+a2+1)*x-b0*b1)*dx+a2*a0*a1[9] os_md.expat(P,x,"?");[[0,[-b1+1,-b0+1,0]],[1,[b1+b0-a1-a0-a2,1,0]],[infty,[a1,a0,a2]]][10] os_md.getbygrs(M0,"irreducible");[b1-a1,b1-a2,a1,a2,b0-a0,b0-a2,b0-a1,a0,b1-a0][11] M1=os_md.sp2grs([[1,1,1],[1,1,1],[2,1]],[a,b,c],[]);[[[1,a0],[1,a1],[1,a2]],[[1,b0],[1,b1],[1,b2]],[[2,c0],[1,c1]]][12] M2 = subst(M1,b0,1-b0,b1,1-b1,b2,0,c0,0,c1,-c1);[[[1,a0],[1,a1],[1,a2]],[[1,-b0+1],[1,-b1+1],[1,0]],[[2,0],[1,-c1]]][13] os_md.getbygrs(M2,"connection");[[c1,b1,b0],[c1+b1+b0-a1-a0,a1,a0],[ 0 -b1-b0+a1+a0 -c1-b1-b0+a1+a0 ]][14] os_md.getbygrs(M2,["connection","simplify"]);[[c1,b1,b0],[a2,a1,a0],[ 0 c1-a2 -a2 ]][15] os_md.getbygrs(M2, "Fuchs");-c1-b1-b0+a2+a1+a0[16] os_md.getbygrs(M2, "TeX")$P\begin{Bmatrix}
x=\infty & 0 & 1\\
a_0 &-b_0+ 1 & [0]_{(2)} & \!\!;x\\a_1 &-b_1+ 1 & -c_1\\
a_2 & 0 & \\\end{Bmatrix}[17] os_md.getbygrs(M2,["connection","simplify","TeX"])$108

c(0:0 \rightsquigarrow 1: -c_1)=\frac{\Gamma(c_1)\Gamma(b_1)\Gamma(b_0)}{\Gamma(a_2)\Gamma(a_1)\Gamma(a_0)}[18] os_md.getbygrs(M2, ["Fuchs","TeX"]);-c_1-b_1-b_0+a_2+a_1+a_0[19] os_md.getbygrs([[1,1],[1,1],[1,1]],"operator");(-x^2+x)*dx^2+((c1+b0-2)*x-b0+1)*dx+a0*c1+a0*b0+a0^2-a0[20] HO=[[1,1,1],[2,1],[2,1],[2,1]]$[21] os_md.getbygrs(HO,["","short"]);[[a0,a1,a2],[[2,0],b1],[[2,0],c1],[[2,0],d1]][22] os_md.getbygrs(HO,"TeX");P\begin{Bmatrix}
x=\infty & 0 & 1& x_3\\
a_0 & [0]_{(2)} & [0]_{(2)} & [0]_{(2)}&\!\!;x\\a_{1} & b_1 & c_1 & d_1\\a_{2} & & & \\\end{Bmatrix}[23] os_md.getbygrs(HO,["basic","short"]);[[b1+a1,b1+a2],[-b1-a0+1,0],[0,c1+a0-1],[0,a0+d1-1]][24] os_md.getbygrs(HO,["","short","general"]);[[a0,a1,a2],[[2,b0],b1],[[2,c0],c1],[[2,d0],d1]][25] os_md.getbygrs(HO,["basic","TeX"]);
P\begin{Bmatrix}
x=\infty & 0 & 1& x_3\\
b_1+a_1 & -b_1-a_0+1 & 0 & 0&\!\!;x\\b_1+a_2 & 0 & c_1+a_0-1 & a_0+d_1-1\\\end{Bmatrix}[26] os_md.getbygrs(HO,"Fuchs");
b1+c1+a1+a0+d1+a2-3[27] P=os_md.getbygrs(HO,"operator");(-x^3+(x_3+1)*x^2-x_3*x)*dx^3+((-a1-a0-a2-3)*x^2+(-x_3*b1+(-x_3+1)*c1+a1+a0+a2+4*x_3+1)*x+x_3*b1-2*x_3)*dx^2+(((-a0-a2-1)*a1+(-a2-1)*a0-a2-1)*x-b1^2+((x_3-1)*c1-a1-a0-a2-2*x_3+2)*b1+(-x_3+1)*c1+a1+a0+a2+2*x_3-r0_0-1)*dx-a2*a0*a1[28] os_md.expat(P,x,"?");[[0,[b1,1,0]],[1,[c1,1,0]],[x_3,[-b1-c1-a1-a0-a2+3,1,0]],[infty,[a1,a0,a2]]]109

In the above example we examine the generalized Riemann scheme


x=∞ 0
1




a0
b0 [c0 ](2) ; x
R=P
b1
c1


 a1

a2
b2
with c1 = −a0 − a1 − a2 − b0 − b1 − b2 − 2c0 + 2
whose spectral type is m = 111, 111, 21. Then getbygrs(m, 1) shows that the equation P u = 0
with the GRS R is given by
P = RAd xb0 (x − 1)c0 ◦ mc−a0 −b0 −c0 +1 ◦ RAd xa0 +b1 +c0 −1
◦ mc−a1 −b1 −c0 +1 ◦ RAd xa1 +b2 +c0 −1 (x − 1)−a2 −b2 −c0 ∂x
and the generalized Riemann scheme changes as follows

x=∞ 0 1P
00 0 ; x
→ RAd xc0 +a1 +b2 −1 (x − 1)−c0 −b2 −a2


x=∞
0
1
P
a2 − a1 + 1 c0 + b2 + a1 − 1 −c0 − b2 − a2 ; x→ RAd xa0 +b1 +c0 −1 ◦ mc−a1 −b1 −c0 +1
(
)
x=∞
0
1
0
P a 1 − a 0 + 1 c 0 + b1 + a 0 − 1
a2 − a0 + 1 c0 + b2 + a0 − 1 −2c0 − b2 − b1 − a2 − a1 + 1 ; x→ RAd xb0 (x − 1)c0 ◦ mc−a0 −b0 −c0 +1


x=∞ 0
1




a0
b0
[c0 ](2).
P
b1 c1 := −a0 − a1 − a2 − b0 − b1 − b2 − 2c0 + 2 ; x


 a1
a2
b2
Hence an integral representation of the solution is
Z x Z s0u(x) = xb0 (1 − x)c0
(x − s0 )a0 +b0 +c0 s0a0 +b1 +c0 −1cc
a1 +b1 +c0 a1 +b2 +c0 −1· (s0 − s1 )s1
(1 − s1 )−a2 −b2 −c0 ds1 ds0 .

When c = 0 or c = 1 or c = ∞, u(x) is a local solution at x = 0 or x = 1 or x = ∞ corresponding to
the exponent b2 or c1 or a2 , respectively. It corresponds to the local solution for the last exponent
with free multiplicity at each singular point.
By getbygrs(m,"connection") we get the connection coeﬃcient
Q1
Γ(a0 + a1 + a2 + b0 + b1 + b2 + 3c0 − 2) ν=0 Γ(b2 − bν + 1)Q2
ν=0 Γ(aν + b2 + c0 )Q1
Γ(c0 − c1 ) ν=0 Γ(b2 − bν + 1)=,Q2
ν=0 Γ(aν + b2 + c0 )c(0 : b2 ⇝ 1 : c1 ) =which corresponds to the local solution
xb2 (1 − x)c0 3 F2 (a0 + b2 + c0 , a1 + b2 + c0 , a2 + b2 + c0 , 1 − b0 + b2 , 1 − b1 + b2 ; x).
The calculation
110[29] G=[[a,b],[1-c,0],[c-a-b,0]];
[
[a,
b],
[-c+1, 0],[-a-b+c,0]][30] os_md.getbygrs(G,"operator");(-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-b*a[31] os_md.getbygrs(G,"connection");[[-a-b+c,c],[-a+c,-b+c],[ 0 -b -b ]][32] os_md.getbygrs(G,["construct","TeX"])$x^{-c+1}(1-x)^{-a-b+c}\int_c^x(x-s_0)^{-b+1}
s_0^{-b+c-1}(1-s_0)^{a-c}ds_0[33] os_md.getbygrs(G,"irreducible")[b,a,b-c,a-c]shows Gauss summation formula
F (a, b, c; 1) =Γ(c − a − b)Γ(c)Γ(c − a)Γ(c − b)for the Gauss hypergeometric series
F (a, b, c; x) =∞X(a)(a + 1) · · · (a + k − 1) · b(b + 1) · · · (b + k − 1)(c)(c + 1) · · · (c + k − 1)k!

k=0

xk ,

which is a solution of the hypergeometric equationx(1 − x)u00 + c − (a + b + 1)x u0 − abu = 0

corresponding to the Riemann scheme
(
x=∞
a
P
b

)
0
1
0
0
; x .
1−c c−a−b

The equation is irreducible if and only if
a, b, a − c, b − c ∈/ Z.
[34] os_md.getbygrs([[a1,a2,a3],[0,b1,b2],[[2,0],"?"]],["reduction","dviout","top0"]);とすると，以下が表示される．


x=0


0
P
 b1

b2


∞


a1 ; x
a2


a3
(
)
x=0
1
∞
0
a2 − a1 + 1 ; x← mc−a1 +1 : P b1 + a1 − 1
b2 + a1 − 1 −b1 − b2 − a3 − a2 + 1 a3 − a1 + 1




x=0
1
∞
← Ad xb1 +a1 −1 mc−b1 −a2 +1 : P
b2 + a2 − 1 −b2 − a3 a3 − a2 + 1 ; x
x=0 1 ∞
← Ad xb2 +a2 −1 (1 − x)−b2 −a3 : P
0
0 0 ;x1[0](2)−b1 − b2 − a3 − a2 − a1 + 2111

[35] os_md.getbygrs("11,11,11",["All","dviout","operator"]);とすると，以下が表示される．

Riemann scheme
(
P

x=∞ 0
a0
0
a1
b

1
0 ;x
c

)

Fuchs conditionb + c + a1 + a0 − 1Connection formulac(0 : b ⇝ 1 : c) =Γ(−c)Γ(b + 1)
Γ(b + a0 )Γ(b + a1 )Recurrence relation shifting the last exponents at ∞, 0, 1
u0,0,0 − u+1,0,−1 =(b + 1)u0,+1,−1(b + a0 )Integral representationZ x

1(x − s0 )−a0 s−c−a(1 − s0 )−b−a1 ds00p∼Γ(−a0 + 1)Γ(b + a0 ) b
x (p = 0, x → 0)
Γ(b + 1)

Series expansion
X (b + a0 )n (b + a1 )nn≥0(b + 1)n n!

xb+n

Irreducibility ⇔ any value of the following linear forms ∈/Z
a0 a1
c + a0 b + a0
which correspond to the decompositions
11, 11, 11 = 10, 10, 01 ⊕ 01, 01, 10= 10, 01, 10 ⊕ 01, 10, 01= 01, 10, 10 ⊕ 10, 01, 01= 10, 10, 10 ⊕ 01, 01, 01
Operator− x(x − 1)∂ 2 + ((b + c − 2)x − b + 1)∂ − a0 a1[36] os_md.getbygrs([[[2,e],f,g],[[2,0],a,b],[[2,0],c,d]],["All","top0","dviout"]);

112

では

Riemann scheme

x=0


[0](2)P ab

1[0](2)cd∞[e](2) ; xfg

Fuchs conditiona + b + c + d + 2e + f + g − 3
Connection formulac(0 : b ⇝ 1 : d) =Γ(−d)Γ(c − d)Γ(b + 1)Γ(−a + b + 1)
Γ(−d − e + 1)Γ(b + e)Γ(b + c + e + g − 1)Γ(b + c + e + f − 1)

Recurrence relation shifting the last exponents at ∞, 0, 1
u0,0,0 − u+1,0,−1 =(b + 1)(−a + b + 1)
u0,+1,−1(b + e)(b + c + e + f − 1)

Integral representation
Z x Z s0(x − s0 )−e sa+e−1(1 − s0 )c+e−1 (s0 − s1 )b+d+e+g−2 s1b+c+e+f −2 (1 − s1 )a+d+e+f −2 ds1 ds0
0
p

∼

p

Γ(−e + 1)Γ(b + e)Γ(b + d + e + g − 1)Γ(b + c + e + f − 1) b
x (p = 0, x → 0)
Γ(b + 1)Γ(−a + b + 1)

Series expansionX
n1 ≥0, n2 ≥0(−c − e + 1)n2 (b + c + e + g − 1)n1 (b + c + e + f − 1)n1 (b + e)n1 +n2 b+n1 +n2x(−a + b + 1)n1 (b + 1)n1 +n2 n1 !n2 !

Irreducibility ⇔ any value of the following linear forms ∈/Zg f ed+e c+e b+e a+e
b+c+e+f a+d+e+f

a+c+e+g

a+c+e+f

which correspond to the decompositions
211, 211, 211 = 110, 110, 101 ⊕ 101, 101, 110= 110, 101, 110 ⊕ 101, 110, 101= 101, 110, 110 ⊕ 110, 101, 101= 110, 110, 110 ⊕ 101, 101, 101= 100, 100, 001 ⊕ 111, 111, 210= 100, 100, 010 ⊕ 111, 111, 201= 100, 001, 100 ⊕ 111, 210, 111= 100, 010, 100 ⊕ 111, 201, 111= 001, 100, 100 ⊕ 210, 111, 111= 010, 100, 100 ⊕ 201, 111, 111= 2(100, 100, 100) ⊕ 011, 011, 011
rigid ではない例では
113

[37] os_md.getbygrs("3111,3111,3111",["All","dviout"]);とすると以下が表示される．

Riemann Scheme


x=∞
0



 [a0 ](3) [0](3)
a1
b1
P


a
b
2
2


a3
b3

Basic Riemann Scheme


1



[0](3) ; x
c1


c2


c3






1


0
;x
c2 − c1
c3 − c1x=∞0
b3 + c 1 + a 1 + a 0 − 1 b 1 − b 3P b3 + c 1 + a 2 + a 0 − 1 b 2 − b3
b3 + c 1 + a 3 + a 0 − 1
0[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
Fuchs condition

b1 + b2 + b3 + c3 + c2 + c1 + a3 + a2 + a1 + 3a0 − 6Connection formulac(0 : b3 ⇝ 1 : c3 )=Integral representationΓ(−c3 )Γ(b3 + 1)
cB (0 : 0 ⇝ 1 : c3 − c1 )Γ(−c3 − a0 + 1)Γ(b3 + a0 )Z x(x − s0 )−a0 sb03 +a0 −1 (1 − s0 )c1 +a0 −1 uB (s0 )ds0p∼

Γ(−a0 + 1)Γ(b3 + a0 )C0 xb3 (p = 0, x → 0)
Γ(b3 + 1)

Series expansionX
n0 ≥0, n1 ≥0(−c1 − a0 + 1)n1 (b3 + a0 )n0 +n1
Cn0 xb3 +n0 +n1(b3 + 1)n0 +n1 n1 !

Irreducibility ⇔ any value of the following linear forms ∈/ Z + fundamental irreducibility
a0 a1 a2 a3
c1 + a0 c 2 + a0

c3 + a0

b3 + a 0

b2 + a 0

b1 + a 0

which correspond to the decompositions
3111, 3111, 3111 = 1000, 1000, 0001 ⊕ 2111, 2111, 3110
= 1000, 1000, 0010 ⊕ 2111, 2111, 3101
= 1000, 1000, 0100 ⊕ 2111, 2111, 3011
= 1000, 0001, 1000 ⊕ 2111, 3110, 2111
= 1000, 0010, 1000 ⊕ 2111, 3101, 2111
= 1000, 0100, 1000 ⊕ 2111, 3011, 2111
= 0001, 1000, 1000 ⊕ 3110, 2111, 2111
= 0010, 1000, 1000 ⊕ 3101, 2111, 2111
= 0100, 1000, 1000 ⊕ 3011, 2111, 2111
= 3(1000, 1000, 1000) ⊕ 0111, 0111, 0111
114

rigid でない Riemann scheme をもつ方程式 P u = 0 は，middle convolution と addition によってbasic Riemann scheme をもつ方程式 PB uB = 0 に変換される．
解 u(x) の接続公式，積分表表示，べき級数表示は PB uB = 0 の解 uB (x) の接続係数 cB やべき級数解
P∞
b3 +n0を使って上のように表すことができる．既約条件の fundamental irreducibility と
n0 =0 Cn0 x
は，PB uB = 0 の既約条件である．
P から PB への具体的変換は mcop() で得られる．
[38] os_md.getbygrs([[0,a,b],[[2,"?"],0],[d,e,f]],[""]|mat=1);[[[1,0],[1,a],[1,b]],[[2,-1/2*a-1/2*b-1/2*d-1/2*e-1/2*f],[1,0]],[[1,d],[1,e],[1,f]]][39] os_md.getbygrs([[0,a,b],[[2,"?"],0],[d,e,f]],["","short"]);[[0,a,b],[[2,-1/2*a-1/2*b-1/2*d-1/2*e-1/2*f+1],0],[d,e,f]]
55. spslm(m,[k1 ,k2 ,. . .]):: rigid な常微分方程式の解の半局所モノドロミーを求める• m はスペクトル型または generalized Riemann scheme.
• k1 ,k2 , . . . : k1 , k2 , . . . 番目の特異点を 1 回まわる単純曲線における半局所モノドロミー（cf. [O7]）を計算する．

• 戻り値は，generalized Riemann scheme と半局所モノドロミーの対数行列のリスト[0] os_md.spslm("21,21,21,21",[0,3]);[1] [[[[2,a0],[1,a1]],[[2,0],[1,-c-d-a1-2*a0]],[[2,0],[1,c]],[[2,0],[1,d]]],[[1,0],[1,a0],[1,d+a1+a0]]]
これは generalized Riemann scheme(x=∞[a0 ]2a10[0]2−2a0 − a1 − c − d

1
[0]2
c

y
[0]2
d

)

で与えられる Jordan Pochhammer 方程式（Schlesinger 型）の ∞ と y とを回る単純曲線におけるモ
ノドロミー行列の固有値が，1, e2πia0 , e2πi(a0 +a1 +d) となることを示している．

56. shiftop(ℓ, s|zero=1,raw=k,all=t,dviout=1):: rigid なスペクトル型 ℓ と shift s から shift 作用素を求めるℓ が Riemann scheme, s がシフトするパラメータとそれの変換後の組のリストでもよい．
shift 作用素，微分作用素，Riemann scheme の 3 項のリストを返す．
• zero=1 : いくつかの特性指数を 0 に正規化
• raw=1 : 定数倍も含めて正規化
raw=2 : 左逆の shift 作用素との合成のスカラーを返す
このスカラーが 0 となる ⇔ shift 作用素が同型写像でない
raw=3 : shift 作用素を上のスカラーとのリストとして返す
raw=4 : さらに左逆 shift 作用素を上のリストの最後に加える• all=0 : shift 作用素のみを返す
all=1 : shift 作用素，微分方程式，Riemann scheme, shift された微分作用素，shift された
Riemann scheme の 5 項のリストを返す• dviout=1 : 結果を dviout によって画面表示する．オプション all を指定可能（all=1 によって微分方程式も表示）．
なお，shift でずれる特性指数は，各特異点でなるべく後に指定した方が高速に計算できる．

[0] os_md.shiftop("11,11,11","00,01,0-1"|zero=1);[1] [x*dx-b,(-x^2+x)*dx^2+((b+c-2)*x-b+1)*dx+a^2+(b+c-1)*a,[[[1,a],[1,-a-b-c+1]],[[1,0],[1,b]],[[1,0],[1,c]]]][2] R=os_md.shiftop("11,11,11","00,01,0-1"|zero=1,raw=2,all=0);115

a^2+(b+c-1)*a+(c-1)*b[3] fctr(R);[[1,1],[a+c-1,1],[a+b,1]][4] os_md.shiftop("11,11,11","00,01,0-1"|zero=1,raw=4,all=0);[x*dx-b,a^2+(b+c-1)*a+(c-1)*b,(x-1)*dx-c+1][5] os_md.shiftop("11,11,11","10,00,0-1"|zero=1,raw=2,all=0);a^2+b*a[6] fctr(@@);[[1,1],[a,1],[a+b,1]][7] os_md.shiftop("11,11,11","10,00,0-1"|zero=1,raw=3,all=0);[x*dx+a,a^2+b*a][8] os_md.shiftop("11,11,11","1-1,00,00"|zero=1,dviout=1,all=1)$
Shift Operator
(

)
x=∞
0 1
a
0 0 = {u | P u = 0}
−a − b − c + 1 b c
(
)
x=∞
0 1
Q1
a+1
0 0
⇄
Q2
−a − b − c b c
Q1 = (2a + b + c)x(x − 1)∂ + a((2a + b + c)x − a − c)
Q2 = −(2a + b + c)x(x − 1)∂ + (a + b + c)((2a + b + c)x − a − b)
Q2 Q1 ≡ a(a + c)(a + b)(a + b + c) mod W (x)P
P = −x(x − 1)∂ 2 + ((b + c − 2)x − b + 1)∂ + a(a + b + c − 1)
57. shiftPfaff(a,b,g,x,[µ1 ,µ2 ]):: Pfaﬀ 系の隣接関係式の middle convolution による変換
ここで，a(x), b(x), g(x) は有理関数の正方行列で，µ1 − µ2 ∈ Z となっている必要がある．
Z x
1u (x) = a(x)u, u(x) =ū(t)(x − t)µ1 −1 dt,
Γ(µ1 ) x0
Z x10v (x) = b(x)v, v(x) =v̄(t)(x − t)µ2 −1 dt,
Γ(µ2 ) x0v̄(x) = g(x)ū(x)0であるとき，u(x) = G(x)v(x) となる有理関数の行列 G(x) を求める．
• µ1 = µ2 のときは，[µ1 ,µ2 ] は単に µ1 としてよい．

58. conf1sp(m|x2= ± 1,conf=0):: スペクトル型 m の微分作用素の Poincare rank 1 の合流過程を示す
スペクトル型を与える各分割は，順に特異点 ∞, 1c , x2 , . . . に対応するものとし，∞ に対応する分割は
1．ただし，x2=1 を指定しないと x2 = 0 とする．
c に対応する分割の細分を指定する（c = 0 が合流）
1
x2=-1 のときは，x2 , . . . を c2
, . . . とする．
conf=0 を指定すると，特異点を ∞, 0, c, x3 , . . . とし，原点と点 c の特異点の合流を示す．
[0] P=os_md.conf1sp([[1,1],[1,1],[1,1]]|x2=1);(-c*x^2+(x_2*c+1)*x-x_2)*dx^2+(((-a01-a00-1)*c+a11)*x+x_2*c-x_2*a11+a01+a00)*dx-a00*a01*c+a00*a11[1] os_md.fctrtos(P|TeX=1,var=dx);116

-(x-x_2)(cx-1){dx}^2-(((a_{01}+a_{00}+1)c-a_{11})x-x_2c+x_2a_{11}-a_{01}-a_{00})[2] os_md.expat(P,x,"?");[[x_2,[-a01-a00+1,0]],[(1)/(c),[(a11)/(c),0]],[infty,[(a01*c-a11)/(c),a00]]][3] Q=os_md.conf1sp([[1,1],[1,1],[1,1]]);(-c*x^2+x)*dx^2+(((-a01-a00-1)*c+a11)*x+a01+a00)*dx-a00*a01*c+a00*a11[4] subst(Q,c,0);x*dx^2+(a11*x+a01+a00)*dx+a00*a11[5] P=os_md.conf1sp([[1,1],[1,1],[1,1]]|conf=0);(-x^2+c*x)*dx^2+((a01-2)*x+(-a01+1)*c+a11)*dx+a20^2+(a01-1)*a20[6] os_md.expat(P,x,"?");[[0,[(a01*c-a11)/(c),0]],[c,[(a11)/(c),0]],[infty,[-a20-a01+1,a20]]][7] subst(-P,c,0);-x^2*dx^2+((a01-2)*x+a11)*dx+a20^2+(a01-1)*a20[8] os_md.fctrtos(-@@|TeX=1,var=dx);x^2{dx}^2-((a_{01}-2)x+a_{11}){dx}-a_{20}(a_{20}+a_{01}-1)
59. pf2kz(m|all=1):: n 変数の Pfaﬀ 系 m を n + 2 変数の KZ 方程式に変換
n = 2 のときは m = [A0 , A1 , A2 , A3 , A4 ] とすると，Pfaﬀ 系
∂u
A1 u
A2 u
A0 u
=
+
+
∂x
x
x−1
y
∂u
A3 u
A4 u
A0 u
=
+
+
∂y
y
y−1
x
を

∂u
=
∂xi

X
0≤j≤3, j6=i

Ai,j uxi − xj(0 ≤ i ≤ 3)に変換する．
ここで(x0 , x1 , x2 , x3 , x4 ) = (x, y, 0, 1, ∞)Ai,j = Aj,i , A0,j = Aj , A1,2 = A3 , A1,3 = A4 ,X
X
Ai,j =
Ai,j = 0.
0≤i<j≤30≤ν≤4, ν6=i

戻り値は [A23 , A04 , A14 , A24 , A34 ] の n + 3 個の成分のリスト
一般には，Pfaﬀ 系の座標と KZ 系の座標の関係は (x0 , x1 , . . . , xn+2 ) = (x, y1 , . . . , yn−1 , 0, 1, ∞) とする．
個）
all=1 を指定すると，Aij の (i, j) による辞書式順序のリストで返す（成分は， (n+2)(n+3)
2[0] N=5$P=[1,2,3,4,5]$MM=os_md.pf2kz(P|all=1)$M=newmat(N,N)$[1] for(I=0;I<N-1;I++) for(J=I+1;J<N;J++)
M[I][J]=M[J][I]=MM[os_md.lext2([I,J,N])[0]][2] dviout(M)$

117



0
1

2

3
−6


1
2
3
−6
0
4
5
−10

4
0
−15
9 
 : 対角成分と各行の和が 0 の正方行列
5
−15
0
7 
−10
9
7
0

60. confexp([[c0 ,f0 ],[c1 ,f1 ],...,[cm , fm ]]) confexp([[f1 ,. . .,fn ],[c1 ,. . .,cm ]]|sym=k]):: 特性指数の合流を返す
1
1(j = 0, . . . , m) の一次結合を ∏j (x−c(j = 0, . . . , m) の一次結合で表す．すなわち
• x−c
j
)
ν=0

ν

m
X

X
fj
λk
=
Qk
x − cjν=0 (x − cν )
j=0
m

k=0

を満たす [λ0 ,λ1 , . . . , λm ] を返す（paracmpl() の項を参照）．
ただし，fj は x を含まない cj などの有理式．
引数は，上のようなリストのリストでもよい（各リストの要素毎の結果をリストとして返す）．
なお，x = y1 とおいて，上の両辺を x で割った等式は以下のようになることに注意．
m
X

X
fj
λk y k=.
Qk
1 − cj y
ν=0 (1 − cν y)
j=0
m

k=0

• sym=1 を指定した場合は



xm−1

f1
(x−c1 )···(x−cm )
xm−2
 f2 
 .  = M  (x−c1 )···(x−cm )  .. 
..


.
fn
1


(x−c1 )···(x−cm )を満たす n × m 行列 M を返す．なお，fj は (x − c1 ) · · · (x − cm ) を掛けると，x の (m − 1) 次以下の多項式となる必要がある．
• sym=2 を指定した場合は，[f1 ,. . .,fn ] の各成分に (x − c1 ) . . . (x − cm ) を掛けた x の多項式のリストを返す．
• sym=3 を指定した場合は



1

f1
x−c1
1
 (x−c )(x−c )  f2 
12

 . =M..
 .. 


.
1
fn


(x−c1 )···(x−cm )を満たす n × m 行列 M を返す．

[0] F=[[c0,((c0-c1)*a0+a1)/(c0-c1)],[c1,(a1)/(-c0+c1)]];[1] os_md.confexp(F);[a0,a1][2] G=os_md.mysubst(F,[c0,0]);[[0,(a0*c1-a1)/(c1)],[c1,(a1)/(c1)]][3] os_md.confexp(G);[a0,a1][4] os_md.confexp([[1/(x-a1),1/(x-a2)],[a1,a2]]|sym=1);[ 1 -a2 ][ 1 -a1 ]118

[5] os_md.confexp([[1/(x-a1),1/(x-a1)/(x-a2)],[a1,a2]]|sym=1);[ 1 -a2 ][ 0 1 ]
[6] os_md.confexp([[1/(x-a1),1/(x-a2)],[a1,a2]]|sym=2);[x-a2,x-a1]
61. mcvm(n|var=x,z=1,get=g) mcvm([n1 ,n2 , . . .]|var=[a,b, . . . ],z=1,get=g)mcvm([r,k,i,j]|e=1,var=[a,b, . . . ]):: versal unfolding の middle convolution
n
du X
Aj
=
u,
dx j=1 (x − a1 )(x − a2 ) · · · (x − aj )nXdu
Aj xj−1=−u,dx(1 − a1 x)(1 − a2 x) · · · (1 − aj x)
j=1
n ri
Aij
du X X=u,dx(x − ai1 )(x − ai2 ) · · · (x − aij )i=1 j=1
r0
n ri
X
du X XAij
A0j xj−1=u−u.
dx(x − ai1 )(x − ai2 ) · · · (x − aij )(1 − a01 x)(1 − a02 x) · · · (1 − a0j x)
i=1 j=1
j=1という versal Schlesinger 系の convolution を求める．
p
du X Cj=udx j=a x − aj1
とおくとという Fuchs 系（Cj は N 次正方行列）は pj = x−aju0 = (C1 , . . . , Cp ) t (p1 , . . . , pn )uと表せるが，この解 u(x) に対して

ũ(x) =

Γ(µ + 1)−1Z xu(t)(x − a1 )−1 (x − t)µ dt


c

..

.

Z
x

Γ(µ + 1)−1u(t)(x − an )−1 (x − t)µ dt








c

と定義すると（c は aj または ∞）ũ0 = diag(p1 IN , . . . , pn IN ) t (1N , . . . , IN )(C1 , . . . , Cn ) + µIpN ũ
j



=

n
X

C̃j
ũ,
x
−
aj
j=1

 0
 .
 .
 .
C̃j = j) 
 C1

 0

..
.

119



⌣

···
···
···
···
···

0
..
.
Cj + µIN
0
..
.

···
···
···
···
···

0 
.. 

. 
.
Cn 

0 

..
.

これは



d
u
(x − a1 ) dxx−a1
du(x − a2 ) dx x−a2=(C1 −1)uC2 ux−a1 + x−a2
C2 −1uC1 ux−a1 + x−a2!

= u 
C2x−a1
u
C2 − 1x−a2

C1 − 1
C1

Rx

d
d
d
d
から得られる（積分変換 v(x) 7→ c v(t)(x − t)µ dt は，作用素 x dx
, dx
を x dx− µ − 1, dxに変換する）．
• 最初の方程式を考える．そこで

1(j = 1, . . . , n),(x − a1 ) · · · (x − aj )Z xΓ(µ + 1)−1u(t)q1 (x)(x − t)µ dt


c


..

û(x) = 
.


Z x


µ
Γ(µ + 1)−1u(t)qn (x)(x − t) dt

qj (x) =cのように基底を取り変えて convolution を行ったとき, 最初の方程式の Ak は Âk に変換されるとする．このとき mcvm(n|get=1) の戻り値を [A01 , . . . , A0p ] とすると, Âk は

Âk = δi,k Aj 1≤i≤n + µA0k
1≤j≤n



で与えられる．なお A0k = Dn,k,i,j IN 1≤i≤n であって Dn,k,i,j は，オプション e=1 で求められる
1≤j≤n

（後述）．
• オプション get を指定しない場合は






p1 (x)
q1 (x)
 ..  = S  .. .
.
pn (x)
qn (x)となる行列 S を返す．すなわち ũ = S −1 û，(C1 , . . . , Cn )S = (A1 , . . . , An ).

0û = S−1 0

ũ = S

−1

p1
..
.

!
(C1 , . . .) ũ + S


S1 q
−1 
= q (A1 , A2 , . . .) û + µS
X


S1 q
−1 
Ak q k = S


 S,

S2 q
..

.

−1

µ

..

..

.

ũ

 S û,

S2 q


!

p1

.


 
S1
q1
S
2
S =   , q = q 2  .
..
..
.
.

• 2 番目の方程式の場合は，(x − ai )−1 を ( a1i − x)−1 に，qi (x) を xi−1 (1 − a1 x)−1 · · · (1 − ai x)−1に置き換えて同様な結果を返す.
• オプション var=[a,b,c, . . .] により方程式の特異点を表す ai を他の文字 a, b, c, . . . のように置き換える．

• 3 番目と 4 番目の方程式の場合は，ℓ として [r1 , . . . , rn ] または [r0 , r1 , . . . , rn ] を指定し，後者はオプション z=1 を指定する.

120

• 上記 Fuchs 系は x0 = x とおくと
∂u
=
∂xi

p
X
ν∈{0,...,i}\{i}Ci,ν
xi − xν(i = 0, . . . , p),Ci,j = Cj,i , C0,j = Cjという KZ 系に拡張できるとする．このとき convolution に対応して C0,j = Cj は Ĉ0,j = C̃j となるが，convolution は KZ 系にも拡張され, それは
i






i) 



C̃i,j =



j) 




j

⌣



⌣

Ci,j
..

















.
−C0,j

Ci,j + C0,j
Ci,j
..
−C0,i

.
Ci,j + C0,i
..

.
Ci,j

で与えられる．

• get=2 を指定すると，versal unfolding では，Aj あるいは Ai,j を用いたが，Fuchs 型への unfoldingの convolution で用いた基底に対応して前項の C̃i,j (1 ≤ i < j ≤ p) の対角部分 Ci,j を除いた部
分が変換される行列を A0,ν を用いて表したリスト（対角部分 Ai,j が除かれている．A0,ν はデフォ
ルトでは a0ν と表示）を返す．これを用いて不確定 KZ 方程式の versal unfolding の convolutionが計算できる（cf. [O9]）．
• get=3 を指定すると，3 番目の常微分方程式で n = 2 の場合に，x0 = x, a1,j = x1 − aj , a2,j =1∂ û= A1 (x)û の A1 (x) を完備化基底 { (x1 −x
x2 − bj とおいたときの方程式 ∂x
ν | ν = 1, . . . , r1 } ∪
1
0)
1
1
1
{ x1 −x2 +a1 −b1 , . . . , (x1 −x2 +a1 −b1 )···(x1 −x2 +a1 −br ) , . . . , (x1 −x2 +a1 −b1 )···(x1 −x2 +ar −br ) } を 用 い
2
1
2たときの後者の部分の係数を返す（r1 r2 個ある）．ただし，a1 = b1 = 0 が代入され，対角部分のAi,j に当たる部分は省かれる．
結果は，さらに a2 = · · · = ar1 = b1 = · · · = br2 = 0 とおいた場合の係数のリストと合わせて返される．
n > 2 のときの結果は，n = 2 のときの結果から分かる（cf. [O9]）.

I = {i0 , i0 + 1, . . . , i0 + rI − 1}, J = {j0 , j0 + 1, . . . , j0 + rJ − 1},
X C0,ν
X C0,i
X
A0,i
du =
dx =
du +
du,
x
−
x
x
−
x
(x
−
x
)
· · · (x − xi )
ν
ν
i
0
ν
X

i6∈I

i∈I


C̃i,ν
S û,
x i0 + e i − x νi∈Iν6∈I, ν6=0C̃i,ν = Ci,ν δp,q + δp,i (δq,i − δq,ν )C0,ν + δp,ν (δq,ν − δq,i )C0,i
,

∂ û
=
∂xi0

X
Ãi,0
+ S −1(xi0 + ei0 − x0 ) · · · (xi0 + ei − x0 )

p,q

121

X
1
U(i,j),(k,ℓ) qk,ℓ ,=x i0 + e i − x j 0 − e jk∈I, ℓ∈JX S −1Ci,j δp,q + δp,i (δq,i − δq,j )C0,j + δp,j (δq,j − δq,i )C0,ii∈I, j∈J

=

X

X

X 

+

X

X

p,q

X

X

SU(i,j),(k,ℓ) qk,ℓ

qk,ℓ

i


X
S −1 δp,i (δq,i − δq,j )A0,s qs−i0 +1,{1,...,s−i0 } (xi0 , . . .)s=i0i∈I, j∈J k∈I, ℓ∈J

+

p,q



Ak,ℓ δp,qk∈I, ℓ∈J(xi0 + ei − xj0 − ej )−1 SS −1 Ci,j δp,q + δp,i (δq,i − δq,j )C0,j + δp,j (δq,j − δq,i )C0,ii∈I, j∈J k∈I, ℓ∈J

=

p,q

p,q

j


X
S −1 δp,i (δq,j − δq,i )A0,s qs−j0 +1,{1,...,s−j0 } (xj0 , . . .)s=j0i∈I, j∈J k∈I, ℓ∈J

SU(i,j),(k,ℓ) qk,ℓp,qSU(i,j),(k,ℓ) qk,ℓ .

• get=4 を指定すると，get=3 で返される係数のリストの後者のみが返される．
• e=1 を指定した場合は，最初の引数を [r,k,i,j] としたとき，j + k − i − 1 次の多項式 Dr,k,i,j を返す（r は無視される）： なお，Dr,k,i,j = Dr,j,i,k .
0(i < j)(最初の方程式),
S = Si,j, Si,j =si,{1,...,j} (i ≥ j)i,jsi,{j1 ,...,jk } (a) :=kY(ai − ajν ),j=1

Dr,k,i,j (a) :=

pi =

i
X

si,{1,...,j−1} qj ,

j=1
i
X

sν,{1,...,j−1}

ν=max{k,j}sν,{k,k+1,...,i}\{ν}.

0• e=2 を指定した場合は，最初の引数を [r,k,i,j] としたとき，j + k − i − 1 次の多項式 Dr,k,i,jを返す（r は無視される）:
0
Dr,k,i,j(a0 ) :=iX
ν=max{k,j}aν+1 sν+1,{2,...,j}sν+1,{k,k+1,...,i+1}\{ν+1}[0] os_md.mcvm([2,1]);[ 1 0 0 ][ 1 -a1+a2 0 ][ 0 0 1 ][1] os_md.mcvm([2,2]|var=[a,b]);[ 1 0 0 0 ][ 1 -a1+a2 0 0 ][ 0 0 1 0 ][ 0 0 1 -b1+b2 ][2] os_md.mcvm([2,1]|get=1);[[ 1 0 0 ][ 0 1 0 ][ 0 0 0 ],[ 0 0 0 ][ 1 -a1+a2 0 ]122= Dr,k,i+1,j+1 (a)|a1 =0 .

[ 0 0 0 ],[ 0 0 0 ][ 0 0 0 ][ 0 0 1 ]]これは 3 番目の方程式で，n = 2, r1 = 2, r2 = 1 の場合でÂ1,1 =

Â2,1 =!
A1 + µ A2 A3
0
µ
0 ,
0
0
0
!
0
0
0
0
0
0
A1 A2 A3 + µÂ1,2 =

0
A1 + µ00A2 + (a2 − a1 )µ0となることを意味する．

[3] subst(os_md.mcvm([1,3]|get=1),b1,0);[[ 1 0 0 0 ][ 0 0 0 0 ][ 0 0 0 0 ][ 0 0 0 0 ],[ 0 0 0 0 ][ 0 1 0 0 ][ 0 0 1 0 ][ 0 0 0 1 ],[ 0 0 0 0 ][ 0 0 0 0 ][ 0 1 b2 0 ][ 0 0 1 b3 ],[ 0 0 0 0 ][ 0 0 0 0 ][ 0 0 0 0 ][ 0 1 b3 -b3*b2+b3^2 ]][4] M=os_md.mcvm([1,3])$[5] A=os_md.mcvm([1,3]|get=2)$[6] M=subst(M,b1,0)$ A=subst(A,b1,0)$[7] map(red,M[1][1]*A[0]+M[2][1]*A[1]+M[3][1]*A[2]); /* A12 */[ a02 -a02 -a03 -a04 ][ -a01 a01 0 0 ][ 0 0 a01 0 ][ 0 0 0 a01 ][8] map(red,M[1][2]*A[0]+M[2][2]*A[1]+M[3][2]*A[2]); /* A13 */[ a03 -a03 -a03*b2-a04 -a04*b3 ][ 0 0 0 0 ][ -a01 a01 a01*b2 0 ][ 0 0 a01 a01*b3 ][9] map(red,M[1][3]*A[0]+M[2][3]*A[1]+M[3][2]*A[3]); /* A14 */[ a04 -a04 -a04*b3 a04*b3*b2-a04*b3^2 ]
123

0
A3
0

!
,

[ 0 0 0 0 ][ 0 0 0 0 ][ -a01 a01 a01*b3 -a01*b3*b2+a01*b3^2 ]
これから
4
 A

X
∂u
A0j
01
=
+
u,
∂x0
x0 − x1 j=2 (x0 − x2 )(x0 − x2 − b2 ) · · · (x0 − x2 − bj−1 )
4
 A

X
A1j
∂u
10
=
+
u,
∂x1
x1 − x0 j=2 (x1 − x2 )(x1 − x2 − b2 ) · · · (x1 − x2 − bj−1 )
1 X
4 

X
∂u
(−1)j Aji=u,∂x2(x2 − xi )(x2 − xi + b2 ) · · · (x2 − x1 + bj−1 )i=0 j=2

Ai,j = Aj,iの convolution が
A01 + µ A02 A03 A04
0
0
0
0
0
0
0
0 
A02 + µ A03 A04 AÂ01 = , Â02 =  01
,
0
0
0
0 
0
0
µ
0 
0
0
0
0
0
0
0
µ



0
0
0
0
0
0
0
0
0
0 
0
0
 0
 0
Â03 = , Â04 = 
a01 A02 + µ A03 + b2 µ A04 
0
0
0
0
0
µ
b3 µ
A01 A02 + µ A03 + b3 µ
A12 + A02
−A02
−A03
−A04
A12 + A0100
 −A01
Â12 = ,00
A12 + A0100
0
0
A12 + A01

A13 + A03 −A03 −b2 A03 − A04−b3 A04
0
A13
0
0


Â13 = 
,
−A01
A01
A13 + A01
b3 A010
0
A01
A13 + b3 A01

A14 + A04 −A04 −b3 A04−b3 (b3 − b2 )A04
0
A
0
0


14
Â14 = 

0
0
A14
0
−A01
A01
b3 A01
A14 + b3 (b3 − b2 )A01
（Ãij = Ãji ）で与えられることが分かる．

[10] os_md.mcvm([2,3]|get=1);[[ 1 0 0 0 0 ][ 0 1 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ],[ 0 0 0 0 0 ][ 1 -a1+a2 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ],[ 0 0 0 0 0 ]
124


0
0

,
0
A04 + b3 (b3 − b2 )µ[ 0 0 0 0 0 ][ 0 0 1 0 0 ][ 0 0 0 1 0 ][ 0 0 0 0 1 ],[ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 1 -b1+b2 0 ][ 0 0 0 1 -b1+b3 ],[ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 1 -b1+b3 (b2-b3)*b1-b3*b2+b3^2 ]][11] os_md.mcvm([2,3]|get=4);[[ a03 0 -a03 -a04 -a05 ][ 0 a03 0 0 0 ][ -a01 -a02 a01 0 0 ][ 0 0 0 a01 0 ][ 0 0 0 0 a01 ],[ a04 0 -a04 -a05 0 ][ -a03 a04 a03 a04 a05 ][ a02 0 -a02 0 0 ][ -a01 -a02 a01 -a02 0 ][ 0 0 0 a01 -a02 ],[ a05 0 -a05 0 0 ][ -2*a04 a05 2*a04 2*a05 0 ][ 0 0 0 0 0 ][ 2*a02 0 -2*a02 0 0 ][ -a01 -a02 a01 -2*a02 0 ],[ 0 0 0 0 0 ][ -3*a05 0 3*a05 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 3*a02 0 -3*a02 0 0 ],[ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ],[ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ][ 0 0 0 0 0 ]]125

上の結果より不確定特異点をもつ KZ 型方程式
2
3
X
X
∂u
A0,ν
A0,ν+2 =+u,∂x0(x0 − x1 )ν ν=1 (x0 − x2 )ν
ν=1
2
4
X
∂u
(−1)ν−1 Aν,0 X A1,ν+2 
+
=
u,
∂x1
(x1 − x0 )ν
(x1 − x2 )ν
ν=1
ν=1
3
4
X
∂u
(−1)ν−1 Aν+2,0 X (−1)ν−1 Aν+2,1 
=
u,
+
∂x2
(x2 − x0 )ν
(x2 − x1 )ν
ν=1
ν=1

Ai,j = Aj,iの convolution は
A01 + µ A02 A03 A04 A05
000A01 + µ A02 A03
0
µ
0
0
0 



0
0
0
0
0  , Â02 = 000Â01 = 


0
0
0
0
0 
0
0
0
0
0
0
0
0
0
0
0



0
0
0
0
0
0
0
0
 0
 0
0
0
0
0 
0
0



0
0
Â03 = A01 A02 A03 + µ A04 A05  , Â04 =  0
 0
A01 A02 A03 + µ
0
0
µ
0 
0
0
0
0
µ
0
0
0


0
0
0
0
0
 0
0
0
0
0 


0
0
0
0 ,
Â05 =  0
 0
0
0
0
0 
A01 A02 A03 + µ A04 A05

A13 + A03
0
−A03
−A0,4
−A05


0
A13 + A03
0
0
0


−A02
A13 + A01
0
0Â13 =  −A01
,


0
0
0
A13 + A01
A02
0
0
0
0
A13 + A01

A14 + A04
0
−A04
−A05
0

 −A03
A14 + A04
A03
A04
A05


0
A14 − A02
0
0
Â14 =  A02, −A01−A02
A14 + A01
−A02
0
0
0
0
A01
A14 − A02

A15 + A05
0
−A05
0
0
 −2A04
A15 + A05
2A04
2A05
0 


0
0
A15
0
0 ,
Â15 =  2A02
0
−2A02
A15
0 
−A01
−A02
A01
−2A02 A15


A16
0
0
0
0
−3A05 A16
3A05
0
0 


0
A16
0
0 
Â16 =  0
 0
0
0
A16
0 
3A02
0
−3A02
0
A16
．
で与えられることが分かる（cf. [O9]）62. anal2sp(m,l):: 同時スペクトル m の解析
m = [[m1 , λ1 , µ1 ], [m2 , λ2 , µ2 ], . . .] は重複度と同時固有値
l は以下の意味を持つ.
0
同じスペクトル型をまとめる（同時スペクトルでなくても可）．
["add",n]スペクトル型 n を加える（同時スペクトルでなくても可）
．
126

0
A04
0
0
0
0
0
0
A04
µ


0
A05 

0 ,
0 
0

0
0 

0 ,
A05 
0

["sub",n]スペクトル型 n を引く（同時スペクトルでなくても可）．
["swap"]
同時スペクト型の順序を入れ替える．
["+",c1 ,c2 ] 固有値をシフトする．
["*",c1 ,c2 ] 固有値の一次結合を返す．
["+",c1 ,c2 ,. . .] 固有値をシフトする（任意個でよい）．
["*",c1 ,c2 ,. . .] 固有値の一次結合を返す（任意個でよい）．
["mult",m] 同次固有値の重複度を全て m 倍する．
["get",f ,c] f 番目の固有値が c となるものを抜き出す．
["put",f ,c] f 番目の固有値を c に置き換える．
["get1",f ] f 番目の固有値のみを抜き出す（結果は同時スペクトルでない）．
["get1",f ,c] f 番目の固有値が c のものを抜き出す（結果は他方のスペクトル）．
["put1",f ,c] 同時でないスペクトルに，f 番目の固有値に c を追加する．
["put1"] 同じスペクトル型をコピーする．
["max"] 重複度最大の場所とそのスペクトル型の組のリストを返す．
["max",f ,c] f 番目の固有値が c となるものの中で，重複度最大の場所とそのスペクトル型の組のリストを返す．存在しない場合は，[-1] を返す．
["val",f ]f 番目のスペクトルの階数と固有値の和を返す．
[[· · · ],[· · · ],. . .] 複数のコマンドを続けて実行する．
[0] R=os_md.anal2sp([[2,a,b],[3,a,c],[-1,a,c]],["add",[[-2,a,b],[1,b,c]]]);[[2,a,b],[3,a,c],[-1,a,c],[-2,a,b],[1,b,c]] /* R の定義 */[1] os_md.anal2sp([[2,a,b],[3,a,c],[-1,a,c]],["sub",[[2,a,b],[-1,b,c]]]);[[2,a,b],[3,a,c],[-1,a,c],[-2,a,b],[1,b,c]][2] os_md.anal2sp(R,["swap"]);/* 順番を逆に */[[2,b,a],[3,c,a],[-1,c,a],[-2,b,a],[1,c,b]][3] os_md.anal2sp(R,0);/* まとめる */[[2,a,c],[1,b,c]][4] os_md.anal2sp(R,["+",f,-g]); /* 固有値のシフト */[[2,a+f,b-g],[3,a+f,c-g],[-1,a+f,c-g],[-2,a+f,b-g],[1,b+f,c-g]][5] os_md.anal2sp(R,["*",f,-g]); /* 固有値の一次結合 */[[2,f*a-g*b],[3,f*a-g*c],[-1,f*a-g*c],[-2,f*a-g*b],[1,f*b-g*c]][6] os_md.anal2sp(R,["*",f]);[[2,f*a],[3,f*a],[-1,f*a],[-2,f*a],[1,f*b]][7] os_md.anal2sp([[2,a,b],[3,a,c],[-1,a,c]],["mult",2]); /* 重複度 *= m */[[4,a,b],[6,a,c],[-2,a,c]][8] os_md.anal2sp(R,["get",2,c]); /* 指定した固有値のみ抽出 */[[3,a,c],[-1,a,c],[1,b,c]][9] os_md.anal2sp(R,["put",1,f]); /* 固有値を置き換える */[[2,f,b],[3,f,c],[-1,f,c],[-2,f,b],[1,f,c]][10] os_md.anal2sp(R,["get",1,a]); /* 指定した固有値のみ抽出 */[[2,a,b],[3,a,c],[-1,a,c],[-2,a,b]][11] R1=os_md.anal2sp(R,["get1",1,a]); /* 指定した固有値の他方を抽出 */[[2,b],[3,c],[-1,c],[-2,b]][12] os_md.anal2sp(R1,["put1",1,a]); /* 固有値の挿入 */[[2,a,b],[3,a,c],[-1,a,c],[-2,a,b]][13] os_md.anal2sp(R1,["put1"]); /* 固有値のコピー */127

[[2,b,b],[3,c,c],[-1,c,c],[-2,b,b]][14] os_md.anal2sp(R,["val",1]); /* 固有値の和 */[3,2*a+b][15] os_md.anal2sp(R,[["get1",1],["put1"],0]);[[2,a,a],[1,b,b]][16] os_md.anal2sp(R,["max"]);/* 最大重複度 */[1,[3,a,c]][17] os_md.anal2sp(R,["max",1,b]);[4,[1,b,c]][18] os_md.anal2sp(R,["max",1,c]);[-1]
63. mc2grs(g,r|top=0,dviout=k,div=ℓ,fig=s):: P1 内の 5 点の配置に対する KZ 型方程式の同時スペクトル g の変換
KZ 型方程式
X

du =

Ai,j

0≤i<j≤3

Ai,4 = −3Xd(xi − xj )u,xi − xj

Ai,j , Aj,i = Ai,j , Ai,i = 0

j=0において，I, J ⊂ {0, 1, 2, 3}, #I = #J = 2, I ∩ J = ∅ のとき[AI , AJ ] = 0が満たされるので，AI と AJ の同時固有値分解が出来る．このような 15 組の [I, J] に対する同時固有値（重複度と各固有値）のリスト（ヘッダは [I,J] で，I=[ii ,i2 ], J=[ji ,j2 ] とすると，i1 < i2 ,j1 < j2 , i1 < j1 となる）のリストを g とする．

!

aA0,1 =a, A2,3 =
b

!

c
c
d

のときは同時固有値のリストは [[[0,1],[2,3]],[2,a,c],[1,b,d]] となる．
P
なお，既約性から 0≤i<j≤3 Ai,j はスカラー行列としてよいので，そのスカラーを κ とする．
同時固有値のリストのリストを g で与えるが，それ以外の指定は• g = 0 のとき，自明な [[[[0,1],[2,3]],[1,0,0]],[[[0,1],[2,4]],[1,0,0]],. . .] を意味する．
• g を，4 行列 A0,4 , A0,1 , A0,2 , A0,3 のスペクトル型（文字列あるいは，4 点の GRS）を, この順で指定する．このときは，m2mc() におけると同様なオプション（dep=[m,n]，int=0）などの指定が可能）．なお，top=0 を指定した場合は，A0,1 , A0,2 , A0,3 , A0,4 の順と解釈される．
スペクトル型や文字列で指定した場合は, 以下の r が特別の意味を持つ．
– r = 1 : スペクトル型を標準的な順序にし，同時固有値のリストのリストをそのまま返す．
– r = 3 : 同時固有値のリストのパラメータを a,b,c,. . . で表し，Fuchs 条件と同次固有値のリ
ストのリストとの組をリストとして返す．
スペクトル型や文字列で指定した場合は, 以下の r が特別の意味を持つ．
• r = 1 : スペクトル型を標準的な順序にし，同時固有値のリストのリストをそのまま返す．
• r = 3 : 同時固有値のリストのパラメータを a,b,c,. . . で表し，Fuchs 条件と同次固有値のリストのリストとの組をリストとして返す．
r によって，以下の機能になる．

128

• 0 : 同時固有値のリストのリストをそのまま返す．
• ["sort"] : ヘッダが標準的な順序になるよう，リストを並び替える（[ ] は省略可）．
• ["deg"] : κ を返す（[ (] は省略可）．なお A0,1 + A0,2 + A0,3 + A1,2 + A1,3 + A2,3 = κ で+κ (j < 4)Ai,j = A{0,1,2,3,4}\{i,j}(0 ≤ i < j ≤ 4).
−κ (j = 4)
• [[i,j],λ] : Ai,j 7→ Ai,j + λ, Ai,4 7→ Ai,4 − λ, Aj,4 7→ Aj,4 − λ という addition を返す（0 ≤ i < j ≤ 3）．
• ["homog"] : r =[[1,3],−κ] に対応する addition によって κ = 0 とする（[ ] は省略可）．
• ["homog",[m,n]] : r =[[m,n],−κ] に対応する addition によって κ = 0 とする（0 ≤ m <n < 4）．
• ["swap",[i,j]] : 添え字の i と j を交換する．i または j が 4 のときは，r =["homog"] を行ってから添え字を交換する．

• ["perm",[i0 , . . . , i4 ]] : 添え字の置換



0
i0

1
i1

2
i2

3
i3

4
i4


を行う．添え字 4 を変更するときは，r =["homog"] を行ってから置換する．
• [µ] : x0 変数に対する middle convolution mcx0 ,µ を行う（アルゴリズムは [O5] によって与えられた）．

• [i,µ] : xi 変 数 に 対 す る middle convolution mcxi ,µ を 行 う ．た だ し ，i = 4 の と き は ，
r =["swap",[0,4]] を行ってから mcx0 ,µ を施し，再度 r =["swap",[0,4]] で戻す．
• [[[i1 ,j1 ],λ1 ],. . .,[ik ,µk ],. . .] : additions と middle convolutions を連続して行う．
• [[a,b,c]] : [[[0,1],a],[[0,2],b],[[0,3],c]] と同じ．
• [[a,b,c,µ]] : [[[0,1],a],[[0,2],b],[[0,3],c],[µ]] と同じ．
• ["get",[I,J]] : [AI , AJ ] = 0 に対する同時固有値を返す（ヘッダ [I, J] のついたリスト）．
• ["get",I] : AI に対する固有値を返す（ヘッダ I のついたリスト）．
• ["get",[i,j,k]] : Ai,j + Ai,k + Aj,k のスペクトルを返す（ヘッダ I のついたリスト）．
• ["get",i] (0 ≤ i ≤ 4) : i ∈ I を満たす AI に対する GRS を返す（変数 xi についての常微分方
程式の GRS）．
dviout=1 を 指 定 す る と TEX を 使 っ て 表 示 す る ．dviout=-1 で は TEX の ソ ー ス を 返 す ．
dviout=2 を指定すると，TEX のソースを書き出すが表示はしない（次回の表示コマンドでまとめて表示する）．

• ["get"] : 10 個全ての AI の固有値のリストを返す．
dviout=k の指定が可能．このとき，オプション div=ℓ によって，Riemann Scheme が分割できる（cf. divmattex()）.
• ["get0",[I,J]], ["get0",I], ["get0",i] (0 ≤ i ≤ 4), ["get0",[i,j,k]]，["get0"] :"get0" を "get" に変えたものと同じであるが，ヘッダはつけない．
• ["get0",I,J] : AI + AJ のスペクトルを返す．
• ["show"] : 同時スペクトルを TEX を使って表示する．
dviout=-1 の指定が可能．
• ["show0"] : 15 組の同時スペクトルの固有値の重複度を示す（15 組の順序は，"show"におけると同じ）．

dviout=1, -1, 2 の指定が可能．さらに– fig=1 を指定すると，結果を図示する（TikZ を使う場合）．
– fig=[k] とすると，図の大きさを k cm 強とする（デフォルトは k = 12）．
– fig=[k,s] または fig=[s]，s は色指定文字列で，10 個を順に指定する．
デフォルトの [s] は ["black,dashed","green,dashed","red,dashed","blue,dashed","black","cyan","green","blue","red","magenta"]．
• ["spct"] : スペクトル型を返す．5 × 5 行列で (i, j) 成分は，i 6= j のとき Ai,j のスペクトル型，
i = j のとき xi についての index of rigidity（0 ≤ i, j ≤ 4）．
dviout=k の指定が可能．

129

• ["spct1"] : スペクトル型と，（reduction が可能なときは）1 ステップの reduction 後のスペクト
ル型（文字列）を，5 × 6 行列で返す（["spct"] と同様だが，さらに 6 列目にそのスペクトル型が入る）．

• ["mult",ℓ1 ,...,ℓm ] : g0 = g として gi = mc2grs(gi−1 ,ℓi ) を i = 1, . . . , m に対して順に実行
して gm を返す．オプションも有効．
• ["eigen",I] : AI の各固有空間にいて，AI と可換な 3 つの留数行列の固有空間分解を返す（固有値と固有空間分解のリストの組のリストで，固有空間分解は重複度と固有値の組のリスト）．
AI と可換な留数行列 AJ は J ⊂ {0, 1, 2, 3, 4} \ I を満たすもので，J を辞書式順序にして返す．
たとえば，I = [0, 2] ならば，J は辞書式順序で [1, 3], [1, 4], [3, 4] の 3 つ．
• ["rest",I] : I = [i, j] のとき，特異直線 xi = xj への各特異成分に対応する境界値の満たす x0の方程式の GRS を返す（x0 = xk の k が小さいに並べ，0 < i < j のときは，x0 = xi は x0 = xkと解釈する）．
• ["rest0",I] : I = [i, j] のとき，特異直線 xi = xj への各特異成分に対応する境界値の方程式のスペクトル型（文字列）を返す．
• ["rest1",I] : I = [i, j] のとき，特異直線 xi = xj への各特異成分に対応する境界値の方程式のうち，rigid でないスペクトル型（文字列）のみを全て返す．
• ["eigen"], ["rest"], ["rest0"]，["rest1"] としたときは，上の I の 10 個全てに対して，その結果の最初に I を付加した結果のリストを返す．このとき，dviout=1, -1, 2 の指定が可能．
(λ)m×• ["K0",[µ,λ]] : K̃x−µ−λ,λ [ [0,0,λ,−µ − λ],[0,0,µ] ] : (1−µ)
m• ["K1",[µ,λ]] : K̃y−µ−λ,λ [["swap",[0,1]],[0,0,λ,−µ − λ],[0,0,µ],["swap",[0,1]]]−µ−λ,λ• ["K01",[µ,λ]] : K̃x,(x,y)7→(x, xy)• ["K2",[µ,λ]] : [ [0,λ,0,−µ − λ],[0,0,µ] ]• ["K3",[µ,λ]] : [["swap",[0,1]], [0,λ,0,−µ − λ],[0,0,µ],["swap",[0,1]] ]
Qp
Qq
Qr
∞ X
∞
X
(a ) (b )(bν )n ν=1 (cν )m+nν=2 (aν )mν=2Q
Qp 1 m 1 n Q• ["K",[p,q,r]] :xm y n
q
r
(1
−
d
)
(1
−
e
)
(1
−
f
)
m!n!
ν
m
ν
n
ν
m+n
ν=2
ν=2
ν=1
m=0 n=0
rank : pq + qr + rp
Qp−1
Qq−1
∞ X
∞
X
(a )
ν=1 (bν )n · (c)m+n
Qp ν=1 ν m Q• ["I",[p,q]] :xm y n
q
(1
−
d
)
(1
−
e
)
m!n!
ν
m
ν
n
ν=2
ν=2
m=0 n=0
rank : pq, (pq − 1)1, (pq − q + 1)1q−1 , q p , q p−1 1q(x0 , x1 , x2 , x3 , x4 ) = (x, y, 1, 0, ∞) のとき(1 − x − y)−λ × : [ [[0,1],−λ],[[2,3],λ] ] at (0, 1) or (1, 0)(1 − x)−λ× : [ [[0,2],−λ],[[2,3],λ] ]−λ(1 − y)× : [ [[1,2],−λ],[[2,3],λ] ]Homogenization : [["homog",[2,3]]]K̃xµ,λ : [ [0,0,λ,µ],[0,0,−λ − µ] ]K̃yµ,λ : [ [[1,3],λ],[1,µ],[[1,3],−λ − µ] ]µ,λK̃x,(x,y)7→(x7→ x ) : ["perm",[2,1,0,4,3]] → [[0,0,λ,µ],[0,0,−λ−µ] ] → ["perm",[2,1,0,4,3]]
y

 Rx



 µ+1,λ xu Kx(x − t)µ tλ u(t,y)
x−yt−x dt
0
R
x


x
µ,λ
u(t,y)µλ(K̃x u)(x, y) =
 0 (x − t) t y dt  = Kxµ+1,λ xuyΓ(µ + 1) R x
µ+1,λ
µ λ−1
Kx
u
(x − t) tu(t, y)dt0
Z 1
Γ(λ + m) m n1
tλ−1 (1 − t)µ−λ−1 u(tx, y)dt, xm y n 7→Kxµ−λ,λ u(x, y) =x y
Γ(µ − λ) 0
Γ(µ + m)Z 1
Γ(λ + n) m n1
tλ−1 (1 − t)µ−λ−1 u(tx, y)dt, xm y n 7→
Kyµ−λ,λ u(x, y) =x y
Γ(µ − λ) 0
Γ(µ + n)Z 11
Γ(λ + m + n) m nµ−λ,λtλ−1 (1 − t)µ−λ−1 u(tx, ty)dt, xm y n 7→x yKx,(x,y)7→(x, x ) u(x, y) =yΓ(µ − λ) 0
Γ(µ + m + n)
−µ−λ

130

[0] M=os_md.mc2grs(0,0);[[[[0,1],[2,3]],[1,0,0]],[[[0,1],[2,4]],[1,0,0]],...
[1] M1=os_md.mc2grs(M,[[[0,1],a],[[0,2],b],[[0,3],c]]);[[[[0,1],[2,3]],[1,a,0]],[[[0,1],[2,4]],[1,a,-b]],...
[2] os_md.mc2grs(M1,"deg");/* Get kappa */a+b+c[3] os_md.mc2grs(M1,["homog",[2,3]]);/* homogenize */[[[[0,1],[2,3]],[1,a,0]],[[[0,1],[2,4]],[1,a,-b]],...,[[[1,4],[2,3]],[1,-a,-a-b-c]]][4] F1=os_md.mc2grs(M1,[d]);[[[[0,1],[2,3]],[1,a+d,0],[1,0,0],[1,0,b+c]],[[[0,1],[2,4]],[1,a+d,-b],[1,0,-b],[1,0,-a-b-c-d]],...
[5] os_md.mc2grs(F1,"get");/* All residue matrices */[[[0,1],[1,a+d],[2,0]],[[0,2],[1,b+d],[2,0]],[[0,3],[1,c+d],[2,0]],[[0,4],[1,-a-b-c-d],[2,-d]],[[1,2],[2,0],[1,a+b]],[[1,3],[2,0],[1,a+c]],[[1,4],[2,-a],[1,-a-b-c-d]],[[2,3],[2,0],[1,b+c]],[[2,4],[2,-b],[1,-a-b-c-d]],[[3,4],[2,-c],[1,-a-b-c-d]]][6] os_md.mc2grs(F1,[-d])==M1; /* middle convolution */1[7] os_md.mc2grs(F1,["get",0]); /* GRS for the variable x0 */[[[0,1],[2,0],[1,a+d]],[[0,2],[2,0],[1,b+d]],[[0,3],[2,0],[1,c+d]],[[0,4],[2,-d],[1,-a-b-c-d]]][8] os_md.mc2grs(F1,["get",0]|dviout=-1);\begin{Bmatrix}
A_{01}&A_{02}&A_{03}&A_{04}\\[0]_2 & [0]_2 & [0]_2 & [-d]_2\\
a+d & b+d & c+d & -a-b-c-d\end{Bmatrix}[9] os_md.mc2grs(F1,["get",0]|dviout=1); /* GRS for the variable x0 */
(

A01
[0]2
a+d

A02
A03
[0]2
[0]2
b+d c+d[10] os_md.mc2grs(F1,"get"|dviout=1)$
{

A01
[0]2
a+d

A02
[0]2
b+d

A03
[0]2
c+d

A04
[−d]2
−a − b − c − d

A12
[0]2
a+b

A13
[0]2
a+c

[11] os_md.mc2grs(F1,"show"|dviout=1)$

A04
[−d]2
−a − b − c − d)/* GRS of KZ equation */
A23
[0]2
b+c

A14
[−a]2
−a − b − c − d

A24
[−b]2
−a − b − c − d/* simultaneous eigenspaces */[A01 : A23 ] = {[a + d : 0], [0 : 0], [0 : b + c]},[A01 : A24 ] = {[a + d : −b], [0 : −b], [0 : −a − b − c − d]},[A01 : A34 ] = {[a + d : −c], [0 : −c], [0 : −a − b − c − d]},[A02 : A13 ] = {[b + d : 0], [0 : 0], [0 : a + c]},[A02 : A14 ] = {[b + d : −a], [0 : −a], [0 : −a − b − c − d]},
131

A34
[−c]2
−a − b − c − d}[A02 : A34 ] = {[b + d : −c], [0 : −c], [0 : −a − b − c − d]},[A03 : A12 ] = {[c + d : 0], [0 : 0], [0 : a + b]},
[A03 : A14 ] = {[c + d : −a], [0 : −a], [0 : −a − b − c − d]},[A03 : A24 ] = {[c + d : −b], [0 : −b], [0 : −a − b − c − d]},[A04 : A12 ] = {[−a − b − c − d : 0], [−d : 0], [−d : a + b]},
[A04 : A13 ] = {[−a − b − c − d : 0], [−d : 0], [−d : a + c]},[A04 : A23 ] = {[−a − b − c − d : 0], [−d : 0], [−d : b + c]},[A12 : A34 ] = {[0 : −c], [0 : −a − b − c − d], [a + b : −c]},[A13 : A24 ] = {[0 : −b], [0 : −a − b − c − d], [a + c : −b]},[A14 : A23 ] = {[−a : 0], [−a − b − c − d : 0], [−a : b + c]}[12] os_md.mc2grs("322,52,52,43","show0"|dviout=1)$/* spectral type of simultaneous eigenspace decomposition */22 13 , 17 , 17 , 22 13 , 17 , 17 , 215 , 17 , 17 , 17 , 17 , 17 , 17 , 17 , 17[13] os_md.mc2grs(F1,"spct"|dviout=1)$
x0
x0
x1
x2
x3
x4

21
21
21
21

x1
21
21
21
21

x2
21
21
21
21

x3
21
21
21
21

x4
21
21
21
21

/* spectral type of KZ equation */

idx
2
2
2
2
2

[14] os_md.mc2grs("21,21,21,21","get"|dviout=1)$ /* GRS of KZ equation */
{

A01
[0]2
a

A02
[0]2
b

A03
A04
A12
A13
A23
A14
A24
A34
[0]2
[d]2
[0]2
[0]2
[0]2
[−a − d]2[−b − d]2[−c − d]2c −a − b − c − 2d a + b + 2d a + c + 2d b + c + 2d −a − b − c − 2d −a − b − c − 2d −a − b − c − 2d}[15] os_md.mc2grs([[[[2,3],[0,4]],[1,a,b]],[[[0,1],[2,3]],[1,c,d]]],"sort");[[[[0,1],[2,3]],[1,c,d]],[[[0,4],[2,3]],[1,b,a]]][16] os_md.mc2grs(F1,["eigen",[0,1]]); /* decomp. of eigenspaces */[[a+d,[[1,0]],[[1,-b]],[[1,-c]]],[0,[[1,0],[1,b+c]],[[1,-b],[1,-a-b-c-d]],[[1,-c],[1,-a-b-c-d]]]][17] os_md.mc2grs(F1,["rest",[0,1]]);/* bry GRS for a sing. line */[[a+d,[[1,a+b+d]],[[1,a+c+d]],[[1,-2*a-b-c-2*d]]],[0,[[1,a+b+d],[1,0]],[[1,a+c+d],[1,0]],[[1,-a-b-c-d],[1,-a-d]]]][18] os_md.mc2grs(F1,["rest0",[0,1]]); /* bry spectral types for sing. line */[[a+d,1,1,1],[0,11,11,11]][19] os_md.mc2grs("322,52,52,43","rest0"); /* all bry spectral types */[[[0,1],[a,11,11,11],[0,11111,11111,221]],[[0,2],[b,11,11,11],[0,11111,11111,221]],...
[20] os_md.mc2grs("322,52,52,43","rest1"); /* non-rigid bry spectral types */[[[0,1],[0,11111,11111,221]],[[0,2],[0,11111,11111,221]],[[0,3],[2*c,111,111,111],[0,1111,1111,211]],[[0,4],[2*d1,111,111,111]]][21] os_md.mc2grs("322,52,52,43","rest1"|dviout=1); /* non-rigid bry spectral types */132

[01] : 221, 15 , 15[02] : 221, 15 , 15[03] : 111, 111, 111 211, 14 , 14[04] : 111, 111, 111[22] os_md.mc2grs("322,52,52,43","rest0"|dviout=1);/* bry spectral type */[01] : 11, 11, 11 221, 15 , 15[02] : 11, 11, 11 221, 15 , 15[03] : 111, 111, 111 211, 14 , 14[04] : 11, 11, 11 11, 11, 11 111, 111, 111[12] : 11, 11, 11 11, 11, 11 21, 111, 111[13] : 1, 1, 1 21, 111, 111 21, 111, 111[14] : 1, 1, 1 1, 1, 1 1, 1, 1 11, 11, 11 11, 11, 11[23] : 1, 1, 1 21, 111, 111 21, 111, 111[24] : 1, 1, 1 1, 1, 1 1, 1, 1 11, 11, 11 11, 11, 11[34] : 1, 1, 1 1, 1, 1 1, 1, 1 11, 11, 11 11, 11, 11[23] os_md.mc2grs("322,52,52,43","rest"|dviout=-1); /* bry Riemann Scheme */−c − d1 − d2
c − d1−a − 2ca + b + 2c + 2d1 + d2 a + 2c + 2d1 −a − b − 2c − 2d1−c − d1 − d2
c − d1[−2c]2 a + b + 2c + 2d1 + d2
a + 2c + 2d1 [−b − 2c − 2d1 ]2 
0−a + 2c − 2d1
b + 4d1→

a + b + 4c + 4d1 + 2d2
0




−a − b − 2c − 2d1 − 2d2−a − 2d1−c − d1 − d2−c − d1−b→
a + b + 2c + 2d1 + d2 b + 2d1 −a − b − 2d1→[01] : a0[02] : b···[24] os_md.mc2grs("322,52,52,43","spct1"|dviout=1)$ /* all spectral types */
x0
x0
x1
x2
x3
x4

52
52
43
322

x1
52
322
331
22111

x2
52
322
331
22111

x3
43
331
331

x4
322
22111
22111
22111

22111

idx
2
−22
−22
−24
−48

reduction
22,22,31,22[25] os_md.mc2grs("322,52,52,43","show0"|dviout=1,fig=[6]);

133

17

17

17
[03]

[04]
17

215
[12]

[13]
7

17

1

[34]
17
[14]
17

17
[02]

[24]

[23]

22 13

17

[01]
17

22 13

17

[26] K222=os_md.mc2grs(0,["K",[2,2,2]])$[27] os_md.mc2grs(K222,"spct1"|dviout=1);
x0
x0
x1
x2
x3
x4

a2
a2
441111441111x1
a2
a2
441111441111x2
a2
a2
441111441111x3
441111441111441111x4
441111441111441111
72111

72111

idx
−8
−8
−8
−124
−124

reduction
62, 62, 414 , 414
62, 62, 414 , 414
62, 62, 414 , 414[28] os_md.mc2grs(K222,"get"|dviout=1,div=5);

A01


[0]10



[−b1 − b2 − d2 − a1 − a2 − e2 ]2

A02
[0]10
[−d2 − a1 − a2 − c1 − f1 − c2 − f2 ]2







A13
[0]4
[e2 ]4
a 1 + f1
a 1 + f2
a 2 + f1
a 2 + f2

A23
[c1 ]4[c2 ]4b1 + a 1
b1 + a 2
b2 + a 1
b2 + a 2

A14[b1 ]4[b2 ]4c1
c2
d 2 + c1
d 2 + c2

A24
[f1 ]4[f2 ]40d2
e2
d 2 + e2A03[0]4[d2 ]4b 1 + f1b 1 + f2b 2 + f1b 2 + f2

A04
[a1 ]4[a2 ]4c1
c2
e2 + c 1
e2 + c 2

A12[0]10[−b1 − b2 − e2 − c1 − f1 − c2 − f2 ]2


A34


[0]7



[−b1 − b2 − d2 − a1 − a2 − e2 − c1 − f1 − c2 − f2 ]2 
−b1 − b2 − d2 − a1 − a2 − e2−b1 − b2 − e2 − c1 − f1 − c2 − f2
−d2 − a1 − a2 − c1 − f1 − c2 − f2[29] os_md.mc2grs(K222,"show0"|dviout=1);
32 16 , 32 16 , 715 , 32 16 , 32 16 , 715 , 32 16 , 112 , 112 , 32 16 , 112 , 112 , 715 , 112 , 112[30] os_md.mc2grs(K222,"show0"|dviout=1,fig=0);01 : 23 = 32 16 , 01 : 24 = 32 16 , 01 : 34 = 715 , 02 : 13 = 32 16 , 02 : 14 = 32 16 ,02 : 34 = 715 , 03 : 12 = 32 16 , 03 : 14 = 112 , 03 : 24 = 112 , 04 : 12 = 32 16 ,04 : 13 = 112 , 04 : 23 = 112 , 12 : 34 = 715 , 13 : 24 = 112 , 14 : 23 = 112[31] I43=os_md.mc2grs(0,["I",[4,3]])$[32] os_md.mc2grs(I43,"spct1"|dviout=1);

134

x0
x0
x1
x2
x3
x4

b1
a11
3333
333111

x1
b1
444
9111
441111x2
a11
444
6111111
42222

x3
3333
9111
6111111x4
333111441111
42222
3333

3333

idx
2
2
−64
−90
−154

reduction
81, 711, 333, 33111
71, 44, 5111, 414[33] os_md.mc2grs(I43,"get"|dviout=1,div=5);

A01



[0]11



−c − b1 − b2 − d1 − d2 − d3 − a1 − a2 − e1 − e2 − a3









A13
[0]9
−c − b1 − b2 + a1 − e1 − e2−c − b1 − b2 + a2 − e1 − e2−c − b1 − b2 − e1 − e2 + a3

A23
[c]6
b1 + a 1
b1 + a 2
b1 + a 3
b2 + a 1
b2 + a 2
b2 + a 3

A14[b1 ]4[b2 ]4cc + d1c + d2c + d3A02[0]10−c + b1 − d1 − d2 − d3 − a1 − a2 − a3−c + b2 − d1 − d2 − d3 − a1 − a2 − a3A24[−c − b1 − b2 − e1 − e2 ]4[0]2[d1 ]2[d2 ]2[d3 ]2

A04[a1 ]3[a2 ]3[a3 ]3cc + e1c + e2A12[0]4[e1 ]4[e2 ]4


A34


[0]3




[e1 ]3
[e2 ]3[−c − d1 − d2 − d3 − a1 − a2 − a3 ]3 








[42] os_md.mc2grs(I43,"show0"|dviout=1);
517 , 324 1, 33 21, 715 , 32 16 , 33 13 , 112 , 112 , 24 14 , 112 , 23 16 , 112 , 33 13 , 24 14 , 112
mc2grs() を使った関数の例を挙げる．
/* KZ 方程式への拡張が同一となるリジッドスペクトル型のサーチ
S: スペクトル型 同一のものがあれば，スペクトル型の組を返す．
S: 数
S 階で 2 変数超幾何に対し，上のリストを返す．*/
def sameKZ(S){if(type(S)==1){
SS=os_md.spgen(S|eq=1,pt=4);
for(L=[];SS!=[];SS=cdr(SS))
if((TL=sameKZ(car(SS)))!=0 && TL[0]>TL[1]) L=cons(TL,L);
return L;}
S=os_md.s2sp(S|std=-1);
KZ=os_md.mc2grs(S,0);
Sp=os_md.mc2grs(KZ,"spct");for(L=[],I=1;I<5;I++){
if(Sp[I][I]==2){
for(S2=[],J=0;J<5;J++) if(I!=J) S2=cons(Sp[I][J],S2);
S2=os_md.s2sp(S2|std=-1);
if(S!=S2) L=cons(S2,L);}}
if(L==[]) return 0;for(LS=[];L!=[];L=cdr(L)) LS=cons(os_md.s2sp(car(L)),LS);
135

A03
[0]3
[d1 ]3[d2 ]3[d3 ]3LS=os_md.lsort(LS,[],"setminus");
return cons(os_md.s2sp(S),LS);}/* KZ 方程式で N 階で idx が K のものが現れるもののリストを得る */def idxKZ(K,N){
L=os_md.spgen(N|eq=1,pt=4,std=-1);
for(LL=[];L!=[];L=cdr(L)){
KZ=os_md.mc2grs(car(L),0);
Sp=os_md.mc2grs(KZ,"spct");for(I=1;I<5;I++){
if(Sp[I][I]==K){
LL=cons(os_md.s2sp(car(L)),LL);
break;}}}
return reverse(LL);}/* N 階の KZ 方程式に対し，特異超平面への制限方程式が rigid でないもののリスト */def rest1KZ(N){
L=os_md.spgen(N|eq=1,pt=4,std=-1);
for(LL=[];L!=[];L=cdr(L)){
KZ=os_md.mc2grs(car(L),0);
R=os_md.mc2grs(KZ,"rest1");
for(S=[];R!=[];R=cdr(R)){
for(T=cdr(car(R));T!=[];T=cdr(T))
S=cons(os_md.s2sp(car(T)[1]|short=1,std=-1),S);}
if(S!=[]){
S=os_md.lsort(S,[],1);
LL=cons([os_md.s2sp(car(L)|short=1),S],LL);}}
return reverse(LL);}/* 上に現れる制限方程式のみの重複を省いたリスト opt="basic" */def rest2KZ(N){F=(getopt(opt)=="basic")?1:0;
136

for(S=[],R=rest1KZ(N);R!=[];R=cdr(R)){
TR=car(R)[1];if(F==1){
T=os_md.chkspt(TR|opt="basic");
if(type(T)==4) TR=os_md.s2sp(T|short=1,std=-1);}
S=append(TR,S);
return os_md.lsort(S,[],1);}/* 上に index of rigidity の情報を入れてソート opt="basic" */def rest3KZ(N){R=rest2KZ(N|opt=getopt()));
else R=rest2KZ(N);
for(S=[];R!=[];R=cdr(R))
S=cons([os_md.chkspt(car(R)|opt="idx"),car(R)],S);
return reverse(qsort(S));}
64. newKZmat(k,l|raw=f ,base=1,ext=1):: convolution of residue matrices of KZ equation[O5] における留数行列 AI , A0J などの convolution を返す
行列 Aij を aij で表し, x0 変数での convolution を Ãij := mc
f x0 ,µ Aij とする．
• k : size of residue matrixX• l =[m1 , . . . , mk ] : Ãm1 ,...,mk :=Ãmi ,mj を返す．
1≤i<j≤k

ただし，mi =[ni,1 ,ni,2 ] としたときは，ni,1 から ni,2 までの自然数を表す（cf. lextn()）.
• l = 0 のときは，Ãi,j を成分とする (k + 1) × (k + 1) 行列を返す.
• base=1 , l =[[n1,1 , n2,1 , . . . ],. . .,[n1,k , n2,k , . . . ,]] : 指定した第 ni,j 成分のみが 1 で残りの成分が 0 の行列を返す• f = −1 : ℓ を展開したものを返す• iand(f ,1) : aij のみで表す• iand(f ,2) : a0···k = 0 の簡約化をしない• ext=1 : l =[[m1 , . . . , mk ],[m01 , . . . , m0k′ ]] とすることによりÃm1 ,...,mk ;m′1 ,...,m′k′ :=X
1≤i<j≤k′Ãmi ,mj +

k X
k
X

Ãmi ,m′j = Ãm1 ,...,mk ,m′1 ,...,m′k′ − Ãm′1 ,...,m′k′

i=1 j=1

を返す[0] A=os_md.newKZmat(4,[[0,3]])$[1] B=os_md.newKZmat(4,[[2,3]])$[2] C=os_md.newKZmat(4,[[1,2,3,4],[2],[3,4],[4]]|base=1)$[3] os_md.show([A,B,C]);[4] os_md.newKZmat(4,[0,3]);[ 0 0 0 0 ][ 0 0 0 0 ]137

[ a01 a02 mu+a03 a04 ][ 0 0 0 0 ]
µ + a0123
0


0
0

0
µ + a0123
0000µ + a0123
0

 
a04
a23
a04   0,
a04   0a123
00a023 − a02
−a02
0

0
−a03
a023 − a03
0

 
0
1
0  1,0  1
a23
1

0
1
0
0

65. midKZ(l,b|raw=1,skip=m,kill=f ,dviout=1):: KZ 方程式の留数行列の middle convolution の対角化
• l : commuting residue matrices• b : base for diagonalization• raw=1: returns matrices in Risa/Asir format• iand(kill,1) : returns only simultaneous eigenvalues• iand(kill,2) : show only transformed matrices• iand(kill,4) : short expression of commutiong matrices• skip=m : at most m sets of eigenvalues for a line
• skip=[m,1] : as above but m − 1 sets for the ﬁrst line
• dviout=1 : diplay the result• dviout=-1 : keep the result to be displayed[0] os_md.xytournament("((**)(**))",0|winner=0,team=[0,1,2,3],dviout=1);[1] os_md.midKZ([[0,1],[2,3]],[[1],[2,3],[3]]|dviout=1);
!
!
1 0 0
1 0 0
−1
U = 0 1 0 , V = U = 0 1 0 , Ã∗ → V Ã∗ U
0 1 2 30 1 1
0 −1 1!
!
µ + A01 A02 A03µ + A01 A03 + A02 A03
0
0
0
0
0
0
Ã01 =
→
0
0
0
0
0
0
!
!
A23
0
0
A23
0
0
0
−A02 + A023
−A03
0
A23 −A03
Ã23 =→
0−A02−A03 + A023
00
A023
[Ã01 : Ã23 ] = {[µ + A01 : A23 ], [0 : A23 ], [0 : A023 ]}[Ã01 : Ã23 ]|L1 = [A01 + µ : A23 ]|ker A01[Ã01 : Ã23 ]|L2 = [0 : A023 ]|ker A02[Ã01 : Ã23 ]|L3 = [0 : A023 ]|ker A03[Ã01 : Ã23 ]|L∞ = [0 : A23 ]|ker (A0∞ −µ)kill=2 :Ã01 →µ + A010
0

A03 + A02
0
0

A03
0
0

!

kill=4 :A : = [Ã01 : Ã23 ][[1], [2, 3], [3]]= {[µ + A01 : A23 ], [0 : A23 ], [0 : A023 ]}A|L1 = [A01 + µ : A23 ]|ker A01··· = ···
N=4; /* N-2=2 variables HG */T=os_md.symtournament(N|to="T");
138

0
0
1
1


0
0
0
1

for(R=KR=[],S=T;S!=[];S=cdr(S)){
for(W=1;W<=N;W++){
TR=os_md.xytournament(car(S),0|verb=5,winner=W); /* verb=4 */if(os_md.findin(TR[1],KR)>=0) continue;
R=cons(cons(car(S),TR), R);
KR=cons(TR[1],KR);}};for(S="",TR=reverse(R);TR!=[];TR=cdr(TR)){
C=car(TR);
for(P=[],TC=C[2];TC!=[];TC=cdr(TC))
P=cons(os_md.n2a([car(TC)]|verb=1),P);
S=S+"\\raisebox{-2mm}{"+os_md.xytournament(C[0],0|teams=C[1],winner=0)+"}\\qquad"+rtostr(reverse(P))+"\\qquad "+rtostr(C[3])+"\\qquad "+rtostr(C[4]);S=S+os_md.midKZ(C[2],C[3]|kill=5,skip=[3,1]); /* os_md.midKZ0(C[2],C[4]); */}dviout(S);66. mcfamily(i,j,[m1 , . . .],ℓ|mult=1,max=1,fix=[p1 , . . .],verb=1)h可換集合族の middle convolutionℓ =[ℓ1 ,ℓ2 , . . .]: 可換集合族，すなわち ℓν は要素の数が 2 個以上のリスト（length(ℓν )> 1）でℓν ∩ ℓν ′ = ∅ or ℓν ⊂ ℓν ′ or ℓν ⊃ ℓν ′ .
ここで [· · · ] は集合 {· · · } とみなしている．
i = j のときは ℓ を返すが，それ以外で返す値は ℓ0 で
j 6= "*" のときはI
pij (I) := I ∪ {i}
I \ {i}ℓi 7→ ℓ0i := [({i, j} ∩ I = ∅ or {i, j} ∩ I = {i, j}),({i, j} ∩ I = {j}),({i, j} ∩ I = {i}),[pji I],

I∈ℓi , |pji (I)|>1
0ℓ 7→ ℓ = [[i,j], ℓ01 , ℓ02 , . . . ].
j = "*" のときはpij (I) := I \ {i},ℓi 7→ ℓ0i := [[pji I],

I∈ℓi , |pji (I)|>1ℓ 7→ ℓ0 = [m \ {i}, ℓ01 , ℓ02 , . . . ].
• [m1 , . . .] は，j = "*", "+" のとき意味をもつ• 可換部分集合族 ℓ は（部分）集合の集合と見なしていて，それらはソートされている．
• 要素の重複があれば重複なしに縮約される．
•（部分）集合には，lextn() にある形式での指定が可能．
• ℓ に可換部分集合族のリスト（集合）を指定できる．
139

– このときは各可換部分集合族の変換で生じた新たな部分集合族を加えたリストを返す．
– i や j をリストとして複数のものを指定できる（複数の変換を表す）．
– ℓ = [["b"]] : Z の異なる 2 元の集合のみからなるすべての部分集合族を ℓ に設定する. ただ
し fix=[n1 , . . .] で設定したリストの 2 元からなる集合は除く．
– ℓ = [["B"]] : 上記と同じだが，∞ についても考慮する．
– mult=1 : 可換集合族の集合が安定するまで指定した（複数の）変換を施す．
– max=1 : 包含関係で他に含まれない可換集合族のみを返す（cf. lmaxsub()）[0] os_md.mcfamily(0,1,[[0,3]],[[0,2]]);[[0,1]][1] os_md.mcfamily(0,1,[[0,3]],[[1,2]]);[[0,1],[0,1,2]][2] os_md.mcfamily(0,1,[[0,3]],[[2,3]]);[[0,1],[2,3]][3] os_md.mcfamily(0,1,[[0,3]],[[2,3],[1,2,3]]);[[0,1],[2,3],[0,1,2,3]][4] os_md.mcfamily(0,1,[[0,3]],[[[2,3],[1,2,3]]]);[[[2,3],[1,2,3]],[[0,1],[2,3],[0,1,2,3]]][5] os_md.mcfamily(0,"*",[[0,3]],[[0,1,2]]);[[1,2],[1,2,3]][6] os_md.mcfamily([0,1],[0,1,2],[[0,3]],[[[2,3],[1,2,3]]]);[[[0,1],[2,3]],[[1,2],[1,2,3]],[[2,3],[1,2,3]],[[0,1],[2,3],[0,1,2,3]],[[0,2],[0,2,3],[0,1,2,3]]][7] os_md.mcfamily([],[],[[0,3]],[[["b"]]]|fix=[2,3]);[[[0,1]],[[0,2]],[[0,3]],[[1,2]],[[1,3]]][7] os_md.mcfamily([],[],[[0,3]],[[["B"]]]|fix=[2,3]);[[[0,1]],[[0,2]],[[0,3]],[[1,2]],[[1,3]],[[0,2,3],[0,1,2,3]],[[1,2,3],[0,1,2,3]]][8] os_md.mcfamily([[0,1]],[[0,3]],[[0,3]],[[[0,2]]]|verb=1);
0 1 : [[0,2]] -> [[0,1]]
0 3 : [[0,2]] -> [[0,3]]
1 0 : [[0,2]] -> [[0,1],[0,1,2]]
1 2 : [[0,2]] -> [[1,2],[0,1,2]]
1 3 : [[0,2]] -> [[0,2],[1,3]][[[0,1]],[[0,2]],[[0,3]],[[0,1],[0,1,2]],[[0,2],[1,3]],[[1,2],[0,1,2]]][9] L=os_md.mcfamily([[0,1]],[[0,3]],[[0,3]],[[[0,2]]]|verb=1,mult=1,max=1)$[10] os_md.llsymred(L,[[0,1],[2,3]]);[[[0,1],[0,1,2]],[[0,2],[1,3]],[[0,2],[0,1,2]]]
67. mcset(x,k,ℓ):: 集合の middle convolution
k, ℓ are lists regarded as ﬁnite sets
Return: [m,f ] with a sorted list m[ℓ,1]
[ℓ ∪ {x},0][m, f ] =[ℓ \ {x},0]


[ℓ,0]
140

(x ∈ ℓ ⊃ k),(x 6∈ ℓ ⊃ k),(x ∈ ℓ 6⊃ k),(x 6∈ ℓ 6⊃ k).

[0] os_md.mcset(1,[2,3],[1,2,3]);[[1,2,3],1][1] os_md.mcset(1,[2,3,4],[1,2,3]);[[2,3],0][2] os_md.mcset(3,[1,2],[0,1,2]);[[0,1,2,3],0][3] os_md.mcset(0,[0,1,2,3],[0,1,2]);[[1,2],0]68. m2mc(ℓ,[a0 ,ay ,a1 ,c]|swap=1,small=1,simplify=0,MC=1)m2mc(ℓ,s|small=1,simplify=0,int=0,swap=t)d(x−y)d(x−1)d(y−1)dy:: Pfaﬀ 形式 du = (A0 dx
x +Ay x−y +A1 x−1 +B0 y +B1 y−1 )u の x 変数での addition+middle
convolution を求める（ℓ = [A0 , Ay , A1 , B0 , B1 ]）．
ℓ がスペクトル型や Riemann scheme のとき，上の後者では s ="GRC", "GRSC", "extend", "Pfaff","sp", "pairs", "irreducible", "All", "swap"• m2mc(0,0) で使い方が簡略化して表示される．
• ℓ は [A0 , Ay , A1 , B0 , B1 ] という 5 個の正方行列のリストまたはベクトル．行列のサイスが 1 のときは，5 個のスカラーのリストまたはベクトルでもよい．A0 , Ay , A1 にそれぞれ a0 , ay , a1 による addition を施したあと，パラメータ c による middle convolution（MC=1 を指定した場合はconvolution ）を行った 5 個の行列のベクトルを返す．
addition を行わないときは，[a0 ,ay ,a1 ,c] の代わりに単に c としてよい．
addition のみのときは，c を省いて [a0 ,ay ,a1 ] と指定する.
• ℓ は x 変数のスペクトル型や Riemann scheme でもよい．スペクトル型や Riemann scheme は
x = ∞, x = 0, x = y, x = 1 の順に与える．このときは a0 や s は 0（[A0 ,Ay ,A1 ,B0 ,B1 ] を返す）または次々項に挙げる文字列とする．

• ℓ をスペクトル型で与えるときは，各特異点で重複度が大きな順に並べると結果が簡単になることが多い（オプション dep=[m,n] の項参照）．
• a0 や s が以下の文字列の場合は，特別の意味を持つ– GRS : Generalized Riemann scheme を返す．ay に "dviout" を指定できる．
– GRSC : 上と同じであるが，さらに x = y = 0, x = y = 1 の一般化特性指数も含める.
– extend：KZ 型に標準拡張した 10 個の以下の留数行列を返す．
[Ax,y , Ax,0 , Ax,1 , Ax,∞ , Ay,0 , Ay,1 , Ay,∞ , A0,1 , A0,∞ , A1,∞ ]この 10 個の行列のリストも入力の引数 ℓ に指定できる．
a0 ="extend", a1 ="eigen" とすると，各留数行列とその固有値，固有ベクトルの TEX ソー
スを返す．

– Pfaff：文字列で Pfaﬀ 形式を返す．ay に "dviout" を指定できる．
– sp : x 変数と y 変数のスペクトル型を x = y から順に表す．
– pairs, pair：可約なときの分解を与える分割を示す．
– irreducible：既約条件を与えるパラメータを示す．
– All：上の全てを指定し，さらに．a1 に "dviout" を指定したと見なされる．さらに GRSCを指定すると, GRS でなくて GRSC を指定したと見なされる．operator=0 のオプションで，
Pfaﬀ 形式の方程式を示さない．
– swap : x 変数と y 変数を入れ替えた変換結果を返す．
さらにオプション swap=t を指定すると別の変換の意味になる．
t = 1 : x 変数と y 変数の入れ替え（指定しない場合と同じ）．
t = 2 : 座標変換 (x, y) 7→ (x, xy ) を行う．
t = [t0 ,t1 ,t2 ] : (t0 , t1 , t2 ) は (0, 1, 2) の並べ替えで，0, 1, 2 は順に特異点 0, 1, ∞ を意味する．
なお, KZ 方程式に拡張した留数行列は

141

x
x
y
0
1
∞

Ax,y
Ax,0
Ax,1
Ax,∞

y
Ax,y
Ay,0
Ay,1
Ay,∞

0
Ax,0
Ay,0
A0,1
A0,∞

1
Ax,1
Ay,1
A0,1

∞
Ax,∞
Ay,∞
A0,∞
A1,∞

A1,∞



A0 = Ax,0 , A1 = Ax,1 , Ay = Ax,y ,B = A , B = A ,
0
y,0
1
y,1
A0 + A1 + Ay + B0 + B1 + A0,1 = 0,
表の各行の行列の和は 0

なお，(x0 , x1 , x2 , x3 , x4 ) = (x, y, 1, 0, ∞) という座標を用いるときは，行列で作用するベクトルの最初と次の成分を入れ替えた変換に対応する．0 と 1 は対称なので入れ替えて考えてよい．[a1 , ay , a0 , c] でaddition + middle convolution が定義される．よって

M1=os_md.m2mc([a02,a01,a03,a12,a13],[0,0,lambda,mu]);
M2=os_md.m2mc(M1,[0,0,-lambda-mu]);
M3=os_md.m2mc(M2,"extend");
MM=os_md.mperm(M3,[1,0,2],1|mult=1);
によって，Appell の F1 に対応する留数行列が得られる（cf. m2grs(), K̂xµ,λ ). K̂xµ,λ に対応）．

(

Ax,∞ = −(Ax,y + Ax,0 + Ax,1 ),A0,1 = Ax,∞ + Ay,∞ + Ax,y ,Ay,∞ = −(Ax,y + Ay,0 + Ay,1 ),A0,∞ = Ax,y + Ax,1 + Ay,1 ,A1,∞ = Ax,y + Ax,0 + Ay,0 .

また，以下のオプションがある．
• swap=1 : x と y を交換して middle convolution を行う• small=1 : TEX での行列を小さなサイズにする• simplify=0 : 対角行列による共役変換による行列の簡単化をしない• simplify=1,3 : 対角行列による共役変換による別の簡単化をする• dep=[m,n] : スペクトル型からの特性指数の自動生成で，m 番目の特異点の n 番目の特性指数をFuchs 条件から定める．デフォルトは m = 1（特異点 x = ∞）で最後の特性指数とする．
なお，x = ∞ 以外の特異点の最初の特性指数は 0 に正規化される．
• int=0 : スペクトル型からの特性指数の自動生成で，パラメータの分数倍が現れることを許す．

[0] F1=os_md.m2mc([0,0,0,0,0],[a,b,c,d]);[ [ a+d b c ][ 0 0 0 ][ 0 0 0 ] [ 0 0 0 ][ a b+d c ][ 0 0 0 ] [ 0 0 0 ][ 0 0 0 ][ a b c+d ] [ b -b 0 ][ -a a 0 ][ 0 0 0 ] [ 0 0 0 ][ 0 c -c ][ 0 -b b ] ][1] os_md.m2mc(F1,["GRS","dviout"]);x = 0
a+d

[0]2

x=y
b+d
[0]2

x=1
c+d
[0]2

y=0
a+b
[0]2

y=1
b+c
[0]2

x=∞
−a − b − c − d[−d]2[2] os_md.m2mc(F1,["Pfaff","dviout"]);

142

y=∞
−a − b − c − d[−b]2x=y=∞ [−a − b − c − d]2−b − d

((

du =

a+d b
0
0
0
0
(
b
−b
a
+ −a
0
0

)
(
c dx
0
0
+ a
0 x
0
)
(
0 dy
0
0
+ 0
0 y
0

)
(
0 d(x − y)
0
c
+ 0
x−y
0
a
)
)
0
d(y − 1)
−c
u
y−1
b

0
b+d
0
0
c
−b

0
0
b

0
0
c+d

)

d(x − 1)x−1[3] F2=os_md.m2mc(F1,[-a-d,0,0,e]);[ [ -a-d+e 0 c 0 ][ 0 -a-d+e 0 c+d ][ 0 0 0 0 ][ 0 0 0 0 ] [ 0 0 0 0 ][ 0 0 0 0 ][ (-d*a-d*b-d^2)/(c) -d b+d+e c+d ][ 0 0 0 0 ] [ 0 0 0 0 ][ 0 0 0 0 ][ 0 0 0 0 ][ (-d*b)/(c+d) (-d*a-d*c-d^2)/(c+d) (c*b)/(c+d) c+d+e ] [ a+b+d c -c 0 ][ 0 0 0 0 ][ (d*a+d*b+d^2)/(c) d -d 0 ][ 0 0 0 0 ] [ c -c 0 0 ][ -b b 0 0 ][ 0 0 c -c-d ][ 0 0 (-c*b)/(c+d) b ] ][4] os_md.m2mc(F2,["GRS","dviout"]);






x=0
[−a − d + e]2
[0]2




x=y
b+d+e
[0]3

x=1
c+d+e
[0]3

y=0
a+b
[0]3

y=1
[b + c]2[0]2x=∞[a − e]2−b − c − e−ey=∞−a − b − c − d−b − c − e[−b]2[5] os_md.m2mc(F1,[-a-d,0,0,e]|simplify=1,small=1);[ [ -a-d+e 0 1 0 ][ 0 -a-d+e 0 1 ][ 0 0 0 0 ][ 0 0 0 0 ] [ 0 0 0 0 ][ 0 0 0 0 ][ -d*a-d*b-d^2 -d b+d+e 1 ][ 0 0 0 0 ] [ 0 0 0 0 ][ 0 0 0 0 ][ 0 0 0 0 ][ -d*c*b -d*a-d*c-d^2 c*b c+d+e ] [ a+b+d 1 -1 0 ][ 0 0 0 0 ][ d*a+d*b+d^2 d -d 0 ][ 0 0 0 0 ] [ c -1 0 0 ][ -c*b b 0 0 ][ 0 0 c -1 ][ 0 0 -c*b b ] ][6] os_md.m2mc("21,21,21,21",["GRSC","dviout"]|small=1);143


x=y=∞ a−b−e[−b − c − e]3  x=0 x=y x=1

y=0
y=1
x=∞
y=∞
x=y=∞
x=y=0 x=y=1abc a+b+2d b+c+2d −a−b−c−2d1 −a−b−c−2d [−a−b−c−2d]2 [a+b+d]2 [b+c+d]2[0]2 [0]2 [0]2
[0]2
[0]2
[d]2
[−b−d]2−b00[7] os_md.m2mc(0,0)$m2mc(m,t) or m2mc(m,[t,s]) Calculation of Pfaff system of two variables
m : list of 5 residue mat. or GRS/spc for rigid 4 singular points
t : [a0,ay,a1,c], swap, GRS, GRSC, extend (eigen), sp, irreducible, pair, pairs, Pfaff, Alls : TeX, dviout, GRSC
option : swap, small, simplify, operator
Ex: m2mc("21,21,21,21","All")[8] os_md.m2mc("21,21,21,21", "All")$Riemann scheme
{

x=0
a
[0]2

x=y
b
[0]2

x=1
c
[0]2

y=0
a + b + 2d
[0]2

y=1
b + c + 2d
[0]2

x=∞
−a − b − c − 2d
[d]2

y=∞
−a − b − c − 2d[−b − d]2x=y=∞[−a − b − c − 2d]2−bSpectre types : 12,12,12,12 : 12,12,12,12
By the decompositions
21, 21, 21, 21 = 10, 10, 10, 01 ⊕ 11, 11, 11, 20= 10, 10, 01, 10 ⊕ 11, 11, 20, 11= 10, 01, 10, 10 ⊕ 11, 20, 11, 11= 01, 10, 10, 10 ⊕ 20, 11, 11, 11= 2(10, 10, 10, 10) ⊕ 01, 01, 01, 01
irreducibility ⇔ ∅ = Z∩{d, c + d, b + d, a + d, a + b + c + 2d}
The equation in a Pfaﬀ form is!
a b + d c + d dx
0
0
0
du =
x
0
0
0
!
0
0
0
d(x − y)+ a+d b c+d
x−y
0
0
0
!
0
0
0 d(x − 1)
0
0
0
+
x−1
a+d b+d c!
b+d−(b + d) 0 dya+d0
+ −(a + d)
0
0
0 y
!
!
0
0
0
d(y − 1)c+d−(c + d)+ 0uy−1
0 −(b + d)b+d
69. mcmgrs(g,r|dviout=k):: P1 内の 5 点以上の点配置に対する KZ 型方程式の同時スペクトル g の変換
KZ 型方程式で mc2grs() にある正方行列 Ai,j のインデックスが 0 から一般の N − 1 までの場合を扱

144}

う（解を多変数超幾何関数と考えたときの変数の個数は N − 2 個となる）．すなわち

∂u
=
∂xi

X
j∈{0,1,...,N −1}\{i}Ai,juxi − xj(i = 0, 1, . . . , N − 1),

Ai,i = 0, Ai,j = Aj,i , Ai,N := −(Ai,0 + Ai,1 + · · · + Ai,N −1 ),A0,i,j := A0,i + A0,j + Ai,j .
可換な組 (A0,i , Aj,k ) と (A0,i , A0,i,j ) に対する同時固有値（重複度と各固有値）のリストを g として与えることができる（i, j, k は {1, . . . , N } の中の互いに異なるインデックス）．前者は N × N −1 C2N 2 (N −1)

組のデータとなる．スペクトル型や文字列や数で g を指組，後者は N × (N − 1) 組で，合計2定した場合は, 以下のようになる．
• g が 2 以上の整数の時，自明な g 変数の超幾何に対応する同時固有値のデータを返す (N = g + 2)．
• g を，行列 A0,N , A0,1 , A0,2 , . . . , A0,N −1 のスペクトル型（文字列あるいは，4 点の GRS）で, この順で指定する．
このとき，short=0 を指定すると，インデックス付きのパラメータを使う．
r によって，以下の機能になる．
• 0 : 同時固有値のリストのリストをそのまま返す．
• ["deg"] : κ を返す（[ ] は省略可）．
• [[i,j],λ] : Ai,j 7→ Ai,j + λ, Ai,N 7→ Ai,N − λ, Aj,N 7→ Aj,N − λ という addition を返す（0 ≤ i < j < N ）．
• [µ] : x0 変数に対する middle convolution mcx0 ,µ を行う（アルゴリズムは [O5] によって与えられた）．
• [[[i1 ,j1 ],λ1 ],. . .,[µk ],. . .] : additions と middle convolutions を連続して行う．
• [[a1 ,. . .,aN −1 ]] : [[[0,1],a1 ],. . .,[[0,N-1],aN −1 ]] と同じ．
• [[a1 ,. . .,aN −1 ,µ]] : [[[0,1],a1 ],. . .,[[0,N-1],aN −1 ],[µ]] と同じ．
• ["get",[I,J]] : [AI , AJ ] = 0 に対する同時固有値を返す（ヘッダ [I, J] のついたリスト）．
• ["get",I] : AI に対する固有値を返す（ヘッダ I のついたリスト）．
• ["get",i] (0 ≤ i ≤ N ) : i ∈ I を満たす AI に対する GRS を返す（変数 xi についての常微分方
程式の GRS）．
dviout=1 を 指 定 す る と TEX を 使 っ て 表 示 す る ．dviout=-1 で は TEX の ソ ー ス を 返 す ．
dviout=2 を指定すると，TEX のソースを書き出すが表示はしない（次回の表示コマンドでまとめて表示する）．
• ["get"] : (N +1)N個全ての Ai,j の固有値のリストを返す．
2
dviout=k の指定が可能．
• ["get0",[I,J]], ["get0",I], ["get0",i] (0 ≤ i ≤ N ), ["get0"] : "get0" を "get" に変えたものと同じであるが，ヘッダはつけない．
• ["show"] : 同時スペクトルを TEX を使って表示する．
dviout=-1 の指定が可能．
2−1)• ["show0"] : N (N組の同時スペクトルの固有値の重複度を示す（順序は，"show"におけると2同じ）．
dviout=1, -1 の指定が可能．
• ["spct"] : スペクトル型を返す．(N + 1) × (N + 1) 行列で (i, j) 成分は，i 6= j のとき Ai,j のス
ペクトル型，i = j のとき xi についての index of rigidity（0 ≤ i, j ≤ N + 1）．
(N + 1) × (N + 1) 行列で (i, j) 成分は，i 6= j のとき Ai,j のスペクトル型，i = j のとき xi についての index of rigidity（0 ≤ i, j ≤ N + 1）．
dviout=k の指定が可能．
• ["mult",ℓ1 ,...,ℓm ] : g0 = g として gi = mcmgrs(gi−1 ,ℓi ) を i = 1, . . . , m に対して順に実行
して gm を返す．オプションも有効．

[0] os_md.mcmgrs("31,31,31,31,31",["get"]|dviout=1)$145

[1] os_md.mcmgrs("31,31,31,31,31",["spct"]|dviout=1)$[2] os_md.mcmgrs("31,31,31,31,31",["show"]|dviout=1)$
give
{

A01
[0]3
a

A02
[0]3
b

A23
[0]3
b + c + 2e

A03
[0]3
c

A04
A05
A12
A13
A14
A15
[0]3
[e]3
[0]3
[0]3
[0]3
[−a − e]3d −a − b − c − d − 3e a + b + 2e a + c + 2e a + d + 2e −a − b − c − d − 3e
}
A24
A25
A34
A35
A45
[0]3
[−b − e]3[0]3[−c − e]3[−d − e]3b + d + 2e −a − b − c − d − 3e c + d + 2e −a − b − c − d − 3e −a − b − c − d − 3e

x0
x0
x1
x2
x3
x4
x5

31
31
31
31
31

x1
31
31
31
31
31

x2
31
31
31
31
31

x3
31
31
31
31
31

x4
31
31
31
31
31

x5
31
31
31
31
31

idx
2
2
2
2
2
2

[A01 : A23 ] = {[a : 0], [0 : 0]2 , [0 : b + c + 2e]} ,[A01 : A24 ] = {[a : 0], [0 : 0]2 , [0 : b + d + 2e]} ,······[A01 : A012 ] = {[a : a + b + e], [0 : 0]2 , [0 : a + b + e]} ,[A01 : A013 ] = {[a : a + c + e], [0 : 0]2 , [0 : a + c + e]} ,······
70. mmc(l,[µ,a1 ,...,an ]|full=1,homog=1,mult=f ):: Schlesinger 型常微分方程式および KZ 型方程式の addition+middle convolution
Schlesinger 型方程式n
du X Aj=udx j=1 x − xj
または KZ 型方程式

∂u
=
∂xi

X
j∈{0,...,n}\{i}Ai,juxi − xj(i = 0, . . . , n)の addition または middle convolution を行う．
前 者 の 場 合 は ℓ に [A1 , . . . , An ]，後 者 の 場 合 は [A0,1 , . . . , A0,n , A1,2 , . . . , A1,n , . . . , An−1,n ]n(n+1)（ 2個の成分）を指定する．有理式のリストの場合は，1 × 1 の行列の成分が並んだリスト，と解釈される．あるいはスペクトル型や GRS を指定する（後者の場合は，変数 x0 の常微分方程式について指定する．このときはリジッドである必要がある）．
• [µ, a1 , . . . , an ] : Aj （または A0,j ）に対して aj を加えた後，x（または x0 ）変数の middle
convolution mcµ を行う，
一方のみの指定は，[a1 , . . . , an ] または [µ] とする．
• mult=f : f = 0 は Schlesinger 型，f = 1 は KZ 型を意味する．
デフォルトでは，ℓ の成分の数が 6 以上の時に KZ 型，5 以下では Schlesinger 型とみなす．また，
スペクトル型で指定したときは KZ 型とみなす．
• homog=1 : KZ 型の場合 homogeneous middle convolution を行う．すなわち，µ に対応する
middle convolution と，最後の留数行列に −µ に対応する addition を行う．

146

71. kzext([a1 , a2 , . . . , am ]|perm=σ):: KZ 方程式の全留数行列を返す
Homogenized KZ 方程式
∂u
=
∂xi

X
ν={0,...,n}\{i}Ai,j uxi − xν

はAi,j = Aj,i , Ai,i = 0, Ai,n+1 =

n
X
ν=0

(0 ≤ i ≤ n)Ai,ν ,

X

Ai,j = 00≤i<j≤nm = 21 n(n + 1) ま た は m = 21 n(n + 1) − 1 な ら ば a1 , . . . , am はA0,1 , . . . , A0,n , A1,2 , . . . , A1,n , A2,3 , . . . とみなして留数行列 Ai,j 0≤i≤n を返す.
を 満 た し て い る.

0≤j≤n

• perm=σ が指定されると [Aσ(0),σ(1) , . . . , Aσ(0),σ(n) , Aσ(1),σ(2) , . . . , Aσ(1),σ(n) , Aσ(2),σ(3) , . . . ,Aσ(n−3),σ(n) , Aσ(n−2),σ(n) ] が返される. ここで σ は 置換を表す {0, . . . , n + 1} を適当に n + 1
個の数字のリストか，互換を表す 2 つの数字のリストとする.
[0] os_md.kzext([1,2,3,4,5]);[ 0 1 2 3 -6 ][ 1 0 4 5 -10 ][ 2 4 0 -15 9 ][ 3 5 0 0 -8 ][ -6 -10 9 -8 0 ][1] os_md.kzext([1,2,3,4,5]|perm=[1,2]);[2,1,3,4,-15]
72. linfrac01(ℓ|over=1):: x = 0, 1, ∞, y, z, . . . の一次分数変換のリスト（ℓ = [x, y] etc.）ℓ = [x,y] あるいは ℓ = [x,y1 , . . . , yq ] とし，x = (x0 , x1 , . . . , xq+3 ) = (x, 0, 1, y1 , . . . , yq , ∞)（x0 = x, x1 = 0, x2 = 1, x3 = y1 , . . . , xq+2 = yq , xq+3 = ∞）と置く．
• 一次分数変換は {0, 1, . . . , q + 3} の置換に対応する（q > 1 のときは (q + 4)! 個ある．但し q = 1のときは，6 個で {1, 2, 3} の置換に対応する．cf. lft01()）ので，それらを全て得る．
• ℓ = [[x,y]] あるいは ℓ = [[x,y1 , . . . , yq ]] とすると対応する置換の組とのリストを返す．
[0] os_md.linfrac01([x]);[[x],[-x+1],[(1)/(x)],[(x-1)/(x)],[(-1)/(x-1)],[(x)/(x-1)]][1] os_md.linfrac01([[x]]);[[[x],[0,1,2,3]],[[-x+1],[0,2,1,3]],[[(1)/(x)],[0,3,2,1]],[[(x-1)/(x)],[0,2,3,1]],[[(-1)/(x-1)],[0,3,1,2]],[[(x)/(x-1)],[0,1,3,2]]][2] os_md.linfrac([x,y]);[[x,y],[y,x],[-x+1,-y+1],[(1)/(x),(1)/(y)],[(1)/(x),(y)/(x)],[(y)/(x),(1)/(x)],...
[(y*x-y)/((y-1)*x),(x-1)/(y-1)],[((y-1)*x)/(y*x-y),(y-1)/(x-1)]]
73. lft01(ℓ, t|tr=τ ):: ℓ = [x,y] または ℓ = [x,y1 ,y2 ,. . .,yq ] に対する特殊一次分数変換
x 変数での特異点は (0, 1, y1 , y2 , . . . , yq , ∞) とし，x = (x0 , x1 , . . . , xq+3 ) = (x, 0, 1, y1 , . . . , yq , ∞)（x0 = x, x1 = 0, x2 = 1, x3 = y1 , . . . , xq+2 = yq , xq+3 = ∞）とおく．

147

• KZ 型方程式
∂u
=
∂xi

X
j∈{0,...,q+2}\{i}Ai,juxi − xj

X

Ai,j = Aj,i ,(0 ≤ i ≤ q + 2),(0 ≤ i ≤ q + 3)

Ai,j = 0j∈{0,...,q+3}\{i}と，それを x1 = 0, x2 = 1 に制限した変数 (x, y1 , . . . , yq ) の方程式の変換に応用される．
• 一次分数変換は {0, 1, . . . , q + 3} の置換に対応する• t に置換 σ を指定すると，対応する一次分数変換を返す．
• σ = [σ0 , . . . , σq+3 ] とすると，特異点特異点 xi = xj は xσi = xσj に変わる. すなわち

∂u
=
∂xi
→

X
j∈{0,...,q+2}\{i}

∂u
=
∂xi

Ai,j
u
xi − xjXj∈{0,...,q+2}\{i}(0 ≤ i ≤ q + 2)
X

Ai,j
u=
xσ(i) − xσ(j)j∈{0,...,q+2}\{i}Aσ−1 (i),σ−1 (j)uxi − xj

σ は，互換 [i,j] や恒等変換を表す 1 でもよい．番号でなくて ℓ の要素と文字列 "0", "1",
"infty" から 2 つの組を指定してもよい．
• ℓ = [[x,y],1] のように指定すると，対応する置換も返す．1 でなく置換を指定できる．すなわち
os md.lft01([[x,y],1],σ ◦ σ 0 ) = os md.lft01(os md.lft01([[x,y],1],σ),σ 0 )• t が整数の時は，以下の座標変換に対応する．
(tx −t0 )(t1 −t∞ )(tx −t∞ )(t1 −t0 )(ty −t0 )(t1 −t∞ )(ty −t∞ )(t1 −t0 )

x
x
y
1−x

y

t

0<j<q

transposition

t∞

t0

t1

tx

ty

yj ↔ yj+1
x ↔ y1
0↔1
∞↔0
1↔x
0↔x
1↔y

(j + 2, j + 3)
(0,3)
(1,2)
(1, q + 3)
(0,2)
(0,1)
(2,3)

∞
∞
∞
∞
0
∞
∞
∞

0
0
0
1
∞
x
0
0

1
1
1
0
1
0
x
x

x
x
y
x
x
1
1
y

y

−j
0
1
2
3
4
5
6
7

∞ ↔ yq1↔∞(q + 2, q + 3)
(2, q + 3)

yq
1

0
0

x
∞

1
x

y

1
x
1
x
x
x−1
x
y
x(1−yq )
x−yq
x
x−1

8

x↔∞

(0, q + 3)

x

0

1

∞

y

1−x

t=0

(y1 , x, y2 , y3 , ...)

x 0 = x ↔ x 3 = y1

t = −j(x, y1 , ..., yj−1 , yj+1 , yj , yj+2 , ...)yj ↔ yj+1

t=1(1 − x, 1 − y1 , 1 − y2 , 1 − y3 , ...)

x 1 = t0 ↔ x 2 = t1

t=2(1/x, 1/y1 , 1/y2 , 1/y3 , ...)

x1 = t0 ↔ xq+3 = t∞t=3(1/x, y1 /x, y2 /x, y3 /x, ...)

x 0 = x ↔ x 2 = t1

t=4x
1 x−y2 x−y3
( x−1
, x−y
x−1 , x−1 , x−1 , ...)
x
1
2
3
( x−1
, y1y−1, y2y−1, y3y−1, ...)

x 0 = x ↔ x 1 = t0x2 = t1 ↔ xq+3 = t∞y2 (x−1) y3 (x−1)(1 − x, y(x−1)
x−y , x−y2 , x−y3 , ...)x0 = x ↔ xq+3 = t∞

t=7
t=8
t0

t∞
2

t1
1

y1

x
3

0

y2

x
y
y
y
y
1

· · · yq−2 yq−1

−1

2−q

148

1−q

yq

x
1−y
1
y
y
x
x−y
x−1
1
y

1−y

(q=1)
y
y−1
y(x−1)x−y(1 ≤ j ≤ q − 1)

x0
x

x1
4

0

x2
1

1

x3
5

y1

x4
−1

y2

x5
−2

· · · xq+1 xq+2 xq+3
1−q

y3

yq−1

yq

6

∞

[0] for(I=-1;I<9;I++) os_md.mycat([I,os_md.lft01([x,y,z],I|tr=1)]);-1 [[x,z,y],[0,1,2,4,3,5]]0 [[y,x,z],[3,1,2,0,4,5]]
1 [[-x+1,-y+1,-z+1],[0,2,1,3,4,5]]
2 [[(1)/(x),(1)/(y),(1)/(z)],[0,5,2,3,4,1]]
3 [[(1)/(x),(y)/(x),(z)/(x)],[2,1,0,3,4,5]]
4 [[(x)/(x-1),(x-y)/(x-1),(x-z)/(x-1)],[1,0,2,3,4,5]]5 [[(x)/(y),(1)/(y),(z)/(y)],[0,1,3,2,4,5]]
6 [[((-z+1)*x)/(x-z),((-z+1)*y)/(y-z),-z+1],[0,1,2,3,5,4]]
7 [[(x)/(x-1),(y)/(y-1),(z)/(z-1)],[0,1,5,3,4,2]]
8 [[-x+1,(y*x-y)/(x-y),(z*x-z)/(x-z)],[5,1,2,3,4,0]][1] os_md.lft01([[x,y],1],1);[[-x+1,-y+1],[0,2,1,3,4]][2] os_md.lft01(@@,2);[[(-1)/(x-1),(-1)/(y-1)],[0,4,1,3,2]] /* (0,1,infty) -> (∞,0,infty) */[3] os_md.lft01([x,y],@@[1]);[(-1)/(x-1),(-1)/(y-1)][4] os_md.lft01([x,y],[2,4,0,3,1]);[x,(x)/(y)][5] os_md.lft01([x,y],[1,0,4,3,2]);[x,(-x+y)/(y-1)][6] os_md.lft01([x,y],[4,2,1,3,0]);[x,((-y+1)*x)/(x-y)][7] os_md.lft01([x,y,z],[x,"0"]);[(x)/(x-1),(x-y)/(x-1),(x-z)/(x-1)]
3.1.3 Some operators
74. okubo3e([p0,1 , . . . , p0,m ],[p1,1 , . . . , p1,n ],[p2,1 , . . . , p2,m+n |opt=1]):: 0, 1, ∞ に確定特異点を持つ m + n 階の単独 Okubo 型微分作用素を求める
0で
 n 次元，1 で m 次元の正則解をもつ．Riemann scheme の記号では
0
1 · · · n − 1 p0,1 . . . . . . . . . . . . . . . . .
p0,m
0:

℘ 1:
0
1 . . . . . . . . . . . . . . . . m − 1 p1,1 · · ·
p1,n
;x


∞ : p2,1 . .P
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p 2,m+n
Fuchs の関係式 :pi,j = mn
アクセサリパラメータが (m − 1)(n − 1) 個あり，r1,r2, . . . で表される．
pi,j のうちの一つは "?" でもよい（値は Fuchs の関係式から計算される）．
• opt=1 を指定すると getbygrs() を用いる．
[0] P = os_md.okubo3e([1-e,1-f],[2-g,"?"],[a,b,c,d]);1 accessory parameters: r1,r2,...
(x^4-2*x^3+x^2)*dx^4+((a+b+c+d+6)*x^3+(-a-b-c-d-e-f-9)*x^2+(e+f+3)*x)*dx^3+(((b+c+d+3)*a+(c+d+3)*b+(d+3)*c+3*d+7)*x^2+((-b-c-d+g-3)*a+(-c-d+g-3)*b149

+(-d+g-3)*c+(g-3)*d+(-f-g-1)*e+(-g-1)*f-g^2+2*g-8)*x+(f+1)*e+f+1)*dx^2+((((c+d+1)*b+(d+1)*c+d+1)*a+((d+1)*c+d+1)*b+(d+1)*c+d+1)*x-r1)*dx+d*c*b*a[1] os_md.expat(P,x,1);[-a-b-c-d+e+f+g,-g+2,1,0]
75. fuchs3e([p0,1 , . . . , p0,n ],[p1,1 , . . . , p1,n ],[p2,1 , . . . , p2,n ]):: 
0, 1, ∞ に確定特異点を持つ n 階のFuchs 型微分作用素を求める
 0 : p0,1 p0,2 · · · p0,n
℘ 1 : p1,1 p1,2 · · · p1,n ; x∞ : p2,1 p2,2 · · · p2,nP
Fuchs の関係式 :pi,j = n(n−1)2(n−1)(n−2)
アクセサリパラメータが個あり，ri_j で表される（cf. getbygrs()）．
2pi,j のうちの一つは "?" でもよい（値は Fuchs の関係式から計算される）．
76. ghg([p1,1 , p1,2 , ..., p1,m ],[p2,1 , p2,2 , ..., p2,n ]):: 一般超幾何函数 m Fn (p1 ; p2 ; x)（cf. seriesHG()）の満たす微分作用素
d
P (x, dx
)=

n
Y

d
d
(x dx
+ p2,j ) · dx
−

m
Y

d
(x dx
+ p1,j )

j=1

j=1
∞ Qm
X
(p1,ν )n xn
Qν=1
F
(p
,
.
.
.
,
p
;
p
,
.
.
.
,
p
;
x)
=
m n 1,1
1.m 2,12,nn
ν=1 (p2,ν )n n!
n=0

変数は x，微分は dx で表記される．
m= n + 1 のときは Rigid な Fuchs 型で01 − p2,1 · · · 1 − p2,m−2
0:
℘ 1:
0
1
···
m−2

∞ : p1,1
p1,2 P . . . . . . P..........
Fuchs の関係式： γ =p1,ν − p2,νm = 2, n = 1 のときが Gauss の超幾何

1 − p2,m−1
−γ
p1,m



;x



[0] os_md.ghg([a,b],[c]);(-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-b*a
77. ghg2([a1 , a2 , . . . , b],[a01 , a02 , . . . , b0 ]|raw=1,all=1,symbol=1,var=v):: 多変数の一般化超幾何級数の微分方程式
ai are lists [ai,1 , ai,2 , . . .].
If ai is a scalar. ai is replaced by [ai ].
Q Q
QX(bk )m1 +··· m1 m2i
j (ai,j )mi
Qk 0
Q Q 0
x1 x2 · · ·u(x1 , x2 , . . .) =k (bk )m1 +···ij (ai,j )mim1 ≥0, m2 ≥0,...

Get the equation satisﬁed by this series modulo constant.
Default : (x1 , x2 , x3 , x4 ) = (x, y, z, w) if the number of variables ≤ 4.
• all=1 : get full equation• raw=1 : get reduced equation if (a01 )1 (a02 )1 · · · = 0• symbol=1 : get the generator of the symbol ideal
The equations satisﬁed by F1 (a; b, b0 ; c; x, y), F2 (a; b, b0 ; c, c0 ; x, y),
F4 (a; b; c, c0 ; x, y) are given byos md.ghg2([b,b0 ,a],[0,0,c]),os md.ghg2([b,b0 ,c],[[0,c],[0,c0 ],[]]),
os md.ghg2([[a,b],[a0 ,b0 ],[]].[0,0,c]),os md.ghg2([[],[],[a,b]],[[0,c],[0,c0 ],[]]).
150

F3 (a, a0 ; b, b0 ; c; x, y),[0] P=os_md.ghg2([b,c,a],[0,0,d]);[((-y*x+y)*dx-b*y)*dy+(-x^2+x)*dx^2+((-a-b-1)*x-d+1)*dx-b*a,(-y^2+y)*dy^2+((-y+1)*x*dx+(-a-c-1)*y-d+1)*dy-c*x*dx-c*a][1] map(os_md.psymbol,P,[[x,dx],[y,dy]]);[(-y*x+y)*dx*dy+(-x^2+x)*dx^2,(-y^2+y)*dy^2+(-y+1)*x*dx*dy]
78. even4e([p1,1 , p1,2 , p1,3 , p1,4 ],[p2,1 , p2,2 ]):: 
4 階 even family (Rigid)

0
1
p2,1
p2,2
0:

℘ 1:
0
1
p0 p0 + 1 ; x∞ : p1,1 p1,2 p1,3
p1,4
Fuchs relation : 2p0 + p1,1 + p1,2 + p1,3 + p1,4 + p2,1 + p1,2 = 3
79. odd5e([p1,1 , p1,2 , p1,3 , p1,4 , p1,5 ],[p2,1 , p2,2 ]):: 
5 階 odd family (Rigid)01
p2,1 p2,2 p2,2 + 1
0:

℘ 1:
0
1
2
p0
p0 + 1 ; x∞ : p1,1 p1,2 p1,3 p1,4 P
p1,5
Fuchs relation 2p0 + p2,1 + 2p2,2 + p1,j = 4
80. rigid211([p0,1 , p0,2 ],[p1,1 , p1,2 ],[q0 , q1 ]):: Type 211,211,211

1
p0,1 p0,2
0: 0
℘ 1: 01
p1,1 p1,2 ; x∞ : q0 q0 + 1 q1
q2
Fuchs relation : p0,1 + p0,2 + p1,1 + p1,2 + 2q0 + q1 + q2 = 4
81. extra6e([p1,1 , p1,2 , p1,3 , p1,4 , p1,5 , p1,6 ],[p2,1 , p2,2 ]):: Extra case (Rigid)01
p2,1 p2,1 + 1 p2,2 p2,2 + 1
0:

℘ 1:
0
1
2
3
p0
p0 + 1 ; x∞ : p1,1 p1,2 p1,3
p1,4
pP
p2,6
1,5
Fuchs relation : 2p0 + 2p2,1 + 2p2,2 + p1,j = 5
82. eofamily([p0,1 , p0,2 ],[p1,1 ],[p2,1 , . . . , p2,n ]):: Even/odd family (obsolete)
83. ev4s(p1 ,p2 ,p3 ,p4 ,p5 ):: Heckman-Opdam 超幾何の (BC2 , BC1 ) 型制限常微分 (Rigid)[0] P=os_md.ev4s(a,b,c,d,e);(x^4-2*x^3+x^2)*dx^4+((-2*a+2*b+8)*x^3+(4*a-2*b-13)*x^2+(-2*...
[1] os_md.expat(P,x,0);[a-c+1/2,a+c-1/2,1,0][2] os_md.expat(P,x,1);[-b+1/2,-b+3/2,1,0][3] os_md.chkexp(P,x,1,-b+1/2,2);[][4] os_md.expat(P,x,"infty");[-1/2*a+1/2*b-1/2*d+1/2,-1/2*a+1/2*b+1/2*d+1/2,-1/2*a+1/2*b-1/2*e+1/2,-1/2*a+1/2*b+1/2*e+1/2]
84. b2e(p1 ,p2 ,p3 ,p4 ,p5 )151

:: Heckman-Opdam 超幾何の (BC2 , A1 ) 型制限常微分 (Non Rigid)[0] P = os_md.b2e(a,b,c,d,e);(x^4-2*x^3+x^2)*dx^4+((-4*c+10)*x^3+(6*c-15)*x^2+(-2*c+5)*x...
[1] os_md.expat(P,x,0);[-a+c+1/2,a+c-1/2,1,0][2] os_md.expat(P,x,1);[-b+c+1/2,b+c-1/2,1,0][3] os_md.expat(P,x,"infty");[-c-1/2*d-1/2*e+1,-c-1/2*d+1/2*e+1,-c+1/2*d-1/2*e+1,-c+1/2*d+1/2*e+1]
85. heun([a, b, c, d, e],p,r|):: 
Heun の微分方程式を与える．
r はアクセサリパラメータ

0
:
0
c






1: 0 d ; x℘
Fuchs relation : a + b + 1 = c + d + ep: 0 e∞: a b[0] os_md.heun([a,b,c,d,"?"],p,r);(x^3+(-p-1)*x^2+p*x)*dx^2+((a+b+1)*x^2+((-c-d)*p-a-b+d-1)*x+c*p)*dx+b*a*x-b*a*r

3.2 Useful functions
以下の函数は module 化され，函数名の先頭に os_md. をつけて os_md.chkfun() のように呼び出す．

3.2.1 Extended function
86. myhelp(h):: os_muldif.rr のマニュアルを表示する• os_muldif.pdf, os_muldif.dvi を get_rootdir()\help に入れておく．それぞれ，h = 1, −1で表示される．

• DVIOUTH が正しく設定されていれば，myhelp("m2mc") のようにして myhelp(h) の h に函数名を文字列で入れると，その函数の解説が（os_muldif.dvi に含まれていれば）表示される．文字列 h には函数の先頭の os_md. は省略できる．
• h = 0, os_md.getbygrs, os_md.m2mc, os_md.mgen でも対応するものが表示される．
• h = [dviout, n] : dviout で dviout のパス名，n で表示する dviout の番号を設定しておく．な
お，Risa/Asir の数式などの結果の表示に最初の dviout が使われるので，n = 2 などが適当．
• 他の環境やより一般的な場合は DVIOUTH で設定する．
87. chkfun(f ,s):: 函数 f （= 文字列）が定義済みかどうか調べ，未定義なら load(s) を実行• f = 0 : Risa/Asir の version 表示• f = 1 : os_muldif.rr の version 表示• s = 0 : f が文字列の時，その函数名の函数が定義済みかどうかのみを調べる• f はモジュール化された函数には対応していない[0] os_md.chkfun(0,0)$
Risa/Asir Ver. 20121217[1] os_md.chkfun(1,0)$
Loaded os_muldif Ver. 00140401 (Toshio Oshima)152

88. isMs():: Microsoft Windows 環境かどうか調べる
環境変数 temp, tmp を調べて 3 文字目が ¥(あるいは \ ) であれば 1 を返す
89. isyes(p|set=ℓ):: 1 か 0 を返す函数を定義し，それを使う• set=1 によって定義する．このとき p は函数とそれに渡すパラメータリストと判断に使うその函数の値をチェックする範囲との 3 つからなるリスト．
すなわち p = [fn,[t1 ,t2 ,. . .],[a,b]] ならば，isyes(X|set=p) はdef foo(X){R=fn(X,t1 ,t2 ,. . .);return (R>=a && R<=b)?1:0;}という関数に対応する．

– p =[type,[],[0,1]] のときは，type(p) の値が 0 以上 1 以下の時は 1(yes) を，そうでないときは 0(no) を返す函数の定義．−∞ や ∞ は "" で表す．
– 範囲が 1 つの値ならば，その値でよい．よって [type,[],1] は [type,[],[1,1]] と同じ．
– 複数の条件を課すときは，上の 3 つ組をさらにリストにする．この場合は全てが yes のときのみ 1 を返す函数を定義する．
– p=[[os_md.isint,[],1],[os_md.calc,[[">",0]],1]]] は，正の整数のときのみ 1 を返す函数の定義．
– 新たに set=1 で定義するまでは前回の定義が有効．
• set=0 では，現在定義されているものを返す（以下の例の [11] を参照）．
• set= の右辺に上の p で与える設定を指定し，p にはその設定で判定すべきものを渡す．このときは，定義されていた設定は破壊されない．
• set= を指定しないときは，定義に従って p を判定して 1 か 0 を返す．

[0] os_md.isyes([[os_md.isint,[],1],[os_md.calc,[[">",0]],1]]|set=1)$[1] os_md.isyes(0|set=0);[[os_md.isint,[],1],[os_md.calc,[[>,0]],1]][2] os_md.isyes(3/2);
0[3] os_md.isyes(@i);
0[4] os_md.isyes(-1);
0[5] os_md.isyes(3/2);
0[6] os_md.isyes(3);1[7] A=mat([1,2],[3,4]);[ 1 2 ]
[ 3 4 ]
[8] os_md.isall(os_md.isyes,A);
1[9] A[1][1]=0$[10] os_md.isall(os_md.isyes,A);0153

[11] def isPositiveInt(X){P=os_md.isyes(0|set=0);
os_md.isyes([[os_md.isint,[],1],[os_md.calc,[[">",0]],1]]|set=1);
V=os_md.isyes(X);os_md.isyes(P|set=1);
return V;}$[12] isPositiveInt(3/2);
0
The above [11] is same as the following function
def isPositiveInt(X){return os_md.isyes(X|set=[[os_md.isint,[],1],[os_md.calc,[[">",0]],1]]);}$90. isall(f ,m):: m の要素に p 対して f (p) が 0 となるものが存在すると 0，そうでなければ 1 を返す
m がリスト，ベクトル，行列のいずれでもなければ，m を [m] で置き換えられる．
isyes() の例を参照．
[0] os_md.isall(os_md.isint,[0,2,3,1/2]);0[1] os_md.isall(os_md.isint,[0,2,3,4]);
1[3] os_md.isall(os_md.isint,[0,2,3,[1]]);0[4] os_md.isall(os_md.isint,mat([0,2,3,4]));
1
91. ptype(p,ℓ):: ℓ は変数，または変数のリストで，それのみを変数とみなした type() を返す• ptype(p,vars(p)) は type(p) と同じ．
• 有理式であって，その分母に与えられた変数の（多項式以外の）初等関数を含む場合は 128 を，分子に与えられた変数の初等関数を含む場合は 64 を戻り値に加えて返す．
[0] P=(x+y)^2/a;(x^2+2*y*x+y^2)/(a)[1] os_md.ptype(P,x);2[2] os_md.ptype(P,a);3[3] os_md.ptype(P,z);
1[4] os_md.ptype(P,[x,y]);2[5] os_md.ptype(P,[x,y,a]);3154

[6] os_md.ptype([1,2],[x,y]);4[7] os_md.ptype(sin(x)+sin(y)+@pi,x);
65[8] os_md.ptype(sin(x)+x,x);66[8] os_md.ptype(sin(x)/x,x);67[9] os_md.ptype(1/sin(x),x);129[10] os_md.ptype(sin(x)/(x+cos(x)),x);
195
92. getline(Id|Max=m,CR=[r1 ,r2 ,..],LF=[l1 ,l2 ,...]):: get line() の拡張版
ファイルから 1 行入力する（改行コードは削除）．
• m で 1 行の最大 byte 数を指定（デフォルトは 1023）• r1 , r2 ,. . . は無視するコード（デフォルトは [13]）• l1 , l2 ,. . . は行の末尾示すコード（デフォルトは [10]）93. keyin(s):: s を表示し，1 行のキー入力を待って，それを文字列として返す
行末の改行記号を削除した文字列を返す．
s の表示には mycat0() を使うので，数字やリストでも可．

[0] S=os_md.keyin("Input? ")$Input? This is a pen.
[1] S;
This is a pen.
94. showbyshell(s):: shell でコマンド s を実行した標準出力の結果を Risa/Asir で表示[0] os_md.showbyshell("echo %temp%")$[1] os_md.showbyshell("dir c:\\")$
95. getbyshell(s):: shell でコマンド s を実行した標準出力の結果をファイルとして得る• 戻り値を Id とおくと，Id ≥ 0 なら出力結果が得られたことを意味し，結果は get_line(Id) で一行ずつ文字列として読み込める．get_byte(Id) で 1 バイトずつ読み込むことも出来る．
• 最終行の後は，getline(Id) は 0 を返す．終了後は getbyshell(Id) または close_file(Id)が（少なくとも再度この函数を呼ぶ前に）必要．

• テンポラリファイルが環境変数 %temp% または %tmp% または DIROUT で定義されたディレクトリ
に作成される．前回用いられたファイルを消去してから新たにファイルが作られる.
96. fcat(f ,s|exe=1):: ファイル f に s を書き出す• ファイル f に print(s) を書き出す．ファイル f が存在していれば追記．
なお，ファイル f を削除するには remove file(f ) とすればよい．
以下では，DIROUT で設定されたディレクトリのファイルとなる．
• f = 0 : デフォルトのファイル fcat.txt に追記する．
• f = 1 : デフォルトのファイルに上書きする．
155

• f = 2, . . . , 9 : ファイル fcatf .txt に上書きする．
• f = −1 : デフォルトのファイル名を返す．
• exe=1 : 出力した後に関連づけされたプログラム（通常はエディター）に渡す．
97. makev([ℓ1 ,ℓ2 , . . . ]|num=1):: ℓ1 , ℓ2 . . . を合わせて一つの変数名を作る• ℓi には，変数，文字列，非負整数などが可能．
• 10, 11, . . . という数字は num=1 を指定しないと，a, b, . . . という文字になる．
[0] os_md.makev(["a_", 0, 1]);a_01[1] os_md.makev([a, 0, 1]);a01
[2] os_md.makev([a, 0, b]);a0b[3] os_md.makev([a, 10, b]);aab[4] os_md.makev([a,10,"_",3]|num=1);
a10_3[5] os_md.my_tex_form(@@);
a_{10,3}98. shortv(p,[v1 ,v2 , . . .]|top=w):: p の添字番号つき不定元 v1 , . . . を一文字の w 以下の変数名に変える
不定元 vi は一文字の不定元で，それに添え字番号は 0 または 1 から始まって連続している変数名の不定元に対し，w （デフォルトは a）から始まって順に使われていない変数名（z まで）に変更する．
[0] P=[a1,a2,b,c0,c1]$[1] os_md.shortv(P,[a,c]);[a,c,b,d,e][2] os_md.shortv(P,[c,a]);[d,e,b,a,c][3] os_md.shortv(P,[a,c]|top=x);[x,y,b,z,c1]
99. makenewv(ℓ|var=v,num=n):: ℓ に使われていない新しい不定元を生成する• 不定元は z_0, z_1, . . .,z_9, z_10, . . . という順で ℓ に使われていない最初のものを返す．
• 不定元のデフォルトの z_の部分は var= v と指定して v で置き換えられる．
ただし v は不定元または文字列．
• ℓ の中の関数の引数に含まれる不定元も考慮される．
• num=n で，n 個の新しい不定元のリストが得られる．
[0] os_md.makenewv(0);z_0[1] os_md.makenewv([z_0+z_1,z_2]);
z_3[2] os_md.makenewv([z_0+z_1,z_2]|var=x);x0[3] os_md.makenewv([z_0,z_1]|num=3);156

[z_2,z_3,z_4][4] os_md.makenewv(z_2*sin(cos(z_0+z_1))+z_3);
z_4100. isvar(p):: p が変数かどうか調べる
p が変数のとき 1, そうでないとき 0 を返す[0] os_md.isvar(dx);1[1] os_md.isvar(-dx);
0[2] os_md.isvar(1);0101. varargs(p|all=t):: 式 p に含まれる初等函数の函数子とその変数に現れる不定元のリストを返す• p は行列やリストでもよい．
• 現れる初等函数の函数子のリストとそれらで使われる変数のリスト．
• 函数の引数に含まれる初等函数についても考慮される．
• all=1 を指定すると含まれる全ての初等函数の函数子と全ての変数を返す．
• all=2 を指定すると含まれる全ての変数を返す．
[0] os_md.varargs(x*sin(y)+z+cos(s-t));[[sin,cos],[y,s,t]][1] os_md.varargs(x*sin(y)+z+cos(s-t)|all=1);[[sin,cos],[x,z,y,s,t]][2] os_md.varargs(x*sin(y)+z+cos(s-t)|all=2);[x,z,y,s,t][3] os_md.varargs(sin(cos(x)*sin(y)+@pi+z));[[sin,cos],[x,y,z]]102. pfargs(p,x|level=t):: 式 p に現れる x 変数を含んだ初等函数と引数のリストを返す• p は行列やリストでもよい．
• 現れる初等函数とその函数子と引数の組のリストをリストにして返す．
• 函数の引数に含まれる初等函数についても考慮される．
• level=t : t = 1 は函数の引数は無視，t = 2 では，函数の引数のみで，その深さを t で表す（デフォルトは t = 0）．
[0] os_md.pfargs(log(log(log(x))),x);[[log(log(log(x))),log,log(log(x))],[log(x),log,x],[log(log(x)),log,log(x)]][1] os_md.pfargs(sin(cos(x)*cos(y)+@pi+z),x);[[sin(z+cos(y)*cos(x)+@pi),sin,z+cos(y)*cos(x)+@pi],[cos(x),cos,x]][2] os_md.pfargs(log(log(log(x))),x|level=1);[[log(log(log(x))),log,log(log(x))]][3] os_md.pfargs(log(log(log(x))),x|level=2);[[log(log(x)),log,log(x)]][4] os_md.pfargs(log(log(log(x))),x|level=3);157

[[log(x),log,x]]103. isdif(p):: p が微分作用素と推測されるときはその変数と微分の組のリストを返し，そうでなければ 0 を返す
p が多項式または有理式であって，d で始まる変数で 2 文字目が小文字のアルファベットとなっている
ものが p に存在し，そのような変数全てに対して p が多項式になっているとき，微分作用素と推測する．
[0] os_md.isdif((x+dx+dx1+dy+dz)^2/z);[[x1,dx1],[x,dx],[y,dy],[z,dz]][1] os_md.isdif((x+dx+dx1+dy+dz)^2/dz);
0104. mysubst(r,[v1 ,r1 ]|inv=1) mysubst(r,[[v1 ,r1 ], . . . ]|inv=1)
mysubst(r,[ℓ1 ,ℓ2 ]|lpair=1,inv=1):: subst(r,v1 ,r1 , . . . ) と同等．r が複雑で r1 が有理式のときに特に有効．
• r は有理式やそれを成分とするリスト，ベクトル，行列（再帰的）とするが，subst() と異なり，文字列の成分があってもよい（文字列の成分は変換されない）．

• rj も不定元のとき inv=1 が指定可能で，逆向きの置き換え（vj と rj を取り替えた変換）を行う．
• inv=1 を指定すると，逆変換をする．
• lpair=1 を指定すると，リスト ℓ1 の各不定元を順に ℓ2 の各式に置き換える．
ただし，ℓ1 の成分の個数が 3 以上なら lpair=1 が指定されていると解釈される．
105. myswap(p,[x1 ,x2 ,. . .,xn ]):: 有理式またはそのリストなどの不定元の巡回置換 (x1 , x2 , . . . , xn )n が 2 のときは，不定元の互換．
[0] os_md.myswap([x,y,z,w],[x,y,z]);[y,z,x,w][1] os_md.myswap([x,y,z,w],[x,z]);[z,y,x,w]
106. substnum(l,s,t|depth=d):: リストまたはベクトルの成分の置き換え• s=[s1 ,s2 , . . .], s=[t1 ,t2 , . . .] のとき，ベクトルまたはリストの成分の si を ti で置き換える．ただし，si は数字あるいは数式• depth=d : 深さ d のリスト（またはベクトル）の成分を置き換える（デフォルトは d = 0）．
• depth=[d1 ,d2 , . . .] : 深さ di のリスト（またはベクトル）の成分を置き換える．
[0] L=[1,2,3,4,[3,1,2]]; U=[2,3]; V=[5,6];[1] os_md.substnum(L,U,V);[1,5,6,4,[3,1,2]][2] os_md.substnum(L,U,V|depth=1);[1,2,3,4,[6,1,5]][3] os_md.substnum(L,U,V|depth=[0,1]);[1,5,6,4,[6,1,5]]
107. mulsubst(r,[[p1,0 , p1,1 ],[p2,0 , p2,1 ], . . . ]|inv=1)
mulsubst(r,[ℓ0 ,ℓ1 ,...]|lpair=1,generate=k,short=1)
mulsubst(r,[ℓ0 ,ℓ1 ]|conj=f ) mulsubst(r,[ℓ0 ,ℓ1 ]|dform=1):: 有理式またはそのリスト，ベクトル，行列 r に複数同時の代入，有理変換の合成, Pfaﬀ 形式の有理変換• pj,0 7→ pj,1

(j = 1, 2, . . .) を同時に行う
158

• [[x,y],[y,x]] で x と y を交換．
• lpair=1 ： リスト ℓ0 の各不定元を ℓ1 の各式に同時に置き換え，その結果に対し，リスト ℓ0 の各不定元を ℓ2 の各式で同時に置き換える，と続けて最終結果を返す．ℓ2 =[ℓ2,0 ,ℓ2,1 ] などとすると，
リスト ℓ2,0 の各不定元を ℓ2,1 の各式で同時に置き換える, という指定になる．
• generate=k ： これらの置き換えの合成で生成されるものと生成手順の組のリストを返す（生成されるものを全て，あるいは |k| 個を超える程度まで）．|k| = 1 のときは，|k| = 160 を指定したと解釈される．
r に ℓj を施していくことによって生成されるが，k > 0 のとき，生成手順はその番号を並べて表される．一方，k < 0 のときは，生成された m 番目のものに ℓj を施したものであれば，[j,m] と表される．
• conjugate=1 : 指定すると，[ℓ0 ,ℓ2 ] を有理変換 s とみなして，s ◦ r ◦ s−1 を返す．
• conjugate=-1 : 指定すると，[ℓ0 ,ℓ2 ] を有理変換 s とみなして，s−1 ◦ r ◦ s を返す．

[0] os_md.mulsubst(x+y^2+z^3,[[x,y],[y,x]]);x^2+y+z^3[1] os_md.mysubst(x+y^2+z^3,[[x,y],[y,x]]);x^2+x+z^3[2] os_md.mysubst(["top",x,y],[x,2]);[top,2,y][3] subst(["top",x,y],[x,2]);
subst : invalid argument
return to toplevel[4] os_md.mulsubst([x,y,z],[x,w]);[w,y,z][5] os_md.mulsubst([x,y,z],[x,w]|inv=1);[x,y,z][6] os_md.mulsubst([x,y,z],[[x,y,z],[y,x,z],[x,z,y]]|generate=1);[[[x,y,z],[y,x,z],[x,z,y],[y,z,x],[z,x,y],[z,y,x]],[[],[1],[2],[1,2],[2,1],[1,2,1]]][7] os_md.mulsubst([x,y,z],[[x,y,z],[y,x,z],[x,z,y]]|generate=-1);[[[x,y,z],[y,x,z],[x,z,y],[y,z,x],[z,x,y],[z,y,x]],[[0],[1,0],[2,0],[1,2],[2,1],[1,4]]][8] os_md.mulsubst([x,z,y],[[x,y,z],[y,z,x]]|conj=1);[z,y,x][9] os_md.mulsubst([x,z,y],[[x,y,z],[y,z,x]]|conj=-1);[y,x,z]108. fmult(f ,m,ℓ,n| · · · ):: mi 7→ mi+1 = f (mi ,ℓ[i],n[0], n[1], . . . | · · · ) という変換（m0 = m）の最終結果 mlength(l) を返す• ℓ と n はリスト．
• オプション指定はそのまま渡される．
109. mtransbys(f ,m,ℓ| · · · ):: スカラーに関する変換 f () をリスト，ベクトルまたは行列 m に拡張する• m の各成分 mν を f (mν , l[0], l[1], . . .|· · · ) と変換する．
• リスト，ベクトルまたは行列はネストしていてもよい（行列のリストなど）．
• 引数はリスト ℓ にしてまとめる．
• オプション指定はそのまま渡される．

159

• map(f ,m,l[0], . . . ) と同じだが，map() はネストやオプション指定が不可．
[0] A=newmat(2,2,[[(x^2-y^2)/(x+y),x/y],[yx/x^2,(x^2-y^2)/(x-y)]]);[ (x^2-y^2)/(x+y) (x)/(y) ][ (y*x)/(x^2) (x^2-y^2)/(x-y) ][1] os_md.mtransbys(red,A,[]);[ x-y (x)/(y) ][ (y)/(x) x+y ][3] os_md.mtransbys(os_md.abs,[[1,-2],[3,-4]],[]);[[1,2],[3,4]][4] map(os_md.abs,[[1,-2],[3,-4]]);[[1,-2],[3,-4]]110. mmulbys(f ,m,n,ℓ| · · · ):: 和が定義された objects の 2 つに対して 1 つの object を与える演算 f を，objects を成分とするベクトルまたは行列 m と n の演算に拡張する• 引数はリスト ℓ にしてまとめる．m は object または行列．
• mと n が行列のときは以下の行列を返す．
P

f
(m
,
n
,
ℓ[0],
ℓ[1],
.
.
.)
i,ν
ν,j
ν
i,j

• m または n がスカラーのときは，他方（の成分）にそのスカラーを掛けた結果を返す．
• m がベクトルのときは行ベクトル，n がベクトルのときは列ベクトルとみなし，同様の計算をして（上で，i または j のインデックスがないと考える），結果をベクトルで返す．
ただし m と n が共に（同じサイズの）ベクトルのときは，結果はスカラーで返す．
• オプション指定はそのまま渡される．
111. cmpsimple(p,q|comp=t):: 式 p と q の簡単さを比較
p の方が q より簡単な場合負の整数を，逆の場合正の整数を返す．
iand(t,1)!=0 のときは変数の個数を，iand(t, 2)!=0 のとき単項式の個数を，iand(t, 4)!=0 のときは表示の長さを基準に，最後に P と Q の大小関係を，この順で比較し，差があった時点で簡単とみなす．デフォルトは，t = 7．
[0] os_md.cmpsimple((x+y)^2,(x+1)^3|comp=1); /* 変数の個数 */1[1] os_md.cmpsimple((x+y)^2,(x+1)^3|comp=2); /* 単項式の個数 */-1[2] os_md.cmpsimple((x+y+z)^2,(sin(x)+cos(x))^2)|comp=4); /* 表示の長さ */-4/* 表示の長さの差 */[3] os_md.cmpsimple(1,-1);-1/* 表示の長さの差 */[4] os_md.cmpsimple(4,2);
1/* 大小比較 */112. simplify(p,ℓ,t|var=[x1 , x2 , . . . ]):: ℓ の一次関係式を使って p を簡単化
• ℓ = [ℓ0 , ℓ1 ] のときは p（の各要素毎）に subst(*, ℓ0 , ℓ1 ) を調べてより簡単なら置き換える（t = 1 ∼ 7）．
• ℓ = [ℓ1 ] で ℓ1 が多項式のときは，ℓ1 に一次に含まれる含まれる変数の線形関係式とみて簡単化

160

する．

• 複数調べるときは ℓ をリストや多項式のリストとする．
• iand(t,1)!=0 のときは変数の個数を，iand(t, 2)!=0 のとき単項式の個数を，iand(t, 4)!=0 のときは表示の長さを基準に，この順で比較し，差があった時点で簡単とみなす．
• この比較で等しいときは，両者を直接比べて小さい方とする．
• 複数の置き換えを試すときは，ℓ = [[ℓ00 , ℓ01 ], [ℓ10 , ℓ11 ], . . .] とする．
• var=[x1 , x2 , . . . ] を指定すると，p を x1 , x2 , . . . の有理式とみて，その分母分子の多項式の係数毎に単純化する．

[0] os_md.simplify([x+y+z+a+b,x+z+a+b],[a,-x-y-w/2-c],1);[z-1/2*w+b-c,x+z+a+b][1] os_md.simplify([x+y+z+a+b,x+z+a+b],[a,-x-y-w/2-c],4);[x+y+z+a+b,x+z+a+b][1] os_md.simplify(x+3*y+4*z,[x+y+z],1);
2*y+3*z[2] os_md.simplify(x+3*y+4*z,[x+y+z],4);-3*x-y113. getel(m,i):: m がリスト，ベクトル，行列で i が非負整数なら m[i] を返す
i が [i1 , i2 ] というリストで m が行列ならば m[i1 ][i2 ] を返す
それ以外では m をそのまま返す
114. evalred(r|opt=[[s1 ,t1 ],[s2 ,t2 ]...]):: sin(0), cos(0), exp(0) などを 0, 1, 1 などの整数に置き換える• 置き換えは，以下のものの値
sin(k@pi), cos(k@pi) で値が 0, ±1, ± 12 のいずれかになるもの，tan(0), asin(0), atan(0),sinh(0), cosh(0), tanh(0), exp(0), log(1), pow(1,x), 1^x• sj を tj で置き換える（j = 1, 2, . . .），という規則を付加する．付加する規則が 1 つのみのときは
opt=[s,t] としてもよい．
[0] evalred(exp(sin(0)));1[1] eval(exp(sin(0)));1.0000000000000000000000000000[2] os_md.evalred(exp(sin(@pi)));1[3] eval(exp(sin(@pi)));1.0000000000000000000000000000
115. evals(r|del=s,raw=1):: 文字列あるいは函数を評価する．
• r が文字列のときは，eval_str(s) を返す．さらに del=s が指定されたときは，文字列 s を区切り記号として区切られた文字列を評価して，順にリストとして返す．ただし，raw=1 が指定してあると，評価せずに文字列のリストに分割して返す．

• r がリスト [r0 ,r1 , . . .] のとき，r0 が文字列でなければ r0 を函数とみなして
r0 (r1 ,r2 , . . .) を返す．
r0 が文字列の時も同様なものを返す．引数 r1 , . . . の中に文字列があれば，それは eval_str() に
よって得られる値として変換される（execproc() も似た機能の函数）．
[0] os_md.evals("(x+1)^2");161

x^2+2*x+1[1] os_md.evals("(x+y)^2,2^3,10/20"|del=",");[x^2+2*y*x+y^2,8,1/2][2] os_md.evals("(x+y)^2,2^3,10/20"|del=",",raw=1);[(x+y)^2,2^3,10/20][3] os_md.evals([dexp,1]);
2.71828[4] os_md.evals(["pari","gamma",3+@i]);(0.96286515302378809804+1.33909717605325744298*@i)116. myeval([r,[x1 ,f1 ,v1 ],[x2 ,f2 ,v2 ],. . .]):: os_md.myeval(subst([r,[x2 ,f2 ,v2 ],. . .],x1 ,f1 (os_md.myeval(v1 )))) を返す
os_myeval([r])=map(eval(r))
117. mydeval([r,[x1 ,f1 ,v1 ],[x2 ,f2 ,v2 ],. . .]):: os_md.mydeval(subst([r,[x2 ,f2 ,v2 ],. . .],x1 ,f1 (os_md.mydeval(v1 )))) を返す
os_md.mydeval([r])=map(deval(r))• r は有理式成分のベクトルや行列やリストなどでもよい．
• 引数が多項式や有理式 r のときは，eval(r) または deval(r) に置き換えられる．
• 引数がベクトルや行列 r のときは，map(eval,r) または map(deval,r) に置き換えられる．
• v1 , v2 , . . . は，数でなくてそれぞれ myeval() で値が求まるものでもよい（ネスティング可能で，合成函数に対応する）．

• 函数 f1 , . . . は，dsin などの函数のほか，引数を数とし，数を返す函数で（ユーザが定義したもの
で）もよい．より一般に定義されたものが解釈可能であればよい．
• f1 = 0 のときは，恒等写像と解釈される．
• 函数 f1 の引数が複数あるときは [x1 ,f1 ,v1,1 ,v1,2 , . . .] と指定すると f1 (os_md.myeval(v1 )) は

f1 (os_md.myeval(v1,1 ),os_md.myeval(v1,2 ),. . .)• v1 , v2 , . . . や v1,1 , v1,2 , . . . がリストのときは，それらを [v1 ], [v1,2 ] のように指定する（mydeval()や myeval()でなくて deval() や eval() で評価される）．
• 函数 f1 にオプションパラメータを付加して用いるときは，f1 の代わりに [f1 ,opt] のように函数とそのオプションリストの組のリストとして指定する．ただし opt は [[s1 ,v1 ],[s2 ,v2 ],. . .]] の形で，sj はオプション文字列，vj はその値である（getopt() で得られる形式）．
• f2 以下についても同様．
• F=sin(x)$for(I=V=0;I<1000;I++) V+=deval(subst(F,x,I/1000));とすると不定元が 1000 個定義され，以降も含めて Risa/Asir の動作が遅くなるが
F=[y,[y,dsin,x]]$for(I=V=0;I<1000;I++) V+=os_md.myeval(subst(F,x,I/1000));とすればそのような不定元の生成が起こらない．これはより簡明に

F=f2df(sin(x))$for(I=V=0;I<1000;I++) V+=os_md.myfeval(F,I/1000));とすればよい（cf. f2df(), myfeval()）• 函数がこの引数の形に変換されたものは，xygraph() や xy2graph() でサポートされている．
[0] F=os_md.f2df(exp(-x^2-y^2));[z__,[z__,dexp,-x^2-y^2]][1] for(V=I=0;I<1000;I++) for(J=0;J<1000;J++)V+=os_md.mydeval(subst(F,x,I/1000,y,J/1000));[2] V/1000^2;
0.558218

162

[3] F=[w,[z,0,x+y*@i],[w,os_md.abs,z^2+1]]$[4] os_md.myeval(subst(F,x,1,y,1));
2.23606797749978969619[5] def mkC(X,Y){return X+Y*@i;}[6] G=[w,[z,mkC,x,y],[w,os_md.abs,z^2+1]]$[7] os_md.myeval(subst(G,x,1,y,1));
2.23606797749978969619
118. myval([r,[x1 ,f1 ,v1 ],[x2 ,f2 ,v2 ],. . .]):: myeval() と同様な函数であるが，可能な限り正確な値を返す• 三角関数は，その引数が r*@pi で 4r または 6r が整数のときに正確な値を返す．
• 指数関数は，その引数が整数または指数または r*@i*@pi で 4r または 6r が整数のときに正確な値を返す．
• 対数関数は，その引数が@e または 1 のとき正確な値を返す．
• べき函数 xy において，x が 0 または 1 あるいは y が整数のとき，あるいは y = 12 で x が有理数のときは正確な値を返す．
• 実数の絶対値は正確な値を返す．√√• 正確な戻り値には，有理数の他， −1, m（m は正整数）が含まれることがある．

[0] os_md.myval(sin(@pi));0[1] os_md.myval(sin(@pi/6));
1/2[2] deval(sin(@pi/6));
0.5[3] eval(sin(@pi/6));
0.49999999999999999991[4] os_md.myval(4^sin(@pi/6));2[5] os_md.myval(2^exp(@pi*@i));
1/2[6] os_md.myval(sin(@pi/3));
1/2*((3)^(1/2))[7] os_md.myval(2*exp(@pi/3*@i));(1*@i)*((3)^(1/2))+1[8] eval(@@);(1+1.73205080756887729346530507834*@i)[9] os_md.myval((2/3)^sin(@pi/6));
1/3*((6)^(1/2))[10] os_md.myval(os_md.abs(1-2^(1/2)));((2)^(1/2))-1[11] os_md.myval((2^(1/2))^(-2)+(3^(3/2))+sin(@pi/6));
3*((3)^(1/2))+1

163

以上は，次のような正確な値を得ている．

sin π = 0,
2 exp π3 i = 1 +π√4sin 6 = 2,3i,π

( 23 )sin 6 =

√

6
3 ,

2exp πi = 12 ,√√1 − 2 = 2 − 1.

119. f2df(f |opt=n):: 函数 f から sin などの函数子を除いて myeval() や mydeval() の引数のリスト形式函数に変換• 函数子 sin,cos,tan,asin,acos,atan,asin,acos,sinh,cosh,tanh,exp,log,pow を含んだ函数，および xy の形のべきの函数を含んだ函数から，それらを除いたリスト形式函数に変換する．
• f は有理式のほか，有理式成分のベクトルや行列でもよい．
• opt=1,3 : map(eval,f ) に対して変換を行う（@pi や cos(0) などが含まれている場合の効率化）
opt=-1,-3 : map(deval,f ) に対して変換を行う
opt=-3,2,3 : f がリストの場合も変換を行う（通常は変換せずに返す）[0] os_md.f2df(exp(-x^2-y^2));[z__,[z__,os_md.myexp,-x^2-y^2]][1] os_md.f2df(x^(y+1));[z__,[z__,os_md.mypow,x,y+1]][2] os_md.f2df(x^0.5);[z__,[z__,dsqrt,x]][3] os_md.f2df(exp(-x)*(sin(x)+cos(y)));[(z__1+z__2)*z__,[z__,os_md.myexp,-x],[z__1,os_md.mysin,x],[z__2,os_md.mycos,y]][4] os_md.f2df(exp(t*sin(x)+cos(y)));[z__,[z__,dexp,[z1__*t+z1__1,[z1__,dsin,x],[z1__1,dcos,y]]]][5] os_md.f2df(exp(t*sin(x)+cos(y))/(sin(x)+2));[(z__1)/(z__+2),[z__,os_md.mysin,x],[z__1,os_md.myexp,[z__*t+z1__,[z1__,
os_md.mycos,y]]]][6] os_md.f2df(tanh(x));[z__,[z__,0,(z__1^2-1)/(z__1^2+1)],[z__1,os_md.myexp,x]][7] os_md.f2df(exp(x+y^2*@pi));[z__,[z__,os_md.myexp,x+@pi*y^2]][8] os_md.f2df(exp(x+y^2*@pi)|opt=1);[z__,[z__,os_md.myexp,x+3.14159265358979323829*y^2]][9] os_md.f2df(exp(x+y^2*@pi)|opt=-1);[1*z__,[z__,os_md.myexp,1*x+3.14159*y^2]][10] M=mat([cos(x),sin(x)],[-sin(x),cos(x)]);[ cos(x) sin(x) ][ -sin(x) cos(x) ][11] F=os_md.f2df(M);[[ z__1 z__ ][ -z__ z__1 ],[z__,os_md.mysin,x],[z__1,os_md.mycos,x]][12] os_md.myeval(subst(F,x,0));[ 1 0 ]
[ 0 1 ]
120. todf(f ,[v1 ,. . .,vn ]) todf([f ,[ops]],[v1 ,. . .,vn ]):: 函数子 f で変数が v1 , . . . , vn のリスト形式函数を得る（n は f の引数の数）164• [ops] は f に渡すオプションリスト（getopt() で得られる形式）．
• n = 1 で v1 がリストでないときは，[v1 ,. . .,vn ] は単に v1 としていしてもよい．
• vj は数値，不定元，有理式，リスト形式函数など
√√ f2df() で解釈できる函数でよい．
以下では z , 2 exp x2 , ζ( 12 + −1x), ζ( 12 + −1x) に対応するリスト形式函数を得ている．
[0] os_md.todf(os_md.abs,z);[z_0,[z_0,os_md.abs,z]][1] os_md.abs(z);[z_0,[z_0,os_md.abs,z]][2] os_md.todf(floor,2*exp(x/2));[z_0,[z_0,floor,[2*z__,[z__,os_md.myexp,1/2*x]]]][3] os_md.todf(os_md.zeta,1/2+x*@i)[z_0,[z_0,os_md.zeta,(1*@i)*x+1/2]][4] F=os_md.abs(os_md.zeta(1/2+x*@i));[z_1,[z_1,os_md.abs,[z_0,[z_0,os_md.zeta,(1*@i)*x+1/2]]]][5] os_md.myfeval(F,98.831194218);
0.00000000068100083539303687859
121. df2big(f |inv=1):: リスト形式函数 f を倍精度浮動小数点計算から bigfloat 計算へ変更する• sin, cos, tan, asin, acos, atan, exp, log に対応．
• inv=1 の指定は逆変換を意味する．
[0] F=os_md.f2df(sin(x));[z__,[z__,os_md.mysin,x]][1] F=os_md.df2big(F);[z__,[z__,sin,x]][2] F=os_md.df2big(F|inv=1);[z__,[z__,os_md.mysin,x]]122. compdf(f ,x,g) compdf(f ,[x1 ,x2 , . . .],[g1 ,g2 , . . .]):: リスト形式函数 f の変数 x にリスト形式函数 g を代入したリスト形式函数を返す• f は多項式や有理函数でもよい．たとえばリスト形式函数 f と g に対して f · g を得るにはcompdf(x*y,[x,y],[f ,g]) とすればよい．
• f や g は f2df() で解釈可能な式でもよい．
• f が文字列のときは，|p|, [p], abs(p), floor(p), rint(p), zeta(p), gamma(p), arg(p),real(p), imag(p), conj(p) が可能．ただし p は f2df() で解釈可能な式．なお (p) を略した場
合は (x) を指定したとみなす．
• 変数 x1 , x2 , . . . にそれぞれリスト形式函数 g1 , g2 , . . . を代入するときは，x = [x1 , x2 , . . .],g = [g1 , g2 , . . .] とすればよい．
[0] Sin_x=os_md.f2df(sin(x))$[1] Exp_x=os_md.f2df(exp(x))$[2] ExpSin_x=os_md.compdf(Exp_x,x,Sin_x)$[3] os_md.myfeval(ExpSin_x,0);
1[4] os_md.compdf("|2*sin(x^2)|",x,x);[z__,[z__,os_md.abs,[2*z__,[z__,os_md.mysin,x^2]]]]123. cutf(f ,x,[[x1 ,v1 ],[x2 ,v2 ],...,[xn ,vn ]])165

cutf(f ,x,[t,[x1 ,v1 ],...,[xn ,vn ]]):: 函数 f の変数が特定の範囲のとき函数値の変更を行い，その値またはリスト形式函数を返す• 第 3 引数のリストの個数 n は 2 以上で，x1 ≤ x2 < x2 < · · · < xn−1 ≤ xn を満たす必要がある．
• x < x1 の場合は v1 を返す，v1 は（リスト形式函数）でもよい（myfeval(v1 ,x) を返す）．
第 3 引数の最初の要素が [] のときは，その項は無視される．
• x > xn の場合は vn を返す．第 3 引数の最後の要素が [] のときは，その項は無視される．
• 1 < j < n で x = xj のときは vj を返す．vj はリスト形式函数でもよい．
• 上記以外の時は f (x) を返す．
• f の 変 数 が x で な い と き は ，そ れ を 第 3 引 数 の 最 初 の 要 素 と し て 指 定 す る ．た と え ば[t,[x1 ,v1 ],. . .] などとする．
• 2 番目の引数が不定元のときは，その不定元を変数とするリスト形式函数にして返す．
[0] os_md.cutf(1/x,3,[[-1,0],[0,0],[1,0]]);0[1] os_md.cutf(1/x,0.5,[[-1,0],[0,0],[1,0]]);2[3] os_md.cutf(1/x,0,[[-1,0],[0,0],[1,0]]);0[4] F=os_md.f2df(sin(x)/x)$[5] os_md.cutf(F,1.5,[[],[0,1],[]]);
0.664997[6] os_md.cutf(F,0,[[],[0,1],[]]);
1[7] os_md.cutf(1,-2,[[0,-1],[0,0],[]]);-1[8] os_md.cutf(1,0,[[0,-1],[0,0],[]]);
0[9] os_md.cutf(1,0.5,[[0,-1],[0,0],[]]);
1[10] os_md.cutf(x/y,0.5,[y,[-1,0],[0,0],[1,0]]);2*x[11] F=os_md.cutf(sin(x)/x,x,[[],[0,1],[]]);/* x=0 のとき 1 と拡張した函数 */[z_0,[z_0,os_md.cutf,[(sin(z_1))/(z_1)],x,[[z_1,[],[0,1],[]]]]][12] os_md.myfdeval(F,0);1[13] os_md.myfdeval(F,1)-dsin(1);0124. periodicf(f ,[a,b],x) periodicf(ltov([g1 ,g2 ,...,gn ]),c,x):: x を変数とする函数 f |[a,b) を周期関数に拡張した函数にする• x − k(b − a) の値 y が a ≤ y < b となる整数 k を選んで f (y) を返す．
• [ xc ] − kn の値が 0 以上 n 未満の数となる整数 k と，x − (kn + ℓ)c の値 y が 0 以上 c 未満にある ℓを選んで gℓ+1 (y) を返す．
gk は数値，あるいは（リスト形式）函数．
• x が不定元のとき，x を変数とする上のようなリスト形式函数にして返す．
[0] os_md.periodicf(x^2,[-1,1],0.2);
0.04

166

[1] os_md.periodicf(x^2,[-1,1],1.2);
0.64[2] os_md.periodicf(x^2,[-1,1],2.2);
0.04[3] F=os_md.periodicf(x^2,[-1,1],x)$[4] os_md.myfeval(F,2.2);
0.04[5] os_md.periodicf(ltov([1,2,3,4]),1,2);
3[6] G=os_md.periodicf(ltov([1,2,3,4]),1,x)$[7] os_md.myfeval(G,2.2);
3[7] os_md.myfeval(G,4);
1[8] G=os_md.periodicf(ltov([x,1-x,-x,x-1]),1,x);[z_1,[z_1,os_md.periodicf,[[ z_0 -z_0+1 -z_0 z_0-1 ]],1,[[z_0,x]]]]125. cmpf([f ,[a,b]]|exp=c)
cmpf(x):: 積分区間をコンパクト閉区間 [0, 1] に直した函数にする
Z b
Z 1• [f ,[a,b]] によってf (x)dx =g(x)dx となる函数 g(x) を定義し，それをリスト形式函数a0として返す．
新たな定義をするまでは，cmpf(x) は g(x) を返す．
• a ="-infty"は a = −∞ を，b ="infty"は b = ∞ を意味し，無限区間の積分を有限区間の積分に変換する．なお，"-infty"，"infty"は任意の文字列でよい．
• exp のオプションを指定しない場合は以下で c = −1 とする．
exp=c と負数 c を指定した場合も含めて
xf (a+ C(1−x))(C = |c|C(1−x)24 ).
1)f (b+1− Cx|c|[−∞,b] で b が有限のときは g(x) =(C = 4 ).
Cx2
1
1
1
1
[−∞,∞] のときは g(x) = ( C(1−x)
2 + Cx2 )f ( C(1−x) − Cx )[a,∞] で a が有限のときは g(x) =• exp=c と正数 c を指定すると

x
1−x

e
e
[a,∞] で a が有限のときは g(x) = C(1−x)
2 f(x
1−x −1

1− 1

C

+ a)

1

x
[−∞,b] で b が有限のときは g(x) = eCx2x f ( 1−e
+ b)
C
1
1
1
1

e 1−x
e 1−x −e xex)[−∞,∞] のときは g(x) = Cx2 + C(1−x)2 f (C• f はリスト形式函数でもよい．
• cmpf([1/(1+x^2),["",""]]) で得られる関数は

g(x) = cmpf(x) =2
2x2 −2x+1

2(C = 2|c|)(C = 6c ).

(C = 6c ).
(C = 12c).

x ∈ [0, 1],x∈/ [0, 1].

• areabezier() で使われている（例にあるグラフを参照）．
126. myfeval(f ,x) (f ,a) myfeval(f ,[x,a]) myfeval(f ,[[x1 ,a1 ],. . .])127. myfdeval(f ,a) myfdeval(f ,[x,a]) myfdeval(f ,[[x1 ,a1 ],. . .]):: myeval() や mydeval() の引数のリスト形式函数 f の変数に a を代入して値を得る• f の変数がデフォルトの x でなくて v のときは x を [v,x] とする．
• f の複数の変数に代入するときは第 2 引数を [[x,0.5],[y,3]] などのようにする．
128. myf2eval(f ,x,y)167

129. myf2deval(f ,x,y):: myeval() や mydeval() の引数のリスト形式 2 変数函数 f に代入して値を得る
130. myf3eval(f ,x,y,z)131. myf3deval(f ,x,y,z):: myeval() や mydeval() の引数のリスト形式 3 変数函数 f に代入して値を得る• 1 変数関数 f は変数 x，2 変数関数 f は変数 x, y，3 変数函数 f は変数 x, y, z を用いて表す．
• myfeval(f ,x) と myeval(mysubst(f ,[x,x])) と は 同 等 で あ る ．同 様 に myf2eval(f ,x,y)と myeval(mysubst(f ,[[x,x],[y,y]])) と は 同 等 で あ り ，さ ら に myf3eval(f ,x,y,z) とmyeval(subst(f ,[[x,x],[y,y],[z,z]])) は同等である（eval を deval に置き換えたものも同様）．

• myf2eval(f ,a,b) は myfeval(f ,[[x,a],[y,b]]) と同等である．
[0] F=[[xx,yy],[xx,dcos,x],[yy,dsin,x]]$[1] os_md.myfdeval(F,0);[1,0][2] os_md.myfdeval(F,@pi/3);[0.5,0.866025]
上は[3] os_md.mydeval(subst(F,x,@pi/3));[0.5,0.866025][4] def afo(X){ return [dcos(X),dsin(X)];}[5] afo(deval(@pi/3));[0.5,0.866025]などと同様な結果を得る．

132. execproc(ℓ|all=1,var=k):: リスト形式手続きの実行
リスト形式手続きとは，函数，引数リスト，オプションリストの 3 つ組のリストを並べたリスト．
すなわち ℓ=[ℓ1 ,ℓ2 ,· · · ] で，ℓj =[fj ,vj ,pj ] となっているとき call(fj ,vj |option list=pj ) を j =1, 2, . . . と実行する．
• オプションがない場合は，略して ℓj =[fj ,vj ] としてよい．
• 最後の函数の戻り値が返される．
• 不定元 v1, v2,. . .,vk は特別の意味を持ち，それぞれ直前，2 つ前 , . . . , k 個前の函数の実行結果の戻り値で置き換えられる．
• 上において，k = 2 がデフォルトであるが，var=k によって変更できる．
• all=1 : これを指定すると，全ての函数の実行結果の戻り値が返される（最後の実行結果の戻り値を先頭とするリスト）．
• evals() も似た機能の函数で，pari() も扱える．

[1] L=[[os_md.binom,[x,2]],[os_md.binom,[v1,2]]]$[2] os_md.execproc(subst(L,x,6)|all=1);[105,15]133. fsum(f ,[m,n,d]|df=1,subst=1) fsum(f ,[x,m,n,d]|df=1,subst=1)
P[ m−n ]:: 一般項が f (x) で与えられる級数の和 k=0d f (m + kd) を返す• f の変数がデフォルトの x のときは，変数 x の指定は不要．
• d が指定されていないときは，d = 1 と解釈される．
• df=1 が指定されていると，f を f2df(f ) に置き換えてから処理する．

168

• subst=1 が指定されていると，単純な代入で処理する（たとえば，sin(0.5) なども実数に変えない）．
[1] os_md.fsum(x,[1,10]);55[2] os_md.fsum(x^y,[y,0,5]);x^5+x^4+x^3+x^2+x+1[3] os_md.fsum(x^y,[y,0,5,2]);x^4+x^2+1[4] P=eval(@pi);
3.14159265358979[5] s_md.fsum(sin(x)/10000,[0,P,P/10000]|df=1)*P;
1.99999998355037[6] An=2*((x)^(2*n-1))/(2*n-1)$/* term */[7] Un=2*x^(2*n+1)/(2*n+1)/(1-x^2)$ /* error */[8] P4=os_md.fsum(An,[n,1,4,1]|subst=1);
2/7*x^7+2/5*x^5+2/3*x^3+2*x/* log((1+x)/(1-x)) */[9] os_md.fctrtos(@@|dviout=1,var=x,rev=1,small=1);
2x + 23 x3 + 25 x5 + 27 x7[10] subst(P4,x,1/3);/* log 2 */53056/76545[11] deval(@@);
0.693135[12] deval(log(2));
0.693147[13] deval(subst(Un,x,1/3,n,4));
1.27013e-005[14] P5=os_md.fsum(An,[n,1,5,1]|subst=1)$[15] subst(P5,x,1/3);
4297606/6200145[17] deval(@@);
0.693146[18] deval(subst(Un,x,1/3,n,5));
1.15467e-006
参照：base sum()134. fint(f ,n,[t1 ,t2 ]]|cpx=1,exp=c,int=k,prec=v,Acc=1) fint(f ,n,ℓ|· · · ):: 複素積分を含む数値積分• f は披積分函数で，第 3 引数は積分範囲を表す．
• n は分割の数であるが，積分範囲の外でも f が定義されているときは −n を与えると精度が上がる
ことが多い．

• n = 0 は，n = 32 と解釈される．
実変数の積分
• 実変数函数 f のとき，デフォルトの変数は x で，n は分割の数，[t1 ,t2 ] は積分区間を表す．
• 積分区間で，t1 ="-" は −∞ を，t2 ="+" は +∞ を表す．
• 変数が x でなくて t のとき，積分区間と合わせて第 3 引数に [t,t1 ,t2 ] と指定する．
• 実変数関数 f が複素数値のとき，cpx=1 を指定する（たとえば 1/(x^2+@i) のとき）.

169

複素積分
• 複素積分のとき，函数 f の変数は x, y, z を使うことができる（同時使用可）．
なお，x は複素変数 z の実部，y は虚部を表す．
• 積分路は，積分路の実部，虚部を表す函数の組と積分区間とのリスト ℓ で表す．函数のパラメータは t とする．たとえば[[(cos(t),sin(t)],[0,2*@pi]]
は単位円を表す．
• 積分路の曲線を表す函数は微分可能な函数でなければならないが，それらの合併でもよい．各曲線毎にリストにする．たとえば[ [[t,0],[-1,1]], [[(cos(t),sin(t)],[0,2*@pi]] ]は単位円の上半平面の部分の周を表す曲線• 折線を積分路とする場合は，通過点の座標を指定する．たとえば[[1,-1],[1,1],[1,-1],[-1,-1],[1,-1]]• 始点に戻る閉曲線の場合は，最後に -1 と指定すればよい．上の長方形の周は[[1,-1],[1,1],[1,-1],[-1,-1],-1]
としてもよい．
オプション• デフォルトではベジェ曲線で積分を近似するが– int=-1 を指定すると，|n| 分割し，分割の中点での値の平均を使って近似計算する． sinx x の[0, 2π] での積分などに便利（端点の値は使わない）．
– int=1 を指定すると，|n| 分割して台形公式で近似計算する．
– int=2 を指定すると，|n| 分割してシンプソンの公式で近似計算する．このとき，n が奇数な
ら |n| + 1 分割する．
– int=3 を指定すると，2k (1 ≤ k ≤ n）分割の台形公式をもとに n 段の Romberg 積分で近似計算する．
– int=4 を指定すると，2k (1 ≤ k ≤ n）分割の中点での値の平均をもとに n 段の Romberg 積
分で近似計算する．
• 積分変数を t とすると，無限区間での積分において無限遠で o(|t|−2 )（有理函数のときは O(|t|−2 )）を満たさないと誤差が大きくなるので，prec=16 または exp=1 などと指定すると改善されることが多い．
• 函数に滑らかでない点や不連続点がある場合は，prec=16 などと指定すると計算誤差が少なくなる．
• Acc=1 を指定すると pari() による高精度計算を行う.
ただし ctrl("bigfloat",1) および setprec(prec) による精度の設定が必要．また，有理関数
でなくて sin(x) などの初等関数を扱う場合は注意が必要で，不定元が大量に生成される可能性がある（myeval() の項を参照．ord() で分かる）．
以下の [0], [1], [2], [3] はそれぞれ次の積分を表す．

Z ∞

dx
= π,
2
−∞ x + 1

Z ∞

√

√
2 dx
√
= π − π −1,2−1−∞ x +Z√dz= π −1,|z|=1 2z[0] os_md.fint(1/(x^2+1),32,["-","+"]);
3.14159[1] os_md.fint(dsqrt(2)/(x^2+@i),96,["-","+"]|cpx=1);(3.1416-3.14158*@i)[2] os_md.fint(1/(2*z),-96,[[cos(t),sin(t)],[0,2*@pi]]);(3.14159*@i)[3] os_md.fint(exp(1/z)/2,-96,[[cos(t),sin(t)],[0,2*@pi]]);(-4.96894e-016+3.14159*@i)
170

Z

√
ez
dz = π −1.
|z|=1 2
1

[4] ctrl("bigfloat",1)$setprec(50)$[5] os_md.fint(1/(1+x),8,[1,2]|Acc=1,int=3,prec=50)-eval(log(3/2));[6] 2.497013766866152101658619415891179242698342742134e-23

Bézier 曲線を使った数値積分の相対誤差
非積分関数

積分範囲

指定

16 分割

32 分割

96 分割

384 分割1536 分割1x2 +1−∞ < x < ∞(n, −)

1.3 × 10−5

1.3 × 10−7

8.5 × 10−10

4.7 × 10−12

2.1 × 10−14

1√x2 + −1−∞ < x < ∞(n, −)

2.3 × 10−3

1.7 × 10−4

2.6 × 10−6

1.9 × 10−8

8.1 × 10−111z|z| = 1(−n, −)

7.6 × 10−5

4.1 × 10−6

4.8 × 10−8

1.9 × 10−10

7.3 × 10−13e135. fimag(f ,x|inv=g):: 複素変数の指数関数を実変数の関数に変換[1] os_md.fimag(exp(r+x*@i));(1*@i)*exp(r)*sin(x)+exp(r)*cos(x)[2] os_md.fimag(2^(r+x*@i));((2)^(r))*cos(log(2)*x)+(1*@i)*((2)^(r))*sin(log(2)*x)
136. trig2exp(f ,x|inv=g):: 三角関数と指数関数の変換と簡単化• デフォルトでは，三角函数を複素変数の指数函数で置き換え，指数関数の積は一つにまとめる．
• inv=1 : 複素変数の指数函数の虚部は，三角函数を使って実変数の函数に置き換える．
三角関数の積は，三角関数の和にまとめられる．
• inv=sin(y), inv=cos(y)，inv=tan(y) : x が trig2exp( ) の第 2 引数のとき，sin x またはcos x または tan x の有理式に可能な限り直す（y = x のとき）．
より一般に inv=sin(ax + b), inv=cos(ax + b) のように，y は第 2 変数 x の 1 次式でもよい（たとえば，inv=cos(x/2), inv=sin(x+@pi/3) など）．
• 合成函数の変数中の三角関数や指数関数は変更されない．

[0] os_md.trig2exp(sin(x),x);(-1/2*@i)*exp((1*@i)*x)+(1/2*@i)*exp((-1*@i)*x)[1] os_md.trig2exp(@@,x|inv=1);
sin(x)[2] os_md.trig2exp(16*sin(x)^5,x|inv=1);
sin(5*x)+10*sin(x)-5*sin(3*x)[3] os_md.trig2exp(4*cos(x)^2*exp(x)^2,x);2*exp(2*x)+exp((2-2*@i)*x)+exp((2+2*@i)*x)[4] os_md.trig2exp(4*x*sin(x)^2*cos(x),x|inv=1);(cos(x)-cos(3*x))*x[5] os_md.trig2exp(sin(5*x),x|inv=sin(x));
16*sin(x)^5-20*sin(x)^3+5sin(x)[6] os_md.trig2exp(cos(x+y),x|inv=cos(x));
cos(y)*cos(x)-sin(x)*sin(y)[7] os_md.trig2exp(cos(2*x+y),x|inv=cos(x));-2*sin(y)*cos(x)*sin(x)+2*cos(y)*cos(x)^2-cos(y)[8] os_md.trig2exp(cos(2*x+y),x|inv=sin(x));-2*cos(y)*sin(x)^2-2*sin(y)*cos(x)*sin(x)+cos(y)[9] os_md.trig2exp(cos(2*x+3*@pi/2),x|inv=cos(x));

171

2*sin(x)*cos(x)[10] os_md.trig2exp(2*cos(2*x+@pi/6),x|inv=cos(x));
2*((3)^(1/2))*cos(x)^2-sin(x)*cos(x)-((3)^(1/2))[11] os_md.trig2exp(cos(x),x|inv=cos(x/3));
4*cos(1/3*x)^3-3*cos(1/3*x)[12] os_md.trig2exp(2*cos(x),x|inv=cos(x+@pi/3));cos(x+1/3*@pi)+sin(x+1/3*@pi)*((3)^(1/2))[13] os_md.trig2exp(tan(3*x),x|inv=tan(x));(tan(x)^3-3*tan(x))/(3*tan(x)^2-1)
上は以下の等式を示している

sin x = − 2i exp(xi) + 2i exp(−xi),
4 cos2 x · exp2 x = 2 exp 2x + exp (2 − 2i)x + exp (2 + 2i)x .
inv=1 を指定した上の例は
16 sin5 x = sin 5x − 5 sin 3x + 10 sin x,
4x sin2 x · cos x = x(cos x − cos 3x).
inv=sin(x) または inv=cos(x) を指定した上の例は
sin 5x = 16 sin5 x − 20 sin3 x + 5 sin x,cos(x + y) = cos x · cos y − sin x · sin y,cos(2x + y) = −2 sin y · cos x · sin x + 2 cos y · cos2 x − cos y= −2 cos y · sin2 x − 2 sin y · cos x · sin x + cos y,cos(2x + π2 ) = −2 sin x · cos x,√√
2 cos(2x + π6 ) = 2 3 cos2 x − sin x · cos x − 3.
inv=cos(x/3) を指定すると
cos x = 4 cos3 x3 − 3 cos x3 .
inv=cos(x+@pi/3) を指定すると
2 cos x = cos(x + π3 ) +√3 sin(x + π3 ).

inv=tan(x) を指定すると
tan 3x =tan3 x − 3 tan x.
3 tan2 x − 1

137. isshortneg(f ):: f と −f を表現する文字列の長さの比較−f の表示文字列の長さが f の表示文字列の長さより短いかどうか判定する．
[0]
1

os_md.isshortneg(x-(x-1)^2);

138. fshorter(f ,x):: x の三角関数の簡単化
172• 三角関数の有理函数を自動的に簡単化する．
• 現れる三角関数の変数の比は有理数になっている必要がある．
[0] os_md.fshorter(8*sin(x)^4-8*sin(x)^2+sin(x)+1,x);
sin(x)+cos(4*x)[1] os_md.fshorter((sin(x)-3*sin(3*x))/(3*cos(x)+cos(3*x)),x);tan(x)^3-2*tan(x)[2] os_md.fshorter((1-cos(2*x))/(1+cos(2*x)),x);tan(x)^2
139. fzero(f ,[x,x1 ,x2 ]|mesh=m,dev=d,zero=1,trans=1,cont=1):: 実数値函数 f の零点を求める• 函数 f は myeval() の引数の形でもよい．
• x は変数で，区間 [x1 , x2 ] での零点を求める．
変数 x がデフォルトの x のときはそれを省略して，二番目の引数は [x1 ,x2 ] でよい．
• 戻り値は，零点の近似値とそこでの f の値の組のリスト• f が多項式や有理式のときは分子の多項式の零点を調べる．その次数が 2 以下の時は根の公式を，
それ以上の次数の時は polroots() を使う．
• mesh=m : 区間を m 等分してその小区間の両端で f の符号が変わるときに，その間の零点をひとつずつ求める．デフォルトは m = 1024.
• dev=d : 小区間の両端の値で函数のグラフを線分で近似したときの零点または両端の中点での函数の値を順に調べて（前者は奇数回目，後者は偶数回目）零点の近似計算をするが，その繰り返しの最大回数．デフォルトは d = 16.
• zero=1 : 区間 [x1 , x2 ] の両端で f の符号が変わるときに，その間の零点をひとつ求める．
• trans=1 : myeval() で値が計算できる函数であることを示す（設定しなくてもよい）．
• cont=1 : f が連続関数であることを示す（設定しなくてもよい）．

[0] os_md.fzero(3-x^2,[-2.0,2.0]);[[-1.73205,-4.44089e-016],[1.73205,-4.44089e-016]][1] os_md.fzero(exp(x)*sin(x)-cos(x),[0.0,10.0]);[[0.531391,1.11022e-016],[3.18303,-4.44089e-016],[6.28505,3.28626e-013],[9.42486,1.23013e-011]][2] os_md.fzero(2/x-x,[-1.0,10.0]);[[1.41421,3.14018e-016]]
140. fmmx(f ,[x,x1 ,x2 ]|mesh=m,dev=d,mmx=1,zero=1,trans=1,cont=1,dif=1):: 実数値函数 f の極値を求める• 函数 f は myeval() の引数の形でもよい．
• x は変数で，区間 [x1 , x2 ] での極値を求める．
変数 x がデフォルトの x のときはそれを省略して，二番目の引数は [x1 ,x2 ] でよい．
• 戻り値は，極値をとる x の近似値とそこでの f の値の組のリスト• mmx=1 : 極値でなくて最大値と最小値を求める．
[[xmin ,f (xmin )],[xmax ,f (xmax )]] が戻り値で，f (xmin ) が最小値，f (xmax ) が最大値．
• mesh=m : 区間を m 等分してその隣接した 2 つの小区間の隣接点での函数の値が両端での値の間にないときその間の極値をひとつずつ求める．デフォルトは m = 1024.
• dev=d : 上で調べる隣接区間をそれぞれ 2 等分してできる 3 組の隣接小区間を順に調べて，極値のある隣接小区間を選ぶ，ということの繰り返しの最大回数．デフォルトは d = 16.
• dif=1 : f が微分できる函数のとき，f 0 の零点を極値を取る点とみなす• dif=g : 函数 g の零点を極値を取る点とみなす• zero=1 : dif を指定したとき，区間の両端で f 0 （または g ）の符号が変わるときに，その間の f 0173

（または g ）の零点のひとつを極値をとる点とする．
• cont=1 : dif を指定したとき，f が連続関数であることを示す（設定しなくてもよい）．
• trans=1 : myeval() で値が計算できる函数であることを示す（設定しなくてもよい）．

[0] os_md.fmmx(sin(x),[0.0,6.0]);[[0,0],[1.5708,1],[4.71239,-1],[6,-0.279415]][1] os_md.fmmx(sin(x),[0.0,6.0]|mmx=1);[[4.71239,-1],[1.5708,1]][2] os_md.fmmx(cos(x),[0.0,6.0]|dif=1);[[0,1],[3.14159,-1],[6,0.96017]]
141. flim(f ,v|prec=c,init=t):: 変数 x の実数値関数 f の極限値を求める• 戻り値は極限値．ただし空文字列は極限値なし，あるいは判定できないこと，また"+", "-"はそれ
ぞれ +∞, −∞ を表す．
• v = a : lim f (x)x→a• v = ["+",a] :• v = ["-",a] :lim f (x)x→a+0

lim f (x)x→a−0

• v = "+" : lim f (x)x→∞• v = "-" :lim f (x)x→−∞

• prec=c : c は −1 以上 30 以下の数で，c を増やすと極限値の正確性が増す（c = 0 がデフォルト）．
• f (x) のとる値の範囲を，v = ["+",a] のときは，[a + 8−k−1 , a + 8−k ] で，v = "+" のときは[8k , 8k+1 ] で，k = 4, 5, . . . , 12 に対して fmmx( |mmx=1,mesh=16,dev=4) で得て，それによって極限の存在を判定している．
• init=t : t は正の実数で，デフォルトと比べて v に t 倍近い値に限って調べる．

[0] os_md.flim(sin(x)/x,0);1[1] os_md.flim(sin(x)/x,"+");
0[2] os_md.flim((1+2*x^2)/(x+x^2),"+");
2[3] os_md.flim((1+x^4)/(1-x),"+");
142. fcont(f ,[x,x1 ,x2 ]|mesh=m,dev=d,zero=1,trans=1,dif=1) ?
:: 実数値函数 f の不連続点や滑らかでない点を求める• 函数 f は myeval() の引数の形でもよい．
• x は変数で，区間 [x1 , x2 ] での極値を求める．
変数 x がデフォルトの x のときはそれを省略して，二番目の引数は [x1 ,x2 ] でよい．
• 戻り値は，特異点を鋏む区間とその 2 点でのギャップの組のリスト
143. fresidue(p,q|cond=[f1 ,f2 ,. . .],sum=1):: 多項式 q を分母とする有理式 p/q の特異点と留数の組のリスト（z が変数で，p は正則函数）• f1 , . . . は z, x, y を変数とする函数で（z=x+yi）これらが全て正となる留数のみを選ぶ• sum=1 : 条件を満たす留数の和を得る• sum=2 : 条件を満たす留数の和の 2πi 倍を得る（複素積分の計算に用いる）[0] os_md.fresidue(z^2,(z^2+1)^2);174[[(1*@i),(-1/4*@i)],[(-1*@i),(1/4*@i)]][1] os_md.fresidue(16,z^4+4);[[(-1+1*@i),(1-1*@i)],[(-1-1*@i),(1+1*@i)],[(1+1*@i),(-1-1*@i)],[(1-1*@i),(-1+1*@i)]][2] os_md.fresidue(16,z^4+4|cond=[y]);[[(-1+1*@i),(1-1*@i)],[(1+1*@i),(-1-1*@i)]][3] os_md.fresidue(16,z^4+4|cond=[y],sum=1);(-2*@i)[4] os_md.fresidue(16,z^4+4|cond=[y],sum=2);
4*@pi[5] os_md.fresidue(3*z^4,z^6+1|cond=[y],sum=2);
2*@pi[6] os_md.fresidue(3*z,z^3+@i|cond=[y],sum=2);
2*@pi[7] os_md.fresidue(@e^(@i*z*xi),z^2+1|cond=[y],sum=2);((@e)^(-xi))*@pi[4], [5], [6], [7]（ξ ≥ 0）は，留数計算により以下の積分計算を得ている．
Z ∞16dx = 4π,
4+4
x
−∞

Z ∞

3x4
dx = 2π,6−∞ x + 1

Z ∞3x√ dx = 2π,
3+
x
−1
−∞

Z ∞

eixξ
dx = e−ξ π.
2−∞ x + 1

3.2.2 Numbers
144. abs(p) abs([p,prec]):: 整数または実数または複素数 p の絶対値を返す• p が複素数のとき [p,prec] として prec で精度の桁数を指定できる．
• 不定変数を引数とすると対応するリスト形式函数が得られる
145. sgn(n|val=1):: 数 n または置換 n の符号を返す• n が数の時は，正負に応じて 1, 0, −1 を返す．
• n がリストまたはベクトルの時，小さい順に並んだものとの転倒数が偶のとき 1, 奇のとき −1 を返す．

val=1 を指定すると，転倒数を返す．
[0] os_md.sgn(-1.2);-1[1] os_md.sgn(4/3);
1[2] os_md.sgn([4,3,2,1]);
1[3] os_md.sgn([4,3,2,1]|val=1);6146. calc(p, [s, q]) calc(p, s):: 数や有理式などあるいはそれらを成分とするリストやベクトルの成分に対して演算を施す
前者は s="+", "-", "*", "/", "^", ">", "<", "=", ">=", "<=", "!="，後者は s="abs","neg", "sqr", "inv", "sgn" が有効．

175

[0] os_md.calc(x,["-",y]);x-y[1] os_md.calc(3,["^",4]);
81[2] os_md.calc(x/y,"inv");(y)/(x)[3] os_md.calc([3,-3,0,2],"sgn");[1,-1,0,1][4] os_md.calc([2,3,1,0],["+",1]);[3,4,2,1][5] os_md.calc([3,-3,0,2],["^",2]);[9,9,0,4][6] os_md.calc([2,3,1,0],[">",1]);[1,1,0,0]147. isint(p):: p が整数かどうか調べる
p が整数の時 1, そうでないとき 0 を返す
148. israt(p):: p が有理数かどうか調べる
p が有理数の時 1, そうでないとき 0 を返す
149. iscrat(p):: p が数でその実部と虚部が共に有理数かどうか調べる
p の実部と虚部が共に有理数の数の時 1, そうでないとき 0 を返す
150. isalpha(n):: 整数 n がアルファベットの文字コードかどうか調べる[0] strtoascii("1")[0];49[1] os_md.isalpha(49);0[2] os_md.isalpha(strtoascii("a")[0]);1151. isnum(n):: 整数 n が数字 0〜9 の文字コードかどうか調べる
152. isalphanum(n):: 整数 n がアルファベットまたは数字の文字コードかどうか調べる
153. isdecimal(s):: 文字列 s が整数または小数を表しているかどうか調べる• s が文字列でないときは 0 を返す．
• 前後の空白文字列は無視して判定する．
[0] os_md.isdecimal("0");1[2] os_md.isdecimal(" -2.5 ");1[3] os_md.isdecimal(" -2.5/2 ");176

0[4] os_md.isdecimal(-2.5);0154. catalan(n):: Catalan 数などの場合の数を返す• n が自然数のときは，Catalan 数 Cn を返す．
Cn は，凸 (n + 2) 角形を対角線によって三角形分割する場合の数（cf. pg2tg()）
n=5または，x-y 平面の点 (−n, 0) から点 (n, 0) まで，上方または右方に x 座標またはy 座標が整数で，x − y ≥ n を満たすように進む道筋の場合の数
このとき，上方を 0, 下方を 1 で表して左から読むと，0 と 1 をそれぞれ n 個並べて，どこから見てもその左側にある 0 の個数が 1 の個数より小さくはない，とい0011001011
う並べ方の個数（n 次の許容 01 列と呼ぶことにする）• n =[m,k] とすると，x-y 平面の点 (−n, 0) から点 (m, 0) まで，上方または右方に x 座標またはy 座標が整数で，x − y ≥ n を満たすように進む道筋の場合の数• n =[1,m,k] のときは, 第 1 種 Stirling 数 [ mk ] を返す．
• n =[2,m,k] のときは, 第 2 種 Stirling 数 { mk } を返す．
• n =["P",m,k] または，[m,"P",k] のときは, m Pk を返す．
n ="mPk"のように 1 つの文字列で指定してもよい．以下も同様．
• n =["C",m,k] のときは, m Ck を返す．
• n =["H",m,k] のときは, m Hk を返す．
•
• n =["!",n] のときは, n! を返す．
• n =["!!",n] のときは, n!! を返す．
• n =["B",n] のときは, ベルヌーイ数 Bn を返す．
• n =["p",n] のときは, 分割数 p(n) を返す．
オプション all=1 を指定すると，Bn 以下のベルヌーイ数 B0 , B1 , B2 , B4 , B6 , . . . のベクトルを返す．

• n ="?" のときは，Help メッセージを示す．
[0] os_md.catalan(4);14[1] os_md.catalan([5,4]);42[2] os_md.catalan([1,5,3]);35[3] os_md.catalan([2,5,3]);25[4] os_md.catalan(["P",5,3]);60[5] os_md.catalan([5,"P",3]);60[6] os_md.catalan(["5P3"]);60[7] os_md.catalan(["5 P 3"]);60[8] os_md.catalan(["5C3"]);10177

[9] os_md.catalan(["H",5,3]);35[10] os_md.catalan(["6!"]);
720[11] os_md.catalan(["6!!"]);
48[12] os_md.catalan(["!!",5]);
15[13] os_md.catalan(["p",10]);42[14] os_md.catalan(["B",10]);
5/66[15] os_md.catalan(["B",16]|all=1);[ -1/2 1/6 -1/30 1/42 -1/30 5/66 -691/2730 7/6 -3617/510 ]155. getCatalan(k,n|opt=1,to=f ):: Catalan 数と許容 01 列，トーナメント表，凸多角形の三角形分割，番号付け，などの間の変換
n 次の許容 01 列の個数は Catalan 数 Cn で与えられるが，それを 2 進数と見たときの大きい方から k
番目を返す（最初は 0 番目とする）．
• n 次の許容 01 列とは，0 と 1 を n 個ずつ一列に並べた列で，先頭から途中までみたとき 1 の個数
が 0 の個数を決して超えないもののこと（01 を横に並べたとき，左端を先頭とする）．
原点から右上（0 に対応）または右下（1 に対応）に格子点（座標が整数の点）を y 座標が非負の部分を進んでいき，(2n, 0) に到達する道筋と対応する．
• n 次の許容 01 列は，先頭に 01 を付加することによって個数 n + 1 の許容 01 列に埋め込める．これにより，n は無限大と見なしてよい（このときは，n = 0 とする）．
• 逆に，n 次の許容 01 列を与えると，それが何番目かを返す（n は無視される）．
• opt=1 ：並べ方の順序を許容 01 列の帰納的構成順に考えたものを返す（対応する多角形の三角形
分割の大小関係順）• to= のオプションで得られる任意の出力形式（相互の自然な対応については [O9]）は k で指定でき
る．新たに指定した to= で，他の形式に変換できる．k が非負整数以外の時は，n は無視される．
• トーナメント表は (*) の 3 文字によって"((**)(**))"のように表せるが，入力では間に空白を入れてもよい．
正しいトーナメント表かどうかは istournament() でチェックできる．
• to="01" : 許容 01 列をリストで返す（デフォルト）• to="s" ：許容 01 列を文字列で返す• to="T" : (n + 1) チームのトーナメント表を返す．k は番号でも n 次の許容 01 列でも凸 (n + 2)角形の三角形分割でもよい．
• to="#" : 凸 (n + 2) 角形の三角形分割に使われる各頂点を端点とする対角線の本数の表（(n + 2)
ベクトル）
• to="P" : 凸 (n + 2) 角形の三角形分割に使われる対角線のリスト

n 次許容 01 列 L の 2 種の順序関係• デフォルト：2 進表記とみて大きな数が先• もう一方（opt=1）：先頭（1 個目）より後で，そこより前の 0 と 1 の数が等しくなる最初の位置を
2k 個目とし（1 ≤ k ≤ n），そこまでで切って，前の k 次許容 01 列 L1 とそれより後の (n − k) 次
許容 01 列 L2 に分割する．L0 を L1 の先頭の 0 と末尾の 1 を削った (k − 1) 次許容 01 列とする．
（a）k が小さい方が先とする（b）k が同じときは，L0 で先になるかどうかを決める（次数が少ないので既に順序は決まってる）（c）L0 が同じときは，L2 で先になるかどうかを決める（次数が少ないので既に順序は決まってる）

178

• どちらも先頭は 0101 · · · 01 で末尾は 00 · · · 011 · · · 100101011 < 00011101 デフォルトの順序
00101011 > 00011101 もう一方の順序（k が前者は 4, 後者は 3）• どちらも，先頭に 01 を付加することで (n + 1) 次許容 01 列に埋め込むことによって, n = ∞ と考
えて順序が決まる．（このときは，引数では n = 0 とする．実現可能な最小の n が用いられる）
3 次許容 01 列の例 : 001011

a1% % & % & &

•

•

•

•

•

•

2

•

3

1

4

(1 ( (2 3) 4))a3
a4% a2 % a2 & (a2 a3 ) % (a2 a3 ) & ((a2 a3 )a4 ) &→ a1 → a1 →
a1 →
a1
→
a1
→ (a1 ((a2 a3 )a4 ))(*((**)*))

これは，スタック式計算機の仕組みに対応する．
五角形の頂点の番号を 0〜4 とし，k と (k − 1) をつなぐ辺を k と番号づける．上の三角形分割は，対角線を両端の 2 頂点の番号で表すと [[1,3],[1,4]] で与えられる．
凸 (n + 2) 多角形の三角形分割に対し，頂点 k と (k − 1) をつなぐ辺を k 番目のチームと考える（k = 1, . . . , n + 1）．分割する対角線の端点のない頂点を挟む 2 チームが試合をし，その頂点を通る 2
辺を消すと，その 2 辺の両端を結ぶ対角線が辺となる凸多角形ができる．その辺に勝ったチームに対応させる．この操作を続ければ，(n + 1) チームのトーナメント戦が定まる．1 番と (n + 1) 番のチームが対戦する可能性があるのは決勝戦のみ．
これらの対応について，より詳しくは [O8] を参照．

[0] for(I=os_md.catalan(4)-1;I>=0;I--) print(os_md.getCatalan(I,4));[0,0,0,0,1,1,1,1][0,0,0,1,0,1,1,1][0,0,0,1,1,0,1,1][0,0,0,1,1,1,0,1][0,0,1,0,0,1,1,1][0,0,1,0,1,0,1,1][0,0,1,0,1,1,0,1][0,0,1,1,0,0,1,1][0,0,1,1,0,1,0,1][0,1,0,0,0,1,1,1][0,1,0,0,1,0,1,1][0,1,0,0,1,1,0,1][0,1,0,1,0,0,1,1][0,1,0,1,0,1,0,1][1] os_md.getCatalan([0,1,0,1,0,0,1,1],0);1[2] os_md.getCatalan(1,4|to="s");01010011[3] os_md.getCatalan(1,4|to="P");[[0,2],[0,3],[3,5]][4] os_md.getCatalan(1,4|to="T");(((**)*)(**))[5] os_md.getCatalan(1,4|to="#");[ 2 0 1 2 0 1 ]179

[6] os_md.getCatalan(@@,4|to="P");[[0,2],[0,3],[3,5]][7] os_md.getCatalan(@@,4|to="s");0101001[8] for(I=os_md.catalan(4)-1;I>=0;I--) print(os_md.getCatalan(I,4|to="T"));(*(*(*(**))))(*(*((**)*)))(*((*(**))*))((*(*(**)))*)(*((**)(**)))(*(((**)*)*))((*((**)*))*)((*(**))(**))(((*(**))*)*)((**)(*(**)))((**)((**)*))(((**)(**))*)(((**)*)(**))((((**)*)*)*)[9] os_md.getCatalan(2000,0|to="s");001010110100100111[10] os_md.getCatalan(2000,0|to="s",opt=1);000111010100101011
156. symtournament(n|to=t,verb=1):: トーナメント戦（2 分木）の場合の数, タイプ• n チームのトーナメント戦の型の数，トーナメント図の数，チームを区別したトーナメント戦の数,
優勝チームのみを指定したトーナメント戦の数を返す（cf. numtournament()）• to=1 or "sym": n チームのトーナメント戦の図の型の数• to=2 or "T": n チームのトーナメント戦の型のリスト• to=3 or "01"": n チームのトーナメント戦の型の 01 列によるリスト• verb=1 : 型を対称性の群 Zm
2 で区別し，対応する m とその個数の組のリスト，および，優勝するチームを決めたときのトーナメント戦の数別にパターンの数のリストを返す[0] os_md.symtournament(4);[2,5,15,4][1] os_md.symtoournament(5);[3,14,105,9][2] os_md.symtournament(5|to="sym");3[3] os_md.symtournament(5|to="T");[((((**)*)*)*),(((**)(**))*),(((**)*)(**))][4] os_md.symtournament(5|verb=1);[[[3,1],[2,1],[1,1]],[[4,1],[3,1],[2,1]]]

180

: 2 patterns: 4 patterns: 8 patterns
5!
5!
:
=
15
cases,:=
30
cases,
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4 : 5!
23
22
2 = 60 cases,
×
×
×
××
× ×××
Number of cases of single-elimination tournaments
teams
2 3
4
5
6
7
8
9
10
11
types
1 1
2
3
6
11
23
46
98
207
patterns
1 2
5
14
42
132
429
1430
4862
16796
tournaments 1 3 15 105 945 10395 135135 2027025 34459425 654729075
win types
1 2
4
9
20
46
106
248
582
1376
win2 types
1 2
5
12
30
74
184
456
1133
2812
dist2 types
1 3
9
26
76
223
664
2009
6199
19524
teams
Z2
Z22
Z32
Z42
Z52
Z62
Z72
Z82
Z92
Z10
2
Z11
2

2
1

3
1

4
1
0
1

5
1
1
1

6
1
2
2
1

Symmetry of patterns
7 8
9 10 11
1 1
1
1
1
4 6
9 12 16
3 7 14 28 50
3 7 14 28 58
1
6 21 54
0
1
4 17
1
1
3
8
1
3

12
1
20
85
119
126
61
27
9
2
1

13
1
25
135
239
273
187
80
32
8
3

14
1
30
206
457
580
500
246
112
33
11
3

15
1
36
301
837
1197
1219
723
363
119
39
15

157. numtournament(n):: トーナメント戦にかかわる場合の数のリスト
n チームのトーナメント戦に関わる次の 6 種類の場合の数のリストを返す
トーナメント図の数，優勝者（1 チーム）を指定した型の数，チームを区別しない型の数，チームを区別した型の数，優勝者と準優勝者を指定した型の数，2 チームを指定した型の数．
チームの数が 0 のときは，便宜的にすべて 0 としている，チームをこれらの数は，簡単な漸化式を持つが，トーナメント図の数はカタラン数（cf. catalan()）
区別しない型の数は Wedderburn-Etherington 数，優勝者を指定した型の数の母関数と前者の母関数の積は 1, チームを区別した型の数は (2n − 3)!! という関係がある（cf. [OEIS], [Okt]）[0] os_md.numtournament(4);[patterns, win types (distinguish winner), types, tournaments, win2 types(winner&runner-up), distinguished two][[ 0 1 1 2 5 ],[ 0 1 1 2 4 ],[ 0 1 1 1 2 ],[ 0 1 1 3 15 ],[ 0 0 1 2 5 ],[ 0 0 1 3 9 ]]158. tobig(n):: 0 以外の有理数を bigfloat に変換する• n は，実部と虚部が有理数の複素数や有理数係数の多項式でもよい.
• 倍精度浮動小数は変換できない.
[0] os_md.tobig(@pi*@i+1/2);(0.5+3.14159265358979*@i)159. nthmodp(a,n,p)181

:: an mod p を返す（a は整数で n, p は自然数）[0] os_md.nthmodp(107,10006,10007);
1[1] os_md.nthmodp(107,1006,1007);
425
160. issquaremodp(a,p|power=n):: 平方剰余を調べる（ルジャンドルの平方剰余記号 ( ap )，n は平方を一般べきに）• p は素数，n は正整数．
• a ≡ 0 mod p のときは 0 を返す．そうでないときは以下の値を返す．
• x2 ≡ a mod p が解をもつとき 1, もたないとき −1．
• power=n を指定したときは，xn ≡ a mod p の解の存在問題に置き換える．
[0] os_md.rootmodp(12,13);[5,8][1] os_md.rootmodp(11,13);[0][2] os_md.rootmodp(5,13|power=3);[7,8,11]161. rootmodp(a,p|power=n):: p を法として a の平方根（一般には n 乗根）を求める• p を法とした p 未満のべき乗根を小さい順にリストで返す．
• p が奇素数のべきのときは原始根を用いて計算する．
[0] os_md.rootmodp(12,13);[5,8][1] os_md.issquaremodp(11,13);[][2] os_md.rootmodp(5,13^2|power=3);[7,8,154][3] 154^3%13^2;
5[4] os_md.rootmodp(17,32);[7,9]162. primroot(p|all=1,ind=a):: 奇素数またはそのべき p の原始根やそれを底とする指数をもとめる• p が素数のときは自然数の最小の原始根を返す．
• all=1：原始根を全て小さい順にリストで返す．
• ind=a：最小の原始根 ζ を底とする a の指数 n を返す（ζ n ≡ a mod p）．
[0] os_md.primroot(7);3[1] os_md.primroot(17|ind=2);14[2] os_md.nthmodp(3,14,17);2

182

[3] os_md.primroot(7^2|all=1);[3,5,10,12,17,24,26,33,38,40,45,47][4] for(P=3,V=0;;P=pari(nextprime,P+2))
if((Q=os_md.primroot(P))>V) os_md.mycat([Q,P]);
2 3
3 7
5 23
6 41
7 71
19 19121 40923 2161......
163. rabin(p,q):: p に対し q を底とするミラー・ラビンの素数判定を行う（素数，擬素数なら 1 を返す）
[0] os_md.rabin(10007,2);
1[1] os_md.rabin(1007,2);0164. cfrac(x,n|neg=1):: 有理数あるいは実数を連分数展開する（n は項数）
• pari(cf,) を参照．
• x が有理数のときは，n = 0 とすると x の連分数展開を返す.
• n が負のときは，分母が |n| 以下の近似分数を返す（近似値から分数に戻す）．
たとえば，分母が 3 桁以下の分数は，近似実数の誤差が 10−6 以下ならそれから定まる．
• neg=1 を指定すると，分子が −1 の連分数展開となる.
[0] os_md.cfrac(3.14159265358979,10);[3,7,15,1,292,1,1,1,2,1,3][1] V=1237.0/4123;
0.300024[2] os_md.cfrac(V,-10000);
1237/4123
165. cfrac2n(l|loop=m,,ex=1,q=f ,reg=1):: （循環）連分数を通常の形（含 q-変形）に直す.
• l =[a0 ,a1 ,a2 , . . . , an ] は次の連分数を表す．
1

a0 +

1

a1 +
a2 +

1
..

. an−2 +1
an−1 + a1n• 上の指定の場合，loop=m : m 項目から n 行目までが循環している連分数を表す．

183

• l =[[b1 ,a1 ],[b2 ,a2 ], . . . ,[bn ,an ]] は次の連分数を表す．
b1
b2

a1 +
a2 +

b3
..

. an−2 +bn−1
bn
an−1 + an上の連分数に a0 を加えたものは，ex=1 を指定した上で l =[a0 ,[b1 ,a1 ],[b2 ,a2 ], . . . ,[bn ,an ]]とする．このときは，bi = 1 となる i に対しては，[bi ,ai ] は単に ai としてよい．
• reg=1 : 分子が 1 とは限らない連分数を，分子が 1 の連分数に直す（分母は整数とは限らない）．
• l =[x,n,g(x),f (x)] は，ai = f (i), bi = g(i) (1 ≤ i ≤ n) で与えられる上の連分数を表す．f (x)または g(x) は x の多項式または有理式とするが，そうでない x の関数の時（リスト形式函数でもよい）は ex=1 を指定する．また，var=1 を指定すると，約分せずに分子と分母の組を返す．
• q=1 とすると，連分数の q-変形（cf. [Morier-Genoud and Ovsienko]）を返す. このときは，l は整数のリストでなければならない.

[0] os_md.cfrac2n([2,3]);
7/3[1] os_md.cfrac2n([2,3]|loop=1);
1/3*((15)^(1/2))+1[2] eval(@@);
2.29099444873580562818[3] os_md.cfrac(@@,11);[2,3,2,3,2,3,2,3,2,3,2,3][4] os_md.cfrac2n([1,2,3]|loop=2);
1/3*((15)^(1/2))+2[5] eval(@@);
1.43649167310370844239[6] os_md.cfrac(@@,11);[1,2,3,2,3,2,3,2,3,2,3,2][7] os_md.cfrac2n([x,4,1,x^2]);
46/741[8] os_md.cfrac2n([0,1,2^2,3^2,4^2]);
596/741[9] os_md.cfrac2n([[1,1],[1,2^2],[1,3^2],[1,4^2]]);
46/741[10] P=-n^6 $ Q=(2*n+1)*(17*n^2+17*n+5)$[11] for(R=[],I=0;I<20;I++) R=cons(6/(5+os_md.cfrac2n([n,I,P,Q])),R);[12] R=reverse(R)$[13] R[0];6/5[14] R[9];43786938951280269198311/36426677336311407264000[15] os_md.cfrac2n(os_md.cfrac(7/3,0)|q=1);(q^4+q^3+2*q^2+2*q+1)/(q^2+q+1)[16] os_md.cfrac(7/3,0);184

[2,3][17] os_md.cfrac(7/3,0|neg=1);[3,2,2][18] os_md.cfrac2n([3,2,2]|q=-1);(q^4+q^3+2*q^2+2*q+1)/(q^2+q+1)[19] os_md.cfrac2n(os_md.cfrac(7/4,0)|q=1);(q^4+2*q^3+2*q^2+q+1)/(q^3+q^2+q+1)[20] os_md.cfrac2n([[2,1],[1,2^2],[1,3^2],[1,4^2]]);1192/741[21] os_md.cfrac2n([[2,1],[1,2^2],[1,3^2],[1,4^2]]|reg=1);[0,1/2,8,9/2,32][22] os_md.cfrac2n([0,1/2,8,9/2,32]);
1192/741[11] では，Apéri [Apéri] が ζ(3) が無理数であることを示すときに使った ζ(3) の以下の連分数展開による近似分数を，20 番目まで求めている.
ζ(3) =
5+
Q(1) +

6
P (1)
P (2)
..
.
Q(n) +

P (n) = −n6 ,Q(n) = (2n + 1)(17n2 + 17n + 5),

P (n)
..
.

166. sqrtrat(r):: 有理数（または実部と虚部が有理数の複素数）の平方根を得る• r が有理数でも実部と虚部が有理数の複素数でもないときは[] を返す．
√√√m p m −pm,,のいずれかを返す．ただし，m, n, p は整数（p > 1）
• r が有理数のとき， m
−1,
n
n
n
n
である．
√
√
p は ((p)^(1/2)) ， −p は @i*((p)^(1/2)) と表示される．

[0] os_md.sqrtrat(4/9);
2/3[1] os_md.sqrtrat(-4/9);(2/3*@i)[2] os_md.sqrtrat(9/8);
3/4*((2)^(1/2))[3] os_md.sqrtrat(-9/8);(3/4*@i)*((2)^(1/2))[4] os_md.sqrtrat(-1);(1*@i)[5] os_md.sqrtrat(os_md.sqrtrat(4*@i-3));(1+2*@i)[6] os_md.sqrtrat((4*@i-3)*2);(1+2*@i)*((2)^(1/2))[7] os_md.sqrtrat(1+@i);((1/2*((2)^(1/2))+1/2)^(1/2))+(1*@i)*((1/2*((2)^(1/2))-1/2)^(1/2))
185

[8] os_md.sqrtrat(-a^2+2*a-1);(1*@i)*a+(-1*@i)
上は以下を示している

r

√ r
√
√
9
3 2
9
3 2i √=,− =, −1 = i, 4i − 3 = 1 + 2i,
8
4
8
4
s√
s√
p
√
√
2 1
2 1 p 22(4i − 3) = 2(1 + 2i), 1 + i =+ +− i,−a + 2a − 1 = ai − i.
2
2
2
2
4
2
= ,
9
3

r

4
2
− = i,
93

r167. sqrt2rat(r|mult=1):: 平方根や虚数を含んだ分数の有理化
11• p(x)n+ 2 は，p(x)n · p(x) 2 の形に直される（n は整数）
• 分子や分母に表れる平方根は高々一つで，共に a^(1/2) の形をしている場合が特に有効．
• a^(1/2) の有理数係数の有理式は, 有理数 r1 , r2 によって r1 + r2 · a^(1/2) の形に標準化される．
• mult=1 を指定すると，函数の引数についてもこの有理化変換を行う．
[0] os_md.sqrt2rat((x+@i)/(y+@i));((y+(-1*@i))*x+(1*@i)*y+1)/(y^2+1)[1] os_md.sqrt2rat((2+2^(1/2))/(2-2^(1/2)));2*((2)^(1/2))+3[2] P=2^(1/2);((2)^(1/2))[3] os_md.sqrt2rat(P^4);4[4] os_md.sqrt2rat((P+1)^3/(P-1));
4*((2)^(1/2))+13[5] -((x-1)^(-1/2))*x+((x-1)^(-1/2))+((x-1)^(1/2))
0以上は，以下の等式を示している．

xy − xi + yi + 1
x+i
=
,
y+i
y2 + 1√√2+ 2√ = 2 2 + 3,
2− 2

√ 4
2 = 4,√√( 2 + 1)3√
= 4 2 + 13.
2−1168. sint(r,p|str=t,sqrt=1,zero=0):: 実数 r または複素数，リストや行列（ネスト対応）などの成分の実数を小数点以下 p 桁に丸める• p が負の時は，四捨五入して下 |p| 桁を 0 にする．
• r やその成分が数でない場合はそのまま返す．
• 円周率@pi, ネピア数@e は評価される．複素数は実部と虚部に分けて処理される．
• str=0 : p > 0 のとき，p を有効数字の桁数として丸めた概数を返す．
• str=1 : 文字列で返す．
• str=2 : 1.034*10^(−2) のような文字列で返す．
• str=3 : 10.34 のような TEX の文字列で返す．
• str=4 : 1.034\times10^{−2} のような TEX の文字列で返す.
• sqrt=1 : TEX の文字列で返すとき，虚数単位の i を \sqrt{-1} に変更する．
• zero=0 : 0. · · · となるとき，最初の 0 を省いて，. · · · とする．
[0] V=eval(exp(1));
2.71828182845904523521[1] os_md.sint(V,4);186

2.7183[2] os_md.sint(1000*V,-2);
2700[3] os_md.sint([2/3,1/7],5);[0.66667,0.14286][4] os_md.sint([2/3,1/7],5|str=3,zero=0);[.66667,.14286][5] os_md.sint(@pi+@e*@i,5);3.14159+2.71828*@i[6] os_md.sint(@pi+@e*@i,5|str=3);
3.14159+2.71828i[7] os_md.sint(@pi+@e*@i,5|str=3,sqrt=1);
3.14159+2.71828\sqrt{-1}[8] os_md.sint(-123.0202,3);-123.02[9] os_md.sint(-123.0202,3|str=1);-123.020[10] os_md.sint(-123.0202,3|str=2);-1.230*10^(2)[11] os_md.sint(-123.0202,3|str=4);-1.230\times10^{2}[12] os_md.sint(-12.30202,3|str=4);-1.230\times10[13] os_md.sint(-123.0202+@i,3|str=4);(-1.230+0.010i)\times10^{2}[14] os_md.sint(-123.0202+@i,3|str=4,sqrt=1);(-1.230+0.010\sqrt{-1})\times10^{2}[15] os_md.sint(1234.567,3|str=0);1230[16] os_md.sint(1234.567+11.1*@i,3|str=0);(1230+10*@i)
169. frac2n(n|big=1):: 分数を実数になおす（r は複素数，有理式やそのリストや行列などでもよい）• big=1 を指定すると bigfloat で返す．
[0] os_md.frac2n(1/3);
0.333333[1] os_md.frac2n([1/3,1/4]);[0.333333,0.25][2] os_md.frac2n([1/3,1/4]|big=1);[0.33333333333333333304,0.25000000000000000000][3] os_md.frac2n([1/3,1/4+1/6*@i+3/4*x]);[0.333333,0.75*x+(0.25+0.166667*@i)]187

3.2.3 Polynomials and rational functions
170. radd(p,q):: 有理式 p と q の和を既約有理式の形で計算する
p と q はベクトルまたは行列でもよい．一方がスカラーで他方がベクトルまたは正方行列でもよい．
[0] P=y^3/(x*y+y^2);(y^3)/(y*x+y^2)[1] Q=(x^2*y-y^3)/(x*y-y^2);(y*x^2-y^3)/(y*x-y^2)[2] P+Q;(y^2*x^3+y^3*x^2-2*y^5)/(y^2*x^2-y^4)[3] os_md.radd(P,Q);(x^2+2*y*x+2*y^2)/(x+y)[4] P*Q;(y^4*x^2-y^6)/(y^2*x^2-y^4)[5] os_md.rmul(P,Q);y^2[6] M = newmat(3,3,[[x,x,x],[x,x,x],[x,x,x]]);[ x x x ][ x x x ][ x x x ][7] M1 = subst(M,x,1/x);[ (1)/(x) (1)/(x) (1)/(x) ][ (1)/(x) (1)/(x) (1)/(x) ][ (1)/(x) (1)/(x) (1)/(x) ][8] M2 = subst(M,x,1/(x+y));[ (1)/(x+y) (1)/(x+y) (1)/(x+y) ][ (1)/(x+y) (1)/(x+y) (1)/(x+y) ][ (1)/(x+y) (1)/(x+y) (1)/(x+y) ][9] M1*M2;[ (3*x^4+6*y*x^3+3*y^2*x^2)/(x^6+3*y*x^5+3*y^2*x^4+y^3*x^3)...
[10] os_md.rmul(M1,M2);[ (3)/(x^2+y*x) (3)/(x^2+y*x) (3)/(x^2+y*x) ][ (3)/(x^2+y*x) (3)/(x^2+y*x) (3)/(x^2+y*x) ][ (3)/(x^2+y*x) (3)/(x^2+y*x) (3)/(x^2+y*x) ][11] N=newmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[12] os_md.radd(x,-N);[ x-a -b ][ -c x-d ][13] os_md.radd(x,N[0]);[ x+a x+b ]188

[14] os_md.rmul(x,N);[ a*x b*x ][ c*x d*x ][15] V=ltov([u,v]);[ u v ]
[16] os_md.rmul(N,V);[ a*u+b*v c*u+d*v ][17] os_md.rmul(V,N);[ a*u+c*v b*u+d*v ][18] os_md.rmul(V,2);[ 2*u 2*v ][19] os_md.rmul(V,V);u^2+v^2
171. rmul(p,q):: 有理式（の行列）p と q の積を既約有理式（の行列）の形で計算する
q はベクトルまたは行列でもよい．このとき p は行列やベクトルでもよい（例は radd() の項を参照）．
172. mulpolyMod(p,q,x,n):: x の多項式 p と q の積を xn+1 以上の項を無視して計算する
x について n 次式を返す．
x は [x1 ,x2 ,...] など多変数でもよい．
n がある程度大きく，また係数が複雑なときの高速化やべき級数の積の計算などに用いられる．
173. polbyroot([p1 , p2 , ..., pn ],x) polbyroot([m,n],x|var=v):: 多項式を根で与える
Q• 戻り値: j (x − pj )• var=v : 根を vi (m ≤ i ≤ n) で与える．
• 第 1 引数が [] または，var=v を指定していて m > n のときは 1 を返す．
[0] os_md.polbyroot([a,b,c],t);t^3+(-a-b-c)*t^2+((b+c)*a+c*b)*t-c*b*a[1] os_md.polbyroot([1,3],x|var=a);x^3+(-a1-a2-a3)*x^2+((a2+a3)*a1+a3*a2)*x-a3*a2*a1
174. polbyvalue([[a1 , b1 ],...,[an , bn ]],x):: x の n − 1 次多項式を n 個の点 x = ai での値 bi で与える
戻り値: n − 1 次多項式[0] os_md.polbyvalue([[0,1],[2,3],[3,6]],t);2/3*t^2-1/3*t+1
175. pgen([[x1 , n1 ],[x2 , n2 ]...],a|sum=n,shift=m,sep=1,num=1):: 係数が a∗ で xi が ni 次，全体で n 次以下の x1 , . . . の一般多項式を作る• shift=1 : suﬃx を 1 から始める• num=1 : 10, 11, . . . を a, b, . . . でなくて数字のままで表す．
• sep=1 : 複数の suﬃces のとき _ で区切る
[0] os_md.pgen([[x,2],[y,1]],a_);(a_21*y+a_20)*x^2+(a_11*y+a_10)*x+a_01*y+a_00[1] os_md.pgen([[x,2],[y,2]],a|sum=3,shift=1);(a32*y+a31)*x^2+(a23*y^2+a22*y+a21)*x+a13*y^2+a12*y+a11189

[2] os_md.pgen([x,6],a);a6*x^6+a5*x^5+a4*x^4+a3*x^3+a2*x^2+a1*x+a0[3] os_md.pgen([[x,2],[y,2]],a|num=1,sep=1);(a2_2*y^2+a2_1*y+a2_0)*x^2+(a1_2*y^2+a1_1*y+a1_0)*x+a0_2*y^2+a0_1*y+a0_0[4] os_md.my_tex_form(@@);(a_{2,2}y^2+a_{2,1}y+a_{2,0})x^2+(a_{1,2}y^2+a_{1,1}y+a_{1,0})x+a_{0,2}y^2+a_{0,1}y+a_{0,0}176. rpdiv(p,q,x):: x の多項式の割り算
戻り値 [r, m, s] : r = m ∗ p − s ∗ q,
mydeg(r,x) < mydeg(q,x), mydeg(m,x) = 0[0] R=os_md.rpdiv(3*x^3+x^2+5,a*x^2+x+1,x);[(-4*a+3)*x+5*a^2-a+3,a^2,3*a*x+a-3][1] R[1]*(3*x^3+x^2+5)-R[2]*(a*x^2+x+1) - R[0];0177. res0(p,q,x|var=[x1 , x2 , . . .],opt=f ,dbg=d):: 1 変数多項式の共通解の存在条件と解，割り算
変数 x の多項式 p, q に共通根が存在するための条件 r を返す．
• var=[x1 , x2 , . . .] とすると，x1 , x2 , . . . 以外の不定元は一般の数と見なす．
• opt=1 : 共通解 s との組 [s,r,S,R] を返す（S, R は，s, r の次数）．
• opt=-1 : 割り算で，次数の高い多項式を他方の多項式 s で割った余り r を上の形で返す．
• opt=-2 : 次数の少ない多項式 r で割るための 1 回の操作後の結果 [s,r,S,R]（次数が等しいとき
は，p の次数を下げる）．
• opt=[m,n] : 次数が m と n になった時点での結果を返す（m ≥ n）．
• dbg=1 : 割り算の途中経過を表示する（2 つの多項式の次数を表示）．
• dbg=2 : 途中で経過で，多項式の次数に加えて，多項式の項数，最高次の多項式の係数となる（xを含まない）多項式の項数を表示する．
• dbg=3 : 上と同じだが，可約なものが現れたら，最後の既約な成分を選ぶ．そうでない場合は
dbg=[3,[2,1,2]] のように指定する．[2,1,2] は現れる順に，可約なものの 2 番目，最初，2 番目の意味で 0 は最後を意味する．> は，計算結果の因数分解の計算の実行を示す．
• dbg=4 : 上と同じだが，可約なものが現れたら，そこで中止して結果を返す．可約なものは，可約分解された形で返す．

[0] os_md.res0(a*x^3-b,c*x^2-x-d,x);-d^3*c^2*a^2+(-3*d*c^3-c^2)*b*a+c^5*b^2[1] os_md.res0(a*x^3-b,c*x^2-x-d,x|opt=1);[(d*c+1)*a*x+d*a-c^2*b,-d^3*c^2*a^2+(-3*d*c^3-c^2)*b*a+c^5*b^2,1,0][2] os_md.res0(a*x^3-b,c*x^2-x-d,x|opt=-1);[c*x^2-x-d,(d*c+1)*a*x+d*a-c^2*b,2,1][3] os_md.res0(a*x^3-b,c*x^2-x-d,x|opt=-2);[a*x^2+d*a*x-c*b,c*x^2-x-d,2,2][4] os_md.res0(a*x^2,a*x+c,x|var=[a,c]);c[5] os_md.res0(a*x^2,a*x+c,x|var=[a,c],opt=1);[a*x+c,c,1,0]190

[6] os_md.res0(a*x^2,a*x+c,x);c^2[7] res(x,a*x^2,a*x+c);c^2*a[8] os_md.res0(0.5*x^2+x,0.7*x^2+c,x|var=[c],opt=1,dbg=1);
2:2,2:1,1:1,1:0 [x-0.714286*c,0.510204*c^2+1.42857*c,1,0]178. sgnstrum([p1 , p2 , . . .],t|):: 多項式の strum 列の t での符号変化の個数を返す
実数係数の多項式 p の strum 列 [p1 , p2 , . . .] に対して，変数の値が t での符号変化の個数を返す. t1 とt2 での値の差が，(t1 , t2 ] にある実根の個数となる．根の重複は無視．
t="+"，t="-"は，それぞれ +∞，−∞ を意味する．
[0] P=(x-2)*(x+2)*(x-4)$[1] L=os_md.polstrum(P);[x^3-4*x^2-4*x+16,x^2-8/3*x-4/3,x-16/7,1][2] os_md.sgnstrum(L,"+");
0[3] os_md.sgnstrum(L,2);
1[4] os_md.sgnstrum(L,0);2[5] os_md.sgnstrum(L,"-");
3
179. polstrum(p|num=[t1 ,t2 ],mul=1):: 多項式の strum 列や，(t1 , t2 ] にある根の個数を返す
p が有理数の係数の多項式の時は，平方因子を除いた多項式にしてから strum 列を返す．
• オプション num=[t1 ,t2 ] を指定すると，(t1 , t2 ] にある根の個数を返す．t1 = "-" は −∞ を，"+"は，∞ を，num=1 は，区間 (−∞, ∞) を表す．
• 有理数の係数の多項式の時に実根の個数を求める場合は，mul=1 を指定すると，指定された区間での重複度を込めた実根の個数が得られる．

• 有理数係数の多項式の時は mul=1 のみを指定すると，平方因子のない多項式の積への分解を返す．
•[0] P=x^2*(x^2+1)*(x-1);x^5-x^4+x^3-x^2[1] os_md.polstrum(P);[x^4-x^3+x^2-x,x^3-3/4*x^2+1/2*x-1/4,-x^2+2*x+1/5,-x,-1][2] os_md.polstrum(P|num=1);2[3] os_md.polstrum(P|num=1,mul=1);3[4] os_md.polstrum(P|num=[1/2,2]);
1[5] os_md.polstrum(P|num=[1/2,1],mul=1);
1[6] os_md.polstrum(P|mul=1);191

[x,x^4-x^3+x^2-x]
180. polrealroots(p|in=[a,b],step=[n1 ,n2 ],nt=k):: 多項式の実根を求める
strum 列を使って実根を求める．
• デフォルトの戻り値は [[a1 ,b1 ,m1 ],...,[an ,bn ,mn ],q] で，(ai , bi ] に実根が mi 個存在する
ことを返す（mi > 0）．
• 有理数係数の時は，q は根の重複度を 1 に変えた多項式．
• 有理数係数の多項式の場合は，重複を除いて実根を求める• step=[n1 ,n2 ] を指定すると，区間の幅を二分法で 2n1 等分まで縮めて調べる．根が分離できな
かった場合は，2n2 等分まで縮める．step=n は，step=[n,n] を意味する．
• デフォルトは step=32．
• in=[a,b] を指定すると，(a, b] の範囲で実根を求める．
• nt=k を指定すると，mi = 1 となった (ai , bi ] 内の実根を，Newton 法を最大 k 回まで用いて近似的に求める．

[0] os_md.polrealroots((x^2-2)^2);[[-1.414213562826262204907834529876,-1.414213561893120640888810157775,1],[1.414213561893120640888810157775,1.414213562826262204907834529876,1],x^2-2][1] os_md.polrealroots(x^2-2|in=[1,2],nt=2);[1.414213562373095048801688724223][2] @@[0]^2;
2.0000000000000000000000000000
181. polroots(p,x|comp=t,err=r,lim=ℓ):: 変数 x の 1 変数多項式の根，多変数多項式の共通根（実根・虚根）の（近似）値を返す• デフォルトでは実根を小さい順に返す（cf. polrealroots）．
• comp=1 を指定すると実根と虚根とを重複を込めて返す．
• comp=-1 とすると，実根と虚根を返すが，多項式の係数が有理数のとき有理根は有理数で返す．
• comp=-2 とすると，実根を全て返すが，多項式の係数が有理数のとき有理根は有理数で返す．
• comp=2 を指定すると有理根のみを返す（全ての係数が有理数のときのみ有効）．
係数に変数以外のパラメータが含まれていてもよい（パラメータについての有理解が得られる）．

• 多変数多項式の場合は，x に変数 n 個のリスト，p に多項式の n 個のリストを指定することによって共通根が得られる．
– 0 以外の数の戻りは，共通根がみつからなかったことを示す．（非存在と推定される）．
– 0 の場合は，一意に定まらなかったことを示す（乱数を用いているので，再度試みると求まる
可能性は皆無ではない）．
– 近似計算をしているので，デフォルトでは 2−32 程度の途中計算の誤差を無視して，共通根かどうかを判断している（求めた根の精度とは異なる）．
この値は，err= r によって変更できる．
• lim= ℓ によって根の範囲を制限できる．
– 実根または実部に対し，変数 x の範囲を [a, b] に限るには，ℓ の要素に [x,[a,b]] を入れる．
– 虚部も [c, d] に限るには，[x,[a,b],[c,d]] を入れる．
– 後者で実部を制限しないときは，[x,[],[c,d]] とする．
– たとえば x と y の実部を [0, 1] に制限するには，lim=[[x,[0,1]],[y,[0,1]]] とする．
– 一つの変数のみの指定のときは，たとえば lim=[x,[0,1]] または lim=[0,1] としてもよい.

[0] os_md.polroots(x^4-x-2,x);[-1.0000000000000000000,1.35320996419932442942][1] os_md.polroots(x^4-x-2,x|comp=1);192

[-1.0000000000000000000,1.35320996419932442942,(-0.17660498209966221474-1.20282081928547880591*@i),(-0.17660498209966221474+1.20282081928547880591*@i)][2] os_md.polroots(x^4-x-2,x|comp=2);[-1][3] os_md.polroots(x^4-x-2,x|comp=-1);[-1,(-0.17660498209966221474-1.20282081928547880591*@i),(-0.17660498209966221474+1.20282081928547880591*@i),1.35320996419932442942][4] os_md.polroots(x^4-x-2,x|comp=-2);[-1,1.35320996419932442942][5] os_md.polroots([x^2+y^2-2,y^2+z^2-2,z^2+x^2-2],[x,y,z]|comp=-1);[[-1,-1,-1],[1,-1,-1],[-1,1,-1],[1,1,-1],[-1,-1,1],[1,-1,1],[-1,1,1],[1,1,1]][6] os_md.polroots([x^2+y^2-2,y^2+z^2-2,z^2+x^2-2],[x,y,z]|comp=2,lim=[x,[0,1]]);[[1,-1,-1],[1,1,-1],[1,-1,1],[1,1,1]][7] os_md.polroots([x^2+y^2-2,y^2+z^2-2,x^2+2*y^2+z^2-2],[x,y,z]|comp=-1);
100[8] os_md.polroots([x^2+y^2-2,y^2+z^2-2,x^2+2*y^2+z^2-4],[x,y,z]|comp=-1);0[9] os_md.polroots([x^3+y^2-2,x^2+y^3-4],[x,y]);[[-0.68364887206699437088,1.52299734898613986185]][10] os_md.polroots([x^3+y^2-2,x^2+y^3-4],[x,y]|comp=1);[[-0.68364887206699437088,1.52299734898613986185],[(0.55290983195525726542+0.67794790320397197786*@i),(1.61325322177512775522-0.096132145655863646024*@i)],...
/* 1 個の実根と 8 個の複素根 */上の [9] の計算には，0.03 sec 程度かかった．
182. easierpol(p,x) または easierpol(p,[x1 , x2 , . . . ]):: 有理式係数の x の多項式の係数に x を含まない有理式をかけて，係数の最大公約元が 1 の整数係数の多項式に変換[0] os_md.easierpol(6*r*y/a-3*r*x^2,x);a*x^2-2*y183. getroot(p,x|mult=1,cpx=1):: 多項式の根を有理式または有理数の平方根の範囲で求める• mult=1 を指定すると，重複度と根の組のリストを返す．
• 係数が有理数の多項式の場合に cpx=1 を指定すると，実部と虚部が有理数の根も合わせて返す．
• 係数が有理数の多項式の場合に cpx=2 を指定すると，実部と虚部が有理数の平方根を使って表せる根も合わせて返す．

• 係数が有理数の多項式の場合に cpx=3 を指定すると，より複雑な根も合わせて返す．
• これら以外の根は，定義方程式で返す．
• 有理式の解については solveEq() も参照．
[0] os_md.getroot(os_md.polbyroot([a,b,a,c+d],t),t);[a,a,b,c+d][1] os_md.getroot(os_md.polbyroot([a,b,(b+c)^2],t^2),t);[t^2-a,t^2-b,-b-c,b+c]193

[2] os_md.getroot(os_md.polbyroot([a^4,(b+c)^2],t^2),t|mult=1);[[1,-a^2],[1,a^2],[1,-b-c],[1,b+c]][3] os_md.getroot(2*x^3-x^2-4*x+2,x);[x^2-2,1/2][4] os_md.getroot((2*x^3-x^2-4*x+2)^2,x|mult=1);[[2,x^2-2],[2,1/2]][5] os_md.getroot(2*x^3+x^2+4*x+2,x|cpx=2);[(-1*@i)*((2)^(1/2)),(1*@i)*((2)^(1/2)),-1/2]
184. fctri(p):: 実部と虚部が有理数係数の１変数多項式を，その範囲で既約分解する
af_noalg() を使うので，load("sp") として関数をロードしておくことが必要．
戻り値は fctr() と同じ形であるが，定数倍は無視される．
[1] os_md.fctri(4*x^2+1);[[1,1],[2*x+(-1*@i),1],[2*x+(1*@i),1],[1,1]][2] os_md.fctri(@i*x^3+1);[[1,1],[x+(1*@i),1],[x^2+(-1*@i)*x-1,1]]
185. polinsym(p,[x1 , . . . , xn ],s):: (x1 , . . . , xn ) の対称有理式を基本対称式で表す
k 次の基本対称式を sk と表す（k = 1, . . . , n）．
[0] os_md.polinsym((a^2+b^2+c^2+d^2)^2,[a,b,c],s);d^4+(2*s1^2-4*s2)*d^2+s1^4-4*s2*s1^2+4*s2^2[1] P=os_md.polinsym(x^2+y^2+a/(x+y+b),[x,y],s);(a+(s1^2-2*s2)*b+s1^3-2*s2*s1)/(b+s1)[2] os_md.polinvsym(P,[u,v],s);(u^3+(v+b)*u^2+v^2*u+v^3+b*v^2+a)/(u+v+b)
186. polinvsym(p,[x1 , . . . , xn ],s):: polinsym(p,[x1 , . . . , xn ],s) の逆函数
187. pol2sft(p,x|sft=t):: shifted power 多項式を与える
PP• p=cn xn ⇒ 戻り値:
cn xn （xn := x(x − 1) · · · (x − n + 1)）n• sft=t を指定すると x 7→ x(x − t)(x − 2t) · · · (x − (n − 1)t) というずらしによる多項式の変換[0] os_md.pol2sft(x^3, x);x^3-3*x^2+2*x[1] os_md.pol2sft(x^3,x|sft=-1);
x^3+3*x^2+2*x[2] os_md.pol2sft(x^3,x|sft=e);x^3-3*e*x^2+2*e^2*x188. polinsft(p,x):: shifted power 多項式に直す（pol2sft() の逆変換）
PPPp=c n xn =an xn ⇒ 戻り値:
an xn (xn := x(x − 1) · · · (x − n + 1))[0] os_md.polinsft(x^3-3*x^2+2*x, x);
x^3

194

189. sftpow(p,n)
190. sftpowext(p,n,s)
Qn:: p の s shifted n power ν=1 (p + (ν − 1)s) を返すnY
p + (ν − 1)s を返す．sftpow( ) では，s = −1 と解釈される．
ν=1

191. binom(p,n):: p(p − 1)(p − 2) · · · (p − n + 1)/n! を返す
192. expower(p,r,n):: (1 + p)r の展開を pn まで求める[0] os_md.expower(x,r,3);(1/6*r^3-1/2*r^2+1/3*r)*x^3+(1/2*r^2-1/2*r)*x^2+r*x+1[2] os_md.expower(0.5,1/3,10);
1.14471√[2] は 3 1.5 の近似値を求めている．
193. orthpoly(n|pol="type")
orthpoly([n,a, . . .]|pol="type"):: 変数 x の n 次直交多項式を返す• デフォルトでは n 次の Legendre 多項式 Pn (x) を返す• type は，Legendre, Gegenbauer, Tchebycheff, 2Tschebyscheff, Jacobi, Laguerre, Hermite,
Selected のいずれかの文字列が指定可能．ただし，先頭から 2 文字のみで判断される（3 文字目
以降は省略可）．

• type が，Gebenbauer のときの引数は [n,a] で，Gegenbauer 多項式 Cna (x) を返す．
(a)• type が，Laguarre のときは，[n,a] を引数として指定すると Laguerre 多項式 Ln (x) を返し，
(0)n を指定すると，Ln (x) を返す．
• type が Jacobi のときは，[n,a,c] を指定すると Jacobi 多項式 Gn (a, b ; x) = F (−n, a + n, c ; x)を返す．

• type が Tchebycheff のときは，戻り値は Tschebyscheﬀ 多項式 Tn (x) で，cos(nθ) √= Tn (cos θ).
• type が 2Tschebyscheff のときは，戻り値 Ūn (x)（この時のみ n − 1 次多項式）に 1 − x2 を掛けたものが第 2 種の Tschebyscheﬀ 関数 Un (x) となる．このとき sin nθ = Ūn (cos θ) sin θ.
• type が Selected のときは，引数 [n,a] に対し，選点直交多項式 Pn,a (x) を返す．
[0] os_md.orthpoly(5);63/8*x^5-35/4*x^3+15/8*x[1] os_md.orthpoly(5|pol="Tc");
16*x^5-20*x^3+5*x[2] os_md.orthpoly(5|pol="He");x^5-10*x^3+15*x[3] os_md.orthpoly(1|pol="La");-x+1[4] os_md.orthpoly([1,a]|pol="La");-x+a+1[5] T=os_md.xylines([[-1,0],[1,0]]|scale=[6,3],opt="thick")$[6] T+=os_md.xylines([[0,-1],[0,1]]|scale=[6,3],opt="thick")$[6] T+=os_md.xylines([[-1,1],[1,1],[-1,-1]]|scale=[6,3])$[7] for(I=2;I<=7;I++) T+=os_md.xygraph(os_md.orthpoly(I),-48,[-1,1],0,[-1,1]|scale=[6,3],prec=6,dviout=-1)$[8] os_md.xyproc(T|dviout=1)$
195

ルジャンドル多項式 P0 (x) ∼ P7 (x) のグラフ

194. schurpoly ([m1 ,m2 , . . .]|var=v):: m1 ≥ m2 ≥ · · · ≥ mn ≥ 0 のウェイトの Schur 多項式を返す• デフォルトの変数は x1,x2,. . .,xn．
• var=y とすると，変数は y1,y2,. . .,yn
• var=[x,y,. . .] とすると，変数は x, y, . . ..
[0] os_md.schurpoly([2,1,0]);(x2+x1)*x3^2+(x2^2+2*x1*x2+x1^2)*x3+x1*x2^2+x1^2*x2[1] os_md.polinsym(@@,[x1,x2,x3],s);s2*s1-s3[2] os_md.schurpoly([2,2,0]|var=[x,y,z]);(y^2+z*y+z^2)*x^2+(z*y^2+z^2*y)*x+z^2*y^2[3] os_md.polinsym(@@,[x,y,z],s);-s3*s1+s2^2
195. seriesMc(f ,k,v|evalopt=[[s1 ,t1 ],[s2 ,t2 ]...]):: 函数 f の変数または変数のリスト v に対する k 次の項までの Maclaurin 展開を求める
evalopt= により，展開係数に対し evalred() を使うときのオプションを設定する[0] os_md.fctrtos(os_md.seriesMc(exp(sin(x)),8,x)|var=x,rev=1);
1+x+1/2*x^2-1/8*x^4-1/15*x^5-1/240*x^6+1/90*x^7+31/5760*x^8[1] os_md.fctrtos(os_md.seriesMc(log(cos(x)+y),4,[x,y])|var=[x,y],rev=1);
y-1/2*y^2-1/2*x^2+1/3*y^3+1/2*x^2*y-1/4*y^4-1/2*x^2*y^2+1/24*x^4[2] S=os_md.seriesMc(subst(1/x,x,x+a),4,x))$[3] T=os_md.fctrtos(S|var=[x,"(x-a)"],rev=1,TeX=1);\frac{1}{a}-\frac{1}{a^2}(x-a)+\frac{1}{a^3}(x-a)^2-\frac{1}{a^4}(x-a)^3+\frac{1}{a^5}(x-a)^4[4] os_md.dviout("$\\frac1x="+T+"+\\cdots$")$
1
1
1
1
1
1
2
3
4
x = a − a2 (x − a) + a3 (x − a) − a4 (x − a) + a5 (x − a) + · · ·上の [2],[3] では x = a での 4 次までの Taylor 展開を求めて，TEX のソースの形で出力している．

196. solveEq([f1 , f2 , . . . ],[x1 , x2 , . . . ]|h=1,inv=1):: 連立代数方程式を解く，双有理変換の逆変換を求める．
196

代数方程式
f1 (x1 , x2 , . . .) = 0,
f2 (x1 , x2 , . . .) = 0,

..

.

を有理式の範囲で解く．
• グレブナー基底の計算パッケージを使うので load("gr") が必要．
• inv=1 を指定したときは

x1 → f1 (x1 , x2 , . . .),x2 → f2 (x1 , x2 , . . .),

..

.

の逆変換を求める．

• 戻り値– [c1 , c2 , . . .] : x1 = c1 , x2 = c2 , . . . が解
– −1 : 解が求まらない（グレブナー基底の数と変数の数が不一致）– −2 : 解が求まらない（上記でないが，1 変数に分離しない）– −3 : 解が求まらない（上記でないが，各変数に分離しない）– −4 : 一変数の 2 次以上の代数方程式を解くことで求まる– −5 : 逆変換の変数と式の数が不一致• h=1 : 上の −2 のエラーに対応するものは，変数とそれについての 2 次以上の方程式を返す．
[0] os_md.solveEq([a*x+b*y-u,c*x+d*y-v],[x,y]);[(-d*u+b*v)/(-d*a+c*b),(c*u-a*v)/(-d*a+c*b)][1] os_md.solveEq([(a*x+b)/(c*x+d)],[x]|inv=1);[(-d*x+b)/(c*x-a)][2] os_md.solveEq([-x^4+2*y*x^2+x-y^2,x^4+(-2*y-1)*x^2-x+y^2+y],[x,y]|inv=1);[x^2+(2*y+1)*x+y^2,x^4+(4*y+2)*x^3+(6*y^2+4*y+1)*x^2+(4*y^3+2*y^2+1)*x+y^4+y]197. baseODE([f1 , f2 , . . . ]|f=y,to=x,var=v,vl=h,ord=d,in=1,TeX=t,pages=p,dbg=d,step=k):: 一階常微分方程式系の単独化, 双有理変換
デフォルトでは 0
x = f1 (t, x, y, z, . . .),


 0

y = f2 (t, x, y, z, . . .),z0 = f3 (t, x, y, z, . . .),..
 .. ..
. .
.

という変数 t についての n 次元の常微分方程式について，x(t) の満たす単独高階微分方程式を求める．
• f1 , f2 , . . . は有理式で，パラメータを含んでもよい．
• n 個のベクトルは x, y, z, w, u, v, p, q, r, s の順に先頭から n 個がデフォルト．11 番目以降は，xx, xy, . . . ,yx, . . . となる．
• load("gr"); によってグレブナー基底の計算パッケージを読み込んでおく必要がある．
デフォルトでは gr() を, オプション指定によっては hgr() なども使う．
• パラメータ f– f=0 : デフォルトで，戻り値は [p,l1 ,l2 ,l3 ] となる．
p : x の単独高階微分方程式で，導関数は 1 階から順に x1, x2, x3, · · · のように表される．
l1 : グレブナー基底を計算するときの変数順序
l2 : 与えた方程式とその微分から生成された多項式のリスト
l3 : 求められたグレブナー基底– f=1 : p のみを返す．

197

– f=-1 : [l1 ,l2 ] を返す．デフォルトでは gr(l2 ,l1 ,2) を計算．
– f=-2 : [l10 ,l2 ] を返す．ℓ01 は ℓ1 を変数毎にリストにしたもののリスト．
– f=-3 : [v,L] を返す（v は変数のリストで，有理変換を行った場合は，変換後）．
• to=x : 変数 x についての単独高階方程式を求める．たとえば to=y．
• to=[g1 , g2 , . . .] : 最初にx̃ = g1 (t,x,y, . . .),ỹ = g2 (t,x,y, . . .),

..
 ..
.
.
という双有理変換を行い，(x̃, ỹ, . . .) についての方程式とみなす．
f=-3 によって変数と変換された方程式を返す．さらに TeX=1，2 の指定により，その方程式を
TEX で返す．
• to=[[g1 , g2 , . . .]] : 最初にx = g1 (t, x̃, ỹ, . . .),y = g2 (t, x̃, ỹ, . . .),

..
 ..
.
.

という双有理変換を行い，(x̃, ỹ, . . .) についての方程式とみなす．
f=-3 によって変数と変換された方程式を返す．さらに TeX=1，2 の指定により，その方程式を
TEX で返す．
• to=g : g が有理式で変数でないときは，to=[g,y, . . .] という指定と等価．g は変数 x についての
1 次式，あるいは分母が 1 次で分子は 1 次以下の有理式（他の変数を定数とみて）でなければならない．x がこの条件を満たさないが，y が満たす場合は，to=[g,x,z, . . .] などとなる．
• var=[v1 , v2 , v3 , . . .] : 変数 x, y, z, . . . でなくて，v1 , v2 , v3 , . . . を用いる．変数名は数字を含まないことが望ましい．
• パラメータ ord, vl : グレブナー基底の求め方の指定– ord=0 : 全次数逆辞書式順序– ord=1 : 全次数辞書式順序– ord=2 : 辞書式順序（デフォルト）– ord=4 : 斉次化後に全次数逆辞書式順序– ord=5 : 斉次化後に全次数辞書式順序– ord=6 : 斉次化後に辞書式順序– vl=0 : 3 変数 (x,y,z) の場合 [z2,z1,y2,y1,z,y,x3,x2,x1,x]（デフォルト）– vl=1 : 3 変数 (x,y,z) の場合 [z2,y2,z1,y1,z,y,x3,x2,x1,x]– vl=2 : 3 変数 (x,y,z) の場合 [z2,z1,z,y2,y1,y,x3,x2,x1,x]– ord=-1 : 微分を一変数化してからグレブナー基底を用いる（オプション in 指定不可）– ord=-2 : 微分を一変数化してから割り算を用い，高速（オプション in 指定不可）– ord=-3 : 上と同じだが，より正確と思われる（オプション in 指定不可）– ord=-4 : 微分を一変数化してから終結式を用いる（オプション in 指定不可）• step=1 : パラメータ ord に負の値を指定したときに有効．戻り値 [[v1 , . . .],[p1 , . . .]] に対し，gr([v1 , . . .],[p1 , . . .],2) が求める単独方程式が最初の成分となるグレブナー基底．
• step=k : パラメータ ord に −2 以下の値を指定したときに有効．v1 , . . . の順に，k − 1 個の変数を減らした段階の上のような結果を求める（k が未知変数の個数の時は，最終結果を返す）．
• step=[s1 ,s2 ,d1 ,d2 ] : パラメータ ord に −2 以下の値を指定したときに有効．dbg=1 のときの表示される Step k1 − −k2 v d1 : d2 の段階の結果 R=[p1 ,p2 ,d1 1,d2 ,w] を返す．p1 , p2 は多項式で，d1 , d2 はそのときの v についての次数．w はそれらが 0 でないという条件を課した．
• dbg=1 : ord=-2 などのときに途中経過を表示する．
• dbg=2 : 上と同じだが，多項式の次数に加えて，多項式の項数，最高次の多項式の項数を表示する．
• dbg=3 : 上と同じだが，可約なものが現れたら，最後の既約な成分を選ぶ．そうでない場合は198

dbg=[3,[2,1,2]] のように指定する．[2,1,2] は現れる順に，可約なものの 2 番目，最初，2 番目の意味で 0 は最後を意味する．> は，計算結果の因数分解の計算の実行を示す．
• dbg=4 : 上と同じだが，可約なものが現れたら，そこで中止して結果を返す．可約なものは，可約分解された形で返す• in=1 : 方程式は導関数を含んだ以下の形で与える（未知関数の数と方程式の数とは異なってよい）．


f1 (t, x, y, z, . . . , x1, y1, z1, . . .) = 0,
f2 (t, x, y, z, . . . , x1, y1, z1, . . .) = 0,
f3 (t, x, y, z, . . . , x1, y1, z1, . . .) = 0,



..

.
• TeX=1 : （-f の負指定が無いとき）与えられた方程式と求めた方程式を TEX のソースとして返す．
• TeX=2 : （-f の負指定が無いとき）与えられた方程式と求めた方程式を TEX を用いて表示する．
• pages=1 : TEX 出力が複数ページにわたる長い式の場合に指定• 引数を [[f1 , f2 , . . . ],s] としてもよい．ただし s は文字列で, TEX のソースにタイトルとして最初に入る．

• 線型の場合は stoe() や mdivisor() が使える．
[0] os_md.baseODE([a*(y-x), x*(b-z)-y, x*y-c*z]);[x*x3+(-x1+(a+c+1)*x)*x2+(-a-1)*x1^2+(x^3+(c*a+c)*x)*x1+a*x^4+(-c*b+c)*a*x^2,[z2,z1,y2,y1,z,y,x3,x2,x1,x],[-a*y2+x3+a*x2,z2+c*z1-x*y1-y*x1,x*z1+y2+y1+(z-b)*x1,-a*y1+x2+a*x1,
z1-y*x+c*z,y1+(z-b)*x+y,x1+a*x-a*y],[x*x3+(-x1+(a+c+1)*x)*x2+(-a-1)*x1^2+(x^3+(c*a+c)*x)*x1+a*x^4+(-c*b+c)*a*x^2,
x1+a*x-a*y,-x2+(-a-1)*x1+(-a*z+(b-1)*a)*x,x3+(a+c+1)*x2+(x^2+a*z+(-b+c+1)*a+c)*x1+a*x^3+(-c*b+c)*a*x,a*y1-x2-a*x1,-a*y2+x3+a*x2,-a*z1+x*x1+a*x^2-c*a*z,a*z2-x*x2-x1^2+(-2*a+c)*x*x1+c*a*x^2-c^2*a*z]][1] os_md.baseODE([[a*(y-x), x*(b-z)-y, x*y-c*z],"Lorenz system :"]|TeX=2)$
Lorenz system : 0x = −ax + ay,
y 0 = (−z + b)x − y, 0z = yx − cz.
xx3 − x1 x2 + (a + c + 1)xx2 − (a + 1)x21 + x3 x1 + c(a + 1)xx1 + ax4 − c(b − 1)ax2 ,ay − x1 + ax,
axz + x2 + (a + 1)x1 − (b − 1)ax
[2] L=[[-a*x+(z+a)*y,(-z+b)*x-y,y*x-c*z],"Qi-Chen-Du-Chen-Yuan system]$[3] tstart$R=os_md.baseODE(L[0]|ord=-3,dbg=1)$tstop;[4]
Step 1-2 y 2:1,1:1,1:0
Step 1-1 y 3:1,2:1,1:1,1:0
Step 2-1 z 4:4,4:3,3:3,3:2,2:2,2:1,1:1,1:0[5] 20.66sec + gc : 6.141sec(26.84sec)[6] nmono(R[0]);4055[7] os_md.show(R[0]|var=[x3])$199

3 変数の上の例では，ord=-3 の指定で，x 変数以外の微分を消した式を 3 つ求め，つぎに z の変数を消した式を 2 つ（Step 1)，最後に y の変数も消すと (Step 2)，求める単独高階方程式が得られる．消したい変数の多項式とみてユークリッド互助法における割り算を行って，次数が減っていく様子が dbg=1で示される．

198. taylorODE(d|series=h,taylor=[s,t],runge=m,f=f ,c1=1,list=1,dif=1,lim=[h,n]):: dy/dx = f (x, y) の解の Taylor 展開と Runge-Kutta 法の解析
dyデフォルトでは dx= f (x, y) の解 y(x) の d + 1 階微分を求める．
• f の偏微分 fxxy を f21 のように表す．
• dif=1 : これを指定すると fxxy のように表される．
• series=h : y(x + h) の Taylor 展開を h の d 次の項まで求める．
• list=1 : y(x) の d + 1 次までの微分をリストで返す．高次の項からのリスト。
• taylor=[s,t] : f (x + s, y + t) の d 次までの Taylor 展開を返す．このとき, lim=[h,n] を指定
すると h について n 次を越える項は無視する．また，n を指定しないときは，d = n と解釈する．
• f=f : f は x, y で偏微分可能な函数で，series=h, list=1, taylor=[s,t] のいずれかを指定したときのみ有効．0 次の項の f は省略される．
• runge=m : series=h を指定したときのみ有効．
– m > 0 のとき，m 段の陽的 Runge-Kutta 法
k1 = f (x, y),ki = f (x + ci h, y +i−1Xai,ν kν h) (i = 2, . . . , m),ν=1ỹ(x, h) = y +mXbi k i h

i=1

に対し，ỹ(x, h) − y(x + h) の h に対する展開を d 次まで求める．
– m < 0 のとき，|m| 段の陽的 Runge-Kutta 法に対し，ỹ(x, h) − y(x + h) の h に対する d 次までの展開が消える条件を返す．
– c1=1 を指定すると，上で k1 = f (x + c1 h, y) に置き換える．

[0] os_md.taylorODE(2|list=1);[f_02*f_00^2+(f_01^2+2*f_11)*f_00+f_10*f_01+f_20,f_01*f_00+f_10,f_00][1] os_md.show(os_md.taylorODE(3|series=h,dif=1)|var=h,rev=1,small=1)$
y + f h + 12 (fy f + fx )h2 + 16 (fyy f 2 + (fy2 + 2fxy )f + fx fy + fxx )h3[2] os_md.taylorODE(2|f=cos(x+y^2),series=h);-sin(x+y^2)*cos(x+y^2)*h^2*y-1/2*sin(x+y^2)*h^2+cos(x+y^2)*h[3] os_md.show(os_md.taylorODE(3|taylor=[s,t],dif=1)|var=[s,t],rev=1,small=1)$
f + fx s + fy t + 12 fxx s2 + fxy st + 12 fyy t2 + 16 fxxx s3 + 12 fxxy s2 t + 12 fxyy st2 + 61 fyyy t3[4] os_md.taylorODE(2|series=h,runge=2,dif=1);(b_2*a_21-1/2)*f_y*h^2+(b_1+b_2-1)*h)*f+(b_2*c_2-1/2)*f_x*h^2[5] os_md.show(os_md.taylorODE(3|series=h,runge=-3)|opt="cr")$
b1 + b 2 + b3 − 1
1(2b2 c2 + 2b3 c3 − 1)2
1(2b2 a21 + 2b3 a31 + 2b3 a32 − 1)
2
200

1
(3b2 c22 + 3b3 c23 − 1)
61
(6b3 a32 c2 − 1)
61
(3b2 c2 a21 + 3b3 c3 a31 + 3b3 c3 a32 − 1)3
1
(6b3 a32 a21 − 1)
61
(3b2 a221 + 3b3 a231 + 6b3 a32 a31 + 3b3 a232 − 1)
6
199. pTaylor([f1 ,f2 , . . .],[x1 ,x2 , . . .],m|raw=1,time=t):: 常微分方程式 x0i = fi (x) (i = 1, 2, . . .) の m 次までのベキ級数解を返す
微分方程式

dxi
= fi (x1 , . . . , xn ) (i = 1, . . . , n)dtの t = 0 でのべき級数解を m 次まで求めて，サイズ n のベクトルで返す（xi の t = 0 での値は xi とする．
• 上で n = 1 のときは，[f1 ], [x1 ] は，単に f1 , x1 でよい．
• raw=1 を指定すると，tk の係数を長さ m + 1 の（k = 0 からの）リストで返す．
リストの成分は，長さ n のリスト．
• time=t を指定すると，t を t で置き換える．
• fi (x1 , . . . , xn ) は, t を含んでいてもよい．(t, x1 , . . . , xn ) の多項式であることが望ましい．

[0] os_md.pTaylor(x,x,6);[ (1/720*t^6+1/120*t^5+1/24*t^4+1/6*t^3+1/2*t^2+t+1)*x ][1] os_md.pTaylor(a*x^2,x,5);[ a^5*t^5*x^6+a^4*t^4*x^5+a^3*t^3*x^4+a^2*t^2*x^3+a*t*x^2+x ][2] os_md.pTaylor([y,-x],[x,y],5);[ (1/24*t^4-1/2*t^2+1)*x+(1/120*t^5-1/6*t^3+t)*y(-1/120*t^5+1/6*t^3-t)*x+(1/24*t^4-1/2*t^2+1)*y ][3] os_md.pTaylor([y,-x],[x,y],5|raw=1);[[x,y],[y,-x],[-1/2*x,-1/2*y],[-1/6*y,1/6*x],[1/24*x,1/24*y],[1/120*y,-1/120*x]][4] os_md.pTaylor(t+x,x,3|raw=1);[[x],[x],[1/2*x+1/2],[1/6*x+1/6]]
200. seriesHG([a1 ,a2 ,. . .],[b1 ,b2 ,. . .],p,k)seriesHG([[a1 ,. . .],[b1 ,. . .],[c1 ,. . .]],[[d1 ,. . .],[e1 ,. . .],[f1 ,. . .]],[x,y],k):: 一般超幾何級数 m Fn (a1 , a2 , . . . , am ; b1 , b2 , . . . , bn ; p) の pk 次の項まで求めるP(a1 )i+j ···(b1 )i ···(c1 )j ··· xi y j
または 2 変数の級数
0≤i+j≤k (d1 )i+j ···(e1 )i ···(f1 )j ··· i!j! を返す．
一般超幾何級数はm Fn (a1 , . . . , am ; b1 , . . . , bn ; x) =!
Qmai (ai + 1) · · · (ai + k − 1) xk
i=1
Qn
k!
j=1 bj (bj + 1) · · · (bj + k − 1)

∞
X
k=0

で与えられる．Gauss の超幾何級数は F (a, b, c; x) = seriesHG([a,b],[c],x,*) となる．
微分方程式は ghg() を，例は fctrtos() の [18] の項を参照．
2 変数の級数X0≤i+j≤k

Q Qi+jν
Q k Qi+jkν(ak + ν − 1) ·(dk + ν − 1) ·Q Qi
Q k Qiνk201(bk + ν − 1) ·ν (ek + ν − 1) ·Q Qj

(ck + ν − 1) xi y j
i! j!
ν (fk + ν − 1)

Qk Qjν
k

を得ることが出来る．
Appell の超幾何級数は 2 変数の級数でF1 (a; b, b0 ; c; x, y) = seriesHG([[a],[b],[b0 ]],[[c],[],[]],[x,y],*),
F2 (a; b, b0 ; c, c0 ; x, y) = seriesHG([[a],[b],[b0 ]],[[],[c],[c0 ]],[x,y],*),
F3 (a, a0 ; b, b0 ; c; x, y) = seriesHG([[],[a,b],[a0 ,b0 ]],[[c],[],[]],[x,y],*),
F4 (a; b; c, c0 ; x, y) = seriesHG([[a,b],[],[]],[[],[c],[c0 ]],[x,y],*).
201. isfctr(r):: 係数が有理数の有理式かどうかを返す[0] os_md.isfctr(2/3*(x+y)^2/z);
1[1] os_md.isfctr(1.5*(x+y)^2);0[2] os_md.isfctr((x+@i)^2);0202. fctrtos(r|var=ℓ,rev=1,dic=1,TeX=f ,dviout=1,lim=n,small=1,pages=1,add=s):: 有理式を因数分解した形の文字列に変換する• TeX=1 : LATEX のソースを出力する．このとき，多項式でなく有理式の場合は，分子と分母がリストで出力される．

• TeX=2, 3 : LATEX のソースを出力する．有理式のときは通常の \frac{ }{ } の文字列となるが，それが行幅制限を超えた場合は，\Bigl( \Bigr)\bigm/\Bigl( \Bigr) の形の文字列と途中に以下の項に述べる必要な改行が出力される．
• var=x : x の多項式として係数（有理式でもよい）を因数分解して表す．さらに，TeX=2（resp.
TeX=3）とすると，1 行の制限を越えないように，指定した変数のベキの後などに \\（resp. \\ &）が入る．より詳しくは，各項が 1 行の文字幅以内ならば，改行は項と項の間のみ．1 行の文字幅を超える項があれば，その前の項の後で改行し，さらに項の途中と（次の項があれば）その項の後に改行を入れる．
• var=[x, s] : 変数 x を文字列 s で置き換える．
• var=[x,y,...] : (x, y, . . .) の多項式とみなす．
• var=[[x, s],[y, t],...] : 上で，さらに x, y, . . . をそれぞれ文字列 s, t, . . . で置き換える．
• rev=1 : 変数を指定した場合, 通常は次数の高い単項式の順に表示されるが，それを逆順にする．
• dic=1 : 変数を指定した場合, 単項式のべき指数の辞書式順序で大きいものから表示する．
• dic=2 : 上と同じだが単項式の変数の積を変数の順序と逆にする．
• var="dif0" : 先頭が d で，その次が小文字のアルファベットで表されている変数を，先頭の d を除いた変数の微分作用素とみなす．オプション TeX を指定した場合，微分は ∂ を用いて，∂x1 のように表す．
• var="dif" : 上と同じであるが，TeX が指定されていて，微分する変数が 1 個のみで変数が 1 文字で表されているときは，微分を単に ∂ で表す．また微分する変数が 2 個以上あってもその変数名が全て辞書式順序で x0 と x99 の間にあるならば，微分は ∂0 や ∂99 などと表す．
d2∂3• var="dif1" : 上と同様であるが，TeX が指定されると微分は dx
2 または ∂x2 ∂y の様に表される．
• var="dif2" : 上と同様であるが，1 変数でも常微分の記号は用いず，偏微分の記号を用いる．
• lim=n : r が多項式のとき，LATEX のソースへの変換で 1 行が n 文字幅を越えないように（TeX=2
ならば）\\ または （TeX=1,3 ならば）\\ & で改行．ただし，後者でも先頭には & を付加しない．
なお，n が 0 以外の 30 以下の正数ならデフォルトの n =TeXLim と解釈される．n = 0 のときは文字幅制限は考慮しない．
• small=1: LATEX のソースへの変換で分数をテキストスタイルにする．
ただし，これによる 1 行の文字数制限の変化は考慮されない．

202• dviout=1 : dviout を用いて表示する．TeX=3 が指定されたとみなされる．
なお，画面表示するときは，show() が便利（オプションパラメータがそのまま有効）．
• pages=1 : TEX 出力で 1 ページに入らないような長大な式のときは，\begin{align*}... の数式環境を使って改ページを許す．pages=2 : 上と同じだが，\allowdisplaybreaks を必要に応じて入れる．（その行数の目安は，TeXPages で設定される.
• add=s : 各項の最後に文字列 s を入れる．s は式でもよい．
[0] S = os_md.fctrtos(1/(x-y)^2-1/(x+y)^2);
4*y*x/((x-y)^2*(x+y)^2);[1] eval_str(S);(4*y*x)/(x^4-2*y^2*x^2+y^4)[2] os_md.fctrtos(1/(x-y)^2-1/(x+y)^2|TeX=1);[4yx,(x-y)^2(x+y)^2][3] os_md.fctrtos(1/(x-y)^2-1/(x+y)^2|TeX=2);\frac{4yx}{(x-y)^2(x+y)^2}[4] os_md.fctrtos((x-a^4+1)^2|var=x);x^2-2*(a-1)*(a+1)*(a^2+1)*x+(a-1)^2*(a+1)^2*(a^2+1)^2[5] os_md.fctrtos((x-a^4+1)^2|var=x, TeX=1);
x^2-2(a-1)(a+1)(a^2+1)x+(a-1)^2(a+1)^2(a^2+1)^2[6] os_md.fctrtos((x+y+1/a)^2|var=[x,y],TeX=1);
x^2+2xy+y^2+\frac{2}{a}x+\frac{2}{a}y+\frac{1}{a^2}[7] os_md.fctrtos((x+y+a+b)^2|var=[x,y],TeX=1);
x^2+2xy+y^2+2(a+b)x+2(a+b)y+(a+b)^2[8] os_md.fctrtos((x+y+a+b)^2|var=[x,y],TeX=1,dic=1);x^2+2xy+2(a+b)x+y^2+2(a+b)y+(a+b)^2[9] os_md.fctrtos((x+y+a+b)^2|var=[x,y],TeX=1,rev=1);(a+b)^2+2(a+b)y+2(a+b)x+y^2+2xy+x^2[10] os_md.fctrtos((a+b+dx)^2|var="dif",TeX=1);\partial^2+2(a+b)\partial+(a+b)^2[11] os_md.fctrtos((a+b+dx1)^2|var="dif",TeX=1);\partial_{x_1}^2+2(a+b)\partial_{x_1}+(a+b)^2[12] os_md.fctrtos((a+b+dx)^2|var="dif1",TeX=1);\frac{d^2}{dx^2}+2(a+b)\frac{d}{dx}+(a+b)^2[13] os_md.fctrtos((a+b+dx)^2|var="dif2",TeX=1);\frac{\partial^2}{\partial x^2}+2(a+b)\frac{\partial}{\partial x}+(a+b)^2[14] os_md.fctrtos((a+dx+dy)^2|var="dif1",TeX=1);\partial_x^2+2\partial_x\partial_y+\partial_y^2+2a\partial_x+2a\partial_y+a^2[15] os_md.fctrtos((dx+dy)^2|var="dif1",TeX=1);\frac{\partial^2}{\partial x^2}+2\frac{\partial^2}{\partial x\partial y}+\frac{\partial^2}{\partial y^2}[16] os_md.fctrtos((x+2*y-z)^(20)+1|dviout=1)$[17] os_md.fctrtos((x+2*y-z)^(20)+1|var=z,dviout=1)$[18] os_md.fctrtos(os_md.seriesHG([a,b],[c],x,3)|var=x,rev=1,dviout=1)$[19] os_md.fctrtos((1/(alpha+beta)+dx+d)^4+1|var="dif1",dviout=1)$203

上の [18] の画面表示は

1+

b(b + 1)a(a + 1) 2 b(b + 1)(b + 2)a(a + 1)(a + 2) 3
ba
x+
x +
x
c
2c(c + 1)
6c(c + 1)(c + 2)

上の [19] の画面表示は，改行位置も含めて次のようになる．
4((α + β)d + 1) d36((α + β)d + 1)2 d24((α + β)d + 1)3 d
d4
+
+
+
4
3
2
2
dx
α+β
dx
(α + β)dx(α + β)3
dx
(
4
3
2 2
3
4 4
3
2
2
3 3
+ (α + 4βα + 6β α + 4β α + β )d + (4α + 12βα + 12β α + 4β )d + (6α2 + 12βα + 6β 2 )d2 + (4α)/()+ 4β)d + α4 + 4βα3 + 6β 2 α2 + 4β 3 α + β 4 + 1(α + β)4var= を指定して微分作用素として扱うと[20] os_md.fctrtos((1/(a+b)+dx1+dx2)^2|var="dif0",dviout=1)$[21] os_md.fctrtos((1/(a+b)+dx1+dx2)^2|var="dif",dviout=1,small=1)$[22] os_md.fctrtos((1/(b-a)+dx1+dx2)^2|var="dif2",dviout=1)$[23] os_md.fctrtos((1/(a+b)+dx+d)^2|var="dif",dviout=1)$[24] os_md.fctrtos((1/(a+b)+dx+d)^2|var="dif0",dviout=1)$[25] os_md.fctrtos((1/(a+b)+dx+d)^2|var="dif1",dviout=1)$[26] os_md.fctrtos((1/(a+b)+dx+d)^2|var="dif2",dviout=1,add="u")$[27] os_md.fctrtos((1/(a+b)+dx+d)^2|var="dif1",dviout=1,small=1)$
はそれぞれ以下のような表示となる．

∂x21 + 2∂x1 ∂x2 + ∂x22 +

2
2
1
∂x +
∂x +
a + b 1 a + b 2 (a + b)22
2
1∂12 + 2∂1 ∂2 + ∂22 + a+b∂1 + a+b∂2 + (a+b)
2

∂2
2
∂
∂
∂2
∂2
2
1
+2
−
+
−
+
2
2
∂x1
∂x1 ∂x2∂x2
a − b ∂x1
a − b ∂x2
(a − b)22(da + db + 1)
(da + db + 1)2
∂2 +
∂+
a+b
(a + b)22(da + db + 1)
(da + db + 1)2
∂x2 +
∂x +
a+b
(a + b)2d2
2(da + db + 1) d(da + db + 1)2
+
+
2
dx
a+b
dx
(a + b)2∂ 2 u 2(da + db + 1) ∂u (da + db + 1)2
+
u
+
∂x2
a+b
∂x
(a + b)22(da+db+1) d(da+db+1)
d2
dx2 +
a+b
dx +
(a+b)22[28] os_md.fctrtos((a+b+x+y)^2|var=[x,y],TeX=2);
x^2+2xy+y^2+2(a+b)x+2(a+b)y+(a+b)^2/* 変数 (x,y) の次数の順 */[29] os_md.fctrtos((a+b+x+y)^2|var=[x,y],dic=1,TeX=2);
x^2+2xy+2(a+b)x+y^2+2(a+b)y+(a+b)^2 /* 変数 x の次数の順 */[30] os_md.fctrtos((a+b+x+y)^2|var=[x,y],dic=2,TeX=2);
x^2+2yx+2(a+b)x+y^2+2(a+b)y+(a+b)^2 /* 変数 x の次数の順（ベキ表示逆順） */[31] os_md.fctrtos((a+b+x+y)^2|var=[x],TeX=2);
x^2+2(y+a+b)x+(y+a+b)^2
204

(20)
(21)
(22)
(23)
(24)
(25)
(26)
(27)

203. tohomog(r,[x1 , x2 , . . . ],y):: (x1 , x2 , . . .) の有理式に変数 y を導入して (y, x1 , x2 , . . .) の斉次式にする[0] os_md.tohomog((x^2+2*x+a*y)/(y+1), [x,y], t);(x^2+2*t*x+a*t*y)/(y+t)[1] P = subst(os_md.tohomog(x^2+a*x+b, [x], y), y, x-y);(a+b+1)*x^2+(-a-2*b)*y*x+b*y^2[2] subst(P, y, x-1);
x^2+a*x+bPPx の n 次 多 項 式 p(x) に 対 し p(x) =aj xj (x − c)n−j を 満 た す 多 項 式
aj xj y n−j は ，subst(tohomog(p, [x], y), y, (x − y)/c) で求められる．
204. substblock(p,x,q,y):: x の多項式 p, q に対し，y = q とおいて p を x の次数が mydeg(q,x) 未満の (x, y) の多項式に直す
p, y は有理式でもよい．y は x を含んではならない．
[0] os_md.substblock(x^4+a*x^3+2*x+1,x,x^2+1,y);(a*y-a+2)*x+y^2-2*y+2[1] subst(P,y,x^2+1);x^4+a*x^3+2*x+1205. invf([p1 , . . . , pn ],[x1 , . . . , xn ],[y1 , . . . , yn ]):: yj = pj (x) (j = 1, . . . , n) を xj = qj (y) (j = 1, . . . , n) と解く（逆函数）．
ただし，deg(pi , xj ) は，i = j のとき 1 で i < j のとき 0 でなければならない．
戻り値：[q1 (y1 ), . . . , qn (yn )]206. mydeg(p,x|opt=1), mydeg(p,[x,y]|opt=1):: deg(p,x) の拡張（x は 1 次，y は −1 次）．p は行列や配列で係数は有理式でよい．
• 有理式 p が x の多項式でなければ −2 を返す．
• p が行列のとき，オプション opt=1 により，戻り値 R において R[0] が次数で R[1] はその位置（の一つ）．

• 第 2 変数が [x,y] のときは，x を 1 次，y を −1 次とみなしたときの次数を返す．
• p = 0 のときは戻り値が −1.
[0] os_md.mydeg((a*x+b*x^2)^2/b^2,x);4[1] os_md.mydeg(0,x);-1[2] os_md.mydeg(x^2*dx/c+dx+1,[x,dx]);1207. mymindeg(p,x|opt=1):: p がスカラーのときは mindeg(p,x) と同じ．係数は有理式でよいが，p が行列などのスカラーでな
いときは 0 以外の成分の最小次数を返す．
• 有理式 p が x の多項式でなければ −2 を返す．
• p が行列やベクトルのとき，オプション opt=1 により，戻り値 R において R[0] が次数で R[1] はその位置（先頭から見て最初のもの．行列の場合は，1 行目の次が 2 行目という順）．
0 ではないが次数が 0 の項が複数あれば，その型が最小の位置を返す．
• 戻り値が−2 : x の多項式でなく，有理式である−3 : 零行列またはベクトルである

205

[0] os_md.mymindeg((a*x+b*x^2)^2/b^2,x);
2[1] A=newmat(2,2,[[x^2,0],[x,x]]);[ x^2 0 ][ x x ]
[2] os_md.mymindeg(A,x|opt=1);[1,[1,0]][3] A=newmat(2,2,[[x^2,y^2],[x,x]]);[ x^2 y^2 ][ x x ]
[4] os_md.mymindeg(A,x|opt=1);[0,[0,1]][5] os_md.mymindeg(0,x);0[6] os_md.mymindeg(x/(x+1)+a,x);-2[7] os_md.mymindeg(newmat(2,2),x);-3
208. iscoef(p,f ):: p の係数の全てが f (∗) 6= 0 を満たすかどうかチェックする• 多項式の係数が条件を満たすかどうかのチェックをして，0 または 1 を返す．
• P が有理式のときは，その分母と分子について，リストやベクトルや行列のときは，その成分全てが条件を満たすかどうかをチェックする．

[0] os_md.iscoef(1+1/2*x*y,os_md.isint); /* 整数係数？ */0[1] os_md.iscoef(1+1/2*x*y,os_md.israt); /* 有理数係数？ */1
209. mycoef(p,n,x):: coef(p,n,x) と同じ．n, x は同じ長さのリストでもよい．p は行列や配列で係数は有理式でよい．
• 戻り値は（有理式なら）既約に直される．
• p が x の有理式でなければ 0 を返す．
[0] os_md.mycoef((a+b*x)^2/b^2,1,x);(2*a)/(b)[1] os_md.mycoef((a+b*x)^2/b^2,2,x);
1[2] coef(x+a/b,1,x);0[3] os_md.mycoef(x+a/b,1,x);
1[4] os_md.mycoef(A,0,x);[ 0 1 ]
[ 0 0 ]
[5] os_md.mycoef(A,1,x);206

[ 1 0 ][ 0 1 ]
[6] os_md.mycoef((x/a+y+1)^3,2,x);(3*y+3)/(a^2)[7] os_md.mycoef((x/a+y+1)^3,[1,1],[x,y]);(6)/(a)210. pcoef(p,m,q)
pcoef(p,m,[[x1 , .., xn ],[m1 , . . . , mn ]]):: 多項式 pm を展開したときの単項式 q に対する係数を返す• p は多項式，m は非負整数．
• q は変数とベキのリストでもよい．
• p の変数が多く，さらに m が大きくて pm が計算不能な場合にも有効．
[0] P=(x+2*y+1)^2+w^2+z$[1] os_md.pcoef(P,8,x^2*y);3360[2] os_md.pcoef(P,8,[[x,y,z],[7,2,0]]);80640*w^3+887040*w^2+2306304*w+1647360
211. pmaj(p|var=t):: 多項式を単項式で表した係数を，全てその絶対値で置き換えた多項式を返す• var=t を指定すると，優多項式の変数を全て t で置き換えた t の多項式を返す．
• var=1 を指定すると，多項式の係数をすべて 1 で置換えた多項式を返す．
[0] os_md.pmaj(-x+2*y-2/3*x^2*y);
2/3*y*x^2+x+2*y[1] os_md.pmaj(-x+2*y-2/3*x^2*y|var=t);
2/3*t^3+3*t[2] os_md.pmaj(-x+2*y-2/3*x^2*y|var=1);
y*x^2+x+y[3] os_md.pmaj(1-y+(1+@i)*x^2*y);1.41421356237309504876*y*x^2+y+1
212. pfctr(p,x):: x の多項式または有理式 p の因数分解[0] os_md.pfctr((x^2-y^4)^3*(x-y^2/z)*y^2/((x*z-1)*z),x);[[(y^2)/(z^2),1],[x-y^2,3],[x+y^2,3],[z*x-y^2,1],[z*x-1,-1]]
213. cterm(p|var=[x,y, . . . ]):: 多項式の定数項を返す．変数を指定可能．
[0] os_md.cterm((x+y+a+2)^3);
8[1] os_md.cterm((x+y+a+2)^3|var=[x,y]);a^3+6*a^2+12*a+8[2] os_md.cterm((x+y+a+2)^3/(a+2)^4|var=[x,y]);(1)/(a+2)
214. terms(p,[x,y, . . . ]|rev=1,dic=1)
207

:: 多項式の存在する項の次数とべき指数のリストを返す
次数と各べき指数のリストの辞書式順序で大きい順に並べて返す．
• rev=1 : 小さい順に並べて返す• dic=1 : 最初の次数は無視してべき指数のみで比較する[0] os_md.terms((x^3+y^2+z)^2,[x,y]);[[6,6,0],[5,3,2],[4,0,4],[3,3,0],[2,0,2],[0,0,0]][1] os_md.terms((x^3+y^2+z)^2,[x,y]|dic=1);[[6,6,0],[5,3,2],[3,3,0],[4,0,4],[2,0,2],[0,0,0]][2] os_md.terms((x^2+y^1+z)^2,[x,y]|rev=1);[[0,0,0],[1,0,1],[2,2,0],[2,0,2],[3,2,1],[4,4,0]]215. pterm(p,[x1 ,x2 , . . . ],[m1 ,m2 , . . . ]):: 多項式の指定した変数が指定した次数となる項を返す[0] os_md.pterm((x^2+x-y-z+1)^4,[x,y],[2,1]);(-12*z^2+36*z-24)*y*x^2216. pweight(p,[x1 ,x2 , . . . ],[m1 ,m2 , . . . ]):: 多項式の変数に重みをつけて斉次式の成分に分解する• 次数と対応する項の組のリストを返す• [m1 ,m2 , . . . ] を単に 1 とすると，（通常の）同次式への分解となる[0] os_md.pweight((x^2-y-z+1)^2,[x,y],[1,-1]);[[4,x^4],[2,(-2*z+2)*x^2],[1,-2*y*x^2],[0,z^2-2*z+1],[-1,(2*z-2)*y],[-2,y^2]][1] os_md.pweight((x^2-y-z+1)^2,[x,y],1);[[4,x^4],[3,-2*y*x^2],[2,(-2*z+2)*x^2+y^2],[1,(2*z-2)*y],[0,z^2-2*z+1]]217. polcut (p,n,[x, y, . . . ]|top=m):: 変数のリスト [x, y, . . . ] の多項式 p から次数が（m 以上）n 以下でない項を削除[0] os_md.polcut((x+1)^5,3,x);10*x^3+10*x^2+5*x+1[1] os_md.polcut((x+y+1)^5,3,[x,y]|top=3);10*x^3+30*y*x^2+30*y^2*x+10*y^3218. mydiff(p,x):: diff(p,x) と同じ．p は行列や配列で係数は有理式でよい．x もリストでよい．
x = 0 のときは 0 を返す．
[0] os_md.diff(x+a/b,x);(b^2)/(b^2)[1] os_md.mydiff(x+a/b,x);
1[2] os_md.mydiff((x/a+y+1)^3,[x,y]);(6*x+6*a*y+6*a)/(a^2)
219. myediff(p,x):: ediff(p,x) と同じ．p は行列や配列で係数は有理式でよい．
x = 0 のときは 0 を返す．
220. mypdiff(p,[x1 ,f1 ,x2 ,f2 ,...]):: 合成関数の微分．
208

p は行列や配列で係数は有理式でよい．
P ∂pi ∂xi fi を返す．
[0] os_md.mypdiff([x,y],[x,a*y,y,-b*x]);[a*y,-b*x][1] os_md.mypdiff(@@,[x,a*y,y,-b*x]);[-b*a*x,-b*a*y][2] os_md.mypdiff(@@,[x,a*y,y,-b*x]);[-b*a^2*y,b^2*a*x][3] os_md.mypdiff(@@,[x,a*y,y,-b*x]);[b^2*a^2*x,b^2*a^2*y][4] os_md.mypdiff([x,y],[x,y^2,y,x^2]);[y^2,x^2][5] os_md.mypdiff(@@,[x,y^2,y,x^2]);[2*y*x^2,2*y^2*x]
221. difflog(L|var=x):: 対数微分を返す
a
L の j 番目の成分が [pj ,aj ] のときは qj = pj j とおき，有理式のときは qj = epj とおき，q = q1 q2 · · ·′に対して qq を返す．
微分の変数のデフォルトは x であるが，オプション var=で指定可能．

[0] os_md.difflog([[x-1,a],[x+1,b],c/x]);((a+b)*x^3+(a-b-c)*x^2+c)/(x^4-x^2)222. ptol(p,x|opt=0):: x の多項式 p の係数のリストを返す• p は多項式のリスト [p1 , p2 , . . .] でもよい．
• x が多変数のときは [x1 , x2 ] のように変数のリストを渡す．
• opt=0 は，リストから 0 の項が省かれる．
[0] os_md.ptol((x-1)*(x+1),x);[-1,0,1][1] os_md.ptol((a*x+b*y+c)^2,y);[a^2*x^2+2*c*a*x+c^2,2*b*a*x+2*c*b,b^2][2] os_md.ptol([a*x+b*y,(a*x+b*y+c*z)^2],[x,y]);[0,b,a,c^2*z^2,2*c*b*z,b^2,2*c*a*z,2*b*a,a^2][3] os_md.ptol([a*x+b*y,(a*x+b*y+c*z)^2],[x,y]|opt=0);[b,a,c^2*z^2,2*c*b*z,b^2,2*c*a*z,2*b*a,a^2]
223. pfrac(p,x|root=2,dviout=1,TeX=1):: x の有理式 p（の行列）を部分分数展開し，分子，分母（多項式とべき）の組のリストを返す• dviout=1 を指定すると，結果を dviout で表示する．
• TeX=1 を指定すると，上の LATEX のソースが得られる．
√√• root=2 を指定すると，x4 + (2c − r)x2 + c2 = (x2 + rx + c)(x2 − rx + c) のような分母の因数分解を許す．

• x は，[x, y,...] とすることによって，多変数を指定できる[0] os_md.pfrac((x^2+1)/((x-1)*(x-2)),x);[[1,1,1],[-2,x-1,1],[5,x-2,1]] % 1/1^1+(-2)/(x-1)^1+5/(x-2)^1
209

[1] os_md.pfrac(1/((x-a)^2*(x-b)),x);[ [(-1)/(a^2-2*b*a+b^2),x-a,1],[(1)/(a-b),x-a,2],[(1)/(a^2-2*b*a+b^2),x-b,1] ][2] os_md.pfrac(a/x+b/y+c/(x-y)+d*y/(x-1)+e/(y-1)+f,[x,y]);[[f,1,1],[e,y-1,1],[b,y,1],[c,x-y,1],[d*y,x-1,1],[a,x,1]]
pfrac(1/((x-a)^2*(x-b)),x|dviout=1) とすると，以下の表示を得る．
−

1
1
1
+
+
(a − b)2 (x − a) (a − b)(x − a)2(a − b)2 (x − b)pfrac(1/(x^4+1),x|dviout=1,root=2), pfrac(1/(x^6+1),x|dviout=1,root=2), とすると，次の = 以下の表示を得る．
√
√
x+ 2
x− 2
1
√
√
√
√
=
−
,
x4 + 12 2(x2 + 2x + 1) 2 2(x2 − 2x + 1)√√
1
3x + 23x − 2
1
√
√
=
.
−
+
6
2
2
2
x +1
6(x + 3x + 1) 6(x − 3x + 1) 3(x + 1)
[3] P=(-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-b*a$[4] os_md.pfrac(os_md.etos(P,x,[1,x]),x|dviout=1);
 


0 1
0
0
0 0
−ba −(a + b − c + 1)+xx−1224. lpgcd([p1 , p2 , . . . ]):: 多項式 p1 , p2 , . . . の共通因子を返す[0] os_md.lpgcd([(x+y)^3*(x-y),(x+y)^2*x^4,(x+y)^2*(x+y+z)]);x^2+2*y*x+y^2[1] os_md.lpgcd([0,0]);0[2] os_md.lpgcd([15/4,9/7,27/2]);
3[3] os_md.lpgcd([4/10,8]);2225. jacobian([f1 , . . . , fm ],[x1 , . . . , xn ]|mat=1):: 関数の組 (f1 , . . . , fm ) の変数 (x1 , . . . , xn ) についてのヤコビアン (m = n) またはヤコビ行列を返す[0] os_md.jacobian([x+y+z,x*y+y*z+z*x,x*y*z],[x,y,z]);(y-z)*x^2+(-y^2+z^2)*x+z*y^2-z^2*y[1] fctr(@@);[[1,1],[y-z,1],[x-z,1],[x-y,1]][2] os_md.jacobian([x+y+z,x*y+y*z+z*x,x*y*z],[x,y,z]|mat=1);[ 1 1 1 ][ y+z x+z x+y ][ z*y z*x y*x ]226. hessian([f ,[x1 , . . . , xn ]|mat=1):: 関数の組 f の変数 (x1 , . . . , xn ) についてのヘシアンまたはヘッセ行列を返す．
210

[0] os_md.hessian(x^3+x*y+y^3,[x,y]);36*y*x-1[1] os_md.hessian(x^3+x*y+y^3,[x,y]|mat=1);[ 6*x 1 ][ 1 6*y ]227. wronskian[f1 , . . . , fn ],x|mat=1):: 関数の組 (f1 , . . . , fn ) の変数 x についてのロンスキアンまたはロンスキー行列を返す．
[0] os_md.wronskian([cos(x),sin(x)],x);cos(x)^2+sin(x)^2[1] os_md.trig2exp(@@,x|inv=1);
1[2] os_md.wronskian([cos(x),sin(x)],x|mat=1);[ cos(x) -sin(x) ][ sin(x) cos(x) ]228. prehombf(p,q|mem=±1):: 概均質ベクトル空間の相対不変式 p の b 函数を得る．q は双対多項式.
• p = q のときは，q = 0 としてよい.
• q(∂x )p(x)s+1 = b(s)p(x)s に対し，fctr(b(s)) を返す.
• mem=1 を指定すると，速度よりメモリー使用量を優先する．
• mem=-1 を指定すると，上と同じだが，計算途中の進行状態も示す．
[0] os_md.prehombf(os_md.mydet(os_md.mgen(5,5,x,1)),0);[[1,1],[s+1,1],[s+2,1],[s+3,1],[s+4,1][s+5,1],][1] A=mgen(2,4,x,1);[ x11 x12 x13 x14 ][ x21 x22 x23 x24 ][2] os_md.prehombf(os_md.mydet(A*os_md.mtranspose(A)),0);[[4,1],[s+1,1],[s+2,1],[2*s+3,2]][3] os_md.prehombf(os_md.mydet(os_md.mgen(6,6,x,1)),0|mem=-1);
229. intpoly(p,x|exp=c,cos=c,sin=c):: 変数 x の多項式 p（またはそれと指数関数, 対数関数や三角関数の積）や有理式の原始函数を返す
Rx• p が多項式のときは，定数項のない多項式p(x) dx を返す
0R• exp=c を指定したとき，R p(x)ecx dx = q(x)ecx となる多項式 q(x) を返す• cos=c を指定したとき， p(x) cos cx dx = q(x) cos cx+r(x) sin cx となる多項式の組 [q(x), r(x)]を返す

R• sin=c を指定したとき， p(x) sin cx dx = q(x) cos cx + r(x) sin cx となる多項式の組 [q(x), r(x)]
を返す
R
c
c
• pow=c を指定したとき， p(x)x
R dx = q(x)x となる多項式 q(x) を返す• log=[c,d] を指定したとき， p(x) log(cx + d) dx = q(x) log(cx + d) + r(x) となる多項式の組[q(x), r(x)] を返すRPm• log=[c,d,m] を指定したとき， p(x) logm (cx + d) dx = j=0 qj (x) logm−j (cx + d) となる多項式のリスト [q0 (x), q1 (x), . . .] を返す (m は正整数)．
• c, d は複素数や x を含まない有理式でもよい．
• p が x の有理式の時，その原始関数を返す．ただし分母は x の 2 次以下の多項式の積に因数分解可能され，2 次多項式の判別式の定数倍は完全平方とする．

211

[0] os_md.intpoly(x^2/c+a/b,x);(b*x^3+3*c*a*x)/(3*c*b)[1] os_md.intpoly(x^2,x|exp=1);x^2-2*x+2[2] os_md.intpoly(x^2,x|sin=c);[(-c^2*x^2+2)/(c^3),(2*x)/(c^2)][3] os_md.intpoly(4*x,x|log=[1,1,2]);[2*x^2-2,-2*x^2+4*x+6,x^2-6*x-7][4] s_md.intpoly(2/(x^2+a^2)^2,x);(atan((x)/(a))*x^2+a*x+atan((x)/(a))*a^2)/(a^3*x^2+a^5)[5] os_md.intpoly(4/(x^2-a^2)^2,x);((log(x+a)-log(x-a))*x^2-2*a*x+(-log(x+a)+log(x-a))*a^2)/(a^3*x^2-a^5)[6] os_md.mycoef(R,1,log(x+1));
1[7] R=os_md.intpoly(1/(x^2-2),x);1/4*log((x-((2)^(1/2)))/(x+((2)^(1/2))))*((2)^(1/2))[8] os_md.sqrt2rat(diff(R,x));(1)/(x^2-2)
230. integrate(f ,x|dumb=k,dviout=p,log=1,frac=t,I=[a,b]):: 関数 f を変数 x について不定積分する
Rb• I=[a,b] : 定積分 a f dx を返す．
• 不定積分が求められなかった場合は，[] を返す．
• dumb=1 : メッセージを表示しない．
• dumb=-1 : 変数変換の過程を示す．
• dviout=1 : 結果の等式を TEX を使って表示する．変形過程を示す dumb=-1 の指定（以下と等価）が可能．

• dviout=2 : 結果を途中過程も含めて TEX を使って表示する．
– log=1 を指定すると，log | · · · | でなくて log(· · · ) とする．
– frac=t : を指定すると，函数で整理して分けての最終表示の仕方を変える．
iand(t, 1) : 使われる函数が一つの時のみ（函数の変数中の函数は無視）．
iand(t, 2) : より表示が短くなるときのみ．
iand(t, 4) : もとのまま．
iand(t, 8) : 函数の有理式のときも（デフォルトは多項式のときのみ）．
• dviout=-1 : f も含めた結果の TEX のソースを返す．変形過程を示す．
dumb=-1 の指定が可能．
• dviout=-2 : 結果の函数の TEX のソースを返す．
dumb=-1 を指定すると，変数変換の過程を含めてリストで返す．
リストの成分は途中結果を表す以下のリスト（その和が途中結果）のリストとなる．
– [x,f (x), . . .] : x を積分変数とする不定積分を表す（f (x), . . . の和）．
– [0,y,p(y),q(x)] : 変数 y を導入して p(y) = q(x) と置く．
なお，y = p(y) のときは，p(y) の項を省略可能．
– [1:f (x), . . .] : 積分結果を表す（f (x), . . . の和）．
以下ような関数の不定積分に対応（以下の有理式の積分に関連して，求まらない場合もある）．
• x の有理関数（分母が 2 次以下の多項式の積に因数分解される必要がある）• x および x の（複数個でもよい）1 次関数の sin, cos, exp を不定元とする多項式• 多項式と xc や ax との積，x と x の 1 次関数の log の多項式，さらにはそれらと前項の式との和212

• sin x, cos x, tan x の有理式．有理数 k を用いた sin kx や cos kx などが混ざっていてもよいZZ 
1 − t22t  2r(cos x, sin x)dx = R,
dt (t = tan x2 )1 + t2 1 + t 2 1 + t 2• r(x) arctan p(x) の形
ZZ
r(x) arctanm p(x) dx = r(x)dx · arctanm p(x)R
Z 0
p (x) r(x)dx−marctanm−1 p(x) dx
1 + p(x)2• arcsin, arccos, log においても上と同様な部分積分を行う．
• exp x や ex の有理式．有理数 k を用いた exp kx や ekx などが混ざっていてもよい
Z
Z
dy
kx
r(e )dx = r(y)(y = ekx )kyp• r x, c2 − (ax − b)2 で，r(x, y) が有理式
Z

• r x,

p

Z
p


2
2
r x, c − (ax − b) dx = r ac sin t + ab , c cos t ac cos t dt(ax − b)2 − c2 で，r(x, y) が有理式

Z
r x,
• r x,

p(x = ac sin t + ab )Z p(ax − b)2 − c2 dx = rcb c sin t  c sin t+ ,dt
a cos t a cos t a cos2 t

(x =

c
b
+ )
a cos t a(x =c sin tb
+ )a cos t a(ax − b)2 + c2 で，r(x, y) が有理式

Z
r x,

p


c2 + (ax − b)2 dx =Zr

 c sin t

b c  c+ ,dt
a cos t a cos t a cos2 tmn• r x, ( αx+βで，r(x, y) が有理式
γx+δ )

Z• r x,

√

m
n
dx =
r x, ( αx+β
γx+δ )

αx + β,

Z
r x,

p

√

Z

 δtn − β d δtn − β r − n, tm −
dt
γt − αdt γtn − α1n(t = ( αx+β
γx+δ ) )
γx + δ で，r(x, y, z) が有理式Zp
αx + β, γx + δ dx = r

t2 − δ
,γs

αt2 − αδ + βγ
,t
γ

!

2t
dt
γ

(t =

p

γx + δ)[0] os_md.integrate(x^2/c+a/b,x);(b*x^3+3*c*a*x)/(3*c*b)[1] os_md.integrate(x^2*exp(x),x);exp(x)*x^2-2*exp(x)*x+2*exp(x)[2] os_md.integrate(x*a^x,x);(((a)^(x))*log(a)^2*x-((a)^(x))*log(a))/(log(a)^3)[3] os_md.integrate(x^2*sin(c*x),x);(-cos(c*x)*c^4*x^2+2*sin(c*x)*c^3*x+2*cos(c*x)*c^2)/(c^5)[4] os_md.integrate(4*x*log(x+1)^2,x);(2*log(x+1)^2-2*log(x+1)+1)*x^2+(4*log(x+1)-6)*x-2*log(x+1)^2+6*log(x+1)
213

[5] os_md.integrate(2/(x^2+a^2)^2,x);(atan((x)/(a))*x^2+a*x+atan((x)/(a))*a^2)/(a^3*x^2+a^5)[6] os_md.integrate(4/(x^2-a^2)^2,x);((log(x+a)-log(x-a))*x^2-2*a*x+(-log(x+a)+log(x-a))*a^2)/(a^3*x^2-a^5)[7] os_md.integrate(1/(x^2-2),x);-1/4*log((x+((2)^(1/2)))/(x-((2)^(1/2))))*((2)^(1/2))[8] os_md.integrate(1/(x^4+1),x);(1/8*log(x^2+((2)^(1/2))*x+1)-1/8*log(x^2-((2)^(1/2))*x+1)+1/4*atan(((2)^(1/2))*x+1)+1/4*atan(((2)^(1/2))*x-1))*((2)^(1/2))[9] os_md.integrate(1/(x^6+1),x);(1/12*log(x^2+((3)^(1/2))*x+1)-1/12*log(x^2-((3)^(1/2))*x+1))*((3)^(1/2))+1/6*atan(2*x+((3)^(1/2)))+1/6*atan(2*x-((3)^(1/2)))+1/3*atan(x)[10] sqrt2rat(diff(@@,x));(1)/(x^6+1)[11] os_md.integrate(2*x*sin(x)*exp(x),x);(sin(x)-cos(x))*exp(x)*x+cos(x)*exp(x)[12] os_md.integrate(tan(x),x);-log(cos(x))[13] os_md.integrate(2*sin(2*x)*tan(2*x),x);-sin(2*x)+log((sin(x)+cos(x))/(sin(x)-cos(x)))[14] os_md.integrate(tan(x)^2,x);(-cos(x)*x+sin(x))/(cos(x))[15] os_md.integrate(1/(3*cos(x)+4*sin(x)),x);1/5*log((3*tan(1/2*x)+1)/(tan(1/2*x)-3))[16] os_md.integrate(atan(x),x);atan(x)*x-1/2*log(x^2+1)[17] os_md.integrate(6*(x^2+1)*atan(1/x),x);2*atan((1)/(x))*x^3+x^2+6*atan((1)/(x))*x+2*log(x^2+1)[18] os_md.integrate((2*b*x-a^2*x^2)^(-1/2),x);(asin((a^2*x-b*a)/(b)))/(a)[19] os_md.integrate((a^2-x^2)^(1/2),x);1/2*((-x^2+a^2)^(1/2))*x+1/2*asin((x)/(a))*a^2[20] os_md.integrate((x^2-1)^(-1/2),x);log(x+((x^2-1)^(1/2)))[21] os_md.integrate((x^2-1)^(1/2),x);1/2*((x^2-1)^(1/2))*x-1/2*log(x+((x^2-1)^(1/2)))[22] os_md.integrate((x^2+a^2)^(-1/2),x);log(x+((x^2+a^2)^(1/2)))[23] os_md.integrate(2*(x^2+a^2)^(1/2),x);((x^2+a^2)^(1/2))*x+log(x+((x^2+a^2)^(1/2)))*a^2[24] os_md.sqrt2rat(diff(@@,x));2*((x^2+a^2)^(1/2))[25] os_md.integrate(x^(1/2)/(x+1),x);2*((x)^(1/2))-2*atan(((x)^(1/2)))
214

[26] os_md.integrate(x^(1/3)/(x+1),x);3*((x)^(1/3))-atan(2/3*((3)^(1/2))*((x)^(1/3))-1/3*((3)^(1/2)))*((3)^(1/2))+1/2*log(((x)^(1/3))^2-((x)^(1/3))+1)-log(((x)^(1/3))+1)[27] os_md.sqrt2rat(diff(@@,x));(((x)^(-2/3))*x)/(x+1)[28] os_md.integrate(((2-x)/x)^(1/2),x);(((-x+2)/(x))^(1/2))*x-2*atan((((-x+2)/(x))^(1/2)))[29] os_md.integrate(1/(@e^x+@e^(-x)),x);atan(exp(x))[30] os_md.integrate((sin(x)*x+cos(x))/(cos(x)*x),x);log|x|-log|cos(x)|[31] os_md.integrate(asin(x)^2,x);(asin(x)^2-2)*x+2*asin(x)*((-x^2+1)^(1/2))[32] os_md.integrate(1/(x*log(x)),x);log(log(x))
上の [0]〜[32] では

Z x
0

Z

1 3
x + ab x,( 1c x2 + ab ) dx = 3cZx2 ex dx = (x2 − 2x + 2)ex ,Z(x log a − 1)ax
xax dx =,(log a)2Zx2 sin cx dx = (− 1c x2 + c13 ) cos cx + c22 x sin cx,

4x log2 |x + 1| dx = (2x2 − 2) log2 |x + 1| − (2x2 − 4x − 6) log |x + 1| + x2 − 6x,
Z
2 dx
1
x
x
= 3 arctan + 2 2,(x2 + a2 )2aa a (x + a2 )
Z

1
4 dx
2x
= 3 log |x + a| − log |x − a| − 2 2,222(x − a )aa (x − a2 )
√
√
Z
dx
2
x− 2
√ ,
=
log
x2 − 2
4
x+ 2
√
√
√
Z
√
√

dx
2
x2 + 2x + 1
2
√
+
2x
+
1)
+
arctan(2x − 1) ,=log
arctan(2x4 + 18
4
x − 2x + 1
Z
√
√
√

dx
= 123 log x2 + 3x + 1 − log x2 − 3x + 1
6
x +1
√
√
+ 61 arctan(2x + 3) + 16 arctan(2x − 3) + 13 arctan x,Zx sin x · ex dx = x(sin x − cos x) + cos x ex ,Ztan x dx = − log | cos x|,
Z
sin x
tan2 x dx =
− x,
cos x

215

Z

Z

3 tan x2 + 1
dx
1
= log
,
3 cos x + 4 sin x
5tan x2 − 3Zarctan x dx = x arctan x − 12 log(x2 + 1),

6(x2 + 1) arctan x1 dx = (2x3 + 6x) arctan x1 + x2 + 2 log(x2 + 1),Z11
a2 x − ab(2bx − a2 x2 )− 2 dx = arcsin
,
a
b
Z p

1 p 2
x
a2 − x2 dx =x a − x2 + a2 arcsin
,
2
a
Z
p
dx
√
= log x + x2 − 1 ,x2 − 1Z pp

1 p 2x2 − 1 dx =x x − 1 − log x + x2 − 1 ,
2
Z
p
dx
√
= log x + x2 + a2 ,x2 + a2Z ppp
2 x2 + a2 dx = x x2 + a2 + a2 log x + x2 + a2 ,
Z √
√
√
x dx
= 2 x − 2 arctan x,
x+1
Z √
3
√ √
√
√
√
√
√
√
x dx
3
= 3 3 x − 3 arctan( 2 3 3 3 x − 33 ) + 21 log | x2 − 3 x + 1| − log | 3 x + 1|,
x+1
r
r
Z r
2−x
2−x
2−x
dx = x− 2 arctan
,
x
x
x
Z
dx
= arctan exp(x),xe + e−xZx sin x + cos x
dx = log |x| − log | cos(x)|,x cos xZp
arcsin2 x dx = x arcsin2 x + 2 1 − x2 arcsin x − 2x,Zdx= log(log x)
x log xを得ている．

[33] os_md.integrate(1/(x^4+4),x|dviout=1,log=1)$
 2

Z
dx
1
1
1
x + 2x + 2=
arctan(x+1)+
arctan(x−1)+
log
x4 + 48
816
x2 − 2x + 2[34] os_md.integrate(((1-cos(x))/(1/2-cos(x)))^(1/2),x|dviout=2)$
Z − cos(x) + 1− cos(x) + 12

1
2

t = tan( 21 x)

dx

=

q
1
Z 4
3t2 −1 t
216

t2 + 1
√
3t =



dt

1
cos(s)



Z
=

−4

dx1
2
3 (sin(s)) − 4(u = tan(s))
Z
4
=
du
2
u +4
= 2 arctan( 21 u)1
2 sin(s)= 2 arctancos(s)
p1= 2 arctan( 2 3t2 − 1)
 q

2
1
1
= 2 arctan 2 3 tan( 2 x) − 1[35] os_md.integrate(x*sin(x),x|I=[0,@pi]);@pi[36] os_md.integrate(x^2*exp(-x),x|I=[0,"infty"]);2[37] os_md.integrate(log(x),x|I=[["+",0],1]);-1
上の [35]〜[37] でオプション dviout=1 を指定すると以下が得られる．

Z π

Z ∞
sin(x)x dx = π,0Z 1exp(−x)x2 dx = 2,0log(x) dx = 1.
0231. rungeKutta(f ,n,[a,b],y,y0 |mul=k,prec=1,single=1,val=1):: Runge-Kutta 法で常微分方程式 y 0 = f (x, y) の数値解を求める（f は連立も可）• 常微分方程式 y 0 = f (x, y) を，初期条件 y(a) = y0 で，区間 [a, b] を n 個等分して 4 次 Runge-Kutta
法によって解く．
戻り値は，各分割点 xν における xν と y(xν ) の値のリスト.
• b < a となることも許す．
• 変数が x でないときは，たとえば変数が t ならば [a,b] のところを [t,a,b] と指定する．
• mul=k を指定すると，k > 1 のときは，区間 [a, b] を kn 個等分して 4 次 Runge-Kutta 法を用いるが，n 等分点での値のみを返す．
• mul=-1 を指定すると，x = b での y の値のみを返す．
• prec=1 を指定すると，（f (x, y) が有理関数ならば）bigfloat で計算する．
• 連立のときは f , y, y0 をリストにする．たとえばdyj= fj (x, y1 , . . . , yn ) (j = 1, . . . , m)dx
ならば

rungeKutta([f1 , . . . , fm ],n,[a,b],[y1 , . . . , ym ],[y1 (a), . . . , ym (a)])とする．

• オプション val=1 では，xν と y の第 1 成分の組のみを返す．
• 単独高階のときは，たとえば
y (m+1) = f (x, y, y 0 , . . . , y (m) )のときはrungeKutta(f (x, y, y1 , . . . , ym ),n,[a,b],[y, y1 , . . . , ym ],[y(a), y 0 (a), . . . , y (m) (a)])とする．ただし f がリスト形式函数のときは，オプション single=1 を指定する．

217

• Runge-Kutta 法の評価については，taylorODE().
[0] os_md.rungeKutta(y,4,[0,1],y,1);[[0,1],[0.25,1.28402],[0.5,1.6487],[0.75,2.11696],[1,2.71821]][1] os_md.rungeKutta(-y,4,[0,-1],y,1);[[0,1],[-0.25,1.28402],[-0.5,1.6487],[-0.75,2.11696],[-1,2.71821]][2] os_md.rungeKutta(y,4,[0,1],y,1|mul=-1);
2.71821[3] ctrl("bigfloat",1)$setprec(30)$ /* 30 桁程度の精度 */[4] os_md.rungeKutta(y,10,[0,1],y,1|last=1,prec=1)-eval(@e);-2.0843238795813042532137297513e-06[5] os_md.rungeKutta(y,1000,[0,1],y,1|last=1,prec=1)-eval(@e);-2.2633479701115224079905528747e-14[6] tstart$os_md.rungeKutta(y,100000,[0,1],y,1|last=1,prec=1)-eval(@e);$tstop;[7] -2.2652151621929664998158339352e-22[8] 5.266sec + gc : 3.484sec(8.75sec)[9] os_md.rungeKutta(-y,4,[0,@pi/2],[y,dy],[1,0]); /* y’’=-y, y(0)=1, y’(0)=0 */[[0,1,0],[0.392699,0.923885,-0.382606],[0.785398,0.707176,-0.706967],[1.1781,0.382859,-0.923726],[1.5708,0.000294303,-0.9999]][10] os_md.rungeKutta(-y,4,[0,@pi/2],[y,dy],[1,0]|val=1);[[0,1],[0.392699,0.923885],[0.785398,0.707176],[1.1781,0.382859],[1.5708,0.000294303]][11] os_md.rungeKutta([y,-x],8,[t,0,@pi/2],[x,y],[1,0]);[[0,1,0],[0.19635,0.980785,-0.195088],[0.392699,0.923881,-0.382679],[0.589049,0.831473,-0.555564],[0.785398,0.707112,-0.707099],[0.981748,0.555579,-0.831461],[1.1781,0.382696,-0.923872],[1.37445,0.195106,-0.980779],[1.5708,1.91889e-005,-0.999997]][12] F0=[a*(y-x), x*(b-z)-y, x*y-c*z];Y=[x,y,z]; /* Lorenz system */[13] F=subst(F0,a,10,b,28,c,8/3);Y0=[1,2,3];[14] ctrl("bigfloat",1);setprec(50); /* 50 桁程度の精度 */[15] R=os_md.rungeKutta(F,1000,[t,0,30],Y,Y0|prec=1,mul=200)$[16] RR=os_md.rungeKutta(F,1000,[t,0,30],Y,Y0|prec=1,mul=10)$[17] D=map(os_md.lsub,os_md.lpair(R,R0))$[18] $E=map(os_md.dnorm,D)$L=map(os_md.nlog,E)$[19] for(LL0=[],T=H=30.0/1000,TL=cdr(L);TL!=[];TL=cdr(TL),T+=H)
LL0=cons([deval(T),car(TL)],LL0);[20] SS=os_md.xyplot(LL0,[0,30],[-12,0]|ax=[0,-12,5,1,0],scale=[4/10,2/3]);[21] RR=os_md.rungeKutta(F,1000,[t,0,30],Y,Y0|prec=1,mul=100)$[22] for(S=R,T=RR,D=[];S!=[];S=cdr(S),T=cdr(T))
D=cons(os_md.lsub([car(S),car(T)]),D);[23] D=reverse(D)$E=map(os_md.dnorm,D)$L=map(os_md.nlog,E)$[24] for(LL=[],T=H=30.0/1000,TL=cdr(L);TL!=[];TL=cdr(TL),T+=H)
LL=cons([deval(T),car(TL)],LL);218

[25] SS+=os_md.xyplot(LL,[0,30],[-12,0]|scale=[4/10,2/3],opt="red");[26] os_md.xyproc(SS|dviout=1);/* TeX を用いて表示 */Lorenz 方程式（カオス力学系）
 0
x = −a(x − y),y 0 = x(b − z) − y, 0z = xy − cz,(a, b, c) = (10, 28, 83 ),(x(0), y(0), z(0)) = (1, 2, 3),|x(t) < 20, |y(t)| < 25, 0 < z(t) < 40
誤差拡大率： e

0.90566tt ∈ [0, 30](∀t ≥ 0)(2.5 秒でほぼ 10 倍になる)

4 次 Runge-Kutta 法を用いたときの誤差のノルムの常用対数のグラフ(時間の分割数 :: 黒：10000 赤：100000)
0
−1
−2
−3
−4
−5
−6
−7
−8
−9
−10
−11
0

5

10

15

20

25

30 sec232. pwTaylor(f ,n,[a,b],x,x0 ,m|mul=k,prec=p,val=1,err=e,view=[[c0 ,c1 ,d0 ,d1 ],c,u],Inf=s):: 区分的な Taylor 展開で常微分方程式 x0 = f (t, x) の数値解を求める（f は連立も可）常微分方程式 x0 = f (t, x) を，初期条件 x(a) = x0 で，区間 [a, b] を n 個等分して, m 次までの Taylor
展開をつなげることによって解く（Taylor 法と呼ぶことにする）．
区間 [a, b] を n 等分した各点 tν における [tν , x(tν )] を返す．
• 変数が t でないときは，たとえば変数が z ならば [a,b] のところを [z,a,b] と指定する．
• mul=k を指定すると，区間 [a, b] を kn 個等分して計算するが，n 等分点での値のみを返す．
• mul=-1 を指定すると，x = b での y の値のみを返す．
• prec=1 を指定すると，bigfloat で計算する．
• prec=p を指定すると，p > 9 のときは，有効桁 p 程度の bigfloat で計算する．
• 連立のときは f , x, x0 をリストにする．たとえばdxj= fj (t, x1 , . . . , xN )dt

(j = 1, . . . , N ),ならば

pwTaylor([f1 , . . . , fN ],n,[a,b],[x1 , . . . , xn ],[x1 (a), . . . , xN (a)],m)
219

とする．

• オプション val=1 では，tν と x の第 1 成分の組のみを返す．
• err=e を指定すると，e が正整数のとき通常の戻り値と，誤差のノルムの常用対数のリストの 2 つを組にしたリストを返す．通常は e = 1 とする．
なお，mul=k （デフォルトは k = 1）の k を (|e| + 1)k に変更したものとの差を誤差と見なしている．通常誤差は (e + 1)m 分の 1 程度に減る．
誤差の常用対数の最大値は

os_md.lmax(os_md.pwTaylor(.......|...,err=1)[1])で得られる．

• err=[e, f ] のときは
– iand(f ,1)? : 常用対数でなくて，単に誤差とする．
– iand(f ,2)? : 相対誤差とする．
– iand(f ,4)? : 基準とした解をリストの最後に付加する．
• m や（正整数）k を変えて得られた 2 つの結果 R1 と R2 の区分点毎の解の差のノルムのリストを得るには以下のようにすればよい（但し，オプション Inf を指定していない場合）．
D=map(os_md.lsub,os_md.lpair(R1,R2)); /* 差のリスト */E=map(os_md.dnorm,D);/* 差のノルムのリスト*/
G=map(os_md.nlog,E);/* 差のノルムの自然対数のリスト */os_md.lmax(G);/* 差のノルムの自然対数の最大値 */H=map(os_md.dnorm,os_md.llget(R1,-1,[0])); /* R1 の成分のノルムのリスト */os_md.lsub([G,map(os_md.nlog,H)]);/* 差の相対ノルムの自然対数のリスト */• Inf=s : 解が [a,b] 内で爆発するときに指定
s=[s1 ,s2 ,s3 ,s4 ,s5 ] とすると, チェック後の精度を表す正整数パラメータ s2 に応じて，s1 分割
毎に爆発をチェックし，（必要に応じて複数回）時刻の進みを遅くし，分割の総数を s3 倍する（一回のみ）．s4 は標準のノルムで正数．s5 は err=を指定したとき，打ち切る相対誤差を s15 に設定する（デフォルトは，s5 = 10）．
デフォルトは，s =[100,2,2,1,10] で，Inf=1 のとき，このようになる．Inf=k のときは，
s =[100,2,k + 1,1,10] となる（1 ≤ k < 100）．
• 単独高階のときは，たとえばx(N +1) = f (t, x, x0 , . . . , x(N ) )ならば

pwTaylor(f (t, x, x1 , . . . , xN ),n,[a,b],[x, x1 , . . . , xN ],[x(a), x0 (a), . . . , x(N ) (a)],m)とする．ただし，xj は x(t) の j 階導関数．
戻り値は [tν ,x(tν ),x0 (tν ),. . .,x(N ) (tν )].
• view=[[c0 ,c1 ,d0 ,d1 ],c,u] を指定すると，Risa/Asir の Canvas で解がグラフ表示される．
[c0 , c1 ] はウインドウの x 座標の範囲，[d0 , d1 ] はウインドウの y の座標の範囲，c は色を示す文字
列（cf. trcolor()）または 0xff0000 などによる色指定（["red","green","blue"] とするとこの順に連続的に変化），u は表示の際の線型変換を与える数または行列．
このとき，wait=t を指定すると，Window 表示から 10t 秒後に描画が開始される．
– x がスカラーまたは長さ N が 1 のとき，あるいは，u が 1 × N 行列の時は，(t, u · x(t)) のグ
ラフ，x の長さ N が 2 以上のときは，u は 2 × N の行列で，ux(t) が表示される．
– u を省略した場合は，(t, x(t)) または (x1 (t), x2 (t)) が表示される．
– c と u は同時に省略できる．c を省略したときは，色は黒．
0– view=[[x0 ,y0 ,x1 ,y1 ,z0 ,z1 ],c,u] とすると，3 番目の成分 x3 (t) によって，定まる x3z(t)−z1 −z0の値によって色が連続変化する．

220

このとき，u が 3 × N 行列ならば，ux(t) = (y1 (t), y2 (t), y3 (t)) とおいたとき，色は y3 (t)で定まる (y1 (t), y2 (t)) の座標の点の描画となる．
– view=[] としたときは，デフォルトまたは前回までのものに従う．

[0] os_md.pwTaylor(y,4,[0,1],y,1,4);[[0,1],[0.25,1.28402],[0.5,1.6487],[0.75,2.11696],[1,2.71821]][1] os_md.pwTaylor([y,-x],8,[0,@pi/2],[x,y],[1,0],4);[[0,1,0],[0.19635,0.980785,-0.195088],[0.392699,0.923881,-0.382679],[0.589049,0.831473,-0.555564],[0.785398,0.707112,-0.707099],[0.981748,0.555579,-0.831461],[1.1781,0.382696,-0.923872],[1.37445,0.195106,-0.980779],[1.5708,1.91889e-005,-0.999997]][2] os_md.pwTaylor([y,-x],8,[0,@pi/2],[x,y],[1,0],10);[[0,1,0],[0.19635,0.980785,-0.19509],[0.392699,0.92388,-0.382683],[0.589049,0.83147,-0.55557],[0.78 5398,0.707107,-0.707107],[0.981748,0.55557,-0.83147],[1.1781,0.382683,-0.92388],[1.37445,0.19509,-0.980785],[1.5708,-3.13638e-015,-1]][3] os_md.pwTaylor(t,2,[0,2],[x,y],[1,1],16|mul=10);[[0,1,1],[1,2.16667,1.5],[2,4.33333,3]][4] os_md.pwTaylor(x,2,[0,2],[x,y],[1,1],16|mul=10);[[0,1,1],[1,2.71828,2.71828],[2,7.38906,7.38906]][5] os_md.pwTaylor(t+x,2,[0,2],[x,y],[1,1],16|mul=10);[[0,1,1],[1,2.89348,3.26136],[2,9.01592,10.1513]][6] os_md.pwTaylor(t+x+y,2,[0,2],[x,y],[1,1],16|mul=10);[[0,1,1],[1,4.02865,6.59649],[2,21.4886,35.9683]][0], [1]（[2] も同じ）は，それぞれ
 dy

dt = y.
y(0) = 1

 dx
 dt = y,
dy
= −x,
 dt
(x(0), y(0)) = (1, 0),t ∈ [0, 1],t ∈ [0, π2 ]という方程式を, 時間を 4 分割して考えている．
[3]〜[6] は，t ∈ [0, 1], x(0) = x0 (0) = 1 を満たす次の各方程式の解を考えている．

x00 = t,x00 = x,x00 = x + t,

x00 = x0 + x + t.

Lorenz 方程式の解の Canvas での表示
[7] ctrl("bigfloat",1)$setprec(50)$/* 精度 50 桁 */[8] F0=[a*(y-x), x*(b-z)-y, x*y-c*z];Y=[x,y,z];/* Lorenz eq. */[9] I=[0,60];Y0=[1,2,3];F=subst(F0,a,10,b,28,c,8/3);[10] os_md.pwTaylor(F,20000,[0,60],Y,Y0,16|prec=1,view=[[-25,25,-30,30],"red"]);/* 表示 */
[11] M=mat([1,0,0],[0,dcos(0.4),-dsin(0.4)]);221

[ 1 0 0 ][ 0 0.921061 -0.389418 ][12] os_md.pwTaylor(F,20000,[0,60],Y,Y0,16|prec=1,view=[[-25,25,-30,30],["red","green","blue"],M]);/* 異なる方向からの表示 */[13] os_md.pwTaylor(F,20000,[0,60],Y,Y0,16|prec=1,view=[[-25,25,-30,30,3,45],["red","blue"]]);/* z 座標を色で表示 */[7] では，0〜30 秒後までは赤から緑へ，30 秒後から 60 秒後までは緑から青へ，色が連続的に変化する．[9] は，z 座標が 3 から 45 に応じて，色が赤から青に連続的に変わる．

高精度数値計算[14] tstart$S=os_md.pwTaylor(-x,100,[0,2*@pi],[x,y],[0,1],24|prec=150,mul=100)$
tstop;/* x’’=-x, x(0)=0, x’(0)=1 */0.1875sec(0.094sec)/* 計算時間 0.1 sec */[15] deval(S[100][1]);-5.80565e-102[16] deval(1-S[100][2]);3.5075e-105[14] は

x00 = −x(x(0) = 0, x0 (0) = 1)の近似解の計算で，計算時間は 0.1 秒程度．解は (x(t), x0 (t)) = (sin t, cos t) であるが，数値計算された (x(2π), x0 (2π)) の精度は，100 桁以上ある．
なお，0.094sec が実行時間，0.1875sec が CPU 時間で，マルチコア CPU の場合は後者の方が長くなることがある．

爆発する解[17] tstart$R=os_md.pwTaylor(x^2,200,[0,2],x,1,16|mul=100,Inf=1,prec=50)$
tstop;/* x’=x^2, x(0)=1 */0.9531sec(0.672sec)/* 計算時間 0.672 sec */[18] N=length(R)-1;
400;[19] R[N][0];0.9999999999999999999999999997843807226498548405911/*
時刻*/[20] R[N][1];4637804245935279921830167185.543044313766311451401/*
値*/[21] (1/(1-R[N][0])-R[N][1])/R[N][1];4.746205248949667664772474469090176901097958325173e-17/* 相対誤差 */[22] R=os_md.pwTaylor(x^2,200,[0,2],x,1,16|mul=100,Inf=1,prec=1,err=[1,3])$[23] R[1][N];4.74576e-17/* 推定相対誤差 */[24] tstart$R=os_md.pwTaylor(x^2,200,[0,2],x,1,16|mul=100,Inf=5,prec=60,
err=[1,3])$tstop;/* 爆発時刻推定 */3.25sec(4.469sec)/* 計算時間 4.469 sec */222

[25] N=length(R[0])-1;
577[26] 1-R[0][N][0];/*推定爆発時刻の誤差 */
1.0112423953501852952512099120069481460519554327626908801126e-43[27] R[1][N];0.0918893/* 推定相対誤差 < 1/10 */[28] tstart$R=os_md.pwTaylor(t+x^2,200,[0,2],x,1,16|mul=100,Inf=5,prec=50,
err=[1,3])$tstop;[31.44sec(19.81sec)[29] N=length(R[0])-1;
570[30] R[1][N];0.101022[31] 1-R[0][N][0];0.06943549147394428369073207146771126523963134791296[17] は 0x = x2 ,x(0) = 1の解を [0, 2] の範囲で求めている．得た解の最後の時刻は，t0 = 1 − 2.15619 · · · × 10−28 で，x(t0 ) =1となり，t → 1 で爆発する．
4.6738 · · · × 1027 となり，これは 16 桁程度の精度．実際の解は x(t) = 1−t[17] では，[0, 2] の範囲を 200 分割し，さらにそれを 100 個に細分して計算しているので，1 秒を104 個に等分割している．但し，解が爆発に近づく（すなわち，細分あたりの解の予想される変化率が閾値を超える）と，それを押さえるため細分は細かくなっていく．ただし，このチェックは 100 細分毎（Inf=の第一成分で指定）で，結果も 100 細分毎（mul=で指定）に出力される．チェックの鋭敏性とチェック後の精度は Inf=の第二成分で調整される．
爆発が起きるので，デフォルトでは，細分の総個数は 2 倍（Inf=の第三成分で指定）されて，4 × 104となり，出力のデータは，401 個となる（爆発がなければ，201 個）．また，最初に分割が細かくなるのは 0.95 秒後で，x(0.95) = 20 のときであった．この状況は以下のグラフを参照．
なお，[24] で得た推定爆発時刻 R[0][N][0] は 43 桁程度の精度がある．

n 番目のデータの情報 (0 ≤ n ≤ 400)

30

1 秒あたりの細分個数の常用対数

2520

近似解の値の常用対数≑ 1−1時刻 の常用対数

15

相対誤差の常用対数の − 12 倍

10
5

0

50

100

150

200

223

250

300

350

400

爆発解の相対誤差は，爆発時刻の近辺では解の大きさにほぼ比例して拡大している（爆発時刻の誤差を考えれば予想されること．グラフの緑の線は (577,0.5) のあたりを通る）．

精度と計算時間• m 次の Taylor 法による精度は，分割の個数 nk の m 乗，すなわち (nk)m に比例すると考えてよい．
• 計算時間は，分割の個数 nk にほぼ比例する．m を増やすと計算精度が上がるが，計算時間は f で与えた方程式の複雑性に依存する．

rungeKutta() の項にある Lorenz 方程式の場合（T 秒後まで）
次数
分割 計算精度
T 最大誤差実行時間 (sec)rungeKutta
4
10000063 桁
30 0.547.22
rungeKutta
416000063 桁
30 0.09
83.47
589.5
rungeKutta
4 1000000
63 桁
30 6.0 × 10−5
pwTaylor
416000063 桁
30 0.12
1.51
pwTaylor
417000063 桁
30 0.09
1.56
pwTaylor
8
5100
63 桁
30 0.08
1.56
pwTaylor
10
1800
63 桁
30 0.06
0.89
pwTaylor
16
1100
63 桁
30 0.05
1.46
pwTaylor
16
20000
63 桁
60 2.4 × 10−7
26.57
pwTaylor
24
10000099 桁 120 1.5 × 10−9
283.2
pwTaylor
4
10000
63 桁
30 − − −−
0.93
pwTaylor
8
10000
63 桁
30 6.9 × 10−5
3.14
pwTaylor
10
10000
63 桁
30 2.1 × 10−8
4.93
pwTaylor
16
10000
63 桁
30 2.0 × 10−19
14.33
pwTaylor
20
10000
63 桁
30 5.5 × 10−27
24.36
pwTaylor
24
10000
63 桁
30 1.6 × 10−34
39.53
pwTaylor
32
10000
149 桁
30 5.8 × 10−50
76.94
関数

• 誤差 0.1 は，相対誤差が 1% 程度より小さいことを意味する．
• Lorenz 方程式のリアプーノフ指数から，10 秒につき誤差が約 104 倍程度に拡大することが分か
3
る．pwTaylor() によって 16 次で 1000
秒毎の分割では，30 秒後の誤差が 2 × 10−19 程度である．
−7
よって 60 秒後の誤差は 2 × 10 程度で，処理時間は 40 秒程度と予想されるが，実際上のようになる．
一方 4 次 Runge-Kutta では， 1017 秒までに細分すると，60 秒後の誤差は 0.1 程度に押さえられるが，所要時間は 3.5 × 105 秒 = 90 時間程度．120 秒後までの計算には，この 80 倍程度の時間がかかる（1024 ≑ 440 ）．
• なお，任意精度浮動小数計算の速度を調べると（用いたノートパソコン：2016 年製造, CPU Corei7-5600U 2.5/3.1 GHz）

E=eval(@e)$P=eval(@pi)$tstart$for(S=I=0;I<10000000;I++) S+=(E+I)*(P+I)^2;$
tstop;
により，積と和の計算 1000 万回の実行にかかった時間（秒数）は, 以下の表のようであった．

224

setprec
–

計算精度

実行時間

計算時間

倍精度

?
9
49
99
199
399
799
1599

3.17
10.40
19.11
20.99
22.69
27.42
37.92
59.70
110.33

0.00
7.23
15.94
17.82
19.52
24.24
34.75
56.53
107.16

10
50
100
200
400
800
1600

225

Lorenz 方程式30x − y 平面への射影
x0 = 10(y − x)





0


y = x(28 − z) − yz 0 = xy − 83 z
0 ≤ t ≤ 30





(x(0), y(0), z(0)) = (1, 2, 3)

−20

20

10

−10

0

10

20

−10

−20

F0=[a*(y-x), x*(b-z)-y, x*y-c*z];
I=[0,120];Y=[x,y,z];Y0=[1,2,3];
F=subst(F0,a,10,b,28,c,8/3);
R=os_md.pwTaylor(F,1000,I,Y,Y0,24|prec=1,mul=100);

−5
−10
−15

10 sec 以降はカオス的運動軌道
10 sec〜120 sec : y = 0.3948 · t − 57.91(相関係数 : 0.9993)
傾きの理論値は，0.3933|x| < 20, |y| < 25, 0 < z < 40

−20
−25
−30
−35

(時刻，誤差の常用対数) のグラフ
(時刻，相対誤差の常用対数) のグラフ
最大相対誤差 : 4.48 × 10−10

−40
−45
−50
−55
−60

0

10

20

30

40

50

60

70

80

90

100

110

120 sec

上で縦軸を自然対数にとった時の漸近的傾き（上の図の漸近的傾きの log 10 = 2.3026 倍）が Lyapunov
指数（Lorenz 方程式では 0.90566 ≑ 0.3948 × 2.3026 = 0.9091）．

226233. powsum(n):: 1n + 2n + · · · + mn の m を x で置き換えた n + 1 次多項式を返す[0] os_md.fctrtos(os_md.powsum(3));
1/4*x^2*(x+1)^2
234. bernoulli(n):: n 次の Bernoulli 多項式 Bn (x) を返す[0] os_md.fctrtos(os_md.bernoulli(3));
1/2*x*(x-1)*(2*x-1)
3.2.4 Functions with real/complex variables
以下の数値函数では変数（引数）を不定変数にすると対応するリスト形式函数を返す．

235. frac(x):: 実数 x の小数部分
pari(frac,x) と同等．
236. erfc(x) erfc([x,prec]) R
2∞:: 相補誤差函数 erfc(x) = √2π x e−t dtpari(erfc,x) または pari(erfc,x,prec) と同等．
237. fouriers([a0 ,a1 ,. . .,am ],[b1 ,b2 ,. . .,bn ],z|cpx=1,sum=f ,y=t,const=c)fouriers([f ,m],[g,n],z|cpx=1,sum=f ,y=t,const=c):: 有限 Fourier 級数 a0 + a1 cos z + a2 cos 2z + · · · + am cos mz + b1 sin x + b2 sin 2z + · · · + bn sin nz• cpx=1 のときは，a0 + a1 eiz + a2 e2iz + · · · + am eimz + b1 e−iz + b2 e−2iz + · · · + bn e−niz• [a0 ,a1 ,. . .,am ] の代わりに [f ,m] と指定することができ，このときは ak = myf2eval(f ,k,t)と解釈される（0 ≤ k ≤ m）．
ただし const=c を指定すると，a0 は c で与えられる．また，f の変数に y が含まれないときは，
y=t の指定は無視される.
• [b1 ,. . .,bn ] の代わりに [g,n] と指定することができ，このときは bk = myf2eval(g,k,t) と解釈される（1 ≤ k ≤ n）．
• sum=1 : チェザロ総和法を用いる．
• sum=2 : シグマ総和法を用いる．
• sum=s(x,y) : フーリエ級数の有限和
a0 +

n−1
X

s( nk , n)(ak cos kx + bk sin kx)

k=1kにおいて 1 とは限らない項 s( n, n) で調整して総和を取る総和法を行う．チェザロ総和法では，s(x,y) は 1 − x，シグマ総和法では sinπxπx を用いる．
sum=@e^(-t*x^2*y^2) : 熱方程式を満たすフーリエ級数の t 秒後の温度分布を示す．

[0] for(R=[],I=21;I>0;I--) R=cons((1-(-1)^I)/(2*I),R);[1] R;[1,0,1/3,0,1/5,0,1/7,0,1/9,0,1/11,0,1/13,0,1/15,0,1/17,0,1/19,0,1/21][2] F=os_md.fouriers([],R,x)$[3] os_md.xygraph(F,-192,[-3*@pi,3*@pi],0,[-1,1]|scale=[0.7,1.2],ax=[0,0],prec=6,
dviout=1);
P10
上の [2] は，次のようにしてもよい（ m=0 sin(2m + 1)x）．
[2] F=os_md.fouriers([],[(1-(-1)^x)/2/x,21],x)$227

fouriers([],[(1-(-1)^x)/x,n],x) : 方形波（最大値は π4 )
fouriers([],[-(-1)^x/x,n],x) : 鋸波（最大値は π2 )2fouriers([(1-(-1)^x)/x,n],[],x) : 三角波（最大値と最小値は ± π4 ）
fouriers([sin(x*y)/x/y,n],[],x|const=1/2,y=t) : 幅 2t の方形パルス波（t > 0 は十分小）
fouriers([2*(1-cos(x*y))/x^2/y^2,n],[],x|const=1/2,y=t) : 幅 2t の三角パルス波
fouriers([1,n],[],x|const=1/2) : ディリクレ核
fouriers([1,n],[],x|const=1/2,sum=1) : フェイエール核
fouriers([e^(-x^2*y),n],[],x|const=1/2,y=t) : 熱方程式の基本解[4] P=os_md.fouriers([],[(1-(-1)^x)/x,41],x|sum=@e^(-x^2*y^2/100))$[5] os_md.xygraph(P,-24,[0,@pi],0,[0,1.8]|ax=[0,0],prec=6,dviout=1)
上の /100 を /10, /3, /1, *3 とすると，順に以下が表示される．これは有限の長さの一定温度（たとえば 1000◦ ）の棒の両端を時刻 0 以降 0◦ に冷やしたときの温度分布の時間経過とみることができる．
1
t = 100

1
t = 10t = 13t=1

t=3

なお，片端のみ冷やして他端が断熱状態の時は，上の図を横に二分したものが温度分布の時間経過を与える．図示するのは，[5] の [0,@pi] を [0,@pi/2] に変更すればよい．

238. myexp(z):: 指数関数 exp(z)239. mysin(z):: 三角関数 sin(z)240. mycos(z):: 三角関数 cos(z)241. mytan(z):: 三角関数 tan(z)242. myasin(z):: 逆三角関数 asin(z)243. myacos(z):: 逆三角関数 acos(z)244. myatan(z):: 逆三角関数 atan(z)245. mylog(z):: 対数函数 log(z)246. nlog(z):: log10 (z)247. dlog10(x):: log10 (|x|)
log10 (|x|) を返す．x は 1000 桁の整数などの大きな有理数や 0 に近い有理数でもよい．
[0] os_md.dlog10(10^(3000)/2);
2999.7228

[1] os_md.dlog10(-10^(-3000)/2);-3000.3
248. mypow(z,w):: 巾関数 z w
mypow(0,w) は w に依らずに 0 を，mypow(z,0) は z 6= 0 のとき 1 を返す．
249. myarg(z):: 偏角 arg(z)偏角は, (−π, π] の範囲が返される．
z は平面の座標 (2 成分のリストかベクトル）でもよい．
[0] os_md.myarg(2-@i);-0.463648[1] os_md.myarg([2,-1]);-0.463648
指数関数，対数関数，三角関数，逆三角函数，mypow(), myarg() は，dexp(), dsin(), dcos(), dtan(),dacos(), dsqrt(), datan(), real(), imag() を組み合わせて実現されている．

250. sqrt(z) sqrt([z,prec]):: z の平方根を与える• pari(sqrt,z) または pari(sqrt,z,prec) と同等．
• prec は精度（桁数）を与える．
√√• z または −z が有理数 r となるときは，r あるいは r*@i を返す．
[0] os_md.sqrt(2);1.41421356237309504876[1] os_md.sqrt([2,30]);
1.414213562373095048801688724209698078568[2] os_md.sqrt(-1);(1.0000000000000000000*@i)[3] os_md.sqrt(@i);(0.70710678118654752438+0.70710678118654752438*@i)251. arg(z) arg([z,prec]):: z の偏角
pari(gamma,z) または pari(arg,z,prec) と同等．
[0] os_md.gamma(1);0.99999999999999999994[1] os_md.gamma(100000);
2.82422940796034787421 E456568[2] os_md.gamma(@i);(-0.15494982830181068512-0.49801566811835604271*@i)252. gamma(z) gamma([z,prec]):: ガンマ函数 Γ(z)pari(gamma,z) または pari(gamma,z,prec) と同等．
[0] os_md.gamma(1);0.99999999999999999994[1] os_md.gamma(100000);229

2.82422940796034787421 E456568[2] os_md.gamma(@i);(-0.15494982830181068512-0.49801566811835604271*@i)253. digamma(z) digamma([z,prec])′(z):: ディガンマ函数 ψ(z) = ΓΓ(z)pari(psi,z) または pari(digamma,z,prec) と同等．
254. lngamma(z) lngamma([z,prec]):: log(Γ(z))
pari(lngamma,z) または pari(lngamma,z,prec) と同等．
255. dilog(z)P∞ k:: ダイログ函数 Li2 (z) = k=1 zk2pari(dilog,z) と同等．
256. zeta(s) zeta([s,prec]):: zeta 函数 ζ(s)pari(zeta,s) または pari(zeta,s,prec) と同等．
257. eta(τ ) eta([τ ,prec])πiτ Q∞:: Dedekind の Eta 函数 η(τ ) = e 12 m=1 (1 − e2πimτ )τ は虚部が正の複素数．
pari(eta,τ ) または pari(eta,τ ,prec) と同等．
258. jell(τ ) jell([τ ,prec]):: Elliptic j-invariant j(τ )τ は虚部が正の複素数．
pari(jell,s) または pari(jell,τ ,prec) と同等．
3.2.5 Lists and vectors
259. lcut(l,m,n):: リスト l の部分リストを返す
m 番目から n 番目を抜き出して返す（初項は 0 番目）．
[0] L=[0,1,2,3,4,5,6,7,8,9]$[1] os_md.lcut(L,3,6);[3,4,5,6]260. llsize([m1 , m2 , . . .]):: リスト mj のリストに対し，成分 mj の個数と mj の要素の最大個数を返す[0] os_md.llsize([[1,2],[0,1,2,3],[1]]);[3,4]261. findin(m,[ℓ0 , ℓ1 , . . . ]):: m に等しい要素を ℓ0 , ℓ1 , . . . から探す
• 最初に見つかった番号を返す．存在しなければ −1 を返す．
• 2 番目の引数はリストでなくてベクトルでも可．
[0] os_md.findin("cat",["man","dog","cat","bird"]);[1] 2
参照：base position()262. lxor(m,[ℓ0 , ℓ1 , . . . ]):: m に等しい要素を除くが，それがなければ m を加える
リストの順序は変えない

230

[0] os_md.lxor(0,[1,0,2]);[1,2][1] os_md.lxor(0,[1,2]);[0,1,2]263. countin(s,m,[ℓ0 , ℓ1 , . . . ]|step=k):: s 以上 m 以下の {ℓ0 , ℓ1 , . . .} の要素の個数，間隔 m での個数分布表を返す最後の引数はリストでな
くてベクトルでも可．
step=k を指定すると，s から等間隔 m 毎に区切った |k| 個の区間に入る元の個数のリストを返す（m > 0 でなければならない）．
間隔の区切りと等しいものは，k が正の時は小さい方に入れて数え，負の時は大きい方に数える．ただし |k| = 1 のときは，データの最大のものを含む区間まで数える．

[0] os_md.countin(2,4,[1,2,3,4,5,2,0]);4[1] os_md.countin(0,0.5,[1.1,1.2,1.4,1.6,3.1,3.4,3.4,3.7]|step=1);[0,0,3,1,0,0,3,1][2] os_md.countin(0,0.5,[1.1,1.2,1.4,1.6,3.1,3.5,3.5,3.7]|step=-1);[0,0,3,1,0,0,1,3][3] os_md.countin(0,0.5,[1.1,1.2,1.4,1.6,3.1,3.4,3.4,3.7]|step=5);[0,0,3,1,0]264. lcount(ℓ):: リストの要素の重複度と要素の組のリストにする
戻り値は，要素の大きい順[0] os_md.lcount([1,2,2,3,4,5,2,0]);[[1,5],[1,4],[1,3],[3,2],[1,1],[1,0]]265. delopt(ℓ,s|inv=1) delopt(ℓ,[s1 ,s2 ,. . .]|inv=f ):: オプションリスト（リストのリスト）からオプション s（複数指定可）を削除，抽出，付加．
ℓ をリスト [ℓ1 , ℓ2 , . . .] とするとき，成分 ℓj がリストであって，ℓj の最初の成分が s に等しいときに ℓj
を除いたリストを返す．
複数のオプション s を指定するときは，それらをリストにまとめて指定する．
• 抜き出された結果の並びは，ℓ 内の順序を保つ．
• inv=1,2 : これを指定すると，ℓj の最初の成分が s に（s がリストの時は，そのいずれかに）等し
いもののみのリストを返す．
但し s がリストのリストの時（si がリストの時）は，s の成分 si と最初の成分同士が一致するものは置き換え，それが存在しない場合は付加する．s の各成分 si は重複せずに l の先頭から置き換
え，または l の先頭（inv=2 では末尾）に付加される．

[0] Opt=[["opt",1],["inv",0],["s",["title",2]]];[[opt,1],[inv,0],[s,[title,2]]][1] os_md.delopt(Opt,"opt");[[inv,0],[s,[title,2]]][2] os_md.delopt(Opt,"inv");[[opt,1],[s,[title,2]]][3] os_md.delopt(Opt,"inv"|inv=1);[[inv,0]][4] L=[[0,1,2],[1,2,3],[3,4,5],[4,5,6],[0,2,4]];231

[[0,1,2],[1,2,3],[3,4,5],[4,5,6],[0,2,4]][5] [2590] os_md.delopt(L,0|inv=1);[[0,1,2],[0,2,4]][6] os_md.delopt(L,[0,2]|inv=1);[[0,1,2],[0,2,4]][7] os_md.delopt(L,[0,3]|inv=1);[[0,1,2],[3,4,5],[0,2,4]][8] os_md.delopt(L,[0,3]);[[1,2,3],[4,5,6]][9] os_md.delopt(L,[[0,1,3],[2,3,4]]|inv=1);[[2,3,4],[0,1,3],[1,2,3],[3,4,5],[4,5,6],[0,2,4]][10] os_md.delopt(L,[[0,1,3],[2,1,4]]|inv=2);[[0,1,3],[1,2,3],[3,4,5],[4,5,6],[0,2,4],[2,1,4]][11] os_md.delopt(L,[[0,1,3],[0,1,4]]|inv=1);[[0,1,3],[1,2,3],[3,4,5],[4,5,6],[0,1,4]]
266. mycat([ℓ1 , . . . , ℓm ]|delim=s)267. mycat0([ℓ1 , . . . , ℓm ],t|delim=s):: ℓ1 , . . . , ℓm を表示する• delim で区切り記号（デフォルトは mycat() では空白，mycat0() では無し）を設定できる．
• t = 0 で非改行，t = 1 で改行．
[0] V=100$[1] os_md.mycat([V, (V>10)?"is":"is not","larger than 10."])$
100 is larger than 10.
[2] V=5$[3] os_md.mycat([V, (V>10)?"is":"is not","larger than 10."])$
5 is not larger than 10.
268. vtozv(v):: 有理式のベクトルをスカラー倍して単純化する• v が有理式のときは，それを長さ 1 のベクトルに自動的に直す• 各成分は整数係数で共通因子のない多項式になる• 戻り値：単純化されたベクトルとスカラー倍したスカラーのリスト[0] V=newvect(2,[-x*z/(2*y),-3*y*z^2/(5*x)]);[ (-z*x)/(2*y) (-3*z^2*y)/(5*x) ][1] os_md.vtozv(V);[[ -5*x^2 -6*z*y^2 ],(10*y*x)/(z)]269. l2p(l,v|size=s):: 係数のリスト l を与えて v の多項式を返す．またその逆変換を返す．
P• l がリストやベクトルの時は， j l[j]v j を返す．
• l は v の多項式の時は，係数のリストを返す．この時は，size=s でリストのサイズを指定できる．
[0] P=os_md.l2p([a,b,c],x);c*x^2+b*x+a[1] os_md.l2p(P,x);[a,b,c]232

[2] os_md.l2p(P,x|size=5);[a,b,c,0,0][3] os_md.l2p([1,1,1,1,1,1,1,1,1,1],1/2);
1023/512
270. mulseries(v1 ,v2 ):: ２つのベクトルをべき級数とみなして，その積のベクトルを返す
戻り値の長さは，両者のベクトルの長さの小さい方とする．
（cf. vprod()．
）
271. pluspower(p,x,r,m):: (1 + p)r の x に関するべき級数展開を第 m 項まで求める• p は定数項のない x の多項式．
• 戻り値は長さ m のベクトルで最初の成分の値は 1．
272. average(ℓ|sint=k)
average([ℓ1 ,ℓ2 ]|opt="co",sint=k):: 実数のリストに対し，平均値や標準偏差や相関係数を求める
戻り値は [平均値，標準偏差，個数，最小値，最大値] または，その 2 つのリストの前に相関係数をつけてリストにしたもの．
sint=k : k が自然数の時は，値を小数点以下 k 桁に丸める（sint() の第 2 引数）．

[0] L=[11,12,34,53,23,12,24,68,55,57,32,20]$[1] os_md.average(L);[33.4167,19.1505,12,11,68][2] os_md.average(L|sint=1);[33.4,19.2,12,11,68][3] os_md.average([L,[1,2,3,4,2,1,3,6,5,4,4,3]]|opt="co",sint=2);[0.92,[33.42,19.15,12,11,68],[3.17,1.46,12,1,6]]273. regress(ℓ|sint=k):: 実数の組のリストに対し，回帰直線を求める
戻り値は [回帰直線の傾き，回帰直線の切片，相関係数，平均値，標準偏差，平均値，標準偏差]．
sint=k : k が自然数の時は，値の有効桁を k 桁に丸める（sint() の第 2 引数）．
戻り値を [a,b,v1 , s1 , v2 , s2 ] とすると y = ax + b が回帰直線（x は第 1 成分，y を第 2 成分に対応，vi は第 i 成分の平均値，si は第 i 成分の標準偏差）274. vprod(v1 ,v2 )275. dvprod(v1 ,v2 ):: 2 つのベクトル（リストでもよい）の内積を返す• リストの長さが長大のときは，ベクトルにするか dvprod( ) を用いるのがよい．
• 成分が有理式のときは，分母の拡大を避けるため vprod( ) を用いるのがよい．
• vi がベクトル vi によって [vi,1 ,vi,2 ] となっているときは，vi,2 − vi,1 とみなされる．
[0] V1=newvect(3,[1,2,3]);[ 1 2 3 ][1] V2=newvect(3,[a,b,c]);[ a b c ][2] os_md.vprod(V1,V2);a+2*b+3*c[3] os_md.mulseries(V1,V2);[ a 2*a+b 3*a+2*b+c ][4] os_md.vprod([1/a^2,2/a,3/a],[a,b,c]);(2*b+3*c+1)/(a)233[5] os_md.dvprod([1/a^2,2/a,3/a],[a,b,c]);((2*b+3*c+1)*a^3)/(a^4)
276. llbase(v,ℓ):: 変数 ℓ[0], ℓ[1], . . . の一次方程式のベクトル v の標準変換を行う（例は lsol() の項を参照）
277. lsol(v,l):: 変数 ℓ[0], ℓ[1], . . . に関する連立一次方程式を解く
変数は，x3 のような変数の正整数ベキでもよい．ベキが異なるとき異なる変数とみなす．
v, l はリストでもよい．戻り値 r は v と同じ長さのベクトル．
• ℓ が変数で v が ℓ の一次式でもよい．そのときは答えの式を返す．
• 戻り値 r の後部にスカラー成分があれば，それらがすべて 0 となるときのみに解が存在することを意味する．

[0] V = [x+2*y-2,3*x+4*y-1,x+y-k]$[ x+2*y-2 3*x+4*y-1 x+y-k ][1] os_md.llbase(V,[x,y]);[ -x+2*k-2 -y-k+2 -2*k-1 ][2] os_md.lsol(V,[x,y]);[ [x,2*k-2] [y,-k+2] -2*k-1 ][3] os_md.lsol(V,[x,y,k]);[ [x,-3] [y,5/2] [k,-1/2] ][4] V = newvect(2, [a*x+b*y-e, c*x+d*y-d]);[ a*x+b*y-e c*x+d*y-d ][5] os_md.lsol(V,[x,y]);[ [x,(-d*b+e*d)/(d*a-c*b)] [y,(d*a-e*c)/(d*a-c*b)] ][6] VV = subst(V,y,x^2);[ b*x^2+a*x-e d*x^2+c*x-f ][7] os_md.lsol(VV,[x^2,x]);[ [x^2,(d*a-e*c)/(d*a-c*b)] [x,(-d*b+e*d)/(d*a-c*b)] ][8] os_md.lsol(a*x+b*y+c,x);(-b*y-c)/(a)[9] os_md.lsol([x+y,x-y,x],[x,y]);[ [x,0] [y,0] 0 ][10] os_md.lsol([x+y,x-y-2,x],[x,y]);[ [x,1] [y,-1] -2 ][11] os_md.lsol([y,y-1,y+2],[x,y]);[ [y,0] -1 2 ]278. lnsol(v,l):: 変数 ℓ[0], ℓ[1], . . . に関する連立一次方程式の有理数解を求める
変数は，x3 のような変数の正整数ベキでもよい．ベキが異なるとき異なる変数とみなす．なお v は多項式のリストとする．

[0] P=(a-1)*x+(a+1)*y-2*a+3;(a-1)*x+(a+1)*y-2*a+3[1] os_md.lnsol([P],[x,y]);[ [x,5/2] [y,-1/2] ]234

279. lchange(ℓ,k,v|flat=1):: （多重）リスト ℓ の k で指定した位置の成分を v に置き換える• k はリストで，重複の深さの成分がある．k が数のときは，[k] とみなす．なお，0 は最初の成分．
• flat=1 を指定したとき，k = [k1 , k2 , . . .], v = [v1 , v2 , . . .] ならば，ℓ[kν ] を vν （ν = 1, 2, . . .）で置き換えたリストを返す．

[0] L=[[1,2,3],[4,5,6],[7,8]]$[1] os_md.lchange(L,[1,0],0);[[1,2,3],[0,5,6],[7,8]][2] os_md.lchange(L,[2],[7,8,9]);[[1,2,3],[4,5,6],[7,8,9]][3] os_md.lchange(L,[1,0],[4,5]|flat=1);[5,4,[7,8]]280. lsum([m1 , m2 , . . .]):: m1 , m2 , . . . の和を返す• 引数はリストでなく，ベクトルや行列でもよい[0] os_md.lsum([1,2,3,4,5]);15[1] os_md.lsum(["1","2","3","4","5"]);12345
281. lextn([m1 ,m2 , . . .]|uniq=1):: 整数のリストの区間表現を展開して返す• mi が [mi,1 ,mi,2 ] となっていたら，mi1 と mi2 の間の整数を表す. ただし，[mi,0 ] は，mi,0 を表す• uniq=1 : 整数の列をソートし，重複があれば除いて返す[0] os_md.lextn([[1,4],7,[6,9],[3]]);[1,2,3,4,7,6,7,8,9,3][1] os_md.lextn([[1,4],7,[6,9],[3]]|uniq=1);[1,2,3,4,6,7,8,9]282. llextn([ℓ1 ,ℓ2 , . . .]):: 整数の区間表現のリストを整数のリストのリストにℓi は区間を表す 2 成分の整数のリスト
ただし，区間を表すリスト [m,n] を指定した場合は，それを展開して返す．
[0] os_md.llextn([[2,5],[3,4],[4,8]]);[[2,3,4,5],[3,4],[4,5,6,7,8]][1] os_md.lextn([[2,5],[3,4],[4,8]]);[2,3,4,5,3,4,4,5,6,7,8][3] os_md.llextn([2,5]);[2,3,4,5][4] os_md.llextn([5,2]);[2,3,4,5]283. lmax([m1 , m2 , . . .]):: m1 , m2 , . . . の中の最大のものを返す

235

284. lmin([m1 , m2 , . . .]):: m1 , m2 , . . . の中の最小のものを返す• 引数はリストでなく，ベクトルや行列でもよい[0] os_md.lmax([1,5,4,2,3]);5[1] os_md.lmin([1,5,4,2,3]);
2[3] A=mat([1,3],[5,2]);[ 1 3 ]
[ 5 2 ]
[4] os_md.lmax(A);5[5] os_md.lmin(A[1]);2285. lmaxsub([ℓ1 ,ℓ2 , . . .]|min=1]):: 包含関係で極大（極小）のリスト ℓi の全体を返す
286. lgcd([m1 , m2 , . . .]|poly=1]):: m1 , m2 , . . . の最大公約数（元）を返す
287. llcm([m1 , m2 , . . .]|poly=1,poly=[x1 , x2 , . . .],dn=1]):: m1 , m2 , . . . の最小公倍数（元）を返す• poly=1 を指定すると，要素を多項式とみなす．
• poly=[x1 , x2 , . . .] を指定すると，要素を x1 , x2 , . . . の多項式とみなす．
• dn=1 を指定すると，要素の分母に対する答を返す．
• 引数はリストでなく，ベクトルや行列でもよい．
• llcm() において，成分が 0 の元は無視される（ilcm() と異なる）．
[0] os_md.lgcd([-6,9,-24]);3[1] os_md.llcm([-6,9,-24]);72[2] os_md.lcmd([2/6,-5/4]|dn=1);12[3] os_md.lgcd([(x+y)^2,x^2-y^2]|poly=1);x+y[4] os_md.llcm([(x+y)^2,x^2-y^2]|poly=1);
x^3+y*x^2-y^2*x-y^3[5] os_md.lcmd([a*x*(y+1)^2,b*x^2*(y+1)]|poly=1);(b*a*y^2+2*b*a*y+b*a)*x^2[6] os_md.lcmd([a*x*(y+1)^2,b*x^2*(y+1)]|poly=[x,y]);(y^2+2*y+1)*x^2[7] os_md.lcmd([a*x*(y+1)^2,b*x^2*(y+1)]|poly=[x]);x^2[8] os_md.lcmd([a*x*(y+1)^2,b*x^2/(c+d)]|poly=[x]);x^2[9] os_md.lcmd([a/(x*(y+1)^2),(c+d*x)*x/(b*x^2)]|poly=[x],dn=1);236

x288. ldev(ℓ,s):: リスト s の整数倍をリスト ℓ に加えて，成分の絶対値を最小にする• ℓ + ms が求めるものとするとき，[m, ℓ + ms] 返す．
[0] os_md.ldev([1,3,5,9],[1,-1,1,-1]);[1] [2,[3,1,7,7]]289. qsortn(ℓ):: 大きい順のクイックソート[0] os_md.qsortn([3,4,2,1,5,0]);[5,4,3,2,1,0]290. rsort(ℓ,s,k):: ネストされたリスト ℓ のリカーシブソート• 深さのレベル s 以下のリストはソートしない．
• k = 1 は逆順ソート• s ＝ 0, k = 2 は，深さが奇数のリストのみをソート．
• s ＝ 1, k = 2 は，深さが偶数のリストのみをソート．
• s ＝ 0, k = 3 は，深さが奇数のリストのみを逆順ソート．
• s ＝ 1, k = 3 は，深さが偶数のリストのみを逆順ソート．
[0] L=[[[3,2,1],[2,5]],[1,3]];[[[3,2,1],[2,5]],[1,3]][1] os_md.rsort(L,0,0);[[1,3],[[2,5],[1,2,3]]][2] os_md.rsort(L,0,1);[[[3,2,1],[5,2]],[3,1]][3] os_md.rsort(L,1,1);[[[3,2,1],[5,2]],[3,1]]
291. isort(ℓ,f ):: ℓ のインデックスソート• ℓ のサイスが n のとき，戻り値 r は長さ n のベクトルで，ℓ(r[0]), ℓ(r[1]), . . . がソートされた順序となる．ソートでの並び替えの情報が得られるが，ℓ 自身は変えない．
• f はソートに用いる関数．ただし f に 1 を指定するとデフォルトの比較順序，−1 を指定するとデフォルトの逆順となる．

[0] os_md.isort(["b","d","a","c"],1);[ 2 0 3 1 ][1] os_md.isort(["b","d","a","c"],-1);[ 1 3 0 2 ]292. llselect(ℓ,n,k|eq=1,val=1):: 表形式のリストを成分の条件で分割する
成分の条件で分割して，リストを分ける．
• n 番目の成分をキーとする• n =[n0 ,[n1 ,n2 ]] : n0 番目の成分の n1 文字目から n2 文字目までをキーとする（n1 = 0 のときは先頭文字から）• eval=1 : 文字列を数値などの値に変換してキーとする

237

• k = 0 のときは，キーでリストでリストを分割する．
• k がリストでないときは，k は [k] で置き換えられる• k=[k1 ,k2 , . . .] : キーが文字列であるか eq=1 が設定されているならば k の中にあるリストを選ん
で残りと 2 分割• 上でなくて k = [k1 , k2 ] のとき，キーが k1 と k2 の間にあるものを選んで残りと 2 分割
• div=1 が指定され，k =[k1 ,k2 , . . .] のときは，Li =llselect(ℓi ,n, ki );ℓi+1 =Li [1] を実行し，[car(L1 ),car(L2 ), . . .] を返す．残りが空でなければ最後に残りのリストを付加する．
293. llget(ℓ,[a1 ,a2 ,. . .],[b1 ,b2 ,. . .]|flat=1):: 表形式のリストから行や列を抽出• [a1 ,a2 ,. . .] : a1 行目，a2 行目，. . . を抽出
aj =[c1 ,c2 ] : c1 , c1 + 1, . . . , c2 を意味する.
aj =[c1 ] : c1 行目以降最後までを意味する．
[a1 , . . .] の代わりに単に 1 のときは行の操作は行わない[b1 , . . .] の代わりに単に −1 のときは，抽出でなくて削除とする．
• [b1 ,b2 ,. . .] : b1 項目，b2 項目，. . . を抽出
bj =[c1 ,c2 ] : c1 , c1 + 1, . . . , c2 を意味する
bj =[c1 ] : c1 項目以降最後までを意味する．
[b1 , . . .] の代わりに単に 1 のときは項目の操作は行わない.
[a1 , . . .] の代わりに単に −1 のときは，抽出でなくて削除とする．
• flat=1 : 結果の内部のリストをほどいて返す．
[0] L=[[1,2,3,4],[5,6,7,8],[9,10,11,12]]$[1] os_md.llget(L,[2,1],1);[[9,10,11,12],[5,6,7,8]][2] os_md.llget(L,[[1]],1);[[5,6,7,8],[9,10,11,12]][3] os_md.llget(L,[[1]],-1);[[1,2,3,4]][4] os_md.llget(L,[1,2],[0,1]);[[5,6],[9,10]][5] os_md.llget(L,[1,2],[[0,2]]);[[5,6,7],[9,10,11]][6] os_md.llget(L,1,[1]);[[2],[6],[10]][7] os_md.llget(L,1,[1]|flat=1);[2,6,10]294. sort2([m1 ,m2 ]):: 2 成分のリストまたはベクトルの成分を小さい順に並び替える
295. lsort(ℓ1 ,ℓ2 ,t|c1=[c1,0 ,c1,1 , . . . ],c2=[c2,0 ,c2,1 , . . . ]):: リスト ℓ1 に対し，ℓ2 との合併，共通部分，または ℓ2 や共通部分を除く
その他，表形式データの操作· ℓ がリストで，t が数または文字列のとき．
• 小さい順にソートされたリストを返す．
• ℓ2 = [] で t = 0 または "cup" のときは l1 をソート，
t = 1 または"setminus"のときは，さらに重複を除く．
t = 7 または"cut"のときは c1=k で ℓ1 を最初の k 個の要素と残りの要素の 2 つのリストに分割する．ただし k が負の数のときは，最後の |k| 個を除いた要素と最後の |k| 個の要素との 2 つに分割

238

する．
t = 8 または"count"のときは，ℓ1 の要素数と，それの重複を除いた要素数の組のリストを返す．
• t = 0, 4, "cup" または "sum" のときは ℓ2 の要素を合わせ（て重複を除い）たリスト• t = 1, "setminus" の と き は ℓ2 に 含 ま れ な い ℓ1 の 要 素 の（ 重 複 を 除 い た ）リ ス ト（cf. base prune()）• t = 2, "cap"のときは，共通の要素の（重複を除いた）リスト• t = 3, "reduce" のときは，同じものを同数消した最小リストの組を返す．
• t = 8, "count" のときは，ℓ1 , ℓ2 の要素数，それぞれで重複を除いた要素数，共通の要素の要素
数，同じものを同数消した最初リストの要素数の 8 個の数のリストを返す．
• t = 9 または"cons"で，ℓ1 がリストのリストのときは，ℓ1 の各要素の先頭に ℓ2 の要素を順に付加
する．ℓ2 の要素の数が ℓ1 の要素より少ないときは，ℓ2 の要素の不足部分は，その最後の要素が続いているとみなす．ℓ2 がリストでないときは，それのみを要素とするリストとみなす．
• t = 10 または"cmp"で，ℓ1 と ℓ2 の違い（その位置と内容の 3 つ組）のリストを出力する．ℓ1 , ℓ2
はリストまたはリストのリスト．
t = 11 または"append"で，ℓ1 , ℓ2 がリストのリストのとき，要素を append したリストを返す．
· t =[t0 ,t1 ,. . .] がリストで，ℓ1 がリストのリストのとき
t0 については，上の t と同様の指定が可能で，以下のようになる．（エクセルの表のようなものの操
作. cf. readcsv()）. また t =[] は，[0] と解釈される．
• ℓ2 =[] または "sort" のとき– t0 = 0 または "put" のときはリストの要素の t1 番目の項をキーとしてソートする（逆順ソー
トでは，−t1 − 1 を指定する）– t0 = 3 または "reduce" のときは，キーが同じものは重複を省いて一つを選ぶ．
– t0 = 6 または "reduce" のときは，キーに重複がないものを削る．
• ℓ2 = 0 または "col" のとき : オプション c1=を指定すると– t0 = 0 または "put" のとき, c1,1 , c1,2 , . . . 番目の項目を抜き出したリストのリストを返す．
– t0 = 1 または "setminus" のとき, c1,1 , c1,2 . . . 番目の項目を削除したリストのリストを返す．
• ℓ2 = 1 または "num" のとき
t1 が存在しないときは，t1 = 0 とみなす．
– t0 ="col" : 項目番号のリストを最初の要素として挿入．
– t1 が数のとき∗ t0 = 0 または "put" : 各要素の先頭に順に t1 から番号を挿入する．
∗ t0 = 1 または "get" : c1 で指定された番号 c1,0 , c1,1 , · · · の要素をこの順に抜き出す．
∗ t0 = 2 または "sub" : c1 で指定された番号の要素を削除．
∗ t0 = 3 または "sum" : 要素の個数を返す– それ以外のとき，以下のように i 番目の要素について値 Vi を得る．
∗ t1 が函数子のとき，その要素（ただし，t2 が指定されていれば，要素の t2 番目の項目）を引数として返された値．isyes() や calc() などが利用できる．
∗ t1 がリスト [s,v] のときは，函数 calc( · ,[s,v]) という函数にその要素（ただし，t2が指定されていれば，要素の t2 番目の項目）を入れて返された値
s は ">", "<", "=", ">=", "<=", "!=" などが可能．
∗ t1 が文字列 "+" のとき，各要素の c1,1 , c1,2 . . . 番目の項目の和（数でないものは 0 とみなして足す）．
この値に Vi 対し∗ t0 = 0 または "put" : 各要素の先頭に Vi を挿入する．
∗ t0 = 1 または "get" : Vi が 0 でない要素のみ抜き出す．
∗ t0 = 2 または "sub" : Vi が 0 の要素のみ抜き出す．
∗ t0 = 3 または "sum" : Vi の和を返す• ℓ2 ="transpose" で t0 ="put" のとき, 行と列を逆にする（転置）．
• ℓ2 ="adjust" で t0 ="put" のとき, 要素の項目の個数が異なっているとき，最大の個数に揃え，239

後ろには空文字列 "" を詰める．なお，t1 で空きに詰めるものを指定できる．
• ℓ2 ="subst" で t0 ="put" のとき tj =[aj ,bj ,cj ] : aj 番目の要素の bj 番目の項を cj で置き換
える．

• ℓ1 , ℓ2 がリストのリストのとき，ℓ1 の要素の t1 番目の項を ℓ1 のキー項目，ℓ2 の要素の t2 番目の項を ℓ2 のキー項目と指定して，以下を行う.
– t1 や t2 が省略された場合は，それらは 0 とみなす．
– ℓ2 の各要素がリストではない 1 項目からなっているとき，その項目のみを並べたリストを ℓ2としてもよい．

– t0 = 0 または "cup" のとき, ℓ1 の要素に同じキーの ℓ2 の要素を付け加える．
– t0 = 2 または "cap" のとき, 上と同様であるが，同じキーをもつ ℓ2 の要素がないものは削除
する．

– t0 = 1 または "setminus" のときは, 同じキーをもつ ℓ2 の要素があるものを ℓ1 から削除する（ℓ2 はキー以外の項は無視される）．
– t0 = 3 または "sum" のときは, 同じキーをもつ ℓ1 の要素と ℓ2 の要素は１つにまとめ，ℓ1 とℓ2 を合併する．
– t0 = 4 または "over" のときは, 同じキーをもつ ℓ1 の要素と ℓ2 の要素に対し，ℓ1 の c1,ν 番
目の項目を ℓ2 の要素の c2,ν 番目の項目によって置き換えて返す．
ℓ1 と ℓ2 の要素が 1 つのときは，リストにせずにそのまま指定してもよい．次においても同様．
– t0 = 5 または "subst" のときは, 同じキーをもつ ℓ1 の要素と ℓ2 の要素に対し，ℓ2 の要素の
c2,ν 番目の項目が空（文字列）でなければ，ℓ1 の c1,ν 番目の項目をそれで置き換えて返す．
上を行って，t0 = 4, 5 以外では，オプション c1 と c2 で指定した ℓ1 と ℓ2 の要素の項目を抜き出した（指定しないときは（t0 = 3 以外では ℓ2 のキーを除いた）全項目のリストのリストを返す．
[0] os_md.lsort([3,2,0,a,1,2,b],[],0);[0,1,2,2,3,b,a][1] os_md.lsort([3,2,0,a,1,2,b],[],1);[0,1,2,3,b,a][2] os_md.lsort([3,2,0,a,1,2,b],[a,c,0],"cup");[0,1,2,3,c,b,a][3] os_md.lsort([3,2,0,1,2,a,b],[a,c,0],"setminus");[1,2,3,b][4] os_md.lsort([3,2,0,a,1,2,b],[a,c,0],"cap");[0,a][5] os_md.lsort([3,2,0,a,1,2,b],[a,c,2],"reduce");[[0,1,2,3,b],[c]][6] os_md.lsort([3,2,0,a,1,2,b],[],"cut"|c1=2);[[3,2],[0,a,1,2,b]][7] os_md.lsort([3,2,0,a,1,2,b],[],"cut"|c1=-2);[[3,2,0,a,1],[2,b]][8] os_md.lsort([3,2,0,1,2,a,b],[a,c,0],"count");[7,3,6,3,2,5][9] L=[[5,"A","P"],[2,"C","Q"],[3,"B","P"]]$[10] os_md.lsort(L,"sort",["put",0]);/* sort by key 0 */[[2,C,Q],[3,B,P],[5,A,P]][11] os_md.lsort(L1,"sort",["put",-2]);/* reverse sort by key 1 */[[2,C,Q],[3,B,P],[5,A,P]][12] os_md.lsort(L,"sort",["reduce",2]); /* reduce duplication by key 2 */240

[[3,B,P],[2,C,Q]][13] os_md.lsort(L,"sort",["duplicate",2]); /* get duplication by key 2 */[[3,B,P],[5,A,P]][14] os_md.lsort(L,"col",["put"]|c1=[2,1]);/* extract column */[[P,A],[Q,C],[P,B]][15] os_md.lsort(L,"col",["setminus"]|c1=[0]); /* delete column */[[A,P],[C,Q],[B,P]][16] os_md.lsort(L,"num",["put",1000]);/* put number */[[1000,5,A,P],[1001,2,C,Q],[1002,3,B,P]][17] os_md.lsort(L,"num",["col"]);/* add column numbers */[[0,1,2],[5,A,P],[2,C,Q],[3,B,P]][18] os_md.lsort(L,"transpose",[]);/* transpose */[[5,2,3],[A,C,B],[P,Q,P]][19] os_md.lsort(L,"num",["get"]|c1=[2,1]); /* get lines */[[3,B,P],[2,C,Q]][20] os_md.lsort(L,"num",["sub"]|c1=[2,1]); /* delete lines */[[5,A,P]][21] os_md.lsort(L,"num",["sum"]);/* num. of elements */3[22] os_md.lsort(L,"num",["put",[">","B"],1]); /* put number */[[0,5,A,P],[1,2,C,Q],[0,3,B,P]][23] os_md.lsort(L,"num",["get",["=","B"],1]); /* get elements */[[3,B,P]][24] os_md.lsort(L,"num",["get",[">=","B"],1]); /* get elements */[[2,C,Q],[3,B,P]][25] os_md.lsort(L,"num",["get",["!=","B"],1]); /* get elements */[[5,A,P],[2,C,Q]][26] os_md.lsort(L,"num",["sub",["=","B"],1]); /* subtract elements */[[5,A,P],[2,C,Q]][27] os_md.lsort(L,"num",["sum",["!=","B"],1]); /* mum. of elements */2[28] os_md.lsort(L,"num",["sum","+"]|c1=[0]);/* sum of column entries */10[29] os_md.lsort(L,"subst",[]|c1=[[0,1,"#"],[1,2,"?"]]); /* substitute */[[5,#,P],[2,C,?],[3,B,P]][30] os_md.lsort(L,"","cons");/* cons "" */[[,5,A,P],[,2,C,Q],[,3,B,P]][31] os_md.lsort(L,["a","b"],"cons");/* cons elements */[[a,5,A,P],[b,2,C,Q],[b,3,B,P]][32] L2=[["a",3,"r"],["c",2,"p"],["b",7,"q"]]$[33] os_md.lsort(L,L2,["cup",0,1]); /* cup two ll */[[5,A,P,,],[2,C,Q,c,p],[3,B,P,a,r]][34] os_md.lsort(L,L2,["cap",0,1]); /* cap two ll */[[2,C,Q,c,p],[3,B,P,a,r]]241

[35] os_md.lsort(L,L2,["sum",0,1]); /* sum two ll */[[5,A,P,,,],[2,C,Q,c,2,p],[3,B,P,a,3,r],[,,,b,7,q]][36] os_md.lsort(L,L2,"append");/* append two ll */[[5,A,P,a,3,r],[2,C,Q,c,2,p],[3,B,P,b,7,q]][37] os_md.lsort(L,[2,5],["cap",0]); /* get lines by list */[[5,A,P],[2,C,Q]][38] os_md.lsort(L,[2,5],["setminus",0]); /* delete lines by list */[[3,B,P]][39] os_md.lsort(L,L2,["subst",0,1]|c1=1,c2=0); /* substitute */[[5,A,P],[2,c,Q],[3,a,P]][40] os_md.lsort(L,L2,["subst",0,1]|c1=[1,2],c2=[0,1]); /* substitute */[[5,A,P],[2,c,2],[3,a,3]][41] os_md.lsort([[a,b,c],[d,e,f]],[[a,b,c],[d,h,f]],"cmp");[[[[1,1],e,h]]][42] os_md.lsort([[a,b,c],[d,e,f]],[[a,b,c],[d,e]],"cmp")$
Different size :line 1[43] os_md.lsort([[a,b,c],[d,e,f]],"transpose",[]);[[a,d],[b,e],[c,f]]
296. issub(ℓ1 , ℓ2 ):: 部分リストかどうかのチェック
リスト ℓ1 がリスト ℓ2 に含まれるかどうかをチェックする
各リストは要素に重複がないとする（重複は解消してから比較）[0] os_md.issub([0,1,2],[2,3,4,5,1,0]);1[1] os_md.issub([2,3,4,5,1,0],[0,1,2]);0[2] os_md.issub([0,1,2,0],[0,1,2]);
1297. isdisjopint(ℓ1 ,ℓ2 )298. isdisjopintfamily([ℓ1 ,ℓ2 , . . .]):: 互いに共通部分がないかどうかのチェック
リストに共通の要素がないかどうかをチェックする（各リストは要素に重複がないとする）[0] os_md.isdisjoint([0,2,4],[3,5]);
1[1] os_md.isdisjoint([0,2,4],[2,5]);0[2] os_md.isdisjointfamily([[0,2,4],[3,5],[9]]);1[3] os_md.isdisjointfamily([[0,2,4],[2,5],[9]]);0299. iscommuteset(ℓ1 ,ℓ2 )300. iscommutefamily([ℓ1 ,ℓ2 , . . .]):: 交換可能かどうかのチェック242

可換とは，一方のリストが他方に含まれるか，あるいは共通要素を持たないことをいう
各リストは要素に重複がないとする[0] os_md.iscommuteset([0,2,4],[2,5]);0[1] os_md.iscommuteset([0,2,4],[3,5]);
1[2] os_md.iscommuteset([0,2,4],[0,4]);
1[3] os_md.iscommutefamily([[0,2,4],[0,4],[3,5]]);1301. llsymred([ℓ1 ,ℓ2 , . . .],[m1 ,m2 , . . .]|sort=f ,depth=d):: リストのリスト（集合族）を集めたリストから対称性で最小なもののみを残す(m1 , m2 , . . .) の入れ替えで最小となるもののみを選んで返す．
入れ替えを行ったあと, f =[s,k] のパラメータ（cf. rsort()）で集合族をソートして比較する（デフォルトは，f =[0,0]．s = 0 ではソートしない）．
depth=d は, 入れ替えを行う深さ（cf. substnum()）．デフォルトは d =[0,1].
302. llord([ℓ1 ,ℓ2 , . . .]|verb=f ):: リストの包含関係の解析
戻り値は 5 つのリストで，最初のリストは，リストを小さい順に並べたベクトル
2 番目のリストは，各リストがどのリストを部分リストに含んでいるリストの番号のリストを順に並べたもの
3 番目のリストは，各リストの包含関係で部分リストとして含む極大リストの番号のリストを順に並べたもの
4 番目のリストは，全体集合
5 番目のリストは，roots（親）集合
verb=1,2,3 とすると 6 番目の戻り値 f は• iand(f ,1) : commuting family?
• iand(f ,2) : loops?
• iand(f ,4) : total set?
• iand(f ,8) : sets with single element?
• iand(f ,16) : empty set?
• iand(f ,32) : not binary tree?
• iand(f ,64) : duplication?
• iand(f ,128): not sorted• iand(f ,256): with multiplicities• iand(f ,512): maximal commutingt family?
verb=2 とすると，6 番目の戻り値が 517 の場合は．極大可換部分集合族となるので，対応するトーナ
メント戦パターンと対応するチームのリストを 7 番目と 8 番目の戻り値に付加する[0] os_md.llord([[0,1],[0,1,2,3],[2,3],[0,1,2,3,4]]);[[ [0,1] [2,3] [0,1,2,3] [0,1,2,3,4] ],[ [] [] [1,0] [2,1,0] ],[ [] [] [1,0] [2] ],[0,1,2,3,4],[3]][1] os_md.llord([[0,1],[0,1,2,3],[2,3],[0,1,2,3,4]]|verb=1);
maximal commuting family of the set [0,1,2,3,4] with the root [0,1,2,3,4][[ [0,1] [2,3] [0,1,2,3] [0,1,2,3,4] ],[ [] [] [1,0] [2,1,0] ],[ [] [] [1,0] [2] ], [0,1,2,3,4],[3],517][2] os_md.llord([[0,1],[0,1,2,3],[2,3],[0,1,2,3,4]]|verb=2);
243

...
[ [] [] [1,0] [2] ],[0,1,2,3,4],[3],517,(((**)(**))*),[0,1,2,3,4]]
303. btree(p,v|opt=s,add=m):: 二分木の作成と要素 p を二分木 v に追加するなどの二分木の操作
二分木 v はベクトル V の形で，V[0] はヘッダ，それ以降の成分はノードまたは空き• 要素 p を二分木 v に追加．戻り値は二分木
要素 p に対応するノードが存在したときは，その重複度を 1 つ増やす（ただし，オプション add=mを指定すると 1 でなくて m となる）．存在しなくてノードが追加されたときのノード番号は，
V[0][7] が空でなければ V[0][7] の先頭，空ならば V[0][1] となる．戻り値は新たな v となるが，通常 v の値は変わらない（ベクトルに空きがなくてベクトルサイズを増やしたときのみ変わる）．

• ノード：長さ 4 のベクトル [x,l,r,c] で, x は対応する要素，l は次の左（要素がより小さい）の，
r は右のノード番号（ノード番号は, 1 から n−1 までの数．ノード番号 0 はそれが非存在を意味する），c は頻度.
頻度 0 は木のノードとしてのみ意味を持つが，対応する要素は非存在とみなす（要素の削除で，keep=1 を設定したときに生じる．空のノードと呼ぶ）．
• V[0]=[h,n,e,u,f,op,dp,de ]– h : トップのノード番号．すなわちトップのノードは V[h ]– n : 木 の 最 大 の ノ ー ド 番 号 +1．n − length(V [7]) − 1 が 木 の ノ ー ド の 総 数 と な り,V[1],...,V[n −1] がノード（ただし V[0][7] のノード番号のものを除く）– e : ベクトルのサイズ（デフォルト 128, ノード置かれていない成分を含む. n 番目以降の空きの成分は 0）– u : ベクトルのサイズを拡大する際の増分サイズ（デフォルト 128）
– f : 大小を比較する函数（0 は, Risa/Asir における大小を意味する）– op : 二分木の最適化が行われる数 +1 のリスト（小さい順のリスト）– dp : 最大の木の深さ– de : 削除されたノード番号のリスト• s="init" : 二分木を作成し，それを返す– v を 8 以上の整数とすると，その値が e と u に設定される．
– オプション data=[x1 ,x2 ,...] によって初期データ（要素のリスト）を与えることができる．
初期データは重複があってもよい．最適化された二分木が初期状態として設定され，e はその長さ +v となる．
– オプション optimize=[d1 ,d2 ,...,dm ,0] によって，それを dp（V[0][6]）に設定する．diは 4 以上の 2 のべき乗が適当．リストの先頭の数がノードの数 +1 になったとき，最適化が自動的に行われてリストの先頭が削られる．
最後の 0 は最適化終了を意味するが，−4 と −3 は特別な以下の特別な意味を持つ．
optimize=[d1 ,d2 ,...,dm ,−4] とすると，ノードの数が dm − 1 のときの最適化の後，[2dm ,−4] に設定される．一方，−4 でなくて −3 とすると，2dm でなくて dm +V[0][4] に再設定される．
– オプション comp=f によって比較函数を設定する．
• s="del" : 要素 p に対応するノードを削除．削除されたノード番号は，V[0][7] に追加される．ただしオプション keep=1 を指定すると，削除せず空のノードとして残して木の形は変えない．
• s="check" : p の存在チェック．p とその親のノード番号の組 L（存在しなければ 0）を返す
存在するときは v[car(L[0])][3] が頻度．L[0]=L[1] はトップのノードを意味する．
• s="num" : 木の要素の個数を返す（空のノードを除いたノードの数）• s="get":– p = 0 : 追加された順の要素のリストを返す– p = 1 : 要素のソートされたリストを返す– p = 2 : 空ノードも含むソートされた要素とその頻度のリストを返す
244

– p = 3 : 空ノードも含む要素のソートされたリストを返す– p = −1 : ソートされた要素のノード番号のリストを返す– p = −2 : 二分木の深さを返す• s="optimize" : 二分木を最適化する，即ち要素の数が N のとき，最大の深さ m は 2m > N を満たす最小非負整数となる．空のノードは削られる．

• s="clear" : v を空の二分木にする• s="info" : V[0] から得られる二本木の情報を返す
以下によって，トップからその要素を含むノードに至る道がノード番号のリストで得られる．親より左にある場合は，ノード番号は，−1 倍された数で示される．

def gettree(X,V){
if(!(S=os_md.btree(X,V|opt="check"))) return 0;for(R=[];S[0]!=S[1];){
P=S[0];
S=os_md.btree(V[S[1]][0],V|opt="check");if(V[S[0]][1]==P) P=-P;
R=cons(P,R);}
return cons(S[0],R);};304. spantree(f ,l,s|optimize=,comp=,unit=u,limit=m,fopt=op):: l の要素を使う函数 f による変換で s の要素から生成される二本木を作る
l=[l1 ,l2 , · · · ], s=[s1 ,s2 , . . .] はリスト
• f (t, li |opt=op) によって要素を生成していく．t は既に生成された要素で，初期値は s の要素
それ以上新たな要素が増えないか，要素が m 個を超えるまで続けて，生成された二本木を返す• f をリストにして，複数の函数の指定ができる• そのほかのオプションは btree() の初期化と同じ[0] L=map(ltov,[[1,0,2,3,4],[1,2,3,4,0]]);[[ 1 0 2 3 4 ],[ 1 2 3 4 0 ]][1] S=[ltov([0,1,2,3,4])];[[ 0 1 2 3 4 ]][2] V=os_md.spantree(os_md.sprod,L,S)$[3] os_md.btree(0,V|opt="num");
120
305. msort(ℓ,s):: ベクトルやリストの成分を（多重）キー s に従ってソートする• s =[f ,m]
f = 1：小さい順，f = −1：大きい順
キーの m は
– 0 : 成分の大小– 1 : 成分がベクトルまたはリストのとき，その長さ– 2 : 成分がベクトルまたはリストのとき，先頭からの辞書式順序– 3 : 成分のタイプ– 4 : 成分の絶対値– 5 : 表示の長さ245

– f n : 引数が 2 個の比較の函数子 f n を用いる
– [f n] : 引数が 1 個の函数 f n に代入して返される値の大小• s =[f ,m,k] : 成分がベクトルまたはリストのとき，(k + 1) 番目の成分で比較する• s =[f ,m,k1 ,k2 ] : 成分がベクトルまたはリストのベクトルまたはリストのとき，(k1 + 1) 番目の成分の (k2 + 1) 番目の成分で比較する（さらに s =[f ,m,k1 ,k2 ,k3 ] なども可能）．
• s =[s1 ,s2 , . . .] : si は上のようなキーで，s1 のキーでの大小比較で同一となったときは s2 キーで比較というようにキーの辞書式順序で比較する．

[0] os_md.msort([3,2,1,5],[-1,0]); /* 逆順 */[5,3,2,1][1] os_md.msort([[1,4],[3,2,1],[4,5]],[1,0,1]); /* 2 番目の成分 */[[3,2,1],[1,4],[4,5]][2] os_md.msort([[1,4],[3,2,1],[4,5]],[-1,1]); /* 長い順 */[[3,2,1],[4,5],[1,4]][3] os_md.msort([[2,2],[3,1],[2,1,1]],[-1,2]); /* 辞書式順序の大きい順 */[[3,1],[2,2],[2,1,1]][4] os_md.msort([[1,4],[3,2,1],[4,5]],[[-1,1],[1,0,0]]); /* マルチキー */[[3,2,1],[1,4],[4,5]][5] os_md.msort(["This","is","not","an","ant"],[[1,[str_len]],[1,0]]);[an,is,ant,not,This]
306. l2min(l,p|check=1,cmp=f ):: リスト ℓ を成分の入れ替えで最小なものに変更する• p は比較する成分の位置のリスト．リストで示された成分の入れ替えで，この順で最小なものを返す• check=1 を指定すると，ℓ が最小であれば 0 を，そうでなければ 1 を返す• cmp=f : 比較函数を指定する[0] os_md.l2min([3,4,2],[0,2]);[2,4,3][1] os_md.l2min([3,4,2],[2,0]);[3,4,2][2] os_md.l2min([3,4,2],[2,0]|check=1);0[3] os_md.l2min([3,4,2],[2,1,0]);[4,3,2][4] os_md.l2min([3,4,2],[0,2]|check=1);
1307. partspt(l,m|opt=f ):: 一つの整数の 2 種の分割に対して細分関係を調べる• 整数の 2 種の分割 l, m に対し，m が l の細分となる関係を全て返す．
デフォルトでは，l の分割は順序づけられているとする（大きい順）．
l = l1 + · · · + lL を l の分割とするとき，m の分割を m = m1 + · · · + mM と並べ替えたもので，
1 ≤ ∀i ≤ L に対して l1 + · · · + li = m1 + · · · + mji となる ji が存在するものが存在する並べ替えをリストにして返す．
• opt=1 : ℓ の分割も順序づけられていないとして, [[l1 , [m1 , . . . , mj1 −1 ], [l2 , [mj1 , . . . , mj2 −1 ], . . .]をリストにして返す．
• opt=2 : l の分割は順序づけられているとして，上の形式で細分となる関係を全て返す．
• opt=3 : l の分割は順序づけられていないとして，デフォルトと同様の形式で細分となる関係を全

246

て返す．

[0] S=[4,4,2]$M=[2,2,2,1,1,1,1]$[1] os_md.partspt(S,M);[[2,2,2,1,1,1,1],[2,2,1,1,1,1,2],[2,1,1,2,2,1,1],[2,1,1,2,1,1,2],[1,1,1,1,2,2,2]][2] os_md.partspt(S,M|opt=3);[[2,1,1,2,2,1,1],[2,1,1,2,1,1,2],[1,1,1,1,2,2,2]][3] os_md.partspt(S,M|opt=1);[[[4,[2,1,1]],[4,[2,2]],[2,[1,1]]],[[4,[2,1,1]],[4,[2,1,1]],[2,[2]]],[[4,[1,1,1,1]],[4,[2,2]],[2,[2]]]]308. lpair(ℓ1 ,ℓ2 ):: 2 つのリストまたはベクトルを pair のリストに変換する• 長さの等しいリストまたはベクトル ℓ1 , ℓ2 を pair のリストに変換する．
• ℓ1 が pair のリストで ℓ2 = 0 のときは上の逆変換する．
[0] os_md.lpair([x,y,z],[1,2,3]);[[x,1],[y,2],[z,3]][1] os_md.lpair(@@,0);[[x,y,z],[1,2,3]][2] os_md.lpair(ltov([x,y,z]),ltov([1,2,3]));[[x,1],[y,2],[z,3]]309. addIL([a,b],[[a1 ,b1 ],[a2 ,b2 ],. . .]|in=t):: 有限区間の合併集合と有限区間の和集合の計算• a1 < b1 < a2 < b2 < . . . となっている必要がある．
• [a,b] の代わりに最初の引数が 0 のときは，第 2 引数を上の形に直す．
• in=-1 を指定すると，[a,b] から [[a1 ,b1 ],[a2 ,b2 ],. . .] を除いた集合を返す．
• in=1 を指定していて最初の引数が数 a とすると，a が集合に含まれているかどうかを返す．
• in=2 を指定していて最初の引数が数 a とすると，a が集合に含まれているかどうかを返す．ただし区間の端になるときは 2 を返す．
• in=2 を指定していて最初の引数が数 a とすると，a が含まれている区間を返す．それがないとき
は 0 を返す．
[0] os_md.addIL([6,7],[[2,5],[8,11]]);[[2,5],[6,7],[8,11]][1] os_md.addIL([4,6],[[2,5],[8,11]]);[[2,6],[8,11]][2] os_md.addIL([1,6],[[2,5],[8,11]]);[[1,6],[8,11]][3] os_md.addIL([9,10],[[2,5],[8,11]]);[[2,5],[8,11]][4] os_md.addIL([4,8],[[2,5],[8,11]]);[[2,11]][5] os_md.addIL(0,[[4,8],[2,5],[8,11]]);[[2,11]][6] os_md.addIL([0,12],[[2,5],[8,11]]|in=-1);[[0,2],[5,8],[11,12]]247

[7] os_md.addIL([6,9],[[2,5],[8,11]]|in=-1);[[6,8]][8] os_md.addIL(3,[[2,5],[8,11]]|in=1);
1[9] os_md.addIL(6,[[2,5],[8,11]]|in=1);0[10] os_md.addIL(5,[[2,5],[8,11]]|in=1);1[11] os_md.addIL(5,[[2,5],[8,11]]|in=2);2[12] os_md.addIL(3,[[2,5],[8,11]]|in=3);[2,5][13] os_md.addIL(6,[[2,5],[8,11]]|in=3);0310. lext2(m):: 2 次の外積の基底の並べ替え
I = {(i, j) | 0 ≤ i < j < n} という n(n−1)
個のインデックスの集合を考える．
2• m=[i,j,n]：0 ≤ i < j < n のとき，(i, j) が k 番目ならば [k,1] を返す（0 ≤ k < n(n−1)）．
2i = j のとき [0,0] を返す
0 ≤ j < i < n のとき，(j, i) が k 番目ならば [k,−1] を返す（0 ≤ k < n(n−1)）．
2• m=[k,n]：上の逆関数で，[i,j] を返す．
[0] os_md.lext2([0,1,4]);[0,1][1] os_md.lext2([1,2,4]);[3,1][2] os_md.lext2([2,1,4]);[3,-1][3] os_md.lext2([3,4]);[1,2]
311. vnext(v):: ベクトルの成分を並べ替え，辞書式順序で次のベクトルに変換する• 成分に等しいものがあってもよい．
• 最後のベクトルを与えたときは 0，それ以外では 1 を返す．
[0] V = newvect(7, [3,1,5,7,6,4,2]);[ 3 1 5 7 6 4 2 ][1] os_md.vnext(V); V;
1[2] [ 3 1 6 2 4 5 7 ][3] V = newvect(4, [4,3,2,1]);[ 4 3 2 1 ][4] os_md.vnext(V); V;248

0[5] [ 4 3 2 1 ][6] V = newvect(7, [2,1,5,5,6,5,2]);[ 2 1 5 5 6 5 2 ][7] os_md.vnext(V); V;
1[8] [ 2 1 5 6 2 5 5 ]312. vgen(v,w,m|opt=0):: 成分の和が m の非負整数成分のベクトル w を順に生成する• v, w は同じサイズのベクトルで，w[i] ≤ v[i] の制限つき．
• opt=0 は，初期化でそのときの戻り値は 0．それ以外での戻り値は書き換えられた最高桁• 最後には 0 を返して，初期化される．
• 戻り値の最初の成分を除くと和が m 以下のベクトルが得られる[0] V=newvect(3,[2,1,2]);[ 2 1 2 ][1] W=newvect(3);[ 0 0 0 ][2] os_md.vgen(V,W,2|opt=0);0[3] W;[ 2 0 0 ][4] os_md.vgen(V,W,2);
1[5] W;[ 1 1 0 ][6] os_md.vgen(V,W,2);
2[7] W;[ 1 0 1 ][8] os_md.vgen(V,W,2);
1[9] W;[ 0 1 1 ]
[10] os_md.vgen(V,W,2);
2[11] W;[ 0 0 2 ]
[12] os_md.vgen(V,W,2);
0[13] W;[ 2 0 0 ]313. paracmpl(l,t|lim=1,low=1,para=[v1 , v2 , . . .]):: 有理的に t に依存したリスト l の成分（たとえば有理式）で張られる空間の正則完備化
l の成分が有理式 f1 (x, t), . . . , fm (x, t) のとき（x は多変数でよい），generic に t = t0 と特殊化した249

f1 (x, t0 ), . . . , fm (x, t0 ) の一次独立な個数を m̄ とする．1 変数 t の有理式 gi,j (t) を適当に取ってhj (x, t) =mXfi (x, t)gi,j (t)i=1とおくと，0 でない hj (x, t) の個数は m̄ で, しかも hj (x, t) は t = 0 で極を持たず，h1 (x, 0), . . . , hm (x, 0)の一次独立な個数は m̄ とできる（cf. [OSe, Proposition 2.21], [O1, Lemma 6.3]）．
paracmpl([f1 (x, t), . . . , fm (x, t)],t) は，この [[h1 (x, t), . . . , hm (x, t)],(gi,j (t))] を返す．
confexp() は，複数パラメータの場合の具体例の計算とみなせる．
• l はベクトルでもよいが，リストで返される．
• [h1 (x, t), . . . , hm (x, t)] は, t の有理式を成分とする可逆行列 A = ai,j (t) 1≤i≤m で，A と A−1 の1≤j≤m

各成分が t = 0 に極を持たないものによる変換を除いて一意となる．
• 返される G = gi,j (t) 1≤i≤m は上三角行列となる．
1≤j≤m• low=1 を指定すると, x の次数が小さい項に注目する．
• lim=1 を指定すると [h1 (x, 0), . . . , hm (x, 0)] を返す．
• fi (x, t) は有理式でなく，有理式を成分とするリストやベクトルでもよい．
• para=[v1 , . . . , vk ] を指定すると，数係数でなくて不定元 v1 , . . . , vk 係数の有理関数体係数の有理式とみなす．

• m̄ = m のとき，fi (x, t) が有理式でなくて exp((1 + t)x) のような式の場合は，適当な次数まで
Taylor 展開した式で fi (t, x)（の分母分子）を置き換え，low=1 を指定して求めた G で変換すれば
よい．

[0] os_md.paracmpl([1/(x-1),1/((t+1)*x-1)],t);[[(1)/(x-1),(1)/((t+1)*x^2+(-t-2)*x+1)],[ 1 (1)/(t) ][ 0 (-t-1)/(t) ]][1] os_md.paracmpl([1/(1-x),1/(1-(t+1)*x)],t|lim=1);[ (1)/(x-1) (1)/(x^2-2*x+1) ][2] os_md.paracmpl([1/(x-1),1/((t+1)*x-1)],t|low=1);[[(-1)/(x-1),(x)/((t+1)*x^2+(-t-2)*x+1)],[ -1 (1)/(t) ][ 0 (-1)/(t) ]][3] os_md.paracmpl([1/(x-1),1/((t+1)*x-1)],t|low=1,lim=1);[ (-1)/(x-1) (x)/(x^2-2*x+1) ][4] os_md.paracmpl([[1/t,1,1],[1+t,0,-t]],t);[[[1,t,t],[0,t+1,t+2]],[ t t+1 ][ 0 (-1)/(t) ]][5] os_md.paracmpl([[1/t,1,1],[1+t,0,-t]],t|lim=1);[[1,0,0],[0,1,2]]
上の [0]〜[5] は以下を示している．



1
1
,
2
x − 1 (t + 1)x + (−t − 2)x + 1




=

=

250

1
1
,
x − 1 (t + 1)x − 1
1
1,
x − 1 (x − 1)2






1

0


1
t 
−t − 1 t

if t = 0,



1
x
,
1 − x (t + 1)x2 + (−t − 2)x + 1




=

1
1
,
x − 1 (t + 1)x − 1




−1

0



!
1
t ,
t


1
t 
1
−
t


1
x
,
if t = 0,=
1 − x (1 − x)2




!!
!
!
1
0
t+1
t t+1
t

1
0
t+1
=  1  ,
0 −
t+2
t
1
t
!
!!
0
1
0 , 1
if t = 0.
=02

ここで以下に注意

1x,
1 − x (1 − x)2




=

1
1
,
x − 1 (x − 1)2




−1 1
.
0 1

微分方程式

(t + 1)x2 − (t + 2)x + 1

 du d2 u+ 2 2(t + 1)x − t − 2+ 2(t + 1)u = 0
2
dx
dx

C1
C2
の解空間は t 6= 0 のとき { x−1+ (t+1)x−1| C1 , C2 ∈ C} である．このことから t = 0 のときの
C1
C2解空間は { x−1+ (x−1)
2 | C1 , C2 ∈ C} となることが分かる．より一般に，任意の t で解空間は
C1
2x+ (t+1)2 x2C−(t+2)x+1| C1 , C2 ∈ C} で与えられる．
{ x−1
x = 0 の近くで考えるときは，low=1 を指定する方が便利なことが多い．

3.2.6 Matrices
314. dupmat(m):: 成分が有理式の行列またはベクトル m の複製を作る[0] A=B=newmat(2,2,[[1,2],[3,4]]);[ 1 2 ]
[ 3 4 ]
[1] C=os_md.dupmat(A);[ 1 2 ]
[ 3 4 ]
[2] C[0][0]=0;
0[3] C;[ 0 2 ]
[ 3 4 ]
[4] A;[ 1 2 ]
[ 3 4 ]
[5] B[0][0]=0;
0[6] B;[ 0 2 ]
251

[ 3 4 ][7] A;[ 0 2 ]
[ 3 4 ]
315. m2v(m):: 行列 m の成分を 1 行目から順に並べてベクトルに変換する[0] M=newmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[1] os_md.m2v(M);[ a b c d ]316. m2l(m|flat=1):: 有理式，ベクトルあるいは行列 m の成分を順に並べてリストにする
flat=1 : リストのリストのときは，一つ内側のリストを外して並べる．
たとえば，リスト ℓ1 , ℓ2 , ℓ3 , ℓ4 をこの順に連結したリストを作るには m2l([ℓ1 ,ℓ2 ,ℓ3 ,ℓ4 ]|flat=1) とすればよい．

[0] M=newmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[1] os_md.m2l(M);[a,b,c,d][2] os_md.m2lv(M);[[ a b ],[ c d ]][3] os_md.m2l(a);[a][4] os_md.m2l([a,b]);[a,b][5] os_md.m2l([[1,2],[3,4,[5,6],7],[8,9]]|flat=1);[1,2,3,4,[5,6],7,8,9];
参照：base flatten()
317. m2lv(m):: 行列 m の行ベクトルを並べてリストにする（cf. 316, 319）
318. m2ll(m):: 行列 m を行ベクトルをリストにかえたものを成分とするリストにする（cf. 319）
319. lv2m(ℓ|fill=n):: 行ベクトル（行成分のリストでも可）のリスト ℓ から行列を作る• 行列の列の大きさは，行ベクトルの最大長で決まり，行ベクトルのサイズが小さい時は，後ろに 0が補充される（cf. mat())．
• fill=n : 行ベクトルのサイズが小さいとき，0 でなくて n を補充する．

[0] A=newmat(3,2,[[1,2],[3,4],[5,6]]);[ 1 2 ]
[ 3 4 ]
[ 5 6 ]

252

[1] LV=os_md.m2lv(A);[[ 1 2 ],[ 3 4 ],[ 5 6 ]][2] LL=os_md.m2ll(A);[[1,2],[3,4],[5,6]][3] os_md.lv2m(LV);[ 1 2 ]
[ 3 4 ]
[ 5 6 ]
[4] os_md.lv2m(LL);[ 1 2 ]
[ 3 4 ]
[ 5 6 ]
[5] A0=newvect(2,[1,2]);[ 1 2 ]
[6] A1=newvect(3,[1,2,3]);[ 1 2 3 ][7] os_md.lv2m([A0,A1]);[ 1 2 0 ][ 1 2 3 ][8] os_md.lv2m([[1,2],[1,2,3]]);[ 1 2 0 ][ 1 2 3 ][9] os_md.lv2m([[1,2],[1,2,3]]|fill=" ");[ 1 2][ 1 2 3 ]320. s2m(s):: 文字列での有理数成分の行列表現や，列のリストから行列を作る．必要最低サイズの行列になる• 整数や有理数成分の行列を，行の区切りをコンマで示した文字列で指定する．成分が一桁の整数のときに便利（以下の [0], [1], [4], [5] を参照）．
– 同じ数が例えば 3 回続くときは，^3 をつけて表してもよい．
– a,b, . . . は 10, 11, . . . を表す．
2
– 10 以上の数は (10) のように括弧で囲んで表してもよい．たとえば，2/b は 11．
– 分数は / を使って表す．
– たとえば 12(-2)/3^2 は，1, 2, − 23 , − 23 と 4 つの数字が並んでいると解釈される．
• s2sp() あるいは Risa/Asir の表示の文字列によって行列成分を表すリストから行列に戻す機能をもつ（以下の [0], [6] の例を参照）．
すなわち，eval str() を式でなくて，式が成分のリストや行列に拡張した機能．
• 行列を作成する newmat(m, n, l) の ℓ を [ ] で囲って渡してもよい（以下の [2], [3] の例）．
• 行列のサイズは自動判定されるが mat() と異なり，列サイズは ℓ の成分の最大の長さとなる（mat() は成分の最初のリストの長さ）．
• s が行列の時は，そのまま返す．
[0] os_md.s2m("21,111,00a");[ 2 1 0 ][ 1 1 1 ][ 0 0 10 ]253

[1] os_md.s2m("-1,0-1,0^2-1,0^3-1");[ -1 0 0 0 ][ 0 -1 0 0 ][ 0 0 -1 0 ][ 0 0 0 -1 ][2] os_md.s2m([[0,a],[0,0,a],[0]]);[ 0 a 0 ][ 0 0 a ][ 0 0 0 ][3] mat([0,a],[0,0,a],[0]);[ 0 a ]
[ 0 0 ]
[ 0 0 ]
[4] os_md.s2m("123,32-2/3^2");[ 1 2 3 0 ][ 3 2 -2/3 -2/3 ][5] os_md.s2m("123,32(-3/b)^2");[ 1 2 3 0 ][ 3 2 -3/11 -3/11 ][6] os_md.s2m("[x*x 1+2][z w+1]");[ x^2 3 ][ z w+1 ]321. c2m(l,v|pow=t):: 基底の変換から係数行列を作る• l は一次変換した結果のリスト• t は基底（変数）のリスト• pow= t を指定したときは，v は変数で v j の j = 0, 1, . . . , t を基底と考えた係数の行列（v の t 次多項式の変換）．

[0] os_md.c2m([a*x+b*y,c*x+d*y],[x,y]);[ a b ]
[ c d ]
[1] os_md.c2m([1+2*x+3*x^2,2*x+4*x^2,1+3*x+5*x^2],x|pow=2);[ 1 2 3 ][ 0 2 4 ][ 1 3 5 ][2] os_md.c2m([1+2*x+3*x^2,2*x+4*x^2,1+3*x+5*x^2],x); /* 次数は自動判断 */[ 1 2 3 ][ 0 2 4 ][ 1 3 5 ]322. mperm(m,[σ0 ,σ1 . . . ],[τ0 ,τ1 , . . . ]|mult=1)
mperm(m,[[σ0 ,σ1 ]],[[τ0 ,τ
 1 ]]|mult=1), mperm(m,[σ,[m1 ]],[τ ,[m2 ]]|mult=1):: 行列 m から小行列mを作る，または置換行列（または互換）で変換する
σ
τ
i j

M = mij 0≤i<m は mσi τj に変わる．
0≤j<n

254

• 元の行列は破壊されず，新たな行列が返される．
• 第 2 引数が [[σ0 ,σ1 ]] となっていると，σ0 行目と σ1 行目の入れ替えを意味する．
• 第 3 引数が 1 のときは，第 3 引数が第 2 引数に等しいことを意味する．
• 第 2 引数，または第 3 引数が 0 のときは，それらが恒等変換であることを意味する．
• [σ,[k]] は [σ, σ + 1, . . . , σ + k − 1] と解釈される．
• m はベクトルまたはリストでもよい．このとき第 3 引数は無視される．
• たとえば，σ ≤ i < σ + k, σ ≤ j < σ + k を満たす m の成分 mi,j からなる k 次の正方行列

mi,j σ≤i<σ+k は mperm(m,[σ,[k]],1) によって，1, 3, 5 行目のみを抜き出して得られる行列σ≤j<σ+kは mperm(m,[1,3,5],0) によって得られる．
• mult=1 : 行列のリストを m と指定して，各成分に対して変換したリストを返す．

[0] A=newmat(3,3,[[a,b,c],[d,e,f],[g,h,i]]);[ a b c ][ d e f ][ g h i ][1] os_md.mperm(A,1,[1,2,0]);[ e f d ][ h i g ][ b c a ][2] os_md.mperm(A,[1,2],[0,1]);[ d e ]
[ g h ]
[3] os_md.mperm(A,[1,[2]],[0,[3]]);[ d e f ][ g h i ][4] os_md.mperm(A,[1,[2]],1);[ e f ]
[ h i ]
[5] os_md.mperm(A,[[0,1]],1);[ e d f ][ b a c ][ h g i ][6] os_md.mperm([a,b,c,d],[1,3,0,2],0);[b,d,a,c][7] os_md.mperm(ltov([a,b,c,d]),[1,3,0,2],0);[ b d a c ]323. mtranspose(m):: 行列 m の転置行列を求める（m はリストのリストでもよい）
リストのリストの時は，内部のリストの長さが順に変わらないか減少していれば転置となる．
（行列のときの例は mtoupper() の項）[0] L=[[1,2,3],[4,5],[6,7]]$[1] os_md.mtranspose(L);[[1,4,6],[2,5,7],[3]]324. madjust(m,w|null=n)255

:: 行列 m の列数を w に調整する• w > 0 のときは，列数が w になるように分割し，分割されたブロックは行を増やして繋げる．
• w < 0 のときは，列数を |w| 倍し，w > 0 のときの逆操作で行数を減らす．
• null=n : 行列の列数調整で定義されない成分を n とする．n = 0 がデフォルト．
• m はリストのリストでもよい．
[0] M=os_md.mgen(3,5,a,1);[ a11 a12 a13 a14 a15 ][ a21 a22 a23 a24 a25 ][ a31 a32 a33 a34 a35 ][1] os_md.madjust(M,3);[ a11 a12 a13 ][ a21 a22 a23 ][ a31 a32 a33 ][ a14 a15 0 ][ a24 a25 0 ][ a34 a35 0 ][2] os_md.madjust(M,-2|null="?");[ a11 a12 a13 a14 a15 a31 a32 a33 a34 a35 ][ a21 a22 a23 a24 a25 ? ? ? ? ? ]325. mpower(m,n):: 行列 m の n 乗を求める
n は整数．
[0] M=newmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[1] os_md.mpower(M,0);[ 1 0 ]
[ 0 1 ]
[2] os_md.mpower(M,3);[ a^3+2*c*b*a+d*c*b b*a^2+d*b*a+c*b^2+d^2*b ][ c*a^2+d*c*a+c^2*b+d^2*c c*b*a+2*d*c*b+d^3 ][3] os_md.mpower(M,-2);[ (c*b+d^2)/(d^2*a^2-2*d*c*b*a+c^2*b^2) (-b*a-d*b)/(d^2*a^2-2*d*c*b*a+c^2*b^2) ][ (-c*a-d*c)/(d^2*a^2-2*d*c*b*a+c^2*b^2) (a^2+c*b)/(d^2*a^2-2*d*c*b*a+c^2*b^2) ]n が正の時は，m, m2 , m4 = (m2 )2 , . . . と計算して積を求めている (n を 2 進法で表した 1 の部分に対応する積)．負の時は m−1 に対して同様な計算．
326. mtoupper(m,n|opt= t,step=1,dviout=1,pages=1,tab=k,lim=w):: 行列 m に対し，以下の行基本変形を行って，行の先頭からの 0 の成分の個数が下の行の方へ狭義単調増加となるようにする．最後の n 列は無視．途中の行から全て 0 になることもある．
• 行頭からの 0 の成分の個数の下方への単調性を保って，以下の操作を 1 行目から順に行う．
– m のある行のスカラー倍を別の行に加える– 行を入れ替え，（opt>1 でなければ）後ろに移動した行を −1 倍する．
• opt=1 : さらに行の 0 でない先頭の要素のある列は，行変形でその要素以外を 0 にする．
• opt=2 : さらに行に 0 でないスカラーをかけて 0 でない行の先頭の成分を 1 にする．

256

• opt=3 : opt=2 とほぼ同じだが，より簡単な計算になるように行交換を増やす（以下の (b), (c) のみ考慮）．

• opt=4 : opt=3 とほぼ同じだが，さらになるべく分数が現れない簡単な行変形にする．
• opt=5 : opt=4 とほぼ同じだが，行列が一つのパラメータを多項式として含むとき，そのパラメー
タによって必要に応じて場合分けを行う．ただし，パラメータの値が有理数で場合分け可能なときに限る．
• opt=6, opt=7 : opt=5 とほぼ同じだが，行列に含まれるパラメータが 2 個以上でも出来るだけ場
合分けを用いて基本変形する．
• 最後の n 列は無視する．よって最後の n 列のみに現れる変数は，上のスカラーには含まれない．
通常 n は 0 または 1 または −1．
– −n が m の行数に等しいときは，m の右側にサイズ |n| の単位行列を付加して列サイズを |n|だけ増やした行列に対し，最後の |n| 列を無視して行変形を行う．
N =size(m)[0] とおくと mperm(m,−N|opt=2),0,[N,[N]]) が m の変換行列となる．特に m が可逆行列であるならば，これは m の逆行列となる．
– n = −1 のときは，第 k 番目の成分が (zz)k−1 となる縦ベクトルを列の最後に付加して列サイズを一つ増やした行列 m0 に対して，mtoupper(m0 , 1) を行う．
– A が変数 zz を含まない size S × S 0 の行列ならば，B = mtoupper(A, −1) とおくと，変換後の行列は mperm(B,1,[0,[S 0 ]]) となり，mycoef(B[I-1][S 0 ],J-1,zz) が左からかける変換行列の (I, J) 成分となる．
• step=1 を指定したときは，途中の行変形過程を表示する．
• dviout=1 は step=1 を指定したときのみ有効で，途中の行変形過程を dviout で表示する．
– こ の と き cr= の オ プ シ ョ ン で 改 行 の LATEX コ ー ド を 指 定 可 能（ デ フ ォ ル ト は
cr="\\\\\n & "で，cr=7 と同じ).
たとえば，dviout で表示する場合は，risaout.tex の begin{document}の直前に\def\pause{\special{dviout ‘+M-}}の一行を挿入しておき，cr="\\\\ \\pause\n &"（cr=23 と同じ）とすれば，表示の際にspace キーを押す毎に 1 ステップずつ進む．
– 通常は 1 ステップ毎に改行されるが，lim=w を指定すると，行幅が w 文字程度と見なして 1
行に複数ステップを入れる．
• dviout=2 も同様であるが，表示は行わない．
• dviout=-1 では，TEX のソースを返す．
• dviout=-2 では，TEX のソースの元となるリストを返す．返されたものを L とするとltotex(reverse(L)|opt=["cr","spts0"],str=1,cr=7)によって TEX のソースが得られる．
• tab=k : dviout を指定し step に 5 以上を指定したときの場合分けのインデントの幅を k mm とする（デフォルトは k = 2）．
• pages=1 : dviout を指定したとき，途中で改ページを許す（結果が長くなる場合などに指定）• unim() によって行基本変形の演習用の行列生成ができる．
• 行基本変形の手順は以下のようになっている．
（a）行列 M = (mj,ℓ ) は k − 1 列目まで基本変形が終了した行列で，それの j0 − 1 行目までの基本変形が完了しているとする．このとき k − 1 列までの成分は j0 行目以降は 0 となっていて，j0 − 1 行目までの行の 0 でない先頭成分は 1 で，それは k − 1 列目以下で，その列の他の成分は 0 になっている．また k 列
目には j0 行目またはそれ以降に初めて 0 でない成分 mj,k があるとする．
以下のように j0 行目またはそれ以降の 0 でない t 行目の成分 mt,k を調べて基準の j1 行目を決め，（必要なら）行交換してそれを j0 行目に移動する．得られた行列 M = (mj,ℓ ) において mj0 ,k で j0 行目を割り，j0 行目のスカラー倍を他の行に加えて少なくとも k 列目までの基本変形を終了させる．
（b） j 行目またはそれ以降の成分 mt,k で 1 となるものがあればその最初の t を j1 行目とおく．
（c）そうでなくて j 行目またはそれ以降の成分 mt,k で −1 となるものがあればその最初を j1 行目とおく．
（d）そうでなくて j 行目またはそれ以降の成分 mt,k が正整数で，その行を mt,k で割ったものが整数行ベク
トルになるものがあればその最初の行を j1 行目とする．

257

（e）そうでなくて j 行目またはそれ以降の成分 mt,k が負整数で，その行を mt,k で割ったものが整数行ベク
トルになるものがあればその最初の行を j1 行目とする．
（f）そうでなくて j 行目またはそれ以降の成分 mt,k が 0 でなくて，その行を mt,k で割ったものが整数行ベクトルになるものがあればその最初の行を j1 行目とする．
（g）そうでなければ，t 行目の成分 mt,k が整数で，k 行目以降の t 行目と異なる j 行目に t 行目の整数倍を足して (j, k) 成分を 0 に出来るか調べ，可能ならそれを行う．
（h）そうでなければ，t 行目の成分 mt,k が整数で，j 行目以降のある行を t 行目に足すか引くかして (t, k) 成
分を 1 に出来るか調べ，可能ならそれを行って j1 = t とする．ただし，j 行目と t 行目に変数を含まないものを優先する．
（i）そうでなければ，t 行目の成分 mt,k が整数で，j 行目以降のある行目に j 行目以降のある行の整数倍を足すか引くかして (t, k) 成分を 1 に出来るか調べ，可能ならそれを行ってその行を j1 = t とする．ただし，j 行目と t 行目に変数を含まないものを優先する．
（j）そうでなければ，t 行目の成分 mt,k が整数で，j 行目以降のある行に j 行目以降のある行を足すか引くかして (t, k) 成分を −1 に出来るか調べ，可能ならそれを行って j1 = t とする．ただし，j 行目と t 行
目に変数を含まないものを優先する．
（k）そうでなければ，t 行目に j 行目以降のある行の整数倍を足すか引くかして (t, k) 成分を −1 に出来るか調べ，可能ならそれを行って j1 = t とする．ただし，j 行目と t 行目に変数を含まないものを優先する．
（l）そうでなければ最初に現れた整数成分 mt,k の行を，整数の行がなければパラメータを含まない数 mt,kの最初の行を j1 行とする．
（m） opt>4 のとき，k 列目の有理式 mt,k の分子がある一つパラメータの多項式となっているとき，行変形によって k 列目の成分の分子の多項式の最低次数を下げることができればそれを行うことを続ける．
（n） opt>4 のとき，k 列目の成分で分子が数となる mt,k があれば，その最初の行 t によって j1 = t とする．
（o） opt>4 のとき，有理式 mt,k で分子の最大公約元の多項式の根が有理数で与えられるときは，その項が 0となる場合をまず扱って行変形の最終形まで求める．そのあと j1 = t とする．
（p） opt>4 のとき，mt,k が 0 になるための条件が，ある変数がその変数を含まない変数の多項式や分母が 0でない有理式（ただし opt=5 のときは有理数）で与えられるものがあるかどうか調べ，そのような t が存在すれば 0 になる場合を最終形まで求め，次に 0 にならない場合を調べるため j1 = t とする．
（q）以上に該当しなければ，成分 mt,k の型が最小となるものが最初に現れる行 t に対して j1 = t とする．

opt>4 で行列の成分が有理式の時は，いずれの成分の分母も 0 でないと判断し，(o) や (p) における場合分けでいずれかの成分の分母が恒等的に 0 になる場合は省かれる．
[0] M=newmat(2,3,[[a,b,1],[c,d,x]]);[ a b 1 ][ c d x ][1] os_md.mtoupper(M,1);[ a b 1 ]
[ 0 (d*a-c*b)/(a) (a*x-c)/(a) ][2] os_md.mtoupper(M,0);[ a b 1 ]
[ 0 (d*a-c*b)/(a) (a*x-c)/(a) ][3] os_md.mtoupper(M,1|opt=1);[ a 0 (-b*a*x+d*a)/(d*a-c*b) ][ 0 (d*a-c*b)/(a) (a*x-c)/(a) ][4] M=os_md.mtranspose(M);[ a c ]
[ b d ]
[ 1 x ]
[5] os_md.mtoupper(M,0);[ a c ][ 0 (d*a-c*b)/(a) ]258

[ 0 0 ][6] M=newmat(3,3,[[0,0,1],[1,1,1],[1,1,2]]);[ 0 0 1 ][ 1 1 1 ][ 1 1 2 ][7] os_md.myrank(M);2[8] os_md.mtoupper(M,0|opt=1,step=1)$[ 0 0 1 ][ 1 1 1 ][ 1 1 2 ]line1 <-> line2[ 1 1 1 ][ 0 0 -1 ][ 1 1 2 ]line3 -= line1[ 1 1 1 ][ 0 0 -1 ][ 0 0 1 ]line1 += line2[ 1 1 0 ][ 0 0 -1 ][ 0 0 1 ]line3 += line2[ 1 1 0 ][ 0 0 -1 ][ 0 0 0 ][9] A=mat([2,1],[1,2]);[ 2 1 ]
[ 1 2 ]
[10] os_md.mtoupper(A,-2|opt=2,step=1)$[ 2 1 1 0 ][ 1 2 0 1 ]line1 * (1/2)[ 1 1/2 1/2 0 ][ 1 2 0 1 ]line2 -= line1[ 1 1/2 1/2 0 ]259

[ 0 3/2 -1/2 1 ]line2 * (2/3)[ 1 1/2 1/2 0 ][ 0 1 -1/3 2/3 ]line1 += line2 * (-1/2)[ 1 0 2/3 -1/3 ][ 0 1 -1/3 2/3 ][11] os_md.mtoupper(A,-2|opt=3,step=1)$[ 2 1 1 0 ][ 1 2 0 1 ]line1 <-> line2[ 1 2 0 1 ][ 2 1 1 0 ]line2 += line1 * (-2)
[ 1 2 0 1 ][ 0 -3 1 -2 ]line2 * (-1/3)[ 1 2 0 1 ][ 0 1 -1/3 2/3 ]line1 += line2 * (-2)
[ 1 0 2/3 -1/3 ][ 0 1 -1/3 2/3 ][12] os_md.myinv(A);[ 2/3 -1/3 ][ -1/3 2/3 ][13] os_md.mtoupper(A,-1|opt=2);[ 1 0 -1/3*zz+2/3 ][ 0 1 2/3*zz-1/3 ][14] os_md.mtoupper(mat([2,1,3],[1,2,3]),-2|opt=3,step=1,dviout=1)$


2 1
1 2

3
3

1
0




2 3 0 1−−−−−−−−→
1 3 1 0
line2 −= line1×(2)1 2
3 0−−−−−−−−−−−−→
0 −3 −3 1
line1 ↔ line2



0
1

1
2

260


1
−2

line2 ×= ( −13 )−−−−−−−−−−→

10

line1 −= line2×(2)−−−−−−−−−−−−→

2
1

3
1

0

1

−1
3

1 0
0 1

2
3
2
3
−1
3

1
1


−1
3
2
3



[15] os_md.mtoupper(os_md.s2m("32,53"),-2|opt=3,step=1,dviout=1)$


3
5

2
3

1
0



0
1

line1 ×= ( 13 )−−−−−−−−−→



2
3

1
5

1
3


0
1

3 0


1
0
1 23
3
−−−−−−−−−−−−→
−5
1
0 −1
3
3


2
1
line2 ×= (−3)
1 3 30−−−−−−−−−→
0 1 5 −3
line1 −= line2×( 23 )1 0 −3 2−−−−−−−−−−−−−→
0 1 5 −3
line2 −= line1×(5)[16] os_md.mtoupper(os_md.s2m("32,53"),-2|opt=4,step=1,dviout=1)$


3 2
5 3

1
0

0
1




1 0
−−−−−−−−−−−−→−2 1
−1 −1 −2 1
line1 ↔ line2−−−−−−−−→
3
2
1 0


line1 ×= (−1)
1 1 2 −1−−−−−−−−−→
3 2 1 0
line2 −= line1×(3)1 1
2 −1−−−−−−−−−−−−→
0 −1 −5 3line2 ×= (−1)
1 1 2 −1−−−−−−−−−→
0 1 5 −3

1 0 −3 2
line1 −= line2−−−−−−−−−→
0 1 5 −3
line2 −= line1×(2)



3
2
−1 −1

[16] os_md.mtoupper(mat([a,2],[a+2,4*a+2]),0|step=1,opt=5,dviout=1)$


a
a+2

2
4a + 2a 2−−−−−−−−−−−−−→
2 4a


2 4a
line1 ↔ line2−−−−−−−−→a 2

line1 ×= ( 21 )1 2a−−−−−−−−−→a 2

line2 += line1×(−a)
12a−−−−−−−−−−−−−→
20 −2a + 2
line2 += line1×(−1)

261If a = 1,


1 2
0 0
If a = −1,


1 −2
0 0
If a2 − 1 6= 0,

(

−1 )
2
a2 −1




1 2a
0 1


line1 += line2×(−2a)
1 0−−−−−−−−−−−−−−→
0 1
line2 ×=−−−−−−−−−−−−→[17] os_md.mtoupper(mat([a,b],[c,d]),-2|step=1,opt=6,dviout=1)$


a b
c d

1
0

0
1

If a = 0,

0 b
c d

1 0
0 1

If c = 0,

0 b
0 d

1 0
0 1







If b = 0,
0 0 1 00 d 0 1
If d = 0,

0 0 1
0 0 0

0
1



If d 6= 0,0−−−−−−−−→0
1
line1 ×= ( d )0−−−−−−−−−→
0
If b 6= 0,
line1 ×= ( 1b )0−−−−−−−−−→
0
line1 ↔ line2

d 0 1
0 1 0
1
0

0
1



1
d



0


1 1b 0d 0 1
line2 += line1×(−d)
0 1 1b−−−−−−−−−−−−−→
0 0 −db
If c 6= 0,

c d 0 1
line1 ↔ line2−−−−−−−−→
0 b 1 01
line1 ×= ( c )1 dc 0 1c−−−−−−−−−→
0 b 1 0

262


0
1

If b = 0,
1 dc 00 0 1
If b 6= 0,

1
c



0

line2 ×= ( 1b )−−−−−−−−−→



d
c

1
0

1

−d
c

)
−−−−−−−−−−−−−−→
line1 += line2×(

If a 6= 0,

1
line1 ×= ( a)−−−−−−−−−→



1
b



0
−d
cb
1
b

1 0
0 1

b
a

1
c

1
c

0

1
a

1
c



0


0
1

d 0


b
1
line2 += line1×(−c)
10aa−−−−−−−−−−−−−→−c0 da−cb
1aa
cb
If d = ,
a


1
1 ab
0
a
1
0 0 −ca
If da − cb 6= 0,a1
line2 ×= ( da−cb) 1 ab0a−−−−−−−−−−−−→−ca
0 1 da−cb
da−cb


d
−b
line1 += line2×( −b1 0 da−cb
a )da−cb−−−−−−−−−−−−−−→−ca
0 1 da−cb
da−cb[18] os_md.mtoupper(mat([a^4-b^2,b]),0|step=1,opt=6,dviout=1)$
a 4 − b2
If b = a2 ,0 a2
If a = 0,

b





(0 0)
If a 6= 0,
line1 ×= ( 12 )−−−−−−−−a−→ (0If b = −a ,

1)

2

0 −a2
If a = 0,(0 0)
If a 6= 0,
line1 ×= ( −1)a2−−−−−−−−−−→ (0 1)

If a4 − b2 6= 0,
line1 ×=(1
a4 −b2)−−−−−−−−−−−−→ 1ba4 −b2

[19] os_md.mtoupper(mat([a*(a+b),1/(a+b)]),0|opt=6,step=1,dviout=1);263

a(a + b)
If a = 0,
0

1
b

1
a+b





line1 ×= (b)−−−−−−−−→ (0If a 6= 0,1)

1
line1 ×= ( a(a+b)) −−−−−−−−−−−−→ 1

1a(a+b)2



上では，(1, 2) 成分を見て，a + b 6= 0 と判断している．

[20] os_md.mtoupper(mat([a^4+b^2,b]),0|step=1,opt=6,dviout=1)$
a 4 + b2bAssume a4 + b2 6= 0,
line1 ×=(1
a4 +b2)−−−−−−−−−−−−→ 1ba4 +b2



327. mytrace(m):: 行列の trace を返す．
328. mydet(m):: det(m) と同じ．ただし成分は有理式でもよい．
329. mydet2(m):: det(m) と同じ．ただし成分は有理式でもよい．
mydet() は det() を，また mydet2() は mtoupper() を利用する．
[0] M=newmat(3,3,[[1,x,x^2],[1,y,y^2],[1,z,z^2]]);[ 1 x x^2 ][ 1 y y^2 ][ 1 z z^2 ][1] fctr(os_md.mydet2(M));[[-1,1],[y-z,1],[x-z,1],[x-y,1]][2] N=newmat(3,3,[[1,x/y,x^2/y^2],[1,y/z,y^2/z^2],[1,z/x,z^2/x^2]]);[ 1 (x)/(y) (x^2)/(y^2) ][ 1 (y)/(z) (y^2)/(z^2) ][ 1 (z)/(x) (z^2)/(x^2) ][3] os_md.fctrtos(os_md.mydet2(N));-(z*x-y^2)*(y*x-z^2)*(x^2-z*y)/(z^2*y^2*x^2)[4] det(N);internal error (SEGV)
return to toplevel
330. permanent(m):: 正方行列の permanent を返す[0] os_md.permanent(os_md.mgen(3,3,[x,y,z],1));(x1*y2+x2*y1)*z3+(x1*y3+x3*y1)*z2+(x2*y3+x3*y2)*z1
331. myrank(m):: 行列 m の rank を求める（例は mtoupper() の項）
264

332. mykernel(m|opt=1):: 行列 m の転置行列の kernel の基底を求める
オプション opt=1 を指定したときは，転置しない行列とする．
[0] A=newmat(4,3,[[x],[y,1,1],[0,1,1],[1,1,1]]);[ x 0 0 ][ y 1 1 ][ 0 1 1 ][ 1 1 1 ][1] os_md.mykernel(A);[[ y -x x 0 ],[ y-1 -x 0 x ]]333. myimage(m|opt=1):: 行列 m の転置行列の像の基底を求める• オプション opt=1 を指定したときは，転置しない像とする．
• 基底のベクトルの最初の 0 でない成分の位置は狭義単調増加で，他のベクトルのその位置の成分は0 となっている．
[0] A=newmat(4,3,[[x,-x],[y,1-y,1],[0,1,1],[0,1,2]]);[ x -x 0 ][ y -y+1 1 ][ 0 1 1 ][ 0 1 2 ][1] Im=os_md.myimage(A|opt=1);[[ x 0 -y 0 ],[ 0 1 1 0 ],[ 0 0 0 1 ]][2] V=newvect(4,[1,1,1,1]);[ 1 1 1 1 ][3] os_md.mymod(V,Im);[ 0 0 (y)/(x) 0 ][4] os_md.mymod(V,Im|opt=1);
1[5] os_md.mymod(V,Im|opt=2);[ (y)/(x) ]334. mymod(v,[v1 , . . . , vk ]| opt=ℓ):: ベクトル v1 , . . . , vk で張られる空間の商空間への v の射影を求める（例は myimage() の項）• v1 , . . . , vk の 0 でない要素の位置は，順に真に増加している必要がある．
• オプション opt=1 を指定した場合，射影が 0 のとき 0 を，それ以外では 1 を返す．
• opt=2 を指定したときは，商空間の標準基底を取った射影を表す．
335. mmod(m,[v1 , . . . , vk ]| opt=1):: ベクトル v1 , . . . , vk で張られる空間の商空間への線形写像 m の射影• v1 , . . . , vk の 0 でない要素の位置は，順に真に増加している必要がある．また，opt=1 を指定しないときは，これらで張られる空間は m で不変でなければならない．
• opt=1 のときは，商空間上の線形変換でなくて，商空間への線形写像とみなす（このときは m は正方行列でなくてよい）．

336. myinv(m):: 正方行列 m の逆行列を求める
成分は有理式でもよい．m が可逆でないとき，0 を返す．

265

[0] M=newmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[1] os_md.myinv(M);[ (d)/(d*a-c*b) (-b)/(d*a-c*b) ][ (-c)/(d*a-c*b) (a)/(d*a-c*b) ]337. madj(g,m):: 行列 gmg −1 を計算する．m は行列のリストか行列のベクトルでもよい．
338. diagm(m,a):: 対角行列を作成する
mgen(m,0,a,1) と同じ
339. mgen(m,n,a,s|sep=1):: size m × n の一般行列を作成する• (i, j)-成分は a が変数の時 ai0 j 0 で，リストの時 a[i]j 0 で与えられる（i0 = i + s, j 0 = j + s）
• s は 0 または 1 で，成分の index は s から始まるものとする．
• a や a[i] は文字列でもよい．また，以下の 3 つの場合（n = 0, −1, −2）のときは数字でもよい．
• n = 0 または diag のときは size m の対角行列を返す．
• n = −1 または highdiag のときは対角成分の一つ上の成分のみ 0 でない size m の正方行列を返す．

• n = −2 または lowdiag のときは対角成分の一つ下の成分のみ 0 でない size m の正方行列を返す．
• n = −3 または skew のときは size m の歪対称正方行列を返す．
• n = −4 または symmetric のときは size m の対称正方行列を返す．
• n = −5 または perm のときは size m の置換行列を返す．この行列 G で縦ベクトルを変換すると，
i 番目に ai 番目の成分が入る．
• sep=1 を指定すると，二重インデックスの間に _ を入れる．
• リストの要素の個数が足りないときは，最後の要素がそれ以降も続いているとみなされる．
mgen(0,0,0,0) で簡単な仕様が表示される．
[0] os_md.mgen(2,2,c,0);[ c00 c01 ][ c10 c11 ][1] os_md.mgen(2,3,[a,b],1);[ a1 a2 a3 ][ b1 b2 b3 ][3] os_md.mgen(3,"diag","a_",1);[ a_1 0 0 ][ 0 a_2 0 ][ 0 0 a_3 ][4] os_md.mgen(2,"diag",[a,b],0);[ a 0 ]
[ 0 b ]
[5] os_md.mgen(3,"diag",[1,2,3],0);[ 1 0 0 ][ 0 2 0 ][ 0 0 3 ][6] os_md.mgen(3,"diag",[x],0);266

[ x 0 0 ][ 0 x 0 ][ 0 0 x ][7] os_md.mgen(3,"highdiag","e_", 1);[ 0 e_1 0 ][ 0 0 e_2 ][ 0 0 0 ][8] os_md.mgen(3,"skew",[a,b,c],0);[ 0 a1 a2 ][ -a1 0 b2 ][ -a2 -b2 0 ][9] os_md.mgen(3,"symmetric",[a,b,c],1);[ a1 a2 a3 ][ a2 b2 b3 ][ a3 b3 c3 ][10] os_md.mgen(4,"diag",[a],0)+os_md.mgen(4,"lowdiag",[1],0);[ a 0 0 0 ][ 1 a 0 0 ][ 0 1 a 0 ][ 0 0 1 a ][10] os_md.mgen(3,"perm",[3,1,2],1);[ 0 0 1 ][ 1 0 0 ][ 0 1 0 ]340. unim(s|abs=m,num=n,both=1,int=1,rank=r,conj=1,res=1,wt=w,dviout=t,lim=w):: 行列式 1 でサイズ s の整数行列をランダムに生成する，行列 s をランダムに変換する• s が正整数の時は，サイズ s で行列式が 1 の行列をランダムに生成する．
• s が正整数で conj=1 を指定したときは，サイズ s の行列とその Jordan 標準型の組をランダムに生成する．
– wt=w によって固有値の広がり（サイズ +w）を指定できる（w = 2 がデフォルト）．
– diag=1 によって，対角化可能行列に制限する．
– res=1 によって，変換行列とその逆行列も返す．すなわち戻り値が [A, B, P, Q] ならば
P = Q−1 , B = P AQ で，B が A の Jordan 標準形．
∗ int=1 を指定すると自明な部分があって不適切な問題が減らされる．
∗ int=2 を指定すると，上に加えて整数行列 Q がユニモジュラーではない例も含める（このとき P の成分は整数でない）．ただし，int の値をより大きくすると，その例の割合は少なくなる．
∗ dviout=1 を指定すると，TEX を使って結果を画面表示する．
∗ dviout=-1 を指定すると，TEX のソースを返す．
• s が行列の時は，ある行の整数倍を別の行に加える変換を何度かランダムに行って返す．
• s が行列で both=1 を指定したときは，列に関しても同様な変換を行う．
• s が正方行列で conj=1 を指定したときは，与えられた行列に共役な行列をランダムに返す．
• s が [p,q] という正整数のリストの時は，行基本変形のための p × q 行列をランダムに生成する．
行列の階数が 2 以上で p と q を越えないものが，各階数に対してほぼ等確率で得られる．
• s が [p,q,k1 ,k2 ,. . .] というリストの時は，ある行の kν 列目が先頭の 1 となる簡約行列に行基本
変形で変換される p × q 行列をランダムに生成する．

267

• s がリストの時，rank=r で行列の階数を指定する．
• s がリストの時，int=1 で行基本変形による簡約行列が整数行列になるものに制限する（一般の場
合も分母は 1 桁の整数に抑えられている）．
• s がリストの時，生成される行列の 1 列目と 2 列目が線形独立となる確率は高めに設定してあるが，wt=w によってそれを変更する（w は非負整数で，デフォルトは w = 2 である．この値が大きいほど確率は高くなる）．

• s がリストの時，res=1 である行の整数倍を別の行に加える変換で得られる上三角行列も返す．
– さらに dviout=1 を指定すると，TEX を使って基本変形の過程を含めて結果を画面表示する．
このとき mtoupper() における lim=w の指定が可能．
– 前項で dviout=1 と指定した場合は，TEX のソースを返す．
• 現れる行列の成分の絶対値が許される範囲内に留まる整数行列内の変形のみが使われる．
• abs=m : 成分の絶対値の最大値を m 以下とする（デフォルトは m = 9）．
• num=n : ランダム化の程度（n = 100 または 200 がデフォルト）．
[0] os_md.unim(4);/* 行列式 1 の 4x4 行列 */[ 3 -2 -8 3 ][ -7 -7 -6 7 ][ 8 7 5 -7 ][ -3 1 6 -2 ][1] os_md.unim([4,5]);/* 行基本変形用 4x5 行列 */[ 2 -2 2 6 9 ][ 3 2 -7 -1 -1 ][ -6 -1 8 -4 -2 ][ 0 4 -8 -8 -5 ][2] os_md.unim([3,3]|rank=2);/* 階数が 2 の行基本変形用 3x3 行列 */[ -9 7 5 ][ 5 -4 -3 ][ 7 1 9 ][3] os_md.unim([3,3]|rank=2,abs=99); /* 階数が 2 の行基本変形用 3x3 行列 */[ 28 -55 24 ][ -15 49 -91 ][ -33 64 -25 ][4] os_md.unim([4,5]|abs=3,res=1); /* 成分の絶対値が 3 以下 + 基本変形結果 */[[ -1 1 3 -3 3 ][ -2 -1 0 1 3 ][ -3 -1 1 -1 2 ][ 2 1 0 1 1 ],[ 1 0 -1 0 0 ][ 0 -1 -2 1 0 ][ 0 0 0 2 0 ][ 0 0 0 0 -1 ]][5] os_md.unim([4,5,0,1,3]);/* 0,1,3 列目が先頭の 1 となる行をもつ簡約型に変換できる行列 */[ 4 5 -6 2 -7 ][ -4 -6 8 1 -1 ][ 3 6 -9 -2 3 ][ 6 5 -4 -1 4 ]268

[6] os_md.unim(os_md.diagm(3,[0,-1,1])|conj=1); /* 固有値が 0,-1,1 の行列 */[ -4 -5 -8 ][ -6 -1 -6 ][ 7 -1 5 ][7] A=os_md.mgen(3,"highdiag",[1,0],0)+os_md.diagm(3,[0,0,1]);[ 0 1 0 ][ 0 0 0 ][ 0 0 1 ][8] os_md.unim(A|conj=1);/* A と共役な行列 */[ 3 -3 1 ][ 5 -1 -3 ][ 4 -2 -1 ][9] os_md.unim(4|conj=1);/* 正方行列と Jordan 標準形の組 */[[ 8 9 -1 -9 ][ -5 -5 6 4 ][ 2 2 -1 -2 ][ 2 3 5 -4 ],[ -1 1 0 0 ][ 0 -1 1 0 ][ 0 0 -1 0 ][ 0 0 0 1 ]]
[10] for(I=0,M=[];I<100;I++) M=cons(os_md.unim([3,4]),M)$[11] for(N=[];M!=[];M=cdr(M)) N=cons([length(os_md.mtoupper(car(M),0|step=1,
opt=7,dviout=-2)),car(M)],N)$[12] for(M=qsort(N);M!=[];M=cdr(M)) os_md.mtoupper(car(M)[1],0|step=1,opt=7,
dviout=2,lim=80)$/* 3x4 行列の行基本変形の問題 100 題 */[13] dviout(" ");[14] for(I=0,R=[];I<100;I++) R=cons(os_md.unim(4|conj=1,res=1,int=1),R);[15] S="&"+os_md.ltotex(R|opt="cr",cr=15)$[16] dviout(S|eq="align")$ /* 4 次正方行列の Jordan 標準形と変換行列 100 題 */上の [15] 以降を以下のようにしてもよい．

[15] for(T=[],S=R;S!=[];S=cdr(S))
T=cons([S[0][1],"&=",S[0][2],S[0][0],S[0][3]],T);[16] S=os_md.ltotex(T|opt=["cr","spts0"],str=1,cr=11)$[17] dviout(S|eq="align")$ /* 4 次正方行列の Jordan 標準形と変換行列 100 題 */上の [17] は，以下のようになる．



−1
0
0
0

−2
0
0
0

1
−1
0
0
0
−1
0
0

0
0
3
0
0
0
3
0

 
0
0
0 −1=1  103
 
000  1=0  0
−1
3

−1
5
−2
1
−2
1
1
0



5 0 −4 02
1
0−3 −1 2 2 −3 1  2
1
1  1 8 −7 0  3
1 −9 7 4
−1
−1 −1


−1 1
−1 6 5 −11
0 −1 −4 −1 0 4  01
0  44 3 −4 00
1−4 6 5 2
1
269


1 2 1
1 1 0
1 1 0
0 0 −1
1 1 0
1 0 1
−1 1 −1
1 1 1

[18] os_md.unim(4|int=2,conj=1,res=1,dviout=1);

  5

1
− 54
− 34
−1 0 0 0−6 5
24
 0 0 0 0 −5 2 −1 2  −4 4
 0 0 1 0 =  2
1
1 − 32   6 −1
11
1
0 0 0 3
−8 8
−4
− 14
2
4

2
1
8
8


0
5
0  3−6  5
−3
12


3 1 3
2 1 1
4 1 11
8 2 12341. newbmat(m,n,[[r00 , r01 , . . . ],[r10 , . . . ], . . . ]|null=t):: ブロック行列を作成する• rij の行または列のサイズが 1 のときは，ベクトルまたはリストで表してもよい．
• rij がサイズ 1 の正方行列のときは，スカラーで表してもよい．
• rij が 0 行列の時は 0 で表してもよい．
このとき null=t が指定してあれば，0 行列でなく，各成分が t の行列と解釈される．
• ブロック対角行列の時は，newbmat(m,m,[r00 ,r11 , . . .) と省略してもよい．
• ブロックに分けた各行や各列には少なくとも 1 つの行列があればよい．
[0] A=os_md.newbmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[1] os_md.newbmat(2,2,[[0,A],[2*A]]);[ 0 0 a b ][ 0 0 c d ][ 2*a 2*b 0 0 ][ 2*c 2*d 0 0 ][2] os_md.newbmat(2,2,[[A],[0,1]]);[ a b 0 ][ c d 0 ][ 0 0 1 ][3] os_md.newbmat(2,2,[A,1]);[ a b 0 ][ c d 0 ][ 0 0 1 ][4] os_md.newbmat(2,3,[[A]]);[ a b 0 0 ][ c d 0 0 ][ 0 0 0 0 ][5] os_md.newbmat(1,2,[[A,[e,f]]]);[ a b e ][ c d f ][6] os_md.newbmat(2,2,[[A],[0,0]]|null="A");[ a b A ][ c d A ][ A A A ][7] os_md.newbmat(2,2,[[A],[0,[0]]]|null="A");[ a b A ][ c d A ][ A A 0 ]270

342. meigen(m|mult=1,vec=1,TeX=1,sep=s):: 行列 m の固有値, 固有ベクトルを返す• mult=1 のときはスペクトル型の形で，重複度が大きい順に返す．
• m は行列のリストやベクトルでもよい．
• 有理式でない固有値は，zz の多項式の根で表される．
• unim() によって固有値計算練習用の行列の生成ができる．
• vec=1 を指定したときは，固有値と固有ベクトルの組を返す．このときは，m は行列か，可換な 2つの行列のリストとし，後者では同時固有値と同時固有ベクトルの組を返す．
さらに, TeX=1 を指定すると，TEX のソースを返す．このとき sep=s により区切り記号を指定できる．s が文字列の時は，改行を s に，s =[s1 ,s2 ] のときは，デフォルトの ”&:”, ”\\\n”を s1 ,
s2 に置き換える．たとえば sep=[":","\\quad\n"] などととする．

[0] A=newmat(3,3,[[1,-1,-1],[4,6,5],[-2,-2,-1]]);[ 1 -1 -1 ][ 4 6 5 ][ -2 -2 -1 ][1] os_md.meigen(A);[1,2,3][2] B=newmat(3,3,[[1,-1,-1],[4,6,5],[-2,-2,1]]);[3] os_md.meigen(B);[zz^2-6*zz+13,2][4] C=newmat(3,3,[[a],[0,b,2],[0,0,a]]);[ a 0 0 ][ 0 b 2 ][ 0 0 a ][5] os_md.meigen(C);[a,a,b][6] os_md.meigen(C|mult=1);[[2,a],[1,b]][7] os_md.ltotex(V|opt="spt");\left\{[a]_2,\, b%\right\}[8] os_md.meigen([A,C]);[[1,2,3],[a,a,b]][9] os_md.meigen([A,C]|mult=1);[[[1,1],[1,2],[1,3]],[[2,a],[1,b]]][10] os_md.meigen(C|vec=1);[[a,[[ 1 0 0 ],[ 0 2 a-b ]]],[b,[[ 0 1 0 ]]]]
[11] os_md.meigen(C|vec=1,TeX=1);\begin{align*}
a&:\begin{pmatrix}
1 & 0\\
0 & 2\\
0 & a-b271

\end{pmatrix}\\
b&:\begin{pmatrix}
0\\
1\\
0
\end{pmatrix}%\end{align*}[12] A1=newmat(3,3,[[0,alpha,0],[0,beta-gamma,0],[0,-beta,0]])$[13] A2=newmat(3,3,[[0,0,0],[0,0,0],[-beta,-beta,-alpha+gamma-beta]])$[14] A1*A2-A2*A1;[ 0 0 0 ][ 0 0 0 ][ 0 0 0 ][14] os_md.dviout(os_md.meigen(A1|vec=1,TeX=1,sep=[":","\\quad\n"])|eq=7)$

0:

1
0
0

!
0
0
1

β−γ :

−α
−(β − γ)β!

[15] os_md.dviout(os_md.meigen([A1,A2]|vec=1,TeX=1,sep=[":","\\quad\n"])|eq=7)$[0, 0] :−(α + β − γ)0
β!
[0, −α − β + γ] :

!
0
0
1

[β − γ, 0] :−α−(β − γ)β!

343. mdsimplify(m|show=1,type=ℓ):: 有理式正方行列 m，またはそのリストやベクトルを対角行列で簡単化• 元の行列は保たれない．
• show=1 を指定すると，用いる対角行列も示す．
• type=1 とすると，行と列の分母を列と行に変換する．
• type=2 (resp. 3) のときは行（resp. 列）の分母を列（resp. 行）に変換する．
[0] A=newmat(2,2,[[a,b/c^2],[c/b,d]]);[ a (b)/(c^2) ][ (c)/(b) d ][1] os_md.mdsimplify(A|show=1);[[ a (1)/(c) ][ 1 d ],[ (c)/(b) 1 ]]344. mext2(m):: 線型変換の外積を与える
P
正方行列 m = (aij ) が ui 7→(0 ≤ ν < n) という線型変換に対し ui ∧ uj 7→0≤ν<n aiν uνPP0≤ν<n aiν uν ∧uj +0≤ν<n ajν ui ∧uν という線型変換の行列を与える．成分は (i, j) (0 ≤ i < j < n)の辞書式順序で並べる．

[0] M=os_md.mext2(os_md.mgen(4,4,a,1))$[1] dviout(M);

272




a11 + a22
u1 ∧ u2
 a32
u1 ∧ u3 
u1 ∧ u4  7→  a42
 −a31u2 ∧ u3  −a41u2 ∧ u4 

a23
a11 + a33
a43
a21
0
−a41

a24
a34
a11 + a44
0
a21
a31

−a13
a12
0
a22 + a33
a43
−a42

−a14
0
a12
a34
a22 + a44a32u1 ∧ u20−a14  u 1 ∧ u 3 u1 ∧ u4 
a13 




−a24  u 2 ∧ u 3 
u2 ∧ u4 
a23
u3 ∧ u4
a33 + a440
u3 ∧ u4345. transm(m|dviout=1):: 行列 m の基本変形をインタラクティブに行う• dviout=1 を指定すると，TEX を用いて結果の画面表示ができる．
• m は s2m() の引数の形式でもよい．
表示される ? の後に１行キー入力して指示することによって基本変形する．例えば空: コマンドの表示
2,5: 2 行目と 5 行目の入れ替え
2,5,-2 : 2 行目に 5 行目の −2 倍を加える
2,2,-2 : 2 行目を −2 倍する
2,5,0 : 2 行目に 5 行目のスカラー倍を加えて，2 行目における 5 行目の先頭の 0 でない列を 0 に
r,2,5 : 2 列目と 5 列目の入れ替え（列変形を行うには先頭に r をつける）
s,x,2 : x に 2 を代入する
t: 転置する0: 最初の行列に戻る
f: 一つ前の行列に戻るg: 次の行列へ（f の直後のみ可能）a: 以降，自動的に行基本変形を行う
A: 上と同じだが dviout=1 のときは，TEX を用いた画面表示となるq: 終わり（変形の過程の行列をリストにして返す）[0] L=os_md.transm(mat([2,3,1,-1,a],[3,2,2,1,1],[4,0,3,4,1],[5,4,4,1,1]))$[ 2 3 1 -1 a ][ 3 2 2 1 1 ][ 4 0 3 4 1 ][ 5 4 4 1 1 ]?
2,5: line2 <-> line5
2,5,-2 ; line2 += (-2)*line5
2,2,-2 : line2 *= -2
2,5,0 : line2 += (?)*line5 for reduction....
? 3,2,-1[ 2 3 1 -1 a ][ 3 2 2 1 1 ][ 1 -2 1 3 0 ][ 5 4 4 1 1 ]? 1,3[ 1 -2 1 3 0 ][ 3 2 2 1 1 ][ 2 3 1 -1 a ][ 5 4 4 1 1 ]273

? 2,1,0[ 1 -2 1 3 0 ][ 0 8 -1 -8 1 ][ 2 3 1 -1 a ][ 5 4 4 1 1 ]? f[ 1 -2 1 3 0 ][ 3 2 2 1 1 ][ 2 3 1 -1 a ][ 5 4 4 1 1 ]? s,a,1[ 2 3 1 -1 1 ][ 3 2 2 1 1 ][ 4 0 3 4 1 ][ 5 4 4 1 1 ]? q[1]
3.2.7 Strings
346. str char(s,n,t):: 文字列 s の n 文字以降に文字列 t の先頭文字が最初に現れる場所を返す（str chr() の拡張）
• 見つからないときは −1 を返す．
• s は，（たとえば strtoascii() で得られる整数の）リストやベクトルなどでもよい．
• s がリストやベクトルの時は，t は文字列以外（たとえば文字コード）でもよい．
• s がリストまたはベクトルの場合，型返還せずにそのまま扱うのでメモリー効率がよい．
• str str() の方が高機能．
347. str pair(s,n,t1 ,t2 |inv=1):: 文字列 s の n 文字以降で，文字（列）t2 の出現回数が t1 の出現回数を超える最初の位置を返す• 見つからないときは −1 を返す．
• s は，（たとえば strtoascii() で得られる整数の）リストやベクトルなどでもよい．
• t1 , t2 は文字コードでもよい．あるいは文字列でもよい．
• sjis=1 が指定されると，シフト JIS の文字列とみなして処理する．
• inv=1 が指定されると，文字列 s の n 文字以前で，文字（列）t1 の出現回数が t2 の出現回数を超える最後の位置を返す．ただし，sjis=1 の指定は無視される．
• s がリストまたはベクトルの場合，型変換せずにそのまま扱うのでメモリー効率がよい．
[0] os_md.str_pair("(1+((2+3)*5)/4)(6+",1,"(",")");
14[1] os_md.str_cut("(1+((2+3)*5)/4)(6+",0,14);(1+((2+3)*5)/4)[2] os_md.str_pair("(1+((2+3)*5)/4)(6+",13,"(",")"|inv=1);0[3] os_md.str_pair("(1+((2+3)*5)/4)(6+",9,"(",")"|inv=1);3348. str str(s,t|top=n,end=m,sjis=1):: 文字列 s に部分文字列 t が最初に現れる場所を返す
274

• 部分文字列 t が文字列 s に含まれないとき，−1 を返す．
• top=n が指定されると，最初の n 文字より後を探す（n = 0 がデフォルト）．
• end=m が指定されると，最初から m + 1 文字を除いた後から現れるものは探さない．
• sjis=1 が指定されると，シフト JIS の文字列とみなして処理する．
• s および t は（strtoascii() によって変換されたような）文字コードのリスト，あるいはベクトルでもよい．

• t の長さが 1 のときは文字コードでもよい．
• s が文字コードのリストまたはベクトルの場合，型変換しないのでメモリー効率がよくて高速．
• t がリストで，その成分が文字列（あるいはそれを文字コードのリストやベクトルとしたもの）であった場合, t の何番目（最初が 0 番目と数える）の文字列が s に最初に現れるかと，その位置の組とのリストを返す．いずれもが現れない場合は [−1, −1] を返す．
– t には頻度の多いものを先に並べる方が効率がよい．
– 同じ位置から t の複数の文字列が現れた場合，先に並べたものを返す．すなわち s ="aabc..."に対して t =["abc","ab"] とした場合，文字列 "abc" が見つけられる．
[0] os_md.str_str("abcdefghiabc", "bc");
1[1] os_md.str_str("abcdefghiabc", "bc"|top=2);10[2] os_md.str_str("abcdefghiabc", "ac");-1[3] os_md.str_str("abcdefghiabc", ["ab","gh"]|top=1);[1,6][4] os_md.str_str("abcdefghiabc", ["ab","gh"]|top=1,end=5);[-1,0][5] os_md.str_str("abcdefghiabc", ["bcd","bc"]);[0,1][6] os_md.str_str("abcdefghiabc", ["bcd","bc"]|top=2);[1,10]
349. str cut(s,m,n):: 文字列 s の先頭から m 文字をスキップして，それ以降 n − m + 1 文字を返す• s が文字列のときは sub str(s,m,n) と同じ（例は str pair() を参照）．
• s は文字コードのリストやベクトルでもよい（こちらの方がオーバーヘッドが少ない）．ただし，戻り値は文字列．

• n が十分大きいときは，s の m + 1 文字目以降を返す．
350. str subst(s,s0 ,s1 |sjis=1,raw=1) または
str_subst(s,[s00 , s01 , . . . ],[s10 , s11 , . . . ]|inv=1,sjis=1,raw=1)
str_subst(s,[[s00 , s10 ],[s01 , s11 ], . . . ],0|sjis=1):: 文字列 s に含まれる部分文字列 s0 を s1 で全て先頭から順に置き換える• 複数種の置き換え，すなわち部分文字列 s0j を s1j へ j = 0, 1, . . . の順に s の置き換えができる．
• 複数種置き換えで，置き換えられた部分文字列の再置き換えは行わない．
• s は strtoascii() によって置き換えられた整数のリストやベクトルでもよい（こちらの方がオー
バーヘッドが少ない．ただし，raw=1 を設定しないと，戻り値は文字列．
• inv=1 によって，逆に s1j を s0j へ j = 0, 1, . . . の順の置き換えが行われる．
• sjis=1 が指定されると，シフト JIS の文字列とみなして処理する．
• raw=1 が指定されていると，strtoascii() で置き換えられた整数のリストを返す（こちらの方がオーバーヘッドが少ない）．

275

[0] os_md.str_subst("abc", ["a","b"],["b","a"]);bac[1] os_md.str_subst("abcdefghi", ["bc","cd","ef"],["cd","ab","ef"]);acddefghi[2] os_md.str_subst("abcdefghi", [["bc","cd"],["cd","ab"],["de","ef"]],0);
acdeffghi
351. str times(s,n):: 文字列 s（またはリスト）を n 回繰り返した文字列（またはリスト）を返す• リストのときは，s = [[s1 , s2 , . . . , sk ]] とすると，[s1 , s2 , . . . , sk , s1 , s2 , . . . , sk , s1 , s2 , . . . ] という長さ n のリストを返す．
• s = [t1 , . . . , tk , [s1 , s2 , . . . , sk ]] のときは，[t1 , . . . , tk , s1 , s2 , . . . , sk , s1 , s2 , . . . , sk , s1 , s2 , . . . ] という長さ n のリストを返す．
[0] os_md.str_times("Abc",5);AbcAbcAbcAbcAbc[1] os_md.str_times([["Abc"]],5);[Abc,Abc,Abc,Abc,Abc][2] os_md.str_times([["Abc","Def"]],5)[Abc,Def,Abc,Def,Abc][3] os_md.str_times(["012",["Abc","Def"]],6);[012,Abc,Def,Abc,Def,Abc]
352. str addc(s,c,n|tail=1):: 文字列 s に文字 c を差し込んで長さ n にする
文字列 s の先頭（tail=1 のときは末尾）に文字 c を入れて長さ n の文字列にする．
c = 0 のときは，空白文字とする[0] os_md.str_addc("12","0",4);0012[1] os_md.str_addc("12","0",4|tail=1);
1200
353. str insert(s,u,[t,e]|transpose=1):: 文字列 s のリストの間に u の成分の（文字列の）リストを順に入れた差し込み文にする
s = [s0 , . . . , sn ], u = [u1 , . . . , un ], uj = [uj,1 , . . . , uj,m ] のとき
ts0 u1,1 s1 u1,1 · · · u1,n sn s0 u2,1 s1 u2,2 · · · sn s1 · · · um,n sn eを返す
• 3 つめの引数を 0 とすると，t と e が空の文字列とみなされる• transpose=1 : u の行と列を入れ替える[0] S=["ren foo_", ".pdf n_", ".pdf\n"]$ T=["AB12","BC34","CD56"]$[1] for(U=[],I=length(T);I>0;I--) U=cons(os_md.str_addc(rtostr(I),"0",3),U);[2] os_md.str_insert(S,[U,T],0|transpose=1);
ren foo_001.pdf n_AB12.pdf
ren foo_002.pdf n_BC34.pdf
ren foo_003.pdf n_CD56.pdf
上の T をたとえばエクセルの表の 2 項目から読み込むには，表を hyou.csv などとして書き出し

276

T=os_md.readcsv("hyou.csv"|col=2);とすればよい．さらに上の結果をバッチファイルとして実行するには

os_md.fcat("foo.bat",@@|exe=1);とする．
[U,T] をエクセルで作っておいて，その表を読み込むこともできる．

354. strip(s,t1 ,t2 ):: 文字列の外側の括弧を外す• s が t1 と t2 のペアの括弧で全体が囲まれているとき，その括弧を外した文字列を返す．
[0] os_md.strip("((x+y)^2+(y+z))","(",")");(x+y)^2+(y+z)[1] os_md.strip("(x+y)^2+(y+z)","(",")");(x+y)^2+(y+z)
355. n2a(n|m=m,s=s,opt=[ab],verb=1):: 自然数を一文字に縮める
自然数 10,11,... を a, b,... などと一文字で表すのが目的で，デフォルトでは ASCII コードを返す．すなわち，返されるのは
n = 0, . . . , 9 は文字 0, . . . , 9 の ASCII コード 48, . . . , 57
n = 10, . . . , 35 は，a, . . . , z の ASCII コード 97, . . . , 122
n = 36, . . . , 61 は，A, . . . , Z の ASCII コード 65, . . . , 90
n > 61 は文字列 “(n)”をアスキーコードのリストに変換したもの
n がリストのときは，各成分にこの変換を施したリストが返される• n をリストとする．このときは，以下の s=1 以外のオプションは無視される．
n の成分にリスト [a,b] が可能で，これは a, a + 1, . . . , b という自然数を並べたものとみなされる．sort=1 を指定すると，数の並びをソートする．
verb=1 を指定すると，上記の変換を行ったものが返される．
• オプションで m を指定すると，m を超える自然数は上の最後の形式になる（デフォルトは m = 61,
9 < m ≤ 61 が必要）
• オプションでたとえば opt="[]"のように指定すると，m 以上の自然数は “[n]”をアスキーコードのリストに変換したものが返される• オプションで s=1 を指定すると，文字列の形で返される• オプションで s=2 を指定すると，アスキーコードのリストが返される• 0 から 61 までの自然数は，数字またはアルファベットの一文字で表すことができる•（ラベルなどのため）0 から 25 までの自然数 n をアルファベットの小文字一文字で n2s(n+10|s=1)
により表すことができる．

[0] os_md.n2a(8);56[1] os_md.n2a(8|s=1);8[2] os_md.n2a(10|s=1);a[3] os_md.n2a(35|s=1);z[4] os_md.n2a(36|s=1);A277

[5] os_md.n2a(61|s=1);Z[6] os_md.n2a(62|s=1);(62)[7] os_md.n2a(62|s=1,opt="[]");[62][8] os_md.n2a(10|s=1,m=9);(10)[9] os_md.n2a([0,[8,10],11]|verb=1);[0,8,9,10,11][10] os_md.n2a([0,[8,10],11]|s=1);089ab[11] os_md.n2a([10,[8,10],11]|verb=1,sort=1);[8,9,10,10,11]356. s2os(s):: 文字列を入力可能な文字列に変換[0] S="\"表\計算\"";"表計算"[1] os_md.s2os(S);\"表\計算\"357. i2hex(i|cap=1,num=1,min=m):: 非負整数 i の 16 進表示• cap=1 16 進数表示に大文字を使う• num=1 16 進数表示の先頭に 0x をつける
• min=m 必要なら先頭に 0 をつけて m 桁以上にする（デフォルトは m = 2）
• i が非負整数のリストのときは，各成分を 16 進表示して返す• i が非負整数やリストでないときは整数 0 を返す[0] os_md.i2hex(123);7b[1] os_md.i2hex(123|cap=1);7B[2] os_md.i2hex(123|cap=1,num=1);
0x7B[3] os_md.i2hex([123,0,231]);[7b,00,e7]358. sjis2jis(l):: 文字コードの整数のリストの先頭 2 つを ShiftJIS から JIS に変換
変換後の長さ 2 の整数のリストを返す
359. jis2sjis(l):: 文字コードの数字のリストの先頭 2 つを JIS から ShiftJIS に変換
変換後の長さ 2 の整数のリストを返す[0] P="整数"$[1] L=strtoascii(P);278[144,174,144,148][2] i2hex(L);[90,ae,90,94][3] LL=os_md.sjis2jis(L);[64,48][4] os_md.jis2sjis(LL);[144,174]360. s2euc(s):: ShiftJIS または JIS 文字列を EUC 文字列に変換
0x0d のコードは削除して 0x0a のコードに変換する．
361. s2sjis(s):: EUC または JIS 文字列を ShiftJIS 文字列に変換
0x0a のコードは 0x0d 0x0a のコードに変換する．
362. str tb([s0 , s1 , . . . ],tb) または str_tb(0,tb):: テキスト用バッファを作成（tb = 0）し，そこ（戻り値 tb）に文字列 s0 , . . . を順に追加する．最初の引数を 0 として文字列を取り出す．
• tb = 0 のときは，tb は空文字列と解釈される．
• tb が文字列ならばそれで初期化されたテキスト用バッファを作成し，さらに第 1 引数で指定された文字列を順に追加したテキスト用バッファを返す．ただしここで第 1 引数が 0 のときは, それは空文字列と解釈される．

• tb がテキスト用バッファの場合は，第 1 引数が文字列またはそのリストのとき，それが順にバッファに追加される．ただし第 1 引数が 0 のときはテキスト用バッファの文字列を取り出して返す．
• 文字列が一つなら，[s0 ] は単に s0 でよい．
• この函数は，細かく文字列を追加していった場合のメモリー消費の非効率性を避けるために用いられる. また，str len(tb) でバッファに格納された文字列サイズが分かる．
[0] Buf=os_md.str_tb("This is ",0);This is[1] os_md.str_tb("a pen.",Buf)$[2] str_len(Buf);
14[3] Str=os_md.str_tb(0,Buf);
This is a pen.
[5] Buf=os_md.str_tb(" a pen.","This is");This is a pen.
[6] type(Buf);
21[7] type(Str);
7[8] Buf=os_md.str_tb(0,0);[9] X=3$[10] os_md.str_tb([rtostr(X),"^2=",rtostr(X^2)],Buf);3^2=9363. l2os(l):: リストを入力可能な文字列に変換279

• 行列やベクトルはリストに直す．これらはネスティング可能．
• 成分の文字列は " で囲って表示する．
[0] P=mat([x+y,"This is"],[(x+y)^2,"\"square\""]);[ x+y This is ][ x^2+2*y*x+y^2 "square" ][1] R=os_md.l2os(P);[[x+y, "This is"], [x^2+2*y*x+y^2, "\"square\""]][2] eval_str(R);[[x+y,This is],[x^2+2*y*x+y^2,"square"]]364. r2os(l):: 数式を eval str() で入力可能な文字列に変換• 行列，ベクトル，リストなども許される．これらはネスティング可能．
• 文字列は " で囲って表示する．
[0] P=mat([x+y,"This is"],[(x+y)^2,"\"square\""]);[ x+y This is ][ x^2+2*y*x+y^2 "square" ][1] R=os_md.r2os(P);mat([x+y,"This is"],[x^2+2*y*x+y^2,"\"square\""])[2] eval_str(R);[ x+y This is ][ x^2+2*y*x+y^2 "square" ]365. evalcoord(s):: 文字列 s から括弧で囲まれた座標を抽出
文字列またはそれを strtoascii() で変換したリストから最初の ( ) の組で挟まれた部分を座標とみなす．
その部分を数字のリストとし，それ以降の頭の空白を除いた文字列を strtoascii() で変換した数
字のリストとの組で返す．
座標でないなら，それを文字列のリストとする．

[0] os_md.evalcoord("This (2/3+1,3) is a coord.");[[5/3,3],[105,115,32,97,32,99,111,111,114,100,46]][1] asciitostr(@@[1]);is a coord.
[2] os_md.evalcoord("This (100 yen) is not.");[[100 yen],[105,115,32,110,111,116,46]]366. evalsint(s):: 文字列 s に含まれる整数とそれ以外を分離• 文字列から整数を表す文字列を整数に直して文字列を分離し，順にリストにする
文字列と整数が入れ替わり並んだリストとなる• 整数部分から切り離された文字列の先頭や末尾の空白は削る[0] os_md.evalsint("35C2");[35,C,2][1] os_md.evalsint("13 - 15 equals -12");280

[13,-,15,equals,-12][2] os_md.evalsint("13 -15 equals -2");[13,-15,equals,-2][3] os_md.evalsint("I am 15 years old");[I am,25,years old]
367. readTikZ(s):: 単純な TikZ のソースを描画実行形式に変換
現時点で以下の文（複数可）からなる文字列がサポートされ，描画実行形式に変換される．
• \draw[...] ま た は \fill[...] や \shade{...} な ど で 始 ま っ て ，複 数 の 座 標, --, ..,controls, and, cycle が続き ; で終わる文（[...] の部分はなくてよい）• \node[...] で始まり，そのあと at，座標と続き { } で囲まれた TEX の表示文字があって，; で終わる文• その他，os_muldif.rr で生成されるいくつかの TikZ のソース（主として座標成分が 2 個のもの）[0] S=os_md.xylines([[0,0],[1,1],[2,3]]|curve=1,opt="red")$[1] R=os_md.readTikZ(S);[[1,[[opt,red]],[[0,0],[0.608,0.412],[1,1],1,[1.62,1.93],[2,3]]]][2] os_md.execdraw(R,1);\begin{tikzpicture}\draw[red] (0,0) .. controls (0.608,0.412) .. (1,1) .. controls (1.62,1.93).. (2,3);\end{tikzpicture}[3] os_md.xyarrow([0,0],[1,1]|opt=["shade,left color=yellow,right color=black","rectangle"])$[4] os_md.readTikZ(@@);[[3,[[opt,[shade,left color=yellow,right color=black,rectangle]]],[0,0],[1,1]]][5] os_md.execdraw(@@);\begin{tikzpicture}\draw[shade,left color=yellow,right color=black](0,0)rectangle(1,1);\end{tikzpicture}[6] os_md.xyarrow([0,0],[".5cm"]|opt=["inner color=red","circle"],cmd="shade")$[7] os_md.readTikZ(@@);[3,[[cmd,shade],[opt,[inner color=red,circle]]],[0,0],[.5cm]]][8] os_md.execdraw(@@,1);\begin{tikzpicture}\shade[inner color=red](0,0)circle(.5cm);\end{tikzpicture}[10] os_md.xyput([0,0,["draw,rectangle","Sum"]]);\node[draw,rectangle] at(0,0){Sum};[11] os_md.readTikZ(@@);[[2,[],[0,0],[[draw,rectangle,Sum]]]][12] os_md.execdraw(@@,1);\begin{tikzpicture}\node[draw,rectangle] at(0,0){Sum};\end{tikzpicture}281

368. r2ma(s):: Mathematica の形式の数式に変換
evalma(s|inv=1) と同じ
369. evalma(s|inv=1):: Mathematica の数式を読み込む• Mathematica の函数 Sin, Cos, Tan, ArcSin, ArcCos, ArcTan, Exp, Log, Sinh, Cosh,
Tanh に対応している．
• s = 0 とすると，Mathematica 形式の文字列を（コピー・ペーストなどにより）直接入力できる．
複数行に渡ってもよい．また入力終了は文字 ; の後の改行で示す．
• inv=1 とすると，逆変換，すなわち数式から Mathematica 形式の文字列に変換する．
[0] P=os_md.evalma(0)$Mathematica text (terminated by ;) ?
{(x+y)^2,y};[1] P;[ x^2+2*y*x+y^2 y ][2] os_md.r2ma(P);{x^2+2*y*x+y^2,y}[3] os_md.evalma(0)$Mathematica text (terminated by ;) ?
{x+y)^2,y};exprparse : syntax error[4] os_md.evalma("{{1,2},{3,4}};");[ 1 2 ]
[ 3 4 ]
[5] os_md.my_tex_form(@@);\begin{pmatrix}
1&2 \\
3&4 \\\end{pmatrix}
370. readcsv(s|eval=[n1 , n2 , . . . ],eval=n,sp=1,col=c,null=t,eq=1):: CSV 形式のデータをリスト形式で読み込む• CSV 形式とは，複数のデータをコンマと改行で区切ったデータ形式であるが，それを 1 行のデー
タをリストにし，さらにそのリストを行順に並べたリストとして読み込む．

• 通常は文字列として読み込むが，各行で n1 , n2 , . . . で指定した項目は式として読み込む（n1 は n1
番目の項目 – 最初は 1 番目 – を表す）．
n 項目のみの指定のときは，eval=n としてもよい．
• eval="all"というオプションでは，可能な項目は全て（小）数として読み込む．
• sp=1 というオプションでは，空白やタブやそれらが連続したものをデータの区切りとみなす．
• col=c というオプションでは，各行の第 c 項目のみを読んだリストとする．
• null=t というオプションでは，データの無い項目を t とする（デフォルトは空文字列）．
• eq=1 というオプションは，数でなくて式として読み込み，t のデフォルトは 0.

282

• CSV 形式では，データにコンマを含む場合は両端を ” で囲って表す．さらにその中に ” があれば，それを二つ重ねて一つの ” を表す．
• ファイルが見つからない場合は，負の数字を返す．
• MS Windows のときは，ShiftJIS の文字列に対応している．
[0] os_md.showbyshell("type z:\\test.txt")$
12,abc,(x+y)^2
0,2/3,2/4
2,"a ""b",4/4[1] os_md.readcsv("z:\\test.txt");[[12,abc,(x+y)^2],[0,2/3,2/4],[2,a "b,4/4]][2] os_md.readcsv("z:\\test.txt"|eval=[3],eq=1);[[12,abc,x^2+2*y*x+y^2],[0,2/3,1/2],[2,a "b,1]][3] os_md.readcsv("z:\\test.txt"|col=3,eval=3,eq=1);[x^2+2*y*x+y^2,1/2,1]
371. tocsv(l|null=n,exe=f ):: リストのリストまたは行列を CSV 形式のデータに変換• null=t というオプションでは，t というデータを空の項目とみなす．
• exe=0, 1 : DIROUT で指定したディレクトリの risaout.csv というファイルに（存在すれば 0 では追加，1 では上書き）出力し，関連づけされた Excel を呼び出す．
• exe=2, . . . ,9 : DIROUT で指定したディレクトリの risaout2.csv, . . . ,risaout9.csv というファ
イルに上書き出力し，関連づけされた Excel を呼び出す．
• exe=f : f が拡張子.csv というファイル名のときは，そのファイル名のファイルとして出力し，関連づけされた Excel を呼び出す．
3.2.8 Permutations
372. ldict(n,m |opt=t):: {0, 1, 2, . . . , m − 1} を並べ替えて辞書式順序で n + 1 番目のリストを返す
存在しないときは 0 を返す．
ただし，数字を逆に並べて大きい順の辞書式順序とする．
• m = 0 のときは m = ∞ とみなし，後ろの並べ替えない部分を省いたリストを返す．
• m > 0 でオプション opt=t を指定した場合の意味は，次項の ndict() で iand(t,3) を指定した順序に対応している．
• iand(t,4) が 0 でないときは，{1, 2, 3, . . . , m} の並び替えとする．

[0] os_md.ldict(0,3);[0,1,2][1] os_md.ldict(1,3);[1,0,2][2] os_md.ldict(2,3);[0,2,1][3] os_md.ldict(3,3);[2,0,1][3] os_md.ldict(4,3);[1,2,0][4] os_md.ldict(5,3);[2,1,0]283

[5] os_md.ldict(6,3);
too small size0[6] os_md.ldict(6,4);[0,1,2,3][7] os_md.ldict(7,0);[1,0,3,2][8] os_md.calc(@@,["+",1]);[2,1,4,3][9] os_md.ldict(7,0|opt=4);[2,1,4,3][10] os_md.ldict(10000,0);[4,7,2,3,5,1,0,6][11] os_md.ldict(3,4|opt=0);[2,0,1,3][12] os_md.ldict(3,4|opt=1);[0,2,3,1][13] os_md.ldict(3,4|opt=2);[3,1,0,2][14] os_md.ldict(3,4|opt=3);[1,3,2,0][16] os_md.ldict(3,4|opt=7);[2,4,3,1]
373. ndict(ℓ |opt=t):: {ℓ0 , ℓ1 , . . . , ℓm−1 } の並べ替えのリスト ℓ が何番目かを返す（最初は 0 番）
ℓ の要素は，互いに異なって比較できるものであればよい．
リストでなくてベクトルでもよい．
オプション opt を指定した場合は• t = 0 : 末尾からみて大きい辞書式順序（デフォルト）• t = 1 : 先頭からみて小さい辞書式順序• t = 2 : 先頭からみて大きい辞書式順序• t = 3 : 末尾からみて小さい辞書式順序[0] os_md.ndict([4,7,2,3,5,1,0,6]);
10000[1] os_md.ndict( [0,2,1] | opt=0);2[2] os_md.ndict( [0,2,1] | opt=1);
1[3] os_md.ndict( [0,2,1] | opt=2);4[4] os_md.ndict( [0,2,1] | opt=3);3374. nextsub([a0 , . . . , am−1 ],n):: {0, . . . , n − 1} の m 個の部分集合を並べたとき，{a0 , . . . , am−1 } の次の部分集合を返す．最後を与284

えた時は 0 を返す．

• 0 ≤ a0 < · · · < am−1 ≤ n の必要がある．
• 先頭からの辞書式順序．
• 最初の引数が非負整数 m のとき，[0, 1, . . . , m − 1] を返す．
[0] S = os_md.nextsub(3,5);[0,1,2];[1] while(S != 0){S = os_md.nextsub(S,5); print(S);}$[0,1,3][0,1,4][0,2,3][0,2,4][0,3,4][1,2,3][1,2,4][1,3,4][2,3,4]375. nextpart(ℓ|max=m):: 自然数の分割のリスト ℓ に対し，辞書式順序で次に大きなものを返す• ℓ = [ℓ0 , ℓ1 , . . . ] は大きさの順に並んでいなければならない• ℓ に正整数を与えると，自然数 ℓ の分割の先頭を返す
このとき，max=m によって正整数 m 以下の自然数による分割の先頭を返す（辞書式順序でこれ以下のは，この要件を満たす分割となる）．
これの転置を考えると m 個以下への分割のリストが得られる．

[0] S=os_md.nextpart(5);[5][1] while((S = os_md.nextpart(S)) != 0) os_md.mycat([S,os_md.transpart(S)]);[4,1] [2,1,1,1][3,2] [2,2,1][3,1,1] [3,1,1][2,2,1] [3,2][2,1,1,1] [4,1][1,1,1,1,1] [5][2] os_md.nextpart(5|max=3);[3,2]376. nextshort(ℓ, ):: 自然数の分割のリスト ℓ に対し，より分割の個数が少なくて辞書式順序で次に大きなものを返す• ℓ = [ℓ0 , ℓ1 , . . . ] は大きさの順に並んでいなければならない• より分割の個数が少なくて辞書式順序がより小さなものないとき [] を返す[0] os_md.nextshort([10,10,5,3]);[10,9,9][1] os_md.nextshort([10,10,7,2]);[]377. transpart(ℓ)
285

:: 自然数の分割のリスト（Young 図式に対応）ℓ に対し，その双対を返す（例は nextpart() を参照）
n 次の置換群の元を {0, 1, 2, . . . , n − 1} の並べ替えと考えて，ベクトル s = [s0 . . . sn−1 ] で表す．互換（リストまたはベクトル [a b] で表す）
，積，逆元など無限次置換群の中で考えているとしてよい．
a a ··· a置換群の元を b10 b21 ··· n−1と表したときは，s =os md.sprod([b1 , b2 , . . .],os md.sinv([a0 , a1 , . . .])bnとなる．
以下，s, t はそのような置換群の元とする．

378. trpos(a,b,n):: 互換 (a, b) にあたる n 次置換群の元を返す[0] os_md.trpos(2,4,6);[ 0 1 4 3 2 5 ][1] os_md.trpos(0,0,6);[ 0 1 2 3 4 5 ]379. sprod(s,t):: 置換群の積を返す
s = [s0 . . . sn−1 ], t = [t0 . . . tn−1 ] のときは積は [st0 . . . stn−1 ] となる．
s と t のサイズが異なっていても S∞ の元と見なして計算される．
s や t が互換でもよい．
s や t が非負整数の時は，S∞ の s 番目，n 番目の元と見なされ，積は非負整数で返される．相互変換
は ldict()（オプション opt=4 を参照）と ndict().
[0] os_md.sprod([1,2,0,4,3],[1,2,0,3,4]);[ 2 0 1 3 4 ][1] os_md.sprod([1,2,0,4,3],[1,2,0]);[ 2 0 1 4 3 ][3] os_md.sprod(80,20);95[4] os_md.sinv(20);15[5] os_md.ldict(80,0|opt=4);[1,5,3,4,2][6] os_md.ldict(20,0|opt=4);[2,4,3,1][7] os_md.ldict(20,5|opt=4);[2,4,3,1,5][8] os_md.ldict(95,0|opt=4);[5,4,3,1,2][9] os_md.ldict(15,0|opt=4);[4,1,3,2][10] os_md.ndict([4,1,3,2]);
15[11] os_md.sprod([0,4,2,3,1],[1,3,2,0,4]);[ 4 3 2 0 1 ][12] os_md.calc(@@,["+",1]);[ 5 4 3 1 2 ][13] os_md.sprod([2,3],[1,2,0,4,3]);286

[ 1 3 0 4 2 ]([3]) は，(1 5 3 4 2 · · · )(2 4 3 1 · · · ) = (5 4 3 1 2 · · · ) を意味している．
380. sadj(s,t):: 置換群の共役変換を返す
sts−1 を返す．すなわち sprod(sprod(s,t),sinv(s))
381. sinv(s):: 置換 s の逆元を返す
s が非負整数の時は，S∞ の s 番目の元と見なされ，積は非負整数で返される．0, 1, 2 は [0,1,2,3, . . .],[1,0,2,3, . . .], [2,0,1,3, . . .] に対応する．
382. slen(s):: 置換 s の長さを返す
383. sexps(s):: 置換 s を隣接互換の積で表す

 


0 1 2
0 1 2
0 1 2
以下は，(1, 2, 0) = (0, 1)(1, 2) すなわち
=
を示す．
1 2 0
1 0 2
0 2 1
[0] os_md.sexps([1,2,0]);[0,1]384. sord(s,t):: 置換を Bruhat order で比較する
戻り値は0: equal

1: s > t−1: s < t

2: no order

3.2.9 TEX
以下の函数の他にも，fctrtos(), getbygrs() などが LATEX の出力に対応している．

385. my tex form(p|subst=[t0 , t1 ],frac=f ,root=r,ket=k):: print tex form(p) の戻り値から文字列置換や不要部分削除を行い，読みやすいソースに変換• 置き換えは str subst(s,t0 ,t1 ) でなされる．
• frac=0 : 係数が分数のとき，2/3 のように出力する• frac=1 : 係数が分数のとき，\frac{2}{3} のように出力する．ただし，AMSTeX=0 のときは{2\over 3} のように出力．
• frac=2 : 係数が分数のとき，\tfrac{2}{3} のように出力する（デフォルト）．ただし，AMSTeX=0のときは {2\over 3} のように出力．
1√√
このとき 2^(1/2) は 2 2 でなく， 2 となるよう\sqrt{2}が出力される（デフォルトでは · · · の· · · が 32 字以内の場合）．
1√
ただし，root=r の指定で r = 0 のときは (· · · ) 2 の形に，r = 2 のときは · · · の形になるよう出
力される．
1

√
3

同様に，2^(1/3) は 2 3 でなく， 2 と出力される．
• ket=1 : 一番内側の ( ) を除いて \left( \right\) とするする．
• ket=2 : 一番内側の ( ) も含めて \left( \right\) に変換する．

[0] AMSTeX=1$[1] print_tex_form(x_1+x_2^2/y);\frac{{x}_{1} {y}+ {x}_{2}^{ 2} }{ {y}}[2] os_md.my_tex_form(x_1+x_2^2/y);\frac{x_1y+x_2^2}y[3] print_tex_form((1+x)^(1/2));( ( {x}+ 1))^{ 1/2}
287

[4] os_md.my_tex_form((1+x)^(1/2));\sqrt{x+1}[5] print_tex_form(x/2*(1+x)^(1/2));
1/2 ( ( {x}+ 1))^{ 1/2}
{x}[6] os_md.my_tex_form(x/2*(1+x)^(1/2)|frac=0);
1/2(x+1)^{1/2}x[7] os_md.my_tex_form(x/2*(1+x)^(1/2)|frac=1);\frac{1}2(x+1)^{\frac{1}2}x[8] os_md.my_tex_form(x/2*(1+x)^(1/2)|frac=2);\tfrac{1}2\sqrt{x+1}x[9] print_tex_form(atan(x));{atan}( {x})[10] os_md.my_tex_form(atan(x));{\arctan}(x)[11] os_md.my_tex_form(2^(1/3));\sqrt[3]{2}[12] print_tex_form(2*2^x);
2 ( ( 2))^{ {x}}[13] os_md.my_tex_form(2*2^x);2\cdot{2}^x386. show(p|opt=ℓ,raw=1):: p を dviout で適切に表示する
微分作用素，重複度つき固有値形式のリスト，GRS 形式などを自動判定して dviout で適切に表示す
る．期待する表示と異なる場合は，オプションを付けるか，別の細かな指定が出来る函数を使う．
• opt="verb"が指定されると，Risa/Asir での表示と同じ形で dviout で表示される．
• raw=1 が指定されると，TEX のソースが返される．
以下はそれ以外の場合• p が有理式や多項式のとき– fctrtos(p) を使って因数分解して表示する．
– opt の指定がなかったときは，p が微分作用素かどうかは isdif(p) で判定し，微分作用素と判断された場合は var="dif" のオプションで表示する．
– opt="pfrac"と指定すると，p の主変数について部分分数展開して表示する．
– それ以外の場合は，fctrtos() に全てのオプションパラメータを引き渡して表示する．
– 1 行の横幅を超えてしまう数式は，行分割されて表示される（単項式や数は除く）．
• p が行列の時は，mtotex(p|lim=1,small=2) を使って表示する．
– サイズの大きな行列も考慮されている．
– opt の指定は，mtotex() に var の指定として渡されて表示する．
• p がリストの時は，各成分がすべて多項式で全体として長くなるときは，eqs2tex() を使って表示する（このときは，オプション var=V によって展開の変数などの指定が可能．V は変数または
eqs2tex() の第 2 引数としてもよい）．それ以外では，opt が文字列かリストで指定されていれば，全てのオプションパラメータを ltotex(p) に渡して結果を表示する．それ以外では– GRS 形式，重複度つきの固有値の形式あるいは文字列のリストなら，それに合わせた形で出力する．なお，重複度つきの固有値の形式とは，最初が非負整数，次が式や数の 2 つの要素からなるリストを集めたリスト，GRS 形式とは，その要素が重複度つきの固有値の形式となっているリスト．
– リスト p の各要素がリストとし，各要素も文字列かあるいは，式（ここでは有理式，ベク

288

トル，行列のいすれかとする）からなるリストとする．文字列も式も現れているとすると，ltotex(p|opt=["cr","spts"]) で変換して表示する．ただしいずれかの文字列に \ が含まれていれば，opt=["cr","spts0"] とし，さらに str=1 のオプションをつける．
• p が文字列のとき– opt="raw" が指定されているとそのまま TEX の文字列とみなして表示– opt="eq" が指定されていると数式を表すとみなして\begin{equation} \end{equation}
で鋏んで display style で表示する．
– これら以外では，文字列の最初の 128 文字の中に\draw または\ar@が含まれているが\begin{が含まれていない場合は，xyproc() を使って表示する（TiKZ の設定とあっているとき）．
– 残りの場合は，文字列に\begin{equation， \begin{align， \[ のいずれかが含まれているか，あるいは，文字列に & ^ _ のいずれの文字も含まれていなければそのまま，そうでなけ
れば display style で表示する．
• 上記以外では dviout(p) によって表示される．

[0] os_md.show(2*2^x|raw=1);
2\cdot{2}^x[1] os_md.show(1.2*2^x|raw=1);
1.2\cdot{2}^x[2] os_md.show((x+@i)^2|raw=1);
x^2+(2\sqrt{-1})x-1[3] os_md.show(2*(x+1)^2/y|raw=1);\frac{2(x+1)^2}{y}387. dviout(p|clear=1,keep=1,delete=t,fctr=1,mult=1,subst=[s0, s1],eq=k,title=s):: p を dviout で表示する• dviout(@@) とすれば，直前の結果が dviout で表示される．
• dviout.exe にはパスを通しておく（あるいは，risatex.bat を書き換える．書き換えによって
dviout 以外や Windows 以外の UNIX などの OS にも対応可）．
• この函数によって LATEX のソースが DIROUT/out.tex に出力され，それが DIROUT/risaout.tex
から読み込まれる．

• p が文字列の場合，通常は LATEX のソースとみなして表示するがeq=0 のときは，デフォルト数式環境
eq=1 のときは \[と\]eq=2 のときは \begin{align} と \end{align}
eq=3 のときは \begin{gather} と \end{gather}eq=4 のときは \begin{multline} と \end{multline}
eq=5 のときは \begin{align}\begin{split} & と \end{split}\end{align}
eq=6 のときは \begin{align*} & と \end{align*}
eq=7 のときは \begin{gather*} と \end{gather*}eq=8 のときは \begin{equation} と \end{equation}
eq=s と文字列 s で与えられたときは，\begin{s} と\end{s}で挟んで数式とみなして LATEX を使って表示する．
• s0 , s1 で部分文字列の（複数）置き換えをする（cf. str subst()）．
• p=" " （１文字の空白）は，再表示．
• clear=1 によって，追加でなくて新規の表示となる．
• keep=1 のときは，LATEX のソースのみの変更で，表示はしない（後から表示）．
• delete=t によって，最後の t 個の式番号の付いた式を削除する（0 ≤ t ≤ 10）．
• mult=1 のときは，p がリストなら，各項を別に表示する．

289

• fcrt=1 のときは，p が多項式または有理式なら因数分解して表示する．
• tilte=s で，s が文字列ならそれのあとに p が表示される．
dviout で source specials が有効になっていれば，dviout の画面で表示された文字の部分のダ
ブルクリックによりエディタが起動され，LATEX のソースの該当箇所が編集可能になる．
この編集処理後の表示（たとえば dviout(" ")）でこの修正が有効になる．
• risatex.bat や risaout.tex が存在しない場合，それらが（ディレクトリが書き込み可能ならば）自動的に作成される．これらは必要に応じて書き換えてよい．

risatex.bat を起動可能なように（デフォルトでは get_rootdir()/bin に置かれる）設定し，また risaout.tex を DIROUT で指定されるディレクトリに入れておく必要がある（cf. DVIOUTA）．
388. dviout0(ℓ) or dviout0([ℓ1 , ℓ2 , . . . ]) or dviout0(ℓ|opt=s):: TEX での表示のための内容削除などの基本操作• ℓ = 0：dviout(" "|keep=1,clear=1) と同じで内容の消去• ℓ = 1：dviout(" ") と同じで再表示• ℓ = 2：dviout(" "|clear=1) と同じで，内容を消去して再表示• ℓ = 3：DIROUT, DVIOUTH, DVIOUTA, DVIOUTB, DVIOUTL, Canvas, TeXLim, TeXEq, AMSTeX, TikZ,
XYPrec, XYcm の値が示される．
• ℓ = 4：DVIOUTA と DVIOUTB の値を交換し，DVIOUTA の値を示す．
実行例は DVIOUTL の項を参照．
• ℓ = 5：DVIOUTA と DVIOUTB を初期状態と逆にする．
• ℓ = 6：TikZ を 1 にする（グラフ表示に TikZ を使う）．
• ℓ = 7：TikZ を 0 にする（グラフ表示に XY-pic を使う）．
• ℓ > 10：AMSTEX における行列サイズを ℓ まで許す．
• ℓ が負の整数：dviout(" "|keep=1,delete= − ℓ) と同じで，最後の ℓ 個の式の消去• ℓ が文字列：先頭に \ を付加した文字列を TEX のソースに付加して改行する．
たとえば dviout0("newpage") は改ページを意味する．
ただし，以下の文字列の時は別の意味を持つ．
– "" : 空白一つと改行を付加する．
– "cls" : ソースを空にする．
– "show" : 表示する．
– "?" : 設定の表示．
• 複数の操作を与えるときは，リストにする．
• opt=s を指定したときは s に ℓ の値が設定される（s は文字列）．
ただし，ℓ = −1 のときは現在の設定値が返される．
s には TikZ, TeXEq, TeXLim, XYPrec, XYcm，XYLim，DVIOUT, Canvas, TeXPages が可能.
なお，DVIOUT のときは，DVIOUTA, DVIOUTB の設定が ℓ = 0 で初期状態，ℓ = 1 で逆の設定となる．

389. verb tex form(p):: p を LATEX で表現可能な文字列にする
verb_tex_form(p) は rtostr(p) と同等であるが，\begin{align}... \end{align} などの数式環境中でも使用できる．

390. monotos(p):: 有理式を文字列に変換．単項式以外では ( と ) で囲む
391. monototex(p|minus=1):: 有理式を TEX の文字列に変換．単項式以外では ( と ) で囲む• minus=1 を指定すると，− で始まる場合も ( と ) で囲む
392. rtotex(p):: 数式を TEX の文字列に変換．1 文字を越えるときは { と } で囲む[0] os_md.monotos(a2);a2290[1] os_md.monototex(a2);a_2[2] os_md.rtotex(a2);{a_2}[3] os_md.monotos(a+1);(a+1)[4] os_md.monototex(a+1);(a+1)[5] os_md.rtotex(a+1);{a+1}[6] P=(a^(12)+b)/(2*c+d)+alpha2;(a^12+b+2*alpha_2*c+alpha2*d)/(2*c+d)[7] os_md.monotos(P);((a^12+b+2*alpha_2*c+alpha2*d)/(2*c+d))[8] os_md.monototex(P);(\frac{a^{12}+b+2{\alpha}_2c+{\alpha}_2d}{2c+d})[9] os_md.rtotex(P);{\frac{a^{12}+b+2{\alpha}_2c+{\alpha}_2d}{2c+d}}393. texsp(s):: TEX の文字列 s の最後が TEX のキーワードのとき，s の末尾に空白をつける．
[0] os_md.my_tex_form(alpha*x);\alpha{x}[1] os_md.my_tex_form(alpha)+"x";\alphax[2] os_md.texsp(os_md.my_tex_form(alpha))+"x";\alpha x[3] os_md.texsp(os_md.my_tex_form(alpha*x))+"y";\alpha{x}y394. texbegin(t,s|opt=u):: TEX の \begin{t}[u] s \end{t} というソースを出力する
395. texcr(k):: 127 以下の非負整数 k に応じて TEX における数式の改行の文字列を返す
k = 127 のときは，改行のコードは,\allowdisplaybreaks\\\pause\n& =となる（なお，TEX のソースでは，上の \\ は \ に，\n は改行になる）．
iand(cr,k)=0 のときは上の文字列から k に応じて順に以下の文字列が削られる．
• 32 : ,• 8 : \allowdisplaybreaks• 2 : \\
• 16 : \pause• 1 : \n• 4: &• 64 : =• k = 0 のときは空白 1 文字となる．

291

• k が 0 から 127 までの整数でない場合は，k がそのまま返される．
[0] os_md.texcr(31);\allowdisplaybreaks\\\pause&[1] os_md.texcr(7);\\&[2] os_md.texcr(15);\allowdisplaybreaks\\&396. texket(s|all=t):: TEX のソース s における括弧のサイズを可変にする• 一番内部の ( ) 以外を \left( \right) に変更する．
一番内部は，その中身が空白や英数字や { } や _ 以外の文字が含まれる場合は同様に変更する．
既に \left( \right) となっている箇所は変更しない．
• all=1 : 全ての括弧を \left( \right) と変更する．
• all=-1 : 一番内部の ( ) は変更しない．
[0] S=os_md.my_tex_form((sin(x+x0)/(cos(x-x0)))^(1/2));( \frac{ \sin(x+x_0)}{ \cos(x-x_0)})^{\tfrac{1}2}[1] os_md.texket(S);\left( \frac{ \sin(x+x_0)}{ \cos(x-x_0)}\right)^{\tfrac{1}2}[2] os_md.texket(S|all=1);\left( \frac{ \sin\left(x+x_0\right)}{ \cos\left(x-x_0\right)}\right)^{\tfrac{1}2}397. eqs2tex(p,[var,dic,pages,cont]|dviout=1):: 長い数式 p を TEX の複数行の display style に変換（複数の）数式を TEX の display style に変換.
• p が数式のリスト [p1 ,p2 , . . .] のときは，それらを display style で並べる．
• var は，変数または変数のリストで，そのベキで展開される．
• dic は，0, 1, 2 が指定可能（cf. fctrtos() のオプションで変数の辞書式順序）• pages は，0, 1, 2 が指定可能（cf. fctrtos() のオプション）• cont は，0, 1 が指定可能（1 は display style につなげることを意味する）• 2 番目の引数のリストは適当なところまで指定すると，残りはデフォルト（var は [] に，残りのパラメータは 0）に設定される．
• −p の方が指定した最初の変数の最高階の係数が短くなるなら，−p を用いる．これを避けるには，変数のリストの最初に 0 を挿入する．
• dviout=1 を指定すると TEX を用いて画面表示される．
398. ltotex(l|opt=s,pre="string",cr="cr",small=1,lim=ℓ,var=v):: リストまたはベクトルを s = "spt" のとき重複度つきのリストとみて\left\{... または s = "GRS"のとき \begin{Bmatrix} · · · の形の Riemann scheme とみて TEX の文字列に変換など• 画面表示する場合は，show() を参照のこと（以下のオプションパラメータはそのまま有効）．
• s = "spt" の場合は meigen( |mult=1) のようなリスト形式をスペクトル型にする.
• s = "GRS" の場合は sp2grs() の結果のようなリスト形式を Riemann scheme 形式にする．この場合は，pre が有効.
• s = "coord" の場合はリストを座標とみなしてその形式( , , . . .) にする．
√
– cpx=1 : 複素数 a + b −1 のとき，a + bi と表示する（デフォルト）．

292

√
√
– cpx=2 : 複素数 a + b −1 のとき，a + b −1 と表示する．
• s = ["Pfaff",u,x,x-y, . . . ] の場合は行列のリストをdxd(x − y)du = A0+ A1+ ··· uxx−yのような Pfaﬀ 形式にする．
• s = ["Fuchs",u,x,x,x-y,x-1, . . . ] の場合は行列のリストを


A0
A1
A2
du
=
+
+
+ ··· udxxx−y x−1のような Fuchs 形式にする．
• s = "dform" のときは，dform() で扱ったような微分形式を表すリストとみなす．
ℓ =[[(a*x-b*y)/(x),x,z],[(-a*x+b*y)/(y),y,z]] ならば(−ax + byax − by) dx ∧ dz + () dy ∧ dzxyとなる．係数は，有理式や有理式の行列などでよい．

• s = "vect" のときは，縦ベクトルとしての表示形態にする．
• s = "cr" のときは，リストの 1 項目毎に改行する．
次項と同様，cr= や var= のオプション指定が可能• s = "spts" のときはリストの各項目を空白を鋏んで，s = "spts0" のときは空白を鋏まずに，1
行あたり出来るだけ多く入れる．
– lim=ℓ でデフォルトの 1 行の文字幅を ℓ に変更可能で，ℓ = 0 のときは文字幅制限なし．
– str=1 で，文字列はそのまま TEX の文字列と解釈して挿入する．
– cr= の指定で改行のコードを指定可能．デフォルトは cr="\\\\\n & "．
0 以上 32 未満の数字 k を指定することもできて，改行のコードは texcr(k) となる．すなわ
ちデフォルトは k = 7 = 2 + 1 + 4 で，k = 0 のときは空白の 1 文字となる．たとえば k = 15のときは \\allowdisplaybreaks\\\\\n&– var= による変数の指定が行列（cf. mtotex()）や多項式，有理式（cf. ltotex()）に適用される．
• s =["cr","spts"] または s =["cr","spts0"] のときは，リストの 1 項目毎に改行するが（cr=や var= のオプション指定が可能），リストの項目がリストのときはその項目を s ="spts" またはs ="spts0" の形式にし，それにはさらに str=1 のオプションが有効．
ℓ のリスト（改行文字列は s1 ）の項目がリストの場合，そこでの改行文字列 s2 を指定するときは，
cr=[s1 ,s2 ] とする．s1 , s2 は数字での指定でもよい．
• s = "text" のときは，s = "spts" のときと同じだがテキストスタイルとする．このときも str=1
や cr= のオプションが可能．
• s = "tab" で ℓ がリストのリストのときは，\begin{tabular}...\end{tabular}の形式でテキストスタイルで出力する．
成分が沢山あるリスト ℓ に対して, ℓ を [ℓ] としてオプション widh=w を指定し，この機能を使うとよい（cf. spbasic()）.
– title=s で文字列 s を指定すると，タイトルがつけられる．
– left=[s1 ,s2 ,. . .] を指定すると，それが 1 列目として付加される．
途中の sj が [sj,1 ,sj,2 ,. . .] となっていると，それが最終の行まで繰り返される（以下も同様）．
– right=[s1 ,s2 ,. . .] を指定すると，それが最終列として付加される．
– top=[s1 ,s2 ,. . .] を指定すると，それが先頭行として付加される（上の right=などがあればそれの処理の後）．
– last=[s1 ,s2 ,. . .] を指定すると，それが最終行として付加される．
– null=n を指定すると，n に等しい要素は表では空白とする（デフォルトは n = ""）．

293

– hline=[h1 , h2 , . . .] を指定すると，hi 行の後に横線を引く．
（タイトルを除いた）表の始まりが 0，最初が 1 行目と数え，重複しての指定は多重線を表す.
∗ z は最終行（の後）を示す．z-1 のような指定も可能．
∗ vj が，[kj ,nj ] という正整数 nj と非負整数 kj の組のリストときは，nj で割った余りがkj となる行全ての指定を意味する．
– vline=[v1 , v2 , . . .] を指定すると，vj 列の後に縦線を引く．表の両端の縦線以外を指定する．
最初が 1 列目で，重複しての指定は多重線を表す.
∗ z は最終列（の後）を示す．z-1 のような指定も可能．
∗ vj が，[kj ,nj ] という正整数 nj と非負整数 kj の組のリストのときは，nj で割った余りが kj となる列全ての指定を意味する．
– align=s : \begin{tabular} に続いて配置や縦線を指定する { } の中の文字列を指定する．
このオプションがあるときは，vline= の指定は無視される．
ただし s が 1 文字の時は，各項の配置を指定する文字で vline= の指定は有効．"r" はデフォ
ルトの右寄せ．"c" は中央配置，"l" は左寄せである．
– vert=1 : 縦横を転置して表にする．
– width=w : w が正のときは，横を w 項にして縦に積み重ねた表にする．
w が負の時は，横の項数を |w| 倍して行数の少ない表にする．
∗ vert=1 が指定してあれば，縦横を転置してから横の項数調整を行う．
オプションの使用例は powprimroot() の項にある．
リ ス ト の 調 整 は lv2m( |null="") で 行 列 に 直 し ，madjust()，mtranspose()，mperm(),
newbmat() などを使って変更後，m2ll() でリストに戻すのが便利．
• s = "graph" で ℓ が数字のリストのときは，XY-pic または TikZ を使って棒グラフを出力する．棒
グラフの下に文字列や数字を入れるときは，それをリストにして数字のリストの後ろにつける．
そのリストの個数がデータの個数より１つ少ないときは，棒グラフの間に文字列や数字を入れる．
– size=ℓ : このときオプションでサイズ指定ができる．ℓ は数のリストで，全体の横幅，最も長いグラフの高さ，棒幅の（隣との幅との）比率（折れ線グラフの時は無視される），文字列との空きの高さ，グラフと文字列との空きの高さ（指定しないときは前者と同じ値），を順に指定できる．最初の 2 つ以外は省略可能．
ℓ の 2 番目の成分が負の数 −c の時は，棒グラフの高さをデータの数値の c 倍とする．
TikZ=0，1 に応じてデフォルトは ℓ = [80, 30, 1/2, 2]，[8, 3, 1/2, 0.2]．（ただし，horiz=1 を指定したときは，4 番目値の 2 または 0.2 のデフォルトは，3 または 0.3 になる）．
– max=m : 上限値を m とする（デフォルトは自動判定，上限値がグラフの高さになる）．
– shift=n : 底の基準線の値を n にずらす（デフォルトは 0）．
– horiz=1 : 棒グラフを縦でなくて横に描く．
– line=1 : 折れ線グラフで描く．
line=2 : 上と同じだが，ポイントを • で明示する．
– line=[n,t]：n は 2 または 1 で折れ線グラフでのポイント有無．
t は XY-pic/TikZ で使われる線種などの指定文字列. たとえば s="@{.}"/dotted は点線（cf. xyarrow()）．
– line=[-1,r] : r mm を半径とする円グラフで表示する．
– value=0 : 値を表示しない．
value=1 : 棒グラフが底の基準線の位置につぶれても値を表示する．
– strip=1 : \begin{xy} · · · \end{xy}や\begin{tikzpicture} · · · \end{tikzpicture} な
どの始まりと終わりの部分を出力しない．
strip=2 : さらに下の基準線や目盛を描かない．
strip=3 : 値のみを表示する（value=0 で抜ける部分のみの表示）– color=s : というオプション指定をすると，TikZ を用いたグラフの場合には色付けや塗りつぶしができる（xybox() のときの指定と同じ）．円グラフでは，指定文字列のデータの個数だ
け並べたリストとする．

294

– mult=1 : 複数の棒グラフまたは複数の折れ線グラフを重ねて書くことができる．この場合，ℓは，[[ℓ1 ,ℓ2 , . . .],m] の形で，color または line も各グラフごとにリストにして指定する必要がある（無指定は不可）．
relative=1 : さらにこれを指定すると，ℓ1 , ℓ2 の値は，順に成分の値を加えたデータとしたグラフを描く．これを指定しない場合は，棒グラフの時は ℓj と ℓj+1 の各成分は，後者の方が大きいとしている．
• 返された文字列 R は，s ="text", "tab", "graph" の場合は dviout(R) で, それ以外では
dviout(R|eq=5) で表示できる．
• small=1 のときは行列を小サイズにする．

[0] os_md.ltotex([a+b, c/d,[2,3]]);\left\{
a+b,\, \frac{c}d,\, [2,3]\right\}[1] os_md.dviout(@@|eq=5)$c[a + b, , [2, 3]]d[2] L=[[12,a+b],[3,c],[1,d]];[[12,a+b],[3,c],[1,d]][3] os_md.ltotex(L|opt="spt");\left\{[a+b]_{12},\, [c]_3,\, d\right\}[4] os_md.dviout(@@|eq=5)${[a + b]12 , [c]3 , d}
[5] LL=[L,[[3,3*b],[2,f]]];[[[12,a+b],[3,c],[1,d]],[[3,3*b],[2,f]]][6] os_md.ltotex(LL|opt="GRS",pre=" 0 & 1\\\\\n");\begin{Bmatrix}
0 & 1\\[a+b]_{12} & [3b]_3\\[c]_3 & [f]_2\\d &\end{Bmatrix}[7] os_md.dviout(@@|eq=5)$


0
1 



[a + b]12 [3b]3[f ]2  [c]3d[8] A=newmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[9] B=newmat(2,2,[[p,q],[r,s]]);295

[ p q ][ r s ]
[10] os_md.ltotex([A,B]|opt=["Pfaff",u,x-1,y]);du= \Biggl(\begin{pmatrix}
a&b \\
c&d\end{pmatrix}\frac{d(x-1)}{x-1}\\&+ \begin{pmatrix}
p&q \\
r&s\end{pmatrix}\frac{dy}{y}\Biggr)u[11] os_md.dviout(@@|eq=5,subst=["\\\\&","%"])$

 !


p q dya b d(x − 1)
+
u
du =
r s y
c d
x−1
[12] os_md.ltotex([A,B]|opt=["Fuchs",u,x,x,x-1]);\frac{du}{dx}= \Biggl(\frac{\begin{pmatrix}
a&b \\
c&d\end{pmatrix}}{x}+ \frac{\begin{pmatrix}
p&q \\
r&s\end{pmatrix}}{x-1}\Biggr)u[13] os_md.dviout(os_md.smallmattex(@@)|eq=5);!
a b( pr qs )
du
c d
=
+
u
dx
x
x−1
[14] P=[[2*a,x,y],[(a+b)^2,y,z],[-2,x,z/y]]$[15] os_md.ltotex(P|opt="dform");2a\,dx\wedge dy+(a^2+2ba+b^2 )\,dy\wedge dz-2\,dx\wedge d(\frac{z}y)[16] os_md.dviout(@@|eq=5,subst=["\\frac","\\tfrac"]);2a dx ∧ dy + (a2 + 2ba + b2 ) dy ∧ dz − 2 dx ∧ d( yz )[17] os_md.ltotex(["There are",(n+1)^2,"points."]);[\texttt{There are},n^2+2n+1,\texttt{points.}][18] os_md.dviout(@@|eq=5)$[There are, n2 + 2n + 1, points.][19] os_md.ltotex(["There are",(n+1)^2,"points."]|opt="text");
296

$\texttt{There are}$$n^2+2n+1$$\texttt{points.}$[20] os_md.dviout(@@)$
There are n2 + 2n + 1 points.
[21] os_md.ltotex(["There are",(n+1)^2,"points."]|opt="text",str=1);
There are $n^2+2n+1$
points.
[22] os_md.dviout(@@)$
There are n2 + 2n + 1 points.
[23] L=[10,12,34,53,23,12,24,68,55,57,32,20]$[24] M=[1,2,3,4,5,6,7,8,9,10,11,12]$[25] os_md.dviout(os_md.ltotex([M,L]|opt="tab",title="Year 2014"));上で得られた TEX のソースを表示または印刷すると（以下の例でも同様）．

1
10

2
12

3
34

4
53

5
23

Year 20146
7
8
12 24 68

9
55

10
57

11
32

12
20

[26] os_md.dviout(os_md.ltotex([L,M]|opt="graph"));
68
55 57

53
34

32
24

23
10 12

20

12

1 2 3 4 5 6 7 8 9 10 11 12[27] L=[10,12,-10,34,53,23,-12,24,48,52,38,32,20]$[28] os_md.ltotex(L|opt="graph");
53

48

52
38

34

32
24

23

20

10 12

−10

−12

[29] L=[12,15,10,8,12,14,19,15,17,13,10,15]$[30] M=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]$[31] os_md.ltotex([L,LL]|opt="graph",line=[2,"@{.}"],shift=5,size=[100,40]);

297

19
•
17
•
15
•

15
•

14
•

12
•

15
•
13
•

12
•
10
•

10
•
8
•

Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec[32] L=cons("number",L)$[33] M=cons("Month",M)$[34] os_md.ltotex([M,L]|opt="tab",hline=[0,1,2],vline=[0,1,1,13],
title="Year 2014");Monthnumber

Jan
12

Feb
15

Mar
10

Apr
8

Year 2014
May Jun
12
14

Jul
19

Aug
15

Sep
17

Oct
13

Nov
10

Dec
15

[35] L=[35,42,19,38]$[36] LL=["春","夏","秋","冬"]$[37] os_md.ltotex([L,LL]|opt="graph",line=[-1,15]);

冬

秋

春

夏

[38] L=[5,12,25,13,22,17,3,2]$[39] M=[0.5,1,1.5,2,2.5,3,3.5]$[40] os_md.dviout0(1|opt="TikZ")$[41] os_md.ltotex([L,M]|opt="graph",color="fill=blue!50",size=[4.5,-0.1,1]);/* 幅 4.5cm, 高さ 0.1 倍，幅比率 1 */\begin{tikzpicture}\draw(0,0)--(4.5,0);\draw[fill=blue!50](0,0)rectangle(0.563,0.5);\node at(0.281,0.7){$5$};\node at(0.563,-0.2){$ 0.5$};\draw[fill=blue!50](0.563,0)rectangle(1.125,1.2);...
[42] L2=[10,18,35,20,27,22,8,6]$[43] os_md.ltotex([[L,L2],M]|opt="graph",color=["fill=blue!40","fill=blue!20"],
size=[4.5,-0.1,1],mult=1);[44] L3=lsub([L2,L]);[5,6,10,7,5,5,5,4]

298

[45] os_md.ltotex([[L,L3],M]|opt="graph",color=["fill=blue!40","fill=blue!20"],
size=[4.5,-0.1,1],mult=1,relative=1);[46] N=cons(0,M);[0,0.5,1,1.5,2,2.5,3,3.5];[47] os_md.ltotex([L,N]|opt="graph",color="fill=blue!40",
size=[4.5,-0.1,1],horiz=1);[48] os_md.ltotex([[L,L3],N]|opt="graph",color=["fill=blue!40","fill=blue!20"],size=[4.5,-0.1,1,0.5,0.25],mult=1,horiz=1,relative=1);[49] os_md.ltotex([L,N]|opt="graph",line=[2,"red"],size=[4.5,-0.1,1]);[50] L3=[8,17,21,24,15,12,9,6]$[51] os_md.ltotex([[L,L3],N]|opt="graph",line=[[1,"red"],[1,"blue"]],mult=1,
size=[4.5,-0.1,1],value=0);[52] L=[35,42,19,38]$LL=["春","夏","秋","冬"]$[53] os_md.ltotex([L,LL]|opt="graph",line=[-1,15],color=["fill=yellow!30","fill=green!30","fill=red!30","fill=blue!30"]);
35
10
25

22
17
13

12
5

3

10
5

2

0.5 1 1.5 2 2.5 3 3.5

27
25
22 22
20
18
17
13
12

3.5 2 4

3

3

3

2
1.5

13

1
0.5
0

12
5

2

22 5
13

1
0.5
0

12
5
5
4
5
3 2
0.5 1 1.5 2 2.5 3 3.5

17 5

1.5
25

5
22 5
7
17
13

3 5

2.5
22

6
2

0.5 1 1.5 2 2.5 3 3.5

2
17

6
8
3

3.5
2.5

25

7
25

10

12 6
5 5

0 0.5 1 1.5 2 2.5 3 3.5

冬

秋

春

夏

399. mtotex(m|small=1,2, null=1,2, sp=1,2, idx=0,1, mat=s,var=ℓ, pfrac=v,raw=1,lim=n):: 行列またはベクトルを TEX の文字列に変換するが，成分が有理式のときは因数分解した形にする• m がベクトルのときは，1 行の行列とみなす．
299

• null=1 では，0 の成分は空白にする. null=2 では対角成分は残す．
• var=ℓ 多項式や有理式の成分を fctrtos() で変換するときのオプション．
ただし，var=0 とすると，成分にこのような変換を用いない.
pfrac=v 成分を変数 v について部分分数展開する．
• small=1 とすると，小さな行列にする．行列の文字数換算の幅は小さくなる．
• small=2 とすると，lim を設定したとき，横幅が大きすぎる行列を小さな行列にする．
• raw=1 を指定しないと，成分が文字列のとき \text{ } の形で，指定した場合は LATEX の文字列としてそのまま用いる．

• sp=1 成分が 2 個の元からなるリスト [s,t] のとき [t]s と，sp=2 のとき [t](s) となるようにする．
• idx=1 とすると，先頭に行を追加して，列の番号を (1), (2), . . . のようにつける．idx=0 のときは(0) から始める．
• idx=ℓ でリストやベクトルを指定したときは，先頭に行を追加してそれを各列に順に並べる．個数が不足したら，それ以降は最後のものを並べる．

• lim=n とすると，行列がその文字数幅に入らないと推測されるときは，行列を分割して表示する．
ただし，0 < n < 30 のときはデフォルトの横幅サイズとする．lim=0 は横幅制限なし．
• mat=s において，s="p", "b", "B", "v", "V" のとき行列は ( ), [ ], { }, | |, k k の形になる．s ="" のときは，括弧は描かれない．
• len=1 を指定すると，LATEX の文字列と推測された横幅の文字数を 2 項目に加えたリストを返す．
[0] A=newmat(2,2,[[y/(x+a),z],[0,1]]);[ (y)/(x+a) z ][ 0 1 ]
[1] os_md.mtotex(A^2);\begin{pmatrix}\frac{y^2}{(x+a)^2} & \frac{z(x+y+a)}{x+a}\\0 & 1\end{pmatrix}[2] os_md.mtotex(A^2|small=1);\left(\begin{smallmatrix}\frac{y^2}{(x+a)^2} & \frac{z(x+y+a)}{x+a}\\0 & 1\end{smallmatrix}\right)[3] B=os_md.mgen(3,"highdiag",a,1);[ 0 a1 0 ][ 0 0 a2 ][ 0 0 0 ][4] os_md.mtotex(B);\begin{pmatrix}
0 & a_1 & 0\\
0 & 0 & a_2\\
0 & 0 & 0\end{pmatrix}[5] os_md.mtotex(B|null=1);\begin{pmatrix}& a_1 & \\300

& & a_2\\& &\end{pmatrix}[6] os_md.mtotex(B|null=2);\begin{pmatrix}
0 & a_1 & \\& 0 & a_2\\& & 0\end{pmatrix}[7] os_md.mtotex(A^3|len=1)$[8] @@[1];34[8] os_md.mtotex(A^3|len=1,small=1)$[9] @@[1];27400. divmattex(s,l):: 行列の TEX のソース s の分割や列の並べ替えを行う
l によって以下のように変換される.
• [[k0 ,k1 , . . .]] : ν 列目をもとの行列の kν 列目とする（ν = 0, 1, . . .）.
• [[k01 ,k11 , . . .],[k02 ,k02 , . . .], . . .] : 横長の行列を分割して複数に分ける．
[k01 ,k11 , . . .] は最初の分割された行列．
• [m1 , . . .] : [[0,1,...m1 − 1],[m1 , . . .],. . .] : を表す．
特に [m] : とすると，行列を最初の m 列とそれ以降との 2 つに分割する．このときは，数字の mのみを指定してもよい．

• 0 : 成分が文字列の Risa/Asir の行列の形で返す．ただし，その成分がない場合は 0 となる．
[0] S=os_md.my_tex_form(os_md.mgen(3,9,a,0));\begin{pmatrix}
a_{00} & a_{01} & a_{02} & a_{03} & a_{04} & a_{05} & a_{06} & a_{07} & a_{08}\\a_{10} & a_{11} & a_{12} & a_{13} & a_{14} & a_{15} & a_{16} & a_{17} & a_{18}\\
a_{20} & a_{21} & a_{22} & a_{23} & a_{24} & a_{25} & a_{26} & a_{27} & a_{28}\end{pmatrix}[1] os_md.divmattex(S,[[2,4,1]]);\begin{pmatrix}
a_{02} & a_{04} & a_{01} \\a_{12} & a_{14} & a_{11} \\a_{22} & a_{24} & a_{21}\end{pmatrix}[2] os_md.divmattex(S,[4]);\begin{align*}&\left(\begin{matrix}
a_{00} & a_{01} & a_{02} & a_{03} \\a_{10} & a_{11} & a_{12} & a_{13} \\a_{20} & a_{21} & a_{22} & a_{23}301\end{matrix}\right.\\&\quad\left.\begin{matrix}
a_{04} & a_{05} & a_{06} & a_{07} & a_{08}\\a_{14} & a_{15} & a_{16} & a_{17} & a_{18}\\a_{24} & a_{25} & a_{26} & a_{27} & a_{28}\end{matrix}\right)%\end{align*}
401. smallmattex(s):: TEX のソースで ( ) や { } で囲まれた行列を小サイズに変換する（cf. mtotex()）
402. texlen(s):: LATEX の数式の横幅を推測して文字数で返す
Risa/Asir の TEX 出力の文字列で，多項式や有理式に対応する．改行記号や行列には対応していない．
より具体的には以下の通り．
• \frac{...}{...} は，分母と分子の推測横幅文字数の大きい方と数える（ネスティング可）• 上を除いて \ で始まりアルファベットか続く部分はまとめて 1 文字幅とみなす．
• 空白や改行文字，& ^ _ { } は文字数に数えない．
• _*^ が存在して * が任意の 1 文字の場合は _* を文字数に含めない．
• _{**}^ または _{**}}^ に対しては（* は任意文字），_{**} を 1 文字とみなして数える．

403. texlim(s, n|del=s0 ,cut=s1 ):: 長い TEX の数式を，複数行に分割する
s は多項式に対応する（\frac などが含まれていない）TEX の数式.
texlen() で計った文字数幅が n を越えないよう分割する．ただし n < 30 のときは，n =TeXLim とみなされる．
• 改行は + - ( の前．ただし \Bigl( や \biggl( などには正しく対応している．
• s0 は元の改行の文字列（これは残される）で s1 は新たに挿入される改行の文字列．
• デフォルトは，s1 ="\\\\\n&" かつ s0 = s1 .
• s = 1 のときは，TeXLim を n に設定するコマンドとなる．

3.2.10 Lines and curves404. ladd(u,v,t)ladd(u,v,[t2 ])ladd(u,v,[t1 ,t2 ]):: ベクトルまたはリストの成分の和（t = 1）や差（t = −1）を成分とするリストを返す
u に v を t 倍して加えた座標を返す．あるいは，u の t1 倍と v の t2 倍の和を返す．
• ladd(u,v,[t2 ]) は，ladd([u,v],0,[1 − t2 ,t2 ]) と解釈される．
• ladd([u,v],0,t) としても同じ結果を返す（map() を用いるときに便利）．
[0] os_md.ladd([1,2],[3,4],1);[4,6][1] os_md.ladd(ltov([1,2]),[3,4],1);[4,6][2] os_md.ladd([1,2],[3,4],-1);[-2,-2][3] os_md.ladd(0,[3,4],1/2);[3/2,2][4] os_md.ladd([1,2],[3,4],[1/2]);[2,3][5] os_md.ladd([1,2],[3,4],[1/4,3/4]);302

[5/2,7/2][6] os_md.ladd([1,2],[3,4],[3/4]);[5/2,7/2][7] os_md.ladd([1,2],[3,4],[-1]);[-1,0]
405. lsub([u,v]):: ベクトルまたはリスト u, v に対して，u − v を返す
引数がリストまたはベクトルで，その第一成分がリストやベクトルでなければ，引数をそのまま返す．

[0] os_md.lsub([[1,2],[3,5]]);[2,3][1] os_md.lsub([ltov([1,2]),ltov([3,5])]);[ 2 3 ]
[2] os_md.lsub([1,2]);[1,2]406. dnorm(v|max=f ):: ベクトルまたはリストのノルム，または 2 点間の距離を返す• max=1 : 成分の絶対値の最大値を返す．
• max=2 : 成分の絶対値の和を返す．
• v が [v1 , v2 ] という 2 つのリストまたはベクトルの時は，その差のノルムを返す．
[0] os_md.dnorm([1,2]);
2.23607[1] os_md.dnorm([[1,2],[2,3]]);1.41421[2] os_md.dnorm([1+@i,1-@i]);2[3] os_md.dnorm([1,2,-3]|max=1);3[4] os_md.dnorm([1,2,-3]|max=2);
6407. dext(u,v)，([u1 ,u2 ],[v1 ,v2 ]):: 2 次元ベクトルまたはリストの外積を返す
u と v の外積，または u2 − u1 と v2 − v1 の外積を返す．
[0] os_md.dext([1,0],[1,1]);
1[1] os_md.dext([[0,0],[1,2]],[[1,1],[2,2]]);-1[2] os_md.dext(ltov([1,2]),[1,1]);-1408. darg([p,q]) darg([p1 ,p2 ],[q1 , q2 ])
→
−
→ −−→
pq = (x, y) の偏角 θ，または −p−
1 p2 と q1 q2 のなす角に応じた数を返す→−• pq = (x, y) の偏角 θ に応じた数（− π2 < θ ≤ 32 π ）：(x, y) = (0, 0) のとき，−8 を返す．

303

2

それ以外では，v = x2y+y2 とおく．
y < 0 のとき，v を −v で置き換え，さらに x ≤ 0 のとき v を 2 − v で置き換える．
戻り v は −2 または −1 ≤ v < 3 を満たす．
→ −−→
• −
p−
1 p2 と q1 q2 のなす角 θ に応じた r を返す数 (−2 < r ≤ 2) ：r = −8: p1 = p2 または q1 = q2
r = 0 : 同じ向き
r = 2 : 逆向き
r = ±1 : 直交→−−→◦r≥0: −
q−
1 q2 の向きは p1 p2 から正の向きに 180 以下回転した方向|r| : なす角の大きさ[0] os_md.darg([1,1],[1,1]);-8[1] os_md.darg([0,0],[1,-1]);-1/2[2] os_md.darg([0,0],[2,1]);
1/5[3] os_md.darg([0,0],[-2,1])
9/5[4] os_md.darg([0,0],[-2,-1]);
11/5[5] os_md.darg([0,0],[0,-1]);
5[6] P=[[0,0],[1,1]]$[7] os_md.darg(P,[[0,0],[2,2]]);0[8] os_md.darg(P,[[0,0],[0,2]]);
1/2[9] os_md.darg(P,[[0,0],[2,-2]]);-1[10] os_md.darg(P,[[0,0],[0,-1]]);-3/2
409. dwinding([p,[q1 , . . . , qn ])点 p に対して，点 q1 , . . . , qn , q1 を順に繋ぐ折れ線の回転数を返す
折れ線が点を基準に反時計回りに何回廻ったかを返す．
点が折れ線の端点にあるときは 13 を，折れ線上にあるときは 21 を返す．

[0] os_md.dwinding([1,1],[[0,0],[4,0],[0,4]]);1[1] os_md.dwinding([1,1],[[2,2],[4,0],[0,4]]);
1/2[2] os_md.dwinding([1,1],[[3,3],[4,0],[0,4]]);0410. mrot(θ|deg=1) mrot([θz0 ,θy ,θz ]|deg=1,conj=1):: 角度 θ の回転行列，または 3 次元の回転行列を返す• deg=1 を指定すると，度単位となる．
304

• 引数が [θz0 ,θy ,θz ] のときは，z 軸の周りに θz , x 軸の周りに θy 最後に z 軸の周りに θz0 回転した
3 次元の直交行列を返す．
このとき conj=1 を指定すると，z 軸の周りに θz , y 軸の周りに θy 回転したときの z 軸にあたる軸に対する θz0 の回転を返す．
[0] os_md.mrot(@pi/6);[ 0.866025 -0.5 ][ 0.5 0.866025 ][1] os_md.mrot(45|deg=1);[ 0.707107 -0.707107 ][ 0.707107 0.707107 ][2] os_md.mrot([30,0,0]|deg=1);[ 0.866025 -0.5 0 ][ 0.5 0.866025 0 ][ 0 0 1 ][3] os_md.mrot([0,30,0]|deg=1);[ 0.866025 0 -0.5 ][ 0 1 0 ][ 0.5 0 0.866025 ][4] os_md.mrot([1,30,45]|deg=1,conj=1);[ 0.999867 -0.0151333 -0.00612372 ][ 0.0150952 0.999867 -0.00621699 ][ 0.00621699 0.00612372 0.999962 ]
411. dvangle(v1 ,v2 ) dvangle([u1 , u2 , u3 ],0):: ベクトルまたはリストの鋏む角度の余弦を返す• dvangle([u1 , u2 , u3 ],0) は dvangle(u2 − u1 ,u3 − u2 ) と解釈される．
• v1 または v2 が 0 のときや u1 , u2 , u3 のいずれかが 0 のときは 1 を返す．
• 2 次元ベクトル V の偏角（π 以下で −π より大）は myarg(V[0]+V[1]*@i) で得られる．
412. ptaffine(m,ℓ|org=v,shift=w,arg=θ,deg=θ,proc=1):: 実数の組（座標）のリストを結合する，またはアフィン変換（こちらは描画実行形式も可）を施す• 曲線や折れ線の通過点の座標を表す複数のデータのリストを想定している．
• m は行列またはスカラー• org=v : v は座標で，ここを原点とした線型変換とする（デフォルトは原点中心）．
• arg=θ : 平面座標のリストのとき指定可能．角度 θ の反時計回り回転を行った後，M による線型変換を行う．θ は@pi/2 など deval() によって実数が得られるものでもよい．
• deg=θ : 上と同じだが，角度をラジアンでなく度で与える．
• shift=w : w は座標で，変換を行ったあと，w だけ平行移動する．
• proc=1 : 描画実行形式（cf. execdraw()）ℓ のアフィン変換の場合に指定．
• ℓ の成分に数や文字列などがあってもよい．それはそのままに保たれる（xybezier() の引数など）．

• ℓ は単に座標であってもよい．
• 座標はリストでなくてベクトルで与えてもよい．
• m が以下の文字列のときは特別の意味をもつ（connect などで，曲線を繋げることができる）．
– reverse : ℓ を xybezier() のデータとみなして，描く順序を逆にしたデータに変換– union : ℓ を xybezier() のデータのリストとみなして，合わせて一つの曲線データとする．
– connect : ℓ を xybezier() のデータのリストとみなして，順につなげた一つの曲線データと
する．

305

– close : ℓ を xybezier() のデータまたはそのリストとみなして，順につなげ，始点と終点をつなげて閉曲線データとする．

– loop : ℓ を xybezier() のデータまたはそのリストとみなして，順につなげ，終点を始点に変えて閉曲線データとする．

[0] L=[[1,0],[0,1],[1,1]]$[1] os_md.ptaffine(2,L|arg=3.1416/8);[[1.84776,0.765369],[-0.765369,1.84776],[1.08239,2.61313]][2] os_md.ptaffine(2,L|arg=3.1416/8,org=[1,1]);[[1.76537,-0.847758],[-0.847758,0.234631],[1,1]][3] os_md.ptaffine(2,L[0]|arg=3.1416/8,org=[1,1]);[1.76537,-0.847758][4] L1=[[2,0],[1,2],[2,1]]$[5] os_md.ptaffine("union",[L,L1]);[[1,0],[0,1],[1,1],0,[2,0],[1,2],[2,1]][6] os_md.ptaffine("connect",[L,L1]);[[1,0],[0,1],[1,1],1,[2,0],1,[1,2],[2,1]][7] os_md.ptaffine("close",[L,L1]);[[1,0],[0,1],[1,1],1,[2,0],1,[1,2],[2,1],1,-1][8] L3=[[1,1],[2,0],[1,2],[1,0]]$[9] os_md.ptaffine("connect",[L,L3]);[[1,0],[0,1],[1,1],1,[2,0],[1,2],[1,0]][10] os_md.ptaffine("close",[L,L3]);[[1,0],[0,1],[1,1],1,[2,0],[1,2],-1][11] L2=[2,1],[1,2],[2,1]]$[12] os_md.ptaffine("close",[L,L2]);[[1,0],[0,1],[1,1],1,[2,1],1,[1,2],[2,1],1,-1][13] os_md.ptaffine("loop",[L,L2]);[[1,0],[0,1],[1,1],1,[2,1],1,[1,2],-1][14] os_md.ptaffine("reverse",[[1,0],[0,1],[1,1],1,[2,0],[1,2],[2,1]]);[[2,1],[1,2],[2,0],[1,1],1,[0,1],[1,0]]413. ptpolygon(n,r|org=p,scale=t,arg=θ,deg=θ):: 半径 r の円に内接する正 n 多角形の頂点の平面座標• 半径 r の円に内接する正多角形の座標のリストを返す• デフォルトでは下辺が水平となる．
• org=p : 中心の座標（デフォルトは (0, 0)）．
• arg=θ : 多角形を反時計回りに θ 回転．@pi/8 などの指定も可能．
• deg=θ : 上と同じだが，角度の単位が度• xylines() の例を参照.
[0] os_md.ptpolygon(5,2);[[-1.17557,-1.61803],[1.17557,-1.61803],[1.90211,0.618034],[-2.07711e-013,2],[-1.90211,0.618034]][1] os_md.sint(os_md.ptpolygon(5,2),4);
os_md.sint(os_md.ptpolygon(5,2),4);[[-1.1756,-1.618],[1.1756,-1.618],[1.9021,0.618],[0,2],[-1.9021,0.618]]306

[2] os_md.ptpolygon(4,2);[[-1.41421,-1.41421],[1.41421,-1.41421],[1.41421,1.41421],[-1.41421,1.41421]][3] os_md.sint(os_md.ptpolygon(4,1|deg=45,scale=2),5);[[0,-2],[2,0],[0,2],[-2,0]][4] os_md.xylines(os_md.ptpolygon(7,10)|close=1,dviout=1);414. ptlattice(m,n,v1 ,v2 |org=p,scale=t,cond=[f1 ,f2 , . . .],line=1):: org を始点として v1 方向に m 個まで，v2 方向に n 個までの合計 m × n 個の格子点の座標• scale=t : 得られた座標を全て t 倍にして返す（org も同様）．
• line=1 : 格子点でなくて，格子を描く線分のデータを返す xylines() の例を参照）．
• f1 , f2 , . . . は (x, y) の函数（一次式または多項式または有理式）で，これらが全て非負の点のみ残す（平面座標の時のみ指定可能）．
fj =[fj1 , . . . , fj,nj ] は，fj,i (x, y) のいずれかが非負となる，という条件を表わす．
たとえば，[x-y,[5-x,y]] は，y ≥ x であって，x は 5 以下かまたは y が非負，という条件を表す．

[0] os_md.ptlattice(2,3,[1,0],[0,1]);[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2]][1] os_md.ptlattice(2,3,[1,0],[0,1]|line=1);[[0,0],[1,0],0,[0,1],[1,1],0,[0,2],[1,2],0,[0,0],[0,2],0,[1,0],[1,2]][2] os_md.xylines(os_md.ptlattice(10,5,[5,0],[0,5]|line=1,cond=[35-x*2+y])|dviout=1);415. ptcopy(ℓ,v):: 座標のリスト ℓ を移動方向のリスト v に従って複製コピーする• 移動方向のリストの成分で 0 はそのままコピーされる．
• 各移動の間には 0 が挿入される．
• 移動方向が一つなら，それを v で指定してよい．
[0] os_md.ptcopy([[0,1],[1,2]],[[0.1,0],[0,0.1],[0.1,0.1]]);[[0.1,1],[1.1,2],0,[0,1.1],[1,2.1],0,[0.1,1.1],[1.1,2.1]]
416. ptcommon([s1 ,s2 ],[t1 ,t2 ]|in=k):: 直線や線分や円に対して共通点，接点や垂線の足，内分点，方向転換進行点，角度などを求める• s1 = [x1 , y1 ], s2 = [x2 , y2 ], t1 = [u1 , v1 ], t2 = [u2 , v2 ] のとき, s1 と s2 とを結ぶ直線と，t1 と t2を結ぶ直線の交点の座標（共通点がないときは 0 を無限にあるときは 1）を返す．
ただし，s1 = s2 のとき，s1 と s2 を結ぶ直線とは，その点と考える（t も同様）．
• s1 = [x1 , y1 ], s2 = [x2 , y2 ], t1 = [u1 , v1 ], t2 = 0 のとき，s1 と s2 とを結ぶ直線に点 t1 から下ろした垂線の足の座標を返す，• s1 = [x1 , y1 ], s2 = [x2 , y2 ], t1 = [u1 , v1 ], t2 > 0 のとき，s1 と s2 とを結ぶ直線と，点 t1 を中心とする半径 t2 の円との交点を返す（交点をリストで，交点がないときは 0 を返す）．
• s1 = [x1 , y1 ], s2 > 0, t1 = [u1 , v1 ], t2 > 0 のとき，点 s1 を中心とする半径 s2 の円と，点 t1 を中心とする半径 t2 の円との交点を返す（交点をリストで，交点がないときは 0 を返す）．

307

• s1 = [x1 , y1 ], s2 > 0, t1 = [u1 , v1 ], t2 = 0 のとき，点 s1 を中心とする半径 s2 の円に t1 を通る接線を引いたときの接点の座標を返す（接点をリストで，接点がないときは 0 を返す）．
→
• s1 = [x1 , y1 ], s2 = [x2 , y2 ], t1 が数のとき，−s−sをtだけ回転した向きの単位ベクトルを
t1 倍し
1 2
2
たベクトルだけ s2 から移動した点を返す（方向転換進行点）．
ただし in=1 を指定すると，線分 s1 s2 の比 t1 : t2 での内分点を返す．
• in=1 を指定すると，2 点を結ぶ直線が 2 点を結ぶ線分で置き換えられる．共通集合が線分になる
ときは，その両端を返す．

• in=-1 を指定すると，2 点を結ぶ直線が 2 点を結ぶ線分の垂直二等分線で置き換えられる．
• in=-2 を指定すると，s1 と s2 とを結ぶ直線が，その 2 点を結ぶ線分の垂直二等分線で置き換えられる．

• in=-3 を指定すると，s1 と s2 とを結ぶ線分の垂直二等分線と，t1 と t2 を結ぶ線分の交点があればそれを返す．

• 直線と直線の交点を求める場合は，座標に不定元が含まれていてもよい．また，全ての座標が有理数で指定してあれば，直線の交点の座標も有理数で返される．

→ −−→
−−→
• in=2 を指定すると，−s−
1 s2 と t1 t2 のなす角度を返す（−π を越えて π 以下で，s1 s2 を基準として反時計回りが正の向き）．

• in=3 を指定すると，上と同じだが度単位で返す．
[0] os_md.ptcommon([[0,0],[1,2]],[[0,4],[4,0]]); /* 二直線 */[4/3,8/3][1] os_md.ptcommon([[0,0],[1,2]],[[0,4],[x,y]]);[(4*x)/(2*x-y+4),(8*x)/(2*x-y+4)][2] os_md.ptcommon([[0,0],[1,2]],[[0,4],[4,0]|in=1); /* 二線分 */0[3] os_md.ptcommon([[0,0],[2,2]],[[0,0],[2,3]]|in=-2); /* 垂直二等分線と直線 */[4/5,6/5][4] os_md.ptcommon([[0,0],[2,2]],[[5,4],0]);/* 垂線の足を求める */[9/2,9/2][5] os_md.ptcommon([[0,a],[1,b]],[[0,c],[1,d]]);[(a-c)/(a-b-c+d),(d*a-c*b)/(a-b-c+d)][6] os_md.ptcommon([[0,0],[4,8]],[[4,8],0.5]|in=1); /* 線分と円 */[[3.77639,7.55279]][7] os_md.ptcommon([[0,0],1],[[1,2],3]);/* 二円 */[[-0.96332495807107996983525630141,-0.26833752096446001508],[0.36332495807107996975,-0.93166247903553998487]][8] os_md.ptcommon([[0,0],1],[[1,4],0]);/* 円の接点を求める */[[-0.88235294117647058813,0.470588235294117647250153324556],[1,0]][9] os_md.ptcommon([[0,1],[2,3]],[1,2]|in=1);/* 内分点 */[2/3,5/3][10] os_md.ptcommon([[0,1],[2,3]],[t,1-t]|in=1);[2*t,2*t+1][11] os_md.ptcommon([[0,1],[2,3]],[2,-1]|in=1);/* 外分点 */[4,5][12] os_md.ptcommon([[0,0],[2,3]],[1,@pi/2]);/* 方向転換進行点 */[1.16795,3.5547][13] os_md.ptcommon([[0,0],[1,1]],[[0,0],[-2,2]]|in=2); /* 角度 (ラジアン)*/308

1.5708[14] os_md.ptcommon([[0,0],[1,1]],[[0,0],[-2,2]]|in=3); /* 角度 (度）*/
90[15] os_md.ptcommon([[-1,0],[1,0]],[[0,1],[1,1]]); /* 二直線：平行 */0[16] for(I=1;I<4;I++) print(os_md.ptcommon([[0,0],[2,0]],[[I,0],[3,0]]));
1
1
[3,0]
[17] for(I=1;I<4;I++) print(os_md.ptcommon([[0,0],[2,0]],[[I,0],[4,0]]|in=1));[[1,0],[2,0]][2,0]0417. pt5center(p,q,r|opt=f ):: p, q, r を頂点とする三角形の五心, 円や直線に接する円• 三点を与えたとき，重心，内心，外心，垂心，傍心（頂角 p, q, r の内側という順）でリストで返す．
– opt=0 : 重心と各辺の中点を返す– opt=1 : 内接円（中心と半径の組）と各辺との接点を返す– opt=2 : 外接円（中心と半径の組）を返す– opt=3 : 垂心と頂点から底辺に下ろした垂線の足を返す– opt=4, 5, 6 : 傍接円（中心と半径の組）と各辺またはそれの延長線との接点を返す• 三点は 3 次元以上のユークリッド空間の点でもよい.
• p = [[x0 ,y0 ],r] で円を指定し（中心と半径），q = [q1 ,q2 ] = [[x1 ,y1 ],[x2 ,y2 ]], r =[r1 ,r2 ] = [[x2 ,y2 ],[x3 ,y3 ]] によって直線上の 2 点で二直線を指定したとき，円と二直線に接→する円の半径と中心座標のリストを返す．ただし −q−
1 q2 を x 軸の正方向で，直線 r1 r2 を y 軸とする
ような（斜交）座標系の第 1 象限および第 3 象限内の接円のみを返す．第 3 象限の場合は，半径の−1 倍を返す．第 1 象限で直線の交点から近いものから順に，次に第 2 象限で原点に近いものから順に，半径と中心座標の組をリストにして返す．
→ −−→– ∠q3 q1 q2 が 180◦ 以下で，−q−
1 q3 は q1 q2 を正方向に回転したものとする. r = [q1 ,q3 ] とおくと，その頂角内の接円は，リストでは半径が正のものとなる．
– neg=1 というオプションを指定すると，半径の符号が逆になる．

[0] os_md.pt5center([3,0],[0,0],[1,2]);[[4/3,2/3],[1.20382,0.744002],[3/2,1/2],[1,1],[-1.03225,1.67021],[4.03225,2.49207],[1.79618,-2.90628]]
418. ptinversion(p|org=[a,b],sc=r):: 点 p または円 p の反転• 反転とは，複素平面上で z 7→ z1 で定まる写像とする.
• sc=r を指定すると，r > 0 のとき，複素平面上で z 7→ z̄r で定まる写像, r < 0 のとき z 7→ |r|z で定まる写像とする.
• p =[x,y] と点を与えると，反転された点を返す（p が原点のときは 0 を返す）.
• p=[[x,y],r] と円の半径と中心で与えたとき，反転された円を同じ形式で返す.
• 円が原点を通るとき，反転は直線となるが，そのときは直線上の二点を返す.
• org=[a,b] : 点 (a, b) を中心として反転する.
• 複数のものをリストの形で渡してもよい[0] RR=1/8;D=1/4;II=-5;JJ=4;ID=1;/* 平行線間の円の反転 */309

for(S="",R=[],I=II;I<=JJ;I++){C=os_md.ptinversion([[(2*I+ID)*RR,-D-RR],RR]);
S+=os_md.xyang(C[1],C[0],0,0);};S+=os_md.xyang(1/2/D,[0,1/2/D],0,0);
S+=os_md.xyang(1/2/(D+2*RR),[0,1/2/(D+2*RR)],0,0);[1] show(S);/* 円環内の N 個の円
X=dsin(3.1416/N), 小円/大円=(1-X)/(1+X), (大円-小円)/大円=2X/(1+X),
囲む円/大円=X/(1+X), 囲む円の中心の円/大円=1/(1+X)
大円を基準 半径 1 */N=6 => X=1/2, R>0, Sc: スケール値 R=3;SC=30; */[2] N=6;R=3;SC=30;[3] for(S="",I=0;I<N;I++){
U=os_md.ptinversion([[1+R+dcos(I*3.1416*2/N+D)/(1+X),dsin(I*3.1416*2/N+D)/(1+X)],X/(1+X)]);
S+=os_md.xyang(SC*U[1],[SC*U[0][0],SC*U[0][1]],0,0);};
U=os_md.ptinversion([[1+R,0],1]);
S+=os_md.xyang(SC*U[1],[SC*U[0][0],SC*U[0][1]],0,0);
U=os_md.ptinversion([[1+R,0],(1-X)/(1+X)]);[4] show(S);419. ptcontain(p,[t1 ,t2 ,t3 ]):: 点 p あるいは線分 p = [p1 ,p2 ] と三角形 t1 , t2 ，t3 の共通部分を返す• p が点のとき，三角形の外部，内部，辺，頂点に属するかどうかに応じて，0，1，2，3 を返す．
• p =[p1 ,p2 ] という線分のとき，三角形で切り取られた部分を返す．
[0] T=[[3,0],[0,0],[2,2]]$[1] os_md.ptcontain([0,3],T);0[2] os_md.ptcontain([1,1/2],T);1[3] os_md.ptcontain([1,1],T);2[4] os_md.ptcontain([0,0],T);3420. pg2tg(n|all=f ,bis=1):: 正 n 多角形の対角線による三角形分割のリストを返す
310

正 n 角形の頂点は，0 から n − 1 まで順に番号がつけられ，頂点 i と j を結ぶ対角線は [i,j] で表され
（i < j とする），三角形分割は，(n − 3) 本の対角線のリストで表される．
• デフォルトでは，opt=1 を指定した getCatalan() を用いるが，bis=1 を指定すると，pgpart()の ["ext",i] によって 4 角形から帰納的に順にすべて構成する．また，bis=2 とすると，opt=2を指定した getCatalan() を用いる．
• デフォルトでは，回転や裏返しで移らない三角形分割のリストを返す．
• all=1 を指定すると，すべての三角形分割のリストを返す. その個数は Catalan 数 Cn−2 でcatalan(n-2) となる．
• all=2 を指定すると，回転で移り合わない三角形分割のリストを返す．
• all=64 を指定すると，回転や裏返しで移らない Zigzag タイプ（分割する対角線のない頂点が 2つ）の三角形分割のリストを返す（上の 1, 2 との同時指定は，64, 65 とする）．
• 負の数 −n を与えると，4 角形から n 角形までの三角形分割のリストのリストを返す（bis=1 が指定されたとみなす）．

[0] os_md.pg2tg(5);n=6:[[[0,2],[0,3]]][1] os_md.pg2tg(5|all=1);[[[0,2],[0,3]],[[0,2],[2,4]],[[0,3],[1,3]],[[1,3],[1,4]],[[1,4],[2,4]]][2] os_md.catalan(5-2);
5[3] os_md.pg2tg(6|all=64);[[[0,2],[0,3],[0,4]],[[0,2],[0,3],[3,5]]]421. pgpart(p,f ):: 正 n 多角形の対角線による三角形分割の種々の変換
p は（通常）前項の形式の三角形分割の一つで，回転，鏡映，フリップ，拡大，縮小などの変換を f で指定する（そのほかに getCatalan() による変換がある）．
変換後は，標準的にソートされたデータとして返される．
• f が 0 または負の整数のときは，−f だけ回転した分割（頂点の番号を −f 増やす）を返す．ただし，番号は mod n で正規化され，対角線は辞書式順序で並べた標準形に変換される．
pgpart(p,0) は，標準形への変換に用いる．pgpart(p,"std") でも同じ．
• f ="#" : 各頂点を通る（分割に用いた）対角線の本数のリストを返す．
• f ="-#" : 上の逆変換を返す．
• f =["pair",i] : 頂点 i を端点とする対角線の他の端点のリストを返す．
• f =["pairb",i] : i と三角形の一辺で直接つながった頂点のリストを返す．
• f =["vertex",i] : 辺 [i − 1,i] を底辺とする三角形の頂点を返す.
• f =["mirror",k] : 頂点の番号 i を k − i mod n に変える変換を行う．k が偶数の時は，頂点 k2k+1を通る対称軸に対する鏡映変換，k が奇数の時は辺 [ k−1
2 , 2 ] の中点を通る対称軸に対する鏡映変換となる．
トーナメント表の左右反転に対応する変換は以下で得られる

os_md.pgpart(,["mirror",length(p)+2]• f =["flip0",[i,j]] : 三角形分割に使われている対角線 [i,j] を対角線として含む四辺形のもう一つの（三角形分割には使われていない）対角線，すなわち，[i,j] を底辺とする三角形 2 つの頂点を返す．[i,j] が三角形分割に使われていないときは 0 を返す．
• f =["flip",[i,j]] : [i,j] を f =["flip0",[i,j]] で得られる対角線に取り替える（フリップという）．

• f =["ext",i] : 辺 [i − 1,i] の間に頂点を加えた (n + 1) 角形の三角形分割を返す．辺 [i − 1,i]は対角線に変化する．

• f ="res" : 分割に使われた対角線の端点にはならない頂点のリストを返す．
• f =["res",i] : 頂点 i を削った (n − 1) 角形の三角形分割を返す．頂点 i は分割に使われた対角線
311

の端点となっていないとき，すなわち f ="res" に含まれる頂点のときに可能．不可能なときは 0を返す．
• f ="check" : 正しい三角形分割を与えているかどうかをチェックする．正しければ 1 を, 正しくな
ければ 0 を返す．

[0] P=[[0,2],[2,5],[3,5]]$[1] os_md.pgpart(P,"#");[1,0,2,1,0,2][2] os_md.pgpart(@@,"-#");[[0,2],[2,5],[3,5]][3] os_md.pgpart(P,["pair",2]);[0,5][4] os_md.pgpart(P,["pairb",2]);[0,1,3,5][5] os_md.pgpart(P,["vertex",2]);0[6] os_md.pgpart(P,["flip0",[2,5]]);[0,3][7] os_md.pgpart(P,["flip",[2,5]]);[[0,2],[0,3],[3,5]][8] os_md.pgpart(P,["ext",3]);[[0,2],[2,4],[2,6],[4,6]][9] os_md.pgpart(P,"res");[1,4][10] os_md.pgpart(P,["res",1]);[[1,4],[2,4]][11] os_md.pgpart(P,"check");
1[12] os_md.pgpart([[0,1],[2,5],[3,5]],"check");
0[13] os_md.pgpart([[1,4],[1,5],[2,5]],"check");
0422. xypg2tg(p|pg=n,skip=s,r=r,org=b,rot=c,opt=t,proc=f ,line=ℓ,every=e,V=v,dviout=d):: （複数の）正多角形の三角形分割などの表示
デフォルトでは p は，pg2tg() で出力された正凸多角形の三角形分割のデータを使う．
すなわち，正 n 角形の頂点を順に反時計回りに 0 から n − 1 としたとき，三角形分割に使われる対角線 (n − 3) 本のデータ. 対角線を [1, 3] のように表し，それの (n − 3) 個のリスト．
p として，複数の三角形分割のリストを集めたリストでもよい.
• pg=n : 正 n 角形（三角形分割でないときに指定. 三角形分割のときは n を自動判断）• r=r : 半径 r(cm) の円に内接する正多角形（デフォルト 0.5)
• r=[r,d,w]: 上記の他，複数の三角形分割間を結ぶ線の端点を正多角形の中心から r + wcm にする（デフォルトは，w=0.2）．
• r=[r,d]: 半径 r(cm) の円に内接する正多角形（デフォルト 0.5) で，ラベルは頂点または辺の外側 d の位置（デフォルト 0.15）．d を負にすれば内側．
• org=[x,y] : 正多角形の中心の座標（デフォルトは [0,0]）• rot=t : 頂点 (0) の偏角（デフォルトは 3.1426/2）, その後は正の向き
312

• opt=s : p で指定した頂点同士を結ぶ線分の属性（色とか点線 "dotted" とか，デフォルトは"red"）• V=v : v =[[p1 ,q1 ],[p2 ,q2 ],[p3 ,q3 ], . . .] は多角形の（中心を原点とする）頂点の座標．これにより正多角形でない場合にも対応．
• 次は，描画を重ねるのに使う（複数の三角形分割，特定の対角線や辺に異なる色をつける, などのため）– skip&1 : 頂点の相対座標を省略– skip&2 : 正多角形の描画を省略– skip&4 : 原点の座標の定義を省略– skip&8 : 頂点同士を結ぶ線分の描画を省略– (skip&48)==32 : 頂点にラベルをつける– (skip&48)==48 : 辺にラベルをつける– skip&64 : ラベルを右回りでつける– skip&128 : ラベルの番号を 0 からでなくて 1 からとする– skip&256 : 出力する TEX のテキストを変更・加筆がより簡単なものとする– skip&512 : 複数の多角形を表示するとき，n 番目の多角形の中心座標をラベル (Sn) で参照できるようにする（複数でないときオプション num=n で n の指定が可能）– たとえば skip で 48 と 256 を同時に指定するときは，skip=48+256 とします．
– dviout=1 : TikZ=1 となっているとき画面表示を行う– dviout=-1 : TikZ=1 となっているとき, TEX のソースを出力• p が多角形の複数の三角形分割のリストを集めたリストのとき
org=[[a1 ,b1 ],[a2 ,b2 ], · · · ] : 多角形の中心位置を（多角形の個数）順に指定
org=[m,[a,b],[c,d]] : 一つごとに [a,b] ずらす. m 個に達すると改行され，[c,d] だけずらす. [c,d] は省略可．
デフォルトは，m = 10, [a,b]=[1.5,0], [c,d]=[0.1.5] となっている.
• every=e : 各多角形描画の際に追加して入れる描画コード e を設定する．

• line=[ℓ1 ,ℓ2 , . . .]– ℓj =[mj ,nj ,sj ] : 多角形の mj 番目と nj 番目を線や矢印でつなぐ（最初は 1 番目）．
オプション文字列を sj で指定する（たとえば，"->, red"）．sj =""はオプションを指定しないことを意味する．

– ℓj =[mj ,mj ] : 前項と同じだが，オプション文字列は ℓj−1 の指定に従う．デフォルトはオプ
ション指定なし．

– ℓ の成分が一つの時は，ℓ =[m,n,s] などとしてもよい．
以 下 は TikZ=1 と な っ て い る と き の 結 果 で ，デ フ ォ ル ト で は TEX の ソ ー ス を 出 力 す る（\begin{tikzpicture}...\end{tikzpicture}の 中 身 ．フ ァ イ ル に 書 き 出 す に は fcat() を使う）．
TEX では最初に以下が必要．

\usepackage{graphicx,color}\usepackage{tikz}\usetikzlibrary{calc,arrows}[0] P=os_md.pg2tg(6);[[[0,2],[0,3],[0,4]],[[0,2],[0,3],[3,5]],[[0,2],[0,4],[2,4]]][1] S=os_md.xypg2tg(P);%TikZ0%%1%\coordinate(0) at (0,0.5);\coordinate(1) at (-0.433,0.25);313

\coordinate(2) at (-0.433,-0.25);\coordinate(3) at (0,-0.5);\coordinate(4) at (0.433,-0.25);\coordinate(5) at (0.433,0.25);%\coordinate(S) at (0,0);\draw($(S)+(0)$)--($(S)+(1)$)--($(S)+(2)$)--($(S)+(3)$)--($(S)+(4)$)--($(S)+(5)$)--cycle;\draw [red]($(S)+(0)$)--($(S)+(2)$) ($(S)+(0)$)--($(S)+(3)$) ($(S)+(0)$)--($(S)+(4)$);%2%\coordinate(S) at (1.5,0);\draw($(S)+(0)$)--($(S)+(1)$)--($(S)+(2)$)--($(S)+(3)$)--($(S)+(4)$)--($(S)+(5)$)--cycle;\draw [red]($(S)+(0)$)--($(S)+(2)$) ($(S)+(0)$)--($(S)+(3)$) ($(S)+(3)$)--($(S)+(5)$);%3%\coordinate(S) at (3,0);\draw($(S)+(0)$)--($(S)+(1)$)--($(S)+(2)$)--($(S)+(3)$)--($(S)+(4)$)--($(S)+(5)$)--cycle;\draw [red]($(S)+(0)$)--($(S)+(2)$) ($(S)+(0)$)--($(S)+(4)$) ($(S)+(2)$)--($(S)+(4)$);[2] os_md.xypg2tg(os_md.pg2tg(6))|skip=32,dviout=1)$
0
1

0
5 1

2

4 2
3

0
5 1

5

4 2
3

4
3

[3] S=os_md.xypg2tg(P|skip=256);%TikZ0%%1%\coordinate(P0) at (0,0.5);\coordinate(P1) at (-0.433,0.25);\coordinate(P2) at (-0.433,-0.25);\coordinate(P3) at (0,-0.5);\coordinate(P4) at (0.433,-0.25);\coordinate(P5) at (0.433,0.25);%\coordinate(S) at (0,0);\coordinate(0) at ($(S)+(P0)$);\coordinate(1) at ($(S)+(P1)$);\coordinate(2) at ($(S)+(P2)$);\coordinate(3) at ($(S)+(P3)$);\coordinate(4) at ($(S)+(P4)$);314

\coordinate(5) at ($(S)+(P5)$);\draw(0)--(1)--(2)--(3)--(4)--(5)--cycle;\draw [red](0)--(2) (0)--(3) (0)--(4);%2%\coordinate(S) at (1.5,0);\coordinate(0) at ($(S)+(P0)$);\coordinate(1) at ($(S)+(P1)$);\coordinate(2) at ($(S)+(P2)$);\coordinate(3) at ($(S)+(P3)$);\coordinate(4) at ($(S)+(P4)$);\coordinate(5) at ($(S)+(P5)$);\draw(0)--(1)--(2)--(3)--(4)--(5)--cycle;\draw [red](0)--(2) (0)--(3) (3)--(5);%3%\coordinate(S) at (3,0);\coordinate(0) at ($(S)+(P0)$);\coordinate(1) at ($(S)+(P1)$);\coordinate(2) at ($(S)+(P2)$);\coordinate(3) at ($(S)+(P3)$);\coordinate(4) at ($(S)+(P4)$);\coordinate(5) at ($(S)+(P5)$);\draw(0)--(1)--(2)--(3)--(4)--(5)--cycle;\draw [red](0)--(2) (0)--(4) (2)--(4);[4] Org=[[0,0],[-1.2,-1.5],[1.2,-1.5]]$[5] Line=[[2,3,dotted],[1,2,<->],[1,3]]$[6] os_md.xypg2tg(os_md.pg2tg(6)|skip=256,line=Line,org=Org,dviout=1);...
%3%\coordinate(S) at (1.2,-1.5);\node(S3)[circle,minimum size=1.4cm] at (S){};\coordinate(0) at ($(S)+(P0)$);\coordinate(1) at ($(S)+(P1)$);\coordinate(2) at ($(S)+(P2)$);\coordinate(3) at ($(S)+(P3)$);\coordinate(4) at ($(S)+(P4)$);\coordinate(5) at ($(S)+(P5)$);\draw(0)--(1)--(2)--(3)--(4)--(5)--cycle;
315\draw [red](0)--(2) (0)--(4) (2)--(4);%%\draw[dotted](S2)--(S3);\draw[<->](S1)--(S2);\draw[<->](S1)--(S3);423. istournament(ℓ|verb=1):: トーナメント戦のチェックℓ が正しいトーナメント戦を与えているかどうかをチェック"((**)(**))" のように与えたトーナメント戦 ℓ が正しいかどうかチェック• "(**)" を "*" での置き換えることを繰り返して，"*" になるかどうかをチェックするが，verb=1を指定すると，正しくないときに書き換えの結果を返す．

• トーナメント戦を与える文字列は間に空白が入っていてもよい• 0 と 1 のリストで与えてもよい（cf. getCatalan()）.
• 01 列は文字列の（空白を挟まない）リストで与えてもよい
424. xytournament(l,[w,h]|dviout=t,teams=s,top=0,winner=m,win=1,rev=1,verb=f ):: トーナメント戦の図の描画トーナメント戦を"T"形式または"01"形式 ℓ で与え，それを図示する.
TikZ の形で返す.
• [w,h] : w と h は横と縦の長さの単位（デフォルト 0.2）
• teams=s : 整数 s で始まるチーム名を高さ −h の位置に入れる.
s にチーム番号（数字）のリストを指定してもよい.
n チームの時，デフォルトのチーム番号は 0, 1, . . . , n − 1 とする．
s を [s, d] とすると，位置が −d と指定される.
• top=0 : 決勝戦の優勝者の縦線を省く．
• winner=m : 図の左から m (≥ 1）番目のチームを優勝チームとする勝ち負けが分かるトーナメン
ト戦の図を描く. このときは，top=0 の指定は無効. 優勝チームが参加しない試合は，各試合で右（rev=1 を指定すると左）側のチームが勝ちとする.
win=1 とすると，優勝者のみが分かるトーナメント戦の図を描く．
m = 0 とすると，番号 0 のチームを優勝チームとする（チーム番号は s[0] で指定可能）
winner=[m,p] とすると, 負けた方の切れ目の長さの比率を p とする（デフォルト 0.5）.
m を [m,[[m1 ,n1 ],[m2 ,n2 ],. . .],p] または [m,[[m1 ,n1 ],[m1 ,n2 ],. . .]] とすることによって，指定した試合の左（rev=1 を指定すると右）側のチームが勝ちとする. なお，mi から ni
番目のトップを決める試合が指定される.
• dviout=1 とすると画面表示される.
dviout=-1 とすると TEX のソースファイルに追加されるが，表示はしない.
• verb=-1 : 試合のリストを返す
各試合は，いくつかのグループのトップを定めるが，そのグループの先頭チームの番号と最後のチームの番号の組で表す。
• verb=-2 : 各試合の情報のリスト（対戦する両チームはどのグループのトップかと，それぞれ何回戦で決まったか）戻り値は [g1 ,g2 , . . .] で，gi =[[m0,0 ,m0,1 ],h0 ],[m1,0 ,m1,1 ],h1 ] : h0 試合目で決まる m0,0から m0,1 までのグループの勝者と h1 試合目で決まる m1,0 から m1,1 までのグループの勝者との試合で以下のようになっている．

m0,0 ≤ m0,1 < m1,0 = m0,1 + 1 ≤ m1,1
• verb=-3 : 優勝チームを 0 とした新たな番号付けのベクトル，優勝チームの参加する試合の情報のリスト，優勝チームが参加しない試合を優勝チームと何試合目で当たるかで分類した試合情報のリ
スト，の 3 つのリスト試合情報は，両チームが（元々の番号で）どのグループの何試合目の勝者か，とどちらのチームが勝ったかの情報（正は右，負は左のチーム，±2 は優勝チームが勝者，±1 はそ

316

れ以外）

• verb=1 : 優勝チームを 0 とした 0 から n − 1 までの番号付けのリスト（n チームのとき），その番
号付けによる（基底の順序に従った優勝決定戦を除く）n − 2 試合のリスト，（n − 1 個の）基底のリスト（cf. midKZ()）, 基底の順序に従った n − 1 試合のリスト
優勝決定戦を含めるときは，verb=1+2 とする（n − 1 試合）．
• iand(verb,2) : 優勝決定戦を加えたリスト• iand(verb,4) : グループの区間表現を展開したリスト• iand(verb,8) : 上と同じだが，戻り値の 2 番目は優勝者の参加する試合をより後に並べたもの• iand(verb,16) : 戻り値の 2 番目は優勝者の参加する試合の順序を逆に並べたもの• verb=2+8+16 : 戻り値の 2 番目は実際に試合が可能な順序に並べたもの[0] for(T=U=os_md.symtournament(4|to="T");T!=[];T=cdr(T))
os_md.xytournament(car(T),0|shift=1,top=0,dviout=1);[1] os_md.xytournament(U[1],0|verb=-1);[[0,1],[2,3],[0,3]][2] os_md.xytournament(U[1],0|verb=-2);[4254] R=os_md.xytournament(U[1],0|verb=-2);[[[[0,0],0],[[1,1],0]],[[[2,2],0],[[3,3],0]],[[[0,1],1],[[2,3],1]]][3] os_md.xytournament(U[1],0|shift=1,dviout=1);[[[[0,0],0],[[1,1],0]],[[[0,1],1],[[2,2],0]],[[[0,2],2],[[3,3],0]]][4] os_md.xytournament("((**)(**))",0|winner=0,teams=[2,3,0,1],dviout=1);[5] os_md.xytournament("((**)(**))",0|winner=[0,[[1,2]]],teams=[2,3,0,1],
dviout=1);[6] os_md.xytournament(U[1],0|winner=3,verb=-3);[[ 2 3 0 1 ],[[[[2,2],0],[[3,3],0],-2],[[[0,1],1],[[2,3],1],2]],[ [] [[[[0,0],0],[[1,1],0],1]] ]][7] os_md.xytournament(U[1],0|winner=3,verb=1);[[2,3,0,1],[[0,1],[2,3]],[[1],[2,3],[2]],[[0,1],[0,3],[2,3]]][8] os_md.xytournament(U[1],0|winner=3,verb=3);[[2,3,0,1],[[0,1],[0,3],[2,3]],[[1],[2,3],[2]],[[0,1],[0,3],[2,3]]][9] os_md.xytournament(U[1],0|winner=3,verb=7);[[2,3,0,1],[[0,1],[0,1,2,3],[2,3]],[[1],[2,3],[2]],[[0,1],[0,1,2,3],[2,3]]][10] T="(((**)(**))*)"$[11] os_md.xytournament(T,0|verb=1,winner=5);[[1,2,3,4,0],[[1,4],[3,4],[1,2]],[[1,2,3,4],[1,2],[3],[1]],[[0,4],[1,4],[3,4],[1,2]]][12] os_md.xytournament(T,0|verb=7,winner=5);[[1,2,3,4,0],[[0,1,2,3,4],[1,2,3,4],[3,4],[1,2]],[[1,2,3,4],[1,2],[3],[1]],[[0,1,2,3,4],[1,2,3,4],[3,4],[1,2]]][13] os_md.xytournament(T,0|verb=2+8+16,winner=5);[[1,2,3,4,0],[[1,2],[3,4],[1,4],[0,4]],[[1,2,3,4],[1,2],[3],[1]],[[0,4],[1,4],[3,4],[1,2]]][14] os_md.xytournament(T,0|dviout=1,winner=5,teams=[1,2,3,4,0]);[15] os_md.xytournament(T,0|dviout=1,winner=5,teams=[1,2,3,4,0],rev=1);[16] os_md.xytournament(T,0|dviout=1,winner=4,teams=[2,3,1,0,4],win=1);317

0 1 2 3

1 2 3 4 0

0 1 2 3

1 2 3 4 0

1 2 3 42 3 0 12 3 0 12 3 1 0 4425. ptconvex([p1 , p2 , . . .]|opt=1):: すべての点 p1 , p2 , . . . の凸包，あるいはすべての点を繋ぐ多角形を返す
複数の点の凸包となる多角形の頂点の座標のリストが返される．
• 点の個数が N のとき，N 個の座標の qsort() と最悪 3N 回程度の数の大小比較で完了するアルゴリズム．
筆者が高校生のとき，雑誌「大学への数学」の学力コンテストのある問題の解答として提出した中で使った 2 つのアルゴリズムのうちの一つ（1966 年）．Graham が 1972 年に発表し，グラハムス
キャンとして知られている（筆者は最近知った）．偏角の大小を使うが，ここでは逆三角関数や平方根は使わずに darg() を使って，有理計算で済ませている．もう一つは「ギフト包装法」と呼ばれているようです．
• 最初の点は座標の辞書式順序が最小の頂点に対応し，反時計回りの順に多角形の周を廻るときの多角形の頂点の座標のリストを順に返す（重複点や辺上の頂点は省いて返す）．
• pi は，3 成分以上あってもよい（点の色，などの情報）．最初の 2 成分を (x, y) 座標とみなす．
• opt=1 : すべての点を結ぶ閉じた交わりのない多角形を返す．
多角形の頂点はいずれかの点で，辺上に点があることも許す．また，同一の点があっても省かな
い．すなわち，戻り値 [Q1 , . . . , Qn ] は引数の並べ替えで，Q1 , Q2 , . . . , Qn , Q1 と折れ線でつなぐと多角形になる.

[0] P1=[0,0]$P2=[2,0]$P3=[2,2]$P4=[0,2]$P5=[1,1]$P6=[1,0]$[1] os_md.ptconvex([P1,P4,P3,P2,P5,P6,P4,P1]);[[0,0],[2,0],[2,2],[0,2]][2] os_md.ptconvex([P1,P4,P3,P2,P5,P6,P4,P1]|opt=1);[[0,0],[0,0],[1,0],[2,0],[1,1],[2,2],[0,2],[0,2]][3] P1=[2,0,"a"]$P2=[1,1,"b"]$P3=[2,2,"c"]$P4=[0,0,"d"]$[4] os_md.ptconvex([P1,P2,P3,P4]);[[0,0,d],[2,0,a],[2,2,c]][5] os_md.ptconvex([P1,P2,P3,P4]|opt=1);[[0,0,d],[2,0,a],[1,1,b],[2,2,c]]以下では，ランダムに点を配置し，その点の凸包の多角形を描き，多角形内部の点で同じことを繰り返して図形を得た．

[6] for(L=[],I=0;I<50;I++) L=cons([random(),random()],L);[7] for(R=[],TL=L;TL!=[];) {R=cons(P=os_md.ptconvex(TL),R);
TL=os_md.lsort(TL,P,"setminus"); }[8] for(S="",TR=R;TR!=[];TR=cdr(TR))
S+=os_md.xylines(car(TR)|close=1,scale=[10/(2^32),6/(2^32)]);[9] os_md.xyproc(S|dviout=1);318

426. ptwindow(ℓ,[x1 ,x2 ],[y1 ,y2 ]|scale=t):: 平面座標 (x, y) のリストで x1 ≤ x ≤ x2 ，y1 ≤ y ≤ y2 を満たさないものを 0 に変える
• scale=t : リストで与えられた平面座標は t 倍されているとみなす．
427. ptbbox([[x1 ,y1 ,. . .],[x2 ,y2 ,. . .],. . .]|box=b)
(2)
(2)
(1)
(1)
(1)
(1)
ptbbox([[[xmin ,xmax ],[ymin ,ymax ],. . .],[[xmin ,xmaxS ],. . .],. . .]|box=1):: 座標 (x, y, . . .) や箱のリストを囲む箱 [[xmin ,xmax ],[ymin ,ymax ],. . .] を返す• 各座標はリストでもベクトルでもよい．xybezier() の引数の形式でもよい．
• box=1 を指定すると，箱のリストを与えて，それらを囲む箱を返す．
• box=b として箱 b を指定すると，ptbbox([ptbbox(ℓ),b]|box=1) と解釈される．
[0] os_md.ptbbox([[1,2],[3,4],[0,8],[4,1]]);[[0,4],[1,8]][1] os_md.ptbbox([[1,2],[3,4],[0,8],[4,1],-1]);[[0,4],[1,8]][2] os_md.ptbbox([[[1,2],[3,4]],[[0,8],[1,3]]]|box=1);[[0,8],[1,4]][3] os_md.ptbbox([[1,2],[3,4],[0,8],[4,1]]|box=[[1,5],[0,7]]);[[0,5],[0,8]]
(1)

(1)

(1)

(2)

(1)

(2)

(2)

(2)

428. iscombox([[xmin ,xmax ],[ymin ,ymax ],. . .], [[xmin ,xmax ],[ymin ,ymax ],. . .]):: 2 つの箱（区間の直積）の共通部分の有無を返す[0] S=[[1,2],[4,6]]$[1] os_md.iscombox(S,[[1.5,3],[4,7]]);1[2] os_md.iscombox(S,[[3,3],[4,6]]);0429. lninbox([p1 ,p2 ],[[xmin ,xmax ],[ymin ,ymax ]]|in=1):: 平面内の 2 点 p1 と p2 を結ぶ直線（または線分）の箱内の部分（2 点を結ぶ線分）を返す• 戻り値は，線分を表す両端点の座標のリスト．
• in=1 : これを指定すると，2 点を結ぶ線分となる．
2 点 (0.2, 0.3) と (−1, 3) とを結ぶ直線（または線分）の 0 ≤ x ≤ 1, 0 ≤ y ≤ 1 内の部分は，[0] os_md.lninbox([[0.2,0.3],[-1,3]],[[0,1],[0,1]]);[[0.333333,0],[0,0.75]][1] os_md.lninbox([[0.2,0.3],[-1,3]],[[0,1],[0,1]]|in=1);319

[[0.2,0.3],[0,0.75]]
430. scale(ℓ|scale=[c1 , . . .],f=f ,shift=[s1 ,s2 ],TeX=1,mes=[t,[a1 ,b1 ,w1 ], . . .],line=[a,b],
mes2=[[x1 ,[t1,0 ,t1,1 ,c1 ],t1 ,s1 ],. . .],prec=0,col=s,inv=1,vert=1):: 目盛や対数（函数）尺の作成[a,b,w] は a から b までの等幅 w の目盛を表す. これらの目盛を表すリスト（3 つの数字のリスト）ℓi,j に対し，ℓ =[[ℓ1,1 ,ℓ1,2 , . . .],[ℓ1,1 ,ℓ1,2 , . . .], . . .] が一般的な目盛の指定で，ℓ1,ν が第 1 段階，ℓ2,ν
が第 2 段階の目盛，というように表す（より多段階も可能）.
なお，1 段階の目盛のみの時は単純に [a1 ,a2 ,a3 , . . .] と表してもよい．
scale(ℓ) は，目盛リスト m =[[m1,1 ,m1,2 , . . .],[m2,1 ,m2,2 , . . .], . . .] を返す. ここで，後ろの段階に現れる目盛は省かれる．
なお，対数尺の目盛のデフォルトは 3 段階で[[1,2,1/50],[2,5,1/20],[5,10,1/10]],[[1,5,1/10],[5,10,1/2]],[[1,5,1/2],[5,10,1]]]
であるが，prec=0 を指定すると，半分程度粗くなる．
· ℓ = 0 または 1 : log10 x (1 ≤ x ≤ 10) に対する目盛（C, D 尺に対応）を生成する．
· ℓ = 2 : 12 log10 x (1 ≤ x ≤ 100) に対する目盛 (A, B 尺に対応）を生成する．
· ℓ = 3 : 31 log10 x (1 ≤ x ≤ 1000) に対する目盛 (K 尺に対応）を生成する．
· ℓ = 4 : frac(0.5 + log10 x) (1 ≤ x ≤ 10) に対する目盛 (CF, DF 尺に対応）を生成する．
· ℓ = 5 : frac(log10 (πx)) (1 ≤ x ≤ 10) に対する目盛 (CF, DF 尺に対応）を生成する．
· ℓ = 6 : log10 (10 sin x) (5◦ 450 ≤ x ≤ 90◦ ) に対する目盛 (S 尺に対応）を生成する．
· ℓ = 7 : log10 (10 tan x) (5◦ 400 ≤ x ≤ 45◦ ) に対する目盛 (T1 尺に対応）を生成する．
· ℓ = 8 : log10 tan x (45◦ ≤ x ≤ 84◦ 100 ) に対する目盛 (T2 尺に対応）を生成する．
0◦◦0· ℓ = 9 : log10 πx
18 (35 ≤ x ≤ 5 45 ) に対する目盛 (ST 尺に対応）を生成する．
· ℓ = 10 : log10 (1000 log x) (1.001 ≤ x ≤ 1.0105) 対する目盛 (LL0 尺に対応）を生成する．
· ℓ = 11 : log10 (100 log x) (1.01 ≤ x ≤ 1.105) 対する目盛 (LL1 尺に対応）を生成する．
· ℓ = 12 : log10 (10 log x) (1.105 ≤ x ≤ 2.72) に対する目盛 (LL2 尺に対応）を生成する．
· ℓ = 13 : log10 (log x) (2.72 ≤ x ≤ 22000) に対する目盛 (LL3 尺に対応）を生成する．
· ℓ = 14 : log10 (−1000 log x) (0.99 ≤ x ≤ 0.999) 対する目盛 (LL00 尺に対応）を生成する．
· ℓ = 15 : log10 (−100 log x) (0.905 ≤ x ≤ 0.99) 対する目盛 (LL01 尺に対応）を生成する．
· ℓ = 16 : log10 (−10 log x) (0.368 ≤ x ≤ 0.905) に対する目盛 (LL02 尺に対応）を生成する．
· ℓ = 17 : log10 (− log x) (0.000045 ≤ x ≤ 0.368) に対する目盛 (LL03 尺に対応）を生成する．
· CI，DI の目盛生成は，ℓ = 0 で inv=1 を指定するか，(c1 , s1 ) を (−c1 , s1 + c1 ) に変える．
· CIF, DIF 尺の目盛り生成は，ℓ = 4 で inv=1 を指定する．
· 同様にして，inv=1 の指定で SI, TI1 , TI2 尺などを作ることができる．
· ℓ は 上 の 数 字 の 代 わ り に ，文 字 列 "C", "D", "A"", "B", "K", "CF", "DF", "CF’","DF’", "S", "T1", "T2", "ST", "LL0", "LL1", "LL2", "LL3", "LL01", "LL02", "ll03","LL04", "CI", "DI", "CIF", "CIF’", "DIF", "DIF’", "SI", "TI1", "TI2", "STI" のいず
れかで指定してもよい．
なお，"CF’", "DF’"は ℓ = 5 を意味する．
• scale=c : 目 盛 の 位 置 [[cf (m1,1 ) + s1 ,cf (m1,2 ) + s1 , . . .],[cf (m2,1 ) + s1 , cf (m2,2 ) +s1 , . . .], . . .] を返す．ここで f (x) のデフォルトは自然対数 log x/ log 10．
f (x) はリスト形式函数の形で指定してもよい．
• scale=[c1 ,c2 , . . .] : 以下の目盛描画用パラメータを返す（xylines() の引数）．
なお，shift=[s1 ,s2 ] によって描画の相対位置を指定する．ただし s1 = 0 のときは shift=s2 と指定してもよい．

[[c1 f (m1,1 )+s1 ,s2 ],[c1 f (m1,1 )+s1 ,s2 +c2 ],0, [c1 f (m1,2 )+s1 ,s2 ],[c1 f (m1,2 )+s1 ,s2 +c2 ],0, . . .], [c1 f (m2,1 ) + s1 ,s2 ],[c1 f (m2,1 ) + s1 ,s2 +c3 ],0, [c1 f (m2,2 ) + s1 ,s2 ],[c1 f (m2,2 ) +s1 ,s2 +c3 ],0, . . .], . . .]c1 , c2 , . . . は負の値も設定可能．なお√c3 以降がないときは，cn のデフォルトは (n − 1)c2 .
• inv=1 : 0.5 の位置（C 尺でいえば 10 の目盛の位置）で左右対称に折り返した目盛を作成する．
320

• TeX=1 : 目盛描画の TEX のソースを返す（戻り値で xyproc() を呼ぶ）．
– 目盛線の色づけなどを行うときは，col="red"などとオプションで指定する（TikZ を用いる）．
– mes=[t,[a1 ,b1 ,w1 ], . . .]，あるいは mes=[t,c1 ,c2 ,c3 , . . .] により，それ以降で指定した目盛の数字を，高さ t の位置に描く．なお，目盛の数字の色付けなどを指定するときは，t を[t,"red"] などと，オプション文字列を指定する．
– ℓ を数字または文字列で指定したときに mes の 2 項目以降を省略すると，デフォルトの目盛の数字が描かれる．

– mes2=[[x1 ,[t1,0 ,t1,1 ,c1 ],t1 ,s1 ],. . .], x1 に対応する場所の高さ t1 の位置に s1 を書く．s1
は"$\\pi$"や ["red","$\\pi$"] などが可能．また高さ t1,0 から t1,1 までの目盛線を描く．
c1 は色付けなどのオプション文字列．目盛線を描かないときは，[t1,0 ,t1,1 ,c1 ] の部分を 0 と指定する．
mes=を指定していて，t1,1 が mes=の t と等しいときは t1,1 の項を省略してよい．
– vert=1 によって縦方向の尺とする．上方向および右方向が正の方向．
– 文字を小さくするには，\begin{tikzpicture} の前に \scriptsize や \tiny などを指定しておけばよい．
– line=[a,b] によって基準線を a から b まで描く．

[0] S=os_md.scale([[[0,5,1/10]],[[0,5,1/2]],[[0,5,1]]]|scale=[1,0.15],f=x,
TeX=1,mes=[0.7,[0,5,1]],line=[0,5])$[1] S=os_md.scale([[[0,5,1/10]],[[0,5,1/2]],[[0,5,1]]]|scale=[-1,-0.15],f=5-x,
TeX=1,mes=[-0.7,[0,5,1]],line=[0,-5]);[2] S=os_md.scale([[[0,5,1/10]],[[0,5,1/2]],[[0,5,1]]]|scale=[-0.5,-0.15],f=x,
TeX=1,mes=[-0.7,[0,5,1]],line=[0,-2.5],vert=1)$[3] S=os_md.scale([[[0,5,1/10]],[[0,5,1/2]],[[0,5,1]]]|scale=[-0.5,-0.15],f=5-x,
TeX=1,mes=[-0.7,[0,5,1]],line=[0,-2.5],vert=1)$[4] S=os_md.scale(0|scale=[14,0.15],TeX=1,mes=[0.7,[1,2,1/2],[2,10,1]])$[5] S+=os_md.scale(0|scale=[14,-0.15],TeX=1,mes=[[-0.7,"red"],[1,2,1/2],[2,10,1]],line=[0,14],inv=1)$[6] os_md.xyproc(S|dviout=1)$[7] S=os_md.scale(4|scale=[14,0.15],prec=0,TeX=1,mes=[0.7,[1,2,1/2],[2,9.5,1]],line=[0,14])$[8] S=os_md.scale(2|scale=[14,0.15],prec=0,TeX=1,mes=[0.7,1,2,5,10,20,50,100],
line=[0,14])$[9] S=os_md.scale(3|scale=[14,0.15],prec=0,TeX=1,mes=[0.7,1,2,5,10,20,50,100,200,
500,1000],line=[0,14])$[10] S=os_md.scale("C"|scale=[14,0.1],TeX=1,mes=[0.5],line=[0,14],
mes2=[3.1416,[0.15,0.3,"red"],0.5,["red","$\\pi$"]])$

0

1

2

3

4

5
0

1

321

2

3

4

5

5
4
3
2
1
0

5
4
3
2
1
0

1

10

1.5

9

8

7

4

1

2

6

5

5

6

1

5

8

9

1.5

1

20

7

9

10

1

2

20

3

50

100

4

8

1.5

1.5

50

3π

2

6

2

10

10

5

3

5

2

4

4
7

2

1

3

200

5

100

500

6

7

8

1000

9

10

431. tobezier(ℓ|inv=[a,b,t],div=k):: 点のリスト ℓ で定まる Bézier 曲線のパラメータ表示とその逆変換と分割• ℓ = [p0 , . . . , pn ] で，pj が座標を表すリストまたはベクトルのとき，これらによって定まる Bézier
曲線（パラメータは t ∈ [0, 1]）を，t の n 次多項式を成分とするベクトル）を返す．
Bézier 曲線とはγ(t) = γ(p1 , . . . , pn ; t) =

n  
X
n
j=0

j

tj (1 − t)n−j pj(t ∈ [0, 1]),

 
n
n!
=
j
j!(n − j)!

で定まる曲線である（このとき n 次 Bézier 曲線という）．
γ(p0 , p1 ; t) = (1 − t)p0 + tp1 は線分 p0 p1 を t : (1 − t) に内分する点で，1 次 Bézier 曲線は p0と p1 を結ぶ線分となる．また平面内の 2 次 Bézier 曲線は，x 座標と y 座標が t の 2 次（以下）の多項式となるが，平面を回転すると x 座標は t の 1 次式にできる．よって，2 次 Bézier 曲線は放物線の一部（または線分）を回転したものとなる．

一方， nj = n−1+ n−1
jj−1 であるから







n j
n−j
j−1
= (1 − t) · n−1
tj (1 − t)n−1−j + t · n−1(1 − t)n−1 ,j t (1 − t)
j
j−1 t

n−1
−1



=

n−1
n



=0

となり，pj にこれを掛けて j = 0, . . . , n について加えるとγ(p0 , . . . , tn : t) = γ γ(p0 , . . . , pn−1 ; t), γ(p1 , . . . , pn ; t); t

がわかる．これを遡れば，元の点 {p0 , . . . , pn } の t : (1 − t) の内分点を取ることを繰り返すことにより γ(p0 , . . . , pn : t) が得られる．
たとえば 3 次 (cubic) Bézier 曲線は

γ(p0 , p1 , p2 , p3 ; t) = γ γ(p0 , p1 , p2 ; t), γ(p1 , p2 , p3 ; t); t = γ γ γ(p0 , p1 ; t), γ(p1 , p2 ; t); t , γ γ(p1 , p2 ; t), γ(p2 , p3 ; t), t ; tとなる．よって p0 p1 , p1 p2 , p3 p4 の t : (1 − t) の内分点を順に q0 , q1 , q2 とし，さらに q0 q1 と q1 q2

322

の t : (1 − t) の内分点を r0 , r1 とすると r0 r1 の t : (1 − t) の内分点が γ(p0 , p1 , p2 , p3 ; t) となる．

p1
×:

t

q0
•/

r0
•

•
γ(t)

t

q1
•
r1
•

p2
×V

t

• q2

•
p0
•
p3
• inv=[a,b] : パラメータが t ∈ [a, b] の部分の Bézier 曲線に対応する座標（ベクトルで表す）のリストを返す．

• div=1 : Bézier 曲線を 2 分割して，それらを定義する座標の組のリストを返す（3 次のときは，ベ．3 次のみ高クトルの 4 個のリストの 2 つのリストで，前者が [0, 12 ] の部分，後者が [ 21 , 1] の部分）
速化対応．

• div=k : 2 ≤ k ≤ 256 のとき，Bézier 曲線を k 分割して，それらを定義する座標の組のリスト k 個のリストを返す.
• inv=[a,b] : ℓ が Bézier 曲線のとき，それを t ∈ [a, b] をパラメータとする Bézier 曲線とみなして，それを定義する点の座標（ベクトルで表す）のリストで返す．パラメータが t でないときは，
それを inv=[a,b,t] のようにして明示することができる．
• inv=1 : inv=[0,1] とみなす．tobezier( ) の逆変換となる．
[0] S=os_md.tobezier([[p0,q0],[p1,q1],[p2,q2],[p3,q3]]);[ (-p0+3*p1-3*p2+p3)*t^3+(3*p0-6*p1+3*p2)*t^2+(-3*p0+3*p1)*t+p0(-q0+3*q1-3*q2+q3)*t^3+(3*q0-6*q1+3*q2)*t^2+(-3*q0+3*q1)*t+q0 ][1] T=os_md.tobezier(@@|inv=1);[[ p0 q0 ],[ p1 q1 ],[ p2 q2 ],[ p3 q3 ]][2] os_md.tobezier(T|inv=[0,1/2]);/* Bezier 曲線の 2 分割の前半 */[[ p0 q0 ],[ 1/2*p0+1/2*p1 1/2*q0+1/2*q1 ],[ 1/4*p0+1/2*p1+1/4*p2 1/4*q0+1/2*q1+1/4*q2 ],[ 1/8*p0+3/8*p1+3/8*p2+1/8*p3 1/8*q0+3/8*q1+3/8*q2+1/8*q3 ]]432. lbezier(l|inv=t):: 区分 Bézier 曲線のデータ変換
xybezier() のデータ形式（座標と，整数 0, 1, −1 のリスト）を，区分 Bézier 曲線を与える座標のリストを成分とするリストに変換する．
• inv=1 : 上の変換の逆変換を行う．区分 Bézier 曲線をつなげる指定 1 や，閉曲線を描く指定 −1
を可能な限り使う．
• inv=2 : 上と同様だが，閉曲線を描く指定を使わない．
• inv=3 : 上と同様だが，閉曲線を描く指定は，全体として一つの閉曲線となる場合のみ使う．

[0] P=os_md.xyoval([1,3.5],2.5,2|opt=0); /* 中心 (1,3.5) 半経 2.5x5 の楕円 */[[3.5,3.5],[3.5,7.349],[1.41667,9.75463],[-0.25,7.83013],1,[-1.91667,5.90563],[-1.91667,1.09437],[-0.25,-0.830127],1,[1.41667,-2.75463],[3.5,-0.349002],-1][1] Q=os_md.lbezier(P);[[[3.5,3.5],[3.5,7.349],[1.41667,9.75463],[-0.25,7.83013]],[[-0.25,7.83013],[-1.91667,5.90563],[-1.91667,1.09437],[-0.25,-0.830127]],[[-0.25,-0.830127],[1.41667,-2.75463],[3.5,-0.349002],[3.5,3.5]]]323

[2] os_md.lbezier(Q|inv=1);[[3.5,3.5],[3.5,7.349],[1.41667,9.75463],[-0.25,7.83013],1,[-1.91667,5.90563],[-1.91667,1.09437],[-0.25,-0.830127],1,[1.41667,-2.75463],[3.5,-0.349002],-1]
433. velbezier(f ,[a,b,t]):: Bézier 曲線の最大速度ベクトル• t ∈ [a, b] をパラメータとする Bézier 曲線 f の成分毎の最大速度をリストで返す．
• 2 番目の引数が 0 のときは，デフォルトの [0,1,t] を意味する．
• パラメータが t のときは，2 番目の引数を [a,b] としてよい．
[0] B=os_md.tobezier([[0,0],[1.2,0.7],[2.1,0.5],[3,0]]);[ 0.3*t^3-0.9*t^2+3.6*t 0.6*t^3-2.7*t^2+2.1*t ];[1] os_md.velbezier(B,0);[3.6,2.1][2] os_md.velbezier(B,[0.5,1]);[2.925,1.5]
434. ptbezier(l,[n, t]) ptbezier(l,s):: （複合）Bézier 曲線上の点と速度ベクトルを求める• l は，xybezier() の引数で与える（複合）Bézier 曲線のデータ，またはそれを lbezier() で変換した形• n 番目の Bézier 曲線の t = x の点の座標と速度ベクトルの組を返す．
• n = 0 は最初の Bézier 曲線，n = 1 は 2 番目，n = −1 は最後の，n = −2 は最後から 2 番目のBézier 曲線を表す．
• 2 番目の引数 s が非負実数の時は，n は s の整数部分 +1 を，t は s の小数部分を表す．
ただし x が Bézier 曲線の個数より大きいときは，（複合）Bézier 曲線の終点を表す．
• 2 番目の引数 x が −1 のときは，Bézier 曲線の個数を返す.
[0] R=os_md.xyang(2,[1,1],0,0|opt=0)$ /* (1,1) 中心の半径 2 の円のデータ */[1] os_md.ptbezier(R,-1);
3/* 3 つのベジェ曲線からなる , 0 <= s <= 3 */[2] S=os_md.ptbezier(R,0.5);/* s=0.5 での座標と速度ベクトル*/[[ 2 2.73205 ],[-3.5,2.02073]][3] T=os_md.ladd(S[0],S[1],1/3);/* 速度ベクトルの頂点（長さ 1/3） */[0.833333,3.40563][4] R1=os_md.xyang(0.3,T,S[0],2|ar=1,opt=0)$/* s=0.5 での速度ベクトルの描画 */[5] U=os_md.ptbezier(R,2)$ /* s=2 での座標と速度ベクトル */[6] V=[U[0][0]-U[1][0],U[0][1]-U[1][1]]$[7] R2=os_md.xyang(0.3,U[0],V,3|opt=0)$/* s=1.5 に曲線上の矢印の描画*/[8] Out=os_md.ptaffine("union",[R,R1,R2])$[9] os_md.dviout(os_md.xyproc(Out));324435. areabezier(l|rev=1,pt=[p1 ,p2 , . . .],para=1,prec=v,int=k,exp=c,Acc=1,cpx=1):: Bézier 曲線を用いた領域の面積・数値積分の計算• l が [f ,n,[t1 ,t2 ]] という xygraph() の最初の 3 つの引数であって，f が変数 x の函数のときは,RtBézier 曲線で近似することによって積分 t12 f (x) dx を近似計算する．
– int=1 を指定すると，|n| 分割して台形公式で近似計算する．
– int=2 を指定すると，|n| 分割してシンプソンの公式で近似計算する．このとき，n が奇数な
ら |n| + 1 分割する。
– cpx=1 : 非積分関数が複素数値函数であるときに指定する．
– 変数が x でなくて，たとえば t のときは，[t,t1 ,t2 ] と明示する．
– 等分割の個数は |n| となる（n = 0 は，32 と解釈される）．
– 積分区間外まで函数が定義されているときは，n を負の数にする（n が分割の数）．
– t1 ="-infty"（""でも可）とすると a = −∞ と, t2 ="infty"（""でも可）とすると b = ∞と解釈され，無限区間での積分となる．
無限区間での積分のとき exp=c の指定が有効（cf. cmpf()）．
– 無限区間での積分において無限遠で o(|x|−2 )（有理函数のときは O(|x|−2 ) を満たさないとき）は誤差が大きくなるので，prec=16 または exp=1 などと指定すると改善される．
• 函数に滑らかでない点や不連続点がある場合は，prec=16 などと指定すると計算誤差が少なくなる．
• f がリストで f =[f1 ,f2 ] というパラメータ表示の曲線のときは，3 番目の要素が [t,t1 ,t2 ] ならRt
ば，その曲線を Bézier 曲線で近似した曲線に沿って，積分 t12 f2 (t) df1 (t) を計算する．
特にこの Bézier 曲線が閉曲線のときは，その曲線で囲まれた領域の面積の計算となる．このとき，時計回りかどうかで正負が決まり，反時計回りに 1 回囲まれた部分の面積は −1 倍される．
• Acc=1 を指定すると pari() による高精度計算を行う.
ただし ctrl("bigfloat",1) および setprec(prec) による精度の設定が必要．また，有理関数
でなくて sin(x) などの初等関数を扱う場合は注意が必要で，不定元が大量に生成される可能性がある（myeval() の項を参照．ord() で分かる）．
• 以上の時のオプションパラメータは xygraph() のときと同じ意味に解釈される．
• Rl が lbezier() の引数となる Bézier 曲線 C のデータ（2 形式のいずれでも可）ならば, 線積分
ydx の値を返す．
C
閉曲線のデータであったなら，その曲線で囲まれた領域の面積となる.

[0] os_md.areabezier([x^3,-4,[0,2]]);4.01564[1] os_md.areabezier([x^3,-8,[0,2]]);4.00105[2] os_md.areabezier([x^3,-16,[0,2]]);4.00007[3] os_md.areabezier([x^3,-32,[0,2]]);4[4] os_md.areabezier([sin(x),-4,[0,@pi]]);1.98989325

[5] os_md.areabezier([sin(x),-8,[0,@pi]]);1.99935[6] os_md.areabezier([sin(x),-16,[0,@pi]]);1.99996[7] os_md.areabezier([sin(x),-32,[0,@pi]]);2[8] os_md.areabezier([[cos(x),-sin(x)],-16,[0,2*@pi]]);3.14159[9] os_md.areabezier([exp(-x),16,[0,"infty"]]);
0.999982[10] tstart$os_md.areabezier([exp(-x),64,[0,"infty"]]);tstop$[11] 1[12] 0.0156sec(0.016sec)[13] os_md.areabezier([exp(-x^2),32,["-infty","infty"]]);
1.77268[14] tstart$R=os_md.areabezier([exp(-x^2),512,["",""]]);tstop$[15] 1.77245[16] 0.0312sec + gc : 0.0312sec(0.063sec)[17] V=eval(@pi^(1/2));
1.77245385090551602720251866962[18] R-V;
0.0000000061022552223961856743[19] os_md.areabezier([x^(-3/2),0,[1,""]]);
1.90184[20] os_md.areabezier([x^(-3/2),0,[1,""]]|prec=16);
1.99991[21] os_md.areabezier([x^(-3/2),0,[1,""]]|exp=1);2.00008[22] os_md.areabezier([1/(1+x^2),0,["",""]]);
3.14159[23] os_md.areabezier([1/(1+x^2),0,["",""]])-eval(@pi);
0.00000040239333897167800513[24] os_md.areabezier([1/(1+x^2),1000,["",""]])-eval(@pi);-3.3363329451 E-13
[25] tstart$os_md.areabezier([1/(1+x^2),5000,["",""]])-eval(@pi);tstop;[26] -5.6638721488 E-16
[27] 0.2964sec + gc : 0.2496sec(0.546sec)[28] os_md.areabezier([1/(1+x^2),0,["",""]]|exp=1);
3.14151[29] os_md.areabezier([1/(1+x^2),-10,["",""]]|exp=1);
3.1417[30] tstart$os_md.areabezier([1/(1+x^2),10000,["",""]]|exp=1)-eval(@pi);
tstop$[31] -9.07164967805 E-14
326

[32] 0.8268sec + gc : 0.4056sec(1.248sec)[33] V=eval(@pi*2^(-1/2));
2.22144146907918312331[34] os_md.areabezier([1/(1+x^4),0,["",""]]);
2.22151[35] os_md.areabezier([1/(1+x^4),0,["",""]]|exp=1);2.22192[36] os_md.areabezier([1/(1+x^4),10000,["",""]])-V;-8.6669820621 E-14
[37] os_md.areabezier([1/(1+x^4),10000,["",""]]|exp=1)-V;-4.6270379014 E-12
[38] os_md.areabezier([dsqrt(2)/(x^2+@i),0,["",""]]|cpx=1);(3.14247-3.1418*@i)[39] os_md.areabezier([dsqrt(2)/(x^2+@i),1000,["",""]]|cpx=1);(3.14159-3.14159*@i)[40] ctrl("bigfloat",1)$setprec(30);19[41] F=[cos(x),-sin(x)]$[42] tstart$os_md.areabezier([F,-1536,[0,2*@pi]])/eval(@pi)-1;tstop$[43] -3.17671236538252799164 E-17
[44] 0.2496sec + gc : 0.0936sec(0.343sec)[45] tstart$os_md.areabezier([F,-1536,[0,2*@pi]]|Acc=1)/eval(@pi)-1;tstop$[46] 8.71510564319365765590 E-20
[47] 0.4212sec + gc : 0.0624sec(0.5sec)

Bézier 曲線を使った数値積分の相対誤差
非積分関数(cos θ, sin θ)

積分範囲

0 ≤ θ ≤ 2π

指定(−n, −)

16 分割
6.8 × 10

−8
−4

32 分割
1.1 × 10−9

3.1 × 10−596 分割
1.5 × 10−12

3.8 × 10−7384 分割1536 分割

3.2 × 10−17

8.7 × 10−20

1.5 × 10−9

5.8 × 10−12

Cardioid−π ≤ θ ≤ π(n, −)

5.4 × 10x sin x0≤x≤π(−n, −)

2.9 × 10−4

1.8 × 10−6

2.2 × 10−8

8.7 × 10−11

3.4 × 10−13

−6

−8

−9

−12

1.7 × 10−14

sin x
x
1
x2 +1
−x2

0<x≤π

(−n, −)

1.5 × 10−∞ < x < ∞(n, −)

1.3 × 10−5

1.3 × 10−7

8.5 × 10−10

4.7 × 10−12

2.1 × 10−14−∞ < x < ∞(n, −)

7.1 × 10

−4

−4

−6

−8

4.3 × 10−11

x

−3
2

1≤x<∞

(n, −)

7.1 × 10−2

4.9 × 10−2

2.8 × 10−2

1.4 × 10−2

7.0 × 10−3

x

−3
2

1≤x<∞

(n, −)

−6

−5

−5

−5

6.9 × 10−6

x

−3
2

1≤x<∞

(n, 1)

6.6 × 10−9

2.6 × 10−11e16

5.9 × 10

3.0 × 10−4

9.5 × 10
1.3 × 10
4.5 × 10

3.8 × 10−5

1.2 × 10
2.6 × 10
2.8 × 10

1.4 × 10−6

4.6 × 10
1.1 × 10
1.4 × 10

• 上表の最初は円の面積の数値計算例で，2 番目の Cardioid は (1 + cos θ) cos θ, (1 + cos θ) sin θでカージオイド曲線で囲まれた領域の面積の数値計算例である．

• n 分割による計算で，上表の指定の欄の ±n は areabezier() の引数の 2 番目を意味する．
• (n, −)16 は prec=16 のオプションの指定を意味する．
• (n, 1) は exp=1 のオプションを指定したことを意味する．
無限区間での積分では，よい近似には exp=c のオプションパラメータ c の指定が必要だが，最後の例（x → ∞ で o(x−2 ) とならない例）のみ標準的な指定をした以外は指定をしていない．
• 上において分割の数が大きくて最も時間がかかる場合の計算時間は，0.1 sec 程度である．
• sinx x の (0, π] での数値積分は以下のように行った．
[0] F=os_md.f2df(sin(x)/x)$327

[1] F=os_md.cutf(F,x,[[],[0,1],[]])$[2] os_md.areabezier([F,-32,[0,@pi]]);
1.85194
Z π
sin x
なお
dx = 1.8519370519824661706 · · ·x0/* x=0 のとき 1 となるように拡張 */1
f = x21+1

o

−5

8
7
6
5
4
3
2
1

−4

−3

−2

0

1

1

2

1

4

5

2

3

/

8
7
6
5
4
3
2
1

5

/

cmpf(f |exp=2)

0

1
8
7
6
5
4
3
2
1

cmpf(f )

0

4

8
7
6
5
4
3
2
1
1

3
x 2 +1

3

1

0

1

0

0

cmpf(f |exp=1)

8
7
6
5
4
3
2
1

cmpf(f )

f=

−1

1

cmpf(f |exp=1)01上のグラフは，次のようにして得られる TEX のソースで描かれている：

os_md.xygraph(1/(1+x^2),-32,[-6,6],0,[0,1.5]|ax=[0,0,1,1,1],scale=[1.25,2]);
R=os_md.cmpf([1/(1+x^2),["",""]]|exp=1);
os_md.xygraph(R,-64,[0,1],0,[0,8]|ax=[0,0,1,1,1],scale=[5,0.5],prec=6);
scale=の指定で 1.25 × 2 = 5 × 0.5 であるから，図の面積が保たれることに注意．
436. ptcombezier(ℓ1 ,ℓ2 ,m):: 点のリスト ℓ1 , ℓ2 で定まる 2 つの Bézier 曲線の交点を求める• ℓ1 , ℓ2 は，3 次 Bézier 曲線を想定している（それ以外でも可）• m は交点の正確さ（パラメータを 2m 分割する）．
m = 0 はデフォルトで，m = 20 を意味する．
• 交点は，対応する ℓ1 のパラメータ値，ℓ2 のパラメータ値，交点の座標の 3 つ組のリストで表され，交点の数だけのそれのリストを返す．

[0] L1=[[0,0],[1,1],[2,2],[3.0,3.0]]$[1] L2=[[3.0,0],[2,1],[1,2],[0,3.0]]$[2] os_md.ptcombezier(L1,L2,24);[[0.5,0.5,[1.5,1.5]]]328

437. ptcombz(b1 ,b2 ,m|red=t,prec=k):: 区分 Bézier 曲線 b1 , b2 の交点を求める• b1 , b2 は，xybezier() の引数の形のデータ，あるいは lbezier で変換された区分 Bézier 曲線を与える座標のリストのリストのいずれか．
• b2 = 0 のときは，b1 で与えられた曲線の自己交叉点を返す．ただし各区分 Bézier 曲線自身や隣り合った区分 Bézier 曲線の交点は除く．
• b1 と b2 のそれぞれ何番目の区分 Bézier 曲線かのリスト（最初を 0 番目と数える）を先頭に付加した ptcombezier() の戻り値をまとめてリストの成分としたリストを返す．
• m は交点の正確さ（パラメータを 2m 分割する）．m = 0 はデフォルトで，m = 20 を意味する．
• red=1 : ほぼ等しい座標の点が複数あるときは，そのうちの一つデータのみ返す．
• red=2 : 交点の座標のみ返す（ほぼ等しい座標の点は重複して表示しない）．
• prec=k : オプション red を指定したとき，x 座標および y 座標の差が曲線の幅（現れる座標の x
座標の最大値と最小値の差，および y 座標の最大値と最小値の差）の 1/2k 程度以下ならば，同じ点と見なす．デフォルトは k = 12.

[0] P=os_md.xyoval([0,0],1,1|opt=0)$/* 中心 (0,0) 半径 1 の円*/
[1] Q=os_md.xyoval([1,1],1.2,0.5|opt=0)$/* 中心 (1,1) 半経 1.2x0.6 の楕円 */[2] os_md.ptcombz(P,Q,0);[[[0,1],[0.853506,0.515474,[-0.199425,0.981241]]], /* 交点 (-0.200,0.981) */[[0,2],[0.188392,0.209443,[0.917957,0.400476]]]]/* 交点 (0.918,0.400) */[3] F=[sin(2*x),sin(3*x)]$[4] LS=os_md.xygraph(F,-24,[0,2*@pi],[-2,2],[-2,2]|opt=0)$/* リサージュ図形 */[5] tstart$os_md.sint(os_md.ptcombz(LT,0,0),4);tstop;[[[12,0],[0,0,[0,0]]],[[13,4],[0,1,[0.5,-0.7071]]],[[13,5],[0,0,[0.5,-0.7071]]],[[16,0],[1,1,[0.5,0.7071]]],[[16,1],[1,0,[0.5,0.7071]]],[[16,3],[0,1,[0.866,0]]],[[16,4],[0,0,[0.866,0]]],[[19,8],[1,0,[-0.866,0]]],[[19,10],[0,1,[-0.5,0.7071]]],[[19,11],[0,0,[-0.5,0.7071]]],[[20,8],[0,0,[-0.866,0]]],[[22,6],[1,1,[-0.5,-0.7071]]],[[22,7],[1,0,[-0.5,-0.7071]]]][6] 0.0312sec(0.047sec)[7] LT=os_md.xygraph(F,-96,[0,2*@pi],[-2,2],[-2,2]|opt=0)$[8] tstart$os_md.ptcombz(LT,0,0)$tstop;[9] [10] 0.2028sec + gc : 0.078sec(0.281sec)[11] os_md.sint(os_md.ptcombz(LS,0,0|red=1),4);[[[12,0],[0,0,[0,0]]],[[13,5],[0,0,[0.5,-0.7071]]],[[16,0],[1,1,[0.5,0.7071]]],[[16,4],[0,0,[0.866,0]]],[[19,10],[0,1,[-0.5,0.7071]]],[[20,8],[0,0,[-0.866,0]]],[[22,7],[1,0,[-0.5,-0.7071]]]][12] os_md.sint(os_md.ptcombz(LS,0,0|red=2),4);[[0,0],[0.5,-0.7071],[0.5,0.7071],[0.866,0],[-0.5,0.7071],[-0.866,0],[-0.5,-0.7071]]
3.2.11 Drawing curves and graphs
438. openGlib([w,h]|null=1):: グラフィックライブラリ（glib）のウインドウを開く• load("glib") が必要• w, h は横幅，縦幅の pixel サイズで，右方向と上方向が，それぞれ x 座標，y 座標の正方向と設定• null=1 を指定すると，（新たな）窓は開かない．

329

• 0 を引数とすると，窓の中身を消す．
• glib window(), glib putpixel(), glib line() などを参照．
439. trcolor(s):: 色を文字列からコードへ変換
色は，red, green, blue, yellow, cyan, magenta, black, white, gray が可能
デフォルトは黒の 0．
[0] os_md.trcolor("red");255
440. mcolor([c0 ,. . .,cm ],k|disc=1):: 中間色のコードを返す• c0 , . . . , cm はカラーコードまたは色を表す文字列（cf. trcolor()）．
• k は混ぜ合わせ比率で，k = 0 のときは c0 ，k が正整数のときは cm の色コードを返す．
• それ以外では，k の小数部分の m 倍を p とするとき，c[p] と c[p+1] を [p + 1] − p と p − [p] の比率
で混ぜた色コードを返す．

• disc=1 とすると，色の混ぜ合わせはなく，上で c[p] の色コードを返す．
[0] os_md.i2hex(os_md.mcolor([0xff0000,0x0000ff],1.2));
cc0033[1] os_md.i2hex(os_md.mcolor([0xff0000,0x0000ff,0x00ff00],1));ff00[2] os_md.i2hex(os_md.mcolor(["green","red","blue"],321/456)));e21d00441. xyproc(f |dviout=1,opt=s,env=t):: XY-pic/TikZ や指定した環境の開始（f = 1）と終了（f = 0）や表示• f が 文 字 列 の 時 は ，TikZ に 応 じ て\begin{xy}と\end{xy}ま た は\begin{tikzpicture}と\end{tikzpicture}で鋏む．
さらに dviout=1 が指定してあれば dviout() を使って画面表示する．
• opt=s で文字列 s を指定してあれば\begin{tikzpicture}[s] などのようにオプションをつける．
• env=t で環境 xy などを別の環境に変更できる（たとえば，env="scope"）．
• dviout=1 で画面表示などがなされる．
• xyput(), xyline(), xyarrow(), xybox(), xycirc(), xylines(), xygraph() などで得た文字列を（str tb() などを使って）足し合わせてこの函数を呼ぶとよい．
[0] os_md.xyproc(1);\begin{xy}[1] os_md.xyproc(0);\end{xy}
442. xypos([x,y,s]) xypos([x,y,s,t]) xypos([x,y,s,t,u]) xypos([x,y]):: XY-pic/TikZ での座標 (x, y) や式 s などの文字出力．t はラベルの文字，u はオプション文字列．
• 引数はベクトルでもよい• xypos([x,y]) のとき，以下の文字列が返される(x,y)
ただし数字 x, y は小数点以下 XYPrec 桁に丸められる．
• s が文字列なら，テキストとして表示する．
• x が文字列ならばラベルとみなし，y は無視される．このラベルは TikZ=0 のときは"x"の形で，TikZ=1 のときは (x) の形に変換されるが，x が空文字列なら空文字列でラベル無しとなる．
330

• TikZ=0 の場合– t は一文字．空文字列 "" のとき出力しない．
– u はオプション文字列でラベルの後につく．0 などとすると出力しない．
– s = [s1 , s2 ] とすると，s1 は前置されるオプション文字列，s2 は出力文字列を表す．
∗ s1 ="[F]" : 枠で囲む
∗ s1 ="[F.]" : 囲む枠が点線（. を = とすると二重線）∗ s1 ="+[F]" : 余裕のある枠で囲む∗ s1 ="[Fo]" : 丸く囲む（o を oo とすると二重丸）∗ s1 ="+!U" : 下に置く．U を D, L, R とすると上，右，左に変わる．
さらに UL などとすると，右下などとなる．
+ を ++ とすると，位置のずらしが大きくなる．
• TikZ=1 の場合– xypos([x,y,[s1 ,s2 ],st ,su ]) で，x, y が数，s1 , s2 , st , su が文字列で s2 が空でないとき
node[s1 ](st ) at(x,y){s2 }su– xypos([x,y,[s1 ,""],st ,su ]) のとき
coordinate[s1 ](st ) at (x,y)su– xypos([x,y,[s1 ,s2 ],st ]) または xypos([x,y,s,st ]) のときは，上の su の項は現れない．
– st が数字 1 のときは，st ="_" と解釈される．
– st が空文字列の時，または xypos([x,y,[s1 ,s2 ]]) や xypos([x,y,s]) のとき，上の (st )の項は現れない．
– s や s1 が文字列でないときは数式として TEX の文字列に変換される．
– s1 にはたとえば以下のオプション文字が可能（複数の指定は , で区切る）．
∗ 位置指定 : above, below, right, left, above right,...

below=1pt,...
anchor=west, anchor=south east,...
∗ 形状指定 : circle, rectangle,...
∗ 指定した形状を描く : draw
∗ テキストボックスの幅指定 ：width=3cm∗ テキストボックスの角を丸める ：rounded corners∗ テキストボックス内の文字位置指定 ：text centered∗ 色指定 ：red, green, blue, green!20!white,...
∗ 塗りつぶし : fill=red, fill=green,...
[0] os_md.xypos([2/7,5/3]);(0.285714,1.66667)[1] os_md.dviout0(0|opt="TikZ")$
TikZ=0[2] os_md.xypos([2/7,5/3,4/5]);(0.285714,1.66667) *{\frac{4}5}[3] os_md.xypos([2.5,3.1,"$\\bullet$"]);(2.5,3.1) *{\bullet}[4] os_md.xypos([2.5,3.1,"This is"]);(2.5,3.1) *\txt{This is}[5] os_md.xypos([2,3,"$\\times$","A"]);(2,3) *{\times}="A"[6] os_md.xypos([2,3,"","A"]);(2,3)="A"[7] os_md.xypos([1,2,["+[F]","Sum"],"S"]);331

(1,2) *+[F]\txt{Sum}="S"[8] os_md.xypos(["A","B",["+[F]","Sum"],"S"]);"A" *+[F]\txt{Sum}="S"[9] os_md.dviout0(1|opt="TikZ")$
TikZ=1[10] os_md.xypos([2/7,5/3,4/5]);
node at(0.2857,1.6667){$\frac{4}5$}[11] os_md.xypos([2.5,3.1,"$\\bullet$"]);
node at(2.5,3.1){$\bullet$}[12] os_md.xypos([2.5,3.1,"This is"]);node at(2.5,3.1){This is}[13] os_md.xypos([2,3,"","A"]);
coordinate(A) at(2,3)[14] os_md.xypos([1,2,["red","Sum"],"S"]);node[red](S) at(1,2){Sum}[15] os_md.xypos(["A","B",["draw,rectangle","Sum"],"S"]);node[draw,rectangle](S) at(A){Sum}[16] os_md.dviout0(3|opt="XYPrec")$
XYPrec=3[17] os_md.xypos([@pi,5/3,4/5]);
node at(3.142,1.667){$\frac{4}5$}443. xyput([x,y,s]|scale=r) xyput([x,y,s,t]) xyput([x,y,s,t,u]):: XY-pic/TikZ での座標 (x, y) や式 s などの文字出力．t はラベルの文字，u はオプション文字列．
• xypos() と同じだが，その結果の前後に
TikZ=0 のときは "{" および "};\n"を

TikZ=1 のときは "\\" および ";\n"を，付加して返す．
• xyput([x,y,s,. . .]) は，xyput([[x,y],s, . . .]) としてもよい．
• scale=r : XY-pic/TikZ の座標に直すときに r 倍する．
• scale=[r1 ,r2 ] : XY-pic/TikZ の座標に直すときに x 座標を r1 倍，y 座標を r2 倍する．
[0] os_md.dviout0([4,6])$
DVIOUTA="%ASIRROOT%\bin\risatex.bat"
TikZ=1[1] os_md.xyput([0,0,"","A"]);\coordinate(A) at(0,0);[2] os_md.xyput([[0,0],"","A"]);\coordinate(A) at(0,0);[3] os_md.xyput([0,0,x,"A"]);\node(A) at(0,0){$x$};[4] os_md.xyput([0,0,["draw,rectangle","Sum"]]);\node[draw,rectangle] at(0,0){Sum};[5] os_md.xyput([0,0,["draw,rectangle,rounded corners","Sum"]]);\node[draw,rectangle,rounded corners] at(0,0){Sum};332

[6] os_md.xyput([0,0,["draw,rectangle,fill=yellow,text=red","Sum"]]);\node[draw,rectangle,fill=yellow,text=red] at(0,0){Sum};[7] os_md.xyput([0,0,["draw,circle,thick,dotted,blue,fill=yellow,text=red!50","$\\tfrac12$"]]);\node[draw,circle,thick,dotted,blue,fill=yellow,text=red!50] at(0,0){$\tfrac12$};[8] os_md.xyput([0,0,["circle,radius=2pt,fill=gray",""]]);\node[circle,radius=2pt,fill=gray] at(0,0){};[9] os_md.xyput([0,0,["draw,ellipse","Sum"]]);\node[draw,ellipse] at(0,0){Sum};上の 9 は, TEX ファイルの初めに\usetikzlibrary{shapes}が必要である．
上の結果を S とおいて，os_md.xyproc(S|dviout=1) とすると以下の表示が得られる．

Sum

Sum

Sum

1
2

Sum

444. xyline([x1 ,y1 ,s1 ],[x2 ,y2 ,s2 ]|opt=t) xyline([x1 ,y1 ],[x1 , y2 ]|opt=t):: XY-pic/TikZ で (x1 , y1 ) と (x2 , y2 ) を線で結ぶ（引数はベクトルでもよい）[x1 ,y1 ,s1 ,t1 ,u1 ] などとするとラベル t1 がつく（cf. xypos()）．
TikZ のときは，opt=t によって色や線種などのオプション指定文字が有効．
[0] os_md.dviout0(0|opt="TikZ")$
TikZ=0[1] os_md.xyline([1,2,x],[3,4,y]);{(1,2) *{x} \ar@{-} (3,4) *{y}};[2] os_md.xyline([1,2,x,"A"],[3,4,y,"B"]);{(1,2) *{x}="A" \ar@{-} (3,4) *{y}="B"};[3] os_md.dviout0(1|opt="TikZ");
TikZ=1[4] os_md.xyline([1,2,x],[3,4,y]);\draw node(_0) at(1,2){$x$} node(_1) at(3,4){$y$}(_0)--(_1);[5] os_md.xyline([1,2,x,"A"],[3,4,y,"B"]);\draw node(A) at(1,2){$x$} node(B) at(3,4){$y$}(A)--(B);
上の [5] において，全体を赤にして，線を点線とするには

os_md.xyline([1,2,x],[3,4,y]|opt="dotted,red");とする．また，[5] において，x を緑に，y を黒に，線を赤にするには

os_md.xyline([1,2,["green",x]],[3,4,["black",y]]|opt="red");とする．さらに y を丸で囲むには

os_md.xyline([1,2,["green",x]],[3,4,["black,draw,circle",y]]|opt="red");とし，さらに y を囲む円内を赤で塗りつぶすには

os_md.xyline([1,2,["green",x]],[3,4,["black,draw,circle,fill=red",y]]|opt="red");
とする．

333

y

x

y

x

y

x

y

x

445. xyarrow([x1 ,y1 ,s1 ],[x2 ,y2 ,s2 ]|opt=t,cmd=s):: XY-pic/TikZ で (x1 , y1 ) と (x2 , y2 ) を矢印等で結ぶ（引数はベクトルでもよい）• 出力する 3 番目の要素 s1 , s2 は省略可．
• xypos() にあるように，[x1 ,y1 ,s1 ,t1 ,u1 ] とするとラベル t1 がつき，s1 = [s1,1 , s1,2 ] の形もサポートされる．

• 最初の引数が数字のときは "%\n" を，また XY-pic の場合は最初の引数が 0 でなくて 2 番目の引数が数字のときは空文字列を返す．

• オプションの t は線種などを指定する XY-pic/TikZ の文字列．
まず XY-pic の場合のいくつかの例を挙げる．
"@{->}""@{<->}""@{-}""@{.}""@{~}""@{=}""@{--}""@2{.}""@{{*}->}""@{x.o}""@2{|.>>}""@/^1.5mm/"

矢印（デフォルト）
両側矢印
実線
点線
波線
二重線
破線
二重点線
矢印の例
矢印の例
矢印の例
進む方向の左側に 1.5 mm 曲げる"@(ru,ld)"

右上に出て左下に入る

/

/

o

/

•

?


◦

+3 +3

)
?

TikZ の場合は，オプション文字列 t で指定する．
線の太さ
点線
点の密度
矢印
矢印の形状
二重線
色づけ

曲線を曲げる

very thin, thin, semithick, thick, very thick, ultra thick,width=2pt,...
dashed, dotted, dashe dot, dashe dot dot
loosely dashed, densely dashed, loosely dotted, densly dotted-, ->, <->, <-, ->>>=stealth, >=latex など
doublered, blue, green, cyan, magenta, yellow, black, gray, white, darkgray,lightgray, brown, lime, olive, orange, pink, purple, teal, violet,
green!30!white（緑 30% 白 70%）, cyan!10 など
bend right,distance=0.2cm など

t = [t0 , t1 ] のときは，t0 が上のように解釈され（t0 = 0 はデフォルト），文字列 t1 は

334

->
デフォルト
to[out=60,in=120]
出る線と入る線の角度指定
to[out=60,in=120,relative] 出る線と入る線の相対角度指定|縦線，次に横線でつなぐ-|
横線，次に縦線でつなぐ
t1 の末尾が "+"相対位置指定• TikZ の場合は，オプション opt や cmd などを利用して，より広い描画コマンドに使うことができる．

– os_md.xyarrow([x1 ,y1 ],[x2 ,y2 ]) で，x1 , x2 , y1 , y2 が数字の時\draw[->](x1 ,y1 ) -- (x2 ,y2 )– os_md.xyarrow([x1 ,y1 ,s1 ],[x2 ,y2 ]) で，x1 , x2 , y1 , y2 が数字, s1 が文字列の時\draw[->]node(_0) at(x1 ,y1 ){s1 } coordinate(_1) at(x2 ,y2 )(_0) -- (_1);– os_md.xyarrow([x1 ,y1 ,s1 ],[x2 ,y2 ,s2 ]) で，x1 , x2 , y1 , y2 が数字, s1 , s2 が文字列
\draw[->]node(_0) at(x1 ,y1 ){s1 } node(_1) at(x2 ,y2 ){s2 }(_0) -- (_1);
s1 や s2 が数式の時は，それを TEX のソースに変換して $ で鋏んだものに置き換えられる．
– os_md.xyarrow([x1 ,y1 ,[s01 ,s1 ],t1 ,u1 ],[x2 ,y2 ,[s02 ,s2 ],t2 ,u2 ]|opt=[t,t0 ,t00 ],cmd=s)で，x1 , x2 , y1 , y2 が数字, 他が文字列\s[t]node[s01 ](t1 ) at(x1 ,y1 ){s1 }u1 node[t02 ](t2 ) at(x2 ,y3 ){s1 }u2 (t1 )t0 (t2 )t00 ;なお，s のデフォルトは draw, t0 のデフォルトは --，t のデフォルトは -> となっている．また t0 , t00 を指定しないときは，opt=t としてよい．

– x1 や x2 が文字列のときは，それはラベルとみなされて y1 や y2 は無視され，( ) で囲まれて出力される．
第 2 引数が数字のときは別の解釈が成される．第 2 引数の値を n とすると, n の値に応じてデフォ
ルトのコマンド \draw が次のように置き換えられる（デフォルト以外の指定をしたときは，オプションの cmd= の設定より優先される）．
n の値 コマンド0\draw\path[draw] と同等
1\fill\path[fill] と同等
2\filldraw\path[fill,draw] と同等
3\shade\path[shade] と同等
4\shadedraw\path[shade,draw] と同等
5\clip\path[clip] と同等
6\pattern\path[pattern] と同等

7
8
9

\path
\node
\coordinate\path node と同等\path coordinate と同等

これで定まるコマンドを \cmd としたとき

os_md.xyarrow([x,y],n|opt=[t,t0 ,t00 ])で x, y, n が数字で他が文字列のとき\cmd[t](x,y)t0 [t00 ]となる．なお，t00 の項がない場合は上の [t00 ] の項は現れない．

335

[0] os_md.dviout0(7)$TikZ=0[1] os_md.xyarrow([1,2,x/y],[30,4,z^2,0,"|f"]|opt="@{<.} @/_5mm/");{(1,2) *{\frac{x}y} \ar@{<.} @/_5mm/ (30,4) *{z^2 }|f};[2] os_md.xyproc(@@|dviout=1);[3] os_md.xyarrow([0,0,["+[F]","Sum"]],[20,0,"$\\sum_{i=1}^na_i$"]);{(0,0) *+[F]\txt{Sum} \ar (20,0) *{\sum_{i=1}^na_i}};[4] os_md.xyproc(@@|dviout=1);
x
z2
P
yf
/ n aiSum
i=1f[0] os_md.dviout0(6)$TikZ=1[1] os_md.xyarrow([0,1],[2,3]);\draw[->](0,1) -- (2,3);[2] os_md.xyarrow([0,1],[1,2]|opt=["->,thin","to[out=60,in=120]+"]);\draw[->,thin](0,1)to[out=30,in=120]+(1,2);[3] os_md.xyarrow([0,1],[2,3]|opt=["bent left, distance=1cm","to"]);\draw[bent left, distance=1cm](0,1)to(2,3);[4] os_md.xyarrow([0,1,"A"],[2,3,["draw,circle","B"]]|opt=[0,"|-"]);\draw[->]node(_0) at(0,0){A} node[draw,circle](_1) at(1,1){B}(_0)|-(_1);[5] os_md.xyarrow([0,1],[2,3]|opt=["very thick","rectangle"]);\draw[very thick](0,1)rectangle(2,3);[6] os_md.xyarrow([-1,-1],[1,1]|opt=["very thin,step=0.3cm","grid"]);\draw[very thin,step=0.3cm](-1,-1)grid(1,1);[7] os_md.xyarrow([-1,-1],[1,1]|opt=["help lines,step=0.5cm","grid"]);\draw[help lines,step=0.5cm](-1,-1)grid(1,1);[8] os_md.xyarrow([0,0],[1,1]|opt=["shade","rectangle"]);\draw[shade](0,0)rectangle(1,1);[9] os_md.xyarrow([0,0],[1,1]|opt=["shade,left color=yellow,right color=black","rectangle"]);\draw[shade,left color=yellow,right color=black](0,0)rectangle(1,1);[10] os_md.xyarrow([0,0],[".5cm"]|opt=["inner color=red","circle"],cmd="shade");\shade[inner color=red](0,0)circle(.5cm);[11] os_md.xyarrow([0,0],[".5cm"]|opt=["ball color=red","circle"],cmd="shade");\shade[ball color=red](0,0)circle(.5cm);[12] os_md.xyarrow([0,0],[1,1]|opt=["pattern=north east lines","rectangle"]);\draw[pattern=north east lines](0,0)rectangle(1,1);[13] os_md.xyarrow([0,0],[1,1]|opt=["dotted,pattern=bricks,pattern color=blue","rectangle"]);\draw[dotted,pattern=bricks,pattern color=blue](0,0)rectangle(1,1);[14] os_md.xyarrow([0,0],[1,1]|opt=["pattern=checkboard light gray","rectangle"],cmd="fill");\fill[pattern=checkboard light gray](0,0)rectangle(1,1);[15] os_md.xyarrow([0,0],0|opt=["pattern=dots","circle","radius=.5cm"]);336

\draw[pattern=dots](0,0)circle[radius=.5cm];[16] os_md.xyarrow([0,0],1|opt=["pattern=crosshatch,pattern color=blue","circle","radius=.5cm"]);\fill[pattern=crosshatch,pattern color=blue](0,0)circle[radius=.5cm];[17] os_md.xyarrow([0,0],3|opt=["shading=color wheel white center","circle","radius=.5cm"]);\shade[shading=color wheel white center](0,0)circle[radius=.5cm];
上の [12] 以降の pattern の指定では, TEX ファイルの初めに\usetikzlibrary{patterns}が必要である．上の結果を S として xyproc(S|dviout=1) とすると順に以下が得られる．

B

A\shade で指定される塗りつぶしの色変化は
top color=, bottom color=, midddle color=
left color=, right color=, midddle color=
inner color=, outer color=ball color=
upper left=, upper right=, lower left=, lower right=
shading=color wheel, color with black center, color wheel white center
pattern= で設定できる塗りつぶしパターンはhorizontal lines, vertical lines, north east lines, north west lines, grid,crosshatch, dots, crosshatch dots, fivepointed stars, sixpointed stars, bricks,
checkerboardがある．そのバリエーションで以下のようなものも可能である．

checkerboard light gray, horizontal lines light gray, horizontal lines gray,horizontal lines dark gray, horizontal lines light blue, horizontal lines dark
blue, crosshatch dots gray, crosshatch dots light steel blue
446. xyarrows([f1 ,f2 ],[v1 ,v2 ],[[x1 ,x2 ,m],[y1 ,y2 ,n]]|scale=r,abs=v):: XY-pic/TikZ で複数の矢印を描く
x 変数の区間 [x1 , x2 ] を m 等分，y 変数の区間 [y1 , y2 ] を n 等分し，それぞれの終点を除いた m × nの各格子点 (x, y) に対して，点 (f1 (x, y), f2 (x, y)) を始点として，(v1 (x, y), v2 (x, y)) というベクトル（矢印）をXY-pic/TikZ で描く．
• y 変数がないときは，第 3 引数を [x1 ,x2 ,m] としてよい．
• scale=r : ベクトルを r 倍して描く．
• abs=v : ベクトルの長さを v にスケール変換する．
• opt=s : xyarrow( ) にそのまま渡されるオプション・パラメータ[0] os_md.dvi([0,4,6])$[1] Abs=os_md.abs(y)$Sqrt=os_md.sqrt(x)$[2] SqrtAbs=os_md.compdf(Sqrt,x,Abs)$337

[3] P=[x,y]$Q=[1,SqrtAbs]$[4] S=os_md.xyarrows(P,Q,[[-1.5,1.5,36],[-1.5,1.5,36]]|abs=0.05)$[5] S+=os_md.xygraph((x+1)^2/4,-36,[-1,1.5],[-1,1.5],[-1.5,1.5])$[6] S+=os_md.xygraph(-(x-1)^2/4,-36,[-1.5,1],[-1.5,1],[-1.5,1.5])$[7] os_md.xyproc(S|opt="scale=5"|dviout=1)$
これの実行結果は図 1 となる．
図1

微分方程式

√
dy
= |y|
dx

447. xybox([[x1 ,y1 ],[x2 ,y2 ],[x3 ,y3 ]]|opt=t,color=s...) xybox([[x1 ,y1 ],[x2 ,y2 ]]|opt=t,color=s,...):: XY-pic/TikZ で (x1 , y1 ) と (x2 , y2 ) を対角点とし，(x3 , y3 ) を頂点とする平行四辺形（あるいは水平な辺をもつ長方形）を描く• [xj ,yj ] はベクトルでもよい．
• xylines() のオプションと同じオプションが有効．

338

• TikZ での長方形描画の場合は，color=s のオプションが指定でき，色付けや塗りつぶしなどが可能．このとき，他のオプションは無視される．
– color=s として s が文字列の時，\draw[s]· · · となる.
color="red" : 赤で箱を描く
color="fill=red" : 赤で塗りつぶす．枠は（指定しなければ）黒– color=[s,cmd] : とすると \cmd\draw[s]· · · となる．

[0] os_md.dviout0(0|opt="TikZ")$
TikZ=0[1] os_md.xybox([[1,2],[30,40]]);{(1,2) \ar@{-} (1,40)};{(1,40) \ar@{-} (30,40)};{(30,40) \ar@{-} (30,2)};{(30,2) \ar@{-} (1,2)};[2] os_md.xybox([[1,2],[3,4],[0,0]]);{(1,2) \ar@{-} (0,0)};{(0,0) \ar@{-} (3,4)};{(3,4) \ar@{-} (4,6)};{(4,6) \ar@{-} (1,2)};[3] os_md.dviout0(1|opt="TikZ")$
TikZ=1[4] os_md.xybox([[1,2],[3,4]]);\draw(1,2)rectangle(3,4);[5] os_md.xybox([[1,2],[3,4]]|color="red");\draw[red](1,2)rectangle(3,4);[6] os_md.xybox([[1,2],[3,4]]|color="red,fill=yellow");\draw[red,fill=yellow](1,2)rectangle(3,4);[7] os_md.xybox([[1,2],[3,4]]|color=["yellow","fill"]);\fill[red](1,2)rectangle(30,40);[8] os_md.xybox([[1,2],[3,4],[0,0]]);\draw (1,2) -- (0,0) -- (3,4) -- (4,6) -- cycle;

448. xycirc([x,y,s],r|opt=t,arg=[θ1 ,θ2 ],deg=[θ1 ,θ2 ],close=1):: XY-pic/TikZ で (x, y) 中心の半径 r mm/cm の円を描く• 出力する 3 番目の s は省略可
• opt=t : オプション文字列• 大きな円が描けない場合は，arg=[-@pi,@pi] を用いる．なお
usepackage[pdf,all]{xy} によって pdf ファイルを作成する場合は，このエラーは起きない．
• s があって r = 0 のときは，s を円で囲む．
• arg を指定したときは意味が異なり，偏角 θ1 から θ2 までの円弧を描く（0 < θ2 − θ1 ≤ 2π)．
このときオプション opt は線種指定文字と解釈される（cf. xylines( |curve=1)）．
また close=1 で中心と線分で繋いで扇型とする．
• より汎用性のある xyang() を用いる方がよい．
[0] os_md.xycirc([2,3],5|opt="l^d");339

{(2,3) *\cir<5mm>{l^d}};[1] os_md.xycirc([2,3,x],0);{(2,3) *+{x} *\cir{}};449. xybezier([[x1 ,y1 ], . . . ,[xn , yn ]]|verb=k,opt=t,cmd=s,relative=1):: XY-pic/TikZ で区分 Bézier 曲線（複合 Bézier 曲線）を描く
始点を (x1 , y1 ), 終点を (xn , yn ) とし，途中の座標を制御点とする Bézier 曲線を描く．
• [xj ,yj ] はベクトルでもよい．
• 途中の [xi ,yi ] を数字の 0, ±1 にすると以下のような特別の意味を持つ．
– 0 : 前後で切り離して別の Bézier 曲線とする．
– 1 : 直前の点を途中の通過点とする Bézier 曲線とする．
– -1 : 始点を終点とする閉じた Bézier 曲線とし，前後で切り離す．
• verb=1 : 始点と終点を •，制御点を × で表示する．単独の Bézier 曲線となる場合のみ有効．
• verb=2 : 上と同様だが，終点は表示しない．
• verb=[k,t1 ,t2 ] : 始点と終点，制御点の描き方を指定する．
– k = 1, 2 は省略できて，省略したときは k = 1 （始点と終点を描く）と解釈される．
– t1 は始点と終点，t2 は制御点の示す記号を表し，xyput() の引数のリストのの成分 s に対応
する．

– デフォルトは，t1 ="$\\bullet$", t2 ="$\\times$"– t2 を省略して verb=[t1 ] とすると，始点と終点のみ描いて，制御点は描かない．
– TikZ のときは，たとえば verb=[["red","$\\bullet$"],"$\\times$"] とすると，始点と終点を赤で描く．

• relative=1 : TikZ のときに，始点以外を座標の相対指定とする．
• cmd=s : TikZ におけるコマンド \draw の代わりに \s を使う．
• XYLim : TEX のソースで，XYLim 個の点毎に見やすくするため改行を入れる．
dviout0(n|opt="XYLim") によって XYLim を n に変更できる（デフォルトは 4）．
• opt=t : コマンドの後にオプション t をつける．
TikZ の場合は，xyarrow() の項に書かれた線種指定の他，以下のような塗りつぶしコマンドが使える．
fill
fill=yellow,draw=blue
fill=red,opacity=.5
fill=red,even odd rule

塗りつぶし
赤で線を描き，内部を黄色で塗りつぶす
赤で透明度 0.5 で塗りつぶす
winding number が奇数（デフォルトは 0 以外）の部分を赤で塗りつぶす[0] A=newvect(8)$[1] for(I=0;I<8;I++) A[I]=[I,I/2];$[2] os_md.dviout0(7)$TikZ=0[3] os_md.xybezier([A[0],A[1],A[2],A[3],A[4]]);{(0,0);(4,2)**\crv{(1,0.5)&(2,1)&(3,1.5)}};[4] os_md.xybezier([A[0],A[1],A[2],A[3],0,A[4],A[5],A[6]]);{(0,0);(3,1.5)**\crv{(1,0.5)&(2,1)}};{(4,2);(6,3)**\crv{(5,2.5)}};[5] os_md.xybezier([A[0],A[1],A[2],A[3],1,A[4],A[5],A[6]]);{(0,0);(3,1.5)**\crv{(1,0.5)&(2,1)}};340

{(3,1.5);(6,3)**\crv{(4,2)&(5,2.5)}};[6] os_md.dviout0(6)$TikZ=1[7] os_md.xybezier([A[0],A[1],A[2],A[3]]);\draw (0,0) .. controls (1,0.5) and (2,1) .. (3,1.5);[8] os_md.xybezier([A[0],A[1],A[2],A[3],0,A[4],A[5],A[6]]);\draw (0,0) .. controls (1,0.5) and (2,1) .. (3,1.5)(4,2) .. controls (5,2.5) .. (6,3);[9] os_md.xybezier([A[0],A[1],A[2],A[3],1,A[4],A[5],A[6]]);\draw (0,0) .. controls (1,0.5) and (2,1) .. (3,1.5).. controls (4,2) and (5,2.5) .. (6,3);[10] os_md.xybezier([A[0],A[1],A[2],A[3],-1,A[4],A[5],A[6],-1]);\draw (0,0) .. controls (1,0.5) and (2,1) and (3,1.5) .. cycle(4,2) .. controls (5,2.5) and (6,3) .. cycle;[11] os_md.xybezier([A[0],A[1],A[2],A[3],0,A[4],A[5],A[6],-1]|relative=1);\draw (0,0) .. controls +(1,0.5) and +(2,1) .. +(3,1.5)(4,2) .. controls +(5,2.5) and +(6,3) .. cycle;[11] os_md.xybezier([[0,0],[2,0],1,[1,1],1,-1]|cmd="fill",opt="green");\fill[green] (0,0) -- (2,0) -- (1,1) -- cycle;[12] os_md.xybezier([[0,0],[2,0],1,[1,1],1,-1]|opt="fill,red");\draw[fill,red](0,0) -- (2,0) -- (1,1) -- cycle;[13] os_md.xybezier([[0,0],[2,0],1,[1,1],1,-1]|opt="fill=yellow,draw=red");\draw[fill=yellow,draw=red](0,0) -- (2,0) -- (1,1) -- cycle;
450. draw bezier(id,idx,b|col=c,opt=s,init=1):: キャンバス上に区分 Bézier 曲線を描く
サーバー id が id でキャンバス id が idx のキャンバスに Bézier 曲線を描く（cf. draw obj()）．
• b は xybezier() の引数の形式, あるいはそれを lbezier() で変換したもの（よって区分 Bézier曲線でよい）．または，tobezier() の戻り値の t 変数の Bézier 曲線でもよい．
• col= c : 色指定（0xffffff が白）．
• 文字列による指定で，red, blue, green, yellow, cyan, magenta, black, white, gray, thin,very thin, dotted, dashed が可能．opt="red,thin,dotted" などという指定ができる．
• init=1 : 点線描画の初期化（他の引数はすべて無視）．
[0] Id=ox_launch_nox(0,"ox_plot")$[1] open_canvas(Id)$[2] Idx=ox_pop_cmo(Id)$[3] B=os_md.xyoval([150,150],100,1|opt=0)$/* 中心 (150,150) 半径 100 の円 */[4] tstart$os_md.draw_bezier(Id,Ind,B|col=0xff00ff)$tstop;[5] [6] 0.0156sec(0.015sec)
451. xylines([[x1 ,y1 ,s1 ],[x2 ,y2 ,s2 ],. . .]|opt=t,close=1,curve=1,ratio=c,verb=1,scale=r,
Acc=1,dviout=1,proc=p):: XY-pic/TikZ で sj を (xj , xj ) に置き，(x1 , y1 ), (x2 , y2 ), . . . を（Bézier 曲）線で結ぶ• close=1 : 最後の点を最初の点と結んで，多角形または滑らかな閉曲線を作る．
• close=-1 : 曲線で結ぶ場合に，最初と最後の点は制御点とし，残りの点を滑らかに結ぶ．

341

• curve=1 : 曲線（Bézier 曲線を使う）で滑らかに結ぶ（cf. [O4]）.
−−−→
P0 , P1 , P2 , P3 を通る曲線で P1 と P2 を結ぶには，P0 P2 の方向に P1 から c1 P1 P2 の距離進んだ−−−→
点 Q と，P3 P1 の方向に P2 から c2 P1 P2 進んだ点 R の 2 点を制御点とする 3 次の Bézier 曲線を−−−→ −−−→
用いる．P0 が存在しないときは Q を，P3 が存在しないときは R を省く．P0 P2 と P1 P3 のなす角を θ (0 ≤ θ ≤ π) とするとき，デフォルトでは
c1 + c22=,23(1 + cos θ2 )c 1 : c 2 = P0 P2 : P3 P1としている．
正 n 角形の頂点を指定し，close=1 を指定すると，デフォルトでは外接円に近い曲線になる．
実際，外接円の半径を 1 としたとき，得られた曲線の中心からの距離と 1 との差の最大値は，n = 3のとき 0.0015, n = 4 のとき 0.00027, n = 6 のとき 0.000024, n = 8 のとき 0.000004 という程度の小さな値となる.
なお，ratio=c を指定したときは，以下のように定める．

−−→−−−→ −−→−−−→P1 Q = c P0 P2 , P2 R = c P 3 P1
• Acc=1 : curve=1 を指定したとき，pari() の高精度で制御点を計算する．
• curve=2 : B-spline 曲線で結ぶ（途中の点は制御点で通らない）．
このときは sj は最初と最後のみ指定可能．TikZ ではサポートされない（3 次以下の Bézier 曲線
はサポート）．

• s1 , s2 , . . . は省略可能．また sj がないときは，[xj ,yj ] はリストでなくてベクトルでもよい．
• 通過点のデータに 0 があるときは，その前後で直線または曲線を切る．
• scale=r : XY-pic/TikZ の座標に直すときに r 倍する．
• scale=[r1 ,r2 ] : XY-pic/TikZ の座標に直すときに x 座標を r1 倍，y 座標を r2 倍する．
XY-pic は数字が mm 単位，TikZ は cm 単位である．
• opt=t : 文字列 t による線種の指定．XY-pic でオプション curve を指定せずに線分で結ぶときの線種指定は xyarrow() を参照．curve= 1, 2 のときは，たとえば XY-pic ならば "~*=<3pt>{.}"
は 3pt 間隔の点線．
TikZ のときの線種指定は，xyarrow() の項を参照（t がオプション opt の値として渡される）．また t = [t0 , t1 ] と 2 つの文字列のリストのときは，t0 と t1 とが xybezier() の opt と cmd のパラメータに設定される．

• opt=0 : xybezier() に渡す引数のリストを返す．
• dviout=1 : 画面で表示する．
• proc=1 : 描画実行形式の描画成分を返す（proc=2 も同様）．
• verb=1 : 通過点を •，制御点を × で表示する．
• verb=[t1 ,t2 ] : 通過点を t1 , 制御点を t2 で表す（cf. xybezier()）．
デフォルトは，t1 ="\\bullet", t2 ="\\times" である．
• verb=[t1 ] : 通過点を t1 で表す．
円の中心 O があって，OP0 = OP1 = OP2 = OP3 かつ P0 P1 = P1 P2 = P3 P4となっている場合を考える．∠P1 OP2 = θ, OP0 = r, P1 Q = P2 R = a
とおいて座標を適当に選ぶと，Bézier 曲線上の t = 21 に対応する点 T は以下のようになる．

O : (0, 0), P1 : (r cos θ2 , r sin θ2 ), P1 : (r cos θ2 , −r sin θ2 )

O

P1
a

•
r

•
T×•

θ

θ
θ−π
Q : (r cos θ2 + a cos θ−π
2 , r sin 2 + a sin 2 )= (r cos θ2 + a sin θ2 , r sin θ2 − a cos θ2 )
R : (r cos θ2 + a sin θ2 , −r sin θ2 + a cos θ2 )T : (r cos θ2 + 43 a sin θ2 , 0)
342

Q

•
•
P2

R

条件 OT = OP1 が成り立つとするとr cos θ2 + 34 a sin θ2 = r
より

4 1 − cos θ2
4 sin θ2
4
θ
r
=
tan
r
=
r.
3
4
3 sin θ2
3 1 + cos θ2

a=
このとき



4 1−cos θ2
4 sin θ2θθ
θ
Q : r cos θ2 +
r,
r
sin
−
cos
r
sin
2
2
2
3 sin θ2
3 1 + cos θ2


θ
sin 2
= ( 43 − 13 cos θ2 )r, (1 − 13 cos θ2 )θr ,1+cos 2sin θ2

P1 Q
4
1
2
=
=
θ
θ
P1 P 23 1 + cos 2 2 sin 2
3(1 + cos θ2 )となる．
r = 1 として，Bézier 曲線を B(t) = x(t), y(t) = P1 (1 − t)3 + 3Qt(1 − t)2 + 3Rt2 (1 − t) + P2 t3 ，c = cos θ2 とおくとL(s) := x(s + 12 )2 + y(s + 12 )2=

16(1 − c)3 6 8(1 − c)3 4 (1 − c)3 2
s −
s +
s +1
1+c
1+c
1+c
3

2
2
2
= (1−c)1+c s (4s − 1) + 1となるので，0 ≤ s ≤ 12 の範囲で

p
8s2 + (1 − 4s2 ) + (1 − 4s2 )2
3
8s2 (1 − 4s2 )2 ≥=
3
3
1となり，等号成立は 8s2 = 1 − 4s2 ，すなわち s2 = 12のときである．よって |s| ≤ 12 の範囲で L(s) は1
s = 0, ± 12 で最小値 1 をとり，s = ± 2√で最大値をとる．
3
1
L(± 2√)−1=
3

q

1
L(± 2√)−1≒
3

1 (1 − c)3,
27 1 + c

 1


 648
1

 3668

1 (1 − cos θ2 )3
1≒ 41900
54 1 + cos θ21 235541
12683400◦(θ = 2π
3 = 120 )π◦(θ = 2 = 90 )(θ = π3 = 60◦ )(θ = π4 = 45◦ )(θ = π6 = 30◦ )デフォルトでは P0 , P1 , P2 , P3 を通る滑らかな曲線の P1 と P2 を結ぶ部分は−−−→ −−−→( P0 P2 , P3 P1 ),P0 P2 · P1 P3rθ
1 + cos θ
cos =
,
2
2
−−−→
P1 P3 −−−→
2P1 P22r
c1· P0 P2 =· P0 P2−−−→ −−−→( P 0 P 2 , P 1 P 3 ) P0 P2 + P1 P3
P0 P2
1+ P P ·P P
0 2 1 33+3
2
cos θ =

343

より

c :=

4P1 P23(P0 P2 + P1 P3 )

1

r
1+

−−−→ −−−→( P P ,P P )1+ P0 P2 ·P1 P3
0 2

1 3

2

とおくと

−−→
−−−→ −−→−−−→P 1 Q = c P0 P2 , P2 R = c P 3 P1によって，P1 を始点，P2 を終点，Q と R の 2 点をこの順に制御点とする 3 次 Bézier 曲線となる．
Q0 , Q1 , Q2 , Q3 と順に与えたとき，Q0 を始点，Q1 と Q2 を制御点，Q3 を終点とする（3 次）Bézier
曲線はB(t) = Q0 (1 − t)3 + 3Q1 t(1 − t)2 + 3Q2 t2 (1 − t) + Q3 t3= (−Q0 + 3Q1 − 3Q2 + Q3 )t3 + (3Q0 − 6Q1 + 3Q2 )t2 + (−3Q0 + 3Q1 )t + Q0
で与えられる．
なお，P0 , P1 , P2 , P3 と順に与えたとき，P1 を始点，P2 を終点とする Catmull-Rom スプライン曲
線はC(t) = (− 12 P0 + 32 P1 − 32 P2 + 12 P3 )t3 + (P0 − 52 P1 + 2P2 + 12 P3 )t2 + (− 12 P0 + 21 P2 )t + P1
である．両者の関係は


Q 0 = P1 ,

Q1 = P1 + 16 (P2 − P0 ),Q2 = P2 + 16 (P3 − P1 ),
Q 3 = P2 .

よって c = 16 と固定したものとみなせる．

[0] L=[[0,0],[20,0],[20,20],[0,20]]$[1] L0=os_md.xylines(L|close=1);{(0,0) \ar@{-} (20,0)};{(20,0) \ar@{-} (20,20)};{(20,20) \ar@{-} (0,20)};{(0,20) \ar@{-} (0,0)};[2] L1=os_md.xylines(L|close=1,curve=1,ratio=1/6)$[3] L2=os_md.xylines(L|close=1,curve=1)$[4] L3=os_md.xylines(L|close=1,curve=2)$[5] L4=os_md.xybezier(append(L,[[0,0]]))$
として，L0, L1, L2, L3, L4 を順に表示するとこれらは XY-pic の例であるが，TikZ の場合は座標のスケールの違いから，scale=0.1 を指定するとサイズが同じになる．たとえば，上の [3] の L2 は344

{(0,0);(20,0)**\crv{(5.523,-5.523)&(14.477,-5.523)}};{(20,0);(20,20)**\crv{(25.523,5.523)&(25.523,14.477)}};{(20,20);(0,20)**\crv{(14.477,25.523)&(5.523,25.523)}};{(0,20);(0,0)**\crv{(-5.523,14.477)&(-5.523,5.523)}};であるが，os_md.dviout(6) などとして TikZ 出力になるようにして

os_md.xylines(L|close=1,curve=1,scale=0.1);を実行したときは\draw (0,0) .. controls (0.552,-0.552) and (1.448,-0.552) .. (2,0) ..
controls (2.552,0.552) and (2.552,1.448) .. (2,2) .. controls (1.448,2.552)
and (0.552,2.552) .. (0,2) .. controls (-0.552,1.448) and (-0.552,0.552).. cycle;となる．これは以下でも同様である．

[6] Pi=3.14159265$[7] for(V=[],I=0;I<=48;I++) V=cons([10*Pi*I/12,dsin(Pi*I/12)*10],V);[8] os_md.xyproc(os_md.xylines(V|curve=1)|dviout=1)$[9] for(V=[],I=0;I<=6;I++) V=cons([10*Pi*I*2/3,dsin(Pi*2*I/3)*10],V);[10] os_md.xylines(V|curve=1,dviout=1,verb=1);
×

•

×

×

•
×

×
•

×

•

×

•

×
•
×

•

×

[11] os_md.xylines(os_md.ptpolygon(5,10)|close=1,dviout=1)$[12] os_md.xylines(os_md.ptlattice(6,4,[4,0],[0,4]|line=1)|dviout=1)$[13] os_md.xylines(os_md.ptlattice(6,4,[4,0],[3,4]|line=1)|dviout=1)$452. xyang(r,p0 ,p1 ,p2 |opt=t,scale=r,prec=1,ar=1,dviout=1,proc=1):: XY-pic/TikZ で角 ∠p1 p0 p2 の記号や円弧や扇形や矢印を描く• p0 = [x0 , y0 ], p1 = [x1 , y1 ], p2 = [x2 , y2 ] のときは，∠p1 p0 p2 の角の記号（すなわち円弧）を→
半径 r の弧で描く（−p−．
0 p1 から反時計回り）345

→• p0 = [x0 , y0 ], p1 = [x1 , y1 ], p2 = ±1 のときは，p0 を頂点する −p−
0 p1 方向とそれと直交する方向に一辺 r の直角記号を描く（p2 = 1 のときは反時計回り，p2 = −1 のときは時計回り）．
• p0 = [x0 , y0 ], p1 = [x1 , y1 ], p2 = ±2, ±3, ±4, 0 のときは，p0 を頂点とする矢印の先を描く．rは先端からの長さ．線分との角度は，順に 45◦ , 30◦ , 60◦ , 90◦ である．ただし，p2 < 0 の時は矢印の先でなくて尾を示す．また，|p2 | ≥ 10 のときは |p2 |◦ の角度とみなす．
p2 = 5, 6, 7, 8 のときは，矢先が曲がっていて，開きは順に 45◦ , 30◦ , 22.5◦ , 15◦ となる．
ar=1 を指定すると，p0 と p1 を結ぶ線分も描いて，矢印となる．
ar=3 を指定すると，矢先は閉じた図形になり，TikZ のときは opt="fill"を指定すると，塗りつぶされた矢先になる（ar=2 では矢先のみ）．p0 と p1 を結ぶ線分も描いて，矢印となる．
• r = −1 : 4p0 p1 p2 の内接円を描く．
• r = −2 : 4p0 p1 p2 の外接円を描く．
• r = −3, −4, −5 : 4p0 p1 p2 の傍接円を描く（∠p|r|−3 内）．
• r = −6 : 直線 p1 p2 に接する p0 中心の円を描く．
• r = −7 : 点 p0 から直線 p1 p2 に下ろした垂線を描く．
• r が数でなくて座標 p3 = [x3 , y3 ] のときは，r は p0 と p3 の距離に置き換えられる．
• p0 = [x0 , y0 ] で，p1 と p2 が数で p1 ≤ p2 ≤ p1 + 2π の時，p0 を中心に半径 r の円弧を，偏角がp1 から p2 まで Bézier 曲線を使って描く．ただし，p1 = p2 のときは円とする．
円弧の場合，ar=1 を指定すると扇形を描く．
• prec=1 : 真の円弧により近くする（デフォルトでの円の中心からの距離の誤差は，0.16% 以下で
1≒ 0.03% 以下とする）．
あるが，それを 3600
11
prec=2, 3 に応じて，誤差は 41900, 235500以下になる．
• proc=1 : 描画実行形式の要素を返す．
• 指定したオプションパラメータは，上のものを除いて全て xylines() に渡される．
TikZ のときは[0] os_md.xyang(0.3,[1,1],[6,1],[5,5]); /* 角度の弧 */\draw (1.3,1) .. controls (1.3,1.08) and (1.268,1.156) .. (1.212,1.212);[1] os_md.xyang(0.3,[1,1],[6,2],1);/* 直角記号 (反時計回り）*/\draw (1.294,1.059) -- (1.235,1.353) -- (0.941,1.294);[2] os_md.xyang(0.3,[1,1],[6,2],-1);/* 直角記号 (時計回り）*/\draw (1.294,1.059) -- (1.235,1.353) -- (0.941,1.294);[3] os_md.xyang(2,[1,1],0,@pi/2|opt="dotted,red"); /* 円弧 */\draw[dotted,red] (3,1) .. controls (3,2.105) and (2.105,3) .. (1,3);[4] os_md.xyang(2,[1,1],@pi/12,@pi/3|ar=1,scale=2); /* 扇形 */\draw (5.864,3.035) .. controls (5.589,4.06) and (4.919,4.934) .. (4,5.464)-- (2,2) -- cycle;[5] os_md.xyang(2,[1,1],0,0);/* 円 ：誤差 1/640 以下 */\draw (3,1) .. controls (3,2.54) and (1.333,3.502) .. (0,2.732).. controls (-1.333,1.962) and (-1.333,0.038) .. (0,-0.732) ..
controls (1.333,-1.502) and (3,-0.54) .. cycle;[6] os_md.xyang(2,[1,1],0,0|prec=1);/* 円 ：誤差 1/3600 以下 */\draw (3,1) .. controls (3,2.105) and (2.105,3) .. (1,3).. controls (-0.105,3) and (-1,2.105) .. (-1,1) .. controls (-1,-0.105)
and (-0.105,-1) .. (1,-1) .. controls (2.105,-1) and (3,-0.105) .. cycle;[7] P=[0,0]$Q=[2,1]$R=[0,1]$S=[4,0]$/* 4 点 P, Q, R, S を定義 */[8][9][10][11][12] T=os_md.ptcommon([P,Q],[R,S]);/* T : PQ と RS の交点 */346[4/3,2/3][13] SS=os_md.xyang(0.3,T,P,S|opt="red")+os_md.xyline(P,Q)+os_md.xyline(R,S)$[14] os_md.xyproc(SS|dviout=1)$/* PQ, RS, 角 PTQ を描く */[15] U=os_md.ptcommon([R,S],[P,0])$/* U : P から RS に下ろした垂線の足 */[16] SS=os_md.xyang(0.3,T,P,1)+os_md.xyline(P,T)+os_md.xyline(R,S)$[17] os_md.xyproc(SS|dviout=1)$/* P から RS に下ろした垂線を描く */[18] os_md.xyproc(os_md.xyang(0.2,Q,P,2|ar=1)|dviout=1)$/* 矢印 */
[19] os_md.xyproc(os_md.xyang(0.2,Q,P,3|ar=1)|dviout=1)$[20] os_md.xyproc(os_md.xyang(0.2,Q,P,4|ar=1)|dviout=1)$[21] os_md.xyproc(os_md.xyang(0.2,Q,P,0|ar=1)|dviout=1)$[22] os_md.xyproc(os_md.xyang(0.2,Q,P,-2|ar=1)|dviout=1)$[23] os_md.xyproc(os_md.xyang(0.2,Q,P,-3|ar=1)|dviout=1)$[24] os_md.xyproc(os_md.xyang(0.2,Q,P,-4|ar=1)|dviout=1)$[25] os_md.xyproc(os_md.xyang(0.3,Q,P,5|ar=1)|dviout=1)$ /* 曲がった矢先 */[26] os_md.xyproc(os_md.xyang(0.3,Q,P,6|ar=1)|dviout=1)$[27] os_md.xyproc(os_md.xyang(0.3,Q,P,7|ar=1)|dviout=1)$[28] os_md.xyproc(os_md.xyang(0.3,Q,P,8|ar=1)|dviout=1)$[29] os_md.show(os_md.xyang(0.3,Q,P,7|ar=3,opt="fill"))$/* 塗りつぶし */[30] os_md.show(os_md.xyang(0.3,Q,P,20|ar=3,opt="fill"))$ /* 20 度 */453. xyoval(p,r,q|opt=t,arg=[t1 ,t2 ,t3 ],deg=[t1 ,t2 ,t3 ],scale=r,ar=1,prec=1,dviout=1,
proc=1):: XY-pic/TikZ で p を中心として，軸の長さが r と qr の楕円またはその弧や扇形を描く• 点 p を中心に，基準軸の半径が r, それに直交する軸の半径が qr の楕円を描く• 楕円の基準軸の偏角は t3 で指定する. この指定がないときは t3 = 0 とみなされる．
• 楕円の基準軸方向から，パラメータが t1 と t2 の間の部分の弧を描く．
この場合，ar=1 を指定すると扇形が描かれる．
t1 = t2 または指定がないときは，楕円全体が描かれる．



cos t
cos t3sin t3p+r(t ∈ [t1 , t2 ])− sin t3 cos t3
q sin t• t1 , t2 , t3 の指定はラジアン (Ang) または角度（deg）．
• opt=t : xylines() におけるオプションと同じ意味．
• proc=1 : 描画実行形式の要素を返す．
[0] os_md.xyoval([0,0],1,1/2|arg=[2*@pi/3,7*@pi/3,@pi/8],scale=10,opt=0);347

[[-6.27647,2.0871],[-10.6562,-1.40948],[-10.451,-5.23007],[-5.84741,-5.90082],
1,[-1.2438,-6.57157],[5.5263,-3.7673],[8.30725,-0.0377664],1,[11.0882,3.69177],[8.53175,6.53844],[2.96233,5.91393]][1] os_md.xyoval([0,0],1,1/2|arg=[2*@pi/3,7*@pi/3,@pi/8],scale=10);{(-6.276,2.087);(-5.847,-5.901)**\crv{(-10.656,-1.409)&(-10.451,-5.23)}};{(-5.847,-5.901);(8.307,-0.038)**\crv{(-1.244,-6.572)&(5.526,-3.767)}};{(8.307,-0.038);(2.962,5.914)**\crv{(11.088,3.692)&(8.532,6.538)}};[3] os_md.dviout0([0,6])$[4] os_md.xyoval([0,0],1,1/2|dviout=1)$[5] os_md.xyoval([0,0],1,1/2|arg=[2*@pi/3,7*@pi/3,@pi/8],dviout=1)$[6] os_md.xyoval([0,0],1,1/2|arg=[2*@pi/3,7*@pi/3,@pi/8],ar=1,dviout=1)$[7] os_md.xyoval([0,0],1,1/2|opt="red",dviout=1)$454. xygrid([x,tx ,ux ,mx ,sx ],[y,ty ,uy ,my ,sy ]|raw=r,shift=[sx ,sy ]):: （対数）方眼紙の描画• 横 x，縦 y の方眼紙を作成する（xyproc() の引数の形で返す）．tx , ty は，0 のときは通常の目盛，
1 のときは対数目盛, −1 のときは逆対数目盛とし，ux , uy は，単位の長さ，mx , my は最小の目盛線の間隔とする．
色付けなどを考慮すると TikZ を利用するのが好ましいので，以下ではそれを念頭に例を述べる（長さの単位は cm となる．dviout0(1|opt="TikZ") によってXY-pic でなくて，TikZ 対応となる）．
• tx , ty は直接 0 からの数字のリストとして指定してもよい（mx , my は無視される）．scale() の返り値の形でもよい．
• 目盛線は，横，縦共に 3 段階で，線種はそれぞれ sx , sy で文字列指定する．3 段階で変えるとき
は，文字列 3 つのリストで，小さい目盛線，中間の目盛線，大きい目盛線の順に指定する．3 段階以外も可能．
• 通常の目盛のときは，単位の長さを，細分なし，2 等分，または 5 等分，または 10 等分まで，最小間隔以上という条件で細かく取る．10 等分のときは，2 等分を 2 段階目の線種とする．あるいは，mx , my を scale() の引数の形（リスト）で指定してもよい．
• 対数目盛のときは，1 から 2 まで，2 から 5 まで，5 から 10 までに分けて（1 から 10 までの間隔が単位の長さ），それぞれ細分なし，2 等分，5 等分，10 等分のいずれかで，最小間隔以上という条件で，細かく取る．10 等分のときは，2 等分を中間の線種とする．あるいは，mx , my を scale()の引数の形（リスト）で指定してもよい．
• shift=[sx ,sy ] によって描画位置の原点を移動できる（左下隅が原点）．
• たとえば，五線譜の用紙を描くには y =22.4, ty =[0,0.2,0.4,0.6,0.8], uy =2.5, tx =[] などとすればよい．
• raw=1 : 縦線の位置（3 段階），横線の位置（3 段階）の組のリストを返す．
• raw=2 : 上を，xylines() の引数のリストの組として返す．

[0] L=["blue!20","blue!35","blue!50"]$/* [最小目盛の線種，中間目盛の線種, 通常目盛の線種] */[1] X=[10,0,2,0.15,L]]$ Y=[3,0,2,0.15,L]]$/* [方眼紙のサイズ（横/縦 cm），0: 等間隔か 1: 対数目盛か，一つのユニットの大きさ (cm),348細分したときの最小幅（cm），線種] */[2] S0=xyproc(os_md.xygrid(X,Y))$/* 2mm 方眼紙 */[3] U=[12,1,3,0.03,L]$ V=[3,1,3,0.03,L]$ W=[3,-1,3,0.03,L]$[4] S1=os_md.xyproc(os_md.xygrid(U,Y))$/* 片対数方眼紙 */[5] S2=os_md.xyproc(os_md.xygrid(U,V))$/* 両対数方眼紙 */[6] S3=os_md.xyproc(os_md.xygrid(U,W))$/* 左上原点両対数方眼紙 */S0, S1, S2, S3 は方眼紙の TEX のソースとなる．

455. xycircuit(p,s|scale=r,opt=t,at=k,rev=1):: 電気回路を描く
R, C, L などを使った電気回路を描く．
「p=[[x0 ,y0 ],[x1 ,y1 ]] としたとき，この 2 点を結ぶ線分を信号線としてそこに s で示される素子を描く」ということが基本• scale=r : 素子の大きさを r 倍する．
• s="R" : R（抵抗）．幅のデフォルトは 23 ．TikZ では，opt="red"などが指定可能．
• s="VR" : 可変抵抗．幅のデフォルトは 23 ．
• s="RT" : 半固定抵抗．幅のデフォルトは 23 ．
• s="VR3" : 可変抵抗（3 端子）．幅のデフォルトは 23 ．3 端子目は信号線から 12 幅がデフォルト．
• s="RN" : 抵抗（新記号）．幅のデフォルトは 23 ．

349

• s="VRN" : 可変抵抗（新記号）．幅のデフォルトは 32 ．
• s="RNT" : 半固定抵抗（新記号）．幅のデフォルトは 23 ．
• s="RN3" : 可変抵抗（3 端子）．幅のデフォルトは 23 ．3 端子目は信号線から 12 幅がデフォルト．
• s="C" : C（キャパシタ：コンデンサ）．幅のデフォルトは 0.15．
• s="VC" : 可変コンデンサ．幅のデフォルトは 0.15．
• s="CT" : 半固定コンデンサ．幅のデフォルトは 0.15．
• s="C+" : 極性つきコンデンサ（電解コンデンサ）．幅のデフォルトは 0.15．
• s="C-" : 極性なしコンデンサ（電解コンデンサ）．幅のデフォルトは 0.15．
• s="L" : L（インダクタ：コイル）．幅のデフォルトは 1.
• s="VL" : 可変コイル．幅のデフォルトは 1．
• s="LT" : 半固定コイル．幅のデフォルトは 1．
• s="Cell" : 電池記号．幅のデフォルトは 0.1.
• s="Cell2" : 電池を 2 つ並べた記号．幅のデフォルトは 0.3.
• s="Cells" : 電池を複数並べた記号．幅のデフォルトは 0.6.
• s="D" : ダイオード• s="PNP" : PNP 型トランジスタ．幅は 0.6, Base 端子は信号線から 0.6 幅がデフォルト（以下ト
ランジスタは同じ．

• s="NPN" : NPN 型トランジスタ• s="PNP0" : PNP 型トランジスタ（IC 内）• s="NPN0" : NPN 型トランジスタ（IC 内）• s="JN" : 接合型 N チャンネル FET トランジスタ• s="JP" : 接合型 P チャンネル FET トランジスタ• s="E" : アース記号（シャーシー）．幅のデフォルトは 0.1.
• s="EE" : アース記号（地面）．幅のデフォルトは 1.5.
• s="circle" : 円．直径のデフォルトは 1．
• s="Sw" : スイッチ．幅のデフォルトは 0.5．
• s="arrow" : (x0 , y0 ) から (x1 , y1 ) への矢印を描く．TikZ では opt="|->"などが指定可能．
• s="gap" : 交差しない線分を描く．半円の直径のデフォルトは 0.3.
• 以上において，p=[x,y] とすると，(x, y) を始点として素子を描画する．
• s="" : 2 点を結ぶ線分を描く．
• s=["str"]: このとき p=[x,y] とすると，(x, y) に文字列 str を置く．
p=[[x1 ,y1 ],[x2 ,y2 ],. . .] とすると．(x1 , y1 ), (x2 , y2 ), . . . の文字列 str を置く．
• at=k : 素子を (x0 , y0 ) と (x1 , y1 ) を両端とする線分の k : 1 − k の内分点に置く（デフォルトは
k = 12 ）．
• s="circle"で at=1,scale=0.1 と指定すると端子が描かれる．
• rev=1 : 可変抵抗や可変コンデンサの矢印を，回路の向きに対称なものにする．なお，[x0 ,y0 ] と[x1 ,y1 ] を入れ替えると，180 度回転したものになる．
[0] P=[[0,0],[0,2]]$Q=reverse(P)$[1] os_md.show(os_md.xycircuit(P,"R"));[2] os_md.show(os_md.xycircuit(P,"VR"));[3] os_md.show(os_md.xycircuit(P,"RT"));[4] os_md.show(os_md.xycircuit(P,"VR3"));[5] os_md.show(os_md.xycircuit(P,"NR"));[6] os_md.show(os_md.xycircuit(P,"VNR"));[7] os_md.show(os_md.xycircuit(P,"NRT"));[8] os_md.show(os_md.xycircuit(P,"NR3"));[9] os_md.show(os_md.xycircuit(P,"C"));350

[10] os_md.show(os_md.xycircuit(P,"VC"));[11] os_md.show(os_md.xycircuit(P,"CT"));[12] os_md.show(os_md.xycircuit(P,"C+"));[13] os_md.show(os_md.xycircuit(P,"C-"));[14] os_md.show(os_md.xycircuit(Q,"L"));[15] os_md.show(os_md.xycircuit(Q,"VL"));[16] os_md.show(os_md.xycircuit(Q,"LT"));[17] os_md.show(os_md.xycircuit(P,"Sw"));[18] os_md.show(os_md.xycircuit(Q,"Sw"|rev=1));[19] os_md.show(os_md.xycircuit(Q,"E"));[20] os_md.show(os_md.xycircuit(Q,"EE"));[21] os_md.show(os_md.xycircuit(Q,"circle"|scale=0.5));[22] os_md.show(os_md.xycircuit(Q,"gap"));[23] os_md.show(os_md.xycircuit(Q,"circle"|scale=0.1,at=1));[24] os_md.show(os_md.xycircuit(Q,"Cell"));[25] os_md.show(os_md.xycircuit(Q,"Cell2"));[26] os_md.show(os_md.xycircuit(Q,"Cells"));[27] os_md.show(os_md.xycircuit(Q,"D"));[28] os_md.show(os_md.xycircuit(Q,"NPN"));[29] os_md.show(os_md.xycircuit(Q,"PNP"));[30] os_md.show(os_md.xycircuit(Q,"NPN0"));[31] os_md.show(os_md.xycircuit(Q,"PNP0"));[32] os_md.show(os_md.xycircuit(Q,"JN"));[33] os_md.show(os_md.xycircuit(Q,"JP"));[32] L=os_md.xycircuit([[0,1.7],[0,-0.2]],"L")$[33] R1=os_md.xycircuit([[0,1.4],[0,3.2]],"R")$[34] R2=os_md.xycircuit([[-1,0],[-1,3]],"R")$[35] C=os_md.xycircuit([[1,-0.5],[1,3]],"C")$[36] L1=os_md.xycircuit([[-1,0],[1,0]],"")$[37] L2=os_md.xycircuit([[-1,3],[1,3]],"")$[38] S=os_md.xycircuit([[0,0],[0,3]],["\\bullet"])$[39] show(L+R1+C+R2+C+L1+L2+S)$[40] W=[[-1.5,0],[0,-1.5],[1.5,0],[0,1.5],[-1.5,0]]$[41] for(S="",TW=W;length(TW)>1;TW=cdr(TW)) S+=os_md.xycircuit([TW[0],TW[1]],"R")$[42] show(S+os_md.xycircuit([W[0],W[2]],"circle"))$
R

VR

RT

VR3

NR

VNR NRT NR3

351

C

VC

CT

C+

C−

L

VL

LT

Sw

Sw

E

EE

circlegap

circle

Cell

Cell2

Cells

D

NPN

PNP

•
NPN0

PNP0

JN

JP

•
456. xypoch(w,h,r1 ,r2 |ar=r):: Pochhammer の cycle を描く• w : 2 点間の距離• h : 隣接した線の間隔• r1 : 小円の半径• r2 : 大円の半径• r : 矢印の大きさ（デフォルト 0.25cm，0 とすると描かない)[1] os_md.xypoch(7,0.3,0.7,1);/* 2 点は 7cm 離れ，それらをつなぐ線の間隔は 0.3cm，点中心の円の半径は 0.7cm と 1cm */

×

•

×

457. xyplot([[a1 ,b1 ],[a2 ,b2 ],. . .],[x0 ,x1 ],[y0 ,y1 ]|opt=t,ax=[x0 ,y0 ,s,t,u],axopt=[w,h,o,z],
scale=r,to=[W ,H],dviout=1,view=v,raw=1):: 与えられた点のリストをプロットして順につなぐ• オプションパラメータの意味は xygraph() におけると同じ．
• view=v を指定すると，（つながずに）キャンバスに点を表示する．v は色コードまたは色を表す文
字列（cf. trcolor()）で，0 は黒．このときの戻り値は [x0 ,x1 ],[y0 ,y1 ].
at=1 を指定すると可能なら軸を描く．at=2 とすると，可能ならスケールを入れる．
• [x0 ,x1 ] や [y0 ,y1 ] を指定しないで 0 を指定すると，データからそれらが入るように自動的に計
1算する．view=v を指定したときは，四隅に少し空きを置く（画面サイスの 32ずつ）．
このとき raw=1 を指定すると，[[x0 ,x1 ],[y0 ,y1 ]] が返される．
• to=[W ,H] : r= でスケーリングを指定しない場合，横 W , 縦 H のサイズ（TikZ の時は cm 単位）になるように，スケーリングが自動設定される（デフォルトは W = 12, H = 8）．
[0] for(R=[],I=0;I<=2*3.1415;I+=0.01) R=cons([I,dsin(I)],R);[1] S=os_md.xyplot(R,0,0|view="red",ax=1);[[-0.19625,6.47625],[-1.0625,1.0625]]352

458. xyaxis([x0 ,y0 ,s,t,u],[x1 ,x2 ],[y1 ,y2 ]|scale=r,opt=t,axopt=[h,w,o,z],view=1):: 座標軸の描画• xygraph() での座標軸描画に準じる．
• (x0 , y0 ) : 座標軸の原点の座標• [x1 ,x2 ],[y1 ,y2 ] : 窓の x 座標，y 座標の範囲• s, t : x 軸，y 軸の目盛りの間隔• view=1 : glib のキャンバスに描く．s, t が指定されて 0 でなければ目盛りも振る．
• view=6 : 上と同じだが，座標の目盛りの数字を振る• view=2 : 上と同じだが，x 座標の目盛りの数字のみ振る• view=4 : 上と同じだが，y 座標の目盛りの数字のみ振る
459. xygraph(f ,n,[t1 , t2 ],[x1 ,x2 ],[y1 , y2 ]|opt=t,rev=1,ax=[x0 ,y0 ,s,t,u],axopt=[h,w,o,z],
scale=r,ratio=c,raw=1,org=[x0 ,y0 ],pt=[p1 ,p2 ,...],verb=1,para=1,prec=v,shift=[u,v],
Acc=1,dviout=t,proc=p):: 変域の n 等分点での値で関数のグラフを描く（t1 ≤ x ≤ t2 ，(x1 , y1 )–(x2 , y2 ) は表示窓の範囲）• 点を繋ぐのは xylines() を curve=1 のオプションで用いる．
• 変数は x で，さらに x1 < x2 ，y1 < y2 でなければならない．
• f は [f1 ,f2 ] の形のパラメータ表示でもよい．
• para=1 : f が [f1 ,f2 ] のパラメータ表示であることを明示する．
• f や前項の f1 , f2 は有理函数や sin(x) などの初等関数に限らず，mydeval() が解釈できる函数ならばよい．よってユーザが定義した函数や，Γ 函数などのように pari() 経由でサポートされた函数でもよい．
• f1 が有理式で f2 がリスト形式の函数のときは，para=1 としてパラメータ表示であることを明示する必要がある．
• 変数を x でなくて t とするときは，[t1 ,t2 ] でなくて [t,t1 ,t2 ] と指定する．
• x1 = t1 , x2 = t2 のときは，第 4 引数 [x1 ,x2 ] を 0 と指定してもよい．
• rev=1 : x = f (y) のグラフとみなす．
• (x1 , y1 ) と (x2 , y2 ) で定まる窓から外れる点は除く．
• n = 0 と指定したときは，n = 32 とみなす．
• n < 0 のときは，|n| 等分した区間の両側の 1 区間外に制御点をとる．
• n 等分点でなくて点を直接指定するときは，[t1 ,t2 ] でなくて [t1 ,t2 , . . . , tm ] のように指定する（なお，t1 , . . . , tm は単調増加な実数列．さらに最初を実数でなく，変数の指定としてもよい）．
n が負の時は，最初と最後の点 t1 , tm は制御点とする．
• prec=[v1 ,v2 ,v3 ] : 折れ線で繋ぐと角度が v2◦ 以上の分割点の両側を 2 つに細分することを v1 ス
テップ行い，さらに v3 > 0 のとき，窓の対角線の長さの v3 分の 1 以上の跳びを不連続点とみなす．
– v2 = 1 のときは v2 = 30 と解釈され，1 < v2 < 10 のときは v2 = 10 と解釈され，v2 > 120のときは v2 = 120 と解釈される．
– v3 = 0 のときは，不連続点はないものと解釈する．
– v3 = 1 のときは v3 = 16 と解釈され，v3 > 512 のときは v3 = 512 と解釈される．

353

– prec=[v1 ,v2 ] は，prec=[v1 ,v2 ,0] と解釈される．
– prec=v1 は, v1 = 0 のとき prec=[4,30,0] と, v1 > 0 のとき prec=[v1 ,30,0] と，v1 < 0のとき prec=[|v1 |,30,16] と解釈される．
• opt=t : 線種の指定など（xylines() に渡される）．
• opt=0: 曲線を xybezier() の引数のデータ形式で返す．
• ratio=c : Bézier 曲線を使うときのパラメータ（xylines() に渡される）．
• ax=[x0 ,y0 ] : (x0 , y0 ) を原点として x 軸と y 軸を窓内に描く．
窓内に現れない軸は描かないので，それを利用して一方の軸のみの描画ができる．

• ax=[x0 ,y0 ,s,t] : s が正数なら，x 軸に原点から s 毎に目盛をつける．
目盛をつける位置を指定するときは s = [s1 , s2 , . . . ] と原点からの x 座標の位置を書く．
sj =[sj,0 ,sj,1 ] となっていると sj,0 の位置に目盛をつけて，そこに sj,1 を書く．
t で同様に y 軸の目盛の指定ができる• ax=[x0 ,y0 ,s,t,u] : s, t が数字で u が 1 と 2 とすると，目盛が ax=[x0 ,y0 ,s,t] に従ってつけられ，u に従ってそこに数字が書かれる．u = 0 のとき k 番目の位置の x 軸には ks + x0 が y 軸には
kt + y0 が書かれ，u = 1 のとき k 番目の位置の x 軸には ks が y 軸には kt が書かれ，u = 2 のと
き k 番目の位置に k が書かれる．
• axopt=z : z が文字列の時は x 軸と y 軸の線種指定文字列（デフォルトは実線で XY-pic のとき
は"@-"）．
• axopt=h : h が 0 以外の数字の時は，目盛の軸からの長さを与える．
値が負の時は軸から負方向（x 軸なら下，y 軸なら左）の目盛．
• axopt=[h,w,o,z] : 軸や目盛の描き方の指定– h =[h0 ,h1 ] または h =[h0 ,h1 ,h2 ] のとき x 軸の目盛の高さを h0 から h1 までとする（XY-pic/TikZ の mm/cm 単位）．
h2 は文字列で，目盛位置に文字などを置く位置指定（デフォルトは下 "+!U"/"below"）．
h が 0 でない数字なら，h0 = 0, h1 = 1 と解釈される（h = 0 のときはデフォルトのまま）．
– w =[w0 ,w1 ] または w =[w0 ,w1 ,w2 ] のとき y 軸の目盛の幅を w0 から w1 までとする（XY-pic/TikZ の mm/cm 単位）．
w3 は文字列で，目盛位置に文字などを置く位置指定（デフォルトは左 "+!R"/"left"）．
w が数字なら，w0 = 0, w1 = 1 と解釈される（w = 0 のときはデフォルトのまま）．
– o が文字列のとき，x 軸の原点に文字を置く位置指定（デフォルトは左下 "+!UR"/"below
left"）．
o が文字列でなければ無視される．
– z : x 軸と y 軸の線種指定文字列（デフォルトは実線で XY-pic のときは "@-"）．
– z または z と o を省略可能．
• pt=[p1 ,p2 ,...] : （複数の）点を明示するまたは線を描く．仕様は xy2graph() の同様なオプションに習う．

• scale=r : XY-pic/TikZ の座標に直すときに r 倍する．
• scale=[r1 ,r2 ] : XY-pic/TikZ の座標に直すときに x 座標を r1 倍，y 座標を r2 倍する．
• org=[x0 ,y0 ] : XY-pic/TikZ の座標に直すときに (x0 , y0 ) をXY-pic/TikZ の原点に対応させる．
上の両者が指定されたとき，座標 (x, y) は XY-pic/TikZ の座標 (r1 (x − x0 ), r2 (y − y0 )) に変換される．

• raw=1 : 通過点のリストを返す (他のオプションは無視される)．
これは xylines() のデータとなり，また ptaffine() でアフィン変換が計算できる．
なお，範囲外の点は 0 というデータに変換される．
• f =[0,0] のときはグラフを描かない．座標軸のみを描くときに用いる．
• err=c : 函数の定義域を外れるエラーが生じるときは，c = 1, c = −1 などとしてこのオプションを指定すると，エラーが解消される可能性がある（c は絶対値があまり大きくない実数）．
• verb=1 : グラフ上の通過点を •，制御点を × で表示する．
• verb=[t1 ,t2 ] , verb=[t1 ]: グラフ上の通過点や制御点の描き方を指定する（cf. xylines()）．

354

• proc=1 : execdraw() の描画実行形式を返す．
• proc=2 : 上と同様であるが，Windows サイズの情報は含めない．
• proc=3 : 描画実行形式の関数描画成分を返す．
• dviout=1 : グラフを TEX を用いて画面表示する．
• dviout= t : t がリストのとき，execdraw() を用いて処理する．t は execdraw(ℓ,t) の 2 番目の引数に対応する．このとき ext=[a,b],cl=1 の execdraw() のオプションも指定可能．
最も簡単な指定は dviout=[0], あるいは dviout=[[0,[500,400]],0] など．
XY-pic のときは[0] os_md.xygraph(x^2,0,[-1.5,1.5],[-1.5,1.5],[-0.5,2.3]|dviout=1,ax=[0,0,1,1,1],scale=10);[1] os_md.xygraph(x^3,0,[-1.2,1.2],[-1.2,1.2],[-1.5,1.5]|dviout=1,ax=[0,0,1,1],axopt="@{.}",scale=10);[2] os_md.xygraph(1/x,0,[-3,3],[-3,3],[-3,3]|dviout=1,ax=[0,0],scale=5);[3] F=[(1+cos(x))*cos(x),(1+cos(x))*sin(x)]$[4] os_md.xygraph(F,0,[-@pi,@pi],[-0.5,2.5],[-1.5,1.5]|dviout=1,scale=10,
ax=[0,0]);
一方，TikZ のときは，上は[0] os_md.xygraph(x^2,0,[-1.5,1.5],[-1.5,1.5],[-0.5,2.3]|dviout=1,ax=[0,0,1,1,1]);[1] os_md.xygraph(x^3,0,[-1.2,1.2],[-1.2,1.2],[-1.5,1.5]|dviout=1,ax=[0,0,1,1],axopt="dotted");[2] os_md.xygraph(1/x,0,[-3,3],[-3,3],[-3,3]|dviout=1,ax=[0,0],scale=0.5);[3] F=[(1+cos(x))*cos(x),(1+cos(x))*sin(x)]$[4] os_md.xygraph(F,0,[-@pi,@pi],[-0.5,2.5],[-1.5,1.5]|dviout=1,ax=[0,0]);となる．
以下，XY-pic の場合の例であるが，TikZ の場合は（前者は mm 単位，後者は cm 単位なので）scale=の値を十分の一に，[9] の opt="~*=<3pt>{.}" を opt="dotted" に，[10] の opt="~*={.}" を
opt="very thick" などに変更する．

2
1
−1

0

1

[5] F1=[sin(2*x),sin(3*x)]$[6] os_md.xygraph(F1,-48,[-@pi,@pi],[-1.2,1.2],[-1.2,1.2]|dviout=1,scale=15,
ax=[0,0])$[7] F2=[sin(4*x),sin(3*x)]$[8] os_md.xygraph(F2,-48,[-@pi,@pi],[-1.2,1.2],[-1.2,1.2]|dviout=1,scale=15,
ax=[0,0],opt="~*=<3pt>{.}")$[9] os_md.xygraph(F2,-48,[-@pi,@pi],[-1.2,1.2],[-1.2,1.2]|dviout=1,scale=15,355

ax=[0,0],opt="~*={.}")$.......... . . . .
... . . .............
..... ................. ...
.....
.
.
.. .... ..... ...... ...... ...
....
... .........
.
.
... .... .... ..... ..... ....
...
...
...
......
... ..... .........
..... ..
... .........
.. .... ....
.. .. .
.. .... .... ..
. ..
.. ....... ............... .........
.. . . .......................... . . ..

............................................................................................................
........
.................
........
. ..
... ..
...
.... .......... ............ .............. ......... .....
.
... ...........
.
.
.
.
.
... ..... ......... ........... ......... ....
...........
.
.....
.
.....
..
.. ...
... .....
....... ............ ........ .....
........
.... ..................
.
... ....... ......... ......... ........ ...
..............
.......
........
... ...
.. ....
........ ........
.......................................................................................................

y = | sin(x)| (0 ≤ x ≤ 10) のような微分不可能点をもつ曲線を描くにはオプション prec を用いる．
[10] F=os_md.abs(sin(x))$[11] os_md.xygraph(F,-32,[0,10],[0,10],[0,1]|dviout=1,scale=[15,25])$[12] os_md.xygraph(F,-32,[0,10],[0,10],[0,1]|dviout=1,scale=[15,25],prec=0)$

微分可能でない点の近くでは不正確であるが，prec=0 を指定すると以下のようにより正確になる．

この例では，[0, 10] を 32 等分した関数の値から 32 本の cubic Bézier 曲線を繋げた近似から，不連続点の近くで自動的に細分して 63 本の cubic Bézier 曲線を繋げたものになった．
y = |2 sin(x)| − floor(|2 sin(x)|) (0 ≤ x ≤ 5) のような不連続点をもつ曲線を描くにもオプション
prec を用いる．ここで floor(t) は t を越えない最大整数を表す．

[13] G=[u,[v,dsin,x],[w,os_md.abs,2*v],[z,dfloor,w],[u,0,-z+w]]$[14] os_md.xygraph(G,-32,[0,5],[0,5],[0,1]|dviout=1,scale=20)$[15] os_md.xygraph(G,-32,[0,5],[0,5],[0,1]|dviout=1,scale=20,prec=0)$[16] os_md.xygraph(G,-32,[0,5],[0,5],[0,1]|dviout=1,scale=20,prec=[4,0,1])$の実行結果は以下のようになる．すなわちオプション prec を指定しない場合 [14] は356

となり，prec=0 のとき [15] はとなり，prec=-4 または prec=[4,0,1] のとき [16] は以下のようになる．

この例では，最初 32 本の cubic Bézier 曲線で描かれていたものが，最終的には 70 本の cubic Bezierに分割された．

[17] H=[w,[z,os_md.zeta,1/2+@i*x],[w,os_md.abs,z]]$[18] os_md.xygraph(H,-64,[0,60],[0,60],[0,4]|dviout=1,scale=[2.5,10],prec=6,
ax=[0,0,10,1,1])$√とすると |ζ( 12 + x −1)| (0 ≤ x ≤ 60) のグラフが得られる．
4
3
2
1

0

10

20

30

40

50

60

この例では，[0, 60] の 96 等分割から自動的に 355 分割に細分した関数値を得て描かれている．

Risa/Asir のキャンバスでの表示は，たとえば次のようにする（以下の [22] では，重ね書きをしている）．

[19] dviout0([0,5,6])$
DVIOUTA="%ASIRROOT%\bin\risatex1%TikZ%.bat"
TikZ=1[20] W=[-1.2,1.2]$[21] P=os_md.xygraph(F1,-48,[-@pi,@pi],W,W|dviout=[0],ax=[0,0])$[22] os_md.xygraph(F2,-48,[-@pi,@pi],W,W|dviout=[P],opt="red,dotted")$[23] S=600$/* 窓のサイズ */[24] os_md.xygraph(F2,-48,[-@pi,@pi],W,W|dviout=[[0,[S]],ax=[0,0])$
その他の例を挙げる．

357

[25] G=[1/7*x-1/2*cos(x),sin(x)]$/* バネ・コイル */[26] os_md.xygraph(G,-63,[0,21*@pi],[-1,10],[-2,2]|scale=0.3,dviout=1)$[27] F=os_md.cutf((1-x^2)^3,x,[[-1,0],[],[1,0]])$ /* 1 つの波 */[28] G=os_md.periodicf(F,[-4,4],x)$/* 周期的拡張 */[29] G1=subst(G,x,x-t-2)$/* 進行波 */[30] G2=subst(G,x,x+t+2)$/* 逆の波 */[31] H=os_md.compdf(x-y,[x,y],[G1,G2]); /* 区間 [0,4] の波，周期 8 */[32] E="\\draw (2.4,-0.6)--(2.4,-0.6);\n"$/* 右端 */
[33] for(I=1;I<2;I+=0.2) os_md.xyproc(os_md.xygraph(os_md.mysubst(H,[t,I]),-24,[0,4],0,[-1,1]|scale=[0.6,0.6],prec=6,ax=[0,10])+E|dviout=1);

これをパラパラ漫画風にする（160 ページ）．

[34] T0="\\newpage\n\\begin{tikzpicture}\n"$[35] T1="\\draw (0,-3) -- (0,3) (16,-3) -- (16,3)\n\\end{tikzpicture}\n"$[36] Tb=os_md.str_tb(0,0)$[37] for(I=0;I<8;I+=1/20) os_md.str_tb(T0+os_md.xygraph(os_md.mysubst(H,[t,I]),-24,[0,4],0,[-1,1]|scale=[4,3],prec=6)+T1,Tb);[38] dviout(os_md.str_tb(0,Tb))$
460. xy2graph(f ,n,[x1 ,x2 ],[y1 , y2 ],[h1 ,h2 ],α,β|opt=t,scale=r,view=h,raw=1,trans=1,
ax=[z1 ,z2 ,t],dev=m,acc=k,org=[x0 ,y0 ,z0 ],pt=[p1 ,p2 ,...],prec=v,title=s,dviout=k,
ext=[a,b],shift=[u,v],cl=1,proc=p):: x, y 変数の区間を n 等分して曲面 z = f (x, y) の 3D グラフを描く• x 軸の正方向から y 軸の正方向に α 度だけ回転した（無限）遠方から β 度 (−90 < β < 90）の角度で見下ろす方向に見た曲面 z = f (x, y) (x1 ≤ x ≤ x2 , y1 ≤ y ≤ y2 ) の 3D グラフを描く．なお，投影した高さ方向の座標（y 座標）が [h1 , h2 ] に入る範囲のみ描く．
より具体的には 3 次元の点 (x, y, z) は以下のように平面の点に投影される．
(x, y, z) 7→ (−x sin α◦ + y cos α◦ , z cos β ◦ − x cos α◦ sin β ◦ − y sin α◦ sin β ◦ )α = 0 のときは α = 60, β = 0 のときは β = 15 と解釈される．
α は 0 であるか，または 90 の整数倍とは 5 以上離れていることが必要．
通常は h1 を十分小さく，h2 を十分大きく取っておけばよい（指定した範囲の曲面全体の表示）．
• 曲面上で x 座標が定数，あるいは y 座標が定数で定まる曲線を（曲面で隠れる部分，すなわち隠線を消して）描くことで曲面を表す．定数は座標の n 等分点と定める．
n < 0 のときも |n| 等分点をとるが，その一つ外側を制御点にとる．
• f は有理函数や sin(x) などの初等関数に限らず，mydeval() が解釈できる函数ならばよい．ユー
ザが定義した函数でもよい.
• cpx=1,2,3 を指定するか f に @i が含まれていれば, mydeval() でなくて myeval() が使われる．

358

• f が 1 変数 z の有理函数ならば，z = x + yi 変数の複素函数と考え z = |f (x + iy)| のグラフを描
く. この場合 f は[w,[z,0,x+y@i],[w,os_md.abs,f]]で置き換えられる．なお，複素変数の sin(z), cos(z), tan(z), atan(z), asin(z), acos(z), sinh(z),cosh(z), tanh(z), exp(z), log(z), z w や，それらを含む合成関数や有理関数がサポートされている．

f が sin(z^2)+1 のときは
[w,[z,0,x+y*@i],[w,os_md.abs,[z__+1,[z__,os_md.sin,z^2]]]]のように置き換えられる．
|Γ(z)| のグラフを描くときは，たとえば f を以下のように取ればよい．

[w,[z,0,x+y*@i],[u,os_md.gamma,z],[w,os_md.abs,u]]
このときタイトルの函数は title="\\Gamma(z)" というオプションで表示できる．
• scale=r : 表示するために XY-pic/TikZ の座標に直すときに r 倍する．
• scale=[r1 ,r2 ] : 元の曲面の z 座標を rr21 倍したものを平面に投影したあと，表示するため
XY-pic/TikZ の座標に直すときに座標の単位を r1 倍する．
• scale=[r1 ,r2 ,r3 ] : 元の曲面の z 座標を rr21 倍，y 座標を rr31 したものを平面に投影したあと，表示するため XY-pic/TikZ の座標に直すときに座標の単位を r1 倍する．
• org=[x0 ,y0 ,z0 ] : 元の座標の (x0 , y0 , z0 ) を XY-pic/TikZ の座標での原点にする（デフォルトでは原点が原点に対応）．
• |n| が大きいと TEX のソース・ファイルが長大になり，ソース・ファイルから dvi ファイルや pdf
ファイルへの変換に時間がかかることがあるので注意．
n = −16 がデフォルト（n = 0 とするとデフォルト値と解釈される）．
• view=1 : 陰線消去を行わない．
view=-1 : 陰線は点線で表示する．
• raw=1 : 通過点のリストを返す．
• dev=m : 陰線消去のためのメッシュを，x 変数, y 変数とも m × |n| 等分したものとする（デフォルトは m = 16）．ただし dev=[m1 , m2 ] とすると，m2 は出力される x 座標のメッシュの細かさ，
m1 は曲線間にとるメッシュの細かさ，と別に指定することができる．
• |n| × m を増やすと処理時間が増える．特に f が多項式や有理函数でなくて三角関数や指数関数，
対数関数，べき函数などを含むときは注意．なお処理時間は，ほぼ |n|2 × m2 に比例．
• acc=k : 描く曲線の等分点の個数を約 k 倍にする（k は実数．曲線の本数は不変）．k = 2 なら n
を 2 倍にして dev を半分にした場合の曲線を一本おきに描くことにほぼ等しい（結果のファイル・
サイズは，n2 × k にほぼ比例）．
• err=c : 有理函数の分母が 0 になるなどの，函数の定義域を外れるエラーが生じるときは，c = 1,c = −1 などとしてこのオプションを指定すると，エラーが解消される可能性が大きい（c は絶対値があまり大きくない実数）．
• prec=v : xygraph() の同様のパラメータと同じ．
• ax=[z1 ,z2 ] : x, y, z の座標が (x2 , y2 , z1 ), (x1 , y1 , z2 ) を対角線の頂点とする直方体の枠を書く，• ax=[z1 ,z2 ,t] ：上に加え，一部の頂点の座標を入れる．
– t = ±1, ±5 : 2 頂点の座標を入れる．
– t = ±2, ±6 : 4 頂点の座標を入れる．
– t = ±5, ±6 : 座標の文字を小さくする．
– t = 0, −8 : 頂点の座標を入れない．
– t < 0 : 直方体の後ろ側の枠を点線で描く（デフォルトは実線）• 複素変数の実数値函数のときに座標を入れる形式は，(x, y, z) = (1, 2, 3) の場合に
– cpx=1 : (1 + 2i, 3) （デフォルト）√– cpx=2 : (1 + 2 −1, 3)359

– cpx=3 : (1, 2, 3)• opt=u : 曲面内の曲線を描くときのオプション文字列を指定する．表側と裏側で変更するときは
opt=[u1 ,u2 ] と，表側，裏側の順に指定する．
TikZ のときは，さらに直方体の枠を描くときのオプション文字列が指定できる．
たとえば TikZ で opt=["black","red","blue"] とすれば，表側を黒，裏側を赤，枠を青で描く．
• title=s : 画面表示するとき，函数名が s で表示される（s は TEX の数式モードでの文字列 ）．函数がリスト形式のときの函数名表示に役立つ．

• pt=[p1 ,p2 ,...] : （複数の）点を明示する，あるいは線を引く．
– pi =[xi ,yi ,zi ] とすると (xi , yi , zi ) を • で明示する，– pi =[[xi ,yi ,zi ],si ] とすると，• （すなわち\bullet）でなくて s1 で明示される（si は数式モードの文字列で，\ は \\ で表す）．
– pi =[[xi ,yi ,zi ],si ,ti ] とすると，• でなくて si で明示され（si は文字列），XY-pic のとき
は，そのあとに文字列 ti を置く（si が文字列でないときは • のまま）．si が不要なときは，
si = "" とする．
TikZ のときは，ti はラベル付け文字で，si は si = [si,0 , si,2 ] というリストでよい．後に置く文字があるときは，ti の後に ti ,ui と続ける．
ti =1 は "_" というラベルを表し，その後で座標の代わり 1 または"_" で参照できる．
– 点が一つの時は，pt=p1 としてよい．
– pt=[0,0,1] : (0, 0, 1) を • で明示する．
– pt=[[0,1,2],"$\\times$"] : (0, 1, 2) を × で明示する．
XY-pic のときは
∗ pt=[[0,0,1],0," *+!D{(0,0,1)}"] : (0, 0, 1) を • で明示し，その上に (0, 0, 1) と表示する．

∗ pt=[[[0,0,1],0," *+!D{(0,0,1)}"],[[0,1,2],"$\\times$"]]] : 上 の 両 方 を 行う．

∗ pt=[[0,0,1],0,"=\"A\""] : 点 (0, 0, 1) を • で明示し，ラベル "A" をつける．
TikZ のときは上と同様なことは以下のように書ける∗ pt=[[[0,0,1],0,1],[1,["below","$(0,0,1)$"]]] : (0, 0, 1) を • で明示し，その上に (0, 0, 1) と表示する．
∗ pt=[[[0,0,1],0,1],[1,["below","$(0,0,1)$"]],[[0,1,2],"$\\times$"]]]:
上の両方を行う．

∗ pt=[[0,0,1],0,"A"] : 点 (0, 0, 1) を • で明示し，ラベル "A" をつける．
– pi =[[xi ,yi ,zi ],[x0i ,yi0 ,zi0 ]] とすると，2 点 (xi , yi , zi ) と (x0i , yi0 , zi0 ) を線で結ぶ．
– pi =[[xi ,yi ,zi ],[x0i ,yi0 ,zi0 ],ti ] とすると，2 点 (xi , yi , zi ) と (x0i , yi0 , zi0 ) を結ぶが∗ ti = 0, 1 : 実線で結ぶ∗ ti = 2 : 点線で結ぶ∗ ti = −1 : 曲面のあるところは除いて実線で結ぶ∗ ti = −2 : 曲面のあるところは除いて点線で結ぶ
さらに ti の後ろにオプション文字列 ui を書いて pi =[[xi ,yi ,zi ],[x0i ,yi0 ,zi0 ],ti ,ui ] とし，
TikZ では色や線の太さ指定などの指定が可能．
• proc=1 : execdraw() の描画実行形式を返す．
• proc=2 : 上と同様であるが，Windows サイズの情報は含めない．
• dviout=1 : 画面表示する．
• dviout=2 : ディスプレイスタイルで函数式も含めて画面表示する．
• dviout=3 : さらに視点の角度と，もとの曲面の高さや y 座標のスケールを変えたとき，その倍率を表示する．

• k が −1, −2, −3 の時は，dviout=|k| に対応する TEX のコードがリスト形式で 出力される．
リストの最後の成分は xyproc() によってグラフの TEX のソースとなる．その前の成分は函数式
360

などを表す TEX のソース，tarns=1 を指定した場合はその結果が先頭につく．
• dviout= k : k がリストのとき，execdraw() を用いて処理する．k は execdraw(ℓ,k) の 2 番目の引数に対応する．このとき ext=[a,b],shift=[u,v],cl=1 の execdraw() のオプションも指定可能．

• dviout=k : この指定が無いときは，戻り値を S したとき，xyproc(S) がグラフの TEX のコードとなる．

• trans=1 : もとの (x, y, z) 座標に対応する XY-pic/TikZ の座標 [X, Y ] を返す．具体的には
X = −r1 (x − x0 ) sin α◦ + r2 (y − y0 ) cos α◦ ,Y = r3 (z − z0 ) cos β ◦ − r1 (x − x0 ) cos α◦ sin β ◦ − r2 (y − y0 ) sin α◦ sin β ◦ .
ただし，これはオプションなどの指定が– xy2graph の第 6, 7 引数：(α, β)(α = 0 のときは α = 60, β = 0 のときは 15 と解釈される)
– scale=[r1 ,r3 ,r2 ] デフォルトは [1,1,1] となり, r2 を指定しないときは r2 = r1 で，r3 を指定しないときは r3 = r1 と解釈される．
– Org=[x0 ,y0 ,z0 ] デフォルトは [0,0,0]の場合である．
F=os_md.xy2graph( · · · |trans=1) とおくと，(x, y, z) に対応するXY-pic/TikZ での座標は

os_md.myf3deval([F],x,y,z)によって得られる．

• pdf ファイルを作成するときは，\usepackage[pdf,all]{xy}と指定して dvipdfmx などを用いるとよい．ジャギーがなく，サイズの小さな pdf ファイルが，より短い時間で作成できる．また，複雑な画像でも処理が出来る．
pdf ファイル作成と dvi ファイル作成とを切り替えるなど，異なるやり方で TEX ファイルを処理するには DVIOUTB および dviout0(4) を利用するとよい．

[0] os_md.xy2graph(x^2-y^2,0,[-1,1],[-1,1],[-2,2],0,0|ax=[-1,1,-6],scale=15,
dev=64,dviout=3)$[1] os_md.xy2graph(-x^3-y^3,-24,[-1,1],[-1,1],[-2,2],60,-35|scale=20,dev=64,
dviout=2)$z = x2 − y 2 (−1 ≤ x ≤ 1, −1 ≤ y ≤ 1)
angle (60◦ , 15◦ )z = −x3 − y 3 (−1 ≤ x ≤ 1, −1 ≤ y ≤ 1)(−1,−1,1)(1,−1,−1)(−1,1,−1)(1,1,−1)
1
上は XY-pic のときで，TikZ を用いる場合の scale の値は 10倍にする．

[2] S0=[[3.1416,0,0],0,"*+!U{(\\pi,0,0)}"]$[3] S1=[[0,0,0],0,"*+!U{(0,0,0)}"]$

361

[4] S2=[[-3.1416,0,0],0,"*+!U{(-\\pi,0,0)}"]$[5] S3=[[3.1416,0,0],[-3.1416,0,0],2]$[6] os_md.xy2graph(sin(z),-60,[-@pi,@pi],[-1,1],[-5,8],50,0|
scale=[15,45,45],ax=[0,1.543,-6],dviout=3,pt=[S0,S1,S2,S3])$
上の入力から次のグラフの描画までに，30 秒程度かかる（2014 年におけるメジャーなパソコン）．なお，有理函数のグラフなら 10 秒程度．
TikZ のときは，上の [2]，[3]，[4] [6] は次のようになる．

[2] S=[[[3.1416,0,0],0,1], [1,["below","$(\\pi,0,0)$"]]]$[3] S=append([[[0,0,0],0,1],[1,["below","$(0,0,0)$"]]],S)$[4] S=append([[[-3.1416,0,0],0,1],[1,["below","$(-\\pi,0,0)$"]]],S)$[6] os_md.xy2graph(sin(z),-60,[-@pi,@pi],[-1,1],[-5,8],50,0|dviout=3,
scale=[1.5,4.5,4.5],ax=[0,1.543,-6],pt=S,opt=["black","red","blue"])$append( ) を使わずに，os_md.m2l([S1,S2,S3]|list=1) などとする方法もある．この結果は図 2である．
図2| sin(z)|xy2graph() の例(z = x + yi, −π ≤ x ≤ π, −1 ≤ y ≤ 1)
angle (50◦ , 15◦ ) ratio 1 : 3 : 3(−π − i, 1.543)•(−π, 0, 0)(π − i, 0)•(0, 0, 0)•(π, 0, 0)(π + i, 0)362(−π + i, 0)461. xy2curve([f1 , f2 , f3 ],n,[t1 ,t2 ],[y1 ,y2 ],[z1 , z2 ],α,β|scale=r,gap=g,opt=s,eq=q,raw=w,
dviout=d):: 空間曲線の隠線処理つき描画• f1 (x), f2 (x), f3 (x) (x ∈ [t1 , t2 ]) で定義される空間曲線を x 軸の正方向を y 軸の正方向に α 度
だけ回転した無限遠方から，β 度 (−90 < β < 90）見下ろす方向に回転して，yz 平面に射影した曲線を描く．
ただし変数が x でなくて t のときは，[t1 ,t2 ] の代わりに [t,t1 ,t2 ] と書く．
描画範囲は y 座標，z 座標が区間 [y1 , y2 ]，[z1 , z2 ] の範囲（回転や以下のスケール変換後）．
• gap=g : 隠線消去の幅を g mm を基準とする．g = 0 のときは，隠線消去は行わない．デフォルトは g = 0.7.
• gap=[g,m] : 隠線消去の幅の最大値を m × g mm とする（デフォルトは m = 3）．
• scale=r : 各座標を r 倍する．
• scale=[r1 ,r2 ] : x 座標を r1 倍，y 座標と z 座標を r2 倍する．
• scale=[r1 ,r2 ,r3 ] : x 座標を r1 倍，y 座標を r2 倍，z 座標を r3 倍する．
• α が 3 行 3 列の行列の場合は，これによる線形変換に置き換える（回転やスケール変換は無視）．
• opt=s : 線種などの指定文字列（xygraph() のときと同様）. ただし gap=0 を指定しないときは，
xybezier() に渡すパラメータの形式に拡張される．
• eq=q : 空間内で q mm 以下の距離の 2 点は同じ点とみなす（デフォルトは q = 0.01）．
• dviout=1 : 画面表示を行う．
• raw=1 : TEX のソースを返す．
• raw=2 : 隠線処理後の区分 Bézier 曲線を与える座標のリストのリストを返す．
• raw=3 : 隠線処理前の区分 Bézier 曲線を与える座標のリストのリストと，交点の情報を返す．
• raw=4 : 隠線処理前の区分 Bézier 曲線を与える座標のリストのリストと，区分点などのデータを返す．
• raw=5 : 隠線処理前の回転やスケール変換後の曲線を返す．

[0] F=[cos(x),1/7*x-1/2*cos(x),sin(x)]$/* 投影したバネ */[1] os_md.xy2curve(H,-63,[0,21*@pi],[-1,10],[-2,2],0,0|dviout=1,scale=0.3);[2] G=[cos(t),t/10,sin(t)]$V=[t,0,40]$/* バネ */
[3] os_md.xy2curve(G,-96,V,[-2,6],[-4,4],30,-20|dviout=1);[4] os_md.xy2curve(G,-96,V,[-2,6],[-4,4],30,-20|dviout=1,gap=0.5);[5] os_md.xy2curve(G,-96,V,[-2,6],[-4,4],50,-25|dviout=1,opt="thick",gap=0.6);

462. execdraw(ℓ,t|shift=[u,v],ext=[a,b],cl=1):: 描画実行形式 ℓ を出力形態 t に従って実行するℓ や t はリストであるが，成分が一つの時は成分のみを指定してもよい．
t = [t0 , t1 , t2 ] は，t0 により出力先を，t1 により描画実行形式と出力先との座標との対応を，t2 により描画実行形式の原点の移動を指定する．
• t2 を指定しないときは，t = [t0 , t1 ] のように，また t1 と t2 を共に指定しないときは，t = [t0 ]のように略してよい．
• t0 が数で t1 , t2 を指定しないときは，t = t0 としてよい．
363

• cl=1 : 表示画面をクリアーしてから描画する．
出力先を指定する t0 は
• 0 : Risa/Asir におけるキャンバスを用いた描画．
リスト形式で [0] あるいは [0,[width,height]] によって新規キャンバス，または [0,index]，あるいは [0,id,index]，あるいは [0,id,index,width]，[0,id,index,width,height]，によって描画キャンバスを指定する．
– id はサーバ Id，index はキャンバス Id, width，height は pixel 単位のサイズ（cf. draw obj()）– [0,[width,height]] において width = height のときは [0,[width]] としてよい．ただし– t=[[0,[x]]] は，t=[[0,[x,x]],x] と解釈される（すなわち t1 = x）．
– execdraw([],0) は，描画画面を新規に開く．
– shift=[u,v] : 右方向に u, 上方向に v だけ pixel 単位で移動する．
– ext=[a,b] : 左側から a, 右側から b だけ pixel 単位で縮めて描く．
– ext や shift は，キャンバスに応じて描画サイズが変更されても文字列の大きさは不変であることに対処するのが主目的のオプションである．
– ℓ 中の Window の x 座標と y 座標の範囲指定が同一で，横幅 t1 と shift と ext の設定が同じであれば（t2 は設定していないか同じとする），同一キャンバスに同じ座標系で上書き表示
される．
– t = [t0 , t1 , t2 , ℓ0 ] により，別の描画実行形式 ℓ0 のものを用いることができる（t1 はキャンバ
スの横幅とする. それが t0 で指定される場合は t1 = 0 としてもよい）．
なお，ℓ0 は，キャンバスサイズとは独立した情報である．
– 戻り値は [0,id,index]，または [0,id,index,width, height]．
これは，同じキャンバスへの描画のときの t0 として用いることができる．
t1 = 0, t2 = −1 のときは，さらに 2 つの 0 と変換情報とを付加して組にしたリストが戻される．最後（4 番目）の成分は上の ℓ0 として用いることができる．また戻り値は，そのまま tとして用いることにより，同じ座標でキャンバス上に他の描画実行形式の重ね描きができる．
たとえば t は以下のようになる– 0 : Canvas で設定されたサイズのキャンバスを新規に開いて，それに合わせた横幅で表示．
[[0,[300,300]],300] や [[0,[300]]] と同じ.
– [[0,[300,400]],280] : 300 × 400 pixel のキャンバスを開き，横幅 280 pixel で表示．すな
わち，t0 = [0,[300,300]]，t1 = 280．
– [[0,[500]],0] : 500 × 500 pixel のキャンバスを開き，スケールと位置を自動調整して描画．
– [[0,[500]],0,-1] : 上と同様で，さらに調整情報も含めて返す.
– [[0,2,3],400] : サーバ Id が 2，キャンバス Id が 3 の窓に，横幅 400 pixel で表示– [[0,2,3,400,400],0] : サーバ Id が 2，キャンバス Id が 3, 400 × 400 pixel のキャンバスに，描画スケールと位置を自動調整して描画.
– [[0,2,3,400,400],0,0,T] : 上と同じであるが，調整は T に従う．
• 1 : TEX のソースを返す．
• 2 : dviout() による画面表示．
• −1 : 窓のサイズを表示してその情報を返す．
t=[-1,[x0 ,x1 ],[y0 ,y1 ],k] : 窓のサイズを再定義した ℓ を返す．
t=[-1,[x0 ,x1 ],[y0 ,y1 ],k,[a,b],[u,v]] も可能．
後者の代わりにオプション shift=[u,v],ext=[a,b] でも指定可能．
• −2 : 表示はせずに窓のサイズを返す．
• −3 : 中身を読んで描画の箱サイズを返す. 2 項目は Risa/Asir で表示の際の文字列の最大長で，その後は文字表示の箱サイズ（文字列表示があると不正確）．
• −4 : 含まれる位置情報の個数を返す．
• −5 : 含まれる実行形式の函数を返す（ℓ の第 1 成分から重複と負の数を除いたリスト）．
たとえば，delopt(ℓ,[0,1]|inv=1) とすると，描画実行形式 ℓ から第 1 成分が 0（描画範囲）と1（Bézier 曲線描画）のもののみを抜き出した描画実行形式を得ることができる．

364

Risa/Asir の描画キャンバスでの表示の場合• t1 = 0 : ℓ の描画範囲の横幅と左上端の位置をキャンバスに合わせる．
さらに微調整するには，キャンバスの縦横比率を変更したり，オプションパラメータの ext とshift を用いるとよい．
このとき– t2 = 1 : 描画範囲の箱サイズの他，自動的に得た ext と shift の値が表示される（オプションパラメータは加味されない）．
– t2 = −1 : 上の情報が戻り値に付加されたリストを返す（オプションパラメータも加味される）．この戻り値が R のとき，execdraw(ℓ̃,R) とすると，同じキャンバスに同じ座標で, ℓ̃ の重ね書きができる．また，execdraw(ℓ,[t0 ,0,0,R[3]]) や execdraw(ℓ,[t0 ,0,-1,R[3]]) のようにして（新規，または既存の）別のキャンバスに描くことも出来る．
たとえば，戻り値は[[0,2,3,500,400],0,0,[0,[-1.2,1],[-1.2,1],0,[10,10],[0,-10]]]のような形になる．
最初の [0,2,3,500,400] は t0 に対応する部分で，順に，0 は Risa/Asir のキャンバスへの描画，そのサーバ Id は 2，キャンバス Id は 3，サイズが 500 × 400 pixel であることを意味する．
次の成分の 0 は表示の際の調整を意味し，その次の 0 は特に意味はなく，最後の成分の[0,[-1.2,1],[-1.2,1],0,[10,10],[5,-15]]は描画実行形式の成分の形である．すなわち描画実行形式の箱がその座標の単位で [-1.2,1]×[-1.2,1] であって，次の 0 は単位あたりの実長が無定義を意味し，ext=[10,10], shift=[5,-15] で Risa/Asir のキャンバスに対応させることを意味している．より具体的にはext によってキャンバスの横幅 500 pixel の左右に 10 pixel ずつ余裕を持たせるので，座標の単位は描画の際に 500−10−101−(−1.2) 倍される．また，描画実行形式の箱の左上端が，キャンバスの左上端から右に (10 + 5) pixel, 下に 15 pixel の位置になる．
なお，画実行形式の箱の外に描画要素があっても，それがキャンバス内に入れば描画される．
• キャンバスへの描画は，まず描画実行形式から描画範囲の箱を読み取ってそれによりキャンバスとの座標対応を定め，次に描画実行種別番号 2 の文字列表示を先頭から順に実行し，最後に残りを先頭から順に実行する．これはキャンバスにおける文字列表示において，文字でなくて文字の箱が上書きされることに対応するため．
• t1 > 0 のときは Windows の横幅が t1 pixel になるようにスケール変換される（t1 = 1 は設定に従う）．
• t1 がリストや行列の時は，以下のキャンバス表示でない場合と同じ．

Risa/Asir の描画キャンバス以外の場合は，t1 はスケール変換を表す（TEX 利用などの場合に有益）．
• t1 が 2 × 2 の行列の時，座標を t1 によって線型変換する．
• t1 = [t10 , t11 ] とすると x 座標が t10 倍，y 座標が t11 倍される（負の値も可能）．
t2 = [x, y] は，座標 (x, y) を原点に移動する平行移動．
t1 によるスケール変換の前に行う．Risa/Asir の描画キャンバスでは無効．
以下，描画実行形式 ℓ について説明する．
• ℓ=[ℓ1 ,ℓ2 ,...]，ℓj =[fj ,...] は，execproc() の形式に従う．ただし，fj が整数の ℓj（描画実行識別番号）は次のような画像描画の特別形式である．
– [0,[x0 ,x1 ],[y0 ,y1 ],k] : 窓の x 座標と y 座標の範囲. 座標の 1 が k cm に対応する．k が省略されたり, k = 0 の場合は，k = 1 と解釈される．
ℓ にこの成分が複数あるときは，最初のものが有効．ℓ の初めの方に書かれるのが望ましい．
– [0,[x0 ,x1 ],[y0 ,y1 ],k,[a,b],[u,v]] : 上 の 拡 張 と し て こ の 形 式 が あ る ．こ れ は
Risa/Asir での表示の際のみ意味を持ち，デフォルトで ext=[a,b], shift=[u,v] というオ

365

プションが設定される．

– [1,pj ,ℓj1 ,ℓj2 ,. . .] : Bézier 曲線描画，pj は xybezier() のオプション．ℓjν はその引数．すなわち xybezier(ℓjν |option list=pj ) (i = 1, 2, . . .) に対応する描画を意味する．あるいは，ℓjν は lbezier() で変換されたデータでもよい．
– [2,pj ,[xj ,yj ],[sj ],tj ] : 文字列描画函数 xyput([xj ,yj ,sj ]) に対応．
tj は Risa/Asir のキャンバス表示での代替文字列（設定しなくてもよい）．
sj が文字列の時は，[2,pj ,[xj ,yj ],sj ,tj ] としてもよい．
– [3,pj ,[xj1 ,yj1 ],[xj2 ,yj2 ],. . .] : 線分描画函数 xyarrow([xj1 ,yj1 ],[xj2 ,yj2 ]) に対応．
– [4,pj ,[xj1 ,yj1 ],[xj2 ,yj2 ],. . .] : 線分描画函数 xyline([xj1 ,yj1 ],[xj2 ,yj2 ]) に対応．
– [5,pj ,sj ] : TEX の文字列描画の dviout(sj ) に対応．
– [-1,...] : この項は無視される（コメントなど）．
– [-2,s] : この項の s は文字列で，TEX のソースには，先頭に % を付加してコメントとして記され，そのあと改行される．

• pj はオプションリストに対応する（fj が函数子の場合は，ℓj の 3 番目の成分にあたる）．
• 複数の描画実行形式は append()，または m2l( |list=1) によって一つにまとめることが出来る（グラフの重ね合わせに対応）．

• ptaffine(m,ℓ|proc=1,shift=w,. . .) で aﬃne 変換（平行移動と線形変換）ができる．
• [1,pj ,ℓj1 ,ℓj2 ,. . .] における ℓjν はリストで, 標準の形の場合，各成分は座標（すなわち実数の 2
つの組のリスト）または，区切り記号の数字の 0, 1, −1 からなり，複数の Bézier 曲線を表わす．
一つの Bézier 曲線は始点，いくつかの制御点，終点とが連続して並んで定義されている．n + 1
個並んでいれば，n 次の Bézier 曲線となる．PDF 化などから 3 次までの Bézier 曲線が望ましい．
なお，1 次の Bézier 曲線は制御点がなく，線分を表す．
0 は Bézier 曲線の区切りで，1 は区切った後に直前の終点の座標を次の Bézier 曲線の始点とみなす（座標を挿入する）ことを意味する．1 で区切られていると連続曲線となるが，−1 は連続曲線の先頭を終点として閉曲線とすることを意味する．たとえば[[x1 ,y1 ],[x2 ,y2 ],1,[x3 ,y3 ],1,-1]
は (x1 , y1 ), (x2 , y2 ), (x3 , y3 ) を頂点とする三角形を意味する．
これが標準の形で，TEX で TikZ のソースを作成するときは，一つの ℓjν が一つの \draw 文に変換される．
一方，ℓjν は一つの Bézier 曲線を表す座標のリストを成分とするリストの形のものも許される．
この場合は，区切り記号の数字は存在しない．TEX で TikZ のソースを作成する場合は，一つのBézier 曲線毎に \draw 文が生成される．上の三角形は，次のように表せる．

[[[x1 ,y1 ],[x2 ,y2 ]],[[x2 ,y2 ],[x3 ,y3 ]],[[x3 ,y3 ],[x1 ,y1 ]]]ℓjν にはこの二つの形式が許されるが，両者は lbezier() によって相互変換できる．
R が描画実行形式の時，たとえば• execdraw(R,[[0,[600]],0]) : 600 × 600 の Risa/Asir のキャンバスを開いて表示する• execdraw(R,[[0,[600,700]],0]|ext=[30,20],shift=[10,-40]) : 600 × 600 の Risa/Asirのキャンバスを開いて表示する．
その際，左側を 30 pixel, 左側を 20 pixel 内側になるように描画を縮小する（負の値で拡大も可）．
さらに右に 10 pixel，上に 40 pixel ずらす．
• execdraw(R,[[0,1,5,600],0]|ext=[30,20],shift=[10,-40]) : サーバ ID が 1，キャンバス
Id が 5 のキャンバスに，横幅が 600 pixel として上と同様に表示する．
• execdraw(R,[1,1.5,[1,1]]) : (1, 1) を原点に並行移動して，さらに画像を 1.5 倍に拡大した
TEX のソースを出力する．

/* TikZ 形式に[0] os_md.dviout0([0,5,6])$[1] F1=[sin(2*x),sin(3*x)]$[2] W=[-1.2,1,2]$

366

*/

[3] R=os_md.xygraph(F1,-48,[-@pi,@pi],W,W|proc=1,ax=[0,0])$ /* リサージュ曲線 */[4] P=os_md.execdraw(R,0)$/* Risa/Asir のキャンパスで表示*/[5] S=os_md.execdraw(R,[1,1.5])$ /* 画像を 1.5 倍した TeX のソースを出力 */[6] os_md.execdraw(R,[2,1.5])$/* 1.5 倍した画像を TeX を用いて表示 */[7] F2=[sin(3*x),sin(4*x)]$[8] R2=os_md.xygraph(F2,-48,[-@pi,@pi],W,W|proc=2,opt="red")$[9] R2=append(R,R2)$/* グラフの重ね合わせ */[10] os_md.execdraw(R2,[2,1.5])$
上の [4], [5], [6] では，描画実行形式 R に対して，それぞれ，Risa/Asir のキャンバスで表示，TEXのソースに変換，TEX を使って PDF に変換して画面表示を行っている．[5], [6] では，グラフを 1.5倍に拡大している．
R2 は 2 つのグラフを重ねた描画実行形式で，[10] ではそれを表示している．

[11] S=os_md.xy2graph(x^2-y^2,0,[-1,1],[-1,1],[-2,2],0,0|ax=[-1,1,-6],scale=1.5,
dviout=3,proc=1)$[12] os_md.execdraw(S,[[0,[500,400]],500]|ext=[80,70],shift=[0,90])$[13] os_md.execdraw(S,[[0,[500]],0])$[14] os_md.execdraw(S,-1);
Windows : -2.04904 < x < 2.04904 , -3.42811 < y < 3.42811
by 1 cm[[-2.04904,2.04904],[-3.42811,3.42811],1][15] os_md.execdraw(S,-3);[[-2.04904,2.04904],[-1.97922,1.97922],9,[[-2.04904,2.04904],[-1.97922,1.97922]]]][16] os_md.execdraw(S,-4);
1366[17] os_md.execdraw(S,-5);[0,1,2,5]
3.2.12 Applications
いくつかの函数を応用した例を述べる．

3.2.12.1

表の作成

463. powprimroot(p,n|all=1,exp=1,log=f ):: p 以上の素数 n 個とその原始根のリストを作る• all=1 各素数に対し最小原始根のみでなく，全ての原始根をリストする• exp=1 最小原始根とそのべき（指数関数の値）のリストを作る• log=1 最小原始根に対する対数関数の値のリストを作る• log=2 上の対数関数のリストにおいて，べき 0 を使わない• log=3 最小原始根に対する対数関数の素数のときの値のリストを作る[0] os_md.powprimroot(3,4);[[3,2],[5,2],[7,3],[11,2]][1] os_md.powprimroot(3,4|all=1);[[3,2],[5,2,3],[7,3,5],[11,2,6,7,8]][2] os_md.powprimroot(3,4|exp=1);[[$p$,1,2,3,4,5,6,7,8,9,10],[3,2,1],[5,2,4,3,1],[7,3,2,6,4,5,1],367

[11,2,4,8,5,10,9,7,3,6,1]][3] os_md.powprimroot(3,4|log=1);[[$p$,1,2,3,4,5,6,7,8,9,10],[3,0,1],[5,0,1,3,2],[7,0,2,1,4,5,3],[11,0,1,8,2,4,9,7,3,6,5]][4] os_md.powprimroot(3,4|log=2);[[$p$,1,2,3,4,5,6,7,8,9,10],[3,2,1],[5,4,1,3,2],[7,6,2,1,4,5,3],[11,10,1,8,2,4,9,7,3,6,5]][5] os_md.powprimroot(3,4|log=3);[[3,2,1],[5,2,1,3],[7,3,2,1,5],[11,2,1,8,4,7],[$p/a$,$r$,2,3,5,7]]
実際に ltotex( |opt="tab") によってリストを TEX の表にして表示してみよう．

[6] T="素数$p$の原始根とそのべきを$p$で割った余り"$[7] L=os_md.powprimroot(3,8|exp=1)$[8] Out=os_md.ltotex(L|opt="tab",hline=[0,1,z],vline=[0,1,z],title=T)$[9] os_md.dviout(Out)$
素数 p の原始根とそのべきを p で割った余り

p
3
5
7
11
13
17
19
23

1
2
2
3
2
2
3
2
5

2
1
4
2
4
4
9
4
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

3
6
8
8
10
8
10

1
4
5
3
13
16
4

5
10
6
5
13
20

1
9
12
15
7
8

7
11
11
14
17

3
9
16
9
16

6
5
14
18
11

1
10
8
17
9

7
7
15
22

1
4
11
18

12
3
21

2
6
13

6
12
19

1
5
3

10
15

1
6

7

12

14

1

上の hline=[0,1,z] で先頭と最後の行の他（z は最後を表す），1 行目の終わりに横線を引いている．
縦線も同様．また title=T でタイトルをつけている．以下も同様の例である．

[10] T="Table of $k$ satisfying $r^k\\equiv a\\pmod{p}$"$[11] L=os_md.powprimroot(11,10|log=3);[[11,2,1,8,4,7],[13,2,1,4,9,11,7],[17,3,14,1,5,11,7,4],[19,2,1,13,16,6,12,5,10],...
[12] S=os_md.ltotex(L|opt="tab",hline=[0,z-1,z],vline=[0,1,2,z],title=T)$[13] os_md.dviout(S)$
11
13
17
19
23
29
31
37
41
43
p/a

2
2
3
2
5
2
3
2
6
3
r

1
1
14
1
2
1
24
1
26
27
2

Table of k satisfying rk ≡ a (mod p)
8
4
7
4
9 11
7
1
5 11
7
4
13 16
6 12
5 10
16
1 19
9 14
7 15
5 22 12 25 18 21
9 20
1 20 28 23 1174 27926 23 32 30 11
7 35 15 21
15 22 39
3 31 339 36
7
1 25 35 30 32 38 19 16 41
35
7 11 13 17 19 23 29

次に，多くのリストをたたんで表示することを考える．
70 個の素数と原始根の組を表示する例を示そう．

368

9
28
34
31

32
7
37

6
41

[13] L=os_md.powprimroot(3,70)；[[3,2],[5,2],[7,3],[11,2],[13,2],[17,3],[19,2],[23,5],[29,2],[31,3],[37,2],[41,6],....
[14] S=os_md.ltotex(L|opt="tab",width=-10,vline=[[0,2]],hline=[0,1,z],top=[["$p$","$\\zeta$"]])$[15] os_md.dviout(S)$横 2 列で縦に 70 行の縦長の表を [14] の width=-10 によって行を 10 分割して横に並べる．
vline=[[0,2]] は，2 で割った余りが 0 の列，すなわち先頭から 2 列毎の罫線を意味している，
top=[["$p$","$\\zeta$"]] によって，1 行目に p と ζ の繰り返しを付加している．
p
3
5
7
11
13
17
19

ζ
2
2
3
2
2
3
2

p
23
29
31
37
41
43
47

ζ
5
2
3
2
6
3
5

p
53
59
61
67
71
73
79

ζ
2
2
2
2
7
5
3

p
83
89
97
101
103
107
109

ζ
2
3
5
2
5
2
6

p
113
127
131
137
139
149
151

ζ
3
3
2
3
2
2
6

p
157
163
167
173
179
181
191

ζ
5
2
5
2
2
2
19

p
193
197
199
211
223
227
229

ζ
5
2
3
2
3
2
6

p
233
239
241
251
257
263
269

ζ
3
7
7
6
3
5
2

p
271
277
281
283
293
307
311

ζ
6
5
3
3
2
5
17

p
313
317
331
337
347
349
353

ζ
10
2
3
10
2
2
3

[16] S=os_md.ltotex(L|opt="tab",width=16,hline=[[0,2]],vert=1);[17] os_md.dviout(S)$横 2 列で縦に 70 行の表を [16] の vert=1 で転置して横 70 列，縦 2 列に変換し，さらに width=16
によって横幅 16 列で切って折り返して並べる．
3
2
61
2
139
2
229
6
317
2

5
2
67
2
149
2
233
3
331
3

3.2.12.2

7
3
71
7
151
6
239
7
337
10

11
2
73
5
157
5
241
7
347
2

13
2
79
3
163
2
251
6
349
2

17
3
83
2
167
5
257
3
353
3

19
2
89
3
173
2
263
5

23
5
97
5
179
2
269
2

29
2
101
2
181
2
271
6

31
3
103
5
191
19
277
5

37
2
107
2
193
5
281
3

41
6
109
6
197
2
283
3

43
3
113
3
199
3
293
2

47
5
127
3
211
2
307
5

53
2
131
2
223
3
311
17

59
2
137
3
227
2
313
10

表や行列の作成• 表とは，Excel の表のように，何項かのデータを縦横に並べたものと考えます．Risa/Asir では，ベクトルのリストか，リストのリストの型のものを意味することとします．

• 表を変形するときは，表を行列に変換すると便利で，様々な変形の機能が使えます．以下では，そのように変換したものも「表」と呼ぶことにします．
• リストのリスト，あるいはベクトルのリストを行列に直すには，lv2m() を用います．データのないところに対応する行列の成分はデフォルトでは 0 になりますが，オプション null=t で t に置き換えられます．
• 逆の変換は，m2ll() または m2ll() を用います．

[0] LL=[[1,2,3],[4,5]];[[1,2,3],[4,5]][1] os_md.lv2m(LL);[ 1 2 3 ][ 4 5 0 ][2] os_md.m2ll(@@);
369

[[1,2,3],[4,5,0]][3] LV=[newvect(3,[1,2,3]),newvect(2,[4,5])];[[ 1 2 3 ],[ 4 5 ]][4] os_md.lv2m(LV|null="");[ 1 2 3 ][ 4 5 ]
[5] os_md.m2ll(@@);[[1,2,3],[4,5,]]行列（表）から行や列を抜き出したり入れ替えて，新しい行列（表）を作るには mperm() を用います（第 2 引数で行を，第 3 引数で列を指定します）．

[6] A=os_md.mgen(3,4,a,0);[ a00 a01 a02 a03 ][ a10 a11 a12 a13 ][ a20 a21 a22 a23 ][7] os_md.mperm(A,[2,0],[1,2,3]);[ a21 a22 a23 ][ a01 a02 a03 ]上で A から 2 行目と 0 行目をこの順に抜き出し，さらにそれの 1 列目，2 列目，3 列目を抜き出して作られる表を得ています．なお，行と列の番号は 0 から始まることに注意．
順に並んだ数字は，先頭の数字の後に並ぶ個数をリストとして指定することも可能です．

[8] os_md.mperm(A,[2,0],[1,[3]]);[ a21 a22 a23 ][ a01 a02 a03 ]
また順に並んだ全ての行や列を表すには，数字 0 を用いることができます．よって以下のようにして最後の列を削除することができます．

[9] os_md.mperm(A,0,[0,[3]]);[ a00 a01 a02 ][ a10 a11 a12 ][ a20 a21 a22 ]2 つの行の入れ替えや 2 つの列の入れ替えは，[[m1 ,m2 ]] で指定します．たとえば，0 行目と 1 行目の入れ替えは[10] os_md.mperm(A,[[0,1]],0);[ a10 a11 a12 a13 ][ a00 a01 a02 a03 ][ a20 a21 a22 a23 ]なお行列は成分を直接指定して変更できます．

[11] AA=os_md.dupmat(A);[ a00 a01 a02 a03 ][ a10 a11 a12 a13 ][ a20 a21 a22 a23 ][12] AA[0][0]=b00$
370

[13] AA;[ b00 a01 a02 a03 ][ a10 a11 a12 a13 ][ a20 a21 a22 a23 ]
行と列を入れ替えて転置した表にするには mtranspose() を用います．

[14] AT=os_md.mtranspose(A);[ a00 a10 a20 ][ a01 a11 a21 ][ a02 a12 a22 ][ a03 a13 a23 ]2 つ（またはそれ以上）の表を結合するには，newbmat() を用います．
[15] B=os_md.mgen(3,3,b,0);[ b00 b01 b02 ][ b10 b11 b12 ][ b20 b21 b22 ][16] C=os_md.newbmat(1,2,[[A,B]]);[ a00 a01 a02 a03 b00 b01 b02 ][ a10 a11 a12 a13 b10 b11 b12 ][ a20 a21 a22 a23 b20 b21 b22 ][17] D=os_md.newbmat(2,1,[[AT],[B]]);[ a00 a10 a20 ][ a01 a11 a21 ][ a02 a12 a22 ][ a03 a13 a23 ][ b00 b01 b02 ][ b10 b11 b12 ][ b20 b21 b22 ]横長の表を分割して縦に繋げるには，madjust() を用います．列の個数を 2 番目の引数で指定します．

[18] os_md.newbmat(C,3|null="");[ a00 a01 a02 ][ a10 a11 a12 ][ a20 a21 a22 ][ a03 b00 b01 ][ a13 b10 b11 ][ a23 b20 b21 ]
[ b02
]
[ b12
]
[ b22
]
縦長の表を折り返して横に並べるには，madjust() を用います．いくつ折り返すかの数の −1 倍を 2番目の引数で指定します．

[19] os_md.newbmat(D,-4|null="");
371

[ a00 a10 a20 a02 a12 a22 b00 b01 b02 b20 b21 b22 ][ a01 a11 a21 a03 a13 a23 b10 b11 b12]
3.2.12.3函数値の数表464. ntable(f ,[a,b],n|dif=1,str=[k1 ,k2 ,. . .],mult=m,title=t,top=[t1 ,. . .],TeX=1):: 区間 [a, b] を n 等分，または n=[n1 ,n2 ] 等分した点での x 変数の函数 f の函数値の数表を作る
n が数字のとき• f は sin(x*@pi/180) のような通常の関数の他，リスト形式函数でもよい．
• dif=1 を指定すると，次の函数値との差の絶対値も表に加える．
• オプション str を指定すると，文字列の表となる．
k1 は変数の小数点以下の桁数．k2 は値の小数点以下の桁数．
k3 は dif=1 で加わった値の差の桁数に対応する．k3 の指定がないときは，k2 と等しいとみなされる．

• mult=m を指定すると，分割して横に m 列並べた TEX 形式の表に変換される．このとき– title=t を指定すると，表にタイトル t がつく.
– top=[t1 ,. . .] を指定すると，それが表の１行目に入る．
n が数字のリスト [n1 ,n2 ] のとき, 区間 [a,b] を n1 等分した小区間 [ai ,bi ] をさらに n2 等分した点での函数値の表を作成する．このとき• TeX=1 またはオプション str を指定すると，表の TEX ソースが出力される．
k1 は変数の小数点以下の桁数．k2 は値の小数点以下の桁数．
k3 は dif=1 で加わった値の差の桁数に対応する．k3 の指定がないときは，k2 と等しいとみなされる.
さらにこのとき，以下のオプションが指定可能– dif=1 を指定すると，次の函数値との差の各小区間での最小値と最大値を表に加える．
– hline=h : 横 線 の 指 定（ltotex(ℓ|opt="tab",hline=h) を 参 照 ）．デ フ ォ ル ト は
h =[0,1,z]．
– vline=v : 縦の指定（ltotex(ℓ|opt="tab",vline=v) を参照）．デフォルトは v =[0,1,z]（dif=1 を指定した場合は [0,1,z-2]．
– top=[t1 ,. . .,tm ] を指定すると，それが表の１行目に入る．m は，n2 , n2 + 1, n2 + 2, n2 + 3のいずれか．
– title=s : タイトルを文字列で指定．
2 番目の引数が [a,b] でなくて，[[a1 ,b1 ],[a2 ,b2 ]] のときは，2 変数函数 f (x, y) の数値表になる．各行は x の値が [a1 ,,b1 ] を n1 等分した値を取り，そのときの y の値は [a2 ,b2 ] の n2 等分した値を取ったとき f (x, y) の票になる
例えば 4 桁常用対数表は，以下の様に作成できる．

[0] os_md.ntable(log(x)/log(10),[1,5.5],[45,10]|str=[1,4],top=[0,1,2,3,4,5,6,7,
8,9],hline=[0,[1,5]],vline=[0,6,z]);/* [1,5.5] を 45 等分し，各行はそれを 10 等分した常用対数（0.01 刻み）.
左端は小数点以下 1 桁，函数値は小数点以下 4 桁で丸める
横線は最初と 1 行目の後から 5 行目毎，縦線は最初と 6 列目の後と最後 */

372

1.0
1.1
1.2
1.3
1.4
1.5

0
.0000
.0414
.0792
.1139
.1461
.1761

1
.0043
.0453
.0828
.1173
.1492
.1790

2
.0086
.0492
.0864
.1206
.1523
.1818

4 桁常用対数表
345.0128 .0170 .0212.0531 .0569 .0607.0899 .0934 .0969.1239 .1271 .1303.1553 .1584 .1614.1847 .1875 .1903

6
.0253
.0645
.1004
.1335
.1644
.1931

7
.0294
.0682
.1038
.1367
.1673
.1959

8
.0334
.0719
.1072
.1399
.1703
.1987

9
.0374
.0755
.1106
.1430
.1732
.2014

以下，5.4 の項まで続く．

4 桁目は線形近似で得るので，例えば 30 から 43 までの計算表は[1] os_md.ntable(x*y/10,[[1,11],[30,44]],[10,14]|hline=[0,z-1,z],str=[0,0],TeX=1);/* x=1,2,...,10 (10 個) y=30,31,...,43 (14 個) */とすれば得られる．

1
2
3
4
5
6
7
8
9
10

3
6
9
12
15
18
21
24
27
30

3
6
9
12
16
19
22
25
28
31

3
6
10
13
16
19
22
26
29
32

3
7
10
13
17
20
23
26
30
33

3
7
10
14
17
20
24
27
31
34

4
7
11
14
18
21
25
28
32
35

4
7
11
14
18
22
25
29
32
36

4
7
11
15
19
22
26
30
33
37

4
8
11
15
19
23
27
30
34
38

4
8
12
16
20
23
27
31
35
39

4
8
12
16
20
24
28
32
36
40

4
8
12
16
21
25
29
33
37
41

4
8
13
17
21
25
29
34
38
42

4
9
13
17
22
26
30
34
39
43

各行の函数値の差分の最小と最大の数の組を加えた函数値表を作成するには, 以下のようにすればよい．

[2] os_md.ntable(log(x)/log(10),[1,5.5],[45,10]|str=[1,4],top=[0,1,2,3,4,5,6,7,
8,9],hline=[0,[1,5]],vline=[0,1,6,z-2],dif=1);

1.0
1.1
1.2

0
.0000
.0414
.0792

1
.0043
.0453
.0828

2
.0086
.0492
.0864

3
.0128
.0531
.0899

4
.0170
.0569
.0934

5
.0212
.0607
.0969

6
.0253
.0645
.1004

7
.0294
.0682
.1038

8
.0334
.0719
.1072

9
.0374
.0755
.1106

40
36
33

43
39
36

その他，たとえば 0◦ から 45◦ までの 100 刻みの三角関数表（正弦）は[3] T=["$0’$","$10’$","$20’$","$30’$","$40’$","$50’$"]$[4] os_md.ntable(sin(@pi*x/180),[0,45],[45,6]|str=[0,4],top=T,hline=[0,[1,5]],
vline=[0,1,z-2],dif=1);とすると得られる（sin を tan で置き換えると，正接の表になる）．

0
1
2
3
4
5

00
.0000
.0175
.0349
.0523
.0698
.0872

100
.0029
.0204
.0378
.0552
.0727
.0901

200
.0058
.0233
.0407
.0581
.0756
.0929

300
.0087
.0262
.0436
.0610
.0785
.0958

400
.0116
.0291
.0465
.0640
.0814
.0987

500
.0145
.0320
.0494
.0669
.0843
.1016
373

29
29
29
29
29
28

30
29
29
30
29
29

90◦ までの表を 1 ページ内に収めるには[5] T=append(T,["$60’$","$70’$","$80’$","$90’$","$100’$","$110’$"])$[6] os_md.ntable(sin(@pi*x/180),[0,90],[45,12]|str=[0,4],top=T,hline=[0,[1,5]],
vline=[0,1,7,z-2],dif=1);とすればよい．
0
2
4
6
8
10

00
.0000
.0349
.0698
.1045
.1392
.1736

3.2.12.4

100
.0029
.0378
.0727
.1074
.1421
.1765

200
.0058
.0407
.0756
.1103
.1449
.1794

300
.0087
.0436
.0785
.1132
.1478
.1822

400
.0116
.0465
.0814
.1161
.1507
.1851

500
.0145
.0494
.0843
.1190
.1536
.1880

600
.0175
.0523
.0872
.1219
.1564
.1908

700
.0204
.0552
.0901
.1248
.1593
.1937

800
.0233
.0581
.0929
.1276
.1622
.1965

900
.0262
.0610
.0958
.1305
.1650
.1994

1000
.0291
.0640
.0987
.1334
.1679
.2022

1100
.0320
.0669
.1016
.1363
.1708
.2051

29
29
28
28
28
28

30
30
29
29
29
29

点数分布表

465. distpoint(l|div=5,opt=s,title=t,size=ℓ):: 100 点満点の点数表のデータ l を元に点数分布などを表にする• 10 点刻みの人数の分布を TEX の表にする• s="data" 10 点刻みの人数の分布をリストにする• s="graph" 10 点刻みの人数の分布を棒グラフにする– size=ℓ でグラフのサイズを指定できる（cf. ltotex( |opt="graph")）• div=5 上で 10 点刻みを 5 点刻みとする• s="average" 平均点，標準偏差，受験人数，最低点，最高点を TEX の表にする• l は，数のリストまたは数のリストのリストとするが，そのなかに非負整数でないものがあれば，それは欠席とみなされ，s="average"でその数が示される[0] M=[[74,71,47,80,66],[54,71,50,76,45],[75,70,78,x,69],[35,44,74,35,37],[59,x,85,75,52],[92,55,70,61,45],[70,79,77,76,55]]$[1] os_md.distpoint(M|opt="data");[0,0,0,3,4,6,3,14,2,1][2] os_md.distpoint(M|opt="data",div=5);[3] [0,0,0,0,0,0,0,3,1,3,3,3,1,2,7,7,1,1,1,0][4] S=os_md.distpoint(M|opt="average",title="線形代数（中間試験）");\begin{tabular}{|cccccc|}\multicolumn{6}{c}{線形代数（中間試験）}\\ \hline
平均点& 標準偏差& 最低点& 最高点& 受験人数& 欠席者\\$63.7$& $15.1$& $35$& $92$& $33$& $2$\\ \hline\end{tabular}[5] os_md.dviout(S)$[1] で M をリストのリストにしているのは，5 人ずつ目印のため．また x は欠席者を表している（アルファベットの任意の文字でよい）．
なお，Excel などに点数のデータが入っているときにそれを読み込むには，それを例えば fname というファイルに CSV 形式で出力する．その n 項目が点数のデータとすると

M=os_md.readcsv(fname|col=n,eval=n)によって点数のデータが M にリストとして読み込まれる．
なお，上の [5] の結果は：
平均点

63.7

線形代数（中間試験）
標準偏差 最低点 最高点 受験人数

15.1

35

92

33
374

欠席者

2

[6] S=os_md.distpoint(M|title="点数分布");\begin{tabular}{|rrrrrrrrrr|}\multicolumn{10}{c}{点数分布}\\ \hline
00--09& 10--19& 20--29& 30--39& 40--49& 50--59& 60--69& 70--79& 80--89& 90--100\\$0$& $0$& $0$& $3$& $4$& $6$& $3$& $14$& $2$& $1$\\ \hline\end{tabular}[7] os_md.dviout(S)$
点数分布

00–09
0

10–19
0

20–29
0

30–39
3

40–49
4

50–59
6

60–69
3

70–79
14

80–89
2

90–100
1[8] S=os_md.distpoint(M|opt="graph")$[9] os_md.dviout(S)$
14

6
3

4

3

2

1

00- 10- 20- 30- 40- 50- 60- 70- 80- 903.2.12.5

Table of score distribution

466. seriesTaylor(f ,k,v|evalopt=opt,small=1,frac=0,dviout=n):: 函数 f の変数または変数のリスト v に対する k 次の項までの Taylor 展開を求める• Taylor 展開を TEX の形に変換して返す．式が長いときは，改行が入る．
• v=x : 変数 x について，原点での Taylor 展開を与える．
• v=[x,a] : 変数 x について，x = a での Taylor 展開を与える．ただし a も変数のときは，
v=[[x,a]] としなくてはならない（次項と区別するため）．
• v=[x,y, . . .] : 変数 (x, y, . . .) についての原点での Taylor 展開を与える．
• v =[[x,a],[y,b],. . .] : 変数 (x, y, . . .) について，点 (a, b, . . .) を中心とする Taylor 展開を与える．ここで，たとえば a = 0 のときは，上の [x,a] の部分は，単に x と表記してよい．
• evalopt=[[s1 ,t1 ],[s2 ,t2 ]...] : は evalred() を使うときのオプション（cf. seriesMc()）．
• small=1 : 分数が現れるとき \frac でなくて \tfrac を使う．
• frac=0 : 有理数が現れるとき，それを（近似）実数に変換する．
このときは，ctrl(double_output,1) を指定するのがよい．
• dviout=1 : Taylor 展開の式を TEX に変換したものを表示する（元の f も表示）．
• dviout=2 : Taylor 展開の部分のみを TEX に変換したものを表示する（元の f は表示せず）．
• dviout=0 : デフォルトで，dviout=2 の TEX ソースを返す．
• dviout=-1 : dviout=2 のときのソースを返す．
まず sin x の Taylor 展開を求めてみる．

[0] os_md.seriesTaylor(sin(x),5,x);x-\frac{1}6x^3+\frac{1}{120}x^5[1] os_md.seriesTaylor(sin(x),5,x|small=1,dviout=-1);\begin{align}\begin{split}\sin(x)&=x-\tfrac{1}6x^3+\tfrac{1}{120}x^5+\cdots375

\end{split}\end{align}[2] os_md.seriesTaylor(sin(x),7,x|small=1)$1
1x5 − 5040
x7 + · · ·sin(x) = x − 61 x3 + 120

ここでは sin x の 7 次の項までの Taylor 展開を求め，係数は小さなサイズの分数で表示している．
また，展開の係数を近似小数で表した表示を得るには，以下のようにすればよい．

[3] os_md.seriesTaylor(sin(x),5,x|frac=0,dviout=-1);\begin{align}\begin{split}\sin(x)&=x- 0.166667x^3+ 0.00833333x^5+\cdots\end{split}\end{align}[4] os_md.dviout(@@)$
sin(x) = x − 0.166667x3 + 0.00833333x5 + · · ·[5] os_md.seriesTaylor(sin(x),5,[x,@pi/2]|dviout=-1,small=1,evalopt=[[sin(@pi/2),1],[cos(@pi/2),0]],dviout=-1);\begin{align}\begin{split}\sin(x)&=1-\tfrac{1}2(x-\tfrac{1}2 \pi)^2+\tfrac{1}{24}(x-\tfrac{1}2 \pi)^4+\cdots\end{split}\end{align}[6] os_md.dviout(@@)$
1sin(x) = 1 − 12 (x − 12 π)2 + 24
(x − 21 π)4 + · · ·[5] において sin(x) の x = π2 での Taylor 展開を 5 次の項まで求めているが, sin( π2 ) = 1, cos( π2 ) = 0という情報を与えている．これを与えないと，係数は近似小数になる（sin(0) = 0, cos(0) = 1 などの．
情報は不要（cf. evalred()））[7] os_md.seriesTaylor((x+1)^(1/2),10,x|frac=0,dviout=1);√

x + 1 = 1 + 0.5x − 0.125x2 + 0.0625x3 − 0.0390625x4 + 0.0273438x5 − 0.0205078x6 + 0.0161133x7− 0.013092x8 + 0.01091x9 − 0.00927353x10 + · · ·√x + 1 の x = 0 での Taylor 展開を求めたが，上のように，長い式は改行して表示される（cf. TeXLim）．
最後に 2 変数函数の原点での Taylor 展開の例を挙げる．
[8] os_md.seriesTaylor(exp(sin((x-y)/(x^2+2*y^2+2))),3,[x,y]|small=1,dviout=1)$x−yexp(sin( 2)) = 1 + 12 x − 12 y + 18 x2 − 14 xy + 18 y 2 − 41 x3 + 41 x2 y − 21 xy 2 + 12 y 3 + · · ·x + 2y 2 + 2376

3.2.12.6

計算尺

scale() を用いて紙などで作成できる 25cm 片面計算尺の原版を以下の例のように作る（A4 用紙に印刷する）．

Ht=4.7;HT=Ht;
Low=[1.5,1,0.5];High=[3.2,3.7,4.2];
Cent=[1.45,1.95,2.75,3.25]; Cent2=[1.45,2.3,2.4,3.25]; /* transparent */Low2=[2.3,1.8,1.3,0.8];High2=[2.4,2.9,3.4,3.9];/* not transparent */L=25;S1=0.15;S2=0.23;S3=0.3;S4=S1;Sp=1;Hm=0.35;Sw=L+Sp;Sn=0.5;Sm=0.7;Rm=0.1;
S=T=MS=MT=""$SCU=[L,S1,S2,S3]$SCD=[L,-S1,-S2,-S3]$/* 固定尺表下部 D, DI, L 尺 */S+=os_md.scale("D"|TeX=1,scale=SCD,mes=[-Hm],shift=Low[0],mes2=[3.1416,[-S3,-S4,"red"],"$\\pi$"])$
S+=os_md.scale("DI"|TeX=1,scale=SCD,mes=[[-Hm,"red"]],shift=Low[1])$S+=os_md.scale([[[0,1,1/500]],[[0,1,1/100]],[[0,1,1/20]]]|TeX=1,f=x,scale=SCD,
mes=[-Hm,[0,1,1/10]],shift=Low[2])$/* 固定尺表上部 DF, A, K 尺 */S+=os_md.scale("DF"|TeX=1,scale=SCU,mes=[Hm],shift=High[0],mes2=[3.1416,[S3,S4,"red"],"$\\pi$"])$
S+=os_md.scale("A"|TeX=1,scale=SCU,mes=[Hm],shift=High[1])$S+=os_md.scale("K"|TeX=1,scale=SCU,mes=[Hm],shift=High[2])$/* 滑尺表 C, CI, CFI, CF, */T+=os_md.scale("C"|TeX=1,scale=SCU,mes=[Hm],shift=Cent[0],mes2=[[3.1416,[S3,S4,"red"],"$\\pi$"],[5.73,[S3,S4,"red"],"$\\rho^\\circ$"],[3.4378,[S3,S4,"red"],"$\\rho’$"],[2.063,[S3,S4,"red"],"$\\rho’’$"]])$
T+=os_md.scale("CI"|TeX=1,scale=SCU,mes=[[Hm,"red"]],shift=Cent[1])$T+=os_md.scale("CIF"|TeX=1,scale=SCD,mes=[[-Hm,"red"]],shift=Cent[2])$T+=os_md.scale("CF"|TeX=1,scale=SCD,mes=[-Hm],shift=Cent[3],mes2=[3.1416,[-S3,-S4,"red"],"$\\pi$"])$/* 固定尺裏 T1, S, D, DI / T2, LL1, LL2, LL3 */S+=os_md.scale("T1"|TeX=1,scale=SCD,mes=[-Hm],shift=Low2[0]+HT)$
S+=os_md.scale("S"|TeX=1,scale=SCD,mes=[-Hm],shift=Low2[1]+HT)$
S+=os_md.scale("D"|TeX=1,scale=SCD,mes=[-Hm],shift=Low2[2]+HT)$
S+=os_md.scale("DI"|TeX=1,scale=SCD,mes=[[-Hm,"red"]],shift=Low2[3]+HT)$
S+=os_md.scale("T2"|TeX=1,scale=SCU,mes=[Hm],shift=High2[0]+HT)$
S+=os_md.scale("LL1"|TeX=1,scale=SCU,mes=[Hm],shift=High2[1]+HT)$
S+=os_md.scale("LL2"|TeX=1,scale=SCU,mes=[Hm],shift=High2[2]+HT)$
S+=os_md.scale("LL3"|TeX=1,scale=SCU,mes=[Hm],shift=High2[3]+HT)$/* 枠 */
377

SS=[[-Sp,-Ht],[Sw,-Ht],[Sw,2*Ht],[-Sp,2*Ht],[-Sp,-Ht],0, /* 外枠 */[-Sp,0],[Sw,0],0,[-Sp,Ht],[Sw,Ht],0, /* 横 */[0,0],[0,Ht],0,[L,0],[L,Ht],0];/* 縦 */;ST=[[-Sp,Rm/2],[Sw,Rm/2],0,[-Sp,Ht-Rm/2],[Sw,Ht-Rm/2],0, /* 横 */[0,Rm/2],[0,Ht-Rm/2],0,[L,Rm/2],[L,Ht-Rm/2];/* 縦 */
MS0=os_md.xylines(SS|opt="green")$
MT0=os_md.xylines(ST|opt="green")$/* 尺名 */
LS=[[Low[0]-S1,"D"],[Low[1]-S1,["red","DI"]],[Low[2]-S1,"L"],[High[0]+S1,"DF"],[High[1]+S1,"A"],[High[2]+S1,"K"],[High2[0]+S1+HT,"T2"],[High2[1]+S1+HT,"LL1"],[High2[2]+S1+HT,"LL2"],[High2[3]+S1+HT,"LL3"],[Low2[0]-S1+HT,"T1"],[Low2[1]-S1+HT,"S"],[Low2[2]-S1+HT,"D"],[Low2[3]-S1+HT,["red","DI"]]]; /* 固定尺名 */LT=[[Cent[0]+S1,"C"],[Cent[1]+S1,["red","CI"]],[Cent[2]-S1,["red","CIF"]],[Cent[3]-S1,"CF"]];/* 滑尺名 */for(TT=LS;TT!=[];TT=cdr(TT))
MS+=os_md.xyput([-Sn,car(TT)[0],car(TT)[1]]);for(TT=LT;TT!=[];TT=cdr(TT))
MT+=os_md.xyput([-Sn,car(TT)[0],car(TT)[1]]);
MT+=os_md.xyput([L+Sm,Ht/2,"\\tiny\\rotatebox{-90}{Toshio}"])$ /* 名前 *//* 出力 */
os_md.dviout("\\scriptsize\n"|keep=1)$
os_md.xyproc(MS0+S+MS|dviout=1)$ /* 固定尺 */os_md.dviout("\\bigskip\n\n"|keep=1)$
os_md.xyproc(MT0+T+MT|dviout=1)$ /* 滑尺*/
両面計算尺の例では

Ht=4.7;HT=Ht;
Low=[1.5,1,0.5];High=[3.2,3.7,4.2];
Cent=[1.45,1.95,2.75,3.25]; Cent2=[1.45,2.3,2.4,3.25]; /* transparent */Low2=[2.3,1.8,1.3,0.8];High2=[2.4,2.9,3.4,3.9];/* not transparent */L=25;S1=0.15;S2=0.23;S3=0.3;S4=S1;Sp=1;Hm=0.35;Sw=L+Sp;Sn=0.5;Sm=0.7;
Rm=0.1; /* 滑尺の余裕 */S=T=MS=MT=""$SCU=[L,S1,S2,S3]$SCD=[L,-S1,-S2,-S3]$/* 固定尺表下部 D, L, LL1 尺 */S+=os_md.scale("D"|TeX=1,scale=SCD,mes=[-Hm],shift=Low[0],mes2=[3.1416,[-S3,-S4,"red"],"$\\pi$"])$
S+=os_md.scale([[[0,1,1/500]],[[0,1,1/100]],[[0,1,1/20]]]|TeX=1,f=x,scale=SCD,378

mes=[-Hm,[0,1,1/10]],shift=Low[1])$S+=os_md.scale("LL1"|TeX=1,scale=SCD,mes=[-Hm],shift=Low[2])$/* 固定尺表上部 DF, LL2, LL3 尺 */S+=os_md.scale("DF"|TeX=1,scale=SCU,mes=[Hm],shift=High[0],mes2=[3.1416,[S3,S4,"red"],"$\\pi$"])$
S+=os_md.scale("LL2"|TeX=1,scale=SCU,mes=[Hm],shift=High[1])$S+=os_md.scale("LL3"|TeX=1,scale=SCU,mes=[Hm],shift=High[2])$/* 滑尺表 C, CI, CFI, CF, */T+=os_md.scale("C"|TeX=1,scale=SCU,mes=[Hm],shift=Cent[0],mes2=[[3.1416,[S3,S4,"red"],"$\\pi$"],[5.73,[S3,S4,"red"],"$\\rho^\\circ$"],[3.4378,[S3,S4,"red"],"$\\rho’$"],[2.063,[S3,S4,"red"],"$\\rho’’$"]])$
T+=os_md.scale("CI"|TeX=1,scale=SCU,mes=[[Hm,"red"]],shift=Cent[1])$T+=os_md.scale("CIF"|TeX=1,scale=SCD,mes=[[-Hm,"red"]],shift=Cent[2])$T+=os_md.scale("CF"|TeX=1,scale=SCD,mes=[-Hm],shift=Cent[3],mes2=[3.1416,[-S3,-S4,"red"],"$\\pi$"])$/* 固定尺裏下 D, DI */S+=os_md.scale("D"|TeX=1,scale=SCD,mes=[-Hm],shift=Low[0]-HT,
mes2=[3.1416,[-S3,-S4,"red"],"$\\pi$"])$
S+=os_md.scale("DI"|TeX=1,scale=SCD,mes=[[-Hm,"red"]],shift=Low[1]-HT)$/* 固定尺裏上 A, K */S+=os_md.scale("A"|TeX=1,scale=SCU,mes=[Hm],shift=High[0]-HT)$
S+=os_md.scale("K"|TeX=1,scale=SCU,mes=[Hm],shift=High[1]-HT)$/* 滑尺裏 SI, TL1, TL2, B */T+=os_md.scale("SI"|TeX=1,scale=SCU,mes=[Hm],shift=Cent2[0]+HT-Rm)$
T+=os_md.scale("TI1"|TeX=1,scale=SCD,mes=[-Hm],shift=Cent2[1]+HT-Rm)$
T+=os_md.scale("TI2"|TeX=1,scale=SCU,mes=[Hm],shift=Cent2[2]+HT-Rm)$
T+=os_md.scale("B"|TeX=1,scale=SCD,mes=[-Hm],shift=Cent2[3]+HT-Rm)$/* 枠 */SS=[[-Sp,-Ht],[Sw,-Ht],[Sw,Ht],[-Sp,Ht],[-Sp,-Ht],0, /* 外枠 */[-Sp,0],[Sw,0],0,/* 横 */[0,-Ht],[0,Ht],0,[L,-Ht],[L,Ht],0];/* 縦 */ST=[[-Sp,Rm/2],[Sw,Rm/2],0,[-Sp,Ht-Rm/2],[Sw,Ht-Rm/2],0,[-Sp,2*HT-3*Rm/2],[Sw,2*HT-3*Rm/2],0,/* 横 */[0,0],[0,2*Ht-3*Rm/2],0,[L,0],[L,2*Ht-3*Rm/2] /* 縦 */];MS0=os_md.xylines(SS|opt="green")$379

MT0=os_md.xylines(ST|opt="green")$/* 尺名 */
LS=[[Low[0]-S1,"D"],[Low[1]-S1,["red","L"]],[Low[2]-S1,"LL1"],[High[0]+S1,"DF"],[High[1]+S1,"LL2"],[High[2]+S1,"LL3"],[High[0]+S1-HT,"A"],[High[1]+S1-HT,"K"],[Low[0]-S1-HT,"D"],[Low[1]-S1-HT,["red","DI"]]]; /* 固定尺名 */LT=[[Cent[0]+S1,"C"],[Cent[1]+S1,["red","CI"]],[Cent[2]-S1,["red","CIF"]],[Cent[3]-S1,"CF"],[Cent2[0]+S1+HT-Rm,"SI"],[Cent2[1]-S1+HT-Rm,"TI1"],[Cent2[2]+S1+HT-Rm,"TI2"],[Cent2[3]-S1+HT-Rm,"B"]]; /* 滑尺名 */for(TT=LS;TT!=[];TT=cdr(TT))
MS+=os_md.xyput([-Sn,car(TT)[0],car(TT)[1]]);for(TT=LT;TT!=[];TT=cdr(TT))
MT+=os_md.xyput([-Sn,car(TT)[0],car(TT)[1]]);
MT+=os_md.xyput([L+Sm,Ht/2,"\\tiny\\rotatebox{-90}{Toshio}"])$ /* 名前 *//* 出力 */
os_md.dviout("\\scriptsize\n"|keep=1)$
os_md.xyproc(MS0+S+MS|dviout=1)$ /* 固定尺 */os_md.dviout("\\bigskip\n\n"|keep=1)$
os_md.xyproc(MT0+T+MT|dviout=1)$ /* 滑尺*/
ここで取り上げる紙などで作られる計算尺は，以下のような形になります．

赤は滑尺，黒は固定尺，緑は透明のシートで，青は透明シートで作ったカーソル，点線は固定尺に開けた窓です．固定尺の部分が滑尺を包み込む形になります．
固定尺の一部（D 尺と DF 尺の間）に窓を開けて，滑尺が見えるようにします．
片面計算尺の重なり具合はのようになります．固定尺の表に透明シートを貼って補強します（これは省略してもかまいません）．透明シートは，例えば薄い OHP シート（このときの接着にはペットボトルの工作用のものが有効）などを用います．
となります．透明シートを貼って固定尺

両面計算尺の重なり具合はの部分を筒状にします．

固定尺の部分に OHP シートを使うと窓を開ける必要はありません（OHP シートには目盛など印刷可能です）．
カーソルは，薄い OHP シートなどを利用して作ります．幅は広い方が（5cm 以上 20cm 以下）正確
さが増します（幅が広い場合，縦のカーソル線を複数描いておく）．

3.2.13 Environments
467. Canvas:: Risa/Asir の描画キャンバスのデフォルトサイズ
execdraw() などで Risa/Asir の描画キャンバスを開くときのデフォルトサイズ
380• 横と縦の pixel サイズのリストで，デフォルトは [400,400] となっている．
• dviout0([800,400]|opt="Canvas") のようにして変更可能• 初期化ファイル.muldif でデフォルト値の設定変更可能
468. AMSTeX:: この値が 1 は AMSLATEX を意味する
os_muldif.rr では，AMSTeX=1 がデフォルトで，これが想定されている．それ以外では，函数によっては作成される TEX のソースファイルが正しくないことがある．
[0] M=newmat(2,2,[[a,b],[c,d]]);[ a b ]
[ c d ]
[1] AMSTeX=0$[2] print_tex_form(M);\pmatrix{{a}& {b} \cr{c}& {d} \cr}[3] AMSTeX=1$[4] print_tex_form(M);\begin{pmatrix}{a}& {b} \\{c}& {d}\end{pmatrix}[5] os_md.my_tex_form(M);\begin{pmatrix}
a&b \\
c&d\end{pmatrix}[6] print_tex_form(x_1+x_2^2/y);\frac{{x}_{1} {y}+ {x}_{2}^{ 2} }{ {y}}[7] os_md.my_tex_form(x_1+x_2^2/y);\frac{x_1y+x_2^2}y469. TeXEq:: デフォルトの LATEX の数式環境の指定（dviout0(3) で値が分かる）
TeXEq の値は，1, 2, 3, 4, 5, 6, 7 のいずれかで，それは dviout() のオプションパラメータの eq= の値に対応する．
AMSTeX=1 のときのデフォルトは 5 で，AMSTeX=0 のときは TeXEq=1 とみなされる．
dviout0(n|opt="TexEq") で変更できる．

470. TeXLim:: LATEX で長い数式を行分割する際の 1 行の許容最大横幅文字数のデフォルト値• .muldif で設定でき，dviout0("?") で値が分かる．
• texlim(1,n) または dviout0(n|opt="TexLim") で変更できる（デフォルトは 80）．
471. TeXPages:: TEX の display style で改ページを許す行数の閾値（cf. fctrtos()）
381

• dviout0(n|opt="TexPages") で変更できる（デフォルトは 20）．
472. TikZ:: グラフ表示に XY-pic を使うか TikZ を使うかを指定
TikZ=1 のときは TikZ を，TikZ=0 のときは XY-pic を使う．
切り替えは dviout0(6), dviout0(7) または dviout0(1|opt="TikZ"), dviout0(0|opt="TikZ").
473. XYPrec:: グラフ表示の時の座標の小数点以下の丸め桁数
切り替えは dviout0(n|opt="XYPrec").
474. XYcm:: Unit is cm even in XY-pic での単位を cm で表して，TikZ に合わせる
切り替えは dviout0(0|opt="XYcm"), dviout0(1|opt="XYcm").
475. XYLim:: XY-pic や TikZ での曲線描画で順に指定する点での改行の間隔
切り替えは dviout0(n|opt="XYLim") （デフォルトは 4）476. DVIOUTH:: myhelp() で指定した函数の解説を示すためのプログラムの指定• .muldif で設定でき，dviout0("?") で設定が分かる．
• デフォルトは Windows 環境の場合の dviout にパスが通っているときの設定でstart dviout -2 -hyper:0x90 "%ASIRROOT%\help\os_muldif.dvi" #%LABEL%– これは 2 番目の dviout に，get_rootdir()\help\os_muldif.dvi のラベル %LABEL%（ここは myhelp() がその引数を使って置き換える）がついた箇所を表示させることを意味します．
– 上において，dviout にパスが通っていないときは，それをフルパス名にする．
– -hyper:0x90 はホットスポットを青の文字で示すことを意味します（ox_muldif.pdf と同じ表示となる設定）．指定しないと，さらにアンダーラインが引かれます．
dviout の Option → Setup parameters... → HyperTeX → Color の項を変更して OK ボタン
を押すとこの設定が変えられる．Option → Non-default Parameters で表示される hyper=の値を上の -hyper: に設定すれば，その設定でホットスポットが表示されるようになる．
– これは 2 番目の dviout に，get_rootdir()\help\os_muldif.dvi のラベル %LABEL%（ここは myhelp() がその引数を使って置き換える）がついた箇所を表示させることを意味します．
– 上において，dviout にパスが通っていないときは，それをフルパス名にする．
– -hyper:0x90 はホットスポットを青の文字で示すことを意味します（ox_muldif.pdf と同じ表示となる設定）．指定しないと，さらにアンダーラインが引かれます．
dviout の Option → Setup parameters... → HyperTeX → Color の項を変更して OK ボタン
を押すとこの設定が変えられる．Option → Non-default Parameters で表示される hyper=の値を上の -hyper: に設定すれば，その設定でホットスポットが表示されるようになる．
函数名 fn の説明は，os_muldif.dvi および os_muldif.pdf の中のラベル r:fn がつけられた場
所にある．ただし fn にアンダースコア− " " が含まれるときは， を削ってラベルになっている．

• %ASIRROOT% が get rootdir() に，%LABEL% が函数名に対応する（上で述べた）ラベルに置き換
えられて shell() の引数として myhelp() で使われ，函数に対応するヘルプが表示される．
477. DIROUT:: 数式を LATEX に変換したソースが格納されるディレクトリ（書き込み可能なことが要請される）
478. DVIOUTA:: LATEX の AMSTEX 環境で risaout.tex を変換して表示するプログラムのパス名
479. DVIOUTB:: LATEX の AMSTEX 環境で risaout10.tex （または risaout10.tex）を変換して表示するプロ
グラムのパス名で，DVIOUTA と交換できる（cf. dviout0(), risatex.bat）
480. DVIOUTL:: LATEX 環境で riasout0.tex を変換して表示するプログラムのパス名
382

.muldif で設定でき，設定された値は dviout0("?") で分かる．
Windows 環境でのデフォルトは[0] os_md.dviout0(3)$DIROUT ="%HOME%\tex"
DVIOUTH="start dviout -2 -hyper:0x90 "%ASIRROOT%\help\os_muldif.dvi" #%LABEL%"DVIOUTA="%ASIRROOT%\bin\risatex.bat"
DVIOUTB="%ASIRROOT%\bin\risatex1%TikZ%.bat"
DVIOUTL="%ASIRROOT%\bin\risatex0.bat"
Canvas = [400,400]
TeXPages = 20
TeXLim = 80
TeXEq = 5
AMSTeX = 1
TikZ= 0
XYPrec = 3
XYcm= 0
XYLim = 4
それ以外でのデフォルトは[0] os_md.dviout0(3)$DIROUT ="%HOME%/asir/tex"
DVIOUTH="%ASIRROOT%/help/os_muldif.pdf"
DVIOUTA="%ASIRROOT%/bin/risaout.sh"
DVIOUTB="%ASIRROOT%/bin/risaout1%TikZ%.sh"
DVIOUTL="%ASIRROOT%/bin/risaout0.sh"
DVIOUTL="%ASIRROOT%/bin\risatex0.bat"
TeXPages = 20
Canvas = [400,400]
TeXLim = 80
TeXEq = 5
AMSTeX = 1
TikZ= 0
XYPrec = 3
XYcm= 0
XYLim = 4となっている．
なお，%TikZ% は TikZ の値，%ASIRROOT% は get rootdir() で得られる Risa/Asir のインストール
ディレクトリ，%HOME% は環境変数 HOME の値を意味するが，Windows のときの後者のデフォルトは%ASIRROOT% に等しい．
%ASIRROOT% や %HOME% に空白が含まれていると正しく動作しないので，次の .muldif によって " で二重に囲んでDIROUT ="\"%HOME%\asir\tex\""DVIOUTA="\"%ASIRROOT%\\bin\risaout.bat\""
DVIOUTB="\"%ASIRROOT%\bin\risaout1%TikZ%.bat\""383

DVIOUTL="\"%ASIRROOT%\bin\risaout0.bat\""in ". のように設定し直して下さい．
481. .muldif:: os_muldif.rr をロードしたときに読み込まれるファイル• フ ァ イ ル.muldif を %HOME% に 入 れ て お く と ，自 動 的 に 読 み 込 ま れ る ．そ の ほ か, 順 に%HOME%/asir，%ASIRROOT%，%ASIRROOT%/bin, %ASIRROOT%/lib-asir-contrib が探される．
なお %ASIRROOT% は get_rootdir() と同じ．また %HOME% は環境変数 HOME の値であるが，Windows では通常 %ASIRROOT% と等しい．
• TeXLim, TeXPages, TeXEq, DIROUT, DVIOUTA, DVIOUTB, DVIOUTL, DVIOUTH, TikZ, XYPrec, XYcm,
XYLim, Canvas のデフォルト設定の変更が可能．
• 設定状態は dviout0(3) で表示される．
たとえば，.muldif の例は

DVIOUTH="start c:\\dviout\\dviout -2 \"%ASIRROOT%\\help\\os_muldif.dvi\" #%LABEL%"
end$
なお，C の文法に準じて，文字列中の文字 \ や " は \\ や \" と書く（そのように書かなくても多くの場合は大丈夫であろう）．さらに文字列の始まりと終わりは " で示す（それらは，行で最初にある" と最後にある " とみなしている）．

482. risatex.bat:: os_muldif.rr が出力する LATEX のソースファイルを変換して表示するプログラム• os_muldif.rr が TEX を使って結果や数式を綺麗に表示する際には，DIROUT 内の LATEX ファイ
ル out.tex（または out0.tex）に LATEX のソースを書き出しますが，それらを risaout.tex（または risaout1.tex，risaout0.tex）から読み込んで dvi ファイルや pdf に変換して表示する
デフォルトのプログラムです（後者は risaout0.bat）．
• DVIOUTA（または DVIOUTB，DVIOUTL）で指定されます．
TEX を使って数式や結果を表示するための設定は以下の通りです．
• Windows 環境におけるデフォルト設定で get_rootdir()\bin に入れる risatex.bat は，例えば以下のような内容です（cf. DVIOUTA）:
cd "c:\Program Files\asir\tex"platex -src=cr,display,hbox,math,par risaout
start dviout -1 "c:\Program Files\asir\tex\risaout" 1000
– c:\Program Files\asir の部分は，デフォルトでは get_rootdir() となります．cd の後には，DIROUT で示されるディレクトリを示しますが，数式を LATEX に直した out.tex を書
き込むディレクトリであって書き込み可能である必要があるので，デフォルトを変更するのがよいでしょう．
– また dviout にパスが通っていないときは，上の 3 行目の dviout をフルパス名に変更します．
– 最後の行のパラメータ −1 は，1 番目の dviout に対する指示を意味し，それが起動していな
いと起動することも意味します．
– 最後の 1000 は表示するページを表し，十分大きな数にしておけば最終ページを表示することを意味します．表示する数式が最後に追加されていくので，このようにしています．

DIROUT に置かれる risaout.tex は以下のような内容のファイルです：\documentclass[a4paper]{amsart}\usepackage{amsmath, amssymb, amsfonts}\pagestyle{empty}\begin{document}\thispagestyle{empty}\input{out}384\end{document}
以下のように変更すると，より長い式が表示できます．またグラフ表示などで XY-pic または TikZを使うことがあるので，それを読み込んでいます．このXY-pic はインタネットなどから情報を得て，インストールしてください.

\documentclass[a4paper]{amsart}\usepackage{amsmath,amssymb,amsfonts}\AtBeginDvi{\special{dviout -y=A3L}}\usepackage[all]{xypic}\pagestyle{empty}\textwidth=7.6in\textheight=11in\voffset=-1.4in\hoffset=-1.4in\begin{document}\thispagestyle{empty}\input{out}\end{document}
dvi ファイルは使わず，dvipdfmx や pdfTeX によって pdf ファイルを生成してそれのみを使う場合は，上の \usepackage[all]{xypic} を\usepackage[pdf,all]{xypic} に変えた方が，良質の pdf ファイルが得られます．
そ れ を（dviout0(4) で の 切 り 替 え に 対 応 の ）DVIOUTB に 設 定 す る に は ，た と え ば 以 下 のrisaoutpdf.tex を c:\Program Files\asir\tex におき\documentclass[a4paper]{amsart}\usepackage{amsmath,amssymb,amsfonts}\usepackage{pdf,all]{xypic}\pagestyle{empty}\begin{document}\thispagestyle{empty}\input{out}\end{document}
さらに risatex1.bat を

cd "c:\Program Files\asir\tex"platex risaoutpdf
dvipdfmx risaoutpdf
risaoutpdf.pdfとし，risatex1.bat はフルパスで DVIOUTB に設定します．
pdf フ ァ イ ル を 更 新 表 示 可 能 な SumatraPDF.exe で 表 示 す る に は ，上 の 最 終 行 のrisaoutpdf.pdf をたとえば"c:\Program Files\SumatraPDF\SumatraPDF.exe" -reuse-instance risaoutpdf.pdf
XY-pic でなくてより高機能の TikZ（ただし速度はより遅い）を使う場合は，risaoutpdf.tex を
たとえば以下のように変更します.
\documentclass[dvipdfmx,a4paper]{amsart}\usepackage{amsmath,amssymb,amsfonts}\usepackage{tikz}
385

\pagestyle{empty}\begin{document}\thispagestyle{empty}\input{out}\end{document}
また上に合わせたグラフィック出力にするには，初期設定ファイル .muldif にTikZ=1という一行を加えます．これは dviout0(6), dviout0(7) で起動後に変更もできます．

XY-pic と TikZ の両方に自動対応するには，たとえば以下のようにします．
DVIOUTB な ど の 中 の %TiKZ% に は TikZ の 値 に 置 き 換 え ら れ る の で デ フ ォ ル ト の DVIOUTBの 場 合 に は ，XY-pic 対 応 と TikZ 対 応 の risaoutpdf.tex を そ れ ぞ れ risaoutpdf0.tex，
risaoutpdf1.tex と い う 異 な っ た フ ァ イ ル 名 に し ，バ ッ チ フ ァ イ ル risatex10.bat,
risatex11.bat をそれぞれ
cd "c:\Program Files\asir\tex"platex risaoutpdf0
dvipdfmx risaoutpdf0"c:\Program Files\SumatraPDF\SumatraPDF.exe" -reuse-instance risaoutpdf0.pdf
および

cd "c:\Program Files\asir\tex"platex risaoutpdf1
dvipdfmx risaoutpdf1"c:\Program Files\SumatraPDF\SumatraPDF.exe" -reuse-instance risaoutpdf1.pdf
XY-pic と TikZ を同時に対応することも出来て，例えば以下のようにします．
\documentclass[dvipdfmx,a4paper]{jsarticle}\usepackage{amsmath,amssymb,amsthm,amscd,mathrsfs}\usepackage{tikz}%\usetikzlibrary{patterns,shapes} % if necessary\usepackage[pdf,all]{xy}\begin{document}\thispagestyle{empty}\input{out}\end{document}• なお，AMSTeX=0 のときは，risatex0.bat と risaout0.tex が使われ，それぞれ以下のようです．
cd "c:\Program Files\asir\tex"platex -src=cr,display,hbox,math,par risaout0
start dviout -1 "c:\Program Files\asir\tex\risaout0" 1000
\documentclass{article}\pagestyle{empty}\begin{document}\thispagestyle{empty}\input{out0}\end{document}• Unix や Mac の場合は，risatex.bat でなくて risatex.sh がデフォルトのファイル名で，例えば以下のようであって，それに実行権限を付加しておきます（chmod 755）．
386

#!/bin/sh
cd ${HOME}/asir/tex
platex -src=cr,display,hbox,math,par risaout
dvipdfmx risaout
evince risaout.pdf &あるいは，環境によっては#!/bin/sh
cd $HOME/asir/tex/usr/local/texlive/2014/bin/x86_64-darwin/platex risaout/usr/local/texlive/2014/bin/x86_64-darwin/dvipdfmx risaout
open -a Preview risaout.pdfのようにフルパスで実行ファイルを指定します．このとき risaout.tex は，たとえば以下のようになります．

\documentclass[a4paper]{amsart}\usepackage{amsmath,amssymb,amsfonts}\usepackage[pdf,all]{xy}\pagestyle{empty}\begin{document}\thispagestyle{empty}\input{out}\end{document}
な お ，risatex0.bat や risatex1.bat も ，デ フ ォ ル ト の フ ァ イ ル 名 は risatex0.sh や
risatex1.sh となります．
• risaout.tex および risaout0.tex が DIROUT に存在しないとき（かつ DIROUT が書き込み可能なとき）は，必要に応じてデフォルトのものが自動的に作成されます．
• get_rootdir()\lib-asir-contrib にある noro_print.rr を以下のように変更し，AM SLATEXにも対応するようにします．
なお，この変更は配布版に取り入れられています．

*** noro_print_org.rr Wed May 24 17:54:34 2006--- noro_print.rr Mon Dec 14 00:26:32 2009****************** 4,7 ****--- 4,8 ---extern Taka_png_form_res$+ extern AMSTeX$
Taka_png_form_res=150$*** 78,84 ****
def taka_tex_form_matrix(A,Tb) {N = size(A)[0];M = size(A)[1];!
write_to_tb("\\pmatrix{\n",Tb);

387

for (I=0; I<N; I++) {for (J=0; J<M; J++) {--- 79,86 ---def taka_tex_form_matrix(A,Tb) {+extern AMSTeX;
N = size(A)[0];M = size(A)[1];!
write_to_tb(AMSTeX?"\\begin{pmatrix}\n":"\\pmatrix{\n",Tb);for (I=0; I<N; I++) {for (J=0; J<M; J++) {****************** 86,102 ****
if (J != M-1) write_to_tb("& ",Tb);}!
write_to_tb(" \\cr\n",Tb);}!
write_to_tb("}\n",Tb);}
def taka_tex_form_vector(A,Tb) {N = size(A)[0];!
write_to_tb("\\pmatrix{\n",Tb);for (I=0; I<N; I++) {taka_tex_form(A[I],Tb);
if (I != N-1) write_to_tb("& ",Tb);}!
write_to_tb("\\cr}\n",Tb);}--- 88,105 ---if (J != M-1) write_to_tb("& ",Tb);}!
write_to_tb(AMSTeX?((I==N-1)?"\n":" \\\\\n"):" \\cr\n",Tb);}!
write_to_tb(AMSTeX?"\\end{pmatrix}\n":"}\n",Tb);}
def taka_tex_form_vector(A,Tb) {+extern AMSTeX;
N = size(A)[0];!
write_to_tb(AMSTeX?"\\begin{pmatrix}\n":"\\pmatrix{\n",Tb);for (I=0; I<N; I++) {taka_tex_form(A[I],Tb);388

if (I != N-1) write_to_tb("& ",Tb);}
write_to_tb(AMSTeX?"\n\\end{pmatrix}\n":"\\cr}\n",Tb);!
}

3.2.14 補足
3.2.14.1 行列の入力
行列の入力が容易になるよう様々な方法が提供されている．



2 1 0
• 行列 0 2 0  の入力は
0 0 −1– mat([2,1,0],[0,2,0],[0,0,-1]) : 各行をリストで列の数だけ並べる．
mat([2,1,0],[0,2],[0,0,-1]) でもよい．
最初の行の成分の個数で列の数が決まるので，最初の行のみ後方の 0 は省略できない．
– s2m("210,020,0^2-1") : 行成分を並べて行を “ , ” で区切る．
s2m("21,02,0^2-1") でもよい．
成分があまり大きくない整数や有理数のとき可能で，入力が短いので便利（詳しくは，s2m()）．
行成分の最大個数で列のサイズが決まり，それに足らない成分には 0 が入る．
たとえば数 0 が 4 個続くときは，0^4 と書いてもよい．
– s2m([[2,1,0],[0,2,0],[0,0,-1]]) : mat() とほぼ同じ，全体を [ ] で囲う．
s2m([[2,1],[0,2],[0,0,-1]]) と省略できる．
– s2m("[2 1 0][0 2 0][0 0 -1]") : Risa/Asir の行列の画面出力を文字列として指定．
s2m("[2 1][0 2][0 0 -1]") と省略できる．
などのいずれもが可能である．
整数成分の 2 が不定元 a のときは，上の 2 番目方法のみ不可（a は整数 10 と解釈される）．

•対角行列 a 0 0
0 b 0
0 0 c


λ 0 0
0 λ 0
0 0 λ
a1 0 0 0 a2 0 
0 0 a3•一般行列
a11 a12 a13
a21 a22 a23 a
a32 a33 31

a00 a01 a02
a10 a11 a12 a
a21 a22 20

a1 a2 a3
 b 1 b 2 b3 c1 c2 c3

: diagm(3,[a,b,c]) （対角成分を与える）: diagm(3,[lambda]) （スカラー行列）: diagm(3,a) （対角成分の自動添え字）: mgen(3,3,a,1)（二重添え字の一般行列）: mgen(3,3,a,0)（二重添え字の一般行列）: mgen(3,3,[a,b,c],1)389（一重添え字の一般行列）
a 1 b1 c 1
a2 b2 c2 a b c
 3 3 3 a11 a12 a13
a12 a22 a23 a
a23 a33
 13

a1 a2 a3
a2 b2 b3 
a b3 c 3
 3

0a12 a13
−a12
0
a23 
−a
−a
0
 13 230 a 0
0 0 a
0 0 0


λ 1 0
0 λ 1
0 0 λ


0 0 1
1 0 0
0 1 0: mtanspose(mgen(3,3,[a,b,c],1))（一重添え字の一般行列）: mgen(3,"symmetric",a,1)（二重添え字の一般対称行列）: mgen(3,"symmetric",[a,b,c],1) （一重添え字の一般対称行列）: mgen(3,"skew",a,1) : （二重添え字の一般歪対称行列）: mgen(3,"highdiag",[a],1) （対角成分の一つ上）: diagm(3,[lambda])+mgen(3,"highdiag",[1],1): mgen(3,"perm",[3,1,2],1) （置換行列）

mgen() を参照．
より詳しくは，
cos α − sin α: mrot(α) （2 次回転行列）
sin α cos α
cos θ◦ − sin θ◦: mrot(θ|deg=1) （2 次回転行列）
sin θ◦cos θ◦

a11 a12 a13
a12 a22 a23  = kz (α)ky (β)kz (γ) : mrot([α,β,γ]) （3 次回転行列, kt (θ) は t 軸中心のa31 a32 a33
θ 回転の行列）A = kz (γ)−1 ky (β)−1kz (α)ky (β)kz (γ) : mrot([α,β,γ]|inv=1) （3 次回転行列）• 行列をつなげる




1 0
2 0
A=
,B=
とすると
0 1
0 2


1 0 2 0: newbmat(1,2,[[A,B]]) （横につなげる）
0 1 0 2


1 0
0 1


: newbmat(2,1,[[A],[B]]) （縦につなげる）
2 0
0

1
0

0
0

1
0

2
0

2
0
1
0
0
0
1
0
2

0
0
2
0
2
0
1
0


0
0

0
2

0
2

0

: newbmat(2,2,[[A],[0,B]]) （対角につなげる）: newbmat(2,2,[[A,B],[B,A]])

1

newbmat(m,n,[[A11 ,A12 ,. . .],[A21 ,A22 ,. . .],. . .]) は, m × n のブロック行列を作る函数である．
390

• 行列を抜き出す
a00 a01 a02 a03
a10 a11 a12 a13 A=a20 a21 a22 a23  とする．ここでは，行や列の番号は 0 から始まると考える．
a30 a31 a32 a33

a00 a01 a02: mperm(A,[0,2],[0,1,2]) （0 行目と 2 行目，0 列目と 1 列目と 2 列目をこa20 a21 a22
 の順に抽出）a00 a01 a02 a03: mperm(A,[0,2],0) （0 行目と 2 行目をこの順に抽出）
a20 a21 a22 a23

a02 a00
a12 a10 : mperm(A,0,[2,0]) （2 列目と 0 列目をこの順に抽出）a22 a20 
a
a30
 32

a00 a02: mperm(A,[0,2],1) （0 行目と 2 行目から正方行列を作る）
a20 a22
a10 a11 a12 a13
a20 a21 a22 a23 a30 a31 a32 a33  : mperm(A,[1,2,3,0],0) （0 行目を最後の行に繰り下げる）
a00 a01 a02 a03
2 番目は行の指定を，3 番目は列の指定をリストで表す．
ただし 0 は変えないこと, 3 番目の引数 1 は 2 番目の引数に等しいことを表す．
より詳しくは mperm() を参照．


• 行列の列数の調整：madjust() を参照
3.2.14.2

平面図形

P , Q, R, S, T は座標，s, t は実数とする（平面座標は，Q = [3, 4] のようにリストで与える）．
交点や接点を求める• 座標 P を小数点以下 m 桁で丸める：
sint(P ,m)−−→ −−→ −−→• OX = OP + OQ となる X を返す（O は原点）：ladd(P ,Q,1)−−→ −−→ −−→• OX = OP − OQ となる X を返す：
lsub([P ,Q]), ladd(P ,Q,−1).
−−→ −−→−−→• OX = OP + t · OQ となる X を返す：
ladd(P ,Q,t)−−→−−→• OX = t · OQ となる X を返す：
ladd(0,Q,t)
−−→
−−→
−−→
• OX = sOP + t · OQ となる X, すなわち線分 P Q の t : s の内分点を返す：
ladd(P ,Q,[s,t])
−−→
−−→
−−→
• OX = (1 − t)OP + t · OQ となる X, すなわち線分 P Q の t : 1 − t の内分点を返す：
ladd(P ,Q,[t])−−→ −−→−−→• OX = OP + t · P Q となる X を返す：
ladd(P ,Q,t)• P から Q の方向へ d だけ進んだ点を返す（d は負でもよい）：
ladd(P ,Q,[ d/dnorm([P ,Q]) ])391

• 線分 P Q の中点を返す：
ladd(P ,Q,[ 21 ])• 直線 P Q と直線 RS との交点を返す （並行なら 0 を，一致するなら 2 を返す）:
ptcommon([P ,Q],[R,S])• 線分 P Q と線分 RS との交点を返す :ptcommon([P ,Q],[R,S]|in=1) （交わらないときは 0 を返す）
• 点 R から直線 P Q に下ろした垂線の足を返す :ptcommon([P ,Q],[R,0])• 点 R から線分 P Q に下ろした垂線の足を返す（線分 P Q 上に垂線の足がないときは 0 を返す）:
ptcommon([P ,Q],[R,0]|in=1)• 直線 P Q の垂直二等分線と直線 RS の垂直二等分線の交点を返す :ptcommon([P ,Q],[R,S]|in=-1)• 直線 P Q の垂直二等分線と直線 RS の交点を返す :ptcommon([P ,Q],[R,S]|in=-2)• 直線 P Q の垂直二等分線と線分 RS の交点を返す （線分 RS と交わらないときは 0 を返す）:
ptcommon([P ,Q],[R,S]|in=-3)−−→−−→ −−→• P Q を s 倍して θ 回転したベクトル v とするとき，OX = OQ + v となる X を返す：
ptcommon([P ,Q],[s,θ])• 線分 P Q の s : t の内分点を返す :ptcommon([P ,Q],[s,t]|in=1)• 線分 P Q の s : t の外分点を返す :ptcommon([P ,Q],[s,−t]|in=1)• 直線 P Q と中心が R で半径が r の円との交点を返す（交点がないときは 0 を返す）：
ptcommon([P ,Q],[R,r])• 線分 P Q と中心が R で半径が r の円との交点を返す（交点がないときは 0 を返す）：
ptcommon([P ,Q],[R,r]|in=1)• 中心が P で半径 s の円と中心が R で半径が r の円との交点（ないときは 0）を返す：
ptcommon([P ,s],[R,r]|in=1)• 中心が P で半径 s の円に点 R から引いた接線の接点を返す：
ptcommon([P ,s],[R,0]|in=1)• 三角形 P QR の五心を返す（重心，内心，外心，垂心，3 つの傍心のリスト）：
pt5center(P ,Q,R)• 三角形 P QR の重心と各辺の中点を返す：
pt5center(P ,Q,R|opt=0)• 内接円（中心と半径の組）と各辺との接点を返す：
pt5center(P ,Q,R|opt=1)• 三角形 P QR の外接円（中心と半径の組）を返す：
pt5center(P ,Q,R|opt=2)• 三角形 P QR の垂心と頂点から底辺に下ろした垂線の足を返す：
pt5center(P ,Q,R|opt=3)• 三角形 P QR の傍心円（中心と半径の組）と各辺またはそれの延長線との接点を返す：
pt5center(P ,Q,R|opt=4, 5, 6)−−→• 中心が O で半径が r の円と，二直線 P Q, RS に接する円を返す（P Q に対して第 1, 3 象限側）：
pt5center([O,r],[P ,Q],[R,S])

392

• 点 P を反転した点を返す（反転の中心を (x0 , y0 ) とする）：
ptinversion(P |org=[x0 ,y0 ])• 円 [[a,b],r] を反転した円を返す：
ptinversion([[a,b],r]|org=[x0 ,y0 ])• 中心が (x0 , y0 ) で半径 r の円に関して，点 P を反転した点を返す：
ptinversion(P |org=[x0 ,y0 ],sc=r)• 2 つの Bézier 曲線 ℓ1 と ℓ2 の交点を返す :ptcombezier(b1 ,b2 ,m)• 2 つの複合 Bézier 曲線 b1 と b2 の交点を返す :ptcombz(b1 ,b2 ,m)• 複合 Bézier 曲線 b の自己交叉点を返す :ptcombz(b,0,m)• 直線 P Q の {(x, y) | xmin ≤ x ≤ xmax , ymin ≤ y ≤ ymax } の部分の両端を返す：
lninbox([P ,Q],[[xmin ,xmax ],[ymin ,ymax ]])• 線分 P Q の {(x, y) | xmin ≤ x ≤ xmax , ymin ≤ y ≤ ymax } の部分の両端を返す：
lninbox([P ,Q],[[xmin ,xmax ],[ymin ,ymax ]]|in=1)
条件を満たす点のリストを求める• 点 P, Q, R, . . . の {(x, y) | xmin ≤ x ≤ xmax , ymin ≤ y ≤ ymax } 外のものを数 0 に変える：
ptwindow([P, Q, R, . . .],[xmin ,xmax ],[ymin ,ymax ])• 点 P, Q, R, . . . にアフィン変換を施す：
V を中心に θ 回転して行列（またはスカラー）M を掛け，さらに W 平行移動する．
座標でなくて数の成分があれば，それは変換しない（xybezier() の引数など）．
ptaffine(M ,[P, Q, R, . . .]|org=V ,arg=θ,deg=θ,shift=W )• 半径 r で中心 P の円に内接する（始点の偏角が θ の）正 n 多角形の頂点の平面座標を返す :ptpolygon(n,r|org=P ,arg=θ,deg=θ)−−→ −→−−→−−→• OX = OS + k · OQ + ℓ · OR （0 ≤ k < m, 0 ≤ ℓ < n）の格子点 X の座標のリストを返す：
f1 (X[0], X[1]) ≥ 0, f2 (X[0], X[1]) ≥ 0, . . . を満たさない点は除く．
ptlattice(m,n,P ,Q|org=S,scale=t,cond=[f1 ,f2 ,...])• 点 P1 , P2 , . . . の凸包の多角形の頂点を求める．
ptconvex([P1 , P2 , . . .])• すべての点 P1 , P2 , . . . を頂点にもつある多角形の頂点を求める．
ptconvex([P1 , P2 , . . .]|opt=1)−−→• 点 R が，直線 P Q の左側にある条件（P Q が正の向き）
dext([P, Q],[P, R]) > 0 あるいは darg([P, Q], [P, R]) > 0
長さや角度を求める−−→• OP の長さを返す :dnorm(P )−−→• P Q の長さを返す :dnorm([P ,Q])−−→ −−→• OP と OQ の内積を返す :dvprod(P ,Q)−−→ −→• P Q と RS の内積を返す :dvprod([P ,Q],[R,S])
393

−−→ −−→• 2 次元ベクトル OP と OQ の外積を返す :dext(P ,Q)−−→ −→• 2 次元ベクトル P Q と RS の外積を返す :dext([P ,Q],[R,S])−−→• 2 次元ベクトル P Q の偏角 θ（− π2 < θ ≤ 32 π ）に応じた値を返す:
darg(P ,Q)
−−−→
−−−→
• 2 次元ベクトル P1 P2 に対し，Q1 Q2 のなす角に応じた値を返す（0: 同じ向き，2: 逆向き，±1: 左（右）回りに直交）．

darg([P1 ,P2 ],[Q1 ,Q2 ])• 閉じた折れ線 Q1 , . . . , Qn , Q1 の点 P に対するの回転数を返す．
dwinding(P ,[Q1 , . . . , Qn ])−−→ −→• P Q と RS のなす角 θ（−π < θ ≤ π ）をラジアンで返す :ptcommon([P ,Q],[R,S]|in=2)−−→ −→• P Q と RS のなす角 θ（−180 < θ ≤ 180）を度で返す :ptcommon([P ,Q],[R,S]|in=3)• ∠P OQ の余弦を返す（P = O または Q = O のときは 1 を返す） :dvangle(P ,Q)• ∠P QR の余弦を返す（P = Q または Q = R のときは 1 を返す） :dvangle([P ,Q,R],0)• 三角形 P QR の面積 :dnorm([P ,ptcommon([Q,R],[P ,0])])*dnorm([Q,R])/2
基本的図形の描画
以下はデフォルトでは TEX のソースを返すが，オプション proc=1 で描画実行形式を返し，dviout=1 で画面表示する．

• 点 P , Q, . . . を折れ線で順に繋ぐ :xylines([P ,Q, . . .]|opt=s)
TikZ の場合は，s に以下のような指定が可能（重複指定は "red,dotted" のように指定）．
線の太さ指定 "thick", "thin", "width=2pt", . . .
線種指定"dotted", "densely dotted", "loosely dotted", "dashed", . . .
二重線"double", "double distance=2pt", . . .
色指定"red", "blue", "lightgray", "green!30!white", . . .
• 点 P , Q, . . . を順に折れ線で繋ぎ，最後の点と最初の点も繋ぐ :xylines([P ,Q, . . .]|close=1,opt=s)
TikZ の場合は，さらに s に以下のような塗りつぶし指定も可能
塗りつぶしの色"fill=red","fill=lightgray", . . .
パターン塗りつぶし "pattern=northeastline", "pattern=grid", "pattern=dots", . . .
パターンの色"pattern color=red", . . .
塗りつぶしの透明度 "opacity=.5"
塗りつぶし部分"even odd rule"
塗りつぶしのみで境界線を描かないときは，opt=[s,"fill"] と指定する．
• 点 P , Q, . . . を順に通る滑らかな曲線 :xylines([P ,Q, . . .]|curve=1,opt=s)• 点 P , Q, . . . を順に通る滑らかな閉曲線 :xylines([P ,Q, . . .]|curve=1,close=1,opt=s)• y = f (x) (x1 ≤ x ≤ x2 ) で定まる函数のグラフの y1 ≤ y ≤ y2 の部分 :394

xygraph(f ,n,[x1 ,x2 ],0,[y1 ,y2 ]|opt=s,org=P ,scale=r,prec=v)
• f1 (t), f2 (t) (t1 ≤ t ≤ t2 ) で定まる平面曲線の x1 ≤ x ≤ x2 , y1 ≤ y ≤ y2 の部分 :xygraph([f1 ,f2 ],n,[t,t1 ,t2 ],[x1 ,x2 ],[y1 ,y2 ]|opt=s,org=P ,scale=r,prec=v)• 点 P , Q を対角の頂点とする水平な長方形 :xybox([P ,Q])
• 点 P , Q を対角の頂点とする水平な長方形の TikZ での色付けと塗りつぶし :xybox([P ,Q]|color=s,fill=t)• 点 P , Q を対角の頂点とし，R をもう一つの頂点とする平行四辺形 :xybox([P ,Q,R])• P を中心とする半径 r の円に内接し，一つの頂点の偏角が θ となる正 n 角形 :xylines(ptpolygon(n,r|org=P ,arg=θ))• 点 P を中心とする半径 r の円 :xyang(r,P ,0,0)• 点 P を中心とし, Q を通る円 :xyang(Q,P ,0,0)• 中心 P ，半径 r の円の偏角が [α, β] の部分の円弧 :xyang(r,P ,α,β)• 点 P を中心とし，反時計回りに Q を始点として直線 P R と交わるまでの円弧:
xyang(Q,P ,Q,R)• 中心 P ，半径 r の円の偏角が [α, β] の部分の扇形 :xyang(r,P ,α,β|ar=1)• 三角形 P QR の内接円 :xyang(-1,P ,Q,R) または
C=pt5circ(P ,Q,R)[2]; xyang(H=ptcommon([P ,Q],[C,0]),O),C,0,0)• 三角形 P QR の外接円 :xyang(-2,P ,Q,R);• 三角形 P QR の傍接円 （∠P 内）:
xyang(-3,P ,Q,R)• 直線 QR に接する P が中心の円 :xyang(-6,P ,Q,R)• 直線 QR に P から下した垂線 :xyang(-7,P ,Q,R)• 中心が P で基準軸の半径が r と qr の楕円 :xyoval(P ,r,q)• 中心が P で基準軸の半径が r と qr で，基準軸の偏角が γ の楕円 :xyoval(P ,r,q|ang=[0,0,γ],deg=[0,0,γ])• 中心が点 P で基準軸の偏角が γ ，半径が r と qr で，偏角が [α, β] の部分の楕円弧 :xyoval(P ,r,q|ang=[α,β,γ],deg=[α,β,γ])• 点 P が中心，基準軸の偏角が γ ，半径が r と qr で，偏角が [α, β] の部分の楕円扇形 :xyoval(P ,r,q|ar=1,ang=[0,0,γ],deg=[0,0,γ])
−→
−−→
−−→
• 格子点を（fj ≥ 0 を満たす）OS + k · OQ + ℓ · OR（0 ≤ k < m, 0 ≤ ℓ < n）とする格子 :xylines(ptlattice(m,n,P ,Q|line=1,org=S,scale=t,cond=[f1 ,f2 ,...]))−−→−→• ∠QP R に半径 r の角度記号（P Q から反時計回りに P R まで）:
xyang(r,P ,Q,R)

395

−−→
• P Q の始点 P に一辺 r で反時計回りに直角記号を描く :xyang(r,P ,Q,1)−−→• P Q の始点 P に一辺 r で時計回りに直角記号を描く :xyang(r,P ,Q,-1)−−→• QP の終点 P に種々の矢印記号の矢先を長さ r で描く (−4 ≤ t ≤ −2, t = 0, 2 ≤ t ≤ 8, 10 ≤ t):t = −4(135◦ ), −3(120◦ ), −2(150◦ ), 0(90◦ ), 2, 5(45◦ ), 3, 6(30◦ ), 4(60◦ )，7(22.5◦ ), 8(15◦ )5 ≤ t ≤ 8 のときは曲線．t ≥ 10 では角度とみなす．ar=2 では閉じた形にする．
xyang(r,P ,Q,t), xyang(r,P ,Q,t|ar=2)−−→• QP の終点 P に種々の矢印を長さ r で描く (−4 ≤ t ≤ −2, t = 0, 2 ≤ t ≤ 8, 10 ≤ t):xyang(r,P ,Q,t|ar=1), xyang(r,P ,Q,t|ar=3)• 関数 y = f (x) のグラフ (x ∈ [a, b]) の [x1 , x2 ] × [x2 , y2 ] 内の部分を [a, b] の n 分点を取って描く ：xygraph(f ,n,[a,b],[x1 ,x2 ],[y1 ,y2 ]|ax=?,scale=?,...)
• 曲線 f (t), g(t) (t ∈ [a, b]) の [x1 , x2 ] × [x2 , y2 ] 内の部分を [a, b] の |n| 分点を取って描く ：xygraph([f, g],n,[t,a,b],[x1 ,x2 ],[y1 ,y2 ]|ax=?,scale=?,...)• 曲面 z = f (x, y) ((x, y) ∈ [x1 , x2 ] × [y1 , y2 ]) を，z ∈ [h1 , h2 ] の範囲で，x 軸を y 軸方向に α◦ 回転した無限遠方から β ◦ 見下ろしたものとして，x, y 座標を共に |n| 等分した曲面上のメッシュで描く．
xy2graph(f ,n,[x1 ,x2 ],[y1 ,y2 ],[h1 ,h2 ],α,β |scale=?,ax=?)• 空間内の曲線 f1 (t), f2 (t), f3 (t) (t ∈ [t1 , t2 ]) を，x 軸を y 軸方向に α◦ 回転した無限遠方から β ◦ 見
下ろしたものとして描く．隠線消去は距離 g mm を基準とする．
xy2curve([f1 ,f2 ,f3 ],n,[t,t1 ,t2 ],[y1 ,y2 ],[z1 ,z2 ],α,β|gap=g,scale=?,ax=?)
3.2.14.3

リスト形式函数

数値に対して値を取る函数には，dsin(x) のような函数と sin(x) のような函数がある．
前者の x は dsin(0.1) のように実数のみが可能で不定元の x を用いて dsin(x) とするとエラーとなる．
後者は不定元 x を用いた sin(x) という形が可能で，たとえばそれの導関数は diff(sin(x),x) によってcos(x) が得られる．これらの函数を代入した exp(sin(x)+y) のような函数を定義することも可能である．
一方，subst(sin(x),x,0.1) としても sin 0.1 の値が得られるのでなく不定元 sin(0.1) が得られ，実際の sin 0.1 の値を得るには eval(sin(0.1)) としなければならない．ところが sin(0.1) や sin(0.2) は異なる不定元として Risa/Asir のメモリー・エリアに登録されたままになるので，いろいろな数値を代入することを何度も行うと大量の不定元が登録されて，Risa/Asir の動作が極端に遅くなったり不安定になったりす
る*2 ．（3D グラフ描画の際に生じた）このような不具合への対処のためリスト形式函数を定義した．
最も簡単なものは[返す式, [不定元，函数子，引数]]というリストの形で，上の引数に不定元 x が含まれているとすると，リストの x に数を代入し，次に（代入を行った）引数を与えて函数を呼んだ戻り値を返す式の不定元に代入して得られた値を返す，という形でリスト
形式函数の値が求められる．
sin(x) をリスト形式函数で表現すると [z,[z,sin,x]] となり*3 ，リスト形式函数に対する eval() やdeval() に対応するものとして myeval() と mydeval() が定義されている．よってたとえば sin2 (0.1) は[0] F=sin(x)^2$[1] FL=[z^2,[z,sin,x]]$[2] eval(subst(F,x,0.1));
0.0099667110793791855371[3] myeval(subst(FL,x,0.1));*2 現時点では，Risa/Asir の再起動以外には，このように発生した不定元をメモリーから消す手段が提供されていない．
*3 この z は任意の不定元でよい.

396

0.0099667110793791855371[4] dsin(0.1)^2;
0.00996671[5] deval(sin(0.1)^2)-dsin(0.1)^2;
0[6] os_md.myfdeval([z^2,[z,dsin,x]],0.1);
0.00996671のようになる．
ここで myfdeval() は，subst() と mydeval() とを同事に行う函数である（同様な myfeval() もある）．
より複雑なリスト形式函数の仕様については myeval() の項を参照して下さい．
なお，次のようなものはリスト形式函数である．

• sin などの函数子を含まない x^2+1 や (x+1)/(y-1) のような多項式や有理式• リスト形式函数にリスト形式函数を代入したものは，リスト形式函数となる（compdf() で代入が可能）．
f2df() は，函数子を含む通常の函数をリスト形式函数に変換する．変換で sin のような函数は dsin のような数値のみを引数とする函数で置き換えるので，多くの値を代入しても不定元の大量発生は起こらない．一方 sin(0.1)^2 の計算は dsin(0.1)^2 に置き換えられるので，任意精度（bigﬂoat）浮動小数の計算ではな
く倍精度浮動小数計算となる（cf. §2.9.2）．
[0] deval(exp(sin(1)));2.31978[1] Exp_x=os_md.f2df(exp(x));[z__,[z__,os_md.myexp,x]][2] Sin_x=os_md.f2df(sin(x));[z__,[z__,os_md.mysin,x]][3] F=os_md.compdf(Exp_x,x,Sin_x);[z__,[z__00,os_md.mysin,x],[z__,os_md.myexp,z__00]][4] os_md.myfdeval(F,1);
2.31978[5] G=os_md.f2df(exp(sin(x)));[z__,[z__,os_md.myexp,[z1__,[z1__,os_md.mysin,x]]]][6] os_md.myfdeval(G,1);
2.31978[7] os_md.compdf(y/(x^2+1),[x,y],[Exp_x,Sin_x]);[(z__01)/(z__00^2+1),[z__01,os_md.mysin,x],[z__00,os_md.myexp,x]]
なお，上の myexp() や mysin() は dexp() や dsin() と違って複素変数も許す拡張された数値函数である．

• 数値函数で，不定変数，すなわち，不定元，有理式，函数やリスト形式函数（など f2df() で扱える函数）を引数としたとき，対応するリスト形式函数を返す函数に次のようなものがある– 倍精度浮動小数点計算の数値函数

myexp(), mycos(), mysin(), mytan(), myacos(), myasin(), myatan(), mylog(), mypow(),myarg(), fouriers()– bigfloat にも対応した
abs()，sqrt(), frac(), arg(), gamma(), lngamma(), digamma(), dilog(), erfc(), zeta(),eta(), jell()• 函数 f をリスト形式函数に変換する

397

f2df(f )• 函数 f の不定元 x に函数 g を代入したリスト形式函数を得る（f , g はリスト形式函数でもよい）
compdf(f ,x,g)• 函数 f の不定元 x1 , x2 , . . . のそれぞれに函数 g1 , g2 , . . . を代入したリスト形式函数を得る
compdf(f ,[x1 ,x2 , . . .],[g1 ,g2 , . . .])• 函数子 f で変数が v1 , . . . , vn のリスト形式函数を得る（n は f の引数の数）
vj は数値，不定元，有理式，リスト形式函数など f2df() で解釈できる函数でよい．
todf(f ,[v1 ,. . .,vn ])• 函数子 f のオプションリストが [ops] で変数が v1 , . . . , vn のリスト形式函数を得る．
vj は数値，不定元，有理式，リスト形式函数など f2df() で解釈できる函数でよい．
todf([f ,[ops]],[v1 ,. . .,vn ])• 変数への代入などによって値を評価できる（リスト形式）函数 f を評価して函数値を得る
myeval(f ) mydeval(f ) myval(f )myeval() は eval() にあたり（可能なら bigﬂoat)，mydeval() は deval() にあたり（複素数値には非対応），myval() は可能な限り浮動小数点を用いない値を得る．
•（リスト形式）函数 f の不定元 x に値 a を代入した函数値を得る
myfeval(f ,a) myfdeval(f ,a)
前者は eval() に対応（可能なら bigﬂoat)，後者は deval() に対応（複素数値には非対応）．
•（リスト形式）函数 f の不定元 x に値 a を代入した函数値を得る
myfeval(f ,[x,a]) myfdeval(f ,[x,a])•（リスト形式）函数 f の不定元 x1 , x2 , . . . に値 a1 , a2 , . . . を代入した函数値を得る
myfeval(f ,[[x1 ,a1 ],[x2 ,a2 ],. . .]) myfdeval()(f ,[[x1 ,a1 ],[x2 ,a2 ],. . .])•（リスト形式）函数 f の不定元 x, y に値 a, b を代入した函数値を得る
myf2eval(f ,a,b) myf2deval(f ,a,b)• リスト形式函数 f を倍精度浮動小数点計算から bigfloat 計算へ変更する
df2big(f )• リスト形式函数 f を bigfloat 計算から倍精度浮動小数点計算へ変更する
df2big(f |inv=1)• 函数 f の変数 x の aj での値を bj に変更した（j = 1, . . . , n − 1）変数 x のリスト形式函数を得る
cutf(f ,x,[[],[a1 ,b1 ],,...,[an−1 ,bn−1 ],[]])• a ≤ x < b のとき f (x) となる周期 b − a の x 変数のリスト形式函数を得る（f の変数は x とする）．
periodicf(f ,[a,b],x)• k = 1, . . . , n に対して (k − 1)c ≤ x < kc のとき hk (y) (0 ≤ y < c, x−yc ∈ Z) となる周期 nc の x 変数のリスト形式函数を得る

periodicf(ltov([h1 ,h2 ,. . .,hn ]),c,x)• 変数の範囲によって異なる函数の値を取るリスト形式函数を得る

v1 (x) (x < a0 ),vk(x = ak , k = 1, . . . , n − 1),g(x) =
v(x)(x> an ),n
f (x) (上以外の x)という x を変数とするリスト形式函数 g(x) は次のようにして得られる．
ただし，f , v1 , vn の変数は x で（v1 , vn は数でもよい），a0 ≤ a1 < a2 < · · · < an−1 ≤ an となっている必要がある（以下で [t,[a0 ,v0 ],[a1 ,v1 ],. . .,[an ,vn ]] とすると，f の変数の t に対応する）．

cutf(f ,x,[[a0 ,v1 ],[a1 ,v2 ],. . .,[an ,vn ]])• pari(funct, ) で呼び出される函数 funct を変数 x のリスト形式函数にする[z_,[z_,os_md.evals,["pari","funct",x]]]398

3.2.14.4

実数値／複素数値函数の解析

以下の函数には sin(x) のような函数のほか，リスト形式函数も含まれる．
零点• 実数値函数 f の区間 [x1 , x2 ] における（近似）零点とそこでの f の値を求める
fzero(f ,[x1 ,x2 ]|mesh=m,dev=d,dif=1,zero=1)• x 変数の多項式 p の実根を求める
polroots(p,x)• x 変数の多項式 p の実根を a ≤ x ≤ b の範囲で求める
polroots(p,x|lim=[a,b])• x 変数の多項式 p の（指定した範囲にある）有理根を求める
polroots(p,x|comp=2,lim=[a,b])• z 変数の多項式 p の（指定した範囲 a ≤ Re z ≤ b, b ≤ Im z ≤ d 内の）複素根をすべて求める
polroots(p,z|comp=1,lim=[z,[a,b],[c,d]])実部の制限がないときは [z,[],[c,d]], 虚部の制限がないときは [z,[a,b]] とする．
• z 変数の多項式 p の（指定した範囲内の）複素根をすべて求め，有理根は近似値でなく有理数を返す
polroots(p,z|comp=-1,lim=[z,[a,b],[c,d]])• x1 , . . . , xn 変数の n 個の多項式 p1 , . . . , pn の共通実根をもとめる
polroots([p1 ,...,pn ],[x1 ,...,xn ]|err=r)• z1 , . . . , zn 変数の n 個の多項式 p1 , . . . , pn の（範囲など）指定した条件を満たす共通根もとめる
polroots([p1 ,...],[z1 ,...]|comp=t,lim=[[z1 ,[a1 ,b1 ],[c1 ,d1 ]],. . .],err=r)
極値• 実数値函数 f の点 a での極限値を求める（a = −∞ を "-" で, a = ∞ を "+" で表す）
flim(f ,a|prec=c,init=t)• 実数値函数 f の点 a での右極限値や左極限値を求める
flim(f ,["±",a]|prec=c,init=t)• 実数値函数 f の区間 [x1 , x2 ] の極値とそのときの変数の値を求める
fmmx(f ,[x1 ,x2 ]|mesh=m,dev=d,dif=1,zero=1)• 実数値函数 g の区間 [x1 , x2 ] 内の零点とその点における函数 f の値を求める
fmmx(f ,[x1 ,x2 ]|mesh=m,dev=d,dif=g,zero=1)• 実数値函数 f の区間 [x1 , x2 ] での最小値と最大値とそのときの変数の値を求める
fmmx(f ,[x1 ,x2 ]|mmx=1,mesh=m,dev=d,dif=1,zero=1)
数値積分• 区間 [a, b] での実数値函数 f の数値積分（n は分割点の個数）a = "-" は −∞ を，b = "+" は +∞ を意味する．
変数が x でなくて t のときは，[a,b] を [t,a,b] とする．
[a, b] の外でも f が滑らかに定義されているときは，分割点の個数の −1 倍を n とする．
fint(f ,n,[a,b]|exp=c,int=k,prec=v)• 区間 [a, b] での複素数値函数 f の数値積分（n は分割点の個数）
fint(f ,n,[a,b]|cpx=1,exp=c,int=k,prec=v)
• 複素数値函数 f の C 1 級曲線 [a, b] 3 t 7→ ϕ(t), ψ(t) に沿った複素積分
f の変数は複素数 z とその実部 x と虚部 y を用いることができる．
fint(f ,n,[[ϕ,ψ],[a,b]]|exp=c,int=k,prec=v)399

• 複素数値函数 f の区分的 C 1 級曲線に沿った複素積分（f の変数は z, x, y）
fint(f ,n,[[[ϕ1 ,ψ1 ],[a1 ,b1 ]],[[ϕ2 ,ψ2 ],[a2 ,b2 ]]. . .]|exp=c,int=k,prec=v)• 点 (a1 , b1 ), (a2 , b2 ), . . . , (an , bn ) を順に繋ぐ折線に沿った複素数値函数 f の複素積分
fint(f ,n,[[a1 ,b1 ],[a2 ,b2 ],. . .,[an ,bn ]]|exp=c,int=k,prec=v)• 点 (a1 , b1 ), . . . , (an , bn ), (a1 , b1 ) を順に繋ぐ閉じた折線に沿った複素数値函数 f の複素積分
fint(f ,n,[[a1 ,b1 ],[a2 ,b2 ],. . .,[an ,bn ],-1]|exp=c,int=k,prec=v)
R• 曲線 C : [a, b] 3 t 7→ ϕ(t), ψ(t) に沿った線積分 C y dx
無限区間，すなわち a = "-"（−∞ を意味する）, b = "+"（+∞ を意味する）も可
areabezier([[ϕ,ψ],n,[t,a,b]]|exp=c,int=k,prec=v)• z 変数の有理式 pq （q は多項式）の ∀fj > 0 で表される領域の周での複素積分（留数計算）
fresidue(p,q|cond=[f1 ,f2 , . . .],sum=2)• 滑らかな閉曲線 C : [a, b] 3 t 7→ ϕ(t), ψ(t) で囲まれた領域の面積（曲線が時計回りならその −1 倍)areabezier([[ϕ,ψ],n,[t,a,b]]|int=k,prec=v)• 点 (a1 , b1 ), (a2 , b2 ), . . . , (an , bn ) を順に通り始点にもどる折線で囲まれた多角形の面積
areabezier(xylines([[a1 ,b1 ],...,[an ,bn ]]|close=1))• 点 (a1 , b1 ), (a2 , b2 ), . . . , (an , bn ) を順に通り始点にもどる滑らかな閉曲線で囲まれた部分の面積
areabezier(xylines([[a1 ,b1 ],...,[an ,bn ]]|close=1,curve=1))• 区分的 Bézier 曲線 ℓ で囲まれた部分の面積（ℓ は lbezier() で扱われるデータ形式のいずれか）
areabezier(ℓ)
不定積分（原始関数）

R• x を変数とする函数 f の不定積分 f (x) dx
integrate(f ,x)Rx• x を変数とする多項式 p の [0, x] での積分 0 p(x) dx
intpoly(p,x)
Rb• 原始関数を求めることによる定積分 a f (x) dx の計算
integrate(f ,x|I=[a,b])
R• x を変数とする有理函数 p の原始関数 p(x) dx
intpoly(p,x)• 多項式 p と三角関数 sin λx の積の原始関数
intpoly(p,x|sin=λ) R
戻り値 [g(x),h(x)] は p(x) sin λx dx = g(x) cos λx + h(x) sin λx を意味する．
• 多項式 p と三角関数 cos λx の積の原始関数
intpoly(p,x|cos=λ) R
戻り値 [g(x),h(x)] は p(x) cos λx dx = g(x) cos λx + h(x) sin λx を意味する．
• 多項式 p とべき函数 xλ の積の原始関数
intpoly(p,x|pow=λ)R
戻り値 g(x) は p(x)xλx dx = g(x)xλ を意味する．
• 多項式 p と対数関数 log(λx + c) の積の原始関数
intpoly(p,x|log=[λ,c])R
戻り値 [g(x),h(x)] は p(x) log(λx + c)dx dx = g(x) log(λx + c) + h(x) を意味する．
• 多項式 p と対数関数の自然数べき logm (λx + c) の積の原始関数
intpoly(p,x|log=[λ,c,m])
R
Pm
戻り値 [g0 (x),g1 (x), . . .] は p(x) logm (λx + c)dx = j=0 gj (x) logm−j (λx + c) を意味する．
留数400

• z 変数の多項式 q を分母とする有理式 pq の特異点と留数のリストを得る
fresidue(p,q)• f1 > 0, f2 > 0, . . . を満たす領域での有理式 pq の特異点と留数のリストを得る
fj は，z, x, y の（リスト形式）函数（z = x + yi）
fresidue(p,q|cond=[f1 ,f2 , . . .])• 条件を満たす留数の和を求める
fresidue(p,q|cond=[f1 ,f2 , . . .],sum=1)• load("sp") によって af_noalg() を使えるようにおくと，正確な値が求められる範囲が拡がる（cf. fctri()）．
初等関数の変換• x 変数の三角関数を，複素変数の指数関数に変更し，指数関数の積は一つにまとめる
trig2exp(f ,x)• x 変数の三角関数や複素変数の指数関数を実変数の三角関数と指数関数に変換し，三角関数の積は和にまとめる

trig2exp(f ,x|inv=1)• x 変数の三角関数を，可能な限り sin x の多項式や sin x の多項式と cos x との積の和に変換する
trig2exp(f ,x|inv=sin(x))• x 変数の三角関数を，可能な限り cos x の多項式や cos x の多項式と sin x との積の和に変換する
trig2exp(f ,x|inv=cos(x))
3.2.14.5

表形式データエクセルの表形式データのような表形式データを，Risa/Asir で処理するための函数について記す．そこでは，各行をリストとし，それを集めたリストをリスト形式データと呼ぶことにする．また，行をリスト形式
データの要素，縦の列を「項目」と呼ぶことにする．
表形式データの変換• エクセルの CSV 形式データをリスト形式データに変換して読み込む（eval="all"とすると，整数または小数を数として読み込む．デフォルトは文字列として読み込み，空の要素の項目は空文字列として読み込む）

readcsv(s|eval=[n1 ,n2 ,· · · ],eval=n,null=t)• リスト形式データを CSV 形式に変換（ファイルとして出力するには，fcat() を用いるとよい）
tocsv(ℓ)• リスト形式データを CSV 形式に変換して，それを Excel に渡す
tocsv(ℓ|exe=f )• リスト形式データを行列に変換
lv2m(ℓ)• 行列をリスト形式データに変換m2ll(m)• リスト形式データを TEX の表に変換
ltotex(ℓ|opt="tab",title=s)• 最初の n 個とそれ以降の要素との 2 つの表形式リストに分割する
lsort(ℓ,[],"cut"|c1=n)• 最初の方の要素とそれ以降の n 個の要素の 2 つの表形式リストに分割する
lsort(ℓ,[],"cut"|c1=−n)• 要素の項目数が異なっているとき，後ろに s（デフォルトは空文字）を詰めて揃える
lsort(ℓ,"adjust",["put",s])• 表を転置する（行と列をひっくり返す）
lsort(ℓ,"transpose",[])
401

データのソート• t1 番目の項目でソート
lsort(ℓ,"sort",["put",t1 ])• t1 番目の項目で逆順ソート
lsort(ℓ,"sort",["put",−t1 − 1])• 多重キーを用いた要素のソート
msort(ℓ,s)• t1 番目が同じものは一つを除いて削除（重複を省く）
lsort(ℓ,"sort",["reduce"])
項目を付加• 要素の先頭に，中身が s の項目を付加
lsort(ℓ,s,"cons")• 要素の先頭に，s1 , s2 , . . . を順に付加
lsort(ℓ,[s1 ,s2 , . . .],"cons")• 項目番号を順に入れたリストを最初の要素として付加
lsort(ℓ,"num",["col"])• 各要素の先頭に要素番号を n から順に入れた項目を付加
lsort(ℓ,"num",["put",n])
要素や項目を抜き出す• 項目 c1,1 , c1,2 , · · · を抜き出す
lsort(ℓ,"col",["put"]|c1 =[c1,1 ,c1,2 ,. . .])• 項目 c1,1 , c1,2 , · · · を除く
lsort(ℓ,"col",["setminus"]|c1 =[c1,1 ,c1,2 ,. . .])• c1,1 番目，c1,2 番目, . . . の要素をこの順に抜き出す
lsort(ℓ,"num",["get"]|c1 =[c1,1 ,c1,2 ,. . .])• c1,1 番目，c1,2 番目, . . . の要素を削除
lsort(ℓ,"num",["sub"]|c1 =[c1,1 ,c1,2 ,. . .])• n 番目の項目が s と等しいものを抜きだす
lsort(ℓ,"num",["get",["=",s],n])• n 番目の項目が s と等しいものを除く
lsort(ℓ,"num",["sub",["=",s],n])• n 番目の項目が s より大きい（小さい etc.）ものを抜きだす（次とその次の ">" は "<", ">=", "<=", "!=" などが可能）
lsort(ℓ,"num",["get",[">",s],n])• n 番目の項目が s より大きい（小さい etc.）ものを削除する
lsort(ℓ,"num",["sub",[">",s],n])• n 番目の項目（n がなければ要素）を函数 f に入れた戻り値が 0 でない要素を抜き出す
lsort(ℓ,"num",["get",f ,n])
• n 番目の項目（n がなければ要素）を函数 f に入れた戻り値が 0 でない要素を削除
lsort(ℓ,"num",["sub",f ,n])数を数える

• 要素の個数を返す
lsort(ℓ,"num",["sum"])• n 番目の項目が s に等しいもの個数を返す（以下の "=" は，"!=", ">"，"<"，">="，<=" が可能）
lsort(ℓ,"num",["sum",["=",s],n])• c1 番目の項目，c2 番目の項目，. . . の和（数でない項目は 0）を全ての要素に渡って足し合わせて返す402

lsort(ℓ,"num",["sum","+"]|c1=[c1,1 ,c1,2 ,. . .])• c1 番目の項目，c2 番目の項目,. . . の和を足し合わせたものを要素の最初の項目に追加
lsort(ℓ,"num",["put","+"]|c1=[c1,1 ,c1,2 ,. . .])• n 番目の項目（n がなければ要素）を函数 f に入れた戻り値を要素の最初の項目に追加
lsort(ℓ,"num",["put",f ,n])
• n 番目の項目（n がなければ要素）を函数 f に入れた戻り値を全ての要素について足した和を返す
lsort(ℓ,"num",["sum",f ,n])
項目の書き換え• mν 番目の要素の nν 番目の項目を sν に置き換える
lsort(ℓ,"subst",[]|c1=[[m1 ,n1 ,s1 ],[m2 ,n2 ,s2 ],. . .)2 つのリスト型式データ ℓ, ℓ0 に対し，指定したキー項目が同じものを対応する要素とみなして ℓ を変換• ℓ の要素に対応する ℓ0 の要素があれば，項目を合わせた要素にする
lsort(ℓ1 ,ℓ2 ,["cup",m,n]|c1=[c1,1 ,c1,2 ,. . .],c2=[c2,1 ,c2,2 ,. . .])• ℓ の要素に対応する ℓ0 の要素があれば，項目を合わせた要素にして抜き出す
lsort(ℓ1 ,ℓ2 ,["cap",m,n]|c1=[c1,1 ,c1,2 ,. . .],c2=[c2,1 ,c2,2 ,. . .])• ℓ の要素に対応する ℓ0 の要素があれば，ℓ から削除する
lsort(ℓ1 ,ℓ2 ,["setminus",m,n]|c1=[c1,1 ,c1,2 ,. . .])• ℓ の要素に対応する ℓ0 の要素があれば，対応する要素で ℓ0 の指定した項目で ℓ の指定した項目を上書きする（複数あればリストにする）

lsort(ℓ1 ,ℓ2 ,["over",m,n]|c1=c1 ,c2=c2 ])• ℓ の要素に対応する ℓ0 の要素があり，対応する要素で ℓ0 の指定した項目が空文字列でなければ，それで ℓ の指定した項目を上書きする
lsort(ℓ1 ,ℓ2 ,["subst",m,n]|c1=c1 ,c2=c2 ])その他• 2 つのリスト型式データの中身の違いをリストで返す
lsort(ℓ1 ,ℓ2 ,"cmp")• 要素数が同じ 2 つのリスト型式データの各要素を繋げて返す
lsort(ℓ1 ,ℓ2 ,"append")
3.2.14.6

有限集合

ここでは，リスト [· · · ] を集合と見なしている

1 つの集合• 集合 s のソート
要素の比較はタイプ順．リスト同士は，長さ，要素の辞書式の順

lsort(s)• 集合 s の逆順ソート
qsortn(s)• 集合 s をソートし，重複を除く
lsort(s,[],1)• 2 成分のソート
sort2([m1 ,m2 ])• 全要素の数（重複込み）と重複を除いた要素の数を得る
lsort(s,[],"count")• 集合のすべての要素を函数 f で調べて 0 となるものが存在しないことをチェック (f は isint など）
isall(s,f )403

• 各要素に演算を施す. 以下の ["+",1] は．[">",3], "neg" などが例．
calc(s,["+",1])• 要素の重複度と要素との組のリストを返す
lcount(s)• t0 と t1 の間にある要素の個数を返す
countin(t0 ,t1 ,s)• t0 と t1 の間にある要素の個数を，間隔 k の幅の分布のリストで返す
countin(t0 ,t1 ,s|skip=w)• 要素の最大のものを返す
lmax(s)• 要素の最小のものを返す
lmin(s)• 要素の和（和が定義出る要素ならばよい）
lsum(s)• 数の集合 s の平均値，標準偏差，個数，最小値，最大値を返す．値は小数点以下 k 桁で丸める．
average(s|sint=k)
2 つの集合• s1 が s2 の部分集合か？（s1 , s2 はソートされている場合，他はオプション）
issub(s1 ,s2 )• s1 と s2 に共通元がないか？
isdisjoint(s1 ,s2 )• s1 と s2 に共通元がないか, または包含関係がある？
iscommuteset(s1 ,s2 )• s1 と s2 の合併
lsort(s1 ,s2 ,"cup")• s1 と s2 の共通部分
lsort(s1 ,s2 ,"cap")• s1 の要素で s2 の要素でないものの集合
lsort(s1 ,s2 ,"setminus")• s1 と s2 から同じ要素を同数除いた最小の集合の組を返す
lsort(s1 ,s2 ,"reduce")• それぞれの要素数，重複を除いたそれぞれの要素数，共通の要素数，同じものを同数消した最初の集合の要素数を得るlsort(s1 ,s2 ,"count")• 数の集合 s1 , s2 の相関係数．値は小数点以下 k 桁で丸める．
average([s1 , s2 ]|sint=k)集合の集合 (集合族)• 集合の包含関係で極大なものをすべて返す
lmaxsub([s1 ,s2 , . . .])• 集合の包含関係で極小なものをすべて返す
lmaxsub([s1 ,s2 , . . .]|min=1)• 集合の包含関係を解析する
llord([s1 ,s2 , . . .])• 集合 si を（リカーシブ）ソートし，さらに集合族をソート
rsort([s1 ,s2 , . . .],0,0)• 各 si をソート
rsort([s1 ,s2 , . . .],1,0)404

• 各 si を逆順ソート
rsort([s1 ,s2 , . . .],1,-1)• 集合族のリストにおいて (x1 , x2 , . . .) の対称性で最小のもののみを残す (si は数字や式が可能)
llsymred([s1 ,s2 , . . .],[x1 ,x2 , . . .])3.2.14.7

次のベクトルやリスト• 並び替えて辞書式順序での次のベクトル（ベクトルの成分に等しいものがあってよい）
vnext([m1 m2 · · · ])• 0 から n − 1 までの中から m 個を選んだリストに対し，辞書式順序で次の部分集合
nextsub([a0 ,...,am−1 ],n)• 和が n となる正整数のリストの辞書式順順序（成分の大きさの順）で次のもの
nextpart([a0 ,a1 , . . .])• 和が n となる m 以下の正整数のリストの辞書式順順序（成分の大きさの順）で次のもの
nextpart([a0 ,a1 , . . .]|max=m)• 和が n となる m 個以下の正整数のリストの辞書式順序（成分の大きさの順）で次のもの
transpart(nextpart([a0 ,a1 , . . .]|max=m))• 成分の和が m のサイズ m の非負整数ベクトル w の大きい順
ただし w[i] ≤ v[i] の制限つき（v[i] = m としておくと制限なしと同じ）
w の 2 項目以降は成分の和が m − 1 以下のベクトル w を与える（和は 0 からの小さい順）
vgen(v,w,n)• 正整数 n の分割を与える（和が n となる）正整数を大きい順に並べたリストで次のもの
nextpart([a0 ,a1 , . . .])3.3 Functions in the original library
以下の函数は，module 化されないので，函数名の先頭に os_md. をつけません．

3.3.1 数の演算
1. idiv(i1 ,i2 ):: 整数除算による商2. irem (i1 ,i2 ):: 整数除算による剰余• i1 の i2 による整数除算による商, 剰余を求める.
• i2 は 0 であってはならない.
• 被除数が負の場合, 絶対値に対する値にマイナスをつけた値を返す.
• i1 % i2 は, 結果が正に正規化されることを除けば irem() の代わりに用いることができる.
• 多項式の場合は sdiv(), srem() を用いる.
[0] idiv(100,7);14[0] idiv(-100,7);-14[1] irem(100,7);2[2] irem(-100,7);-2
3. fac(i)405

:: 自然数 i の階乗• i が負の場合は 0 を返す.
4. nm(p):: 有理数または有理式の分子5. dn(p):: 有理数または有理式の分母• 与えられた有理数また有理式の分子及び分母を返す.
• 有理数の場合, 分母は常に正で, 符号は分子が持つ.
• 有理式の場合, 単に分母, 分子を取り出すだけである. 有理式に対しては, 約分は自動的には行われない. red() を明示的に呼び出す必要がある.
[0] [nm(-43/8),dn(-43/8)];[-43,8][1] dn((x*z)/(x*y));y*x[2] dn(red((x*z)/(x*y)));y6. igcd(i1 ,i2 ):: 整数 i1 と i2 の GCD を求める
• 引数が整数でない場合は, エラーまたは無意味な結果を返す.
• 多項式の場合は, gcd(), gcdz() を用いる.
• 整数 GCD にはさまざまな方法があり, igcdcntl() で設定できる.
7. igcdcntl([i]):: 整数 GCD のアルゴリズムの選択
0 Euclid 互除法 (default)
1 binary GCD
2 bmod GCD
3 accelerated integer GCD
2, 3 は [Weber] による. おおむね 3 が高速だが, 例外もある.
[0] A=lrandom(10^4)$[1] B=lrandom(10^4)$[2] C=lrandom(10^4)$[3] D=A*C$[4] E=A*B$[5] cputime(1)$[6] igcd(D,E)$
0.6sec + gc : 1.93sec(2.531sec)[7] igcdcntl(1)$[8] igcd(D,E)$
0.27sec(0.2635sec)[9] igcdcntl(2)$[10] igcd(D,E)$
0.19sec(0.1928sec)[11] igcdcntl(3)$[12] igcd(D,E)$
0.08sec(0.08023sec)
406

8. ilcm(i1 ,i2 ):: 整数の最小公倍数を求める
一方が 0 のとき 0 を返す．
9. isqrt(n):: n の平方根を越えない最大の整数を返す
10. inv(i,m):: m を法とする i の逆数• ia = 1 mod (m) なる整数 a を求める．
• i と m は互いに素でなければならないが, inv() はそのチェックは行わない[0] igcd(1234,4321);
1[1] inv(1234,4321);
3239[2] irem(3239*1234,4321);
1
11. random([seed]):: 乱数を生成する• 最大 232 − 1 の非負整数の乱数を生成する.
• 0 でない引数がある時, その値を seed として設定してから, 乱数を生成する.
• default の seed は固定のため, 種を設定しなければ, 生成される乱数の系列は起動毎に一定である.
• 松本眞–西村拓士による Mersenne Twister アルゴリズムの, 彼ら自身による実装を用いている.
(http://www.math.keio.ac.jp/matsumoto/mt.html)• 周期は 219937 − 1 と非常に長い. mt save により state をファイルに save できる. これを mt load
で読み込むことにより, 異る Asir セッション間で一つの乱数の系列を辿ることができる
12. lrandom(bit):: 多倍長乱数を生成する• 高々 bit の非負整数の乱数を生成する.
• random を複数回呼び出して結合し, 指定の bit 長にマスクしている
13. mt save(fname):: 乱数生成器の現在の状態をファイルにセーブする
14. mt load(fname):: ファイルにセーブされた乱数生成器の状態をロードする• ある状態をセーブし, その状態をロードすることで, 一つの疑似乱数系列を, 新規の Asir セッションで続けてたどることができる.
[0] random();
3510405877[1] mt_save("/tmp/mt_state");1[2] random();
4290933890[3] quit;% asirThis is Asir, Version 991108.
Copyright (C) FUJITSU LABORATORIES LIMITED.
3 March 1994. All rights reserved.
[4] mt_load("/tmp/mt_state");407

1[5] random();
4290933890
15. real(comp):: comp の実数部分
16. imag(comp):: comp の虚数部分
17. conj(comp):: comp の共役複素数• 複素数に対し, 実部, 虚部, 共役を求める.
• これらは, 多項式に対しても働く.
[0] A=(2+@i)^3;(2+11*@i)[1] [real(A),imag(A),conj(A)];[2,11,(2-11*@i)]18. eval(obj [, prec]):: obj の値の評価
19. deval(obj):: obj の値の評価（倍精度浮動小数）• obj に含まれる函数の値を可能な限り評価する.
• deval は倍精度浮動小数を結果として返すが，eval は有理数はそのまま残す.
• eval においては, 計算は PARI (section pari) が行う. deval においては, 計算は C 数学ライブ
ラリの函数を用いて行う.
• deval は複素数は扱えない.
• eval においては, prec を指定した場合, 計算は, 10 進 prec 桁程度で行われる. prec の指定がない場合, 現在設定されている精度で行われる. (See section setprec().)• 扱える函数は, 次の通り. sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh,atanh, exp, log, pow(a,b), (a^b)• 以下の記号を数として評価できる. ただし @i を扱えるのは eval() のみである.
@i 虚数単位@pi 円周率@e 自然対数の底[0] eval(exp(@pi*@i));-1.0000000000000000000000000000[1] eval(2^(1/2));
1.414213562373095048763788073031[2] eval(sin(@pi/3));
0.86602540378443864674620506632[3] eval(sin(@pi/3)-3^(1/2)/2,50);-2.78791084448179148471 E-58
[4] eval(1/2);
1/2[5] deval(sin(1)^2+cos(1)^2);
1
20. pari(func,arg,prec)
408

:: PARI の函数 func を呼び出す.
• PARI [Batut et al.] は Bordeaux 大学で開発されフリーソフトウェアとして公開されている.
PARI は数式処理的な機能を有してはいるが, 主なターゲットは整数論に関連した数 (bignum,
bigfloat) の演算で, 四則演算に限らず bigfloat によるさまざまな函数値の評価を高速に行うことができる. PARI は他のプログラムからサブルーチンライブラリとして用いることができ, また, gp という PARI ライブラリのインタフェースにより UNIX のアプリケーションとして利用することもできる. 現在のバージョンは 2.0.17beta でいくつかの ftp site (たとえばhttp://pari.math.u-bordeaux.fr/) から anonymous ftp できる.
• 最後の引数 prec で計算精度を指定できる. prec を省略した場合 setprec() で指定した精度となる. 現時点で実行できる PARI の函数は次の通りである. いずれも 1 引数で Asir が対応できる型の引数をとる函数である. なお各々の機能については PARI のマニュアルを参照のこと.
abs, adj, arg, bigomega, binary, ceil, centerlift, cf, classno, classno2, conj,
content, denom, det, det2, detr, dilog, disc, discf, divisors, eigen, eintg1, erfc,
eta, factor, floor, frac, galois, galoisconj, gamh, gamma, hclassno, hermite, hess,imag, image, image2, indexrank, indsort, initalg, isfund, isprime, ispsp, isqrt,
issqfree, issquare, jacobi, jell, ker, keri, kerint, kerintg1, kerint2, kerr, length,
lexsort, lift, lindep, lll, lllg1, lllgen, lllgram, lllgramg1, lllgramgen, lllgramint,
lllgramkerim, lllgramkerimgen, lllint, lllkerim, lllkerimgen, lllrat, lngamma,
logagm, mat, matrixqz2, matrixqz3, matsize, modreverse, mu, nextprime, norm, norml2,
numdiv, numer, omega, order, ordred, phi, pnqn, polred, polred2, primroot, psi, quadgen,quadpoly, real, recip, redcomp, redreal, regula, reorder, reverse, rhoreal, roots,
rootslong, round, sigma, signat, simplify, smalldiscf, smallfact, smallpolred,
smallpolred2, smith, smith2, sort, sqr, sqred, sqrt, supplement, trace, trans, trunc,
type, unit, vec, wp, wp2, zeta
• Asir で用いているのは PARI のほんの一部の機能であるが, 今後より多くの機能が利用できるよう改良する予定である.
/* 行列の固有ベクトルを求める. */[0] pari(eigen,newmat(2,2,[[1,1],[1,2]]));[ -1.61803398874989484819771921990 0.61803398874989484826 ][ 1 1 ]/* 1 変数多項式の根を求める. */[1] pari(roots,t^2-2);[ -1.41421356237309504876 1.41421356237309504876 ]21. setprec([n]):: bigfloat の桁数を n 桁に設定する• 引数がある場合, bigfloat の桁数を n 桁に設定する. 引数のあるなしにかかわらず, 以前に設定されていた値を返す.
• bigfloat の計算は PARI によって行われる.
• bigfloat での計算に対し有効である. bigfloat の ﬂag を on にする方法は, ctrl() を参照. 設
定できる桁数に上限はないが, 指定した桁数に設定されるとは限らない. 大きめの値を設定するのが安全である.
[0] setprec();
9[1] setprec(100);9[3] setprec(100);

409

96
22. setmode([p]):: 有限体を GF (p) に設定する• p は 227 未満の素数• 有限体を GF (p) に設定する. 設定値を返す.
• 有限体の元の型を持つ数は, それ自身はどの有限体に属するかの情報を持たず, 現在設定されている素数 p により GF (p) 上での演算が適用される.
• 位数の大きな有限体に関しては有限体における演算を参照.
[0] A=dp_mod(dp_ptod(2*x,[x]),3,[]);(2)*<<1>>[1] A+A;
addmi : invalid modulus
return to toplevel[2] setmod(3);3[3] A+A;(1)*<<1>>
23. ntoint32(n):: 非負整数と符号なし 32bit 整数の間の型変換
24. int32ton(int32):: 非負整数と符号なし 32bit 整数の間の型変換• n は 232 未満の非負整数，int32 は符号なし 32bit 整数• 非負整数 (識別子 1) の符号なし 32bit 整数 (識別子 10) への変換, またはその逆変換を行う.
• 32bit 整数は OpenXM の基本構成要素であり, 整数をその型で送信する必要がある場合に用いる.
25. iand(m,n):: 整数 m, n のビット毎の and
26. ior(m,n):: 整数 m, n のビット毎の or
27. ixor(m,n):: 整数 m, n のビット毎の xor• 整数 m, n の絶対値を bit 列とみて演算する.
• 引数の符号は無視し, 非負の値を返す.
[0] ctrl("hex",1);0x1[1] iand(0xeeeeeeeeeeeeeeee,0x2984723234812312312);
0x4622224802202202[2] ior(0xa0a0a0a0a0a0a0a0,0xb0c0b0b0b0b0b0b);0xabacabababababab[3] ixor(0xfffffffffff,0x234234234234);
0x2cbdcbdcbdcb
28. ishift(i,count):: 整数 i の絶対値を bit 列とみて shift する• i の符号は無視し, 非負の値を返す.
• count が正ならば右 shift, 負ならば左 shift を行う

410

[0] ctrl("hex",1);0x1[1] ishift(0x1000000,12);0x1000[2] ishift(0x1000,-12);0x1000000[3] ixor(0x1248,ishift(1,-16)-1);0xedb729. pari(binary,n):: 数 n の 2 進数表示[0] pari(binary,6);[ 1 1 0 ][1] pari(binary,6.3);[ [ 1 1 0 ] [ 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 0 0
0 0 0 0 0 0 0 0 0 ] ]30. pari(factor,n):: 整数 n または 1 変数多項式 n の素因数分解を求める[0] pari(factor,1239321);[ 3 1 ]
[ 73 1 ][ 5659 1 ][1] pari(factor,-24);[ -1 1 ][ 2 3 ]
[ 3 1 ]
[2] pari(factor,2*x^3-2);[ x-1 1 ][ x^2+x+1 1 ][3] pari(factor,x^2-y^2);***sorry, factor for general polynomials is not yet implemented.
31. pari(issquare,n):: 整数 n または多項式 n が平方数（元）かどうか調べる[0] pari(issquare,36);
1[1] pari(issquare,8);0[2] pari(issquare,16/9);
1[3] pari(issquare,9*x^2+12*x*y+4*y^2);
1[4] pari(issquare,2*x^2);
0411

32. pari(omega,n):: 整数 n または 1 変数多項式 n の素因子の個数33. pari(bigomega,n):: 整数 n または 1 変数多項式 n の素因子の重複度込みの個数[0] pari(omega,-24);
2[1] pari(bigomega,-24);
4
34. pari(numdiv,n):: 整数 n を割り切る正整数の個数[0] pari(numdiv,-12);1235. pari(sigma,n):: n の正の約数の和[0] pari(sigma,-12);28
36. pari(isprime,num):: 自然数 num が素数かどうか調べる（合成数なら 0 を返す）
[0] pari(isprime,113);1
37. pari(ispsp,num):: 自然数 num が擬素数かどうか調べる（合成数なら 0 を返す）
Baillie-Pomerance-Selfridge-Wagstaﬀ の擬素数かどうかを調べる．
少なくとも 264 = 1.84 · · · × 1020 以下では素数と一致．
[0] pari(ispsp,113);1
38. pari(nextprime,num):: 自然数 num 以上の最小の擬素数を返す[0] pari(nextprime,10^30);
1000000000000000000000000000057
39. pari(frac,num):: 実数 num の小数部分[0] pari(frac,2.25);
0.25000000000000000000
40. pari(conj,num):: 複素数 num（行列でも可）の共役複素数を返す[0] pari(conj,2+3*@i);(2-3*@i)41. pari(abs,num[,prec])412

:: 複素数 num の絶対値を返す[0] pari(abs,1+@i);
1.41421356237309504876[1] pari(abs,1+@i,50);
1.41421356237309504880168872420969807856967187537694807317638
42. pari(cf,num):: num の連分数展開を返す[0] pari(cf,1234567/678901);[ 1 1 4 1 1 27 3 2 2 3 3 5 2 ][1] pari(cf,eval(@pi));[ 3 7 15 1 292 1 1 1 2 1 3 1 14 2 1 1 2 2 2 ]43. pari(mu,n):: 自然数 n のメビウス函数 µ(n) の値（0 または ±1）を返す[0] pari(mu,230);-144. pari(phi,n):: 自然数 n に対する Euler の φ 函数の値（n 以下の n と素なものの個数）を返す[0] pari(phi,12);4
3.3.2 多項式，有理式の演算
45. var(rat):: rat の主変数を返す• 主変数に関しては, Asir で使用可能な型の項を参照• デフォルトの変数順序は次のようになっている. x, y, z, u, v, w, p, q, r, s, t, a, b,
c, d, e, f, g, h, i, j, k, l, m, n, o, 以後は変数の現れた順.
[0] var(x^2+y^2+a^2);x[1] var(a*b*c*d*e);a[2] var(3/abc+2*xy/efg);
46. vars(obj):: obj に含まれる変数のリスト• 与えられた式に含まれる変数のリストを返す.
• 変数順序の高いものから順に並べる.
• 関数の引数に現れる変数（たとえば exp(x*sin(y+z))）もリストするには varargs() を用いる．
[0] vars(x^2+y^2+a^2);[x,y,a][1] vars(3/abc+2*xy/efg);[abc,xy,efg][2] vars([x,y,z]);413

[x,y,z]47. uc():: 未定係数法のための vtype が 1 の不定元を生成する.
• uc() を実行するたびに, _0, _1, _2,... という不定元を生成する.
• uc() で生成された不定元は, 直接キーボードから入力することができない. これは, プログラム中で未定係数を自動生成する場合, 入力などに含まれる不定元と同一のものが生成されることを防ぐためである.
• 通常の不定元 (vtype が 0) の自動生成には rtostr(), strtov() を用いる.
• uc() で生成された不定元の不定元としての型 (vtype) は 1 である. (See section 不定元の型.)• makev() では不定元の生成が容易に出来る．
[0] A=uc();_0[1] B=uc();_1[2] (uc()+uc())^2;_2^2+2*_3*_2+_3^2[3] (A+B)^2;_0^2+2*_1*_0+_1^2
48. coef(poly,deg [,var]):: poly の var (省略時は主変数) に関する deg 次の係数を出力する• var は, 省略すると主変数 var(poly) だとみなされる.
• var が主変数でない時, var が主変数の場合に比較して効率が落ちる.
• mycoef() は，初等函数係数や行列係数の多項式にも対応する．
[0] A = (x+y+z)^3;x^3+(3*y+3*z)*x^2+(3*y^2+6*z*y+3*z^2)*x+y^3+3*z*y^2+3*z^2*y+z^3[1] coef(A,1,y);3*x^2+6*z*x+3*z^2[2] coef(A,0);y^3+3*z*y^2+3*z^2*y+z^3
49. deg(poly,var):: poly の, 変数 var に関する最高次数50. mindeg(poly,var):: poly の, 変数 var に関する最低次数• 与えられた多項式の変数 var に関する最高次数, 最低次数を出力する.
• 変数 var を省略することは出来ない.
• 初等函数成分の行列係数多項式などにも対応した上位互換函数 mydeg(), mymindeg() がある．
[0] deg((x+y+z)^10,x);10[1] deg((x+y+z)^10,w);
0[75] mindeg(x^2+3*x*y,x);
1
51. nmono(rat)414

:: rat の単項式の項数• 多項式を展開した状態での 0 でない係数を持つ単項式の項数を求める.
• 有理式の場合は, 分子と分母の項数の和が返される.
• 函数形式 (section 不定元の型) は, 引数が何であっても単項とみなされる (1 個の不定元と同じ)．
[0] nmono((x+y)^10);
11[1] nmono((x+y)^10/(x+z)^10);22[2] nmono(sin((x+y)^10));1
52. ord([varlist]):: 変数順序の設定• 引数があるとき, 引数の変数リストを先頭に出し, 残りの変数がその後に続くように変数順序を設定する. 引数のあるなしに関わらず, ord() の終了時における変数順序リストを返す.
• この函数による変数順序の変更を行っても, 既にプログラム変数などに代入されている式の内部形
式は新しい順序に従っては変更されない. 従って, この函数による順序の変更は, Asir の起動直後,
あるいは, 新たな変数が現れた時点に行われるべきである. 異なる変数順序のもとで生成された式
どうしの演算が行われた場合, 予期せぬ結果が生ずることもあり得る.
[0] ord();[x,y,z,u,v,w,p,q,r,s,t,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,_x,_y,_z,_u,_v,_w,_p,_q,_r,_s,_t,_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,exp(_x),(_x)^(_y),log(_x),(_x)^(_y-1),cos(_x),sin(_x),tan(_x),(-_x^2+1)^(-1/2),cosh(_x),sinh(_x),tanh(_x),(_x^2+1)^(-1/2),(_x^2-1)^(-1/2)][1] ord([dx,dy,dz,a,b,c]);[dx,dy,dz,a,b,c,x,y,z,u,v,w,p,q,r,s,t,d,e,f,g,h,i,j,k,l,m,n,o,_x,_y,_z,_u,_v,_w,_p,_q,_r,_s,_t,_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,_m,_n,_o,exp(_x),(_x)^(_y),log(_x),(_x)^(_y-1),cos(_x),sin(_x),tan(_x),(-_x^2+1)^(-1/2),cosh(_x),sinh(_x),tanh(_x),(_x^2+1)^(-1/2),(_x^2-1)^(-1/2)]
53. sdiv(poly1,poly2[,v]):: poly1 を poly2 で割る除算が最後まで実行できる場合に商を求める
54. sdivm(poly1,poly2,mod[,v]):: GF (mod) 上で poly1 を poly2 で割る除算が最後まで実行できる場合に商を求める
55. srem(poly1,poly2[,v]):: poly1 を poly2 で割る除算が最後まで実行できる場合に剰余を求める
56. sremm(poly1,poly2,mod[,v]):: GF (mod) 上で poly1 を poly2 で割る除算が最後まで実行できる場合に剰余を求める
57. sqr(poly1,poly2[,v]):: poly1 を poly2 で割る除算が最後まで実行できる場合に商, 剰余を求める
58. sqrm(poly1,poly2,mod[,v]):: GF (mod) 上で poly1 を poly2 で割る除算が最後まで実行できる場合に商, 剰余を求める• poly1 を poly2 の主変数 var(poly2) ( 引数 v がある場合には v) に関する多項式と見て, poly2
で, 割り算を行う.
• sdivm(), sremm(), sqrm() は GF (mod) 上で計算する.

415

• 多項式の除算は, 主係数どうしの割算により得られた商と, 主変数の適当な冪の積を poly2 に掛けて, poly1 から引くという操作を poly1 の次数が poly2 の次数より小さくなるまで繰り返して行う. この操作が, 多項式の範囲内で行われるためには, 各ステップにおいて主係数どうしの除算が,多項式としての整除である必要がある. これが, 「除算が最後まで実行できる」ことの意味である.
典型的な場合として, poly2 の主係数が, 有理数である場合, あるいは, poly2 が poly1 の因子であることがわかっている場合などがある.
• sqr() は商と剰余を同時に求めたい時に用いる.
• 整数除算の商, 剰余は idiv, irem を用いる.
• 係数に対する剰余演算は % を用いる.
• 上の仮定を満たさない，より一般の場合の割り算を行う函数 rpdiv() がある．
[0] sdiv((x+y+z)^3,x^2+y+a);x+3*y+3*z[1] srem((x+y+z)^2,x^2+y+a);(2*y+2*z)*x+y^2+(2*z-1)*y+z^2-a[2] X=(x+y+z)*(x-y-z)^2;
x^3+(-y-z)*x^2+(-y^2-2*z*y-z^2)*x+y^3+3*z*y^2+3*z^2*y+z^3[3] Y=(x+y+z)^2*(x-y-z);x^3+(y+z)*x^2+(-y^2-2*z*y-z^2)*x-y^3-3*z*y^2-3*z^2*y-z^3[4] G=gcd(X,Y);x^2-y^2-2*z*y-z^2[5] sqr(X,G);[x-y-z,0][6] sqr(Y,G);[x+y+z,0][7] sdiv(y*x^3+x+1,y*x+1);
divsp: cannot happen
return to toplevel
59. tdiv([poly1,poly2]):: poly1 が poly2 で割れたら商を割れなければ 0 を返す• ある多項式が既約因子であることはわかっているが, その重複度がわからない場合に, tdiv() を繰り返し呼ぶことにより重複度がわかる.
[1] Y=(x+y+z)^5*(x-y-z)^3;
x^8+(2*y+2*z)*x^7+(-2*y^2-4*z*y-2*z^2)*x^6+(-6*y^3-18*z*y^2-18*z^2*y-6*z^3)*x^5+(6*y^5+30*z*y^4+60*z^2*y^3+60*z^3*y^2+30*z^4*y+6*z^5)*x^3+(2*y^6+12*z*y^5+30*z^2*y^4+40*z^3*y^3+30*z^4*y^2+12*z^5*y+2*z^6)*x^2+(-2*y^7-14*z*y^6-42*z^2*y^5-70*z^3*y^4-70*z^4*y^3-42*z^5*y^2-14*z^6*y-2*z^7)*x-y^8-8*z*y^7-28*z^2*y^6-56*z^3*y^5-70*z^4*y^4-56*z^5*y^3-28*z^6*y^2-8*z^7*y-z^8[2] for(I=0,F=x+y+z,T=Y; T=tdiv(T,F); I++);[3] I;
5
60. subst(rat[,varn,ratn ]*):: 有理式の特定の不定元に, 定数あるいは多項式, 有理式などを代入する
416

61. psubst(rat[,varn,ratn ]*):: 有理式の特定の不定元に, 定数あるいは多項式, 有理式などを代入する• subst(rat,var1,rat1,var2,rat2,...) は, subst(subst(rat,var1,rat1),var2,rat2,...) と同じ意味である.
• 入力の左側から順に代入を繰り返すために, 入力の順によって結果が変わることがある.
• subst() は, sin() などの函数の引数に対しても代入を行う. psubst() は, このような函数を一つの独立した不定元と見なして, その引数には代入は行わない (partial substitution のつもり)• Asir では, 有理式の約分は自動的には行わないため, 有理式の代入は, 思わぬ計算時間の増大を引き起こす場合がある. 有理式を代入する場合には, 問題に応じた独自の函数を書いて, なるべく分母, 分子が大きくならないように配慮することもしばしば必要なる. 分数を代入する場合も同様である.
• 約分しながら代入を行う函数 mysubst() がある．また mulsubst() は，複数の代入の順序にはよらない．T oF psubst は，函数の中の不定元に対しても代入を行う．
• subst() の引数 rat が文字列ならばエラーとなるが，mysubst() や mulsubst() はそのまま rat
を返す．
• subst の引数 rat がリスト, 配列, 行列, あるいは分散表現多項式であった場合には, それぞれの要素または係数に対して再帰的に subst を行う.

[0] subst(x^3-3*y*x^2+3*y^2*x-y^3,y,2);x^3-6*x^2+12*x-8[1] subst(@@,x,-1);-27[2] subst(x^3-3*y*x^2+3*y^2*x-y^3,y,2,x,-1);-27[3] subst(x*y^3,x,y,y,x);x^4[4] subst(x*y^3,y,x,x,y);y^4[5] subst(x*y^3,x,t,y,x,t,y);y*x^3[6] mulsubst(x*y^3,[[x,y],[y,x]]);y*x^3[7] subst(x*sin(x),x,t);sin(t)*t[8] psubst(x*sin(x),x,t);sin(x)*t[9] subst(["afo",x],x,2);
subst : invalid argument
return to toplevel[10] os_md.mysubst(["afo",x],[x,2]);[afo,2]62. diff(rat[,varn]*) または diff(rat,varlist):: rat を varn あるいは varlist の中の変数で順次微分する• 与えられた初等函数を varn あるいは varlist の中の変数で順次微分する.
• 左側の不定元より, 順に微分していく. つまり, diff(rat,x,y) は, diff(diff(rat,x),y) と同じ
である.

417

• 有理式を微分する場合は約分されないので分母が膨らんで計算が複雑になるのを避ける appldo()という函数がある．これは行列やベクトルにも対応している．

[0] diff((x+2*y)^2,x);2*x+4*y[1] diff((x+2*y)^2,x,y);4[2] diff(x/sin(log(x)+1),x);(sin(log(x)+1)-cos(log(x)+1))/(sin(log(x)+1)^2)[3] diff(sin(x),[x,x,x,x]);sin(x)[4] diff(sin(x)+1/(a+1),x,x);(-sin(x)*a^4-4*sin(x)*a^3-6*sin(x)*a^2-4*sin(x)*a-sin(x))/(a^4+4*a^3+6*a^2+4*a+1)[5] appldo(dx^2,sin(x)+1/(a+1),x);-sin(x)63. res(var,poly1,poly2 [,mod]):: 変数 var に関する多項式 poly1 と poly2 の終結式を求める• 部分終結式アルゴリズムによる.
• 引数 mod がある時, GF (mod) 上での計算を行う.
[0] res(t,(t^3+1)*x+1,(t^3+1)*y+t);-x^3-x^2-y^3
64. fctr(poly):: poly を既約因子に分解する
65. sqfr(poly):: poly を無平方分解する• 有理数係数の多項式 poly を因数分解する. fctr() は既約因子分解, sqfr() は無平方因子分解.
• 結果は [[数係数,1],[因子, 重複度],...] なるリスト.
• 数係数と全ての因子^重複度 の積が poly と等しい.
• 数係数 は, (poly/数係数) が, 整数係数で, 係数の GCD が 1 となるような多項式になるように選ばれている (cf. ptozp())．
[0] fctr(x^10-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]][1] fctr(x^3+y^3+(z/3)^3-x*y*z);[[1/27,1],[9*x^2+(-9*y-3*z)*x+9*y^2-3*z*y+z^2,1],[3*x+3*y+z,1]][2] A=(a+b+c+d)^2;
a^2+(2*b+2*c+2*d)*a+b^2+(2*c+2*d)*b+c^2+2*d*c+d^2[3] fctr(A);[[1,1],[a+b+c+d,2]][4] A=(x+1)*(x^2-y^2)^2;x^5+x^4-2*y^2*x^3-2*y^2*x^2+y^4*x+y^4[5] sqfr(A);[[1,1],[x+1,1],[-x^2+y^2,2]][6] fctr(A);[[1,1],[x+1,1],[-x-y,2],[x-y,2]]418

66. ufctrhint(poly,hint):: 次数情報を用いた有理数係数の 1 変数多項式の因数分解• 各既約因子の次数が自然数 hint の倍数であることがわかっている場合に poly の既約因子分解を
fctr() より効率良く行う. poly が, d 次の拡大体上におけるある多項式のノルム (section 代数的数に関する演算) で無平方である場合, 各既約因子の次数は d の倍数となる. このような場合に用いられる[0] A=t^9-15*t^6-87*t^3-125;t^9-15*t^6-87*t^3-125
0msec[1] N=res(t,subst(A,t,x-2*t),A);-x^81+1215*x^78-567405*x^75+139519665*x^72-19360343142*x^69+1720634125410*x^66-88249977024390*x^63-4856095669551930*x^60+1999385245240571421*x^57-15579689952590251515*x^54+15956967531741971462865*x^51...
+140395588720353973535526123612661444550659875*x^6+10122324287343155430042768923500799484375*x^3+139262743444407310133459021182733314453125
980msec + gc : 250msec[2] sqfr(N);[[-1,1],[x^81-1215*x^78+567405*x^75-139519665*x^72+19360343142*x^69-1720634125410*x^66+88249977024390*x^63+4856095669551930*x^60-1999385245240571421*x^57+15579689952590251515*x^54...
-10122324287343155430042768923500799484375*x^3-139262743444407310133459021182733314453125,1]]
20msec[3] fctr(N);[[-1,1],[x^9-405*x^6-63423*x^3-2460375,1],[x^18-486*x^15+98739*x^12-9316620*x^9+945468531*x^6-12368049246*x^3+296607516309,1],[x^18-8667*x^12+19842651*x^6+19683,1],[x^18-324*x^15+44469*x^12-1180980*x^9+427455711*x^6+2793253896*x^3+31524548679,1],[x^18+10773*x^12+2784051*x^6+307546875,1]]
167.050sec + gc : 1.890sec[4] ufctrhint(N,9);[[-1,1],[x^9-405*x^6-63423*x^3-2460375,1],[x^18-486*x^15+98739*x^12-9316620*x^9+945468531*x^6-12368049246*x^3+296607516309,1],[x^18-8667*x^12+19842651*x^6+19683,1],[x^18-324*x^15+44469*x^12-1180980*x^9+427455711*x^6+2793253896*x^3+31524548679,1],[x^18+10773*x^12+2784051*x^6+307546875,1]]
119.340sec + gc : 1.300sec
67. modfctr(poly,mod)419

:: 有限体上での多項式の因数分解• 229 未満の自然数 mod を標数とする素体上で多項式 poly を既約因子に分解する.
• 結果は [[数係数,1],[因子, 重複度],...] なるリスト.
• 数係数 と 全ての 因子 重複度 の積が poly と等しい.
• 大きな位数を持つ有限体上の因数分解には fctr ff() を用いる. (cf. 有限体における演算）[0] modfctr(x^10+x^2+1,2147483647);[[1,1],[x+1513477736,1],[x+2055628767,1],[x+91854880,1],[x+634005911,1],[x+1513477735,1],[x+634005912,1],[x^4+1759639395*x^2+2045307031,1]][1] modfctr(2*x^6+(y^2+z*y)*x^4+2*z*y^3*x^2+(2*z^2*y^2+z^3*y)*x+z^4,3);[[2,1],[2*x^3+z*y*x+z^2,1],[2*x^3+y^2*x+2*z^2,1]]
68. ptozp(poly|factor=1) labelr:ptozp:: 有理係数多項式を有理数倍して整数係数で係数の GCD が 1 の多項式に直す• 与えられた多項式 poly に適当な有理数を掛けて, 整数係数かつ係数の GCD が 1 になるようにする.
• 分数の四則演算は, 整数の演算に比較して遅いため, 種々の多項式演算の前に, 多項式を整数係数にしておくことが望ましい.
• 有理式を約分する red() で分数係数有理式を約分しても, 分子多項式の係数は有理数のままであり, 有理式の分子を求める nm() では, 分数係数多項式は, 分数係数のままの形で出力されるため,直ちに整数係数多項式を得る事は出来ない.
• オプション factor が設定された場合の戻り値はリスト [g,c] である. ここで c は有理数であり,g がオプションのない場合の戻り値であり, poly = c ∗ g となる.
[0] ptozp(2*x+5/3);
6*x+5[1] nm(2*x+5/3);
2*x+5/3
69. % poly % m:: poly の各係数を整数 m で割った剰余で置き換えた多項式を返す• 結果の係数は全て正の整数となる.
• poly は整数でもよい. この場合, 結果が正に正規化されることを除けば irem() と同様に用いることができる.
• poly の係数, m とも整数である必要があるが, チェックは行なわれない．
[0] (x+2)^5 % 3;x^5+x^4+x^3+2*x^2+2*x+2[1] (x-2)^5 % 3;
x^5+2*x^4+x^3+x^2+2*x+1[2] (-5) % 4;
3[3] irem(-5,4);-1
70. prim(poly[,v]):: 有理係数多項式 poly の原始的部分 (primitive part)71. cont(poly[,v])420

:: 有理係数多項式 poly の容量 (content)• poly の主変数 (引数 v がある場合には v) に関する原始的部分, 容量を求める[0] E=(y-z)*(x+y)*(x-z)*(2*x-y);(2*y-2*z)*x^3+(y^2-3*z*y+2*z^2)*x^2+(-y^3+z^2*y)*x+z*y^3-z^2*y^2[1] prim(E);2*x^3+(y-2*z)*x^2+(-y^2-z*y)*x+z*y^2[2] cont(E);y-z[3] prim(E,z);(y-z)*x-z*y+z^2
72. gcd(poly1,poly2[,mod]):: 二つの多項式の最大公約式 (GCD) を求める
73. gcdz(poly1,poly2):: 有限体上の二つの多項式の最大公約式 (GCD) を求める
• gcd() は有理数体上の多項式としての GCD を返す. すなわち, 結果は整数係数で, かつ係数のGCD が 1 になるような多項式, または, 互いに素の場合は 1 を返す.
• gcdz() は poly1, poly2 ともに整数係数の場合に, 整数環上の多項式としての GCD を返す. すな
わち, gcd() の値に, 係数全体の整数 GCD の値を掛けたものを返す.
• 引数 mod がある時, gcd() は GF (mod) 上での GCD を返す.
• gcd(), gcdz() は Extended Zassenhaus アルゴリズムによる. 有限体上の GCD は PRS アルゴ
リズムによっているため, 大きな問題, GCD が 1 の場合などにおいて効率が悪い.
• 有理函数体係数の多項式環や常微分作用素環，さらには整数環に汎用的に対応している mygcd()がある．

[0] gcd(12*(x^2+2*x+1)^2,18*(x^2+(y+1)*x+y)^3);x^3+3*x^2+3*x+1[1] gcdz(12*(x^2+2*x+1)^2,18*(x^2+(y+1)*x+y)^3);
6*x^3+18*x^2+18*x+6[2] gcd((x+y)*(x-y)^2,(x+y)^2*(x-y));x^2-y^2[3] gcd((x+y)*(x-y)^2,(x+y)^2*(x-y),2);x^3+y*x^2+y^2*x+y^3
74. red(rat):: rat を約分する• Asir は有理数の約分を常に自動的に行う. しかし, 有理式については通分は行うが, 約分はユーザーが指定しない限り行わない. この約分を行うコマンドが red である.
• EZGCD により rat の分子, 分母を約分する.
• 出力される有理式の分母の多項式は, 各係数の GCD が 1 の整数係数多項式である. 分子については整数係数多項式となるとは限らない.
• GCD は大変重い演算なので, 他の方法で除ける共通因子は可能な限り除くのが望ましい. また, 分母, 分子が大きくなってからのこの函数の呼び出しは, 非常に時間が掛かる場合が多い. 有理式演算を行う場合は, ある程度頻繁に, 約分を行う必要がある.
[0] (x^3-1)/(x-1);(x^3-1)/(x-1)[1] red((x^3-1)/(x-1));421

x^2+x+1[2] red((x^3+y^3+z^3-3*x*y*z)/(x+y+z));x^2+(-y-z)*x+y^2-z*y+z^2[3] red((3*x*y)/(12*x^2+21*y^3*x));(y)/(4*x+7*y^3)[4] red((3/4*x^2+5/6*x)/(2*y*x+4/3*x));(9/8*x+5/4)/(3*y+2)
75. umul(p1 ,p2 ):: 整数係数一変数多項式の高速乗算
76. umul ff(p1 ,p2 ):: 有限体係数一変数多項式の高速乗算
77. usquare(p1 ):: 整数係数一変数多項式の高速 2 乗算
78. usquare ff(p1 ):: 有限体係数一変数多項式の高速 2 乗算
79. utmul(p1 ,p2 ,d):: 整数係数一変数多項式の高速乗算 (打ち切り次数指定)
80. utmul ff(p1 ,p2 ,d):: 有限体係数一変数多項式の高速乗算 (打ち切り次数指定)• 一変数多項式の乗算を, 次数に応じて決まるアルゴリズムを用いて高速に行う.
• umul(), usquare(), utmul() は係数を整数と見なして, 整数係数の多項式として積を求める. 係
数が有限体 GF (p) の元の場合には, 係数は 0 以上 p 未満の整数と見なされる.
• umul ff(), usquare ff(), utmul ff() は, 係数を有限体の元と見なして, 有限体上の多項式として積を求める. ただし, 引数の係数が整数の場合, 整数係数の多項式を返す場合もあるので, これらを呼び出した結果が有限体係数であることを保証するためにはあらかじめ simp ff() で係数を有限体の元に変換しておくとよい.
• umul ff(), usquare ff(), utmul ff() は, GF (2n ) 係数の多項式を引数に取れない.
• umul(), umul ff() の結果は p1 , p2 の積, usquare(), usquare ff() の結果は p1 の 2 乗,
utmul(), utmul ff() の結果は p1 , p2 の積の, d 次以下の部分となる.
• いずれも, set upkara() (utmul, utmul ff については set uptkara()) で返される値以下の次数に対しては通常の筆算形式の方法, set upfft() で返される値以下の次数に対しては Karatsuba
法, それ以上では FFT および中国剰余定理が用いられる. すなわち, 整数に対する FFT ではなく,十分多くの 1 ワード以内の法 mi を用意し, p1 , p2 の係数を mi で割った余りとしたものの積を,FFT で計算し, 最後に中国剰余定理で合成する. その際, 有限体版の函数においては, 最後に基礎体を表す法で各係数の剰余を計算するが, ここでは Shoup によるトリック [Shoup] を用いて高速化してある[0] load("fff")$[1] cputime(1)$0sec(1.407e-05sec)[2] setmod_ff(2^160-47);
1461501637330902918203684832716283019655932542929
0sec(0.00028sec)[3] A=randpoly_ff(100,x)$0sec(0.001422sec)[4] B=randpoly_ff(100,x)$0sec(0.00107sec)

422

[5] for(I=0;I<100;I++)A*B;
7.77sec + gc : 8.38sec(16.15sec)[6] for(I=0;I<100;I++)umul(A,B);
2.24sec + gc : 1.52sec(3.767sec)[7] for(I=0;I<100;I++)umul_ff(A,B);
1.42sec + gc : 0.24sec(1.653sec)[8] for(I=0;I<100;I++)usquare_ff(A);1.08sec + gc : 0.21sec(1.297sec)[9] for(I=0;I<100;I++)utmul_ff(A,B,100);
1.2sec + gc : 0.17sec(1.366sec)[10] deg(utmul_ff(A,B,100),x);100
81. kmul(p1 ,p2 ):: 一変数多項式の乗算を Karatsuba 法で行う
82. ksquare(p1 ):: 一変数多項式の高速 2 乗算を Karatsuba 法で行う
83. ktmul(p1 ,p2 ,d)
一変数多項式の高速乗算 (打ち切り次数指定) を Karatsuba 法で行う
• 一変数多項式の乗算を Karatsuba 法で行う.
• 基本的には umul() と同様だが, 次数が大きくなっても FFT を用いた高速化は行わない.
• GF (2n ) 係数の多項式にも用いることができる.
[0] load("code/fff");
1[1] setmod_ff(defpoly_mod2(160));
x^160+x^5+x^3+x^2+1
A=randpoly_ff(100,x)$
B=randpoly_ff(100,x)$[2] umul(A,B)$
umul : invalid argument
return to toplevel[3] kmul(A,B)$
84. set upkara([threshold]):: 1 変数多項式の積演算における N 2 , Karatsuba, FFT アルゴリズムの切替えの閾値
85. set uptkara([threshold]):: 1 変数多項式の積演算における N 2 , Karatsuba, FFT アルゴリズムの切替えの閾値
86. set upfft([threshold]):: 1 変数多項式の積演算における N 2 , Karatsuba, FFT アルゴリズムの切替えの閾値• いずれも, 一変数多項式の積の計算における, アルゴリズム切替えの閾値を設定する.
• 一変数多項式の積は, 次数 N が小さい範囲では通常の N 2 アルゴリズム, 中程度の場合 Karatsuba
アルゴリズム, 大きい場合には FFT アルゴリズムで計算される. この切替えの次数を設定する.
• 詳細は, それぞれの積函数の項を参照のこと.
87. utrunc(p,d):: 一変数多項式を次数で切る
88. udecomp(p,d):: 一変数多項式を次数で分ける

423

89. ureverse(p):: 一変数多項式の次数を逆にした多項式を作る• p の変数を x とする. このとき p = p1 + xd+1 p2 (p1 の次数は d 以下) と分解できる. utrunc()
は p1 を返し, udecomp() は [p1 ,p2 ] を返す.
• p の次数を e とし, i 次の係数を p[i] とすれば, ureverse() は p[e] + p[e − 1]x + · · · を返す[0] utrunc((x+1)^10,5);252*x^5+210*x^4+120*x^3+45*x^2+10*x+1[1] udecomp((x+1)^10,5);[252*x^5+210*x^4+120*x^3+45*x^2+10*x+1,x^4+10*x^3+45*x^2+120*x+210][2] ureverse(3*x^3+x^2+2*x);2*x^2+x+3
90. uinv as power series(p,d):: 一変数多項式を冪級数とみて, 逆元計算
91. ureverse inv as power series(p,d):: 一変数多項式を次数を逆にして冪級数とみて, 逆元計算
• uinv_as_power_series(p,d) は, 定数項が 0 でない多項式 p に対し, pr − 1 の最低次数が d + 1以上になるような 高々 d 次の多項式 r を求める.
• ureverse_inv_as_power_series(p,d) は p の次数を e とするとき, p1 =ureverse(p,e) に対して uinv_as_power_series(p1 ,d) を計算する.
• rembymul_precomp() の引数として用いる場合, ureverse_inv_as_power_series() の結果をそのまま用いることができる.
[123] A=(x+1)^5;x^5+5*x^4+10*x^3+10*x^2+5*x+1[124] uinv_as_power_series(A,5);-126*x^5+70*x^4-35*x^3+15*x^2-5*x+1[126] A*R;
-126*x^10-560*x^9-945*x^8-720*x^7-210*x^6+1[127] A=x^10+x^9;
x^10+x^9[128] R=ureverse_inv_as_power_series(A,5);-x^5+x^4-x^3+x^2-x+1[129] ureverse(A)*R;-x^6+192. udiv(p1 ,p2 ):: 一変数多項式 p1 , p2 に対し, 商を返す
93. urem(p1 ,p2 ):: 一変数多項式 p1 , p2 に対し, 剰余を返す
94. urembymul(p1 ,p2 ):: 一変数多項式 p1 , p2 に対し, 剰余を返す
95. urembymul precomp(p1 ,p2 ,inv):: 固定された多項式による剰余計算を多数行う場合などに用いる
96. ugcd(p1 ,p2 ):: 一変数多項式 p1 , p2 に対し, GCD を返す• 一変数多項式 p1 , p2 に対し, udiv は商, urem, urembymul は剰余, ugcd は GCD を返す. これらは, 密な一変数多項式に対する高速化を図ったものである. urembymul は, p2 による剰余計算を,424

p2 の冪級数としての逆元計算および, 乗算 2 回に置き換えたもので, 次数が大きい場合に有効である.
• urembymul_precomp は, 固定された多項式による剰余計算を多数行う場合などに効果を発揮する.
第 3 引数は, あらかじめ ureverse_inv_as_power_series() により計算しておく.
[0] setmod_ff(2^160-47);
1461501637330902918203684832716283019655932542929[1] A=randpoly_ff(200,x)$[2] B=randpoly_ff(101,x)$[3] cputime(1)$0sec(1.597e-05sec)[4] srem(A,B)$
0.15sec + gc : 0.15sec(0.3035sec)[5] urem(A,B)$
0.11sec + gc : 0.12sec(0.2347sec)[6] urembymul(A,B)$
0.08sec + gc : 0.09sec(0.1651sec)[7] R=ureverse_inv_as_power_series(B,101)$
0.04sec + gc : 0.03sec(0.063sec)[8] urembymul_precomp(A,B,R)$
0.03sec(0.02501sec)
97. pari(content,p):: x 変数の多項式とみて，係数の最大公約元を返す[0] pari(content,12*x^2-9*x+15);
3[1] pari(content,3*x^2-2*x+2/3);
1/3[2] pari(content,3*y^2*x^2-2*x*y+2/3*y);1/3*y98. pari(round,p):: 多項式の各係数を近似整数に置き換える[0] pari(round,(1.3+x+3*y)^2);x^2+(6*y+3)*x+9*y^2+8*y+2
99. pari(roots,p[,prec]):: 多項式の根を求める[0] pari(roots,x^3+2);[ -1.25992104989487316475(0.62996052494743658237-1.091123635971721403457*@i)(0.62996052494743658237+1.091123635971721403457*@i) ]100. pari(disc,p):: x 変数の多項式 p の判別式を返す．
[0] pari(disc,a*x^2+b*x+c);425

-4*c*a+b^2[1] pari(disc,x^4+a*x^2+b*x+c);
16*c*a^4-4*b^2*a^3-128*c^2*a^2+144*c*b^2*a-27*b^4+256*c^3
3.3.3 リスト，ベクトル，配列の演算
101. car(list):: 空でない list の先頭要素（空の場合は空のリスト）を返す
102. cdr(list):: 空でない list から先頭要素を除いた（空の場合は空の）リストを返す
103. cons(obj,list):: list の先頭に obj を加えたリストを返す
104. append(list1,list2):: list1 の後に list2 をつなげたリストを返す
m2l( |list=1) を使うと，一度に多くのリストをつなげることができる．
105. reverse(list):: 逆順に並べ替えたリストを返す
106. length(lv):: リストまたはベクトルの長さを返す• リストは [obj1,obj2,...] と表される. obj1 が先頭要素である.
• car() は, 空でない list の先頭要素を出力する. 空リストが入力された場合は, 空リストが出力される.
• cdr() は, 空でない list から先頭要素を取り除いたリストを出力する. 空リストが入力された場合
は, 空リストが出力される.
• cons() は, list の先頭に obj を付け加えたリストを出力する.
• append() は, list1 の要素と list2 のすべての要素を結合させたリスト [list1 の要素の並び,list2の要素の並び] を出力する.
• reverse() は, list を逆順にしたリストを出力する.
• length() は, list または vect の長さを出力する. 行列の要素の個数は, size() を用いる.
• リストは読み出し専用で, 要素の入れ替えはできない. リストの n 番目の要素の取り出しは, cdr()
を n 回適用した後 car() を適用することにより可能であるが, 便法として, ベクトル, 行列などの配列と同様, インデックス [n] を後ろに付けることにより取り出すことができる. ただし, システ
ム内部では, 実際にポインタを n 回たどるので, 後ろの要素ほど取り出しに時間がかかる.
• cdr() は新しいセルを生成しないが, append() は, 実際には第 1 引数のリストの長さだけのcons() の繰り返しとなるため, 第 1 引数のリストが長い場合には多くのメモリを消費することになる. reverse() に関しても同様である.
[0] L = [[1,2,3],4,[5,6]];[[1,2,3],4,[5,6]][1] car(L);[1,2,3][2] cdr(L);[4,[5,6]][3] cons(x*y,L);[y*x,[1,2,3],4,[5,6]][4] append([a,b,c],[d]);[a,b,c,d][5] reverse([a,b,c,d]);[d,c,b,a]426

[6] length(L);3[7] length(ltov(L));
3[8] L[2][0];5107. newvect(len[,list]):: 長さ len のベクトルを生成する
108. vector(len[,list]):: 長さ len のベクトルを生成する
109. vect([elements]):: 要素の並びからベクトルを生成する• vect() は要素の並びからベクトルを生成する.
• vector() は newvect() の別名である.
• newvect() は長さ len のベクトルを生成する. 第 2 引数がない場合, 各成分は 0 に初期化される.
第 2 引数がある場合, インデックスの小さい成分から, リストの各要素により初期化される. 各要
素は, 先頭から順に使われ, 足りない分は 0 が埋められる.
• ベクトルの成分は, 第 0 成分から第 len−1 成分となる. (第 1 成分からではない事に注意. )• リストは各成分が, ポインタを辿る事によってシーケンシャルに呼び出されるのに対し, ベクトルは各成分が第一成分からのメモリ上の displacement (変位) によってランダムアクセスで呼び出され, その結果, 成分のアクセス時間に大きな差が出てくる. 成分アクセスは, リストでは, 成分の量が増えるに従って時間がかかるようになるが, ベクトルでは, 成分の量に依存せずほぼ一定である.
• Asir では, 縦ベクトル, 横ベクトルの区別はない. 行列を左から掛ければ縦ベクトルとみなされる
し, 右から掛ければ横ベクトルとみなされる.
• ベクトルの長さは size() によって得られる. 函数の引数としてベクトルを渡した場合, 渡された函数は, そのベクトルの成分を書き換えることができる．
[0] A=newvect(5);[ 0 0 0 0 0 ][1] A=newvect(5,[1,2,3,4,[5,6]]);[ 1 2 3 4 [5,6] ][2] A[0];1[3] A[4];[5,6][4] size(A);[5][5] length(A);5[6] vect(1,2,3,4,[5,6]);[ 1 2 3 4 [5,6] ][7] def afo(V) { V[0] = x; }[8] afo(A)$[9] A;[ x 2 3 4 [5,6] ]110. ltov(list)427

:: list をベクトルに変換する• リスト list を同じ長さのベクトルに変換する.
• この函数は newvect(length(list),list) に等しい
[0] A=[1,2,3];[1] ltov(A);[ 1 2 3 ]111. vtol(vect):: ベクトルをリストに変換する• 長さ n のベクトル vect を [vect[0],...,vect[n-1]] なるリストに変換する.
• リストからベクトルへの変換は newvect() で行う.
[0] A=newvect(3,[1,2,3]);[ 1 2 3 ][1] vtol(A);[1,2,3]112. newbytearray(len,[listorstring]):: newvect と同様にして byte array を生成する• 文字列で初期値を指定することも可能である.
• byte array の要素のアクセスは配列と同様である.
[0] A=newbytearray(3);|00 00 00|[1] A=newbytearray(3,[1,2,3]);|01 02 03|[2] A=newbytearray(3,"abc");|61 62 63|[3] A[0];97[4] A[1]=123;
123[5] A;|61 7b 63|
113. size(vect/mat):: 行列のサイズまたはベクトルの長さを求める函数（戻り値はリスト）• vect の長さ, または mat の大きさをリスト [vect の長さ]，[mat の行数, mat の列数] で出力する.
• vect の長さは length() で求めることもできる.
• list の長さは length() を, 有理式に現れる単項式の数は nmono() を用いる.
[0] A = newvect(4);[ 0 0 0 0 ][1] size(A);[4][2] length(A);4[3] B = newmat(2,3,[[1,2,3],[4,5,6]]);428

[ 1 2 3 ][ 4 5 6 ][4] size(B);[2,3]114. qsort(array [,func]):: 一次元配列 array をソートする.
• 一次元配列（リストまたはベクトル）を quick sort でソートする.
• 比較用函数が指定されていない場合, オブジェクトどうしの比較結果で順序が下のものから順に並べ換えられる.
• 0, 1, −1 を返す 2 引数函数が func として与えられた場合, func(A,B)=1 の場合に A>B として,順序が下のものから順に並べ換えられる.
• 配列は新たに生成されず, 引数の配列の要素のみ入れ替わる.
[0] qsort(newvect(10,[1,4,6,7,3,2,9,6,0,-1]));[ -1 0 1 2 3 4 6 6 7 9 ][1] def rev(A,B) { return A>B?-1:(A<B?1:0); }[2] qsort(newvect(10,[1,4,6,7,3,2,9,6,0,-1]),rev);[ 9 7 6 6 4 3 2 1 0 -1 ][3] qsort([1,4,6,7,3,2,9,6,0,-1]);[-1,0,1,2,3,4,6,6,7,9]
3.3.4 行列の演算
115. newmat(row,col [,[[a,b,...],[c,d,...],...]] )116. matrix(row,col [,[[a,b,...],[c,d,...],...]] ):: row 行 col 列の行列を生成する• matrix は newmat の別名である.
• row 行 col 列の行列を生成する. 第 3 引数がない場合, 各成分は 0 に初期化される. 第 3 引数がある場合, インデックスの小さい成分から, 各行が, リストの各要素 (これはまたリストである) により初期化される. 各要素は, 先頭から順に使われ, 足りない分は 0 が埋められる.
• 行列のサイズは size() で得られる.
• M が行列のとき, M[I] により第 I 行をベクトルとして取り出すことができる. このベクトルは, もとの行列と成分を共有しており, いずれかの成分を書き換えれば, 他の対応する成分も書き換わることになる.
• 函数の引数として行列を渡した場合, 渡された函数は, その行列の成分を書き換えることができる.
[0] A = newmat(3,3,[[1,1,1],[x,y],[x^2]]);[ 1 1 1 ][ x y 0 ][ x^2 0 0 ][1] det(A);-y*x^2[2] size(A);[3,3][3] A[1];[ x y 0 ][4] A[1][3];getarray : Out of range429

return to toplevel[5] B=A[2][ x^2 0 0 ][6] B[1]=y^2;y^2[7] A;[ 1 1 1 ][ x y 0 ][ x^2 y^2 0 ]117. mat(vector[,...])
118. matr(vector[,...]):: 行ベクトル（またはリスト）の並びから行列を生成する
119. matc(vector[,...]):: 列ベクトル（またはリスト）の並びから行列を生成する• mat() は matr() の別名．
• 行列のサイズは，最初のベクトル（リスト）の長さと引数の個数で決まり，足りない部分は 0 で埋められる．

• s2m() の方が高機能[0] matr([1,2,3],[4,5,6],[7,8]);[ 1 2 3 ][ 4 5 6 ][ 7 8 0 ][1] matr([1,2],[4,5,6],[7,8,0]);[ 1 2 ]
[ 4 5 ]
[ 7 8 ]
[2] matc([1,2,3],[4,5,6],[7,8]);[ 1 4 7 ][ 2 5 8 ][ 3 6 0 ][3] mat(ltov([1,2]),[4,5,6]);[ 1 2 ]
[ 4 5 ]
120. det(mat[,mod]):: mat の行列式
121. nd det(mat[,mod]):: 有理数または有限体上の多項式行列 mat の行列式
• det() および nd det() は行列 mat の行列式を求める.
• 引数 mod がある時, GF (mod) 上での行列式を求める. 分数なしのガウス消去法によっているた
め, 多変数多項式を成分とする行列に対しては小行列式展開による方法のほうが効率がよい場合もある.
• nd det() は有理数または有限体上の多項式行列の行列式計算専用である. アルゴリズムはやはり分数なしのガウス消去法だが, データ構造および乗除算の工夫により, 一般に det() より高速に計算できる．

• 有理式を成分とする行列には非対応なので，mydet() または mydet2() を用いる．
430

[0] A=newmat(5,5)$[1] V=[x,y,z,u,v];[x,y,z,u,v][2] for(I=0;I<5;I++)for(J=0,B=A[I],W=V[I];J<5;J++)B[J]=W^J;[3] A;[ 1 x x^2 x^3 x^4 ][ 1 y y^2 y^3 y^4 ][ 1 z z^2 z^3 z^4 ][ 1 u u^2 u^3 u^4 ][ 1 v v^2 v^3 v^4 ][4] fctr(det(A));[[1,1],[u-v,1],[-z+v,1],[-z+u,1],[-y+u,1],[y-v,1],[-y+z,1],[-x+u,1],[-x+z,1],[-x+v,1],[-x+y,1]]
B=mat([1,0],[0,1/x]);[ 1 0 ][ 0 (1)/(x) ][5] det(B);internal error (SEGV)
return to toplevel[6] os_md.mydet(B);(1)/(x)122. invmat(mat):: 行列 mat の逆行列
• 逆行列は [分母, 分子] の形で返され, 分母が行列, 分母/分子 が逆行列となる.
• 有理式を成分とする行列には非対応なので，そのときは myinv() を用いる．
[0] A = newmat(3,3)$[1] for(I=0;I<3;I++)for(J=0,B=A[I],W=V[I];J<3;J++)B[J]=W^J;[2] A;[ 1 x x^2 ][ 1 y y^2 ][ 1 z z^2 ][3] invmat(A);[[ -z*y^2+z^2*y z*x^2-z^2*x -y*x^2+y^2*x ][ y^2-z^2 -x^2+z^2 x^2-y^2 ][ -y+z x-z -x+y ],(-y+z)*x^2+(y^2-z^2)*x-z*y^2+z^2*y][4] A*B[0];[ (-y+z)*x^2+(y^2-z^2)*x-z*y^2+z^2*y 0 0 ][ 0 (-y+z)*x^2+(y^2-z^2)*x-z*y^2+z^2*y 0 ][ 0 0 (-y+z)*x^2+(y^2-z^2)*x-z*y^2+z^2*y ][5] map(red,A*B[0]/B[1]);[ 1 0 0 ][ 0 1 0 ][ 0 0 1 ]431

[6] C=mat([1,0],[0,1/x]);[ 1 0 ][ 0 (1)/(x) ][7] invmat(C);internal error (SEGV)
return to toplevel[8] os_md.myinv(C);[ 1 0 ]
[ 0 x ]
[9] M=mat([2,0],[0,1/2]);[ 2 0 ]
[ 0 1/2 ][10] invmat(M);[[ 1/2 0 ][ 0 2 ],1]
[11] N=mat([2,0],[0,1]);[ 2 0 ]
[ 0 1 ]
[12] invmat(N);[[ 1 0 ][ 0 2 ],2]123. rowx(matrix,i,j):: 第 i 行と第 j 行を交換する
124. rowm(matrix,i,c):: 第 i 行を c 倍する
125. rowa(matrix,i,j,c):: 第 i 行に第 j 行の c 倍を加える
126. colx(matrix,i,j):: 第 i 列と第 j 列を交換する
127. colm(matrix,i,c):: 第 i 列を c 倍する.
128. cola(matrix,i,j,c):: 第 i 列に第 j 列の c 倍を加える.
• 行列の基本変形を行うための函数である.
• 行列が破壊されることに注意する.
[0] A=newmat(3,3,[[1,2,3],[4,5,6],[7,8,9]]);[ 1 2 3 ][ 4 5 6 ][ 7 8 9 ][1] rowx(A,1,2)$[2] A;[ 1 2 3 ][ 7 8 9 ][ 4 5 6 ][3] rowm(A,2,x);432

[ 1 2 3 ][ 7 8 9 ][ 4*x 5*x 6*x ][4] rowa(A,0,1,z);[ 7*z+1 8*z+2 9*z+3 ][ 7 8 9 ][ 4*x 5*x 6*x ]129. pari(adj,mat):: 行列 mat の余因子行列（元の行列との積が行列式となる）を返す[0] pari(adj,mat([1,1,1],[x,1,1],[1,y,1]));[ -y+1 y-1 0 ][ -x+1 0 x-1 ][ y*x-1 -y+1 -x+1 ]130. pari(trace,mat):: 行列 mat の trace を返す[0] pari(trace,mat([1,1,1],[x,1,1],[1,y,1]));
3
131. pari(signat,mat):: 実対称行列の符号を返す[0] pari(signat,mat([1,2,3],[1,1,1],[3,2,1]));[ 2 1 ]
132. pari(indexrank,mat):: 行列 mat の階数に等しいサイズの正則小行列の一つの行と列の位置を返す[0] pari(indexrank,mat([1,2,3],[2,4,6],[1,3,2],[2,5,5],[0,1,-1]));[ [ 1 3 ] [ 1 2 ] ]133. pari(supplement,mat):: 列ベクトルが一次独立な行列 mat の右に列を補って正則正方行列を作る[0] A=mat([1,1],[1,1],[1,0],[0,1]);[ 1 1 ]
[ 1 1 ]
[ 1 0 ]
[ 0 1 ]
[1] pari(supplement,A);[ 1 1 0 0 ][ 1 1 1 0 ][ 1 0 0 0 ][ 0 1 0 1 ]134. pari(hess,mat):: 正方行列をヘッセンベルグ行列に変換する
ヘッセンベルグ行列（対角成分の 2 つより下の成分が 0 の行列）に相似変換する．

433

[0]pari(hess,mat([1,2,3],[4,5,6],[7,8,9]));[ 1 29/7 2 ][ 7 95/7 8 ][ 0 54/49 3/7 ]135. pari(eigen,mat[,prec]):: 数を成分とする行列の固有ベクトルを返す[0] A=os_md.s2m("(13)2,(10)(14)");[ 13 2 ][ 10 14 ][1] pari(eigen,A);[ -1/2 2/5 ][ 1 1 ]
136. pari(jacobi,mat[,prec]):: 実対称行列の固有値と固有ベクトルを返す[0] pari(jacobi,mat([1,2],[2,1]));[ [ 3.000000000000000000 -1.0000000000000000000 ][ 0.70710678118654752449 -0.70710678118654752438 ][ 0.70710678118654752438 0.70710678118654752449 ] ]3.3.5 文字列に関する演算
137. rtostr(obj):: obj を文字列に変える• 任意のオブジェクト obj を文字列に変える.
• 整数などを文字列に変換して変数名と結合することにより, 添字付きの不定元を生成する場合に多く用いられる.
• 逆に, 文字列を不定元に変換する時には, strtov()（cf. makev()）を用いる.
[0] A=afo;
afo[1] type(A);2[2] B=rtostr(A);afo[3] type(B);7[4] B+"1";
afo1
138. strtov(str):: str (文字列) を不定元に変える• 不定元として変換可能な文字列とは, 英小文字で始まり, 英字, 数字および記号 で作られる文字列である.
• rtostr() と組合せて, プログラム中で自動的に不定元を生成したい時に用いられる.
[0] A="afo";

434

afo
[1] for (I=0;I<3;I++) {B=strtov(A+rtostr(I)); print([B,type(B)]);}[afo0,2][afo1,2]
139. eval str(str):: str (文字列) を評価する.
• Asir の parser が受理可能な文字列を評価してその結果を返す.
• 評価可能な文字列は, 式を表すものに限る.
• 論理的には rtostr() の逆函数となる.
• Mathematica の文字列の評価には evalma() を用いる．
[0] eval_str("1+2");
3[1] fctr(eval_str(rtostr((x+y)^10)));[[1,1],[x+y,10]]140. strtoascii(str):: 文字列をアスキーコード（1 以上 255 以下の整数）のリストで表す
strtoascii() は文字列を整数のリストに変換する. 各整数は文字列のアスキーコードを表す.
141. asciitostr(list):: アスキーコードの列を文字列に変換する
asciitostr() は asciitostr() の逆函数である.
[0] strtoascii("abcxyz");[97,98,99,120,121,122][1] asciitostr(@);
abcxyz[2] asciitostr([256]);
asciitostr : argument out of range
return to toplevel
142. str len(str):: 文字列の長さを返す
143. str chr(str,start,c):: 文字が最初に現れる位置を返す• str の start 番目の文字からスキャンして 最初に c の最初の文字が現れた位置を返す. 文字列の先頭は 0 番目とする• str char() が上位互換函数．str str() はより多機能な函数．
[0] Line="123 456 (x+y)^3";
123 456 (x+y)^3[1] Sp1 = str_chr(Line,0," ");3[2] D0 = eval_str(sub_str(Line,0,Sp1-1));
123[3] Sp2 = str_chr(Line,Sp1+1," ");7[4] D1 = eval_str(sub_str(Line,Sp1+1,Sp2-1));

435

456
[5] C = eval_str(sub_str(Line,Sp2+1,str_len(Line)-1));x^3+3*y*x^2+3*y^2*x+y^3
144. sub str(str,start,end):: 部分文字列を返す• str cut() はより多機能な函数．
3.3.6 構造体に関する函数
145. newstruct(name):: 構造体名が name の構造体を生成する• あらかじめ, name なる構造体が定義されていなければならない.
• 構造体の各メンバは演算子 -> により名前でアクセスする. メンバが構造体の場合, 更に -> による指定を続けることができる[0] struct list {h,t};0[1] A=newstruct(list);{0,0}[2] A->t = newstruct(list);{0,0}[3] A;{0,{0,0}}[4] A->h = 1;
1
[5] A->t->h = 2;
2
[6] A->t->t = 3;
3[7] A;{1,{2,3}}146. arfreg(name,add,sub,mul,div,pwr,chsgn,comp):: 構造体に体する基本演算を登録する• 登録したくない基本演算に対しては引数に 0 を与える. これによって一部の演算のみを利用することができる.
• それぞれの函数の仕様は次の通りである.
add(A,B)
A+B
sub(A,B)
A-B
mul(A,B)
A*B
div(A,B)
A/B
pwr(A,B)
A^B
chsgn(A)-A
comp(A,B) 1,0,-1 according to the result of a comparison between A and B.
% cat test
struct a {id,body}\$
def add(A,B)

436

{C = newstruct(a);C->id = A->id; C->body = A->body+B->body;
return C;}
def sub(A,B){
C = newstruct(a);C->id = A->id; C->body = A->body-B->body;
return C;}
def mul(A,B){
C = newstruct(a);C->id = A->id; C->body = A->body*B->body;
return C;}
def div(A,B){
C = newstruct(a);C->id = A->id; C->body = A->body/B->body;
return C;}
def pwr(A,B){
C = newstruct(a);C->id = A->id; C->body = A->body^B;
return C;}
def chsgn(A){C = newstruct(a);C->id = A->id; C->body = -A->body;
return C;}
def comp(A,B){
if ( A->body > B->body )437

return 1;
else if ( A->body < B->body )return -1;
else
return 0;}
arfreg("a",add,sub,mul,div,pwr,chsgn,comp)$
end$% asirThis is Risa/Asir, Version 20000908.
Copyright (C) FUJITSU LABORATORIES LIMITED.
1994-2000. All rights reserved.
[0] load("./test")$[11] A=newstruct(a);{0,0}[12] B=newstruct(a);{0,0}[13] A->body = 3;
3[14] B->body = 4;4[15] A*B;{0,12}
147. str type(name|object):: 構造体の識別番号を取得する• 名前が name である構造体, または object の指す構造体の識別番号を取得する. エラーのときは−1 を返す[0] struct list {h,t};0[1] A=newstruct(list);{0,0}[2] struct_type(A);3[3] struct_type("list");3
3.3.7 入出力
148. end
149. quit:: 現在読み込み中のファイルを閉じる. トップレベルにおいてはセッションを終了することになる• end, quit ともに無引数の函数であるが, ‘()’ なしで呼び出すことができる. いずれも現在読み込
み中のファイルを閉じる. これは, トップレベルにおいてはセッションを終了させることになる.
• ファイルの場合, ファイルの終端まで読めば, 自動的にファイルは閉じられるが, トップレベルの場

438

合プロンプトが出ないまま, 入力待ちになるので, ファイルの終端には end$ を書くのが望ましい.

[0] quit;%150. load("ﬁlename"):: ﬁlename を読み込む• 実際のプログラムの書き方は, ユーザ言語 Asir を参照. テキストファイルを読み込む場合, cpp
を通すので, C のプログラム同様 #include, #define を使うことができる.
• 指定したファイルが存在した時には 1 を返し, 存在しなかった時は 0 を返す.
• ファイル名が ‘/’ で始まる場合は絶対パス, ‘.’ で始まる場合はカレントディレクトリからの相対パスと見なされる. それ以外の場合, 環境変数 ASIRLOADPATH に設定されているディレクトリを左から順にサーチする. それらに該当するファイルが存在しない場合, 標準ライブラリディレクトリ
(あるいは環境変数 ASIR_LIBDIR に設定されているディレクトリ) もサーチする. Windows 版の場合, ASIR_LIBDIR が設定されていない場合には, get_rootdir()/lib をサーチする.
• 読み込むファイルの最後に, end$ がないと load() 終了後にプロンプトがでないが, 実際には入力を受け付ける. しかし, 混乱を招くおそれがあるのでファイルの最後に end$ を書いておくことが望ましい. (end; でもよいが, end が返す値 0 が表示されるため, end$ をお勧めする. )• Windows 版もディレクトリのセパレータとして ‘/’ を用いる
151. which("ﬁlename"):: 引数 ﬁlename に対し, load() が読み込むパス名を返す• load() がファイルをサーチする手順に従ってサーチし, ファイルが存在する場合にはパス名を文字列として, 存在しない場合には 0 を返す.
• サーチの手順については load() を参照.
• Windows 版もディレクトリのセパレータとして ‘/’ を用いる
[0] which("gr");./gb/gr[1] which("/usr/local/lib/gr");0[2] which("/usr/local/lib/asir/gr");/usr/local/lib/asir/gr
152. output(["ﬁlename"]):: 以降の出力先を ﬁlename または標準出力に切替える• Asir の出力を標準出力から, ファイルへの出力に切替える. なお, ファイル出力の間は, 標準出力にはキーボードからの入力以外, 出力されない.
• 別のファイル出力に切替える時には, 再び output("ﬁlename") を実行する. 又, ファイル出力を終了し標準出力に戻りたい時には, 引数なしで output() を実行する.
• 指定したファイル ﬁlename が存在した時は, そのファイルの末尾に追書きされ, 存在しなかった時には, 新たにファイルを作成し, そこに書き込まれる.
• ファイルネームを " " ダブルクォートなしで指定をしたり, ユーザが, 書き込めないファイルを指定したりすると, エラーによりトップレベルに戻る.
• 入力したものも込めてファイルに出力したい場合には, ctrl("echo",1) を実行した後でファイル出力に切替えれば良い. 計算時間など, 標準エラー出力に書き出されるものはファイルには書き出されない. 函数形式, 未定係数 (vtype() 参照) を含まない数式のファイルへの読み書きは,bload(), bsave() を使うのが, 時間, 空間ともに効率がよい.
• Windows 版もディレクトリのセパレータとして ‘/’ を用いる．
[0] output("afo");fctr(x^2-y^2);439

print("afo");
output();1[1] quit;% cat afo
1[2] [[1,1],[x+y,1],[x-y,1]][3] afo
0[4]
153. bsave(obj,"ﬁlename"):: ﬁlename に obj をバイナリ形式で書き込む
154. bload("ﬁlename"):: ﬁlename から数式をバイナリ形式で読み込む• obj は 函数形式, 未定係数を含まない任意の数式• bsave() は内部形式をほぼそのままバイナリ形式でファイルに書き込む. bload() は, bsave()で書き込んだ数式を読み込んで内部形式に変換する. 現在のインプリメンテーションの制限により,
函数形式, 未定係数 (vtype()) を含まないリスト, 配列などを含む任意の数式をファイルに保存することができる. output などで保存した場合, 読み込み時にパーザが起動されるが, bsave() で保存したものを bload() で読む場合, 直接内部形式が構成できるため, 時間的, 空間的に効率がよい.
• 多項式の場合, 書き込み時と読み込み時で変数順序が異なる場合があるが, その場合には, 自動的に現在の変数順序における内部形式に変換される.
• Windows 版もディレクトリのセパレータとして ‘/’ を用いる.
[0] A=(x+y+z+u+v+w)^20$[1] bsave(A,"afo");
1[2] B = bload("afo")$[3] A == B;
1[4] X=(x+y)^2;
x^2+2*y*x+y^2[5] bsave(X,"afo")$[6] quit;% asir[0] ord([y,x])$[1] bload("afo");y^2+2*x*y+x^2155. print(obj[,nl]):: obj を評価して表示する• 第 2 引数がないか, または 0, 2 以外の場合, 改行する. 第 2 引数が 0 の場合, 改行せず, 出力はバッ
ファに書き込まれ, バッファはフラッシュされない. 第 2 引数が 2 の場合, 改行しないがバッファ
はフラッシュされる. この函数の戻り値は 0 であるから, print(); で実行すると, 出力の後に 0が返される. print()$ とすれば, 最後の 0 は出力されない.
• 複数の obj を同時に出力したい時は obj をリストにするとよい．mycat(), mycat0() を参照．

440

[0] def cat(L) { while ( L != [] ) { print(car(L),0); L = cdr(L);}print(""); }[1] cat([xyz,123,"gahaha"])$xyz123gahaha
156. printf(format[,args])
157. fprintf(fd,format[,args])158. sprintf(format[,args]):: C に似たプリント関数（実験的仕様関数）• printf は書式文字列 format にしたがい, オブジェクト args を標準出力に書き出す.
• fprintf は結果を, ファイル記述子 fd の指すファイルに書き出す.
• sprintf は結果を文字列で返し, 標準出力には書き出さない.
• 書式文字列の中で %a (any) が利用可能．args の個数は書式文字列の中の %a の個数に等しくする
こと. ファイル記述子は openfile() 関数を用いて得ること.
[0] printf("%a: rat = %a\n",10,x^2-1)$
10: rat = x^2-1[1] S=sprintf("%a: rat = %a",20,x^2-1)$[2] S;
20: rat = x^2-1[3] Fd=open_file("hoge.txt","w");
0[4] fprintf(Fd,"Poly=%a\n",(x-1)^3)$[5] close_file(Fd)$[6] quit;$ cat hoge.txt
Poly=x^3-3*x^2+3*x-1
159. access(ﬁle):: ﬁle の存在をテストし，存在すれば 1，存在しなければ 0 を返す
160. remove file(ﬁle):: ﬁle を消去する
161. open file("ﬁlename" [,"mode"]):: ﬁlename をオープンする
162. close file(num):: 識別子 num のファイルをクローズする
163. get line([num]):: 識別子 num のファイルから 1 行読む
164. get byte(num):: 識別子 num のファイルから 1 バイト読む
165. put byte(num,c):: 識別子 num のファイルに 1 バイト c を書く
166. purge stdin():: 標準入力のバッファをクリアする• open_file() はファイルをオープンする. mode 指定がない場合は読み出し用, mode 指定がある
場合には, C の標準入出力関数 fopen() に対するモード指定とみなす. たとえば新規書き込み用の場合 "w", 末尾追加の場合 "a" など. 成功した場合, ファイル識別子として非負整数を返す. 失敗の場合エラーとなる. 不要になったファイルは close_file() でクローズする. 特別なファイル441

名 unix://stdin, unix://stdout, unix://stderr を与えるとそれぞれ標準入力, 標準出力, 標
準エラー出力をオープンする. この場合モード指定は無視される.
• get_line() は現在オープンしているファイルから 1 行読み, 文字列として返す. 引数がない場合,
標準入力から 1 行読む.
• ファイルの終りまで読んだ後に get_line() が呼ばれた場合, 整数の 0 を返す.
• get_byte() は現在オープンしているファイルから 1 バイト読み 整数として返す.
• put_byte() は現在オープンしているファイルに 1 バイト書き, そのバイトを整数として返す.
• 読み出した文字列は, 必要があれば sub str() などの文字列処理関数で加工したのち eval str()
により内部形式に変換できる.
• purge_stdin() は, 標準入力バッファを空にする. 関数内で get_line() により標準入力から文字列を受け取る場合, 既にバッファ内に存在する文字列による誤動作を防ぐためにあらかじめ呼び
出す.

[0] Id = open_file("test");0[1] get_line(Id);12345[2] get_line(Id);67890[3] get_line(Id);0[4] type(@@);
0[5] close_file(Id);1[6] open_file("test");1[7] get_line(1);12345[8] get_byte(1);54/* the ASCII code of ’6’ */[9] get_line(1);7890/* the rest of the last line */[10] def test() { return get_line(); }[11] def test1() { purge_stdin(); return get_line(); }[12] test();/* a remaining newline character has been read *//* returns immediately */[13] test1();
123;/* input from a keyboard */123;/* returned value */442

3.3.8 型や函数，モジュールに関わる函数
167. type(obj):: obj の型を求める函数−1: 空 0:0 1: 数 2: 多 項 式 3: 有 理 式 4: リ ス ト 5: ベ ク ト ル 6: 行 列 7: 文 字 列 8: 構 造 体
9: 分散表現多項式 10: 符号なしマシン 32bit 整数 11: エラーオブジェクト 12: GF (2) 上の行列
13: MATHCAP オブジェクト 14: ﬁrst order formula 15: matrix over GF (p) 16: ビット列
• 数の型を求めるには, ntype() を用いる. 不定元の型を求めるには, vtype() を用いる.
168. ntype(num):: num (数) の 型 (整数) を返す. 数の型の値は0: 有理数 1: 倍精度浮動小数 2: 代数的数 3: 任意精度浮動小数 (bigﬂoat) 4: 複素数
5: 有限体の元 6: 大標数素体の元 7: 標数 2 の有限体の元• newalg(x^2+1) で生成した数と, 虚数単位 @i は, 異なるものとして扱われる.
• 代数的数に関しては, See section 代数的数に関する演算.
[0] [10/37,ntype(10/37)];[10/37,0][1] [10.0/37.0,ntype(10.0/37.0)];[0.27027,1][2] [newalg(x^2+1)+1,ntype(newalg(x^2+1)+1)];[(#0+1),2][3] [eval(sin(@pi/6)),ntype(eval(sin(@pi/6)))];[0.49999999999999999991,3][4] [@i+1,ntype(@i+1)];[(1+1*@i),4]
169. vtype(var):: var (不定元) の型 (整数) を返す• var (不定元) の型の値は次の通り.
0 一般不定元 (a,b,x,afo,bfo,..., etc)
1 uc() で生成された不定元 (_0, _1, _2, ... etc)
2 函数形式 (sin(x), log(a+1), acosh(1), @pi, @e, ... etc)
3 函数子 (組み込み函数子, ユーザ定義函数子, 初等函数子 : sin, log, ... etc)
170. call(name,args):: 函数 name を呼び出す• 函数子に関しては, vtype() を参照.
• 引数の個数があらかじめ分かっているときは *(name)() の形式が使える．
[0] A=igcd;
igcd[1] call(A,[4,6]);2[2] (*A)(4,6);2171. functor(func):: func の函数子を取り出す
172. args(func):: func の引数リストを取り出す
443

173. funargs(func):: cons(functor(func),args(func)) を返す• 函数形式に関しては, vtype() を参照.
• 函数形式 func の函数子, 引数リストを取り出す.
• 逆に, 取り出した函数子を値に持つプログラム変数を F とすれば (*F)(x) で x を引数とする函数
呼び出しまたは函数形式が入力できる[0] functor(sin(x));
sin[1] args(sin(x));[x][2] funargs(sin(3*cos(y)));[sin,3*cos(y)][3] for (L=[sin,cos,tan];L!=[];L=cdr(L)) {A=car(L);print(eval((*A)(@pi/3)));}
0.86602540349122136831
0.5000000002
1.7320508058
174. module list():: 定義済みのモジュールのリストを得る[0] module_list();[gr,primdec,bfct,sm1,gnuplot,tigers,phc]
175. module definedp(name):: モジュール name の存在をテストする• モジュール name が存在すれば 1, 存在しなければ 0 を返す[0] module_definedp("gr");1176. remove module(name):: モジュール name を削除する• 削除に成功すれば 1, 失敗すれば 0 を返す．
[0] remove_module("gr");
1
3.3.9 数値函数
177. dacos(num):: 函数値 Arccos(num) を倍精度浮動小数で求める
178. dasin(num):: 函数値 Arcsin(num) を倍精度浮動小数で求める
179. datan(num):: 函数値 Arctan(num) を倍精度浮動小数で求める
180. dcos(num):: 函数値 cos(num) を倍精度浮動小数で求める
181. dsin(num):: 函数値 sin(num) を倍精度浮動小数で求める

444

182. dtan(num):: 函数値 tan(num) を倍精度浮動小数で求める• これらの函数は C 言語の標準数学ライブラリを用いる. したがって, 計算結果はオペレーティング
システムとコンパイラに依存する.
• 複素数に対しては正しくない結果を返すので注意しなければならない.
• @pi などのシンボルを引数に与えることはできない.
[0] 4*datan(1);3.14159183. dabs(num):: 絶対値 |num| を倍精度浮動小数で求める
184. dexp(num):: 函数値 exp(num) を倍精度浮動小数で求める
185. dlog(num):: 対数値 log(num) を倍精度浮動小数で求める
186. dsqrt(num)√:: 平行根 num を倍精度浮動小数で求める• これらの函数は C 言語の標準数学ライブラリを用いる. したがって, 計算結果はオペレーティング
システムとコンパイラに依存する.
• dabs() と dsqrt() を除き、複素数に対しては正しくない結果を返すので注意しなければならない.
• @pi などのシンボルを引数に与えることはできない[0] dexp(1);2.71828
187. ceil(num):: num 以上の最小の整数を求める[0] dceil(1.1);
1188. dceil(num):: num 以上の最小の整数を求める（ceil() の別名）
189. floor(num):: num 以下の最大の整数を求める
190. dfloor(num):: num 以下の最大の整数を求める（floor() の別名）
191. rint(num):: num を整数にまるめる
192. drint(num):: num を整数にまるめる（rint() の別名）
193. pari(sqrt,num[,prec]):: （複素）数 num の平方根を与える[0] pari(sqrt,2);
1.41421356237309504876[1] pari(sqrt,1+@i);(1.098684113467809965957+0.45508986056222734133*@i)194. pari(arg,num[,prec]):: 複素数 num の偏角を与える（−π < 戻り値 ≤ π ）445

[0] pari(arg,1+@i);
0.78539816339744830961566084581
195. pari(gamma,num[,prec]):: ガンマ関数（num は複素数でもよい）
196. pari(gamh,num[,prec]):: Γ(num + 12 )（num は複素数でもよい）[0] pari(gamma,5);
23.99999999999999999826[1] pari(gamma,1+@i);(0.49801566811835604271-0.15494982830181068512*@i)197. pari(lngamma,num[,prec]):: log(Γ(x))[0] pari(lngamma,1000);
5905.22042320918121172113
198. pari(psi,num[,prec]):: digamma 関数′(x)ψ(x) = ΓΓ(x)[0] pari(psi,1);-0.57721566490153286077[1] pari(psi,1+@i);(0.094650320622476976191+1.076674047468581172509*@i)199. pari(erfc,num[,prec]):: 相補誤差関数 (complementary error function)
R∞2
erfc(x) = √2π x e−t dt = 1 − erc(x)[0] pari(erfc,1);
0.15729920705028513139
200. pari(dilog,num[,prec]):: dilogarithm 関数
P∞ k
Li2 (x) = k=1 xk2[0] pari(dilog,1);
1.64493406684822643609
201. pari(eta,τ [,prec]):: Dedekind の Eta 関数 η(τ ) で τ は虚部が正の複素数
πiτ Q∞
η(τ ) = e 12 m=1 (1 − e2πimτ )[0] pari(eta,1/2*@i+1/3);(1.0225406050061628844976445066022-0.035807228435521009596*@i)202. pari(wp,τ [,prec]):: Weber 関数 f(τ ) で τ は虚部が正の複素数−2πiτ η( τ +1 )2f(τ ) = e 48 η(x)203. pari(wp2,τ [,prec])446

:: Weber 関数 f2 (τ ) で τ は虚部が正の複素数√)
f2 (τ ) = 2 η(2τη(τ )[0] pari(wf,1/2*@i+1/3);(1.17550045802164239612+0.13899974799314382921*@i)[1] pari(wf2,1/2*@i+1/3);(1.20443909031006247316+0.14997728710366899256*@i)204. pari(jell,τ [,prec]):: Elliptic j-invariant j(τ ) で τ は虚部が正の複素数
g22
j(τ ) = 1728 g3 −27g
2
2
3
P
P
g2 = 60 (m,n)6=(0,0) (m + nτ )−4 , g3 = 140 (m,n)6=(0,0) (m + nτ )−6[0] pari(jell,1/3+1/2*@i);(6087.61214259402217852112-2773.38047013180067823512*@i)205. pari(zeta,s[,prec]):: Riemann の ζ 関数
P∞ζ(s) = n=1 n−s[0] pari(zeta,2);
1.64493406684822643609
3.3.10 描画函数
206. ifplot(func [,geometry] [,xrange] [,yrange] [,id] [,name]):: 2 変数関数の実数上での零点を表示する
207. conplot(func [,geometry] [,xrange] [,yrange] [,zrange] [,id] [,name]):: 2 変数関数の実数上での等高線を表示する
208. plot(func [,geometry] [,xrange] [,id] [,name]):: 1 変数関数のグラフを表示する
209. polarplo(func [,geometry] [,thetarange] [,id] [,name]):: 極形式 r =func(θ) で与えられた曲線を表示する
210. plotover(func,id,number):: すでに存在しているウィンドウへ描画する• これらは OpenXM サーバとして実現されている. UNIX 上では ‘ox_plot’ が, Windows 上では ‘engine’ がこれらの機能を提供しており, これらは Asir の標準ライブラリディレクトリにある. アクティブな ‘ox_plot’ の id が id として指定された場合, そのサーバが用いられる. id の指定がない場合には, 起動されているサーバのうち, ‘ox_plot’ があればそのサーバが用いられる.
‘ox_plot’ が起動されていない場合には, ox_launch_nox() が自動的に実行されて, ‘ox_plot’が立ち上がり, それが用いられる. 引数の内, func は必須である. その他の引数はオプションである. オプションの形式およびそのデフォルト値 (カッコ内) は次の通り.
geometry ウィンドウのサイズをドット単位で [x,y] で指定する. ([300,300]. )xrange yrange 変数の範囲の指定で, [v,vmin,vmax] で指定する. (いずれの変数も [v,-2,2].) この指定がない場合, func に含まれる変数の内変数順序の上の変数が ‘x’, 下の変数が ‘y’ として扱われる. これを避けるためには xrange, yrange を指定する. また, func が 1 変数の場合, これらの指定は必須となる.
zrange conplot() の場合のみ指定できる. 形式は [v,vmin,vmax [,step ]] で, step が指定された場合には, 等高線の間隔が (vmax-vmin)/step となる. ([z,-2,2,16].)
id 遠隔プロセスの番号, すなわち ox_launch() が返した番号を指定する. (一番身近に作られ,かつアクティブなプロセスに対応する番号.)447

name ウィンドウの名前. (Plot.) 生成されたウィンドウのタイトルは name:n/m となる. これは, プロセス番号 n のプロセスの, m 番のウィンドウを意味する. この番号は, plotover()で用いられる.
• 一つのプロセス上で描画できるウィンドウの数は最大 128 個である.
• plotover() は, 指定したウィンドウ上に, 引数である 2 変数多項式の零点を上書きする.
• 描画終了後のウィンドウ上で, マウスの左ボタンを押しながらのドラッグで範囲を指定しボタンを離すと新たなウィンドウが生成され, 指定した範囲が拡大して表示される. ドラッグは左上から右下へと行う. ドラッグを始めた後キャンセルする場合は, マウスポインタを始点の上か左に持っていってボタンを離せばよい. 新しいウインドウの形は, 指定領域と相似で, 最大辺が, 元のウィンド
ウの最大辺と一致するように定められる. 以下で説明する precise が on の場合, 選択した領域が同一 window 上で書き直される.
• ウィンドウ内で右ボタンを押すと, その点の座標がウィンドウの下部に表示される.
• conplot() で生成したウィンドウにおいて, ウィンドウの右側のマーカを中ボタンでドラッグすると, 対応する等高線の色が変わり, 右上のウィンドウに対応するレベルが表示される.
• UNIX 版ではいくつかのボタンによりいくつかの設定変更, 操作ができる. UNIX 版では次のボタンがある.
quit window を破壊する. 計算を中断する場合, ox_reset() を用いる.
wide (トグル) 現在の表示部分を縦横各 10 倍した領域を表示する. 現在表示されている範囲はこの表示において中央部に長方形で示される. この表示で範囲指定を行うと, その範囲が新しいウィンドウに描画される.
precise (トグル) 選択領域を, 整数演算により, より正確に再描画する. これは, func が有理数係
数の 2 変数多項式の場合にのみ有効である. このモードでは Sturm 列と二分法により, 区間内の零点の個数を正確に求めていくもので, デフォルトの計算法よりも正確な描画が期待できる. ただし, 描画時間は余計にかかる場合が多い. この説明から明らかなように, この機能は有理数係数の多項式の描画に対してのみ有効である（(x2 + y 2 − 1)2 の描画で試してみよ.)formula 対応する式を表示する.
noaxis (トグル) 座標軸を消す.
• ‘ox_plot’ が起動されるマシンによっては, スタックを大量に使用するものもあるため, ‘.cshrc’
でスタックサイズを大きめ (16MB 程度) に指定しておくのが安全である. スタックサイズはlimit stacksize 16m などと指定する.
• X では、ウインドウの各部分について resource により色付けや、ボタンの形を変えることができる．resource の指定の仕方は以下の通り. （デフォルトを示しておく） plot*form*shapeStyle
は、rectangle, oval, ellipse, roundedRectangle が、指定できる．
plot*background:white
plot*form*shapeStyle:rectangle
plot*form*background:white
plot*form*quit*background:white
plot*form*wide*background:white
plot*form*precise*background:white
plot*form*formula*background:white
plot*form*noaxis*background:white
plot*form*xcoord*background:white
plot*form*ycoord*background:white
plot*form*level*background:white
plot*form*xdone*background:white
plot*form*ydone*background:white
211. open canvas(id[,geometry]):: 描画用ウィンドウ (キャンバス) を生成する
448

212. clear canvas(id,index):: キャンバスをクリアする
213. draw obj(id,index,pointorsegment [,color]):: キャンバス上に点または線分を描画する
214. draw string(id,index,[x,y],string [,color]):: キャンバス上に文字列を描画する• これらは OpenXM サーバ ‘ox_plot’ (Windows 上では ‘engine’) により提供される.
• open_canvas() は, 描画用のウィンドウ (キャンバス) を生成する. geometry によりウィンドウのサイズを pixel 単位で [x,y] で指定する. default size は [300,300]. キャンバスの識別子として, 整数値を OpenXM サーバのスタックに push する. この識別子は draw_obj の呼び出しに必要であり, ox_pop_cmo により取り出して保持する必要がある.
• clear_canvas() は, サーバ id id, キャンバス id index で指定されるキャンバスをクリアする.
• draw_obj は, サーバ id id, キャンバス id index で指定されるキャンバスに点または線分を描画する. pointorsegment が [x,y] の場合点の座標, [x,y,u,v] の場合 [x,y], [u,v] を結ぶ線分を表すと見なされる. キャンバスの座標は, 左上隅を原点として横方向に第一座標, 縦方向に第二座標をとる. 値は pixel 単位で指定する. color の指定がある場合, color/65536 mod 256, color/256
mod 256, color mod 256 をそれぞれ Red, Green, Blue の値 (最大 255) とみなす.
• draw_string は, サーバ id id, キャンバス id index で指定されるキャンバスに文字列を描画す
る. 位置は [x,y] により指定する.
[182] Id=ox_launch_nox(0,"ox_plot");0[183] open_canvas(Id);0[184] Ind=ox_pop_cmo(Id);0[185] draw_obj(Id,Ind,[100,100]);
0[186] draw_obj(Id,Ind,[200,200],0xffff);
0[187] draw_obj(Id,Ind,[10,10,50,50],0xff00ff);
0[187] draw_string(Id,Ind,[100,50],"hello",0xffff00);
0[189] clear_canvas(Id,Ind);0
3.3.11 有限体に関する函数
215. setmod ff([p |defpoly2 ]) setmod ff([defpolyp,p]) setmod ff([p,n]):: 有限体の設定, 設定されている有限体の法, 定義多項式の表示
p 素数
defpoly2 GF (2) 上既約な 1 変数多項式
defpolyp GF (p) 上既約な 1 変数多項式
n 拡大次数• 引数が正整数 p の時, GF (p) を基礎体として設定する.
• 引数が多項式 defpoly2 の時, GF (2deg (defpoly2 mod 2)) = GF (2)[t]/(defpoly2(t) mod 2) を基礎体として設定する.

449

• 引数が defpolyp と p の時, GF (pdeg (defpolyp)) を基礎体として設定する.
• 引数が p と n の時, GF (pn ) を基礎体として設定する. pn は 229 未満でなければならない. また,
p が 214 以上のとき, n は 1 でなければならない.
• 無引数の時, 設定されている基礎体が GF (p) の場合 p, GF (2n ) の場合定義多項式を返す. 基
礎体が setmod ff(defpoly,p) で定義された GF (pn ) の場合, [defpoly,p] を返す. 基礎体
が setmod ff(p,n) で定義された GF (pn ) の場合, [p,defpoly,prim elem ] を返す. ここで,defpoly は, n 次拡大の定義多項式, prim elem は, GF (pn ) の乗法群の生成元を意味する.
• GF (2n ) の 定 義 多 項 式 は, GF (2) 上 n 次 既 約 な ら な ん で も 良 い が, 効 率 に 影 響 す る た め,
defpoly mod2() で生成するのがよい.
[0] defpoly_mod2(100);x^100+x^15+1[1] setmod_ff(@@);
x^100+x^15+1[2] setmod_ff();x^100+x^15+1[3] setmod_ff(x^4+x+1,547);[1*x^4+1*x+1,547][4] setmod_ff(2,5);[2,x^5+x^2+1,x]216. field type ff([p |defpoly2 ]):: 設定されている基礎体の種類• 設定されている基礎体の種類を返す.
• 設定なしなら 0, GF (p) なら 1, GF (2n ) なら 2 を返す.
[0] field_type_ff();
0[1] setmod_ff(3);3[2] field_type_ff();
1[3] setmod_ff(x^2+x+1);x^2+x+1[4] field_type_ff();
2
217. field order ff():: 設定されている基礎体の位数• 設定されている基礎体の位数 (元の個数) を返す.
• 設定されている体が GF(q) ならば q を返す.
[0] field_order_ff();
field_order_ff : current_ff is not set
return to toplevel[1] setmod_ff(3);3[2] field_order_ff();

450

3[3] setmod_ff(x^2+x+1);x^2+x+1[4] field_order_ff();
4218. characteristic ff():: 設定されている体の標数
GF (p) の場合 p, GF (2n ) の場合 2 を返す.
[0] characteristic_ff();
characteristic_ff : current_ff is not set
return to toplevel[1] setmod_ff(3);3[2] characteristic_ff();
3[3] setmod_ff(x^2+x+1);x^2+x+1[4] characteristic_ff();
2
219. extdeg ff():: 設定されている基礎体の, 素体に対する拡大次数
GF (p) の場合 1, GF (2n ) の場合 n を返す.
[0] extdeg_ff();
extdeg_ff : current_ff is not set
return to toplevel[1] setmod_ff(3);3[2] extdeg_ff();
1[3] setmod_ff(x^2+x+1);x^2+x+1[4] extdeg_ff();
2
220. simp ff(obj):: 数, あるいは多項式の係数を有限体の元に変換• 数, あるいは多項式の係数を有限体の元に変換する.
• 整数, あるいは整数係数多項式を, 有限体, あるいは有限体係数に変換するために用いる.
• 有限体の元に対し, 法あるいは定義多項式による reduction を行う場合にも用いる.
• 小標数有限体の元に変換する場合, 一旦素体上に射影してから, 拡大体の元に変換される. 拡大体の元に直接変換するには ptosfp() を用いる.
[0] simp_ff((x+1)^10);x^10+10*x^9+45*x^8+120*x^7+210*x^6+252*x^5+210*x^4+120*x^3+45*x^2+10*x+1451

[1] setmod_ff(3);3[2] simp_ff((x+1)^10);
1*x^10+1*x^9+1*x+1[3] ntype(coef(@@,10));6[4] setmod_ff(2,3);[2,x^3+x+1,x][5] simp_ff(1);@_0[6] simp_ff(2);0[7] ptosfp(2);@_1221. random ff():: 有限体の元の乱数生成• 有限体の元を乱数生成する.
• random(), lrandom() と同じ 32bit 乱数発生器を使用している.
[0] random_ff();
random_ff : current_ff is not set
return to toplevel[1] setmod_ff(pari(nextprime,2^40));
1099511627791[2] random_ff();
561856154357[3] random_ff();
45141628299
222. lmptop(obj):: GF (p) 係数多項式の係数を整数に変換
obj
GF (p) 係数多項式• GF (p) 係数多項式の係数を整数に変換する.
• GF (p) の元は, 0 以上 p 未満の整数で表現されている. 多項式の各係数は, その値を整数オブジェ
クト (数識別子 0) としたものに変換される.
[0] setmod_ff(pari(nextprime,2^40));
1099511627791[1] F=simp_ff((x-1)^10);
1*x^10+1099511627781*x^9+45*x^8+1099511627671*x^7+210*x^6+1099511627539*x^5+210*x^4+1099511627671*x^3+45*x^2+1099511627781*x+1[2] setmod_ff(547);
547[3] F=simp_ff((x-1)^10);
1*x^10+537*x^9+45*x^8+427*x^7+210*x^6+295*x^5+210*x^4+427*x^3+45*x^2+537*x+1452

[4] lmptop(F);x^10+537*x^9+45*x^8+427*x^7+210*x^6+295*x^5+210*x^4+427*x^3+45*x^2+537*x+1[5] lmptop(coef(F,1));
537[6] ntype(@@);
0223. ntogf2n(m):: 自然数を GF (2n ) の元に変換
m
非負整数• 自然数 m の 2 進表現 m = m0 + m1 2 + · · · + mk 2k に対し, GF (2n ) = GF (2)[t]/(g(t)) の元
m0 + m1 t + · · · + mk tk mod g(t) を返す.
• 定義多項式による剰余は自動的には計算されないため, simp ff() を適用する必要がある.
[0] setmod_ff(x^30+x+1);
x^30+x+1[1] N=ntogf2n(2^100);(@^100)[2] simp_ff(N);(@^13+@^12+@^11+@^10)224. gf2nton(m):: GF (2n ) の元を自然数に変換m
GF (2n ) の元
• gf2nton の逆変換である.
[1] setmod_ff(x^30+x+1);
x^30+x+1[2] N=gf2nton(2^100);(@^100)[3] simp_ff(N);(@^13+@^12+@^11+@^10)[4] gf2nton(N);1267650600228229401496703205376[5] gf2nton(simp_ff(N));
15360
225. ptogf2n(poly):: 一変数多項式を GF (2n ) の元に変換
一変数多項式poly• poly の表す GF (2n ) の元を生成する. 係数は, 2 で割った余りに変換される. poly の変数に @ を代入した結果と等しい.
[0] setmod_ff(x^30+x+1);
x^30+x+1[1] ptogf2n(x^100);(@^100)226. gf2ntop(m,[v])453:: GF (2n ) の元を多項式に変換
m GF (2n ) の元
v 不定元
• m を表す多項式を, 整数係数の多項式オブジェクトとして返す.
• v の指定がない場合, 直前の ptogf2n() 呼び出しにおける引数の変数 (デフォルトは x), 指定がある場合には指定された不定元を変数とする多項式を返す.
[0] setmod_ff(x^30+x+1);
x^30+x+1[1] N=simp_ff(gf2ntop(2^100));(@^13+@^12+@^11+@^10)[2] gf2ntop(N);x^13+x^12+x^11+x^10[3] gf2ntop(N,t);t^13+t^12+t^11+t^10227. ptosfp(p):: 小標数有限体への変換
228. sfptop(p):: 小標数有限体からの変換p多項式• ptosfp() は, 多項式の係数を, 現在設定されている小標数有限体 GF (pn ) の元に直接変換する.
係数が既に有限体の元の場合は変化しない. 正整数の場合, まず位数で剰余を計算したあと, 標数
p により p 進展開し, p を x に置き換えた多項式を, 原始元表現に変換する. 例えば, GF (35 ) はGF (3)[x]/(x5 + 2x + 1) として表現され, その各元は原始元 x に関するべき指数 k により @ k として表示される. このとき, 例えば 23 = 2 · 32 + 3 + 2 は, 2x2 + x + 2 と表現され, これは結局 x17と法 x5 + 2x + 1 で等しいので, @ 17 と変換される.
• sfptop() は ptosfp() の逆変換である.
[0] setmod_ff(3,5);[3,x^5+2*x+1,x][1] A = ptosfp(23);@_17[2] 9*2+3+2;
23[3] x^17-(2*x^2+x+2);
x^17-2*x^2-x-2[4] sremm(@,x^5+2*x+1,3);
0[5] sfptop(A);23229. defpoly mod2(d):: GF (2) 上既約な d 次の一変数多項式の生成d
正整数• fff で定義されている.
• 与えられた次数 d に対し, GF (2) 上 d 次の既約多項式を返す.
• もし 既約 3 項式が存在すれば, 第 2 項の次数がもっとも小さい 3 項式, もし既約 3 項式が存在しなければ, 既約 5 項式の中で, 第 2 項の次数がもっとも小さく, その中で第 3 項の次数がもっとも454

小さく, その中で第 4 項の次数がもっとも小さいものを返す.
230. sffctr(poly):: 多項式の小標数有限体上での既約分解
poly有限体上の多項式• 多項式を, 現在設定されている小標数有限体上で既約分解する.
• 結果は, [[f1 ,m1 ],[f2 ,m2 ],...] なるリストである. ここで, fi は monic な既約因子, mi はその重複度である.
[0] setmod_ff(2,10);[2,x^10+x^3+1,x][1] sffctr((z*y^3+z*y)*x^3+(y^5+y^3+z*y^2+z)*x^2+z^11*y*x+z^10*y^3+z^11);[[@_0,1],[@_0*z*y*x+@_0*y^3+@_0*z,1],[(@_0*y+@_0)*x+@_0*z^5,2]]231. fctr ff(poly):: 1 変数多項式の有限体上での既約分解
poly有限体上の 1 変数多項式• fff で定義されている.
• 一変数多項式を, 現在設定されている有限体上で既約分解する.
• 結果は, [[f1 ,m1 ],[f2 ,m2 ],...] なるリストである. ここで, fi は monic な既約因子, mi はその重複度である.
• poly の主係数は捨てられる.

[0] setmod_ff(2^64-95);
18446744073709551521[1] fctr_ff(x^5+x+1);[[1*x+14123390394564558010,1],[1*x+6782485570826905238,1],[1*x+15987612182027639793,1],[1*x^2+1*x+1,1]]
232. irredcheck ff(poly):: 1 変数多項式の有限体上での既約判定• 有限体上の 1 変数多項式• fff で定義されている.
• 有限体上の 1 変数多項式の既約判定を行い, 既約の場合 1, それ以外は 0 を返す.
[1] setmod_ff(2^64-95);
18446744073709551521[2] F=x^10+random_ff();x^10+14687973587364016969[3] irredcheck_ff(F);1233. randpoly ff(d,v):: 有限体上の乱数係数 1 変数多項式の生成
d
正整数
v
不定元
• fff で定義されている.
• d 次未満, 変数が v, 係数が現在設定されている有限体に属する 1 変数多項式を生成する. 係数はgotor:randomffrandom ff() により生成される.
[0] setmod_ff(2^64-95);
18446744073709551521[1] F=x^10+random_ff();455

[2] randpoly_ff(3,x);
17135261454578964298*x^2+4766826699653615429*x+18317369440429479651[3] randpoly_ff(3,x);7565988813172050604*x^2+7430075767279665339*x+4699662986224873544[4] randpoly_ff(3,x);10247781277095450395*x^2+10243690944992524936*x+4063829049268845492
234. ecm add ff(p1 ,p2 ,ec):: 楕円曲線上の点の加算
235. ecm sub ff(p1 ,p2 ,ec):: 楕円曲線上の点の減算
236. ecm chsgn ff(p1 ):: 楕円曲線上の点の逆元
p1 p2 長さ 3 のベクトルまたは 0ec 長さ 2 のベクトル• 現在設定されている有限体上で, ec で定義される楕円曲線上の点 p1 , p2 の和 p1 + p2 , 差 p1 − p2 ,逆元 −p1 を返す.
• ec は, 設定されている有限体が奇標数素体の場合, y 2 = x3 + ec[0]x + ec[1], 標数 2 の場合
y 2 + xy = x3 + ec[0]x2 + ec[1] を表す.
• 引数, 結果ともに, 無限遠点は 0 で表される.
• p1 , p2 が長さ 3 のベクトルの場合, 斉次座標による曲線上の点を表す. この場合, 第 3 座標は 0 であってはいけない.
• 結果が長さ 3 のベクトルの場合, 第 3 座標は 0 でないが, 1 とは限らない. アフィン座標による結果を得るためには, 第 1 座標, 第 2 座標を第 3 座標で割る必要がある.
• p1 , p2 が楕円曲線上の点かどうかのチェックはしない.
[0] setmod_ff(1125899906842679)$[1] EC=newvect(2,[ptolmp(1),ptolmp(1)])$[2] Pt1=newvect(3,[1,-412127497938252,1])$[3] Pt2=newvect(3,[6,-252647084363045,1])$[4] Pt3=ecm_add_ff(Pt1,Pt2,EC);[ 560137044461222 184453736165476 125 ][5] F=y^2-(x^3+EC[0]*x+EC[1])$[6] subst(F,x,Pt3[0]/Pt3[2],y,Pt3[1]/Pt3[2]);0[7] ecm_add_ff(Pt3,ecm_chsgn_ff(Pt3),EC);
0[8] D=ecm_sub_ff(Pt3,Pt2,EC);[ 886545905133065 119584559149586 886545905133065 ][9] D[0]/D[2]==Pt1[0]/Pt1[2];1[10] D[1]/D[2]==Pt1[1]/Pt1[2];1
3.3.12 代数的数に関する函数
237. newalg(defpoly):: root を生成456

• defpoly を定義多項式とする代数的数 (root) を生成する.
• defpoly に対する制限に関しては, See section 代数的数の表現.
[0] A0=newalg(x^2-2);(#0)
238. defpoly(alg):: root の定義多項式を返す• root alg の定義多項式を返す.
• root を #n とすれば, 定義多項式の主変数は t#n となる.
[1] defpoly(A0);t#0^2-2
239. alg(i):: インデックスに対応する root を返す• root #i を返す.
• #i はユーザが直接入力できないため, alg(i) と いう形で入力する.
[2] x+#0;
syntax error
0[3] alg(0);(#0)
240. algv(i):: alg(i) に対応する不定元を返す• 多項式 t#i を返す.
• t#i はユーザが直接入力できないため, algv(i) と いう形で入力する.
[4] var(defpoly(A0));t#0[5] t#0;
syntax error
0[6] algv(0);t#0241. simpalg(rat):: 有理式に含まれる代数的数を簡単化• sp で定義されている.
• 数, 多項式, 有理式に含まれる代数的数を, 含まれる root の定義多項式により簡単化する.
• 数の場合, 分母があれば有理化され, 結果は root の多項式となる.
• 多項式の場合, 各係数が簡単化される.
• 有理式の場合, 分母分子が多項式として簡単化される.
[8] simpalg((1+A0)/(1-A0));
simpalg undefined
return to toplevel[9] load("sp")$[47] simpalg((1+A0)/(1-A0));457

(-2*#0-3)[49] simpalg((2-A0)/(2+A0)*x^2-1/(3+A0));(-2*#0+3)*x^2+(1/7*#0-3/7)[50] simpalg((x+1/(A0-1))/(x-1/(A0+1)));(x+(#0+1))/(x+(-#0+1))
242. algptorat(poly):: 多項式に含まれる root を, 対応する不定元に置き換える• sp で定義されている.
• 多項式に含まれる root #n を全て t#n に 置き換える.
[49] algptorat((-2*alg(0)+3)*x^2+(1/7*alg(0)-3/7));(-2*t#0+3)*x^2+1/7*t#0-3/7
243. rattoalgp(poly,alglist):: 多項式に含まれる root に対応する不定元を root に置き換える• sp で定義されている.
• 第 2 引数は root のリストである. rattoalgp() は, この root に対応する不定元を, それぞれroot に置き換える.
[51] rattoalgp((-2*algv(0)+3)*x^2+(1/7*algv(0)-3/7),[alg(0)]);(-2*#0+3)*x^2+(1/7*#0-3/7)
244. cr gcda(poly1,poly2):: 代数体上の 1 変数多項式の GCD• sp で定義されている.
• 2 つの 1 変数多項式の GCD を求める.
[76] X=x^6+3*x^5+6*x^4+x^3-3*x^2+12*x+16$[77] Y=x^6+6*x^5+24*x^4+8*x^3-48*x^2+384*x+1024$[78] A=newalg(X);(#0)[79] cr_gcda(X,subst(Y,x,x+A));
x+(-#0)245. sp norm(alg,var,poly,alglist):: 代数体上でのノルムの計算• sp で定義されている.
• poly の, alg に関するノルムをとる. すなわち, K = Q(alglist / alg) とするとき, poly に現れる
alg を, alg の K 上の共役に置き換えたもの全ての積を返す.
• 結果は K 上の多項式となる.
• 実際には入力により場合わけが行われ, 終結式の直接計算や中国剰余定理に より計算されるが, 最適な選択が行われているとは限らない. 大域変数 SE_RES を 1 に設定することにより, 常に終結式
により計算 させることができる.
[0] load("sp")$[39] A0=newalg(x^2+1)$[40] A1=newalg(x^2+A0)$[41] sp_norm(A1,x,x^3+A0*x+A1,[A1,A0]);x^6+(2*#0)*x^4+(#0^2)*x^2+(#0)[42] sp_norm(A0,x,@@,[A0]);458

x^12+2*x^8+5*x^4+1246. asq(poly):: 代数体上の 1 変数多項式の無平方分解
247. af(poly,alglist)
248. af noalg(poly,defpolylist):: 代数体上の 1 変数多項式の因数分解• いずれも sp で定義されている.
• root を含まない場合は整数上の函数が呼び出され高速であるが, root を含む場合には, cr_gcda()が起動されるためしばしば時間がかかる.
• af() は, 基礎体の指定, すなわち第 2 引数の, root のリストの指定が必要である.
• alglist で指定される root は, 後で定義されたものほど前の方に来なければならない.
• af(F,AL) に お い て, AL は 代 数 的 数 の リ ス ト で あ り, 有 理 数 体 の 代 数 拡 大 を 表 す.
AL=[An ,...,A1 ] と 書 く と き, 各 Ak は, そ れ よ り 右 に あ る 代 数 的 数 を 係 数 と し た, モ
ニックな定義多項式で定義されていなければ ならない.
• defpolylist は root を表す不定元と定義多項式のペアのリスト[1] A1 = newalg(x^2+1);[2] A2 = newalg(x^2+A1);[3] A3 = newalg(x^2+A2*x+A1);[4] af(x^2+A2*x+A1,[A2,A1]);[[x^2+(#1)*x+(#0),1]]
af_noalg() では, poly に含まれる代数的数 ai を不定元 vi で置き換える. defpolylist() は,[[vn ,dn (vn ,...,v1 )],...,[v1 ,d1 (v1 )]] なるリストである. ここで di (vi ,...,v1 ) は ai の定義多項式において 代数的数を全て vj に置き換えたものである.
[1] af_noalg(x^2+a2*x+a1,[[a2,a2^2+a1],[a1,a1^2+1]]);[[x^2+a2*x+a1,1]]• 結果は, 通常の無平方分解, 因数分解と同様 [因子, 重複度] のリストである.
• af_noalg() の場合, 因子 に現れる代数的数は, defpolylist に従って不定元に置き換えられる.
• 重複度を込めた因子の全ての積は, poly と定数倍の違いがあり得る.
[98] A = newalg(t^2-2);(#0)[99] asq(-x^4+6*x^3+(2*alg(0)-9)*x^2+(-6*alg(0))*x-2);[[-x^2+3*x+(#0),2]][100] af(-x^2+3*x+alg(0),[alg(0)]);[[x+(#0-1),1],[-x+(#0+2),1]][101] af_noalg(-x^2+3*x+a,[[a,x^2-2]]);[[x+a-1,1],[-x+a+2,1]]
249. sp(poly)250. sp noalg (poly):: 最小分解体を求める• sp() で定義されている.
• 有理数係数の 1 変数多項式 poly の最小分解体, およびその体上での poly の 1 次因子への分解を求める.
• 結果は, poly の因子のリストと, 最小分解体の, 逐次拡大による表現 からなるリストである.
sp_noalg() では, 全ての代数的数が, 対応する 不定元 (即ち #i に対する t#i) に置き換えられ459

る. これに より, sp_noalg() の出力は, 整数係数多変数多項式のリストとなる.
• 最小分解体は, [root,algptorat(defpoly(root))] のリストとして 表現されている. すなわち,
求める最小分解体は, 有理数体に, この root を全て添加した体として得られる. 添加は, 右の方のroot から順に 行われる.
• sp() は, 内部でノルムの計算のために sp_norm() をしばしば起動する. ノルムの計算は, 状況に応じてさまざまな方法で行われるが, そこで用いられる方法が最善とは限らず, 単純な終結式の計算の方が高速である場合もある. 大域変数 USE_RES を 1 に設定することにより, 常に終結式により計算 させることができる.

[101] L=sp(x^9-54);[[x+(-#2),-54*x+(#1^6*#2^4),54*x+(#1^6*#2^4+54*#2),
54*x+(-#1^8*#2^2),-54*x+(#1^5*#2^5),54*x+(#1^5*#2^5+#1^8*#2^2),-54*x+(-#1^7*#2^3-54*#1),54*x+(-#1^7*#2^3),x+(-#1)],[[(#2),t#2^6+t#1^3*t#2^3+t#1^6],[(#1),t#1^9-54]]][102] for(I=0,M=1;I<9;I++)M*=L[0][I];[111] M=simpalg(M);-1338925209984*x^9+72301961339136[112] ptozp(M);-x^9+54251. set field(rootlist):: 代数体を基礎体として設定• root のリスト rootlist で生成される代数体を基礎体として設定する.
• root は内部的に順序づけられているので, rootlist は集合として指定すればよい. (順序は気にしなくてよい.)[0] A=newalg(x^2+1);(#0)[1] B=newalg(x^3+A);(#1)[2] C=newalg(x^4+B);(#1)[3] set_field([C,B,A]);
0252. algtodalg(alg):: 代数的数 alg を DAlg に変換
253. dalgtoalg(dalg):: DAlg dalg を代数的数に変換
254. dptodalg(dp):: 分散多項式 dp を DAlg に変換
255. dalgtodp(dalg):: DAlg dalg を分散多項式に変換する.
• root を含む代数的数, DAlg および分散多項式間の変換を行う.
• DAlg が属すべき代数体は, set_field() により あらかじめ設定しておく必要がある.
• dalgtodp() は, 分子である整数係数分散多項式と, 分母である整数を要素に持つリストを返す.
algtodalg(), dptodalg() は簡単化された結果を返す.
•

460

[0] A=newalg(x^2+1);(#0)[1] B=newalg(x^3+A*x+A);(#1)[2] set_field([B,A]);
0[3] C=algtodalg((A+B)^10);((408)*<<2,1>>+(103)*<<2,0>>+(-36)*<<1,1>>+(-446)*<<1,0>>+(-332)*<<0,1>>+(-218)*<<0,0>>)[4] dalgtoalg(C);((408*#0+103)*#1^2+(-36*#0-446)*#1-332*#0-218)[5] D=dptodalg(<<10,10>>/10+2*<<5,5>>+1/3*<<0,0>>);((-9)*<<2,1>>+(57)*<<2,0>>+(-63)*<<1,1>>+(-12)*<<1,0>>+(-60)*<<0,1>>+(1)*<<0,0>>)/30[6] dalgtodp(D);[(-9)*<<2,1>>+(57)*<<2,0>>+(-63)*<<1,1>>+(-12)*<<1,0>>+(-60)*<<0,1>>+(1)*<<0,0>>,30]
3.3.13 グレブナー基底に関する函数
256. gr(plist,vlist,order)
257. hgr(plist,vlist,order)
258. gr mod(plist,vlist,order,p)259. dgr(plist,vlist,order,procs):: グレブナ基底の計算• 標準ライブラリの gr で定義されている.
• いずれも, 多項式リスト plist の, 変数順序 vlist, 項順序型 order （数，リスト，または行列）に関するグレブナ基底を求める. gr(), hgr() は 有理数係数, gr mod() は GF (p) 係数として計算する（p は 227 未満の素数）.
• vlist は不定元のリスト. vlist に現れない不定元は, 係数体に属すると見なされる. gr(), tracelifting (モジュラ演算を用いた高速化) および sugar strategy による計算, hgr() は trace-lifting
および 斉次化による 矯正された sugar strategy による計算を行う.
• dgr() は, gr(), hgr() を 子プロセスリスト procs の 2 つのプロセスにより同時に計算させ, 先に結果を返した方の結果を返す. 結果は同一であるが, どちらの方法が 高速か一般には不明のため,実際の経過時間を短縮するのに有効である. dgr() で表示される時間は, この函数が実行されているプロセスでの CPU 時間であり, この函数の場合はほとんど通信のための時間である.
• 多項式リスト plist の要素が分散表現多項式の場合は 結果も分散表現多項式のリストである. この場合, 引数の分散多項式は与えられた順序に従い dp sort() でソートされてから計算される. 多項式リストの要素が分散表現多項式の場合も 変数の数分の不定元のリストを vlist 引数として与えな
いといけない (ダミー).
[0] load("gr")$[64] load("cyclic")$[74] G=gr(cyclic(5),[c0,c1,c2,c3,c4],2);[c4^15+122*c4^10-122*c4^5-1,...][75] GM=gr_mod(cyclic(5),[c0,c1,c2,c3,c4],2,31991)$
24628*c4^15+29453*c4^10+2538*c4^5+7363

461

[76] (G[0]*24628-GM[0])%31991;
0260. lex hensel(plist,vlist1,order,vlist2,homo)261. lex tl(plist,vlist1,order,vlist2,homo):: 基底変換による辞書式順序グレブナ基底の計算
262. tolex(plist,vlist1,order,vlist2)
263. tolex d(plist,vlist1,order,vlist2,procs)
264. tolex tl(plist,vlist1,order,vlist2,homo):: グレブナ基底を入力とする, 基底変換による辞書式順序グレブナ基底の計算• 標準ライブラリの gr で定義されている.
• lex hensel(), lex tl() は, 多項式リスト plist の, 変数順序 vlist1, 項順序型 order に関するグ
レブナ基底を求め, それを, 変数順序 vlist2 の辞書式順序グレブナ基底に変換する.
• tolex(), tolex tl() は, 変数順序 vlist1, 項順序型 order に関するグレブナ基底であ 多項式リスト plist を変数順序 vlist2 の辞書式順序グレブナ基底に変換する. tolex d() は, tolex() における, 各基底の計算を, 子プロセスリスト procs の各プロセスに分散計算させる.
• lex hensel(), lex tl() においては, 辞書式順序グレブナ基底の計算は次のように行われる.
(citeNoro-Yokoyama 参照.)（a）vlist1, order に関するグレブナ基底 G0 を計算する. (lex hensel() のみ. )（b）G0 の各元の vlist2 に関する辞書式順序における頭係数を割らないような素数 p を選び,
GF (p) 上での辞書式順序グレブナ基底 Gp を計算する.
（c）Gp に現れるすべての項の, G0 に関する正規形 NF を計算する.
（d）Gp の各元 f につき, f の係数を未定係数で, f の各項を対応する NF の元で置き換え, 各項の係数を 0 と置いた, 未定係数に関する線形方程式系 Lf を作る.
（e）Lf が, 法 p で一意解を持つことを用いて Lf の解を 法 p の解から Hensel 構成により求める.
（f）すべての Gp の元につき線形方程式が解けたらその解全体が求める辞書式順序でのグレブナ基底. もしどれかの線形方程式の求解に失敗したら, p をとり直してやり直す.
• lex tl(), tolex tl() においては, 辞書式順序グレブナ基底の計算は次のように行われる.
（a）vlist1, order に関するグレブナ基底 G0 を計算する. (lex_hensel() のみ. )（b）G0 が 0 次元システムでないとき, G0 を入力として, G0 の各元の vlist2 に関する辞書式順序における頭係数を割らない ような素数 p を選び, p を用いた trace-lifting により辞書式 順序のグレブナ基底候補を求め, もし求まったならチェックなしにそれが求める グレブナ基底となる. もし失敗したら, p をとり直してやり直す.
（c）G0 が 0 次元システムのとき, G0 を入力として, まず, vlist2 の最後の変数以外を消去する
消去順序によりグレブナ基底 G1 を計算し, それから辞書式順序のグレブナ基底を計算する.
その際, 各ステップでは, 入力の各元の, 求める順序における 頭係数を割らない素数を用いたtrace-lifting でグレブナ基底候補を求め, もし求まったらチェックなしにそれがその順序でのグレブナ基底となる.
• 有理式係数の計算は, lex tl(), tolex tl() のみ受け付ける.
• homo が 0 でない場合, 内部で起動される Buchberger アルゴリズムに おいて, 斉次化が行われる.
• tolex d() で表示される時間は, この函数が実行されているプロセスに おいて行われた計算に対応していて, 子プロセスにおける時間は含まれない.
[78] K=katsura(5)$30msec + gc : 20msec[79] V=[u5,u4,u3,u2,u1,u0]$0msec[80] G0=hgr(K,V,2)$
91.558sec + gc : 15.583sec

462

[81] G1=lex_hensel(K,V,0,V,0)$49.049sec + gc : 9.961sec[82] G2=lex_tl(K,V,0,V,1)$
31.186sec + gc : 3.500sec[83] gb_comp(G0,G1);
1
10msec[84] gb_comp(G0,G2);
1265. gr minipoly(plist,vlist,order,poly,v,homo):: 多項式の, イデアルを法とした最小多項式の計算
266. minipoly(plist,vlist,order,poly,v):: グレブナ基底を入力とする, 多項式の最小多項式の計算• gr minipoly() はグレブナ基底の計算から行い, minipoly() は入力をグレブナ基底とみなす.
• イデアル I が体 K 上の多項式環 K[X] の 0 次元イデアルの時, K[v] の元 f (v) に f (p) mod Iを対応させる 環準同型の核は 0 でない多項式により生成される. この生成元を p の, 法 I での最小多項式と呼ぶ. gr minipoly(), minipoly() は, 多項式 p の最小多項式 を求め, v を変数とする多項式として返す.
• 最小多項式は, グレブナ基底の 1 つの元として計算することもできるが, 最小多項式のみを求めたい場合, minipoly(), gr minipoly() は グレブナ基底を用いる方法に比べて効率がよい.
gr minipoly() に指定する項順序としては, 通常全次数逆辞書式順序を 用いる.
[117] G=tolex(G0,V,0,V)$
43.818sec + gc : 11.202sec[118] GSL=tolex_gsl(G0,V,0,V)$
17.123sec + gc : 2.590sec[119] MP=minipoly(G0,V,0,u0,z)$4.370sec + gc : 780msec
267. tolexm(plist,vlist1,order,vlist2,mod):: 法 mod での基底変換によるグレブナ基底計算• FGLM 法による基底変換により vlist2, 辞書式順序によるグレブナ基底を計算する.
• 入力 plis は, 変数順序 vlist1, 項順序型 order, 法 mod におけるグレブナ基底[197] tolexm(G0,V,0,V,31991);[8271*u0^31+10435*u0^30+816*u0^29+26809*u0^28+...,...]
268. minipolym(plist,vlist1,order,poly,v,mod):: 法 mod でのグレブナ基底による多項式の最小多項式の計算• minipoly() に対応する計算を法 mod で行う.
• 入力 plis は, 変数順序 vlist1, 項順序型 order, 法 mod におけるグレブナ基底[198] minipolym(G0,V,0,u0,z,31991);z^32+11405*z^31+20868*z^30+21602*z^29+...
269. dp gr main(plist,vlist,homo,modular,order)
270. dp gr mod main(plist,vlist,homo,modular,order)
271. dp gr f main(plist,vlist,homo,order)
272. dp weyl gr main(plist,vlist,homo,modular,order)
273. dp weyl gr mod main(plist,vlist,homo,modular,order)463

274. dp weyl gr f main(plist,vlist,homo,order):: グレブナ基底の計算 (組み込み函数)• これらの函数は, グレブナ基底計算の基本的組み込み函数であり, gr(), hgr(), gr mod() などは
すべてこれらの函数を呼び出して計算を行っている. 関数名に weyl が入っているものは, Weyl 代
数上の計算のための関数である.
• dp gr f main(), dp weyl f main() は, 種々の有限体上のグレブナ基底を計算する場合に用いる.
入力は, あらかじめ, simp ff() などで, 考える有限体上に射影されている必要がある.
• フラグ homo が 0 でない時, 入力を斉次化してから Buchberger アルゴリズム を実行する.
• dp gr mod main() に対しては, modular は, GF (modular) 上での計算を意味する. dp gr main()に対しては, modular は次のような意味を持つ.
（a）modular が 1 の時, trace-lifting による計算を行う. 素数は lprime(0) から順に成功するまで lprime() を呼び出して生成する.
（b）modular が 2 以上の自然数の時, その値を素数とみなして trace-lifting を行う. その素数で失敗した場合, 0 を返す.
（c）modular が負の場合, −modular に対して上述の規則が適用されるが, trace-lifting の最終段
階のグレブナ基底チェックとイデアルメンバシップチェックが省略される.
• gr(P,V,O) は dp gr main(P,V,0,1,O), hgr(P,V,O) は dp gr main(P,V,1,1,O), gr mod(P,V,O,M)
は dp gr mod main(P,V,0,M,O) をそれぞれ実行する.
• homo, modular の他に, dp gr flags() で設定されるさまざまなフラグにより計算が制御される.
275. dp f4 main(plist,vlist,order)
276. dp f4 mod main(plist,vlist,order)
277. dp weyl f4 main(plist,vlist,order)
278. dp weyl f4 mod main(plist,vlist,order):: F4 アルゴリズムによるグレブナ基底の計算 (組み込み函数)• F4 アルゴリズムによりグレブナ基底の計算を行う.
• F4 アルゴリズムは, J.C. Faugere により提唱された新世代グレブナ基底 算法であり, 本実装は, 中
国剰余定理による線形方程式求解を用いた 試験的な実装である.
• 斉次化の引数がないことを除けば, 引数および動作はそれぞれ dp gr main(), dp gr mod main(),dp weyl gr main(), dp weyl gr mod main() と同様である.
279. nd gr(plist,vlist,p,order)
280. nd gr trace(plist,vlist,homo,p,order)
281. nd f4(plist,vlist,modular,order)
282. nd f4 trace(plist,vlist,homo,p,order)
283. nd weyl gr(plist,vlist,p,order)
284. nd weyl gr trace(plist,vlist,homo,p,order):: グレブナ基底の計算 (組み込み函数)• これらの函数は, グレブナ基底計算組み込み関数の新実装である.
• nd gr() は, p が 0 のとき有理数体上の Buchberger アルゴリズムを実行する. p が 2 以上の自然数のとき, GF (p) 上の Buchberger アルゴリズムを実行する.
• nd gr trace および nd f4 trace() は有理数体上で trace アルゴリズムを実行する.
p が 0 または 1 のとき, 自動的に選ばれた素数を用いて, 成功する まで trace アルゴリズムを実行する. p が 2 以上のとき, trace は GF (p) 上で計算される. trace アルゴリズム が失敗した場合 0が返される.
p が負の場合, グレブナ基底チェックは 行わない. この場合, p が -1 ならば自動的に選ばれた素数
が, それ以外は指定された素数を用いてグレブナ基底候補の計算が行われる. nd f4 trace() は,各全次数について, ある有限体上で F4 アルゴリズムで行った結果をもとに, その有限体上で 0 でない基底を与える S-多項式のみを 用いて行列生成を行い, その全次数における基底を生成する方法である. 得られる 多項式集合はやはりグレブナ基底候補であり, nd gr trace() と同様のチェックが行われる.

464

• nd f4() は modular が 0 のとき有理数体上の, modular がマシンサイズ素数のとき有限体上のF4 アルゴリズムを実行する.
• plist が多項式リストの場合, plist で生成されるイデアルのグレブナー基底が 計算される. plist が多項式リストのリストの場合, 各要素は多項式環上の自由加群の元と見なされ, これらが生成する部分加群のグレブナー基底が計算される. 後者の場合, 項順序は加群に対する項順序を 指定する必要がある. これは [s,ord] の形で指定する. s が 0 ならば TOP (Term Over Position), 1 ならば
POT (Position Over Term) を意味し, ord は多項式環の単項式に対する項順序である.
• nd weyl gr(), nd weyl gr trace() は Weyl 代数用である.
• f4 系関数以外はすべて有理関数係数の計算が可能である.
• 一般に dp gr main(), dp gr mod main() より高速であるが, 特に有限体上の場合顕著である.
[38] load[49] C=cyclic(7)$[50] V=vars(C)$[51] cputime(1)$[52] dp_gr_mod_main(C,V,0,31991,0)$26.06sec + gc : 0.313sec(26.4sec)[53] nd_gr(C,V,31991,0)$
ndv_alloc=1477188
5.737sec + gc : 0.1837sec(5.921sec)[54] dp_f4_mod_main(C,V,31991,0)$3.51sec + gc : 0.7109sec(4.221sec)[55] nd_f4(C,V,31991,0)$
1.906sec + gc : 0.126sec(2.032sec)
285. dp gr flags([list])
286. dp gr print([i]):: 計算および表示用パラメタの設定, 参照• dp gr main(), dp gr mod main(), dp gr f main() 実行時におけるさまざまなパラメタを設定,参照する.
• 引数がない場合, 現在の設定が返される.
• 引数は, ["Print",1,"NoSugar",1,...] なる形のリストで, 左から順に設定される. パラメタ名
は文字列で与える必要がある.
• dp gr print() は, 特にパラメタ Print, PrintShort の値を直接設定, 参照できる. 設定される
値は次の通りである。

i = 0 Print=0, PrintShort=0
i = 1 Print=1, PrintShort=0
i = 2 Print=0, PrintShort=1
これは, dp gr main() などをサブルーチンとして用いるユーザ函数において, そのサブルーチンが中間情報の表示を行う際に, 迅速にフラグを見ることができるように用意されている.
287. dp ord([order]):: 変数順序型の設定, 参照• 引数がある時, 変数順序型を order に設定する. 引数がない時, 現在設定されている変数順序型を返す.
• 分散表現多項式に関する函数, 演算は引数として変数順序型をとるものととらないもの があり, とらないものに関しては, その時点で設定されている値を用いて計算が行われる.
• gr() など, 引数として変数順序型をとるものは, 内部で dp ord() を呼び出し, 変数順序型を設定
する. この設定は, 計算終了後も生き残る.
• 分散表現多項式の四則演算も, 設定されている値を用いて計算される. 従って, その多項式が生成さ465

れた時点における変数順序型が, 四則演算時に正しく設定 されていなければならない. また, 演算対象となる多項式は, 同一の変数順序 型に基づいて生成されたものでなければならない.
• トップレベル函数以外の函数を直接呼び出す場合には, この函数により変数順序型を正しく設定しなければならない.

[19] dp_ord(0)$[20] <<1,2,3>>+<<3,1,1>>;(1)*<<1,2,3>>+(1)*<<3,1,1>>[21] dp_ord(2)$[22] <<1,2,3>>+<<3,1,1>>;(1)*<<3,1,1>>+(1)*<<1,2,3>>
288. dp set weight([weight]):: sugar weight の設定, 参照
289. dp set top weight([weight]):: top weight の設定, 参照
290. dp weyl set weight([weight]):: weyl weight の設定, 参照• dp set weight() は sugar weight を weight に設定する. 引数がない時, 現在設定されている
sugar weight を返す. sugar weight は正整数を成分とするベクトルで, 各変数の重みを表す. 次数つき順序において, 単項式の次数を計算する際に用いられる. 斉次化変数用に, 末尾に 1 を付け加えておくと安全である.
• dp set top weight() は top weight を weight に設定する. 引数がない時, 現在設定されている
top weight を返す. top weight が設定されているとき, まず top weight による単項式比較を先に行う. tie breaker として現在設定されている 項順序が用いられるが, この比較には top weight は用いられない.
• dp weyl set weight() は weyl weight を weight に設定する. 引数がない時, 現在設定されている weyl weight を返す. weyl weight w を設定すると, 項順序型 11 での計算において, (−w, w) を
top weight, tie breaker を graded reverse lex とした項順序が設定される.
291. dp ptod(poly,vlist):: 多項式を分散表現多項式に変換する.
変数順序 vlist および現在の変数順序型に従って分散表現多項式に変換する. vlist に含まれない不定元
は, 係数体に属するとして変換される.
[50] dp\ord(0);1[51] dp_ptod((x+y+z)^2,[x,y,z]);(1)*<<2,0,0>>+(2)*<<1,1,0>>+(1)*<<0,2,0>>+(2)*<<1,0,1>>+(2)*<<0,1,1>>+(1)*<<0,0,2>>[52] dp_ptod((x+y+z)^2,[x,y]);(1)*<<2,0>>+(2)*<<1,1>>+(1)*<<0,2>>+(2*z)*<<1,0>>+(2*z)*<<0,1>>+(z^2)*<<0,0>>292. dp dtop(dpoly,vlist):: 分散表現多項式を多項式に変換する.
分散表現多項式を, 与えられた不定元リストを用いて多項式に変換する. 不定元リストは, 長さ分散表現
多項式の変数の個数と一致していれば何でもよい.
[53] T=dp_ptod((x+y+z)^2,[x,y]);(1)*<<2,0>>+(2)*<<1,1>>+(1)*<<0,2>>+(2*z)*<<1,0>>+(2*z)*<<0,1>>466

+(z^2)*<<0,0>>[54] P=dp_dtop(T,[a,b]);z^2+(2*a+2*b)*z+a^2+2*b*a+b^2293. dp mod(p,mod,subst):: 有理数係数分散表現多項式の有限体係数への変換
294. dp rat(p):: 有限体係数分散表現多項式の有理数係数への変換• dp nf mod(), dp true nf mod() は, 入力として有限体係数の分散表現多項式を必要とする. このような場合, dp mod() により 有理数係数分散表現多項式を変換して用いることができる. また,得られた 結果は, 有限体係数多項式とは演算できるが, 有理数係数多項式とは演算できないため,
dp rat() により変換する必要がある.
• 有限体係数の演算においては, あらかじめ setmode ff() により有限体の元の個数を指定しておく必要がある.
• subst は, 係数が有理式の場合, その有理式の変数にあらかじめ数を代入 した後有限体係数に変換するという操作を行う際の, 代入値を指定するもので, [[var,value],...] の形のリストである.
295. dp homo(dpoly):: 分散表現多項式の斉次化
296. dp dehomo(dpoly):: 斉次分散表現多項式の非斉次化• dp homo() は, dpoly の 各項 t について, 指数ベクトルの長さを 1 伸ばし, 最後の成分の値をd − deg(t) (d は dpoly の全次数) とした分散表現多項式を返す.
• dp dehomo() は, dpoly の各項について, 指数ベクトルの最後の成分を取り除いた分散多項式を返す.
• いずれも, 生成された多項式を用いた演算を行う場合, それらに適合する項順序を正しく設定する必要がある.
• hgr() などにおいて, 内部的に用いられている.
[202] X=<<1,2,3>>+3*<<1,2,1>>;(1)*<<1,2,3>>+(3)*<<1,2,1>>[203] dp_homo(X);(1)*<<1,2,3,0>>+(3)*<<1,2,1,2>>[204] dp_dehomo(@);(1)*<<1,2,3>>+(3)*<<1,2,1>>
297. dp ptozp(dpoly):: 定数倍して係数を整数係数かつ係数の整数 GCD を 1 にする.
298. dp prim(dpoly):: 有理式倍して係数を整数係数多項式係数かつ係数の多項式 GCD を 1 にする.
• dp ptozp() は, ptozp() に相当する操作を分散表現多項式に対して行う. 係数が多項式を含む場
合, 係数に含まれる多項式共通因子は 取り除かない.
• dp prim() は, 係数が多項式を含む場合, 係数に含まれる多項式共通因子を取り除く.
[208] X=dp_ptod(3*(x-y)*(y-z)*(z-x),[x]);(-3*y+3*z)*<<2>>+(3*y^2-3*z^2)*<<1>>+(-3*z*y^2+3*z^2*y)*<<0>>[209] dp_ptozp(X);(-y+z)*<<2>>+(y^2-z^2)*<<1>>+(-z*y^2+z^2*y)*<<0>>[210] dp_prim(X);(1)*<<2>>+(-y-z)*<<1>>+(z*y)*<<0>>467299. dp nf(indexlist,dpoly,dpolyarray,fullreduce)
300. dp weyl nf(indexlist,dpoly,dpolyarray,fullreduce)
301. dp nf mod(indexlist,dpoly,dpolyarray,fullreduce,mod)302. dp weyl nf mod(indexlist,dpoly,dpolyarray,fullreduce,mod):: 分散表現多項式の正規形を求める. (結果は定数倍されている可能性あり)
303. dp true nf(indexlist,dpoly,dpolyarray,fullreduce)
304. dp true nf mod(indexlist,dpoly,dpolyarray,fullreduce,mod):: 分散表現多項式の正規形を求める. (真の結果を [分子, 分母] の形で返す)• 分散表現多項式 dpoly の正規形を求める.
• 名前に weyl を含む関数はワイル代数における正規形計算を行う. 以下の説明は weyl を含むものに対しても同様に成立する.
• dp nf mod(), dp true nf mod() の入力は, dp mod() などにより, 有限体上の分散表現多項式になっていなければならない.
• 結果に有理数, 有理式が含まれるのを避けるため, dp nf() は 真の値の定数倍の値を返す. 有理式
係数の場合の dp nf mod() も同様であるが, 係数体が有限体の場合 dp nf mod() は真の値を返す.
• dp true nf(), dp true nf mod() は, [nm,dn] なる形のリストを返す. ただし, nm は係数に分数, 有理式を含まない分散表現多項式, dn は 数または多項式で nm/dn が真の値となる.
• dpolyarray は分散表現多項式を要素とするベクトル, indexlist は正規化計算に用いる dpolyarrayの要素のインデックス のリスト.
• fullreduce が 0 でないとき全ての項に対して簡約を行う. fullreduce が 0 のとき頭項のみに対して簡約を行う.
• indexlist で指定された多項式は, 前の方のものが優先的に使われる.
• 一般には indexlist の与え方により函数の値は異なる可能性があるが, グレブナ基底に対しては一意的に定まる.
• 分散表現でない固定された多項式集合による正規形を多数求める必要がある場合 に便利である. 単一の演算に関しては, p nf(), p true nf() を用いるとよい.
[0] load("gr")$[64] load("katsura")$[69] K=katsura(4)$[70] dp_ord(2)$[71] V=[u0,u1,u2,u3,u4]$[72] DP1=newvect(length(K),map(dp_ptod,K,V))$[73] G=gr(K,V,2)$[74] DP2=newvect(length(G),map(dp_ptod,G,V))$[75] T=dp_ptod((u0-u1+u2-u3+u4)^2,V)$[76] dp_dtop(dp_nf([0,1,2,3,4],T,DP1,1),V);u4^2+(6*u3+2*u2+6*u1-2)*u4+9*u3^2+(6*u2+18*u1-6)*u3+u2^2+(6*u1-2)*u2+9*u1^2-6*u1+1[77] dp_dtop(dp_nf([4,3,2,1,0],T,DP1,1),V);-5*u4^2+(-4*u3-4*u2-4*u1)*u4-u3^2-3*u3-u2^2+(2*u1-1)*u2-2*u1^2-3*u1+1[78] dp_dtop(dp_nf([0,1,2,3,4],T,DP2,1),V);-11380879768451657780886122972730785203470970010204714556333530492210
456775930005716505560062087150928400876150217079820311439477560587583
488*u4^15+...
[79] dp_dtop(dp_nf([4,3,2,1,0],T,DP2,1),V);-11380879768451657780886122972730785203470970010204714556333530492210

468

456775930005716505560062087150928400876150217079820311439477560587583
488*u4^15+...
[80] @78==@79;1305. dp hm(dpoly):: 頭単項式を取り出す.
306. dp ht(dpoly):: 頭項を取り出す.
307. dp hc(dpoly):: 頭係数を取り出す.
308. dp rest(dpoly):: 頭単項式を取り除いた残りを返す.
• これらは, 分散表現多項式の各部分を取り出すための函数である.
• 分散表現多項式 p に対し次が成り立つ.
p = dp hm(p) + dp rest(p)dp hm(p) = dp hc(p)dp ht(p)[87] dp_ord(0)$[88] X=ptozp((a46^2+7/10*a46+7/48)*u3^4-50/27*a46^2-35/27*a46-49/216)$[89] T=dp_ptod(X,[u3,u4,a46])$[90] dp_hm(T);(2160)*<<4,0,2>>[91] dp_ht(T);(1)*<<4,0,2>>[92] dp_hc(T);2160[93] dp_rest(T);(1512)*<<4,0,1>>+(315)*<<4,0,0>>+(-4000)*<<0,0,2>>+(-2800)*<<0,0,1>>+(-490)*<<0,0,0>>309. dp td(dpoly):: 頭項の全次数を返す.
310. dp sugar(dpoly):: 多項式の sugar を返す.
• dp td() は, 頭項の全次数, すなわち各変数の指数の和を返す.
• 分散表現多項式が生成されると, sugar と呼ばれるある整数が付与される. この値は仮想的に斉次化して計算した場合に結果が持つ全次数の値となる.
• sugar は, グレブナ基底計算における正規化対の選択のストラテジを決定するための重要な指針となる.
[74] dp_ord(0)$[75] X=<<1,2>>+<<0,1>>$[76] Y=<<1,2>>+<<1,0>>$[77] Z=X-Y;(-1)*<<1,0>>+(1)*<<0,1>>[78] dp_sugar(T);3469

311. dp lcm(dpoly1,dpoly2):: 最小公倍項を返す.
それぞれの引数の頭項の最小公倍項を返す. 係数は 1 である.

[100] dp_lcm(<<1,2,3,4,5>>,<<5,4,3,2,1>>);(1)*<<5,4,3,4,5>>
312. dp redble(dpoly1,dpoly2):: 頭項どうしが整除可能かどうか調べる.
313. dp subd(dpoly1,dpoly2):: 頭項の商単項式を返す.
• dp ht(dpoly1)/dp ht(dpoly2) を求める. 結果の係数は 1 である.
• 割り切れることがあらかじめわかっている必要がある.
[162] dp_subd(<<1,2,3,4,5>>,<<1,1,2,3,4>>);(1)*<<0,1,1,1,1>>
314. dp vtoe(vect):: 指数ベクトルを項に変換
315. dp etov(dpoly):: 頭項を指数ベクトルに変換• dp vtoe() は, ベクトル vect を指数ベクトルとする項を生成する.
• dp etov() は, 分散表現多項式 dpoly の頭項の指数ベクトルをベクトルに変換する.
[211] X=<<1,2,3>>;(1)*<<1,2,3>>[212] V=dp_etov(X);[ 1 2 3 ][213] V[2]++$[214] Y=dp_vtoe(V);(1)*<<1,2,4>>316. dp mbase(dplist):: monomial 基底の計算• ある順序でグレブナ基底となっている多項式集合の, その順序に関する分散表現である dplist について, dplist が K[X] 中で生成するイデアル I が 0 次元の時, K 上有限次元線形空間である
K[X]/I の monomial による基底を求める.
• 得られた基底の個数が, K[X]/I の K-線形空間としての次元に等しい.
[215] K=katsura(5)$[216] V=[u5,u4,u3,u2,u1,u0]$[217] G0=gr(K,V,0)$[218] H=map(dp_ptod,G0,V)$[219] map(dp_dtop,dp_mbase(H),V)$[u0^5,u4*u0^3,u3*u0^3,u2*u0^3,u1*u0^3,u0^4,u3^2*u0,u2*u3*u0,u1*u3*u0,
u1*u2*u0,u1^2*u0,u4*u0^2,u3*u0^2,u2*u0^2,u1*u0^2,u0^3,u3^2,u2*u3,u1*u3,
u1*u2,u1^2,u4*u0,u3*u0,u2*u0,u1*u0,u0^2,u4,u3,u2,u1,u0,1]
317. dp mag(p):: 係数のビット長の和を返す• 分散表現多項式の係数に現れる有理数につき, その分母分子 (整数の場合は分子) のビット長の総470

和を返す.
• 対象となる多項式の大きさの目安として有効である. 特に, 0 次元システムにおいては 係数膨張が問題となり, 途中生成される多項式が係数膨張を起こしているかどうかの判定に役立つ.
• dp gr flags() で, ShowMag, Print を on にすることにより，途中生成される多項式にたいする
dp mag() の値を見ることができる.

[221] X=dp_ptod((x+2*y)^10,[x,y])$[222] dp_mag(X);115318. dp red(dpoly1,dpoly2,dpoly3)319. dp red mod(dpoly1,dpoly2,dpoly3,mod):: 一回の簡約操作• dpoly1 + dpoly2 なる分散表現多項式を dpoly3 で 1 回簡約する.
• dp red mod() の入力は, 全て有限体係数に変換されている必要がある.
• 簡約される項は dpoly2 の頭項である. 従って, dpoly2 の 頭項が dpoly3 の頭項で割り切れることがあらかじめわかっていなければならない.
• 引数が整数係数の時, 簡約は, 分数が現れないよう, 整数 a, b, 項 t により a(dpoly1 + dpoly2) −btdpoly3 として計算される.
• 結果は, [adpoly1,a dpoly2 - bt dpoly3] なるリストである.
[157] D=(3)*<<2,1,0,0,0>>+(3)*<<1,2,0,0,0>>+(1)*<<0,3,0,0,0>>;(3)*<<2,1,0,0,0>>+(3)*<<1,2,0,0,0>>+(1)*<<0,3,0,0,0>>[158] R=(6)*<<1,1,1,0,0>>;(6)*<<1,1,1,0,0>>[159] C=12*<<1,1,1,0,0>>+(1)*<<0,1,1,1,0>>+(1)*<<1,1,0,0,1>>;(12)*<<1,1,1,0,0>>+(1)*<<0,1,1,1,0>>+(1)*<<1,1,0,0,1>>[160] dp_red(D,R,C);[(6)*<<2,1,0,0,0>>+(6)*<<1,2,0,0,0>>+(2)*<<0,3,0,0,0>>,(-1)*<<0,1,1,1,0>>+(-1)*<<1,1,0,0,1>>]
320. dp sp(dpoly1,dpoly2)
321. dp sp mod(dpoly1,dpoly2,mod):: S-多項式の計算• dpoly1, dpoly2 の S-多項式を計算する.
• dp sp mod() の入力は, 全て有限体係数に変換されている必要がある.
• 結果に有理数, 有理式が入るのを避けるため, 結果が定数倍, あるいは多項式倍されている可能性がある.
[227] X=dp_ptod(x^2*y+x*y,[x,y]);(1)*<<2,1>>+(1)*<<1,1>>[228] Y=dp_ptod(x*y^2+x*y,[x,y]);(1)*<<1,2>>+(1)*<<1,1>>[229] dp_sp(X,Y);(-1)*<<2,1>>+(1)*<<1,2>>
322. p nf(poly,plist,vlist,order)
323. p nf mod(poly,plist,vlist,order,mod):: 表現多項式の正規形を求める. (結果は定数倍されている可能性あり)
324. p true nf(poly,plist,vlist,order)471

325. p true nf mod(poly,plist,vlist,order,mod):: 表現多項式の正規形を求める. (真の結果を [分子, 分母] の形で返す)• gr で定義されている.
• 多項式の, 多項式リストによる正規形を求める.
• dp nf(), dp true nf(), dp nf mod(), dp true nf mod に対するインタフェースである.
• poly および plist は, 変数順序 vlist および 変数順序型 otype に従って分散表現多項式に変換され, dp nf(), dp true nf(), dp nf mod(), dp true nf mod() に渡される.
• dp nf(), dp true nf(), dp nf mod(), dp true nf mod() は fullreduce が 1 で呼び出される.
• 結果は多項式に変換されて出力される.
• p true nf(), p true nf mod() の出力に関しては, dp true nf(), dp true nf mod() の項を参照.
[79] K = katsura(5)$[80] V = [u5,u4,u3,u2,u1,u0]$[81] G = hgr(K,V,2)$[82] p_nf(K[1],G,V,2);
0[83] L = p_true_nf(K[1]+1,G,V,2);[-1503...,-1503...][84] L[0]/L[1];1326. p terms(poly,vlist,order):: 多項式にあらわれる単項をリストにする.
• gr で定義されている.
• 多項式を単項に展開した時に現れる項をリストにして返す. vlist および order により定まる項順
序により, 順序の高いものがリストの先頭に来るようにソートされる.
• グレブナ基底はしばしば係数が巨大になるため, 実際にどの項が現れているのかを見るためなどに用いる.
[233] G=gr(katsura(5),[u5,u4,u3,u2,u1,u0],2)$[234] p_terms(G[0],[u5,u4,u3,u2,u1,u0],2);[u5,u0^31,u0^30,u0^29,u0^28,u0^27,u0^26,u0^25,u0^24,u0^23,u0^22,
u0^21,u0^20,u0^19,u0^18,u0^17,u0^16,u0^15,u0^14,u0^13,u0^12,u0^11,
u0^10,u0^9,u0^8,u0^7,u0^6,u0^5,u0^4,u0^3,u0^2,u0,1]
327. gb comp(plist1, plist2):: 多項式リストが, 符号を除いて集合として等しいかどうか調べる.
• plist1, plist2 について, 符号を除いて集合として等しいかどうか 調べる.
• 異なる方法で求めたグレブナ基底は, 基底の順序, 符号が異なる場合があり, それらが等しいかどうかを調べるために用いる.
[243] C=cyclic(6)$[244] V=[c0,c1,c2,c3,c4,c5]$[245] G0=gr(C,V,0)$[246] G=tolex(G0,V,0,V)$[247] GG=lex_tl(C,V,0,V,0)$[248] gb_comp(G,GG);
1472

328. katsura(n)329. hkatsura(n)330. cyclic(n)331. hcyclic(n):: 多項式リストの生成• katsura() は katsura, cyclic() は cyclic で定義されている.
• グレブナ基底計算でしばしばテスト, ベンチマークに用いられる katsura, cyclic およびその斉次化を生成する.
• cyclic は Arnborg, Lazard, Davenport などの名で呼ばれることもある.
[74] load("katsura")$[79] load("cyclic")$[89] katsura(5);[u0+2*u4+2*u3+2*u2+2*u1+2*u5-1,2*u4*u0-u4+2*u1*u3+u2^2+2*u5*u1,
2*u3*u0+2*u1*u4-u3+(2*u1+2*u5)*u2,2*u2*u0+2*u2*u4+(2*u1+2*u5)*u3-u2+u1^2,2*u1*u0+(2*u3+2*u5)*u4+2*u2*u3+2*u1*u2-u1,
u0^2-u0+2*u4^2+2*u3^2+2*u2^2+2*u1^2+2*u5^2][90] hkatsura(5);[-t+u0+2*u4+2*u3+2*u2+2*u1+2*u5,-u4*t+2*u4*u0+2*u1*u3+u2^2+2*u5*u1,-u3*t+2*u3*u0+2*u1*u4+(2*u1+2*u5)*u2,-u2*t+2*u2*u0+2*u2*u4+(2*u1+2*u5)*u3+u1^2,-u1*t+2*u1*u0+(2*u3+2*u5)*u4+2*u2*u3+2*u1*u2,-u0*t+u0^2+2*u4^2+2*u3^2+2*u2^2+2*u1^2+2*u5^2][91] cyclic(6);[c5*c4*c3*c2*c1*c0-1,((((c4+c5)*c3+c5*c4)*c2+c5*c4*c3)*c1+c5*c4*c3*c2)*c0+c5*c4*c3*c2*c1,(((c3+c5)*c2+c5*c4)*c1+c5*c4*c3)*c0+c4*c3*c2*c1+c5*c4*c3*c2,((c2+c5)*c1+c5*c4)*c0+c3*c2*c1+c4*c3*c2+c5*c4*c3,(c1+c5)*c0+c2*c1+c3*c2+c4*c3+c5*c4,c0+c1+c2+c3+c4+c5][92] hcyclic(6);[-c^6+c5*c4*c3*c2*c1*c0,((((c4+c5)*c3+c5*c4)*c2+c5*c4*c3)*c1+c5*c4*c3*c2)*c0+c5*c4*c3*c2*c1,(((c3+c5)*c2+c5*c4)*c1+c5*c4*c3)*c0+c4*c3*c2*c1+c5*c4*c3*c2,((c2+c5)*c1+c5*c4)*c0+c3*c2*c1+c4*c3*c2+c5*c4*c3,(c1+c5)*c0+c2*c1+c3*c2+c4*c3+c5*c4,c0+c1+c2+c3+c4+c5]
332. primadec(plist,vlist)
333. primedec (plist,vlist):: イデアルの分解• primadec(), primedec() は primdec で定義されている.
• primadec(), primedec() はそれぞれ有理数体上でのイデアルの準素分解, 根基の素イデアル分解を行う.
• 引数は多項式リストおよび変数リストである. 多項式は有理数係数のみが許される.
• primadec() は [準素成分, 付属素イデアル] のリストを返す.
• primadec() は 素因子のリストを返す.
• 結果において, 多項式リストとして表示されている各イデアルは全て グレブナ基底である. 対応する項順序は, それぞれ変数 PRIMAORD, PRIMEORD に格納されている.

473

• primadec() は [Shimoyama-Yokoyama] の準素分解アルゴリズム を実装している.
• もし素因子のみを求めたいなら, primedec を使う方がよい. これは, 入力イデアルが根基イデアルでない場合に, primadec() の計算に余分なコストが必要となる場合があるからである.
[84] load("primdec")$[102] primedec([p*q*x-q^2*y^2+q^2*y,-p^2*x^2+p^2*x+p*q*y,(q^3*y^4-2*q^3*y^3+q^3*y^2)*x-q^3*y^4+q^3*y^3,-q^3*y^4+2*q^3*y^3+(-q^3+p*q^2)*y^2],[p,q,x,y]);[[y,x],[y,p],[x,q],[q,p],[x-1,q],[y-1,p],[(y-1)*x-y,q*y^2-2*q*y-p+q]][103] primadec([x,z*y,w*y^2,w^2*y-z^3,y^3],[x,y,z,w]);[[[x,z*y,y^2,w^2*y-z^3],[z,y,x]],[[w,x,z*y,z^3,y^3],[w,z,y,x]]]334. primedec mod(plist,vlist,ord,mod,strategy):: イデアルの分解• primedec mod() は primdec mod で定義されている. [Yokoyama] の素イデアル分解アルゴリズ
ム を実装している.
• primedec mod() は有限体上でのイデアルの 根基の素イデアル分解を行い, 素イデアルのリストを返す.
• primedec mod() は, GF (mod) 上での分解を与える. 結果の各成分の生成元は, 整数係数多項式である.
• 結果において, 多項式リストとして表示されている各イデアルは全て [vlist,ord] で指定される項順序に関するグレブナ基底である.
• strategy が 0 でないとき, incremental に component の共通部分を計算することによる earlytermination を行う. 一般に, イデアルの次元が高い場合に有効だが, 0 次元の場合など, 次元が小さい 場合には overhead が大きい場合がある.
• 計算途中で内部情報を見たい場合には、 前もって dp gr print(2) を実行しておけばよい.
[0] load("primdec_mod")$[246] PP444=[x^8+x^2+t,y^8+y^2+t,z^8+z^2+t]$[247] primedec_mod(PP444,[x,y,z,t],0,2,1);[[y+z,x+z,z^8+z^2+t],[x+y,y^2+y+z^2+z+1,z^8+z^2+t],[y+z+1,x+z+1,z^8+z^2+t],[x+z,y^2+y+z^2+z+1,z^8+z^2+t],[y+z,x^2+x+z^2+z+1,z^8+z^2+t],[y+z+1,x^2+x+z^2+z+1,z^8+z^2+t],[x+z+1,y^2+y+z^2+z+1,z^8+z^2+t],[y+z+1,x+z,z^8+z^2+t],[x+y+1,y^2+y+z^2+z+1,z^8+z^2+t],[y+z,x+z+1,z^8+z^2+t]][248]
335. bfunction(f )336. bfct(f )
337. generic bfct(plist,vlist,dvlist,weight):: b 関数の計算
338. ann(f )339. ann0(f ):: 多項式のベキの annihilator の計算• bfct で定義されている.
• bfunction(f ) は多項式 f の global b 関数 b(s) を 計算する. b(s) は, Weyl 代数 D 上の一変数多項式環 D[s] の元 P (x, s) が存在して, P (x, s)f s+1 = b(s)f s を満たすような 多項式 b(s) の中で, 次数が最も低いものである.
• generic bfct(f ,vlist,dvlist,weight) は, plist で生成される D の左イデアル I の, ウェイト474

weight に関する global b 関数を計算する. vlist は x-変数, vlist は対応する D-変数 を順に並べる.
• bfunction と bfct では用いているアルゴリズムが 異なる. どちらが高速かは入力による.
• ann(f ) は, f s の annihilator ideal の生成系を返す. ann(f ) は, [a,list] なるリストを返す. こ
こで, a は f の b 関数の最小整数根, list は ann(f ) の結果の s に, a を 代入したものである. 詳
細については, [Saito-Sturmfels-Takayama] を見よ.
[0] load("bfct")$[216] bfunction(x^3+y^3+z^3+x^2*y^2*z^2+x*y*z);-9*s^5-63*s^4-173*s^3-233*s^2-154*s-40[217] fctr(@);[[-1,1],[s+2,1],[3*s+4,1],[3*s+5,1],[s+1,2]][218] F = [4*x^3*dt+y*z*dt+dx,x*z*dt+4*y^3*dt+dy,
x*y*dt+5*z^4*dt+dz,-x^4-z*y*x-y^4-z^5+t]$[219] generic_bfct(F,[t,z,y,x],[dt,dz,dy,dx],[1,0,0,0]);20000*s^10-70000*s^9+101750*s^8-79375*s^7+35768*s^6-9277*s^5+1278*s^4-72*s^3[220] P=x^3-y^2$[221] ann(P);[2*dy*x+3*dx*y^2,-3*dx*x-2*dy*y+6*s][222] ann0(P);[-1,[2*dy*x+3*dx*y^2,-3*dx*x-2*dy*y-6]]
3.3.14 分散計算に関する関数
340. ox launch([host[,dir],command])
341. ox launch nox([host[,dir],command]):: 遠隔プロセスの起動および通信を開始する.
342. ox shutdown(id):: 遠隔プロセスを終了させ, 通信を終了する.
• ox_launch() は, ホスト host 上でコマンド command を起動し, このプロセスと通信を開始する. 引数が 3 つの場合, host 上で, dir にある ox_launch というサーバ起動用プログラムを立ち上げる. ox_launch は command を起動する. host が 0 の時, Asir が動作しているマシン上でコマンドを起動する. 無引数の場合, host は 0, dir は get_rootdir() で返されるディレクトリ,
command は同じディレクトリの ox_asir を意味する.
• host が 0, すなわちサーバを local に起動する場合には, dir を省略できる. この場合, dir は
get_rootdir() で返される ディレクトリとなる.
• command が / で始まる文字列の場合, 絶対パスと解釈される. それ以外の場合, dir からの相対パスと解釈される.
• UNIX 版においては, ox_launch() は, command の標準出力, 標準エラー出力を表示するための xterm を起動する. ox_launch_nox() は, X なしの環境の場合, あるいは xterm を起動せずにサーバを立ち上げる場合に用いる. この場合, command の出力は /dev/null に接続される.
ox_launch() の場合でも, 環境変数 DISPLAY が設定されていない 場合には, ox_launch_nox()と同じ動作をする.
• 返される整数は通信のための識別子となる.
• Asir と通信するプロセスは同一のマシン上で動作している必要はない. また, 通信におけるバイト
オーダは server, client 間での最初の negotiation で決まるため, 相手先のマシンとバイトオーダ
が異なっていても構わない.

475• host にマシン名を指定する場合, 以下の準備が必要である. ここで, Asir の動いているホストをA, 通信相手のプロセス が起動されるホストを B とする.
（a）ホスト B の ~.rhosts/ に, ホスト A のホスト 名を登録する.
（b）ox_plot() など, X とのコネクションも用いられる場合, Xserver に対し, 必要なホストを
authorize させる. xhost で必要なホスト名を追加すればよい.
（c）command に よ っ て は, ス タ ッ ク を 大 量 に 使 用 す る も の も あ る た め, .cshrc で ス タ ッ
ク サ イ ズ を 大 き め (16MB 程 度) に 指 定 し て お く の が 安 全 で あ る. ス タ ッ ク サ イ ズ は
limit stacksize 16m などと指定する.
• command が, X 上にウインドウを開ける場合, display が指定されればその文字列を, 省略時には環境変数 DISPLAY の値を用いる.
• 環境変数 ASIR_RSH がセットされている場合, サーバの立ち上げプログラム として rsh の代わりにこの変数の値が用いられる. 例えば,
% setenv ASIR_RSH "ssh -f -X -A "により, サーバの立ち上げに ssh が用いられ, X11 の通信が forwarding される. 詳しくは ssh のマニュアルを 参照.
• ox_shutdown() は識別子 id に対応する遠隔プロセス を終了させる.
• Asir が正常した場合には全ての入出力ストリームは自動的に閉じられ, 起動されているプロセス
は全て終了するが, 異常終了した場合, 遠隔プロセス が終了しない場合もある. Asir が異常終了した場合, 遠隔プロセスを 起動したマシン上で ps などを起動して, もし Asir から起動したプロセスが残っている場合, kill する必要がある.
• log 表示用 xterm は -name ox_term オプションで起動される. よって, ox_term なるリソース
名に対して xterm のリソース設定 を行えば, log 用 xterm の挙動のみを変えることができる. 例
えば,
ox_xterm*iconic:on
ox_xterm*scrollBar:on
ox_xterm*saveLines:1000
により, icon で起動, scrollbar つき, scrollbar で参照できる行数が最大 1000 行, という指定ができる.
[219] ox_launch();0[220] ox_rpc(0,"fctr",x^10-y^10);0[221] ox_pop_local(0);[[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]][222] ox_shutdown(0);0343. ox launch generic(host,launch,server,use unix,use ssh,use x,conn to serv):: 遠隔プロセスの起動および通信を開始する• ox_launch_generic() は, ホスト host 上で, コントロールプロセス launch およびサーバプロセ
ス server を起動する. その他の引数は, 使用する protocol の種類, X の使用/不使用, rsh/ssh によるプロセス起動, connect 方法の指定などを行うスイッチである.
• host が 0 の場合, Asir が動作しているマシン上に, launch, server を立ち上げる. この場合,
use_unix の値にかかわらず, UNIX internal protocol が用いられる.
• use unix が 1 の場合, UNIX internal protocol を用いる. 0 の場合, Internet protocol を用いる.
• use ssh が 1 の場合, ssh (Secure Shell) によりコントロール, サーバプロセスを立ち上げる.
ssh-agent などを利用していな場合, パスワードの入力が必要となる. 相手先で sshd が動いてい476

ない場合, 自動的に rsh が用いられるが, パスワードが必要となる場合には, その場で起動に失敗する.
• use x が 1 の場合, X 上での動作を仮定し, 設定されている DISPLAY 変数を用いて, log 表示用
xterm のもとで server が起動され る. DISPLAY 変数がセットされていない場合には, 自動的に Xなしの設定とな る. DISPLAY が不適切にセットされている場合には, コントロール, サーバがハングするので要注意である.
• conn to serv が 1 の場合, Asir (client) が生成したポートに対し, client が bind, listen し, 起動されたプロセスが connect する. conn to serv が 0 の場合, 起動されたプロセスが bind, listen
し, client が connect する.

[342] LIB=get_rootdir();/export/home/noro/ca/Kobe/build/OpenXM/lib/asir[343] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",0,0,0,0);1[344] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,0,0,0);2[345] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,0,0);3[346] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,1,0);4[347] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,1,1);
5[348] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,0,1);
6344. generate port([use unix]):: port の生成345. try bind listen(port):: port に対して bind, listen
346. try connect(host,port):: port に対して connect
347. try accept(socket,port):: connect 要求を accept
348. register server(control socket,control port,server socket,server port):: connection の成立した control socket, server socket の登録• これらの関数は, 遠隔プロセスと通信を成立させるためのプリミティブである.
• generate_port() は通信のための port を生成する. 無引数あるいは 引数が 0 の場合, Internet
domain の socket のための port 番号, それ以外の場合には, UNIX domain (host-internal protocol) のための, ファイル名を生成する. port 番号は random に生成されるが, その port が使用中
でない保証はない.
• try_bind_listen() は, 与えられた port に対し, その protocol に 対応した socket を生成し,
bind, listen する. 成功した場合, socket 識別子を返す. 失敗した場合, −1 が返る.
• try_connect() は, ホスト host の port port に対し connect を試みる. 成功した場合, socket 識
別子を返す. 失敗した場合 −1 が返る.
• try_accept() は, socket に対する connect 要求を accept し, 新たに生成された socket を返す. 失敗した場合 −1 が返る. いずれの場合にも, socket は自動的に close される. 引数 port は,socket の protocol を判別するために与える.
• register_server() は, control, server それぞれの socket を 一組にして, server list に登録し,
ox_push_cmo() などで用いる プロセス識別子を返す.
477

• 遠隔プロセスの起動は, shell() または手動で行う.
[340] CPort=generate_port();39896[341] SPort=generate_port();37222[342] CSocket=try_bind_listen(CPort);
3[343] SSocket=try_bind_listen(SPort);
5/*
ここで, ox_launch を起動 :% ox_launch "127.1" 0 39716 37043 ox_asir "shio:0"*/[344] CSocket=try_accept(CSocket,CPort);
6[345] SSocket=try_accept(SSocket,SPort);
3[346] register_server(CSocket,CPort,SSocket,SPort);
0349. ox asir:: Asir の機能を OpenXM サーバとして提供 ox asir は, Asir のほぼ全ての機能を OpenXM サーバとして提供する. ox asir は, ox launch() または ox launch nox() で起動する. 後者は X 環境を用いない場合のために用意されている.
[5] ox_launch();0[6] ox_launch_nox("127.0.0.1","/usr/local/lib/asir","/usr/local/lib/asir/ox_asir");
0[7] RemoteLibDir = "/usr/local/lib/asir/"$[8] Machines = ["sumire","rokkaku","genkotsu","shinpuku"];[sumire,rokkaku,genkotsu,shinpuku][9] Servers = map(ox_launch,Machines,RemoteLibDir,RemoteLibDir+"ox_asir");[0,1,2,3]350. ox rpc(number,"func",arg0,...)
351. ox cmo rpc(number,"func",arg0,...)
352. ox execute string(number,"command",...):: プロセスの函数呼び出し• 識別子 number のプロセスの函数を呼び出す.
• 函数の計算終了を待たず, 直ちに 0 を返す.
• ox_rpc() は, サ ー バ が ox_asir の 場 合 の み 用 い る こ と が で き る. そ れ 以 外 の 場 合 は,
ox_cmo_rpc() を用いる.
• 函数が返す値は ox_pop_local(), ox_pop_cmo() により取り出す.
• サーバが ox_asir 以外のもの (例えば Kan サーバ ox_sm1 など) の場合には, Open_XM プロトコ
ルでサポートされているデータのみを 送ることができる.
478

• ox_execute_string() は, 送った文字列 command をサーバが自らのユーザ言語パーザで解析
し, 評価した結果をサーバのスタックに置くように 指示する.
[234] ox_cmo_rpc(0,"dp_ht",dp_ptod((x+y)^10,[x,y]));0[235] ox_pop_cmo(0);(1)*<<10,0>>[236] ox_execute_string(0,"12345 % 678;");0[237] ox_pop_cmo(0);141353. ox reset(number):: プロセスのリセット
354. ox intr(number):: プロセスに SIGINT 送付
355. register handler(func):: プロセスのリセットのための関数登録• ox_reset() は, 識別子 number のプロセスをリセットし, コマンド受け付け状態にする.
• そのプロセスが既に書き出した, あるいは現在書き出し中のデータがある場合, それを全部読み出
し, 出力バッファを空にした時点で戻る.
• 子プロセスが RUN 状態の場合でも, 割り込みにより強制的に計算を終了させる.
• 分散計算を行う函数の先頭で, 使用するプロセスに対して実行する. あるいは計算途中での強制中断に用いる.
• ox_intr() は, 識別子 number のプロセスをに対して SIGINT を送付する. SIGINT に対するプロ
セスの動作は規定されていないが, ox_asir の場合, ただちに debug mode に 入る. X 上で動作している場合, デバッグコマンド入力用のウィンドウがポップアップする.
• register_handler() は, C-c などによる割り込みの際に, u を指定することで, 無引数ユーザ定
義関数 func() が呼び出されるように設定する. この関数に, ox_reset() を呼び出させることで,割り込みの際に自動的に OpenXM server のリセットを行うことができる.
• func に 0 を指定することで, 設定を解除できる.
[10] ox_launch();0[11] ox_rpc(0,"fctr",x^100-y^100);0[12] ox_reset(0); /* xterm のウィンドウには*/
1/* usr1 : return to toplevel by SIGUSR1 が表示される. */[340] Procs=[ox_launch(),ox_launch()];[0,1][341] def reset() { extern Procs; map(ox_reset,Procs);}[342] map(ox_rpc,Procs,"fctr",x^100-y^100);[0,0][343] register_handler(reset);
1[344] interrupt ?(q/t/c/d/u/w/?) u
Abort this computation? (y or n) y
Calling the registered exception handler...done.
479

return to toplevel
356. ox push cmo(number,obj)
357. ox push local(number,obj):: obj を識別子 number のプロセスに送信• 識別子 number のプロセスに obj を送信する.
• ox_push_cmo() は, Asir 以外の Open_XM サーバに送信する際に用いる.
• ox_push_local() は, ox_asir, ox_plot にデータを送る場合に用いることができる.
• バッファがいっぱいにならない限り, ただちに復帰する
358. ox pop cmo(number)
359. ox pop local(number):: プロセス識別子 number からデータを受信する.
• プロセス識別子 number のプロセスからデータを受信する.
• ox_pop_cmo() は, Asir 以外の Open_XM サーバから受信する際に用いる.
• ox_pop_local() は, ox_asir, ox_plot からデータを受け取る場合に用いることができる.
• サ ー バ が 計 算 中 の 場 合 ブ ロ ッ ク す る.
こ れ を 避 け る た め に は, ox_push_cmd() で
SM_popCMO (262) または SM_popSerializedLocalObject (258) を送っておき, ox_select()
でプロセスが ready になっていることを確かめてから ox_get() すればよい.
[341] ox_cmo_rpc(0,"fctr",x^2-1);
0[342] ox_pop_cmo(0);[[1,1],[x-1,1],[x+1,1]][343] ox_cmo_rpc(0,"newvect",3);0[344] ox_pop_cmo(0);error([41,cannot convert to CMO object])[345] ox_pop_local(0);[ 0 0 0 ]360. ox push cmd(number,command):: プロセス識別子 number のプロセスにコマンド command を送信する.
361. ox sync(number):: プロセス識別子 number のプロセスに OX_SYNC_BALL を送信する.
• 識別子 number のプロセスにコマンドまたは OX_SYNC_BALL を送信する.
• Open_XM において送受信データは OX_DATA, OX_COMMAND, OX_SYNC_BALL の 3 種類に分かれる.
通常, コマンドは何らかの操作に付随して暗黙のうちに送信されるが, これをユーザが個別に送りたい場合に 用いられる.
• OX_SYNC_BALL は ox_reset() による計算中断, 復帰の際に送受信されるが, これを個別に送りたい場合に用いる. なお, 通常状態では OX_SYNC_BALL は無視される.
[3] ox_rpc(0,"fctr",x^100-y^100);0[4] ox_push_cmd(0,258);0[5] ox_select([0]);[0][6] ox_get(0);362. ox get(number)480

:: プロセス識別子 number のプロセスからデータを受信する.
• プロセス識別子 number のプロセスからデータを受信する. 既にストリーム上にデータがあることを仮定している.
• ox_push_cmd() と組み合わせて用いる.
• ox_pop_cmo(), ox_pop_local() は, ox_push_cmd() と ox_get() の組み合わせで実現されている.
[11] ox_push_cmo(0,123);0[12] ox_push_cmd(0,262); /* 262=OX_popCMO */0[13] ox_get(0);123363. ox pops(number[,nitem]):: プロセス識別子 number のプロセスのスタックからデータを取り除く.
• プロセス識別子 number のプロセスのスタックからデータを取り除く. nitem が指定されている場
合は nitem 個, 指定のない場合は 1 個取り除く.
[69] for(I=1;I<=10;I++)ox_push_cmo(0,I);[70] ox_pops(0,4);0[71] ox_pop_cmo(0);6364. ox select(nlist[,timeout]):: 読み出し可能なプロセスの識別子を返す.
• 識別子リスト nlist のプロセスのうち既に出力を返しているプロセスの識別子リストを返す.
• 全てのプロセスが RUN 状態のとき, いずれかのプロセスの終了を待つ. 但し, timeout が指定されている場合, timeout 秒だけ待つ.
• ox_push_cmd() で SM_popCMO あ る い は SM_popSerializedLocalObject を 送 っ て お き,
ox_select() で ready 状 態 の プ ロ セ ス を 調 べ て ox_get() す る こ と で, ox_pop_local(),ox_pop_cmo() で待ち状態に入るのを防ぐことができる.
ox_launch();0[220] ox_launch();1[221] ox_launch();2[222] ox_rpc(2,"fctr",x^500-y^500);0[223] ox_rpc(1,"fctr",x^100-y^100);0[224] ox_rpc(0,"fctr",x^10-y^10);0[225] P=[0,1,2];[0,1,2][226] map(ox_push_cmd,P,258);481

[0,0,0][227] ox_select(P);[0][228] ox_get(0);[[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]]365. ox flush(id):: 送信バッファの強制 ﬂush
• 通常はバッチモードは oﬀ であり, データ, コマンド送信ごとに 送信バッファは ﬂush される.
• バッチモードは ctrl コマンドの ox_batch スイッチ で on/oﬀ できる.
• 細かいデータを多数送る場合に, ctrl("ox_batch",1) でバッチモードを on にすると, バッファがいっぱいになった場合にのみ ﬂush されるため, overhead が小さくなる場合がある. ただしこの場合には, 最後に ox flush(id) を実行して, バッファを強制的に ﬂush する必要が ある.
• ox_pop_cmo(), ox_pop_local() のように, コマンド送信後ただちにデータ待ちに入る関数がハングしないよう, これらの関数の内部では 強制 ﬂush が実行されている.
[340] ox_launch_nox();0[341] cputime(1);07e-05sec + gc : 4.8e-05sec(0.000119sec)[342] for(I=0;I<10000;I++)ox_push_cmo(0,I);
0.232sec + gc : 0.006821sec(0.6878sec)[343] ctrl("ox_batch",1);
1
4.5e-05sec(3.302e-05sec)[344] for(I=0;I<10000;I++)ox_push_cmo(0,I); ox_flush(0);0.08063sec + gc : 0.06388sec(0.4408sec)[345] 19.6e-05sec(0.01317sec)
366. ox get serverinfo([id]):: server の Mathcap, 動作中のプロセス識別子の取得• 引数 id があるとき, プロセス識別子 id のプロセスの Mathcap をリストとして返す.
• 引数なしのとき, 現在動作中のプロセス識別子およびその Mathcap からなるペアを, リストとして返す.
[343] ox_get_serverinfo(0);[[199909080,Ox_system=ox_sm1.plain,Version=2.991118,HOSTTYPE=FreeBSD],[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,16,34]]][344] ox_get_serverinfo();[[0,[[199909080,Ox_system=ox_sm1.plain,Version=2.991118,
HOSTTYPE=FreeBSD],[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,
482

40,16,34]]]],[1,[[199901160,ox_asir],[276,275,258,262,263,266,267,268,274,269,272,265,264,273,300,270,271],[[514,2144202544],[1,2,3,4,5,2130706433,2130706434,17,19,20,21,22,24,25,26,31,27,33,60],[0,1]]]]]
3.3.15 その他の函数
367. ctrl("switch" [,obj]):: "switch" で指定した環境の設定，設定値を返す．
• Asir の実行環境の設定変更, 参照を行う.
• switch のみの場合, そのスイッチの現在の状態を返す.
• obj が与えられているとき, その値を設定する.
• スイッチは文字列として入力する. すなわちダブルクォートで囲む.
• スイッチは次の通り. 以下で, on は 1, oﬀ は 0 を意味する.
cputime on の時 CPU time および GC time を表示, oﬀ の時 表示しない. ctrl("cputime",onoff)
は cputime(onoff) と同じである.
nez EZGCD のアルゴリズムの切替え. デフォルトで 1 であり, とくに切替える必要はない.
echo on の時は標準入力を繰り返して出力し, oﬀ の時は標準入力を繰り返さない. output コマンドを用いる際に有効である.
bigﬂoat on の時, 入力された浮動小数は bigﬂoat に変換され, 浮動小数演算は PARI により行われる.
デフォルトの有効桁数は 9 桁である. 有効桁数を増やしたい時には setprec() を用いる. oﬀ の時, 入力された浮動小数は, 倍精度浮動小数に変換される.
evalef 1 のとき，初等関数の引数が数の場合は直ちに値を返す．
adj ガーベッジコレクションの頻度の変更. 1 以上の有理数が指定できる. デフォルト値は 3. 1 に近い程, ガーベッジコレクションせずにヒープを大きくとるようになる. 整数値はコマンドラインで指定できる. See section コマンドラインオプション.
verbose on の時, 函数の再定義時にメッセージを表示する.
quiet mode 1 のとき, 起動時に著作権表示を行わない. See section コマンドラインオプション.
prompt 0 のときプロンプトを表示しない. 1 のとき標準プロンプトを表示. C スタイルのフォマット
文字列をもちいるとユーザ定義のプロンプト.
例 (asirgui では不可): ctrl("prompt","\033[32m[%d]:= \033[0m")hex 1 のとき, 整数は 0x で始まる 16 進数として表示される. −1 のとき, 16 進数は, 間に ‘—’ をはさんで 8 桁ごとに区切って表示される.
real digit 倍精度浮動小数の表示の桁数を指定する.
double output 1 のとき, 倍精度浮動小数はつねに ddd.ddd の形で表示される.
fortran output 1 のとき, 多項式の表示が FORTRAN スタイルになる. すなわち冪が ‘^’ の代わりに ‘**’で表される. (デフォルト値は 0.)
ox batch 1 のとき, 送信バッファがいっぱいになった時のみ自動的に ﬂush. 0 のとき, データ, コマン
ド送信毎に ﬂush. (デフォルト値は 0.) 分散計算.
ox check 1 のとき, 送信データを相手プロセスが受け取れるかどうかチェックする. 0 のときしない.
(デフォルト値は 1.) See section 分散計算.
ox exchange mathcap 1 のとき, OX server との接続開始時に, 自動的に mathcap の交換を行う. (デフォルト値は 1.) 分散計算.
loadpath asir のロードパスの出力または設定を行う.
[0] L=ctrl("loadpath");[/home/you/OpenXM/lib/asir-contrib,/home/you/OpenXM/lib/asir,.][1] ctrl("loadpath", cons(getenv("HOME")+"/lib",L));483

0[2] sin(1);sin(1)[3] ctrl("evalef",1);
1[4] sin(1);0.841470984807897
368. debug:: デバッグモードに入る• debug は無引数の函数であるが, ‘()’ なしで呼び出せる.
• デバッグモードに入るとプロンプトが (debug) となり, コマンド受け付け状態となる. quit を入力するとデバッガから抜ける.
• デバッグモードについての詳細はデバッガを参照.
369. error(message):: エラーメッセージを表示してデバッグモードに入る• 一般に, 引数の間違いなど, 続行不可能なエラーが組み込み函数において発生した時, トップレベルに戻る前に, 可能ならばそのエラーの時点でデバッグモードに入る. error() は, ユーザ函数の内部でこの動作と同様の動作を行わせるための函数である.
• 引数は, error() が呼び出される際に表示されるメッセージで, 文字列である.
• ユーザ函数において, 変数をチェックして, あり得ない値の場合に error() を呼び出すようにしておけば, その時点で自動的にデバッグモードに入れる.
% cat mod3
def mod3(A) {if ( type(A) >= 2 )error("invalid argument");
else
return A % 3;}end$
% asir[0] load("mod3");
1[1] mod3(5);2[2] mod3(x);invalid argument
stopped in mod3 at line 3 in file "./mod3"
3
error("invalid argument");(debug) print A
A = x(debug) quit
return to toplevel[3]370. time():: セッション開始から現在までの CPU 時間および GC 時間を表示する484

• CPU 時間および GC 時間の表示に関するコマンドである.
• GC 時間とは, ガーベジコレクタにより消費されたと見なされる時間, CPU 時間は, 全体の CPU
時間から GC 時間を引いた残りで, 単位は秒である.
• time() は引数なしで, セッション開始から現在までの CPU 時間, GC 時間, 現在までに要求されたメモリののべ容量, およびセッション開始から現在までの経過時間の表示をする. すなわち,[CPU 時間 (秒), GC 時間 (秒), メモリ量 (ワード), 経過時間 (秒)] なるリストを返す. 1 ワードは
通常 4 バイトである.
• 計算の実行開始時, 終了時の time() から, その計算に対する CPU 時間, GC 時間がわかる.
• メモリ量は多倍長数ではないため, ある値を越えると無意味な値となるためあくまでも目安として用いるべきである. ctrl() や cputime() により cputime スイッチが on になっている場合には,トップレベルの文を一つの単位として, その実行時間が表示される. しかし, プログラムの内部など
で, 特定の計算に対する計算時間を知りたい時には, time() などを使う必要がある. getrusage()が使える UNIX 上では time() は信頼性のある値を返すが, Windows 95, 98 上では時刻を用いる
ほか方法がないため経過時間そのものが表示される. よって, 待ち状態があると, それも経過時間に加算される.
[0] T0=time();[2.390885,0.484358,46560,9.157768][1] G=hgr(katsura(4),[u4,u3,u2,u1,u0],2)$[2] T1=time();[8.968048,7.705907,1514833,63.359717][3] ["CPU",T1[0]-T0[0],"GC",T1[1]-T0[1]];[CPU,6.577163,GC,7.221549]
371. cputime(onoﬀ):: 引数が 0 ならば cputime の表示を止める，それ以外ならば表示を行う
372. tstart():: CPU time 計測開始
373. tstop():: CPU time 計測終了および表示• cputime() は, 引数が 0 ならば CPU time の表示を止める. それ以外ならば表示を行う.
• tsart は引数なし, ‘()’ なしで, CPU time 計測を開始する.
• tstop は引数なし, ‘()’ なしで, CPU time 計測を終了, および表示する.
• cputime(onoff) は ctrl("cputime",onoff) と同じである.
• tstart, tstop は, 入れ子にして使われることは想定していないため, そのような可能性がある場
合には, time() による計測を行う必要がある.
• cputime() による on, oﬀ は, 単に表示の on, oﬀ であり, トップレベルの一つの文に対する計測は常に行われている. よって, 計算を始めてからでも, 計算終了前にデバッガに入って cputime(1)を実行させれば計算時間は表示される.
[0] tstart$[1] fctr(x^10-y^10);[[1,1],[x+y,1],[x^4-y*x^3+y^2*x^2-y^3*x+y^4,1],[x-y,1],[x^4+y*x^3+y^2*x^2+y^3*x+y^4,1]][2] tstop$
80msec + gc : 40msec
374. timer(interval,expr,val):: 制限時間つきで計算を実行する• 時間を指定して計算を実行する. 指定時間内に計算が完了した場合その値を返す. 指定時間内に計485

算が完了しなかった場合, 第 3 引数を返す.
• 第 3 引数の値は, 計算が完了した場合の値と区別できる必要がある.

[0] load("cyclic");
1[1] timer(10,dp_gr_main(cyclic(7),[c0,c1,c2,c3,c4,c5,c6],1,1,0),0);interval timer expired (VTALRM)
0[2]375. currenttime()
1970 年 1 月 1 日 0 時 0 分 0 秒からの経過秒数• currenttime() は現在時刻を返す. UNIX の場合, time(3) を呼んでいるだけである.
[0] currenttime();1071639228[1]376. sleep(interval):: プロセスの実行を interval×10−3 秒停止• sleep() は, プロセスの実行を停止する. UNIX の場合, usleep を呼んでいるだけである[0] sleep(1000);1[1]377. heap():: 現在のヒープの大きさを返す (単位: バイト)
• 現在のヒープの大きさ (単位 : バイト) を返す. ヒープとは, Asir のさまざまな数式や, ユーザプ
ログラムなどがおかれるメモリの領域で, ガーベジコレクタにより管理されている. プログラムの動作中は, ヒープの大きさは単調非減少であり, 実メモリの量をこえて大きくなった場合には, OSによるスワップエリアへの読み書きがほとんどの計算時間を占めることになる.
• 実メモリが少ない場合には, 起動時の -adj オプションにより, GC 主体の設定を行っておく必要がある.
% asir -adj 16[0] load("fctrdata")$0[97] cputime(1)$0msec[98] heap();
5242880msec[99] fctr(Wang[8])$3.190sec + gc : 3.420sec[100] heap();
11182080msec[101] quit;486

% asir[0] load("fctrdata")$0[97] cputime(1)$0msec[98] heap();
8273920msec[99] fctr(Wang[8])$3.000sec + gc : 1.180sec[100] heap();
16261120msec[101] quit;
378. version():: Asir のバージョン（整数）を返す.
[0] version();991214379. shell(command):: command をシェルコマンドとして実行する• command を C の system() 函数によりシェルコマンドとして実行する. シェルの終了ステータ
スを返す．

[0] shell("ls");
alg
da
algt
defs.halpi
edetasir.ofee
asir_symtab
gr
base
gr.h
bgk
help
chou
hom
const
ifplotcyclicis0

katsurakimurakimura3
mfee
mksym
mp
msubst
p
proot
r

ralg
ratint
robot
sasa
shira
snf1
solve
sp
strum
sugar

suit
test
texput.log
wang
wang_datawt

380. map(function,arg0,arg1,...):: リスト, 配列の各要素に函数を適用する• arg0 の各要素を最初の引数, arg1 以下の残りの引数として函数 function を呼び出し, arg0 の対応する要素の位置に函数呼び出しの結果が入った同じ型のオブジェクトを生成して返す.
• function は, ダブルクォートのない函数名を用いる.
• function にプログラム変数は使えない.
• arg0 がリスト, ベクトル, 行列以外の場合, 単に arg0, arg1, ... を引数として function を呼び出しその結果を返す.
• map の引数 function で与えられる函数は, 内部的にも函数として実装されていなければならない.

487

そうでなければ parse error になる. 例えば map 自身や car, cdr などは内部的には函数ではなく,Asir の文法におけるキーワードとして実装されている. したがって map の引数に map をとることはできない• オプションやネスティングが可能な函数 mtransbys() がある．

[0] def afo(X) { return X^3; }[1] map(afo,[1,2,3]);[1,8,27]381. flist():: 現在定義されている組み込み函数, ユーザ定義函数の函数名を文字列リストとして返す• システム函数の後にユーザ定義函数が続く.
[0] flist();[defpoly,newalg,mainalg,algtorat,rattoalg,getalg,alg,algv,...]
382. delete history([index]):: ヒストリを消去する• 引数がないとき, これまで計算したヒストリを全て消去する.
• 引数があるとき, その番号の結果のみ消去する.
• ここでヒストリとは, 番号つきのプロンプトに対しての入力を評価して得られた式で, この式は@number により取り出すことができる. このことは, ガーベッジコレクションの際にもこの式が生き残ることを意味する.
• 大きな式がヒストリとして残った場合, 以降のメモリ管理に支障を来す場合が多いため, bsave()などでファイルにセーブして, delete_history() によりヒストリを消去しておくのが有効である.
[0] (x+y+z)^100$[1] @0;...
[2] delete_history(0);[3] @0;0383. get rootdir():: Asir のルートディレクトリ名を取り出す• UNIX 版の場合, 環境変数 ASIR LIBDIR が定義されている場合にはその値, されていない場合には ‘/usr/local/lib/asir’ を返す.
• Windows 版の場合, ‘asirgui.exe’ のあるディレクトリ (‘bin’ という名前のはずである) の親
ディレクトリが返される.
• この関数が返すディレクトリ名を基準とした相対パス名を指定することにより, インストールされた場所によらないファイル読み込みプログラムを書くことができる.
384. getopt([key]):: オプションの値を返す• ユーザ定義関数は, 固定個数引数でしか宣言できない. ユーザ定義関数で可変個引数を実現する方法の一つとして, オプションによる引数の指定がある (see オプション指定). 指定されたオプションを関数内で受け取るためにこの関数を用いる.
• 無引数で呼び出された場合, getopt() は [[key1,value1],[key2,value2],...] なるリストを返す. ここで, key は関数呼び出し時に指定されたオプション, value はその値である.
• 関数呼び出しの際に key がオプションとして指定されている場合には, その値を返す. もし指定がない場合には, VOID 型オブジェクト (型識別子 −1) を返す. getopt() が返した値の型を488

type() で調べることで, そのオプションが指定されたかどうか調べることができる.
• 関数呼び出しにおけるオプションの指定は, 正規の引数ならびの後ろにxxx(A,B,C,D|x=X,y=Y,z=Z)という風に, ‘|’ に続く, key=value の ‘,’ で区切られた並びを置くことで行う.
385. getenv(name):: 環境変数 name の値を返す[0] getenv("HOME");/home/pcrf/noro

3.4 Functions in the contributed library
3.4.1 基礎 (標準函数)
1. base cancel(S):: 分母と分子の共通項を探して簡略化する[0] base_cancel([(x-1)/(x^2-1), (x-1)/(x^3-1)]);[(1)/(x+1),(1)/(x^2+x+1)]
2. base choose(L,M ):: リスト L の M 個の成分からなる部分集合のリストのリストを返す[0] base_choose([1,2,3],2);[[3,2],[2,1],[3,1]]
参照：nextsub()3. base flatten(S):: リスト S のネストをはずす[0] base_flatten([[1,2,[3,4]],5]);[1,2,3,4,5]
参照：m2l()4. base intersection(A,B):: A と B の共通部分集合を返す[0] base_intersection([1,2,3],[2,3,5,[6,5]]);[2,3]
参照：高機能な lsort() がある．
5. base makelist(Obj,K,B,T |qt=1,step=d):: It generate a list from Obj where K runs in [B,T ]• Options are qt=1 (keep quote data), step (step size).
• When B is a list, T is ignored and K runs in B.

[0] base_makelist(k^2,k,1,10);[1,4,9,16,25,36,49,64,81,100][1] map(print_input_form,base_makelist(quote(x^2),x,1,10 |qt=1, step=0.5));[quote(1^2),quote(1.5^2),quote(2^2),quote(2.5^2),quote(3^2),quote(3.5^2),
quote(4^2),quote(4.5^2),...,quote(10^2)][2] base_makelist(quote("the "+k),k,["cat","dog"],0);[the cat,the dog]489

6. base memberq(A,S): It returns 1 if A is a member of the set S else returns 0[0] base_memberq(2,[1,2,3]);
1
7. base permutation(L):: It outputs all permutations of L.
BUG; it uses a slow algorithm[0] base_permutation([1,2,3,4]);[[1,2,3,4],[1,2,4,3],[1,3,2,4],...,[4,3,2,1]]
参照：nextsub()

8. base position(A,S):: It returns the position of A in S
[0] base_position("cat",["dog","cat","monkey"]);1
参照：findin()

9. base product(Obj,K,B,T ):: base product returns the product of Obj where K runs in [B,T].
• Options are qt=1 (keep quote data), step (step size).
• When B is a list, K runs in B and T is ignored.
[0] base_product(k^2,k,1,10);13168189440000[1] base_product(quote(x^2),x,1,10 | qt=1, step=0.5);
quote(1*1^2*1.5^2*2^2*2.5^2*3^2*3.5^2*4^2*...*10^2)[2] base_product(quote(x^2),x,[a,b,c],0 | qt=1);
quote(1*a^2*b^2*c^2)
10. base prune(A,S):: It returns a list in which A is removed from S[0] base_prune("cat",["dog","cat","monkey"]);[dog,monkey]
11. base rebuild opt(Opt):: It rebuilt the option list Opt[0] base_rebuild_opt([[key1,1],[key2,3]] | remove_keys=["key2"]);[[key1,1]]
参照：delopt() はより高機能

12. base replace(S,Rule):: It rewrites S by using the rule Rule[0] base_replace(x^2+y^2,[[x,a+1],[y,b]]);a^2+2*a+b^2+1
x is replaced by a + 1 and y is replaced by b in x2 + y 2
参照：mysubst(), mulsubst(), psubst()

490

13. base replace n(S,Rule):: It rewrites S by using the rule Rule.
It is used only for specializing variables to numbers and faster than base replace()[0] base_replace_n(x^2+y^2,[[x,1/2],[y,2.0+3*@i]]);(-4.75+12*@i)x is replaced by 1/2 and y is replaced by 2.0+3*@i in x^2+y^2
14. base set minus(A,B):: It returns A \ B[0] base_set_minus([1,2,3],[3,4,5]);[1,2]
参照：lsort()
15. base set union(A,B):: It returns A ∪ B[0] base_set_union([1,2,3],[3,4,5]);[5,4,3,2,1]
参照：lsort()
16. base subsetq(A,B):: A ⊂ B?

[0] base_subsetq([1,2],[1,2,3,4,5]);
1[1] base_subsetq([2,1,1],[1,2,3,4]);
1
17. base subsets of size(K,S):: It outputs all subsets of S of the size K.
BUG; it uses a slow algorithm. Do not input a large S.
[0] base_subsets_of_size(2,[3,5,3,2]);[[3,2],[5,2],[3,5],[3,2]]
参照：nextsub()18. base sum(Obj,K,B,T ):: It returns the sum of Obj where K runs in [B,T ]• Options are qt=1 (keep quote data), step (step size).
• When B is a list, K runs in B and T is ignored.
• When K is 0, then Obj is assumed to be a list or vector and Obj[B]+ · · · +Obj[T ] is returned.

[0] base_sum(k^2,k,1,10);385[1] base_sum(quote(x^2),x,1,10 | qt=1, step=0.5);
quote(1^2+1.5^2+...+9.5^2+10^2)[2] base_sum(quote(x^2),x,[a,b,c],0 | qt=1);
quote(a^2+b^2+c^2)
参照：fsum()

19. base var list(Name,B,T )491

:: generate a list of variables Name+Index where Index runs on [B,T ].
[0] base_var_list(x,0,10);[x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10][1] base_var_list(x,1,4 | d = 1); /* Options are d=1 (add d before the name) */[dx1,dx2,dx3,dx4]
3.4.2 数（数学標準函数）
20. number abs(X)::[0] number_abs(-3);
3[1] number_abs(@i-1);
1.4142135623730950488016887242096980786
21. number ceiling(X)::[0] number_ceiling(1.5);
2
22. number factor(X):: It factors the given integer X.
[0] number_factor(20);[ 2 2 ]
[ 5 1 ]
参照：pari(factor,)
23. number float to rational(X|prec=m)::[0] number_float_to_rational(1.5234 | prec=14);
参照：cfrac()
24. number floor(X)::[0] number_floor(1.5);
125. number imaginary part(X)::[0] number_imaginary_part(1+2*@i);2
26. number is integer(X)::[0] number_is_integer(2/3);
0492

27. number real part(X)::[0] number_real_part(1+2*@i);1
3.4.3 行列（数学標準函数）
28. matrix adjugate(M ):: It generates the adjugate matrix of the matrix M[0] matrix_adjugate(matrix_list_to_matrix([[a,b],[c,d]]));[ d -b ][ -c a ]参照：pari(adj,)
29. matrix clone(M ):: It generates the clone of the matrix M[0] matrix_clone(matrix_list_to_matrix([[1,1],[0,1]]));[ 1 1 ]
[ 0 1 ]
参照：dupmat()

30. matrix image(M ):: It computes the image of M . Redundant vectors are removed[0] matrix_image([[1,2,3],[2,4,6],[1,0,0]]);[[1,0,0],[0,2,3]]
参照：myimage()

31. matrix matrix to list(M ):: It translates the matrix M to a list.
参照：m2ll()
32. matrix list to matrix(M ):: It translates the list M to a matrix[0] print_xdvi_form(matrix_list_to_matrix([[1,1],[0,2]]));
参照：lv2m()
33. matrix diagonal matrix(L):: It returns the diagonal matrix with diagonal entries L[0] matrix_diagonal_matrix([1,2,3]);[ 1 0 0 ][ 0 2 0 ][ 0 0 3 ]参照：diagm()

34. matrix identity matrix(N ): It returns the identity matrix of the size N[0] matrix_identity_matrix(5);[ 1 0 0 0 0 ]493

[ 0 1 0 0 0 ][ 0 0 1 0 0 ][ 0 0 0 1 0 ][ 0 0 0 0 1 ]参照：diagm()
35. matrix inner product(A,B):: It returns the inner product of two vectors A and B[0] matrix_inner_product([1,2],[x,y]);x+2*y36. matrix transpose(M ):: It returns the transpose of the matrix M
参照: mtranspose()
37. matrix inverse(M ):: It returns the inverse of the matrix M[0] matrix_inverse([[1,2],[0,1]]);[ 1 -2 ][ 0 1 ]
参照：myinv(), invmat()
38. matrix det(M ):: It returns the determinant of the matrix M[0] poly_factor(matrix_det([[1,x,x^2],[1,y,y^2],[1,z,z^2]]));
new__poly_factored_polynomial([[-1,1],[y-z,1],[x-z,1],[x-y,1]])
参照：mydet(), mydet2(), nd det()
39. matrix solve linear(M ,X,B):: It solves the system of linear equations M X = B[0] matrix_solve_linear([[1,2],[0,1]],[x,y],[1,2]);[[x,-3],[y,2]]
参照：mtoupper()40. matrix submatrix(M ,Ind):: It returns the submatrix of M deﬁned by the index set Ind[0] matrix_submatrix([[0,1],[2,3],[4,5]],[1,2]);[[2,3],[4,5]]
参照：mperm() がより高機能
41. matrix kernel(M ):: It returns the basis of the kernel of the matrix M .

[0] matrix_kernel([[1,1,1,1],[0,1,3,4]]);[2,[[1,0,-4,3],[0,1,-3,2]]][1] matrix_kernel([[x,y,1],[x,y,1]]);[2,[[1,0,-x],[0,1,-y]]][3] matrix_kernel([[x,y,1],[x,y,-1]]);[1,[[1,(x)/(-y),0]]]494

参照：mykernel()
42. matrix eigenavalues(M ):: It returns the eigenvalues of the matrix M .

[0] matrix_eigenvalues([[x,1],[0,y]]);[y,x][1] matrix_eigenvalues([[1,1],[1,-1]]);[omatrix_v^2-2]
43. matrix rank(M ):: It returns the rank of the matrix M .
[0] matrix_rank([[1,1,1,1],[0,1,3,4]]);2[1] matrix_rank([[x,-y],[-x,y]]);1
参照：myrank()

3.4.4 表示（数学標準函数）
44. print em(S):: It outputs S by a font to emphasize it.
[0] print_em(x^2-1);
45. print dvi form(S):: It outputs S to a dvi ﬁle.
[0] print_dvi_form(x^2-1);
46. print gif form(S| table=key0 ):: It outputs S to a ﬁle of the gif format
This function allows optional variables table[0] print_gif_form(newmat(2,2,[[x^2,x],[y^2-1,x/(x-1)]]));
47. print input form(S):: It transforms S to a string which can be parsed by asir.
[0] print_input_form(quote(x^3-1));
48. print open math xml form(S):: It transforms S to a string which is compliant to OpenMath(1999).
[0] print_open_math_xml_form(x^3-1);
www.openmath.org
49. print ox rfc100 xml form(S):: It transforms S to a string which is compliant to OpenXM RFC 100.
[0] print_ox_rfc100_xml_form(x^3-1);
50. print png form(S):: It transforms S to a ﬁle of the format png. dvipng should be installed.
[0] print_png_form(x^3-1);

495

51. print terminal form(S):: It transforms S to the terminal form???
52. print tex form(S|table=key0,raw=key1):: It transforms S to a string of the LATEX format• This function allows optional variables table, raw.
• The global variable Print tex form fraction format takes the values "auto", "frac", or"/".
• The global variable Print tex form no automatic subscript takes the values 0 or 1.
• The optional variable table is used to give a translation table of asir symbols and tex symbols.
• when AMSTeX = 1, "\begin{pmatrix}" and "\end{pmatrix}" will be used to output matrix.
• BUG; A large input S cannot be translated.
[0] print_tex_form(x*dx+1 | table=[["dx","\\partial_x"]]);
参照： ?
53. print xdvi form(S):: It transforms S to a xdvi ﬁle and previews the ﬁle by xdvi

[0] print_xdvi_form(newmat(2,2,[[x^2,x],[y^2-1,x/(x-1)]]));[1] print_xdvi_form(print_tex_form(1/2));
54. print xv form(S|input=key0 , format=key1 ):: It transforms S to a gif ﬁle and previews the ﬁle by xv.
• This function allows optional variables input, format.
• If the optional variable format="png" is set, png format will be used to generate an input forxv (cf. print tex form()).
[0] print_xv_form(newmat(2,2,[[x^2,x],[y^2-1,x/(x-1)]]));[1] print_xv_form(x+y|format="png");
print gif form()).
55. print tfb form(S): It transforms S to the tfb format.
[0] print_tfb_form(x+1);
56. print output(Obj|file=key0 ,mode=key1 ):: It outputs the object Obj to a ﬁleThis function allows optional variables file, mode
• If the optional variable file is set, then it outputs the Obj to the speciﬁed ﬁle, else it outputs
it to ”asi output tmp.txt”.
• If the optional variable mode is set to "w", then the ﬁle is newly created.
• If the optional variable is not set, the Obj is appended to the ﬁle.

[0] print_output("Hello"|file="test.txt");
See glib tops().
57. print open math tfb form(S): It transforms S to a tfb format of OpenMath XML.
It is experimental. You need to load taka print tfb.rr to call it.
print_open_math_tfb_form(quote(f(x,1/(y+1))+2));496

3.4.5 多項式（数学標準函数）
58. poly factor(F ):: It factorizes the polynomial F[0] poly_factor(x^10-y^10);
new__poly_factored_polynomial([[1,1],[x-y,1],[x+y,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]])59. poly gcd(F ,G):: It computes the polynomial GCD of F and G.
[0] poly_gcd(x^10-y^10,x^25-y^25);x^5-y^5
60. poly elimination ideal(I,V V ):: It computes the intersection of the ideal I and the subring K[V V ].
poly elimination ideal(I,V V |grobner basis=key0 ,v=key1 ,homo=key2 ,grace=key3 ,strategy=key4 ):: This function allows optional variables grobner basis, v, homo, grace, strategy
If grobner basis is ”yes”, I is assumed to be a Grobner basis. The optional variable v is a list ofvariables which deﬁnes the ring of polynomials.
poly_elimination_ideal([x^2+y^2-4,x*y-1],[x]);A = poly_grobner_basis([x^2+y^2-4,x*y-1]|order=2,v=[y,x]);
poly_elimination_ideal(A,[x]|grobner_basis="yes");
When strategy=1(default),
nd_gr is used when trace=0(default),
nd_gr_trace is used when trace=1.
参照：gr , hgr , gr mod , dp *61. poly expand(F ):: This is an alias of poly sort.
See poly sort().
62. poly grobner basis(I|order=key0 ,v=key1 ):: It returns the Grobner basis of I.
This function allows optional variables order, v• The optional variable v is a list of variables which deﬁnes the ring of polynomials.

[0] A = poly_grobner_basis([x^2+y^2-4,x*y-1]|order=2,v=[y,x],str=1);
A->Generators;
A->Ring->Variables;
A->Ring->Order;[1] B = poly_grobner_basis([x^2+y^2-4,x*y-1]|order=[[10,1]],v=[y,x]);[x^4-4*x^2+1,-x^3+4*x-y][2] C = poly_grobner_basis([x^2+y^2-4,x*y-1]|order=[block,[0,1],[0,1]],v=[y,x]);[x^4-4*x^2+1,-x^3+4*x-y]
63. poly hilbert polynomial(I|s=key0 ,v=key1 ):: It returns the Hilbert polynomial of the ideal I.
• This function allows optional variables s, v
• The optional variable v is a list of variables.
497

[0] poly_hilbert_polynomial([x1*y1,x1*y2,x2*y1,x2*y2]|s=k,v=[x1,x2,y1,y2]);64. poly in(I|order=key0 ,v=key1 ):: It is an alias of poly initial()
This function allows optional variables order, v[0] poly_in([x^2+y^2-4,x*y-1]|order=0,v=[x,y]);[y^3,x^2,y*x]
65. poly initial(I|order=key0 ,v=key1 ):: It returns the initial ideal of I with respect to the given order• This function allows optional variables order, v• The optional variable v is a list of variables.
[0] poly_initial([x^2+y^2-4,x*y-1]|order=0,v=[x,y]);[y^3,x^2,y*x][1] poly_initial([x^2+y^2-4,x*y-1]|order=0,v=[x,y],gb=1);[x^2,y*x]
66. poly initial coefficients(I)|order=key0 ,v=key1 ):: It computes the coeﬃcients of the initial ideal of I with respect to the given order• This function allows optional variables order, v• The optional variable v is a list of variables.
• The order is speciﬁed by the optional variable order.
[0] poly_initial_coefficients([x^2+y^2-4,x*y-1]|order=0,v=[x,y]);[1,1,1]
67. poly initial term(F |weight=key0 ,order=key1 ,v=key2 ):: It returns the initial term of a polynomial F with respect to the given weight vector• This function allows optional variables weight, order, v• The weight is given by the optional variable weight w.
[0] poly_initial_term(x^2+y^2-4|weight=[100,1],v=[x,y]);[x^2,200]
68. poly degree(F |weight=key0 ,v=key1 ):: It returns the degree of F with respect to the given weight vector• This function allows optional variables weight, v.
• The weight is given by the optional variable weight w. It returns[0] poly_degree(x^2+y^2-4 |weight=[100,1],v=[x,y]);200
69. poly gr w(F ,V ,W ):: It returns the Grobner basis of F for the weight vector W .
It is the second interface for poly grobner basis.
[0] poly_gr_w([x^2+y^2-1,x*y-1],[x,y],[1,0]);[y^4-y^2+1,-x-y^3+y]
See poly in w(), poly grobner bais().
70. poly r omatrix(N ):: It gives a weight matrix, which is used to compute a Grobner basis in K(x) < dx >, |x| =498

|dx| = N[0] poly_r_omatrix(3);[ 0 0 0 1 1 1 ][ 0 0 0 0 0 -1 ][ 0 0 0 0 -1 0 ][ 0 0 0 -1 0 0 ][ 1 1 1 0 0 0 ][ 0 0 -1 0 0 0 ][ 0 -1 0 0 0 0 ][ -1 0 0 0 0 0 ]See poly weight to omatrix()
71. poly in w (F |v=key0 ,weight=key1 ,gb=key2 ):: It returns the initial term or the initial ideal in w(F ) for the weight vector given by order• F is s single polynomial or a list of polynomials.
• This is a new interface of poly in w with shorter args.
• This function allows optional variables v, weight, gb[0] poly_in_w_([x^2+y^2-1,x*y-x]|v=[x,y],weight=[1,0]);[y^3-y^2-y+1,x^2,(y-1)*x]
参照： poly weight to omatrix(), poly grobner basis() , poly gr w().
72. poly in w(F ,V ,W |gb=key0 ):: It returns the initial term or the initial ideal in w(F ) for the weight vector given by order• F is s single polynomial or a list of polynomials.

• This function allows optional variables gb[0] poly_in_w([x^2+y^2-1,x*y-x]|v=[x,y],weight=[1,0]);
参照：poly weight to omatrix(), poly grobner basis() , poly gr w().
73. poly ord w(F ,V ,W ):: It returns the order with respect to W of F .

poly_ord_w(x^2+y^2-1,[x,y],[1,3]);
参照： poly in w()
74. poly solve linear(Eqs,V ):: It solves the system of linear equations Eqs with respect to the set of variables V .

[0] poly_solve_linear([2*x+3*y-z-2, x+y+z-1], [x,y,z]);[[y,-3/4*x+3/4],[z,-1/4*x+1/4]]
75. poly sort(F |v=key0 ,w=key1 ,truncate=key2 ):: It expands F with a given variables v=V and a given weight w=W• It returns a quote object.
• If trucate option is set, the expansion is truncated at the given degree.
• This function allows optional variables v, w, truncate[0] poly_sort((x-y-a)^3 | v=[x,y], w=[-1,-1]);
quote((-a^3)*1+(3*a^2)*x+(-3*a^2)*y+(-3*a)*x^2+(6*a)*y*x+(-3*a)*y^2+x^3+(-3)*y*x^2+(3)*y^2*x+(-1)*y^3)poly_sort((x-y-a)^3 | v=[x,y], w=[-1,-1])499

returns a series expansion in terms of x and y.
76. poly toric ideal(A,V ):: It returns generators of the aﬃne toric ideal deﬁned by the matrix(list) A. V is the list ofvariables.
poly_toric_ideal([[1,1,1,1],[0,1,2,3]],base_var_list(x,0,3));77. poly weight to omatrix(W ,V ):: It translates the weight vector W into a matrix, which is used to set the order in asir Grobnerbasis functions. V is the list of variables.
[0] M=poly_weight_to_omatrix([2,1,0],[x,y,z]);[ 2 1 0 ][ 1 1 1 ][ 0 0 -1 ][ 0 -1 0 ][ -1 0 0 ]78. poly prime dec(I,V ):: It computes the prime ideal decomposition of the radical of I. V is a list of variables.
[0] B=[x00*x11-x01*x10,x01*x12-x02*x11,x02*x13-x03*x12,x03*x14-x04*x13,-x11*x20+x21*x10,-x21*x12+x22*x11,-x22*x13+x23*x12,-x23*x14+x24*x13];[1] V=[x00,x01,x02,x03,x04,x10,x11,x12,x13,x14,x20,x21,x22,x23,x24];[2] poly_prime_dec(B,V|radical=1);
79. poly ideal intersection(I,J,V ,Ord):: It computes the intersection of the ideal I and J, V is the list of variables. Ord is the order.
[0] A=[j*h*g*f*e*d*b,j*i*g*d*c*b,j*i*h*g*d*b,j*i*h*e*b,i*e*c*b,z]$[1] B=[a*d-j*c,b*c,d*e-f*g*h]$[2] V=[a,b,c,d,e,f,g,h,i,j,z]$[3] poly_ideal_intersection(A,B,V,0);80. poly ideal colon(I,J,V ):: It computes the colon ideal of I by J, V is the list of variables.
[0] B=[(x+y+z)^50,(x-y+z)^50]$[1] V=[x,y,z]$[2] B=poly_ideal_colon(B,[(x+y+z)^49,(x-y+z)^49],V);
81. poly ideal saturation(I,J,V ):: It computes the saturation ideal of I by J. V is the list of variables.
[0] B=[(x+y+z)^50,(x-y+z)^50]$[1] V=[x,y,z]$[2] B=poly_ideal_saturation(B,[(x+y+z)^49,(x-y+z)^49],V);82. poly coefficient(F ,Deg,V ):: It returns the coeﬃcient of V Deg in F . F may be rational or list or vector.
[0] F=[(x+y+z)^10/z^2,(x-y+z)^10/z^3]$[1] poly_coefficient(F,10,x);500

グラフィックライブラリ（2 次元）ライブラリ glib は, Risa/Asir の グラフィック基本関数 (draw obj()) に対する, 昔の BASIC のよ
うな単純なインタフェースを提供する.

3.4.6

83. glib open():: It starts the ox plot server and opens a canvas.
• The canvas size is set to Glib canvas x×Glib canvas y (the default value is 400).
• This function is automatically called when the user calls glib functions.
84. glib clear():: Clear the screen.
85. glib window(Xmin ,Ymin ,Xmax ,Ymax ):: It generates a window with the left top corner [Xmin ,Ymin ] and the right bottom corner[Xmax ,Ymax ].
If the global variable Glib math coordinate is set to 1, mathematical coordinate system will be
employed, i.e., the left top corner will have the coordinate [Xmin,Y max].
[0] glib_window(-1,-1,10,10);
86. glib putpixel(X,Y |color=key0 ):: It puts a pixel at [X,Y ] with color
This function allows optional variables color[0] glib_putpixel(1,2 | color=0xffff00);
87. glib line(X0 ,Y0 ,X1 ,Y1 |color=key0 ,shape=key1 ):: It draws the line [X0 ,Y0 ] – [X1 ,Y1 ] with color and shape
This function allows optional variables color, shape[0] glib_line(0,0,5,3/2 | color=0xff00ff);[1] glib_line(0,0,10,0 | shape=arrow);
88. glib print(X,Y ,Text|color=key0 ):: It put a string Text at [X,Y ] on the glib canvas
This function allows optional variables color[0] glib_print(100,100,"Hello Worlds" | color=0xff0000);
89. glib tops():: If Glib ps is set to 1, it returns a postscript program to draw the picture on the canvas.
参照： print output()
90. glib ps form(S):: It returns the PS code generated by executing S (experimental).
[0] glib_ps_form(quote( glib_line(0,0,100,100) ));[1] glib_ps_form(quote([glib_line(0,0,100,100),glib_line(100,0,0,100)]));
参照： glib tops()

91. glib plot(F ):: It plots an object F on the glib canvas.
[0] glib_plot([[0,1],[0.1,0.9],[0.2,0.7],[0.3,0.5],[0.4,0.8]]);[1] glib_plot(tan(x));
92. glib flush()
501

:: Flush the output. (Cfep only. It also set initGL to 1.).
93. glib set pixel size(P ):: Set the size of putpixel to P
1.0 is the default. (cfep only).
94. glib remove last():: Remove the last object.
glib flush() should also be called to remove the last object. (cfep only).
3.4.7 OpenXM-Conrib 一般函数
95. ox check errors2(p):: 識別番号 p のサーバのスタック上にあるエラーオブジェクトをリストで戻す.
• 識別番号 p のサーバのスタック上にあるエラーオブジェクトをリストで戻す.
• エラーオブジェクトのポップはしない.
[0] P=sm1.start();0[1] sm1.sm1(P," 0 get ");0[2] ox_check_errors2(P);[error([7,4294967295,executeString: Usage:get])]Error on the server of the process number = 1
To clean the stack of the ox server,
type in ox_pops(P,N) (P: process number, N: the number of data you need to pop)
out of the debug mode.
If you like to automatically clean data on the server stack,set XM_debug=0;
3.4.8 OXShell の関数
OXshell はシステムのコマンドを ox server より実行する仕組みである. 詳しくはOpenXM/src/kan96xx/Doc/oxshell.oxw および OpenXM/doc/Papers/rims-2003-12-16-ja.tex
を見よ

96. oxshell.oxshell(L):: It executes command L on a ox shell server• L must be an array.
• The result is the outputs to stdout and stderr.
• A temporary ﬁle will be generated under $TMP.
参照： oxshell.keep tmp()[0] oxshell.oxshell(["ls"]);
参照： ox shell.ox shell(), oxshell.set value(), oxshell.get value(), oxshell, of, sm1.
97. oxshell.set value(Name,V ):: It set the value V to the variable Name on the server ox shell.

[0] oxshell.set_value("abc","Hello world!");[1] oxshell.oxshell(["cat", "stringIn://abc"]);
参照： oxshell.oxshell() , oxshell.get value()
98. oxshell.get value(Name,V ):: It get the value of the variable Name on the server ox shell.

502

[0] oxshell.set_value("abc","Hello world!");[1] oxshell.oxshell(["cp", "stringIn://abc", "stringOut://result"]);[2] oxshell.get_value("result");
What we do is a ﬁle $TMP/abc* is generated with the contents Hello world! and copied to$TMP/result*
The contents of the ﬁle is stored in the variable result on ox sm1.
参照：oxshell.oxshell() , oxshell.set value()
3.4.9 OpenMath 函数 (1999 版)‘om’ にこの節で定義されている関数が定義されている.
Java の実行環境が設定されていることが必要である.
Author of OMproxy : Yasushi Tamura , tamura@math.kobe-u.ac.jp
99. om start():: OMproxy をスタートする.
このサーバは CMO と OpenMath XML (CD’s in 1999) との間の変換をおこなう.
[0] load("om");
1[1] om_start();control: wait OX
Trying to connect to the server... Done.
0[2] om_xml(<<1,0>>+2*<<0,1>>);<OMOBJ><OMA><OMS name="DMP" cd="poly"/><OMA><OMS name="PolyRing" cd="poly"/><OMI>2</OMI></OMA><OMA><OMS name="SDMP" cd="poly"/><OMA><OMS name="Monom" cd="poly"/><OMI>1</OMI><OMI>1</OMI><OMI>0</OMI></OMA><OMA><OMS name="Monom" cd="poly"/><OMI>2</OMI><OMI>0</OMI><OMI>1</OMI></OMA></OMA></OMA></OMOBJ>[3] om_xml_to_cmo(@);(1)*<<1,0>>+(2)*<<0,1>>
100. om xml(s|proc=p):: s の CMO 表現を OpenMath の XML (CD’s in 1999) 表現になおす[0] For (I=0; I<10; I++) {A = 2^I;
B = om_xml(A);C = om_xml_to_cmo(B);print(A == C);}101. om xml to cmo(s|proc=p):: OpenMath の XML (CD’s in 1999) 表現 s を CMO になおす
3.4.10 Diﬀerential equations (by Okutani)
ファイル ‘gr’, ‘Matrix’, ‘Diff’ が必要です.
503

OpenXM/Risa/Asir での利用にあたっては,[0] load("Diff")$
が始めに必要.

Yukio Okutani 氏による Risa/Asir 言語で書かれた連立線形偏微分方程式用 のライブラリです.
すべての関数名は odiff_ で始まります.
102. odiff op appell4(a,b,c1 ,c2 ,V ):: Appell の F4 を零化する微分作用素を生成します.
[0] odiff_op_appell4(a,b,c1,c2,[x,y]);[ [ [-x^2+x,[2,0]], [-2*y*x,[1,1]], [-y^2,[0,2]],[(-a-b-1)*x+c1,[1,0]], [(-a-b-1)*y,[0,1]], [-b*a,[0,0]] ],[ [-y^2+y,[0,2]], [-2*y*x,[1,1]], [-x^2,[2,0]],[(-a-b-1)*y+c2,[0,1]], [(-a-b-1)*x,[1,0]], [-b*a,[0,0]] ] ]103. odiff op tosm1(LL,V ):: リスト形式の微分作用素リストを sm1 形式に変換します
微分作用素の係数は整数多項式に変換されます.
[0] odiff_op_tosm1([[[x,[2,0]],[-1,[0,0]]],[[y,[0,2]],[-1,[0,0]]]],[x,y]);[ + ( + (1) x) dx^2 + ( + (-1)), + ( + (1) y) dy^2 + ( + (-1))][1] odiff_op_tosm1([[[x,[1,0]],[y,[0,1]],[1,[0,0]]],[[1,[2,0]],[1,[0,2]]]],[x,y]);[ + ( + (1) x) dx + ( + (1) y) dy + ( + (1)), + ( + (1)) dx^2 + ( + (1)) dy^2][2] odiff_op_tosm1([[[1/2,[1,0]],[1,[0,0]]],[[1/3,[0,1]],[1/4,[0,0]]]],[x,y]);[ + ( + (6)) dx + ( + (12)), + ( + (4)) dy + ( + (3))][3] odiff_op_tosm1([[[1/2*x,[1,0]],[1,[0,0]]],[[1/3*y,[0,1]],[1/4,[0,0]]]],[x,y]);[ + ( + (6) x) dx + ( + (12)), + ( + (4) y) dy + ( + (3))]
104. odiff op toasir(LL,V ):: リスト形式の微分作用素リスト LL を asir の多項式に変換します.
[0] odiff_op_toasir([[[1/2*x,[1,0]],[1,[0,0]]],[[1/3*y,[0,1]],[1/4,[0,0]]]],[x,y]);[1/2*x*dx+1,1/3*y*dy+1/4][1] odiff_op_toasir([[[x,[1,0]],[y,[0,1]],[1,[0,0]]],[[1,[2,0]],[1,[0,2]]]],[x,y]);[x*dx+y*dy+1,dx^2+dy^2]105. odiff op fromasir(Dlist ,V ):: asir の多項式からリスト形式の微分作用素リストに変換します.
[0] odiff_op_fromasir([1/2*x*dx+1,1/3*y*dy+1/4],[x,y]);[[[1/2*x,[1,0]],[1,[0,0]]],[[1/3*y,[0,1]],[1/4,[0,0]]]][1] odiff_op_fromasir([x*dx+y*dy+1,dx^2+dy^2],[x,y]);[[[x,[1,0]],[y,[0,1]],[1,[0,0]]],[[1,[2,0]],[1,[0,2]]]]504

106. odiff act(L,F ,V ):: 微分作用素 L を有理式 F に作用させる. V は変数リスト.
[0] odiff_act([[1,[2]]],x^3+x^2+x+1,[x]);6*x+2[1] odiff_act([[1,[1,0]],[1,[0,1]]],x^2+y^2,[x,y]);2*x+2*y[2] odiff_act(x*dx+y*dy, x^2+x*y+y^2, [x,y]);2*x^2+2*y*x+2*y^2107. odiff act appell4(a,b,c1 ,c2 ,F ,V ):: 微分作用素 odiff op appell4 を有理式 F に作用させる[0] odiff_act_appell4(1,0,1,1,x^2+y^2,[x,y]);[-6*x^2+4*x-6*y^2,-6*x^2-6*y^2+4*y][1] odiff_act_appell4(0,0,1,1,x^2+y^2,[x,y]);[-4*x^2+4*x-4*y^2,-4*x^2-4*y^2+4*y][2] odiff_act_appell4(-2,-2,-1,-1,x^2+y^2,[x,y]);[0,0]108. odiff poly solve(LL,N ,V ):: 与えられた線型微分方程式系の N 次以下の多項式解を求める[0] odiff_poly_solve([[[x,[1,0]],[-1,[0,0]]],[[y,[0,1]],[-1,[0,0]]]],5,[x,y]);[_4*y*x,[_4]][1] odiff_poly_solve([[[x,[1,0]],[-2,[0,0]]],[[y,[0,1]],[-2,[0,0]]]],5,[x,y]);[_33*y^2*x^2,[_33]][2] odiff_poly_solve([x*dx+y*dy-3,dx+dy],4,[x,y]);[-_126*x^3+3*_126*y*x^2-3*_126*y^2*x+_126*y^3,[_126]]
109. odiff poly solve hg1(a,b,c,V ):: ガウスの超幾何微分方程式の多項式解を求める[0] odiff_poly_solve_hg1(-3,-6,-5,[x]);[_1*x^6-2*_0*x^3+9/2*_0*x^2-18/5*_0*x+_0,[_0,_1]][1] odiff_poly_solve_hg1(-3,-6,-7,[x]);[-4/7*_2*x^3+15/7*_2*x^2-18/7*_2*x+_2,[_2]]110. odiff poly solve appell4(a,b,c1 ,c2 ,V ):: F4 がみたす線型微分方程式系の多項式解を求める[0] odiff_poly_solve_appell4(-3,1,-1,-1,[x,y]);[-_26*x^3+(3*_26*y+_26)*x^2+3*_24*y^2*x-_24*y^3+_24*y^2,[_24,_26]][1] odiff_poly_solve_appell4(-3,1,1,-1,[x,y]);[-3*_45*y^2*x-_45*y^3+_45*y^2,[_45]]
111. odiff rat solve(LL,Dn,N ,V ):: 与えられた線型微分方程式系の分母が Dn, 分子が N 次以下の多項式であるような解を求める[0] odiff_rat_solve([[[x,[1]],[1,[0]]]],x,1,[x]);[(_8)/(x),[_8]]505[1] odiff_rat_solve([x*(1-x)*dx^2+(1-3*x)*dx-1],1-x,2,[x]);[(_180)/(-x+1),[_180]][2] D = odiff_op_appell4(0,0,3,0,[x,y])$[3] odiff_rat_solve(D,x^2,2,[x,y]);[(_118*x^2-_114*y*x+1/2*_114*y^2+_114*y)/(x^2),[_114,_118]]
3.4.11 D-module (by Okutani)
ファイル ‘gr’, ‘xm’, ‘Matrix’, ‘Diff’, ‘Dmodule’ が必要です.
OpenXM/Risa/Asir での利用にあたっては,[0] load("Diff")$[1] load("Dmodule")$が始めに必要.

Yukio Okutani 氏による D-加群計算用の sm1 サーバとのインタフェースライブラリです.
すべての関数名は odmodule で始まります.
112. odmodule d op tosm1(LL,V ):: リスト形式の微分作用素リストを sm1 形式に変換します.
• 微分作用素の係数は整数多項式に変換されます.
• この関数は odiff op tosm1() と等価です.
[0] odmodule_d_op_tosm1([[[x,[2,0]],[-1,[0,0]]],[[y,[0,2]],[-1,[0,0]]]],[x,y]);[ + ( + (1) x) dx^2 + ( + (-1)), + ( + (1) y) dy^2 + ( + (-1))][1] odmodule_d_op_tosm1([[[x,[1,0]],[y,[0,1]],[1,[0,0]]],[[1,[2,0]],[1,[0,2]]]],[x,y]);[ + ( + (1) x) dx + ( + (1) y) dy + ( + (1)), + ( + (1)) dx^2 + ( + (1)) dy^2][2] odmodule_d_op_tosm1([[[1/2,[1,0]],[1,[0,0]]],[[1/3,[0,1]],[1/4,[0,0]]]],[x,y]);[ + ( + (6)) dx + ( + (12)), + ( + (4)) dy + ( + (3))][3] odmodule_d_op_tosm1([[[1/2*x,[1,0]],[1,[0,0]]],[[1/3*y,[0,1]],[1/4,[0,0]]]],[x,y]);[ + ( + (6) x) dx + ( + (12)), + ( + (4) y) dy + ( + (3))]
113. odmodule d op toasir(LL,V ):: リスト形式の微分作用素リスト LL を asir の多項式に変換します
この関数は diff op toasir() と等価です.
[0] odmodule_d_op_toasir([[[1/2*x,[1,0]],[1,[0,0]]],[[1/3*y,[0,1]],[1/4,[0,0]]]],[x,y]);[1/2*x*dx+1,1/3*y*dy+1/4][1] odmodule_d_op_toasir([[[x,[1,0]],[y,[0,1]],[1,[0,0]]],[[1,[2,0]],[1,[0,2]]]],[x,y]);[x*dx+y*dy+1,dx^2+dy^2]
114. odmodule d op fromasir(Dlist ,V ):: asir の多項式からリスト形式の微分作用素リストに変換します506この関数は diff op fromasir() と等価です.

[0] odmodule_d_op_fromasir([1/2*x*dx+1,1/3*y*dy+1/4],[x,y]);[[[1/2*x,[1,0]],[1,[0,0]]],[[1/3*y,[0,1]],[1/4,[0,0]]]][1] odmodule_d_op_fromasir([x*dx+y*dy+1,dx^2+dy^2],[x,y]);[[[x,[1,0]],[y,[0,1]],[1,[0,0]]],[[1,[2,0]],[1,[0,2]]]]115. odmodule ch ideal(Dideal ,V ):: Dideal の characteristic ideal を求めます
Dideal は generic parameter を含むことができます.
[0] odmodule_ch_ideal([x*dx+y*dy+a,dx^2+dy^2],[x,y]);[x*dx+y*dy,dx^2+dy^2,y*dy*dx-x*dy^2,(x^2+y^2)*dy^2][1] odmodule_ch_ideal(diff_op_appell4(a,b,c1,c2,[x,y]),[x,y]);[-x*dx^2+y*dy^2,2*y*x*dy*dx+(y*x+y^2-y)*dy^2,(2*y^2-2*y)*dy^2*dx+(-y*x+3*y^2+y)*dy^3,
2*y*x*dy^2*dx+(y*x^2+(-2*y^2-y)*x+y^3-y^2)*dy^3]116. odmodule restriction(Dideal ,V ,Rest):: Dideal の 0 次の restriction を求めます
Didea l は generic parameter を含むことができます.
[0] odmodule_restriction([x*dx+y*dy+a,dx^2+dy^2],[x,y],[y]);[[2,[-x*dx-a,-e0*x*dx-e0*a-e0]]]117. odmodule elimination(Dideal ,V ,Elim):: Dideal の elimination ideal を求めます
Didea l は generic parameter を含むことができます.
[0] odmodule_elimination([x*dx+y*dy+a,dx^2+dy^2],[x,y],[[y],[0]]);[x^2*dx^2+(2*a+2)*x*dx+a^2+a][1] odmodule_elimination([x*dx+y*dy+a,dx^2+dy^2],[x,y],[[y],[b]]);[(x^2+b^2)*dx^2+(2*a+2)*x*dx+a^2+a]
3.4.12 DSOLV 函数
この節は正則ホロノミック系を級数で解くための函数を集めてある.
アルゴリズムについては [SST] に説明がある.
このパッケージは次のコマンド load("dsolv"); でロードできる.
このパッケージは Diff および Dmodule を使用する.
OpenXM/Risa/Asir での利用にあたっては,[0] load("dsolv");$
が始めに必要. このパッケージは ox sm1 を利用している.
したがって使用できる変数は sm1 パッケージと同様の変数しか使えない.

118. dsolv dual(f ,v):: f のグレブナ双対• 変数 v 上の多項式環において, f のグレブナ双対を求める.
• f で生成されるイデアルは, v で生成される極大イデアルに 対して, primary でないといけない.
primary でない場合, この函数は無限ループにおちいる.
.
• Algorithm: この函数は本 [SST] の Algorithm 2.3.14 の実装である. 出力中の変数 x, y, .. をそれ
507

ぞれ log(x), log(y), · · · でおきかえると, これらの log 多項式は, f_(x->x*dx, y->y*dy, ...)
で生成される微分方程式系の解となっている.

[0] dsolv_dual([y-x^2,y+x^2],[x,y]);[x,1][1] dsolv_act(y*dy-sm1_mul(x*dx,x*dx,[x,y]),log(x),[x,y]);0[2] dsolv_act(y*dy+sm1_mul(x*dx,x*dx,[x,y]),log(x),[x,y]);0[3] primadec([y^2-x^3,x^2*y^2],[x,y]);[[[y^2-x^3,y^4,x^2*y^2],[y,x]]][4] dsolv_dual([y^2-x^3,x^2*y^2],[x,y]);[x*y^3+1/4*x^4*y, x^2*y, x*y^2+1/12*x^4, y^3+x^3*y,x^2, x*y, y^2+1/3*x^3, x, y, 1][5] dsolv_test_dual();119. dsolv starting term(f ,v,w):: 正則ホロノミック系 f の方向 w での級数解の Staring terms を計算する. ここで, v は変数の集合.
• 正則ホロノミック系 f の方向 w での級数解の Staring terms を計算する. ここで, v は変数の集合. 戻り値は次の形をしている: [[e1 , e2 ,...], [s1 , s2 , ...]]. ここで e1 は exponent ベク
トルであり s1 はこのベクトルに 対応する解の集合, 以下同様.
• 変数 Dsolv_message_starting_term を 1 にしておくと, この函数は計算の途中にいろいろとメッセージを出力する.
• Algorithm: Saito, Sturmfels, Takayama, Grobner Deformations of Hypergeometric Diﬀerential
Equations ([SST]), Chapter 2.
[0]
F = sm1_gkz( [ [[1,1,1,1,1],[1,1,0,-1,0],[0,1,1,-1,0]], [1,0,0]]);[[x5*dx5+x4*dx4+x3*dx3+x2*dx2+x1*dx1-1,-x4*dx4+x2*dx2+x1*dx1,-x4*dx4+x3*dx3+x2*dx2,-dx2*dx5+dx1*dx3,dx5^2-dx2*dx4],[x1,x2,x3,x4,x5]][1] A= dsolv_starting_term(F[0],F[1],[1,1,1,1,0])$Computing the initial ideal.
Done.
Computing a primary ideal decomposition.
Primary ideal decomposition of the initial Frobenius ideal
to the direction [1,1,1,1,0] is[[[x5+2*x4+x3-1,x5+3*x4-x2-1,x5+2*x4+x1-1,3*x5^2+(8*x4-6)*x5-8*x4+3,
x5^2-2*x5-8*x4^2+1,x5^3-3*x5^2+3*x5-1],[x5-1,x4,x3,x2,x1]]]/* root is [ 0 0 0 0 1 ] *//* dual system is */[x5^2+(-3/4*x4-1/2*x3-1/4*x2-1/2*x1)*x5+1/8*x4^2+(1/4*x3+1/4*x1)*x4+1/4*x2*x3-1/8*x2^2+1/4*x1*x2,
x4-2*x3+3*x2-2*x1,x5-x3+x2-x1,1][1] A[0];[[ 0 0 0 0 1 ]][2] map(fctr,A[1][0]);508[[[1/8,1],[x5,1],[log(x2)+log(x4)-2*log(x5),1],[2*log(x1)-log(x2)+2*log(x3)+log(x4)-4*log(x5),1]],[[1,1],[x5,1],[-2*log(x1)+3*log(x2)-2*log(x3)+log(x4),1]],[[1,1],[x5,1],[-log(x1)+log(x2)-log(x3)+log(x5),1]],[[1,1],[x5,1]]]
3.4.13 GNUPLOT 函数
この節では GNUPLOT の ox サーバ ox sm1 gnuplot とのインタフェース関数を解説する. これらの関数はファイル ‘gnuplot’ で定義されている. gnuplot は ‘\$(OpenXM_HOME)/lib/asir-contrib/’にある.
nobuki@yama:~$ asirThis is Risa/Asir, Version 20020802 (Kobe Distribution).
Copyright (C) 1994-2000, all rights reserved, FUJITSU LABORATORIES LIMITED.
Copyright 2000,2001, Risa/Asir committers, http://www.openxm.org/.
GC 6.1(alpha5) copyright 2001, H-J. Boehm, A. J. Demers, Xerox, SGI, HP.
PARI 2.2.1(alpha), copyright (C) 2000,
C. Batut, K. Belabas, D. Bernardi, H. Cohen and M. Olivier.
OpenXM/Risa/Asir-Contrib(20020804), Copyright 2000-2002, OpenXM.org
help("keyword"); ox_help(0); ox_help("keyword"); ox_grep("keyword");for help messages (unix version only).
[255] gnuplot.start();0[257] gnuplot.gnuplot("plot sin(x**2);");
関 数 gnuplot.heat(dt,step) は わ れ わ れ の GNUPLOT イ ン タ フ ェ ー ス 関 数 の デ モ で あ る. この 関 数 は 熱 伝 導 方 程 式 区 間 [0,1] は Heat N 個 に 分 割 さ れ る. static 変 数 Heat N は 関 数
gnuplot.set heat N() で設定する. 有名な Courant-Friedrichs-Levi 数 dt*Heat_N*Heat_N が 0.5以下であれば, 陽的差分スキームは安定である. CFL を変えることにより, 不安定性が生じるのを観察できる.

gnuplot.set_heat_N(20); gnuplot.heat(0.001,30);
gnuplot.set_heat_N(20); gnuplot.heat(0.003,30);(CFL number is 0.4)
(CFL > 0.5 unstable)

Author of GNUPLOT: Thomas Williams, Colin Kelley120. gnuplot.start():: Localhost で ox_sm1_gnuplot を起動する• 起動された ox_sm1_gnuplot の識別番号を戻す.
• Xm_noX=1 としておくと, ox_sm1_gnuplot 用の debug window が開かない.
• 識別番号は, Gnuplot_proc に格納される.
[0] P = gnuplot.start();
参照: ox launch(), gnuplot
121. gnuplot.gnuplot(s|proc=p):: GNUPLOT にコマンド s を実行してもらう• サーバは GNUPLOT のコマンド s を実行する. エラーがおきた場合 GNUPLOT 本体は終了してしまうが, ox_sm1_gnuplot は自動的に GNUPLOT 本体をリスタートする.
• GNUPLOT は長い多項式を正しく受けつけない.

509

• GNUPLOT は ^ をうけつけない. かわりに, ** を使う.
[0] P = gnuplot.start();0/* Plot 3 dimensional graph. */[1] gnuplot.gnuplot("splot x**2-y**2;"|proc=P);0/* Plot 2 dimensional graph. */[2] gnuplot.gnuplot("plot [-pi:pi] [-2:2] cos(x);");
0/* Output a graph as a postscript figure. */[3] gnuplot.output(|file="hoge.eps");
0[4] gnuplot.gnuplot("plot sin(x)*cos(x);");
0[5] gnuplot.gnuplot(|file="x11");0/* Plot 3 dimensional graph hiding unvisible lines. */[6] gnuplot.gnuplot("set hidden3d");0[7] gnuplot.gnuplot("splot (x**2+y**2)*sin(x**2+y**2)");0[8] gnuplot.gnuplot("set isosamples 50");0[9] gnuplot.gnuplot("splot (x**2+y**2)*sin(x**2+y**2)");
参照 : ox launch(), gnuplot.start(), rtostr(), gnuplot.plot dots() 参考書 : 矢吹道郎, 大竹
つよし; 使いこなす GNUPLOT, テクノプレス, ISBN4-924998-11-7

122. gnuplot.plot dots(d,s|proc=p):: 点の集合 d をスタイル s でプロットする.
• 点集合 d をスタイル s でプロットする. s は次のような文字列: ”style color point”. ここで styleには lines, points, linespoints, impulses, dots, steps, errorbars, boxes, boxerrorbars を選べる.
color には 1 (red), 2 (green), 3 (blue), 4, ... , 8 を選べる. point は 1 から 8 の数を入れる.
color, point は省略してよい.
• d == [ ] のときはスクリーンがまず消去される.
[0] P = gnuplot.start();0[1] gnuplot.plot_dots([ ],0);0[2] for (I=0; I<10; I++) gnuplot.plot_dots([[I,I^2]]," lines ");[2] A = [ ];[][4] for (I=0; I<10; I++) A = append(A,[ [I,I^2]]);[5] A;[[0,0],[1,1],[2,4],[3,9],[4,16],[5,25],[6,36],[7,49],[8,64],[9,81]][6] gnuplot.plot_dots(A," lines ");510

0
参照 : gnuplot.start(), plot ”ﬁleName” with options(GNUPLOT command), gnuplot.clean,gnuplot
123. gnuplot.heat(dt,step) :: 熱伝導方程式を数値的に解く• 熱伝導方程式 du/dt = d2 u/dx2 , u(t, 0) = u(t, 1) = 0 を初期条件 u(0, x) = x (0 ≤ x ≤ 0.5),
u(0, x) = 1 − x(0.5 ≤ x ≤ 1.0) で解く.
• Heat_N は空間方向でのメッシュの数.
• この関数は将来 pde_heat_demo と呼ばれる予定.
[0] Heat_N = 20$[1] gnuplot.heat(0.001,30)$
124. gnuplot.output(|file=s):: GNUPLOT にファイル s へポストスクリプトで出力するように頼む• s が "x11" または, この関数を引数無しでよぶと, 以後, X11 の display に graphics が出力される.
[0] gnuplot.output(|file="hoge.eps");
Graphic output of GNUPLOT will be written to hoge.eps as a Poscript file.
0[1] gnuplot.gnuplot("plot tan(x)+sin(x);");
0[2] gnuplot.output();
Usage of gnuplot.output: gnuplot.output(|file="string")
gnuplot.output(|file="x11")
Output device is set to X11
参照 : gnuplot
125. gnuplot.plot function(f|proc=p):: gnuplot サーバに f のグラフを書くように頼む[0] gnuplot.plot_function((x+sin(x))^2);0[1] gnuplot.plot_function([x,x^2,x^3]);0
参照 : gnuplot.to_gnuplot_format()126. gnuplot.stop():: GNUPLOT を停止し, 通信用の fifo ファイルを消す• GNUPLOT を停止し, 一時ディレクトリの下に作成された通信用の fifo ファイルを消す.
• 通信用の fifo ファイル名は gnuplot で始まる.
[0] gnuplot.stop()
参照 : gnuplot.start()
127. gnuplot.setenv(key,value)::• key は ”gnuplot.callingMethod” または ”plot.gnuplotexec”.
Use the old method to communicate with gnuplot (version 3).
This method does not use mkﬁfo, but we need a patched version of gnuplot.

[0] gnuplot.setenv("gnuplot.callingMethod",0);511

[1] gnuplot.setenv("plot.gnuplotexec",getenv("OpenXM_HOME")+"/bin/gnuplot4ox");/*Calling your own gnuplot binary. */[2] gnuplot.setenv("plot.gnuplotexec","/cygdrive/c/program files/gnuplot/pgnuplot.exe");
参照 : gnuplot.start()
p Fq に関するコホモロジー
この節では超幾何関数 p Fq の (コ) ホモロジ群に関連した不変量を計算する関数を解説する.
OpenXM/Risa/Asir での利用にあたっては,

3.4.14load("pfpcoh.rr")$ load("pfphom.rr")$
が始めに必要.
128. pfp omega(p): It returns the Gauss-Manin connection Omega for the generalized hypergeometric function
p Fp−1 (aa1 , aa2 , . . . ; cc1 , cc2 , . . . ; x)
• Deﬁne a vector valued function Y of which elements are generalized hypergeometric function
f1 = F and f2 = xdf1 /dx, f3 = xdf2 /dx, . . .
• It satisﬁes dY /dx = ΩY .
• Generalized hypergeometric function is deﬁned by the series
p Fp−1 (aa1 , aa2 , . . . ; cc1 , cc2 , . . . ; x) =∞X
(aa1 )k (aa2 )k · · · kx(1)k (cc1 )k (cc2 )k · · ·k=0

pfp_omega(3);129. pfpcoh intersection(p):: returns an intersection matrix for cocycles associated to the generalized hypergeometric function
p Fp−1 .
This program pfpcoh.rr computes an intersection matrix S of cocycles of p Fp−1 and compares itwith the matrix obtained by solving a diﬀerential equation for intersection matrix.
Algorithm: Ohara, Sugiki, Takayama, Quadratic Relations for Generalized Hypergeometric Functions p Fp−1[0] load("pfpcoh.rr")$[1] S=pfpcoh_intersection(3);Author : K.Ohara
130. pfphom intersection(p):: intersection matrix of homology cycles• Computing intersection matrix of cycles associated to p Fp−1 .
• As to the meaning of parameters c1 , c2 , c3 , . . . see the paper Ohara, Kyushu J. Math. Vol. 51
PP.123.
• Algorithm: Ohara, Sugiki, Takayama, Quadratic Relations for Generalized Hypergeometric
Functions p Fp−1[0] SS = pfphom_intersection(3)$/* You get the intersection matrix of homologies for ${}_3 F_2$ */Author : K.Ohara
131. pfphom monodromy pair kyushu(p):: It returns the pair of monodromy matrices
Algorithm: Ohara, Kyushu J. Math. Vol.51 PP.123 (1997)
512

[0] MP = pfphom_monodromy_pair_kyushu(3)$You get a pair of monodromy matricies for 3 F2 standing for two paths encircling 0 and 1.
3.4.15 PHC 函数
この節では PHC pack の ox サーバ ox_sm1_phc とのインタフェース関数を解説する. これらの関数
はファイル ‘phc’ で定義されている. phc は ‘$(OpenXM_HOME)/lib/asir-contrib’ にある.
nobuki@yama:~$ asirThis is Risa/Asir, Version 20020802 (Kobe Distribution).
Copyright (C) 1994-2000, all rights reserved, FUJITSU LABORATORIES LIMITED.
Copyright 2000,2001, Risa/Asir committers, http://www.openxm.org/.
GC 6.1(alpha5) copyright 2001, H-J. Boehm, A. J. Demers, Xerox, SGI, HP.
PARI 2.2.1(alpha), copyright (C) 2000,
C. Batut, K. Belabas, D. Bernardi, H. Cohen and M. Olivier.
OpenXM/Risa/Asir-Contrib(20020804), Copyright 2000-2002, OpenXM.org
help("keyword"); ox_help(0); ox_help("keyword"); ox_grep("keyword");for help messages (unix version only).
[0] phc.start();0[1] phc.phc([x^2+y^2-4,x*y-1]);
The detailed output is in the file tmp.output.*
The answer is in the variable Phc.
0[2] Phc ;[[[-0.517638,0],[-1.93185,0]],[[1.93185,0],[0.517638,0]],[[-1.93185,0],[-0.517638,0]],[[0.517638,0],[1.93185,0]]]Author of PHC pack: Jan Verschelde.
参考書 1: Jan Verschelde, PHCpack: A general-purpose solver for polynomial systems by homotopy
continuation”. ACM Transaction on Mathematical Softwares, 25(2): 251-276, 1999.
参考書 2: Cox, D., O’Shea, Little, J., Using Algebraic Geometry, Springer. Mixed volumes につい
ての
章を見よ.

132. phc.start ():: Localhost で ox sm1 phc() を起動する.
• Localhost で ox sm1 phc() を起動する.
• 起動された ox sm1 phc() の識別番号を戻す.
• Xm_noX =1 としておくと, ox sm1 phc() 用の debug window が開かない.
• 識別番号は Phc proc に格納される. P = phc.start()
参照 ox launch(), phc
133. phc.phc(s|proc=p):: PHC pack に代数方程式系 s の解をすべてもとめてくれるように頼む• 代数方程式系 S をホモトピー法で解くために PHC pack を呼ぶ.
• PHC pack を開発したのは Jan Verschelde である. オリジナルの配布元は www.mth.msu.edu/ janである. PHC pack は代数方程式系を解くためにいろいろな戦略をえらぶことができるが, このイ

513

ンタフェース関数では, black-box solver しか用いていない. black-box solver は一般的な戦略ではあるが, 能率的ではない.
• この関数で代数方程式を解くのに失敗したら, オリジナルの PHC pack を用い, ほかの戦略を試してみるとよい.
• PHC は作業ファイル tmp.phc.out.pid, tmp.input.*, tmp.output.* を生成する. ここで pidは ox_sm1_phc() のプロセス番号である.
• ファイル tmp.output.* には PHC pack がどのように方程式系を解いたのかの詳しい情報がはいっている.
• 変数の数と方程式の数 length(s) は等しくないといけない.

• Algorithm: Jan Verschelde, PHCpack: A general-purpose solver for polynomial systems byhomotopy continuation”. ACM Transaction on Mathematical Softwares, 25(2): 251-276, 1999.
[0] P = phc.start();0[1] phc.phc([x^2+y^2-4,x*y-1]|proc=P);0/* The detailed output is in the file tmp.output.* *//* The answer is in the variable Phc. */[2] Phc;[[[-1.93185,0],[-0.517638,0]],[[0.517638,0],[1.93185,0]],[[-0.517638,0],[-1.93185,0]],[[1.93185,0],[0.517638,0]]][[x=[real, imaginary], y=[real,imaginary]], /* the first solution */[x=[real, imaginary], y=[real,imaginary]], /* the second solution */...
参照 ox launch(), phc.start(), ‘$(OpenXM HOME)/bin/lin phcv2’(original PHC pack binary

for linux)
3.4.16 Plucker 関係式
134. plucker y(L):: Index 集合 L に対応する変数を戻す
Index 集合 L は小さい順にソートされる. このとき符号もともに計算される.
[0] plucker_y([1,2,3]);
y_1_2_3[1] plucker_y([2,1,3]);-y_1_2_3
135. plucker index(V ):: It gets the index of the variable V[0] plucker_index(plucker_y([1,2,3]));3.4.17 SM1 函数
この節では sm1 の ox サーバ ox sm1 forAsir とのインタフェース関数を解説する. これらの関数はファイル ‘sm1’ で定義されている. ‘sm1’ は ‘$(OpenXM_HOME)/lib/asir-contrib’ にある. シス
テム sm1 は微分作用素環で計算するためのシステムである. 計算代数幾何のいろいろな不変量の計算

514

が微分作用素の計算に帰着する. sm1 についての文書は OpenXM/doc/kan96xx にある. とくに断りがないかぎりこの節のすべての関数は, 有理数係数の式を入力としてうけつけない. すべての多項式の係数は整数でないといけない.

nobuki@yama:~$ asirThis is Risa/Asir, Version 20020802 (Kobe Distribution).
Copyright (C) 1994-2000, all rights reserved, FUJITSU LABORATORIES LIMITED.
Copyright 2000,2001, Risa/Asir committers, http://www.openxm.org/.
GC 6.1(alpha5) copyright 2001, H-J. Boehm, A. J. Demers, Xerox, SGI, HP.
PARI 2.2.1(alpha), copyright (C) 2000,
C. Batut, K. Belabas, D. Bernardi, H. Cohen and M. Olivier.
OpenXM/Risa/Asir-Contrib(20020804), Copyright 2000-2002, OpenXM.org
help("keyword"); ox_help(0); ox_help("keyword"); ox_grep("keyword");for help messages (unix version only).
[283] sm1.deRham([x*(x-1),[x]]);[1,2]
The author of sm1 : Nobuki Takayama, takayama@math.sci.kobe-u.ac.jp
The author of sm1 packages : Toshinori Oaku, oaku@twcu.ac.jp
Reference: [SST] Saito, M., Sturmfels, B., Takayama, N., Grobner Deformations of HypergeometricDiﬀerential Equations, 1999, Springer. See the appendix.
136. sm1.start():: localhost で ox sm1 forAsir をスタートする• localhost で ox sm1 forAsir をスタートする.
• サーバ ox sm1 forAsir の識別番号を戻す.
• Xm_noX = 1 とおくとサーバ ox sm1 forAsir をデバッグ用の ィンドウなしに起動できる.
• コマンド ord を用いて変数順序を正しく設定しておく必要が ある. たとえば, 変数 x と dx 上の微分作用素環 (dx は ?に対応) で計算しているとき, sm1 サーバは式を印刷したとき, 変数 dx は右側に集められ，変数 x は左側にあつめられていると仮定している.
• 次の例では, 変数 cc を sm1 での計算のために用いてはいけない.
• a より z のなかで, d と o を除いたもの, それから, x0, ..., x20, y0, ..., y20, z0, ..., z20 は, デフォールトで微分作用素環の変数として 使える (cf. Sm1 ord list in sm1).
• 識別番号は static Sm1 proc に格納される. この識別番号は関数 sm1.get Sm1 proc() でとりだすことができる.
[0] ord([da,a,db,b]);[da,a,db,b,dx,dy,dz,x,y,z,dt,ds,t,s,u,v,w,......... omit ..................
][1] a*da;a*da[2] cc*dcc;
dcc*cc[3] sm1.mul(da,a,[a]);a*da+1[4] sm1.mul(a,da,[a]);
a*da
515

参照 ox launch(), sm1.push int0(), sm1.push poly0(), ord137. sm1.sm1(p,s):: サーバ sm1 にコマンド列 s を実行してくれるようにたのむ
識別番号 p の sm1 サーバに コマンド列 s を実行してくれるように頼む. (次の例では, 識別番号 0)[0] sm1.sm1(0," ( (x-1)^2 ) . ");0[1] ox_pop_string(0);x^2-2*x+1[2] sm1.sm1(0," [(x*(x-1)) [(x)]] deRham ");0[3] ox_pop_string(0);[1 , 2]
参照 sm1.start(), ox push int0(), sm1.push poly0(), sm1.get Sm1 proc().

138. sm1.push int0(p,f ):: オブジェクト f を識別子 p のサーバへ送る• type(f ) が 2 (再帰多項式) のとき, f は文字列 (type == 7) に変換されて, (oxpushcmo) を用
いてサーバへ送られる.
• type(f ) が 0 (zero) のときは, サーバ上では, 32 bit 整数と解釈される.
なお ox push cmo(P ,0) はサーバに対して CMO_NULL をおくるので, サーバ側では, 32 bit 整数を受け取るわけではない.
• sm1 の整数は, 32 bit 整数と bignum にわけることができる.
• type(f ) が 1 (数) のとき, この関数は 32 bit integer をサーバに おくる. ox push cmo(p,1234)
は bignum の 1234 を sm1 サーバにおくることに注意しよう.
• その他の場合には ox push cmo() をデータ型の変換なしに呼び出す.
[219] P=sm1.start();0[220] sm1.push_int0(P,x*dx+1);0[221] A=ox_pop_cmo(P);x*dx+1[223] type(A);7(string)[271] sm1.push_int0(0,[x*(x-1),[x]]);0[272] ox_execute_string(0," deRham ");0[273] ox_pop_cmo(0);[1,2]Referenceox_push_cmo139. sm1.gb([f ,v,w]|proc=p,sorted=q,dehomogenize=r):: v 上の微分作用素環において f のグレブナ基底を計算する
140. sm1.gb d([f ,v,w]|proc=p):: v 上の微分作用素環において f のグレブナ基底を計算する. 結果を分散多項式のリストで戻す.

516

• Weight ベクトル w は省略してよい. 省略した場合, graded reverse lexicographic order をつかってブレブナ基底を計算する.
• 戻り値は f のグレブナ基底およびイニシャルモノミアル ( w がないとき ) またはイニシァル多項式 ( w が与えらたとき) のリストである.
• sm1.gb d() は結果を分散多項式のリストで戻す. 多項式の中に現れるモノミアルはグレブナ基底を計算するときに与えらた順序でソートされている. 戻り値は [変数名のリスト, 順序をきめる行
列, グレブナ基底, イニシャルモノミアルまたはイニシァル多項式] である.
• Term order でない順序が与えられた場合は, 同次化ワイル代数でグレブナ基底が計算される (SSTの本の Section 1.2 を見よ). 同次化変数 h が結果に加わる.
• オプショナル変数 q がセットされているときは, 3 番目の戻り値として, グレブナ基底およびイニシァルのリストが 与えられた順序でソートされたモノミアルの和として戻される. いまのところ
この多項式は, 文字列で表現される.
• オプショナル変数 r がセットされているときは, 戻り多項式は dehomogenize される (すなわち hに 1 が代入される).
[0] sm1.gb([[x*dx+y*dy-1,x*y*dx*dy-2],[x,y]]);[[x*dx+y*dy-1,y^2*dy^2+2],[x*dx,y^2*dy^2]]/* 上の例において, */[1] sm1.gb([[dx^2+dy^2-4,dx*dy-1],[x,y],[[dx,50,dy,2,x,1]]]);[[dx+dy^3-4*dy,-dy^4+4*dy^2-1],[dx,-dy^4]]
上の例において二つのモノミアル[2] F=sm1.gb([[dx^2+dy^2-4,dx*dy-1],[x,y],[[dx,50,dy,2,x,1]]]|sorted=1);
map(print,F[2][0])$map(print,F[2][1])$[3] sm1.gb([["dx*(x*dx +y*dy-2)-1","dy*(x*dx + y*dy -2)-1"],[x,y],[[dx,1,x,-1],[dy,1]]]);[[x*dx^2+(y*dy-h^2)*dx-h^3,x*dy*dx+y*dy^2-h^2*dy-h^3,h^3*dx-h^3*dy],[x*dx^2+(y*dy-h^2)*dx,x*dy*dx+y*dy^2-h^2*dy-h^3,h^3*dx]][4] sm1.gb_d([["dx (x dx +y dy-2)-1","dy (x dx + y dy -2)-1"],"x,y",[[dx,1,x,-1],[dy,1]]]);[[[e0,x,y,H,E,dx,dy,h],[[0,-1,0,0,0,1,0,0],[0,0,0,0,0,0,1,0],[1,0,0,0,0,0,0,0],[0,1,1,1,1,1,1,0],[0,0,0,0,0,0,-1,0],[0,0,0,0,0,-1,0,0],[0,0,0,0,-1,0,0,0],[0,0,0,-1,0,0,0,0],[0,0,-1,0,0,0,0,0],[0,0,0,0,0,0,0,1]]],[[(1)*<<0,0,1,0,0,1,1,0>>+(1)*<<0,1,0,0,0,2,0,0>>+(-1)*<<0,0,0,0,0,1,0,2>>+(-1)*<<0,0,0,0,0,0,0,3>>,(1)*<<0,0,1,0,0,0,2,0>>+(1)*<<0,1,0,0,0,1,1,0>>+(-1)*<<0,0,0,0,0,0,1,2>>+(-1)*<<0,0,0,0,0,0,0,3>>,(1)*<<0,0,0,0,0,1,0,3>>+(-1)*<<0,0,0,0,0,0,1,3>>],[(1)*<<0,0,1,0,0,1,1,0>>+(1)*<<0,1,0,0,0,2,0,0>>+(-1)*<<0,0,0,0,0,1,0,2>>,(1)*<<0,0,1,0,0,0,2,0>>+(1)*<<0,1,0,0,0,1,1,0>>+(-1)*<<0,0,0,0,0,0,1,2>>+(-1)*<<0,0,0,0,0,0,0,3>>,(1)*<<0,0,0,0,0,1,0,3>>]]]
参照 sm1.reduction(), sm1.rat to p()
141. sm1.deRham([f ,v]|proc=p):: 空間 Cn − (the zero set of f = 0) で前命題 のドラームコホモロジ群の次元を計算してくれる517

ようにサーバに頼む.
• こ の 函 数 は 空 間 X = C n \ V (f ) の ド ラ ー ム コ ホ モ ロ ジ 群 の 次 元 を 計 算 す る. す な わ ち,
[dim H 0 (X, C), dim H 1 (X, C), dim H 2 (X, C), . . . , dim H n (X, C)] を戻す.
• v は変数のリスト. n = length(v) である.
• sm1.deRham() は計算機の資源を大量に使用する. たとえば
sm1.deRham(0,[x*y*z*(x+y+z-1)*(x-y),[x,y,z]]) の計算すらすでに非常に大変である.
• b-関数の根を効率よく解析するには, ox asir が ox sm1 forAsir より使用されるべきである. コ
マンド sm1(0,"[(parse) (oxasir.sm1) pushfile] extension"); を用いて, ox asir との通信モジュールをあらかじめロードしておくとよい. このコマンドは ox asir forAsir のスター
ト時に自動的に実行されている.
• sm1.deRham() を ox reset(sm1.get Sm1 proc()); で中断すると, 以後 sm1 サーバが非標準モードに入り予期しない動作をする場合があるので, コマンド ox shutdown(sm1.get Sm1 proc());
で, ox sm1 forAsir を一時 shutdown してリスタートした方が安全である.

[0] sm1.deRham([x^3-y^2,[x,y]]);[1,1,0][1] sm1.deRham([x*(x-1),[x]]);[1,2]
参照 sm1.start() (sm1 command)

Algorithm: Oaku, Takayama, An algorithm for de Rham cohomology groups of the complementof an aﬃne variety via D-module computation, Journal of pure and applied algebra 139 (1999),
201–233.
142. sm1.hilbert([f ,v]|proc=p):: 多項式の集合 f のヒルベルト多項式を計算する.
• 多項式の集合 f の変数 v に関するヒルベルト多項式 ＄ h(k) ＄ を計算する.
h(k) = dimQ (Fk /I ∩ Fk )ここで Fk は次数が k 以下であるような 多項式の集合である. I は多項式の集合 f で生成されるイデアルである.
• sm1.hilbert() に関するノート: 効率よく計算するには f はモノミアルの集合にした方がいい.
実際, この函数はまず f のグレブナ基底を計算し, それからその initial monomial 達のヒルベルト多項式を計算する. したがって, 入力 f がすでにグレブナ基底だとこの函数のなかでもう一度グ
レブナ基底の計算がおこなわれる. これは時間の無駄であるし, sm1 の多項式グレブナ基底計算は
asir より遅い.

[0] load("katsura")$[1] A=hilbert_polynomial(katsura(5),[u0,u1,u2,u3,u4,u5]);
32[2] load("katsura")$[3] A=gr(katsura(5),[u0,u1,u2,u3,u4,u5],0)$[4] dp_ord();0[282] B=map(dp_ht,map(dp_ptod,A,[u0,u1,u2,u3,u4,u5]));[(1)*<<1,0,0,0,0,0>>,(1)*<<0,0,0,2,0,0>>,(1)*<<0,0,1,1,0,0>>,(1)*<<0,0,2,0,0,0>>,(1)*<<0,1,1,0,0,0>>,(1)*<<0,2,0,0,0,0>>,(1)*<<0,0,0,1,1,1>>,(1)*<<0,0,0,1,2,0>>,(1)*<<0,0,1,0,2,0>>,(1)*<<0,1,0,0,2,0>>,(1)*<<0,1,0,1,1,0>>,(1)*<<0,0,0,0,2,2>>,(1)*<<0,0,1,0,1,2>>,(1)*<<0,1,0,0,1,2>>,(1)*<<0,1,0,1,0,2>>,(1)*<<0,0,0,0,3,1>>,(1)*<<0,0,0,0,4,0>>,(1)*<<0,0,0,0,1,4>>,(1)*<<0,0,0,1,0,4>>,(1)*<<0,0,1,0,0,4>>,(1)*<<0,1,0,0,0,4>>,(1)*<<0,0,0,0,0,6>>]518

[5] C=map(dp_dtop,B,[u0,u1,u2,u3,u4,u5]);[u0,u3^2,u3*u2,u2^2,u2*u1,u1^2,u5*u4*u3,u4^2*u3,u4^2*u2,u4^2*u1,u4*u3*u1,
u5^2*u4^2,u5^2*u4*u2,u5^2*u4*u1,u5^2*u3*u1,u5*u4^3,u4^4,u5^4*u4,u5^4*u3,
u5^4*u2,u5^4*u1,u5^6][6] sm1.hilbert([C,[u0,u1,u2,u3,u4,u5]]);32
参照 sm1.start(), sm1.gb(), longname

143. sm1.genericAnn([f ,v]|proc=p):: f s のみたす微分方程式全体をもとめる. v は変数のリストである. ここで, s は v[0] であり, f は変数 rest(v) 上の多項式である.
[0] sm1.genericAnn([x^3+y^3+z^3,[s,x,y,z]]);[-x*dx-y*dy-z*dz+3*s,z^2*dy-y^2*dz,z^2*dx-x^2*dz,y^2*dx-x^2*dy]
参照: sm1.start()
144. sm1.wTensor0([f ,g,v,w]|proc=p):: f と g の D-module としての 0 次テンソル積を計算する• v は変数のリストである. w は weight のリストである. 整数 w[i] は変数 v[i] の weight である.
• sm1.wTensor0() は ox sm1 の wRestriction0 をよんでいる. wRestriction0 は, generic な
weight ベクトル w をもとにして制限を計算している.
• Weight ベクトル w が generic でないと計算がエラーで停止する.
• F および G を f と g それぞれの解とする. 直観的にいえば, 0 次のテンソル積は関数 F G のみた
す微分方程式系である.
• 入力 f , g が D の左イデアルであっても, 一般に, 出力は自由加群 Dr の部分加群である.

[0] sm1.wTensor0([[x*dx -1, y*dy -4],[dx+dy,dx-dy^2],[x,y],[1,2]]);[[-y*x*dx-y*x*dy+4*x+y],[5*x*dx^2+5*x*dx+2*y*dy^2+(-2*y-6)*dy+3],[-25*x*dx+(-5*y*x-2*y^2)*dy^2+((5*y+15)*x+2*y^2+16*y)*dy-20*x-8*y-15],[y^2*dy^2+(-y^2-8*y)*dy+4*y+20]]
145. sm1.reduction([f ,g,v,w]|proc=p):: ワイル代数における多項式集合 f の g による割り算• この函数は f を homogenized ワイル代数において, 多項式集合 g で簡単化 (reduce) する; つまり, この函数は, f に割算アルゴリズムを適用する.
• 変数集合は v で指定する. w は順序を指定するためのウエイトベクトルであり, 省略してもよい.
• sm1.reduction noH() は, Weyl algebra 用.
• 戻り値は次の形をしている: [r,c0,[c1, . . . , cm],g] ここで g =[g1 , ..., gm ] であり, c0 f + c1 g1 +· · · + cm gm = r がなりたつ. r/c0 が normal form である.
• この函数は, 低次項にあらわれる reducible な項も簡単化する.
• 函数 sm1.reduction d(P ,F ,G) および sm1.reduction noH d(P ,F ,G) は, 分散多項式用である.
[0] sm1.reduction([x^2+y^2-4,[y^4-4*y^2+1,x+y^3-4*y],[x,y]]);[x^2+y^2-4,1,[0,0],[y^4-4*y^2+1,x+y^3-4*y]][1] sm1.reduction([x^2+y^2-4,[y^4-4*y^2+1,x+y^3-4*y],[x,y],[[x,1]]]);[0,1,[-y^2+4,-x+y^3-4*y],[y^4-4*y^2+1,x+y^3-4*y]]
参照: sm1.start(), d true nf
146. sm1.xml tree to prefix string(s|proc=p):: XML で書かれた OpenMath の木表現 s を前置記法になおす519

• この函数は om_*() に将来移すべきである.
• om xml to cmo(OpenMath Tree Expression) は CMO TREE を戻す. asir はこの CMO をまだサポートしていない. java の実行環境が必要. (たとえば, /usr/local/jdk1.1.8/bin をコマン
ドサーチパスに入れるなど.)[0] load("om");
1[1] F=om_xml(x^4-1);
control: wait OX
Trying to connect to the server... Done.
<OMOBJ><OMA><OMS name="plus" cd="basic"/><OMA><OMS name="times" cd="basic"/><OMA><OMS name="power" cd="basic"/><OMV name="x"/><OMI>4</OMI></OMA><OMI>1</OMI></OMA><OMA><OMS name="times" cd="basic"/><OMA><OMS name="power" cd="basic"/><OMV name="x"/><OMI>0</OMI></OMA><OMI>-1</OMI></OMA></OMA></OMOBJ>[2] sm1.xml_tree_to_prefix_string(F);[3] basic_plus(basic_times(basic_power(x,4),1),basic_times(basic_power(x,0),-1))
参照: om *(), OpenXM/src/OpenMath, eval str()

147. sm1.syz([f ,v,w]|proc=p):: v 上の微分作用素環において f の syzygy を計算する• 戻り値は次の形をしている: [s,[g, m, t]]. ここで s は f の v で前命題 を変数とする微分作
用素環における syzygy である. g は f で前命題 の weight vector w に関するグレブナ基底である. m は入力行列 f をグレブナ基底 g へ変換する行列である. t はグレブナ基底 g の syzygy である. まとめると, 次の等式がなりたつ: g = mf, sf = 0.
• Weight ベクトル w は省略してよい. 省略した場合, graded reverse lexicographic order をつかってブレブナ基底を計算する.
• Term order でない順序が与えられた場合は, 同次化ワイル代数でグレブナ基底が計算される (SSTの本の Section 1.2 を見よ). 同次化変数 h が結果に加わる.
[0] sm1.syz([[x*dx+y*dy-1,x*y*dx*dy-2],[x,y]]);[[[y*x*dy*dx-2,-x*dx-y*dy+1]],
generators of the syzygy[[[x*dx+y*dy-1],[y^2*dy^2+2]],
grobner basis[[1,0],[y*dy,-1]],transformation matrix[[y*x*dy*dx-2,-x*dx-y*dy+1]]]][1] sm1.syz([[x^2*dx^2+x*dx+y^2*dy^2+y*dy-4,x*y*dx*dy-1],[x,y],[[dx,-1,x,1]]]);[[[y*x*dy*dx-1,-x^2*dx^2-x*dx-y^2*dy^2-y*dy+4]], generators of the syzygy[[[x^2*dx^2+h^2*x*dx+y^2*dy^2+h^2*y*dy-4*h^4],[y*x*dy*dx-h^4], GB[h^4*x*dx+y^3*dy^3+3*h^2*y^2*dy^2-3*h^4*y*dy]],[[1,0],[0,1],[y*dy,-x*dx]],transformation matrix
148. sm1.mul(f ,g,v|proc=p):: sm1 サーバ に f かける g を v 上の微分作用素環でやってくれるように頼む.
• sm1.mul h() は homogenized Weyl 代数用.
• BUG: sm1.mul(p0*dp0,1,[p0]) は dp0*p0+1 を戻す. d 変数が後ろにくるような変数順序がはいっていないと, この関数は正しい答えを戻さない.
[0] sm1.mul(dx,x,[x]);520x*dx+1[1] sm1.mul([x,y],[1,2],[x,y]);x+2*y[2] sm1.mul([[1,2],[3,4]],[[x,y],[1,2]],[x,y]);[[x+2,y+4],[3*x+4,3*y+8]]149. sm1.distraction([f ,v,x,d,s]|proc=p):: sm1 に f f の distraction を計算してもらう• 識別子 p の sm1 サーバに, f の distraction を v 上の微分作用素環で計算してもらう.
• x, d は, それぞれ, distract すべき x 変数, d 変数の リスト. Distraction したら, s を変数として結果を表す.
• Distraction というのは x*dx を x で置き換えることである. 詳しくは Saito, Sturmfels, Takayama: Grobner Deformations of Hypergeometric Diﬀerential Equations の page 68 を見よ.
[0] sm1.distraction([x*dx,[x],[x],[dx],[x]]);x[1] sm1.distraction([dx^2,[x],[x],[dx],[x]]);x^2-x[2] sm1.distraction([x^2,[x],[x],[dx],[x]]);x^2+3*x+2[3] fctr(@);[[1,1],[x+1,1],[x+2,1]][4] sm1.distraction([x*dx*y+x^2*dx^2*dy,[x,y],[x],[dx],[x]]);(x^2-x)*dy+x*y
参照: distraction2(sm1),
150. sm1.gkz([A,B]|proc=p):: 行列 A とパラメータ B に付随した GKZ 系 (A-hypergeometric system) をもどす

[0] sm1.gkz([ [[1,1,1,1],[0,1,3,4]], [0,2] ]);[[x4*dx4+x3*dx3+x2*dx2+x1*dx1,4*x4*dx4+3*x3*dx3+x2*dx2-2,-dx1*dx4+dx2*dx3,-dx2^2*dx4+dx1*dx3^2,dx1^2*dx3-dx2^3,-dx2*dx4^2+dx3^3],[x1,x2,x3,x4]]
151. sm1.appell1(a|proc=p):: F1 または FD に対応する方程式系を戻す• Appell の関数 F1 および その n 変数化である Lauricella の関数 FD (a, b1 , b2 , . . . , bn , c; x1 , . . . , xn )のみたす微分方程式系を戻す. ここで, a = (a, c, b1 , . . . , bn ). パラメータは有理数でもよい.
• sm1 の関数 appell1() をよぶわけでないので, パラメータが有理数や文字式の場合も正しく動く.
[0] sm1.appell1([1,2,3,4]);[[((-x1+1)*x2*dx1-3*x2)*dx2+(-x1^2+x1)*dx1^2+(-5*x1+2)*dx1-3,(-x2^2+x2)*dx2^2+((-x1*x2+x1)*dx1-6*x2+2)*dx2-4*x1*dx1-4,((-x2+x1)*dx1+3)*dx2-4*dx1],
equations[x1,x2]]the list of variables[1] sm1.gb(@);[[((-x2+x1)*dx1+3)*dx2-4*dx1,((-x1+1)*x2*dx1-3*x2)*dx2+(-x1^2+x1)*dx1^2+(-5*x1+2)*dx1-3,(-x2^2+x2)*dx2^2+((-x2^2+x1)*dx1-3*x2+2)*dx2+(-4*x2-4*x1)*dx1-4,521

(x2^3+(-x1-1)*x2^2+x1*x2)*dx2^2+((-x1*x2+x1^2)*dx1+6*x2^2+(-3*x1-2)*x2+2*x1)*dx2-4*x1^2*dx1+4*x2-4*x1],[x1*dx1*dx2,-x1^2*dx1^2,-x2^2*dx1*dx2,-x1*x2^2*dx2^2]][3] sm1.rank(sm1.appell1([1/2,3,5,-1/3]));3[4] Mu=2$ Beta = 1/3$
[5] sm1.rank(sm1.appell1([Mu+Beta,Mu+1,Beta,Beta,Beta]));4152. sm1.appell4(a|proc=p):: F4 または FC に対応する方程式系を戻す• Appell の関数 F4 および その n 変数化である Lauricella の関数 FC (a, b, c1 , c2 , . . . , cn ; x1 . . . . , xn )のみたす微分方程式系を戻す. ここで, a = (a, b, c1 , . . . , cn ).
• sm1 の関数 appell1() をよぶわけでないので, パラメータが有理数や文字式の場合も正しく動く.
[0] sm1.appell4([1,2,3,4]);[[-x2^2*dx2^2+(-2*x1*x2*dx1-4*x2)*dx2+(-x1^2+x1)*dx1^2+(-4*x1+3)*dx1-2,(-x2^2+x2)*dx2^2+(-2*x1*x2*dx1-4*x2+4)*dx2-x1^2*dx1^2-4*x1*dx1-2],
equations[x1,x2]]the list of variables[1] sm1.rank(@);
4
153. sm1.rank(a|proc=p):: 微分方程式系 a の holonomic rank を戻す• 微分方程式系 a の, generic point での正則解の次元を 戻す. この次元を, holonomic rank と呼ぶ.
• a は微分作用素のリストと変数のリストよりなる.
• a が regular holonomic のときは sm1.rrank() も holonomic rank を戻す. 一般にこの関数の方が sm1.rank() より早い.
[0] sm1.gkz([ [[1,1,1,1],[0,1,3,4]], [0,2] ]);[[x4*dx4+x3*dx3+x2*dx2+x1*dx1,4*x4*dx4+3*x3*dx3+x2*dx2-2,-dx1*dx4+dx2*dx3, -dx2^2*dx4+dx1*dx3^2,dx1^2*dx3-dx2^3,-dx2*dx4^2+dx3^3],[x1,x2,x3,x4]][1] sm1.rrank(@);
4[2] sm1.gkz([ [[1,1,1,1],[0,1,3,4]], [1,2]]);[[x4*dx4+x3*dx3+x2*dx2+x1*dx1-1,4*x4*dx4+3*x3*dx3+x2*dx2-2,-dx1*dx4+dx2*dx3,-dx2^2*dx4+dx1*dx3^2,dx1^2*dx3-dx2^3,-dx2*dx4^2+dx3^3],[x1,x2,x3,x4]][3] sm1.rrank(@);
5154. sm1.auto reduce(s|proc=p):: フラグ ”AutoReduce” を s に設定• s が 1 のとき, 以後計算されるグレブナ基底はすべて, reduced グレブナ基底となる.
• s が 0 のとき, 計算されるグレブナ基底は reduced グレブナ基底とはかぎらない. こちらがデ522

フォールト.
155. sm1.slope(ii,v,ff iltration ,vf iltration |proc=p):: 微分方程式系 ii の slope を戻す• 微分方程式系 ii の V ﬁltratio vf iltration で指定する超平面に沿っての (geomeric) slope を計算
する.
• v は変数のリスト.
• 戻り値は, リストを成分とするリストである. 成分リストの第 1 要素が slope, 第 2 要素は, そのweight vector に対応する microcharacteristic variety が bihomogeneous でない.
• Algorithm: ”A.Assi, F.J.Castro-Jimenez and J.M.Granger, How to calculate the slopes of a
D-module, Compositio Math, 104, 1-17, 1996” をみよ.
Slope の本来の定義では, 符号が負となるが, このプログラムは, Slope の絶対値を戻す.

[0] A= sm1.gkz([ [[1,2,3]], [-3] ]);[1] sm1.slope(A[0],A[1],[0,0,0,1,1,1],[0,0,-1,0,0,1]);[2] A2 = sm1.gkz([ [[1,1,1,0],[2,-3,1,-3]], [1,0]]);/* This is an interesting example given by Laura Matusevich,June 9, 2001 */[3] sm1.slope(A2[0],A2[1],[0,0,0,0,1,1,1,1],[0,0,0,-1,0,0,0,1]);156. sm1.ahg(A):: It idential with sm1.gkz(A)157. sm1.bfunction(F ):: It computes the global b-function of F
It no longer calls sm1’s original bfunction. Instead, it calls asir ”bfct”. Algorithm: M.Noro,
Mathematical Software, icms 2002, pp.147–157.
[0] sm1.bfunction(x^2-y^3);158. sm1.call sm1(F ):: It executes F on the sm1 server. See also sm1.
159. sm1.ecart homogenize01Ideal(A):: It (0, 1)-homogenizes the ideal A[0]Note that it is not an elementwise homogenization.
[0] F=[(1-x)*dx+1]$ FF=[F,"x,y"]$[1] sm1.ecart_homogenize01Ideal(FF);[2] F=sm1.appell1([1,2,3,4]);[3] sm1.ecart_homogenize01Ideal(F);160. sm1.ecartd gb(A):: It returns a standard basis of A by using a tangent cone algorithm• h[0, 1](D)-homogenization is used.
• If the option rv="dp" (return value="dp") is given, the answer is returned in distributed
polynomials.
[0] F=[2*(1-x-y)*dx+1,2*(1-x-y)*dy+1]$[1] FF=[F,"x,y",[[dx,1,dy,1],[x,-1,y,-1]]]$[2] sm1.ecartd_gb(FF);[[(-2*x-2*y+2)*dx+h,(-2*x-2*y+2)*dy+h],[(-2*x-2*y+2)*dx,(-2*x-2*y+2)*dy]][3] F=[2*(1-x-y)*dx+h,2*(1-x-y)*dy+h]$523

[4] FF=[F,"x,y",[[dx,1,dy,1],[x,-1,y,-1,dx,1,dy,1]],["noAutoHomogenize",1]]$
161. sm1.ecartd gb oxRingStructure(): It returns the oxRingStructure of the most recent ecartd gb() computation.
162. sm1.ecartd isSameIdeal h(F ):: Here, F =[II,JJ,V ]. It compares two ideals II and JJ in h[0, 1](D)alg[0] II=[(1-x)^2*dx+h*(1-x)]$ JJ = [(1-x)*dx+h]$[1] V=[x]$[2] sm1.ecartd_isSameIdeal_h([II,JJ,V]);
163. sm1.ecartd reduction(F ,A): It returns a reduced form of F in terms of A by using a tangent cone algorithm.
h[0, 1](D)-homogenization is used.
[0] F=[2*(1-x-y)*dx+h,2*(1-x-y)*dy+h]$[1] FF=[F,"x,y",[[dx,1,dy,1],[x,-1,y,-1]]]$[2] sm1.ecartd_reduction(dx+dy,FF);
164. sm1.ecartd reduction noh(F ,A):: It returns a reduced form of F in terms of A by using a tangent cone algorithm
h[0, 1](D)-homogenization is NOT used. A[0] must not contain the variable h.
[0] F=[2*(1-x-y)*dx+1,2*(1-x-y)*dy+1]$[1] FF=[F,"x,y",[[dx,1,dy,1],[x,-1,y,-1]]]$[2] sm1.ecartd_reduction_noh(dx+dy,FF);
165. sm1.ecartd syz(A):: It returns a syzygy of A by using a tangent cone algorithm.
• h[0, 1](D)-homogenization is used
• If the option rv="dp" (return value="dp") is given, the answer is returned in distributed
polynomials.
• The return value is in the format [s,[g,m,t]].
• s is the generator of the syzygies, g is the Grobner basis, m is the translation matrix from thegenerators to g. t is the syzygy of g.
[0] F=[2*(1-x-y)*dx+1,2*(1-x-y)*dy+1]$[1] FF=[F,"x,y",[[dx,1,dy,1],[x,-1,y,-1]]]$[2] sm1.ecartd_syz(FF);[3] F=[2*(1-x-y)*dx+h,2*(1-x-y)*dy+h]$[4] FF=[F,"x,y",[[dx,1,dy,1],[x,-1,y,-1,dx,1,dy,1]],["noAutoHomogenize",1]]$[5] sm1.ecartd_syz(FF);166. sm1.gb oxRingStructure():: It returns the oxRingStructure of the most recent gb computation.
167. sm1.gb reduction(F,A):: It returns a reduced form of F in terms of A by using a normal form algorithmh[1, 1](D)-homogenization is used.
[0] F=[2*(h-x-y)*dx+h^2,2*(h-x-y)*dy+h^2]$[1] FF=[F,"x,y",[[dx,1,dy,1],[x,-1,y,-1,dx,1,dy,1]]]$[3] sm1.gb_reduction((h-x-y)^2*dx*dy,FF);524

168. sm1.gb reduction noh(F ,A):: It returns a reduced form of F in terms of A by using a normal form algorithm[0] F=[2*dx+1,2*dy+1]$[1] FF=[F,"x,y",[[dx,1,dy,1]]]$[2] sm1.gb_reduction_noh((1-x-y)^2*dx*dy,FF);
169. sm1.generalized bfunction(I,V ,V D,W ): It computes the generalized b-function (indicial equation) of I with respect to the weight W
It no longer calls sm1’s original function. Instead, it calls asir "generic bfct".
[0] sm1.generalized_bfunction([x^2*dx^2-1/2,dy^2],[x,y],[dx,dy],[-1,0,1,0]);170. sm1.isSameIdeal in Dalg(I,J,V ):: It compares two ideals I and J in Dalg (algebraic D with variables V , no homogenization)[0] II=[(1-x)^2*dx+(1-x)]$ JJ = [(1-x)*dx+1]$ V=[x]$[1] sm1.isSameIdeal_in_Dalg(II,JJ,V);
171. sm1.restriction(I,V ,R|degree=key0 ):: It computes the restriction of I as a D-module to the set deﬁned by R.
• This function allows optional variables degree• V is the list of variables.
• When the optional variable degree=d is given, only the restrictions from 0 to d are computed.
• Note that, in case of vector input, RESTRICTION VARIABLES MUST APPEAR FIRST in
the list of variable V .
• We are using wbfRoots to get the roots of b-functions, so we can use only generic weight vector
for now.
• Algorithm: T.Oaku and N.Takayama, math.AG/9805006, http://xxx.langl.gov[0] sm1.restriction([dx^2-x,dy^2-1],[x,y],[y]);172. sm1.saturation(T ):: T =[I,J,V ]. It returns saturation of I with respect to J ∞ . V is a list of variables.
[0] sm1.saturation([[x2^2,x2*x4, x2, x4^2], [x2,x4], [x2,x4]]);3.4.18 TIGERS 函数
この章では, tigers ox server ox_sm1_tigers にたいするインタフェース函数を説明する.
173. tigers.tigers(a|proc=a):: この函数は識別子 p の tigers サーバに行列 a に付随したトーリックイデアルのすべてのグレブナ
基底を 計算してくれるようにたのむ
Tigers は アフィントーリックイデアルの reduced グレブナ基底をすべて数えあげるための専用のプ
ログラムである. このプログラムは, アフィントーリックイデアルの state polytope をきめるために使える. 理論的なバックグラウンドについては, 本

B.Sturmfels, Grobner bases and Convex Polytopes
を見よ. Tigers は Birk Hubert が作者である. このプログラムの利用しているアルゴリズムは
B.Huber and R.Thomas, Computing Grobner Fans of Toric Idealsに説明されている.
[0] A=[[1,1,1,1],[0,1,2,3]]$[1] S=tigers.tigers(A)$525[2] length(S);8[3] S[0];[[[1,0,1,0],[0,2,0,0]],[[1,0,0,1],[0,1,1,0]],[[0,1,0,1],[0,0,2,0]]][4] S[1];[[[1,0,0,1],[0,1,1,0]],[[0,2,0,0],[1,0,1,0]],[[0,1,0,1],[0,0,2,0]]]
この 例 で は, A に付随 し た ア フ ィ ン ト ーリ ッ クイ デ アルの すべて のグレ ブナ基 底が S に格納
さ れ る. こ の 例 で は, 8 個 の グ レ ブ ナ 基 底 が あ る. [[i1 , i2 , . . .],[j1 , j2 . . .]] は 二 つ の モ ノ
ミアルの exponent をならべたものであり, 2 項式をあらわす. たとえば, S[0] は次の多項式の集合{x1 x3 - x2^2, x1 x4 - x2 x3, x2 x4 - x3^2} であり, <x1 x3, x1 x4, x2 x4> がそのinitial ideal である.

Mathematica 函数
この節では Mathematica の ox サーバ ox math とのインタフェース関数を解説する. これらの関数はファイル ‘m’ で定義されているのでこのファイルを
3.4.19[0] load("m")$でこのファイルをロードしてから使用しないといけない. ‘m’ は ‘$(OpenXM HOME)/lib/asir-contrib’にある.
注意: ox reset は動かない.

nobuki@yama:~$ asirThis is Risa/Asir, Version 20020802 (Kobe Distribution).
Copyright (C) 1994-2000, all rights reserved, FUJITSU LABORATORIES LIMITED.
Copyright 2000,2001, Risa/Asir committers, http://www.openxm.org/.
GC 6.1(alpha5) copyright 2001, H-J. Boehm, A. J. Demers, Xerox, SGI, HP.
PARI 2.2.1(alpha), copyright (C) 2000,
C. Batut, K. Belabas, D. Bernardi, H. Cohen and M. Olivier.
OpenXM/Risa/Asir-Contrib(20020804), Copyright 2000-2002, OpenXM.org
help("keyword"); ox_help(0); ox_help("keyword"); ox_grep("keyword");for help messages (unix version only).
[258] load("m")$m Version 19991113. mathematica.start, mathematica.tree_to_string,mathematica.n_Eigenvalues[259] mathematica.start();ox_math has started.
ox_math: Portions copyright 2000 Wolfram Research, Inc.
See OpenXM/Copyright/Copyright.mathlink for details.
0[260] mathematica.n_Eigenvalues([[1,2],[4,5]]);[-0.464102,6.4641]
Mathematica is the trade mark of Wolfram Research Inc. This package requires Mathmatica Version 3.0, so you need Mathematica to make this package work. See http://www.wolfram.com. The
copyright and license agreement of the mathlink is put at OpenXM/Copyright/Copyright.mathlink.
Note that the licence prohibits to connect to a mathematica kernel via the internet.
Author of ox math: Katsuyoshi Ohara, ohara@air.s.kanazawa-u.ac.jp.
526

174. mathematica.start():: Localhost で ox math を起動する• 起動された ox_math の識別番号を戻す.
• Xm_noX =1 としておくと, ox_math 用の debug window が開かない.
• 識別番号は M_proc に格納される.
[0] P = mathematica.start()
参照： ox launch()

175. mathematica.tree to string(t):: ox_math の戻す Mathematica の木構造データ t を asir 形式になおす
t は ox_math の戻す Mathematica の木構造データ. t をなるべく asir が理解できる形での, 前置または中置記法の文字列に変換する. t の先頭要素の文字列がキーワードであるが, その文字が変換テーブ
ルにないときは, m_ をキーワードの先頭につけて, 関数呼出形式の文字列へかえる.
[0] mathematica.start();0[1] ox_execute_string(0,"Expand[(x-1)^2]");0[2] A=ox_pop_cmo(0);[Plus,1,[Times,-2,x],[Power,x,2]][3] mathematica.tree_to_string(A);(1)+((-2)*(x))+((x)^(2))[4] eval_str(@);
x^2-2*x+1[5] mathematica.tree_to_string(["List",1,2]);[1 , 2][6] mathematica.tree_to_string(["Plus",2,3]);(2)+(3)[7] mathematica.tree_to_string(["Complex",2.3,4.55]);
mathematica.complex(2.3 , 4.55)[8] mathematica.tree_to_string(["Plus",["Complex",1.2,3.5],1/2]);(mathematica.complex(1.2 , 3.5))+(1/2)[9] eval_str(@);(1.7+3.5*@i)
参照 ox pop cmo(), eval str(), mathematica.rtomstr()
176. mathematica.rtomstr(t):: t をなるべく Mathematica の理解可能な文字列に変える
たとえば, asir ではリストを [ , ] で囲むが, Mathematica では { , } で囲む. この関数はこの変換をおこなう.

[0] mathematica.rtomstr([1,2,3]);{1,2,3}[1] mathematica.rtomstr([[1,x,x^2],[1,y,y^2]]);{{1,x,x^2},{1,y,y^2}}
もう一つ例をあげよう. 次の関数 mathematica.inverse(M ) は ox_math をよんで行列 M の逆行列を計算する関数である. mathematica.inverse(M ) は次のように r tostr(M ) を用いて asir の行

527

列を Mathematica 形式に変換してから ox execute string() で Mathematica に逆行列を計算させている.

[0] def inverse(M) {P = 0;
A = mathematica.rtomstr(M);ox_execute_string(P,"Inverse["+A+"]");
B = ox_pop_cmo(B);C = mathematica.tree_to_string(B);return(eval_str(C));}[1] M=[[1,x,x^2],[1,y,y^2],[1,z,z^2]];[[1,x,x^2],[1,y,y^2],[1,z,z^2]][2] A=mathematica.inverse(M)$[3] red(A[0][0]);(z*y)/(x^2+(-y-z)*x+z*y)
参 照： ox execute string(), ToExpression(Mathematica), mathematica.tree to string(),r2ma(), evalma()
3.4.20 便利な関数
177. util timing(Q):: Show the timing data to execute Q.
[0] util_timing( quote( fctr(x^50-y^50) ));[[[1,1],[x-y,1],[x+y,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^20-y^5*x^15+y^10*x^10-y^15*x^5+y^20,1],[x^20+y^5*x^15+y^10*x^10+y^15*x^5+y^20,1]],[cpu,0.03125,gc,0.03125,memory,3540380,real,0.063]]
178. util load file as a string(F ):: It reads a ﬁle F as a string.
179. util read file as a string(F ):: It reads a ﬁle F as a string.
180. util write string to a file(Fname,S):: It writes a string S to a ﬁle Fname.
参照：fcat()181. util filter(Command,Input|env=key0 ):: It executes the ﬁlter program Command with the Input and returns the output of the ﬁlter
This function allows optional variables env[0] util_filter("sort","cat\ndog\ncentipede\n");参照：getbyshell()
182. util find and replace(W ,S,Wnew):: It replaces W in S by Wnew
• Arguments must be a list of ascii codes.
• より高機能な str subst() がある．
183. util find substr(W ,S):: It returns the position of W in S.

528

• If W cannot be found, it returns −1.
• Arguments must be a list of ascii codes.
• より高機能な str str() がある．
[0] util_find_substr(strtoascii("in"),strtoascii("singing"));1184. util part(S,P ,Q):: It returns from P th element to Qth element of S.
185. util remove cr(S):: It removes cr/lf/tabs from S.
Arguments must be a list of ascii codes.
186. util index(V ):: It returns the name part and the index part of V .
[0] util_index(x_2_3)[x,[ 2 3 ]]参照：util v(), rtostr()

187. util v(V ,L):: It returns a variable indexed by L.
[0] util_v("x",[1,3]);
x_1_3
参照：makev(), util index(), makenewv(), strtov()
188. util file exists(Fname):: It returns 1 when Fname exists.
It returns 0 when Fname does not exist.
189. util find start( |browser=key0 ):: It tries to ﬁnd the gnome-open command or an installed browser in unix systems. It returns”open” on MacOS X and returns ”start” on Windows.
This function allows optional variables browser
190. util damepathq(S):: When S is a string by the ShiftJIS code and S contains dame-moji with respect to /, it returns[a non-zero number, the string].

[0] T = [0x5c,0xe4,0x5c,0x41,0x42]$[1] T2=asciitostr(T);\臀 AB[2] util_damepathq(T2);[2, 臀][3] os_md.s2os(T2);\\臀\AB
参照：s2os()
その他
この節ではまだ分類がおわっていない関数を解説する. この節の関数は将来は別の独立した節へ移す予定である.

3.4.21

191. todo parametrize(p):: 有理曲線のパラメータ表示をみつける
529

• パッケージ todo_parametrize/todo_parametrize.rr をロードすることにより, 有理曲線のパラメータ表示を見付ける関数である paramerize が利用できるようになる.
詳しくは See section ‘概要’ in Risa/Asir 代数曲線論用パッケージ説明書を見よ(http://www.math.kobe-u.ac.jp/OpenXM/Current/doc/asir-contrib/html-ja/todo_parametrize_ja/todo_parametrize_ja_toc.html, Web 版 Risa/Asir 代数曲線論用パッケージ説明書).
• このパッケージのマニュアルへの統合はまだできていない. このパッケージはまだ module 構造を利用していないので, 既存のライブラリと名前の衝突の可能性がある.
[0] load("todo_parametrize/todo_parametrize.rr");
1[1] parametrize(y^2-x^3);[155*t^2+20*t+1,720*t^4+1044*t^3+580*t^2,155*t^4+20*t^3+t^2,(-x)/(y)][2] parametrize(y^2+x^3);[-t,1,t^3,(-x)/(y)]参考文献[Apéri] R. Apéry, Irrationalité de ζ(2) et ζ(3), Journées arithmétiques de Luminy, Astérisque no.61,(1979), 11–13.
[Batut et al.] C. Batut, D. Bernardi, H. Cohen, M. Olivier, User’s Guide to PARI–GP, 1993.
[Becker-Weispfenning] T. Becker, V. Weispfenning, Groebner Bases, Graduate Texts in Math. 141,
Springer-Verlag, 1993.
[Boehm-Weiser] H. Boehm, M. Weiser, Garbage Collection in an Uncooperative Environment, Software
Practice & Experience, September 1988, 807–820.
[DR] M. Dettweiler and S. Reiter, An algorithm of Katz and its applications to the inverse Galois
problems, J. Symbolic Comput. 30(2000), 761–798.
[Gebaue-Moeller] R. Gebauer, H. H. Moeller, An installation of Buchberger’s algorithm, J. of Symbolic
Computation 6, 275–286.
[Giovini et al.] A. Giovini, T. Mora, G. Niesi, L. Robbiano, C. Traverso, “One sugar cube, please” OR
Selection strategies in the Buchberger algorithm, Proc. ISSAC’91, 49–54.
[Ha] Y. Haraoka, Middle convolution for completely integrable systems with logarithmic singularities
along hyperplane arrangements, Adv. Studies in Pure Math. 62(2012), 109–136.
[Hiroe-Kawakami-Nakamura-Sakai] K. Hiroe, H. Kawakami, A. Nakamura and H. Sakai, 4-dimensional
Painlevé-type equations, MSJ Memoirs vol.37, Mathematical Society of Japan, 2018.
[Hiroe-Oshima] K. Hiroe and T. Oshima, A classiﬁcation of roots of symmetric Kac-Moody root systems
and its application, Symmetries, Integrable Systems and Representations, Springer Proceedings inMathematics and Statistics 40 (2012), 195–241.
[Morier-Genoud and Ovsienko] S. Morier-Genoud and V. Ovsienko, q-deformed rationals and qcontinued fractions, arXiv:1812.00170, 2020.
[Noro-Takeshima] M. Noro, T. Takeshima, Risa/Asir – A Computer Algebra System, Proc. ISSAC’92,
387–396.
[Noro-Yokoyama] M. Noro, K. Yokoyama, A Modular Method to Compute the Rational Univariate
Representation of Zero-Dimensional Ideals, J. Symb. Comp. 28/1 (1999), 243–263.
[O1] T. Oshima, Annihilators of generalized Verma modules of the scalar type for classical Lie algebras,“Harmonic Analysis, Group Representations, Automorphic forms and Invariant Theory”, in honorof Roger Howe, Vol. 12, Lecture Notes Series, 2007, 277-319, National University of Singapore.

530

[O2] T. Oshima, 特殊関数と代数的線型常微分方程式, 東京大学数理科学レクチャーノート 11, 2011,
http://www.ms.u-tokyo.ac.jp/publication/documents/spfct3.pdf.
[O3] T. Oshima, Fractional calculus of Weyl algebra and Fuchsian diﬀerential equations, MSJ Memoirs
28, Mathematical Society of Japan, Tokyo, 2012.
[O4] T. Oshima, Drawing Curves, Mathematical Progress in Expressive Image Synthesis III, edited by
Y. Dobashi and H. Ochiai, Mathematics for Industry, 24 (2016), 95–106, Springer.
[O5] T. Oshima, Transformation of KZ type equations, Microlocal Analysis and Singular Perterbation
Theory, RIMS Kôkyûroku Bessatsu B61 (2017), 141–162.
[O6] T. Oshima, os muldif.rr, a library of the calculation of diﬀerential operators for computer algebra
Risa/Asir, 2007–2022, https://www.ms.u-tokyo.ac.jp/~oshima[O7] T. Oshima, Semilocal monodromy of rigid local systems, Formal and Analytic Solutions of Diﬀ.
Equations, Springer Proceedings in Mathematics and Statistics 256(2018) 189-199,[O8] 大島利雄，個数を数える, 数学書房, 2019, 226 pp.
[O9] T. Oshima, Conﬂuence and versal unfolding of Pfaﬃan systems, Josai Mathematical Journal
12(2020), 117–151.
[O10] T. Oshima, Versal unfolding of irregular singularities of a linear diﬀerential equation on the Riemann sphere, Publ. RIMS Kyoto Univ. 57 (2021), 893–920.
[Okt] T. Oshima, Middle convolution of KZ-type equations and single-elimination tournaments, to appear.
[Osp] T. Oshima, Algorithm classifying roots of star-shaped Kac-Moody root systems,
https://www.ms.u-tokyo.ac.jp/~oshima/paper/spbasic.pdf[OSe] T. Oshima and J. Sekiguchi, Eigenspaces of invariant diﬀerential operators on an aﬃne symmetricspaces, Invent. Math. 57(1980), 1–81.
[OSh] T. Oshima and N. Shimeno, Heckman-Opdam hypergeometric functions and their specializations,
RIMS Kôkyûroku Bessatsu B20 (2010), 129–162.
[Saito-Sturmfels-Takayama] M. Saito, B. Sturmfels, N. Takayama, Groebner deformations of hypergeometric diﬀerential equations, Algorithms and Computation in Mathematics 6, Springer-Verlag(2000).
[Shimoyama-Yokoyama] T. Shimoyama, K. Yokoyama, Localization and primary decomposition of polynomial ideals, J. Symb. Comp. 22 (1996), 247–277.
[Shoup] V. Shoup, A new polynomial factorization algorithm and its implementation, J. Symb. Comp.
20(1995), 364–397.
[OEIS] N. Sloane. The on-line encyclopedia of integer sequences, 1964–, https://oeis.org/.
[Traverso] C. Traverso, Groebner trace algorithms, Proc. ISSAC ’88(LNCS 358), 125-138.
[Yokoyama] K. Yokoyama, Prime decomposition of polynomial ideals over ﬁnite ﬁelds, Proc. ICMS,(2002), 217–227.
[Weber] K. Weber, The accelerated Integer GCD Algorithm, ACM TOMS, 21, 1(1995), 111–122.

531

索引
4.16 Plucker 関係式, 514
4.17 SM1 函数, 514
4.18 TIGERS 函数, 525
4.19 Mathematica 函数, 526
4.20 便利な関数, 528
4.21 その他, 529

1–2. Functions in os muldif.rr, 5, 74
1.1 Fundamental Function, 5, 74
1.2 Fractional calculus, 6, 93
1.3 Some operators, 8, 149
2.1 Extended function, 9, 152
2.2 Numbers, 11, 175
2.3 Polynomials and rational functions, 13, 188
2.4 Functions with real/complex variables, 15, 227
2.5 List and vectors, 16, 230
2.6 Matrices, 19, 251
2.7 Strings, 20, 274
2.8 Permutations, 21, 283
2.9 TEX, 22, 287
2.10 Lines and curves, 23, 302
2.11 Drawing curves and graphs, 24, 329
2.12 Applications, 25, 367
2.12.1 表の作成, 367
2.12.2 表や行列の変形, 369
2.12.3 函数値の数表, 372
2.12.4 点数分布表, 374
2.12.5 Taylor 展開, 375
2.12.6 計算尺, 377
2.13 Environments, 26, 380
2.14 補足, 389
2.14.1 行列の入力, 389
2.14.2 平面図形, 391
2.14.3 リスト形式函数, 396
2.14.4 函数値の解析, 399
2.14.5 表形式データ, 401
2.14.6 有限集合, 403
2.14.7 次のベクトルやリスト, 405
3. Functions in the original library, 405
3.1 数の演算, 405
3.2 多項式，有理式の演算, 413
3.3 リスト，ベクトル，配列の演算, 426
3.4 行列の演算, 429
3.5 文字列に関する演算, 434
3.6 構造体に関する函数, 436
3.7 入出力, 438
3.8 型や函数，モジュールに関わる函数, 443
3.9 数値函数, 444
3.10 描画函数, 447
3.11 有限体に関する函数, 449
3.12 代数的数に関する函数, 456
3.13 グレブナー基底に関する函数, 461
3.14 分散計算に関する関数, 475
3.15 その他の函数, 483
4. Functions in the contributed library, 489
4.1 基礎 (標準関数), 489
4.2 数（数学標準関数）, 492
4.3 行列（数学標準函数）, 493
4.4 表示（数学標準函数）, 495
4.5 多項式（数学標準函数）, 497
4.6 グラフィックライブラリ（2 次元）, 501
4.7 OpenXM-Conrib 一般函数, 502
4.8 OXShell の関数, 502
4.9 OpenMath 函数, 503
4.10 Diﬀerential equations (by Okutani), 503
4.11 D-module (by Okutani), 506
4.12 DSOLV 函数, 507
4.13 GNUPLOT 函数, 509
4.14 p Fq に関するコホモロジー, 512
4.15 PHC 函数, 513%, 420.asirrc, 72.muldif, 384
abs, 175access, 441
ad, 93
add, 93
addIL, 247
addl, 93
adj, 77af, 459
af noalg, 459
alg, 457
algptorat, 458
algtodalg, 460
algv, 457
AMSTeX, 381
anal2sp, 126ann, 474
ann0, 474
append, 426
appldo, 77
appledo, 78
areabezier, 325
arfreg, 436
arg, 229
args, 443
asciitostr, 435
asq, 459
average, 233b2e, 151
base cancel, 489
base choose, 489
base ﬂatten, 489
base intersection, 489
base makelist, 489
base memberq, 490
base permutation, 490
base position, 490
base product, 490
base prune, 490
base rebuild opt, 490
base replace, 490
base replace n, 491
base set minus, 491
base set union, 491
base subsetq, 491
base subsets of size, 491
base sum, 491
base var list, 491
baseODE, 197
bernoulli, 227bfct, 474
bfunction, 474
binom, 195532

bload, 440
bsave, 440
btree, 244

dgr, 461
diagm, 266
diﬀ, 417
diﬄog, 209
digamma, 230dilog, 230
DIROUT, 382
distpoint, 374
divdo, 78
divmattex, 301
dlog, 445
dlog10, 228
dn, 406
dnorm, 303
dp dehomo, 467
dp dtop, 466
dp etov, 470
dp f4 main, 464
dp f4 mod main, 464
dp gr f main, 463
dp gr ﬂags, 465
dp gr main, 463
dp gr mod main, 463
dp gr print, 465
dp hc, 469
dp hm, 469
dp homo, 467
dp ht, 469
dp lcm, 470
dp mag, 470
dp mbase, 470
dp mod, 467
dp nf, 468
dp nf mod, 468
dp ord, 465
dp prim, 467
dp ptod, 466
dp ptozp, 467
dp rat, 467
dp red, 471
dp red mod, 471
dp redble, 470
dp rest, 469
dp set top weight, 466
dp set weight, 466
dp sp, 471
dp sp mod, 471
dp subd, 470
dp sugar, 469
dp td, 469
dp true nf, 468
dp true nf mod, 468
dp vtoe, 470
dp weyl f4 main, 464
dp weyl f4 mod main, 464
dp weyl gr f main, 464
dp weyl gr main, 463
dp weyl gr mod main, 463
dp weyl nf, 468
dp weyl nf mod, 468
dp weyl set weight, 466
dptodalg, 460
draw bezier, 341
draw obj, 449
draw string, 449
drint, 445

c2m, 254
calc, 175
caldo, 75
call, 443
Canvas, 380
car, 426
catalan, 177
cdr, 426
ceil, 445
cfrac, 183
cfrac2n, 183
characteristic ﬀ, 451
chkexp, 88
chkfun, 152
chkspt, 95
clear canvas, 449
close ﬁle, 441
cmpf, 167
cmpsimple, 160
coef, 414
cola, 432
colm, 432
colx, 432
compdf, 165
conf1sp, 116confexp, 118
conj, 408
conplot, 447
cons, 426
cont, 420
cotr, 94
countin, 231
cputime, 485
cr gcda, 458
cterm, 207
ctrl, 483
currenttime, 486
cutf, 165
cyclic, 473
dabs, 445
dacos, 444
dalgtoalg, 460
dalgtodp, 460
darg, 303
dasin, 444
datan, 444
dceil, 445
dcos, 444
debug, 484
defpoly, 457
defpoly mod2, 454
deg, 414
delete history, 488
delopt, 231
det, 430
deval, 408
dexp, 445
dext, 303
df2big, 165
dﬂoor, 445
dform, 91533

dsin, 444
dsolv dual, 507
dsolv starting term, 508
dsqrt, 445
dtan, 445
dupmat, 251
dvangle, 305
dviout, 289
dviout0, 290
DVIOUTA, 382
DVIOUTB, 361, 382, 385
DVIOUTH, 382
DVIOUTL, 382
dvprod, 233
dwinding, 304

fresidue, 174
fromeul, 87
fshorter, 172
fsum, 168
fuchs3e, 150
funargs, 444
functor, 443
fzero, 173
gamma, 229
gb comp, 472
gcd, 421
gcdz, 421
generate port, 477
generic bfct, 474
get byte, 441
get line, 441
get rootdir, 488
getbygrs, 104
getbyshell, 155
getCatalan, 178
getel, 161
getenv, 489
getline, 155
getopt, 488
getroot, 193
getSSE, 91
gf2nton, 453
gf2ntop, 453
ghg, 150
ghg2, 150
glib clear, 501
glib ﬂush, 501
glib line, 501
glib open, 501
glib plot, 501
glib print, 501
glib ps form, 501
glib putpixel, 501
glib remove last, 502
glib set pixel size, 502
glib tops, 501
glib window, 501
gnuplot.gnuplot, 509
gnuplot.heat, 511
gnuplot.output, 511
gnuplot.plot dots, 510
gnuplot.plot function, 511
gnuplot.setenv, 511
gnuplot.start, 509
gnuplot.stop, 511
gr, 461
gr minipoly, 463
gr mod, 461

easierpol, 193
ecm add ﬀ, 456
ecm chsgn ﬀ, 456
ecm sub ﬀ, 456
end, 438
eofamily, 151
eqs2tex, 292
erfc, 227
error, 484
eta, 230
etos, 90
ev4s, 151
eval, 408
eval str, 435
evalcoord, 280
evalma, 282
evalred, 161evals, 161evalsint, 280
even4e, 151
execdraw, 363
execproc, 168
expat, 87
expower, 195
extdeg ﬀ, 451
extra6e, 151
f2df, 164
fac, 405
fcat, 155
fcont, 174
fctr, 418
fctr ﬀ, 455
fctri, 194
fctrtos, 202
ﬁeld order ﬀ, 450
ﬁeld type ﬀ, 450
ﬁmag, 171ﬁndin, 230
ﬁnt, 169
ﬂim, 174
ﬂist, 488
ﬂoor, 445
fmmx, 173
fmult, 159
fouriers, 227
fprintf, 441
frac, 227
frac2n, 187
fractrans, 87

hcyclic, 473
heap, 486
hessian, 210
heun, 152
hgr, 461
hkatsura, 473
i2hex, 278
iand, 410
idiv, 405
ifplot, 447

534

igcd, 406
igcdcntl, 406
ilcm, 407
imag, 408
int32ton, 410
integrate, 212
intpoly, 211
inv, 407
invf, 205
invmat, 431
ior, 410
irem, 405
irredcheck ﬀ, 455
isall, 154
isalpha, 176
isalphanum, 176
iscoef, 206
iscombox, 319
iscommutefamily, 242
iscommuteset, 242
iscrat, 176
isdecimal, 176
isdif, 158
isdisjopint, 242
isdisjopintfamily, 242
isfctr, 202
ishift, 410
isint, 176
isMs, 153
isnum, 176
isort, 237
isqrt, 407
israt, 176
isshortneg, 172
issquaremodp, 182
issub, 242
istournament, 316
isvar, 157
isyes, 153ixor, 410

lex tl, 462
lext2, 248
lextn, 235
lft01, 147
lgcd, 236
linfrac01, 147llbase, 234llcm, 236
llextn, 235
llget, 238
llord, 243llselect, 237
llsize, 230
llsymred, 243lmax, 235
lmaxsub, 236
lmin, 236
lmptop, 452
lngamma, 230
lninbox, 319
lnsol, 234
load, 439
lpair, 247
lpgcd, 210
lrandom, 407
lsol, 234
lsort, 238
lsub, 303
lsum, 235
ltotex, 292
ltov, 427
lv2m, 252
lxor, 230
m1div, 80m2l, 252m2ll, 252
m2lv, 252
m2mc, 141
m2v, 252
madj, 266
madjust, 255
makenewv, 156
makev, 156map, 487
mat, 430
matc, 430
mathematica.rtomstr, 527
mathematica.start, 527
mathematica.tree to string, 527
matr, 430
matrix, 429
matrix adjugate, 493
matrix clone, 493
matrix det, 494
matrix diagonal matrix, 493
matrix eigenavalues, 495
matrix identity matrix, 493
matrix image, 493
matrix inner product, 494
matrix inverse, 494
matrix kernel, 494
matrix list to matrix, 493
matrix matrix to list, 493
matrix rank, 495
matrix solve linear, 494

jacobian, 210jell, 230
jis2sjis, 278
katsura, 473
keyin, 155kmul, 423
ksquare, 423
ktmul, 423
kzext, 147
l2min, 246
l2os, 279l2p, 232
ladd, 302
laplace, 93
laplace1, 93
lbezier, 323
lchange, 235
lcount, 231
lcut, 230
ldev, 237
ldict, 283
length, 426
lex hensel, 462

535

matrix submatrix, 494
matrix transpose, 494
mc, 93
mc2grs, 128
mce, 93
mcfamily, 139
mcgrs, 103
mcmgrs, 144mcolor, 330
mcop, 103
mcset, 140mcvm, 119mdivisor, 80
mdsimplify, 272
meigen, 271
mext2, 272
mgen, 266
midKZ, 138
mindeg, 414
minipoly, 463
minipolym, 463
mmc, 146
mmod, 265
mmulbys, 160
modfctr, 419
module deﬁnedp, 444
module list, 444
monotos, 290
monototex, 290
mperm, 254
mpower, 256mrot, 304
msort, 245
mt load, 407
mt save, 407
mtotex, 299
mtoupper, 256
mtransbys, 159
mtranspose, 255
muldo, 74
muledo, 75
mulpolyMod, 189
mulseries, 233
mulsubst, 158
my tex form, 287
myacos, 228
myarg, 229
myasin, 228
myatan, 228
mycat, 232
mycat0, 232
mycoef, 206
mycos, 228
mydeg, 205
mydet, 264
mydet2, 264
mydeval, 162
mydiﬀ, 208
myediﬀ, 208
myeval, 162
myexp, 228
myf2deval, 168
myf2eval, 167
myf3deval, 168
myf3eval, 168
myfdeval, 167

myfeval, 167
mygcd, 78
myhelp, 152
myimage, 265
myinv, 265
mykernel, 265
mylcm, 80
mylog, 228
mymindeg, 205
mymod, 265
mypdiﬀ, 208
mypow, 229
myrank, 264
mysin, 228
mysubst, 158
myswap, 158
mytan, 228
mytrace, 264
myval, 163
n2a, 277
nd det, 430
nd f4, 464
nd f4 trace, 464
nd gr, 464
nd gr trace, 464
nd weyl gr, 464
nd weyl gr trace, 464
ndict, 284
newalg, 456
newbmat, 270
newbytearray, 428
newKZmat, 137
newmat, 429
newstruct, 436
newvect, 427
nextpart, 285
nextshort, 285
nextsub, 284
nlog, 228
nm, 406
nmono, 414
ntable, 372
nthmodp, 181
ntogf2n, 453
ntoint32, 410
ntype, 443
number abs, 492
number ceiling, 492
number factor, 492
number ﬂoat to rational, 492
number ﬂoor, 492
number imaginary part, 492
number is integer, 492
number real part, 493
numtournament, 181
odd5e, 151
odiﬀ act, 505
odiﬀ act appell4, 505
odiﬀ op appell4, 504
odiﬀ op fromasir, 504
odiﬀ op toasir, 504
odiﬀ op tosm1, 504
odiﬀ poly solve, 505
odiﬀ poly solve appell4, 505

536

odiﬀ poly solve hg1, 505
odiﬀ rat solve, 505
odmodule ch ideal, 507
odmodule d op fromasir, 506
odmodule d op toasir, 506
odmodule d op tosm1, 506
odmodule elimination, 507
odmodule restriction, 507
okubo3e, 149
okuboetos, 88
om start, 503
om xml, 503
om xml to cmo, 503
open canvas, 448
open ﬁle, 441
openGlib, 329
ord, 415
orthpoly, 195
output, 439
ox asir, 478
ox check errors2, 502
ox cmo rpc, 478
ox execute string, 478
ox ﬂush, 482
ox get, 480
ox get serverinfo, 482
ox intr, 479
ox launch, 475
ox launch generic, 476
ox launch nox, 475
ox pop cmo, 480
ox pop local, 480
ox pops, 481
ox push cmd, 480
ox push cmo, 480
ox push local, 480
ox reset, 479
ox rpc, 478
ox select, 481
ox shutdown, 475
ox sync, 480
oxshell.get value, 502
oxshell.oxshell, 502
oxshell.set value, 502

frac, 412
gamh, 446
gamma, 446
hess, 433
indexrank, 433
isprime, 412
ispsp, 412
issquare, 411
jacobi, 434
jell, 447
lngamma, 446
mu, 413
nextprime, 412
numdiv, 412
omega, 412
phi, 413
psi, 446
roots, 425
round, 425
sigma, 412
signat, 433
sqrt, 445
supplement, 433
trace, 433
wp, 446
wp2, 446
zeta, 447
partspt, 246
pcoef, 207
periodicf, 166
permanent, 264
pf2kz, 117
pfargs, 157
pfctr, 207
pfp omega, 512
pfpcoh intersection, 512
pfphom intersection, 512
pfphom monodromy pair kyushu, 512
pfrac, 209
pg2tg, 310
pgen, 189
pgpart, 311
phc.phc, 513
phc.start, 513
plot, 447
plotover, 447
plucker index, 514
plucker y, 514
pluspower, 233
pmaj, 207pol2sft, 194
polarplo, 447
polbyroot, 189
polbyvalue, 189
polcut, 208
polinsft, 194
polinsym, 194
polinvsym, 194
polrealroots, 192
polroots, 192
polstrum, 191poly coeﬃcient, 500
poly degree, 498
poly elimination ideal, 497
poly expand, 497
poly factor, 497

p nf, 471
p nf mod, 471
p terms, 472
p true nf, 471
p true nf mod, 472
paracmpl, 249
pari, 408
abs, 412
adj, 433
arg, 445
bigomega, 412
binary, 411
cf, 413conj, 412
content, 425
dilog, 446
disc, 425
eigen, 434
erfc, 446
eta, 446
factor, 411537

poly gcd, 497
poly gr w, 498
poly grobner basis, 497
poly hilbert polynomial, 497
poly ideal colon, 500
poly ideal intersection, 500
poly ideal saturation, 500
poly in, 498
poly in w, 499
poly in w , 499
poly initial, 498
poly initial coeﬃcients, 498
poly initial term, 498
poly ord w, 499
poly prime dec, 500
poly r omatrix, 498
poly solve linear, 499
poly sort, 499
poly toric ideal, 500
poly weight to omatrix, 500
powprimroot, 367
powsum, 227
prehombf, 211
prim, 420
primadec, 473
primedec, 473
primedec mod, 474
primroot, 182
print, 440
print dvi form, 495
print em, 495
print gif form, 495
print input form, 495
print open math tfb form, 496
print open math xml form, 495
print output, 496
print ox rfc100 xml form, 495
print png form, 495
print terminal form, 496
print tex form, 496
print tfb form, 496
print xdvi form, 496
print xv form, 496
printf, 441
psubst, 417
psymbol, 78
pt5center, 309
ptaﬃne, 305
pTaylor, 201
ptbbox, 319
ptbezier, 324
ptcombezier, 328
ptcombz, 329
ptcommon, 307
ptcontain, 310
ptconvex, 318
ptcopy, 307
pterm, 208
ptinversion, 309
ptlattice, 307
ptogf2n, 453
ptol, 209
ptosfp, 454
ptozp, 420
ptpolygon, 306
ptwindow, 319

ptype, 154
purge stdin, 441
put byte, 441
pweight, 208
pwTaylor, 219
qdo, 80
qsort, 429
qsortn, 237
quit, 438
r2ma, 282
r2os, 280
rabin, 183
radd, 188
random, 407
random ﬀ, 452
randpoly ﬀ, 455
rattoalgp, 458
rcotr, 94
readcsv, 282
readTikZ, 281
real, 408
red, 421
rede, 93
redgrs, 104register handler, 479
register server, 477
regress, 233
remove ﬁle, 441
remove module, 444
res, 418
res0, 190
reverse, 426
rigid211, 151
rint, 445
risaout.tex, 384
risatex.bat, 384
rmul, 189
rootmodp, 182
rowa, 432
rowm, 432
rowx, 432
rpdiv, 190
rsort, 237
rtostr, 434
rtotex, 290
rungeKutta, 217
s2csp, 95
s2euc, 279
s2m, 253
s2os, 278s2sjis, 279
s2sp, 94sadj, 287
scale, 320
schurpoly, 196
sdiv, 415
sdivm, 415
seriesHG, 201
seriesMc, 196
seriesTaylor, 375
set ﬁeld, 460
set upﬀt, 423
set upkara, 423

538

set uptkara, 423
setmod ﬀ, 449
setmode, 410
setprec, 409
sexps, 287
sﬀctr, 455
sfptop, 454
sftexp, 87
sftpexp, 78
sftpow, 195
sftpowext, 195sgn, 175
sgnstrum, 191
shell, 487
shiftop, 115
shiftPfaﬀ, 116
shortv, 156
show, 288
showbyshell, 155
simp ﬀ, 451
simpalg, 457
simplify, 160
sint, 186
sinv, 287
size, 428
sjis2jis, 278
sleep, 486
slen, 287
sm1.ahg, 523
sm1.appell1, 521
sm1.appell4, 522
sm1.auto reduce, 522
sm1.bfunction, 523
sm1.call sm1, 523
sm1.deRham, 517
sm1.distraction, 521
sm1.ecart homogenize01Ideal, 523
sm1.ecartd gb, 523
sm1.ecartd gb oxRingStructure, 524
sm1.ecartd isSameIdeal h, 524
sm1.ecartd reduction, 524
sm1.ecartd reduction noh, 524
sm1.ecartd syz, 524
sm1.gb, 516
sm1.gb d, 516
sm1.gb oxRingStructure, 524
sm1.gb reduction, 524
sm1.gb reduction noh, 525
sm1.generalized bfunction, 525
sm1.genericAnn, 519
sm1.gkz, 521
sm1.hilbert, 518
sm1.isSameIdeal in Dalg, 525
sm1.mul, 520
sm1.push int0, 516
sm1.rank, 522
sm1.reduction, 519
sm1.restriction, 525
sm1.saturation, 525
sm1.slope, 523
sm1.sm1, 516
sm1.start, 515
sm1.syz, 520
sm1.wTensor0, 519
sm1.xml tree to preﬁx string, 519
smallmattex, 302

soldif, 88
solpokubo, 91
solveEq, 196
sord, 287
sort2, 238
sp, 459
sp noalg, 459
sp norm, 458
sp2grs, 102
spantree, 245
spbasic, 101
spgen, 97
sprintf, 441
sprod, 286
sproot, 98
spslm, 115
sqfr, 418
sqr, 415
sqrm, 415
sqrt, 229
sqrt2rat, 186
sqrtdo, 86
sqrtrat, 185srem, 415
sremm, 415
ssubgrs, 103stoe, 89str addc, 276
str char, 274
str chr, 435
str cut, 275
str insert, 276
str len, 435
str pair, 274
str str, 274
str subst, 275
str tb, 279
str times, 276
str type, 438
strip, 277
strtoascii, 435
strtov, 434
sub str, 436
subst, 416
substblock, 205
substnum, 158
symtournament, 180
taylorODE, 200
tdiv, 416
terms, 207
texbegin, 291
texcr, 291
TeXEq, 381
texket, 292
texlen, 302
TeXLim, 381
texlim, 302
TeXPages, 381
texsp, 291
tigers.tigers, 525
TikZ, 382
time, 484
timer, 485
tobezier, 322
tobig, 181539

tocsv, 283
todf, 164
todo parametrize, 529
toeul, 86
tohomog, 205
tolex, 462
tolex d, 462
tolex tl, 462
tolexm, 463
translpdo, 76transm, 273
transpart, 285
transpdo, 75
transppow, 76
trcolor, 330
trig2exp, 171
trpos, 286
try accept, 477
try bind listen, 477
try connect, 477
tstart, 485
tstop, 485
type, 443

version, 487
vgen, 249
vnext, 248
vprod, 233
vtol, 428
vtozv, 232
vtype, 443
which, 439
wronskian, 211
xy2curve, 363
xy2graph, 358
xyang, 345
xyarrow, 334
xyarrows, 337
xyaxis, 353
xybezier, 340
xybox, 338
xycirc, 339
xycircuit, 349
XYcm, 382
xygraph, 353
xygrid, 348
XYLim, 382
xyline, 333
xylines, 341
xyoval, 347
xypg2tg, 312
xyplot, 352
xypoch, 352
xypos, 330
XYPrec, 382
xyproc, 330
xyput, 332
xytournament, 316

uc, 414udecomp, 423
udiv, 424
ufctrhint, 419
ugcd, 424
uinv as power series, 424
umul, 422
umul ﬀ, 422
unim, 267
urem, 424
urembymul, 424
urembymul precomp, 424
ureverse, 424
ureverse inv as power series, 424
usquare, 422
usquare ﬀ, 422
util damepathq, 529
util ﬁle exists, 529
util ﬁlter, 528
util ﬁnd and replace, 528
util ﬁnd start, 529
util ﬁnd substr, 528
util index, 529
util load ﬁle as a string, 528
util part, 529
util read ﬁle as a string, 528
util remove cr, 529
util timing, 528
util v, 529
util write string to a ﬁle, 528
utmul, 422
utmul ﬀ, 422
utrunc, 423

zeta, 230
応用

Taylor 展開, 375
函数値の数表, 372
三角函数表, 373
常用対数表, 372
行列の行基本変形, 260
グラフ
円グラフ, 298
折線グラフ, 297
棒グラフ, 297
原始根の表, 367
点数分布表, 374
不定積分の解法, 216
型変換

CSV 形式 → リスト, 282
DAlg ↔ 代数的数, 460
DAlg ↔ 分散多項式, 460
EUC/JIS 文 →ShiftJIS 文, 279
JIS code → ShiftJIS code, 278
root → 不定元, 458
ShiftJIS code → JIS code, 278
ShiftJIS/JIS 文 →EUC 文, 279
TikZ→ 描画実行形式, 281
数 → 文字列, 186
函数 → リスト形式函数, 164
行列 → TEX, 299

vadd, 93var, 413
varargs, 157
vars, 413
vect, 427
vector, 427
velbezier, 324
verb tex form, 290540

行列 → リスト, 252
互換 → 置換, 286
式 → 文字列, 282, 434
自然数 → 一文字, 277
実数 → 整数, 445
実数 → 分数, 183
数式 → TEX, 290, 292
数式 → 入力可能文字列, 280
スペクトル型
GRS → 重複度リストのリスト, 95
GRS ← 重複度リストのリスト, 102
文字列 ↔ 重複度リストのリスト, 94
整数 →16 進文字列, 278
整数の分離, 280
整数のリスト → 文字列, 435
多項式 → リスト, 232
多項式 → 分散多項式, 466
微分作用素 → TEX, 202, 204
不定元 → root, 458分散多項式 → 多項式, 466
分数 → 実数, 187
分数の有理化, 186
ベクトル → TEX, 292, 299
ベクトル → リスト, 428
変数 → 文字列, 529
文字列 → 色コード, 330
文字列 → 行列, 253
文字列 → 座標, 280
文字列 → 式, 282, 435
文字列 → 整数のリスト, 435
文字列 → 入力可能文字列, 278
文字列 → バイト列, 428
文字列 → 変数, 156, 434, 529
有理式 → TEX, 202, 290
有理式 → 文字列, 202
有理数 → bigﬂoat, 181
リスト →CSV 形式, 283
リスト → TEX, 292
リスト → 行列, 252, 253
リスト → 座標文字列, 330
リスト → 多項式, 232
リスト → 入力可能文字列, 279
リスト → ベクトル, 427, 428
リスト形式函数 →bigﬂoat リスト形式函数, 165
連分数 → 分数, 183

trace, 264, 433
演習用の整数行列生成, 267
階数, 264, 495
回転行列, 304
核, 265, 494
簡単化, 272
基本変形, 273
逆行列, 265, 431, 494
行基本変形, 256, 432
演習問題生成, 267
問題解法生成, 256
行の交換, 432
行のスカラー倍, 432
共役変換, 266
行列式, 264, 430, 494
係数行列, 254
固有値, 271, 495
固有ベクトル, 434
固有値ベクトル, 271
サイズ, 428実対称行列の符号, 433
小行列, 254
商写像, 265
正則拡張, 433
正則小行列, 433
線型変換の外積, 272
線形方程式の解, 494
像, 265, 493
単因子, 80置換行列で変換, 254
定義, 253, 429, 430
一般行列, 266
対角行列, 266, 493対称行列, 266
置換行列, 266
ブロック行列, 270
転置, 255, 494
同時スペクトル, 126
複製, 251, 493
部分行列, 494
べき, 256
ヘッセンベルグ行列, 433
ユニモジュラー行列生成, 267
余因子行列, 433, 493
列基本変形, 432
列数調整, 256
列の交換, 432
列のスカラー倍, 432

函数
値を得る, 168
オプション, 488
オプションリストの変更, 231
函数子, 444
自明簡略化, 161
スカラー演算を行列演算に拡張, 160
定義済みかとうかのチェック, 152
定義済み函数, 488
引数リスト, 444
評価, 161
含まれる初等函数のリスト, 157
含まれる変数と初等関数, 157
呼び出し, 443
リスト形式函数, 396
リスト形式手続きの実行, 168
リスト，配列に拡張, 159, 487

グレブナー基底, 461, 464b 関数, 474
F4 アルゴリズム, 464
S-多項式, 471

sugar, 469
weight, 466
Weyl 代数, 464
頭項の商, 470
頭項の全次数, 469
一回の簡約, 471
イデアルの分解, 473, 474
基底変換, 462, 463
係数の型変換, 467
係数のビット長の和, 470
係数の標準化, 467
最小公倍項, 470最小多項式, 463

逆変換, 196
行列

permanent, 264541

指数ベクトル, 470
正規化, 468, 472
先頭部分, 469
多項式 → 分散多項式, 466
多項式リスト生成, 473
パラメータの設定，表示, 465
比較, 472
非斉次化, 467
分散多項式 → 多項式, 466
変数順序型の設定, 参照, 465
リスト化, 472

ヒストリの消去, 488
プロセスの一時停止, 486
プロンプト, 483
マニュアル表示, 152
集合, 403

disjoint?, 242
middle convolution, 140
可換部分集合族, 139
合併, 238, 491
共通部分, 238, 489
極小, 236
極大, 236
区間表現された整数のリスト, 235
交換可能か？, 242
集合族
対称性で最小元, 243
除外, 238, 490, 491
整数の区間表現, 235
重複を除く, 238
部分集合か？, 242
包含関係, 243
常微分作用素座標

Bézier 曲線, 322
キャンバスに描画, 341
結合, 305
交点, 328, 329
最大速度, 324
座標と速度, 324
データ変換, 323

Bounding box, 319
Window, 319
アフィン変換, 305
回転行列, 304
回転数, 304
角度, 307
共通部分の有無, 319
距離, 303
格子点, 307
交点, 307
コピー, 307
差の座標, 303

addition, 93
versal, 93
Basic スペクトル型の生成, 101
Euler 型から変換, 87
Euler 型の積, 75
Euler 型へ変換, 86
middle convolution, 93
留数行列の和, 103
Riemann scheme
middle convolution and addition, 103
reduction, 104
解析, 95
生成, 102
部分特性指数和, 103
一次分数変換, 87
合流, 116特性指数, 118

三角形
五心, 309
三角形内, 310
垂線の足, 307
正多角形, 306
接円, 309
接点, 307
直線と箱内の共通部分, 319
凸包, 318
内分点, 307
反転, 309
描画実行形式, 305
平行移動, 307
偏角, 229
方向転換進行点, 307
面積, 325
和や差や一時結合の座標, 302

合流スペクトル型
文字列との変換, 95固有多項式, 91
最小公倍元, 80
最大公約元, 78
スペクトル型
Riemann scheme 生成, 102
解析, 95, 98
生成, 97
並べ替え, 94
文字列との変換, 94
単因子, 80
割り算, 78
常微分方程式KZ 系

GRS, 104
CSV 形式, 282, 283
システム

Asir のバージョン, 487
Asir のルートディレクトリ, 488
CPU time, 484
開始, 485
終了, 485
ガベジコレクション, 483
環境変数, 489
時刻, 486
制限時間つき実行, 485
設定の表示, 290
デバッグモード, 484
エラー表示, 484
ヒープサイズ, 486

residue matrices, 137, 138
全留数行列, 147

middle convolution
合流, 119
Okubo 型に変換, 88
Pfaﬀ 系を KZ 系に変換, 117
Runge-Kutta 法, 200
一階線型システムを高階単独へ変換, 89
基底の変換, 80
形式解, 88
数値解析, 217, 219
双有理変換, 197542

単独化, 197
単独高階線形を一階システムへ変換, 90
特性指数, 87
半局所モノドロミー, 103, 115
Fuchs 型の解析, 104
べき級数解, 201
隣接関係式, 115, 116

不定積分, 212
解法生成, 212
平均値, 233
平方根, 229, 445
ヘシアン, 210
偏角, 229
ヤコビアン, 210
有限フーリエ級数, 227
リスト形式函数, 396
リスト形式函数の合成, 165
リスト形式函数の生成, 164
ロンスキアン, 211

数式
符号反転との表示比較, 172
不定変数, 397
数値函数

arccos, 444
arcsin, 444
arctan, 444
cos, 228, 444
log, 228, 445
log10 , 228acos, 228
asin, 228
atan, 228
sin, 228, 444
tan, 228, 445
xy , 229
erf, 227
Maclaurin 展開, 196
sgn, 175
Taylor 展開, 196, 375
常微分方程式, 200, 201
値を得る, 162, 163, 168, 408
回帰直線, 233
函数形式削除, 164
函数値の変更, 166
ガンマ函数, 229
級数の和, 168
極限値, 174
極値, 173
切り上げ整数, 445
合成関数の微分, 208
最大値，最小値, 173三角函数と指数函数の簡単化, 171, 172

整数

16 進表示, 278
2 進数, 411
and, 410
bit shift, 410
Catalan 数, 177
許容 01 列, 178
トーナメント表, 178
凸多角形の三角形分割, 178or, 410
pPq, pCq, pHq, 177
Stirling 数, 177
xor, 410
オイラーの φ 函数, 413
階乗, 406
原始根, 182
表作成, 367
合同式
逆数, 407
平方剰余, 182
べき, 182
べき乗根, 182
最小公倍数, 80, 407
最大公約数, 78, 406
自然数
一文字表記, 277
商, 405
剰余, 405, 420
素因数の個数, 412
素因数分解, 411, 492
素数生成, 412
判定, 183, 412
単因子, 80
トーナメント図のタイプ数, 180
トーナメント戦の場合の数, 180, 181場合の数, 177
分割
生成, 285
双対, 286
短い, 285
分割数, 177
平方根, 407
平方数, 411
ベルヌーイ数, 177
メビウス函数, 413
約数の個数, 412
約数の和, 412
乱数, 407

四捨五入
桁指定, 186
整数に, 445
指数函数, 228, 445
実数の小数部分, 227周期函数に拡張, 166
小数部分, 412
数値積分, 169, 325, 399
Bezier 曲線法, 169
Romberg 積分, 169
シンプソンの公式, 169
台形公式, 169
整数部分, 445
積分区間変更, 167
絶対値, 175, 445
零点, 173
相関係数, 233
相補誤差関数, 446
対数ガンマ函数, 230
ダイログ函数, 230
ディガンマ函数, 230
特異点, 174
任意精度浮動小数, 409, 483
標準偏差, 233
複素積分, 169

双有理変換, 196
ソート, 429
2 成分, 238

543

インデックス, 237
逆順, 237
二分木, 244
マルチキー, 245
リカーシブ, 237
リストのリスト, 238

因数分解, 418
重み付き斉次式に分解, 208
基本対称式, 194
共通因子, 210
共通根, 192
係数, 207, 414
係数抽出, 206
係数のチェック, 206
係数のリスト, 209
係数を整数に丸める, 425
項数, 415合成関数の微分, 208項の抽出, 208
最低次数, 205
斉次化, 205
生成, 189
定数項, 207
べき指数の項, 208
べき指数のリスト, 208優多項式, 207
割り算, 415

対数尺, 320
代数的数

DAlg ↔ 代数的数, 460
DAlg ↔ 分散多項式, 460
GCD, 458
root, 457
root → 不定元, 458
因数分解, 459
簡単化, 457
基礎体, 460
最小分解体, 459
生成, 456
定義多項式, 457
ノルム, 458
不定元, 457
不定元 → root, 458

チェック

代数方程式
連立
数値解, 192, 513
有理式解, 196
有理数解, 192
多角形
三角形分割, 310, 311
表示, 312凸包, 318
多項式
Schur 多項式, 196disjoint, 242
Windows 環境, 153
アルファベット/数字の文字コード, 176
アルファベットの文字コード, 176
交換可能リスト, 242
実部虚部共に有理数数, 176
小数を表す文字列, 176
数字の文字コード, 176
整数, 176多項式の係数, 206
定義済み函数, 152
微分作用素, 158
部分リスト, 242
平方式, 411
平方数, 411
変数, 157
有理数, 176
有理数係数, 202

shifted power, 195
一変数

Gauss 整数体上の既約分解, 194
Gegenbauer 多項式, 195
Hermite 多項式, 195
Jacobi 多項式, 195
Laguerre 多項式, 195
Legendre 多項式, 195
shifted power, 194
strum 列と実根の個数, 191
strum 列の符号変化数, 191
因数分解, 207
共通根の存在条件, 190
係数の最大公約元, 425
原始函数, 211
高次の項を無視した積, 189根, 189, 192, 193, 425
最小公倍式, 80
最大公約式, 78
最低次数, 414
次数, 205, 414
実根, 192
終結式, 418
選点直交多項式, 195
素因子の個数, 412
単因子, 80
チェビシェフ多項式, 195
直交多項式, 195
判別式, 425
べき和多項式, 227
ベルヌーイ多項式, 227
割り算, 190

置換

Bruhat order, 287
完約表現, 287
逆元, 287
共役変換, 287
互換, 286
積, 286次の置換, 283
長さ, 287
TEX
Pfaﬀ 形式, 293
Pochhammer cycle, 352
Riemann scheme, 292
xypic, 385
2 変数関数の 3D グラフ, 358Bézier 曲線, 340
円, 339円弧, 345
扇形, 345
折線, 341
開始と終了, 330
角の記号, 345関数のグラフ, 353
曲線, 341544

空間曲線の描画, 363
座標，式, 331
座標軸, 354
線種, 334, 394
方眼紙, 348
楕円の弧, 347
多角形, 341
長方形, 338
直線, 333
通過点のアフィン変換, 305
通過点の複数コピー, 345
塗りつぶし, 340, 394
描画実行形式の実行, 363
表示, 330
閉曲線, 341
平行四辺形, 338
目盛, 320
文字列，式, 332
文字列表示, 330
矢印, 334, 337, 345
因数分解, 202
改行, 290
改ページ, 290
数, 186
括弧のサイズ調整, 292
画面表示, 289, 290
自動制御, 288
制御, 290
キーワード, 291
行分割, 302
行列, 299
小サイズ, 302
分割と並べ替え, 301
行列の行基本変形, 256, 260
グラフ
2 変数関数, 358
円グラフ, 294, 298
折線グラフ, 294, 297
関数のグラフ, 353
座標軸, 353
点のプロット, 352
棒グラフ, 294, 297
消去, 290常微分方程式の解析, 104
数式, 290
改行文字列, 291
ページ内行数閾値, 381
電気回路, 349
微分形式, 293
微分作用素, 202, 204
表, 293変形, 369
例, 297, 298, 367
部分分数展開, 209
ベクトル, 299
文字数幅, 302, 381
有理式, 202, 290
リスト, 292
列ベクトル, 293

入出力shell, 487
結果の表示, 155
結果を文字列として取得, 155
１行入力, 155
環境変数, 489
キー入力, 155
出力切り替え, 439

CPU time, 483
表示, 232, 440
実数, 483
標準入力
バッファクリア, 441
ファイル
1 行読む, 441
1 バイト書く, 441
1 バイト読む, 441
CSV 形式に変換, 283
CSV 形式読み込み, 282
出力, 155
消去, 441
存在チェック, 441
閉じる, 441
バイナリ読み書き, 440
開く, 441
フォーマットつき表示, 441
プログラム
読み込みパス名, 439
読み込み, 439
パッフ形式

addition, middle convolution, 141
変換

Riemann scheme, 128, 144
パラメータ
基底の完備化, 249
微分形式
外微分, 91

TEX, 293

微分作用素

formal adjoint, 77
principal symbol, 78
一般準同型変換, 75
座標のベキ函数変換公式, 76
積, 74
積と和, 75
線形座標変換, 76
双有理座標変換, 75
有理式への作用, 78
有理式への作用積, 78
ラプラス変換, 93
描画

1 変数函数, 447
TEX, 353
2 変数函数
TEX, 358
零点, 447
等高線, 447
Bézier 曲線, 341
Pochhammer cycle, 352
円弧, 345
扇形, 345角の記号, 345
重ね書き, 305, 366, 367

トーナメント戦タイプ, 180
チェック, 316
トーナメント図, 316
トーナメント表の数, 178場合の数, 180, 181545

極形式, 447
空間曲線, 363
座標軸, 353三角形
外接円, 345
内接円, 345
垂線, 345
方眼紙, 348
楕円, 347
点，線分, 449
電気回路, 349
描画実行形式, 365
種別番号, 365
描画実行形式の実行, 363
複数の点

順序, 415
生成, 156, 434, 529
添え字番号をはずす, 156
チェック, 157
含まれる不定元のリスト, 157
分散計算
遠隔プロセス終了, 475
遠隔プロセス起動, 475, 476
コマンド送信, 480
送信, 480
送信バッファフラッシュ, 482
データ削除, 481
データ受信, 480, 481
動作中のプロセス識別子, 482
プリミティブ, 477
プロセス函数呼び出し, 478
プロセスリセット, 479
読み出し可能プロセス, 481
分数q-変形, 183
循環連分数, 183
有理化, 186
連分数, 183
連分数展開, 183, 413

TEX, 352

文字列, 449
矢印, 345
描画キャンバスglib
クリア, 329, 501
座標対応, 501
線分, 501
点, 501
開く, 501
窓サイズ, 329
文字列, 501
色変換, 330
クリア, 449
生成, 449
中間色, 330
デフォルトサイズ, 380

巾級数, 232

Appell の超幾何級数, 202
Maclaurin 展開, 196
Taylor 級数, 375
一般超幾何級数, 201
逆元, 424
高次のカット, 208
積, 2332 変数超幾何級数, 202
巾関数, 233

複素変数

Appell の超幾何級数, 202
Dedekind の Eta 函数, 230, 446
digamma 函数, 446
dilogarithm 函数, 446
elliptic j-invariant, 230
一般超幾何級数, 201
ウエーバー函数 f(τ ), 446
ウエーバー函数 f2 (τ ), 447ガンマ函数, 229, 446
逆三角関数, 228
共役複素数, 408, 412
虚部, 408三角函数, 228
指数函数, 228
指数関数を実変数に, 171
実部, 408
常用対数, 228
絶対値, 175, 413
対数関数, 228
対数ガンマ函数, 230
ダイログ函数, 230
ディガンマ函数, 230
2 変数超幾何級数, 202
複素積分, 169
平方根, 229, 445
べき函数, 195
巾関数, 229
偏角, 229, 445
リーマンの ζ 函数, 230, 447
留数, 174ベクトル
2 つのベクトルを pair のリストへ, 247
外積, 303
成分の置き換え, 158
ソート, 429
マルチキー, 245
次の並び替えたベクトル, 248
定義, 427
内積, 233成す角に応じた数, 303
ノルム, 303
鋏む角の余弦, 305
範囲内の成分数, 231
偏角に応じた数, 303
要素の値の個数分布表, 231
変数｜ see 不定元, 34

Mathematica, 282
目盛, 320
文字列

cr/lf/tabs を削除, 529
EUC/JIS 文を ShiftJIS 文に変換, 279
ShiftJIS/JIS 文を EUC 文に変換, 279
繰り返し, 276
差し込み印刷, 276
数式を入力可能文字列に, 280
外側の括弧を外す, 277
テキスト用バッファ, 279
長さ, 435

不定元型, 443546

部分文字列検索, 274, 528
部分文字列対応検索, 274
部分文字列置換, 275, 528
部分文字列抽出, 275, 436
文字検索, 274, 435
文字挿入, 276

整数のリストの区間表現, 235
成分の置き換え, 158, 235
成分の削除・抽出・付加, 231
成分の和, 235
先頭, 426
先頭に追加, 426
先頭を除く, 426
ソート, 429
インデックス, 237
逆順, 237
成分, 246
二分木, 244
マルチキー, 245
リカーシブ, 237
次の並び替え, 285
転倒数, 175
内部のリストをほどく, 252, 489
長さ, 426
並び替え番目, 284
二分木, 244函数による生成, 245
入力可能文字列に変換, 279
範囲内の要素数, 231
表形式データの操作, 237, 238
符号, 175
部分リスト, 230
部分リストか？, 242
部分リストの列挙, 489
分数のリストの簡略化, 489
包含関係交換, 243
有限区間の集合, 247
要素 xor, 230
要素検索, 230
要素数調整, 256
要素の値の分布個数表, 231
要素の重複度, 231
リスト形式函数, 162–164
リストのリストのサイズ, 230
リストのリストを転置, 255
連結, 252, 426
リスト形式データ, 401

ユークリッドの互除法, 78, 190
有限体
基礎体
位数, 450拡大次数, 451
種類, 450元の定義, 451
設定, 449
多項式, 452
既約判定, 455
既約分解, 455
生成, 454, 455多項式の変換, 453
標数, 451
変換, 453, 454
乱数, 452
有理式

TEX, 202
因数分解, 207
項数, 415
主変数, 413
双有理変換, 196
対数微分, 209
代入, 158, 417
不定元の巡回置換, 158
部分分数展開, 209
分子, 406
分母, 406
変数のリスト, 413
偏微分, 77
文字列へ, 202
約分, 421, 489
有理数係数？, 202
有理変換の合成, 158
有理数
近似実数から変換, 183
分子, 406
分母, 406
平方根, 185

Runge-Kutta 法, 217
解析, 200, 201
連立一次方程式, 234
簡易化, 234
有理数解, 234

リスト
2 次の外積の並べ替え, 248
2 成分のソート, 238
pair のリスト, 247
合併，共通部分，除外, 238, 489–491
逆順, 426
共通なし？, 242
最小集合, 236
最大集合, 236
繰り返し, 276
繰り返しを用いたリストの生成, 489
交換可能か？, 242
最小公倍数（元）, 236
最小の成分, 236
最大公約数（元）, 236
最大の成分, 236
細分関係, 246
整数商での割り算, 237
整数の集合の区間表現のリスト, 235

Risa/Asir, 27
コマンドラインオプション, 28
環境変数, 28
起動から終了まで, 28割り込み, 29
エラー処理, 30
計算結果，特殊な数, 30型, 31Asir で使用可能な型, 31
数の型, 33
不定元の型, 34
ユーザ言語 Asir, 35
文法 (C 言語との違い), 35
ユーザ定義函数, 36
変数および不定元, 37
引数, 38
コメント, 38547

文, 39return 文, 39
if 文, 40
ループ, 40
構造体定義, 41
さまざまな式, 41
プリプロセッサ, 42
オプション指定, 43
モジュール, 45デバッガ, 47
デバッガとは, 47
コマンドの解説, 47
デバッガの使用例, 49
デバッガの初期化の例, 50
文法の詳細, 50
有限体における演算, 53
有限体の表現および演算, 53
有限体上での 1 変数多項式環の演算, 54
小標数有限体上での多項式環の演算, 54
有限体上の楕円曲線に関する演算, 54
代数的数に関する演算, 55
代数的数の表現, 55分散多項式による代数的数の表現, 56
代数的数の演算, 57
代数体上での 1 変数多項式の演算, 58
グレブナー基底の計算, 60
分散表現多項式, 60
ファイルの読み込み, 60
基本的な関数, 60
計算および表示の制御, 61
項順序の設定, 63

Weight, 64
有理式を係数とするグレブナ基底, 65
基底変換, 65
Weyl 代数, 66
分散計算, 66

OpenXM, 66
Mathap, 67
スタックマシンコマンド, 67
デバッグ, 68

Asir-Contrib, 69
Risa/Asir と os muldif.rr, 71
os muldif.rr のインストール, 72

548