os muldif

大島利雄

March 20, 2024

目次

1  List of Functions  6

1.1 Functions related to differential operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.1.1 Fundamental functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.1.2 Fractional calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.1.3 Some operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.2 Useful functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.2.1 Extended function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.2.2 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.2.3 Polynomials and rational functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.2.4 Functions with real/complex variables . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.2.5 Lists and vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 1.2.6 Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.2.7 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.2.8 Permutations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.2.9 TEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.2.10 Lines and curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 1.2.11 Drawing curves and graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 1.2.12 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.2.13 Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

1.3 Functions in the original library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.3.1 数の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.3.2 多項式，有理式の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 1.3.3 リスト，ベクトル，配列の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 1.3.4 行列の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 1.3.5 文字列に関する演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 1.3.6 構造体に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 1.3.7 入出力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 1.3.8 型や函数，モジュールに関わる函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 1.3.9 数値函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 1.3.10 描画函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 1.3.11 有限体に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 1.3.12 代数的数に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 1.3.13 グレブナー基底に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 1.3.14 分散計算に関する関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 1.3.15 その他の函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

1.4 Functions in the contributed library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 1.4.1 基礎 (標準函数) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 1.4.2 数（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 1.4.3 行列（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 1.4.4 表示（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 1.4.5 多項式（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 1.4.6 グラフィックライブラリ（2 次元） . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 1.4.7 OpenXM-Conrib 一般函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 1.4.8 OXShell の関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 1.4.9 OpenMath 函数 (1999 版) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.4.10 Differential equations (by Okutani) . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.4.11 D-module (by Okutani) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.4.12 DSOLV 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.4.13 GNUPLOT 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.4.14 _{p}F_{q} に関するコホモロジー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.4.15 PHC 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.4.16 Plucker 関係式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.4.17 SM1 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.4.18 TIGERS 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 1.4.19 Mathematica 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 1.4.20 便利な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 1.4.21 その他 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

2  Risa/Asir  52

2.1 Risa および Asir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 2.2 Asir の特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 2.3 コマンドラインオプション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 2.4 環境変数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 2.5 起動から終了まで . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 2.6 割り込み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 2.7 エラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 2.8 計算結果，特殊な数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 2.9 型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

2.9.1 Asir で使用可能な型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 2.9.2 数の型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 2.9.3 不定元の型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

2.10 ユーザ言語 Asir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 2.10.1 文法（C 言語との違い） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 2.10.2 ユーザ定義函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 2.10.3 変数および不定元 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 2.10.4 引数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 2.10.5 コメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 2.10.6 文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 2.10.7 return 文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 2.10.8 if 文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 2.10.9 ループ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 2.10.10 構造体定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 2.10.11 さまざまな式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 2.10.12 プリプロセッサ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 2.10.13 オプション指定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 2.11 モジュール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 2.12 デバッガ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

2.12.1 デバッガとは . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 2.12.2 コマンドの解説 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 2.12.3 デバッガの使用例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 2.12.4 デバッガの初期化ファイルの例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 2.12.5 文法の詳細 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

2.13 有限体における演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 2.13.1 有限体の表現および演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 2.13.2 有限体上での 1 変数多項式環の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 2.13.3 小標数有限体上での多項式環の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 2.13.4 有限体上の楕円曲線に関する演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

2.14 代数的数に関する演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 2.14.1 代数的数の表現 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 2.14.2 分散多項式による代数的数の表現 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 2.14.3 代数的数の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 2.14.4 代数体上での 1 変数多項式の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

2.14.4.1 GCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 2.14.4.2 無平方分解，因数分解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 2.14.4.3 最小分解体 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

2.15 グレブナー基底の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 2.15.1 分散表現多項式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 2.15.2 ファイルの読み込み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 2.15.3 基本的な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 2.15.4 計算および表示の制御 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 2.15.5 項順序の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 2.15.6 Weight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 2.15.7 有理式を係数とするグレブナ基底 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 2.15.8 基底変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 2.15.9 Weyl 代数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

2.16 分散計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 2.16.1 OpenXM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 2.16.2 Mathcap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 2.16.3 スタックマシンコマンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 2.16.4 デバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

2.16.4.1 エラーオブジェクト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 2.16.4.2 リセット . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 2.16.4.3 デバッグ用ポップアウトウインドウ . . . . . . . . . . . . . . . . . . . . . . . . . 94

2.17 Asir-Contrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 2.17.1 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 2.17.2 Asir/Contrib のロード方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 2.17.3 Asir Contrib の函数名について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 2.17.4 Windows 版 Asir-Contrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

2.18 Risa/Asir と os muldif.rr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 2.18.1 os muldif.rr のインストール . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

3  Functions  99

3.1 Functions related to differential operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 3.1.1 Fundamental functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 3.1.2 Fractional calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 3.1.3 Some operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

3.2 Useful functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 3.2.1 Extended function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 3.2.2 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 3.2.3 Polynomials and rational functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 3.2.4 Functions with real/complex variables . . . . . . . . . . . . . . . . . . . . . . . . . . 245 3.2.5 Lists and vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 3.2.6 Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 3.2.7 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 3.2.8 Permutations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 3.2.9 TEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 3.2.10 Lines and curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 3.2.11 Drawing curves and graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 3.2.12 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375

3.2.12.1 表の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 3.2.12.2 表や行列の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 3.2.12.3 函数値の数表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 3.2.12.4 点数分布表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 3.2.12.5 Table of score distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382 3.2.12.6 計算尺 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384

3.2.13 Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 3.2.14 補足 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

3.2.14.1 行列の入力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 3.2.14.2 平面図形 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 3.2.14.3 リスト形式函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 3.2.14.4 実数値／複素数値函数の解析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 3.2.14.5 表形式データ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408

3.3 Functions in the original library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 3.3.1 数の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 3.3.2 多項式，有理式の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 3.3.3 リスト，ベクトル，配列の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431 3.3.4 行列の演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434 3.3.5 文字列に関する演算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439 3.3.6 構造体に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441 3.3.7 入出力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 3.3.8 型や函数，モジュールに関わる函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448 3.3.9 数値函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 3.3.10 描画函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452 3.3.11 有限体に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455 3.3.12 代数的数に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462 3.3.13 グレブナー基底に関する函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466 3.3.14 分散計算に関する関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 3.3.15 その他の函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488

3.4 Functions in the contributed library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 3.4.1 基礎 (標準函数) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 3.4.2 数（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497 3.4.3 行列（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 3.4.4 表示（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 3.4.5 多項式（数学標準函数） . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 3.4.6 グラフィックライブラリ（2 次元） . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506 3.4.7 OpenXM-Conrib 一般函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 3.4.8 OXShell の関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507 3.4.9 OpenMath 函数 (1999 版) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508 3.4.10 Differential equations (by Okutani) . . . . . . . . . . . . . . . . . . . . . . . . . . . 509 3.4.11 D-module (by Okutani) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511 3.4.12 DSOLV 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513 3.4.13 GNUPLOT 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514 3.4.14 _{p}F_{q} に関するコホモロジー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517 3.4.15 PHC 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518 3.4.16 Plucker 関係式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520 3.4.17 SM1 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520 3.4.18 TIGERS 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531 3.4.19 Mathematica 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531 3.4.20 便利な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533 3.4.21 その他 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535

索引 537

              os_muldif.rr for Risa/Asir

A library for computing (ordinary/partial) differential operators

by Toshio Oshima

1 List of Functions

1.1 Functions related to differential operators

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

1.1.1 Fundamental functions

1. muldo(p_{1},p_{2},[x,∂_{x}]|lim=n) または muldo(p_{1},p_{2},x|lim=n)
muldo(p_{1},p_{2},[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .]|lim=n)

:: 有理函数（初等函数でもよい）係数の常（または偏）微分作用素（の行列）の積 (⇐ [∂_{x}, x] = 1)

2. caldo([p_{1},p_{2},. . .],[x,∂_{x}]|mono=f) or caldo([p_{1},p_{2},. . .],[[x_{1},∂_{x_{1}}],. . .]|mono=f)

:: 微分作用素の積の和を計算する

3. muledo(p_{1},p_{2},[x,∂_{x}]) or muledo(p_{1},p_{2},x)

:: Euler 型常微分作用素（の行列）の積 (⇐ [∂_{x}, x] = x)

4. transpdo(p,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .],[[y_{1},∂_{y_{1}}],[y_{2},∂_{y_{2}}],. . .]|ex=1,inv=f)

:: 微分作用素の変換（x_{i} ↦ y_{i} = y_{i}(x), ∂_{x_{j}} ↦ ∂_{y_{j}} = c_{j}(x) + ∑_{ν} a_{jν}(x)∂_{x_{ν}} ）

5. translpdo(p,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .],mat)

:: 微分作用素の線形座標変換（x_{i} ↦ ∑_{j}(mat)_{ij}x_{j}）

6. transppow([[x_{1},∂_{x_{1}}],. . .,[x_{n},∂_{x_{n}}]],m)

:: ベキ函数による座標変換での変換公式

7. appldo(p,r,[x,∂_{x}]|Pfaff=1) or appldo(p,r,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .])

:: 微分作用素（の行列）の有理式，初等函数（の行列）， Pfaff 系への作用の計算

8. adj(p,[x,∂_{x}]) または adj(p,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .])

:: 微分作用素（の行列） p の formal adjoint

9. psymbol(p,,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .])

:: principal symbol of differential operator

10. sftpexp(p,[x,∂_{x}],q,r) or sftpexp(p,[[x_{1},∂_{x_{1}}],. . .],q,r])

:: 微分作用素 p を q^{−r} ∘ p ∘ q^{r} と変換する

11. appledo(p,r,[x,∂_{x}])

:: Euler 型常微分作用素の有理式への作用の計算

12. divdo(p_{1},p_{2},[x,∂_{x}]|rev=1)

:: 常微分作用素の割り算

13. mygcd(p_{1},p_{2},[x, ∂_{x}]|rev=1,dviout=n) or mygcd(p_{1},p_{2},[x]|rev=1,dviout=n)
mygcd(p_{1},p_{2},x|dviout=n), mygcd(p_{1},p_{2},0|dviout=n)

:: 有理函数係数の常微分作用素（または x の多項式，または正整数） p_{1} と p_{2} の GCD （最大公約元）

14. mylcm(p_{1},p_{2},[x, ∂_{x}]|rev=1) or mylcm(p_{1},p_{2},[x]|rev=1)
mylcm(p_{1},p_{2},x), mylcm(p_{1},p_{2},0)

:: 有理函数係数の常微分作用素（または x の多項式，または正整数） p_{1} と p_{2} の 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(p_{1},p_{2},[x,∂_{x}])

:: 常微分方程式 p_{1}u = 0 に対し q_{1}p_{2}u = 0 となる微分作用素 q_{1} と q_{2}p_{2}u = u となる微分作用素 q_{2} の

リスト [q_{1}, q_{2}] を返す

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 ↦ 1/x で（x のべき倍を除いて）不変な微分作用素 p に対する変数変換 x ↦ y = x + \sqrt{x^{2} − 1}

19. toeul(p,[x,∂_{x}],n)

:: （Fuchs 型）常微分作用素を x = n で Euler 型に変換

20. fromeul(p,[x,p_{x}],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}],n_{0},n_{1},n_{2})

:: 常微分作用素 p に x の一次分数変換 (n_{0}, n_{1}, n_{2}) ↦ (0, 1, ∞) を行う

24. chkexp(p,[x, ∂_{x}],n,r,m)

:: j = 0, …, m − 1 の全てに対し，確定特異点型常微分作用素 p の解 u_{j} で (x − n)^{−(r+j)}u_{j} が x = n で正則でそこでの値が 1 となるものの存在条件

25. soldif(p,[x, ∂_{x}],n,q,m)

:: 常微分作用素 p の x = n の近傍での z^{q}(1 + ∑_{j=1}^{∞} c_{j}z^{j}) の形の形式解に対し，長さ m + 1 のベクトル [1 c_{1} c_{2} ⋯ c_{m}] を返す（z = x − n）．

26. okuboetos(p, [x, ∂_{x}]|diag=[c_{1}, c_{2}, . . .])

:: 単独 Okubo 型方程式 pu = 0 を Okubo 型の 1 階のシステムに変換する

27. stoe(p,[x, dx],m)

:: 1 階の線型常微分方程式系を単独高階に直す

28. etos(p,[x, dx],m)

:: 単独高階線型常微分方程式を 1 階系に直す

29. dform(ℓ, x|dif=1)

:: 変数 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 defined 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,[[x_{1}, ∂_{x_{1}}],[x_{2}, ∂_{x_{2}}], . . .])

:: 微分作用素 p の（部分） Laplace 変換

33. laplace1(p,[x, ∂_{x}]) or laplace1(p,[[x_{1}, ∂_{x_{1}}],[x_{2}, ∂_{x_{2}}], . . .])

:: 微分作用素 p の（部分）逆 Laplace 変換

34. mc(p,[x, ∂_{x}],r)

:: 常微分作用素 p の middle convolution mc_{r}(p)

35. mce(p,[x, ∂_{x}],n,r)

:: 常微分作用素 p を (∂_{x} − n)^{−r} ∘ p ∘ (∂_{x} − n)^{r} と変換

36. rede(p,[x, ∂_{x}]) or rede(p,[[x_{1}, ∂_{x_{1}}],[x_{2}, ∂_{x_{2}}], …]) :: 部分作用素 p の reduced representative を返す 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}],[[c_{0}, r_{0}],[c_{1}, r_{1}], …])

:: Versal addition add(p,[x, ∂_{x}], ∑_{j≥0} \frac{r_{j}x^{j}}{∏_{ν=0}^{j}(1−c_{ν}x)})

40. addl(p,[x, ∂_{x}],f)

:: 常微分作用素の addition の Laplace 変換 laplace1(add(laplace()))

41. cotr(p,[x, ∂_{x}],f)

:: 常微分作用素 p の x ↦ f(x) による座標変換

42. rcotr(p,[x, ∂_{x}],f)

:: 常微分作用素 p の x ↦ 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, fuchs, rod, redsp, fspt] を返す

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(k,d|str=1)

:: d 階で rigidity index が k の fundamental スペクトル型のリストを返す

49. sp2grs(m,a,ℓ|mat=1)

:: spectral type から generalized Riemann scheme を生成する

50. sp2grs(m,a,ℓ|mat=1)

:: Generates generalized Riemann scheme with a given spectral type

51. ssubgrs (m, ℓ)

:: Generalized Riemann scheme m の ℓ に対する特性指数和

52. mcgrs(m,[r_{1}, r_{2}, . . . , r_{n}]|mat=1,slm=[[k_{1},k_{2},. . .],m′])

:: middle convolution と addition を順に generalized Riemann scheme や留数行列の和に施す

53. mcop(p,[r_{1}, r_{2}, …, r_{n}],[x, x_{1}, x_{2}, …])

:: middle convolution と addition を (偏）微分作用素 p に順に施していく

54. redgrs(m|mat=1)

:: 常微分作用素の generalized Riemann scheme の 1-step reduction

55. getbygrs(m,t|perm=ℓ,var=v,pt=[p_{1}, . . .],mat=1) or

getbygrs(m,[t,s_{1}, s_{2}, …]|perm=ℓ,var=v,pt=[p_{1}, …],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()） , p_{1}, … は特異点の位置（∞ は除く）．

56. spslm(m,[k_{1},k_{2},. . .])

:: rigid な常微分方程式の解の半局所モノドロミーを求める

57. shiftop(ℓ, s|zero=1,raw=k,all=t,dviout=1)

:: rigid なスペクトル型 ℓ と shift s から shift 作用素を求める

58. shiftPfaff(a,b,g,x,[μ_{1},μ_{2}])

:: Pfaff 系の隣接関係式の middle convolution による変換

59. conf1sp(m|x2= ± 1,conf=0)

:: スペクトル型 m の微分作用素の Poincare rank 1 の合流過程を示す

60. pf2kz(m|all=1)

:: n 変数の Pfaff 系 m を n + 2 変数の KZ 方程式に変換

61. confexp([[c_{0},f_{0}],[c_{1},f_{1}],...,[c_{m}, f_{m}]]) confexp([[f_{1},. . .,f_{n}],[c_{1},. . .,c_{m}]]|sym=k])

:: 特性指数の合流を返す

62. mcvm(n|var=x,z=1,get=g)  mcvm([n_{1},n_{2}, . . .]|var=[a,b, . . .],z=1,get=g)
   mcvm([r,k,i,j]|e=1,var=[a,b, . . .])

:: versal unfolding の middle convolution

63. anal2sp(m,l)

:: 同時スペクトル m の解析

64. mc2grs(g,r|top=0,dviout=k,div=ℓ,fig=s)

:: ℙ^{1} 内の 5 点の配置に対する KZ 型方程式の同時スペクトル g の変換

65. newKZmat(k,l|verb=1)

:: convolution of residue matrices of KZ equation

66. midKZ(l,b|raw=1,skip=m,kill=f)

:: KZ 方程式の留数行列の middle convolution の対角化

67. m2mc(ℓ,[a_{0},a_{y},a_{1},c]|swap=1,small=1,simplify=0,MC=1)
   m2mc(ℓ,s|small=1,simplify=0,int=0,swap=t)

:: Pfaff 形式 du = (A_{0} \frac{dx}{x} +A_{y} \frac{d(x−y)}{x−y} +A_{1} \frac{d(x−1)}{x−1} +B_{0} \frac{dy}{y} +B_{1} \frac{d(y−1)}{y−1})u の x 変数での addition+middle convolution を求める（ℓ = [A_{0}, A_{y}, A_{1}, B_{0}, B_{1}]）． ℓ がスペクトル型や Riemann scheme のとき，上の後者では s ="GRC", "GRSC", "extend", "Pfaff",

   "sp", "pairs", "irreducible", "All", "swap"
68. mcmgrs(g,r|dviout=k)

:: ℙ^{1} 内の 5 点以上の点配置に対する KZ 型方程式の同時スペクトル g の変換

69. mmc(l,[μ,a_{1},...,a_{n}]|full=1,homog=1,mult=f)

:: Schlesinger 型常微分方程式および KZ 型方程式の addition+middle convolution

70. kzext([a_{1}, a_{2}, …, a_{m}]|perm=σ)

:: KZ 方程式の全留数行列を返す

71. linfrac01(ℓ|over=1)

:: x = 0, 1, ∞, y, z, … の一次分数変換のリスト（ℓ = [x, y] etc.）

72. lft01(ℓ, t|tr=τ)

:: ℓ = [x,y] または ℓ = [x,y_{1},y_{2},…,y_{q}] に対する特殊一次分数変換

1.1.3 Some operators

73. okubo3e([p_{0,1}, …, p_{0,m}],[p_{1,1}, …, p_{1,n}],[p_{2,1}, …, p_{2,m+n}|opt=1])

:: 0, 1, ∞ に確定特異点を持つ m + n 階の単独 Okubo 型微分作用素を求める

74. fuchs3e([p_{0,1}, …, p_{0,n}],[p_{1,1}, …, p_{1,n}],[p_{2,1}, …, p_{2,n}])

:: 0, 1, ∞ に確定特異点を持つ n 階の Fuchs 型微分作用素を求める

75. ghg([p_{1,1}, p_{1,2}, ..., p_{1,m}],[p_{2,1}, p_{2,2}, ..., p_{2,n}])

:: 一般超幾何函数_{m}F_{n}(p_{1}; p_{2}; x) （cf. seriesHG()）の満たす微分作用素

76. ghg2([a_{1}, a_{2}, . . . , b],[a′_{1}, a′_{2}, . . . , b′]|raw=1,all=1,symbol=1,var=v)

:: 多変数の一般化超幾何級数の微分方程式 77. even4e([p_{1,1}, p_{1,2}, p_{1,3}, p_{1,4}],[p_{2,1}, p_{2,2}])

:: 4 階 even family (Rigid)

78. odd5e([p_{1,1}, p_{1,2}, p_{1,3}, p_{1,4}, p_{1,5}],[p_{2,1}, p_{2,2}])

:: 5 階 odd family (Rigid)

79. rigid211([p_{0,1}, p_{0,2}],[p_{1,1}, p_{1,2}],[q_{0}, q_{1}])

:: Type 211,211,211

80. extra6e([p_{1,1}, p_{1,2}, p_{1,3}, p_{1,4}, p_{1,5}, p_{1,6}],[p_{2,1}, p_{2,2}]) :: Extra case (Rigid)

81. eofamily([p_{0,1}, p_{0,2}],[p_{1,1}],[p_{2,1}, …, p_{2,n}]) :: Even/odd family (obsolete)

82. ev4s(p_{1},p_{2},p_{3},p_{4},p_{5})

:: Heckman-Opdam 超幾何の (BC_{2}, BC_{1}) 型制限常微分 (Rigid)

83. b2e(p_{1},p_{2},p_{3},p_{4},p_{5})

:: Heckman-Opdam 超幾何の (BC_{2}, A_{1}) 型制限常微分 (Non Rigid)

84. 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

85. myhelp(h)

:: os_muldif.rr のマニュアルを表示する

86. chkfun(f,s)

:: 函数 f （= 文字列）が定義済みかどうか調べ，未定義なら load(s) を実行

87. isMs()

:: Microsoft Windows 環境かどうか調べる

88. isyes(p|set=ℓ)

:: 1 か 0 を返す函数を定義し，それを使う

89. isall(f,m)

:: m の要素に p 対して f(p) が 0 となるものが存在すると 0，そうでなければ 1 を返す

90. ptype(p,ℓ)

:: ℓ は変数，または変数のリストで，それのみを変数とみなした type() を返す

91. getline(Id|Max=m,CR=[r_{1},r_{2},..],LF=[l_{1},l_{2},...])
   :: get line() の拡張版
92. keyin(s)

:: s を表示し， 1 行のキー入力を待って，それを文字列として返す

93. showbyshell(s)

:: shell でコマンド s を実行した標準出力の結果を Risa/Asir で表示

94. getbyshell(s)

:: shell でコマンド s を実行した標準出力の結果をファイルとして得る

95. fcat(f,s|exe=1)

:: ファイル f に s を書き出す

96. makev([ℓ_{1},ℓ_{2}, . . .]|num=1)

:: ℓ_{1}, ℓ_{2} … を合わせて一つの変数名を作る

97. shortv(p,[v_{1},v_{2}, . . .]|top=w)

:: p の添字番号つき不定元 v_{1}, … を一文字の w 以下の変数名に変える

98. makenewv(ℓ|var=v,num=n)

:: ℓ に使われていない新しい不定元を生成する

 99. isvar(p)

:: p が変数かどうか調べる

100. varargs(p|all=t)

:: 式 p に含まれる初等函数の函数子とその変数に現れる不定元のリストを返す

101. pfargs(p,x|level=t)

:: 式 p に現れる x 変数を含んだ初等函数と引数のリストを返す

102. isdif(p)

:: p が微分作用素と推測されるときはその変数と微分の組のリストを返し，そうでなければ 0 を返す

103. mysubst(r,[v_{1},r_{1}]|inv=1) mysubst(r,[[v_{1},r_{1}], . . .]|inv=1)
    mysubst(r,[ℓ_{1},ℓ_{2}]|lpair=1,inv=1)

:: subst(r,v_{1},r_{1}, …) と同等． r が複雑で r_{1} が有理式のときに特に有効．

104. myswap(p,[x_{1},x_{2},. . .,x_{n}])

:: 有理式またはそのリストなどの不定元の巡回置換 (x_{1}, x_{2}, …, x_{n})

105. substnum(l,s,t|depth=d)

:: リストまたはベクトルの成分の置き換え

106. mulsubst(r,[[p_{1,0}, p_{1,1}],[p_{2,0}, p_{2,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 に複数同時の代入，有理変換の合成, Pfaff 形式の有理変換

107. fmult(f,m,ℓ,n| · · ·)

:: m_{i} ↦ m_{i+1} = f(m_{i},ℓ[i],n[0], n[1], … | ⋯) という変換（m_{0} = m）の最終結果 m_{length(l)} を返す

108. mtransbys(f,m,ℓ| · · ·)

:: スカラーに関する変換 f() をリスト，ベクトルまたは行列 m に拡張する

109. mmulbys(f,m,n,ℓ| · · ·)

:: 和が定義された objects の 2 つに対して 1 つの object を与える演算 f を， objects を成分とするベクトルまたは行列 m と n の演算に拡張する

110. cmpsimple(p,q|comp=t)

:: 式 p と q の簡単さを比較

111. simplify(p,ℓ,t|var=[x_{1}, x_{2}, . . .])

:: ℓ の一次関係式を使って p を簡単化

112. getel(m,i)

:: m がリスト，ベクトル，行列で i が非負整数なら m[i] を返す

113. evalred(r|opt=[[s_{1},t_{1}],[s_{2},t_{2}]...])

:: sin(0), cos(0), exp(0) などを 0, 1, 1 などの整数に置き換える

114. evals(r|del=s,raw=1)

:: 文字列あるいは函数を評価する．

115. myeval([r,[x_{1},f_{1},v_{1}],[x_{2},f_{2},v_{2}],. . .])
    :: os_md.myeval(subst([r,[x_{2},f_{2},v_{2}],. . .],x_{1},f_{1}(os_md.myeval(v_{1})))) を返す
      os_myeval([r])=map(eval(r))
116. mydeval([r,[x_{1},f_{1},v_{1}],[x_{2},f_{2},v_{2}],. . .])
    :: os_md.mydeval(subst([r,[x_{2},f_{2},v_{2}],. . .],x_{1},f_{1}(os_md.mydeval(v_{1})))) を返す
      os_md.mydeval([r])=map(deval(r))
117. myval([r,[x_{1},f_{1},v_{1}],[x_{2},f_{2},v_{2}],. . .])

:: myeval() と同様な函数であるが，可能な限り正確な値を返す

118. f2df(f|opt=n)

:: 函数 f から sin などの函数子を除いて myeval() や mydeval() の引数のリスト形式函数に変換

119. todf(f,[v_{1},. . .,v_{n}]) todf([f,[ops]],[v_{1},. . .,v_{n}])

:: 函数子 f で変数が v_{1}, …, v_{n} のリスト形式函数を得る（n は f の引数の数）

120. df2big(f|inv=1)

:: リスト形式函数 f を倍精度浮動小数点計算から bigfloat 計算へ変更する

121. compdf(f,x,g)  compdf(f,[x_{1},x_{2}, . . .],[g_{1},g_{2}, . . .])

:: リスト形式函数 f の変数 x にリスト形式函数 g を代入したリスト形式函数を返す

122. cutf(f,x,[[x_{1},v_{1}],[x_{2},v_{2}],...,[x_{n},v_{n}]])  cutf(f,x,[t,[x_{1},v_{1}],...,[x_{n},v_{n}]])

:: 函数 f の変数が特定の範囲のとき函数値の変更を行い，その値またはリスト形式函数を返す

123. periodicf(f,[a,b],x)  periodicf(ltov([g_{1},g_{2},...,g_{n}]),c,x)

:: x を変数とする函数 f|_{[a,b)} を周期関数に拡張した函数にする

124. cmpf([f,[a,b]]|exp=c)    cmpf(x)

:: 積分区間をコンパクト閉区間 [0, 1] に直した函数にする

125. myfeval(f,x) (f,a)  myfeval(f,[x,a])  myfeval(f,[[x_{1},a_{1}],. . .])
126. myfdeval(f,a)  myfdeval(f,[x,a])  myfdeval(f,[[x_{1},a_{1}],. . .])

:: myeval() や mydeval() の引数のリスト形式函数 f の変数に a を代入して値を得る

127. myf2eval(f,x,y)
128. myf2deval(f,x,y)

:: myeval() や mydeval() の引数のリスト形式 2 変数函数 f に代入して値を得る

129. myf3eval(f,x,y,z)
130. myf3deval(f,x,y,z)

:: myeval() や mydeval() の引数のリスト形式 3 変数函数 f に代入して値を得る

131. execproc(ℓ|all=1,var=k)

:: リスト形式手続きの実行

132. fsum(f,[m,n,d]|df=1,subst=1)  fsum(f,[x,m,n,d]|df=1,subst=1)

:: 一般項が f(x) で与えられる級数の和 ∑_{k=0}^{[ \frac{m−n}{d}]} f(m + kd) を返す

133. fint(f,n,[t_{1},t_{2}]]|cpx=1,exp=c,int=k,prec=v,Acc=1)  fint(f,n,ℓ|· · ·)

:: 複素積分を含む数値積分

134. fimag(f,x|inv=g)

:: 複素変数の指数関数を実変数の関数に変換

135. trig2exp(f,x|inv=g)

:: 三角関数と指数関数の変換と簡単化

136. isshortneg(f)

:: f と −f を表現する文字列の長さの比較

137. fshorter(f,x)

:: x の三角関数の簡単化

138. fzero(f,[x,x_{1},x_{2}]|mesh=m,dev=d,zero=1,trans=1,cont=1)

:: 実数値函数 f の零点を求める

139. fmmx(f,[x,x_{1},x_{2}]|mesh=m,dev=d,mmx=1,zero=1,trans=1,cont=1,dif=1)

:: 実数値函数 f の極値を求める

140. flim(f,v|prec=c,init=t)

:: 変数 x の実数値関数 f の極限値を求める

141. fcont(f,[x,x_{1},x_{2}]|mesh=m,dev=d,zero=1,trans=1,dif=1) ?

:: 実数値函数 f の不連続点や滑らかでない点を求める

142. fresidue(p,q|cond=[f_{1},f_{2},. . .],sum=1)

:: 多項式 q を分母とする有理式 p/q の特異点と留数の組のリスト（z が変数で， p は正則函数）

1.2.2 Numbers

143. abs(p)  abs([p,prec])

:: 整数または実数または複素数 p の絶対値を返す

144. sgn(n|val=1)

:: 数 n または置換 n の符号を返す

145. calc(p, [s, q]) calc(p, s)

:: 数や有理式などあるいはそれらを成分とするリストやベクトルの成分に対して演算を施す

146. isint(p)

:: p が整数かどうか調べる

147. israt(p)

:: p が有理数かどうか調べる

148. iscrat(p)

:: p が数でその実部と虚部が共に有理数かどうか調べる

149. isalpha(n)

:: 整数 n がアルファベットの文字コードかどうか調べる

150. isnum(n)

:: 整数 n が数字 0〜9 の文字コードかどうか調べる

151. isalphanum(n)

:: 整数 n がアルファベットまたは数字の文字コードかどうか調べる

152. isdecimal(s)

:: 文字列 s が整数または小数を表しているかどうか調べる

153. catalan(n)

:: Catalan 数などの場合の数を返す

154. getCatalan(k,n|opt=1,to=f)

:: Catalan 数と許容 01 列，トーナメント表，凸多角形の三角形分割，番号付け，などの間の変換

155. symtournament(n|to=t,verb=1)

:: トーナメント戦（2 分木）の場合の数, タイプ

156. tobig(n)

:: 0 以外の有理数を bigfloat に変換する

157. nthmodp(a,n,p)

:: a^{n} mod p を返す（a は整数で n, p は自然数）

158. issquaremodp(a,p|power=n)

:: 平方剰余を調べる（ルジャンドルの平方剰余記号 (\frac{a}{p})， n は平方を一般べきに）

159. rootmodp(a,p|power=n)

:: p を法として a の平方根（一般には n 乗根）を求める

160. primroot(p|all=1,ind=a)

:: 奇素数またはそのべき p の原始根やそれを底とする指数をもとめる

161. rabin(p,q)

:: p に対し q を底とするミラー・ラビンの素数判定を行う（素数，擬素数なら 1 を返す）

162. cfrac(x,n|neg=1)

:: 有理数あるいは実数を連分数展開する（n は項数）

163. cfrac2n(l|loop=m,,ex=1,q=f,reg=1)

:: （循環）連分数を通常の形（含 q-変形）に直す.

164. sqrtrat(r)

:: 有理数（または実部と虚部が有理数の複素数）の平方根を得る

165. sqrt2rat(r|mult=1)

:: 平方根や虚数を含んだ分数の有理化

166. sint(r,p|str=t,sqrt=1,zero=0)

:: 実数 r または複素数，リストや行列（ネスト対応）などの成分の実数を小数点以下 p 桁に丸める

167. frac2n(n|big=1)

:: 分数を実数になおす（r は複素数，有理式やそのリストや行列などでもよい）

1.2.3 Polynomials and rational functions

168. radd(p,q)

:: 有理式（の行列） p と q の和を既約有理式（の行列）の形で計算する

169. rmul(p,q)

:: 有理式（の行列） p と q の積を既約有理式（の行列）の形で計算する

170. mulpolyMod(p,q,x,n)

:: x の多項式 p と q の積を x^{n+1} 以上の項を無視して計算する

171. polbyroot([p_{1}, p_{2}, ..., p_{n}],x) polbyroot([m,n],x|var=v)

:: 多項式を根で与える

172. polbyvalue([[a_{1}, b_{1}],...,[a_{n}, b_{n}]],x)

:: x の n − 1 次多項式を n 個の点 x = a_{i} での値 b_{i} で与える

173. pgen([[x_{1}, n_{1}],[x_{2}, n_{2}]...],a|sum=n,shift=m,sep=1,num=1)

:: 係数が a_{∗} で x_{i} が n_{i} 次，全体で n 次以下の x_{1}, … の一般多項式を作る

174. rpdiv(p,q,x)

:: x の多項式の割り算

175. res0(p,q,x|var=[x_{1}, x_{2}, . . .],opt=f,dbg=d)

:: 1 変数多項式の共通解の存在条件と解，割り算

176. sgnstrum([p_{1}, p_{2}, . . .],t|)

:: 多項式の strum 列の t での符号変化の個数を返す

177. polstrum(p|num=[t_{1},t_{2}],mul=1)

:: 多項式の strum 列や， (t_{1}, t_{2}] にある根の個数を返す

178. polrealroots(p|in=[a,b],step=[n_{1},n_{2}],nt=k)

:: 多項式の実根を求める

179. polroots(p,x|comp=t,err=r,lim=ℓ)

:: 変数 x の 1 変数多項式の根，多変数多項式の共通根（実根・虚根）の（近似）値を返す

180. easierpol(p,x) または easierpol(p,[x_{1}, x_{2}, . . .])

:: 有理式係数の x の多項式の係数に x を含まない有理式をかけて，係数の最大公約元が 1 の整数係数の多項式に変換

181. getroot(p,x|mult=1,cpx=1)

:: 多項式の根を有理式または有理数の平方根の範囲で求める

182. fctri(p)

:: 実部と虚部が有理数係数の１変数多項式を，その範囲で既約分解する

183. polinsym(p,[x_{1}, …, x_{n}],s)

:: (x_{1}, …, x_{n}) の対称有理式を基本対称式で表す

184. polinvsym(p,[x_{1}, . . . , x_{n}],s)

:: polinsym(p,[x_{1}, …, x_{n}],s) の逆函数

185. pol2sft(p,x|sft=t)

:: shifted power 多項式を与える

186. polinsft(p,x)

:: shifted power 多項式に直す（pol2sft() の逆変換）

187. sftpow(p,n)
188. sftpowext(p,n,s)

:: p の s shifted n power ∏_{ν=1}^{n}(p + (ν − 1)s) を返す

189. binom(p,n)

:: p(p − 1)(p − 2) ⋯ (p − n + 1)/n! を返す

190. expower(p,r,n)

:: (1 + p)^{r} の展開を p^{n} まで求める

191. orthpoly(n|pol="type")    orthpoly([n,a, . . .]|pol="type")

:: 変数 x の n 次直交多項式を返す

192. schurpoly ([m_{1},m_{2}, . . .]|var=v)

:: m_{1} ≥ m_{2} ≥ ⋯ ≥ m_{n} ≥ 0 のウェイトの Schur 多項式を返す

193. seriesMc(f,k,v|evalopt=[[s_{1},t_{1}],[s_{2},t_{2}]...])

:: 函数 f の変数または変数のリスト v に対する k 次の項までの Maclaurin 展開を求める

194. solveEq([f_{1}, f_{2}, …],[x_{1}, x_{2}, …]|h=1,inv=1)

:: 連立代数方程式を解く，双有理変換の逆変換を求める．

195. baseODE([f_{1}, f_{2}, . . .]|f=y,to=x,var=v,vl=h,ord=d,in=1,TeX=t,pages=p,dbg=d,step=k)

:: 一階常微分方程式系の単独化, 双有理変換

196. 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 法の解析

197. pTaylor([f_{1},f_{2}, . . .],[x_{1},x_{2}, . . .],m|raw=1,time=t)

:: 常微分方程式 x′_{i} = f_{i}(x) (i = 1, 2, …) の m 次までのベキ級数解を返す

198. seriesHG([a_{1},a_{2},. . .],[b_{1},b_{2},. . .],p,k)
    seriesHG([[a_{1},. . .],[b_{1},. . .],[c_{1},. . .]],[[d_{1},. . .],[e_{1},. . .],[f_{1},. . .]],[x,y],k)

:: 一般超幾何級数_{m}F_{n}(a_{1}, a_{2}, …, a_{m}; b_{1}, b_{2}, …, b_{n}; p) の p^{k} 次の項まで求める

または 2 変数の級数 ∑_{0≤i+j≤k} \frac{(a_{1})_{i+j}···(b_{1})_{i}···(c_{1})_{j}···}{(d_{1})_{i+j}···(e_{1})_{i}···(f_{1})_{j}···} \frac{x^{i}y^{j}}{i!j!} を返す．

199. isfctr(r)

:: 係数が有理数の有理式かどうかを返す

200. fctrtos(r|var=ℓ,rev=1,dic=1,TeX=f,dviout=1,lim=n,small=1,pages=1,add=s)

:: 有理式を因数分解した形の文字列に変換する

201. tohomog(r,[x_{1}, x_{2}, …],y)

:: (x_{1}, x_{2}, …) の有理式に変数 y を導入して (y, x_{1}, x_{2}, …) の斉次式にする

202. substblock(p,x,q,y)

:: x の多項式 p, q に対し， y = q とおいて p を x の次数が mydeg(q,x) 未満の (x, y) の多項式に直す 203. invf([p_{1}, …, p_{n}],[x_{1}, …, x_{n}],[y_{1}, …, y_{n}])

:: y_{j} = p_{j}(x) (j = 1, …, n) を x_{j} = q_{j}(y) (j = 1, …, n) と解く

204. mydeg(p,x|opt=1), mydeg(p,[x,y]|opt=1)

:: deg(p,x) の拡張（x は 1 次， y は −1 次）． p は行列や配列で係数は有理式でよい．

205. mymindeg(p,x|opt=1)

:: p がスカラーのときは mindeg(p,x) と同じ．係数は有理式でよいが， p が行列などのスカラーでないときは 0 以外の成分の最小次数を返す．

206. iscoef(p,f)

:: p の係数の全てが f(∗) ≠ 0 を満たすかどうかチェックする

207. mycoef(p,n,x)

:: coef(p,n,x) と同じ． n, x は同じ長さのリストでもよい． p は行列や配列で係数は有理式でよい．

208. pcoef(p,m,q)

pcoef(p,m,[[x_{1}, .., x_{n}],[m_{1}, …, m_{n}]])

:: 多項式 p^{m} を展開したときの単項式 q に対する係数を返す

209. pmaj(p|var=t)

:: 多項式を単項式で表した係数を，全てその絶対値で置き換えた多項式を返す

210. pfctr(p,x)

:: x の多項式または有理式 p の因数分解

211. cterm(p|var=[x,y, . . .])

:: 多項式の定数項を返す．変数を指定可能．

212. terms(p,[x,y, . . .]|rev=1,dic=1)

:: 多項式の存在する項の次数とべき指数のリストを返す

213. pterm(p,[x_{1},x_{2}, …],[m_{1},m_{2}, …])

:: 多項式の指定した変数が指定した次数となる項を返す 214. pweight(p,[x_{1},x_{2}, …],[m_{1},m_{2}, …])

:: 多項式の変数に重みをつけて斉次式の成分に分解する

215. polcut (p,n,[x, y, . . .]|top=m)

:: 変数のリスト [x, y, …] の多項式 p から次数が（m 以上） n 以下でない項を削除

216. mydiff(p,x)

:: diff(p,x) と同じ． p は行列や配列で係数は有理式でよい． x もリストでよい．

217. myediff(p,x)

:: ediff(p,x) と同じ． p は行列や配列で係数は有理式でよい．

218. mypdiff(p,[x_{1},f_{1},x_{2},f_{2},...])

:: 合成関数の微分．

219. difflog(L|var=x)

:: 対数微分を返す

220. ptol(p,x|opt=0)

:: x の多項式 p の係数のリストを返す

221. pfrac(p,x|root=2,dviout=1,TeX=1)

:: x の有理式 p （の行列）を部分分数展開し，分子，分母（多項式とべき）の組のリストを返す 222. lpgcd([p_{1}, p_{2}, …])

:: 多項式 p_{1}, p_{2}, … の共通因子を返す

223. jacobian([f_{1}, …, f_{m}],[x_{1}, …, x_{n}]|mat=1)

:: 関数の組 (f_{1}, …, f_{m}) の変数 (x_{1}, …, x_{n}) についてのヤコビアン (m = n) またはヤコビ行列を返す

224. hessian([f,[x_{1}, . . . , x_{n}]|mat=1)

:: 関数の組 f の変数 (x_{1}, …, x_{n}) についてのヘシアンまたはヘッセ行列を返す．

225. wronskian[f_{1}, . . . , f_{n}],x|mat=1)

:: 関数の組 (f_{1}, …, f_{n}) の変数 x についてのロンスキアンまたはロンスキー行列を返す．

226. prehombf(p,q|mem=±1)

:: 概均質ベクトル空間の相対不変式 p の b 函数を得る． q は双対多項式.

227. intpoly(p,x|exp=c,cos=c,sin=c)

:: 変数 x の多項式 p （またはそれと指数関数, 対数関数や三角関数の積）や有理式の原始函数を返す

228. integrate(f,x|dumb=k,dviout=p,log=1,frac=t,I=[a,b])

:: 関数 f を変数 x について不定積分する

229. rungeKutta(f,n,[a,b],y,y_{0}|mul=k,prec=1,single=1,val=1)

:: Runge-Kutta 法で常微分方程式 y′ = f(x, y) の数値解を求める（f は連立も可）

230. pwTaylor(f,n,[a,b],x,x_{0},m|mul=k,prec=p,val=1,err=e,view=[[c_{0},c_{1},d_{0},d_{1}],c,u],Inf=s)

:: 区分的な Taylor 展開で常微分方程式 x′ = f(t, x) の数値解を求める（f は連立も可）

231. powsum(n)

:: 1^{n} + 2^{n} + ⋯ + m^{n} の m を x で置き換えた n + 1 次多項式を返す

232. bernoulli(n)

:: n 次の Bernoulli 多項式 B_{n}(x) を返す

1.2.4 Functions with real/complex variables

以下の数値函数では変数（引数）を不定変数にすると対応するリスト形式函数を返す．

233. frac(x)

:: 実数 x の小数部分

234. erfc(x)  erfc([x,prec])

:: 相補誤差函数 erfc(x) = \frac{2}{\sqrt{π}} ∫_{x}^{∞} e^{−t^{2}}dt

235. fouriers([a_{0},a_{1},. . .,a_{m}],[b_{1},b_{2},. . .,b_{n}],z|cpx=1,sum=f,y=t,const=c)
    fouriers([f,m],[g,n],z|cpx=1,sum=f,y=t,const=c)

:: 有限 Fourier 級数 a_{0} + a_{1} cos z + a_{2} cos 2z + ⋯ + a_{m} cos mz + b_{1} sin x + b_{2} sin 2z + ⋯ + b_{n} sin nz

236. myexp(z)

:: 指数関数 exp(z)

237. mysin(z)

:: 三角関数 sin(z)

238. mycos(z)

:: 三角関数 cos(z)

239. mytan(z)

:: 三角関数 tan(z)

240. myasin(z)

:: 逆三角関数 asin(z)

241. myacos(z)

:: 逆三角関数 acos(z)

242. myatan(z)

:: 逆三角関数 atan(z)

243. mylog(z)

:: 対数函数 log(z)

244. nlog(z)

:: log_{10}(z)

245. dlog10(x)

:: log_{10}(|x|)

246. mypow(z,w)

:: 巾関数 z^{w}

247. myarg(z)

:: 偏角 arg(z)

248. sqrt(z)  sqrt([z,prec])

:: z の平方根を与える

249. arg(z)  arg([z,prec])

:: z の偏角

250. gamma(z)  gamma([z,prec])

:: ガンマ函数 Γ(z)

251. digamma(z)  digamma([z,prec])

:: ディガンマ函数 ψ(z) = \frac{Γ′(z)}{Γ(z)}

252. lngamma(z)  lngamma([z,prec])

:: log(Γ(z))

253. dilog(z)

:: ダイログ函数 Li_{2}(z) = ∑_{k=1}^{∞} \frac{z^{k}}{k^{2}}

254. zeta(s)  zeta([s,prec])

:: zeta 函数 ζ(s)

255. eta(τ)  eta([τ,prec])

:: Dedekind の Eta 函数 η(τ) = e^{\frac{πiτ}{12}} ∏_{m=1}^{∞}(1 − e^{2πimτ})

256. jell(τ)  jell([τ,prec])

:: Elliptic j-invariant j(τ)

1.2.5 Lists and vectors

257. lcut(l,m,n)

:: リスト l の部分リストを返す

258. llsize([m_{1}, m_{2}, …])

:: リスト m_{j} のリストに対し，成分 m_{j} の個数と m_{j} の要素の最大個数を返す 259. findin(m,[ℓ_{0}, ℓ_{1}, …])

:: m に等しい要素を ℓ_{0}, ℓ_{1}, … から探す

260. countin(s,m,[ℓ_{0}, ℓ_{1}, . . .]|step=k)

:: s 以上 m 以下の {ℓ_{0}, ℓ_{1}, …} の要素の個数，間隔 m での個数分布表を返す

261. lcount(ℓ)

:: リストの要素の重複度と要素の組のリストにする

262. delopt(ℓ,s|inv=1)  delopt(ℓ,[s_{1},s_{2},. . .]|inv=f)

:: オプションリスト（リストのリスト）からオプション s （複数指定可）を削除，抽出，付加．

263. mycat([ℓ_{1}, . . . , ℓ_{m}]|delim=s)
264. mycat0([ℓ_{1}, . . . , ℓ_{m}],t|delim=s)

:: ℓ_{1}, …, ℓ_{m} を表示する

265. vtozv(v)

:: 有理式のベクトルをスカラー倍して単純化する

266. l2p(l,v|size=s)

:: 係数のリスト l を与えて v の多項式を返す．またその逆変換を返す．

267. mulseries(v_{1},v_{2})

:: ２つのベクトルをべき級数とみなして，その積のベクトルを返す

268. pluspower(p,x,r,m)

:: (1 + p)^{r} の x に関するべき級数展開を第 m 項まで求める

269. average(ℓ|sint=k)    average([ℓ_{1},ℓ_{2}]|opt="co",sint=k)

:: 実数のリストに対し，平均値や標準偏差や相関係数を求める

270. regress(ℓ|sint=k)

:: 実数の組のリストに対し，回帰直線を求める

271. vprod(v_{1},v_{2})
272. dvprod(v_{1},v_{2})

:: 2 つのベクトル（リストでもよい）の内積を返す

273. llbase(v,ℓ)

:: 変数 ℓ[0], ℓ[1], … の一次方程式のベクトル v の標準変換を行う（例は lsol() の項を参照）

274. lsol(v,l)

:: 変数 ℓ[0], ℓ[1], … に関する連立一次方程式を解く

275. lnsol(v,l)

:: 変数 ℓ[0], ℓ[1], … に関する連立一次方程式の有理数解を求める

276. lchange(ℓ,k,v|flat=1)

:: （多重）リスト ℓ の k で指定した位置の成分を v に置き換える

277. lsum([m_{1}, m_{2}, …])

:: m_{1}, m_{2}, … の中の和を返す

278. lmax([m_{1}, m_{2}, …])

:: m_{1}, m_{2}, … の中の最大のものを返す

279. lmin([m_{1}, m_{2}, …])

:: m_{1}, m_{2}, … の中の最小のものを返す

280. lgcd([m_{1}, m_{2}, . . .]|poly=1])

:: m_{1}, m_{2}, … の最大公約数（元）を返す

281. llcm([m_{1}, m_{2}, . . .]|poly=1,poly=[x_{1}, x_{2}, . . .],dn=1])

:: m_{1}, m_{2}, … の最小公倍数（元）を返す

282. ldev(ℓ,s)

:: リスト s の整数倍をリスト ℓ に加えて，成分の絶対値を最小にする

283. qsortn(ℓ)

:: 大きい順のクイックソート

284. rsort(ℓ,s,k)

:: ネストされたリスト ℓ のリカーシブソート

285. llselect(ℓ,n,k|eq=1,val=1)

:: 表形式のリストを成分の条件で分割する

286. llget(ℓ,[a_{1},a_{2},. . .],[b_{1},b_{2},. . .]|flat=1)

:: 表形式のリストから行や列を抽出

287. sort2([m_{1},m_{2}])

:: 2 成分のリストまたはベクトルの成分を小さい順に並び替える

288. lsort(ℓ_{1},ℓ_{2},t|c1=[c_{1,0},c_{1,1}, …],c2=[c_{2,0},c_{2,1}, …]) :: リスト ℓ_{1} に対し， ℓ_{2} との合併，共通部分，または ℓ_{2} や共通部分を除くその他，表形式データの操作

t = "cup", "setminus", "cap", "reduce", "sum", "subst"
289. btree(p,v|opt=s,add=m)

:: 二分木の作成と要素 p を二分木 v に追加するなどの二分木の操作

290. spantree(f,l,s|optimize=,comp=,unit=u,limit=m,fopt=op)

:: l の要素を使う函数 f による変換で s の要素から生成される二本木を作る

291. msort(ℓ,s)

:: ベクトルやリストの成分を（多重）キー s に従ってソートする

292. l2min(l,p|check=1,cmp=f)

:: リスト ℓ を成分の入れ替えで最小なものに変更する

293. partspt(l,m|opt=f)

:: 一つの整数の 2 種の分割に対して細分関係を調べる

294. lpair(ℓ_{1},ℓ_{2})

:: 2 つのリストを pair のリストに変換する

295. addIL([a,b],[[a_{1},b_{1}],[a_{2},b_{2}],. . .]|in=t)

:: 有限区間の合併集合と有限区間の和集合の計算

296. lext2(m)

:: 2 次の外積の基底の並べ替え

297. vnext(v)

:: ベクトルの成分を並べ替え，辞書式順序で次のベクトルに変換する

298. vgen(v,w,m|opt=0)

:: 成分の和が m の非負成分のベクトル w を順に生成する

299. paracmpl(l,t|lim=1,low=1,para=[v_{1}, v_{2}, . . .])

:: 有理的に t に依存したリスト l の成分（たとえば有理式）で張られる空間の正則完備化

1.2.6 Matrices

300. dupmat(m)

:: 成分が有理式の行列またはベクトル m の複製を作る

301. m2v(m)

:: 行列 m の成分を 1 行目から順に並べてベクトルに変換する

302. m2l(m|flat=1)

:: 有理式，ベクトルあるいは行列 m の成分を順に並べてリストにする

303. m2lv(m)

:: 行列 m の行ベクトルを並べてリストにする

304. m2ll(m)

:: 行列 m を行ベクトルをリストにかえたものを成分とするリストにする

305. lv2m(ℓ|fill=n)

:: 行ベクトル（行成分のリストでも可）のリスト ℓ から行列を作る

306. s2m(s)

:: 文字列での有理数成分の行列表現や，列のリストから行列を作る．必要最低サイズの行列になる

307. c2m(l,v|pow=t)

:: 基底の変換から係数行列を作る

308. mperm(m,[σ_{0},σ_{1} . . .],[τ_{0},τ_{1}, . . .]|mult=1)
    mperm(m,[[σ_{0},σ_{1}]],[[τ_{0},τ_{1}]]|mult=1), mperm(m,[σ,[m_{1}]],[τ,[m_{2}]]|mult=1)

:: 行列 m から小行列 (m_{σ_{i}τ_{j}}) を作る，または置換行列（または互換）で変換する

309. mtranspose(m)

:: 行列 m の転置行列を求める（m はリストのリストでもよい）

310. madjust(m,w|null=n)

:: 行列 m の列数を w に調整する

311. mpower(m,n)

:: 行列 m の n 乗を求める

312. mtoupper(m,n|opt= t,step=1,dviout=1,pages=1,tab=k,lim=w)

:: 行列 m に対し，行基本変形を行って，行の先頭からの 0 の成分の個数が下の行の方へ狭義単調増加となるようにする．最後の n 列は無視．

313. mytrace(m)

:: 行列の trace を返す．

314. mydet(m)

:: det(m) と同じ．ただし成分は有理式でもよい．

315. mydet2(m)

:: det(m) と同じ．ただし成分は有理式でもよい．

316. permanent(m)

:: 正方行列の permanent を返す

317. myrank(m)

:: 行列 m の rank を求める（例は mtoupper() の項）

318. mykernel(m|opt=1)

:: 行列 m の転置行列の kernel の基底を求める

319. myimage(m|opt=1)

:: 行列 m の転置行列の像の基底を求める

320. mymod(v,[v_{1}, . . . , v_{k}]|opt=ℓ)

:: ベクトル v_{1}, …, v_{k} で張られる空間の商空間への v の射影を求める（例は myimage() の項）

321. mmod(m,[v_{1}, . . . , v_{k}]|opt=1)

:: ベクトル v_{1}, …, v_{k} で張られる空間の商空間への線形写像 m の射影

322. myinv(m)

:: 正方行列 m の逆行列を求める

323. madj(g,m)

:: 行列 gmg^{−1} を計算する． m は行列のリストか行列のベクトルでもよい．

324. diagm(m,a)

:: 対角行列を作成する

325. mgen(m,n,a,s|sep=1)

:: size m × n の一般行列を作成する

326. 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 をランダムに変換する

327. newbmat(m,n,[[r_{00}, r_{01}, …],[r_{10}, …], …]|null=t)

:: ブロック行列を作成する

328. meigen(m|mult=1,vec=1,TeX=1,sep=s)

:: 行列 m の固有値, 固有ベクトルを返す

329. mdsimplify(m|show=1,type=ℓ)

:: 有理式正方行列 m，またはそのリストやベクトルを対角行列で簡単化

330. mext2(m)

:: 線型変換の外積を与える

331. transm(m|dviout=1)

:: 行列 m の基本変形をインタラクティブに行う

1.2.7 Strings

332. str char(s,n,t)

:: 文字列 s の n 文字以降に文字列 t の先頭文字が最初に現れる場所を返す（str chr() の拡張）

333. str pair(s,n,t_{1},t_{2}|inv=1)

:: 文字列 s の n 文字以降で，文字（列） t_{2} の出現回数が t_{1} の出現回数を超える最初の位置を返す

334. str str(s,t|top=n,end=m,sjis=1)

:: 文字列 s に部分文字列 t が最初に現れる場所を返す

335. str cut(s,m,n)

:: 文字列 s の先頭から m 文字をスキップして，それ以降 n − m + 1 文字を返す

336. str subst(s,s_{0},s_{1}|sjis=1,raw=1) または
    str_subst(s,[s_{00}, s_{01}, . . .],[s_{10}, s_{11}, . . .]|inv=1,sjis=1,raw=1)
    str_subst(s,[[s_{00}, s_{10}],[s_{01}, s_{11}], . . .],0|sjis=1)

:: 文字列 s に含まれる部分文字列 s_{0} を s_{1} で全て先頭から順に置き換える

337. str times(s,n)

:: 文字列 s （またはリスト）を n 回繰り返した文字列（またはリスト）を返す

338. str addc(s,c,n|tail=1)

:: 文字列 s に文字 c を差し込んで長さ n にする

339. str insert(s,u,[t,e]|transpose=1)

:: 文字列 s のリストの間に u の成分のリストを順に入れた差し込み文にする

340. strip(s,t_{1},t_{2})

:: 文字列の外側の括弧を外す

341. n2a(n|m=m,s=s,opt=[ab],verb=1)

:: 自然数を一文字に縮める

342. s2os(s)

:: 文字列を入力可能な文字列に変換

343. i2hex(i|cap=1,num=1,min=m)

:: 非負整数 i の 16 進表示

344. sjis2jis(l)

:: 文字コードの整数のリストの先頭 2 つを ShiftJIS から JIS に変換

345. jis2sjis(l)

:: 文字コードの数字のリストの先頭 2 つを JIS から ShiftJIS に変換

346. s2euc(s)

:: ShiftJIS または JIS 文字列を EUC 文字列に変換

347. s2sjis(s)

:: EUC または JIS 文字列を ShiftJIS 文字列に変換

348. str tb([s_{0}, s_{1}, . . .],tb) または str_tb(0,tb)

:: テキスト用バッファを作成（tb = 0）し，そこ（戻り値 tb）に文字列 s_{0}, … を順に追加する．最初の引数を 0 として文字列を取り出す．

349. l2os(l)

:: リストを入力可能な文字列に変換

350. r2os(l)

:: 数式を eval str() で入力可能な文字列に変換

351. evalcoord(s)

:: 文字列 s から括弧で囲まれた座標を抽出

352. readTikZ(s)

:: 単純な TikZ のソースを描画実行形式に変換

353. r2ma(s)
    :: Mathematica の形式の数式に変換
354. evalma(s|inv=1)
    :: Mathematica の数式を読み込む
355. readcsv(s|eval=[n_{1}, n_{2}, . . .],eval=n,sp=1,col=c,null=t,eq=1)

:: CSV 形式のデータをリスト形式で読み込む

356. tocsv(l|null=n,exe=f)

:: リストのリストまたは行列を CSV 形式のデータに変換

1.2.8 Permutations

357. ldict(n,m |opt=t)

:: {0, 1, 2, …, m − 1} を並べ替えて辞書式順序で n + 1 番目のリストを返す

358. ndict(ℓ |opt=t)

:: {ℓ_{0}, ℓ_{1}, …, ℓ_{m−1}} の並べ替えのリスト ℓ が何番目かを返す（最初は 0 番）

359. nextsub([a_{0}, …, a_{m−1}],n)

:: {0, …, n − 1} の m 個の部分集合を並べたとき， {a_{0}, …, a_{m−1}} の次の部分集合を返す．最後を与えた時は 0 を返す．

360. nextpart(ℓ|max=m)

:: 自然数の分割のリスト ℓ に対し，辞書式順序で次に大きなものを返す

361. transpart(ℓ)

:: 自然数の分割のリスト（Young 図式に対応） ℓ に対し，その双対を返す（例は nextpart() を参照）

362. trpos(a,b,n)

:: 互換 (a, b) にあたる n 次置換群の元を返す

363. sprod(s,t)

:: 置換群の積を返す

364. sadj(s,t)

:: 置換群の共役変換を返す

365. sinv(s)

:: 置換 s の逆元を返す

366. slen(s)

:: 置換 s の長さを返す

367. sexps(s)

:: 置換 s を隣接互換の積で表す

368. sord(s,t)

:: 置換を Bruhat order で比較する

1.2.9 TEX

369. my tex form(p|subst=[t_{0}, t_{1}],frac=f,root=r,ket=k)

:: print tex form(p) の戻り値から文字列置換や不要部分削除を行い，読みやすいソースに変換

370. show(p|opt=ℓ,raw=1)

:: p を dviout で適切に表示する

371. dviout(p|clear=1,keep=1,delete=t,fctr=1,mult=1,subst=[s0, s1],eq=k,title=s)

:: p を dviout で表示する

372. dviout0(ℓ) or dviout0([ℓ_{1}, ℓ_{2}, . . .]) or dviout0(ℓ|opt=s)

:: TEX での表示のための内容削除などの基本操作

373. verb tex form(p)

:: p を L^{A}TEX で表現可能な文字列にする

374. monotos(p)

:: 有理式を文字列に変換．単項式以外では ( と ) で囲む

375. monototex(p|minus=1)

:: 有理式を TEX の文字列に変換．単項式以外では ( と ) で囲む

376. rtotex(p)

:: 数式を TEX の文字列に変換． 1 文字を越えるときは { と } で囲む

377. texsp(s)

:: TEX の文字列 s の最後が TEX のキーワードのとき， s の末尾に空白をつける．

378. texbegin(t,s|opt=u)

:: TEX の \begin{t}[u] s \end{t} というソースを出力する

379. texcr(k)

:: 127 以下の非負整数 k に応じて TEX における数式の改行の文字列を返す

380. texket(s|all=t)

:: TEX のソース s における括弧のサイズを可変にする

381. eqs2tex(p,[var,dic,pages,cont]|dviout=1)

:: 長い数式 p を TEX の複数行の display style に変換

382. ltotex(l|opt=s,pre="string",cr="cr",small=1,lim=ℓ,var=v)

:: リストまたはベクトルを s = "spt" のとき重複度つきのリストとみて\left\{... または s = "GRS" のとき \begin{Bmatrix} ⋯ の形の Riemann scheme とみて TEX の文字列に変換など

383. mtotex(m|small=1,2, null=1,2, sp=1,2, idx=0,1, mat=s,var=ℓ, pfrac=v,raw=1,lim=n)

:: 行列またはベクトルを TEX の文字列に変換するが，成分が有理式のときは因数分解した形にする

384. divmattex(s,l)

:: 行列の TEX のソース s の分割や列の並べ替えを行う

385. smallmattex(s)

:: TEX のソースで ( ) や { } で囲まれた行列を小サイズに変換する

386. texlen(s)

:: L^{A}TEX の数式の横幅を推測して文字数で返す

387. texlim(s, n|del=s_{0},cut=s_{1})

:: 長い TEX の数式を，複数行に分割する

1.2.10 Lines and curves

388. ladd(u,v,t)    ladd(u,v,[t_{2}])    ladd(u,v,[t_{1},t_{2}])

:: ベクトルまたはリストの成分の和（t = 1）や差（t = −1）を成分とするリストを返す

389. lsub([u,v])

:: ベクトルまたはリスト u, v に対して， u − v を返す

390. dnorm(v|max=f)

:: ベクトルまたはリストのノルム，または 2 点間の距離を返す

391. dext(u,v)， ([u_{1},u_{2}],[v_{1},v_{2}])

:: 2 次元ベクトルまたはリストの外積を返す

392. darg([p,q])  darg([p_{1},p_{2}],[q_{1}, q_{2}])

\overrightarrow{pq} = (x, y) の偏角 θ，または\overrightarrow{p_{1}p_{2}} と\overrightarrow{q_{1}q_{2}} のなす角に応じた数を返す

393. dwinding([p,[q_{1}, . . . , q_{n}])

点 p に対して，点 q_{1}, …, q_{n}, q_{1} を順に繋ぐ折れ線の回転数を返す

394. mrot(θ|deg=1)  mrot([θ′_{z},θ_{y},θ_{z}]|deg=1,conj=1)

:: 角度 θ の回転行列，または 3 次元の回転行列を返す

395. dvangle(v_{1},v_{2})  dvangle([u_{1}, u_{2}, u_{3}],0)

:: ベクトルまたはリストの鋏む角度の余弦を返す

396. ptaffine(m,ℓ|org=v,shift=w,arg=θ,deg=θ,proc=1)

:: 実数の組（座標）のリストを結合する，またはアフィン変換（こちらは描画実行形式も可）を施す

397. ptpolygon(n,r|org=p,scale=t,arg=θ,deg=θ)

:: 半径 r の円に内接する正 n 多角形の頂点の平面座標

398. ptlattice(m,n,v_{1},v_{2}|org=p,scale=t,cond=[f_{1},f_{2}, . . .],line=1)

:: org を始点として v_{1} 方向に m 個まで， v_{2} 方向に n 個までの合計 m × n 個の格子点の座標

399. ptcopy(ℓ,v)

:: 座標のリスト ℓ を移動方向のリスト v に従って複製コピーする

400. ptcommon([s_{1},s_{2}],[t_{1},t_{2}]|in=k)

:: 直線や線分や円に対して共通点，接点や垂線の足，内分点，方向転換進行点，角度などを求める

401. pt5center(p,q,r|opt=f)

:: p, q, r を頂点とする三角形の五心, 円や直線に接する円

402. ptinversion(p|org=[a,b],sc=r)

:: 点 p または円 p の反転

403. ptcontain(p,[t_{1},t_{2},t_{3}])

:: 点 p あるいは線分 p = [p_{1},p_{2}] と三角形 t_{1}, t_{2}， t_{3} の共通部分を返す

404. pg2tg(n|all=f,bis=1)

:: 正 n 多角形の対角線による三角形分割のリストを返す

405. pgpart(p,f)

:: 正 n 多角形の対角線による三角形分割の種々の変換

406. xypg2tg(p|pg=n,skip=s,r=r,org=b,rot=c,opt=t,proc=f,line=ℓ,every=e,V=v,dviout=d)

:: （複数の）正多角形の三角形分割などの表示

407. xytournament(l,[w,h]|dviout=t,teams=s,top=0,winner=m,win=1,rev=1,verb=f)

:: トーナメント戦の図の描画

408. ptconvex([p_{1}, p_{2}, . . .]|opt=1)

:: すべての点 p_{1}, p_{2}, … の凸包，あるいはすべての点を繋ぐ多角形を返す

409. ptwindow(ℓ,[x_{1},x_{2}],[y_{1},y_{2}]|scale=t)

:: 平面座標 (x, y) のリストで x_{1} ≤ x ≤ x_{2}， y_{1} ≤ y ≤ y_{2} を満たさないものを 0 に変える

410. ptbbox([[x_{1},y_{1},. . .],[x_{2},y_{2},. . .],. . .]|box=b)

ptbbox([[[x_{min}^{(1)},x_{max}^{(1)}],[y_{min}^{(1)},y_{max}^{(1)}],…],[[x_{min}^{(2)},x_{maxS}^{(2)}],…],…]|box=1) :: 座標 (x, y, …) や箱のリストを囲む箱 [[x_{min},x_{max}],[y_{min},y_{max}],…] を返す

411. iscombox([[x_{min}^{(1)},x_{max}^{(1)}],[y_{min}^{(1)},y_{max}^{(1)}],…], [[x_{min}^{(2)},x_{max}^{(2)}],[y_{min}^{(2)},y_{max}^{(2)}],…]) :: 2 つの箱（区間の直積）の共通部分の有無を返す

412. lninbox([p_{1},p_{2}],[[x_{min},x_{max}],[y_{min},y_{max}]]|in=1)

:: 平面内の 2 点 p_{1} と p_{2} を結ぶ直線（または線分）の箱内の部分（2 点を結ぶ線分）を返す

413. scale(ℓ|scale=[c_{1}, . . .],f=f,shift=[s_{1},s_{2}],TeX=1,mes=[t,[a_{1},b_{1},w_{1}], . . .],line=[a,b],
    mes2=[[x_{1},[t_{1,0},t_{1,1},c_{1}],t_{1},s_{1}],. . .],prec=0,col=s,inv=1,vert=1)

:: 目盛や対数（函数）尺の作成

414. tobezier(ℓ|inv=[a,b,t],div=k)

:: 点のリスト ℓ で定まる Bézier 曲線のパラメータ表示とその逆変換と分割

415. lbezier(l|inv=t)

:: 区分 Bézier 曲線のデータ変換

416. velbezier(f,[a,b,t])

:: Bézier 曲線の最大速度ベクトル

417. ptbezier(l,[n, t])  ptbezier(l,s)

:: （複合） Bézier 曲線上の点と速度ベクトルを求める

418. areabezier(l|rev=1,pt=[p_{1},p_{2}, . . .],para=1,prec=v,int=k,exp=c,Acc=1,cpx=1)

:: Bézier 曲線を用いた領域の面積・数値積分の計算

419. ptcombezier(ℓ_{1},ℓ_{2},m)

:: 点のリスト ℓ_{1}, ℓ_{2} で定まる 2 つの Bézier 曲線の交点を求める

420. ptcombz(b_{1},b_{2},m|red=t,prec=k)

:: 区分 Bézier 曲線 b_{1}, b_{2} の交点を求める

1.2.11 Drawing curves and graphs

421. openGlib([w,h]|null=1)

:: グラフィックライブラリ（glib）のウインドウを開く

422. trcolor(s)

:: 色を文字列からコードへ変換

    色は， red, green, blue, yellow, cyan, magenta, black, white, gray が可能
423. mcolor([c_{0},. . .,c_{m}],k|disc=1)

:: 中間色のコードを返す

424. xyproc(f|dviout=1,opt=s,env=t)

:: XY-pic/TikZ や指定した環境の開始（f = 1）と終了（f = 0）や表示

425. 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 はオプション文字列．

426. 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 はオプション文字列．

427. xyline([x_{1},y_{1},s_{1}],[x_{2},y_{2},s_{2}]|opt=t)  xyline([x_{1},y_{1}],[x_{1}, y_{2}]|opt=t)

:: XY-pic/TikZ で (x_{1}, y_{1}) と (x_{2}, y_{2}) を線で結ぶ（引数はベクトルでもよい）

428. xyarrow([x_{1},y_{1},s_{1}],[x_{2},y_{2},s_{2}]|opt=t,cmd=s)

:: XY-pic/TikZ で (x_{1}, y_{1}) と (x_{2}, y_{2}) を矢印等で結ぶ（引数はベクトルでもよい）

429. xyarrows([f_{1},f_{2}],[v_{1},v_{2}],[[x_{1},x_{2},m],[y_{1},y_{2},n]]|scale=r,abs=v)

:: XY-pic/TikZ で複数の矢印を描く

430. xybox([[x_{1},y_{1}],[x_{2},y_{2}],[x_{3},y_{3}]]|opt=t,color=s...)  xybox([[x_{1},y_{1}],[x_{2},y_{2}]]|opt=t,color=s,...)

:: XY-pic/TikZ で (x_{1}, y_{1}) と (x_{2}, y_{2}) を対角点とし， (x_{3}, y_{3}) を頂点とする平行四辺形（あるいは水平な辺をもつ長方形）を描く

431. xycirc([x,y,s],r|opt=t,arg=[θ_{1},θ_{2}],deg=[θ_{1},θ_{2}],close=1)

:: XY-pic/TikZ で (x, y) 中心の半径 r mm/cm の円を描く

432. xybezier([[x_{1},y_{1}], . . . ,[x_{n}, y_{n}]]|verb=k,opt=t,cmd=s,relative=1)

:: XY-pic/TikZ で区分 Bézier 曲線（複合 Bézier 曲線）を描く

433. draw bezier(id,idx,b|col=c,opt=s,init=1)

:: キャンバス上に区分 Bézier 曲線を描く

434. xylines([[x_{1},y_{1},s_{1}],[x_{2},y_{2},s_{2}],. . .]|opt=t,close=1,curve=1,ratio=c,verb=1,scale=r,
    Acc=1,dviout=1,proc=p)

:: XY-pic/TikZ で s_{j} を (x_{j}, x_{j}) に置き， (x_{1}, y_{1}), (x_{2}, y_{2}), … を（Bézier 曲）線で結ぶ

435. xyang(r,p_{0},p_{1},p_{2}|opt=t,scale=r,prec=1,ar=1,dviout=1,proc=1)

:: XY-pic/TikZ で角 ∠p_{1}p_{0}p_{2} の記号や円弧や扇形や矢印を描く

436. xyoval(p,r,q|opt=t,arg=[t_{1},t_{2},t_{3}],deg=[t_{1},t_{2},t_{3}],scale=r,ar=1,prec=1,dviout=1,
    proc=1)

:: XY-pic/TikZ で p を中心として，軸の長さが r と qr の楕円またはその弧や扇形を描く

437. xygrid([x,t_{x},u_{x},m_{x},s_{x}],[y,t_{y},u_{y},m_{y},s_{y}]|raw=r,shift=[s_{x},s_{y}])

:: （対数）方眼紙の描画

438. xycircuit(p,s|scale=r,opt=t,at=k,rev=1)

:: 電気回路を描く

439. xypoch(w,h,r_{1},r_{2}|ar=r)

:: Pochhammer の cycle を描く

440. xyplot([[a_{1},b_{1}],[a_{2},b_{2}],. . .],[x_{0},x_{1}],[y_{0},y_{1}]|opt=t,ax=[x_{0},y_{0},s,t,u],axopt=[w,h,o,z],
    scale=r,to=[W,H],dviout=1,view=v,raw=1)

:: 与えられた点のリストをプロットして順につなぐ

441. xyaxis([x_{0},y_{0},s,t,u],[x_{1},x_{2}],[y_{1},y_{2}]|scale=r,opt=t,axopt=[h,w,o,z],view=1)

:: 座標軸の描画

442. xygraph(f,n,[t_{1}, t_{2}],[x_{1},x_{2}],[y_{1}, y_{2}]|opt=t,rev=1,ax=[x_{0},y_{0},s,t,u],axopt=[h,w,o,z],
    scale=r,ratio=c,raw=1,org=[x_{0},y_{0}],pt=[p_{1},p_{2},...],verb=1,para=1,prec=v,shift=[u,v],
    Acc=1,dviout=t,proc=p)

:: 変域の n 等分点での値で関数のグラフを描く（t_{1} ≤ x ≤ t_{2}， (x_{1}, y_{1})–(x_{2}, y_{2}) は表示窓の範囲）

443. xy2graph(f,n,[x_{1},x_{2}],[y_{1}, y_{2}],[h_{1},h_{2}],α,β|opt=t,scale=r,view=h,raw=1,trans=1,
    ax=[z_{1},z_{2},t],dev=m,acc=k,org=[x_{0},y_{0},z_{0}],pt=[p_{1},p_{2},...],prec=v,title=s,dviout=k,
    ext=[a,b],shift=[u,v],cl=1,proc=p)

:: x, y 変数の区間を n 等分して曲面 z = f(x, y) の 3D グラフを描く

444. xy2curve([f_{1}, f_{2}, f_{3}],n,[t_{1},t_{2}],[y_{1},y_{2}],[z_{1}, z_{2}],α,β|scale=r,gap=g,opt=s,eq=q,raw=w,
    dviout=d)

:: 空間曲線の隠線処理つき描画

445. execdraw(ℓ,t|shift=[u,v],ext=[a,b],cl=1)

:: 描画実行形式 ℓ を出力形態 t に従って実行する

1.2.12 Applications

446. powprimroot(p,n|all=1,exp=1,log=f)

:: p 以上の素数 n 個とその原始根のリストを作る

447. distpoint(l|div=5,opt=s,title=t,size=ℓ)

:: 100 点満点の点数表のデータ l を元に点数分布などを表にする

448. seriesTaylor(f,k,v|evalopt=opt,small=1,frac=0,dviout=n)

:: 函数 f の変数または変数のリスト v に対する k 次の項までの Taylor 展開を求める

1.2.13 Environments

449. Canvas

:: Risa/Asir の描画キャンバスのデフォルトサイズ

450. AMSTeX

:: この値が 1 は AMSL^{A}TEX を意味する

451. TeXEq

:: デフォルトの L^{A}TEX の数式環境の指定（dviout0(3) で値が分かる）

452. TeXLim

:: L^{A}TEX で長い数式を行分割する際の 1 行の許容最大横幅文字数のデフォルト値

453. TeXPages

:: TEX の display style で改ページを許す行数の閾値（cf. fctrtos()）

454. TikZ

:: グラフ表示に XY-pic を使うか TikZ を使うかを指定

455. XYPrec

:: グラフ表示の時の座標の小数点以下の丸め桁数

456. XYcm

:: Unit is cm even in XY-pic での単位を cm で表して， TikZ に合わせる

457. XYLim

:: XY-pic や TikZ での曲線描画で順に指定する点での改行の間隔

458. DVIOUTH

:: myhelp() で指定した函数の解説を示すためのプログラムの指定

459. DIROUT

:: 数式を L^{A}TEX に変換したソースが格納されるディレクトリ（書き込み可能なことが要請される）

460. DVIOUTA

:: L^{A}TEX の AMSTEX 環境で risaout.tex を変換して表示するプログラムのパス名

461. DVIOUTB

:: L^{A}TEX の AMSTEX 環境で risaout10.tex （または risaout10.tex）を変換して表示するプロ

    グラムのパス名で， DVIOUTA と交換できる（cf. dviout0(), risatex.bat）

462. DVIOUTL

:: L^{A}TEX 環境で riasout0.tex を変換して表示するプログラムのパス名

463. .muldif

:: os_muldif.rr をロードしたときに読み込まれるファイル

464. risatex.bat

:: os_muldif.rr が出力する L^{A}TEX のソースファイルを変換して表示するプログラム

1.3 Functions in the original library

以下の函数は， module 化されないので，函数名の先頭に os_md. をつけません．

1.3.1 数の演算

1. idiv(i_{1},i_{2})

:: 整数除算による商

2. irem (i_{1},i_{2})

:: 整数除算による剰余

3. fac(i)

:: 自然数 i の階乗

4. nm(p)

:: 有理数または有理式の分子

5. dn(p)

:: 有理数または有理式の分母

6. igcd(i_{1},i_{2})

:: 整数 i_{1} と i_{2} の GCD を求める

7. igcdcntl([i])

:: 整数 GCD のアルゴリズムの選択

8. ilcm(i_{1},i_{2})

:: 整数の最小公倍数を求める

9. isqrt(n)

:: n の平方根を越えない最大の整数を返す

10. inv(i,m)

:: m を法とする i の逆数

11. random([seed]) :: 乱数を生成する

12. lrandom(bit)

:: 多倍長乱数を生成する

13. mt save(fname)

:: 乱数生成器の現在の状態をファイルにセーブする

14. mt load(fname)

:: ファイルにセーブされた乱数生成器の状態をロードする

15. real(comp)

:: comp の実数部分

16. imag(comp)

:: comp の虚数部分

17. conj(comp)

:: comp の共役複素数

18. eval(obj [, prec]) :: obj の値の評価

19. deval(obj)

:: obj の値の評価（倍精度浮動小数）

20. pari(func,arg,prec) :: PARI の函数 func を呼び出す.

21. setprec([n])

:: bigfloat の桁数を n 桁に設定する

22. setmode([p])

:: 有限体を GF (p) に設定する

23. ntoint32(n)

:: 非負整数と符号なし 32bit 整数の間の型変換

24. int32ton(int32)

:: 非負整数と符号なし 32bit 整数の間の型変換

25. iand(m,n)

:: 整数 m, n のビット毎の and

26. ior(m,n)

:: 整数 m, n のビット毎の or

27. ixor(m,n)

:: 整数 m, n のビット毎の xor

28. ishift(i,count)

:: 整数 i の絶対値を bit 列とみて shift する

29. pari(binary,n)

:: 数 n の 2 進数表示

30. pari(factor,n)

:: 整数 n または 1 変数多項式 n の素因数分解を求める

31. pari(issquare,n)

:: 整数 n または多項式 n が平方数（元）かどうか調べる

32. pari(omega,n)

:: 整数 n または 1 変数多項式 n の素因子の個数

33. pari(bigomega,n)

:: 整数 n または 1 変数多項式 n の素因子の重複度込みの個数

34. pari(numdiv,n)

:: 整数 n を割り切る正整数の個数

35. pari(sigma,n)

:: n の正の約数の和

36. pari(isprime,num)

:: 自然数 num が素数かどうか調べる（合成数なら 0 を返す）

37. pari(ispsp,num)

:: 自然数 num が擬素数かどうか調べる（合成数なら 0 を返す）

38. pari(nextprime,num)

:: 自然数 num 以上の最小の擬素数を返す

39. pari(frac,num)

:: 実数 num の小数部分

40. pari(conj,num)

:: 複素数 num （行列でも可）の共役複素数を返す

41. pari(abs,num[,prec]) :: 複素数 num の絶対値を返す

42. pari(cf,num)

:: num の連分数展開を返す

43. pari(mu,n)

:: 自然数 n のメビウス函数 μ(n) の値（0 または ±1）を返す

44. pari(phi,n)

:: 自然数 n に対する Euler の φ 函数の値（n 以下の n と素なものの個数）を返す

1.3.2 多項式，有理式の演算

45. var(rat)

:: rat の主変数を返す

46. vars(obj)

:: obj に含まれる変数のリスト

47. uc()

:: 未定係数法のための vtype が 1 の不定元を生成する.

48. coef(poly,deg [,var])

:: poly の var (省略時は主変数) に関する deg 次の係数を出力する

49. deg(poly,var)

:: poly の, 変数 var に関する最高次数

50. mindeg(poly,var)

:: poly の, 変数 var に関する最低次数

51. nmono(rat)

:: rat の単項式の項数

52. ord([varlist])

:: 変数順序の設定

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 で割る除算が最後まで実行できる場合に商, 剰余を求める 59. tdiv([poly1,poly2])

:: poly1 が poly2 で割れたら商を割れなければ 0 を返す

60. subst(rat[,varn,ratn ]*)

:: 有理式の特定の不定元に, 定数あるいは多項式, 有理式などを代入する

61. psubst(rat[,varn,ratn ]*)

:: 有理式の特定の不定元に, 定数あるいは多項式, 有理式などを代入する

62. diff(rat[,varn]*) または diff(rat,varlist) :: rat を varn あるいは varlist の中の変数で順次微分する

63. res(var,poly1,poly2 [,mod])

:: 変数 var に関する多項式 poly1 と poly2 の終結式を求める

64. fctr(poly)

:: poly を既約因子に分解する

65. sqfr(poly)

:: poly を無平方分解する

66. ufctrhint(poly,hint)

:: 次数情報を用いた有理数係数の 1 変数多項式の因数分解

67. modfctr(poly,mod)

:: 有限体上での多項式の因数分解

68. ptozp(poly|factor=1)

:: 有理係数多項式を有理数倍して整数係数で係数の GCD が 1 の多項式に直す

69. % poly % m :: poly の各係数を整数 m で割った剰余で置き換えた多項式を返す

70. prim(poly[,v])

:: 有理係数多項式 poly の原始的部分 (primitive part)

71. cont(poly[,v])

:: 有理係数多項式 poly の容量 (content)

72. gcd(poly1,poly2[,mod])

:: 二つの多項式の最大公約式 (GCD) を求める

73. gcdz(poly1,poly2)

:: 有限体上の二つの多項式の最大公約式 (GCD) を求める

74. red(rat)

:: rat を約分する

75. umul(p_{1},p_{2})

:: 整数係数一変数多項式の高速乗算

76. umul ff(p_{1},p_{2})

:: 有限体係数一変数多項式の高速乗算

77. usquare(p_{1})

:: 整数係数一変数多項式の高速 2 乗算

78. usquare ff(p_{1})

:: 有限体係数一変数多項式の高速 2 乗算

79. utmul(p_{1},p_{2},d)

:: 整数係数一変数多項式の高速乗算 (打ち切り次数指定)

80. utmul ff(p_{1},p_{2},d)

:: 有限体係数一変数多項式の高速乗算 (打ち切り次数指定)

81. kmul(p_{1},p_{2})

:: 一変数多項式の乗算を Karatsuba 法で行う

82. ksquare(p_{1})

:: 一変数多項式の高速 2 乗算を Karatsuba 法で行う

83. ktmul(p_{1},p_{2},d)

一変数多項式の高速乗算 (打ち切り次数指定) を Karatsuba 法で行う

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 アルゴリズムの切替えの閾値

87. utrunc(p,d)

:: 一変数多項式を次数で切る

88. udecomp(p,d)

:: 一変数多項式を次数で分ける

89. ureverse(p)

:: 一変数多項式の次数を逆にした多項式を作る

90. uinv as power series(p,d)

:: 一変数多項式を冪級数とみて, 逆元計算

91. ureverse inv as power series(p,d)

:: 一変数多項式を次数を逆にして冪級数とみて, 逆元計算

92. udiv(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, 商を返す

93. urem(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, 剰余を返す

94. urembymul(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, 剰余を返す

95. urembymul precomp(p_{1},p_{2},inv)

:: 固定された多項式による剰余計算を多数行う場合などに用いる

96. ugcd(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, GCD を返す

97. pari(content,p)

:: x 変数の多項式とみて，係数の最大公約元を返す

98. pari(round,p)

:: 多項式の各係数を近似整数に置き換える

99. pari(roots,p[,prec])

:: 多項式の根を求める

100. pari(disc,p)

:: x 変数の多項式 p の判別式を返す．

1.3.3 リスト，ベクトル，配列の演算

101. car(list)

:: 空でない list の先頭要素（空の場合は空のリスト）を返す

102. cdr(list)

:: 空でない list から先頭要素を除いた（空の場合は空の）リストを返す 103. cons(obj,list)

:: list の先頭に obj を加えたリストを返す

104. append(list1,list2)

:: list1 の後に list2 をつなげたリストを返す

105. reverse(list)

:: 逆順に並べ替えたリストを返す

106. length(lv)

:: リストまたはベクトルの長さを返す

107. newvect(len[,list])

:: 長さ len のベクトルを生成する

108. vector(len[,list])

:: 長さ len のベクトルを生成する

109. vect([elements])

:: 要素の並びからベクトルを生成する

110. ltov(list)

:: list をベクトルに変換する

111. vtol(vect)

:: ベクトルをリストに変換する

112. newbytearray(len,[listorstring]) :: newvect と同様にして byte array を生成する

113. size(vect/mat)

:: 行列のサイズまたはベクトルの長さを求める函数（戻り値はリスト） 114. qsort(array [,func])

:: 一次元配列 array をソートする.

1.3.4 行列の演算

115. newmat(row,col [,[[a,b,...],[c,d,...],...]] )
116. matrix(row,col [,[[a,b,...],[c,d,...],...]] )

:: row 行 col 列の行列を生成する

117. mat(vector[,...])
118. matr(vector[,...])

:: 行ベクトル（またはリスト）の並びから行列を生成する

119. matc(vector[,...])

:: 列ベクトル（またはリスト）の並びから行列を生成する

120. det(mat[,mod])

:: mat の行列式

121. nd det(mat[,mod])

:: 有理数または有限体上の多項式行列 mat の行列式

122. invmat(mat)

:: 行列 mat の逆行列

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 倍を加える.

129. pari(adj,mat)

:: 行列 mat の余因子行列（元の行列との積が行列式となる）を返す

130. pari(trace,mat)

:: 行列 mat の trace を返す

131. pari(signat,mat)

:: 実対称行列の符号を返す

132. pari(indexrank,mat)

:: 行列 mat の階数に等しいサイズの正則小行列の一つの行と列の位置を返す

133. pari(supplement,mat)

:: 列ベクトルが一次独立な行列 mat の右に列を補って正則正方行列を作る

134. pari(hess,mat)

:: 正方行列をヘッセンベルグ行列に変換する

135. pari(eigen,mat[,prec])

:: 数を成分とする行列の固有ベクトルを返す

136. pari(jacobi,mat[,prec])

:: 実対称行列の固有値と固有ベクトルを返す

1.3.5 文字列に関する演算

137. rtostr(obj)

:: obj を文字列に変える

138. strtov(str)

:: str (文字列) を不定元に変える

139. eval str(str)

:: str (文字列) を評価する.

140. strtoascii(str)

:: 文字列をアスキーコード（1 以上 255 以下の整数）のリストで表す

141. asciitostr(list)

:: アスキーコードの列を文字列に変換する

142. str len(str)

:: 文字列の長さを返す

143. str chr(str,start,c)

:: 文字が最初に現れる位置を返す

144. sub str(str,start,end)

:: 部分文字列を返す

1.3.6 構造体に関する函数

145. newstruct(name)

:: 構造体名が name の構造体を生成する

146. arfreg(name,add,sub,mul,div,pwr,chsgn,comp) :: 構造体に体する基本演算を登録する

147. str type(name|object)

:: 構造体の識別番号を取得する

1.3.7 入出力

148. end

149. quit

:: 現在読み込み中のファイルを閉じる. トップレベルにおいてはセッションを終了することになる 150. load("filename")

:: filename を読み込む

151. which("filename")

:: 引数 filename に対し, load() が読み込むパス名を返す

152. output(["filename"])

:: 以降の出力先を filename または標準出力に切替える

153. bsave(obj,"filename")

:: filename に obj をバイナリ形式で書き込む

154. bload("filename")

:: filename から数式をバイナリ形式で読み込む

155. print(obj[,nl])

:: obj を評価して表示する

156. printf(format[,args])

157. fprintf(fd,format[,args])

158. sprintf(format[,args])

:: C に似たプリント関数（実験的仕様関数）

159. access(file)

:: file の存在をテストし，存在すれば 1，存在しなければ 0 を返す

160. remove file(file)

:: file を消去する

161. open file("filename" [,"mode"])

:: filename をオープンする

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()

:: 標準入力のバッファをクリアする

1.3.8 型や函数，モジュールに関わる函数

167. type(obj)

:: obj の型を求める函数

168. ntype(num)

:: num (数) の型 (整数) を返す.

169. vtype(var)

:: var (不定元) の型 (整数) を返す

170. call(name,args)

:: 函数 name を呼び出す

171. functor(func)

:: func の函数子を取り出す

172. args(func)

:: func の引数リストを取り出す

173. funargs(func)
:: cons(functor(func),args(func)) を返す
174. module list()

:: 定義済みのモジュールのリストを得る

175. module definedp(name)

:: モジュール name の存在をテストする

176. remove module(name)

:: モジュール name を削除する

1.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) を倍精度浮動小数で求める 182. dtan(num)

:: 函数値 tan(num) を倍精度浮動小数で求める 183. dabs(num)

:: 絶対値 |num| を倍精度浮動小数で求める

184. dexp(num)

:: 函数値 exp(num) を倍精度浮動小数で求める 185. dlog(num)

:: 対数値 log(num) を倍精度浮動小数で求める

186. dsqrt(num)

:: 平行根\sqrt{num} を倍精度浮動小数で求める

187. ceil(num)

:: num 以上の最小の整数を求める

188. 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 の平方根を与える

194. pari(arg,num[,prec])

:: 複素数 num の偏角を与える（−π < 戻り値 ≤ π）

195. pari(gamma,num[,prec])

:: ガンマ関数（num は複素数でもよい）

196. pari(gamh,num[,prec])

:: Γ(num + \frac{1}{2}) （num は複素数でもよい）

197. pari(lngamma,num[,prec])

:: log(Γ(x))

198. pari(psi,num[,prec])

:: digamma 関数

199. pari(erfc,num[,prec])

:: 相補誤差関数 (complementary error function)

200. pari(dilog,num[,prec])

:: dilogarithm 関数

201. pari(eta,τ[,prec])

:: Dedekind の Eta 関数 η(τ) で τ は虚部が正の複素数 202. pari(wp,τ[,prec])

:: Weber 関数 𝔣(τ) で τ は虚部が正の複素数

203. pari(wp2,τ[,prec])

:: Weber 関数 𝔣_{2}(τ) で τ は虚部が正の複素数

204. pari(jell,τ[,prec])

:: Elliptic j-invariant j(τ) で τ は虚部が正の複素数

205. pari(zeta,s[,prec])

:: Riemann の ζ 関数

1.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)

:: すでに存在しているウィンドウへ描画する

211. open canvas(id[,geometry])

:: 描画用ウィンドウ (キャンバス) を生成する

212. clear canvas(id,index)

:: キャンバスをクリアする

213. draw obj(id,index,pointorsegment [,color])

:: キャンバス上に点または線分を描画する

214. draw string(id,index,[x,y],string [,color])

:: キャンバス上に文字列を描画する

1.3.11 有限体に関する函数

215. setmod ff([p|defpoly2])  setmod ff([defpolyp,p])  setmod ff([p,n])

:: 有限体の設定, 設定されている有限体の法, 定義多項式の表示

216. field type ff([p|defpoly2])

:: 設定されている基礎体の種類

217. field order ff()

:: 設定されている基礎体の位数

218. characteristic ff()

:: 設定されている体の標数

219. extdeg ff()

:: 設定されている基礎体の, 素体に対する拡大次数

220. simp ff(obj)

:: 数, あるいは多項式の係数を有限体の元に変換

221. random ff()

:: 有限体の元の乱数生成

222. lmptop(obj)

:: GF (p) 係数多項式の係数を整数に変換

223. ntogf2n(m)

:: 自然数を GF (2^{n}) の元に変換

224. gf2nton(m)

:: GF (2^{n}) の元を自然数に変換

225. ptogf2n(poly)

:: 一変数多項式を GF (2^{n}) の元に変換

226. gf2ntop(m,[v])

:: GF (2^{n}) の元を多項式に変換

227. ptosfp(p)

:: 小標数有限体への変換

228. sfptop(p)

:: 小標数有限体からの変換

229. defpoly mod2(d)

:: GF (2) 上既約な d 次の一変数多項式の生成

230. sffctr(poly)

:: 多項式の小標数有限体上での既約分解

231. fctr ff(poly)

:: 1 変数多項式の有限体上での既約分解

232. irredcheck ff(poly)

:: 1 変数多項式の有限体上での既約判定

233. randpoly ff(d,v)

:: 有限体上の乱数係数 1 変数多項式の生成

234. ecm add ff(p_{1},p_{2},ec)

:: 楕円曲線上の点の加算

235. ecm sub ff(p_{1},p_{2},ec)

:: 楕円曲線上の点の減算

236. ecm chsgn ff(p_{1})

:: 楕円曲線上の点の逆元

1.3.12 代数的数に関する函数

237. newalg(defpoly)

:: root を生成

238. defpoly(alg)

:: root の定義多項式を返す

239. alg(i)

:: インデックスに対応する root を返す

240. algv(i)

:: alg(i) に対応する不定元を返す

241. simpalg(rat)

:: 有理式に含まれる代数的数を簡単化

242. algptorat(poly)

:: 多項式に含まれる root を, 対応する不定元に置き換える

243. rattoalgp(poly,alglist)

:: 多項式に含まれる root に対応する不定元を root に置き換える 244. cr gcda(poly1,poly2)

:: 代数体上の 1 変数多項式の GCD

245. sp norm(alg,var,poly,alglist) :: 代数体上でのノルムの計算

246. asq(poly)

:: 代数体上の 1 変数多項式の無平方分解

247. af(poly,alglist)

248. af noalg(poly,defpolylist) :: 代数体上の 1 変数多項式の因数分解

249. sp(poly)

250. sp noalg (poly)

:: 最小分解体を求める

251. set field(rootlist)

:: 代数体を基礎体として設定

252. algtodalg(alg)

:: 代数的数 alg を DAlg に変換

253. dalgtoalg(dalg)

:: DAlg dalg を代数的数に変換

254. dptodalg(dp)

:: 分散多項式 dp を DAlg に変換

255. dalgtodp(dalg)

:: DAlg dalg を分散多項式に変換する.

1.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)

:: グレブナ基底の計算

260. 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)

:: グレブナ基底を入力とする, 基底変換による辞書式順序グレブナ基底の計算 265. gr minipoly(plist,vlist,order,poly,v,homo)

:: 多項式の, イデアルを法とした最小多項式の計算

266. minipoly(plist,vlist,order,poly,v)

:: グレブナ基底を入力とする, 多項式の最小多項式の計算

267. tolexm(plist,vlist1,order,vlist2,mod)

:: 法 mod での基底変換によるグレブナ基底計算

268. minipolym(plist,vlist1,order,poly,v,mod)

:: 法 mod でのグレブナ基底による多項式の最小多項式の計算

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)

274. dp weyl gr f main(plist,vlist,homo,order)

:: グレブナ基底の計算 (組み込み函数)

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 アルゴリズムによるグレブナ基底の計算 (組み込み函数)

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)

:: グレブナ基底の計算 (組み込み函数)

285. dp gr flags([list])
286. dp gr print([i])

:: 計算および表示用パラメタの設定, 参照

287. dp ord([order])

:: 変数順序型の設定, 参照

288. dp set weight([weight])

:: sugar weight の設定, 参照

289. dp set top weight([weight])

:: top weight の設定, 参照

290. dp weyl set weight([weight])

:: weyl weight の設定, 参照

291. dp ptod(poly,vlist)

:: 多項式を分散表現多項式に変換する.

292. dp dtop(dpoly,vlist)

:: 分散表現多項式を多項式に変換する.

293. dp mod(p,mod,subst)

:: 有理数係数分散表現多項式の有限体係数への変換

294. dp rat(p)

:: 有限体係数分散表現多項式の有理数係数への変換

295. dp homo(dpoly)

:: 分散表現多項式の斉次化

296. dp dehomo(dpoly)

:: 斉次分散表現多項式の非斉次化

297. dp ptozp(dpoly)

:: 定数倍して係数を整数係数かつ係数の整数 GCD を 1 にする.

298. dp prim(dpoly)

:: 有理式倍して係数を整数係数多項式係数かつ係数の多項式 GCD を 1 にする.

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) :: 分散表現多項式の正規形を求める. (真の結果を [分子, 分母] の形で返す)

305. dp hm(dpoly)

:: 頭単項式を取り出す.

306. dp ht(dpoly)

:: 頭項を取り出す.

307. dp hc(dpoly)

:: 頭係数を取り出す.

308. dp rest(dpoly)

:: 頭単項式を取り除いた残りを返す.

309. dp td(dpoly)

:: 頭項の全次数を返す.

310. dp sugar(dpoly)

:: 多項式の sugar を返す.

311. dp lcm(dpoly1,dpoly2)

:: 最小公倍項を返す.

312. dp redble(dpoly1,dpoly2)

:: 頭項どうしが整除可能かどうか調べる.

313. dp subd(dpoly1,dpoly2)

:: 頭項の商単項式を返す.

314. dp vtoe(vect)

:: 指数ベクトルを項に変換

315. dp etov(dpoly)

:: 頭項を指数ベクトルに変換

316. dp mbase(dplist)

:: monomial 基底の計算

317. dp mag(p)

:: 係数のビット長の和を返す 318. dp red(dpoly1,dpoly2,dpoly3)

319. dp red mod(dpoly1,dpoly2,dpoly3,mod)

:: 一回の簡約操作

320. dp sp(dpoly1,dpoly2)

321. dp sp mod(dpoly1,dpoly2,mod)

:: S-多項式の計算

322. p nf(poly,plist,vlist,order)

323. p nf mod(poly,plist,vlist,order,mod)

:: 表現多項式の正規形を求める. (結果は定数倍されている可能性あり)

324. p true nf(poly,plist,vlist,order)

325. p true nf mod(poly,plist,vlist,order,mod)

:: 表現多項式の正規形を求める. (真の結果を [分子, 分母] の形で返す)

326. p terms(poly,vlist,order)

:: 多項式にあらわれる単項をリストにする.

327. gb comp(plist1, plist2)

:: 多項式リストが, 符号を除いて集合として等しいかどうか調べる.

328. katsura(n)
329. hkatsura(n)
330. cyclic(n)
331. hcyclic(n)

:: 多項式リストの生成

332. primadec(plist,vlist)

333. primedec (plist,vlist)

:: イデアルの分解

334. primedec mod(plist,vlist,ord,mod,strategy)

:: イデアルの分解

335. bfunction(f)
336. bfct(f)

337. generic bfct(plist,vlist,dvlist,weight)

:: b 関数の計算

338. ann(f)
339. ann0(f)

:: 多項式のベキの annihilator の計算

1.3.14 分散計算に関する関数

340. ox launch([host[,dir],command])

341. ox launch nox([host[,dir],command])

:: 遠隔プロセスの起動および通信を開始する.

342. ox shutdown(id)

:: 遠隔プロセスを終了させ, 通信を終了する.

343. ox launch generic(host,launch,server,use unix,use ssh,use x,conn to serv) :: 遠隔プロセスの起動および通信を開始する

344. 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 の登録

349. ox asir

:: Asir の機能を OpenXM サーバとして提供

350. ox rpc(number,"func",arg0,...)

351. ox cmo rpc(number,"func",arg0,...)
352. ox execute string(number,"command",...)

:: プロセスの函数呼び出し

353. ox reset(number)

:: プロセスのリセット

354. ox intr(number)

:: プロセスに SIGINT 送付

355. register handler(func)

:: プロセスのリセットのための関数登録

356. ox push cmo(number,obj)

357. ox push local(number,obj)

:: obj を識別子 number のプロセスに送信

358. ox pop cmo(number)
359. ox pop local(number)

:: プロセス識別子 number からデータを受信する.

360. ox push cmd(number,command)

:: プロセス識別子 number のプロセスにコマンド command を送信する.

361. ox sync(number)

:: プロセス識別子 number のプロセスに OX_SYNC_BALL を送信する.

362. ox get(number)

:: プロセス識別子 number のプロセスからデータを受信する.

363. ox pops(number[,nitem])

:: プロセス識別子 number のプロセスのスタックからデータを取り除く.

364. ox select(nlist[,timeout])

:: 読み出し可能なプロセスの識別子を返す.

365. ox flush(id)

:: 送信バッファの強制 flush

366. ox get serverinfo([id])

:: server の Mathcap, 動作中のプロセス識別子の取得

1.3.15 その他の函数

367. ctrl("switch" [,obj])

:: "switch" で指定した環境の設定，設定値を返す．

368. debug

:: デバッグモードに入る

369. error(message)

:: エラーメッセージを表示してデバッグモードに入る

370. time()

:: セッション開始から現在までの CPU 時間および GC 時間を表示する

371. cputime(onoff)

:: 引数が 0 ならば cputime の表示を止める，それ以外ならば表示を行う

372. tstart()

:: CPU time 計測開始

373. tstop()

:: CPU time 計測終了および表示

374. timer(interval,expr,val) :: 制限時間つきで計算を実行する

375. currenttime()

1970 年 1 月 1 日 0 時 0 分 0 秒からの経過秒数

376. sleep(interval)

:: プロセスの実行を interval×10^{−3} 秒停止

377. heap()

:: 現在のヒープの大きさを返す (単位: バイト)

378. version()

:: Asir のバージョン（整数）を返す.

379. shell(command)

:: command をシェルコマンドとして実行する

380. map(function,arg0,arg1,...) :: リスト, 配列の各要素に函数を適用する

381. flist()

:: 現在定義されている組み込み函数, ユーザ定義函数の函数名を文字列リストとして返す

382. delete history([index])

:: ヒストリを消去する

383. get rootdir()

:: Asir のルートディレクトリ名を取り出す

384. getopt([key])

:: オプションの値を返す

385. getenv(name)

:: 環境変数 name の値を返す

1.4 Functions in the contributed library

1.4.1 基礎 (標準函数)

  1. base cancel(S)

:: 分母と分子の共通項を探して簡略化する

  2. base choose(L,M)

:: リスト L の M 個の成分からなる部分集合のリストのリストを返す

  3. base flatten(S)

:: リスト S のネストをはずす

  4. base intersection(A,B)

:: A と B の共通部分集合を返す

  5. base makelist(Obj,K,B,T |qt=1,step=d)

:: It generate a list from Obj where K runs in [B,T]

  6. base memberq(A,S)

: It returns 1 if A is a member of the set S else returns 0

  7. base permutation(L)

:: It outputs all permutations of L.

  8. base position(A,S)

:: It returns the position of A in S

  9. base product(Obj,K,B,T)

:: base product returns the product of Obj where K runs in [B,T].

 10. base prune(A,S)

:: It returns a list in which A is removed from S

11. base rebuild opt(Opt)

:: It rebuilt the option list Opt

12. base replace(S,Rule)

:: It rewrites S by using the rule Rule

13. base replace n(S,Rule)

:: It rewrites S by using the rule Rule.

14. base set minus(A,B)

:: It returns A \ B

15. base set union(A,B)

:: It returns A ∪ B

16. base subsetq(A,B)

:: A ⊂ B?

17. base subsets of size(K,S)

:: It outputs all subsets of S of the size K.

18. base sum(Obj,K,B,T)

:: It returns the sum of Obj where K runs in [B,T]

19. base var list(Name,B,T)

:: generate a list of variables Name+Index where Index runs on [B,T].

1.4.2 数（数学標準函数）

20. number abs(X)

::

21. number ceiling(X)

::

22. number factor(X)

:: It factors the given integer X.

23. number float to rational(X|prec=m)

::

24. number floor(X)

::

25. number imaginary part(X)

::

26. number is integer(X)

::

27. number real part(X)

::

1.4.3 行列（数学標準函数）

28. matrix adjugate(M)

:: It generates the adjugate matrix of the matrix M

29. matrix clone(M)

:: It generates the clone of the matrix M

30. matrix image(M)

:: It computes the image of M. Redundant vectors are removed

31. matrix matrix to list(M)

:: It translates the matrix M to a list.

32. matrix list to matrix(M)

:: It translates the list M to a matrix

33. matrix diagonal matrix(L)

:: It returns the diagonal matrix with diagonal entries L

34. matrix identity matrix(N)

: It returns the identity matrix of the size N

35. matrix inner product(A,B)

:: It returns the inner product of two vectors A and B

36. matrix transpose(M)

:: It returns the transpose of the matrix M

37. matrix inverse(M)

:: It returns the inverse of the matrix M

38. matrix det(M)

:: It returns the determinant of the matrix M

39. matrix solve linear(M,X,B)

:: It solves the system of linear equations MX = B

40. matrix submatrix(M,Ind)

:: It returns the submatrix of M defined by the index set Ind

41. matrix kernel(M)

:: It returns the basis of the kernel of the matrix M.

42. matrix eigenavalues(M)

:: It returns the eigenvalues of the matrix M.

43. matrix rank(M)

:: It returns the rank of the matrix M.

1.4.4 表示（数学標準函数）

44. print em(S)

:: It outputs S by a font to emphasize it.

45. print dvi form(S)

:: It outputs S to a dvi file.

46. print gif form(S| table=key_{0})

:: It outputs S to a file of the gif format

47. print input form(S)

:: It transforms S to a string which can be parsed by asir.

48. print open math xml form(S)

:: It transforms S to a string which is compliant to OpenMath(1999). www.openmath.org

49. print ox rfc100 xml form(S)

:: It transforms S to a string which is compliant to OpenXM RFC 100.

50. print png form(S)

:: It transforms S to a file of the format png. dvipng should be installed.

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 L^{A}TEX format

53. print xdvi form(S)

:: It transforms S to a xdvi file and previews the file by xdvi

54. print xv form(S|input=key_{0}, format=key_{1})

:: It transforms S to a gif file and previews the file by xv.

55. print tfb form(S)

: It transforms S to the tfb format.

56. print output(Obj|file=key_{0},mode=key_{1})

:: It outputs the object Obj to a file

57. print open math tfb form(S)

: It transforms S to a tfb format of OpenMath XML.

1.4.5 多項式（数学標準函数）

58. poly factor(F)

:: It factorizes the polynomial F

59. poly gcd(F,G)

:: It computes the polynomial GCD of F and G.

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=key_{0},v=key_{1},homo=key_{2},grace=key_{3},strategy=key_{4})

:: This function allows optional variables grobner basis, v, homo, grace, strategy

61. poly expand(F)

:: This is an alias of poly sort.

62. poly grobner basis(I|order=key_{0},v=key_{1})

:: It returns the Grobner basis of I.

63. poly hilbert polynomial(I|s=key_{0},v=key_{1})

:: It returns the Hilbert polynomial of the ideal I.

64. poly in(I|order=key_{0},v=key_{1})

:: It is an alias of poly initial()

65. poly initial(I|order=key_{0},v=key_{1})

:: It returns the initial ideal of I with respect to the given order

66. poly initial coefficients(I)|order=key_{0},v=key_{1})

:: It computes the coefficients of the initial ideal of I with respect to the given order

67. poly initial term(F |weight=key_{0},order=key_{1},v=key_{2})

:: It returns the initial term of a polynomial F with respect to the given weight vector

68. poly degree(F |weight=key_{0},v=key_{1})

:: It returns the degree of F with respect to the given weight vector

69. poly gr w(F,V,W)

:: It returns the Grobner basis of F for the weight vector W.

70. poly r omatrix(N)

:: It gives a weight matrix, which is used to compute a Grobner basis in K(x) < dx >, |x| = |dx| = N

71. poly in w (F |v=key_{0},weight=key_{1},gb=key_{2})

:: It returns the initial term or the initial ideal in w(F) for the weight vector given by order

72. poly in w(F,V,W |gb=key_{0})

:: It returns the initial term or the initial ideal in w(F) for the weight vector given by order

73. poly ord w(F,V,W)

:: It returns the order with respect to W of F.

74. poly solve linear(Eqs,V)

:: It solves the system of linear equations Eqs with respect to the set of variables V.

75. poly sort(F |v=key_{0},w=key_{1},truncate=key_{2})

:: It expands F with a given variables v=V and a given weight w=W

76. poly toric ideal(A,V)

:: It returns generators of the affine toric ideal defined by the matrix(list) A. V is the list of variables.

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 Grobner

basis functions. V is the list of variables.

78. poly prime dec(I,V)

:: It computes the prime ideal decomposition of the radical of I. V is a list of variables.

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.

80. poly ideal colon(I,J,V)

:: It computes the colon ideal of I by J, V is the list of variables.

81. poly ideal saturation(I,J,V)

:: It computes the saturation ideal of I by J. V is the list of variables.

82. poly coefficient(F,Deg,V)

:: It returns the coefficient of V^{Deg} in F. F may be rational or list or vector.

1.4.6 グラフィックライブラリ（2 次元）ライブラリ glib は, Risa/Asir のグラフィック基本関数 (draw obj()) に対する, 昔の BASIC のような単純なインタフェースを提供する.

83. glib open()

:: It starts the ox plot server and opens a canvas.

84. glib clear()

:: Clear the screen.

85. glib window(X_{min},Y_{min},X_{max},Y_{max})

:: It generates a window with the left top corner [X_{min},Y_{min}] and the right bottom corner [X_{max},Y_{max}].

86. glib putpixel(X,Y |color=key_{0})

:: It puts a pixel at [X,Y] with color

87. glib line(X_{0},Y_{0},X_{1},Y_{1}|color=key_{0},shape=key_{1})

:: It draws the line [X_{0},Y_{0}] – [X_{1},Y_{1}] with color and shape

88. glib print(X,Y,Text|color=key_{0})

:: It put a string Text at [X,Y] on the glib canvas

89. glib tops()

:: If Glib ps is set to 1, it returns a postscript program to draw the picture on the canvas.

90. glib ps form(S)

:: It returns the PS code generated by executing S (experimental).

91. glib plot(F)

:: It plots an object F on the glib canvas.

92. glib flush()

:: Flush the output. (Cfep only. It also set initGL to 1.).

93. glib set pixel size(P)

:: Set the size of putpixel to P

94. glib remove last()

:: Remove the last object.

1.4.7 OpenXM-Conrib 一般函数

95. ox check errors2(p)

:: 識別番号 p のサーバのスタック上にあるエラーオブジェクトをリストで戻す.

1.4.8 OXShell の関数

96. oxshell.oxshell(L)

:: It executes command L on a ox shell server

97. oxshell.set value(Name,V)

:: It set the value V to the variable Name on the server ox shell.

 98. oxshell.get value(Name,V)

:: It get the value of the variable Name on the server ox shell.

1.4.9 OpenMath 函数 (1999 版)

 99. om start()

:: OMproxy をスタートする.

100. om xml(s|proc=p)

:: s の CMO 表現を OpenMath の XML (CD’s in 1999) 表現になおす

101. om xml to cmo(s|proc=p)

:: OpenMath の XML (CD’s in 1999) 表現 s を CMO になおす

1.4.10 Differential equations (by Okutani)

102. odiff op appell4(a,b,c_{1},c_{2},V)

:: Appell の F_{4} を零化する微分作用素を生成します.

103. odiff op tosm1(LL,V)

:: リスト形式の微分作用素リストを sm1 形式に変換します

104. odiff op toasir(LL,V)

:: リスト形式の微分作用素リスト LL を asir の多項式に変換します.

105. odiff op fromasir(D_{list},V)

:: asir の多項式からリスト形式の微分作用素リストに変換します.

106. odiff act(L,F,V)

:: 微分作用素 L を有理式 F に作用させる. V は変数リスト.

107. odiff act appell4(a,b,c_{1},c_{2},F,V)

:: 微分作用素 odiff op appell4 を有理式 F に作用させる

108. odiff poly solve(LL,N,V)

:: 与えられた線型微分方程式系の N 次以下の多項式解を求める

109. odiff poly solve hg1(a,b,c,V)

:: ガウスの超幾何微分方程式の多項式解を求める

110. odiff poly solve appell4(a,b,c_{1},c_{2},V)

:: F_{4} がみたす線型微分方程式系の多項式解を求める

111. odiff rat solve(LL,Dn,N,V)

:: 与えられた線型微分方程式系の分母が Dn, 分子が N 次以下の多項式であるような解を求める

1.4.11 D-module (by Okutani)

112. odmodule d op tosm1(LL,V)

:: リスト形式の微分作用素リストを sm1 形式に変換します.

113. odmodule d op toasir(LL,V)

:: リスト形式の微分作用素リスト LL を asir の多項式に変換します

114. odmodule d op fromasir(D_{list},V)

:: asir の多項式からリスト形式の微分作用素リストに変換します

115. odmodule ch ideal(D_{ideal},V)

:: D_{ideal} の characteristic ideal を求めます

116. odmodule restriction(D_{ideal},V,Rest)

:: D_{ideal} の 0 次の restriction を求めます

117. odmodule elimination(D_{ideal},V,Elim)

:: D_{ideal} の elimination ideal を求めます

1.4.12 DSOLV 函数

118. dsolv dual(f,v)

:: f のグレブナ双対

119. dsolv starting term(f,v,w)

:: 正則ホロノミック系 f の方向 w での級数解の Staring terms を計算する. ここで, v は変数の集合.

1.4.13 GNUPLOT 函数

120. gnuplot.start()

:: Localhost で ox_sm1_gnuplot を起動する

121. gnuplot.gnuplot(s|proc=p)

:: GNUPLOT にコマンド s を実行してもらう

122. gnuplot.plot dots(d,s|proc=p)

:: 点の集合 d をスタイル s でプロットする.

123. gnuplot.heat(dt,step) :: 熱伝導方程式を数値的に解く

124. gnuplot.output(|file=s)

:: GNUPLOT にファイル s へポストスクリプトで出力するように頼む

125. gnuplot.plot function(f|proc=p)

:: gnuplot サーバに f のグラフを書くように頼む

126. gnuplot.stop()

:: GNUPLOT を停止し, 通信用の fifo ファイルを消す

127. gnuplot.setenv(key,value)

::

1.4.14 _{p}F_{q} に関するコホモロジー

128. pfp omega(p)

: It returns the Gauss-Manin connection Omega for the generalized hypergeometric function pF_{p−1}(aa_{1}, aa_{2}, …; cc_{1}, cc_{2}, …; x)

129. pfpcoh intersection(p)

:: returns an intersection matrix for cocycles associated to the generalized hypergeometric function pF_{p−1}.

130. pfphom intersection(p)

:: intersection matrix of homology cycles

131. pfphom monodromy pair kyushu(p)

:: It returns the pair of monodromy matrices

1.4.15 PHC 函数

132. phc.start ()

:: Localhost で ox sm1 phc() を起動する.

133. phc.phc(s|proc=p)

:: PHC pack に代数方程式系 s の解をすべてもとめてくれるように頼む

1.4.16 Plucker 関係式

134. plucker y(L)

:: Index 集合 L に対応する変数を戻す

135. plucker index(V)

:: It gets the index of the variable V

1.4.17 SM1 函数

136. sm1.start()

:: localhost で ox sm1 forAsir をスタートする

137. sm1.sm1(p,s)

:: サーバ sm1 にコマンド列 s を実行してくれるようにたのむ

138. sm1.push int0(p,f)

:: オブジェクト f を識別子 p のサーバへ送る

139. sm1.gb([f,v,w]|proc=p,sorted=q,dehomogenize=r)

:: v 上の微分作用素環において f のグレブナ基底を計算する

140. sm1.gb d([f,v,w]|proc=p)

:: v 上の微分作用素環において f のグレブナ基底を計算する. 結果を分散多項式のリストで戻す.

141. sm1.deRham([f,v]|proc=p)

:: 空間 ℂ^{n} − (the zero set of f = 0) で前命題のドラームコホモロジ群の次元を計算してくれるようにサーバに頼む.

142. sm1.hilbert([f,v]|proc=p)

:: 多項式の集合 f のヒルベルト多項式を計算する.

143. sm1.genericAnn([f,v]|proc=p)

:: f^{s} のみたす微分方程式全体をもとめる. v は変数のリストである. ここで, s は v[0] であり, f は変数 rest(v) 上の多項式である.

144. sm1.wTensor0([f,g,v,w]|proc=p)

:: f と g の D-module としての 0 次テンソル積を計算する

145. sm1.reduction([f,g,v,w]|proc=p)

:: ワイル代数における多項式集合 f の g による割り算

146. sm1.xml tree to prefix string(s|proc=p)

:: XML で書かれた OpenMath の木表現 s を前置記法になおす

147. sm1.syz([f,v,w]|proc=p)

:: v 上の微分作用素環において f の syzygy を計算する

148. sm1.mul(f,g,v|proc=p)

:: sm1 サーバに f かける g を v 上の微分作用素環でやってくれるように頼む.

149. sm1.distraction([f,v,x,d,s]|proc=p)

:: sm1 に ff の distraction を計算してもらう

150. sm1.gkz([A,B]|proc=p)

:: 行列 A とパラメータ B に付随した GKZ 系 (A-hypergeometric system) をもどす

151. sm1.appell1(a|proc=p)

:: F_{1} または F_{D} に対応する方程式系を戻す

152. sm1.appell4(a|proc=p)

:: F_{4} または F_{C} に対応する方程式系を戻す

153. sm1.rank(a|proc=p)

:: 微分方程式系 a の holonomic rank を戻す

154. sm1.auto reduce(s|proc=p)

:: フラグ ”AutoReduce” を s に設定

155. sm1.slope(ii,v,f_{filtration},v_{filtration}|proc=p) :: 微分方程式系 ii の slope を戻す

156. sm1.ahg(A)

:: It idential with sm1.gkz(A)

157. sm1.bfunction(F)

:: It computes the global b-function of F

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]

160. sm1.ecartd gb(A)

:: It returns a standard basis of A by using a tangent cone algorithm

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}

163. sm1.ecartd reduction(F,A)

: It returns a reduced form of F in terms of A by using a tangent cone algorithm.

164. sm1.ecartd reduction noh(F,A)

:: It returns a reduced form of F in terms of A by using a tangent cone algorithm

165. sm1.ecartd syz(A)

:: It returns a syzygy of A by using a tangent cone algorithm.

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 algorithm

168. sm1.gb reduction noh(F,A)

:: It returns a reduced form of F in terms of A by using a normal form algorithm

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

170. sm1.isSameIdeal in Dalg(I,J,V)

:: It compares two ideals I and J in D_{alg} (algebraic D with variables V, no homogenization)

171. sm1.restriction(I,V,R|degree=key_{0})

:: It computes the restriction of I as a D-module to the set defined by R.

172. sm1.saturation(T)

:: T =[I,J,V]. It returns saturation of I with respect to J^{∞}. V is a list of variables.

1.4.18 TIGERS 函数

173. tigers.tigers(a|proc=a)

:: この函数は識別子 p の tigers サーバに行列 a に付随したトーリックイデアルのすべてのグレブナ基底を計算してくれるようにたのむ

    1.4.19 Mathematica 函数
174. mathematica.start()

:: Localhost で ox math を起動する

175. mathematica.tree to string(t)

:: ox_math の戻す Mathematica の木構造データ t を asir 形式になおす

176. mathematica.rtomstr(t)

:: t をなるべく Mathematica の理解可能な文字列に変える

1.4.20 便利な関数

177. util timing(Q)

:: Show the timing data to execute Q.

178. util load file as a string(F)

:: It reads a file F as a string.

179. util read file as a string(F)

:: It reads a file F as a string.

180. util write string to a file(Fname,S)

:: It writes a string S to a file Fname.

181. util filter(Command,Input|env=key_{0})

:: It executes the filter program Command with the Input and returns the output of the filter

182. util find and replace(W,S,Wnew)

:: It replaces W in S by Wnew

183. util find substr(W,S)

:: It returns the position of W in S.

184. 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.

186. util index(V)

:: It returns the name part and the index part of V.

187. util v(V,L)

:: It returns a variable indexed by L.

188. util file exists(Fname)

:: It returns 1 when Fname exists.

189. util find start( |browser=key_{0})

:: It tries to find the gnome-open command or an installed browser in unix systems. It returns ”open” on MacOS X and returns ”start” on Windows.

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].

1.4.21 その他

191. todo parametrize(p)

:: 有理曲線のパラメータ表示をみつける

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 の各部分はすべてこれにより必要なメモリを得ている.

• Asir

Asir は, Risa の計算エンジンの言語インタフェースである. Risa では, 比較的容易にユーザ用の言語インタフェースを作ることができる. Asir はその一つの例として作ったもので, C 言語に近い文法をもつ. また, C のデバッガとして広く用いられている dbx 風のデバッガも備えている.

2.2 Asir の特徴

Asir は, 前述の通り, 計算エンジンの言語インタフェースである. 通常 Asir という名前の実行可能ファイルとして提供される. 現在サポートされている機能は概ね次の通りである.

• C 言語風のユーザ言語

• 数, 多項式, 有理式の加減乗 (除)

• ベクトル, 行列の演算

• 最小限のリスト処理

• 組み込み函数 (因数分解, GCD, グレブナ基底など)

• ユーザ定義函数によるツール (代数体上の因数分解など)

• dbx 風のデバッガ

• 陰函数の描画

• PARI (see section pari()) による初等超越函数を含む式の評価

• UNIX 上での分散計算機能 (OpenXM)

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 file 標準入力の代わりに, file から入力を読み込んで実行する. エラーの際にはただちに終了する. -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]

なるプロンプトが表示され, セッションが開始する. `$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 Asir を終了する. (確認あり) t トップレベルに戻る. (確認あり) c 実行を継続する. d デバッグモードに入る. デバッガに関しては See section デバッガ.

u  register_handler() (see section ox_reset, ox_intr, register_handler) で登録された関数を実

行後トップレベルに戻る. (確認あり) w 中断点までの函数の呼び出し列を表示する. ? 各選択肢の意味を説明する

2.7 エラー処理

組み込み函数に不正な型の引数を渡した場合などには実行が中断されるが, ユーザ函数の中でエラーが起きた場合にはトップレベルに戻る前に自動的にデバッグモードに入る. この状態でエラーの場所, 直前の引数の値などを調べることができる. 表示されるエラーメッセージはさまざまであり, 内部の函数名に引き続いてメッセージが表示される. これは, 呼び出された組み込み函数と必ずしも対応はしない.

その他, さまざまな原因により内部演算函数においてエラーが生ずることがある. UNIX 版の場合, これは次のいずれかの internal error として報告され, 通常のエラーと同様に扱って, デバッグモードに入る.

SEGV BUS ERROR 組み込み函数によっては, 引数の型を厳密にチェックせずに演算ルーチンに引き渡してしまう

ものも存在している. このような状況において, 不正なポインタ, あるいは NULL ポインタによるアクセス違反があった場合, これらのエラーとなる.

BROKEN PIPE プロセス間通信において, 相手先のプロセスとの間のストリームが既に存在していない場合 (例えば既に相手先のプロセスが終了している場合など) に, そのストリームに入出力しようとした場合にこのエラーとなる. これらは実際には, 組み込み函数の入口において, 引数を完全にチェックすることにより大部分は防げるが, 手間が多くかかることと, 場合によっては効率を落すことにもなるため, あえて引数チェックはユーザ任せにしてある.

2.8 計算結果，特殊な数

@ はエスケープ文字として使用される. 現在次のような規定がある.

@n n 番目の計算結果. @@ 直前の計算結果. @i 虚数単位. @pi 円周率. @e 自然対数の底. @ 2 元体 GF(2) 上の一変数多項式の変数 (不定元) @>, @<, @>=, @<=, @==, @&&, @|| quantifier 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)

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

2.9 型

2.9.1 Asir で使用可能な型

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

0 0 実際には 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 ] ]

 [ [ 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";
 afotake
8 構造体 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 first order formula

quantifier elimination で用いられる一階述語論理式. 15 matrix over GF (p)

小標数有限体上の行列. 16 byte array

符号なし byte の配列 −1 VOID オブジェクト

型識別子 −1 をもつオブジェクトは関数の戻り値などが無効であることを示す.

2.9.2 数の型

0 有理数

有理数は, 任意多倍長整数 (bignum) により実現されている. 有理数は常に既約分数で表現される. 1 倍精度浮動小数

マシンの提供する倍精度浮動小数である. Asir の起動時には, 通常の形式で入力された浮動小数はこの型に変換される. ただし, ctrl() により bigfloat が選択されている場合には bigfloat に変換される.

 [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 bigfloat

bigfloat は, Asir では PARI ライブラリにより実現されている. PARI においては, bigfloat は, 仮数部のみ任意多倍長で, 指数部は 1 ワード以内の整数に限られている. ctrl() で bigfloat を選択することにより, 以後の浮動小数の入力は bigfloat として扱われる. 精度はデフォルトでは 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 複素数複素数は, 有理数, 倍精度浮動小数, bigfloat を実部, 虚部として a+b*@i (@i は虚数単位) として与えられる数である. 実部, 虚部はそれぞれ real(), imag() で取り出せる.

5 小標数の有限素体の元ここで言う小標数とは, 標数が 2^{27} 未満のもののことである. このような有限体は, 現在のところグレブナ基底計算において内部的に用いられ, 有限体係数の分散表現多項式の係数を取り出すことで得られる. それ自身は属する有限体に関する情報は持たず, setmode() で設定されている素数 p を用いて GF (p) 上での演算が適用される.

6 大標数の有限素体の元標数として任意の素数がとれる. この型の数は, 整数に対し simp ff を適用することにより得られる.

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 位数 p^{n} の有限体の元位数が p^{n} (p は任意の素数, n は正整数) は, 標数 p および GF (p) 上既約な n 次多項式 m(x) を setmod ff により指定することにより設定する. この体の元は m(x) を法とする GF (p) 上の多項式として表現される.

9 位数 p^{n} の有限体の元 (小位数) 位数が p^{n} の有限体 (p^{n} が 2^{29} 以下, p が 2^{14} 以上なら n は 1) は, 標数 p および拡大次数 n を setmod ff() により指定することにより設定する. この体の 0 でない元は, p が 2^{14} 未満の場合, GF (p^{n}) の乗法群の生成元を固定することにより, この元のべきとして表される. これにより, この体の 0 でない元は, このべき指数として表現される. p が 2^{14} 以上の場合は通常の剰余による表現となるが, 共通のプログラムで双方の場合を扱えるようにこのような仕様となっている.

10 位数 p^{n} の小位数有限体の代数拡大の元前項の, 位数が p^{n} の小位数有限体の m 次拡大の元である. 標数 p および拡大次数 n, m を setmod ff() により指定することにより設定する. 基礎体上の m 次既約多項式が自動生成され, その代数拡大の生成元の定義多項式として用いられる. 生成元は @s である.

11 分散表現の代数的数 See section 代数的数に関する演算. 小標数有限素体以外の有限体は setmod ff() で設定する. 有限体の元どうしの演算では, 一方が有理数の場合には, その有理数は自動的に現在設定されている有限体の元に変換され, 演算が行われる.

2.9.3 不定元の型

多項式の変数となり得る対象を不定元とよぶ. Asir では, 英小文字で始まり, 任意個のアルファベット, 数字, ` ' からなる文字列を不定元として扱うが, その他にもシステムにより不定元として扱われるものがいくつかある. Asir の内部形式としては, これらは全て多項式としての型を持つが, 数と同様, 不定元の型により区別される.

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

[0] [vtype(a),vtype(aA_12)];
[0,0]

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

 [1] U=uc();
_0

 [2] vtype(U);
 1

2 函数形式組み込み函数, ユーザ函数の呼び出しは, 評価されて何らかの 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);
3

2.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 種類に単純化されている. トップレベル, すなわちプロンプトに対して入力された変数は全て大域変数として登録される. また函数内では次のいずれかとなる. 函数が定義されるファイルにおいて, その函数定義以前に, ある変数が 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

2.10.2 ユーザ定義函数

ユーザによる函数の定義は `def' 文で行う. 文法エラーは読み込み時にある程度チェックされ, おおよその場所が表示される. 既に (引数の個数に関係なく) 同名の函数が定義されている場合には, その函数は再定義される. ctrl() 函数により verbose フラグが on になっている場合,

afo() redefined.

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

 def  f(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 言語によるプログラムの書き方を解説する.

2.10.3 変数および不定元既に述べた通り, Asir においてはプログラム変数と不定元を明確に区別している.

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

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

不定元小文字で始まり, アルファベット, 数字, `_' からなる文字列, またはシングルクオートで囲まれた文字列, もしくは函数形式. 不定元とは, 多項式環を構成する際に添加される変数をいう. 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.
  */

 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 つの形式がある. いずれも函数から抜けるための文である. 前者は函数の値として式を返す. 後者では, 函数の値として何が返されるかはわからない.

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 文を用いるときは $ または ; で終了する必要がある. これらがないと次の文がよみとばされる.

2.10.9 ループループを構成する文は, while 文, for 文, do 文の 3 種類がある.

   • while 文

形式は,

      while ( 式 ) 文

で, これは, 式を評価して, その値が 0 でない限り文を実行するという意味となる. たとえば式が 1 ならば, 単純な無限ループとなる.

   • for 文

形式は,

      for ( 式並び-1; 式; 式並び-2 ) 文

で, これは式並び −1 (を単文並びにしたもの)

 while ( 式 ) {

文

式並び$-2$ (を単文並びにしたもの)

 }

と等価である.

• do 文
 do {

文

 } while ( 式 )

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

• break

break 文は, それを囲むループを一つだけ抜ける.

• return

return 文は, 一般に函数から抜けるための文であり, ループの中からでも有効である.

• continue

continue 文は, ループの本体の文の末端に制御を移す. 例えば for 文では, 最後の式並びの実行を行い, while 文では条件式の判定に移る.

2.10.10 構造体定義

構造体とは, 各成分の要素が名前でアクセスできる固定長配列と思ってよい. 各構造体は名前で区別される. 構造体は, struct 文により宣言される. 構造体が宣言されるとき, asir は内部で構造体のそれぞれの型に固有の識別番号をつける. この番号は, 組み込み関数 str type() により取得できる. ある型の構造体は, 組み込み関数 newstruct() により生成される. 構造体の各メンバは, 演算子 -> によりアクセスする. メンバが構造体の場合, -> による指定は入れ子にできる.

[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 を表す. 整数除算, 多項式除算 (剰余を含む演算) には別途組み込み函数が用意されている.

 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+1
 A-- 値は元の A の値, A = A-1
 ++A  A = A+1, 値は変化後の値
 --A  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

#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 $ と書かないといけない.

2.10.13 オプション指定ユーザ定義関数が N 変数で宣言された場合, その関数は, N 変数での呼び出しのみが許される.

[0] def factor(A) { return fctr(A); }
[1] factor(x^5-1,3);
evalf : argument mismatch in factor()
return to toplevel

不定個引数の関数をユーザ言語で記述したい場合, リスト, 配列を用いることで可能となるが, 次のようなより分かりやすい方法も可能である.

% 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]]

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 を呼んでいる.

 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;
 }

 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() が呼び出された場合

2.12.2 コマンドの解説

コマンドは dbx のコマンドの内必要最小限のものを採用した. 更に, gdb のコマンドからもいくつか便利なものを採用した. 実際の機能は dbx とほぼ同様であるが, step, next は, 次の行ではなく次の文を実行する. 従って, 1 行に複数の文がある場合は, その文の数だけ next を実行しなければ次の行に進めない. また, dbx と同様 `.dbxinit' を読み込むので, dbx と同じ alias を使うことができる.

step

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

次の文を実行する. finish

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

cont quit

デバッグモードから抜け, 実行を継続する. up [n] スタックフレームを 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() により調べている.

     (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;
4       else
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 の消去

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

2.12.4 デバッガの初期化ファイルの例

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

% cat ~/.dbxinit
alias n next
alias c cont
alias 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 文法の詳細

<式>:
   `('<式>`)'

<式> <二項演算子> <式>

   `+' <式>
   `-' <式>

<左辺値>

<左辺値> <代入演算子> <式>

   <左辺値> `++'
   <左辺値> `--'
   `++' <左辺値>
   `--' <左辺値>
   `!' <式>
   <式> `?' <式> `:' <式>
   <函数> `(' <式並び> `)'
   <函数> `(' <式並び> `|' <オプション並び> `)'

<文字列>

<指数ベクトル>

<アトム> <リスト>

(See section さまざまな式.)

<左辺値>:
    <変数> [`['<式>`]']*

<二項演算子>:

    `+' `-' `*' `/' `%' `^'(冪)
    `==' `!=' `<' `>' `<=' `>=' `&&' `||'

<代入演算子>:

    `=' `+=' `-=' `*=' `/=' `%=' `^='
<式並び>:
    <空>
    <式> [`,' <式>]*

<オプション>:

    alphabet で始まる文字列 `=' <式>

<オプション並び>:

<オプション>

    <オプション> [`,' <オプション>]*
<リスト>:
    `[' <式並び> `]'
<変数>:

大文字で始まる文字列 (X,Y,Japan など)

(See section 変数と不定元.)

<函数>:

小文字で始まる文字列 (fctr,gcd など)

<アトム>:

<不定元>

   <数>
<不定元>:
   小文字で始まる文字列 (a,bCD,c1_2 など)

(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 文.)

<終端>:
   `;' `$'

<変数宣言>:

   [`extern' <変数> [`,' <変数>]* <終端>]*
<複文>:
   `{' <文並び> `}'
<文並び>:
   [<文>]*

2.13 有限体における演算

2.13.1 有限体の表現および演算

Asir においては, 有限体は, 正標数素体 GF (p), 標数 2 の有限体 GF (2^{n}), GF (p) の n 次拡大 GF (p^{n}) が定義できる. これらは全て, 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 (2^{n}) をそれぞれ基礎体としてセットする. また, 有限素体の有限次拡大も定義できる. 詳しくは数の型を参照. setmod ff() においては引数の既約チェックは行わず, 呼び出し側が責任を持つ.

基礎体とは, あくまで有限体の元として宣言あるいは定義されたオブジェクトが, セットされた基礎体の演算に従うという意味である. 即ち, 有理数どうしの演算の結果は有理数となる. 但し, 四則演算において一方のオペランドが有限体の元の場合には, 他の元も自動的に同じ有限体の元と見なされ, 演算結果も同様になる.

0 でない有限体の元は, 数オブジェクトであり, 識別子の値は 1 である. さらに, 0 でない有限体の元の数識別子は, GF (p) の場合 6, GF (2^{n}) の場合 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 (2^{n}) の場合いくつかの方法がある.

 [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 (2^{n}) の, GF (2) 上の生成元である. 詳しくは数の型を参照.

2.13.2 有限体上での 1 変数多項式環の演算

fff では, 有限体上の 1 変数多項式に対し, 無平方分解, DDF, 因数分解, 多項式の既約判定などの関数が定義されている.

いずれも, 結果は [因子, 重複度] のリストとなるが, 因子は monic となり, 入力多項式の主係数は捨てられる. 無平方分解は, 多項式とその微分との GCD の計算から始まるもっとも一般的なアルゴリズムを採用している.

有限体上での因数分解は, DDF の後, 次数別因子の分解の際に, Berlekamp アルゴリズムで零空間を求め, 基底ベクトルの最小多項式を求め, その根を Cantor-Zassenhaus アルゴリズムにより求める, という方法を実装している.

2.13.3 小標数有限体上での多項式環の演算

小標数有限体係数の多項式に限り, 多変数多項式の因数分解が組み込み関数として実装されている. 関数は sffctr() である. また, modfctr() も, 有限素体上で多変数多項式の因数分解を行うが, 実際には, 内部で十分大きな拡大体を設定し, sffctr() を呼び出して, 最終的に素体上の因子を構成する, という方法で計算している.

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

楕円曲線の指定は, 長さ 2 のベクトル [a b] で行う. a, b は有限体の元で, setmod ff() で定義されている有限体が素体の場合, y^{2} = x^{3} + ax + b, 標数 2 の体の場合 y^{2} + xy = x^{3} + ax^{2} + b を表す.

楕円曲線上の点は, 無限遠点も込めて加法群をなす. この演算に関して, 加算 (ecm add ff()), 減算 (ecm sub ff()) および逆元計算のための関数 (ecm chsgn ff()) が提供されている. 注意すべきは, 演算の対象となる点の表現が,

無限遠点は 0. それ以外の点は, 長さ 3 のベクトル [x y z]. ただし, z は 0 でない. という点である. [x y z] は斉次座標による表現であり, アフィン座標では [x/z y/z] なる点を表す. よって, アフィン座標 [x y] で表現された点を演算対象とするには， [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 は x^{2} + 1 = 0 の根, A1 は, その A0 を係数に含む x^{3} + 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() を呼べば, 新しい代数的数は定義されずに既に定義されたものが得られる.

 [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]

2.14.2 分散多項式による代数的数の表現

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

 [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) (a^{2} + 1 = 0, b^{3} + ab + b = 0) において, (a + b)^{5} および 1/(a + b) を計算 (簡単化) している．分子である分散多項式の表示は, 分散多項式の表示をそのまま流用している． 2.14.3 代数的数の演算

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

 [0] load("gr")$
 [1] load("sp")$

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

 [49] T=A0^2+1;
 (#0^2+1)
 [50] simpalg(T);
 0

simpalg() は有理式の形をした代数的数を, 多項式の形に簡単化する.

 [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);

[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)$

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

2.15 グレブナー基底の計算

2.15.1 分散表現多項式

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

項 (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 coefficient)

分散表現多項式における各単項式は, 項順序により整列される. この時順序最大の単項式を頭単項式, それに現れる項, 係数をそれぞれ頭項, 頭係数と呼ぶ.

2.15.2 ファイルの読み込み

  グレブナ基底を計算するための基本的な函数は dp gr main() および dp gr mod main(), dp gr f main()

なる 3 つの組み込み函数であるが, 通常は, パラメタ設定などを行ったのちこれらを呼び出すユーザ函数を用いるのが便利である. これらのユーザ函数は, ファイル gr を load() により読み込むことにより使用可能となる. gr は, Asir の標準ライブラリディレクトリに置かれている.

[0] load("gr")$

2.15.3 基本的な関数

gr では数多くの函数が定義されているが, 直接グレブナ基底を計算するためのトップレベルは次の 3 つである. 以下で, plist は多項式のリスト, vlist は変数 (不定元) のリスト, order は変数順序型, p は 2^{27} 未満の素数である. 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) 係数グレブナ基底計算函数.

2.15.4 計算および表示の制御

グレブナ基底の計算において, さまざまなパラメタ設定を行うことにより計算, 表示を制御することができる. これらは, 組み込み函数 dp gr flags() により設定参照することができる. 無引数で dp gr flags() を実行すると, 現在設定されているパラメタが, 名前と値のリストで返される.

 [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 (off) である.

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 が off の場合, グレブナ基底計算の途中の情報を短縮形で表示する. Stat on で Print が off ならば, Print が on のとき表示されるデータの内, 集計データのみが表示される. ShowMag on で Print が on ならば, 生成が生成される毎に, その多項式の係数のビット長の和を表示し, 最

後に, それらの和の最大値を表示する. Content Multiple 0 でない有理数の時, 有理数上の正規形計算において, 係数のビット長の和が Content 倍になるご

とに係数全体の GCD が計算され, その GCD で割った多項式を簡約する. Content が 1 ならば, 簡約するごとに GCD 計算が行われ一般には効率が悪くなるが, Content を 2 程度とすると, 巨大な整数が係数に現れる場合, 効率が良くなる場合がある. backward compatibility のため、 Multiple で整数値を指定できる.

Demand 正当なディレクトリ名 (文字列) を値に持つとき, 生成された多項式はメモリ中におかれず, そのディレクトリ中にバイナリデータとして置かれ, その多項式を用いる normal form 計算の際, 自動的にメモリ中にロードされる. 各多項式は, 内部でのインデックスをファイル名に持つファイルに格納される. ここで指定されたディレクトリに書かれたファイルは自動的には消去されないため, ユーザが責

任を持って消去する必要がある. 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 有理数係数多項式の係数に対する剰余演算の計算時間 MP S-多項式を生成するペアの選択にかかった時間 RA interreduce 計算時間 MC trace-lifting における, 入力多項式のメンバシップ計算時間 GC 結果のグレブナ基底候補のグレブナ基底チェック時間 T 生成されたペアの数 B, M, F, D 各 criterion により除かれたペアの数 ZR 0 に reduce されたペアの数 NZR 0 でない多項式に reduce されたペアの数 Max mag 生成された多項式の, 係数のビット長の和の最大値

2.15.5 項順序の設定

項は内部では, 各変数に関する指数を成分とする整数ベクトルとして表現される. 多項式を分散表現多項式に変換する際, 各変数がどの成分に対応するかを指定するのが, 変数リストである. さらに, それら整数ベクトルの全順序を指定するのが項順序の型である. 項順序型は, 数, 数のリストあるいは行列で表現される. 基本的な項順序型として次の 3 つがある.

0 (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 に対し Mv = 0 と v = 0 は同値.

2. 非負成分を持つ長さ m の 0 でない整数ベクトル v に対し, Mv の 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,

(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 と見なされる. また, ブロック順序は, 各ブロックの変数に対応する成分のみ 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] におけるグレブナ基底を求めることになる. 注意すべきことは, 係数が体として扱われていることである. すなわち, 係数の間に多項式としての共通因子があった場合には, 結果からその因子は除かれているため, 有理数体上の多項式環上の問題として考えた場合の結果とは一般には異なる. また, 主として計算効率上の問題のため, 分散表現多項式の係数として実際に許されるのは多項式までであるすなわち, 分母を持つ有理式は分散表現多項式の係数としては許されない.

2.15.8 基底変換

辞書式順序のグレブナ基底を求める場合, 直接 gr() などを起動するより, 一旦他の順序 (例えば全次数逆辞書式順序) のグレブナ基底を計算して, それを入力として辞書式順序のグレブナ基底を計算する方が効率がよい場合がある. また, 入力が何らかの順序でのグレブナ基底になっている場合, 基底変換と呼ばれる方法により, Buchberger アルゴリズムによらずに効率良く辞書式順序のグレブナ基底が計算できる場合がある. このような目的のための函数が, ユーザ定義函数として gr にいくつか定義されている. 以下の 2 つの函数は, 変数順序 vlist1, 項順序型 order で既にグレブナ基底となっている多項式リスト gbase を, 変数順序 vlist2 における辞書式順序のグレブナ基底に変換する函数である.

tolex(gbase,vlist1,order,vlist2)

この函数は, gbase が有理数体上のシステムの場合にのみ使用可能である. この函数は, 辞書式順序のグレブナ基底を, 有限体上で計算されたグレブナ基底を雛型として, 未定係数法および Hensel 構成により求めるものである.

tolex tl(gbase,vlist1, order,vlist2,homo)

この函数は, 辞書式順序のグレブナ基底を Buchberger アルゴリズムにより求めるものであるが, 入力がある順序におけるグレブナ基底である場合の 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 のスタックに積まれ, コマンドが送られた時に, 必要なだけスタックからデータを取り出して, 関数呼び出しの引数とする. 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 オブジェクトをスタックから取り出し, 通信路に流す.

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 なにもしない.

2.16.4 デバッグ

デバッグ分散計算においては, 一般にデバッグが困難となる. ox_asir においては, デバッグのためのいくつかの機能を提供している.

2.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])

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

2.17.1 はじめに

数式処理システム 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' を見て下さい.

それでは, あなたの計算機上で数学をお楽しみ下さい.

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, diff, ...)

• 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 のトップレベルのファイルである. このファイルよりその他のファイルが読み込まれている. 一部のパッケージは `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.*

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 の中の函数が使

用できるようになる． • デフォルトではモジュール化して読み込まれるので，函数名の先頭に 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") などとすれば，そのディレ

クトリが分かる．

と書き換えると，モジュール化されずに読み込まれるので，函数の先頭に 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 の設定は不要です．

3 Functions

3.1 Functions related to differential operators

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

3.1.1 Fundamental functions

1. muldo(p_{1},p_{2},[x,∂_{x}]|lim=n) または muldo(p_{1},p_{2},x|lim=n)
muldo(p_{1},p_{2},[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .]|lim=n) または muldo(p_{1},p_{2},[[x_{1}],x_{2},. . .]|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] は常微分作用素と解釈される．

以下の函数で微分作用素とある場合は，同様な省略が可能である．

• p_{2} はベクトルまたは行列でもよい．このときは p_{1} は行列でもよい．

• x や x_{i} が 0 のときは，単なる積を返す．

• exp(∂) などの無限階微分作用素や ∂^{−1} などの擬微分作用素も計算可能（ただし， appldo() などでは不可，また計算が有限回で終わらないこともあり，そのときは途中で打ち切る）．

• Leibniz 公式での積の計算で，各変数の微分の回数が 100 回以上になるとそこで打ち切るのがデフォルトであるが lim=n のオプションで変更可能（これは p_{1}, p_{2} がスカラーのときのみ有効）．

   たとえば， muldo(dx^(-1),1/x,x) や muldo(exp(dx),1/x,x) は有限回で計算が終わらない．

[dx, x] = 1, [dy, y] = 1 という交換関係のとき（⇐ dx = \frac{∂}{∂x}, dy = \frac{∂}{∂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!

(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] は

((1 + x)\frac{d}{dx} + 1) ∘ ((1 − x)\frac{d}{dx} + 1) = (1 − x^{2})\frac{d^{2}}{dx^{2}} + (1 − x)\frac{d}{dx} + 1

を意味する．なお， [6], [8], [9], [10], [11] の結果は，微分と函数とが可換と考えて割り算をして並べ直したものが通常の表記での結果となる．すなわち

[6] は

e^{\frac{d}{dx}} ∘ \frac{1}{(x−1)^{4}} = x^{4}e^{\frac{d}{dx}} = x^{4}(1 + \frac{d}{dx} + \frac{1}{2} \frac{d^{2}}{dx^{2}} + \frac{1}{3!} \frac{d^{3}}{dx^{3}} + ⋯)

[8] は

x(\frac{d}{dx})^{−1} ∘ \frac{1}{x} \frac{d}{dx} = 1 + \frac{1}{x}(\frac{d}{dx})^{−1} + \frac{2}{x^{2}} (\frac{d}{dx})^{−2} + ⋯

[10] は

xe^{\frac{d}{dx}} ∘ \frac{1}{x} = (1 − \frac{1}{x} + \frac{1}{x^{2}} − \frac{1}{x^{3}} + \frac{1}{x^{4}} − \frac{1}{x^{5}} )(1 + \frac{d}{dx} + \frac{1}{2!} \frac{d^{2}}{dx^{2}} + \frac{1}{3!} \frac{d^{3}}{dx^{3}} + ⋯)

と解釈する． [11] は，実際は

e^{\frac{d}{dx}} ∘ e^{x} = e^{x+1}e^{\frac{d}{dx}}

である.

2. caldo([p_{1},p_{2},. . .],[x,∂_{x}]|mono=f) or caldo([p_{1},p_{2},. . .],[[x_{1},∂_{x_{1}}],. . .]|mono=f)

:: 微分作用素の積の和を計算する p_{1} + p_{2} + ⋯ を返す. p_{j} は微分作用素でなくてリスト [p_{j,1}, …] でもよい. その場合は

• p_{j} = p_{j,1}p_{j,2} ⋯ という微分作用素の積を表す.

• p_{j,ν} が， [q_{j,ν}, m_{j,ν}] となっていた場合は p_{j,ν} = q_{j,ν}^{m_{j,ν}} とする. m_{j,ν} は非負整数でなければならない.

• p_{j,ν} が， [q_{j,ν},[m_{j,ν,1}, …]] となっていた場合は, p_{j,ν} = (q_{j,ν} + s_{j,ν,1})(q_{j,ν} + s_{j,ν,2}) ⋯ とする.

• momo=1 : [p_{1}] を計算するときは， momo=1 を指定して引数を p_{1} としてもよい．

• momo=2 : p_{1,1} を計算するときは， momo=2 を指定して引数を p_{1,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(p_{1},p_{2},[x,∂_{x}]) or muledo(p_{1},p_{2},x)

:: Euler 型常微分作用素の積 (⇐ [∂_{x}, x] = x) p_{2} は行列またはベクトルでもよい．このとき， p_{1} は行列でもよい． [dx, x] = x という交換関係のとき（⇐ dx = x\frac{d}{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,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .],[[y_{1},∂_{y_{1}}],[y_{2},∂_{y_{2}}],. . .]|ex=1,inv=f)

:: 微分作用素の変換（x_{i} ↦ y_{i} = y_{i}(x), ∂_{x_{j}} ↦ ∂_{y_{j}} = c_{j}(x) + ∑_{ν} a_{jν}(x)∂_{x_{ν}} ） • y_{i}, ∂_{y_{j}} は (x_{1}, …, x_{n}) の有理式および有理式係数の微分作用素

• [x_{i}, ∂_{x_{i}}] の方は x_{i} の形の省略形も可（⇐ ∂_{x_{i}} = dx_{i}）

• 引数のリストの 2 番目が 3 番目より長い場合，残りは恒等変換とみなす．

• p は微分作用素のリスト，ベクトル，行列でもよい．

• 双有理変換のときは，第 2 引数は第 1 引数と同じ長さにとって， [y_{1},y_{2}, …] とのみ指定すればよ

い． ∂_{y_{1}}, ∂_{y_{2}}, … は自動計算される．このとき – inv=1 : 逆変換を表す

    – inv=2 : [∂_{y_{1}},∂_{y_{2}},...] を返す．

– inv=3 : 逆変換の [∂_{y_{1}},∂_{y_{2}},...] を返す．

• 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] などでは， [[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],…] について省略形を用いている（cf. muldo()）． • [0] や [1] では， x ↦ \frac{1}{x} や (x, y) ↦ (x + y, x − y) という座標変換による微分作用素の変換を求

めている．このとき，対応する変換\frac{d}{dx} ↦ −\frac{1}{x^{2}} \frac{d}{dx} や (\frac{∂}{∂x}, \frac{∂}{∂y}) ↦ (\frac{1}{2} \frac{∂}{∂x} + \frac{1}{2} \frac{∂}{∂y} , \frac{1}{2} \frac{∂}{∂x} − \frac{1}{2} \frac{∂}{∂y}) も指定しているが， [2] のように省略してよい．

• 座標変換ではないが (x, \frac{d}{dx}) ↦ (x, \frac{d}{dx} + c) のような微分作用素環の同型変換となるものでもよい． • ex=1 : (x_{i}, ∂_{x_{i}}) ↦ (S_{i}(x, ∂), T_{i}(x, ∂)) という微分作用素環の準同型写像による変換を計算する．

すなわち [T_{i}(x, ∂), S_{j}(x, ∂)] = δ_{i,j} であって， p は (x, ∂) について多項式である必要がある．

[5] は， (x, \frac{d}{dx}) ↦ (−\frac{d}{dx} + \frac{1}{x}, x) という変換を考えている．

5. translpdo(p,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .],mat)

:: 微分作用素の線形座標変換（x_{i} ↦ ∑_{j}(mat)_{ij}x_{j}） [x_{i},∂_{x_{i}}] は x_{i} の形の省略形も可（⇐ ∂_{x_{i}} = dx_{i}）．

[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([[x_{1},∂_{x_{1}}],. . .,[x_{n},∂_{x_{n}}]],m)

:: ベキ函数による座標変換での変換公式

x_{i} ↦ ∏_{j=1}^{n} x_{j}^{m_{i,j}} (j = 1, …, n)

という座標変換による [[x_{1},∂_{x_{1}}],…,[x_{n},∂_{x_{n}}]] の変換結果を返す． 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,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .])

:: 微分作用素（の行列）の有理式，初等函数（の行列）， Pfaff 系への作用の計算 r はベクトルまたは行列でもよい．この場合は p は行列でもよい．

• Pfaff=1 : \frac{du}{dx} = r(x)u に対し p(x, \frac{d}{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);

u_{0} = ∂^{−μ}x^{λ_{1}}(1 − x)^{λ_{2}} （Gauss の超幾何） , u = (\begin{matrix}u_{0} \\ ∂u_{0} \end{matrix}), v = ∂^{−μ−1} (\begin{matrix}x^{λ_{1}−1}(1 − x)^{λ_{2}} \\ x^{λ_{1}}(1 − x)^{λ_{2}−1} \end{matrix}) に対し

u = Uv, v = V u となる有理関数の行列 U, V を上で求めた．

8. adj(p,[x,∂_{x}]) または adj(p,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .])

:: 微分作用素（の行列） p の formal adjoint

[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,,[[x_{1},∂_{x_{1}}],[x_{2},∂_{x_{2}}],. . .])

:: principal symbol of differential operator 微分作用素 p の主表象を返す（cf. ghg2()）．

10. sftpexp(p,[x,∂_{x}],q,r) or sftpexp(p,[[x_{1},∂_{x_{1}}],. . .],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(p_{1},p_{2},[x,∂_{x}]|rev=1)

:: 常微分作用素の割り算

• 戻り値 [q, r, m] ⇒ m ∗ p_{1} = q ∗ p_{2} + r (ord m = 0, ord r < ord p_{2})

• rev=1 と指定すると p_{1} ∗ m = p_{2} ∗ q + r (ord m = 0, ord r < ord p_{2})

[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(p_{1},p_{2},[x, ∂_{x}]|rev=1,dviout=n) or mygcd(p_{1},p_{2},[x]|rev=1,dviout=n)
mygcd(p_{1},p_{2},x|dviout=n), mygcd(p_{1},p_{2},0|dviout=n)

:: 有理函数係数の常微分作用素（または x の多項式，または正整数） p_{1} と p_{2} の GCD （最大公約元）

• 戻り値を R とおくと GCD は R[0] = R[1] ∗ p_{1} + R[2] ∗ p_{2} となる．

R[3] ∗ p_{1} + R[4] ∗ p_{2} = 0 が成立し，行列 (\begin{matrix}R[1] & R[2] \\ R[3] & R[4] \end{matrix}) は可逆．

また R[3] ∗ p_{1} = −R[4] ∗ p_{2} が LCM となる．

• rev=1 を指定すると，上で積の順序が全て逆になる.

• ユークリッドの互除法による計算であるが， p_{1} と p_{2} の大きさが同じ場合は p_{1} を p_{2} で割ることか

ら始める．

• 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)$

(\begin{matrix}234 \\ 111 \end{matrix}) = (\begin{matrix}2 & 1 \\ 1 & 0 \end{matrix}) (\begin{matrix}111 \\ 12 \end{matrix})

= (\begin{matrix}2 & 1 \\ 1 & 0 \end{matrix}) (\begin{matrix}9 & 1 \\ 1 & 0 \end{matrix}) (\begin{matrix}12 \\ 3 \end{matrix}) = (\begin{matrix}19 & 2 \\ 9 & 1 \end{matrix}) (\begin{matrix}12 \\ 3 \end{matrix})

= (\begin{matrix}19 & 2 \\ 9 & 1 \end{matrix}) (\begin{matrix}4 & 1 \\ 1 & 0 \end{matrix}) (\begin{matrix}3 \\ 0 \end{matrix}) = (\begin{matrix}78 & 19 \\ 37 & 9 \end{matrix}) (\begin{matrix}3 \\ 0 \end{matrix}) ,

(\begin{matrix}3 \\ 0 \end{matrix}) = (\begin{matrix}−9 & 19 \\ 37 & −78 \end{matrix}) (\begin{matrix}234 \\ 111 \end{matrix})

[9] os_md.mygcd(P,Q,[x,dx]|dviout=2)$

x^{2}∂^{2} + 3x∂ + 1 = (x)(x∂^{2} − (x − 2)∂ − 1) + (x(x + 1)∂ + (x + 1))
(x^{2} + 2x + 1)(x∂^{2} − (x − 2)∂ − 1) = ((x + 1)∂ − (x + 2))(x(x + 1)∂ + (x + 1))

[10] os_md.mygcd(P,Q,[x,dx]|dviout=2);

(\begin{matrix}x^{2}∂^{2} + 3x∂ + 1 \\ x∂^{2} − (x − 2)∂ − 1 \end{matrix}) = (\begin{matrix}x & 1 \\ 1 & 0 \end{matrix}) (\begin{matrix}x∂^{2} − (x − 2)∂ − 1 \\ x(x + 1)∂ + (x + 1) \end{matrix})

= (\begin{matrix}x & 1 \\ 1 & 0 \end{matrix}) (\begin{matrix}\frac{1}{x+1}∂ − \frac{x+2}{(x+1)^{2}} & 1 \\ 1 & 0 \end{matrix}) (\begin{matrix}x(x + 1)∂ + (x + 1) \\ 0 \end{matrix})

= (\begin{matrix}\frac{x}{x+1}∂ + \frac{1}{(x+1)^{2}} & x \\ \frac{1}{x+1}∂ − \frac{x+2}{(x+1)^{2}} & 1 \end{matrix}) (\begin{matrix}x(x + 1)∂ + (x + 1) \\ 0 \end{matrix})

= (\begin{matrix}x∂ + 1 & x \\ ∂ − 1 & 1 \end{matrix}) (\begin{matrix}x∂ + 1 \\ 0 \end{matrix}) ,

(\begin{matrix}x∂ + 1 \\ 0 \end{matrix}) = (\begin{matrix}\frac{1}{(x+1)^{2}} & −\frac{x}{(x+1)^{2}} \\ −\frac{1}{x+1}∂ + \frac{x+2}{(x+1)^{2}} & \frac{x}{x+1}∂ + \frac{x+2}{(x+1)^{2}} \end{matrix} ) (\begin{matrix}x^{2}∂^{2} + 3x∂ + 1 \\ x∂^{2} − (x − 2)∂ − 1 \end{matrix})

14. mylcm(p_{1},p_{2},[x, ∂_{x}]|rev=1) or mylcm(p_{1},p_{2},[x]|rev=1)
mylcm(p_{1},p_{2},x), mylcm(p_{1},p_{2},0)

:: 有理函数係数の常微分作用素（または x の多項式，または正整数） p_{1} と p_{2} の 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(p_{1},p_{2},[x,∂_{x}])

:: 常微分方程式 p_{1}u = 0 に対し q_{1}p_{2}u = 0 となる微分作用素 q_{1} と q_{2}p_{2}u = u となる微分作用素 q_{2} のリスト [q_{1}, q_{2}] を返す q_{1}, q_{2} は以下の以下の性質をもつ．

qp_{2}u = 0 ⇒ ∃r such that q = rq_{1}

qp_{2}u = u ⇒ ∃r such that q = q_{2} + rq_{1} 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 成分のリスト

を返す.

• 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 ]

[ 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);

(\begin{matrix}∂ & 0 & 1 & 0 \\ 0 & ∂ & 0 & 1 \\ 1 & 0 \\ 0 & 1 \end{matrix})

C1 += C2 × (x)

→ (\begin{matrix}∂ & 0 & 1 & 0 \\ x∂ + 1 & ∂ & 0 & 1 \\ 1 & 0 \\ x & 1 \end{matrix})

(\begin{matrix}−x & 1 \\ x∂ + 2 & −∂ \end{matrix}) (\begin{matrix}L1 \\ L2 \end{matrix})

→ (\begin{matrix}1 & ∂ & −x & 1 \\ 0 & −∂^{2} & x∂ + 2 & −∂ \\ 1 & 0 \\ x & 1 \end{matrix})

Cj −= C1 × ∘ (j > 1)

→ (\begin{matrix}1 & 0 & −x & 1 \\ 0 & −∂^{2} & x∂ + 2 & −∂ \\ 1 & −∂ \\ x & −x∂ + 1 \end{matrix})

L2 ← (−1) × L2

→ (\begin{matrix}1 & 0 & −x & 1 \\ 0 & ∂^{2} & −x∂ − 2 & ∂ \\ 1 & −∂ \\ x & −x∂ + 1 \end{matrix})

As a result,

(\begin{matrix}1 & 0 \\ 0 & ∂^{2} \end{matrix}) = (\begin{matrix}−x & 1 \\ −x∂ − 2 & ∂ \end{matrix}) (\begin{matrix}∂ & 0 \\ 0 & ∂ \end{matrix}) (\begin{matrix}1 & −∂ \\ x & −x∂ + 1 \end{matrix}) ,

(\begin{matrix}−x & 1 \\ −x∂ − 2 & ∂ \end{matrix})^{−1} = (\begin{matrix}∂ & −1 \\ x∂ + 1 & −x \end{matrix}) ,

(\begin{matrix}1 & −∂ \\ x & −x∂ + 1 \end{matrix})^{−1} = (\begin{matrix}−x∂ & ∂ \\ −x & 1 \end{matrix}) .

上の 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 x^{k} と (1, 1) 成分の作る左イデアルが (1, 1) 成分の作る左イデアルに入らない k を求める（k は (i, j) 成分の階数以下の非負整数となる）．なお x は微分との交換子が恒等写像となるかけ算作

用素． j 列目に x^{k} を右からかけたものを 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)） .

一方， TEX においては， i 行目を Li と表し, j 列目を Cj と表して，たとえば (\begin{matrix}1 & 2 \\ 3 & 4 \end{matrix}) を 3 行目と 5 行

目にかけるのは

(\begin{matrix}1 & 2 \\ 3 & 4 \end{matrix}) (\begin{matrix}L3 \\ L5 \end{matrix})

と表す.

[6] os_md.mdivisor(mat([3,5,7],[5,3,3]),0|dviout=2)

(\begin{matrix}3 & 5 & 7 & 1 & 0 \\ 5 & 3 & 3 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{matrix})

(\begin{matrix}2 & −1 \\ −5 & 3 \end{matrix}) (\begin{matrix}L1 \\ L2 \end{matrix})

→ (\begin{matrix}1 & 7 & 11 & 2 & −1 \\ 0 & −16 & −26 & −5 & 3 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{matrix})

Cj −= C1 × ∘ (j > 1)

→ (\begin{matrix}1 & 0 & 0 & 2 & −1 \\ 0 & −16 & −26 & −5 & 3 \\ 1 & −7 & −11 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{matrix})

(C2 C3) (\begin{matrix}−5 & −13 \\ 3 & 8 \end{matrix})

→ (\begin{matrix}1 & 0 & 0 & 2 & −1 \\ 0 & 2 & 0 & −5 & 3 \\ 1 & 2 & 3 \\ 0 & −5 & −13 \\ 0 & 3 & 8 \end{matrix})

As a result,

(\begin{matrix}1 & 0 & 0 \\ 0 & 2 & 0 \end{matrix}) = (\begin{matrix}2 & −1 \\ −5 & 3 \end{matrix}) (\begin{matrix}3 & 5 & 7 \\ 5 & 3 & 3 \end{matrix}) (\begin{matrix}1 & 2 & 3 \\ 0 & −5 & −13 \\ 0 & 3 & 8 \end{matrix}) ,

(\begin{matrix}2 & −1 \\ −5 & 3 \end{matrix})^{−1} = (\begin{matrix}3 & 1 \\ 5 & 2 \end{matrix}) ,

(\begin{matrix}1 & 2 & 3 \\ 0 & −5 & −13 \\ 0 & 3 & 8 \end{matrix})^{−1} = (\begin{matrix}1 & 7 & 11 \\ 0 & −8 & −13 \\ 0 & 3 & 5 \end{matrix}) .

[7] os_md.mdivisor(mat([dx,0,0],[0,dx,0],[0,0,dx]),[x,dx]|dviout=3)

(\begin{matrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & ∂^{3} \end{matrix}) = P (\begin{matrix}∂ & 0 & 0 \\ 0 & ∂ & 0 \\ 0 & 0 & ∂ \end{matrix}) Q,

P = (\begin{matrix}−x & 1 & 0 \\ −\frac{1}{2}x∂ − 1 & \frac{1}{2}∂ & −\frac{1}{2}x^{2}∂ − 2x \\ −x∂^{2} − 3∂ & ∂^{2} & −x^{2}∂^{2} − 6x∂ − 6 \end{matrix}) = (\begin{matrix}∂ & −x^{2}∂^{2} − 4x∂ − 2 & \frac{1}{2}x^{2}∂ + 2x \\ x∂ + 1 & −x^{3}∂^{2} − 4x^{2}∂ − 2x & \frac{1}{2}x^{3}∂ + 2x^{2} \\ 0 & ∂ & \frac{−1}{2} \end{matrix})^{−1} ,

Q = (\begin{matrix}1 & −x^{2}∂ − 2x & \frac{1}{2}x^{2}∂^{3} + x∂^{2} − ∂ \\ x & −x^{3}∂ − x^{2} & \frac{1}{2}x^{3}∂^{3} + \frac{1}{2}x^{2}∂^{2} − x∂ + 1 \\ 0 & 1 & −\frac{1}{2}∂^{2} \end{matrix}) = (\begin{matrix}−x∂ & ∂ & 0 \\ −\frac{1}{2}x∂^{2} − ∂ & \frac{1}{2}∂^{2} & −\frac{1}{2}x^{2}∂^{2} − 2x∂ \\ −x & 1 & −x^{2} \end{matrix})^{−1} .

[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)$

(\begin{matrix}x − 2 & 2 & 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 \end{matrix})

C1 ↔ C2

→ (\begin{matrix}2 & x − 2 & 2 & 1 & 0 & 0 \\ x − 1 & 0 & 1 & 0 & 1 & 0 \\ 0 & 0 & x − 2 & 0 & 0 & 1 \\ 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{matrix})

L1 ← (\frac{1}{2}) × L1

→ (\begin{matrix}1 & \frac{1}{2}(x − 2) & 1 & \frac{1}{2} & 0 & 0 \\ x − 1 & 0 & 1 & 0 & 1 & 0 \\ 0 & 0 & x − 2 & 0 & 0 & 1 \\ 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{matrix})

Li −= ∘ × L1 (i > 1)

→ (\begin{matrix}1 & \frac{1}{2}(x − 2) & 1 & \frac{1}{2} & 0 & 0 \\ 0 & −\frac{1}{2}(x − 2)(x − 1) & −(x − 2) & −\frac{1}{2}(x − 1) & 1 & 0 \\ 0 & 0 & x − 2 & 0 & 0 & 1 \\ 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{matrix})

Cj −= C1 × ∘ (j > 1)

→ (\begin{matrix}1 & 0 & 0 & \frac{1}{2} & 0 & 0 \\ 0 & −\frac{1}{2}(x − 2)(x − 1) & −(x − 2) & −\frac{1}{2}(x − 1) & 1 & 0 \\ 0 & 0 & x − 2 & 0 & 0 & 1 \\ 0 & 1 & 0 \\ 1 & −\frac{1}{2}(x − 2) & −1 \\ 0 & 0 & 1 \end{matrix})

L2 ↔ L3, C2 ↔ C3

→ (\begin{matrix}1 & 0 & 0 & \frac{1}{2} & 0 & 0 \\ 0 & x − 2 & 0 & 0 & 0 & 1 \\ 0 & −(x − 2) & −\frac{1}{2}(x − 2)(x − 1) & −\frac{1}{2}(x − 1) & 1 & 0 \\ 0 & 0 & 1 \\ 1 & −1 & −\frac{1}{2}(x − 2) \\ 0 & 1 & 0 \end{matrix})

(\begin{matrix}1 & 0 \\ 1 & 1 \end{matrix}) (\begin{matrix}L2 \\ L3 \end{matrix})

→ (\begin{matrix}1 & 0 & 0 & \frac{1}{2} & 0 & 0 \\ 0 & x − 2 & 0 & 0 & 0 & 1 \\ 0 & 0 & −\frac{1}{2}(x − 2)(x − 1) & −\frac{1}{2}(x − 1) & 1 & 1 \\ 0 & 0 & 1 \\ 1 & −1 & −\frac{1}{2}(x − 2) \\ 0 & 1 & 0 \end{matrix})

L3 ← (−2) × L3

→ (\begin{matrix}1 & 0 & 0 & \frac{1}{2} & 0 & 0 \\ 0 & x − 2 & 0 & 0 & 0 & 1 \\ 0 & 0 & (x − 2)(x − 1) & x − 1 & −2 & −2 \\ 0 & 0 & 1 \\ 1 & −1 & −\frac{1}{2}(x − 2) \\ 0 & 1 & 0 \end{matrix})

As a result,

(\begin{matrix}1 & 0 & 0 \\ 0 & x − 2 & 0 \\ 0 & 0 & (x − 2)(x − 1) \end{matrix}) = (\begin{matrix}\frac{1}{2} & 0 & 0 \\ 0 & 0 & 1 \\ x − 1 & −2 & −2 \end{matrix}) (\begin{matrix}x − 2 & 2 & 2 \\ 0 & x − 1 & 1 \\ 0 & 0 & x − 2 \end{matrix}) (\begin{matrix}0 & 0 & 1 \\ 1 & −1 & −\frac{1}{2}(x − 2) \\ 0 & 1 & 0 \end{matrix})

(\begin{matrix}\frac{1}{2} & 0 & 0 \\ 0 & 0 & 1 \\ x − 1 & −2 & −2 \end{matrix})^{−1} = (\begin{matrix}2 & 0 & 0 \\ x − 1 & −1 & −\frac{1}{2} \\ 0 & 1 & 0 \end{matrix}) ,

(\begin{matrix}0 & 0 & 1 \\ 1 & −1 & −\frac{1}{2}(x − 2) \\ 0 & 1 & 0 \end{matrix})^{−1} = (\begin{matrix}\frac{1}{2}(x − 2) & 1 & 1 \\ 0 & 0 & 1 \\ 1 & 0 & 0 \end{matrix}) .

18. sqrtdo(p,[x,∂_{x}]) ?

:: x ↦ 1/x で（x のべき倍を除いて）不変な微分作用素 p に対する変数変換 x ↦ y = x + \sqrt{x^{2} − 1} x = \frac{1}{2}(y + y^{−1}) に注意

19. toeul(p,[x,∂_{x}],n)

:: （Fuchs 型）常微分作用素を x = n で Euler 型に変換変数変換 x ↦ x + n のあと x∂_{x} を ∂_{x} で置き換え，多項式係数にする. ただし， n が文字列 "infty" のときは，変数変換 x ↦ 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");

(x-1)*dx^2+((-c+1)*x+a+b)*dx-b*a
20. fromeul(p,[x,p_{x}],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() については， (75) を参照

[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}],n_{0},n_{1},n_{2})

:: 常微分作用素 p に x の一次分数変換 (n_{0}, n_{1}, n_{2}) ↦ (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]

[3] os_md.expat(P,x,0);
[a,b]
24. chkexp(p,[x, ∂_{x}],n,r,m)

:: j = 0, …, m − 1 の全てに対し，確定特異点型常微分作用素 p の解 u_{j} で (x − n)^{−(r+j)}u_{j} が 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 の x = n の近傍での z^{q}(1 + ∑_{j=1}^{∞} c_{j}z^{j}) の形の形式解に対し，長さ m + 1 のベクトル [1 c_{1} c_{2} ⋯ c_{m}] を返す（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=[c_{1}, c_{2}, . . .])

:: 単独 Okubo 型方程式 pu = 0 を Okubo 型の 1 階のシステムに変換する m 階の多項式係数の常微分方程式 pu = 0 は， p の n 階微分の係数が n 次以下の多項式ならば Okubo 型（n = 0, …, m）．

• 戻り値は [[a_{0}, …, a_{m−1}], B, T]

• オプション diag=[c_{0}, c_{1}, …] によって， [a_{0}, …, a_{m−1}] の順序を変えたものを指定することができる．

• 単独 Fuchs 型のとき， p ↦ p ∗ ∂_{x} + p′ の変換を何度か施すと Okubo 型になる

(x − a_{i})u′_{i} = ∑_{j=0}^{m−1} B_{ij}u_{j}  (i = 0, …, m − 1),
u_{i} = ∑_{j=0}^{m−1} T_{i,j}u^{(j)}.

[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];

[ -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),
\binom{u_{0}}{u_{1}} = \binom{u}{(c − 1)u + xu′},
(\begin{matrix}x \\ & x − 1 \end{matrix}) \binom{u′_{0}}{u′_{1}} = (\begin{matrix}1 − c & 1 \\ −(b − c + 1)(a − c + 1) & −a − b + c − 1 \end{matrix}) \binom{u_{0}}{u_{1}}.

特に

v = \binom{v_{0}}{v_{1}} = \binom{u}{\frac{c−1}{a−c+1}u + \frac{x}{a−c+1}u′},
(\begin{matrix}x \\ & x − 1 \end{matrix}) \binom{v′_{0}}{v′_{1}} = (\begin{matrix}1 − c & a − c + 1 \\ −(b − c + 1) & −a − b + c − 1 \end{matrix}) \binom{v_{0}}{v_{1}},

\frac{dv}{dx} = \frac{(\begin{matrix}1 − c & a − c + 1 \\ 0 & 0 \end{matrix})}{x}v + \frac{(\begin{matrix}0 & 0 \\ −b + c − 1 & −a − b + c − 1 \end{matrix})}{x − 1}v

27. stoe(p,[x, dx],m)

:: 1 階の線型常微分方程式系を単独高階に直す • 方程式系 u′_{i} = ∑_{j≥0} p_{ij}(x)u_{j} の u_{m} の満たす方程式を返す． p は有理式を成分とする正方行列． • m がリスト [m_{1}, m_{2}] のときは， u_{m_{1}} を u_{m_{2}} を用いて表す (u_{m_{2}} に施す微分作用素）．

• 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*a

[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 を一階系 ũ′ = Aũ に変換し，行列 A を返す．

• m は有理式成分の行列で，成分を m_{ij} とするとき，一階系の i 番目の成分を u_{i} = ∑ m_{ij}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);

\frac{(\begin{matrix}0 & 1 \\ 0 & 0 \end{matrix})}{x} + \frac{(\begin{matrix}0 & 0 \\ −ba & −(a + b − c + 1) \end{matrix})}{x − 1}

29. dform(ℓ, x|dif=1)

:: 変数 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]]

上の計算は，以下を意味する．

ay · d(\frac{x}{y}) + bx · d(\frac{y}{x}) = \frac{ax−by}{x} dx + \frac{−ax+by}{y} dy
ax · d(\frac{x}{y}) ∧ dx + bx · d(\frac{y}{x}) ∧ dy = \frac{ax^{2}−by^{2}}{xy} dx ∧ dy
d((x − y)dy + (x − y − 1)dx) = 2dx ∧ dy

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 defined 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");

[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

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

32. laplace(p,[x, ∂_{x}])
laplace(p,[[x_{1}, ∂_{x_{1}}],[x_{2}, ∂_{x_{2}}], . . .])

:: 微分作用素 p の（部分） Laplace 変換 (x, ∂_{x}) ↦ (−∂_{x}, x)

[0] os_md.laplace(x^2*dx+1,x);
x*dx^2+2*dx+1
33. laplace1(p,[x, ∂_{x}])
laplace1(p,[[x_{1}, ∂_{x_{1}}],[x_{2}, ∂_{x_{2}}], . . .])

:: 微分作用素 p の（部分）逆 Laplace 変換 (x, ∂_{x}) ↦ (∂_{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 mc_{r}(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 mc_{r}(p)．

36. rede(p,[x, ∂_{x}])

rede(p,[[x_{1}, ∂_{x_{1}}],[x_{2}, ∂_{x_{2}}], …]) :: 部分作用素 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}],[[c_{0}, r_{0}],[c_{1}, r_{1}], …]) :: Versal addition add(p,[x, ∂_{x}], ∑_{j≥0} \frac{r_{j}x^{j}}{∏_{ν=0}^{j}(1−c_{ν}x)})

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

41. cotr(p,[x, ∂_{x}],f)

:: 常微分作用素 p の x ↦ f(x) による座標変換

42. rcotr(p,[x, ∂_{x}],f)

:: 常微分作用素 p の x ↦ 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

[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, fuchs, rod, redsp, fspt] を返す pts 特異点の数（分割の組の数） ord 階数 idx rigidity index fuchs Fuchs の関係式 rod reduction での階数減 redsp reduction exponents のリスト fspt 対応する basic なスペクトルタイプ

• 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 番目の fspt のみを返す． 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 を返す（数字による指定は不可）短縮形とは，重複度が 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]],
 [[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]]]
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));
[ 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 ]

[0] 階数が 4 で特異点が 4 個の rigid なスペクトル型のリストを得る

[1] 同じスペクトル型を文字列形式で得て表示

[2] rigid 指数が −2 で特異点数 4 のスペクトル型を文字列形式で得て表示プログラムの例は

/* 8 階で特異点が 4 個のリジッドなスペクトル型を辞書式順序の大きい順に

並べたリストを得る（文字列で） */

[5] Rank=8; /* give rank */
[6] G=os_md.spgen(Rank|eq=1,pt=4); /* get spectral types */
[7] for(L=[];G!=[];G=cdr(G))
       L=cons(os_md.s2sp(os_md.s2sp(car(G)|std=-1)),L);
[8] 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");
[[[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 = (m_{j,ν}) と Kac-Moody ルート系のルート α との対応が解説されている．

α_{m} = nα_{o} + ∑_{j≥0}(∑_{ν>i} m_{j,ν})α_{j,i}, n = m_{j,1} + m_{j,2} + ⋯ （j に依らない）
"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}

\begin{aligned}(α|α) & = 2 (α ∈ Π := \{α_{0}, α_{j,ν} | j ≥ 0, ν > 0\}) \\ (α_{0}|α_{j,ν}) & = −δ_{ν,1} \\ (α_{i,μ}|α_{j,ν}) & = \begin{cases}0 & (i ≠ j or |μ − ν| > 1) \\ −1 & (i = j and |μ − ν| = 1) \end{cases} \\ s_{α} & : x ↦ x − (x|α)α  (α ∈ Π) \end{aligned} [figure: α_{0}; α_{1,1}; α_{1,2}; ⋯; α_{2,1}; α_{2,2}; ⋯; α_{0,1}; α_{0,2}; ⋯; α_{3,1}; α_{3,2}; ⋯]

Gauss の超幾何に対応する"11,11,11"のときは

α_{m} = 2α_{0} + α_{0,1} + α_{1,1} + α_{1,2} = s_{α_{0}}s_{α_{2,1}}s_{α_{1,1}}s_{α_{0,1}}(α_{0}) = w_{m}^{−1}(α_{0}),
w_{m} = 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 : 1^{4}

であって， 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 項目によって

w_{m}^{−1} = s_{α_{2,1}}s_{α_{1,1}}s_{α_{0,1}}s_{α_{0}} を意味し，最初の数字は対応する鏡映による height の変化の数を示している．なお，一般に w_{m} = s_{α_{i_{0}}} s_{α_{i_{1}}} ⋯ s_{α_{i_{K}}} のときは

Δ(m) = {s_{α_{i_{0}}} ⋯ s_{α_{i_{ν−1}}} (α_{i_{ν}}) | ν = 0, …, K}

であり， m が rigid なときは w_{m}α_{m} = α_{0} となる長さ (= K) 最小の Weyl 群 (鏡映 s_{α} (α ∈ Π) で生成される群) の元．なお m_{j,ν} は m_{j,1} ≥ m_{j,2} ≥ ⋯ となるように正規化して考えるので， i_{0} = 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);
48. spbasic(k,d|str=1)

:: d 階で rigidity index が k の fundamental スペクトル型のリストを返す • k は 0 または負の偶数

• d = 0 のときは全ての階数のものを返す．恒等式

( ∑_{j=0}^{p}(ord m − m_{j,1}) − 2ord m)ord m + ∑_{j=0}^{p}(∑_{ν=1}^{n_{j}}(m_{j,1} − m_{j,ν})m_{j,ν}) = −idx m

において， m_{j,1} ≥ m_{j,2} ≥ ⋯ かつ m_{1} ≥ m_{2} ≥ ⋯ で，左辺の第 1 項目が非負なものが求めるもの．

辞書式順序で大きい順に求める. なお，

0 ≤ (∑_{j=0}^{p}(ord m − m_{j,1}) − 2ord m)ord m ≤ |idx m|

に注意．特に ord m > |idx m| のときは ∑_{j=0}^{p}(ord m − m_{j,1}) = 2ord m. さらに以下に注意

p + 1 ≤ \frac{1}{2}|idx m| + 4, ord m ≤ 3|idx m| + 6, ord m ≤ |idx m| + 2 (p + 1 > 3).

特に， ord m > |idx m| + 2 の時は， p = 2 で m_{0,1} + m_{1,1} + m_{2,1} = ord m.

そこで

L = \frac{1}{2}|idx m| + 4, Si(p) = ∑_{j=0}^{p}(ord m − m_{j,1}) − 2idx m, Sv(p) = ∑_{j=0}^{p}(∑_{ν≥1}(m_{j,1} − m_{j,ν})m_{j,ν})

とおく．

（a） p = 0, 1, 2, …, L の順で Sv(p) > |k| のとき

T_{i} = ∑_{ν=n_{p}−i}^{n_{j}} m_{j,ν}, S_{i} = ∑_{ν=n_{p}−i}^{n_{p}} m_{p,ν}^{2}, U_{i} = T_{i}%(m_{p,n_{p}−i} − 1), W_{i} = m_{p,n_{p}−i}(T_{i} − U_{i}) + U_{i}^{2}

とおいて， m_{p,n_{p}−i} > 2 となる最大の i から i = n_{p} − 2 まで W_{i} − S_{i} ≥ Sv(p) − |k| となる最初の i を求める．

• それが存在したらそれに基づいて m_{j}, Sv(j), Si(j) (j ≥ p) を更新する．

• 存在しない場合． j = m_{p,1} − 1, m_{p,1} − 2, …, 1 に対し，

U := d%j, (d − U)U ≤ S_{v}(p − 1)

となる最初の j を求める（必ず存在する）．それに基づいて m_{j}, Sv(j), Si(j) (j ≥ p) を更新する．

（b） p = 3, 4, …, L の順で • S_{i}(p) ≥ 0 のとき : − dS_{i}(p) + Sv(p) ≥ |ord m| ：等号のときは求まった．さらに m_{p} を次のものに変えて， m_{j}, Sv(j), Si(j) (j ≥ p) を更新し， (a) に戻る．

• S_{i}(p) < 0 で p = L のとき : m_{p,1} = −Si(p) とおき，それに基づいて m_{j}, Sv(j), Si(j) (j ≥ p)

を更新し， (a) に戻る．ただし −Si(p) ≥ d − 1 のときは， m_{p−1} や m_{p−2} も用いて調整．

rigidity index 0 −2 −4 −6 −8 −10 −12 −14 −16 −18 −20 −22
計算時間 (sec)  0.02 0.03 0.11 0.22 0.64 1.13 2.25 4.03 7.50 12.92
総個数  4 13 37 69 113 198 291 415 647 883 1186 1682
3 点特異点 3 9 25 46 73 127 182 249 395 521 680 963
4 点特異点 1 3  9 17 29 50 76 115 172 243 345 478

[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.03125sec(0.219sec)

上は， 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]);
[[[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. sp2grs(m,a,ℓ|mat=1)

:: Generates generalized Riemann scheme with a given spectral type • The inverse transformation is given by chkspt() with the option opt="sp".

• The j + 1-th spectral parameter in the i + 1-th singular point is aij (resp. a[i]j) if a is a variable (resp. a list), where a or a[i] may be a string.

• When ℓ is a list [ℓ_{1}, ℓ_{2}], ℓ_{2}-th exponent of ℓ_{1}-th singular point is determined by Fuchs relation. If the exponent is zero, another exponent is arranged.

• When ℓ is a positive integer, aij is changed into aij + k or a[i]j + k. If the above indication is also necessary, we indicate ℓ = [ℓ_{1}, ℓ_{2}, k].

• When ℓ is a negative integer −1 − k， some exponents are set to 0 in a standard way together

with the above k shift of indices.

• mat=1 means the Schleginger type (which has a different Fuchs relation)

[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]);
[[[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
51. 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
52. mcgrs(m,[r_{1}, r_{2}, . . . , r_{n}]|mat=1,slm=[[k_{1},k_{2},. . .],m′])

:: middle convolution と addition を順に generalized Riemann scheme や留数行列の和に施す

• r_{j} がスカラーの時は mc_{r_{j}} を， r_{j} がリスト [r_{j,1}, …, r_{j,n}] のときは addition を意味する. また [r_{j,0}, r_{j,1}, …, r_{j,n}] のときは，まず middle convolution mc_{r_{j,0}} を施し，そのあと [r_{j,1}, …, r_{j,n}] に対応する addition を施す．施す順序は，最初が r_{n}，次に r_{n−1} という順で，最後が r_{1}.

• Schlesinger 型のときは， mat=1 を指定する.

さらに sm1=の指定により， k_{1}, k_{2}, … 番目の留数行列の和のスペクトル型 m′ の変換を得る. これにより，半局所モノドロミーや合流で得られる不確定特異点での局所モノドロミーが計算できる（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]]]

53. mcop(p,[r_{1}, r_{2}, …, r_{n}],[x, x_{1}, x_{2}, …])

:: middle convolution と addition を (偏）微分作用素 p に順に施していく • [x, x_{1}, x_{2}, …] によって， x は変数， x_{1}, x_{2}, … は有限の特異点の位置を示す．

• [r_{1}, r_{2}, …] において， r_{j} = [r_{j,0}, r_{j,1}, …] は middle convolution と additions を表す．

– まず middle convolution mc_{r_{j,0}} を施し，その後 x = x_{ν} における additions （関数 u の (x − x_{ν})^{r_{j,ν}} u へのゲージ変換に対応）を行う（ν = 1, 2, …）．

– p に対して r_{j} に対応する変換を， r_{1}, r_{2}, … の順に行う．

[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∂_{y}

54. redgrs(m|mat=1)

:: 常微分作用素の generalized Riemann scheme の 1-step reduction 結果のデータ [redsp, m′] を返す． reduction 出来ないときは非負整数（basic, 0 は rigid) または負の値（非存在）を返す．

55. getbygrs(m,t|perm=ℓ,var=v,pt=[p_{1}, . . .],mat=1) or

getbygrs(m,[t,s_{1}, s_{2}, …]|perm=ℓ,var=v,pt=[p_{1}, …],mat=1) :: generalized Riemann scheme (GRS) で定義される Fuchs 型常微分方程式の解析（GRS は短縮形またはスペクトルタイプでもよい）

• mat=1 は， Schleginger 型を意味する.

• getbygrs(0,0) で渡されるパラメータが示される．

• m の要素の数を p + 1 個とすると，それは p + 1 個の特異点に対応する．それを順に x_{0} = ∞, x_{1} = 0, x_{2} = 1, x_{3}, …, x_{p} とする.

• Fuchs 型方程式の特異点 x = x_{j} における generalized exponents （一般特性指数）が {[λ_{0}]_{(n_{0})}, …, [λ_{k}]_{(n_{k})}} であるとは exponents が重複度を込めて {λ_{j} + ν; 0 ≤ ν < n_{j}, j = 0, …, k} であって， {λ_{0}, …, λ_{k}} に互いに差が整数となる要素が含まれない場合（そうでない場合の定義は略すが，たとえば λ_{j} が全て等しいなら対応する局所モノドロミー群の Jordan ブロックへの分解サイズが， n = n_{0} + ⋯ + n_{k} の分割の双対分割に対応すること）， x = x_{j} での局所モノドロミー群が半単純（対角化可能）となるとき，すなわち (x − x_{j})^{λ_{j}+ν}ϕ_{j,ν}(x) （0 ≤ ν < n_{ν}）という形の局所解が存在することをいう（ϕ_{j,ν}(x) は， x = x_{j} で正則で， ϕ_{j,ν}(x_{j}) = 1)．

• 各特異点での generalized exponents を並べて表にしたものを generalized Riemann scheme (GRS) という（cf. [O2, 第 5 章]， [O3, Definition 4.6]） :

\begin{cases}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[0][i][0])} & [m[j][i][1]]_{(m[j][i][0])} \\ ⋮ & ⋮ \end{cases}\}

• perm=[[i, j]] : i 番目の特異点と j 番目の特異点の入れ替え

• perm=[j_{0}, …, j_{p}] : 特異点の並べ替え（x_{j_{0}} の特性指数が ∞ に移る）．

• var=v : exponents の変数の指定． sp2grs() の第２変数の指定にあたる．

• pt=[p_{1}, p_{2}, …] : 特異点の位置を ∞, p_{1}, p_{2}, … とする．

• 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 な方程式への reduction s ="TeX" を指定したときは，さらに "top0" も指定可能 R[i][0] : i 番目の reduction の x_{j} での 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 : 方程式の構成法と解の積分表示 R[0][1]: reduction された basic な方程式の GRS (m′ とおく）． RAd(∏_{ν=1}^{p}(x − x_{ν})^{R[i][0][ν]}) ∘ mc_{R[i][0][0]} によって GRS が R[i − 1][1] から R[i][1] に変わり（i = 1, 2, …）， m′ から m への変換が分かる．

s ="short" を指定可能

s ="TeX" を指定すると，解の積分表示が得られる（局所モノドロミーの固有値の重複度が 1 の局所解）

• t ="connection" or 2 : 接続公式を求める

s ="simplify" を指定可能

特異点が p + 1 点のときは，特異点の位置が x_{0} = ∞, x_{1} = 0, x_{2} = 1, x_{3}, x_{4}, …, x_{p} とする上記 GRS であって， x = 0 と 1 での最後の exponent の重複度が共に 1 であるとき，対応する正規化した局所解の 0 から 1 への接続係数は

c_{B} \frac{∏_{ν} Γ(R[0][ν])}{∏_{ν} Γ(R[1][ν])} ∏_{j≥3}(1 − x_{j}^{−1})^{R[2][j]}

で与えられる． c_{B} は対応する basic 方程式の接続係数であるが， rigid なとき（すなわちアクセサリ・パラメータの無いとき）は c_{B} = 1 となる．特異点が 3 点のときは、 (1 − x_{j}^{−1})^{R[2][j]} の項はないことに注意．

• t ="operator" or 3 : 方程式を求める

s ="simplify" を指定可能．

結果は， x が変数 x， dx が\frac{d}{dx} を表す．

アクセサリ・パラメータは ri_j と表され，それは帰着 basic 方程式の x^{j} \frac{d^{i}}{dx^{i}} の係数にあたる．この計算は、他の計算に比べて重いので注意．

• t ="series" or 4 : x = 0 での最後の exponent （重複度が 1 の必要あり）に対応する局所解のベキ級数表示を求める． R = [R_{0}, R_{1}, R_{2}] R_{0} = [[R_{00}, [R_{01}, T_{1}], [R_{02}, T_{2}], …], [P_{1}, Q_{1}], [P_{2}, Q_{2}], …] R_{1} = [[R_{100}, P_{101}, P_{102}, …], [R_{110}, P_{111}, P_{112}, …], …] R_{2} = [[R_{200}, P_{201}, P_{202}, …], [R_{210}, P_{211}, P_{212}, …], …] 0 ≤ P_{1} < P_{2} < P_{3} < ⋯

∑_{n_{P_{1}} ,n_{P_{2}} ,...} C_{n_{0}}x^{R_{00}+n_{0}} ∏_{j≥0, P j≠0}(\frac{x}{x_{Q_{j}}} )^{n_{P j}}

· ∏_{j≥1}(1 − \frac{x}{x_{T_{j}}} )^{R_{0j}} \frac{∏_{j≥0}(R_{1j0})_{n_{P_{1j1}} +n_{P_{1j2}} +···}}{∏_{j≥0}(R_{2j0})_{n_{P_{2j1}} +n_{P_{2j2}} +···}} ,

x_{1} = x_{2} = 1,
P_{1} ≠ 0 ⇒ n_{0} = 0 and C_{0} = 1.

• t = "TeX" or 5 : GRS を L^{A}TEX で表示 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" : L^{A}TEX の数式で出力する

• "dviout" : dviout で表示する

このときオプション・パラメータ title= で文字列を指定できる

• "keep" : 上と同様だが，表示はしない

• "short" : GRS を短縮形で表示

• "general" : スペクトルタイプを与えたとき， exponents を完全に generic にとる

• "x1" : 特異点を， ∞, x_{1}, x_{2}, … とする（GRS の TEX 表示、および作用素を得るときのみ有効） • "x2" : 特異点を， ∞, 0, x_{2}, … とする（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]]
 ]
],
[[ 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],
 [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_0
s_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"])$
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]]]

In the above example we examine the generalized Riemann scheme

R = P \begin{cases}x = ∞ & 0 & 1 \\ a_{0} & b_{0} & [c_{0}]_{(2)} & ; x \\ a_{1} & b_{1} & c_{1} \\ a_{2} & b_{2} \end{cases}\}

with c_{1} = −a_{0} − a_{1} − a_{2} − b_{0} − b_{1} − b_{2} − 2c_{0} + 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(x^{b_{0}}(x − 1)^{c_{0}}) ∘ mc_{−a_{0}−b_{0}−c_{0}+1} ∘ RAd(x^{a_{0}+b_{1}+c_{0}−1})
∘ mc_{−a_{1}−b_{1}−c_{0}+1} ∘ RAd(x^{a_{1}+b_{2}+c_{0}−1}(x − 1)^{−a_{2}−b_{2}−c_{0}})∂_{x}

and the generalized Riemann scheme changes as follows

P \left\{{x = ∞ 0 1 \atop 0 0 0 ; x}\right\}

→ RAd(x^{c_{0}+a_{1}+b_{2}−1}(x − 1)^{−c_{0}−b_{2}−a_{2}})

P \left\{{x = ∞  0  1 \atop a_{2} − a_{1} + 1 c_{0} + b_{2} + a_{1} − 1 −c_{0} − b_{2} − a_{2} ; x}\right\}

→ RAd(x^{a_{0}+b_{1}+c_{0}−1}) ∘ mc_{−a_{1}−b_{1}−c_{0}+1}

P \begin{cases}x = ∞ & 0 & 1 \\ a_{1} − a_{0} + 1 & c_{0} + b_{1} + a_{0} − 1 & 0 \\ a_{2} − a_{0} + 1 & c_{0} + b_{2} + a_{0} − 1 & −2c_{0} − b_{2} − b_{1} − a_{2} − a_{1} + 1 & ; x \end{cases}\}

→ RAd(x^{b_{0}}(x − 1)^{c_{0}}) ∘ mc_{−a_{0}−b_{0}−c_{0}+1}

P \begin{cases}x = ∞ & 0 & 1 \\ a_{0} & b_{0} & [c_{0}]_{(2)} \\ a_{1} & b_{1} & c_{1} := −a_{0} − a_{1} − a_{2} − b_{0} − b_{1} − b_{2} − 2c_{0} + 2 & ; x \\ a_{2} & b_{2} \end{cases}\} .

Hence an integral representation of the solution is

u(x) = x^{b_{0}}(1 − x)^{c_{0}} ∫_{c}^{x} ∫_{c}^{s_{0}}(x − s_{0})^{a_{0}+b_{0}+c_{0}}s_{0}^{a_{0}+b_{1}+c_{0}−1}
· (s_{0} − s_{1})^{a_{1}+b_{1}+c_{0}}s_{1}^{a_{1}+b_{2}+c_{0}−1}(1 − s_{1})^{−a_{2}−b_{2}−c_{0}}ds_{1}ds_{0}.

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 b_{2} or c_{1} or a_{2}, 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 coefficient

c(0:b_{2} ⇝1:c_{1}) = \frac{Γ(a_{0} + a_{1} + a_{2} + b_{0} + b_{1} + b_{2} + 3c_{0} − 2) ∏_{ν=0}^{1} Γ(b_{2} − b_{ν} + 1)}{∏_{ν=0}^{2} Γ(a_{ν} + b_{2} + c_{0})}

= \frac{Γ(c_{0} − c_{1}) ∏_{ν=0}^{1} Γ(b_{2} − b_{ν} + 1)}{∏_{ν=0}^{2} Γ(a_{ν} + b_{2} + c_{0})},

which corresponds to the local solution

x^{b_{2}}(1 − x)^{c_{0}}_{3}F_{2}(a_{0} + b_{2} + c_{0}, a_{1} + b_{2} + c_{0}, a_{2} + b_{2} + c_{0}, 1 − b_{0} + b_{2}, 1 − b_{1} + b_{2}; x).

The calculation

[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) = \frac{Γ(c − a − b)Γ(c)}{Γ(c − a)Γ(c − b)}

for the Gauss hypergeometric series

F (a, b, c; x) = ∑_{k=0}^{∞} \frac{(a)(a + 1) ⋯ (a + k − 1) · b(b + 1) ⋯ (b + k − 1)}{(c)(c + 1) ⋯ (c + k − 1)k!}x^{k},

which is a solution of the hypergeometric equation

x(1 − x)u′′ + (c − (a + b + 1)x)u′ − abu = 0

corresponding to the Riemann scheme

P \begin{cases}x = ∞ & 0 & 1 \\ a & 0 & 0 & ; x \\ b & 1 − c & c − a − b \end{cases}\} .

The equation is irreducible if and only if

a, b, a − c, b − c ∉ ℤ.

[34] os_md.getbygrs([[a1,a2,a3],[0,b1,b2],[[2,0],"?"]],["reduction","dviout","top0"]);

とすると，以下が表示される．

P \begin{cases}x = 0 & 1 & ∞ \\ 0 & [0]_{(2)} & a_{1} & ; x \\ b_{1} & −b_{1} − b_{2} − a_{3} − a_{2} − a_{1} + 2 & a_{2} \\ b_{2} & & a_{3} \end{cases}\}

← mc_{−a_{1}+1} : P \begin{cases}x = 0 & 1 & ∞ \\ b_{1} + a_{1} − 1 & 0 & a_{2} − a_{1} + 1 & ; x \\ b_{2} + a_{1} − 1 & −b_{1} − b_{2} − a_{3} − a_{2} + 1 & a_{3} − a_{1} + 1 \end{cases}\}

← Ad(x^{b_{1}+a_{1}−1})mc_{−b_{1}−a_{2}+1} : P \left\{{x = 0  1  ∞ \atop b_{2} + a_{2} − 1 −b_{2} − a_{3} a_{3} − a_{2} + 1 ; x}\right\}

← Ad(x^{b_{2}+a_{2}−1}(1 − x)^{−b_{2}−a_{3}}) : P \left\{{x = 0 1 ∞ \atop 0 0 0 ; x}\right\}

 [35] os_md.getbygrs("11,11,11",["All","dviout","operator"]);

とすると，以下が表示される． Riemann scheme

P \begin{cases}x = ∞ & 0 & 1 \\ a_{0} & 0 & 0 & ; x \\ a_{1} & b & c \end{cases}\}

Fuchs condition

b + c + a_{1} + a_{0} − 1

Connection formula

c(0:b ⇝ 1:c) = \frac{Γ(−c)Γ(b + 1)}{Γ(b + a_{0})Γ(b + a_{1})}

Recurrence relation shifting the last exponents at ∞, 0, 1

u_{0,0,0} − u_{+1,0,−1} = \frac{(b + 1)}{(b + a_{0})}u_{0,+1,−1}

Integral representation

\begin{matrix}∫_{p}^{x}(x − s_{0})^{−a_{0}}s_{0}^{−c−a_{1}}(1 − s_{0})^{−b−a_{1}}ds_{0} \\ ∼ \frac{Γ(−a_{0} + 1)Γ(b + a_{0})}{Γ(b + 1)}x^{b} (p = 0, x → 0) \end{matrix}

Series expansion

∑_{n≥0} \frac{(b + a_{0})_{n}(b + a_{1})_{n}}{(b + 1)_{n}n!} x^{b+n}

Irreducibility ⇔ any value of the following linear forms ∉ ℤ

\begin{matrix}a_{0} a_{1} \\ c + a_{0} b + a_{0} \end{matrix}

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)∂ − a_{0}a_{1}

 [36] os_md.getbygrs([[[2,e],f,g],[[2,0],a,b],[[2,0],c,d]],["All","top0","dviout"]);

では Riemann scheme

P \begin{cases}x = 0 & 1 & ∞ \\ [0]_{(2)} & [0]_{(2)} & [e]_{(2)} & ; x \\ a & c & f \\ b & d & g \end{cases}\}

Fuchs condition

a + b + c + d + 2e + f + g − 3

Connection formula

c(0:b ⇝ 1:d) = \frac{Γ(−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

u_{0,0,0} − u_{+1,0,−1} = \frac{(b + 1)(−a + b + 1)}{(b + e)(b + c + e + f − 1)}u_{0,+1,−1}

Integral representation

\begin{matrix}∫_{p}^{x} ∫_{p}^{s_{0}}(x − s_{0})^{−e}s_{0}^{a+e−1}(1 − s_{0})^{c+e−1}(s_{0} − s_{1})^{b+d+e+g−2}s_{1}^{b+c+e+f−2}(1 − s_{1})^{a+d+e+f−2}ds_{1}ds_{0} \\ ∼ \frac{Γ(−e + 1)Γ(b + e)Γ(b + d + e + g − 1)Γ(b + c + e + f − 1)}{Γ(b + 1)Γ(−a + b + 1)}x^{b} (p = 0, x → 0) \end{matrix}

Series expansion

∑_{n_{1}≥0, n_{2}≥0} \frac{(−c − e + 1)_{n_{2}}(b + c + e + g − 1)_{n_{1}}(b + c + e + f − 1)_{n_{1}}(b + e)_{n_{1}+n_{2}}}{(−a + b + 1)_{n_{1}}(b + 1)_{n_{1}+n_{2}}n_{1}!n_{2}!} x^{b+n_{1}+n_{2}}

Irreducibility ⇔ any value of the following linear forms ∉ ℤ g f e

d + 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 ではない例では

[37] os_md.getbygrs("3111,3111,3111",["All","dviout"]);

とすると以下が表示される． Riemann Scheme

P \begin{cases}x = ∞ & 0 & 1 \\ [a_{0}]_{(3)} & [0]_{(3)} & [0]_{(3)} & ; x \\ a_{1} & b_{1} & c_{1} \\ a_{2} & b_{2} & c_{2} \\ a_{3} & b_{3} & c_{3} \end{cases}\}

Basic Riemann Scheme

P \begin{cases}x = ∞ & 0 & 1 \\ b_{3} + c_{1} + a_{1} + a_{0} − 1 & b_{1} − b_{3} & 0 & ; x \\ b_{3} + c_{1} + a_{2} + a_{0} − 1 & b_{2} − b_{3} & c_{2} − c_{1} \\ b_{3} + c_{1} + a_{3} + a_{0} − 1 & 0 & c_{3} − c_{1} \end{cases}\}

[[1, 1, 1], [1, 1, 1], [1, 1, 1]]

Fuchs condition

b_{1} + b_{2} + b_{3} + c_{3} + c_{2} + c_{1} + a_{3} + a_{2} + a_{1} + 3a_{0} − 6

Connection formula

\begin{matrix}c(0:b_{3} ⇝ 1:c_{3}) \\ = \frac{Γ(−c_{3})Γ(b_{3} + 1)}{Γ(−c_{3} − a_{0} + 1)Γ(b_{3} + a_{0})}c_{B}(0:0 ⇝ 1:c_{3} − c_{1}) \end{matrix}

Integral representation

\begin{matrix}∫_{p}^{x}(x − s_{0})^{−a_{0}}s_{0}^{b_{3}+a_{0}−1}(1 − s_{0})^{c_{1}+a_{0}−1}u_{B}(s_{0})ds_{0} \\ ∼ \frac{Γ(−a_{0} + 1)Γ(b_{3} + a_{0})}{Γ(b_{3} + 1)}C_{0}x^{b_{3}} (p = 0, x → 0) \end{matrix}

Series expansion

∑_{n_{0}≥0, n_{1}≥0} \frac{(−c_{1} − a_{0} + 1)_{n_{1}}(b_{3} + a_{0})_{n_{0}+n_{1}}}{(b_{3} + 1)_{n_{0}+n_{1}}n_{1}!} C_{n_{0}}x^{b_{3}+n_{0}+n_{1}}

Irreducibility ⇔ any value of the following linear forms ∉ ℤ + fundamental irreducibility

\begin{matrix}a_{0} a_{1} a_{2} a_{3} \\ c_{1} + a_{0} c_{2} + a_{0} c_{3} + a_{0} b_{3} + a_{0} b_{2} + a_{0} b_{1} + a_{0} \end{matrix}

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

rigid でない Riemann scheme をもつ方程式 P u = 0 は， middle convolution と addition によって basic Riemann scheme をもつ方程式 P_{B}u_{B} = 0 に変換される．解 u(x) の接続公式，積分表表示，べき級数表示は P_{B}u_{B} = 0 の解 u_{B}(x) の接続係数 c_{B} やべき級数解 ∑_{n_{0}=0}^{∞} C_{n_{0}}x^{b_{3}+n_{0}} を使って上のように表すことができる．既約条件の fundamental irreducibility とは， P_{B}u_{B} = 0 の既約条件である． P から P_{B} への具体的変換は 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]]
56. spslm(m,[k_{1},k_{2},. . .])

:: rigid な常微分方程式の解の半局所モノドロミーを求める • m はスペクトル型または generalized Riemann scheme.

• k_{1},k_{2}, …: k_{1}, k_{2}, … 番目の特異点を 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

\begin{cases}x = ∞ & 0 & 1 & y \\ [a_{0}]_{2} & [0]_{2} & [0]_{2} & [0]_{2} \\ a_{1} & −2a_{0} − a_{1} − c − d & c & d \end{cases}\}

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

57. 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);
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

\begin{cases}x = ∞ & 0 & 1 \\ a & 0 & 0 \\ −a − b − c + 1 & b & c \end{cases}\} = \{u | P u = 0\}

⇄^{Q_{1}}_{Q_{2}} \begin{cases}x = ∞ & 0 & 1 \\ a + 1 & 0 & 0 \\ −a − b − c & b & c \end{cases}\}
Q_{1} = (2a + b + c)x(x − 1)∂ + a((2a + b + c)x − a − c)
Q_{2} = −(2a + b + c)x(x − 1)∂ + (a + b + c)((2a + b + c)x − a − b)
Q_{2}Q_{1} ≡ 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)

58. shiftPfaff(a,b,g,x,[μ_{1},μ_{2}])

:: Pfaff 系の隣接関係式の middle convolution による変換ここで， a(x), b(x), g(x) は有理関数の正方行列で， μ_{1} − μ_{2} ∈ ℤ となっている必要がある．

u′(x) = a(x)u, u(x) = \frac{1}{Γ(μ_{1})} ∫_{x_{0}}^{x} ū(t)(x − t)^{μ_{1}−1}dt,
v′(x) = b(x)v, v(x) = \frac{1}{Γ(μ_{2})} ∫_{x_{0}}^{x} v̄(t)(x − t)^{μ_{2}−1}dt,
v̄(x) = g(x)ū(x)

であるとき， u(x) = G(x)v(x) となる有理関数の行列 G(x) を求める．

• μ_{1} = μ_{2} のときは， [μ_{1},μ_{2}] は単に μ_{1} としてよい．

59. conf1sp(m|x2= ± 1,conf=0)

:: スペクトル型 m の微分作用素の Poincare rank 1 の合流過程を示すスペクトル型を与える各分割は，順に特異点 ∞, \frac{1}{c}, x_{2}, … に対応するものとし， ∞ に対応する分割は \frac{1}{c} に対応する分割の細分を指定する（c = 0 が合流）．ただし， x2=1 を指定しないと x_{2} = 0 とする． x2=-1 のときは， x_{2}, … を\frac{1}{c2}, … とする． conf=0 を指定すると，特異点を ∞, 0, c, x_{3}, … とし，原点と点 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);
-(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)
60. pf2kz(m|all=1)

:: n 変数の Pfaff 系 m を n + 2 変数の KZ 方程式に変換 n = 2 のときは m = [A_{0}, A_{1}, A_{2}, A_{3}, A_{4}] とすると， Pfaff 系

\frac{∂u}{∂x} = \frac{A_{1}u}{x} + \frac{A_{2}u}{x − 1} + \frac{A_{0}u}{y}
\frac{∂u}{∂y} = \frac{A_{3}u}{y} + \frac{A_{4}u}{y − 1} + \frac{A_{0}u}{x}

を

\frac{∂u}{∂x_{i}} = ∑_{0≤j≤3, j≠i} \frac{A_{i,j}u}{x_{i} − x_{j}} (0 ≤ i ≤ 3)

に変換する．ここで

(x_{0}, x_{1}, x_{2}, x_{3}, x_{4}) = (x, y, 0, 1, ∞)
A_{i,j} = A_{j,i}, A_{0,j} = A_{j}, A_{1,2} = A_{3}, A_{1,3} = A_{4},
∑_{0≤i<j≤3} A_{i,j} = ∑_{0≤ν≤4, ν≠i} A_{i,j} = 0.

戻り値は [A_{23}, A_{04}, A_{14}, A_{24}, A_{34}] の n + 3 個の成分のリスト一般には， Pfaff 系の座標と KZ 系の座標の関係は (x_{0}, x_{1}, …, x_{n+2}) = (x, y_{1}, …, y_{n−1}, 0, 1, ∞) とする． all=1 を指定すると， A_{ij} の (i, j) による辞書式順序のリストで返す（成分は，\frac{(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)$

(\begin{matrix}0 & 1 & 2 & 3 & −6 \\ 1 & 0 & 4 & 5 & −10 \\ 2 & 4 & 0 & −15 & 9 \\ 3 & 5 & −15 & 0 & 7 \\ −6 & −10 & 9 & 7 & 0 \end{matrix}) : 対角成分と各行の和が 0 の正方行列

61. confexp([[c_{0},f_{0}],[c_{1},f_{1}],...,[c_{m}, f_{m}]]) confexp([[f_{1},. . .,f_{n}],[c_{1},. . .,c_{m}]]|sym=k])

:: 特性指数の合流を返す • \frac{1}{x−c_{j}} (j = 0, …, m) の一次結合を_{\frac{1}{∏_{ν=0}^{j}(x−c_{ν})}} (j = 0, …, m) の一次結合で表す．すなわち

∑_{j=0}^{m} \frac{f_{j}}{x − c_{j}} = ∑_{k=0}^{m} \frac{λ_{k}}{∏_{ν=0}^{k}(x − c_{ν})}

を満たす [λ_{0},λ_{1}, …, λ_{m}] を返す（paracmpl() の項を参照）．

ただし， f_{j} は x を含まない c_{j} などの有理式．

引数は，上のようなリストのリストでもよい（各リストの要素毎の結果をリストとして返す）．なお， x = \frac{1}{y} とおいて，上の両辺を x で割った等式は以下のようになることに注意．

∑_{j=0}^{m} \frac{f_{j}}{1 − c_{j}y} = ∑_{k=0}^{m} \frac{λ_{k}y^{k}}{∏_{ν=0}^{k}(1 − c_{ν}y)}.

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

(f_{1} ; f_{2} ; ⋮ ; f_{n}) = M (\frac{x^{m−1}}{(x−c_{1})···(x−c_{m})} ; \frac{x^{m−2}}{(x−c_{1})···(x−c_{m})} ; ⋮ ; \frac{1}{(x−c_{1})···(x−c_{m})} )

を満たす n × m 行列 M を返す．なお， f_{j} は (x − c_{1}) ⋯ (x − c_{m}) を掛けると， x の (m − 1) 次以下の多項式となる必要がある． • sym=2 を指定した場合は， [f_{1},…,f_{n}] の各成分に (x − c_{1}) … (x − c_{m}) を掛けた x の多項式のリ

ストを返す．

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

(f_{1} ; f_{2} ; ⋮ ; f_{n}) = M ( \frac{1}{x−c_{1}} ; \frac{1}{(x−c_{1})(x−c_{2})} ; ⋮ ; \frac{1}{(x−c_{1})···(x−c_{m})} )

を満たす 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 ]
[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]
62. mcvm(n|var=x,z=1,get=g)  mcvm([n_{1},n_{2}, . . .]|var=[a,b, . . .],z=1,get=g)
mcvm([r,k,i,j]|e=1,var=[a,b, . . .])

:: versal unfolding の middle convolution

\frac{du}{dx} = ∑_{j=1}^{n} \frac{A_{j}}{(x − a_{1})(x − a_{2}) ⋯ (x − a_{j})}u,
\frac{du}{dx} = − ∑_{j=1}^{n} \frac{A_{j}x^{j−1}}{(1 − a_{1}x)(1 − a_{2}x) ⋯ (1 − a_{j}x)}u,
\frac{du}{dx} = ∑_{i=1}^{n} ∑_{j=1}^{r_{i}} \frac{A_{ij}}{(x − a_{i1})(x − a_{i2}) ⋯ (x − a_{ij})}u,
\frac{du}{dx} = ∑_{i=1}^{n} ∑_{j=1}^{r_{i}} \frac{A_{ij}}{(x − a_{i1})(x − a_{i2}) ⋯ (x − a_{ij})}u − ∑_{j=1}^{r_{0}} \frac{A_{0j}x^{j−1}}{(1 − a_{01}x)(1 − a_{02}x) ⋯ (1 − a_{0j}x)}u.

という versal Schlesinger 系の convolution を求める．

\frac{du}{dx} = ∑_{j=a}^{p} \frac{C_{j}}{x − a_{j}} u

という Fuchs 系（C_{j} は N 次正方行列）は p_{j} = \frac{1}{x−a_{j}} とおくと

u′ = (C_{1}, …, C_{p})^{t}(p_{1}, …, p_{n})u

と表せるが，この解 u(x) に対して

ũ(x) = (\begin{matrix}Γ(μ + 1)^{−1} ∫_{c}^{x} u(t)(x − a_{1})^{−1}(x − t)^{μ}dt \\ ⋮ \\ Γ(μ + 1)^{−1} ∫_{c}^{x} u(t)(x − a_{n})^{−1}(x − t)^{μ}dt \end{matrix})

と定義すると（c は a_{j} または ∞）

ũ′ = diag(p_{1}I_{N}, …, p_{n}I_{N})(^{t}(1_{N}, …, I_{N})(C_{1}, …, C_{n}) + μI_{pN})ũ

= ∑_{j=1}^{n} \frac{C̃_{j}}{x − a_{j}} ũ, C̃_{j} = ( j_{⌣} ; 0 ⋯  0  ⋯ 0 ; ⋮ ⋯  ⋮  ⋯ ⋮ ; j) C_{1} ⋯ C_{j} + μI_{N} ⋯ C_{n} ; 0 ⋯  0  ⋯ 0 ; ⋮ ⋯  ⋮  ⋯ ⋮ ).

これは

(\begin{matrix}(x − a_{1})\frac{d}{dx} \frac{u}{x−a_{1}} \\ (x − a_{2})\frac{d}{dx} \frac{u}{x−a_{2}} \end{matrix} ) = (\begin{matrix}\frac{(C_{1}−1)u}{x−a_{1}} + \frac{C_{2}u}{x−a_{2}} \\ \frac{C_{1}u}{x−a_{1}} + \frac{C_{2}−1u}{x−a_{2}} \end{matrix} ) = (\begin{matrix}C_{1} − 1 & C_{2} \\ C_{1} & C_{2} − 1 \end{matrix}) (\frac{u}{x−a_{1}} ; \frac{u}{x−a_{2}} )

から得られる（積分変換 v(x) ↦ ∫_{c}^{x} v(t)(x − t)^{μ}dt は，作用素 x\frac{d}{dx}, \frac{d}{dx} を x\frac{d}{dx} − μ − 1, \frac{d}{dx} に変換する）．

• 最初の方程式を考える．そこで

q_{j}(x) = \frac{1}{(x − a_{1}) ⋯ (x − a_{j})}  (j = 1, …, n),

û(x) = (Γ(μ + 1)^{−1} ∫_{c}^{x} u(t)q_{1}(x)(x − t)^{μ}dt ; ⋮ ; Γ(μ + 1)^{−1} ∫_{c}^{x} u(t)q_{n}(x)(x − t)^{μ}dt)

のように基底を取り変えて convolution を行ったとき, 最初の方程式の A_{k} は Â_{k} に変換されるとする．このとき mcvm(n|get=1) の戻り値を [A′_{1}, …, A′_{p}] とすると, Â_{k} は

Â_{k} = (δ_{i,k}A_{j})\begin{matrix}1≤i≤n \\ 1≤j≤n \end{matrix} + μA′_{k}

で与えられる．なお A′_{k} = (D_{n,k,i,j}I_{N})\begin{matrix}1≤i≤n \\ 1≤j≤n \end{matrix} であって D_{n,k,i,j} は，オプション e=1 で求められる

（後述）．

• オプション get を指定しない場合は

(p_{1}(x) ; ⋮ ; p_{n}(x)) = S (q_{1}(x) ; ⋮ ; q_{n}(x))

となる行列 S を返す．すなわち ũ = S^{−1}û， (C_{1}, …, C_{n})S = (A_{1}, …, A_{n}).

û′ = S^{−1}ũ′ = S^{−1} (p_{1} ; ⋮) (C_{1}, …) ũ + S^{−1}μ (\begin{matrix}p_{1} \\ & . & . & . \end{matrix}) ũ

= q (A_{1}, A_{2}, …) û + μS^{−1} (\begin{matrix}S_{1}q \\ & S_{2}q \\ & & . & . & . \end{matrix}) Sû,

∑ A_{k}q_{k} = S^{−1} (\begin{matrix}S_{1}q \\ & S_{2}q \\ & & . & . & . \end{matrix}) S, S = (S_{1} ; S_{2} ; ⋮) , q = (q_{1} ; q_{2} ; ⋮) .

• 2 番目の方程式の場合は， (x − a_{i})^{−1} を (\frac{1}{a_{i}} − x)^{−1} に， q_{i}(x) を x^{i−1}(1 − a_{1}x)^{−1} ⋯ (1 − a_{i}x)^{−1} に置き換えて同様な結果を返す.

• オプション var=[a,b,c, …] により方程式の特異点を表す a_{i} を他の文字 a, b, c, … のように置き換える．

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

• 上記 Fuchs 系は x_{0} = x とおくと

\begin{aligned}\frac{∂u}{∂x_{i}} & = ∑_{ν∈\{0,...,i\}\\{i\}}^{p} \frac{C_{i,ν}}{x_{i} − x_{ν}} (i = 0, …, p), \\ C_{i,j} & = C_{j,i}, C_{0,j} = C_{j} \end{aligned}

という KZ 系に拡張できるとする．このとき convolution に対応して C_{0,j} = C_{j} は Ĉ_{0,j} = C̃_{j} となるが， convolution は KZ 系にも拡張され, それは

C̃_{i,j} = ( \begin{matrix}& & & & & i_{⌣} & & & & & j_{⌣} \\ & C_{i,j} \\ & & . & . & . \\ i) & & & & & C_{i,j} + C_{0,j} & & & & & −C_{0,j} \\ & & & & & & C_{i,j} \\ & & & & & & & . & . & . \\ j) & & & & & −C_{0,i} & & & & & C_{i,j} + C_{0,i} \\ & & & & & & & & & & & . & . & . \\ & & & & & & & & & & & & & & C_{i,j} \end{matrix} )

で与えられる．

• get=2 を指定すると， versal unfolding では， A_{j} あるいは A_{i,j} を用いたが， Fuchs 型への unfolding の convolution で用いた基底に対応して前項の C̃_{i,j} (1 ≤ i < j ≤ p) の対角部分 C_{i,j} を除いた部分が変換される行列を A_{0,ν} を用いて表したリスト（対角部分 A_{i,j} が除かれている． A_{0,ν} はデフォルトでは a0ν と表示）を返す．これを用いて不確定 KZ 方程式の versal unfolding の convolution が計算できる（cf. [O9]）．

• get=3 を指定すると， 3 番目の常微分方程式で n = 2 の場合に， x_{0} = x, a_{1,j} = x_{1} − a_{j}, a_{2,j} = x_{2} − b_{j} とおいたときの方程式\frac{∂û}{∂x_{1}} = A_{1}(x)û の A_{1}(x) を完備化基底 \{\frac{1}{(x_{1}−x_{0})^{ν}} | ν = 1, …, r_{1}\} ∪ \{\frac{1}{x_{1}−x_{2}+a_{1}−b_{1}} , …, \frac{1}{(x_{1}−x_{2}+a_{1}−b_{1})···(x_{1}−x_{2}+a_{1}−b_{r_{2}} )}, …, \frac{1}{(x_{1}−x_{2}+a_{1}−b_{1})···(x_{1}−x_{2}+a_{r_{1}} −b_{r_{2}} )}\} を用いたときの後者の部分の係数を返す（r_{1}r_{2}個ある）．ただし， a_{1} = b_{1} = 0 が代入され，対角部分の A_{i,j} に当たる部分は省かれる．結果は，さらに a_{2} = ⋯ = a_{r_{1}} = b_{1} = ⋯ = b_{r_{2}} = 0 とおいた場合の係数のリストと合わせて返される． n > 2 のときの結果は， n = 2 のときの結果から分かる（cf. [O9]） .

I = {i_{0}, i_{0} + 1, …, i_{0} + r_{I} − 1}, J = {j_{0}, j_{0} + 1, …, j_{0} + r_{J} − 1},
du = ∑_{ν} \frac{C_{0,ν}}{x − x_{ν}} dx = ∑_{i∉I} \frac{C_{0,i}}{x − x_{ν}} du + ∑_{i∈I} \frac{A_{0,i}}{(x − x_{i_{0}}) ⋯ (x − x_{i})}du,

\frac{∂û}{∂x_{i_{0}}} = ∑_{i∈I}(\frac{Ã_{i,0}}{(x_{i_{0}} + e_{i_{0}} − x_{0}) ⋯ (x_{i_{0}} + e_{i} − x_{0})} + S^{−1} ∑_{ν∉I, ν≠0} \frac{C̃_{i,ν}}{x_{i_{0}} + e_{i} − x_{ν}} S)û,
C̃_{i,ν} = (C_{i,ν}δ_{p,q} + δ_{p,i}(δ_{q,i} − δ_{q,ν})C_{0,ν} + δ_{p,ν}(δ_{q,ν} − δ_{q,i})C_{0,i})_{p,q},

\frac{1}{x_{i_{0}} + e_{i} − x_{j_{0}} − e_{j}} = ∑_{k∈I, ℓ∈J} U_{(i,j),(k,ℓ)}q_{k,ℓ},

S^{−1} ∑_{i∈I, j∈J}(C_{i,j}δ_{p,q} + δ_{p,i}(δ_{q,i} − δ_{q,j})C_{0,j} + δ_{p,j}(δ_{q,j} − δ_{q,i})C_{0,i})_{p,q}(x_{i_{0}} + e_{i} − x_{j_{0}} − e_{j})^{−1}S

= ∑_{i∈I, j∈J} ∑_{k∈I, ℓ∈J} S^{−1}(C_{i,j}δ_{p,q} + δ_{p,i}(δ_{q,i} − δ_{q,j})C_{0,j} + δ_{p,j}(δ_{q,j} − δ_{q,i})C_{0,i})_{p,q}SU_{(i,j),(k,ℓ)}q_{k,ℓ}

= ∑_{k∈I, ℓ∈J}(A_{k,ℓ}δ_{p,q})_{p,q}q_{k,ℓ}

+ ∑_{i∈I, j∈J} ∑_{k∈I, ℓ∈J} S^{−1}(δ_{p,i}(δ_{q,i} − δ_{q,j}) ∑_{s=i_{0}}^{i} A_{0,s}q_{s−i_{0}+1,{1,...,s−i_{0}}}(x_{i_{0}}, …))_{p,q}SU_{(i,j),(k,ℓ)}q_{k,ℓ}

+ ∑_{i∈I, j∈J} ∑_{k∈I, ℓ∈J} S^{−1}(δ_{p,i}(δ_{q,j} − δ_{q,i}) ∑_{s=j_{0}}^{j} A_{0,s}q_{s−j_{0}+1,{1,...,s−j_{0}}}(x_{j_{0}}, …))_{p,q}SU_{(i,j),(k,ℓ)}q_{k,ℓ}.

• get=4 を指定すると， get=3 で返される係数のリストの後者のみが返される．

• e=1 を指定した場合は，最初の引数を [r,k,i,j] としたとき， j + k − i − 1 次の多項式 D_{r,k,i,j} を返す（r は無視される）：なお， D_{r,k,i,j} = D_{r,j,i,k}.

S = (S_{i,j})_{i,j}, S_{i,j} = \begin{cases}0 & (i < j) \\ s_{i,\{1,...,j\}} & (i ≥ j) \end{cases} (最初の方程式),

s_{i,{j_{1},...,j_{k}}}(a) := ∏_{j=1}^{k}(a_{i} − a_{j_{ν}}), p_{i} = ∑_{j=1}^{i} s_{i,{1,...,j−1}}q_{j},

D_{r,k,i,j}(a) := ∑_{ν=max\{k,j\}}^{i} \frac{s_{ν,\{1,...,j−1\}}}{s_{ν,\{k,k+1,...,i\}\\{ν\}}} .

• e=2 を指定した場合は，最初の引数を [r,k,i,j] としたとき， j + k − i − 1 次の多項式 D′_{r,k,i,j} を返す（r は無視される） :

D′_{r,k,i,j}(a′) := ∑_{ν=max\{k,j\}}^{i} \frac{a_{ν+1}s_{ν+1,\{2,...,j\}}}{s_{ν+1,\{k,k+1,...,i+1\}\\{ν+1\}}} = D_{r,k,i+1,j+1}(a)|_{a_{1}=0}.

[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 ]
   [ 0 0 0 ],
   [ 0 0 0 ]
   [ 0 0 0 ]
   [ 0 0 1 ]]

これは 3 番目の方程式で， n = 2, r_{1} = 2, r_{2} = 1 の場合で

Â_{1,1} = (\begin{matrix}A_{1} + μ & A_{2} & A_{3} \\ 0 & μ & 0 \\ 0 & 0 & 0 \end{matrix}) , Â_{1,2} = (\begin{matrix}0 & 0 & 0 \\ A_{1} + μ & A_{2} + (a_{2} − a_{1})μ & A_{3} \\ 0 & 0 & 0 \end{matrix}) ,

Â_{2,1} = (\begin{matrix}0 & 0 & 0 \\ 0 & 0 & 0 \\ A_{1} & A_{2} & A_{3} + μ \end{matrix})

となることを意味する．

[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 ]
[ 0 0 0 0 ]
[ 0 0 0 0 ]
[ -a01 a01 a01*b3 -a01*b3*b2+a01*b3^2 ]

これから

\frac{∂u}{∂x_{0}} = (\frac{A_{01}}{x_{0} − x_{1}} + ∑_{j=2}^{4} \frac{A_{0j}}{(x_{0} − x_{2})(x_{0} − x_{2} − b_{2}) ⋯ (x_{0} − x_{2} − b_{j−1})})u,
\frac{∂u}{∂x_{1}} = (\frac{A_{10}}{x_{1} − x_{0}} + ∑_{j=2}^{4} \frac{A_{1j}}{(x_{1} − x_{2})(x_{1} − x_{2} − b_{2}) ⋯ (x_{1} − x_{2} − b_{j−1})})u,
\frac{∂u}{∂x_{2}} = ∑_{i=0}^{1} ∑_{j=2}^{4}(\frac{(−1)^{j}A_{ji}}{(x_{2} − x_{i})(x_{2} − x_{i} + b_{2}) ⋯ (x_{2} − x_{1} + b_{j−1})})u,
A_{i,j} = A_{j,i}

の convolution が

Â_{01} = (\begin{matrix}A_{01} + μ & A_{02} & A_{03} & A_{04} \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \end{matrix}) , Â_{02} = (\begin{matrix}0 & 0 & 0 & 0 \\ A_{01} & A_{02} + μ & A_{03} & A_{04} \\ 0 & 0 & μ & 0 \\ 0 & 0 & 0 & μ \end{matrix}) ,

Â_{03} = (\begin{matrix}0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ a_{01} & A_{02} + μ & A_{03} + b_{2}μ & A_{04} \\ 0 & 0 & μ & b_{3}μ \end{matrix}) , Â_{04} = (\begin{matrix}0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ A_{01} & A_{02} + μ & A_{03} + b_{3}μ & A_{04} + b_{3}(b_{3} − b_{2})μ \end{matrix}) ,

Â_{12} = (\begin{matrix}A_{12} + A_{02} & −A_{02} & −A_{03} & −A_{04} \\ −A_{01} & A_{12} + A_{01} & 0 & 0 \\ 0 & 0 & A_{12} + A_{01} & 0 \\ 0 & 0 & 0 & A_{12} + A_{01} \end{matrix}) ,

Â_{13} = (\begin{matrix}A_{13} + A_{03} & −A_{03} & −b_{2}A_{03} − A_{04} & −b_{3}A_{04} \\ 0 & A_{13} & 0 & 0 \\ −A_{01} & A_{01} & A_{13} + A_{01} & b_{3}A_{01} \\ 0 & 0 & A_{01} & A_{13} + b_{3}A_{01} \end{matrix}) ,

Â_{14} = (\begin{matrix}A_{14} + A_{04} & −A_{04} & −b_{3}A_{04} & −b_{3}(b_{3} − b_{2})A_{04} \\ 0 & A_{14} & 0 & 0 \\ 0 & 0 & A_{14} & 0 \\ −A_{01} & A_{01} & b_{3}A_{01} & A_{14} + b_{3}(b_{3} − b_{2})A_{01} \end{matrix})

（Ã_{ij} = Ã_{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 ]
[ 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 ]]

上の結果より不確定特異点をもつ KZ 型方程式

\frac{∂u}{∂x_{0}} = (∑_{ν=1}^{2} \frac{A_{0,ν}}{(x_{0} − x_{1})^{ν}} + ∑_{ν=1}^{3} \frac{A_{0,ν+2}}{(x_{0} − x_{2})^{ν}} )u,
\frac{∂u}{∂x_{1}} = (∑_{ν=1}^{2} \frac{(−1)^{ν−1}A_{ν,0}}{(x_{1} − x_{0})^{ν}} + ∑_{ν=1}^{4} \frac{A_{1,ν+2}}{(x_{1} − x_{2})^{ν}} )u,
\frac{∂u}{∂x_{2}} = (∑_{ν=1}^{3} \frac{(−1)^{ν−1}A_{ν+2,0}}{(x_{2} − x_{0})^{ν}} + ∑_{ν=1}^{4} \frac{(−1)^{ν−1}A_{ν+2,1}}{(x_{2} − x_{1})^{ν}} )u,
A_{i,j} = A_{j,i}

の convolution は

Â_{01} = (\begin{matrix}A_{01} + μ & A_{02} & A_{03} & A_{04} & A_{05} \\ 0 & μ & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \end{matrix}) , Â_{02} = (\begin{matrix}0 & 0 & 0 & 0 & 0 \\ A_{01} + μ & A_{02} & A_{03} & A_{04} & A_{05} \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \end{matrix}) ,

Â_{03} = (\begin{matrix}0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ A_{01} & A_{02} & A_{03} + μ & A_{04} & A_{05} \\ 0 & 0 & 0 & μ & 0 \\ 0 & 0 & 0 & 0 & μ \end{matrix}) , Â_{04} = (\begin{matrix}0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ A_{01} & A_{02} & A_{03} + μ & A_{04} & A_{05} \\ 0 & 0 & 0 & μ & 0 \end{matrix}) ,

Â_{05} = (\begin{matrix}0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ A_{01} & A_{02} & A_{03} + μ & A_{04} & A_{05} \end{matrix}) ,

Â_{13} = (\begin{matrix}A_{13} + A_{03} & 0 & −A_{03} & −A_{0,4} & −A_{05} \\ 0 & A_{13} + A_{03} & 0 & 0 & 0 \\ −A_{01} & −A_{02} & A_{13} + A_{01} & 0 & 0 \\ 0 & 0 & 0 & A_{13} + A_{01} & A_{02} \\ 0 & 0 & 0 & 0 & A_{13} + A_{01} \end{matrix}) ,

Â_{14} = (\begin{matrix}A_{14} + A_{04} & 0 & −A_{04} & −A_{05} & 0 \\ −A_{03} & A_{14} + A_{04} & A_{03} & A_{04} & A_{05} \\ A_{02} & 0 & A_{14} − A_{02} & 0 & 0 \\ −A_{01} & −A_{02} & A_{14} + A_{01} & −A_{02} & 0 \\ 0 & 0 & 0 & A_{01} & A_{14} − A_{02} \end{matrix}) ,

Â_{15} = (\begin{matrix}A_{15} + A_{05} & 0 & −A_{05} & 0 & 0 \\ −2A_{04} & A_{15} + A_{05} & 2A_{04} & 2A_{05} & 0 \\ 0 & 0 & A_{15} & 0 & 0 \\ 2A_{02} & 0 & −2A_{02} & A_{15} & 0 \\ −A_{01} & −A_{02} & A_{01} & −2A_{02} & A_{15} \end{matrix}) ,

Â_{16} = (\begin{matrix}A_{16} & 0 & 0 & 0 & 0 \\ −3A_{05} & A_{16} & 3A_{05} & 0 & 0 \\ 0 & 0 & A_{16} & 0 & 0 \\ 0 & 0 & 0 & A_{16} & 0 \\ 3A_{02} & 0 & −3A_{02} & 0 & A_{16} \end{matrix})

で与えられることが分かる（cf. [O9]）．

63. anal2sp(m,l)

:: 同時スペクトル m の解析 m = [[m_{1}, λ_{1}, μ_{1}], [m_{2}, λ_{2}, μ_{2}], …] は重複度と同時固有値 l は以下の意味を持つ. 0 同じスペクトル型をまとめる（同時スペクトルでなくても可）． ["add",n] スペクトル型 n を加える（同時スペクトルでなくても可）． ["sub",n] スペクトル型 n を引く（同時スペクトルでなくても可）． ["swap"] 同時スペクト型の順序を入れ替える． ["+",c_{1},c_{2}] 固有値をシフトする． ["*",c_{1},c_{2}] 固有値の一次結合を返す． ["+",c_{1},c_{2},…] 固有値をシフトする（任意個でよい）． ["*",c_{1},c_{2},…] 固有値の一次結合を返す（任意個でよい）． ["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"]); /* 固有値のコピー */
[[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]
64. mc2grs(g,r|top=0,dviout=k,div=ℓ,fig=s)

:: ℙ^{1} 内の 5 点の配置に対する KZ 型方程式の同時スペクトル g の変換 KZ 型方程式

du = ∑_{0≤i<j≤3} A_{i,j} \frac{d(x_{i} − x_{j})}{x_{i} − x_{j}}u,

A_{i,4} = − ∑_{j=0}^{3} A_{i,j}, A_{j,i} = A_{i,j}, A_{i,i} = 0

において， I, J ⊂ {0, 1, 2, 3}, #I = #J = 2, I ∩ J = ∅ のとき

[A_{I}, A_{J}] = 0

が満たされるので， A_{I} と A_{J} の同時固有値分解が出来る．このような 15 組の [I, J] に対する同時固有値（重複度と各固有値）のリスト（ヘッダは [I,J] で， I=[i_{i},i_{2}], J=[j_{i},j_{2}] とすると， i_{1} < i_{2}, j_{1} < j_{2}, i_{1} < j_{1} となる）のリストを g とする．

A_{0,1} = (\begin{matrix}a \\ & a \\ & & b \end{matrix}) , A_{2,3} = (\begin{matrix}c \\ & c \\ & & d \end{matrix})

のときは同時固有値のリストは [[[0,1],[2,3]],[2,a,c],[1,b,d]] となる．

なお，既約性から ∑_{0≤i<j≤3} A_{i,j} はスカラー行列としてよいので，そのスカラーを κ とする．同時固有値のリストのリストを g で与えるが，それ以外の指定は

 • g = 0 のとき，自明な [[[[0,1],[2,3]],[1,0,0]],[[[0,1],[2,4]],[1,0,0]],. . .] を意味

する．

• g を， 4 行列 A_{0,4}, A_{0,1}, A_{0,2}, A_{0,3} のスペクトル型（文字列あるいは， 4 点の GRS）を, この順で指定する．このときは， m2mc() におけると同様なオプション（dep=[m,n]， int=0）などの指定が可能）．なお， top=0 を指定した場合は， A_{0,1}, A_{0,2}, A_{0,3}, A_{0,4} の順と解釈される．スペクトル型や文字列で指定した場合は, 以下の r が特別の意味を持つ．

– r = 1 : スペクトル型を標準的な順序にし，同時固有値のリストのリストをそのまま返す． – r = 3 : 同時固有値のリストのパラメータを a,b,c,… で表し， Fuchs 条件と同次固有値のリ

ストのリストとの組をリストとして返す．スペクトル型や文字列で指定した場合は, 以下の r が特別の意味を持つ．

• r = 1 : スペクトル型を標準的な順序にし，同時固有値のリストのリストをそのまま返す．

• r = 3 : 同時固有値のリストのパラメータを a,b,c,… で表し， Fuchs 条件と同次固有値のリスト

のリストとの組をリストとして返す． r によって，以下の機能になる．

• 0 : 同時固有値のリストのリストをそのまま返す．

• ["sort"] : ヘッダが標準的な順序になるよう，リストを並び替える（[ ] は省略可）．

• ["deg"] : κ を返す（[ ] は省略可）．なお A_{0,1} + A_{0,2} + A_{0,3} + A_{1,2} + A_{1,3} + A_{2,3} = κ で

A_{i,j} = A_{\{0,1,2,3,4\}\\{i,j\}} \begin{cases}+κ & (j < 4) \\ −κ & (j = 4) \end{cases} (0 ≤ i < j ≤ 4).

• [[i,j],λ] : A_{i,j} ↦ A_{i,j} + λ, A_{i,4} ↦ A_{i,4} − λ, A_{j,4} ↦ A_{j,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",[i_{0}, …, i_{4}]] : 添え字の置換 (\begin{matrix}0 & 1 & 2 & 3 & 4 \\ i_{0} & i_{1} & i_{2} & i_{3} & i_{4} \end{matrix}) を行う．添え字 4 を変更するとき

は， r =["homog"] を行ってから置換する．

• [μ] : x_{0} 変数に対する middle convolution mc_{x_{0},μ} を行う（アルゴリズムは [O5] によって与えられた）．

• [i,μ] : x_{i} 変数に対する middle convolution mc_{x_{i},μ} を行う．ただし， i = 4 のときは，

  r =["swap",[0,4]] を行ってから mc_{x_{0},μ} を施し，再度 r =["swap",[0,4]] で戻す．

• [[[i_{1},j_{1}],λ_{1}],…,[i_{k},μ_{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]] : [A_{I}, A_{J}] = 0 に対する同時固有値を返す（ヘッダ [I, J] のついたリスト）．

• ["get",I] : A_{I} に対する固有値を返す（ヘッダ I のついたリスト）．

• ["get",[i,j,k]] : A_{i,j} + A_{i,k} + A_{j,k} のスペクトルを返す（ヘッダ I のついたリスト）．

• ["get",i] (0 ≤ i ≤ 4) : i ∈ I を満たす A_{I} に対する GRS を返す（変数 x_{i} についての常微分方程式の GRS）． dviout=1 を指定すると TEX を使って表示する． dviout=-1 では TEX のソースを返す． dviout=2 を指定すると， TEX のソースを書き出すが表示はしない（次回の表示コマンドでまとめて表示する）．

• ["get"] : 10 個全ての A_{I} の固有値のリストを返す． 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] : A_{I} + A_{J} のスペクトルを返す．

• ["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 ≠ j のとき A_{i,j} のスペクトル型， i = j のとき x_{i} についての index of rigidity （0 ≤ i, j ≤ 4）． dviout=k の指定が可能．

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

• ["mult",ℓ_{1},...,ℓ_{m}] : g_{0} = g として g_{i} = mc2grs(g_{i−1},ℓ_{i}) を i = 1, …, m に対して順に実行して g_{m} を返す．オプションも有効．

• ["eigen",I] : A_{I} の各固有空間にいて， A_{I} と可換な 3 つの留数行列の固有空間分解を返す（固有値と固有空間分解のリストの組のリストで，固有空間分解は重複度と固有値の組のリスト）． A_{I} と可換な留数行列 A_{J} は J ⊂ {0, 1, 2, 3, 4} \ I を満たすもので， J を辞書式順序にして返す．たとえば， I = [0, 2] ならば， J は辞書式順序で [1, 3], [1, 4], [3, 4] の 3 つ．

• ["rest",I] : I = [i, j] のとき，特異直線 x_{i} = x_{j} への各特異成分に対応する境界値の満たす x_{0} の方程式の GRS を返す（x_{0} = x_{k} の k が小さいに並べ， 0 < i < j のときは， x_{0} = x_{i} は x_{0} = x_{k} と解釈する）．

• ["rest0",I] : I = [i, j] のとき，特異直線 x_{i} = x_{j} への各特異成分に対応する境界値の方程式のスペクトル型（文字列）を返す．

• ["rest1",I] : I = [i, j] のとき，特異直線 x_{i} = x_{j} への各特異成分に対応する境界値の方程式のうち， rigid でないスペクトル型（文字列）のみを全て返す．

• ["eigen"], ["rest"], ["rest0"]， ["rest1"] としたときは，上の I の 10 個全てに対して，そ

の結果の最初に I を付加した結果のリストを返す．このとき， dviout=1,-1,2 の指定が可能．

• ["K0",[μ,λ]] : K̃_{x}^{−μ−λ,λ} [ [0,0,λ,−μ − λ],[0,0,μ] ] : \frac{(λ)_{m}}{(1−μ)_{m}} ×

• ["K1",[μ,λ]] : K̃_{y}^{−μ−λ,λ} [["swap",[0,1]],[0,0,λ,−μ − λ],[0,0,μ],["swap",[0,1]]]

• ["K01",[μ,λ]] : K̃_{x,(x,y)↦(x, \frac{x}{y})}^{−μ−λ,λ}

• ["K2",[μ,λ]] : [ [0,λ,0,−μ − λ],[0,0,μ] ]
• ["K3",[μ,λ]] : [["swap",[0,1]], [0,λ,0,−μ − λ],[0,0,μ],["swap",[0,1]] ]

• ["K",[p,q,r]] : ∑_{m=0}^{∞} ∑_{n=0}^{∞} \frac{(a_{1})_{m}(b_{1})_{n} ∏_{ν=2}^{p}(a_{ν})_{m} ∏_{ν=2}^{q}(b_{ν})_{n} ∏_{ν=1}^{r}(c_{ν})_{m+n}}{∏_{ν=2}^{p}(1 − d_{ν})_{m} ∏_{ν=2}^{q}(1 − e_{ν})_{n} ∏_{ν=1}^{r}(1 − f_{ν})_{m+n}m!n!}x^{m}y^{n}

rank : pq + qr + rp

• ["I",[p,q]] : ∑_{m=0}^{∞} ∑_{n=0}^{∞} \frac{∏_{ν=1}^{p−1}(a_{ν})_{m} ∏_{ν=1}^{q−1}(b_{ν})_{n} · (c)_{m+n}}{∏_{ν=2}^{p}(1 − d_{ν})_{m} ∏_{ν=2}^{q}(1 − e_{ν})_{n}m!n!}x^{m}y^{n}

rank : pq, (pq − 1)1, (pq − q + 1)1^{q−1}, q^{p}, q^{p−1}1^{q} (x_{0}, x_{1}, x_{2}, x_{3}, x_{4}) = (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)↦(x↦ \frac{x}{y})}^{μ,λ}: ["perm",[2,1,0,4,3]] → [[0,0,λ,μ],[0,0,−λ−μ] ] → ["perm",[2,1,0,4,3]]

(K̃_{x}^{μ,λ}u)(x, y) = \frac{x^{−μ−λ}}{Γ(μ + 1)} (\begin{matrix}∫_{0}^{x}(x − t)^{μ}t^{λ} \frac{u(t,y)}{t−x}dt \\ ∫_{0}^{x}(x − t)^{μ}t^{λ} \frac{u(t,y)}{y}dt \\ ∫_{0}^{x}(x − t)^{μ}t^{λ−1}u(t, y)dt \end{matrix}) = (\begin{matrix}K_{x}^{μ+1,λ} \frac{xu}{x−y} \\ K_{x}^{μ+1,λ} \frac{xu}{y} \\ K_{x}^{μ+1,λ}u \end{matrix} )

K_{x}^{μ−λ,λ}u(x, y) = \frac{1}{Γ(μ − λ)} ∫_{0}^{1} t^{λ−1}(1 − t)^{μ−λ−1}u(tx, y)dt, x^{m}y^{n} ↦ \frac{Γ(λ + m)}{Γ(μ + m)}x^{m}y^{n}
K_{y}^{μ−λ,λ}u(x, y) = \frac{1}{Γ(μ − λ)} ∫_{0}^{1} t^{λ−1}(1 − t)^{μ−λ−1}u(tx, y)dt, x^{m}y^{n} ↦ \frac{Γ(λ + n)}{Γ(μ + n)}x^{m}y^{n}
K_{x,(x,y)↦(x, \frac{x}{y})}^{μ−λ,λ}u(x, y) = \frac{1}{Γ(μ − λ)} ∫_{0}^{1} t^{λ−1}(1 − t)^{μ−λ−1}u(tx, ty)dt, x^{m}y^{n} ↦ \frac{Γ(λ + m + n)}{Γ(μ + m + n)}x^{m}y^{n}

[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 */

\begin{cases}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{cases}\}

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

\begin{cases}A_{01} & A_{02} & A_{03} & A_{04} & A_{12} & A_{13} & A_{23} & A_{14} & A_{24} & A_{34} \\ [0]_{2} & [0]_{2} & [0]_{2} & [−d]_{2} & [0]_{2} & [0]_{2} & [0]_{2} & [−a]_{2} & [−b]_{2} & [−c]_{2} \\ a + d & b + d & c + d & −a − b − c − d & a + b & a + c & b + c & −a − b − c − d & −a − b − c − d & −a − b − c − d \end{cases}\}

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

[A_{01} : A_{23}] = {[a + d : 0], [0 : 0], [0 : b + c]},
[A_{01} : A_{24}] = {[a + d : −b], [0 : −b], [0 : −a − b − c − d]},
[A_{01} : A_{34}] = {[a + d : −c], [0 : −c], [0 : −a − b − c − d]},
[A_{02} : A_{13}] = {[b + d : 0], [0 : 0], [0 : a + c]},
[A_{02} : A_{14}] = {[b + d : −a], [0 : −a], [0 : −a − b − c − d]},
[A_{02} : A_{34}] = {[b + d : −c], [0 : −c], [0 : −a − b − c − d]},
[A_{03} : A_{12}] = {[c + d : 0], [0 : 0], [0 : a + b]},
[A_{03} : A_{14}] = {[c + d : −a], [0 : −a], [0 : −a − b − c − d]},
[A_{03} : A_{24}] = {[c + d : −b], [0 : −b], [0 : −a − b − c − d]},
[A_{04} : A_{12}] = {[−a − b − c − d : 0], [−d : 0], [−d : a + b]},
[A_{04} : A_{13}] = {[−a − b − c − d : 0], [−d : 0], [−d : a + c]},
[A_{04} : A_{23}] = {[−a − b − c − d : 0], [−d : 0], [−d : b + c]},
[A_{12} : A_{34}] = {[0 : −c], [0 : −a − b − c − d], [a + b : −c]},
[A_{13} : A_{24}] = {[0 : −b], [0 : −a − b − c − d], [a + c : −b]},
[A_{14} : A_{23}] = {[−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 */

2^{2}1^{3}, 1^{7}, 1^{7}, 2^{2}1^{3}, 1^{7}, 1^{7}, 21^{5}, 1^{7}, 1^{7}, 1^{7}, 1^{7}, 1^{7}, 1^{7}, 1^{7}, 1^{7}

[13] os_md.mc2grs(F1,"spct"|dviout=1)$   /* spectral type of KZ equation */

\begin{aligned}& x_{0} & x_{1} & x_{2} & x_{3} & x_{4} & idx \\ x_{0} & & 21 & 21 & 21 & 21 & 2 \\ x_{1} & 21 & & 21 & 21 & 21 & 2 \\ x_{2} & 21 & 21 & & 21 & 21 & 2 \\ x_{3} & 21 & 21 & 21 & & 21 & 2 \\ x_{4} & 21 & 21 & 21 & 21 & & 2 \end{aligned}

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

\begin{cases}A_{01} & A_{02} & A_{03} & A_{04} & A_{12} & A_{13} & A_{23} & A_{14} & A_{24} & A_{34} \\ [0]_{2} & [0]_{2} & [0]_{2} & [d]_{2} & [0]_{2} & [0]_{2} & [0]_{2} & [−a − d]_{2} & [−b − d]_{2} & [−c − d]_{2} \\ a & b & c & −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 \end{cases}\}

[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 */

[01] : 221, 1^{5}, 1^{5}
[02] : 221, 1^{5}, 1^{5}
[03] : 111, 111, 111 211, 1^{4}, 1^{4}
[04] : 111, 111, 111

[22] os_md.mc2grs("322,52,52,43","rest0"|dviout=1);  /* bry spectral type */

[01] : 11, 11, 11 221, 1^{5}, 1^{5}
[02] : 11, 11, 11 221, 1^{5}, 1^{5}
[03] : 111, 111, 111 211, 1^{4}, 1^{4}
[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 */

[01] : a  → \begin{cases}−c − d_{1} − d_{2} & c − d_{1} & −a − 2c \\ a + b + 2c + 2d_{1} + d_{2} & a + 2c + 2d_{1} & −a − b − 2c − 2d_{1} \end{cases}\}

0  → \begin{cases}−c − d_{1} − d_{2} & c − d_{1} & [−2c]_{2} \\ a + b + 2c + 2d_{1} + d_{2} & a + 2c + 2d_{1} & [−b − 2c − 2d_{1}]_{2} \\ 0 & −a + 2c − 2d_{1} & b + 4d_{1} \\ a + b + 4c + 4d_{1} + 2d_{2} & 0 \\ −a − b − 2c − 2d_{1} − 2d_{2} & −a − 2d_{1} \end{cases}\}

[02] : b  → \begin{cases}−c − d_{1} − d_{2} & −c − d_{1} & −b \\ a + b + 2c + 2d_{1} + d_{2} & b + 2d_{1} & −a − b − 2d_{1} \end{cases}\}
⋯

[24] os_md.mc2grs("322,52,52,43","spct1"|dviout=1)$ /* all spectral types */

x_{0}  x_{1}  x_{2}  x_{3}  x_{4} idx reduction
x_{0}  52  52  43  322  2 22,22,31,22
x_{1} 52  322  331 22111 −22
x_{2} 52  322  331 22111 −22
x_{3} 43  331  331  22111 −24
x_{4} 322 22111 22111 22111  −48

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

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);
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;
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));
}
65. newKZmat(k,l|verb=1)

:: convolution of residue matrices of KZ equation

[O5] における留数行列 A_{I}, A_{0J} などの convolution を返す • k: size of residue matrix

• l =[0,m] : Ã_{0,1,...,m} を返す

• l =[m,n] (m > 0): Ã_{m,m+1,...n} を返す

• l =[[m_{1,1}, m_{2,1}, …],…,[m_{1,k}, m_{2,k}, …,]] : 指定した第 m_{i,j} 成分のみが 1 で残りの成分が 0 の行列を返す

• verb=1: a_{01···k} = 0 と簡約しない

[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]])$
[3] os_md.show([A,B,C]);

(\begin{matrix}μ + a_{0123} & 0 & 0 & a_{04} \\ 0 & μ + a_{0123} & 0 & a_{04} \\ 0 & 0 & μ + a_{0123} & a_{04} \\ 0 & 0 & 0 & a_{123} \end{matrix}) , (\begin{matrix}a_{23} & 0 & 0 & 0 \\ 0 & a_{023} − a_{02} & −a_{03} & 0 \\ 0 & −a_{02} & a_{023} − a_{03} & 0 \\ 0 & 0 & 0 & a_{23} \end{matrix}) , (\begin{matrix}1 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 \\ 1 & 0 & 1 & 0 \\ 1 & 0 & 1 & 1 \end{matrix})

66. midKZ(l,b|raw=1,skip=m,kill=f)

:: 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 first line

[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);

U = (\begin{matrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 1 & 1 \end{matrix}) , V = U^{−1} = (\begin{matrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & −1 & 1 \end{matrix}) , Ã_{∗} → V Ã_{∗}U

Ã_{01} = (\begin{matrix}μ + A_{01} & A_{02} & A_{03} \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{matrix}) → (\begin{matrix}μ + A_{01} & A_{03} + A_{02} & A_{03} \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{matrix})

Ã_{23} = (\begin{matrix}A_{23} & 0 & 0 \\ 0 & −A_{02} + A_{023} & −A_{03} \\ 0 & −A_{02} & −A_{03} + A_{023} \end{matrix}) → (\begin{matrix}A_{23} & 0 & 0 \\ 0 & A_{23} & −A_{03} \\ 0 & 0 & A_{023} \end{matrix})
[Ã_{01} : Ã_{23}] = {[μ + A_{01} : A_{23}], [0 : A_{23}], [0 : A_{023}]}
[Ã_{01} : Ã_{23}]|_{L_{1}} = [A_{01} + μ : A_{23}]|_{ker A_{01}}
[Ã_{01} : Ã_{23}]|_{L_{2}} = [0 : A_{023}]|_{ker A_{02}}
[Ã_{01} : Ã_{23}]|_{L_{3}} = [0 : A_{023}]|_{ker A_{03}}
[Ã_{01} : Ã_{23}]|_{L_{∞}} = [0 : A_{23}]|_{ker (A_{0∞}−μ)}

N=4;  /* N-2=2 variables HG */
T=os_md.symtournament(N|to="T");
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);
67. m2mc(ℓ,[a_{0},a_{y},a_{1},c]|swap=1,small=1,simplify=0,MC=1)
m2mc(ℓ,s|small=1,simplify=0,int=0,swap=t)

:: Pfaff 形式 du = (A_{0} \frac{dx}{x} +A_{y} \frac{d(x−y)}{x−y} +A_{1} \frac{d(x−1)}{x−1} +B_{0} \frac{dy}{y} +B_{1} \frac{d(y−1)}{y−1})u の x 変数での addition+middle convolution を求める（ℓ = [A_{0}, A_{y}, A_{1}, B_{0}, B_{1}]）． ℓ がスペクトル型や Riemann scheme のとき，上の後者では s ="GRC", "GRSC", "extend", "Pfaff",

"sp", "pairs", "irreducible", "All", "swap"

• m2mc(0,0) で使い方が簡略化して表示される．

• ℓ は [A_{0}, A_{y}, A_{1}, B_{0}, B_{1}] という 5 個の正方行列のリストまたはベクトル．行列のサイスが 1 のときは， 5 個のスカラーのリストまたはベクトルでもよい． A_{0}, A_{y}, A_{1} にそれぞれ a_{0}, a_{y}, a_{1} による addition を施したあと，パラメータ c による middle convolution （MC=1 を指定した場合は convolution ）を行った 5 個の行列のベクトルを返す． addition を行わないときは， [a_{0},a_{y},a_{1},c] の代わりに単に c としてよい．

addition のみのときは， c を省いて [a_{0},a_{y},a_{1}] と指定する.

• ℓ は x 変数のスペクトル型や Riemann scheme でもよい．スペクトル型や Riemann scheme は x = ∞, x = 0, x = y, x = 1 の順に与える．このときは a_{0} や s は 0 （[A_{0},A_{y},A_{1},B_{0},B_{1}] を返す）または次々項に挙げる文字列とする．

• ℓ をスペクトル型で与えるときは，各特異点で重複度が大きな順に並べると結果が簡単になることが多い（オプション dep=[m,n] の項参照）．

• a_{0} や s が以下の文字列の場合は，特別の意味を持つ – GRS : Generalized Riemann scheme を返す． a_{y} に "dviout" を指定できる．

– GRSC : 上と同じであるが，さらに x = y = 0, x = y = 1 の一般化特性指数も含める.

– extend ： KZ 型に標準拡張した 10 個の以下の留数行列を返す．

[A_{x,y}, A_{x,0}, A_{x,1}, A_{x,∞}, A_{y,0}, A_{y,1}, A_{y,∞}, A_{0,1}, A_{0,∞}, A_{1,∞}] この 10 個の行列のリストも入力の引数 ℓ に指定できる． a_{0} ="extend", a_{1} ="eigen" とすると，各留数行列とその固有値，固有ベクトルの TEX ソースを返す．

– Pfaff ：文字列で Pfaff 形式を返す． a_{y} に "dviout" を指定できる．

– sp : x 変数と y 変数のスペクトル型を x = y から順に表す．

– pairs, pair ：可約なときの分解を与える分割を示す．

– irreducible ：既約条件を与えるパラメータを示す．

– All ：上の全てを指定し，さらに． a_{1} に "dviout" を指定したと見なされる．さらに GRSC を指定すると, GRS でなくて GRSC を指定したと見なされる． operator=0 のオプションで， Pfaff 形式の方程式を示さない．

– swap : x 変数と y 変数を入れ替えた変換結果を返す．さらにオプション swap=t を指定すると別の変換の意味になる． t = 1 : x 変数と y 変数の入れ替え（指定しない場合と同じ）． t = 2 : 座標変換 (x, y) ↦ (x, \frac{x}{y}) を行う． t = [t_{0},t_{1},t_{2}] : (t_{0}, t_{1}, t_{2}) は (0, 1, 2) の並べ替えで， 0, 1, 2 は順に特異点 0, 1, ∞ を意味する．

なお, KZ 方程式に拡張した留数行列は

\begin{aligned}& x & y & 0 & 1 & ∞ \\ x & & A_{x,y} & A_{x,0} & A_{x,1} & A_{x,∞} \\ y & A_{x,y} & & A_{y,0} & A_{y,1} & A_{y,∞} \\ 0 & A_{x,0} & A_{y,0} & & A_{0,1} & A_{0,∞} \\ 1 & A_{x,1} & A_{y,1} & A_{0,1} & & A_{1,∞} \\ ∞ & A_{x,∞} & A_{y,∞} & A_{0,∞} & A_{1,∞} \end{aligned}  \begin{cases}A_{0} = A_{x,0}, A_{1} = A_{x,1}, A_{y} = A_{x,y}, \\ B_{0} = A_{y,0}, B_{1} = A_{y,1}, \\ A_{0} + A_{1} + A_{y} + B_{0} + B_{1} + A_{0,1} = 0, \\ 表の各行の行列の和は 0 \end{cases}

なお， (x_{0}, x_{1}, x_{2}, x_{3}, x_{4}) = (x, y, 1, 0, ∞) という座標を用いるときは，行列で作用するベクトルの最初と次の成分を入れ替えた変換に対応する． 0 と 1 は対称なので入れ替えて考えてよい． [a_{1}, a_{y}, a_{0}, 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 の F_{1} に対応する留数行列が得られる（cf. m2grs(), K̂_{x}^{μ,λ}). K̂_{x}^{μ,λ} に対応）．

\begin{cases}A_{x,∞} = −(A_{x,y} + A_{x,0} + A_{x,1}), A_{y,∞} = −(A_{x,y} + A_{y,0} + A_{y,1}), \\ A_{0,1} = A_{x,∞} + A_{y,∞} + A_{x,y}, A_{0,∞} = A_{x,y} + A_{x,1} + A_{y,1}, A_{1,∞} = A_{x,y} + A_{x,0} + A_{y,0}. \end{cases}

また，以下のオプションがある． • 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"]);

\begin{cases}x = 0 & x = y & x = 1 & y = 0 & y = 1 & x = ∞ & y = ∞ & x = y = ∞ \\ a + d & b + d & c + d & a + b & b + c & −a − b − c − d & −a − b − c − d & [−a − b − c − d]_{2} \\ [0]_{2} & [0]_{2} & [0]_{2} & [0]_{2} & [0]_{2} & [−d]_{2} & [−b]_{2} & −b − d \end{cases}\}

[2] os_md.m2mc(F1,["Pfaff","dviout"]);

du = ((\begin{matrix}a + d & b & c \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{matrix}) \frac{dx}{x} + (\begin{matrix}0 & 0 & 0 \\ a & b + d & c \\ 0 & 0 & 0 \end{matrix}) \frac{d(x − y)}{x − y} + (\begin{matrix}0 & 0 & 0 \\ 0 & 0 & 0 \\ a & b & c + d \end{matrix}) \frac{d(x − 1)}{x − 1}

+ (\begin{matrix}b & −b & 0 \\ −a & a & 0 \\ 0 & 0 & 0 \end{matrix}) \frac{dy}{y} + (\begin{matrix}0 & 0 & 0 \\ 0 & c & −c \\ 0 & −b & b \end{matrix}) \frac{d(y − 1)}{y − 1} )u

[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"]);

\begin{cases}x = 0 & x = y & x = 1 & y = 0 & y = 1 & x = ∞ & y = ∞ & x = y = ∞ \\ [−a − d + e]_{2} & b + d + e & c + d + e & a + b & [b + c]_{2} & [a − e]_{2} & −a − b − c − d & a − b − e \\ [0]_{2} & [0]_{3} & [0]_{3} & [0]_{3} & [0]_{2} & −b − c − e & −b − c − e & [−b − c − e]_{3} \\ & & & & & −e & [−b]_{2} \end{cases}\}

[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);

\{ \begin{matrix}x=0 & x=y & x=1 & y=0 & y=1 & x=∞ & y=∞ & x=y=∞ & x=y=0 & x=y=1 \\ a & b & c & a+b+2d & b+c+2d & −a−b−c−2d_{1} & −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} & −b & 0 & 0 \end{matrix} \}

[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, All
  s : 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

\begin{cases}x = 0 & x = y & x = 1 & y = 0 & y = 1 & x = ∞ & y = ∞ & x = y = ∞ \\ a & b & c & a + b + 2d & b + c + 2d & −a − b − c − 2d & −a − b − c − 2d & [−a − b − c − 2d]_{2} \\ [0]_{2} & [0]_{2} & [0]_{2} & [0]_{2} & [0]_{2} & [d]_{2} & [−b − d]_{2} & −b \end{cases}\}

Spectre 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 ⇔ ∅ = ℤ∩

{d, c + d, b + d, a + d, a + b + c + 2d}

The equation in a Pfaff form is

du = ((\begin{matrix}a & b + d & c + d \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{matrix}) \frac{dx}{x}

+ (\begin{matrix}0 & 0 & 0 \\ a + d & b & c + d \\ 0 & 0 & 0 \end{matrix}) \frac{d(x − y)}{x − y}

+ (\begin{matrix}0 & 0 & 0 \\ 0 & 0 & 0 \\ a + d & b + d & c \end{matrix}) \frac{d(x − 1)}{x − 1}

+ (\begin{matrix}b + d & −(b + d) & 0 \\ −(a + d) & a + d & 0 \\ 0 & 0 & 0 \end{matrix}) \frac{dy}{y}

+ (\begin{matrix}0 & 0 & 0 \\ 0 & c + d & −(c + d) \\ 0 & −(b + d) & b + d \end{matrix}) \frac{d(y − 1)}{y − 1})u

68. mcmgrs(g,r|dviout=k)

:: ℙ^{1} 内の 5 点以上の点配置に対する KZ 型方程式の同時スペクトル g の変換 KZ 型方程式で mc2grs() にある正方行列 A_{i,j} のインデックスが 0 から一般の N − 1 までの場合を扱う（解を多変数超幾何関数と考えたときの変数の個数は N − 2 個となる）．すなわち

\frac{∂u}{∂x_{i}} = ∑_{j∈\{0,1,...,N−1\}\\{i\}} \frac{A_{i,j}}{x_{i} − x_{j}} u  (i = 0, 1, …, N − 1),
A_{i,i} = 0, A_{i,j} = A_{j,i}, A_{i,N} := −(A_{i,0} + A_{i,1} + ⋯ + A_{i,N−1}),
A_{0,i,j} := A_{0,i} + A_{0,j} + A_{i,j}.

可換な組 (A_{0,i}, A_{j,k}) と (A_{0,i}, A_{0,i,j}) に対する同時固有値（重複度と各固有値）のリストを g として与えることができる（i, j, k は {1, …, N} の中の互いに異なるインデックス）．前者は N ×_{N−1}C_{2} 組，後者は N × (N − 1) 組で，合計\frac{N^{2}(N−1)}{2} 組のデータとなる．スペクトル型や文字列や数で g を指定した場合は, 以下のようになる．

• g が 2 以上の整数の時，自明な g 変数の超幾何に対応する同時固有値のデータを返す (N = g + 2)． • g を，行列 A_{0,N}, A_{0,1}, A_{0,2}, …, A_{0,N−1} のスペクトル型（文字列あるいは， 4 点の GRS）で, こ

の順で指定する．このとき， short=0 を指定すると，インデックス付きのパラメータを使う．

r によって，以下の機能になる． • 0 : 同時固有値のリストのリストをそのまま返す．

• ["deg"] : κ を返す（[ ] は省略可）．

• [[i,j],λ] : A_{i,j} ↦ A_{i,j} + λ, A_{i,N} ↦ A_{i,N} − λ, A_{j,N} ↦ A_{j,N} − λ という addition を返す（0 ≤ i < j < N）． • [μ] : x_{0} 変数に対する middle convolution mc_{x_{0},μ} を行う（アルゴリズムは [O5] によって与えら

れた）．

• [[[i_{1},j_{1}],λ_{1}],…,[μ_{k}],…] : additions と middle convolutions を連続して行う．

• [[a_{1},. . .,a_{N−1}]] : [[[0,1],a_{1}],. . .,[[0,N-1],a_{N−1}]] と同じ．
• [[a_{1},. . .,a_{N−1},μ]] : [[[0,1],a_{1}],. . .,[[0,N-1],a_{N−1}],[μ]] と同じ．

• ["get",[I,J]] : [A_{I}, A_{J}] = 0 に対する同時固有値を返す（ヘッダ [I, J] のついたリスト）．

• ["get",I] : A_{I} に対する固有値を返す（ヘッダ I のついたリスト）．

• ["get",i] (0 ≤ i ≤ N) : i ∈ I を満たす A_{I} に対する GRS を返す（変数 x_{i} についての常微分方程式の GRS）． dviout=1 を指定すると TEX を使って表示する． dviout=-1 では TEX のソースを返す． dviout=2 を指定すると， TEX のソースを書き出すが表示はしない（次回の表示コマンドでまとめて表示する）．

• ["get"] : \frac{(N+1)N}{2} 個全ての A_{i,j} の固有値のリストを返す． dviout=k の指定が可能．

• ["get0",[I,J]], ["get0",I], ["get0",i] (0 ≤ i ≤ N), ["get0"] : "get0" を "get" に変え

たものと同じであるが，ヘッダはつけない．

• ["show"] : 同時スペクトルを TEX を使って表示する．

  dviout=-1 の指定が可能．

• ["show0"] : \frac{N^{2}(N−1)}{2} 組の同時スペクトルの固有値の重複度を示す（順序は， "show"におけると同じ）．

  dviout=1,-1 の指定が可能．

• ["spct"] : スペクトル型を返す． (N + 1) × (N + 1) 行列で (i, j) 成分は， i ≠ j のとき A_{i,j} のスペクトル型， i = j のとき x_{i} についての index of rigidity （0 ≤ i, j ≤ N + 1）． (N + 1) × (N + 1) 行列で (i, j) 成分は， i ≠ j のとき A_{i,j} のスペクトル型， i = j のとき x_{i} についての index of rigidity （0 ≤ i, j ≤ N + 1）． dviout=k の指定が可能．

• ["mult",ℓ_{1},...,ℓ_{m}] : g_{0} = g として g_{i} = mcmgrs(g_{i−1},ℓ_{i}) を i = 1, …, m に対して順に実行して g_{m} を返す．オプションも有効．

[0] os_md.mcmgrs("31,31,31,31,31",["get"]|dviout=1)$
[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

\begin{cases}A_{01} & A_{02} & A_{03} & A_{04} & A_{05} & A_{12} & A_{13} & A_{14} & A_{15} \\ [0]_{3} & [0]_{3} & [0]_{3} & [0]_{3} & [e]_{3} & [0]_{3} & [0]_{3} & [0]_{3} & [−a − e]_{3} \\ a & b & c & d & −a − b − c − d − 3e & a + b + 2e & a + c + 2e & a + d + 2e & −a − b − c − d − 3e \end{cases}

\begin{matrix}A_{23} & A_{24} & A_{25} & A_{34} & A_{35} & A_{45} \\ [0]_{3} & [0]_{3} & [−b − e]_{3} & [0]_{3} & [−c − e]_{3} & [−d − e]_{3} \\ b + c + 2e & b + d + 2e & −a − b − c − d − 3e & c + d + 2e & −a − b − c − d − 3e & −a − b − c − d − 3e \end{matrix}\}

\begin{aligned}& x_{0} & x_{1} & x_{2} & x_{3} & x_{4} & x_{5} & idx \\ x_{0} & & 31 & 31 & 31 & 31 & 31 & 2 \\ x_{1} & 31 & & 31 & 31 & 31 & 31 & 2 \\ x_{2} & 31 & 31 & & 31 & 31 & 31 & 2 \\ x_{3} & 31 & 31 & 31 & & 31 & 31 & 2 \\ x_{4} & 31 & 31 & 31 & 31 & & 31 & 2 \\ x_{5} & 31 & 31 & 31 & 31 & 31 & & 2 \end{aligned}

[A_{01} : A_{23}] = {[a : 0], [0 : 0]_{2}, [0 : b + c + 2e]} ,
[A_{01} : A_{24}] = {[a : 0], [0 : 0]_{2}, [0 : b + d + 2e]} ,
· · · · · ·
[A_{01} : A_{012}] = {[a : a + b + e], [0 : 0]_{2}, [0 : a + b + e]} ,
[A_{01} : A_{013}] = {[a : a + c + e], [0 : 0]_{2}, [0 : a + c + e]} ,
· · · · · ·

69. mmc(l,[μ,a_{1},...,a_{n}]|full=1,homog=1,mult=f)

:: Schlesinger 型常微分方程式および KZ 型方程式の addition+middle convolution Schlesinger 型方程式

\frac{du}{dx} = ∑_{j=1}^{n} \frac{A_{j}}{x − x_{j}} u

または KZ 型方程式

\frac{∂u}{∂x_{i}} = ∑_{j∈\{0,...,n\}\\{i\}} \frac{A_{i,j}}{x_{i} − x_{j}} u  (i = 0, …, n)

の addition または middle convolution を行う．

前者の場合は ℓ に [A_{1}, …, A_{n}]，後者の場合は [A_{0,1}, …, A_{0,n}, A_{1,2}, …, A_{1,n}, …, A_{n−1,n}] （\frac{n(n+1)}{2} 個の成分）を指定する．有理式のリストの場合は， 1 × 1 の行列の成分が並んだリスト，と解釈される．あるいはスペクトル型や GRS を指定する（後者の場合は，変数 x_{0} の常微分方程式について指定する．このときはリジッドである必要がある）．

• [μ, a_{1}, …, a_{n}] : A_{j} （または A_{0,j}）に対して a_{j} を加えた後， x （または x_{0}）変数の middle convolution mc_{μ} を行う，一方のみの指定は， [a_{1}, …, a_{n}] または [μ] とする．

• mult=f : f = 0 は Schlesinger 型， f = 1 は KZ 型を意味する．デフォルトでは， ℓ の成分の数が 6 以上の時に KZ 型， 5 以下では Schlesinger 型とみなす．また，スペクトル型で指定したときは KZ 型とみなす．

• homog=1 : KZ 型の場合 homogeneous middle convolution を行う．すなわち， μ に対応する

middle convolution と，最後の留数行列に −μ に対応する addition を行う．

70. kzext([a_{1}, a_{2}, …, a_{m}]|perm=σ)

:: KZ 方程式の全留数行列を返す Homogenized KZ 方程式

\frac{∂u}{∂x_{i}} = ∑_{ν=\{0,...,n\}\\{i\}} \frac{A_{i,j}u}{x_{i} − x_{ν}} (0 ≤ i ≤ n)

は

A_{i,j} = A_{j,i}, A_{i,i} = 0, A_{i,n+1} = ∑_{ν=0}^{n} A_{i,ν}, ∑_{0≤i<j≤n} A_{i,j} = 0

を満たしている. m = \frac{1}{2}n(n + 1) または m = \frac{1}{2}n(n + 1) − 1 ならば a_{1}, …, a_{m} は

A_{0,1}, …, A_{0,n}, A_{1,2}, …, A_{1,n}, A_{2,3}, … とみなして留数行列 (A_{i,j})\begin{matrix}0≤i≤n \\ 0≤j≤n \end{matrix} を返す.

• 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]
71. linfrac01(ℓ|over=1)

:: x = 0, 1, ∞, y, z, … の一次分数変換のリスト（ℓ = [x, y] etc.） ℓ = [x,y] あるいは ℓ = [x,y_{1}, …, y_{q}] とし， x = (x_{0}, x_{1}, …, x_{q+3}) = (x, 0, 1, y_{1}, …, y_{q}, ∞) （x_{0} = x, x_{1} = 0, x_{2} = 1, x_{3} = y_{1}, …, x_{q+2} = y_{q}, x_{q+3} = ∞）と置く．

• 一次分数変換は {0, 1, …, q + 3} の置換に対応する（q > 1 のときは (q + 4)! 個ある．但し q = 1 のときは， 6 個で {1, 2, 3} の置換に対応する． cf. lft01()）ので，それらを全て得る．

• ℓ = [[x,y]] あるいは ℓ = [[x,y_{1}, …, y_{q}]] とすると対応する置換の組とのリストを返す．

[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)]]
72. lft01(ℓ, t|tr=τ)

:: ℓ = [x,y] または ℓ = [x,y_{1},y_{2},…,y_{q}] に対する特殊一次分数変換 x 変数での特異点は (0, 1, y_{1}, y_{2}, …, y_{q}, ∞) とし， x = (x_{0}, x_{1}, …, x_{q+3}) = (x, 0, 1, y_{1}, …, y_{q}, ∞) （x_{0} = x, x_{1} = 0, x_{2} = 1, x_{3} = y_{1}, …, x_{q+2} = y_{q}, x_{q+3} = ∞）とおく．

• KZ 型方程式

\frac{∂u}{∂x_{i}} = ∑_{j∈\{0,...,q+2\}\\{i\}} \frac{A_{i,j}}{x_{i} − x_{j}} u (0 ≤ i ≤ q + 2),

A_{i,j} = A_{j,i}, ∑_{j∈{0,...,q+3}\{i}}A_{i,j} = 0  (0 ≤ i ≤ q + 3)

と，それを x_{1} = 0, x_{2} = 1 に制限した変数 (x, y_{1}, …, y_{q}) の方程式の変換に応用される．

• 一次分数変換は {0, 1, …, q + 3} の置換に対応する

• t に置換 σ を指定すると，対応する一次分数変換を返す．

• σ = [σ_{0}, …, σ_{q+3}] とすると，特異点特異点 x_{i} = x_{j} は x_{σ_{i}} = x_{σ_{j}} に変わる. すなわち

\frac{∂u}{∂x_{i}} = ∑_{j∈\{0,...,q+2\}\\{i\}} \frac{A_{i,j}}{x_{i} − x_{j}} u (0 ≤ i ≤ q + 2)

→ \frac{∂u}{∂x_{i}} = ∑_{j∈\{0,...,q+2\}\\{i\}} \frac{A_{i,j}}{x_{σ(i)} − x_{σ(j)}} u = ∑_{j∈\{0,...,q+2\}\\{i\}} \frac{A_{σ^{−1}(i),σ^{−1}(j)}}{x_{i} − x_{j}} u

σ は，互換 [i,j] や恒等変換を表す 1 でもよい．番号でなくて ℓ の要素と文字列 "0", "1", "infty" から 2 つの組を指定してもよい．

• ℓ = [[x,y],1] のように指定すると，対応する置換も返す． 1 でなく置換を指定できる．すなわち

    os md.lft01([[x,y],1],σ ∘ σ′) = os md.lft01(os md.lft01([[x,y],1],σ),σ′)

• t が整数の時は，以下の座標変換に対応する．

t 0 < j < q transposition t_{∞} t_{0} t_{1} t_{x} t_{y}  \frac{(t_{x}−t_{0})(t_{1}−t_{∞})}{(t_{x}−t_{∞})(t_{1}−t_{0})}  \frac{(t_{y}−t_{0})(t_{1}−t_{∞})}{(t_{y}−t_{∞})(t_{1}−t_{0})}
∞ 0 1 x y  x  y
−j y_{j} ↔ y_{j+1} (j + 2, j + 3) ∞ 0 1 x  x
0  x ↔ y_{1}  (0,3)  ∞ 0 1 y x  y  x
1  0 ↔ 1  (1,2)  ∞ 1 0 x y  1 − x  1 − y
2  ∞ ↔ 0  (1, q + 3)  0 ∞ 1 x y  \frac{1}{x}  \frac{1}{y}
3  1 ↔ x  (0,2)  ∞ x 0 1 y  \frac{1}{x}  \frac{y}{x}
4  0 ↔ x  (0,1)  ∞ 0 x 1 y  \frac{x}{x−1}  \frac{x−y}{x−1}
5  1 ↔ y  (2,3)  ∞ 0 x y 1  \frac{x}{y}  \frac{1}{y}
6  ∞ ↔ y_{q} (q + 2, q + 3) y_{q} 0 x 1  \frac{x(1−y_{q})}{x−y_{q}}  1 − y _{(q=1)}
7  1 ↔ ∞  (2, q + 3)  1 0 ∞ x y  \frac{x}{x−1}  \frac{y}{y−1}
8  x ↔ ∞  (0, q + 3)  x 0 1 ∞ y  1 − x  \frac{y(x−1)}{x−y}
t = 0  (y_{1}, x, y_{2}, y_{3}, ...)  x_{0} = x ↔ x_{3} = y_{1}
t = −j  (x, y_{1}, ..., y_{j−1}, y_{j+1}, y_{j}, y_{j+2}, ...)  y_{j} ↔ y_{j+1} (1 ≤ j ≤ q − 1)
t = 1  (1 − x, 1 − y_{1}, 1 − y_{2}, 1 − y_{3}, ...)  x_{1} = t_{0} ↔ x_{2} = t_{1}
t = 2  (1/x, 1/y_{1}, 1/y_{2}, 1/y_{3}, ...)  x_{1} = t_{0} ↔ x_{q+3} = t_{∞}
t = 3  (1/x, y_{1}/x, y_{2}/x, y_{3}/x, ...)  x_{0} = x ↔ x_{2} = t_{1}
t = 4  (\frac{x}{x−1}, \frac{x−y_{1}}{x−1} , \frac{x−y_{2}}{x−1} , \frac{x−y_{3}}{x−1} , ...)  x_{0} = x ↔ x_{1} = t_{0}
t = 7  (\frac{x}{x−1}, \frac{y_{1}}{y_{1}−1}, \frac{y_{2}}{y_{2}−1}, \frac{y_{3}}{y_{3}−1}, ...)  x_{2} = t_{1} ↔ x_{q+3} = t_{∞}
t = 8  (1 − x, \frac{y(x−1)}{x−y}, \frac{y_{2}(x−1)}{x−y_{2}}, \frac{y_{3}(x−1)}{x−y_{3}}, ...)  x_{0} = x ↔ x_{q+3} = t_{∞}
[figure: t_{∞}; t_{0}; 2; t_{1}; 1; x; 3; y_{1}; 0; y_{2}; −1; ⋯; y_{q−2}; y_{q−1}; 2−q; y_{q}; 1−q]
[figure: x_{0}; x; x_{1}; 0; 4; x_{2}; 1; 1; x_{3}; y_{1}; 5; x_{4}; y_{2}; −1; x_{5}; y_{3}; −2; ⋯; x_{q+1}; y_{q−1}; x_{q+2}; y_{q}; 1−q; x_{q+3}; ∞; 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

73. okubo3e([p_{0,1}, …, p_{0,m}],[p_{1,1}, …, p_{1,n}],[p_{2,1}, …, p_{2,m+n}|opt=1]) :: 0, 1, ∞ に確定特異点を持つ m + n 階の単独 Okubo 型微分作用素を求める 0 で n 次元， 1 で m 次元の正則解をもつ． Riemann scheme の記号では

℘ \begin{cases}0 : & 0 & 1 & ⋯ & n − 1 & p_{0,1} & . . . . . . . . . . . . . . . . . & p_{0,m} \\ 1 : & 0 & 1 & . . . . . . . . . . . . . . . . & m − 1 & p_{1,1} & ⋯ & p_{1,n} & ; x \\ ∞ : & p_{2,1} & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & p_{2,m+n} \end{cases}\}

Fuchs の関係式 : ∑ p_{i,j} = mn アクセサリパラメータが (m − 1)(n − 1) 個あり， r1,r2, … で表される． p_{i,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)*b
+(-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]

74. fuchs3e([p_{0,1}, …, p_{0,n}],[p_{1,1}, …, p_{1,n}],[p_{2,1}, …, p_{2,n}]) :: 0, 1, ∞ に確定特異点を持つ n 階の Fuchs 型微分作用素を求める

℘ \begin{cases}0 : & p_{0,1} & p_{0,2} & ⋯ & p_{0,n} \\ 1 : & p_{1,1} & p_{1,2} & ⋯ & p_{1,n} & ; x \\ ∞ : & p_{2,1} & p_{2,2} & ⋯ & p_{2,n} \end{cases}\}

Fuchs の関係式 : ∑ p_{i,j} = \frac{n(n−1)}{2} アクセサリパラメータが\frac{(n−1)(n−2)}{2} 個あり， ri_j で表される（cf. getbygrs()）． p_{i,j} のうちの一つは "?" でもよい（値は Fuchs の関係式から計算される）．

75. ghg([p_{1,1}, p_{1,2}, ..., p_{1,m}],[p_{2,1}, p_{2,2}, ..., p_{2,n}])

:: 一般超幾何函数_{m}F_{n}(p_{1}; p_{2}; x) （cf. seriesHG()）の満たす微分作用素

P (x, \frac{d}{dx}) = ∏_{j=1}^{n}(x\frac{d}{dx} + p_{2,j}) · \frac{d}{dx} − ∏_{j=1}^{m}(x\frac{d}{dx} + p_{1,j})

mF_{n}(p_{1,1}, …, p_{1.m}; p_{2,1}, …, p_{2,n}; x) = ∑_{n=0}^{∞} \frac{∏_{ν=1}^{m}(p_{1,ν})_{n}}{∏_{ν=1}^{n}(p_{2,ν})_{n}} \frac{x^{n}}{n!}

変数は x，微分は dx で表記される． m = n + 1 のときは Rigid な Fuchs 型で

℘ \begin{cases}0 : & 0 & 1 − p_{2,1} & ⋯ & 1 − p_{2,m−2} & 1 − p_{2,m−1} \\ 1 : & 0 & 1 & ⋯ & m − 2 & −γ & ; x \\ ∞ : & p_{1,1} & p_{1,2} & . . . . . . . . . . . . . . . . & p_{1,m} \end{cases}\}

Fuchs の関係式： γ = ∑ p_{1,ν} − ∑ p_{2,ν} m = 2, n = 1 のときが Gauss の超幾何

 [0] os_md.ghg([a,b],[c]);
 (-x^2+x)*dx^2+((-a-b-1)*x+c)*dx-b*a
76. ghg2([a_{1}, a_{2}, . . . , b],[a′_{1}, a′_{2}, . . . , b′]|raw=1,all=1,symbol=1,var=v)

:: 多変数の一般化超幾何級数の微分方程式 a_{i} are lists [a_{i,1}, a_{i,2}, …]. If a_{i} is a scalar. a_{i} is replaced by [a_{i}].

u(x_{1}, x_{2}, …) = ∑_{m_{1}≥0, m_{2}≥0,...} \frac{∏_{i} ∏_{j}(a_{i,j})_{m_{i}} ∏_{k}(b_{k})_{m_{1}+···}}{∏_{i} ∏_{j}(a′_{i,j})_{m_{i}} ∏_{k}(b′_{k})_{m_{1}+···}} x_{1}^{m_{1}}x_{2}^{m_{2}} ⋯

Get the equation satisfied by this series modulo constant. Default : (x_{1}, x_{2}, x_{3}, x_{4}) = (x, y, z, w) if the number of variables ≤ 4.

• all=1 : get full equation

• raw=1 : get reduced equation if (a′_{1})_{1}(a′_{2})_{1} ⋯ = 0

• symbol=1 : get the generator of the symbol ideal The equations satisfied by F_{1}(a; b, b′; c; x, y), F_{2}(a; b, b′; c, c′; x, y), F_{3}(a, a′; b, b′; c; x, y), F_{4}(a; b; c, c′; x, y) are given by

os md.ghg2([b,b′,a],[0,0,c]),
os md.ghg2([b,b′,c],[[0,c],[0,c′],[]]),
os md.ghg2([[a,b],[a′,b′],[]].[0,0,c]),
os md.ghg2([[],[],[a,b]],[[0,c],[0,c′],[]]).
 [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]

77. even4e([p_{1,1}, p_{1,2}, p_{1,3}, p_{1,4}],[p_{2,1}, p_{2,2}])

:: 4 階 even family (Rigid)

℘ \begin{cases}0 : & 0 & 1 & p_{2,1} & p_{2,2} \\ 1 : & 0 & 1 & p_{0} & p_{0} + 1 & ; x \\ ∞ : & p_{1,1} & p_{1,2} & p_{1,3} & p_{1,4} \end{cases}\}

Fuchs relation : 2p_{0} + p_{1,1} + p_{1,2} + p_{1,3} + p_{1,4} + p_{2,1} + p_{1,2} = 3

78. odd5e([p_{1,1}, p_{1,2}, p_{1,3}, p_{1,4}, p_{1,5}],[p_{2,1}, p_{2,2}])

:: 5 階 odd family (Rigid)

℘ \begin{cases}0 : & 0 & 1 & p_{2,1} & p_{2,2} & p_{2,2} + 1 \\ 1 : & 0 & 1 & 2 & p_{0} & p_{0} + 1 & ; x \\ ∞ : & p_{1,1} & p_{1,2} & p_{1,3} & p_{1,4} & p_{1,5} \end{cases}\}

Fuchs relation 2p_{0} + p_{2,1} + 2p_{2,2} + ∑ p_{1,j} = 4

79. rigid211([p_{0,1}, p_{0,2}],[p_{1,1}, p_{1,2}],[q_{0}, q_{1}])

:: Type 211,211,211

℘ \begin{cases}0 : & 0 & 1 & p_{0,1} & p_{0,2} \\ 1 : & 0 & 1 & p_{1,1} & p_{1,2} & ; x \\ ∞ : & q_{0} & q_{0} + 1 & q_{1} & q_{2} \end{cases}\}

Fuchs relation : p_{0,1} + p_{0,2} + p_{1,1} + p_{1,2} + 2q_{0} + q_{1} + q_{2} = 4

80. extra6e([p_{1,1}, p_{1,2}, p_{1,3}, p_{1,4}, p_{1,5}, p_{1,6}],[p_{2,1}, p_{2,2}]) :: Extra case (Rigid)

℘ \begin{cases}0 : & 0 & 1 & p_{2,1} & p_{2,1} + 1 & p_{2,2} & p_{2,2} + 1 \\ 1 : & 0 & 1 & 2 & 3 & p_{0} & p_{0} + 1 & ; x \\ ∞ : & p_{1,1} & p_{1,2} & p_{1,3} & p_{1,4} & p_{1,5} & p_{2,6} \end{cases}\}

Fuchs relation : 2p_{0} + 2p_{2,1} + 2p_{2,2} + ∑ p_{1,j} = 5

81. eofamily([p_{0,1}, p_{0,2}],[p_{1,1}],[p_{2,1}, …, p_{2,n}]) :: Even/odd family (obsolete)

82. ev4s(p_{1},p_{2},p_{3},p_{4},p_{5})

:: Heckman-Opdam 超幾何の (BC_{2}, BC_{1}) 型制限常微分 (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]

83. b2e(p_{1},p_{2},p_{3},p_{4},p_{5})

:: Heckman-Opdam 超幾何の (BC_{2}, A_{1}) 型制限常微分 (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]

84. heun([a, b, c, d, e],p,r|)

:: Heun の微分方程式を与える． r はアクセサリパラメータ

℘ \begin{cases}0 : & 0 & c \\ 1 : & 0 & d & ; x \\ p : & 0 & e \\ ∞ : & a & b \end{cases}\} Fuchs relation : a + b + 1 = c + d + e

[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

85. 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 で設定する．

86. 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)
87. isMs()

:: Microsoft Windows 環境かどうか調べる環境変数 temp, tmp を調べて 3 文字目が ¥(あるいは \ ) であれば 1 を返す

88. isyes(p|set=ℓ)

:: 1 か 0 を返す函数を定義し，それを使う

• set=1 によって定義する．このとき p は函数とそれに渡すパラメータリストと判断に使うその函

数の値をチェックする範囲との 3 つからなるリスト．すなわち p = [fn,[t_{1},t_{2},…],[a,b]] ならば， isyes(X|set=p) は

    def foo(X){
      R=fn(X,t_{1},t_{2},. . .);
      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);
0
[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]]);
}$
89. 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]);

[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
90. 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]);
3
[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
91. getline(Id|Max=m,CR=[r_{1},r_{2},..],LF=[l_{1},l_{2},...])
:: get line() の拡張版

ファイルから 1 行入力する（改行コードは削除）． • m で 1 行の最大 byte 数を指定（デフォルトは 1023）

• r_{1}, r_{2},… は無視するコード（デフォルトは [13]）

• l_{1}, l_{2},… は行の末尾示すコード（デフォルトは [10]）

92. keyin(s)

:: s を表示し， 1 行のキー入力を待って，それを文字列として返す行末の改行記号を削除した文字列を返す． s の表示には mycat0() を使うので，数字やリストでも可．

[0] S=os_md.keyin("Input? ")$
Input? This is a pen.
[1] S;
This is a pen.
93. showbyshell(s)

:: shell でコマンド s を実行した標準出力の結果を Risa/Asir で表示

[0] os_md.showbyshell("echo %temp%")$
[1] os_md.showbyshell("dir c:\\")$
94. 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 で定義されたディレクトリ

に作成される．前回用いられたファイルを消去してから新たにファイルが作られる.

95. fcat(f,s|exe=1)

:: ファイル f に s を書き出す

• ファイル f に print(s) を書き出す．ファイル f が存在していれば追記．なお，ファイル f を削除するには remove file(f) とすればよい．以下では， DIROUT で設定されたディレクトリのファイルとなる．

• f = 0 : デフォルトのファイル fcat.txt に追記する．

• f = 1 : デフォルトのファイルに上書きする．

• f = 2, …, 9 : ファイル fcatf.txt に上書きする．

• f = −1 : デフォルトのファイル名を返す．

• exe=1 : 出力した後に関連づけされたプログラム（通常はエディター）に渡す．

96. 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}

97. shortv(p,[v_{1},v_{2}, . . .]|top=w)

:: p の添字番号つき不定元 v_{1}, … を一文字の w 以下の変数名に変える不定元 v_{i} は一文字の不定元で，それに添え字番号は 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]
98. 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);
[z_2,z_3,z_4]
[4] os_md.makenewv(z_2*sin(cos(z_0+z_1))+z_3);
z_4
99. isvar(p)

:: p が変数かどうか調べる p が変数のとき 1, そうでないとき 0 を返す

[0] os_md.isvar(dx);
1
[1] os_md.isvar(-dx);
0
[2] os_md.isvar(1);
0
100. 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]]
101. 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);
[[log(x),log,x]]
102. 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);
0
103. mysubst(r,[v_{1},r_{1}]|inv=1) mysubst(r,[[v_{1},r_{1}], . . .]|inv=1)
mysubst(r,[ℓ_{1},ℓ_{2}]|lpair=1,inv=1)

:: subst(r,v_{1},r_{1}, …) と同等． r が複雑で r_{1} が有理式のときに特に有効．

• r は有理式やそれを成分とするリスト，ベクトル，行列（再帰的）とするが， subst() と異なり，文字列の成分があってもよい（文字列の成分は変換されない）．

• r_{j} も不定元のとき inv=1 が指定可能で，逆向きの置き換え（v_{j} と r_{j} を取り替えた変換）を行う． • inv=1 を指定すると，逆変換をする．

• lpair=1 を指定すると，リスト ℓ_{1} の各不定元を順に ℓ_{2} の各式に置き換える．

ただし， ℓ_{1} の成分の個数が 3 以上なら lpair=1 が指定されていると解釈される．

104. myswap(p,[x_{1},x_{2},. . .,x_{n}])

:: 有理式またはそのリストなどの不定元の巡回置換 (x_{1}, x_{2}, …, x_{n}) 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]
105. substnum(l,s,t|depth=d)

:: リストまたはベクトルの成分の置き換え

• s=[s_{1},s_{2}, …], s=[t_{1},t_{2}, …] のとき，ベクトルまたはリストの成分の s_{i} を t_{i} で置き換える．ただし， s_{i} は数字あるいは数式

• depth=d : 深さ d のリスト（またはベクトル）の成分を置き換える（デフォルトは d = 0）．

• depth=[d_{1},d_{2}, …] : 深さ d_{i} のリスト（またはベクトル）の成分を置き換える．

[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]]

106. mulsubst(r,[[p_{1,0}, p_{1,1}],[p_{2,0}, p_{2,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 に複数同時の代入，有理変換の合成, Pfaff 形式の有理変換

• p_{j,0} ↦ p_{j,1} (j = 1, 2, …) を同時に行う

 • [[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]
107. fmult(f,m,ℓ,n| · · ·)

:: m_{i} ↦ m_{i+1} = f(m_{i},ℓ[i],n[0], n[1], … | ⋯) という変換（m_{0} = m）の最終結果 m_{length(l)} を返す • ℓ と n はリスト．

• オプション指定はそのまま渡される．

108. mtransbys(f,m,ℓ| · · ·)

:: スカラーに関する変換 f() をリスト，ベクトルまたは行列 m に拡張する • m の各成分 m_{ν} を f(m_{ν}, l[0], l[1], …|⋯) と変換する．

• リスト，ベクトルまたは行列はネストしていてもよい（行列のリストなど）．

• 引数はリスト ℓ にしてまとめる．

• オプション指定はそのまま渡される．

• 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]]
109. mmulbys(f,m,n,ℓ| · · ·)

:: 和が定義された objects の 2 つに対して 1 つの object を与える演算 f を， objects を成分とするベクトルまたは行列 m と n の演算に拡張する

• 引数はリスト ℓ にしてまとめる． m は object または行列．

• m と n が行列のときは以下の行列を返す． (∑_{ν} f(m_{i,ν}, n_{ν,j}, ℓ[0], ℓ[1], …))_{i,j} • m または n がスカラーのときは，他方（の成分）にそのスカラーを掛けた結果を返す．

• m がベクトルのときは行ベクトル， n がベクトルのときは列ベクトルとみなし，同様の計算をして（上で， i または j のインデックスがないと考える），結果をベクトルで返す．ただし m と n が共に（同じサイズの）ベクトルのときは，結果はスカラーで返す．

• オプション指定はそのまま渡される．

110. 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                                             /* 大小比較 */
111. simplify(p,ℓ,t|var=[x_{1}, x_{2}, . . .])

:: ℓ の一次関係式を使って p を簡単化

• ℓ = [ℓ_{0}, ℓ_{1}] のときは p （の各要素毎）に subst(*, ℓ_{0}, ℓ_{1}) を調べてより簡単なら置き換える（t = 1 ∼ 7）．

• ℓ = [ℓ_{1}] で ℓ_{1} が多項式のときは， ℓ_{1} に一次に含まれる含まれる変数の線形関係式とみて簡単化する．

• 複数調べるときは ℓ をリストや多項式のリストとする．

• iand(t,1)!=0 のときは変数の個数を， iand(t, 2)!=0 のとき単項式の個数を， iand(t, 4)!=0 のときは表示の長さを基準に，この順で比較し，差があった時点で簡単とみなす．

• この比較で等しいときは，両者を直接比べて小さい方とする．

• 複数の置き換えを試すときは， ℓ = [[ℓ_{00}, ℓ_{01}], [ℓ_{10}, ℓ_{11}], …] とする．

• var=[x_{1}, x_{2}, …] を指定すると， p を x_{1}, x_{2}, … の有理式とみて，その分母分子の多項式の係数毎に単純化する．

[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-y
112. getel(m,i)

:: m がリスト，ベクトル，行列で i が非負整数なら m[i] を返す i が [i_{1}, i_{2}] というリストで m が行列ならば m[i_{1}][i_{2}] を返す

それ以外では m をそのまま返す

113. evalred(r|opt=[[s_{1},t_{1}],[s_{2},t_{2}]...])

:: sin(0), cos(0), exp(0) などを 0, 1, 1 などの整数に置き換える

• 置き換えは，以下のものの値

   sin(k@pi), cos(k@pi) で値が 0, ±1, ±\frac{1}{2} のいずれかになるもの， tan(0), asin(0), atan(0),
   sinh(0), cosh(0), tanh(0), exp(0), log(1), pow(1,x), 1^x

• s_{j} を t_{j} で置き換える（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
114. evals(r|del=s,raw=1)

:: 文字列あるいは函数を評価する．

• r が文字列のときは， eval_str(s) を返す．さらに del=s が指定されたときは，文字列 s を区切り記号として区切られた文字列を評価して，順にリストとして返す．ただし， raw=1 が指定してあると，評価せずに文字列のリストに分割して返す．

• r がリスト [r_{0},r_{1}, …] のとき， r_{0} が文字列でなければ r_{0} を函数とみなして

r_{0}(r_{1},r_{2}, …) を返す． r_{0} が文字列の時も同様なものを返す．引数 r_{1}, … の中に文字列があれば，それは eval_str() によって得られる値として変換される（execproc() も似た機能の函数）．

[0] os_md.evals("(x+1)^2");
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)
115. myeval([r,[x_{1},f_{1},v_{1}],[x_{2},f_{2},v_{2}],. . .])
:: os_md.myeval(subst([r,[x_{2},f_{2},v_{2}],. . .],x_{1},f_{1}(os_md.myeval(v_{1})))) を返す
 os_myeval([r])=map(eval(r))
116. mydeval([r,[x_{1},f_{1},v_{1}],[x_{2},f_{2},v_{2}],. . .])
:: os_md.mydeval(subst([r,[x_{2},f_{2},v_{2}],. . .],x_{1},f_{1}(os_md.mydeval(v_{1})))) を返す
 os_md.mydeval([r])=map(deval(r))

• r は有理式成分のベクトルや行列やリストなどでもよい．

• 引数が多項式や有理式 r のときは， eval(r) または deval(r) に置き換えられる．

• 引数がベクトルや行列 r のときは， map(eval,r) または map(deval,r) に置き換えられる．

• v_{1}, v_{2}, … は，数でなくてそれぞれ myeval() で値が求まるものでもよい（ネスティング可能で，

合成函数に対応する）．

• 函数 f_{1}, … は， dsin などの函数のほか，引数を数とし，数を返す函数で（ユーザが定義したもので）もよい．より一般に定義されたものが解釈可能であればよい．

• f_{1} = 0 のときは，恒等写像と解釈される．

• 函数 f_{1} の引数が複数あるときは [x_{1},f_{1},v_{1,1},v_{1,2}, …] と指定すると f_{1}(os_md.myeval(v_{1})) は

    f_{1}(os_md.myeval(v_{1,1}),os_md.myeval(v_{1,2}),. . .)

• v_{1}, v_{2}, … や v_{1,1}, v_{1,2}, … がリストのときは，それらを [v_{1}], [v_{1,2}] のように指定する（mydeval()

   や myeval()でなくて deval() や eval() で評価される）．

• 函数 f_{1} にオプションパラメータを付加して用いるときは， f_{1} の代わりに [f_{1},opt] のように函数とそのオプションリストの組のリストとして指定する．ただし opt は [[s_{1},v_{1}],[s_{2},v_{2}],…]] の形で， s_{j} はオプション文字列， v_{j} はその値である（getopt() で得られる形式）．

• f_{2} 以下についても同様．

 • 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
[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

117. myval([r,[x_{1},f_{1},v_{1}],[x_{2},f_{2},v_{2}],. . .])

:: myeval() と同様な函数であるが，可能な限り正確な値を返す • 三角関数は，その引数が r*@pi で 4r または 6r が整数のときに正確な値を返す．

• 指数関数は，その引数が整数または指数または r*@i*@pi で 4r または 6r が整数のときに正確な値を返す．

• 対数関数は，その引数が@e または 1 のとき正確な値を返す．

• べき函数 x^{y} において， x が 0 または 1 あるいは y が整数のとき，あるいは y = \frac{1}{2} で x が有理数のときは正確な値を返す．

• 実数の絶対値は正確な値を返す．

• 正確な戻り値には，有理数の他，\sqrt{−1}, \sqrt{m} （m は正整数）が含まれることがある．

[0] os_md.myval(sin(@pi));

[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

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

sin π = 0,  4^{sin ^{\frac{π}{6}}} = 2,  2^{exp πi} = \frac{1}{2},
2 exp \frac{π}{3} i = 1 + \sqrt{3}i,  (\frac{2}{3})^{sin ^{\frac{π}{6}}} = \frac{\sqrt{6}}{3},  |1 − \sqrt{2}| = \sqrt{2} − 1.

118. f2df(f|opt=n)

:: 函数 f から sin などの函数子を除いて myeval() や mydeval() の引数のリスト形式函数に変換

 • 函数子 sin,cos,tan,asin,acos,atan,asin,acos,sinh,cosh,tanh,exp,log,pow を含んだ

函数，および x^{y} の形のべきの函数を含んだ函数から，それらを除いたリスト形式函数に変換する． • 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 ]
119. todf(f,[v_{1},. . .,v_{n}]) todf([f,[ops]],[v_{1},. . .,v_{n}])

:: 函数子 f で変数が v_{1}, …, v_{n} のリスト形式函数を得る（n は f の引数の数） • [ops] は f に渡すオプションリスト（getopt() で得られる形式）．

• n = 1 で v_{1} がリストでないときは， [v_{1},…,v_{n}] は単に v_{1} としていしてもよい．

• v_{j} は数値，不定元，有理式，リスト形式函数など f2df() で解釈できる函数でよい．以下では|z|, [2 exp \frac{x}{2}], ζ(\frac{1}{2} + \sqrt{−1}x), |ζ(\frac{1}{2} + \sqrt{−1}x)| に対応するリスト形式函数を得ている．

    [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
120. 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]]
121. compdf(f,x,g)  compdf(f,[x_{1},x_{2}, . . .],[g_{1},g_{2}, . . .])

:: リスト形式函数 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) を指定したとみなす．

• 変数 x_{1}, x_{2}, … にそれぞれリスト形式函数 g_{1}, g_{2}, … を代入するときは， x = [x_{1}, x_{2}, …], g = [g_{1}, g_{2}, …] とすればよい．

[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]]]]
122. cutf(f,x,[[x_{1},v_{1}],[x_{2},v_{2}],...,[x_{n},v_{n}]])  cutf(f,x,[t,[x_{1},v_{1}],...,[x_{n},v_{n}]])

:: 函数 f の変数が特定の範囲のとき函数値の変更を行い，その値またはリスト形式函数を返す • 第 3 引数のリストの個数 n は 2 以上で， x_{1} ≤ x_{2} < x_{2} < ⋯ < x_{n−1} ≤ x_{n} を満たす必要がある． • x < x_{1} の場合は v_{1} を返す， v_{1} は（リスト形式函数）でもよい（myfeval(v_{1},x) を返す）．

第 3 引数の最初の要素が [] のときは，その項は無視される．

• x > x_{n} の場合は v_{n} を返す．第 3 引数の最後の要素が [] のときは，その項は無視される．

• 1 < j < n で x = x_{j} のときは v_{j} を返す． v_{j} はリスト形式函数でもよい．

• 上記以外の時は f(x) を返す．

• f の変数が x でないときは，それを第 3 引数の最初の要素として指定する．たとえば [t,[x_{1},v_{1}],…] などとする．

• 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);
0
123. periodicf(f,[a,b],x)  periodicf(ltov([g_{1},g_{2},...,g_{n}]),c,x)

:: x を変数とする函数 f|_{[a,b)} を周期関数に拡張した函数にする • x − k(b − a) の値 y が a ≤ y < b となる整数 k を選んで f(y) を返す．

• [\frac{x}{c}] − kn の値が 0 以上 n 未満の数となる整数 k と， x − (kn + ℓ)c の値 y が 0 以上 c 未満にある ℓ を選んで g_{ℓ+1}(y) を返す． g_{k} は数値，あるいは（リスト形式）函数．

• x が不定元のとき， x を変数とする上のようなリスト形式函数にして返す．

[0] os_md.periodicf(x^2,[-1,1],0.2);
0.04
[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]]]]
124. cmpf([f,[a,b]]|exp=c)    cmpf(x)

:: 積分区間をコンパクト閉区間 [0, 1] に直した函数にする

• [f,[a,b]] によって ∫_{a}^{b} f(x)dx = ∫_{0}^{1} g(x)dx となる函数 g(x) を定義し，それをリスト形式函数として返す．

新たな定義をするまでは， cmpf(x) は g(x) を返す．

• a ="-infty"は a = −∞ を， b ="infty"は b = ∞ を意味し，無限区間の積分を有限区間の積分に変換する．なお， "-infty"， "infty"は任意の文字列でよい．

• exp のオプションを指定しない場合は以下で c = −1 とする． exp=c と負数 c を指定した場合も含めて [a,∞] で a が有限のときは g(x) = \frac{f(a+ \frac{x}{C(1−x)} )}{C(1−x)^{2}} (C = \frac{|c|}{4}).

[−∞,b] で b が有限のときは g(x) = \frac{f(b+1− \frac{1}{Cx})}{Cx^{2}} (C = \frac{|c|}{4}).

[−∞,∞] のときは g(x) = (\frac{1}{C(1−x)^{2}} + \frac{1}{Cx^{2}} )f(\frac{1}{C(1−x)} − \frac{1}{Cx}) (C = 2|c|)

• exp=c と正数 c を指定すると [a,∞] で a が有限のときは g(x) = ^{\frac{e^{\frac{x}{1−x}}}{C(1−x)^{2}}} f(^{\frac{e^{\frac{x}{1−x}} −1}{C}} + a) (C = \frac{c}{6}).

[−∞,b] で b が有限のときは g(x) = \frac{e^{1− \frac{1}{x}}}{Cx^{2}} f(\frac{1−e^{\frac{1}{x}}}{C} + b) (C = \frac{c}{6}).

[−∞,∞] のときは g(x) = (\frac{e^{\frac{1}{x}}}{Cx^{2}} + ^{\frac{e^{\frac{1}{1−x}}}{C(1−x)^{2}}} )f(^{\frac{e^{\frac{1}{1−x}} −e^{\frac{1}{x}}}{C}} ) (C = 12c).

• f はリスト形式函数でもよい．

 • cmpf([1/(1+x^2),["",""]]) で得られる関数は

g(x) = cmpf(x) = \begin{cases}\frac{2}{2x^{2}−2x+1} & x ∈ [0, 1], \\ 2 & x ∉ [0, 1]. \end{cases}

• areabezier() で使われている（例にあるグラフを参照）．

125. myfeval(f,x) (f,a)  myfeval(f,[x,a])  myfeval(f,[[x_{1},a_{1}],. . .])
126. myfdeval(f,a)  myfdeval(f,[x,a])  myfdeval(f,[[x_{1},a_{1}],. . .])

:: myeval() や mydeval() の引数のリスト形式函数 f の変数に a を代入して値を得る • f の変数がデフォルトの x でなくて v のときは x を [v,x] とする．

• f の複数の変数に代入するときは第 2 引数を [[x,0.5],[y,3]] などのようにする．

127. myf2eval(f,x,y)
128. myf2deval(f,x,y)

:: myeval() や mydeval() の引数のリスト形式 2 変数函数 f に代入して値を得る

129. myf3eval(f,x,y,z)
130. 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]

などと同様な結果を得る．

131. execproc(ℓ|all=1,var=k)

:: リスト形式手続きの実行リスト形式手続きとは，函数，引数リスト，オプションリストの 3 つ組のリストを並べたリスト．すなわち ℓ=[ℓ_{1},ℓ_{2},⋯] で， ℓ_{j}=[f_{j},v_{j},p_{j}] となっているとき call(f_{j},v_{j}|option list=p_{j}) を j = 1, 2, … と実行する．

• オプションがない場合は，略して ℓ_{j}=[f_{j},v_{j}] としてよい．

• 最後の函数の戻り値が返される．

• 不定元 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]
132. fsum(f,[m,n,d]|df=1,subst=1)  fsum(f,[x,m,n,d]|df=1,subst=1)

:: 一般項が f(x) で与えられる級数の和 ∑_{k=0}^{[ \frac{m−n}{d}]} f(m + kd) を返す • f の変数がデフォルトの x のときは，変数 x の指定は不要．

• d が指定されていないときは， d = 1 と解釈される．

• df=1 が指定されていると， f を f2df(f) に置き換えてから処理する．

• 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 + \frac{2}{3}x^{3} + \frac{2}{5}x^{5} + \frac{2}{7}x^{7}

[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()
133. fint(f,n,[t_{1},t_{2}]]|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 は分割の数， [t_{1},t_{2}] は積分区間を表す．

• 積分区間で， t_{1} ="-" は −∞ を， t_{2} ="+" は +∞ を表す．

• 変数が x でなくて t のとき，積分区間と合わせて第 3 引数に [t,t_{1},t_{2}] と指定する．

• 実変数関数 f が複素数値のとき， cpx=1 を指定する（たとえば 1/(x^2+@i) のとき） . 複素積分

• 複素積分のとき，函数 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| 分割し，分割の中点での値の平均を使って近似計算する．\frac{sin x}{x} の [0, 2π] での積分などに便利（端点の値は使わない）．

– int=1 を指定すると， |n| 分割して台形公式で近似計算する．

– int=2 を指定すると， |n| 分割してシンプソンの公式で近似計算する．このとき， n が奇数なら |n| + 1 分割する．

– int=3 を指定すると， 2^{k} (1 ≤ k ≤ n）分割の台形公式をもとに n 段の Romberg 積分で近似計算する． – int=4 を指定すると， 2^{k} (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] はそれぞれ次の積分を表す．

∫_{−∞}^{∞} \frac{dx}{x^{2} + 1} = π, ∫_{−∞}^{∞} \frac{\sqrt{2} dx}{x^{2} + \sqrt{−1}} = π − π\sqrt{−1}, ∫_{|z|=1} \frac{dz}{2z} = π\sqrt{−1}, ∫_{|z|=1} \frac{e^{\frac{1}{z}}}{2} dz = π\sqrt{−1}.

[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)
[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

Bézier 曲線を使った数値積分の相対誤差

非積分関数積分範囲指定  16 分割  32 分割  96 分割  384 分割  1536 分割
\frac{1}{x^{2}+1}  −∞ < x < ∞ (n, −) 1.3 × 10^{−5} 1.3 × 10^{−7} 8.5 × 10^{−10} 4.7 × 10^{−12} 2.1 × 10^{−14}
\frac{1}{x^{2}+\sqrt{−1}} −∞ < x < ∞ (n, −) 2.3 × 10^{−3} 1.7 × 10^{−4} 2.6 × 10^{−6} 1.9 × 10^{−8} 8.1 × 10^{−11}
e^{\frac{1}{z}}  |z| = 1  (−n, −) 7.6 × 10^{−5} 4.1 × 10^{−6} 4.8 × 10^{−8} 1.9 × 10^{−10} 7.3 × 10^{−13}

134. 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)
135. 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));
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 = −\frac{i}{2} exp(xi) + \frac{i}{2} exp(−xi),
4 cos^{2} x · exp^{2} x = 2 exp 2x + exp((2 − 2i)x) + exp((2 + 2i)x).

inv=1 を指定した上の例は

16 sin^{5} x = sin 5x − 5 sin 3x + 10 sin x,
4x sin^{2} x · cos x = x(cos x − cos 3x).

inv=sin(x) または inv=cos(x) を指定した上の例は

sin 5x = 16 sin^{5} x − 20 sin^{3} 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 · cos^{2} x − cos y
= −2 cos y · sin^{2} x − 2 sin y · cos x · sin x + cos y,
cos(2x + \frac{π}{2} ) = −2 sin x · cos x,
2 cos(2x + \frac{π}{6} ) = 2\sqrt{3} cos^{2} x − sin x · cos x − \sqrt{3}.

inv=cos(x/3) を指定すると

cos x = 4 cos^{3} \frac{x}{3} − 3 cos \frac{x}{3}.

inv=cos(x+@pi/3) を指定すると

2 cos x = cos(x + \frac{π}{3} ) + \sqrt{3} sin(x + \frac{π}{3} ).

inv=tan(x) を指定すると

tan 3x = \frac{tan^{3} x − 3 tan x}{3 tan^{2} x − 1}.

136. isshortneg(f)

:: f と −f を表現する文字列の長さの比較 −f の表示文字列の長さが f の表示文字列の長さより短いかどうか判定する．

[0]  os_md.isshortneg(x-(x-1)^2);
1
137. fshorter(f,x)

:: x の三角関数の簡単化 • 三角関数の有理函数を自動的に簡単化する．

• 現れる三角関数の変数の比は有理数になっている必要がある．

[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
138. fzero(f,[x,x_{1},x_{2}]|mesh=m,dev=d,zero=1,trans=1,cont=1)

:: 実数値函数 f の零点を求める • 函数 f は myeval() の引数の形でもよい．

• x は変数で，区間 [x_{1}, x_{2}] での零点を求める．変数 x がデフォルトの x のときはそれを省略して，二番目の引数は [x_{1},x_{2}] でよい．

• 戻り値は，零点の近似値とそこでの f の値の組のリスト

• f が多項式や有理式のときは分子の多項式の零点を調べる．その次数が 2 以下の時は根の公式を，それ以上の次数の時は polroots() を使う．

• mesh=m : 区間を m 等分してその小区間の両端で f の符号が変わるときに，その間の零点をひとつずつ求める．デフォルトは m = 1024.

• dev=d : 小区間の両端の値で函数のグラフを線分で近似したときの零点または両端の中点での函数の値を順に調べて（前者は奇数回目，後者は偶数回目）零点の近似計算をするが，その繰り返しの最大回数．デフォルトは d = 16.

• zero=1 : 区間 [x_{1}, x_{2}] の両端で 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]]
139. fmmx(f,[x,x_{1},x_{2}]|mesh=m,dev=d,mmx=1,zero=1,trans=1,cont=1,dif=1)

:: 実数値函数 f の極値を求める • 函数 f は myeval() の引数の形でもよい．

• x は変数で，区間 [x_{1}, x_{2}] での極値を求める．変数 x がデフォルトの x のときはそれを省略して，二番目の引数は [x_{1},x_{2}] でよい．

• 戻り値は，極値をとる x の近似値とそこでの f の値の組のリスト

• mmx=1 : 極値でなくて最大値と最小値を求める． [[x_{min},f(x_{min})],[x_{max},f(x_{max})]] が戻り値で， f(x_{min}) が最小値， f(x_{max}) が最大値．

• mesh=m : 区間を m 等分してその隣接した 2 つの小区間の隣接点での函数の値が両端での値の間にないときその間の極値をひとつずつ求める．デフォルトは m = 1024.

• dev=d : 上で調べる隣接区間をそれぞれ 2 等分してできる 3 組の隣接小区間を順に調べて，極値のある隣接小区間を選ぶ，ということの繰り返しの最大回数．デフォルトは d = 16.

• dif=1 : f が微分できる函数のとき， f′ の零点を極値を取る点とみなす

• dif=g : 函数 g の零点を極値を取る点とみなす

• zero=1 : dif を指定したとき，区間の両端で f′ （または g）の符号が変わるときに，その間の f′ （または 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]]
140. flim(f,v|prec=c,init=t)

:: 変数 x の実数値関数 f の極限値を求める

• 戻り値は極限値．ただし空文字列は極限値なし，あるいは判定できないこと，また"+", "-"はそれぞれ +∞, −∞ を表す．

• v = a : lim_{x→a} f(x)

• v = ["+",a] : lim_{x→a+0} f(x)

• v = ["-",a] : lim_{x→a−0} f(x)

• v = "+" : lim_{x→∞} f(x)

• v = "-" : lim_{x→−∞} f(x)

• prec=c : c は −1 以上 30 以下の数で， c を増やすと極限値の正確性が増す（c = 0 がデフォルト）． • f(x) のとる値の範囲を， v = ["+",a] のときは， [a + 8^{−k−1}, a + 8^{−k}] で， v = "+" のときは

[8^{k}, 8^{k+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),"+");
-
141. fcont(f,[x,x_{1},x_{2}]|mesh=m,dev=d,zero=1,trans=1,dif=1) ?

:: 実数値函数 f の不連続点や滑らかでない点を求める • 函数 f は myeval() の引数の形でもよい．

• x は変数で，区間 [x_{1}, x_{2}] での極値を求める．変数 x がデフォルトの x のときはそれを省略して，二番目の引数は [x_{1},x_{2}] でよい．

• 戻り値は，特異点を鋏む区間とその 2 点でのギャップの組のリスト

142. fresidue(p,q|cond=[f_{1},f_{2},. . .],sum=1)

:: 多項式 q を分母とする有理式 p/q の特異点と留数の組のリスト（z が変数で， p は正則函数） • f_{1}, … は z, x, y を変数とする函数で（z=x+yi）これらが全て正となる留数のみを選ぶ

• sum=1 : 条件を満たす留数の和を得る

• sum=2 : 条件を満たす留数の和の 2πi 倍を得る（複素積分の計算に用いる）

[0] os_md.fresidue(z^2,(z^2+1)^2);
[[(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）は，留数計算により以下の積分計算を得ている．

∫_{−∞}^{∞} \frac{16}{x^{4} + 4}dx = 4π, ∫_{−∞}^{∞} \frac{3x^{4}}{x^{6} + 1}dx = 2π, ∫_{−∞}^{∞} \frac{3x}{x^{3} + \sqrt{−1}}dx = 2π, ∫_{−∞}^{∞} \frac{e^{ixξ}}{x^{2} + 1}dx = e^{−ξ}π.

3.2.2 Numbers

143. abs(p)  abs([p,prec])

:: 整数または実数または複素数 p の絶対値を返す • p が複素数のとき [p,prec] として prec で精度の桁数を指定できる．

• 不定変数を引数とすると対応するリスト形式函数が得られる

144. 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);
6

145. calc(p, [s, q]) calc(p, s) :: 数や有理式などあるいはそれらを成分とするリストやベクトルの成分に対して演算を施す

前者は s="+", "-", "*", "/", "^", ">", "<", "=", ">=", "<=", "!="，後者は s="abs",
"neg", "sqr", "inv", "sgn" が有効．
[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]
146. isint(p)

:: p が整数かどうか調べる

p が整数の時 1, そうでないとき 0 を返す

147. israt(p)

:: p が有理数かどうか調べる p が有理数の時 1, そうでないとき 0 を返す

148. iscrat(p)

:: p が数でその実部と虚部が共に有理数かどうか調べる p の実部と虚部が共に有理数の数の時 1, そうでないとき 0 を返す

149. isalpha(n)

:: 整数 n がアルファベットの文字コードかどうか調べる

 [0] strtoascii("1")[0];
 49
 [1] os_md.isalpha(49);
 0
 [2] os_md.isalpha(strtoascii("a")[0]);
 1
150. isnum(n)

:: 整数 n が数字 0〜9 の文字コードかどうか調べる

151. isalphanum(n)

:: 整数 n がアルファベットまたは数字の文字コードかどうか調べる

152. 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 ");
 0
 [4] os_md.isdecimal(-2.5);
 0
153. catalan(n)

:: Catalan 数などの場合の数を返す

• n が自然数のときは， Catalan 数 C_{n} を返す． C_{n} は，凸 (n + 2) 角形を対角線によって三角形分割する場合の数（cf. pg2tg()）または， x-y 平面の点 (−n, 0) から点 (n, 0) まで，上方または右方に x 座標または y 座標が整数で， x − y ≥ n を満たすように進む道筋の場合の数このとき，上方を 0, 下方を 1 で表して左から読むと， 0 と 1 をそれぞれ n 個並べて，どこから見てもその左側にある 0 の個数が 1 の個数より小さくはない，という並べ方の個数（n 次の許容 01 列と呼ぶことにする）

• n =[m,k] とすると， x-y 平面の点 (−n, 0) から点 (m, 0) まで，上方または右方に x 座標または y 座標が整数で， x − y ≥ n を満たすように進む道筋の場合の数

• n =[1,m,k] のときは, 第 1 種 Stirling 数 [ \begin{matrix}m \\ k \end{matrix}] を返す．

• n =[2,m,k] のときは, 第 2 種 Stirling 数 \{ \begin{matrix}m \\ k \end{matrix} \} を返す．

• n =["P",m,k] のときは, _{m}P_{k} を返す．

• n =["C",m,k] のときは, _{m}C_{k} を返す． • n =["H",m,k] のときは, _{m}H_{k} を返す． •

• n =["!",n] のときは, n! を返す．

• n =["!!",n] のときは, n!! を返す．

• n =["B",n] のときは, ベルヌーイ数 B_{n} を返す．

• n =["p",n] のときは, 分割数 p(n) を返す．オプション all=1 を指定すると， B_{n} 以下のベルヌーイ数 B_{0}, B_{1}, B_{2}, B_{4}, B_{6}, … のベクトルを返す．

• 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(["C",5,3]);
10
[6] os_md.catalan(["H",5,3]);
35
[7] os_md.catalan(["!",6]);
720
[8] os_md.catalan(["!!",6]);
48
[9] os_md.catalan(["!!",5]);
15
[10] os_md.catalan(["p",10]);
42
[11]  os_md.catalan(["B",10]);
5/66
[12] 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 ]
154. getCatalan(k,n|opt=1,to=f)

:: Catalan 数と許容 01 列，トーナメント表，凸多角形の三角形分割，番号付け，などの間の変換 n 次の許容 01 列の個数は Catalan 数 C_{n} で与えられるが，それを 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 は無視される．

• 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 列 L_{1} とそれより後の (n − k) 次許容 01 列 L_{2} に分割する． L_{0} を L_{1} の先頭の 0 と末尾の 1 を削った (k − 1) 次許容 01 列とする．

（a） k が小さい方が先とする（b） k が同じときは， L_{0} で先になるかどうかを決める（次数が少ないので既に順序は決まってる）（c） L_{0} が同じときは， L_{2} で先になるかどうかを決める（次数が少ないので既に順序は決まってる）

• どちらも先頭は 0101 ⋯ 01 で末尾は 00 ⋯ 011 ⋯ 1 00101011 < 00011101 デフォルトの順序 00101011 > 00011101 もう一方の順序（k が前者は 4, 後者は 3）

• どちらも，先頭に 01 を付加することで (n + 1) 次許容 01 列に埋め込むことによって, n = ∞ と考えて順序が決まる．（このときは，引数では n = 0 とする．実現可能な最小の n が用いられる）

3 次許容 01 列の例 : 001011 ↗ ↗ ↘ ↗ ↘ ↘ (1 ( (2 3) 4)) [figure: 1; 2; 3; 4]

a_{1} \underrightarrow{↗} \begin{matrix}a_{2} \\ a_{1} \end{matrix} \underrightarrow{↗} \begin{matrix}a_{3} \\ a_{2} \\ a_{1} \end{matrix} \underrightarrow{↘} \begin{matrix}(a_{2}a_{3}) \\ a_{1} \end{matrix} \underrightarrow{↗} \begin{matrix}a_{4} \\ (a_{2}a_{3}) \\ a_{1} \end{matrix} \underrightarrow{↘} \begin{matrix}((a_{2}a_{3})a_{4}) \\ a_{1} \end{matrix} \underrightarrow{↘} (a_{1}((a_{2}a_{3})a_{4}))  (*((**)*))

これは，スタック式計算機の仕組みに対応する．五角形の頂点の番号を 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 ]
[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
155. symtournament(n|to=t,verb=1)

:: トーナメント戦（2 分木）の場合の数, タイプ • n チームのトーナメント戦の型の数，トーナメント図の数，チームを区別したトーナメント戦の数,

優勝チームのみを指定したトーナメント戦の数を返す

• to=1 or "sym": n チームのトーナメント戦の図の型の数

• to=2 or "T": n チームのトーナメント戦の型のリスト

• to=3 or "01"": n チームのトーナメント戦の型の 01 列によるリスト

• verb=1 : 型を対称性の群 ℤ_{2}^{m} で区別し，対応する 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]]]

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

Symmetry of patterns

teams 2 3 4 5 6 7 8 9 10 11 12 13 14  15
ℤ_{2} 1 1 1 1 1 1 1 1 1 1  1  1  1  1
ℤ_{2}^{2}  0 1 2 4 6 9 12 16 20 25 30  36
ℤ_{2}^{3}  1 1 2 3 7 14 28 50 85 135 206 301
ℤ_{2}^{4}  1 3 7 14 28 58 119 239 457 837
ℤ_{2}^{5}  1 6 21 54 126 273 580 1197
ℤ_{2}^{6}  0 1 4 17 61 187 500 1219
ℤ_{2}^{7}  1 1 3 8 27 80 246 723
ℤ_{2}^{8}  1 3  9 32 112 363
ℤ_{2}^{9}  2  8 33 119
ℤ_{2}^{10}  1  3 11  39
ℤ_{2}^{11}  3  15

156. tobig(n)

:: 0 以外の有理数を bigfloat に変換する • n は，実部と虚部が有理数の複素数や有理数係数の多項式でもよい.

• 倍精度浮動小数は変換できない.

 [0] os_md.tobig(@pi*@i+1/2);
 (0.5+3.14159265358979*@i)
157. nthmodp(a,n,p)

:: a^{n} mod p を返す（a は整数で n, p は自然数）

[0] os_md.nthmodp(107,10006,10007);
1
[1] os_md.nthmodp(107,1006,1007);
425
158. issquaremodp(a,p|power=n)

:: 平方剰余を調べる（ルジャンドルの平方剰余記号 (\frac{a}{p})， n は平方を一般べきに） • p は素数， n は正整数．

• a ≡ 0 mod p のときは 0 を返す．そうでないときは以下の値を返す．

• x^{2} ≡ a mod p が解をもつとき 1, もたないとき −1．

• power=n を指定したときは， x^{n} ≡ 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]
159. 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]
160. 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
[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 191
21 409
23 2161
......
161. rabin(p,q)

:: p に対し q を底とするミラー・ラビンの素数判定を行う（素数，擬素数なら 1 を返す）

[0] os_md.rabin(10007,2);
1
[1] os_md.rabin(1007,2);
0
162. 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
163. cfrac2n(l|loop=m,,ex=1,q=f,reg=1)

:: （循環）連分数を通常の形（含 q-変形）に直す.

• l =[a_{0},a_{1},a_{2}, …, a_{n}] は次の連分数を表す．

a_{0} + \frac{1}{a_{1} + \frac{1}{a_{2} + \frac{1}{... a_{n−2} + _{\frac{1}{a_{n−1}+ \frac{1}{an}}}}}}

• 上の指定の場合， loop=m : m 項目から n 行目までが循環している連分数を表す． • l =[[b_{1},a_{1}],[b_{2},a_{2}], …,[b_{n},a_{n}]] は次の連分数を表す．

\frac{b_{1}}{a_{1} + \frac{b_{2}}{a_{2} + \frac{b_{3}}{... a_{n−2} + _{\frac{b_{n−1}}{a_{n−1}+ \frac{bn}{an}}}}}}

上の連分数に a_{0} を加えたものは， ex=1 を指定した上で l =[a_{0},[b_{1},a_{1}],[b_{2},a_{2}], …,[b_{n},a_{n}]] とする．このときは， b_{i} = 1 となる i に対しては， [b_{i},a_{i}] は単に a_{i} としてよい．

• reg=1 : 分子が 1 とは限らない連分数を，分子が 1 の連分数に直す（分母は整数とは限らない）． • l =[x,n,g(x),f(x)] は， a_{i} = f(i), b_{i} = 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);

[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] では， Apéri [Apéri] が ζ(3) が無理数であることを示すときに使った ζ(3) の以下の連分数展開による近似分数を， 20 番目まで求めている.

ζ(3) = \frac{6}{5 + \frac{P (1)}{Q(1) +  \frac{P (2)}{\frac{...}{Q(n) + \frac{P (n)}{...}}}}}  _{\begin{cases}P (n) = −n^{6}, \\ Q(n) = (2n + 1)(17n^{2} + 17n + 5), \end{cases}}

164. sqrtrat(r)

:: 有理数（または実部と虚部が有理数の複素数）の平方根を得る • r が有理数でも実部と虚部が有理数の複素数でもないときは [] を返す．

• r が有理数のとき，\frac{m}{n}, \frac{m}{n} \sqrt{−1}, \frac{m\sqrt{p}}{n}, \frac{m\sqrt{−p}}{n} のいずれかを返す．ただし， m, n, p は整数（p > 1）である．

   \sqrt{p} は ((p)^(1/2)) ，\sqrt{−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))

[8] os_md.sqrtrat(-a^2+2*a-1);
(1*@i)*a+(-1*@i)

上は以下を示している

\sqrt{\frac{4}{9}} = \frac{2}{3}, \sqrt{−\frac{4}{9}} = \frac{2}{3}i, \sqrt{\frac{9}{8}} = \frac{3\sqrt{2}}{4}, \sqrt{−\frac{9}{8}} = \frac{3\sqrt{2}i}{4}, \sqrt{−1} = i, \sqrt{4i − 3} = 1 + 2i,

\sqrt{2(4i − 3)} = \sqrt{2}(1 + 2i), \sqrt{1 + i} = \sqrt{\frac{\sqrt{2}}{2} + \frac{1}{2}} + \sqrt{\frac{\sqrt{2}}{2} − \frac{1}{2}}i, \sqrt{−a^{2} + 2a − 1} = ai − i.

165. sqrt2rat(r|mult=1)

:: 平方根や虚数を含んだ分数の有理化 • p(x)^{n+ \frac{1}{2}} は， p(x)^{n} · p(x)^{\frac{1}{2}} の形に直される（n は整数）

• 分子や分母に表れる平方根は高々一つで，共に a^(1/2) の形をしている場合が特に有効．

• a^(1/2) の有理数係数の有理式は, 有理数 r_{1}, r_{2} によって r_{1} + r_{2} · 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

以上は，以下の等式を示している．

\frac{x + i}{y + i} = \frac{xy − xi + yi + 1}{y^{2} + 1}, \frac{2 + \sqrt{2}}{2 − \sqrt{2}} = 2\sqrt{2} + 3, (\sqrt{2})^{4} = 4, \frac{(\sqrt{2} + 1)^{3}}{\sqrt{2} − 1} = 4\sqrt{2} + 13.

166. 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);

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)
167. 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)]

3.2.3 Polynomials and rational functions

168. 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 ]

[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
169. rmul(p,q)

:: 有理式（の行列） p と q の積を既約有理式（の行列）の形で計算する q はベクトルまたは行列でもよい．このとき p は行列やベクトルでもよい（例は radd() の項を参照）．

170. mulpolyMod(p,q,x,n)

:: x の多項式 p と q の積を x^{n+1} 以上の項を無視して計算する x について n 次式を返す． x は [x_{1},x_{2},...] など多変数でもよい． n がある程度大きく，また係数が複雑なときの高速化やべき級数の積の計算などに用いられる．

171. polbyroot([p_{1}, p_{2}, ..., p_{n}],x) polbyroot([m,n],x|var=v)

:: 多項式を根で与える • 戻り値: ∏_{j}(x − p_{j})

• var=v : 根を v_{i} (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
172. polbyvalue([[a_{1}, b_{1}],...,[a_{n}, b_{n}]],x)

:: x の n − 1 次多項式を n 個の点 x = a_{i} での値 b_{i} で与える戻り値: n − 1 次多項式

[0] os_md.polbyvalue([[0,1],[2,3],[3,6]],t);
2/3*t^2-1/3*t+1
173. pgen([[x_{1}, n_{1}],[x_{2}, n_{2}]...],a|sum=n,shift=m,sep=1,num=1)

:: 係数が a_{∗} で x_{i} が n_{i} 次，全体で n 次以下の x_{1}, … の一般多項式を作る • shift=1 : suffix を 1 から始める

• num=1 : 10, 11, … を a, b, … でなくて数字のままで表す．

• sep=1 : 複数の suffices のとき _で区切る

[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+a11

[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}
174. 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];
0
175. res0(p,q,x|var=[x_{1}, x_{2}, . . .],opt=f,dbg=d)

:: 1 変数多項式の共通解の存在条件と解，割り算変数 x の多項式 p, q に共通根が存在するための条件 r を返す．

• var=[x_{1}, x_{2}, …] とすると， x_{1}, x_{2}, … 以外の不定元は一般の数と見なす．

• 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]

[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]
176. sgnstrum([p_{1}, p_{2}, . . .],t|)

:: 多項式の strum 列の t での符号変化の個数を返す実数係数の多項式 p の strum 列 [p_{1}, p_{2}, …] に対して，変数の値が t での符号変化の個数を返す. t_{1} と t_{2} での値の差が， (t_{1}, t_{2}] にある実根の個数となる．根の重複は無視． 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
177. polstrum(p|num=[t_{1},t_{2}],mul=1)

:: 多項式の strum 列や， (t_{1}, t_{2}] にある根の個数を返す p が有理数の係数の多項式の時は，平方因子を除いた多項式にしてから strum 列を返す．

• オプション num=[t_{1},t_{2}] を指定すると， (t_{1}, t_{2}] にある根の個数を返す． t_{1} = "-" は −∞ を， "+"は， ∞ を， 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);

[x,x^4-x^3+x^2-x]
178. polrealroots(p|in=[a,b],step=[n_{1},n_{2}],nt=k)

:: 多項式の実根を求める strum 列を使って実根を求める．

• デフォルトの戻り値は [[a_{1},b_{1},m_{1}],...,[a_{n},b_{n},m_{n}],q] で， (a_{i}, b_{i}] に実根が m_{i} 個存在することを返す（m_{i} > 0）．

• 有理数係数の時は， q は根の重複度を 1 に変えた多項式．

• 有理数係数の多項式の場合は，重複を除いて実根を求める

• step=[n_{1},n_{2}] を指定すると，区間の幅を二分法で 2^{n_{1}} 等分まで縮めて調べる．根が分離できなかった場合は， 2^{n_{2}} 等分まで縮める． step=n は， step=[n,n] を意味する．

• デフォルトは step=32．

• in=[a,b] を指定すると， (a, b] の範囲で実根を求める．

• nt=k を指定すると， m_{i} = 1 となった (a_{i}, b_{i}] 内の実根を， 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
179. 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);

[-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 程度かかった．

180. easierpol(p,x) または easierpol(p,[x_{1}, x_{2}, . . .])

:: 有理式係数の x の多項式の係数に x を含まない有理式をかけて，係数の最大公約元が 1 の整数係数の多項式に変換

[0] os_md.easierpol(6*r*y/a-3*r*x^2,x);
a*x^2-2*y
181. 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]

[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]
182. 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]]

183. polinsym(p,[x_{1}, …, x_{n}],s) :: (x_{1}, …, x_{n}) の対称有理式を基本対称式で表す 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)
184. polinvsym(p,[x_{1}, . . . , x_{n}],s)

:: polinsym(p,[x_{1}, …, x_{n}],s) の逆函数

185. pol2sft(p,x|sft=t)

:: shifted power 多項式を与える • p = ∑ c_{n}x^{n} ⇒ 戻り値: ∑ c_{n}x\underline{n} （x\underline{n} := x(x − 1) ⋯ (x − n + 1)）

• sft=t を指定すると x^{n} ↦ 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*x
186. polinsft(p,x)

:: shifted power 多項式に直す（pol2sft() の逆変換） p = ∑ c_{n}x^{n} = ∑ a_{n}x\underline{n} ⇒ 戻り値: ∑ a_{n}x^{n} (x\underline{n} := x(x − 1) ⋯ (x − n + 1))

[0] os_md.polinsft(x^3-3*x^2+2*x, x);
x^3

187. sftpow(p,n)
188. sftpowext(p,n,s)

:: p の s shifted n power ∏_{ν=1}^{n}(p + (ν − 1)s) を返す

∏_{ν=1}^{n}(p + (ν − 1)s) を返す． sftpow( ) では， s = −1 と解釈される．

189. binom(p,n)

:: p(p − 1)(p − 2) ⋯ (p − n + 1)/n! を返す

190. expower(p,r,n)

:: (1 + p)^{r} の展開を p^{n} まで求める

[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] は\sqrt[3]{1.5} の近似値を求めている．

191. orthpoly(n|pol="type")    orthpoly([n,a, . . .]|pol="type")

:: 変数 x の n 次直交多項式を返す • デフォルトでは n 次の Legendre 多項式 P_{n}(x) を返す

 • type は，Legendre, Gegenbauer, Tchebycheff, 2Tschebyscheff, Jacobi, Laguerre, Hermite,

Selected のいずれかの文字列が指定可能．ただし，先頭から 2 文字のみで判断される（3 文字目以降は省略可）．

• type が， Gebenbauer のときの引数は [n,a] で， Gegenbauer 多項式 C_{n}^{a}(x) を返す．

• type が， Laguarre のときは， [n,a] を引数として指定すると Laguerre 多項式 L_{n}^{(a)}(x) を返し， n を指定すると， L_{n}^{(0)}(x) を返す．

• type が Jacobi のときは， [n,a,c] を指定すると Jacobi 多項式 G_{n}(a, b; x) = F (−n, a + n, c; x) を返す．

• type が Tchebycheff のときは，戻り値は Tschebyscheff 多項式 T_{n}(x) で， cos(nθ) = T_{n}(cos θ).

• type が 2Tschebyscheff のときは，戻り値 Ū_{n}(x) （この時のみ n − 1 次多項式）に\sqrt{1 − x^{2}} を掛けたものが第 2 種の Tschebyscheff 関数 U_{n}(x) となる．このとき sin nθ = Ū_{n}(cos θ) sin θ.

• type が Selected のときは，引数 [n,a] に対し，選点直交多項式 P_{n,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)$

192. schurpoly ([m_{1},m_{2}, . . .]|var=v)

:: m_{1} ≥ m_{2} ≥ ⋯ ≥ m_{n} ≥ 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
193. seriesMc(f,k,v|evalopt=[[s_{1},t_{1}],[s_{2},t_{2}]...])

:: 函数 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$")$

\frac{1}{x} = \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} + ⋯ 上の [2],[3] では x = a での 4 次までの Taylor 展開を求めて， TEX のソースの形で出力している．

194. solveEq([f_{1}, f_{2}, …],[x_{1}, x_{2}, …]|h=1,inv=1) :: 連立代数方程式を解く，双有理変換の逆変換を求める．代数方程式

{f_{1}(x_{1}, x_{2}, …) = 0, ; f_{2}(x_{1}, x_{2}, …) = 0, ; ⋮

を有理式の範囲で解く． • グレブナー基底の計算パッケージを使うので load("gr") が必要．

• inv=1 を指定したときは

{x_{1} → f_{1}(x_{1}, x_{2}, …), ; x_{2} → f_{2}(x_{1}, x_{2}, …), ; ⋮

の逆変換を求める．

• 戻り値 – [c_{1}, c_{2}, …] : x_{1} = c_{1}, x_{2} = c_{2}, … が解

– −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]
195. baseODE([f_{1}, f_{2}, . . .]|f=y,to=x,var=v,vl=h,ord=d,in=1,TeX=t,pages=p,dbg=d,step=k)

:: 一階常微分方程式系の単独化, 双有理変換デフォルトでは

x′ = f_{1}(t, x, y, z, …),
y′ = f_{2}(t, x, y, z, …),
z′ = f_{3}(t, x, y, z, …),
⋮ ⋮  ⋮

という変数 t についての n 次元の常微分方程式について， x(t) の満たす単独高階微分方程式を求める． • f_{1}, f_{2}, … は有理式で，パラメータを含んでもよい．

• n 個のベクトルは x, y, z, w, u, v, p, q, r, s の順に先頭から n 個がデフォルト． 11 番目以降は， xx, xy, …,yx, … となる．

• load("gr"); によってグレブナー基底の計算パッケージを読み込んでおく必要がある．デフォルトでは gr() を, オプション指定によっては hgr() なども使う．

• パラメータ f

– f=0 : デフォルトで，戻り値は [p,l_{1},l_{2},l_{3}] となる． p : x の単独高階微分方程式で，導関数は 1 階から順に x1, x2, x3, ⋯ のように表される． l_{1} : グレブナー基底を計算するときの変数順序 l_{2} : 与えた方程式とその微分から生成された多項式のリスト l_{3} : 求められたグレブナー基底

– f=1 : p のみを返す．

– f=-1 : [l_{1},l_{2}] を返す．デフォルトでは gr(l_{2},l_{1},2) を計算．

– f=-2 : [l′_{1},l_{2}] を返す． ℓ′_{1} は ℓ_{1} を変数毎にリストにしたもののリスト．

– f=-3 : [v,L] を返す（v は変数のリストで，有理変換を行った場合は，変換後）．

• to=x : 変数 x についての単独高階方程式を求める．たとえば to=y．

• to=[g_{1}, g_{2}, …] : 最初に

\begin{cases}x̃ = g_{1}(t,x,y, …), \\ ỹ = g_{2}(t,x,y, …), \\ ⋮ & ⋮ \end{cases}

という双有理変換を行い， (x̃, ỹ, …) についての方程式とみなす．

f=-3 によって変数と変換された方程式を返す．さらに TeX=1， 2 の指定により，その方程式を TEX で返す．

• to=[[g_{1}, g_{2}, …]] : 最初に

\begin{cases}x = g_{1}(t, x̃, ỹ, …), \\ y = g_{2}(t, x̃, ỹ, …), \\ ⋮ & ⋮ \end{cases}

という双有理変換を行い， (x̃, ỹ, …) についての方程式とみなす．

f=-3 によって変数と変換された方程式を返す．さらに TeX=1， 2 の指定により，その方程式を TEX で返す．

• to=g : g が有理式で変数でないときは， to=[g,y, …] という指定と等価． g は変数 x についての 1 次式，あるいは分母が 1 次で分子は 1 次以下の有理式（他の変数を定数とみて）でなければならない． x がこの条件を満たさないが， y が満たす場合は， to=[g,x,z, …] などとなる．

• var=[v_{1}, v_{2}, v_{3}, …] : 変数 x, y, z, … でなくて， v_{1}, v_{2}, v_{3}, … を用いる．変数名は数字を含まないことが望ましい．

• パラメータ 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 に負の値を指定したときに有効．戻り値 [[v_{1}, …],[p_{1}, …]] に対し， gr([v_{1}, …],[p_{1}, …],2) が求める単独方程式が最初の成分となるグレブナー基底．

• step=k : パラメータ ord に −2 以下の値を指定したときに有効． v_{1}, … の順に， k − 1 個の変数を減らした段階の上のような結果を求める（k が未知変数の個数の時は，最終結果を返す）．

• step=[s_{1},s_{2},d_{1},d_{2}] : パラメータ ord に −2 以下の値を指定したときに有効． dbg=1 のときの表示される Step k_{1} − −k_{2} v d_{1} : d_{2} の段階の結果 R=[p_{1},p_{2},d_{1}1,d_{2},w] を返す． p_{1}, p_{2} は多項式で， d_{1}, d_{2} はそのときの v についての次数． w はそれらが 0 でないという条件を課した．

• dbg=1 : ord=-2 などのときに途中経過を表示する．

• dbg=2 : 上と同じだが，多項式の次数に加えて，多項式の項数，最高次の多項式の項数を表示する． • dbg=3 : 上と同じだが，可約なものが現れたら，最後の既約な成分を選ぶ．そうでない場合は

dbg=[3,[2,1,2]] のように指定する． [2,1,2] は現れる順に，可約なものの 2 番目，最初， 2 番目の意味で 0 は最後を意味する． > は，計算結果の因数分解の計算の実行を示す．

• dbg=4 : 上と同じだが，可約なものが現れたら，そこで中止して結果を返す．可約なものは，可約分解された形で返す

• in=1 : 方程式は導関数を含んだ以下の形で与える（未知関数の数と方程式の数とは異なってよい）．

f_{1}(t, x, y, z, …, x1, y1, z1, …) = 0,
f_{2}(t, x, y, z, …, x1, y1, z1, …) = 0,
f_{3}(t, x, y, z, …, x1, y1, z1, …) = 0,
⋮

• TeX=1 : （-f の負指定が無いとき）与えられた方程式と求めた方程式を TEX のソースとして返す． • TeX=2 : （-f の負指定が無いとき）与えられた方程式と求めた方程式を TEX を用いて表示する． • pages=1 : TEX 出力が複数ページにわたる長い式の場合に指定

• 引数を [[f_{1}, f_{2}, …],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 :

\begin{cases}x′ & = −ax + ay, \\ y′ & = (−z + b)x − y, \\ z′ & = yx − cz. \end{cases}

xx_{3} − x_{1}x_{2} + (a + c + 1)xx_{2} − (a + 1)x_{1}^{2} + x^{3}x_{1} + c(a + 1)xx_{1} + ax^{4} − c(b − 1)ax^{2}, ay − x_{1} + ax, axz + x_{2} + (a + 1)x_{1} − (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])$

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

196. 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 法の解析デフォルトでは\frac{dy}{dx} = f(x, y) の解 y(x) の d + 1 階微分を求める．

• f の偏微分 f_{xxy} を f_{21} のように表す．

• dif=1 : これを指定すると f_{xxy} のように表される．

• 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 法

k_{1} = f(x, y),
k_{i} = f(x + c_{i}h, y + ∑_{ν=1}^{i−1} a_{i,ν}k_{ν}h) (i = 2, …, m),
ỹ(x, h) = y + ∑_{i=1}^{m} b_{i}k_{i}h

に対し， ỹ(x, h) − y(x + h) の h に対する展開を d 次まで求める．

– m < 0 のとき， |m| 段の陽的 Runge-Kutta 法に対し， ỹ(x, h) − y(x + h) の h に対する d 次までの展開が消える条件を返す．

– c1=1 を指定すると，上で k_{1} = f(x + c_{1}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 + fh + \frac{1}{2}(f_{y}f + f_{x})h^{2} + \frac{1}{6}(f_{yy}f^{2} + (f_{y}^{2} + 2f_{xy})f + f_{x}f_{y} + f_{xx})h^{3}

[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 + f_{x}s + f_{y}t + \frac{1}{2}f_{xx}s^{2} + f_{xy}st + \frac{1}{2}f_{yy}t^{2} + \frac{1}{6}f_{xxx}s^{3} + \frac{1}{2}f_{xxy}s^{2}t + \frac{1}{2}f_{xyy}st^{2} + \frac{1}{6}f_{yyy}t^{3}

[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")$

b_{1} + b_{2} + b_{3} − 1

\frac{1}{2}(2b_{2}c_{2} + 2b_{3}c_{3} − 1)

\frac{1}{2}(2b_{2}a_{21} + 2b_{3}a_{31} + 2b_{3}a_{32} − 1)

\frac{1}{6}(3b_{2}c_{2}^{2} + 3b_{3}c_{3}^{2} − 1)

\frac{1}{6}(6b_{3}a_{32}c_{2} − 1)

\frac{1}{3}(3b_{2}c_{2}a_{21} + 3b_{3}c_{3}a_{31} + 3b_{3}c_{3}a_{32} − 1)

\frac{1}{6}(6b_{3}a_{32}a_{21} − 1)

\frac{1}{6}(3b_{2}a_{21}^{2} + 3b_{3}a_{31}^{2} + 6b_{3}a_{32}a_{31} + 3b_{3}a_{32}^{2} − 1)

197. pTaylor([f_{1},f_{2}, . . .],[x_{1},x_{2}, . . .],m|raw=1,time=t)

:: 常微分方程式 x′_{i} = f_{i}(x) (i = 1, 2, …) の m 次までのベキ級数解を返す微分方程式

\frac{dx_{i}}{dt} = f_{i}(x_{1}, …, x_{n}) (i = 1, …, n)

の t = 0 でのべき級数解を m 次まで求めて，サイズ n のベクトルで返す（x_{i} の t = 0 での値は x_{i} とする． • 上で n = 1 のときは， [f_{1}], [x_{1}] は，単に f_{1}, x_{1} でよい．

• raw=1 を指定すると， t^{k} の係数を長さ m + 1 の（k = 0 からの）リストで返す．リストの成分は，長さ n のリスト．

• time=t を指定すると， t を t で置き換える．

• f_{i}(x_{1}, …, x_{n}) は, t を含んでいてもよい． (t, x_{1}, …, x_{n}) の多項式であることが望ましい．

[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]]
198. seriesHG([a_{1},a_{2},. . .],[b_{1},b_{2},. . .],p,k)
seriesHG([[a_{1},. . .],[b_{1},. . .],[c_{1},. . .]],[[d_{1},. . .],[e_{1},. . .],[f_{1},. . .]],[x,y],k)

:: 一般超幾何級数_{m}F_{n}(a_{1}, a_{2}, …, a_{m}; b_{1}, b_{2}, …, b_{n}; p) の p^{k} 次の項まで求めるまたは 2 変数の級数 ∑_{0≤i+j≤k} \frac{(a_{1})_{i+j}···(b_{1})_{i}···(c_{1})_{j}···}{(d_{1})_{i+j}···(e_{1})_{i}···(f_{1})_{j}···} \frac{x^{i}y^{j}}{i!j!} を返す．一般超幾何級数は

mF_{n}(a_{1}, …, a_{m}; b_{1}, …, b_{n}; x) = ∑_{k=0}^{∞} (\frac{∏_{i=1}^{m} a_{i}(a_{i} + 1) ⋯ (a_{i} + k − 1)}{∏_{j=1}^{n} b_{j}(b_{j} + 1) ⋯ (b_{j} + k − 1)}) \frac{x^{k}}{k!}

で与えられる． Gauss の超幾何級数は F (a, b, c; x) = seriesHG([a,b],[c],x,*) となる．

微分方程式は ghg() を，例は fctrtos() の [18] の項を参照．

2 変数の級数

∑_{0≤i+j≤k} \frac{∏_{k} ∏_{ν}^{i+j}(a_{k} + ν − 1) · ∏_{k} ∏_{ν}^{i}(b_{k} + ν − 1) · ∏_{k} ∏_{ν}^{j}(c_{k} + ν − 1)}{∏_{k} ∏_{ν}^{i+j}(d_{k} + ν − 1) · ∏_{k} ∏_{ν}^{i}(e_{k} + ν − 1) · ∏_{k} ∏_{ν}^{j}(f_{k} + ν − 1)} \frac{x^{i}}{i!} \frac{y^{j}}{j!}

を得ることが出来る． Appell の超幾何級数は 2 変数の級数で

         F_{1}(a; b, b′; c; x, y) = seriesHG([[a],[b],[b′]],[[c],[],[]],[x,y],*),
       F_{2}(a; b, b′; c, c′; x, y) = seriesHG([[a],[b],[b′]],[[],[c],[c′]],[x,y],*),
       F_{3}(a, a′; b, b′; c; x, y) = seriesHG([[],[a,b],[a′,b′]],[[c],[],[]],[x,y],*),
         F_{4}(a; b; c, c′; x, y) = seriesHG([[a,b],[],[]],[[],[c],[c′]],[x,y],*).

199. 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);
0
200. fctrtos(r|var=ℓ,rev=1,dic=1,TeX=f,dviout=1,lim=n,small=1,pages=1,add=s)

:: 有理式を因数分解した形の文字列に変換する

• TeX=1 : L^{A}TEX のソースを出力する．このとき，多項式でなく有理式の場合は，分子と分母がリストで出力される．

• TeX=2, 3 : L^{A}TEX のソースを出力する．有理式のときは通常の \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 を指定した場合，微分は ∂ を用いて， ∂_{x_{1}} のように表す．

• var="dif" : 上と同じであるが， TeX が指定されていて，微分する変数が 1 個のみで変数が 1 文字で表されているときは，微分を単に ∂ で表す．また微分する変数が 2 個以上あってもその変数名が全て辞書式順序で x0 と x99 の間にあるならば，微分は ∂_{0} や ∂_{99} などと表す．

• var="dif1" : 上と同様であるが， TeX が指定されると微分は\frac{d^{2}}{dx^{2}} または\frac{∂^{3}}{∂x^{2}∂y} の様に表される．

• var="dif2" : 上と同様であるが， 1 変数でも常微分の記号は用いず，偏微分の記号を用いる．

• lim=n : r が多項式のとき， L^{A}TEX のソースへの変換で 1 行が n 文字幅を越えないように（TeX=2 ならば） \\ または（TeX=1,3 ならば） \\ & で改行．ただし，後者でも先頭には & を付加しない．なお， n が 0 以外の 30 以下の正数ならデフォルトの n =TeXLim と解釈される． n = 0 のときは文字幅制限は考慮しない．

• small=1: L^{A}TEX のソースへの変換で分数をテキストスタイルにする．ただし，これによる 1 行の文字数制限の変化は考慮されない．

• 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)$

上の [18] の画面表示は

1 + \frac{ba}{c}x + \frac{b(b + 1)a(a + 1)}{2c(c + 1)}x^{2} + \frac{b(b + 1)(b + 2)a(a + 1)(a + 2)}{6c(c + 1)(c + 2)}x^{3}

上の [19] の画面表示は，改行位置も含めて次のようになる．

\frac{d^{4}}{dx^{4}} + \frac{4((α + β)d + 1)}{α + β} \frac{d^{3}}{dx^{3}} + \frac{6((α + β)d + 1)^{2}}{(α + β)^{2}} \frac{d^{2}}{dx^{2}} + \frac{4((α + β)d + 1)^{3}}{(α + β)^{3}} \frac{d}{dx}

+ ((α^{4} + 4βα^{3} + 6β^{2}α^{2} + 4β^{3}α + β^{4})d^{4} + (4α^{3} + 12βα^{2} + 12β^{2}α + 4β^{3})d^{3} + (6α^{2} + 12βα + 6β^{2})d^{2} + (4α

+ 4β)d + α^{4} + 4βα^{3} + 6β^{2}α^{2} + 4β^{3}α + β^{4} + 1) / ((α + β)^{4})

var= を指定して微分作用素として扱うと

[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)$

はそれぞれ以下のような表示となる．

∂_{x_{1}}^{2} + 2∂_{x_{1}}∂_{x_{2}} + ∂_{x_{2}}^{2} + \frac{2}{a + b}∂_{x_{1}} + \frac{2}{a + b}∂_{x_{2}} + \frac{1}{(a + b)^{2}}  (20)
∂_{1}^{2} + 2∂_{1}∂_{2} + ∂_{2}^{2} + \frac{2}{a+b}∂_{1} + \frac{2}{a+b}∂_{2} + \frac{1}{(a+b)^{2}}  (21)
\frac{∂^{2}}{∂x_{1}^{2}} + 2\frac{∂^{2}}{∂x_{1}∂x_{2}} + \frac{∂^{2}}{∂x_{2}^{2}} − \frac{2}{a − b} \frac{∂}{∂x_{1}} − \frac{2}{a − b} \frac{∂}{∂x_{2}} + \frac{1}{(a − b)^{2}}  (22)
∂^{2} + \frac{2(da + db + 1)}{a + b}∂ + \frac{(da + db + 1)^{2}}{(a + b)^{2}}  (23)
∂_{x}^{2} + \frac{2(da + db + 1)}{a + b}∂_{x} + \frac{(da + db + 1)^{2}}{(a + b)^{2}}  (24)
\frac{d^{2}}{dx^{2}} + \frac{2(da + db + 1)}{a + b} \frac{d}{dx} + \frac{(da + db + 1)^{2}}{(a + b)^{2}}  (25)
\frac{∂^{2}u}{∂x^{2}} + \frac{2(da + db + 1)}{a + b} \frac{∂u}{∂x} + \frac{(da + db + 1)^{2}}{(a + b)^{2}} u  (26)
\frac{d^{2}}{dx^{2}} + \frac{2(da+db+1)}{a+b} \frac{d}{dx} + \frac{(da+db+1)^{2}}{(a+b)^{2}}  (27)

[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

201. tohomog(r,[x_{1}, x_{2}, …],y) :: (x_{1}, x_{2}, …) の有理式に変数 y を導入して (y, x_{1}, x_{2}, …) の斉次式にする

[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+b

x の n 次多項式 p(x) に対し p(x) = ∑ a_{j}x^{j}(x − c)^{n−j} を満たす多項式 ∑ a_{j}x^{j}y^{n−j} は， subst(tohomog(p, [x], y), y, (x − y)/c) で求められる．

202. 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+1

203. invf([p_{1}, …, p_{n}],[x_{1}, …, x_{n}],[y_{1}, …, y_{n}]) :: y_{j} = p_{j}(x) (j = 1, …, n) を x_{j} = q_{j}(y) (j = 1, …, n) と解く（逆函数）．ただし， deg(p_{i}, x_{j}) は， i = j のとき 1 で i < j のとき 0 でなければならない．戻り値： [q_{1}(y_{1}), …, q_{n}(y_{n})]

204. 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]);
1
205. 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 : 零行列またはベクトルである

[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
206. iscoef(p,f)

:: p の係数の全てが f(∗) ≠ 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
207. 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);
[ 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)
208. pcoef(p,m,q)

pcoef(p,m,[[x_{1}, .., x_{n}],[m_{1}, …, m_{n}]]) :: 多項式 p^{m} を展開したときの単項式 q に対する係数を返す

• p は多項式， m は非負整数．

• q は変数とベキのリストでもよい．

• p の変数が多く，さらに m が大きくて p^{m} が計算不能な場合にも有効．

[0] P=(x+2*y+1)^2+w^2+z$
[1] os_md.pcoef(P,8,x^2*y);

[2] os_md.pcoef(P,8,[[x,y,z],[7,2,0]]);
80640*w^3+887040*w^2+2306304*w+1647360
209. 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
210. 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]]
211. 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)
212. terms(p,[x,y, . . .]|rev=1,dic=1)

:: 多項式の存在する項の次数とべき指数のリストを返す次数と各べき指数のリストの辞書式順序で大きい順に並べて返す．

• 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]]

213. pterm(p,[x_{1},x_{2}, …],[m_{1},m_{2}, …]) :: 多項式の指定した変数が指定した次数となる項を返す

[0] os_md.pterm((x^2+x-y-z+1)^4,[x,y],[2,1]);

(-12*z^2+36*z-24)*y*x^2

214. pweight(p,[x_{1},x_{2}, …],[m_{1},m_{2}, …])

:: 多項式の変数に重みをつけて斉次式の成分に分解する • 次数と対応する項の組のリストを返す

• [m_{1},m_{2}, …] を単に 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]]
215. 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^3
216. 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)
217. myediff(p,x)

:: ediff(p,x) と同じ． p は行列や配列で係数は有理式でよい． x = 0 のときは 0 を返す．

218. mypdiff(p,[x_{1},f_{1},x_{2},f_{2},...])

:: 合成関数の微分． p は行列や配列で係数は有理式でよい． ∑_{i} \frac{∂p}{∂x_{i}} f_{i} を返す．

[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]
219. difflog(L|var=x)

:: 対数微分を返す L の j 番目の成分が [p_{j},a_{j}] のときは q_{j} = p_{j}^{a_{j}} とおき，有理式のときは q_{j} = e^{p_{j}} とおき， q = q_{1}q_{2} ⋯ に対して\frac{q′}{q} を返す．微分の変数のデフォルトは 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)
220. ptol(p,x|opt=0)

:: x の多項式 p の係数のリストを返す • p は多項式のリスト [p_{1}, p_{2}, …] でもよい．

• x が多変数のときは [x_{1}, x_{2}] のように変数のリストを渡す．

• 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]
221. pfrac(p,x|root=2,dviout=1,TeX=1)

:: x の有理式 p （の行列）を部分分数展開し，分子，分母（多項式とべき）の組のリストを返す • dviout=1 を指定すると，結果を dviout で表示する．

• TeX=1 を指定すると，上の L^{A}TEX のソースが得られる．

• root=2 を指定すると， x^{4} + (2c − r)x^{2} + c^{2} = (x^{2} + \sqrt{r}x + c)(x^{2} − \sqrt{r}x + 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
[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) とすると，以下の表示を得る．

− \frac{1}{(a − b)^{2}(x − a)} + \frac{1}{(a − b)(x − a)^{2}} + \frac{1}{(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), とすると，次

の = 以下の表示を得る．

\frac{1}{x^{4} + 1} = \frac{x + \sqrt{2}}{2\sqrt{2}(x^{2} + \sqrt{2}x + 1)} − \frac{x − \sqrt{2}}{2\sqrt{2}(x^{2} − \sqrt{2}x + 1)},
\frac{1}{x^{6} + 1} = \frac{\sqrt{3}x + 2}{6(x^{2} + \sqrt{3}x + 1)} − \frac{\sqrt{3}x − 2}{6(x^{2} − \sqrt{3}x + 1)} + \frac{1}{3(x^{2} + 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);

\frac{(\begin{matrix}0 & 1 \\ 0 & 0 \end{matrix})}{x} + \frac{(\begin{matrix}0 & 0 \\ −ba & −(a + b − c + 1) \end{matrix})}{x − 1}

222. lpgcd([p_{1}, p_{2}, …])

:: 多項式 p_{1}, p_{2}, … の共通因子を返す

[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]);
2

223. jacobian([f_{1}, …, f_{m}],[x_{1}, …, x_{n}]|mat=1) :: 関数の組 (f_{1}, …, f_{m}) の変数 (x_{1}, …, x_{n}) についてのヤコビアン (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 ]
224. hessian([f,[x_{1}, . . . , x_{n}]|mat=1)

:: 関数の組 f の変数 (x_{1}, …, x_{n}) についてのヘシアンまたはヘッセ行列を返す．

[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 ]
225. wronskian[f_{1}, . . . , f_{n}],x|mat=1)

:: 関数の組 (f_{1}, …, f_{n}) の変数 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) ]
226. 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);
227. intpoly(p,x|exp=c,cos=c,sin=c)

:: 変数 x の多項式 p （またはそれと指数関数, 対数関数や三角関数の積）や有理式の原始函数を返す • p が多項式のときは，定数項のない多項式 ∫_{0}^{x} p(x) dx を返す

• exp=c を指定したとき， ∫ p(x)e^{cx}dx = q(x)e^{cx} となる多項式 q(x) を返す

• cos=c を指定したとき， ∫ p(x) cos cx dx = q(x) cos cx+r(x) sin cx となる多項式の組 [q(x), r(x)] を返す

• sin=c を指定したとき， ∫ p(x) sin cx dx = q(x) cos cx+r(x) sin cx となる多項式の組 [q(x), r(x)] を返す

• pow=c を指定したとき， ∫ p(x)x^{c} dx = q(x)x^{c} となる多項式 q(x) を返す

• log=[c,d] を指定したとき， ∫ p(x) log(cx + d) dx = q(x) log(cx + d) + r(x) となる多項式の組 [q(x), r(x)] を返す

• log=[c,d,m] を指定したとき， ∫ p(x) log^{m}(cx + d) dx = ∑_{j=0}^{m} q_{j}(x) log^{m−j}(cx + d) となる多項式のリスト [q_{0}(x), q_{1}(x), …] を返す (m は正整数)．

• c, d は複素数や x を含まない有理式でもよい．

• p が x の有理式の時，その原始関数を返す．ただし分母は x の 2 次以下の多項式の積に因数分解可能され， 2 次多項式の判別式の定数倍は完全平方とする．

[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)
228. integrate(f,x|dumb=k,dviout=p,log=1,frac=t,I=[a,b])

:: 関数 f を変数 x について不定積分する • I=[a,b] : 定積分 ∫_{a}^{b} 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 を不定元とする多項式

• 多項式と x^{c} や a^{x} との積， x と x の 1 次関数の log の多項式，さらにはそれらと前項の式との和 • sin x, cos x, tan x の有理式．有理数 k を用いた sin kx や cos kx などが混ざっていてもよい

∫ r(cos x, sin x)dx = ∫ R(\frac{1 − t^{2}}{1 + t^{2}} , \frac{2t}{1 + t^{2}} )\frac{2}{1 + t^{2}} dt (t = tan \frac{x}{2})

• r(x) arctan p(x) の形

∫ r(x) arctan^{m} p(x) dx = ∫ r(x)dx · arctan^{m} p(x)

− m ∫ \frac{p′(x) ∫ r(x)dx}{1 + p(x)^{2}} arctan^{m−1} p(x) dx

• arcsin, arccos, log においても上と同様な部分積分を行う． • exp x や e^{x} の有理式．有理数 k を用いた exp kx や e^{kx} などが混ざっていてもよい

∫ r(e^{kx})dx = ∫ r(y)\frac{dy}{ky} (y = e^{kx})

• r(x, \sqrt{c^{2} − (ax − b)^{2}}) で， r(x, y) が有理式

∫ r(x, \sqrt{c^{2} − (ax − b)^{2}}) dx = ∫ r(\frac{c}{a} sin t + \frac{b}{a}, c cos t)\frac{c}{a} cos t dt (x = \frac{c}{a} sin t + \frac{b}{a})

• r(x, \sqrt{(ax − b)^{2} − c^{2}}) で， r(x, y) が有理式

∫ r(x, \sqrt{(ax − b)^{2} − c^{2}}) dx = ∫ r(\frac{c}{a cos t} + \frac{b}{a}, \frac{c sin t}{cos t})\frac{c sin t}{a cos^{2} t}dt (x = \frac{c}{a cos t} + \frac{b}{a})

• r(x, \sqrt{(ax − b)^{2} + c^{2}}) で， r(x, y) が有理式

∫ r(x, \sqrt{c^{2} + (ax − b)^{2}}) dx = ∫ r(\frac{c sin t}{a cos t} + \frac{b}{a}, \frac{c}{cos t})\frac{c}{a cos^{2} t}dt (x = \frac{c sin t}{a cos t} + \frac{b}{a})

• r(x, (\frac{αx+β}{γx+δ})^{\frac{m}{n}} ) で， r(x, y) が有理式

∫ r(x, (\frac{αx+β}{γx+δ})^{\frac{m}{n}} ) dx = ∫ r(−\frac{δt^{n} − β}{γt^{n} − α}, t^{m})(−\frac{d}{dt} \frac{δt^{n} − β}{γt^{n} − α}) dt (t = (\frac{αx+β}{γx+δ})^{\frac{1}{n}})

• r(x, \sqrt{αx + β}, \sqrt{γx + δ}) で， r(x, y, z) が有理式

∫ r(x, \sqrt{αx + β}, \sqrt{γx + δ})dx = ∫ r (\frac{t^{2} − δ}{γ} , \sqrt{\frac{αt^{2} − αδ + βγ}{γ}} , t) \frac{2t}{γ}dt (t = \sqrt{γ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)
[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)))
[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] では

∫_{0}^{x}(\frac{1}{c}x^{2} + \frac{a}{b}) dx = \frac{1}{3c}x^{3} + \frac{a}{b}x,
∫ x^{2}e^{x} dx = (x^{2} − 2x + 2)e^{x},
∫ xa^{x} dx = \frac{(x log a − 1)a^{x}}{(log a)^{2}} ,
∫ x^{2} sin cx dx = (−\frac{1}{c}x^{2} + \frac{1}{c^{3}} ) cos cx + \frac{2}{c^{2}} x sin cx,
∫ 4x log^{2} |x + 1| dx = (2x^{2} − 2) log^{2} |x + 1| − (2x^{2} − 4x − 6) log |x + 1| + x^{2} − 6x,
∫ \frac{2 dx}{(x^{2} + a^{2})^{2}} = \frac{1}{a^{3}} arctan \frac{x}{a} + \frac{x}{a^{2}(x^{2} + a^{2})},
∫ \frac{4 dx}{(x^{2} − a^{2})^{2}} = \frac{1}{a^{3}} (log |x + a| − log |x − a|) − \frac{2x}{a^{2}(x^{2} − a^{2})},
∫ \frac{dx}{x^{2} − 2} = \frac{\sqrt{2}}{4} log |\frac{x − \sqrt{2}}{x + \sqrt{2}}| ,
∫ \frac{dx}{x^{4} + 1} = \frac{\sqrt{2}}{8} log |\frac{x^{2} + \sqrt{2}x + 1}{x^{2} − \sqrt{2}x + 1}| + \frac{\sqrt{2}}{4}(arctan(\sqrt{2}x + 1) + arctan(\sqrt{2}x − 1)),
∫ \frac{dx}{x^{6} + 1} = \frac{\sqrt{3}}{12}(log |x^{2} + \sqrt{3}x + 1| − log |x^{2} − \sqrt{3}x + 1|)
+ \frac{1}{6}arctan(2x + \sqrt{3}) + \frac{1}{6}arctan(2x − \sqrt{3}) + \frac{1}{3} arctan x,
∫ x sin x · e^{x} dx = (x(sin x − cos x) + cos x)e^{x},
∫ tan x dx = − log | cos x|,
∫ tan^{2} x dx = \frac{sin x}{cos x} − x,
∫ \frac{dx}{3 cos x + 4 sin x} = \frac{1}{5} log |\frac{3 tan \frac{x}{2} + 1}{tan \frac{x}{2} − 3}| ,
∫ arctan x dx = x arctan x − \frac{1}{2} log(x^{2} + 1),
∫ 6(x^{2} + 1) arctan \frac{1}{x} dx = (2x^{3} + 6x) arctan \frac{1}{x} + x^{2} + 2 log(x^{2} + 1),
∫ (2bx − a^{2}x^{2})^{− \frac{1}{2}} dx = \frac{1}{a} arcsin \frac{a^{2}x − ab}{b},
∫ \sqrt{a^{2} − x^{2}} dx = \frac{1}{2}(x\sqrt{a^{2} − x^{2}} + a^{2} arcsin \frac{x}{a}),
∫ \frac{dx}{\sqrt{x^{2} − 1}} = log|x + \sqrt{x^{2} − 1}|,

∫ \sqrt{x^{2} − 1} dx = \frac{1}{2}(x\sqrt{x^{2} − 1} − log(x + \sqrt{x^{2} − 1})),
∫ \frac{dx}{\sqrt{x^{2} + a^{2}}} = log|x + \sqrt{x^{2} + a^{2}}|,
∫ 2\sqrt{x^{2} + a^{2}} dx = x\sqrt{x^{2} + a^{2}} + a^{2} log|x + \sqrt{x^{2} + a^{2}}|,
∫ \frac{\sqrt{x} dx}{x + 1} = 2\sqrt{x} − 2 arctan \sqrt{x},
∫ \frac{\sqrt[3]{x} dx}{x + 1} = 3\sqrt[3]{x} − \sqrt{3} arctan(\frac{2\sqrt{3}}{3} \sqrt[3]{x} − \frac{\sqrt{3}}{3}) + \frac{1}{2} log |\sqrt[3]{x^{2}} − \sqrt[3]{x} + 1| − log |\sqrt[3]{x} + 1|,
∫ \sqrt{\frac{2 − x}{x}} dx = x\sqrt{\frac{2 − x}{x}} − 2 arctan \sqrt{\frac{2 − x}{x}},
∫ \frac{dx}{e^{x} + e^{−x}} = arctan exp(x),
∫ \frac{x sin x + cos x}{x cos x} dx = log |x| − log | cos(x)|,
∫ arcsin^{2} x dx = x arcsin^{2} x + 2\sqrt{1 − x^{2}} arcsin x − 2x,
∫ \frac{dx}{x log x} = log(log x)

を得ている．

[33] os_md.integrate(1/(x^4+4),x|dviout=1,log=1)$

∫ \frac{dx}{x^{4} + 4} = \frac{1}{8} arctan(x + 1) + \frac{1}{8} arctan(x − 1) + \frac{1}{16} log (\frac{x^{2} + 2x + 2}{x^{2} − 2x + 2})

[34] os_md.integrate(((1-cos(x))/(1/2-cos(x)))^(1/2),x|dviout=2)$

∫ (\frac{− cos(x) + 1}{− cos(x) + \frac{1}{2}} )^{\frac{1}{2}} dx  (t = tan(\frac{1}{2}x))

= ∫ \frac{4\sqrt{\frac{1}{3t^{2}−1}}t}{t^{2} + 1} dt

(\sqrt{3}t = \frac{1}{cos(s)})

= ∫ \frac{−4}{3 (sin(s))^{2} − 4} dx_{1}

(u = tan(s))

= ∫ \frac{4}{u^{2} + 4} du

= 2 arctan(\frac{1}{2}u) = 2 arctan ( \frac{\frac{1}{2} sin(s)}{cos(s)}) = 2 arctan(\frac{1}{2} \sqrt{3t^{2} − 1}) = 2 arctan (\frac{1}{2} \sqrt{3 (tan(\frac{1}{2}x))^{2} − 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 を指定すると以下が得られる．

∫_{0}^{π} sin(x)x dx = π, ∫_{0}^{∞} exp(−x)x^{2} dx = 2, ∫_{0}^{1} log(x) dx = 1.

229. rungeKutta(f,n,[a,b],y,y_{0}|mul=k,prec=1,single=1,val=1)

:: Runge-Kutta 法で常微分方程式 y′ = f(x, y) の数値解を求める（f は連立も可）

• 常微分方程式 y′ = f(x, y) を，初期条件 y(a) = y_{0} で，区間 [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, y_{0} をリストにする．たとえば

\frac{dy_{j}}{dx} = f_{j}(x, y_{1}, …, y_{n}) (j = 1, …, m)

ならば

rungeKutta([f_{1}, …, f_{m}],n,[a,b],[y_{1}, …, y_{m}],[y_{1}(a), …, y_{m}(a)])

とする．

• オプション val=1 では， x_{ν} と y の第 1 成分の組のみを返す．

• 単独高階のときは，たとえば

y^{(m+1)} = f(x, y, y′, …, y^{(m)})

のときは

rungeKutta(f(x, y, y_{1}, …, y_{m}),n,[a,b],[y, y_{1}, …, y_{m}],[y(a), y′(a), …, y^{(m)}(a)])

とする．ただし f がリスト形式函数のときは，オプション single=1 を指定する．

• 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);
[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 を用いて表示 */
230. pwTaylor(f,n,[a,b],x,x_{0},m|mul=k,prec=p,val=1,err=e,view=[[c_{0},c_{1},d_{0},d_{1}],c,u],Inf=s)

:: 区分的な Taylor 展開で常微分方程式 x′ = f(t, x) の数値解を求める（f は連立も可）常微分方程式 x′ = f(t, x) を，初期条件 x(a) = x_{0} で，区間 [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, x_{0} をリストにする．たとえば

\frac{dx_{j}}{dt} = f_{j}(t, x_{1}, …, x_{N}) (j = 1, …, N),

ならば

pwTaylor([f_{1}, …, f_{N}],n,[a,b],[x_{1}, …, x_{n}],[x_{1}(a), …, x_{N}(a)],m)

とする．

• オプション 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=[s_{1},s_{2},s_{3},s_{4},s_{5}] とすると, チェック後の精度を表す正整数パラメータ s_{2} に応じて， s_{1} 分割毎に爆発をチェックし，（必要に応じて複数回）時刻の進みを遅くし，分割の総数を s_{3} 倍する（一回のみ）． s_{4} は標準のノルムで正数． s_{5} は err=を指定したとき，打ち切る相対誤差を\frac{1}{s_{5}} に設定する（デフォルトは， s_{5} = 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, x′, …, x^{(N)})

ならば

pwTaylor(f(t, x, x_{1}, …, x_{N}),n,[a,b],[x, x_{1}, …, x_{N}],[x(a), x′(a), …, x^{(N)}(a)],m)

とする．ただし， x_{j} は x(t) の j 階導関数．

戻り値は [t_{ν},x(t_{ν}),x′(t_{ν}),…,x^{(N)}(t_{ν})].

• view=[[c_{0},c_{1},d_{0},d_{1}],c,u] を指定すると， Risa/Asir の Canvas で解がグラフ表示される． [c_{0}, c_{1}] はウインドウの x 座標の範囲， [d_{0}, d_{1}] はウインドウの 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)) または (x_{1}(t), x_{2}(t)) が表示される．

– c と u は同時に省略できる． c を省略したときは，色は黒．

– view=[[x_{0},y_{0},x_{1},y_{1},z_{0},z_{1}],c,u] とすると， 3 番目の成分 x_{3}(t) によって，定まる\frac{x_{3}(t)−z_{0}}{z_{1}−z_{0}}

の値によって色が連続変化する．

このとき， u が 3 × N 行列ならば， ux(t) = (y_{1}(t), y_{2}(t), y_{3}(t)) とおいたとき，色は y_{3}(t) で定まる (y_{1}(t), y_{2}(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] も同じ）は，それぞれ

\begin{cases}\frac{dy}{dt} = y. \\ y(0) = 1 \end{cases} t ∈ [0, 1],  \begin{cases}\frac{dx}{dt} = y, \\ \frac{dy}{dt} = −x, \\ (x(0), y(0)) = (1, 0), \end{cases} t ∈ [0, \frac{π}{2} ]

という方程式を, 時間を 4 分割して考えている． [3]〜[6] は， t ∈ [0, 1], x(0) = x′(0) = 1 を満たす次の各方程式の解を考えている．

x′′ = t,  x′′ = x,  x′′ = x + t,  x′′ = x′ + 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)]);
[ 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] は

x′′ = −x (x(0) = 0, x′(0) = 1)

の近似解の計算で，計算時間は 0.1 秒程度．解は (x(t), x′(t)) = (sin t, cos t) であるが，数値計算された (x(2π), x′(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 */
[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] は

\begin{cases}x′ = x^{2}, \\ x(0) = 1   \end{cases}

の解を [0, 2] の範囲で求めている．得た解の最後の時刻は， t_{0} = 1 − 2.15619 ⋯ × 10^{−28} で， x(t_{0}) = 4.6738 ⋯ × 10^{27} となり，これは 16 桁程度の精度．実際の解は x(t) = \frac{1}{1−t} となり， t → 1 で爆発する．

[17] では， [0, 2] の範囲を 200 分割し，さらにそれを 100 個に細分して計算しているので， 1 秒を 10^{4} 個に等分割している．但し，解が爆発に近づく（すなわち，細分あたりの解の予想される変化率が閾値を超える）と，それを押さえるため細分は細かくなっていく．ただし，このチェックは 100 細分毎（Inf=の第一成分で指定）で，結果も 100 細分毎（mul=で指定）に出力される．チェックの鋭敏性とチェック後の精度は Inf=の第二成分で調整される．

爆発が起きるので，デフォルトでは，細分の総個数は 2 倍（Inf=の第三成分で指定）されて， 4 × 10^{4} となり，出力のデータは， 401 個となる（爆発がなければ， 201 個）．また，最初に分割が細かくなるのは 0.95 秒後で， x(0.95) = 20 のときであった．

なお， [24] で得た推定爆発時刻 R[0][N][0] は 43 桁程度の精度がある．

精度と計算時間

• m 次の Taylor 法による精度は，分割の個数 nk の m 乗，すなわち (nk)^{m} に比例すると考えてよい．

• 計算時間は，分割の個数 nk にほぼ比例する． m を増やすと計算精度が上がるが，計算時間は f で与えた方程式の複雑性に依存する．

rungeKutta() の項にある Lorenz 方程式の場合（T 秒後まで）

関数次数分割計算精度 T 最大誤差実行時間 (sec)
rungeKutta  4 100000  63 桁 30 0.5  47.22
rungeKutta  4 160000  63 桁 30 0.09  83.47
rungeKutta  4 1000000  63 桁 30 6.0 × 10^{−5}  589.5
pwTaylor  4 160000  63 桁 30 0.12  1.51
pwTaylor  4 170000  63 桁 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 100000  99 桁 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 秒につき誤差が約 10^{4} 倍程度に拡大することが分かる． pwTaylor() によって 16 次で\frac{3}{1000} 秒毎の分割では， 30 秒後の誤差が 2 × 10^{−19} 程度である．よって 60 秒後の誤差は 2 × 10^{−7} 程度で，処理時間は 40 秒程度と予想されるが，実際上のようになる．

一方 4 次 Runge-Kutta では，\frac{1}{10^{7}} 秒までに細分すると， 60 秒後の誤差は 0.1 程度に押さえられるが，所要時間は 3.5 × 10^{5} 秒 = 90 時間程度． 120 秒後までの計算には，この 80 倍程度の時間がかかる（10^{24} ≑ 4^{40}）．

• なお，任意精度浮動小数計算の速度を調べると（用いたノートパソコン： 2016 年製造, CPU Core

i7-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 万回の実行にかかった時間（秒数）は, 以下の表のようであった．

setprec 計算精度実行時間計算時間
–  3.17  0.00
倍精度  ?  10.40  7.23
10  9  19.11  15.94
50  49  20.99  17.82
100  99  22.69  19.52
200  199  27.42  24.24
400  399  37.92  34.75
800  799  59.70  56.53
1600  1599  110.33  107.16

231. powsum(n)

:: 1^{n} + 2^{n} + ⋯ + m^{n} の m を x で置き換えた n + 1 次多項式を返す

[0] os_md.fctrtos(os_md.powsum(3));
1/4*x^2*(x+1)^2
232. bernoulli(n)

:: n 次の Bernoulli 多項式 B_{n}(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 以下の数値函数では変数（引数）を不定変数にすると対応するリスト形式函数を返す．

233. frac(x)

:: 実数 x の小数部分

pari(frac,x) と同等．
234. erfc(x)  erfc([x,prec])

:: 相補誤差函数 erfc(x) = \frac{2}{\sqrt{π}} ∫_{x}^{∞} e^{−t^{2}}dt

pari(erfc,x) または pari(erfc,x,prec) と同等．
235. fouriers([a_{0},a_{1},. . .,a_{m}],[b_{1},b_{2},. . .,b_{n}],z|cpx=1,sum=f,y=t,const=c)
fouriers([f,m],[g,n],z|cpx=1,sum=f,y=t,const=c)

:: 有限 Fourier 級数 a_{0} + a_{1} cos z + a_{2} cos 2z + ⋯ + a_{m} cos mz + b_{1} sin x + b_{2} sin 2z + ⋯ + b_{n} sin nz • cpx=1 のときは， a_{0} + a_{1}e^{iz} + a_{2}e^{2iz} + ⋯ + a_{m}e^{imz} + b_{1}e^{−iz} + b_{2}e^{−2iz} + ⋯ + b_{n}e^{−niz}

• [a_{0},a_{1},…,a_{m}] の代わりに [f,m] と指定することができ，このときは a_{k} = myf2eval(f,k,t) と解釈される（0 ≤ k ≤ m）．ただし const=c を指定すると， a_{0} は c で与えられる．また， f の変数に y が含まれないときは， y=t の指定は無視される.

• [b_{1},…,b_{n}] の代わりに [g,n] と指定することができ，このときは b_{k} = myf2eval(g,k,t) と解釈される（1 ≤ k ≤ n）．

• sum=1 : チェザロ総和法を用いる．

• sum=2 : シグマ総和法を用いる．

• sum=s(x,y) : フーリエ級数の有限和

a_{0} + ∑_{k=1}^{n−1} s(\frac{k}{n}, n)(a_{k} cos kx + b_{k} sin kx)

において 1 とは限らない項 s(\frac{k}{n}, n) で調整して総和を取る総和法を行う．チェザロ総和法では， s(x,y) は 1 − x，シグマ総和法では\frac{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);

上の [2] は，次のようにしてもよい（∑_{m=0}^{10} sin(2m + 1)x）．

[2] F=os_md.fouriers([],[(1-(-1)^x)/2/x,21],x)$

fouriers([],[(1-(-1)^x)/x,n],x) : 方形波（最大値は\frac{π}{4} )
fouriers([],[-(-1)^x/x,n],x) : 鋸波（最大値は\frac{π}{2} )
fouriers([(1-(-1)^x)/x,n],[],x) : 三角波（最大値と最小値は ±\frac{π^{2}}{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)
236. myexp(z)

:: 指数関数 exp(z)

237. mysin(z)

:: 三角関数 sin(z)

238. mycos(z)

:: 三角関数 cos(z)

239. mytan(z)

:: 三角関数 tan(z)

240. myasin(z)

:: 逆三角関数 asin(z)

241. myacos(z)

:: 逆三角関数 acos(z)

242. myatan(z)

:: 逆三角関数 atan(z)

243. mylog(z)

:: 対数函数 log(z)

244. nlog(z)

:: log_{10}(z)

245. dlog10(x)

:: log_{10}(|x|) log_{10}(|x|) を返す． x は 1000 桁の整数などの大きな有理数や 0 に近い有理数でもよい．

 [0] os_md.dlog10(10^(3000)/2);
 2999.7
 [1] os_md.dlog10(-10^(-3000)/2);
 -3000.3
246. mypow(z,w)

:: 巾関数 z^{w} mypow(0,w) は w に依らずに 0 を， mypow(z,0) は z ≠ 0 のとき 1 を返す．

247. 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() を組み合わせて実現されている．
248. sqrt(z)  sqrt([z,prec])

:: z の平方根を与える

 • pari(sqrt,z) または pari(sqrt,z,prec) と同等．

• prec は精度（桁数）を与える．

• \sqrt{z} または\sqrt{−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)
249. 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)
250. 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);
2.82422940796034787421 E456568
[2] os_md.gamma(@i);
(-0.15494982830181068512-0.49801566811835604271*@i)
251. digamma(z)  digamma([z,prec])

:: ディガンマ函数 ψ(z) = \frac{Γ′(z)}{Γ(z)}

pari(psi,z) または pari(digamma,z,prec) と同等．
252. lngamma(z)  lngamma([z,prec])

:: log(Γ(z))

pari(lngamma,z) または pari(lngamma,z,prec) と同等．
253. dilog(z)

:: ダイログ函数 Li_{2}(z) = ∑_{k=1}^{∞} \frac{z^{k}}{k^{2}}

pari(dilog,z) と同等．

254. zeta(s)  zeta([s,prec])

:: zeta 函数 ζ(s)

pari(zeta,s) または pari(zeta,s,prec) と同等．
255. eta(τ)  eta([τ,prec])

:: Dedekind の Eta 函数 η(τ) = e^{\frac{πiτ}{12}} ∏_{m=1}^{∞}(1 − e^{2πimτ})

τ は虚部が正の複素数．

pari(eta,τ) または pari(eta,τ,prec) と同等．
256. jell(τ)  jell([τ,prec])

:: Elliptic j-invariant j(τ)

τ は虚部が正の複素数．

pari(jell,s) または pari(jell,τ,prec) と同等．

3.2.5 Lists and vectors

257. 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]

258. llsize([m_{1}, m_{2}, …])

:: リスト m_{j} のリストに対し，成分 m_{j} の個数と m_{j} の要素の最大個数を返す

[0] os_md.llsize([[1,2],[0,1,2,3],[1]]);
[3,4]

259. findin(m,[ℓ_{0}, ℓ_{1}, …])

:: m に等しい要素を ℓ_{0}, ℓ_{1}, … から探す • 最初に見つかった番号を返す．存在しなければ −1 を返す．

• 2 番目の引数はリストでなくてベクトルでも可．

[0] os_md.findin("cat",["man","dog","cat","bird"]);
[1] 2
参照： base position()
260. 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]
261. 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]]
262. delopt(ℓ,s|inv=1)  delopt(ℓ,[s_{1},s_{2},. . .]|inv=f)

:: オプションリスト（リストのリスト）からオプション s （複数指定可）を削除，抽出，付加． ℓ をリスト [ℓ_{1}, ℓ_{2}, …] とするとき，成分 ℓ_{j} がリストであって， ℓ_{j} の最初の成分が s に等しいときに ℓ_{j} を除いたリストを返す．複数のオプション s を指定するときは，それらをリストにまとめて指定する．

• 抜き出された結果の並びは， ℓ 内の順序を保つ．

• inv=1,2 : これを指定すると， ℓ_{j} の最初の成分が s に（s がリストの時は，そのいずれかに）等しいもののみのリストを返す．但し s がリストのリストの時（s_{i} がリストの時）は， s の成分 s_{i} と最初の成分同士が一致するものは置き換え，それが存在しない場合は付加する． s の各成分 s_{i} は重複せずに 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]];
[[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]]
263. mycat([ℓ_{1}, . . . , ℓ_{m}]|delim=s)
264. 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.
265. 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)]
266. l2p(l,v|size=s)

:: 係数のリスト l を与えて v の多項式を返す．またその逆変換を返す． • 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]
[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
267. mulseries(v_{1},v_{2})

:: ２つのベクトルをべき級数とみなして，その積のベクトルを返す戻り値の長さは，両者のベクトルの長さの小さい方とする．（cf. vprod()．）

268. pluspower(p,x,r,m)

:: (1 + p)^{r} の x に関するべき級数展開を第 m 項まで求める • p は定数項のない x の多項式．

• 戻り値は長さ m のベクトルで最初の成分の値は 1．

269. 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]]
270. regress(ℓ|sint=k)

:: 実数の組のリストに対し，回帰直線を求める戻り値は [回帰直線の傾き，回帰直線の切片，相関係数，平均値，標準偏差，平均値，標準偏差]． sint=k : k が自然数の時は，値の有効桁を k 桁に丸める（sint() の第 2 引数）．戻り値を [a,b,v_{1}, s_{1}, v_{2}, s_{2}] とすると y = ax + b が回帰直線（x は第 1 成分， y を第 2 成分に対応， v_{i} は第 i 成分の平均値， s_{i} は第 i 成分の標準偏差）

271. vprod(v_{1},v_{2})
272. dvprod(v_{1},v_{2})

:: 2 つのベクトル（リストでもよい）の内積を返す • リストの長さが長大のときは，ベクトルにするか dvprod( ) を用いるのがよい．

• 成分が有理式のときは，分母の拡大を避けるため vprod( ) を用いるのがよい．

• v_{i} がベクトル v_{i} によって [v_{i,1},v_{i,2}] となっているときは， v_{i,2} − v_{i,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)
[5] os_md.dvprod([1/a^2,2/a,3/a],[a,b,c]);
((2*b+3*c+1)*a^3)/(a^4)
273. llbase(v,ℓ)

:: 変数 ℓ[0], ℓ[1], … の一次方程式のベクトル v の標準変換を行う（例は lsol() の項を参照）

274. lsol(v,l)

:: 変数 ℓ[0], ℓ[1], … に関する連立一次方程式を解く変数は， x^{3} のような変数の正整数ベキでもよい．ベキが異なるとき異なる変数とみなす． 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 ]
275. lnsol(v,l)

:: 変数 ℓ[0], ℓ[1], … に関する連立一次方程式の有理数解を求める変数は， x^{3} のような変数の正整数ベキでもよい．ベキが異なるとき異なる変数とみなす．なお 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] ]
276. lchange(ℓ,k,v|flat=1)

:: （多重）リスト ℓ の k で指定した位置の成分を v に置き換える • k はリストで，重複の深さの成分がある． k が数のときは， [k] とみなす．なお， 0 は最初の成分． • flat=1 を指定したとき， k = [k_{1}, k_{2}, …], v = [v_{1}, v_{2}, …] ならば， ℓ[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]]

277. lsum([m_{1}, m_{2}, …])

:: m_{1}, m_{2}, … の中の和を返す • 引数はリストでなく，ベクトルや行列でもよい

[0] os_md.lsum([1,2,3,4,5]);
15

[1] os_md.lsum(["1","2","3","4","5"]);
12345

278. lmax([m_{1}, m_{2}, …])

:: m_{1}, m_{2}, … の中の最大のものを返す

279. lmin([m_{1}, m_{2}, …])

:: m_{1}, m_{2}, … の中の最小のものを返す • 引数はリストでなく，ベクトルや行列でもよい

[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]);
2
280. lgcd([m_{1}, m_{2}, . . .]|poly=1])

:: m_{1}, m_{2}, … の最大公約数（元）を返す

281. llcm([m_{1}, m_{2}, . . .]|poly=1,poly=[x_{1}, x_{2}, . . .],dn=1])

:: m_{1}, m_{2}, … の最小公倍数（元）を返す • poly=1 を指定すると，要素を多項式とみなす．

• poly=[x_{1}, x_{2}, …] を指定すると，要素を x_{1}, x_{2}, … の多項式とみなす． • 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);
x
282. ldev(ℓ,s)

:: リスト s の整数倍をリスト ℓ に加えて，成分の絶対値を最小にする • ℓ + ms が求めるものとするとき， [m, ℓ + ms] 返す．

[0] os_md.ldev([1,3,5,9],[1,-1,1,-1]);
[1] [2,[3,1,7,7]]
283. qsortn(ℓ)

:: 大きい順のクイックソート

[0] os_md.qsortn([3,4,2,1,5,0]);
[5,4,3,2,1,0]
284. 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]]
285. llselect(ℓ,n,k|eq=1,val=1)

:: 表形式のリストを成分の条件で分割する成分の条件で分割して，リストを分ける．

• n 番目の成分をキーとする

• n =[n_{0},[n_{1},n_{2}]] : n_{0} 番目の成分の n_{1} 文字目から n_{2} 文字目までをキーとする（n_{1} = 0 のときは先頭文字から）

• eval=1 : 文字列を数値などの値に変換してキーとする

• k = 0 のときは，キーでリストでリストを分割する．

• k がリストでないときは， k は [k] で置き換えられる

• k=[k_{1},k_{2}, …] : キーが文字列であるか eq=1 が設定されているならば k の中にあるリストを選んで残りと 2 分割

• 上でなくて k = [k_{1}, k_{2}] のとき，キーが k_{1} と k_{2} の間にあるものを選んで残りと 2 分割

• div=1 が指定され， k =[k_{1},k_{2}, …] のときは， L_{i}=llselect(ℓ_{i},n, k_{i});ℓ_{i+1}=L_{i}[1] を実行し，

[car(L_{1}),car(L_{2}), …] を返す．残りが空でなければ最後に残りのリストを付加する．

286. llget(ℓ,[a_{1},a_{2},. . .],[b_{1},b_{2},. . .]|flat=1)

:: 表形式のリストから行や列を抽出 • [a_{1},a_{2},…] : a_{1} 行目， a_{2} 行目， … を抽出

a_{j} =[c_{1},c_{2}] : c_{1}, c_{1} + 1, …, c_{2} を意味する. a_{j} =[c_{1}] : c_{1} 行目以降最後までを意味する． [a_{1}, …] の代わりに単に 1 のときは行の操作は行わない [b_{1}, …] の代わりに単に −1 のときは，抽出でなくて削除とする．

• [b_{1},b_{2},…] : b_{1} 項目， b_{2} 項目， … を抽出 b_{j} =[c_{1},c_{2}] : c_{1}, c_{1} + 1, …, c_{2} を意味する b_{j} =[c_{1}] : c_{1} 項目以降最後までを意味する． [b_{1}, …] の代わりに単に 1 のときは項目の操作は行わない. [a_{1}, …] の代わりに単に −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]
287. sort2([m_{1},m_{2}])

:: 2 成分のリストまたはベクトルの成分を小さい順に並び替える

288. lsort(ℓ_{1},ℓ_{2},t|c1=[c_{1,0},c_{1,1}, …],c2=[c_{2,0},c_{2,1}, …]) :: リスト ℓ_{1} に対し， ℓ_{2} との合併，共通部分，または ℓ_{2} や共通部分を除くその他，表形式データの操作 · ℓ がリストで， t が数または文字列のとき．

• 小さい順にソートされたリストを返す．

• ℓ_{2} = [] で t = 0 または "cup" のときは l_{1} をソート， t = 1 または"setminus"のときは，さらに重複を除く． t = 7 または"cut"のときは c1=k で ℓ_{1} を最初の k 個の要素と残りの要素の 2 つのリストに分割する．ただし k が負の数のときは，最後の |k| 個を除いた要素と最後の |k| 個の要素との 2 つに分割する． 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 =[t_{0},t_{1},…] がリストで， ℓ_{1} がリストのリストのとき

t_{0} については，上の t と同様の指定が可能で，以下のようになる．（エクセルの表のようなものの操作. cf. readcsv()） . また t =[] は， [0] と解釈される．

• ℓ_{2} =[] または "sort" のとき

– t_{0} = 0 または "put" のときはリストの要素の t_{1} 番目の項をキーとしてソートする（逆順ソートでは， −t_{1} − 1 を指定する）

– t_{0} = 3 または "reduce" のときは，キーが同じものは重複を省いて一つを選ぶ．

– t_{0} = 6 または "reduce" のときは，キーに重複がないものを削る．

• ℓ_{2} = 0 または "col" のとき : オプション c1=を指定すると – t_{0} = 0 または "put" のとき, c_{1,1}, c_{1,2}, … 番目の項目を抜き出したリストのリストを返す．

– t_{0} = 1 または "setminus" のとき, c_{1,1}, c_{1,2} … 番目の項目を削除したリストのリストを返す．

• ℓ_{2} = 1 または "num" のとき

t_{1} が存在しないときは， t_{1} = 0 とみなす． – t_{0} ="col" : 項目番号のリストを最初の要素として挿入．

– t_{1} が数のとき ∗ t_{0} = 0 または "put" : 各要素の先頭に順に t_{1} から番号を挿入する．

∗ t_{0} = 1 または "get" : c_{1} で指定された番号 c_{1,0}, c_{1,1}, ⋯ の要素をこの順に抜き出す．

∗ t_{0} = 2 または "sub" : c_{1} で指定された番号の要素を削除．

∗ t_{0} = 3 または "sum" : 要素の個数を返す

– それ以外のとき，以下のように i 番目の要素について値 V_{i} を得る．

∗ t_{1} が函数子のとき，その要素（ただし， t_{2} が指定されていれば，要素の t_{2} 番目の項目）を引数として返された値． isyes() や calc() などが利用できる．

∗ t_{1} がリスト [s,v] のときは，函数 calc( ·,[s,v]) という函数にその要素（ただし， t_{2} が指定されていれば，要素の t_{2} 番目の項目）を入れて返された値

      s は ">", "<", "=", ">=", "<=", "!=" などが可能．

∗ t_{1} が文字列 "+" のとき，各要素の c_{1,1}, c_{1,2} … 番目の項目の和（数でないものは 0 とみな

して足す）．この値に V_{i} 対し

∗ t_{0} = 0 または "put" : 各要素の先頭に V_{i} を挿入する．

∗ t_{0} = 1 または "get" : V_{i} が 0 でない要素のみ抜き出す．

∗ t_{0} = 2 または "sub" : V_{i} が 0 の要素のみ抜き出す．

∗ t_{0} = 3 または "sum" : V_{i} の和を返す

• ℓ_{2} ="transpose" で t_{0} ="put" のとき, 行と列を逆にする（転置）．

• ℓ_{2} ="adjust" で t_{0} ="put" のとき, 要素の項目の個数が異なっているとき，最大の個数に揃え，後ろには空文字列 "" を詰める．なお， t_{1} で空きに詰めるものを指定できる．

• ℓ_{2} ="subst" で t_{0} ="put" のとき t_{j}=[a_{j},b_{j},c_{j}] : a_{j} 番目の要素の b_{j} 番目の項を c_{j} で置き換える．

• ℓ_{1}, ℓ_{2} がリストのリストのとき， ℓ_{1} の要素の t_{1} 番目の項を ℓ_{1} のキー項目， ℓ_{2} の要素の t_{2} 番目の

項を ℓ_{2} のキー項目と指定して，以下を行う.

– t_{1} や t_{2} が省略された場合は，それらは 0 とみなす．

– ℓ_{2} の各要素がリストではない 1 項目からなっているとき，その項目のみを並べたリストを ℓ_{2} としてもよい．

– t_{0} = 0 または "cup" のとき, ℓ_{1} の要素に同じキーの ℓ_{2} の要素を付け加える． – t_{0} = 2 または "cap" のとき, 上と同様であるが，同じキーをもつ ℓ_{2} の要素がないものは削除

する．

– t_{0} = 1 または "setminus" のときは, 同じキーをもつ ℓ_{2} の要素があるものを ℓ_{1} から削除する（ℓ_{2} はキー以外の項は無視される）．

– t_{0} = 3 または "sum" のときは, 同じキーをもつ ℓ_{1} の要素と ℓ_{2} の要素は１つにまとめ， ℓ_{1} と ℓ_{2} を合併する．

– t_{0} = 4 または "over" のときは, 同じキーをもつ ℓ_{1} の要素と ℓ_{2} の要素に対し， ℓ_{1} の c_{1,ν} 番目の項目を ℓ_{2} の要素の c_{2,ν} 番目の項目によって置き換えて返す． ℓ_{1} と ℓ_{2} の要素が 1 つのときは，リストにせずにそのまま指定してもよい．次においても同様．

– t_{0} = 5 または "subst" のときは, 同じキーをもつ ℓ_{1} の要素と ℓ_{2} の要素に対し， ℓ_{2} の要素の c_{2,ν} 番目の項目が空（文字列）でなければ， ℓ_{1} の c_{1,ν} 番目の項目をそれで置き換えて返す．上を行って， t_{0} = 4, 5 以外では，オプション c1 と c2 で指定した ℓ_{1} と ℓ_{2} の要素の項目を抜き

出した（指定しないときは（t_{0} = 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 */
[[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]]
[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]]
289. 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=[x_{1},x_{2},...] によって初期データ（要素のリスト）を与えることができる．初期データは重複があってもよい．最適化された二分木が初期状態として設定され， e はその長さ +v となる．

– オプション optimize=[d_{1},d_{2},...,d_{m},0] によって，それを dp （V[0][6]）に設定する． d_{i} は 4 以上の 2 のべき乗が適当．リストの先頭の数がノードの数 +1 になったとき，最適化が自動的に行われてリストの先頭が削られる．

最後の 0 は最適化終了を意味するが， −4 と −3 は特別な以下の特別な意味を持つ． optimize=[d_{1},d_{2},...,d_{m},−4] とすると，ノードの数が d_{m} − 1 のときの最適化の後， [2d_{m},−4] に設定される．一方， −4 でなくて −3 とすると， 2d_{m} でなくて d_{m}+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 : 空ノードも含むソートされた要素とその頻度のリストを返す

– p = 3 : 空ノードも含む要素のソートされたリストを返す

– p = −1 : ソートされた要素のノード番号のリストを返す

– p = −2 : 二分木の深さを返す

• s="optimize" : 二分木を最適化する，即ち要素の数が N のとき，最大の深さ m は 2^{m} > 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);
};
290. spantree(f,l,s|optimize=,comp=,unit=u,limit=m,fopt=op)

:: l の要素を使う函数 f による変換で s の要素から生成される二本木を作る l=[l_{1},l_{2}, ⋯], s=[s_{1},s_{2}, …] はリスト

• f(t, l_{i}|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
291. msort(ℓ,s)

:: ベクトルやリストの成分を（多重）キー s に従ってソートする • s =[f,m]

f = 1 ：小さい順， f = −1 ：大きい順

キーの m は – 0 : 成分の大小

– 1 : 成分がベクトルまたはリストのとき，その長さ

– 2 : 成分がベクトルまたはリストのとき，先頭からの辞書式順序

– 3 : 成分のタイプ

– 4 : 成分の絶対値

– 5 : 表示の長さ

– fn : 引数が 2 個の比較の函数子 fn を用いる

– [fn] : 引数が 1 個の函数 fn に代入して返される値の大小

• s =[f,m,k] : 成分がベクトルまたはリストのとき， (k + 1) 番目の成分で比較する

• s =[f,m,k_{1},k_{2}] : 成分がベクトルまたはリストのベクトルまたはリストのとき， (k_{1} + 1) 番目の成分の (k_{2} + 1) 番目の成分で比較する（さらに s =[f,m,k_{1},k_{2},k_{3}] なども可能）．

• s =[s_{1},s_{2}, …] : s_{i} は上のようなキーで， s_{1} のキーでの大小比較で同一となったときは s_{2} キーで比較というようにキーの辞書式順序で比較する．

[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]
292. 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);
    1
293. partspt(l,m|opt=f)

:: 一つの整数の 2 種の分割に対して細分関係を調べる • 整数の 2 種の分割 l, m に対し， m が l の細分となる関係を全て返す．

デフォルトでは， l の分割は順序づけられているとする（大きい順）．

l = l_{1} + ⋯ + l_{L} を l の分割とするとき， m の分割を m = m_{1} + ⋯ + m_{L} と並べ替えたもので， 1 ≤ ∀i ≤ L に対して n_{1} + ⋯ + l_{i} = m_{1} + ⋯ + m_{j_{i}} となる j_{i} が存在するものが存在する並べ替えをリストにして返す．

• opt=1 : ℓ の分割も順序づけられていないとして, [[l_{1}, [m_{1}, …, m_{j_{1}−1}], [l_{2}, [m_{j_{1}}, …, m_{j_{2}−1}], …] をリストにして返す．

• opt=2 : l の分割は順序づけられているとして，上の形式で細分となる関係を全て返す．

• opt=3 : l の分割は順序づけられていないとして，デフォルトと同様の形式で細分となる関係を全て返す．

[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]]]]
294. 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]]
295. addIL([a,b],[[a_{1},b_{1}],[a_{2},b_{2}],. . .]|in=t)

:: 有限区間の合併集合と有限区間の和集合の計算 • a_{1} < b_{1} < a_{2} < b_{2} < … となっている必要がある．

• [a,b] の代わりに最初の引数が 0 のときは，第 2 引数を上の形に直す．

• in=-1 を指定すると， [a,b] から [[a_{1},b_{1}],[a_{2},b_{2}],…] を除いた集合を返す．

• 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]]
[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);
0
296. lext2(m)

:: 2 次の外積の基底の並べ替え I = \{(i, j) | 0 ≤ i < j < n\} という\frac{n(n−1)}{2} 個のインデックスの集合を考える．

• m=[i,j,n] ： 0 ≤ i < j < n のとき， (i, j) が k 番目ならば [k,1] を返す（0 ≤ k < \frac{n(n−1)}{2}）． i = j のとき [0,0] を返す 0 ≤ j < i < n のとき， (j, i) が k 番目ならば [k,−1] を返す（0 ≤ k < \frac{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]
297. 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;
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 ]
298. 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);

[13] W;
[ 2 0 0 ]
299. paracmpl(l,t|lim=1,low=1,para=[v_{1}, v_{2}, . . .])

:: 有理的に t に依存したリスト l の成分（たとえば有理式）で張られる空間の正則完備化 l の成分が有理式 f_{1}(x, t), …, f_{m}(x, t) のとき（x は多変数でよい）， generic に t = t_{0} と特殊化した f_{1}(x, t_{0}), …, f_{m}(x, t_{0}) の一次独立な個数を m̄ とする． 1 変数 t の有理式 g_{i,j}(t) を適当に取って

h_{j}(x, t) = ∑_{i=1}^{m} f_{i}(x, t)g_{i,j}(t)

とおくと，0 でない h_{j}(x, t) の個数は m̄ で, しかも h_{j}(x, t) は t = 0 で極を持たず，h_{1}(x, 0), …, h_{m}(x, 0) の一次独立な個数は m̄ とできる（cf. [OSe, Proposition 2.21], [O1, Lemma 6.3]）．

paracmpl([f_{1}(x, t), …, f_{m}(x, t)],t) は，この [[h_{1}(x, t), …, h_{m}(x, t)],(g_{i,j}(t))] を返す． confexp() は，複数パラメータの場合の具体例の計算とみなせる．

• l はベクトルでもよいが，リストで返される．

• [h_{1}(x, t), …, h_{m}(x, t)] は, t の有理式を成分とする可逆行列 A = (a_{i,j}(t))\begin{matrix}1≤i≤m \\ 1≤j≤m \end{matrix} で， A と A^{−1} の

各成分が t = 0 に極を持たないものによる変換を除いて一意となる．

• 返される G = (g_{i,j}(t))\begin{matrix}1≤i≤m \\ 1≤j≤m \end{matrix} は上三角行列となる．

• low=1 を指定すると, x の次数が小さい項に注目する．

• lim=1 を指定すると [h_{1}(x, 0), …, h_{m}(x, 0)] を返す．

• f_{i}(x, t) は有理式でなく，有理式を成分とするリストやベクトルでもよい．

• para=[v_{1}, …, v_{k}] を指定すると，数係数でなくて不定元 v_{1}, …, v_{k} 係数の有理関数体係数の有理式とみなす．

• m̄ = m のとき， f_{i}(x, t) が有理式でなくて exp((1 + t)x) のような式の場合は，適当な次数まで Taylor 展開した式で f_{i}(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] は以下を示している．

(\frac{1}{x − 1}, \frac{1}{(t + 1)x^{2} + (−t − 2)x + 1}) = (\frac{1}{x − 1}, \frac{1}{(t + 1)x − 1}) (\begin{matrix}1 & \frac{1}{t} \\ 0 & \frac{−t − 1}{t} \end{matrix})

= (\frac{1}{x − 1}, \frac{1}{(x − 1)^{2}} ) if t = 0,

(\frac{1}{1 − x}, \frac{x}{(t + 1)x^{2} + (−t − 2)x + 1}) = (\frac{1}{x − 1}, \frac{1}{(t + 1)x − 1}) (\begin{matrix}−1 & \frac{1}{t} \\ 0 & −\frac{1}{t} \end{matrix})

= (\frac{1}{1 − x}, \frac{x}{(1 − x)^{2}} ) if t = 0,

((\begin{matrix}1 \\ t \\ t \end{matrix}) , (\begin{matrix}0 \\ t + 1 \\ t + 2 \end{matrix})) = ((\frac{1}{t} ; 1 ; 1) , (\begin{matrix}t + 1 \\ 0 \\ t \end{matrix})) (\begin{matrix}t & t + 1 \\ 0 & −\frac{1}{t} \end{matrix})

= ((\begin{matrix}1 \\ 0 \\ 0 \end{matrix}) , (\begin{matrix}0 \\ 1 \\ 2 \end{matrix})) if t = 0.

ここで以下に注意

(\frac{1}{1 − x}, \frac{x}{(1 − x)^{2}} ) = (\frac{1}{x − 1}, \frac{1}{(x − 1)^{2}} ) (\begin{matrix}−1 & 1 \\ 0 & 1 \end{matrix}) .

微分方程式

((t + 1)x^{2} − (t + 2)x + 1)\frac{d^{2}u}{dx^{2}} + 2(2(t + 1)x − t − 2)\frac{du}{dx} + 2(t + 1)u = 0

の解空間は t ≠ 0 のとき \{\frac{C_{1}}{x−1} + \frac{C_{2}}{(t+1)x−1} | C_{1}, C_{2} ∈ ℂ\} である．このことから t = 0 のときの解空間は \{\frac{C_{1}}{x−1} + \frac{C_{2}}{(x−1)^{2}} | C_{1}, C_{2} ∈ ℂ\} となることが分かる．より一般に，任意の t で解空間は \{\frac{C_{1}}{x−1} + \frac{C_{2}x}{(t+1)^{2}x^{2}−(t+2)x+1} | C_{1}, C_{2} ∈ ℂ\} で与えられる．

x = 0 の近くで考えるときは， low=1 を指定する方が便利なことが多い．

3.2.6 Matrices

300. 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 ]
[ 3 4 ]
[7] A;
[ 0 2 ]
[ 3 4 ]
301. 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 ]
302. 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()
303. m2lv(m)

:: 行列 m の行ベクトルを並べてリストにする（cf. 302, 305）

304. m2ll(m)

:: 行列 m を行ベクトルをリストにかえたものを成分とするリストにする（cf. 305）

305. 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 ]
[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 ]
306. s2m(s)

:: 文字列での有理数成分の行列表現や，列のリストから行列を作る．必要最低サイズの行列になる

• 整数や有理数成分の行列を，行の区切りをコンマで示した文字列で指定する．成分が一桁の整数の

ときに便利（以下の [0], [1], [4], [5] を参照）． – 同じ数が例えば 3 回続くときは， ^3 をつけて表してもよい．

– a,b, … は 10, 11, … を表す．

– 10 以上の数は (10) のように括弧で囲んで表してもよい．たとえば， 2/b は\frac{2}{11}．

– 分数は / を使って表す．

– たとえば 12(-2)/3^2 は， 1, 2, −\frac{2}{3}, −\frac{2}{3} と 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 ]
[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 ]
307. 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 ]
308. mperm(m,[σ_{0},σ_{1} . . .],[τ_{0},τ_{1}, . . .]|mult=1)
mperm(m,[[σ_{0},σ_{1}]],[[τ_{0},τ_{1}]]|mult=1), mperm(m,[σ,[m_{1}]],[τ,[m_{2}]]|mult=1)

:: 行列 m から小行列 (m_{σ_{i}τ_{j}}) を作る，または置換行列（または互換）で変換する

M = (m_{ij})\begin{matrix}0≤i<m \\ 0≤j<n \end{matrix} は (m_{σ_{i}τ_{j}}) に変わる．

• 元の行列は破壊されず，新たな行列が返される．

• 第 2 引数が [[σ_{0},σ_{1}]] となっていると， σ_{0} 行目と σ_{1} 行目の入れ替えを意味する．

• 第 3 引数が 1 のときは，第 3 引数が第 2 引数に等しいことを意味する．

• 第 2 引数，または第 3 引数が 0 のときは，それらが恒等変換であることを意味する．

• [σ,[k]] は [σ, σ + 1, …, σ + k − 1] と解釈される．

• m はベクトルまたはリストでもよい．このとき第 3 引数は無視される．

• たとえば， σ ≤ i < σ + k, σ ≤ j < σ + k を満たす m の成分 m_{i,j} からなる k 次の正方行列 (m_{i,j})\begin{matrix}σ≤i<σ+k \\ σ≤j<σ+k \end{matrix} は mperm(m,[σ,[k]],1) によって， 1, 3, 5 行目のみを抜き出して得られる行列

   は 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 ]
309. 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]]
310. madjust(m,w|null=n)

:: 行列 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 ? ? ? ? ? ]
311. 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, m^{2}, m^{4} = (m^{2})^{2}, … と計算して積を求めている (n を 2 進法で表した 1 の部分に対応する積)．負の時は m^{−1} に対して同様な計算．

312. 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 にする．

• 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} となる縦ベクトルを列の最後に付加して列サイズを一つ増やした行列 m′ に対して， mtoupper(m′, 1) を行う．

– A が変数 zz を含まない size S × S′ の行列ならば， B = mtoupper(A, −1) とおくと，変換後

     の行列は mperm(B,1,[0,[S′]]) となり， mycoef(B[I-1][S′],J-1,zz) が左からかける変

換行列の (I, J) 成分となる．

• step=1 を指定したときは，途中の行変形過程を表示する．

• dviout=1 は step=1 を指定したときのみ有効で，途中の行変形過程を dviout で表示する．

– このとき cr= のオプションで改行の L^{A}TEX コードを指定可能（デフォルトは

     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 = (m_{j,ℓ}) は k − 1 列目まで基本変形が終了した行列で，それの j_{0} − 1 行目までの基本変形が完了しているとする．このとき k − 1 列までの成分は j_{0} 行目以降は 0 となっていて， j_{0} − 1 行目までの行の 0 でない先頭成分は 1 で，それは k − 1 列目以下で，その列の他の成分は 0 になっている．また k 列目には j_{0} 行目またはそれ以降に初めて 0 でない成分 m_{j,k} があるとする．以下のように j_{0} 行目またはそれ以降の 0 でない t 行目の成分 m_{t,k} を調べて基準の j_{1} 行目を決め，（必要なら）行交換してそれを j_{0} 行目に移動する．得られた行列 M = (m_{j,ℓ}) において m_{j_{0},k} で j_{0} 行目を割り， j_{0} 行目のスカラー倍を他の行に加えて少なくとも k 列目までの基本変形を終了させる．

（b）j 行目またはそれ以降の成分 m_{t,k} で 1 となるものがあればその最初の t を j_{1} 行目とおく．（c）そうでなくて j 行目またはそれ以降の成分 m_{t,k} で −1 となるものがあればその最初を j_{1} 行目とおく．（d）そうでなくて j 行目またはそれ以降の成分 m_{t,k} が正整数で，その行を m_{t,k} で割ったものが整数行ベク

トルになるものがあればその最初の行を j_{1} 行目とする．（e）そうでなくて j 行目またはそれ以降の成分 m_{t,k} が負整数で，その行を m_{t,k} で割ったものが整数行ベク

トルになるものがあればその最初の行を j_{1} 行目とする．（f）そうでなくて j 行目またはそれ以降の成分 m_{t,k} が 0 でなくて，その行を m_{t,k} で割ったものが整数行ベ

クトルになるものがあればその最初の行を j_{1} 行目とする．（g）そうでなければ， t 行目の成分 m_{t,k} が整数で， k 行目以降の t 行目と異なる j 行目に t 行目の整数倍を

足して (j, k) 成分を 0 に出来るか調べ，可能ならそれを行う．（h）そうでなければ， t 行目の成分 m_{t,k} が整数で， j 行目以降のある行を t 行目に足すか引くかして (t, k) 成

分を 1 に出来るか調べ，可能ならそれを行って j_{1} = t とする．ただし， j 行目と t 行目に変数を含まないものを優先する．

（i）そうでなければ， t 行目の成分 m_{t,k} が整数で， j 行目以降のある行目に j 行目以降のある行の整数倍を足すか引くかして (t, k) 成分を 1 に出来るか調べ，可能ならそれを行ってその行を j_{1} = t とする．ただし， j 行目と t 行目に変数を含まないものを優先する．

（j）そうでなければ， t 行目の成分 m_{t,k} が整数で， j 行目以降のある行に j 行目以降のある行を足すか引くかして (t, k) 成分を −1 に出来るか調べ，可能ならそれを行って j_{1} = t とする．ただし， j 行目と t 行目に変数を含まないものを優先する．

（k）そうでなければ， t 行目に j 行目以降のある行の整数倍を足すか引くかして (t, k) 成分を −1 に出来るか

調べ，可能ならそれを行って j_{1} = t とする．ただし， j 行目と t 行目に変数を含まないものを優先する．（l）そうでなければ最初に現れた整数成分 m_{t,k} の行を，整数の行がなければパラメータを含まない数 m_{t,k}

の最初の行を j_{1} 行とする．（m）opt>4 のとき， k 列目の有理式 m_{t,k} の分子がある一つパラメータの多項式となっているとき，行変形に

よって k 列目の成分の分子の多項式の最低次数を下げることができればそれを行うことを続ける．（n）opt>4 のとき， k 列目の成分で分子が数となる m_{t,k} があれば，その最初の行 t によって j_{1} = t とする．（o）opt>4 のとき，有理式 m_{t,k} で分子の最大公約元の多項式の根が有理数で与えられるときは，その項が 0

となる場合をまず扱って行変形の最終形まで求める．そのあと j_{1} = t とする．（p）opt>4 のとき， m_{t,k} が 0 になるための条件が，ある変数がその変数を含まない変数の多項式や分母が 0

でない有理式（ただし opt=5 のときは有理数）で与えられるものがあるかどうか調べ，そのような t が存在すれば 0 になる場合を最終形まで求め，次に 0 にならない場合を調べるため j_{1} = t とする．

（q）以上に該当しなければ，成分 m_{t,k} の型が最小となるものが最初に現れる行 t に対して j_{1} = 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) ]
[ 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 ]
[ 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)$

(\begin{matrix}2 & 1 & 3 & 1 & 0 \\ 1 & 2 & 3 & 0 & 1 \end{matrix})

⟶^{line1 ↔ line2} (\begin{matrix}1 & 2 & 3 & 0 & 1 \\ 2 & 1 & 3 & 1 & 0 \end{matrix})

line2 −= line1×(2) ⟶ (\begin{matrix}1 & 2 & 3 & 0 & 1 \\ 0 & −3 & −3 & 1 & −2 \end{matrix})

⟶^{line2 ×= (\frac{−1}{3})} (\begin{matrix}1 & 2 & 3 & 0 & 1 \\ 0 & 1 & 1 & \frac{−1}{3} & \frac{2}{3} \end{matrix})

line1 −= line2×(2) ⟶ (\begin{matrix}1 & 0 & 1 & \frac{2}{3} & \frac{−1}{3} \\ 0 & 1 & 1 & \frac{−1}{3} & \frac{2}{3} \end{matrix})

[15] os_md.mtoupper(os_md.s2m("32,53"),-2|opt=3,step=1,dviout=1)$

(\begin{matrix}3 & 2 & 1 & 0 \\ 5 & 3 & 0 & 1 \end{matrix})

⟶^{line1 ×= (\frac{1}{3})} (\begin{matrix}1 & \frac{2}{3} & \frac{1}{3} & 0 \\ 5 & 3 & 0 & 1 \end{matrix})

line2 −= line1×(5) ⟶ (\begin{matrix}1 & \frac{2}{3} & \frac{1}{3} & 0 \\ 0 & \frac{−1}{3} & \frac{−5}{3} & 1 \end{matrix})

⟶^{line2 ×= (−3)} (\begin{matrix}1 & \frac{2}{3} & \frac{1}{3} & 0 \\ 0 & 1 & 5 & −3 \end{matrix})

line1 −= line2×(\frac{2}{3}) ⟶ (\begin{matrix}1 & 0 & −3 & 2 \\ 0 & 1 & 5 & −3 \end{matrix})

[16] os_md.mtoupper(os_md.s2m("32,53"),-2|opt=4,step=1,dviout=1)$

(\begin{matrix}3 & 2 & 1 & 0 \\ 5 & 3 & 0 & 1 \end{matrix})

line2 −= line1×(2) ⟶ (\begin{matrix}3 & 2 & 1 & 0 \\ −1 & −1 & −2 & 1 \end{matrix})

⟶^{line1 ↔ line2} (\begin{matrix}−1 & −1 & −2 & 1 \\ 3 & 2 & 1 & 0 \end{matrix})

⟶^{line1 ×= (−1)} (\begin{matrix}1 & 1 & 2 & −1 \\ 3 & 2 & 1 & 0 \end{matrix})

line2 −= line1×(3) ⟶ (\begin{matrix}1 & 1 & 2 & −1 \\ 0 & −1 & −5 & 3 \end{matrix})

⟶^{line2 ×= (−1)} (\begin{matrix}1 & 1 & 2 & −1 \\ 0 & 1 & 5 & −3 \end{matrix})

line1 −= line2 ⟶ (\begin{matrix}1 & 0 & −3 & 2 \\ 0 & 1 & 5 & −3 \end{matrix})

[16] os_md.mtoupper(mat([a,2],[a+2,4*a+2]),0|step=1,opt=5,dviout=1)$

(\begin{matrix}a & 2 \\ a + 2 & 4a + 2 \end{matrix})

line2 += line1×(−1)

⟶

(\begin{matrix}a & 2 \\ 2 & 4a \end{matrix})
⟶^{line1 ↔ line2} (\begin{matrix}2 & 4a \\ a & 2 \end{matrix})
⟶^{line1 ×= (\frac{1}{2})} (\begin{matrix}1 & 2a \\ a & 2 \end{matrix})

line2 += line1×(−a) ⟶ (\begin{matrix}1 & 2a \\ 0 & −2a^{2} + 2 \end{matrix})

If a = 1,

(\begin{matrix}1 & 2 \\ 0 & 0 \end{matrix})

If a = −1,

(\begin{matrix}1 & −2 \\ 0 & 0 \end{matrix})

If a^{2} − 1 ≠ 0,

⟶^{line2 ×= ( \frac{\frac{−1}{2}}{a^{2}−1} )} (\begin{matrix}1 & 2a \\ 0 & 1 \end{matrix})

line1 += line2×(−2a)

⟶

(\begin{matrix}1 & 0 \\ 0 & 1 \end{matrix})

[17] os_md.mtoupper(mat([a,b],[c,d]),-2|step=1,opt=6,dviout=1)$

(\begin{matrix}a & b & 1 & 0 \\ c & d & 0 & 1 \end{matrix})

If a = 0,

(\begin{matrix}0 & b & 1 & 0 \\ c & d & 0 & 1 \end{matrix})

If c = 0,

(\begin{matrix}0 & b & 1 & 0 \\ 0 & d & 0 & 1 \end{matrix})

If b = 0,

(\begin{matrix}0 & 0 & 1 & 0 \\ 0 & d & 0 & 1 \end{matrix})

If d = 0,

(\begin{matrix}0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{matrix})

If d ≠ 0,

⟶^{line1 ↔ line2} (\begin{matrix}0 & d & 0 & 1 \\ 0 & 0 & 1 & 0 \end{matrix})
⟶^{line1 ×= (\frac{1}{d})} (\begin{matrix}0 & 1 & 0 & \frac{1}{d} \\ 0 & 0 & 1 & 0 \end{matrix})

If b ≠ 0,

⟶^{line1 ×= (\frac{1}{b})} (\begin{matrix}0 & 1 & \frac{1}{b} & 0 \\ 0 & d & 0 & 1 \end{matrix})

line2 += line1×(−d) ⟶ (\begin{matrix}0 & 1 & \frac{1}{b} & 0 \\ 0 & 0 & \frac{−d}{b} & 1 \end{matrix})

If c ≠ 0,

⟶^{line1 ↔ line2} (\begin{matrix}c & d & 0 & 1 \\ 0 & b & 1 & 0 \end{matrix})

⟶^{line1 ×= (\frac{1}{c})} (\begin{matrix}1 & \frac{d}{c} & 0 & \frac{1}{c} \\ 0 & b & 1 & 0 \end{matrix})

If b = 0,

(\begin{matrix}1 & \frac{d}{c} & 0 & \frac{1}{c} \\ 0 & 0 & 1 & 0 \end{matrix})

If b ≠ 0,

⟶^{line2 ×= (\frac{1}{b})} (\begin{matrix}1 & \frac{d}{c} & 0 & \frac{1}{c} \\ 0 & 1 & \frac{1}{b} & 0 \end{matrix})

line1 += line2×(\frac{−d}{c}) ⟶ (\begin{matrix}1 & 0 & \frac{−d}{cb} & \frac{1}{c} \\ 0 & 1 & \frac{1}{b} & 0 \end{matrix})

If a ≠ 0,

⟶^{line1 ×= (\frac{1}{a})} (\begin{matrix}1 & \frac{b}{a} & \frac{1}{a} & 0 \\ c & d & 0 & 1 \end{matrix})

line2 += line1×(−c) ⟶ (\begin{matrix}1 & \frac{b}{a} & \frac{1}{a} & 0 \\ 0 & \frac{da−cb}{a} & \frac{−c}{a} & 1 \end{matrix})

If d = \frac{cb}{a},

(\begin{matrix}1 & \frac{b}{a} & \frac{1}{a} & 0 \\ 0 & 0 & \frac{−c}{a} & 1 \end{matrix})

If da − cb ≠ 0,

⟶^{line2 ×= (\frac{a}{da−cb})} (\begin{matrix}1 & \frac{b}{a} & \frac{1}{a} & 0 \\ 0 & 1 & \frac{−c}{da−cb} & \frac{a}{da−cb} \end{matrix})

line1 += line2×(\frac{−b}{a}) ⟶ (\begin{matrix}1 & 0 & \frac{d}{da−cb} & \frac{−b}{da−cb} \\ 0 & 1 & \frac{−c}{da−cb} & \frac{a}{da−cb} \end{matrix})

[18] os_md.mtoupper(mat([a^4-b^2,b]),0|step=1,opt=6,dviout=1)$

(a^{4} − b^{2} b)

If b = a^{2},

(0 a^{2})

If a = 0,

(0 0)

If a ≠ 0,

⟶^{line1 ×= (\frac{1}{a^{2}} )} (0 1)

If b = −a^{2},
(0 −a^{2})
If a = 0,
(0 0)
If a ≠ 0,
⟶^{line1 ×= (\frac{−1}{a^{2}})} (0 1)
If a^{4} − b^{2} ≠ 0,
⟶^{line1 ×= ( \frac{1}{a^{4}−b^{2}} )} (1 \frac{b}{a^{4}−b^{2}} )

[19] os_md.mtoupper(mat([a*(a+b),1/(a+b)]),0|opt=6,step=1,dviout=1);

(a(a + b) \frac{1}{a+b})
If a = 0,
(0 \frac{1}{b})
⟶^{line1 ×= (b)} (0 1)
If a ≠ 0,
⟶^{line1 ×= (\frac{1}{a(a+b)})} (1 \frac{1}{a(a+b)^{2}} )

上では， (1, 2) 成分を見て， a + b ≠ 0 と判断している．

[20] os_md.mtoupper(mat([a^4+b^2,b]),0|step=1,opt=6,dviout=1)$

(a^{4} + b^{2} b)
Assume a^{4} + b^{2} ≠ 0,
⟶^{line1 ×= ( \frac{1}{a^{4}+b^{2}} )} (1 \frac{b}{a^{4}+b^{2}} )

313. mytrace(m)

:: 行列の trace を返す．

314. mydet(m)

:: det(m) と同じ．ただし成分は有理式でもよい．

315. 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
316. 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
317. myrank(m)

:: 行列 m の rank を求める（例は mtoupper() の項）

318. 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 ]]
319. 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) ]

320. mymod(v,[v_{1}, . . . , v_{k}]|opt=ℓ)

:: ベクトル v_{1}, …, v_{k} で張られる空間の商空間への v の射影を求める（例は myimage() の項） • v_{1}, …, v_{k} の 0 でない要素の位置は，順に真に増加している必要がある．

• オプション opt=1 を指定した場合，射影が 0 のとき 0 を，それ以外では 1 を返す．

• opt=2 を指定したときは，商空間の標準基底を取った射影を表す．

321. mmod(m,[v_{1}, . . . , v_{k}]|opt=1)

:: ベクトル v_{1}, …, v_{k} で張られる空間の商空間への線形写像 m の射影

• v_{1}, …, v_{k} の 0 でない要素の位置は，順に真に増加している必要がある．また， opt=1 を指定しないときは，これらで張られる空間は m で不変でなければならない．

• opt=1 のときは，商空間上の線形変換でなくて，商空間への線形写像とみなす（このときは m は

正方行列でなくてよい）．

322. myinv(m)

:: 正方行列 m の逆行列を求める成分は有理式でもよい． m が可逆でないとき， 0 を返す．

[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) ]
323. madj(g,m)

:: 行列 gmg^{−1} を計算する． m は行列のリストか行列のベクトルでもよい．

324. diagm(m,a)

:: 対角行列を作成する

mgen(m,0,a,1) と同じ
325. mgen(m,n,a,s|sep=1)

:: size m × n の一般行列を作成する • (i, j)-成分は a が変数の時 ai′j′ で，リストの時 a[i]j′ で与えられる（i′ = i + s, j′ = 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 番目に a_{i} 番目の成分が入る．

• 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);
[ 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 ]
326. 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,k_{1},k_{2},…] というリストの時は，ある行の k_{ν} 列目が先頭の 1 となる簡約行列に行基本変形で変換される p × q 行列をランダムに生成する．

• 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 ]
[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] は，以下のようになる．

(\begin{matrix}−1 & 1 & 0 & 0 \\ 0 & −1 & 0 & 0 \\ 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 3 \end{matrix}) = (\begin{matrix}0 & −1 & 1 & 0 \\ −1 & 5 & −3 & −1 \\ 1 & −2 & 1 & 1 \\ 0 & 1 & −1 & −1 \end{matrix}) (\begin{matrix}5 & 0 & −4 & 0 \\ 2 & 2 & −3 & 1 \\ 1 & 8 & −7 & 0 \\ 1 & −9 & 7 & 4 \end{matrix}) (\begin{matrix}2 & 1 & 2 & 1 \\ 2 & 1 & 1 & 0 \\ 3 & 1 & 1 & 0 \\ −1 & 0 & 0 & −1 \end{matrix})

(\begin{matrix}−2 & 0 & 0 & 0 \\ 0 & −1 & 0 & 0 \\ 0 & 0 & 3 & 0 \\ 0 & 0 & 0 & 3 \end{matrix}) = (\begin{matrix}0 & −2 & −1 & 1 \\ 1 & 1 & 0 & −1 \\ 0 & 1 & 1 & 0 \\ −1 & 0 & 0 & 1 \end{matrix}) (\begin{matrix}−1 & 6 & 5 & −1 \\ −4 & −1 & 0 & 4 \\ 4 & 4 & 3 & −4 \\ −4 & 6 & 5 & 2 \end{matrix}) (\begin{matrix}1 & 1 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 0 & −1 & 1 & −1 \\ 1 & 1 & 1 & 1 \end{matrix})

[18] os_md.unim(4|int=2,conj=1,res=1,dviout=1);

(\begin{matrix}−1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 3 \end{matrix}) = (\begin{matrix}\frac{5}{2} & −\frac{5}{4} & \frac{1}{4} & −\frac{3}{4} \\ −5 & 2 & −1 & 2 \\ 2 & 1 & 1 & −\frac{3}{2} \\ \frac{1}{2} & −\frac{1}{4} & \frac{1}{4} & −\frac{1}{4} \end{matrix} ) (\begin{matrix}−6 & 5 & 2 & 0 \\ −4 & 4 & 1 & 0 \\ 6 & −1 & 8 & −6 \\ −8 & 8 & 8 & −3 \end{matrix}) (\begin{matrix}5 & 3 & 1 & 3 \\ 3 & 2 & 1 & 1 \\ 5 & 4 & 1 & 11 \\ 12 & 8 & 2 & 12 \end{matrix})

327. newbmat(m,n,[[r_{00}, r_{01}, …],[r_{10}, …], …]|null=t)

:: ブロック行列を作成する • r_{ij} の行または列のサイズが 1 のときは，ベクトルまたはリストで表してもよい．

• r_{ij} がサイズ 1 の正方行列のときは，スカラーで表してもよい．

• r_{ij} が 0 行列の時は 0 で表してもよい．このとき null=t が指定してあれば， 0 行列でなく，各成分が t の行列と解釈される．

• ブロック対角行列の時は， newbmat(m,m,[r_{00},r_{11}, …) と省略してもよい．

• ブロックに分けた各行や各列には少なくとも 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 ]
328. 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 =[s_{1},s_{2}] のときは，デフォルトの ”&:”, ”\\\n”を s_{1},

   s_{2} に置き換える．たとえば 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-b
\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 : (\begin{matrix}1 & 0 \\ 0 & 0 \\ 0 & 1 \end{matrix}) β − γ : (\begin{matrix}−α \\ −(β − γ) \\ β \end{matrix})

[15] os_md.dviout(os_md.meigen([A1,A2]|vec=1,TeX=1,sep=[":","\\quad\n"])|eq=7)$

[0, 0] : (\begin{matrix}−(α + β − γ) \\ 0 \\ β \end{matrix}) [0, −α − β + γ] : (\begin{matrix}0 \\ 0 \\ 1 \end{matrix}) [β − γ, 0] : (\begin{matrix}−α \\ −(β − γ) \\ β \end{matrix})

329. 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 ]]
330. mext2(m)

:: 線型変換の外積を与える正方行列 m = (a_{ij}) が u_{i} ↦ ∑_{0≤ν<n} a_{iν}u_{ν} (0 ≤ ν < n) という線型変換に対し u_{i} ∧ u_{j} ↦ ∑_{0≤ν<n} a_{iν}u_{ν}∧u_{j}+∑_{0≤ν<n} a_{jν}u_{i}∧u_{ν} という線型変換の行列を与える．成分は (i, j) (0 ≤ i < j < n) の辞書式順序で並べる．

[0] M=os_md.mext2(os_md.mgen(4,4,a,1))$
[1] dviout(M);

(\begin{matrix}u_{1} ∧ u_{2} \\ u_{1} ∧ u_{3} \\ u_{1} ∧ u_{4} \\ u_{2} ∧ u_{3} \\ u_{2} ∧ u_{4} \\ u_{3} ∧ u_{4} \end{matrix}) ↦ (\begin{matrix}a_{11} + a_{22} & a_{23} & a_{24} & −a_{13} & −a_{14} & 0 \\ a_{32} & a_{11} + a_{33} & a_{34} & a_{12} & 0 & −a_{14} \\ a_{42} & a_{43} & a_{11} + a_{44} & 0 & a_{12} & a_{13} \\ −a_{31} & a_{21} & 0 & a_{22} + a_{33} & a_{34} & −a_{24} \\ −a_{41} & 0 & a_{21} & a_{43} & a_{22} + a_{44} & a_{23} \\ 0 & −a_{41} & a_{31} & −a_{42} & a_{32} & a_{33} + a_{44} \end{matrix}) (\begin{matrix}u_{1} ∧ u_{2} \\ u_{1} ∧ u_{3} \\ u_{1} ∧ u_{4} \\ u_{2} ∧ u_{3} \\ u_{2} ∧ u_{4} \\ u_{3} ∧ u_{4} \end{matrix})

331. 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 ]
? 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

332. str char(s,n,t)

:: 文字列 s の n 文字以降に文字列 t の先頭文字が最初に現れる場所を返す（str chr() の拡張） • 見つからないときは −1 を返す．

• s は，（たとえば strtoascii() で得られる整数の）リストやベクトルなどでもよい．

• s がリストやベクトルの時は， t は文字列以外（たとえば文字コード）でもよい．

• s がリストまたはベクトルの場合，型返還せずにそのまま扱うのでメモリー効率がよい．

• str str() の方が高機能．
333. str pair(s,n,t_{1},t_{2}|inv=1)

:: 文字列 s の n 文字以降で，文字（列） t_{2} の出現回数が t_{1} の出現回数を超える最初の位置を返す • 見つからないときは −1 を返す．

• s は，（たとえば strtoascii() で得られる整数の）リストやベクトルなどでもよい．

• t_{1}, t_{2} は文字コードでもよい．あるいは文字列でもよい．

• sjis=1 が指定されると，シフト JIS の文字列とみなして処理する．

• inv=1 が指定されると，文字列 s の n 文字以前で，文字（列） t_{1} の出現回数が t_{2} の出現回数を超

える最後の位置を返す．ただし， 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);
3
334. str str(s,t|top=n,end=m,sjis=1)

:: 文字列 s に部分文字列 t が最初に現れる場所を返す • 部分文字列 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]
335. str cut(s,m,n)

:: 文字列 s の先頭から m 文字をスキップして，それ以降 n − m + 1 文字を返す • s が文字列のときは sub str(s,m,n) と同じ（例は str pair() を参照）．

• s は文字コードのリストやベクトルでもよい（こちらの方がオーバーヘッドが少ない）．ただし，戻り値は文字列．

• n が十分大きいときは， s の m + 1 文字目以降を返す．

336. str subst(s,s_{0},s_{1}|sjis=1,raw=1) または
str_subst(s,[s_{00}, s_{01}, . . .],[s_{10}, s_{11}, . . .]|inv=1,sjis=1,raw=1)
str_subst(s,[[s_{00}, s_{10}],[s_{01}, s_{11}], . . .],0|sjis=1)

:: 文字列 s に含まれる部分文字列 s_{0} を s_{1} で全て先頭から順に置き換える • 複数種の置き換え，すなわち部分文字列 s_{0j} を s_{1j} へ j = 0, 1, … の順に s の置き換えができる． • 複数種置き換えで，置き換えられた部分文字列の再置き換えは行わない．

• s は strtoascii() によって置き換えられた整数のリストやベクトルでもよい（こちらの方がオーバーヘッドが少ない．ただし， raw=1 を設定しないと，戻り値は文字列．

• inv=1 によって，逆に s_{1j} を s_{0j} へ j = 0, 1, … の順の置き換えが行われる．

• sjis=1 が指定されると，シフト JIS の文字列とみなして処理する．

• raw=1 が指定されていると， strtoascii() で置き換えられた整数のリストを返す（こちらの方がオーバーヘッドが少ない）．

[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
337. str times(s,n)

:: 文字列 s （またはリスト）を n 回繰り返した文字列（またはリスト）を返す

• リストのときは， s = [[s_{1}, s_{2}, …, s_{k}]] とすると， [s_{1}, s_{2}, …, s_{k}, s_{1}, s_{2}, …, s_{k}, s_{1}, s_{2}, …] という長さ n のリストを返す．

• s = [t_{1}, …, t_{k}, [s_{1}, s_{2}, …, s_{k}]] のときは， [t_{1}, …, t_{k}, s_{1}, s_{2}, …, s_{k}, s_{1}, s_{2}, …, s_{k}, s_{1}, s_{2}, …] という長さ 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]
338. 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
339. str insert(s,u,[t,e]|transpose=1)

:: 文字列 s のリストの間に u の成分のリストを順に入れた差し込み文にする s = [s_{1}, …, s_{n}], u = [u_{1}, …, u_{m}], u_{j} = [u_{j,1}, …, u_{j,m}] のとき

ts_{1}u_{1,1}s_{2}u_{1,2} ⋯ u_{1,n−1}s_{n}s_{1}u_{2,1}s_{2}u_{2,2} ⋯ s_{n}s_{1} ⋯ u_{m,n−1}u_{n}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
340. strip(s,t_{1},t_{2})

:: 文字列の外側の括弧を外す • s が t_{1} と t_{2} のペアの括弧で全体が囲まれているとき，その括弧を外した文字列を返す．

[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)
341. 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);
A
[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]
342. s2os(s)

:: 文字列を入力可能な文字列に変換

[0] S="\"表\計算\"";

"表計算"

[1] os_md.s2os(S);
\"表\計算\"
343. 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]
344. sjis2jis(l)

:: 文字コードの整数のリストの先頭 2 つを ShiftJIS から JIS に変換変換後の長さ 2 の整数のリストを返す

345. jis2sjis(l)

:: 文字コードの数字のリストの先頭 2 つを JIS から ShiftJIS に変換変換後の長さ 2 の整数のリストを返す

[0] P="整数"$
[1] L=strtoascii(P);
[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]
346. s2euc(s)

:: ShiftJIS または JIS 文字列を EUC 文字列に変換 0x0d のコードは削除して 0x0a のコードに変換する．

347. s2sjis(s)

:: EUC または JIS 文字列を ShiftJIS 文字列に変換 0x0a のコードは 0x0d 0x0a のコードに変換する．

348. str tb([s_{0}, s_{1}, . . .],tb) または str_tb(0,tb)

:: テキスト用バッファを作成（tb = 0）し，そこ（戻り値 tb）に文字列 s_{0}, … を順に追加する．最初の引数を 0 として文字列を取り出す．

• tb = 0 のときは， tb は空文字列と解釈される．

• tb が文字列ならばそれで初期化されたテキスト用バッファを作成し，さらに第 1 引数で指定された文字列を順に追加したテキスト用バッファを返す．ただしここで第 1 引数が 0 のときは, それは空文字列と解釈される．

• tb がテキスト用バッファの場合は，第 1 引数が文字列またはそのリストのとき，それが順にバッファに追加される．ただし第 1 引数が 0 のときはテキスト用バッファの文字列を取り出して返す．

• 文字列が一つなら， [s_{0}] は単に s_{0} でよい．

• この函数は，細かく文字列を追加していった場合のメモリー消費の非効率性を避けるために用いられる. また， 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=9
349. l2os(l)

:: リストを入力可能な文字列に変換 • 行列やベクトルはリストに直す．これらはネスティング可能．

• 成分の文字列は " で囲って表示する．

[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"]]
350. 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" ]
351. 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]]
352. 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}
353. r2ma(s)
:: Mathematica の形式の数式に変換
evalma(s|inv=1) と同じ
354. 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}
355. readcsv(s|eval=[n_{1}, n_{2}, . . .],eval=n,sp=1,col=c,null=t,eq=1)

:: CSV 形式のデータをリスト形式で読み込む

• CSV 形式とは，複数のデータをコンマと改行で区切ったデータ形式であるが，それを 1 行のデータをリストにし，さらにそのリストを行順に並べたリストとして読み込む．

• 通常は文字列として読み込むが，各行で n_{1}, n_{2}, … で指定した項目は式として読み込む（n_{1} は n_{1} 番目の項目 – 最初は 1 番目 – を表す）． n 項目のみの指定のときは， eval=n としてもよい．

• eval="all"というオプションでは，可能な項目は全て（小）数として読み込む．

• sp=1 というオプションでは，空白やタブやそれらが連続したものをデータの区切りとみなす． • col=c というオプションでは，各行の第 c 項目のみを読んだリストとする．

• null=t というオプションでは，データの無い項目を t とする（デフォルトは空文字列）．

• eq=1 というオプションは，数でなくて式として読み込み， t のデフォルトは 0.

• 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]
356. 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

357. 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]
[5] os_md.ldict(6,3);
too small size
0
[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]
358. 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);
3

359. nextsub([a_{0}, …, a_{m−1}],n) :: {0, …, n − 1} の m 個の部分集合を並べたとき， {a_{0}, …, a_{m−1}} の次の部分集合を返す．最後を与えた時は 0 を返す．

• 0 ≤ a_{0} < ⋯ < a_{m−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]
360. 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]
[1] os_md.nextpart(5|max=3);
[3,2]
361. transpart(ℓ)

:: 自然数の分割のリスト（Young 図式に対応） ℓ に対し，その双対を返す（例は nextpart() を参照） n 次の置換群の元を {0, 1, 2, …, n − 1} の並べ替えと考えて，ベクトル s = [s_{0} … s_{n−1}] で表す．互換（リ

ストまたはベクトル [a b] で表す），積，逆元など無限次置換群の中で考えているとしてよい．置換群の元を ( \begin{matrix}a_{0} & a_{1} & ··· & a_{n−1} \\ b_{1} & b_{2} & ··· & b_{n} \end{matrix} ) と表したときは，s =os md.sprod([b_{1}, b_{2}, …],os md.sinv([a_{0}, a_{1}, …]) となる．

以下， s, t はそのような置換群の元とする．

362. 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 ]
363. sprod(s,t)

:: 置換群の積を返す s = [s_{0} … s_{n−1}], t = [t_{0} … t_{n−1}] のときは積は [s_{t_{0}} … s_{t_{n−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]);
[ 1 3 0 4 2 ]

([3]) は， (1 5 3 4 2 ⋯)(2 4 3 1 ⋯) = (5 4 3 1 2 ⋯) を意味している．

364. sadj(s,t)

:: 置換群の共役変換を返す

sts^{−1} を返す．すなわち sprod(sprod(s,t),sinv(s))
365. sinv(s)

:: 置換 s の逆元を返す s が非負整数の時は， S_{∞} の s 番目の元と見なされ，積は非負整数で返される． 0, 1, 2 は [0,1,2,3, …], [1,0,2,3, …], [2,0,1,3, …] に対応する．

366. slen(s)

:: 置換 s の長さを返す

367. sexps(s)

:: 置換 s を隣接互換の積で表す

以下は， (1, 2, 0) = (\underline{0}, 1)(\underline{1}, 2) すなわち (\begin{matrix}0 & 1 & 2 \\ 1 & 2 & 0 \end{matrix}) = (\begin{matrix}0 & 1 & 2 \\ 1 & 0 & 2 \end{matrix}) (\begin{matrix}0 & 1 & 2 \\ 0 & 2 & 1 \end{matrix}) を示す．

[0] os_md.sexps([1,2,0]);
[0,1]
368. sord(s,t)

:: 置換を Bruhat order で比較する戻り値は 0: equal 1: s > t −1: s < t 2: no order

3.2.9 TEX 以下の函数の他にも， fctrtos(), getbygrs() などが L^{A}TEX の出力に対応している．

369. my tex form(p|subst=[t_{0}, t_{1}],frac=f,root=r,ket=k)

:: print tex form(p) の戻り値から文字列置換や不要部分削除を行い，読みやすいソースに変換 • 置き換えは str subst(s,t_{0},t_{1}) でなされる．

• frac=0 : 係数が分数のとき， 2/3 のように出力する

• frac=1 : 係数が分数のとき， \frac{2}{3} のように出力する．ただし， AMSTeX=0 のときは

   {2\over 3} のように出力．

• frac=2 : 係数が分数のとき， \tfrac{2}{3} のように出力する（デフォルト）．ただし， AMSTeX=0 のときは {2\over 3} のように出力．このとき 2^(1/2) は 2^{\frac{1}{2}} でなく，\sqrt{2} となるよう\sqrt\{2\}が出力される（デフォルトでは\sqrt{⋯} の ⋯ が 32 字以内の場合）．ただし， root=r の指定で r = 0 のときは (⋯)^{\frac{1}{2}} の形に， r = 2 のときは\sqrt{⋯} の形になるよう出力される．同様に， 2^(1/3) は 2^{\frac{1}{3}} でなく，\sqrt[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}
[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}^x
370. 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 の各要素がリストとし，各要素も文字列かあるいは，式（ここでは有理式，ベクトル，行列のいすれかとする）からなるリストとする．文字列も式も現れているとすると，

  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}
371. 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 にも対応可）．

• この函数によって L^{A}TEX のソースが DIROUT/out.tex に出力され，それが DIROUT/risaout.tex

から読み込まれる．

• p が文字列の場合，通常は L^{A}TEX のソースとみなして表示するが 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} で挟んで数式とみなして L^{A}TEX を使って表示する．

• s_{0}, s_{1} で部分文字列の（複数）置き換えをする（cf. str subst()）．

• p=" " （１文字の空白）は，再表示．

• clear=1 によって，追加でなくて新規の表示となる．

• keep=1 のときは， L^{A}TEX のソースのみの変更で，表示はしない（後から表示）．

• delete=t によって，最後の t 個の式番号の付いた式を削除する（0 ≤ t ≤ 10）．

• mult=1 のときは， p がリストなら，各項を別に表示する．

• fcrt=1 のときは， p が多項式または有理式なら因数分解して表示する．

• tilte=s で， s が文字列ならそれのあとに p が表示される． dviout で source specials が有効になっていれば， dviout の画面で表示された文字の部分のダブルクリックによりエディタが起動され， L^{A}TEX のソースの該当箇所が編集可能になる．この編集処理後の表示（たとえば dviout(" ")）でこの修正が有効になる．

• risatex.bat や risaout.tex が存在しない場合，それらが（ディレクトリが書き込み可能ならば）自動的に作成される．これらは必要に応じて書き換えてよい．

  risatex.bat を起動可能なように（デフォルトでは get_rootdir()/bin に置かれる）設定し，

また risaout.tex を DIROUT で指定されるディレクトリに入れておく必要がある（cf. DVIOUTA）．

372. 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 で逆の設定となる．

373. verb tex form(p)

:: p を L^{A}TEX で表現可能な文字列にする

verb_tex_form(p) は rtostr(p) と同等であるが， \begin{align}... \end{align} などの数式環

境中でも使用できる．

374. monotos(p)

:: 有理式を文字列に変換．単項式以外では ( と ) で囲む

375. monototex(p|minus=1)

:: 有理式を TEX の文字列に変換．単項式以外では ( と ) で囲む

• minus=1 を指定すると， − で始まる場合も ( と ) で囲む

376. rtotex(p)

:: 数式を TEX の文字列に変換． 1 文字を越えるときは { と } で囲む

[0] os_md.monotos(a2);
a2
[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}}

377. 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}y
378. texbegin(t,s|opt=u)

:: TEX の \begin{t}[u] s \end{t} というソースを出力する

379. 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 文字となる．

• k が 0 から 127 までの整数でない場合は， k がそのまま返される．

[0] os_md.texcr(31);
\allowdisplaybreaks\\\pause
&
[1] os_md.texcr(7);
\\
&
[2] os_md.texcr(15);
\allowdisplaybreaks\\
&
380. 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}
381. eqs2tex(p,[var,dic,pages,cont]|dviout=1)

:: 長い数式 p を TEX の複数行の display style に変換（複数の）数式を TEX の display style に変換.

• p が数式のリスト [p_{1},p_{2}, …] のときは，それらを 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 を用いて画面表示される．

382. 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\sqrt{−1} のとき， a + bi と表示する（デフォルト）．

– cpx=2 : 複素数 a + b\sqrt{−1} のとき， a + b\sqrt{−1} と表示する．

• s = ["Pfaff",u,x,x-y, . . .] の場合は行列のリストを

du = (A_{0} \frac{dx}{x} + A_{1} \frac{d(x − y)}{x − y} + ⋯) u

のような Pfaff 形式にする．

• s = ["Fuchs",u,x,x,x-y,x-1, . . .] の場合は行列のリストを

\frac{du}{dx} = (\frac{A_{0}}{x} + \frac{A_{1}}{x − y} + \frac{A_{2}}{x − 1} + ⋯) u

のような Fuchs 形式にする．

• s = "dform" のときは， dform() で扱ったような微分形式を表すリストとみなす．

  ℓ =[[(a*x-b*y)/(x),x,z],[(-a*x+b*y)/(y),y,z]] ならば

(\frac{ax − by}{x}) dx ∧ dz + (\frac{−ax + by}{y}) dy ∧ dz

となる．係数は，有理式や有理式の行列などでよい．

• 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 のオプションが有効． ℓ のリスト（改行文字列は s_{1}）の項目がリストの場合，そこでの改行文字列 s_{2} を指定するときは， cr=[s_{1},s_{2}] とする． s_{1}, s_{2} は数字での指定でもよい．

• s = "text" のときは， s = "spts" のときと同じだがテキストスタイルとする．このときも str=1 や cr= のオプションが可能．

• s = "tab" で ℓ がリストのリストのときは， \begin{tabular}...\end{tabular}の形式でテキ

ストスタイルで出力する．成分が沢山あるリスト ℓ に対して, ℓ を [ℓ] としてオプション widh=w を指定し，この機能を使う

とよい（cf. spbasic()） .

– title=s で文字列 s を指定すると，タイトルがつけられる．

– left=[s_{1},s_{2},…] を指定すると，それが 1 列目として付加される．途中の s_{j} が [s_{j,1},s_{j,2},…] となっていると，それが最終の行まで繰り返される（以下も同様）．

– right=[s_{1},s_{2},…] を指定すると，それが最終列として付加される．

– top=[s_{1},s_{2},…] を指定すると，それが先頭行として付加される（上の right=などがあればそれの処理の後）．

– last=[s_{1},s_{2},…] を指定すると，それが最終行として付加される．

– null=n を指定すると， n に等しい要素は表では空白とする（デフォルトは n = ""）．

– hline=[h_{1}, h_{2}, …] を指定すると， h_{i} 行の後に横線を引く．

（タイトルを除いた）表の始まりが 0，最初が 1 行目と数え，重複しての指定は多重線を表す. ∗ z は最終行（の後）を示す． z-1 のような指定も可能．

∗ v_{j} が， [k_{j},n_{j}] という正整数 n_{j} と非負整数 k_{j} の組のリストときは， n_{j} で割った余りが

k_{j} となる行全ての指定を意味する．

– vline=[v_{1}, v_{2}, …] を指定すると， v_{j} 列の後に縦線を引く．表の両端の縦線以外を指定する．

最初が 1 列目で，重複しての指定は多重線を表す.

∗ z は最終列（の後）を示す． z-1 のような指定も可能．

∗ v_{j} が， [k_{j},n_{j}] という正整数 n_{j} と非負整数 k_{j} の組のリストのときは， n_{j} で割った余り

が k_{j} となる列全ての指定を意味する．

– 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() のときの指定と同じ）．円グラフでは，指定文字列のデータの個数だけ並べたリストとする．

– 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)$

[a + b, \frac{c}{d}, [2, 3]]

[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)$

\begin{cases}0 & 1 \\ [a + b]_{12} & [3b]_{3} \\ [c]_{3} & [f]_{2} \\ d \end{cases}\}

[8] A=newmat(2,2,[[a,b],[c,d]]);
[ a b ]
[ c d ]
[9] B=newmat(2,2,[[p,q],[r,s]]);
[ 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=["\\\\&","%"])$

du = ((\begin{matrix}a & b \\ c & d \end{matrix}) \frac{d(x − 1)}{x − 1} + (\begin{matrix}p & q \\ r & s \end{matrix}) \frac{dy}{y} )u

[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);

\frac{du}{dx} = (\frac{( \begin{matrix}a & b \\ c & d \end{matrix} )}{x} + \frac{( \begin{matrix}p & q \\ r & s \end{matrix})}{x − 1})u

[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 + (a^{2} + 2ba + b^{2}) dy ∧ dz − 2 dx ∧ d(\frac{z}{y})

[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, n^{2} + 2n + 1, points.]
[19] os_md.ltotex(["There are",(n+1)^2,"points."]|opt="text");
$\texttt{There are}$
$n^2+2n+1$
$\texttt{points.}$
[20] os_md.dviout(@@)$
   There are n^{2} + 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 n^{2} + 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 のソースを表示または印刷すると（以下の例でも同様）．

Year 2014

1 2 3 4 5 6 7 8 9 10 11 12
10 12 34 53 23 12 24 68 55 57 32 20

[26] os_md.dviout(os_md.ltotex([L,M]|opt="graph"));

10 1 12 2 34 3 53 4 23 5 12 6 24 7 68 8 55 9 57 10 32 11 20 12

[27] L=[10,12,-10,34,53,23,-12,24,48,52,38,32,20]$
[28] os_md.ltotex(L|opt="graph");

10 12 −10 34 53 23 −12 24 48 52 38 32 20

[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]);

12 • Jan 15 • Feb 10 • Mar 8 • Apr 12 • May 14 • Jun 19 • Jul 15 • Aug 17 • Sep 13 • Oct 10 • Nov 15 • 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");

Year 2014

Month Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
number 12 15  10  8  12 14 19  15 17 13 10 15

[35] L=[35,42,19,38]$
[36] LL=["春","夏","秋","冬"]$

[37] os_md.ltotex([L,LL]|opt="graph",line=[-1,15]);

[figure: 春; 夏; 秋; 冬]

[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]
[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"]);
383. 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 行の行列とみなす．

• null=1 では， 0 の成分は空白にする. null=2 では対角成分は残す． • var=ℓ 多項式や有理式の成分を fctrtos() で変換するときのオプション．

ただし， var=0 とすると，成分にこのような変換を用いない.

pfrac=v 成分を変数 v について部分分数展開する．

• small=1 とすると，小さな行列にする．行列の文字数換算の幅は小さくなる．

• small=2 とすると， lim を設定したとき，横幅が大きすぎる行列を小さな行列にする．

• raw=1 を指定しないと，成分が文字列のとき \text{ } の形で，指定した場合は L^{A}TEX の文字列としてそのまま用いる．

• 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" のとき行列は ( ), [ ], { }, | |, ∥ ∥ の形になる． s ="" のときは，括弧は描かれない．

• len=1 を指定すると， L^{A}TEX の文字列と推測された横幅の文字数を 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 & \\
 &  & 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];
27
384. divmattex(s,l)

:: 行列の TEX のソース s の分割や列の並べ替えを行う l によって以下のように変換される.

• [[k_{0},k_{1}, …]] : ν 列目をもとの行列の k_{ν} 列目とする（ν = 0, 1, …） .

• [[k_{0}^{1},k_{1}^{1}, …],[k_{0}^{2},k_{0}^{2}, …], …] : 横長の行列を分割して複数に分ける． [k_{0}^{1},k_{1}^{1}, …] は最初の分割された行列．

• [m_{1}, …] : [[0,1,...m_{1} − 1],[m_{1}, …],…] : を表す．特に [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}
\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*}
385. smallmattex(s)

:: TEX のソースで ( ) や { } で囲まれた行列を小サイズに変換する（cf. mtotex()）

386. texlen(s)

:: L^{A}TEX の数式の横幅を推測して文字数で返す Risa/Asir の TEX 出力の文字列で，多項式や有理式に対応する．改行記号や行列には対応していない．より具体的には以下の通り．

• \frac{...}{...} は，分母と分子の推測横幅文字数の大きい方と数える（ネスティング可）

• 上を除いて \ で始まりアルファベットか続く部分はまとめて 1 文字幅とみなす．

• 空白や改行文字， & ^_{ } は文字数に数えない．

• _*^が存在して * が任意の 1 文字の場合は _* を文字数に含めない．

• _{**}^または _{**}}^に対しては（* は任意文字）， _{**} を 1 文字とみなして数える．

387. texlim(s, n|del=s_{0},cut=s_{1})

:: 長い TEX の数式を，複数行に分割する s は多項式に対応する（\frac などが含まれていない） TEX の数式. texlen() で計った文字数幅が n を越えないよう分割する．ただし n < 30 のときは， n =TeXLim とみなされる．

• 改行は + - ( の前．ただし \Bigl( や \biggl( などには正しく対応している．

• s_{0} は元の改行の文字列（これは残される）で s_{1} は新たに挿入される改行の文字列．

• デフォルトは， s_{1} ="\\\\\n&" かつ s_{0} = s_{1}.

• s = 1 のときは， TeXLim を n に設定するコマンドとなる．

3.2.10 Lines and curves

388. ladd(u,v,t)    ladd(u,v,[t_{2}])    ladd(u,v,[t_{1},t_{2}])

:: ベクトルまたはリストの成分の和（t = 1）や差（t = −1）を成分とするリストを返す u に v を t 倍して加えた座標を返す．あるいは， u の t_{1} 倍と v の t_{2} 倍の和を返す．

  • ladd(u,v,[t_{2}]) は， ladd([u,v],0,[1 − t_{2},t_{2}]) と解釈される．

• 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]);
 [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]
389. 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]
390. dnorm(v|max=f)

:: ベクトルまたはリストのノルム，または 2 点間の距離を返す • max=1 : 成分の絶対値の最大値を返す．

• max=2 : 成分の絶対値の和を返す．

• v が [v_{1}, v_{2}] という 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);
6
391. dext(u,v)， ([u_{1},u_{2}],[v_{1},v_{2}])

:: 2 次元ベクトルまたはリストの外積を返す u と v の外積，または u_{2} − u_{1} と v_{2} − v_{1} の外積を返す．

[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]);
-1
392. darg([p,q])  darg([p_{1},p_{2}],[q_{1}, q_{2}])

\overrightarrow{pq} = (x, y) の偏角 θ，または\overrightarrow{p_{1}p_{2}} と\overrightarrow{q_{1}q_{2}} のなす角に応じた数を返す

• \overrightarrow{pq} = (x, y) の偏角 θ に応じた数（−\frac{π}{2} < θ ≤ \frac{3}{2}π）： (x, y) = (0, 0) のとき， −8 を返す．それ以外では， v = \frac{y^{2}}{x^{2}+y^{2}} とおく． y < 0 のとき， v を −v で置き換え，さらに x ≤ 0 のとき v を 2 − v で置き換える．戻り v は −2 または −1 ≤ v < 3 を満たす．

• \overrightarrow{p_{1}p_{2}} と\overrightarrow{q_{1}q_{2}} のなす角 θ に応じた r を返す数 (−2 < r ≤ 2) ： r = −8: p_{1} = p_{2} または q_{1} = q_{2} r = 0 : 同じ向き r = 2 : 逆向き r = ±1 : 直交 r ≥ 0 : \overrightarrow{q_{1}q_{2}} の向きは\overrightarrow{p_{1}p_{2}} から正の向きに 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
393. dwinding([p,[q_{1}, . . . , q_{n}])

点 p に対して，点 q_{1}, …, q_{n}, q_{1} を順に繋ぐ折れ線の回転数を返す折れ線が点を基準に反時計回りに何回廻ったかを返す．点が折れ線の端点にあるときは\frac{1}{3} を，折れ線上にあるときは\frac{1}{2} を返す．

[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]]);
0
394. mrot(θ|deg=1)  mrot([θ′_{z},θ_{y},θ_{z}]|deg=1,conj=1)

:: 角度 θ の回転行列，または 3 次元の回転行列を返す • deg=1 を指定すると，度単位となる．

• 引数が [θ′_{z},θ_{y},θ_{z}] のときは， z 軸の周りに θ_{z}, x 軸の周りに θ_{y} 最後に z 軸の周りに θ′_{z} 回転した 3 次元の直交行列を返す．このとき conj=1 を指定すると， z 軸の周りに θ_{z}, y 軸の周りに θ_{y} 回転したときの z 軸にあたる軸に対する θ′_{z} の回転を返す．

[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 ]
395. dvangle(v_{1},v_{2})  dvangle([u_{1}, u_{2}, u_{3}],0)

:: ベクトルまたはリストの鋏む角度の余弦を返す • dvangle([u_{1}, u_{2}, u_{3}],0) は dvangle(u_{2} − u_{1},u_{3} − u_{2}) と解釈される．

• v_{1} または v_{2} が 0 のときや u_{1}, u_{2}, u_{3} のいずれかが 0 のときは 1 を返す．

• 2 次元ベクトル V の偏角（π 以下で −π より大）は myarg(V[0]+V[1]*@i) で得られる．

396. 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() のデータのリストとみなして，順につなげた一つの曲線データと

する．

– 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]]
397. 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]]
[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);

[figure]

398. ptlattice(m,n,v_{1},v_{2}|org=p,scale=t,cond=[f_{1},f_{2}, . . .],line=1)

:: org を始点として v_{1} 方向に m 個まで， v_{2} 方向に n 個までの合計 m × n 個の格子点の座標 • scale=t : 得られた座標を全て t 倍にして返す（org も同様）．

• line=1 : 格子点でなくて，格子を描く線分のデータを返す xylines() の例を参照）．

• f_{1}, f_{2}, … は (x, y) の函数（一次式または多項式または有理式）で，これらが全て非負の点のみ残す（平面座標の時のみ指定可能）． f_{j} =[f_{j_{1}}, …, f_{j,n_{j}}] は， f_{j,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);

399. 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]]
400. ptcommon([s_{1},s_{2}],[t_{1},t_{2}]|in=k)

:: 直線や線分や円に対して共通点，接点や垂線の足，内分点，方向転換進行点，角度などを求める

• s_{1} = [x_{1}, y_{1}], s_{2} = [x_{2}, y_{2}], t_{1} = [u_{1}, v_{1}], t_{2} = [u_{2}, v_{2}] のとき, s_{1} と s_{2} とを結ぶ直線と， t_{1} と t_{2} を結ぶ直線の交点の座標（共通点がないときは 0 を無限にあるときは 1）を返す．ただし， s_{1} = s_{2} のとき， s_{1} と s_{2} を結ぶ直線とは，その点と考える（t も同様）．

• s_{1} = [x_{1}, y_{1}], s_{2} = [x_{2}, y_{2}], t_{1} = [u_{1}, v_{1}], t_{2} = 0 のとき， s_{1} と s_{2} とを結ぶ直線に点 t_{1} から下ろした垂線の足の座標を返す，

• s_{1} = [x_{1}, y_{1}], s_{2} = [x_{2}, y_{2}], t_{1} = [u_{1}, v_{1}], t_{2} > 0 のとき， s_{1} と s_{2} とを結ぶ直線と，点 t_{1} を中心とする半径 t_{2} の円との交点を返す（交点をリストで，交点がないときは 0 を返す）．

• s_{1} = [x_{1}, y_{1}], s_{2} > 0, t_{1} = [u_{1}, v_{1}], t_{2} > 0 のとき，点 s_{1} を中心とする半径 s_{2} の円と，点 t_{1} を中心とする半径 t_{2} の円との交点を返す（交点をリストで，交点がないときは 0 を返す）．

• s_{1} = [x_{1}, y_{1}], s_{2} > 0, t_{1} = [u_{1}, v_{1}], t_{2} = 0 のとき，点 s_{1} を中心とする半径 s_{2} の円に t_{1} を通る接線を引いたときの接点の座標を返す（接点をリストで，接点がないときは 0 を返す）． • s_{1} = [x_{1}, y_{1}], s_{2} = [x_{2}, y_{2}], t_{1} が数のとき，\overrightarrow{s_{1}s_{2}} を t_{2} だけ回転した向きの単位ベクトルを t_{1} 倍し

たベクトルだけ s_{2} から移動した点を返す（方向転換進行点）．ただし in=1 を指定すると，線分 s_{1}s_{2} の比 t_{1} : t_{2} での内分点を返す．

• in=1 を指定すると， 2 点を結ぶ直線が 2 点を結ぶ線分で置き換えられる．共通集合が線分になるときは，その両端を返す．

• in=-1 を指定すると， 2 点を結ぶ直線が 2 点を結ぶ線分の垂直二等分線で置き換えられる．

• in=-2 を指定すると， s_{1} と s_{2} とを結ぶ直線が，その 2 点を結ぶ線分の垂直二等分線で置き換えられる．

• in=-3 を指定すると， s_{1} と s_{2} とを結ぶ線分の垂直二等分線と， t_{1} と t_{2} を結ぶ線分の交点があればそれを返す．

• 直線と直線の交点を求める場合は，座標に不定元が含まれていてもよい．また，全ての座標が有理数で指定してあれば，直線の交点の座標も有理数で返される．

• in=2 を指定すると，\overrightarrow{s_{1}s_{2}} と\overrightarrow{t_{1}t_{2}} のなす角度を返す（−π を越えて π 以下で，\overrightarrow{s_{1}s_{2}} を基準として反時計回りが正の向き）．

• 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);  /* 角度 (ラジアン)*/
1.5708
[14] os_md.ptcommon([[0,0],[1,1]],[[0,0],[-2,2]]|in=3);  /* 角度 (度） */

[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]
0
401. 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 = [[x_{0},y_{0}],r] で円を指定し（中心と半径）， q = [q_{1},q_{2}] = [[x_{1},y_{1}],[x_{2},y_{2}]], r = [r_{1},r_{2}] = [[x_{2},y_{2}],[x_{3},y_{3}]] によって直線上の 2 点で二直線を指定したとき，円と二直線に接する円の半径と中心座標のリストを返す．ただし\overrightarrow{q_{1}q_{2}} を x 軸の正方向で，直線 r_{1}r_{2} を y 軸とするような（斜交）座標系の第 1 象限および第 3 象限内の接円のみを返す．第 3 象限の場合は，半径の −1 倍を返す．第 1 象限で直線の交点から近いものから順に，次に第 2 象限で原点に近いものから順に，半径と中心座標の組をリストにして返す．

– ∠q_{3}q_{1}q_{2} が 180^{∘} 以下で，\overrightarrow{q_{1}q_{3}} は\overrightarrow{q_{1}q_{2}} を正方向に回転したものとする. r = [q_{1},q_{3}] とおくと，その頂角内の接円は，リストでは半径が正のものとなる．

– 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]]
402. ptinversion(p|org=[a,b],sc=r)

:: 点 p または円 p の反転 • 反転とは，複素平面上で z ↦ \frac{1}{z} で定まる写像とする.

• sc=r を指定すると， r > 0 のとき，複素平面上で z ↦ \frac{r}{z̄} で定まる写像, r < 0 のとき z ↦ \frac{|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;  /* 平行線間の円の反転 */
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);
403. ptcontain(p,[t_{1},t_{2},t_{3}])

:: 点 p あるいは線分 p = [p_{1},p_{2}] と三角形 t_{1}, t_{2}， t_{3} の共通部分を返す • p が点のとき，三角形の外部，内部，辺，頂点に属するかどうかに応じて， 0， 1， 2， 3 を返す． • p =[p_{1},p_{2}] という線分のとき，三角形で切り取られた部分を返す．

[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);
3
404. pg2tg(n|all=f,bis=1)

:: 正 n 多角形の対角線による三角形分割のリストを返す正 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 数 C_{n−2} で

   catalan(n-2) となる．

• all=2 を指定すると，回転で移り合わない三角形分割のリストを返す．

• all=64 を指定すると，回転や裏返しで移らない Zigzag タイプ（分割する対角線のない頂点が 2 つ）の三角形分割のリストを返す（上の 1, 2 との同時指定は， 64, 65 とする）．

• 負の数 −n を与えると， 4 角形から n 角形までの三角形分割のリストのリストを返す（bis=1 が指定されたとみなす）．

[0] os_md.pg2tg(5);
[[[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]]]
405. 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 が偶数の時は，頂点\frac{k}{2} を通る対称軸に対する鏡映変換， k が奇数の時は辺 [\frac{k−1}{2},\frac{k+1}{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 は分割に使われた対角線の端点となっていないとき，すなわち 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");
0
406. 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） , その後は正の向き

• opt=s : p で指定した頂点同士を結ぶ線分の属性（色とか点線 "dotted" とか，デフォルトは

  "red"）

• V=v : v =[[p_{1},q_{1}],[p_{2},q_{2}],[p_{3},q_{3}], …] は多角形の（中心を原点とする）頂点の座標．これにより正多角形でない場合にも対応．

• 次は，描画を重ねるのに使う（複数の三角形分割，特定の対角線や辺に異なる色をつける, などの

ため） – 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=[[a_{1},b_{1}],[a_{2},b_{2}], ⋯] : 多角形の中心位置を（多角形の個数）順に指定 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}=[m_{j},n_{j},s_{j}] : 多角形の m_{j} 番目と n_{j} 番目を線や矢印でつなぐ（最初は 1 番目）．オプション文字列を s_{j} で指定する（たとえば， "->, red"）． s_{j} =""はオプションを指定しないことを意味する．

– ℓ_{j}=[m_{j},m_{j}] : 前項と同じだが，オプション文字列は ℓ_{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);
\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)$
[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)$);
\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;
\draw [red]
(0)--(2) (0)--(4) (2)--(4);
%%
\draw[dotted](S2)--(S3);
\draw[<->](S1)--(S2);
\draw[<->](S1)--(S3);
407. 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 にチーム番号（数字）のリストを指定してもよい.

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,[[m_{1},n_{1}],[m_{2},n_{2}],…],p] または [m,[[m_{1},n_{1}],[m_{1},n_{2}],…]] とすることによって，指定した試合の左（rev=1 を指定すると右）側のチームが勝ちとする. なお， m_{i} から n_{i} 番目のトップを決める試合が指定される.

• dviout=1 とすると画面表示される.

dviout=-1 とすると TEX のソースファイルに追加されるが，表示はしない.

• verb=1 : 各試合の情報のリスト（対戦する両チームはどのグループのトップかと，それぞれ何回戦で決まったか）

• verb=2 : 優勝チームを 0 とした番号付けのベクトル，優勝チームの参加する試合の情報のリスト，優勝チームが参加しない試合を優勝チームと何試合目で当たるかで分類した試合情報のリスト，の 3 つのリスト

• verb=5 : 優勝チームを 0 とした 0 から n までの番号付けのリスト（n + 1 チームのとき），（基底の順序に従った） n − 1 試合のリスト），（n 個の）基底のリスト（cf. midKZ()）各試合は，いくつかのグループのトップを定めるが，そのグループの先頭チームの番号と最後のチームの番号の組で表す。ただし，優勝決定戦は省く（n − 1 試合）。

• verb=4 : 上と同じだが，優勝者の参加する試合をより後に並べたもの

• iand(verb,16) : 優勝決定戦を加えたリスト

• verb=4+8+16 : 実際に試合が可能な順序

[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[0],0|verb=1);
[2] 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]]]
[3] os_md.xytournament("((**)(**))",0|winner=0,teams=[2,3,0,1],dviout=1);
[4] os_md.xytournament("((**)(**))",0|winner=[0,[[1,2]]],teams=[2,3,0,1],
    dviout=1);
[5] os_md.xytournament(U[1],0|verb=1);
[[[[0,0],0],[[1,1],0]],[[[2,2],0],[[3,3],0]],[[[0,1],1],[[2,3],1]]]
[6] os_md.xytournament(U[1],0|verb=2,winner=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("(((**)(**))",0|verb=4,winner=3);
[[2,3,0,1],[[0,1],[2,3]],[[1],[2,3],[3]]]
[8] T="(((**)(**))*)"$
[9] os_md.xytournament(T,0|verb=3,winner=5);
[[1,2,3,4,0],[[1,4],[3,4],[1,2]],[[1,2,3,4],[3,4],[4],[2]]]
[10] os_md.xytournament(T,0|verb=4,winner=5);
[[1,2,3,4,0],[[1,2],[3,4],[1,4]],[[1,2,3,4],[3,4],[4],[2]]]
[11] os_md.xytournament(T,0|verb=4,winner=5,rev=1);
[[1,2,3,4,0],[[1,2],[3,4],[1,4]],[[1,2,3,4],[1,2],[3],[1]]]
[12] os_md.xytournament(T,0|dviout=1,winner=5,teams=[1,2,3,4,0]);
[13] os_md.xytournament(T,0|dviout=1,winner=5,teams=[1,2,3,4,0],rev=1);
 [14] os_md.xytournament(T,0|dviout=1,winner=4,teams=[2,3,1,0,4],win=1);

408. ptconvex([p_{1}, p_{2}, . . .]|opt=1)

:: すべての点 p_{1}, p_{2}, … の凸包，あるいはすべての点を繋ぐ多角形を返す複数の点の凸包となる多角形の頂点の座標のリストが返される．

• 点の個数が N のとき， N 個の座標の qsort() と最悪 3N 回程度の数の大小比較で完了するアルゴリズム．筆者が高校生のとき，雑誌「大学への数学」の学力コンテストのある問題の解答として提出した中で使った 2 つのアルゴリズムのうちの一つ（1966 年）． Graham が 1972 年に発表し，グラハムスキャンとして知られている（筆者は最近知った）．偏角の大小を使うが，ここでは逆三角関数や平方根は使わずに darg() を使って，有理計算で済ませている．もう一つは「ギフト包装法」と呼ばれているようです．

• 最初の点は座標の辞書式順序が最小の頂点に対応し，反時計回りの順に多角形の周を廻るときの多角形の頂点の座標のリストを順に返す（重複点や辺上の頂点は省いて返す）．

• p_{i} は， 3 成分以上あってもよい（点の色，などの情報）．最初の 2 成分を (x, y) 座標とみなす． • opt=1 : すべての点を結ぶ閉じた交わりのない多角形を返す．

多角形の頂点はいずれかの点で，辺上に点があることも許す．また，同一の点があっても省かない．すなわち，戻り値 [Q_{1}, …, Q_{n}] は引数の並べ替えで， Q_{1}, Q_{2}, …, Q_{n}, Q_{1} と折れ線でつなぐと多角形になる.

[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]]
409. ptwindow(ℓ,[x_{1},x_{2}],[y_{1},y_{2}]|scale=t)

:: 平面座標 (x, y) のリストで x_{1} ≤ x ≤ x_{2}， y_{1} ≤ y ≤ y_{2} を満たさないものを 0 に変える

• scale=t : リストで与えられた平面座標は t 倍されているとみなす．

410. ptbbox([[x_{1},y_{1},. . .],[x_{2},y_{2},. . .],. . .]|box=b)

ptbbox([[[x_{min}^{(1)},x_{max}^{(1)}],[y_{min}^{(1)},y_{max}^{(1)}],…],[[x_{min}^{(2)},x_{maxS}^{(2)}],…],…]|box=1) :: 座標 (x, y, …) や箱のリストを囲む箱 [[x_{min},x_{max}],[y_{min},y_{max}],…] を返す

• 各座標はリストでもベクトルでもよい． 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]]

411. iscombox([[x_{min}^{(1)},x_{max}^{(1)}],[y_{min}^{(1)},y_{max}^{(1)}],…], [[x_{min}^{(2)},x_{max}^{(2)}],[y_{min}^{(2)},y_{max}^{(2)}],…])

:: 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]]);
0
412. lninbox([p_{1},p_{2}],[[x_{min},x_{max}],[y_{min},y_{max}]]|in=1)

:: 平面内の 2 点 p_{1} と p_{2} を結ぶ直線（または線分）の箱内の部分（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);
[[0.2,0.3],[0,0.75]]
413. scale(ℓ|scale=[c_{1}, . . .],f=f,shift=[s_{1},s_{2}],TeX=1,mes=[t,[a_{1},b_{1},w_{1}], . . .],line=[a,b],
mes2=[[x_{1},[t_{1,0},t_{1,1},c_{1}],t_{1},s_{1}],. . .],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 段階の目盛のみの時は単純に [a_{1},a_{2},a_{3}, …] と表してもよい． scale(ℓ) は，目盛リスト m =[[m_{1,1},m_{1,2}, …],[m_{2,1},m_{2,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 : log_{10} x (1 ≤ x ≤ 10) に対する目盛（C, D 尺に対応）を生成する． · ℓ = 2 : \frac{1}{2} log_{10} x (1 ≤ x ≤ 100) に対する目盛 (A, B 尺に対応）を生成する． · ℓ = 3 : \frac{1}{3} log_{10} x (1 ≤ x ≤ 1000) に対する目盛 (K 尺に対応）を生成する． · ℓ = 4 : frac(0.5 + log_{10} x) (1 ≤ x ≤ 10) に対する目盛 (CF, DF 尺に対応）を生成する． · ℓ = 5 : frac(log_{10}(πx)) (1 ≤ x ≤ 10) に対する目盛 (CF, DF 尺に対応）を生成する． · ℓ = 6 : log_{10}(10 sin x) (5^{∘}45′ ≤ x ≤ 90^{∘}) に対する目盛 (S 尺に対応）を生成する． · ℓ = 7 : log_{10}(10 tan x) (5^{∘}40′ ≤ x ≤ 45^{∘}) に対する目盛 (T1 尺に対応）を生成する． · ℓ = 8 : log_{10} tan x (45^{∘} ≤ x ≤ 84^{∘}10′) に対する目盛 (T2 尺に対応）を生成する． · ℓ = 9 : log_{10} \frac{πx}{18} (35′ ≤ x^{∘} ≤ 5^{∘}45′) に対する目盛 (ST 尺に対応）を生成する． · ℓ = 10 : log_{10}(1000 log x) (1.001 ≤ x ≤ 1.0105) 対する目盛 (LL0 尺に対応）を生成する． · ℓ = 11 : log_{10}(100 log x) (1.01 ≤ x ≤ 1.105) 対する目盛 (LL1 尺に対応）を生成する． · ℓ = 12 : log_{10}(10 log x) (1.105 ≤ x ≤ 2.72) に対する目盛 (LL2 尺に対応）を生成する． · ℓ = 13 : log_{10}(log x) (2.72 ≤ x ≤ 22000) に対する目盛 (LL3 尺に対応）を生成する． · ℓ = 14 : log_{10}(−1000 log x) (0.99 ≤ x ≤ 0.999) 対する目盛 (LL00 尺に対応）を生成する． · ℓ = 15 : log_{10}(−100 log x) (0.905 ≤ x ≤ 0.99) 対する目盛 (LL01 尺に対応）を生成する． · ℓ = 16 : log_{10}(−10 log x) (0.368 ≤ x ≤ 0.905) に対する目盛 (LL02 尺に対応）を生成する． · ℓ = 17 : log_{10}(− log x) (0.000045 ≤ x ≤ 0.368) に対する目盛 (LL03 尺に対応）を生成する． · CI， DI の目盛生成は， ℓ = 0 で inv=1 を指定するか， (c_{1}, s_{1}) を (−c_{1}, s_{1} + c_{1}) に変える． · CIF, DIF 尺の目盛り生成は， ℓ = 4 で inv=1 を指定する． · 同様にして， inv=1 の指定で SI, TI_{1}, TI_{2} 尺などを作ることができる．

 · ℓ は上の数字の代わりに，文字列 "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(m_{1,1}) + s_{1},cf(m_{1,2}) + s_{1}, …],[cf(m_{2,1}) + s_{1}, cf(m_{2,2}) + s_{1}, …], …] を返す．ここで f(x) のデフォルトは自然対数 log x/ log 10． f(x) はリスト形式函数の形で指定してもよい．

• scale=[c_{1},c_{2}, …] : 以下の目盛描画用パラメータを返す（xylines() の引数）．なお， shift=[s_{1},s_{2}] によって描画の相対位置を指定する．ただし s_{1} = 0 のときは shift=s_{2} と指定してもよい． [[c_{1}f(m_{1,1})+s_{1},s_{2}],[c_{1}f(m_{1,1})+s_{1},s_{2}+c_{2}],0, [c_{1}f(m_{1,2})+s_{1},s_{2}],[c_{1}f(m_{1,2})+s_{1},s_{2}+c_{2}], 0, …], [c_{1}f(m_{2,1}) + s_{1},s_{2}],[c_{1}f(m_{2,1}) + s_{1},s_{2}+c_{3}],0, [c_{1}f(m_{2,2}) + s_{1},s_{2}],[c_{1}f(m_{2,2}) + s_{1},s_{2}+c_{3}],0, …], …] c_{1}, c_{2}, … は負の値も設定可能．なお c_{3} 以降がないときは， c_{n} のデフォルトは (n − 1)c_{2}.

• inv=1 : 0.5 の位置（C 尺でいえば\sqrt{10} の目盛の位置）で左右対称に折り返した目盛を作成する． • TeX=1 : 目盛描画の TEX のソースを返す（戻り値で xyproc() を呼ぶ）．

– 目盛線の色づけなどを行うときは， col="red"などとオプションで指定する（TikZ を用いる）． – mes=[t,[a_{1},b_{1},w_{1}], …]，あるいは mes=[t,c_{1},c_{2},c_{3}, …] により，それ以降で指定した目

盛の数字を，高さ t の位置に描く．なお，目盛の数字の色付けなどを指定するときは， t を [t,"red"] などと，オプション文字列を指定する．

– ℓ を数字または文字列で指定したときに mes の 2 項目以降を省略すると，デフォルトの目盛の数字が描かれる．

– mes2=[[x_{1},[t_{1,0},t_{1,1},c_{1}],t_{1},s_{1}],…], x_{1} に対応する場所の高さ t_{1} の位置に s_{1} を書く． s_{1} は"$\\pi$"や ["red","$\\pi$"] などが可能．また高さ t_{1,0} から t_{1,1} までの目盛線を描く． c_{1} は色付けなどのオプション文字列．目盛線を描かないときは， [t_{1,0},t_{1,1},c_{1}] の部分を 0 と指定する． mes=を指定していて， t_{1,1} が mes=の t と等しいときは t_{1,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$"]])$
414. tobezier(ℓ|inv=[a,b,t],div=k)

:: 点のリスト ℓ で定まる Bézier 曲線のパラメータ表示とその逆変換と分割

• ℓ = [p_{0}, …, p_{n}] で， p_{j} が座標を表すリストまたはベクトルのとき，これらによって定まる Bézier

曲線（パラメータは t ∈ [0, 1]）を， t の n 次多項式を成分とするベクトル）を返す． Bézier 曲線とは

γ(t) = γ(p_{1}, …, p_{n}; t) = ∑_{j=0}^{n} \binom{n}{j}t^{j}(1 − t)^{n−j}p_{j} (t ∈ [0, 1]), \binom{n}{j} = \frac{n!}{j!(n − j)!}

で定まる曲線である（このとき n 次 Bézier 曲線という）．

γ(p_{0}, p_{1}; t) = (1 − t)p_{0} + tp_{1} は線分 p_{0}p_{1} を t : (1 − t) に内分する点で， 1 次 Bézier 曲線は p_{0} と p_{1} を結ぶ線分となる．また平面内の 2 次 Bézier 曲線は， x 座標と y 座標が t の 2 次（以下）の多項式となるが，平面を回転すると x 座標は t の 1 次式にできる．よって， 2 次 Bézier 曲線は放物線の一部（または線分）を回転したものとなる．

一方，\binom{n}{j} = \binom{n−1}{j} + \binom{n−1}{j−1} であるから

\binom{n}{j}t^{j}(1 − t)^{n−j} = (1 − t) · \binom{n−1}{j}t^{j}(1 − t)^{n−1−j} + t · \binom{n−1}{j−1}t^{j−1}(1 − t)^{n−1}, \binom{n−1}{−1} = \binom{n−1}{n} = 0

となり， p_{j} にこれを掛けて j = 0, …, n について加えると

γ(p_{0}, …, t_{n} : t) = γ(γ(p_{0}, …, p_{n−1}; t), γ(p_{1}, …, p_{n}; t); t)

がわかる．これを遡れば，元の点 {p_{0}, …, p_{n}} の t : (1 − t) の内分点を取ることを繰り返すことにより γ(p_{0}, …, p_{n} : t) が得られる．

たとえば 3 次 (cubic) Bézier 曲線は

γ(p_{0}, p_{1}, p_{2}, p_{3}; t) = γ(γ(p_{0}, p_{1}, p_{2}; t), γ(p_{1}, p_{2}, p_{3}; t); t)
= γ(γ(γ(p_{0}, p_{1}; t), γ(p_{1}, p_{2}; t); t), γ(γ(p_{1}, p_{2}; t), γ(p_{2}, p_{3}; t), t); t)

となる．よって p_{0}p_{1}, p_{1}p_{2}, p_{3}p_{4} の t : (1 − t) の内分点を順に q_{0}, q_{1}, q_{2} とし，さらに q_{0}q_{1} と q_{1}q_{2} の t : (1 − t) の内分点を r_{0}, r_{1} とすると r_{0}r_{1} の t : (1 − t) の内分点が γ(p_{0}, p_{1}, p_{2}, p_{3}; t) となる．

[figure: •; p_{0}; •; p_{3}; ×; p_{1}; ×; p_{2}; •; q_{0}; •; q_{1}; •; q_{2}; •; r_{0}; •; r_{1}; •; γ(t); t; t; t]

• inv=[a,b] : パラメータが t ∈ [a, b] の部分の Bézier 曲線に対応する座標（ベクトルで表す）のリストを返す． • div=1 : Bézier 曲線を 2 分割して，それらを定義する座標の組のリストを返す（3 次のときは，ベ

クトルの 4 個のリストの 2 つのリストで，前者が [0, \frac{1}{2}] の部分，後者が [\frac{1}{2}, 1] の部分）． 3 次のみ高速化対応．

• div=k : 2 ≤ k ≤ 256 のとき， Bézier 曲線を k 分割して，それらを定義する座標の組のリスト k 個のリストを返す.

• inv=[a,b] : ℓ が Bézier 曲線のとき，それを t ∈ [a, b] をパラメータとする Bé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 ]]
415. lbezier(l|inv=t)

:: 区分 Bézier 曲線のデータ変換 xybezier() のデータ形式（座標と，整数 0, 1, −1 のリスト）を，区分 Bézier 曲線を与える座標のリストを成分とするリストに変換する．

• inv=1 : 上の変換の逆変換を行う．区分 Bé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]]]
[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]
416. velbezier(f,[a,b,t])

:: Bézier 曲線の最大速度ベクトル • t ∈ [a, b] をパラメータとする Bé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]
417. ptbezier(l,[n, t])  ptbezier(l,s)

:: （複合） Bézier 曲線上の点と速度ベクトルを求める

• l は， xybezier() の引数で与える（複合） Bézier 曲線のデータ，またはそれを lbezier() で変換した形

• n 番目の Bézier 曲線の t = x の点の座標と速度ベクトルの組を返す．

• n = 0 は最初の Bézier 曲線， n = 1 は 2 番目， n = −1 は最後の， n = −2 は最後から 2 番目の Bézier 曲線を表す．

• 2 番目の引数 s が非負実数の時は， n は s の整数部分 +1 を， t は s の小数部分を表す．ただし x が Bézier 曲線の個数より大きいときは，（複合） Bézier 曲線の終点を表す．

• 2 番目の引数 x が −1 のときは， Bé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));
418. areabezier(l|rev=1,pt=[p_{1},p_{2}, . . .],para=1,prec=v,int=k,exp=c,Acc=1,cpx=1)

:: Bézier 曲線を用いた領域の面積・数値積分の計算

• l が [f,n,[t_{1},t_{2}]] という xygraph() の最初の 3 つの引数であって， f が変数 x の函数のときは,

Bézier 曲線で近似することによって積分 ∫_{t_{1}}^{t_{2}} f(x) dx を近似計算する． – int=1 を指定すると， |n| 分割して台形公式で近似計算する．

– int=2 を指定すると， |n| 分割してシンプソンの公式で近似計算する．このとき， n が奇数なら |n| + 1 分割する。

– cpx=1 : 非積分関数が複素数値函数であるときに指定する．

– 変数が x でなくて，たとえば t のときは， [t,t_{1},t_{2}] と明示する．

– 等分割の個数は |n| となる（n = 0 は， 32 と解釈される）．

– 積分区間外まで函数が定義されているときは， n を負の数にする（n が分割の数）．

– t_{1} ="-infty" （""でも可）とすると a = −∞ と, t_{2} ="infty" （""でも可）とすると b = ∞ と解釈され，無限区間での積分となる．無限区間での積分のとき exp=c の指定が有効（cf. cmpf()）．

– 無限区間での積分において無限遠で o(|x|^{−2}) （有理函数のときは O(|x|^{−2}) を満たさないとき）

は誤差が大きくなるので， prec=16 または exp=1 などと指定すると改善される．

• 函数に滑らかでない点や不連続点がある場合は， prec=16 などと指定すると計算誤差が少なくなる．

• f がリストで f=[f_{1},f_{2}] というパラメータ表示の曲線のときは， 3 番目の要素が [t,t_{1},t_{2}] ならば，その曲線を Bézier 曲線で近似した曲線に沿って，積分 ∫_{t_{1}}^{t_{2}} f_{2}(t) df_{1}(t) を計算する．特にこの Bézier 曲線が閉曲線のときは，その曲線で囲まれた領域の面積の計算となる．このとき，時計回りかどうかで正負が決まり，反時計回りに 1 回囲まれた部分の面積は −1 倍される．

• Acc=1 を指定すると pari() による高精度計算を行う.

ただし ctrl("bigfloat",1) および setprec(prec) による精度の設定が必要．また，有理関数でなくて sin(x) などの初等関数を扱う場合は注意が必要で，不定元が大量に生成される可能性がある（myeval() の項を参照． ord() で分かる）．

• 以上の時のオプションパラメータは xygraph() のときと同じ意味に解釈される．

• l が lbezier() の引数となる Bézier 曲線 C のデータ（2 形式のいずれでも可）ならば, 線積分 ∫_{C} ydx の値を返す．閉曲線のデータであったなら，その曲線で囲まれた領域の面積となる.

[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.98989
[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
[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)

Bézier 曲線を使った数値積分の相対誤差

非積分関数積分範囲指定  16 分割  32 分割  96 分割  384 分割  1536 分割
(cos θ, sin θ) 0 ≤ θ ≤ 2π (−n, −) 6.8 × 10^{−8} 1.1 × 10^{−9} 1.5 × 10^{−12} 3.2 × 10^{−17} 8.7 × 10^{−20}
Cardioid  −π ≤ θ ≤ π  (n, −) 5.4 × 10^{−4} 3.1 × 10^{−5} 3.8 × 10^{−7} 1.5 × 10^{−9} 5.8 × 10^{−12}
x sin x  0 ≤ x ≤ π  (−n, −) 2.9 × 10^{−4} 1.8 × 10^{−6} 2.2 × 10^{−8} 8.7 × 10^{−11} 3.4 × 10^{−13}
\frac{sin x}{x}  0 < x ≤ π  (−n, −) 1.5 × 10^{−6} 9.5 × 10^{−8} 1.2 × 10^{−9} 4.6 × 10^{−12} 1.7 × 10^{−14}
\frac{1}{x^{2}+1}  −∞ < x < ∞ (n, −) 1.3 × 10^{−5} 1.3 × 10^{−7} 8.5 × 10^{−10} 4.7 × 10^{−12} 2.1 × 10^{−14}
e^{−x^{2}}  −∞ < x < ∞ (n, −) 7.1 × 10^{−4} 1.3 × 10^{−4} 2.6 × 10^{−6} 1.1 × 10^{−8} 4.3 × 10^{−11}
x^{− \frac{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^{− \frac{3}{2}}  1 ≤ x < ∞ (n, −)^{16} 5.9 × 10^{−6} 4.5 × 10^{−5} 2.8 × 10^{−5} 1.4 × 10^{−5} 6.9 × 10^{−6}
x^{− \frac{3}{2}}  1 ≤ x < ∞  (n, 1) 3.0 × 10^{−4} 3.8 × 10^{−5} 1.4 × 10^{−6} 6.6 × 10^{−9} 2.6 × 10^{−11}

• 上表の最初は円の面積の数値計算例で， 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 程度である．

• \frac{sin x}{x} の (0, π] での数値積分は以下のように行った．

  [0] F=os_md.f2df(sin(x)/x)$
  [1] F=os_md.cutf(F,x,[[],[0,1],[]])$     /* x=0 のとき 1 となるように拡張 */
  [2] os_md.areabezier([F,-32,[0,@pi]]);
  1.85194

なお ∫_{0}^{π} \frac{sin x}{x} dx = 1.8519370519824661706 ⋯

[figure: f = \frac{1}{x^{2}+1}; 5; 4; 3; 2; 1; 0; −1; −2; −3; −4; −5; 1]

cmpf(f)  1 0 8 7 6 5 4 3 2 1  cmpf(f|exp=1)  1 0 8 7 6 5 4 3 2 1  cmpf(f|exp=2)  1 0 8 7 6 5 4 3 2 1

[figure: f = \frac{1}{x^{\frac{3}{2}} +1}; 5; 4; 3; 2; 1; 0; 1; cmpf(f); 1; 0; 8; 7; 6; 5; 4; 3; 2; 1; cmpf(f|exp=1)  1 0 8 7 6 5 4 3 2 1]

上のグラフは，次のようにして得られる 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 であるから，図の面積が保たれることに注意．

419. ptcombezier(ℓ_{1},ℓ_{2},m)

:: 点のリスト ℓ_{1}, ℓ_{2} で定まる 2 つの Bézier 曲線の交点を求める • ℓ_{1}, ℓ_{2} は， 3 次 Bézier 曲線を想定している（それ以外でも可）

• m は交点の正確さ（パラメータを 2^{m} 分割する）． 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]]]
420. ptcombz(b_{1},b_{2},m|red=t,prec=k)

:: 区分 Bézier 曲線 b_{1}, b_{2} の交点を求める

• b_{1}, b_{2} は， xybezier() の引数の形のデータ，あるいは lbezier で変換された区分 Bézier 曲線を与える座標のリストのリストのいずれか．

• b_{2} = 0 のときは， b_{1} で与えられた曲線の自己交叉点を返す．ただし各区分 Bézier 曲線自身や隣り合った区分 Bézier 曲線の交点は除く．

• b_{1} と b_{2} のそれぞれ何番目の区分 Bézier 曲線かのリスト（最初を 0 番目と数える）を先頭に付加した ptcombezier() の戻り値をまとめてリストの成分としたリストを返す．

• m は交点の正確さ（パラメータを 2^{m} 分割する）． m = 0 はデフォルトで， m = 20 を意味する． • red=1 : ほぼ等しい座標の点が複数あるときは，そのうちの一つデータのみ返す．

• red=2 : 交点の座標のみ返す（ほぼ等しい座標の点は重複して表示しない）．

• prec=k : オプション red を指定したとき， x 座標および y 座標の差が曲線の幅（現れる座標の x 座標の最大値と最小値の差，および y 座標の最大値と最小値の差）の 1/2^{k} 程度以下ならば，同じ点と見なす．デフォルトは 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

421. openGlib([w,h]|null=1)

:: グラフィックライブラリ（glib）のウインドウを開く

 • load("glib") が必要

• w, h は横幅，縦幅の pixel サイズで，右方向と上方向が，それぞれ x 座標， y 座標の正方向と設定 • null=1 を指定すると，（新たな）窓は開かない．

• 0 を引数とすると，窓の中身を消す．

 • glib window(), glib putpixel(), glib line() などを参照．
422. trcolor(s)

:: 色を文字列からコードへ変換

色は， red, green, blue, yellow, cyan, magenta, black, white, gray が可能

デフォルトは黒の 0．

[0] os_md.trcolor("red");
255
423. mcolor([c_{0},. . .,c_{m}],k|disc=1)

:: 中間色のコードを返す • c_{0}, …, c_{m} はカラーコードまたは色を表す文字列（cf. trcolor()）．

• k は混ぜ合わせ比率で， k = 0 のときは c_{0}， k が正整数のときは c_{m} の色コードを返す．

• それ以外では， 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)));

e21d00
424. 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}
425. 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 が空文字列なら空文字列でラベル無しとなる．

• TikZ=0 の場合

– t は一文字．空文字列 "" のとき出力しない．

– u はオプション文字列でラベルの後につく． 0 などとすると出力しない．

– s = [s_{1}, s_{2}] とすると， s_{1} は前置されるオプション文字列， s_{2} は出力文字列を表す． ∗ s_{1} ="[F]" : 枠で囲む

∗ s_{1} ="[F.]" : 囲む枠が点線（. を = とすると二重線）

∗ s_{1} ="+[F]" : 余裕のある枠で囲む

∗ s_{1} ="[Fo]" : 丸く囲む（o を oo とすると二重丸）

∗ s_{1} ="+!U" : 下に置く． U を D, L, R とすると上，右，左に変わる．さらに UL などとすると，右下などとなる． + を ++ とすると，位置のずらしが大きくなる．

• TikZ=1 の場合

– xypos([x,y,[s_{1},s_{2}],s_{t},s_{u}]) で， x, y が数， s_{1}, s_{2}, s_{t}, s_{u} が文字列で s_{2} が空でないとき

       node[s_{1}](s_{t}) at(x,y){s_{2}}s_{u}
   – xypos([x,y,[s_{1},""],s_{t},s_{u}]) のとき
       coordinate[s_{1}](s_{t}) at (x,y)s_{u}

– xypos([x,y,[s_{1},s_{2}],s_{t}]) または xypos([x,y,s,s_{t}]) のときは，上の s_{u} の項は現れない． – s_{t} が数字 1 のときは， s_{t} ="_" と解釈される．

– s_{t} が空文字列の時，または xypos([x,y,[s_{1},s_{2}]]) や xypos([x,y,s]) のとき，上の (s_{t}) の項は現れない．

– s や s_{1} が文字列でないときは数式として TEX の文字列に変換される．

– s_{1} にはたとえば以下のオプション文字が可能（複数の指定は , で区切る）．

        ∗ 位置指定 : 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"]);
(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$}
426. 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=[r_{1},r_{2}] : XY-pic/TikZ の座標に直すときに x 座標を r_{1} 倍， y 座標を r_{2} 倍する．

[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};
[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}

が必要である．

427. xyline([x_{1},y_{1},s_{1}],[x_{2},y_{2},s_{2}]|opt=t)  xyline([x_{1},y_{1}],[x_{1}, y_{2}]|opt=t)

:: XY-pic/TikZ で (x_{1}, y_{1}) と (x_{2}, y_{2}) を線で結ぶ（引数はベクトルでもよい） [x_{1},y_{1},s_{1},t_{1},u_{1}] などとするとラベル t_{1} がつく（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");

とする．

428. xyarrow([x_{1},y_{1},s_{1}],[x_{2},y_{2},s_{2}]|opt=t,cmd=s)

:: XY-pic/TikZ で (x_{1}, y_{1}) と (x_{2}, y_{2}) を矢印等で結ぶ（引数はベクトルでもよい） • 出力する 3 番目の要素 s_{1}, s_{2} は省略可．

• xypos() にあるように， [x_{1},y_{1},s_{1},t_{1},u_{1}] とするとラベル t_{1} がつき， s_{1} = [s_{1,1}, s_{1,2}] の形もサポートされる．

• 最初の引数が数字のときは "%\n" を，また XY-pic の場合は最初の引数が 0 でなくて 2 番目の引数が数字のときは空文字列を返す．

• オプションの t は線種などを指定する XY-pic/TikZ の文字列．まず XY-pic の場合のいくつかの例を挙げる．

[figure: "@{->}"; 矢印（デフォルト）]

[figure: "@{<->}"; 両側矢印]
"@{-}"  実線
"@{.}"  点線
[figure: "@{~}"; 波線]
"@{=}"  二重線
[figure: "@{--}"; 破線]
"@2{.}"  二重点線
"@{{*}->}" 矢印の例[figure: •]
"@{x.o}"  矢印の例[figure: ∘]
[figure: "@2{|.>>}"; 矢印の例]

[figure: "@/^1.5mm/"; 進む方向の左側に 1.5 mm 曲げる]

[figure: "@(ru,ld)"; 右上に出て左下に入る]

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 など
二重線  double
色づけ  red, 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 = [t_{0}, t_{1}] のときは， t_{0} が上のように解釈され（t_{0} = 0 はデフォルト），文字列 t_{1} は

->  デフォルト

to[out=60,in=120]  出る線と入る線の角度指定
to[out=60,in=120,relative] 出る線と入る線の相対角度指定

|-  縦線，次に横線でつなぐ
-|  横線，次に縦線でつなぐ
t_{1} の末尾が "+"  相対位置指定

• TikZ の場合は，オプション opt や cmd などを利用して，より広い描画コマンドに使うことがで

きる．

– os_md.xyarrow([x_{1},y_{1}],[x_{2},y_{2}]) で， x_{1}, x_{2}, y_{1}, y_{2} が数字の時

  \draw[->](x_{1},y_{1}) -- (x_{2},y_{2})

– os_md.xyarrow([x_{1},y_{1},s_{1}],[x_{2},y_{2}]) で， x_{1}, x_{2}, y_{1}, y_{2} が数字, s_{1} が文字列の時

  \draw[->]node(_0) at(x_{1},y_{1}){s_{1}} coordinate(_1) at(x_{2},y_{2})(_0) -- (_1);

– os_md.xyarrow([x_{1},y_{1},s_{1}],[x_{2},y_{2},s_{2}]) で， x_{1}, x_{2}, y_{1}, y_{2} が数字, s_{1}, s_{2} が文字列

  \draw[->]node(_0) at(x_{1},y_{1}){s_{1}} node(_1) at(x_{2},y_{2}){s_{2}}(_0) -- (_1);

s_{1} や s_{2} が数式の時は，それを TEX のソースに変換して $ で鋏んだものに置き換えられる．

– os_md.xyarrow([x_{1},y_{1},[s′_{1},s_{1}],t_{1},u_{1}],[x_{2},y_{2},[s′_{2},s_{2}],t_{2},u_{2}]|opt=[t,t′,t′′],cmd=s)

で， x_{1}, x_{2}, y_{1}, y_{2} が数字, 他が文字列

\s[t]node[s′_{1}](t_{1}) at(x_{1},y_{1}){s_{1}}u_{1} node[t′_{2}](t_{2}) at(x_{2},y_{3}){s_{1}}u_{2}(t_{1})t′(t_{2})t′′; なお， s のデフォルトは draw, t′ のデフォルトは --， t のデフォルトは -> となっている．また t′, t′′ を指定しないときは， opt=t としてよい．

– x_{1} や x_{2} が文字列のときは，それはラベルとみなされて y_{1} や y_{2} は無視され， ( ) で囲まれて

出力される．第 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  \path
       8  \node        \path node と同等
       9  \coordinate  \path coordinate と同等

これで定まるコマンドを \cmd としたとき

    os_md.xyarrow([x,y],n|opt=[t,t′,t′′])

で x, y, n が数字で他が文字列のとき

    \cmd[t](x,y)t′[t′′]

となる．なお， t′′ の項がない場合は上の [t′′] の項は現れない．

[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);

[figure: \frac{x}{y}; z^{2}; f; Sum; ∑_{i=1}^{n} a_{i}]

[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"]);
\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}

が必要である．

429. xyarrows([f_{1},f_{2}],[v_{1},v_{2}],[[x_{1},x_{2},m],[y_{1},y_{2},n]]|scale=r,abs=v)

:: XY-pic/TikZ で複数の矢印を描く x 変数の区間 [x_{1}, x_{2}] を m 等分， y 変数の区間 [y_{1}, y_{2}] を n 等分し，それぞれの終点を除いた m × n の各格子点 (x, y) に対して，点 (f_{1}(x, y), f_{2}(x, y)) を始点として， (v_{1}(x, y), v_{2}(x, y)) というベクトル（矢印）をXY-pic/TikZ で描く．

• y 変数がないときは，第 3 引数を [x_{1},x_{2},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)$
[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)$

430. xybox([[x_{1},y_{1}],[x_{2},y_{2}],[x_{3},y_{3}]]|opt=t,color=s...)  xybox([[x_{1},y_{1}],[x_{2},y_{2}]]|opt=t,color=s,...)

:: XY-pic/TikZ で (x_{1}, y_{1}) と (x_{2}, y_{2}) を対角点とし， (x_{3}, y_{3}) を頂点とする平行四辺形（あるいは水平な辺をもつ長方形）を描く

• [x_{j},y_{j}] はベクトルでもよい．

• xylines() のオプションと同じオプションが有効．

• 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;
431. 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");
{(2,3) *\cir<5mm>{l^d}};
[1] os_md.xycirc([2,3,x],0);
{(2,3) *+{x} *\cir{}};
432. xybezier([[x_{1},y_{1}], . . . ,[x_{n}, y_{n}]]|verb=k,opt=t,cmd=s,relative=1)

:: XY-pic/TikZ で区分 Bézier 曲線（複合 Bézier 曲線）を描く始点を (x_{1}, y_{1}), 終点を (x_{n}, y_{n}) とし，途中の座標を制御点とする Bézier 曲線を描く．

• [x_{j},y_{j}] はベクトルでもよい．

• 途中の [x_{i},y_{i}] を数字の 0, ±1 にすると以下のような特別の意味を持つ． – 0 : 前後で切り離して別の Bézier 曲線とする．

– 1 : 直前の点を途中の通過点とする Bézier 曲線とする．

– -1 : 始点を終点とする閉じた Bézier 曲線とし，前後で切り離す．

• verb=1 : 始点と終点を •，制御点を × で表示する．単独の Bézier 曲線となる場合のみ有効．

• verb=2 : 上と同様だが，終点は表示しない．

• verb=[k,t_{1},t_{2}] : 始点と終点，制御点の描き方を指定する． – k = 1, 2 は省略できて，省略したときは k = 1 （始点と終点を描く）と解釈される．

– t_{1} は始点と終点， t_{2} は制御点の示す記号を表し， xyput() の引数のリストのの成分 s に対応する．

    – デフォルトは， t_{1} ="$\\bullet$", t_{2} ="$\\times$"

– t_{2} を省略して verb=[t_{1}] とすると，始点と終点のみ描いて，制御点は描かない．

    – 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  赤で透明度 0.5 で塗りつぶす

fill=red,even odd rule 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)}};
{(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;
433. draw bezier(id,idx,b|col=c,opt=s,init=1)

:: キャンバス上に区分 Bézier 曲線を描くサーバー id が id でキャンバス id が idx のキャンバスに Bézier 曲線を描く（cf. draw obj()）．

• b は xybezier() の引数の形式, あるいはそれを lbezier() で変換したもの（よって区分 Bézier 曲線でよい）．または， tobezier() の戻り値の t 変数の Bé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)
434. xylines([[x_{1},y_{1},s_{1}],[x_{2},y_{2},s_{2}],. . .]|opt=t,close=1,curve=1,ratio=c,verb=1,scale=r,
Acc=1,dviout=1,proc=p)

:: XY-pic/TikZ で s_{j} を (x_{j}, x_{j}) に置き， (x_{1}, y_{1}), (x_{2}, y_{2}), … を（Bézier 曲）線で結ぶ • close=1 : 最後の点を最初の点と結んで，多角形または滑らかな閉曲線を作る．

• close=-1 : 曲線で結ぶ場合に，最初と最後の点は制御点とし，残りの点を滑らかに結ぶ．

• curve=1 : 曲線（Bézier 曲線を使う）で滑らかに結ぶ（cf. [O4]） .

P_{0}, P_{1}, P_{2}, P_{3} を通る曲線で P_{1} と P_{2} を結ぶには，\overrightarrow{P_{0}P_{2}} の方向に P_{1} から c_{1}\overline{P_{1}P_{2}} の距離進んだ点 Q と，\overrightarrow{P_{3}P_{1}} の方向に P_{2} から c_{2}\overline{P_{1}P_{2}} 進んだ点 R の 2 点を制御点とする 3 次の Bézier 曲線を用いる． P_{0} が存在しないときは Q を， P_{3} が存在しないときは R を省く．\overrightarrow{P_{0}P_{2}} と\overrightarrow{P_{1}P_{3}} のなす角を θ (0 ≤ θ ≤ π) とするとき，デフォルトでは

\frac{c_{1} + c_{2}}{2} = \frac{2}{3(1 + cos \frac{θ}{2})}, c_{1} : c_{2} = \overline{P_{0}P_{2}} : \overline{P_{3}P_{1}}

としている．

正 n 角形の頂点を指定し， close=1 を指定すると，デフォルトでは外接円に近い曲線になる．実際，外接円の半径を 1 としたとき，得られた曲線の中心からの距離と 1 との差の最大値は， n = 3 のとき 0.0015, n = 4 のとき 0.00027, n = 6 のとき 0.000024, n = 8 のとき 0.000004 という程度の小さな値となる. なお， ratio=c を指定したときは，以下のように定める．

\overrightarrow{P_{1}Q} = c\overrightarrow{P_{0}P_{2}}, \overrightarrow{P_{2}R} = c\overrightarrow{P_{3}P_{1}}

• Acc=1 : curve=1 を指定したとき， pari() の高精度で制御点を計算する．

• curve=2 : B-spline 曲線で結ぶ（途中の点は制御点で通らない）．このときは s_{j} は最初と最後のみ指定可能． TikZ ではサポートされない（3 次以下の Bézier 曲線はサポート）．

• s_{1}, s_{2}, … は省略可能．また s_{j} がないときは， [x_{j},y_{j}] はリストでなくてベクトルでもよい．

• 通過点のデータに 0 があるときは，その前後で直線または曲線を切る．

• scale=r : XY-pic/TikZ の座標に直すときに r 倍する．

• scale=[r_{1},r_{2}] : XY-pic/TikZ の座標に直すときに x 座標を r_{1} 倍， y 座標を r_{2} 倍する． XY-pic は数字が mm 単位， TikZ は cm 単位である．

• opt=t : 文字列 t による線種の指定． XY-pic でオプション curve を指定せずに線分で結ぶときの線種指定は xyarrow() を参照． curve= 1, 2 のときは，たとえば XY-pic ならば "~*=<3pt>{.}" は 3pt 間隔の点線． TikZ のときの線種指定は， xyarrow() の項を参照（t がオプション opt の値として渡される）．また t = [t_{0}, t_{1}] と 2 つの文字列のリストのときは， t_{0} と t_{1} とが xybezier() の opt と cmd のパラメータに設定される．

• opt=0 : xybezier() に渡す引数のリストを返す．

• dviout=1 : 画面で表示する．

• proc=1 : 描画実行形式の描画成分を返す（proc=2 も同様）．

• verb=1 : 通過点を •，制御点を × で表示する．

• verb=[t_{1},t_{2}] : 通過点を t_{1}, 制御点を t_{2} で表す（cf. xybezier()）．

デフォルトは， t_{1} ="\\bullet", t_{2} ="\\times" である．

• verb=[t_{1}] : 通過点を t_{1} で表す．

[figure: O; P_{1}; P_{2}; Q; R; r; a; θ; •; •; •; •; •; ×; T]

円の中心 O があって， OP_{0} = OP_{1} = OP_{2} = OP_{3} かつ P_{0}P_{1} = P_{1}P_{2} = P_{3}P_{4} となっている場合を考える． ∠P_{1}OP_{2} = θ, OP_{0} = r, P_{1}Q = P_{2}R = a とおいて座標を適当に選ぶと， Bézier 曲線上の t = \frac{1}{2} に対応する点 T は以下のようになる．

O : (0, 0), P_{1} : (r cos \frac{θ}{2}, r sin \frac{θ}{2}), P_{1} : (r cos \frac{θ}{2}, −r sin \frac{θ}{2}) Q : (r cos \frac{θ}{2} + a cos \frac{θ−π}{2} , r sin \frac{θ}{2} + a sin \frac{θ−π}{2} )

= (r cos \frac{θ}{2} + a sin \frac{θ}{2}, r sin \frac{θ}{2} − a cos \frac{θ}{2}) R : (r cos \frac{θ}{2} + a sin \frac{θ}{2}, −r sin \frac{θ}{2} + a cos \frac{θ}{2}) T : (r cos \frac{θ}{2} + \frac{3}{4}a sin \frac{θ}{2}, 0)

条件 OT = OP_{1} が成り立つとすると

r cos \frac{θ}{2} + \frac{3}{4}a sin \frac{θ}{2} = r

より

a = \frac{4}{3} \frac{1 − cos \frac{θ}{2}}{sin \frac{θ}{2}} r = \frac{4}{3} tan \frac{θ}{4}r = \frac{4}{3} \frac{sin \frac{θ}{2}}{1 + cos \frac{θ}{2}} r.

このとき

Q : (r cos \frac{θ}{2} + \frac{4}{3} \frac{1−cos \frac{θ}{2}}{sin \frac{θ}{2}} sin \frac{θ}{2}r, r sin \frac{θ}{2} − \frac{4}{3} \frac{sin \frac{θ}{2}}{1 + cos \frac{θ}{2}} cos \frac{θ}{2}r)
= ((\frac{4}{3} − \frac{1}{3} cos \frac{θ}{2})r, (1 − \frac{1}{3} cos \frac{θ}{2})\frac{sin \frac{θ}{2}}{1+cos \frac{θ}{2}} r),
\frac{P_{1}Q}{P_{1}P_{2}} = \frac{4}{3} \frac{sin \frac{θ}{2}}{1 + cos \frac{θ}{2}} \frac{1}{2 sin \frac{θ}{2}} = \frac{2}{3(1 + cos \frac{θ}{2})}

となる． r = 1 として， Bézier 曲線を B(t) = (x(t), y(t)) = P_{1}(1 − t)^{3} + 3Qt(1 − t)^{2} + 3Rt^{2}(1 − t) + P_{2}t^{3}， c = cos \frac{θ}{2} とおくと

L(s) := x(s + \frac{1}{2})^{2} + y(s + \frac{1}{2})^{2}

= \frac{16(1 − c)^{3}}{1 + c} s^{6} − \frac{8(1 − c)^{3}}{1 + c} s^{4} + \frac{(1 − c)^{3}}{1 + c} s^{2} + 1

= \frac{(1−c)^{3}}{1+c} s^{2}(4s^{2} − 1)^{2} + 1

となるので， 0 ≤ s ≤ \frac{1}{2} の範囲で

\sqrt[3]{8s^{2}(1 − 4s^{2})^{2}} ≥ \frac{8s^{2} + (1 − 4s^{2}) + (1 − 4s^{2})}{3} = \frac{2}{3}

となり，等号成立は 8s^{2} = 1 − 4s^{2}，すなわち s^{2} = \frac{1}{12} のときである．よって |s| ≤ \frac{1}{2} の範囲で L(s) は s = 0, ±\frac{1}{2} で最小値 1 をとり， s = ±\frac{1}{2\sqrt{3}} で最大値をとる．

L(±\frac{1}{2\sqrt{3}}) − 1 = \frac{1}{27} \frac{(1 − c)^{3}}{1 + c} ,

\sqrt{L(±\frac{1}{2\sqrt{3}})} − 1 ≒ \frac{1}{54} \frac{(1 − cos \frac{θ}{2})^{3}}{1 + cos \frac{θ}{2}} ≒ \begin{cases}\frac{1}{648} & (θ = \frac{2π}{3} = 120^{∘}) \\ \frac{1}{3668} & (θ = \frac{π}{2} = 90^{∘}) \\ \frac{1}{41900} & (θ = \frac{π}{3} = 60^{∘}) \\ \frac{1}{235541} & (θ = \frac{π}{4} = 45^{∘}) \\ \frac{1}{2683400} & (θ = \frac{π}{6} = 30^{∘}) \end{cases}

デフォルトでは P_{0}, P_{1}, P_{2}, P_{3} を通る滑らかな曲線の P_{1} と P_{2} を結ぶ部分は

cos θ = \frac{(\overrightarrow{P_{0}P_{2}}, \overrightarrow{P_{3}P_{1}})}{\overline{P_{0}P_{2}} · \overline{P_{1}P_{3}}},
cos \frac{θ}{2} = \sqrt{\frac{1 + cos θ}{2}} ,
c_{1} \frac{\overline{P_{1}P_{3}}}{\overline{P_{0}P_{2}}} · \overrightarrow{P_{0}P_{2}} = \frac{2}{3 + 3\sqrt{\frac{1+ \frac{(\overrightarrow{P_{0}P_{2}},\overrightarrow{P_{1}P_{3}})}{\overline{P_{0}P_{2}}·\overline{P_{1}P_{3}}}}{2}}} \frac{2\overline{P_{1}P_{2}}}{\overline{P_{0}P_{2}} + \overline{P_{1}P_{3}}} · \overrightarrow{P_{0}P_{2}}

より

c := \frac{4\overline{P_{1}P_{2}}}{3(\overline{P_{0}P_{2}} + \overline{P_{1}P_{3}})} \frac{1}{1 + \sqrt{\frac{1+ \frac{(\overrightarrow{P_{0}P_{2}},\overrightarrow{P_{1}P_{3}})}{\overline{P_{0}P_{2}}·\overline{P_{1}P_{3}}}}{2}}}

とおくと

\overrightarrow{P_{1}Q} = c\overrightarrow{P_{0}P_{2}}, \overrightarrow{P_{2}R} = c\overrightarrow{P_{3}P_{1}}

によって， P_{1} を始点， P_{2} を終点， Q と R の 2 点をこの順に制御点とする 3 次 Bézier 曲線となる． Q_{0}, Q_{1}, Q_{2}, Q_{3} と順に与えたとき， Q_{0} を始点， Q_{1} と Q_{2} を制御点， Q_{3} を終点とする（3 次） Bézier 曲線は

B(t) = Q_{0}(1 − t)^{3} + 3Q_{1}t(1 − t)^{2} + 3Q_{2}t^{2}(1 − t) + Q_{3}t^{3}
= (−Q_{0} + 3Q_{1} − 3Q_{2} + Q_{3})t^{3} + (3Q_{0} − 6Q_{1} + 3Q_{2})t^{2} + (−3Q_{0} + 3Q_{1})t + Q_{0}

で与えられる．なお， P_{0}, P_{1}, P_{2}, P_{3} と順に与えたとき， P_{1} を始点， P_{2} を終点とする Catmull-Rom スプライン曲線は

C(t) = (−\frac{1}{2}P_{0} + \frac{3}{2}P_{1} − \frac{3}{2}P_{2} + \frac{1}{2}P_{3})t^{3} + (P_{0} − \frac{5}{2}P_{1} + 2P_{2} + \frac{1}{2}P_{3})t^{2} + (−\frac{1}{2}P_{0} + \frac{1}{2}P_{2})t + P_{1}

である．両者の関係は

\begin{cases}Q_{0} = P_{1}, \\ Q_{1} = P_{1} + \frac{1}{6}(P_{2} − P_{0}), \\ Q_{2} = P_{2} + \frac{1}{6}(P_{3} − P_{1}), \\ Q_{3} = P_{2}. \end{cases}

よって c = \frac{1}{6} と固定したものとみなせる．

[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 は

{(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)$

[figure]

435. xyang(r,p_{0},p_{1},p_{2}|opt=t,scale=r,prec=1,ar=1,dviout=1,proc=1)

:: XY-pic/TikZ で角 ∠p_{1}p_{0}p_{2} の記号や円弧や扇形や矢印を描く

• p_{0} = [x_{0}, y_{0}], p_{1} = [x_{1}, y_{1}], p_{2} = [x_{2}, y_{2}] のときは， ∠p_{1}p_{0}p_{2} の角の記号（すなわち円弧）を半径 r の弧で描く（\overrightarrow{p_{0}p_{1}} から反時計回り）．

• p_{0} = [x_{0}, y_{0}], p_{1} = [x_{1}, y_{1}], p_{2} = ±1 のときは， p_{0} を頂点する\overrightarrow{p_{0}p_{1}} 方向とそれと直交する方向に一辺 r の直角記号を描く（p_{2} = 1 のときは反時計回り， p_{2} = −1 のときは時計回り）．

• p_{0} = [x_{0}, y_{0}], p_{1} = [x_{1}, y_{1}], p_{2} = ±2, ±3, ±4, 0 のときは， p_{0} を頂点とする矢印の先を描く． r は先端からの長さ．線分との角度は，順に 45^{∘}, 30^{∘}, 60^{∘}, 90^{∘} である．ただし， p_{2} < 0 の時は矢印の先でなくて尾を示す．また， |p_{2}| ≥ 10 のときは |p_{2}|^{∘} の角度とみなす． p_{2} = 5, 6, 7, 8 のときは，矢先が曲がっていて，開きは順に 45^{∘}, 30^{∘}, 22.5^{∘}, 15^{∘} となる． ar=1 を指定すると， p_{0} と p_{1} を結ぶ線分も描いて，矢印となる． ar=3 を指定すると，矢先は閉じた図形になり， TikZ のときは opt="fill"を指定すると，塗りつぶされた矢先になる（ar=2 では矢先のみ）． p_{0} と p_{1} を結ぶ線分も描いて，矢印となる．

• r = −1 : △p_{0}p_{1}p_{2} の内接円を描く．

• r = −2 : △p_{0}p_{1}p_{2} の外接円を描く．

• r = −3, −4, −5 : △p_{0}p_{1}p_{2} の傍接円を描く（∠p_{|r|−3} 内）．

• r = −6 : 直線 p_{1}p_{2} に接する p_{0} 中心の円を描く．

• r = −7 : 点 p_{0} から直線 p_{1}p_{2} に下ろした垂線を描く．

• r が数でなくて座標 p_{3} = [x_{3}, y_{3}] のときは， r は p_{0} と p_{3} の距離に置き換えられる．

• p_{0} = [x_{0}, y_{0}] で， p_{1} と p_{2} が数で p_{1} ≤ p_{2} ≤ p_{1} + 2π の時， p_{0} を中心に半径 r の円弧を，偏角が p_{1} から p_{2} まで Bézier 曲線を使って描く．ただし， p_{1} = p_{2} のときは円とする．円弧の場合， ar=1 を指定すると扇形を描く．

• prec=1 : 真の円弧により近くする（デフォルトでの円の中心からの距離の誤差は， 0.16% 以下であるが，それを\frac{1}{3600} ≒ 0.03% 以下とする）． prec=2, 3 に応じて，誤差は\frac{1}{41900}, \frac{1}{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 の交点 */
[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 度 */

[figure]

[figure]

[figure]

436. xyoval(p,r,q|opt=t,arg=[t_{1},t_{2},t_{3}],deg=[t_{1},t_{2},t_{3}],scale=r,ar=1,prec=1,dviout=1,
proc=1)

:: XY-pic/TikZ で p を中心として，軸の長さが r と qr の楕円またはその弧や扇形を描く • 点 p を中心に，基準軸の半径が r, それに直交する軸の半径が qr の楕円を描く • 楕円の基準軸の偏角は t_{3} で指定する. この指定がないときは t_{3} = 0 とみなされる．

• 楕円の基準軸方向から，パラメータが t_{1} と t_{2} の間の部分の弧を描く．この場合， ar=1 を指定すると扇形が描かれる． t_{1} = t_{2} または指定がないときは，楕円全体が描かれる．

p + r (\begin{matrix}cos t_{3} & sin t_{3} \\ − sin t_{3} & cos t_{3} \end{matrix}) \binom{cos t}{q sin t} (t ∈ [t_{1}, t_{2}])

• t_{1}, t_{2}, t_{3} の指定はラジアン (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);
[[-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)$

[figure]

437. xygrid([x,t_{x},u_{x},m_{x},s_{x}],[y,t_{y},u_{y},m_{y},s_{y}]|raw=r,shift=[s_{x},s_{y}])

:: （対数）方眼紙の描画

• 横 x，縦 y の方眼紙を作成する（xyproc() の引数の形で返す）． t_{x}, t_{y} は， 0 のときは通常の目盛， 1 のときは対数目盛, −1 のときは逆対数目盛とし， u_{x}, u_{y} は，単位の長さ， m_{x}, m_{y} は最小の目盛線の間隔とする．色付けなどを考慮すると TikZ を利用するのが好ましいので，以下ではそれを念頭に例を述べる（長さの単位は cm となる． dviout0(1|opt="TikZ") によってXY-pic でなくて， TikZ 対応となる）．

• t_{x}, t_{y} は直接 0 からの数字のリストとして指定してもよい（m_{x}, m_{y} は無視される）． scale() の返り値の形でもよい．

• 目盛線は，横，縦共に 3 段階で，線種はそれぞれ s_{x}, s_{y} で文字列指定する． 3 段階で変えるときは，文字列 3 つのリストで，小さい目盛線，中間の目盛線，大きい目盛線の順に指定する． 3 段階以外も可能．

• 通常の目盛のときは，単位の長さを，細分なし， 2 等分，または 5 等分，または 10 等分まで，最小間隔以上という条件で細かく取る． 10 等分のときは， 2 等分を 2 段階目の線種とする．あるいは， m_{x}, m_{y} を scale() の引数の形（リスト）で指定してもよい．

• 対数目盛のときは， 1 から 2 まで， 2 から 5 まで， 5 から 10 までに分けて（1 から 10 までの間隔が単位の長さ），それぞれ細分なし， 2 等分， 5 等分， 10 等分のいずれかで，最小間隔以上という条件で，細かく取る． 10 等分のときは， 2 等分を中間の線種とする．あるいは， m_{x}, m_{y} を scale() の引数の形（リスト）で指定してもよい．

• shift=[s_{x},s_{y}] によって描画位置の原点を移動できる（左下隅が原点）．

• たとえば，五線譜の用紙を描くには y =22.4, t_{y} =[0,0.2,0.4,0.6,0.8], u_{y} =2.5, t_{x} =[] などとすればよい．

• 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),

細分したときの最小幅（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 のソースとなる．

438. xycircuit(p,s|scale=r,opt=t,at=k,rev=1)

:: 電気回路を描く R, C, L などを使った電気回路を描く．「p=[[x_{0},y_{0}],[x_{1},y_{1}]] としたとき，この 2 点を結ぶ線分を信号線としてそこに s で示される素子を描く」ということが基本

• scale=r : 素子の大きさを r 倍する．

• s="R" : R （抵抗）．幅のデフォルトは\frac{2}{3}． TikZ では， opt="red"などが指定可能．

• s="VR" : 可変抵抗．幅のデフォルトは\frac{2}{3}．

• s="RT" : 半固定抵抗．幅のデフォルトは\frac{2}{3}．

• s="VR3" : 可変抵抗（3 端子）．幅のデフォルトは\frac{2}{3}． 3 端子目は信号線から\frac{1}{2} 幅がデフォルト． • s="RN" : 抵抗（新記号）．幅のデフォルトは\frac{2}{3}．

• s="VRN" : 可変抵抗（新記号）．幅のデフォルトは\frac{2}{3}．

• s="RNT" : 半固定抵抗（新記号）．幅のデフォルトは\frac{2}{3}．

• s="RN3" : 可変抵抗（3 端子）．幅のデフォルトは\frac{2}{3}． 3 端子目は信号線から\frac{1}{2} 幅がデフォルト． • 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" : (x_{0}, y_{0}) から (x_{1}, y_{1}) への矢印を描く． TikZ では opt="|->"などが指定可能．

• s="gap" : 交差しない線分を描く．半円の直径のデフォルトは 0.3.

• 以上において， p=[x,y] とすると， (x, y) を始点として素子を描画する．

• s="" : 2 点を結ぶ線分を描く．

• s=["str"]: このとき p=[x,y] とすると， (x, y) に文字列 str を置く． p=[[x_{1},y_{1}],[x_{2},y_{2}],…] とすると． (x_{1}, y_{1}), (x_{2}, y_{2}), … の文字列 str を置く．

• at=k : 素子を (x_{0}, y_{0}) と (x_{1}, y_{1}) を両端とする線分の k : 1 − k の内分点に置く（デフォルトは k = \frac{1}{2}）．

 • s="circle"で at=1,scale=0.1 と指定すると端子が描かれる．

• rev=1 : 可変抵抗や可変コンデンサの矢印を，回路の向きに対称なものにする．なお， [x_{0},y_{0}] と [x_{1},y_{1}] を入れ替えると， 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"));
[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"))$
439. xypoch(w,h,r_{1},r_{2}|ar=r)

:: Pochhammer の cycle を描く • w : 2 点間の距離

• h : 隣接した線の間隔

• r_{1} : 小円の半径

• r_{2} : 大円の半径

• r : 矢印の大きさ（デフォルト 0.25cm， 0 とすると描かない)

[1] os_md.xypoch(7,0.3,0.7,1);

/* 2 点は 7cm 離れ，それらをつなぐ線の間隔は 0.3cm，点中心の円の半径は 0.7cm と 1cm */

440. xyplot([[a_{1},b_{1}],[a_{2},b_{2}],. . .],[x_{0},x_{1}],[y_{0},y_{1}]|opt=t,ax=[x_{0},y_{0},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 は黒．このときの戻り値は [x_{0},x_{1}],[y_{0},y_{1}]. at=1 を指定すると可能なら軸を描く． at=2 とすると，可能ならスケールを入れる．

• [x_{0},x_{1}] や [y_{0},y_{1}] を指定しないで 0 を指定すると，データからそれらが入るように自動的に計

算する． view=v を指定したときは，四隅に少し空きを置く（画面サイスの\frac{1}{32} ずつ）．

このとき raw=1 を指定すると， [[x_{0},x_{1}],[y_{0},y_{1}]] が返される．

• 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]]
441. xyaxis([x_{0},y_{0},s,t,u],[x_{1},x_{2}],[y_{1},y_{2}]|scale=r,opt=t,axopt=[h,w,o,z],view=1)

:: 座標軸の描画 • xygraph() での座標軸描画に準じる．

• (x_{0}, y_{0}) : 座標軸の原点の座標

• [x_{1},x_{2}],[y_{1},y_{2}] : 窓の x 座標， y 座標の範囲

• s, t : x 軸， y 軸の目盛りの間隔

• view=1 : glib のキャンバスに描く． s, t が指定されて 0 でなければ目盛りも振る．

• view=6 : 上と同じだが，座標の目盛りの数字を振る

• view=2 : 上と同じだが， x 座標の目盛りの数字のみ振る

• view=4 : 上と同じだが， y 座標の目盛りの数字のみ振る

442. xygraph(f,n,[t_{1}, t_{2}],[x_{1},x_{2}],[y_{1}, y_{2}]|opt=t,rev=1,ax=[x_{0},y_{0},s,t,u],axopt=[h,w,o,z],
scale=r,ratio=c,raw=1,org=[x_{0},y_{0}],pt=[p_{1},p_{2},...],verb=1,para=1,prec=v,shift=[u,v],
Acc=1,dviout=t,proc=p)

:: 変域の n 等分点での値で関数のグラフを描く（t_{1} ≤ x ≤ t_{2}， (x_{1}, y_{1})–(x_{2}, y_{2}) は表示窓の範囲） • 点を繋ぐのは xylines() を curve=1 のオプションで用いる．

• 変数は x で，さらに x_{1} < x_{2}， y_{1} < y_{2} でなければならない．

• f は [f_{1},f_{2}] の形のパラメータ表示でもよい．

• para=1 : f が [f_{1},f_{2}] のパラメータ表示であることを明示する．

• f や前項の f_{1}, f_{2} は有理函数や sin(x) などの初等関数に限らず， mydeval() が解釈できる函数ならばよい．よってユーザが定義した函数や， Γ 函数などのように pari() 経由でサポートされた函数でもよい．

• f_{1} が有理式で f_{2} がリスト形式の函数のときは， para=1 としてパラメータ表示であることを明示する必要がある．

• 変数を x でなくて t とするときは， [t_{1},t_{2}] でなくて [t,t_{1},t_{2}] と指定する．

• x_{1} = t_{1}, x_{2} = t_{2} のときは，第 4 引数 [x_{1},x_{2}] を 0 と指定してもよい．

• rev=1 : x = f(y) のグラフとみなす．

• (x_{1}, y_{1}) と (x_{2}, y_{2}) で定まる窓から外れる点は除く．

• n = 0 と指定したときは， n = 32 とみなす．

• n < 0 のときは， |n| 等分した区間の両側の 1 区間外に制御点をとる．

• n 等分点でなくて点を直接指定するときは， [t_{1},t_{2}] でなくて [t_{1},t_{2}, …, t_{m}] のように指定する（なお， t_{1}, …, t_{m} は単調増加な実数列．さらに最初を実数でなく，変数の指定としてもよい）． n が負の時は，最初と最後の点 t_{1}, t_{m} は制御点とする．

• prec=[v_{1},v_{2},v_{3}] : 折れ線で繋ぐと角度が v_{2}^{∘} 以上の分割点の両側を 2 つに細分することを v_{1} ス

テップ行い，さらに v_{3} > 0 のとき，窓の対角線の長さの v_{3} 分の 1 以上の跳びを不連続点とみなす．

– v_{2} = 1 のときは v_{2} = 30 と解釈され， 1 < v_{2} < 10 のときは v_{2} = 10 と解釈され， v_{2} > 120 のときは v_{2} = 120 と解釈される．

– v_{3} = 0 のときは，不連続点はないものと解釈する．

– v_{3} = 1 のときは v_{3} = 16 と解釈され， v_{3} > 512 のときは v_{3} = 512 と解釈される．

   – prec=[v_{1},v_{2}] は， prec=[v_{1},v_{2},0] と解釈される．
   – prec=v_{1} は, v_{1} = 0 のとき prec=[4,30,0] と, v_{1} > 0 のとき prec=[v_{1},30,0] と， v_{1} < 0

のとき prec=[|v_{1}|,30,16] と解釈される．

• opt=t : 線種の指定など（xylines() に渡される）．

• opt=0: 曲線を xybezier() の引数のデータ形式で返す．

• ratio=c : Bézier 曲線を使うときのパラメータ（xylines() に渡される）．

• ax=[x_{0},y_{0}] : (x_{0}, y_{0}) を原点として x 軸と y 軸を窓内に描く．窓内に現れない軸は描かないので，それを利用して一方の軸のみの描画ができる．

• ax=[x_{0},y_{0},s,t] : s が正数なら， x 軸に原点から s 毎に目盛をつける．目盛をつける位置を指定するときは s = [s_{1}, s_{2}, …] と原点からの x 座標の位置を書く． s_{j} =[s_{j,0},s_{j,1}] となっていると s_{j,0} の位置に目盛をつけて，そこに s_{j,1} を書く． t で同様に y 軸の目盛の指定ができる • ax=[x_{0},y_{0},s,t,u] : s, t が数字で u が 1 と 2 とすると，目盛が ax=[x_{0},y_{0},s,t] に従ってつけら

れ， u に従ってそこに数字が書かれる． u = 0 のとき k 番目の位置の x 軸には ks + x_{0} が y 軸には kt + y_{0} が書かれ， 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 =[h_{0},h_{1}] または h =[h_{0},h_{1},h_{2}] のとき x 軸の目盛の高さを h_{0} から h_{1} までとする（XY-pic/TikZ の mm/cm 単位）． h_{2} は文字列で，目盛位置に文字などを置く位置指定（デフォルトは下 "+!U"/"below"）． h が 0 でない数字なら， h_{0} = 0, h_{1} = 1 と解釈される（h = 0 のときはデフォルトのまま）．

– w =[w_{0},w_{1}] または w =[w_{0},w_{1},w_{2}] のとき y 軸の目盛の幅を w_{0} から w_{1} までとする（XY-pic/TikZ の mm/cm 単位）． w_{3} は文字列で，目盛位置に文字などを置く位置指定（デフォルトは左 "+!R"/"left"）． w が数字なら， w_{0} = 0, w_{1} = 1 と解釈される（w = 0 のときはデフォルトのまま）．

– o が文字列のとき， x 軸の原点に文字を置く位置指定（デフォルトは左下 "+!UR"/"below

    left"）．

o が文字列でなければ無視される．

– z : x 軸と y 軸の線種指定文字列（デフォルトは実線で XY-pic のときは "@-"）．

– z または z と o を省略可能．

• pt=[p_{1},p_{2},...] : （複数の）点を明示するまたは線を描く．仕様は xy2graph() の同様なオプションに習う．

• scale=r : XY-pic/TikZ の座標に直すときに r 倍する．

• scale=[r_{1},r_{2}] : XY-pic/TikZ の座標に直すときに x 座標を r_{1} 倍， y 座標を r_{2} 倍する．

• org=[x_{0},y_{0}] : XY-pic/TikZ の座標に直すときに (x_{0}, y_{0}) をXY-pic/TikZ の原点に対応させる．上の両者が指定されたとき，座標 (x, y) は XY-pic/TikZ の座標 (r_{1}(x − x_{0}), r_{2}(y − y_{0})) に変換される．

• raw=1 : 通過点のリストを返す (他のオプションは無視される)．これは xylines() のデータとなり，また ptaffine() でアフィン変換が計算できる．なお，範囲外の点は 0 というデータに変換される．

• f =[0,0] のときはグラフを描かない．座標軸のみを描くときに用いる．

• err=c : 函数の定義域を外れるエラーが生じるときは， c = 1, c = −1 などとしてこのオプションを指定すると，エラーが解消される可能性がある（c は絶対値があまり大きくない実数）．

• verb=1 : グラフ上の通過点を •，制御点を × で表示する．

• verb=[t_{1},t_{2}] , verb=[t_{1}]: グラフ上の通過点や制御点の描き方を指定する（cf. xylines()）．

• 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" などに変更する．

1 0 −1 2 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,
    ax=[0,0],opt="~*={.}")$

........._{.........}_{....} ⋮_{. . ... . .}_{. . . . . . . . .}_{. . . . . . . . .} . . .......^{.......}^{.....}^{........}^{.........}^{.........}^{........}^{.....} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{aligned}& & . \\ & & . \\ & & . \\ & & . \\ & & . \\ & & . \\ & & . \\ & . \\ . \end{aligned} \begin{aligned}& & . \\ & . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{aligned} \begin{aligned}& & . \\ & & . \\ & & . \\ & & . \\ & & . \\ & . \\ . \end{aligned}_{. ..}_{....}_{.........}.........^{.........}^{.........}^{....}^{.. .} \begin{aligned}& & . \\ & . \\ . \\ . \\ . \\ . \\ . \end{aligned} \begin{aligned}& & . \\ & & . \\ & & . \\ & & . \\ & & . \\ & & . \\ & & . \\ & . \\ . \end{aligned} \begin{aligned}& & . \\ & . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{aligned} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}_{.....}_{........}_{.........}_{.........}_{........}_{.....}.......^{....... . .}^{. . . . . . . . .}^{. . . . . . . . .}^{. . ... . .} ⋮^{....}^{.........}^{.........}  \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}_{............................................................}_{......................................................................}_{.................................................................................................................} .................................................................^{.................................................................}^{.................................................................}^{.................................................................}^{.................................................................}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}_{...........................}_{............................................}_{.................................................................}............................................................................................................................^{............................................................................................................................}^{.................................................................}^{............................................}^{...........................} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}_{.................................................................}_{.................................................................}_{.................................................................}.................................................................^{.................................................................}^{.................................................................................................................}^{......................................................................}^{............................................................} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix} \begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}\begin{matrix}. \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \\ . \end{matrix}

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 Bézier 曲線を繋げた近似から，不連続点の近くで自動的に細分して 63 本の cubic Bé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] は

となり， prec=0 のとき [15] は

となり， prec=-4 または prec=[4,0,1] のとき [16] は以下のようになる．

この例では，最初 32 本の cubic Bé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])$

とすると |ζ(\frac{1}{2} + x\sqrt{−1})| (0 ≤ x ≤ 60) のグラフが得られる．

60 50 40 30 20 10 0 4 3 2 1

この例では， [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])$

その他の例を挙げる．

[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))$
443. xy2graph(f,n,[x_{1},x_{2}],[y_{1}, y_{2}],[h_{1},h_{2}],α,β|opt=t,scale=r,view=h,raw=1,trans=1,
ax=[z_{1},z_{2},t],dev=m,acc=k,org=[x_{0},y_{0},z_{0}],pt=[p_{1},p_{2},...],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) (x_{1} ≤ x ≤ x_{2}, y_{1} ≤ y ≤ y_{2}) の 3D グラフを描く．なお，投影した高さ方向の座標（y 座標）が [h_{1}, h_{2}] に入る範囲のみ描く．より具体的には 3 次元の点 (x, y, z) は以下のように平面の点に投影される．

(x, y, z) ↦ (−x sin α^{∘} + y cos α^{∘}, z cos β^{∘} − x cos α^{∘} sin β^{∘} − y sin α^{∘} sin β^{∘})

α = 0 のときは α = 60, β = 0 のときは β = 15 と解釈される．

α は 0 であるか，または 90 の整数倍とは 5 以上離れていることが必要．

通常は h_{1} を十分小さく， h_{2} を十分大きく取っておけばよい（指定した範囲の曲面全体の表示）． • 曲面上で x 座標が定数，あるいは y 座標が定数で定まる曲線を（曲面で隠れる部分，すなわち隠線

を消して）描くことで曲面を表す．定数は座標の n 等分点と定める．

n < 0 のときも |n| 等分点をとるが，その一つ外側を制御点にとる．

• f は有理函数や sin(x) などの初等関数に限らず， mydeval() が解釈できる函数ならばよい．ユーザが定義した函数でもよい.

 • cpx=1,2,3 を指定するか f に @i が含まれていれば, mydeval() でなくて myeval() が使われる．

• 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=[r_{1},r_{2}] : 元の曲面の z 座標を\frac{r_{2}}{r_{1}} 倍したものを平面に投影したあと，表示するため XY-pic/TikZ の座標に直すときに座標の単位を r_{1} 倍する． • scale=[r_{1},r_{2},r_{3}] : 元の曲面の z 座標を\frac{r_{2}}{r_{1}} 倍， y 座標を\frac{r_{3}}{r_{1}} したものを平面に投影したあと，表

示するため XY-pic/TikZ の座標に直すときに座標の単位を r_{1} 倍する．

• org=[x_{0},y_{0},z_{0}] : 元の座標の (x_{0}, y_{0}, z_{0}) を 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=[m_{1}, m_{2}] とすると， m_{2} は出力される x 座標のメッシュの細かさ， m_{1} は曲線間にとるメッシュの細かさ，と別に指定することができる．

• |n| × m を増やすと処理時間が増える．特に f が多項式や有理函数でなくて三角関数や指数関数，対数関数，べき函数などを含むときは注意．なお処理時間は，ほぼ |n|^{2} × m^{2} に比例．

• acc=k : 描く曲線の等分点の個数を約 k 倍にする（k は実数．曲線の本数は不変）． k = 2 なら n を 2 倍にして dev を半分にした場合の曲線を一本おきに描くことにほぼ等しい（結果のファイル・サイズは， n^{2} × k にほぼ比例）．

• err=c : 有理函数の分母が 0 になるなどの，函数の定義域を外れるエラーが生じるときは， c = 1, c = −1 などとしてこのオプションを指定すると，エラーが解消される可能性が大きい（c は絶対値があまり大きくない実数）．

• prec=v : xygraph() の同様のパラメータと同じ．

• ax=[z_{1},z_{2}] : x, y, z の座標が (x_{2}, y_{2}, z_{1}), (x_{1}, y_{1}, z_{2}) を対角線の頂点とする直方体の枠を書く，

• ax=[z_{1},z_{2},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\sqrt{−1}, 3)

– cpx=3 : (1, 2, 3)

• opt=u : 曲面内の曲線を描くときのオプション文字列を指定する．表側と裏側で変更するときは opt=[u_{1},u_{2}] と，表側，裏側の順に指定する． TikZ のときは，さらに直方体の枠を描くときのオプション文字列が指定できる．たとえば TikZ で opt=["black","red","blue"] とすれば，表側を黒，裏側を赤，枠を青で描く．

• title=s : 画面表示するとき，函数名が s で表示される（s は TEX の数式モードでの文字列）．函数がリスト形式のときの函数名表示に役立つ．

• pt=[p_{1},p_{2},...] : （複数の）点を明示する，あるいは線を引く． – p_{i}=[x_{i},y_{i},z_{i}] とすると (x_{i}, y_{i}, z_{i}) を • で明示する，

– p_{i}=[[x_{i},y_{i},z_{i}],s_{i}] とすると， • （すなわち\bullet）でなくて s_{1} で明示される（s_{i} は数式モードの文字列で， \ は \\ で表す）．

– p_{i}=[[x_{i},y_{i},z_{i}],s_{i},t_{i}] とすると， • でなくて s_{i} で明示され（s_{i} は文字列）， XY-pic のときは，そのあとに文字列 t_{i} を置く（s_{i} が文字列でないときは • のまま）． s_{i} が不要なときは， s_{i} = "" とする． TikZ のときは， t_{i} はラベル付け文字で， s_{i} は s_{i} = [s_{i,0}, s_{i,2}] というリストでよい．後に置く文字があるときは， t_{i} の後に t_{i},u_{i} と続ける． t_{i}=1 は "_" というラベルを表し，その後で座標の代わり 1 または"_" で参照できる． – 点が一つの時は， pt=p_{1} としてよい．

– 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" をつける．

– p_{i}=[[x_{i},y_{i},z_{i}],[x′_{i},y′_{i},z′_{i}]] とすると， 2 点 (x_{i}, y_{i}, z_{i}) と (x′_{i}, y′_{i}, z′_{i}) を線で結ぶ．

– p_{i}=[[x_{i},y_{i},z_{i}],[x′_{i},y′_{i},z′_{i}],t_{i}] とすると， 2 点 (x_{i}, y_{i}, z_{i}) と (x′_{i}, y′_{i}, z′_{i}) を結ぶが ∗ t_{i} = 0, 1 : 実線で結ぶ

∗ t_{i} = 2 : 点線で結ぶ

∗ t_{i} = −1 : 曲面のあるところは除いて実線で結ぶ

∗ t_{i} = −2 : 曲面のあるところは除いて点線で結ぶさらに t_{i} の後ろにオプション文字列 u_{i} を書いて p_{i}=[[x_{i},y_{i},z_{i}],[x′_{i},y′_{i},z′_{i}],t_{i},u_{i}] とし， TikZ では色や線の太さ指定などの指定が可能．

• proc=1 : execdraw() の描画実行形式を返す．

• proc=2 : 上と同様であるが， Windows サイズの情報は含めない．

• dviout=1 : 画面表示する．

• dviout=2 : ディスプレイスタイルで函数式も含めて画面表示する．

• dviout=3 : さらに視点の角度と，もとの曲面の高さや y 座標のスケールを変えたとき，その倍率を表示する．

• k が −1, −2, −3 の時は， dviout=|k| に対応する TEX のコードがリスト形式で 出力される．リストの最後の成分は xyproc() によってグラフの TEX のソースとなる．その前の成分は函数式などを表す 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 = −r_{1}(x − x_{0}) sin α^{∘} + r_{2}(y − y_{0}) cos α^{∘},
Y = r_{3}(z − z_{0}) cos β^{∘} − r_{1}(x − x_{0}) cos α^{∘} sin β^{∘} − r_{2}(y − y_{0}) sin α^{∘} sin β^{∘}.

ただし，これはオプションなどの指定が

– xy2graph の第 6, 7 引数： (α, β) (α = 0 のときは α = 60, β = 0 のときは 15 と解釈される)

– scale=[r_{1},r_{3},r_{2}] デフォルトは [1,1,1] となり, r_{2} を指定しないときは r_{2} = r_{1} で， r_{3} を指定しないときは r_{3} = r_{1} と解釈される．

– Org=[x_{0},y_{0},z_{0}] デフォルトは [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)$

[figure: z = x^{2} − y^{2} (−1 ≤ x ≤ 1, −1 ≤ y ≤ 1); angle (60^{∘}, 15^{∘}); (1,1,−1); (−1,−1,1); (−1,1,−1); (1,−1,−1)] z = −x^{3} − y^{3} (−1 ≤ x ≤ 1, −1 ≤ y ≤ 1)

上は XY-pic のときで， TikZ を用いる場合の scale の値は{1 \atop 10} 倍にする．

444. xy2curve([f_{1}, f_{2}, f_{3}],n,[t_{1},t_{2}],[y_{1},y_{2}],[z_{1}, z_{2}],α,β|scale=r,gap=g,opt=s,eq=q,raw=w,
dviout=d)

:: 空間曲線の隠線処理つき描画

• (f_{1}(x), f_{2}(x), f_{3}(x)) (x ∈ [t_{1}, t_{2}]) で定義される空間曲線を x 軸の正方向を y 軸の正方向に α 度だけ回転した無限遠方から， β 度 (−90 < β < 90）見下ろす方向に回転して， yz 平面に射影した曲線を描く．ただし変数が x でなくて t のときは， [t_{1},t_{2}] の代わりに [t,t_{1},t_{2}] と書く．描画範囲は y 座標， z 座標が区間 [y_{1}, y_{2}]， [z_{1}, z_{2}] の範囲（回転や以下のスケール変換後）．

• gap=g : 隠線消去の幅を g mm を基準とする． g = 0 のときは，隠線消去は行わない．デフォルトは g = 0.7.

• gap=[g,m] : 隠線消去の幅の最大値を m × g mm とする（デフォルトは m = 3）．

• scale=r : 各座標を r 倍する．

• scale=[r_{1},r_{2}] : x 座標を r_{1} 倍， y 座標と z 座標を r_{2} 倍する．

• scale=[r_{1},r_{2},r_{3}] : x 座標を r_{1} 倍， y 座標を r_{2} 倍， z 座標を r_{3} 倍する．

• α が 3 行 3 列の行列の場合は，これによる線形変換に置き換える（回転やスケール変換は無視）． • opt=s : 線種などの指定文字列（xygraph() のときと同様） . ただし gap=0 を指定しないときは，

xybezier() に渡すパラメータの形式に拡張される．

• eq=q : 空間内で q mm 以下の距離の 2 点は同じ点とみなす（デフォルトは q = 0.01）．

• dviout=1 : 画面表示を行う．

• raw=1 : TEX のソースを返す． • raw=2 : 隠線処理後の区分 Bézier 曲線を与える座標のリストのリストを返す．

• raw=3 : 隠線処理前の区分 Bézier 曲線を与える座標のリストのリストと，交点の情報を返す．

• raw=4 : 隠線処理前の区分 Bé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);
445. execdraw(ℓ,t|shift=[u,v],ext=[a,b],cl=1)

:: 描画実行形式 ℓ を出力形態 t に従って実行する ℓ や t はリストであるが，成分が一つの時は成分のみを指定してもよい． t = [t_{0}, t_{1}, t_{2}] は， t_{0} により出力先を， t_{1} により描画実行形式と出力先との座標との対応を， t_{2} により描画実行形式の原点の移動を指定する．

• t_{2} を指定しないときは， t = [t_{0}, t_{1}] のように，また t_{1} と t_{2} を共に指定しないときは， t = [t_{0}] のように略してよい．

• t_{0} が数で t_{1}, t_{2} を指定しないときは， t = t_{0} としてよい．

• cl=1 : 表示画面をクリアーしてから描画する．出力先を指定する t_{0} は

• 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] と解釈される（すなわち t_{1} = x）．

   – execdraw([],0) は，描画画面を新規に開く．

– shift=[u,v] : 右方向に u, 上方向に v だけ pixel 単位で移動する．

– ext=[a,b] : 左側から a, 右側から b だけ pixel 単位で縮めて描く．

– ext や shift は，キャンバスに応じて描画サイズが変更されても文字列の大きさは不変であることに対処するのが主目的のオプションである．

– ℓ 中の Window の x 座標と y 座標の範囲指定が同一で，横幅 t_{1} と shift と ext の設定が同じであれば（t_{2} は設定していないか同じとする），同一キャンバスに同じ座標系で上書き表示される．

– t = [t_{0}, t_{1}, t_{2}, ℓ′] により，別の描画実行形式 ℓ′ のものを用いることができる（t_{1} はキャンバスの横幅とする. それが t_{0} で指定される場合は t_{1} = 0 としてもよい）．なお， ℓ′ は，キャンバスサイズとは独立した情報である．

– 戻り値は [0,id,index]，または [0,id,index,width, height]．

これは，同じキャンバスへの描画のときの t_{0} として用いることができる．

t_{1} = 0, t_{2} = −1 のときは，さらに 2 つの 0 と変換情報とを付加して組にしたリストが戻される．最後（4 番目）の成分は上の ℓ′ として用いることができる．また戻り値は，そのまま t として用いることにより，同じ座標でキャンバス上に他の描画実行形式の重ね描きができる．

たとえば t は以下のようになる

– 0 : Canvas で設定されたサイズのキャンバスを新規に開いて，それに合わせた横幅で表示．

     [[0,[300,300]],300] や [[0,[300]]] と同じ.

– [[0,[300,400]],280] : 300 × 400 pixel のキャンバスを開き，横幅 280 pixel で表示．すな

わち， t_{0} = [0,[300,300]]， t_{1} = 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,[x_{0},x_{1}],[y_{0},y_{1}],k] : 窓のサイズを再定義した ℓ を返す．

t=[-1,[x_{0},x_{1}],[y_{0},y_{1}],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 （Bézier 曲線描画）のもののみを抜き出した描画実行形式を得ることができる．

Risa/Asir の描画キャンバスでの表示の場合

• t_{1} = 0 : ℓ の描画範囲の横幅と左上端の位置をキャンバスに合わせる．さらに微調整するには，キャンバスの縦横比率を変更したり，オプションパラメータの ext と shift を用いるとよい．

このとき

– t_{2} = 1 : 描画範囲の箱サイズの他，自動的に得た ext と shift の値が表示される（オプションパラメータは加味されない）．

– t_{2} = −1 : 上の情報が戻り値に付加されたリストを返す（オプションパラメータも加味される）．この戻り値が R のとき， execdraw(ℓ̃,R) とすると，同じキャンバスに同じ座標で, ℓ̃の重

ね書きができる．また， execdraw(ℓ,[t_{0},0,0,R[3]]) や execdraw(ℓ,[t_{0},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] は t_{0} に対応する部分で，順に， 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 ずつ余裕を持たせるので，座標の単位は描画の際に\frac{500−10−10}{1−(−1.2)} 倍される．また，描画実行形式の箱の左上端が，キャンバスの左上端から右に (10 + 5) pixel, 下に 15 pixel の位置になる．

なお，画実行形式の箱の外に描画要素があっても，それがキャンバス内に入れば描画される． • キャンバスへの描画は，まず描画実行形式から描画範囲の箱を読み取ってそれによりキャンバスと

の座標対応を定め，次に描画実行種別番号 2 の文字列表示を先頭から順に実行し，最後に残りを先頭から順に実行する．これはキャンバスにおける文字列表示において，文字でなくて文字の箱が上書きされることに対応するため．

• t_{1} > 0 のときは Windows の横幅が t_{1} pixel になるようにスケール変換される（t_{1} = 1 は設定に従う）．

• t_{1} がリストや行列の時は，以下のキャンバス表示でない場合と同じ．

Risa/Asir の描画キャンバス以外の場合は， t_{1} はスケール変換を表す（TEX 利用などの場合に有益）． • t_{1} が 2 × 2 の行列の時，座標を t_{1} によって線型変換する．

• t_{1} = [t_{10}, t_{11}] とすると x 座標が t_{10} 倍， y 座標が t_{11} 倍される（負の値も可能）．

t_{2} = [x, y] は，座標 (x, y) を原点に移動する平行移動． t_{1} によるスケール変換の前に行う． Risa/Asir の描画キャンバスでは無効．

以下，描画実行形式 ℓ について説明する．

• ℓ=[ℓ_{1},ℓ_{2},...]， ℓ_{j}=[f_{j},...] は， execproc() の形式に従う．ただし， f_{j} が整数の ℓ_{j} （描画実行

識別番号）は次のような画像描画の特別形式である．

– [0,[x_{0},x_{1}],[y_{0},y_{1}],k] : 窓の x 座標と y 座標の範囲. 座標の 1 が k cm に対応する． k が省略されたり, k = 0 の場合は， k = 1 と解釈される． ℓ にこの成分が複数あるときは，最初のものが有効． ℓ の初めの方に書かれるのが望ましい．

– [0,[x_{0},x_{1}],[y_{0},y_{1}],k,[a,b],[u,v]] : 上の拡張としてこの形式がある．これは Risa/Asir での表示の際のみ意味を持ち，デフォルトで ext=[a,b], shift=[u,v] というオプションが設定される．

– [1,p_{j},ℓ_{j1},ℓ_{j2},…] : Bézier 曲線描画， p_{j} は xybezier() のオプション． ℓ_{jν} はその引数．すなわち xybezier(ℓ_{jν}|option list=p_{j}) (i = 1, 2, …) に対応する描画を意味する．あるいは， ℓ_{jν} は lbezier() で変換されたデータでもよい．

– [2,p_{j},[x_{j},y_{j}],[s_{j}],t_{j}] : 文字列描画函数 xyput([x_{j},y_{j},s_{j}]) に対応． t_{j} は Risa/Asir のキャンバス表示での代替文字列（設定しなくてもよい）． s_{j} が文字列の時は， [2,p_{j},[x_{j},y_{j}],s_{j},t_{j}] としてもよい．

– [3,p_{j},[x_{j1},y_{j1}],[x_{j2},y_{j2}],…] : 線分描画函数 xyarrow([x_{j1},y_{j1}],[x_{j2},y_{j2}]) に対応．

– [4,p_{j},[x_{j1},y_{j1}],[x_{j2},y_{j2}],…] : 線分描画函数 xyline([x_{j1},y_{j1}],[x_{j2},y_{j2}]) に対応．

– [5,p_{j},s_{j}] : TEX の文字列描画の dviout(s_{j}) に対応．

– [-1,...] : この項は無視される（コメントなど）．

– [-2,s] : この項の s は文字列で， TEX のソースには，先頭に % を付加してコメントとして

記され，そのあと改行される．

• p_{j} はオプションリストに対応する（f_{j} が函数子の場合は， ℓ_{j} の 3 番目の成分にあたる）．

• 複数の描画実行形式は append()，または m2l( |list=1) によって一つにまとめることが出来る（グラフの重ね合わせに対応）．

• ptaffine(m,ℓ|proc=1,shift=w,…) で affine 変換（平行移動と線形変換）ができる．

• [1,p_{j},ℓ_{j1},ℓ_{j2},…] における ℓ_{jν} はリストで, 標準の形の場合，各成分は座標（すなわち実数の 2

つの組のリスト）または，区切り記号の数字の 0, 1, −1 からなり，複数の Bézier 曲線を表わす．

一つの Bézier 曲線は始点，いくつかの制御点，終点とが連続して並んで定義されている． n + 1 個並んでいれば， n 次の Bézier 曲線となる． PDF 化などから 3 次までの Bézier 曲線が望ましい．なお， 1 次の Bézier 曲線は制御点がなく，線分を表す．

0 は Bézier 曲線の区切りで， 1 は区切った後に直前の終点の座標を次の Bézier 曲線の始点とみなす（座標を挿入する）ことを意味する． 1 で区切られていると連続曲線となるが， −1 は連続曲線の先頭を終点として閉曲線とすることを意味する．たとえば

        [[x_{1},y_{1}],[x_{2},y_{2}],1,[x_{3},y_{3}],1,-1]

は (x_{1}, y_{1}), (x_{2}, y_{2}), (x_{3}, y_{3}) を頂点とする三角形を意味する．

これが標準の形で， TEX で TikZ のソースを作成するときは，一つの ℓ_{jν} が一つの \draw 文に変換される．

一方， ℓ_{jν} は一つの Bézier 曲線を表す座標のリストを成分とするリストの形のものも許される．この場合は，区切り記号の数字は存在しない． TEX で TikZ のソースを作成する場合は，一つの Bézier 曲線毎に \draw 文が生成される．上の三角形は，次のように表せる．

          [[[x_{1},y_{1}],[x_{2},y_{2}]],[[x_{2},y_{2}],[x_{3},y_{3}]],[[x_{3},y_{3}],[x_{1},y_{1}]]]

ℓ_{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 のソースを出力する．

[0] os_md.dviout0([0,5,6])$                                  /* TikZ 形式に  */
[1] F1=[sin(2*x),sin(3*x)]$
[2] W=[-1.2,1,2]$
[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 表の作成

446. 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],
[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 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
3 2 1
5 2 4 3 1
7 3 2 6 4 5 1
11 2 4 8 5 10 9 7 3 6 1
13 2 4 8 3 6 12 11 9 5 10 7 1
17 3 9 10 13 5 15 11 16 14 8 7 4 12 2 6 1
19 2 4 8 16 13 7 14 9 18 17 15 11 3 6 12 5 10 1
23 5 2 10 4 20 8 17 16 11 9 22 18 21 13 19 3 15 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)$

Table of k satisfying r^{k} ≡ a (mod p)

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
23 5 2 16 1 19 9 14 7 15
29 2 1 5 22 12 25 18 21 9 20
31 3 24 1 20 28 23 11 7 4 27 9
37 2 1 26 23 32 30 11 7 35 15 21 9
41 6 26 15 22 39 3 31 33 9 36 7 28 32
43 3 27 1 25 35 30 32 38 19 16 41 34 7 6
p/a r 2 3 5 7 11 13 17 19 23 29 31 37 41

次に，多くのリストをたたんで表示することを考える． 70 個の素数と原始根の組を表示する例を示そう．

[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 と ζ の繰り返しを付加している．

\begin{matrix}p & ζ & p & ζ & p & ζ & p & ζ & p & ζ & p & ζ & p & ζ & p & ζ & p & ζ & p & ζ \\ 3 & 2 & 23 & 5 & 53 & 2 & 83 & 2 & 113 & 3 & 157 & 5 & 193 & 5 & 233 & 3 & 271 & 6 & 313 & 10 \\ 5 & 2 & 29 & 2 & 59 & 2 & 89 & 3 & 127 & 3 & 163 & 2 & 197 & 2 & 239 & 7 & 277 & 5 & 317 & 2 \\ 7 & 3 & 31 & 3 & 61 & 2 & 97 & 5 & 131 & 2 & 167 & 5 & 199 & 3 & 241 & 7 & 281 & 3 & 331 & 3 \\ 11 & 2 & 37 & 2 & 67 & 2 & 101 & 2 & 137 & 3 & 173 & 2 & 211 & 2 & 251 & 6 & 283 & 3 & 337 & 10 \\ 13 & 2 & 41 & 6 & 71 & 7 & 103 & 5 & 139 & 2 & 179 & 2 & 223 & 3 & 257 & 3 & 293 & 2 & 347 & 2 \\ 17 & 3 & 43 & 3 & 73 & 5 & 107 & 2 & 149 & 2 & 181 & 2 & 227 & 2 & 263 & 5 & 307 & 5 & 349 & 2 \\ 19 & 2 & 47 & 5 & 79 & 3 & 109 & 6 & 151 & 6 & 191 & 19 & 229 & 6 & 269 & 2 & 311 & 17 & 353 & 3 \end{matrix}

[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  5  7 11 13 17 19 23 29 31 37 41 43 47 53 59
2  2  3  2  2  3  2  5  2  3  2  6  3  5  2  2
61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137
2 2 7 5 3 2 3 5 2 5 2 6 3 3 2 3
139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227
2 2 6 5 2 5 2 2 2 19 5 2 3 2 3 2
229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313
6 3 7 7 6 3 5 2 6 5 3 3 2 5 17 10
317 331 337 347 349 353
2  3 10  2  2  3

3.2.12.2 表や行列の作成

• 表とは， 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(@@);
 [[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 つの列の入れ替えは， [[m_{1},m_{2}]] で指定します．たとえば， 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$
[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="");
 [ 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 函数値の数表

447. ntable(f,[a,b],n|dif=1,str=[k_{1},k_{2},. . .],mult=m,title=t,top=[t_{1},. . .],TeX=1)

:: 区間 [a, b] を n 等分，または n=[n_{1},n_{2}] 等分した点での x 変数の函数 f の函数値の数表を作る n が数字のとき

• f は sin(x*@pi/180) のような通常の関数の他，リスト形式函数でもよい．

• dif=1 を指定すると，次の函数値との差の絶対値も表に加える．

• オプション str を指定すると，文字列の表となる． k_{1} は変数の小数点以下の桁数． k_{2} は値の小数点以下の桁数． k_{3} は dif=1 で加わった値の差の桁数に対応する． k_{3} の指定がないときは， k_{2} と等しいとみなされる．

• mult=m を指定すると，分割して横に m 列並べた TEX 形式の表に変換される．このとき – title=t を指定すると，表にタイトル t がつく.

– top=[t_{1},…] を指定すると，それが表の１行目に入る． n が数字のリスト [n_{1},n_{2}] のとき, 区間 [a,b] を n_{1} 等分した小区間 [a_{i},b_{i}] をさらに n_{2} 等分した

点での函数値の表を作成する．このとき

• TeX=1 またはオプション str を指定すると，表の TEX ソースが出力される． k_{1} は変数の小数点以下の桁数． k_{2} は値の小数点以下の桁数． k_{3} は dif=1 で加わった値の差の桁数に対応する． k_{3} の指定がないときは， k_{2} と等しいとみなされる.

さらにこのとき，以下のオプションが指定可能 – 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=[t_{1},…,t_{m}] を指定すると，それが表の１行目に入る． m は， n_{2}, n_{2} + 1, n_{2} + 2, n_{2} + 3 のいずれか．

– title=s : タイトルを文字列で指定． 2 番目の引数が [a,b] でなくて， [[a_{1},b_{1}],[a_{2},b_{2}]] のときは， 2 変数函数 f(x, y) の数値表にな

る．各行は x の値が [a_{1},,b_{1}] を n_{1} 等分した値を取り，そのときの y の値は [a_{2},b_{2}] の n_{2} 等分した値を取ったとき 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 列目の後と最後 */

4 桁常用対数表

0 1 2 3 4 5 6 7 8 9
1.0 .0000 .0043 .0086 .0128 .0170 .0212 .0253 .0294 .0334 .0374
1.1 .0414 .0453 .0492 .0531 .0569 .0607 .0645 .0682 .0719 .0755
1.2 .0792 .0828 .0864 .0899 .0934 .0969 .1004 .1038 .1072 .1106
1.3 .1139 .1173 .1206 .1239 .1271 .1303 .1335 .1367 .1399 .1430
1.4 .1461 .1492 .1523 .1553 .1584 .1614 .1644 .1673 .1703 .1732
1.5 .1761 .1790 .1818 .1847 .1875 .1903 .1931 .1959 .1987 .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 3 3 3 3 3 4 4 4 4 4 4 4 4 4
2 6 6 6 7 7 7 7 7 8 8 8 8 8 9
3 9 9 10 10 10 11 11 11 11 12 12 12 13 13
4 12 12 13 13 14 14 14 15 15 16 16 16 17 17
5 15 16 16 17 17 18 18 19 19 20 20 21 21 22
6 18 19 19 20 20 21 22 22 23 23 24 25 25 26
7 21 22 22 23 24 25 25 26 27 27 28 29 29 30
8 24 25 26 26 27 28 29 30 30 31 32 33 34 34
9 27 28 29 30 31 32 32 33 34 35 36 37 38 39
10 30 31 32 33 34 35 36 37 38 39 40 41 42 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);

0  1  2  3  4  5  6  7  8  9
1.0 .0000 .0043 .0086 .0128 .0170 .0212 .0253 .0294 .0334 .0374 40 43
1.1 .0414 .0453 .0492 .0531 .0569 .0607 .0645 .0682 .0719 .0755 36 39
1.2 .0792 .0828 .0864 .0899 .0934 .0969 .1004 .1038 .1072 .1106 33 36

その他，たとえば 0^{∘} から 45^{∘} までの 10′ 刻みの三角関数表（正弦）は

[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′  10′  20′  30′  40′  50′
0 .0000 .0029 .0058 .0087 .0116 .0145 29 30
1 .0175 .0204 .0233 .0262 .0291 .0320 29 29
2 .0349 .0378 .0407 .0436 .0465 .0494 29 29
3 .0523 .0552 .0581 .0610 .0640 .0669 29 30
4 .0698 .0727 .0756 .0785 .0814 .0843 29 29
5 .0872 .0901 .0929 .0958 .0987 .1016 28 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′ 10′ 20′ 30′ 40′ 50′ 60′ 70′ 80′ 90′ 100′ 110′
0 .0000 .0029 .0058 .0087 .0116 .0145 .0175 .0204 .0233 .0262 .0291 .0320 29 30
2 .0349 .0378 .0407 .0436 .0465 .0494 .0523 .0552 .0581 .0610 .0640 .0669 29 30
4 .0698 .0727 .0756 .0785 .0814 .0843 .0872 .0901 .0929 .0958 .0987 .1016 28 29
6 .1045 .1074 .1103 .1132 .1161 .1190 .1219 .1248 .1276 .1305 .1334 .1363 28 29
8 .1392 .1421 .1449 .1478 .1507 .1536 .1564 .1593 .1622 .1650 .1679 .1708 28 29
10 .1736 .1765 .1794 .1822 .1851 .1880 .1908 .1937 .1965 .1994 .2022 .2051 28 29

3.2.12.4 点数分布表

448. 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  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 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

[8] S=os_md.distpoint(M|opt="graph")$
[9] os_md.dviout(S)$

00- 10- 20- 3 30- 4 40- 6 50- 3 60- 14 70- 2 80- 1 90-

3.2.12.5 Table of score distribution

449. 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=[[s_{1},t_{1}],[s_{2},t_{2}]...] : は 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+\cdots
\end{split}\end{align}
[2] os_md.seriesTaylor(sin(x),7,x|small=1)$

sin(x) = x − \frac{1}{6}x^{3} + \frac{1}{120}x^{5} − \frac{1}{5040}x^{7} + ⋯

ここでは 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.166667x^{3} + 0.00833333x^{5} + ⋯

[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(@@)$

sin(x) = 1 − \frac{1}{2}(x − \frac{1}{2}π)^{2} + \frac{1}{24}(x − \frac{1}{2}π)^{4} + ⋯

[5] において sin(x) の x = \frac{π}{2} での Taylor 展開を 5 次の項まで求めているが, sin(\frac{π}{2} ) = 1, cos(\frac{π}{2} ) = 0 という情報を与えている．これを与えないと，係数は近似小数になる（sin(0) = 0, cos(0) = 1 などの情報は不要（cf. evalred()））．

 [7] os_md.seriesTaylor((x+1)^(1/2),10,x|frac=0,dviout=1);

\sqrt{x + 1} = 1 + 0.5x − 0.125x^{2} + 0.0625x^{3} − 0.0390625x^{4} + 0.0273438x^{5} − 0.0205078x^{6} + 0.0161133x^{7}

− 0.013092x^{8} + 0.01091x^{9} − 0.00927353x^{10} + ⋯

\sqrt{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)$

exp(sin(\frac{x − y}{x^{2} + 2y^{2} + 2})) = 1 + \frac{1}{2}x − \frac{1}{2}y + \frac{1}{8}x^{2} − \frac{1}{4}xy + \frac{1}{8}y^{2} − \frac{1}{4}x^{3} + \frac{1}{4}x^{2}y − \frac{1}{2}xy^{2} + \frac{1}{2}y^{3} + ⋯

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)$
/* 枠 */
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,
 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")$
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)$  /* 滑尺 */

3.2.13 Environments

450. Canvas

:: Risa/Asir の描画キャンバスのデフォルトサイズ execdraw() などで Risa/Asir の描画キャンバスを開くときのデフォルトサイズ

• 横と縦の pixel サイズのリストで，デフォルトは [400,400] となっている．

  • dviout0([800,400]|opt="Canvas") のようにして変更可能

• 初期化ファイル.muldif でデフォルト値の設定変更可能

451. AMSTeX

:: この値が 1 は AMSL^{A}TEX を意味する 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}y
452. TeXEq

:: デフォルトの L^{A}TEX の数式環境の指定（dviout0(3) で値が分かる） TeXEq の値は， 1, 2, 3, 4, 5, 6, 7 のいずれかで，それは dviout() のオプションパラメータの eq= の値に対応する． AMSTeX=1 のときのデフォルトは 5 で， AMSTeX=0 のときは TeXEq=1 とみなされる．

dviout0(n|opt="TexEq") で変更できる．
453. TeXLim

:: L^{A}TEX で長い数式を行分割する際の 1 行の許容最大横幅文字数のデフォルト値

 • .muldif で設定でき， dviout0("?") で値が分かる．
 • texlim(1,n) または dviout0(n|opt="TexLim") で変更できる（デフォルトは 80）．
454. TeXPages

:: TEX の display style で改ページを許す行数の閾値（cf. fctrtos()）

 • dviout0(n|opt="TexPages") で変更できる（デフォルトは 20）．
455. TikZ

:: グラフ表示に XY-pic を使うか TikZ を使うかを指定 TikZ=1 のときは TikZ を， TikZ=0 のときは XY-pic を使う．

切り替えは dviout0(6), dviout0(7) または dviout0(1|opt="TikZ"), dviout0(0|opt="TikZ").
456. XYPrec

:: グラフ表示の時の座標の小数点以下の丸め桁数

切り替えは dviout0(n|opt="XYPrec").
457. XYcm

:: Unit is cm even in XY-pic での単位を cm で表して， TikZ に合わせる

切り替えは dviout0(0|opt="XYcm"), dviout0(1|opt="XYcm").
458. XYLim

:: XY-pic や TikZ での曲線描画で順に指定する点での改行の間隔

切り替えは dviout0(n|opt="XYLim") （デフォルトは 4）
459. 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() で使われ，函数に対応するヘルプが表示される．

460. DIROUT

:: 数式を L^{A}TEX に変換したソースが格納されるディレクトリ（書き込み可能なことが要請される）

461. DVIOUTA

:: L^{A}TEX の AMSTEX 環境で risaout.tex を変換して表示するプログラムのパス名

462. DVIOUTB

:: L^{A}TEX の AMSTEX 環境で risaout10.tex （または risaout10.tex）を変換して表示するプロ

グラムのパス名で， DVIOUTA と交換できる（cf. dviout0(), risatex.bat）
463. DVIOUTL

:: L^{A}TEX 環境で riasout0.tex を変換して表示するプログラムのパス名

.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\""
DVIOUTL="\"%ASIRROOT%\bin\risaout0.bat\""

in ". のように設定し直して下さい．

464. .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 の文法に準じて，文字列中の文字 \ や " は \\ や \" と書く（そのように書かなくても多くの場合は大丈夫であろう）．さらに文字列の始まりと終わりは " で示す（それらは，行で最初にある " と最後にある " とみなしている）．

465. risatex.bat

:: os_muldif.rr が出力する L^{A}TEX のソースファイルを変換して表示するプログラム

• os_muldif.rr が TEX を使って結果や数式を綺麗に表示する際には， DIROUT 内の L^{A}TEX ファイル out.tex （または out0.tex）に L^{A}TEX のソースを書き出しますが，それらを 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 で示されるディレクトリを示しますが，数式を L^{A}TEX に直した 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}
\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}
\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）．

#!/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 を以下のように変更し，AMSL^{A}TEX

にも対応するようにします．なお，この変更は配布版に取り入れられています．

*** 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);
   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);
      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 I 行列の入力

行列の入力が容易になるよう様々な方法が提供されている．

• 行列(\begin{matrix}2 & 1 & 0 \\ 0 & 2 & 0 \\ 0 & 0 & −1 \end{matrix}) の入力は

– 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 と解釈される）．

• 対角行列

(\begin{matrix}a & 0 & 0 \\ 0 & b & 0 \\ 0 & 0 & c \end{matrix}) : diagm(3,[a,b,c]) （対角成分を与える）

(\begin{matrix}λ & 0 & 0 \\ 0 & λ & 0 \\ 0 & 0 & λ \end{matrix}) : diagm(3,[lambda]) （スカラー行列）

(\begin{matrix}a_{1} & 0 & 0 \\ 0 & a_{2} & 0 \\ 0 & 0 & a_{3} \end{matrix}) : diagm(3,a) （対角成分の自動添え字）

• 一般行列

(\begin{matrix}a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{matrix}) : mgen(3,3,a,1) （二重添え字の一般行列）

(\begin{matrix}a_{00} & a_{01} & a_{02} \\ a_{10} & a_{11} & a_{12} \\ a_{20} & a_{21} & a_{22} \end{matrix}) : mgen(3,3,a,0) （二重添え字の一般行列）

(\begin{matrix}a_{1} & a_{2} & a_{3} \\ b_{1} & b_{2} & b_{3} \\ c_{1} & c_{2} & c_{3} \end{matrix}) : mgen(3,3,[a,b,c],1) （一重添え字の一般行列）

(\begin{matrix}a_{1} & b_{1} & c_{1} \\ a_{2} & b_{2} & c_{2} \\ a_{3} & b_{3} & c_{3} \end{matrix}) : mtanspose(mgen(3,3,[a,b,c],1)) （一重添え字の一般行列） (\begin{matrix}a_{11} & a_{12} & a_{13} \\ a_{12} & a_{22} & a_{23} \\ a_{13} & a_{23} & a_{33} \end{matrix}) : mgen(3,"symmetric",a,1) （二重添え字の一般対称行列） (\begin{matrix}a_{1} & a_{2} & a_{3} \\ a_{2} & b_{2} & b_{3} \\ a_{3} & b_{3} & c_{3} \end{matrix}) : mgen(3,"symmetric",[a,b,c],1) （一重添え字の一般対称行列） (\begin{matrix}0 & a_{12} & a_{13} \\ −a_{12} & 0 & a_{23} \\ −a_{13} & −a_{23} & 0 \end{matrix}) : mgen(3,"skew",a,1) : （二重添え字の一般歪対称行列）

(\begin{matrix}0 & a & 0 \\ 0 & 0 & a \\ 0 & 0 & 0 \end{matrix})  : mgen(3,"highdiag",[a],1) （対角成分の一つ上）
(\begin{matrix}λ & 1 & 0 \\ 0 & λ & 1 \\ 0 & 0 & λ \end{matrix})  : diagm(3,[lambda])+mgen(3,"highdiag",[1],1)
(\begin{matrix}0 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{matrix})  : mgen(3,"perm",[3,1,2],1) （置換行列）

より詳しくは， mgen() を参照． (\begin{matrix}cos α & − sin α \\ sin α & cos α \end{matrix}) : mrot(α) （2 次回転行列） (\begin{matrix}cos θ^{∘} & − sin θ^{∘} \\ sin θ^{∘} & cos θ^{∘} \end{matrix}) : mrot(θ|deg=1) （2 次回転行列）

(\begin{matrix}a_{11} & a_{12} & a_{13} \\ a_{12} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{matrix}) = k_{z}(α)k_{y}(β)k_{z}(γ) : mrot([α,β,γ]) （3 次回転行列, k_{t}(θ) は t 軸中心の

θ 回転の行列）

A = k_{z}(γ)^{−1}k_{y}(β)^{−1}k_{z}(α)k_{y}(β)k_{z}(γ) : mrot([α,β,γ]|inv=1) （3 次回転行列）

• 行列をつなげる

A = (\begin{matrix}1 & 0 \\ 0 & 1 \end{matrix}), B = (\begin{matrix}2 & 0 \\ 0 & 2 \end{matrix}) とすると

(\begin{matrix}1 & 0 & 2 & 0 \\ 0 & 1 & 0 & 2 \end{matrix})  : newbmat(1,2,[[A,B]]) （横につなげる）
(\begin{matrix}1 & 0 \\ 0 & 1 \\ 2 & 0 \\ 0 & 2 \end{matrix})  : newbmat(2,1,[[A],[B]]) （縦につなげる）

(\begin{matrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 2 \end{matrix}) : newbmat(2,2,[[A],[0,B]]) （対角につなげる）

(\begin{matrix}1 & 0 & 2 & 0 \\ 0 & 1 & 0 & 2 \\ 2 & 0 & 1 & 0 \\ 0 & 2 & 0 & 1 \end{matrix})  : newbmat(2,2,[[A,B],[B,A]])

newbmat(m,n,[[A_{11},A_{12},…],[A_{21},A_{22},…],…]) は, m × n のブロック行列を作る函数である． • 行列を抜き出す

A = (\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} \\ a_{30} & a_{31} & a_{32} & a_{33} \end{matrix}) とする．ここでは，行や列の番号は 0 から始まると考える．

(\begin{matrix}a_{00} & a_{01} & a_{02} \\ a_{20} & a_{21} & a_{22} \end{matrix}) : mperm(A,[0,2],[0,1,2]) （0 行目と 2 行目， 0 列目と 1 列目と 2 列目をこ

の順に抽出）

(\begin{matrix}a_{00} & a_{01} & a_{02} & a_{03} \\ a_{20} & a_{21} & a_{22} & a_{23} \end{matrix}) : mperm(A,[0,2],0) （0 行目と 2 行目をこの順に抽出）

(\begin{matrix}a_{02} & a_{00} \\ a_{12} & a_{10} \\ a_{22} & a_{20} \\ a_{32} & a_{30} \end{matrix}) : mperm(A,0,[2,0]) （2 列目と 0 列目をこの順に抽出）

(\begin{matrix}a_{00} & a_{02} \\ a_{20} & a_{22} \end{matrix}) : mperm(A,[0,2],1) （0 行目と 2 行目から正方行列を作る）

(\begin{matrix}a_{10} & a_{11} & a_{12} & a_{13} \\ a_{20} & a_{21} & a_{22} & a_{23} \\ a_{30} & a_{31} & a_{32} & a_{33} \\ a_{00} & a_{01} & a_{02} & a_{03} \end{matrix}) : mperm(A,[1,2,3,0],0) （0 行目を最後の行に繰り下げる）

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)

• \overrightarrow{OX} = \overrightarrow{OP} + \overrightarrow{OQ} となる X を返す（O は原点）：

ladd(P,Q,1)

• \overrightarrow{OX} = \overrightarrow{OP} − \overrightarrow{OQ} となる X を返す：

lsub([P,Q]), ladd(P,Q,−1).

• \overrightarrow{OX} = \overrightarrow{OP} + t · \overrightarrow{OQ} となる X を返す：

ladd(P,Q,t)

• \overrightarrow{OX} = t · \overrightarrow{OQ} となる X を返す：

ladd(0,Q,t)

• \overrightarrow{OX} = s\overrightarrow{OP} + t · \overrightarrow{OQ} となる X, すなわち線分 P Q の t : s の内分点を返す：

ladd(P,Q,[s,t])

• \overrightarrow{OX} = (1 − t)\overrightarrow{OP} + t · \overrightarrow{OQ} となる X, すなわち線分 P Q の t : 1 − t の内分点を返す：

ladd(P,Q,[t])

• \overrightarrow{OX} = \overrightarrow{OP} + t · \overrightarrow{P Q} となる X を返す：

ladd(P,Q,t)

• P から Q の方向へ d だけ進んだ点を返す（d は負でもよい）：

ladd(P,Q,[ d/dnorm([P,Q]) ])

• 線分 P Q の中点を返す：

  ladd(P,Q,[\frac{1}{2}])

• 直線 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)

• \overrightarrow{P Q} を s 倍して θ 回転したベクトル v とするとき，\overrightarrow{OX} = \overrightarrow{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 に接する円を返す（\overrightarrow{P Q} に対して第 1, 3 象限側）：

  pt5center([O,r],[P,Q],[R,S])

• 点 P を反転した点を返す（反転の中心を (x_{0}, y_{0}) とする）：

ptinversion(P |org=[x_{0},y_{0}])

• 円 [[a,b],r] を反転した円を返す：

ptinversion([[a,b],r]|org=[x_{0},y_{0}])

• 中心が (x_{0}, y_{0}) で半径 r の円に関して，点 P を反転した点を返す：

ptinversion(P |org=[x_{0},y_{0}],sc=r)

• 2 つの Bézier 曲線 ℓ_{1} と ℓ_{2} の交点を返す :

ptcombezier(b_{1},b_{2},m)

• 2 つの複合 Bézier 曲線 b_{1} と b_{2} の交点を返す :

ptcombz(b_{1},b_{2},m)

• 複合 Bézier 曲線 b の自己交叉点を返す :

ptcombz(b,0,m)

• 直線 P Q の {(x, y) | x_{min} ≤ x ≤ x_{max}, y_{min} ≤ y ≤ y_{max}} の部分の両端を返す：

lninbox([P,Q],[[x_{min},x_{max}],[y_{min},y_{max}]])

• 線分 P Q の {(x, y) | x_{min} ≤ x ≤ x_{max}, y_{min} ≤ y ≤ y_{max}} の部分の両端を返す：

lninbox([P,Q],[[x_{min},x_{max}],[y_{min},y_{max}]]|in=1)

条件を満たす点のリストを求める

• 点 P, Q, R, … の {(x, y) | x_{min} ≤ x ≤ x_{max}, y_{min} ≤ y ≤ y_{max}} 外のものを数 0 に変える： ptwindow([P, Q, R, …],[x_{min},x_{max}],[y_{min},y_{max}])

• 点 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=θ)

• \overrightarrow{OX} = \overrightarrow{OS} + k · \overrightarrow{OQ} + ℓ · \overrightarrow{OR} （0 ≤ k < m, 0 ≤ ℓ < n）の格子点 X の座標のリストを返す： f_{1}(X[0], X[1]) ≥ 0, f_{2}(X[0], X[1]) ≥ 0, … を満たさない点は除く．

ptlattice(m,n,P,Q|org=S,scale=t,cond=[f_{1},f_{2},...])

• 点 P_{1}, P_{2}, … の凸包の多角形の頂点を求める．

ptconvex([P_{1}, P_{2}, . . .])

• すべての点 P_{1}, P_{2}, … を頂点にもつある多角形の頂点を求める．

ptconvex([P_{1}, P_{2}, . . .]|opt=1)

• 点 R が，直線 P Q の左側にある条件（\overrightarrow{P Q} が正の向き） dext([P, Q],[P, R]) > 0 あるいは darg([P, Q], [P, R]) > 0

長さや角度を求める

• \overrightarrow{OP} の長さを返す :

dnorm(P)

• \overrightarrow{P Q} の長さを返す :

dnorm([P,Q])

• \overrightarrow{OP} と\overrightarrow{OQ} の内積を返す :

dvprod(P,Q)

• \overrightarrow{P Q} と\overrightarrow{RS} の内積を返す :

dvprod([P,Q],[R,S])

• 2 次元ベクトル\overrightarrow{OP} と\overrightarrow{OQ} の外積を返す :

dext(P,Q)

• 2 次元ベクトル\overrightarrow{P Q} と\overrightarrow{RS} の外積を返す :

dext([P,Q],[R,S])

• 2 次元ベクトル\overrightarrow{P Q} の偏角 θ （−\frac{π}{2} < θ ≤ \frac{3}{2}π）に応じた値を返す:

darg(P,Q)

• 2 次元ベクトル\overrightarrow{P_{1}P_{2}} に対し，\overrightarrow{Q_{1}Q_{2}} のなす角に応じた値を返す（0: 同じ向き， 2: 逆向き， ±1: 左（右）回りに直交）．

darg([P_{1},P_{2}],[Q_{1},Q_{2}])

• 閉じた折れ線 Q_{1}, …, Q_{n}, Q_{1} の点 P に対するの回転数を返す．

dwinding(P,[Q_{1}, . . . , Q_{n}])

• \overrightarrow{P Q} と\overrightarrow{RS} のなす角 θ （−π < θ ≤ π）をラジアンで返す :

ptcommon([P,Q],[R,S]|in=2)

• \overrightarrow{P Q} と\overrightarrow{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) (x_{1} ≤ x ≤ x_{2}) で定まる函数のグラフの y_{1} ≤ y ≤ y_{2} の部分 :

xygraph(f,n,[x_{1},x_{2}],0,[y_{1},y_{2}]|opt=s,org=P,scale=r,prec=v)

• (f_{1}(t), f_{2}(t)) (t_{1} ≤ t ≤ t_{2}) で定まる平面曲線の x_{1} ≤ x ≤ x_{2}, y_{1} ≤ y ≤ y_{2} の部分 :

xygraph([f_{1},f_{2}],n,[t,t_{1},t_{2}],[x_{1},x_{2}],[y_{1},y_{2}]|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,γ])

• 格子点を（f_{j} ≥ 0 を満たす）\overrightarrow{OS} + k · \overrightarrow{OQ} + ℓ · \overrightarrow{OR} （0 ≤ k < m, 0 ≤ ℓ < n）とする格子 :

xylines(ptlattice(m,n,P,Q|line=1,org=S,scale=t,cond=[f_{1},f_{2},...]))

• ∠QP R に半径 r の角度記号（\overrightarrow{P Q} から反時計回りに\overrightarrow{P R} まで） :

xyang(r,P,Q,R)

• \overrightarrow{P Q} の始点 P に一辺 r で反時計回りに直角記号を描く :

xyang(r,P,Q,1)

• \overrightarrow{P Q} の始点 P に一辺 r で時計回りに直角記号を描く :

xyang(r,P,Q,-1)

• \overrightarrow{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)

• \overrightarrow{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]) の [x_{1}, x_{2}] × [x_{2}, y_{2}] 内の部分を [a, b] の n 分点を取って描く：

xygraph(f,n,[a,b],[x_{1},x_{2}],[y_{1},y_{2}]|ax=?,scale=?,...)

• 曲線 (f(t), g(t)) (t ∈ [a, b]) の [x_{1}, x_{2}] × [x_{2}, y_{2}] 内の部分を [a, b] の |n| 分点を取って描く：

xygraph([f, g],n,[t,a,b],[x_{1},x_{2}],[y_{1},y_{2}]|ax=?,scale=?,...)

• 曲面 z = f(x, y) ((x, y) ∈ [x_{1}, x_{2}] × [y_{1}, y_{2}]) を， z ∈ [h_{1}, h_{2}] の範囲で， x 軸を y 軸方向に α^{∘} 回転した無限遠方から β^{∘} 見下ろしたものとして， x, y 座標を共に |n| 等分した曲面上のメッシュで描く．

xy2graph(f,n,[x_{1},x_{2}],[y_{1},y_{2}],[h_{1},h_{2}],α,β |scale=?,ax=?)

• 空間内の曲線 (f_{1}(t), f_{2}(t), f_{3}(t)) (t ∈ [t_{1}, t_{2}]) を， x 軸を y 軸方向に α^{∘} 回転した無限遠方から β^{∘} 見下ろしたものとして描く．隠線消去は距離 g mm を基準とする．

xy2curve([f_{1},f_{2},f_{3}],n,[t,t_{1},t_{2}],[y_{1},y_{2}],[z_{1},z_{2}],α,β|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() が定義されている．よってたとえば sin^{2}(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 は任意の不定元でよい.

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 に置き換えられるので，任意精度（bigfloat）浮動小数の計算ではなく倍精度浮動小数計算となる（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 をリスト形式函数に変換する

  f2df(f)

• 函数 f の不定元 x に函数 g を代入したリスト形式函数を得る（f, g はリスト形式函数でもよい）

  compdf(f,x,g)

• 函数 f の不定元 x_{1}, x_{2}, … のそれぞれに函数 g_{1}, g_{2}, … を代入したリスト形式函数を得る compdf(f,[x_{1},x_{2}, …],[g_{1},g_{2}, …])

• 函数子 f で変数が v_{1}, …, v_{n} のリスト形式函数を得る（n は f の引数の数） v_{j} は数値，不定元，有理式，リスト形式函数など f2df() で解釈できる函数でよい．

  todf(f,[v_{1},. . .,v_{n}])

• 函数子 f のオプションリストが [ops] で変数が v_{1}, …, v_{n} のリスト形式函数を得る． v_{j} は数値，不定元，有理式，リスト形式函数など f2df() で解釈できる函数でよい．

  todf([f,[ops]],[v_{1},. . .,v_{n}])

• 変数への代入などによって値を評価できる（リスト形式）函数 f を評価して函数値を得る

  myeval(f)  mydeval(f)  myval(f)

myeval() は eval() にあたり（可能なら bigfloat)， mydeval() は deval() にあたり（複素数値には非対応）， myval() は可能な限り浮動小数点を用いない値を得る．

• （リスト形式）函数 f の不定元 x に値 a を代入した函数値を得る

  myfeval(f,a)  myfdeval(f,a)

前者は eval() に対応（可能なら bigfloat)，後者は deval() に対応（複素数値には非対応）．

• （リスト形式）函数 f の不定元 x に値 a を代入した函数値を得る

  myfeval(f,[x,a])  myfdeval(f,[x,a])

• （リスト形式）函数 f の不定元 x_{1}, x_{2}, … に値 a_{1}, a_{2}, … を代入した函数値を得る

  myfeval(f,[[x_{1},a_{1}],[x_{2},a_{2}],. . .])   myfdeval()(f,[[x_{1},a_{1}],[x_{2},a_{2}],. . .])

• （リスト形式）函数 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 の a_{j} での値を b_{j} に変更した（j = 1, …, n − 1）変数 x のリスト形式函数を得る

  cutf(f,x,[[],[a_{1},b_{1}],,...,[a_{n−1},b_{n−1}],[]])

• a ≤ x < b のとき f(x) となる周期 b − a の x 変数のリスト形式函数を得る（f の変数は x とする）．

  periodicf(f,[a,b],x)

• k = 1, …, n に対して (k − 1)c ≤ x < kc のとき h_{k}(y) (0 ≤ y < c, \frac{x−y}{c} ∈ ℤ) となる周期 nc の x 変数のリスト形式函数を得る

  periodicf(ltov([h_{1},h_{2},. . .,h_{n}]),c,x)

• 変数の範囲によって異なる函数の値を取るリスト形式函数を得る

g(x) = \begin{cases}v_{1}(x) & (x < a_{0}), \\ v_{k} & (x = a_{k}, k = 1, …, n − 1), \\ v_{n}(x) & (x > a_{n}), \\ f(x) & (上以外の x) \end{cases}

という x を変数とするリスト形式函数 g(x) は次のようにして得られる．

ただし， f, v_{1}, v_{n} の変数は x で（v_{1}, v_{n} は数でもよい）， a_{0} ≤ a_{1} < a_{2} < ⋯ < a_{n−1} ≤ a_{n} となっている必要がある（以下で [t,[a_{0},v_{0}],[a_{1},v_{1}],…,[a_{n},v_{n}]] とすると， f の変数の t に対応する）．

  cutf(f,x,[[a_{0},v_{1}],[a_{1},v_{2}],. . .,[a_{n},v_{n}]])

• pari(funct, ) で呼び出される函数 funct を変数 x のリスト形式函数にする

  [z_,[z_,os_md.evals,["pari","funct",x]]]

3.2.14.4 実数値／複素数値函数の解析

以下の函数には sin(x) のような函数のほか，リスト形式函数も含まれる．零点

• 実数値函数 f の区間 [x_{1}, x_{2}] における（近似）零点とそこでの f の値を求める

  fzero(f,[x_{1},x_{2}]|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]])

• x_{1}, …, x_{n} 変数の n 個の多項式 p_{1}, …, p_{n} の共通実根をもとめる

  polroots([p_{1},...,p_{n}],[x_{1},...,x_{n}]|err=r)

• z_{1}, …, z_{n} 変数の n 個の多項式 p_{1}, …, p_{n} の（範囲など）指定した条件を満たす共通根もとめる

  polroots([p_{1},...],[z_{1},...]|comp=t,lim=[[z_{1},[a_{1},b_{1}],[c_{1},d_{1}]],. . .],err=r)

極値

• 実数値函数 f の点 a での極限値を求める（a = −∞ を "-" で, a = ∞ を "+" で表す）

  flim(f,a|prec=c,init=t)

• 実数値函数 f の点 a での右極限値や左極限値を求める

  flim(f,["±",a]|prec=c,init=t)

• 実数値函数 f の区間 [x_{1}, x_{2}] の極値とそのときの変数の値を求める

  fmmx(f,[x_{1},x_{2}]|mesh=m,dev=d,dif=1,zero=1)

• 実数値函数 g の区間 [x_{1}, x_{2}] 内の零点とその点における函数 f の値を求める

  fmmx(f,[x_{1},x_{2}]|mesh=m,dev=d,dif=g,zero=1)

• 実数値函数 f の区間 [x_{1}, x_{2}] での最小値と最大値とそのときの変数の値を求める

  fmmx(f,[x_{1},x_{2}]|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] ∋ t ↦ (ϕ(t), ψ(t)) に沿った複素積分 f の変数は複素数 z とその実部 x と虚部 y を用いることができる．

  fint(f,n,[[ϕ,ψ],[a,b]]|exp=c,int=k,prec=v)

• 複素数値函数 f の区分的 C^{1} 級曲線に沿った複素積分（f の変数は z, x, y）

fint(f,n,[[[ϕ_{1},ψ_{1}],[a_{1},b_{1}]],[[ϕ_{2},ψ_{2}],[a_{2},b_{2}]]. . .]|exp=c,int=k,prec=v)

• 点 (a_{1}, b_{1}), (a_{2}, b_{2}), …, (a_{n}, b_{n}) を順に繋ぐ折線に沿った複素数値函数 f の複素積分

fint(f,n,[[a_{1},b_{1}],[a_{2},b_{2}],. . .,[a_{n},b_{n}]]|exp=c,int=k,prec=v)

• 点 (a_{1}, b_{1}), …, (a_{n}, b_{n}), (a_{1}, b_{1}) を順に繋ぐ閉じた折線に沿った複素数値函数 f の複素積分

fint(f,n,[[a_{1},b_{1}],[a_{2},b_{2}],. . .,[a_{n},b_{n}],-1]|exp=c,int=k,prec=v)

• 曲線 C : [a, b] ∋ t ↦ (ϕ(t), ψ(t)) に沿った線積分 ∫_{C} y dx 無限区間，すなわち a = "-" （−∞ を意味する） , b = "+" （+∞ を意味する）も可

areabezier([[ϕ,ψ],n,[t,a,b]]|exp=c,int=k,prec=v)

• z 変数の有理式\frac{p}{q} （q は多項式）の ∀f_{j} > 0 で表される領域の周での複素積分（留数計算）

fresidue(p,q|cond=[f_{1},f_{2}, . . .],sum=2)

• 滑らかな閉曲線 C : [a, b] ∋ t ↦ (ϕ(t), ψ(t)) で囲まれた領域の面積（曲線が時計回りならその −1 倍)

areabezier([[ϕ,ψ],n,[t,a,b]]|int=k,prec=v)

• 点 (a_{1}, b_{1}), (a_{2}, b_{2}), …, (a_{n}, b_{n}) を順に通り始点にもどる折線で囲まれた多角形の面積

areabezier(xylines([[a_{1},b_{1}],...,[a_{n},b_{n}]]|close=1))

• 点 (a_{1}, b_{1}), (a_{2}, b_{2}), …, (a_{n}, b_{n}) を順に通り始点にもどる滑らかな閉曲線で囲まれた部分の面積

areabezier(xylines([[a_{1},b_{1}],...,[a_{n},b_{n}]]|close=1,curve=1))

• 区分的 Bézier 曲線 ℓ で囲まれた部分の面積（ℓ は lbezier() で扱われるデータ形式のいずれか）

areabezier(ℓ)

不定積分（原始関数）

• x を変数とする函数 f の不定積分 ∫ f(x) dx

integrate(f,x)

• x を変数とする多項式 p の [0, x] での積分 ∫_{0}^{x} p(x) dx

intpoly(p,x)

• 原始関数を求めることによる定積分 ∫_{a}^{b} f(x) dx の計算

integrate(f,x|I=[a,b])

• x を変数とする有理函数 p の原始関数 ∫ p(x) dx

intpoly(p,x)

• 多項式 p と三角関数 sin λx の積の原始関数

intpoly(p,x|sin=λ)

戻り値 [g(x),h(x)] は ∫ p(x) sin λx dx = g(x) cos λx + h(x) sin λx を意味する．

• 多項式 p と三角関数 cos λx の積の原始関数

intpoly(p,x|cos=λ)

戻り値 [g(x),h(x)] は ∫ p(x) cos λx dx = g(x) cos λx + h(x) sin λx を意味する．

• 多項式 p とべき函数 x^{λ} の積の原始関数

intpoly(p,x|pow=λ)

戻り値 g(x) は ∫ p(x)x^{λx}dx = g(x)x^{λ} を意味する．

• 多項式 p と対数関数 log(λx + c) の積の原始関数

intpoly(p,x|log=[λ,c])

戻り値 [g(x),h(x)] は ∫ p(x) log(λx + c)dx dx = g(x) log(λx + c) + h(x) を意味する．

• 多項式 p と対数関数の自然数べき log^{m}(λx + c) の積の原始関数

intpoly(p,x|log=[λ,c,m])

戻り値 [g_{0}(x),g_{1}(x), …] は ∫ p(x) log^{m}(λx + c)dx = ∑_{j=0}^{m} g_{j}(x) log^{m−j}(λx + c) を意味する．

留数 • z 変数の多項式 q を分母とする有理式\frac{p}{q} の特異点と留数のリストを得る

  fresidue(p,q)

• f_{1} > 0, f_{2} > 0, … を満たす領域での有理式\frac{p}{q} の特異点と留数のリストを得る f_{j} は， z, x, y の（リスト形式）函数（z = x + yi）

  fresidue(p,q|cond=[f_{1},f_{2}, . . .])

• 条件を満たす留数の和を求める

  fresidue(p,q|cond=[f_{1},f_{2}, . . .],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=[n_{1},n_{2},· · ·],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",[])

データのソート

• t_{1} 番目の項目でソート

lsort(ℓ,"sort",["put",t_{1}])

• t_{1} 番目の項目で逆順ソート

lsort(ℓ,"sort",["put",−t_{1} − 1])

• 多重キーを用いた要素のソート

msort(ℓ,s)

• t_{1} 番目が同じものは一つを除いて削除（重複を省く）

lsort(ℓ,"sort",["reduce"])

項目を付加

• 要素の先頭に，中身が s の項目を付加

lsort(ℓ,s,"cons")

• 要素の先頭に， s_{1}, s_{2}, … を順に付加

lsort(ℓ,[s_{1},s_{2}, . . .],"cons")

• 項目番号を順に入れたリストを最初の要素として付加

lsort(ℓ,"num",["col"])

• 各要素の先頭に要素番号を n から順に入れた項目を付加

lsort(ℓ,"num",["put",n])

要素や項目を抜き出す

• 項目 c_{1,1}, c_{1,2}, ⋯ を抜き出す

lsort(ℓ,"col",["put"]|c_{1}=[c_{1,1},c_{1,2},. . .])

• 項目 c_{1,1}, c_{1,2}, ⋯ を除く

lsort(ℓ,"col",["setminus"]|c_{1}=[c_{1,1},c_{1,2},. . .])

• c_{1,1} 番目， c_{1,2} 番目, … の要素をこの順に抜き出す

lsort(ℓ,"num",["get"]|c_{1}=[c_{1,1},c_{1,2},. . .])

• c_{1,1} 番目， c_{1,2} 番目, … の要素を削除

lsort(ℓ,"num",["sub"]|c_{1}=[c_{1,1},c_{1,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])

• c_{1} 番目の項目， c_{2} 番目の項目， … の和（数でない項目は 0）を全ての要素に渡って足し合わせて返す

  lsort(ℓ,"num",["sum","+"]|c1=[c_{1,1},c_{1,2},. . .])

• c_{1} 番目の項目， c_{2} 番目の項目,… の和を足し合わせたものを要素の最初の項目に追加

  lsort(ℓ,"num",["put","+"]|c1=[c_{1,1},c_{1,2},. . .])

• n 番目の項目（n がなければ要素）を函数 f に入れた戻り値を要素の最初の項目に追加

  lsort(ℓ,"num",["put",f,n])

• n 番目の項目（n がなければ要素）を函数 f に入れた戻り値を全ての要素について足した和を返す

  lsort(ℓ,"num",["sum",f,n])

項目の書き換え

• m_{ν} 番目の要素の n_{ν} 番目の項目を s_{ν} に置き換える

  lsort(ℓ,"subst",[]|c1=[[m_{1},n_{1},s_{1}],[m_{2},n_{2},s_{2}],. . .)

2 つのリスト型式データ ℓ, ℓ′ に対し，指定したキー項目が同じものを対応する要素とみなして ℓ を変換

• ℓ の要素に対応する ℓ′ の要素があれば，項目を合わせた要素にする

  lsort(ℓ_{1},ℓ_{2},["cup",m,n]|c1=[c_{1,1},c_{1,2},. . .],c2=[c_{2,1},c_{2,2},. . .])

• ℓ の要素に対応する ℓ′ の要素があれば，項目を合わせた要素にして抜き出す

  lsort(ℓ_{1},ℓ_{2},["cap",m,n]|c1=[c_{1,1},c_{1,2},. . .],c2=[c_{2,1},c_{2,2},. . .])

• ℓ の要素に対応する ℓ′ の要素があれば， ℓ から削除する

  lsort(ℓ_{1},ℓ_{2},["setminus",m,n]|c1=[c_{1,1},c_{1,2},. . .])

• ℓ の要素に対応する ℓ′ の要素があれば，対応する要素で ℓ′ の指定した項目で ℓ の指定した項目を上書きする（複数あればリストにする）

  lsort(ℓ_{1},ℓ_{2},["over",m,n]|c1=c_{1},c2=c_{2}])

• ℓ の要素に対応する ℓ′ の要素があり，対応する要素で ℓ′ の指定した項目が空文字列でなければ，それで ℓ の指定した項目を上書きする

  lsort(ℓ_{1},ℓ_{2},["subst",m,n]|c1=c_{1},c2=c_{2}])

その他

• 2 つのリスト型式データの中身の違いをリストで返す

  lsort(ℓ_{1},ℓ_{2},"cmp")

• 要素数が同じ 2 つのリスト型式データの各要素を繋げて返す

  lsort(ℓ_{1},ℓ_{2},"append")

3.3 Functions in the original library

以下の函数は， module 化されないので，函数名の先頭に os_md. をつけません．

3.3.1 数の演算

1. idiv(i_{1},i_{2})

:: 整数除算による商

2. irem (i_{1},i_{2})

:: 整数除算による剰余 • i_{1} の i_{2} による整数除算による商, 剰余を求める.

• i_{2} は 0 であってはならない.

• 被除数が負の場合, 絶対値に対する値にマイナスをつけた値を返す.

• i_{1} % i_{2} は, 結果が正に正規化されることを除けば 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)

:: 自然数 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)));
y
6. igcd(i_{1},i_{2})

:: 整数 i_{1} と i_{2} の 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)
8. ilcm(i_{1},i_{2})

:: 整数の最小公倍数を求める一方が 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])

:: 乱数を生成する • 最大 2^{32} − 1 の非負整数の乱数を生成する.

• 0 でない引数がある時, その値を seed として設定してから, 乱数を生成する.

• default の seed は固定のため, 種を設定しなければ, 生成される乱数の系列は起動毎に一定である.

• 松本眞–西村拓士による Mersenne Twister アルゴリズムの, 彼ら自身による実装を用いている.

  (http://www.math.keio.ac.jp/matsumoto/mt.html)

• 周期は 2^{19937} −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;
% asir
This is Asir, Version 991108.
Copyright (C) FUJITSU LABORATORIES LIMITED.
3 March 1994. All rights reserved.
[4] mt_load("/tmp/mt_state");
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)

:: 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 の flag を on にする方法は, ctrl() を参照. 設定できる桁数に上限はないが, 指定した桁数に設定されるとは限らない. 大きめの値を設定するのが安全である.

[0] setprec();
9
[1] setprec(100);
9
[3] setprec(100);
96
22. setmode([p])

:: 有限体を GF (p) に設定する • p は 2^{27} 未満の素数

• 有限体を 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 は 2^{32} 未満の非負整数， 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 を行う

[0] ctrl("hex",1);
0x1
[1] ishift(0x1000000,12);
0x1000
[2] ishift(0x1000,-12);
0x1000000
[3] ixor(0x1248,ishift(1,-16)-1);
0xedb7
29. 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] 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);
0
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);
12
35. 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-Wagstaff の擬素数かどうかを調べる．少なくとも 2^{64} = 1.84 ⋯ × 10^{20} 以下では素数と一致．

[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]) :: 複素数 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);
-1
44. 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]);
[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)

:: 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) 上で計算する.

• 多項式の除算は, 主係数どうしの割算により得られた商と, 主変数の適当な冪の積を 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 ]*) :: 有理式の特定の不定元に, 定数あるいは多項式, 有理式などを代入する

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) と同じである.

• 有理式を微分する場合は約分されないので分母が膨らんで計算が複雑になるのを避ける 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]]
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)

:: 有限体上での多項式の因数分解 • 2^{29} 未満の自然数 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])

:: 有理係数多項式 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));
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(p_{1},p_{2})

:: 整数係数一変数多項式の高速乗算

76. umul ff(p_{1},p_{2})

:: 有限体係数一変数多項式の高速乗算

77. usquare(p_{1})

:: 整数係数一変数多項式の高速 2 乗算

78. usquare ff(p_{1})

:: 有限体係数一変数多項式の高速 2 乗算

79. utmul(p_{1},p_{2},d)

:: 整数係数一変数多項式の高速乗算 (打ち切り次数指定)

80. utmul ff(p_{1},p_{2},d)

:: 有限体係数一変数多項式の高速乗算 (打ち切り次数指定) • 一変数多項式の乗算を, 次数に応じて決まるアルゴリズムを用いて高速に行う.

• umul(), usquare(), utmul() は係数を整数と見なして, 整数係数の多項式として積を求める. 係数が有限体 GF (p) の元の場合には, 係数は 0 以上 p 未満の整数と見なされる.

• umul ff(), usquare ff(), utmul ff() は, 係数を有限体の元と見なして, 有限体上の多項式として積を求める. ただし, 引数の係数が整数の場合, 整数係数の多項式を返す場合もあるので, これらを呼び出した結果が有限体係数であることを保証するためにはあらかじめ simp ff() で係数を有限体の元に変換しておくとよい.

• umul ff(), usquare ff(), utmul ff() は, GF (2^{n}) 係数の多項式を引数に取れない.
• umul(), umul ff() の結果は p_{1}, p_{2} の積, usquare(), usquare ff() の結果は p_{1} の 2 乗,

utmul(), utmul ff() の結果は p_{1}, p_{2} の積の, d 次以下の部分となる.

• いずれも, set upkara() (utmul, utmul ff については set uptkara()) で返される値以下の次

数に対しては通常の筆算形式の方法, set upfft() で返される値以下の次数に対しては Karatsuba 法, それ以上では FFT および中国剰余定理が用いられる. すなわち, 整数に対する FFT ではなく, 十分多くの 1 ワード以内の法 mi を用意し, p_{1}, p_{2} の係数を 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)
[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(p_{1},p_{2})

:: 一変数多項式の乗算を Karatsuba 法で行う

82. ksquare(p_{1})

:: 一変数多項式の高速 2 乗算を Karatsuba 法で行う

83. ktmul(p_{1},p_{2},d)

一変数多項式の高速乗算 (打ち切り次数指定) を Karatsuba 法で行う • 一変数多項式の乗算を Karatsuba 法で行う.

• 基本的には umul() と同様だが, 次数が大きくなっても FFT を用いた高速化は行わない.

• GF (2^{n}) 係数の多項式にも用いることができる.

[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)

:: 一変数多項式を次数で分ける

89. ureverse(p)

:: 一変数多項式の次数を逆にした多項式を作る

• p の変数を x とする. このとき p = p_{1} + x^{d+1}p_{2} (p_{1} の次数は d 以下) と分解できる. utrunc() は p_{1} を返し, udecomp() は [p_{1},p_{2}] を返す.

• 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 とするとき, p_{1} =ureverse(p,e) に対
    して uinv_as_power_series(p_{1},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+1
92. udiv(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, 商を返す

93. urem(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, 剰余を返す

94. urembymul(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, 剰余を返す

95. urembymul precomp(p_{1},p_{2},inv)

:: 固定された多項式による剰余計算を多数行う場合などに用いる

96. ugcd(p_{1},p_{2})

:: 一変数多項式 p_{1}, p_{2} に対し, GCD を返す

• 一変数多項式 p_{1}, p_{2} に対し, udiv は商, urem, urembymul は剰余, ugcd は GCD を返す. これらは, 密な一変数多項式に対する高速化を図ったものである. urembymul は, p_{2} による剰余計算を, p_{2} の冪級数としての逆元計算および, 乗算 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*y
98. 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);
 -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]
[6] length(L);
3
[7] length(ltov(L));
3
[8] L[2][0];
5

107. 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] 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)

:: 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]]);
[ 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 range
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() を用いる．

[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 ]
[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);
[ 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 の行列）に相似変換する．

[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";
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));
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)
{
  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 )
    return 1;
  else if ( A->body < B->body )
    return -1;
  else
    return 0;
}
arfreg("a",add,sub,mul,div,pwr,chsgn,comp)$
end$
% asir
This 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 ともに無引数の函数であるが, `()' なしで呼び出すことができる. いずれも現在読み込み中のファイルを閉じる. これは, トップレベルにおいてはセッションを終了させることになる.

• ファイルの場合, ファイルの終端まで読めば, 自動的にファイルは閉じられるが, トップレベルの場合プロンプトが出ないまま, 入力待ちになるので, ファイルの終端には end$ を書くのが望ましい.

[0] quit;
%

150. load("filename")

:: filename を読み込む

• 実際のプログラムの書き方は, ユーザ言語 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("filename")

:: 引数 filename に対し, 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(["filename"])

:: 以降の出力先を filename または標準出力に切替える • Asir の出力を標準出力から, ファイルへの出力に切替える. なお, ファイル出力の間は, 標準出力

にはキーボードからの入力以外, 出力されない.

• 別のファイル出力に切替える時には, 再び output("filename") を実行する. 又, ファイル出力を終了し標準出力に戻りたい時には, 引数なしで output() を実行する.

• 指定したファイル filename が存在した時は, そのファイルの末尾に追書きされ, 存在しなかった時には, 新たにファイルを作成し, そこに書き込まれる.

• ファイルネームを " " ダブルクォートなしで指定をしたり, ユーザが, 書き込めないファイルを指定したりすると, エラーによりトップレベルに戻る.

• 入力したものも込めてファイルに出力したい場合には, ctrl("echo",1) を実行した後でファイル出力に切替えれば良い. 計算時間など, 標準エラー出力に書き出されるものはファイルには書き出されない. 函数形式, 未定係数 (vtype() 参照) を含まない数式のファイルへの読み書きは, bload(), bsave() を使うのが, 時間, 空間ともに効率がよい.

• Windows 版もディレクトリのセパレータとして `/' を用いる．

[0] output("afo");
fctr(x^2-y^2);
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,"filename") :: filename に obj をバイナリ形式で書き込む

154. bload("filename")

:: filename から数式をバイナリ形式で読み込む • 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^2

155. print(obj[,nl])

:: obj を評価して表示する

• 第 2 引数がないか, または 0, 2 以外の場合, 改行する. 第 2 引数が 0 の場合, 改行せず, 出力はバッファに書き込まれ, バッファはフラッシュされない. 第 2 引数が 2 の場合, 改行しないがバッファはフラッシュされる. この函数の戻り値は 0 であるから, print(); で実行すると, 出力の後に 0 が返される. print()$ とすれば, 最後の 0 は出力されない.

• 複数の obj を同時に出力したい時は obj をリストにするとよい． mycat(), mycat0() を参照．

[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(file)

:: file の存在をテストし，存在すれば 1，存在しなければ 0 を返す

160. remove file(file)

:: file を消去する

161. open file("filename" [,"mode"])

:: filename をオープンする

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() でクローズする. 特別なファイル

名 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 */

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: first order formula 15: matrix over GF (p) 16: ビット列

• 数の型を求めるには, ntype() を用いる. 不定元の型を求めるには, vtype() を用いる.

168. ntype(num)

:: num (数) の型 (整数) を返す. 数の型の値は 0: 有理数 1: 倍精度浮動小数 2: 代数的数 3: 任意精度浮動小数 (bigfloat) 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);
2
171. functor(func)

:: func の函数子を取り出す

172. args(func)

:: func の引数リストを取り出す

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");
1
176. remove module(name)

:: モジュール name を削除する • 削除に成功すれば 1, 失敗すれば 0 を返す．

[0] remove_module("gr");

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) を倍精度浮動小数で求める

182. dtan(num)

:: 函数値 tan(num) を倍精度浮動小数で求める

• これらの函数は C 言語の標準数学ライブラリを用いる. したがって, 計算結果はオペレーティングシステムとコンパイラに依存する.

• 複素数に対しては正しくない結果を返すので注意しなければならない.

• @pi などのシンボルを引数に与えることはできない.

 [0] 4*datan(1);
 3.14159

183. dabs(num) :: 絶対値 |num| を倍精度浮動小数で求める

184. dexp(num) :: 函数値 exp(num) を倍精度浮動小数で求める

185. dlog(num) :: 対数値 log(num) を倍精度浮動小数で求める

186. dsqrt(num)

:: 平行根\sqrt{num} を倍精度浮動小数で求める

• これらの函数は C 言語の標準数学ライブラリを用いる. したがって, 計算結果はオペレーティングシステムとコンパイラに依存する.

• dabs() と dsqrt() を除き、複素数に対しては正しくない結果を返すので注意しなければならない.

• @pi などのシンボルを引数に与えることはできない

 [0] dexp(1);
 2.71828

187. ceil(num) :: num 以上の最小の整数を求める

 [0] dceil(1.1);
 1
188. 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 の偏角を与える（−π < 戻り値 ≤ π）

[0] pari(arg,1+@i);
0.78539816339744830961566084581
195. pari(gamma,num[,prec])

:: ガンマ関数（num は複素数でもよい）

196. pari(gamh,num[,prec]) :: Γ(num + \frac{1}{2}) （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) = \frac{Γ′(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) erfc(x) = \frac{2}{\sqrt{π}} ∫_{x}^{∞} e^{−t^{2}}dt = 1 − erc(x)

[0] pari(erfc,1);
0.15729920705028513139
200. pari(dilog,num[,prec])

:: dilogarithm 関数 Li_{2}(x) = ∑_{k=1}^{∞} \frac{x^{k}}{k^{2}}

[0] pari(dilog,1);
1.64493406684822643609
201. pari(eta,τ[,prec])

:: Dedekind の Eta 関数 η(τ) で τ は虚部が正の複素数 η(τ) = e^{\frac{πiτ}{12}} ∏_{m=1}^{∞}(1 − e^{2πimτ})

[0] pari(eta,1/2*@i+1/3);
(1.0225406050061628844976445066022-0.035807228435521009596*@i)

202. pari(wp,τ[,prec])

:: Weber 関数 𝔣(τ) で τ は虚部が正の複素数 𝔣(τ) = e^{\frac{−2πiτ}{48}} \frac{η( \frac{τ+1}{2} )}{η(x)}

203. pari(wp2,τ[,prec])

:: Weber 関数 𝔣_{2}(τ) で τ は虚部が正の複素数 𝔣_{2}(τ) = \sqrt{2}\frac{η(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(τ) で τ は虚部が正の複素数 j(τ) = 1728\frac{g_{2}^{2}}{g_{2}^{3}−27g_{3}^{2}} g_{2} = 60 ∑_{(m,n)≠(0,0)}(m + nτ)^{−4}, g_{3} = 140 ∑_{(m,n)≠(0,0)}(m + nτ)^{−6}

[0] pari(jell,1/3+1/2*@i);
(6087.61214259402217852112-2773.38047013180067823512*@i)
205. pari(zeta,s[,prec])

:: Riemann の ζ 関数 ζ(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() が返した番号を指定する. (一番身近に作られ,

かつアクティブなプロセスに対応する番号.) 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 列と二分法により, 区間内の零点の個数を正確に求めていくもので, デフォルトの計算法よりも正確な描画が期待できる. ただし, 描画時間は余計にかかる場合が多い. この説明から明らかなように, この機能は有理数係数の多項式の描画に対してのみ有効である（(x^{2} + 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])

:: 描画用ウィンドウ (キャンバス) を生成する

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);

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 (2^{deg}(defpoly2 mod 2)) = GF (2)[t]/(defpoly2(t) mod 2) を基礎体として設定する.

• 引数が defpolyp と p の時, GF (p^{deg}(defpolyp)) を基礎体として設定する.

• 引数が p と n の時, GF (p^{n}) を基礎体として設定する. p^{n} は 2^{29} 未満でなければならない. また, p が 2^{14} 以上のとき, n は 1 でなければならない.

• 無引数の時, 設定されている基礎体が GF (p) の場合 p, GF (2^{n}) の場合定義多項式を返す. 基

   礎体が setmod ff(defpoly,p) で定義された GF (p^{n}) の場合, [defpoly,p] を返す. 基礎体
   が setmod ff(p,n) で定義された GF (p^{n}) の場合, [p,defpoly,prim elem] を返す. ここで,

defpoly は, n 次拡大の定義多項式, prim elem は, GF (p^{n}) の乗法群の生成元を意味する.

• GF (2^{n}) の定義多項式は, 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 (2^{n}) なら 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();
3
[3] setmod_ff(x^2+x+1);
x^2+x+1
[4] field_order_ff();
4
218. characteristic ff()

:: 設定されている体の標数 GF (p) の場合 p, GF (2^{n}) の場合 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 (2^{n}) の場合 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+1
[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);
@_1
221. 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+1
[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(@@);
0
223. ntogf2n(m)

:: 自然数を GF (2^{n}) の元に変換 m 非負整数

• 自然数 m の 2 進表現 m = m_{0} + m_{1}2 + ⋯ + m_{k}2^{k} に対し, GF (2^{n}) = GF (2)[t]/(g(t)) の元 m_{0} + m_{1}t + ⋯ + m_{k}t^{k} 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 (2^{n}) の元を自然数に変換 m GF (2^{n}) の元

• 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 (2^{n}) の元に変換 poly 一変数多項式

• poly の表す GF (2^{n}) の元を生成する. 係数は, 2 で割った余りに変換される. poly の変数に @ を代入した結果と等しい.

 [0] setmod_ff(x^30+x+1);
 x^30+x+1
 [1] ptogf2n(x^100);
 (@^100)
226. gf2ntop(m,[v])

:: GF (2^{n}) の元を多項式に変換 m GF (2^{n}) の元 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^10
227. ptosfp(p)

:: 小標数有限体への変換

228. sfptop(p)

:: 小標数有限体からの変換 p 多項式

• ptosfp() は, 多項式の係数を, 現在設定されている小標数有限体 GF (p^{n}) の元に直接変換する. 係数が既に有限体の元の場合は変化しない. 正整数の場合, まず位数で剰余を計算したあと, 標数 p により p 進展開し, p を x に置き換えた多項式を, 原始元表現に変換する. 例えば, GF (3^{5}) は GF (3)[x]/(x^{5} + 2x + 1) として表現され, その各元は原始元 x に関するべき指数 k により @ k として表示される. このとき, 例えば 23 = 2 · 3^{2} + 3 + 2 は, 2x^{2} + x + 2 と表現され, これは結局 x^{17} と法 x^{5} + 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);
23
229. defpoly mod2(d)

:: GF (2) 上既約な d 次の一変数多項式の生成 d 正整数

• fff で定義されている.

• 与えられた次数 d に対し, GF (2) 上 d 次の既約多項式を返す.

• もし既約 3 項式が存在すれば, 第 2 項の次数がもっとも小さい 3 項式, もし既約 3 項式が存在しなければ, 既約 5 項式の中で, 第 2 項の次数がもっとも小さく, その中で第 3 項の次数がもっとも小さく, その中で第 4 項の次数がもっとも小さいものを返す.

230. sffctr(poly)

:: 多項式の小標数有限体上での既約分解 poly 有限体上の多項式

• 多項式を, 現在設定されている小標数有限体上で既約分解する.

• 結果は, [[f_{1},m_{1}],[f_{2},m_{2}],...] なるリストである. ここで, f_{i} は monic な既約因子, m_{i} はその重複度である.

    [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 で定義されている.

• 一変数多項式を, 現在設定されている有限体上で既約分解する.

• 結果は, [[f_{1},m_{1}],[f_{2},m_{2}],...] なるリストである. ここで, f_{i} は monic な既約因子, m_{i} はその重複度である.

• 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);

233. 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();
[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(p_{1},p_{2},ec)

:: 楕円曲線上の点の加算

235. ecm sub ff(p_{1},p_{2},ec)

:: 楕円曲線上の点の減算

236. ecm chsgn ff(p_{1})

:: 楕円曲線上の点の逆元 p_{1} p_{2} 長さ 3 のベクトルまたは 0 ec 長さ 2 のベクトル

• 現在設定されている有限体上で, ec で定義される楕円曲線上の点 p_{1}, p_{2} の和 p_{1} + p_{2}, 差 p_{1} − p_{2}, 逆元 −p_{1} を返す.

• ec は, 設定されている有限体が奇標数素体の場合, y^{2} = x^{3} + ec[0]x + ec[1], 標数 2 の場合 y^{2} + xy = x^{3} + ec[0]x^{2} + ec[1] を表す.

• 引数, 結果ともに, 無限遠点は 0 で表される.

• p_{1}, p_{2} が長さ 3 のベクトルの場合, 斉次座標による曲線上の点を表す. この場合, 第 3 座標は 0 であってはいけない.

• 結果が長さ 3 のベクトルの場合, 第 3 座標は 0 でないが, 1 とは限らない. アフィン座標による結果を得るためには, 第 1 座標, 第 2 座標を第 3 座標で割る必要がある.

• p_{1}, p_{2} が楕円曲線上の点かどうかのチェックはしない.

[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);

[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 を生成 • 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#0
241. 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));
(-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]);
x^12+2*x^8+5*x^4+1

246. 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=[A_{n},...,A_{1}] と書くとき, 各 A_{k} は, それより右にある代数的数を係数とした, モニックな定義多項式で定義されていなければならない.

• 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() は, [[v_{n},d_{n}(v_{n},...,v_{1})],...,[v_{1},d_{1}(v_{1})]] なるリストである. ここで d_{i}(v_{i},...,v_{1}) は a_{i} の定義多項式において代数的数を全て v_{j} に置き換えたものである.

[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) に置き換えられる. これにより, 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+54

251. 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]);
0
252. 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() は簡単化された結果を返す.

•

[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 は 2^{27} 未満の素数） .

• 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
[76] (G[0]*24628-GM[0])%31991;
0

260. 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
[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);
1

265. 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)

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() と同様のチェックが行われる.

• 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() を呼び出し, 変数順序型を設定する. この設定は, 計算終了後も生き残る.

• 分散表現多項式の四則演算も, 設定されている値を用いて計算される. 従って, その多項式が生成された時点における変数順序型が, 四則演算時に正しく設定されていなければならない. また, 演算対象となる多項式は, 同一の変数順序型に基づいて生成されたものでなければならない.

• トップレベル函数以外の函数を直接呼び出す場合には, この函数により変数順序型を正しく設定しなければならない.

[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>>
 +(z^2)*<<0,0>>
 [54] P=dp_dtop(T,[a,b]);
 z^2+(2*a+2*b)*z+a^2+2*b*a+b^2

293. 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>>

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
456775930005716505560062087150928400876150217079820311439477560587583
488*u4^15+...
[80] @78==@79;
1

305. 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);
3

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)

:: 係数のビット長の和を返す

• 分散表現多項式の係数に現れる有理数につき, その分母分子 (整数の場合は分子) のビット長の総和を返す.

• 対象となる多項式の大きさの目安として有効である. 特に, 0 次元システムにおいては係数膨張が問題となり, 途中生成される多項式が係数膨張を起こしているかどうかの判定に役立つ.

• dp gr flags() で, ShowMag, Print を on にすることにより，途中生成される多項式にたいする dp mag() の値を見ることができる.

[221] X=dp_ptod((x+2*y)^10,[x,y])$
[222] dp_mag(X);
115

318. 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)

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];
1

326. 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);
1
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 に格納されている.

• 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 の共通部分を計算することによる early termination を行う. 一般に, イデアルの次元が高い場合に有効だが, 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 の, ウェイト 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 で決まるため, 相手先のマシンとバイトオーダが異なっていても構わない.

• 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);

0

343. 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 が動いていない場合, 自動的に 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);
6
344. 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() などで用いるプロセス識別子を返す.

• 遠隔プロセスの起動は, 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);
0
349. 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 プロトコルでサポートされているデータのみを送ることができる.

• 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);
141

353. 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.
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)

:: プロセス識別子 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);
123

363. 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);
6

364. 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();

[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);
[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)

:: 送信バッファの強制 flush • 通常はバッチモードは off であり, データ, コマンド送信ごとに送信バッファは flush される.

• バッチモードは ctrl コマンドの ox_batch スイッチで on/off できる.

• 細かいデータを多数送る場合に, ctrl("ox_batch",1) でバッチモードを on にすると, バッファがいっぱいになった場合にのみ flush されるため, overhead が小さくなる場合がある. ただしこの場合には, 最後に ox flush(id) を実行して, バッファを強制的に flush する必要がある.

• ox_pop_cmo(), ox_pop_local() のように, コマンド送信後ただちにデータ待ちに入る関数がハングしないよう, これらの関数の内部では強制 flush が実行されている.

[340] ox_launch_nox();
0
[341] cputime(1);
0
7e-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] 1
9.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,
 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, off は 0 を意味する. cputime on の時 CPU time および GC time を表示, off の時表示しない. ctrl("cputime",onoff)

    は cputime(onoff) と同じである.

nez EZGCD のアルゴリズムの切替え. デフォルトで 1 であり, とくに切替える必要はない. echo on の時は標準入力を繰り返して出力し, off の時は標準入力を繰り返さない. output コマンドを

用いる際に有効である. bigfloat on の時, 入力された浮動小数は bigfloat に変換され, 浮動小数演算は PARI により行われる.

デフォルトの有効桁数は 9 桁である. 有効桁数を増やしたい時には setprec() を用いる. off の時, 入力された浮動小数は, 倍精度浮動小数に変換される.

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 のとき, 送信バッファがいっぱいになった時のみ自動的に flush. 0 のとき, データ, コマン

ド送信毎に flush. (デフォルト値は 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));
     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 時間を表示する • 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(onoff)

:: 引数が 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, off は, 単に表示の on, off であり, トップレベルの一つの文に対する計測は常に行われている. よって, 計算を始めてからでも, 計算終了前にデバッガに入って 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)

:: 制限時間つきで計算を実行する

• 時間を指定して計算を実行する. 指定時間内に計算が完了した場合その値を返す. 指定時間内に計算が完了しなかった場合, 第 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();
524288
0msec
[99] fctr(Wang[8])$
3.190sec + gc : 3.420sec
[100] heap();
1118208
0msec
[101] quit;
% asir
[0] load("fctrdata")$
0
[97] cputime(1)$
0msec
[98] heap();
827392
0msec
[99] fctr(Wang[8])$
3.000sec + gc : 1.180sec
[100] heap();
1626112
0msec
[101] quit;
378. version()

:: Asir のバージョン（整数）を返す.

[0] version();
991214

379. shell(command)

:: command をシェルコマンドとして実行する

• command を C の system() 函数によりシェルコマンドとして実行する. シェルの終了ステータスを返す．

[0] shell("ls");
alg           da            katsura       ralg          suit
algt          defs.h        kimura        ratint        test
alpi          edet          kimura3       robot         texput.log
asir.o        fee           mfee          sasa          wang
asir_symtab   gr            mksym         shira         wang_data
base          gr.h          mp            snf1          wt
bgk           help          msubst        solve

chou          hom           p             sp
const         ifplot        proot         strum
cyclic        is            r             sugar
0

380. map(function,arg0,arg1,...)

:: リスト, 配列の各要素に函数を適用する

• arg0 の各要素を最初の引数, arg1 以下の残りの引数として函数 function を呼び出し, arg0 の対応する要素の位置に函数呼び出しの結果が入った同じ型のオブジェクトを生成して返す.

• function は, ダブルクォートのない函数名を用いる.

• function にプログラム変数は使えない.

• arg0 がリスト, ベクトル, 行列以外の場合, 単に arg0, arg1, ... を引数として function を呼び出しその結果を返す.

• map の引数 function で与えられる函数は, 内部的にも函数として実装されていなければならない. そうでなければ 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;
0
383. 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() が返した値の型を 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]
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 x^{2} + y^{2}

参照： mysubst(), mulsubst(), psubst()
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)

:: 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);
1
25. number imaginary part(X)

::

[0] number_imaginary_part(1+2*@i);
2
26. number is integer(X)

::

[0] number_is_integer(2/3);
0
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 ]
[ 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*y
36. 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 MX = 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 defined 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]]]
参照： 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 file.

[0] print_dvi_form(x^2-1);
46. print gif form(S| table=key_{0})

:: It outputs S to a file 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 file of the format png. dvipng should be installed.

 [0] print_png_form(x^3-1);
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 L^{A}TEX 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 file and previews the file 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=key_{0}, format=key_{1})

:: It transforms S to a gif file and previews the file 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 for

    xv (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=key_{0},mode=key_{1})

:: It outputs the object Obj to a file This function allows optional variables file, mode • If the optional variable file is set, then it outputs the Obj to the specified file, else it outputs

it to ”asi output tmp.txt”.

• If the optional variable mode is set to "w", then the file is newly created.

• If the optional variable is not set, the Obj is appended to the file.

 [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));

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=key_{0},v=key_{1},homo=key_{2},grace=key_{3},strategy=key_{4})

:: 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 of variables which defines 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=key_{0},v=key_{1})

:: It returns the Grobner basis of I.

This function allows optional variables order, v

• The optional variable v is a list of variables which defines 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=key_{0},v=key_{1})

:: 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.

[0] poly_hilbert_polynomial([x1*y1,x1*y2,x2*y1,x2*y2]|s=k,v=[x1,x2,y1,y2]);
64. poly in(I|order=key_{0},v=key_{1})

:: 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=key_{0},v=key_{1})

:: 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=key_{0},v=key_{1})

:: It computes the coefficients 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 specified 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=key_{0},order=key_{1},v=key_{2})

:: 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=key_{0},v=key_{1})

:: 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| = |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=key_{0},weight=key_{1},gb=key_{2})

:: 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=key_{0})

:: 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=key_{0},w=key_{1},truncate=key_{2})

:: 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])

returns a series expansion in terms of x and y.

76. poly toric ideal(A,V)

:: It returns generators of the affine toric ideal defined by the matrix(list) A. V is the list of variables.

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 Grobner basis 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 coefficient 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);

3.4.6 グラフィックライブラリ（2 次元）ライブラリ glib は, Risa/Asir のグラフィック基本関数 (draw obj()) に対する, 昔の BASIC のような単純なインタフェースを提供する.

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(X_{min},Y_{min},X_{max},Y_{max})

:: It generates a window with the left top corner [X_{min},Y_{min}] and the right bottom corner [X_{max},Y_{max}]. 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=key_{0})

:: 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(X_{0},Y_{0},X_{1},Y_{1}|color=key_{0},shape=key_{1})

:: It draws the line [X_{0},Y_{0}] – [X_{1},Y_{1}] 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=key_{0})

:: 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()

:: 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 file 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.

[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 file $TMP/abc* is generated with the contents Hello world! and copied to

$TMP/result*

The contents of the file 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 Differential equations (by Okutani)

ファイル `gr', `Matrix', `Diff' が必要です.
OpenXM/Risa/Asir での利用にあたっては,
[0] load("Diff")$

が始めに必要. Yukio Okutani 氏による Risa/Asir 言語で書かれた連立線形偏微分方程式用のライブラリです. すべての関数名は odiff_で始まります.

102. odiff op appell4(a,b,c_{1},c_{2},V)

:: Appell の F_{4} を零化する微分作用素を生成します.

[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(D_{list},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]]]]
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^2
107. odiff act appell4(a,b,c_{1},c_{2},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,c_{1},c_{2},V)

:: F_{4} がみたす線型微分方程式系の多項式解を求める

[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]]
[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(D_{list},V)

:: asir の多項式からリスト形式の微分作用素リストに変換します

この関数は 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(D_{ideal},V)

:: D_{ideal} の characteristic ideal を求めます D_{ideal} は 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(D_{ideal},V,Rest)

:: D_{ideal} の 0 次の restriction を求めます D_{idea}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(D_{ideal},V,Elim)

:: D_{ideal} の elimination ideal を求めます D_{idea}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, ⋮ をそれぞれ 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 は変数の集合. 戻り値は次の形をしている: [[e_{1}, e_{2},...], [s_{1}, s_{2}, ...]]. ここで e_{1} は exponent ベクトルであり s1 はこのベクトルに対応する解の集合, 以下同様.

• 変数 Dsolv_message_starting_term を 1 にしておくと, この函数は計算の途中にいろいろとメッセージを出力する.

• Algorithm: Saito, Sturmfels, Takayama, Grobner Deformations of Hypergeometric Differential 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]);
[[[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:~$ asir
This 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);   (CFL number is 0.4)
 gnuplot.set_heat_N(20); gnuplot.heat(0.003,30);   (CFL > 0.5 unstable)

Author of GNUPLOT: Thomas Williams, Colin Kelley

120. 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 は長い多項式を正しく受けつけない.

• 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 ");
0
参照 : gnuplot.start(), plot ”fileName” with options(GNUPLOT command), gnuplot.clean,
gnuplot

123. gnuplot.heat(dt,step) :: 熱伝導方程式を数値的に解く

• 熱伝導方程式 du/dt = d^{2}u/dx^{2}, 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);

 [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 mkfifo, but we need a patched version of gnuplot.

 [0] gnuplot.setenv("gnuplot.callingMethod",0);
 [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()

3.4.14 _{p}F_{q} に関するコホモロジーこの節では超幾何関数_{p}F_{q} の (コ) ホモロジ群に関連した不変量を計算する関数を解説する.

OpenXM/Risa/Asir での利用にあたっては,
 load("pfpcoh.rr")$ load("pfphom.rr")$

が始めに必要.

128. pfp omega(p)

: It returns the Gauss-Manin connection Omega for the generalized hypergeometric function pF_{p−1}(aa_{1}, aa_{2}, …; cc_{1}, cc_{2}, …; x)

• Define a vector valued function Y of which elements are generalized hypergeometric function f_{1} = F and f_{2} = xdf_{1}/dx, f_{3} = xdf_{2}/dx, …

• It satisfies dY/dx = ΩY.

• Generalized hypergeometric function is defined by the series

pF_{p−1}(aa_{1}, aa_{2}, …; cc_{1}, cc_{2}, …; x) = ∑_{k=0}^{∞} \frac{(aa_{1})_{k}(aa_{2})_{k} ⋯}{(1)_{k}(cc_{1})_{k}(cc_{2})_{k} ⋯}x^{k}

 pfp_omega(3);
129. pfpcoh intersection(p)

:: returns an intersection matrix for cocycles associated to the generalized hypergeometric function pF_{p−1}. This program pfpcoh.rr computes an intersection matrix S of cocycles of _{p}F_{p−1} and compares it with the matrix obtained by solving a differential equation for intersection matrix. Algorithm: Ohara, Sugiki, Takayama, Quadratic Relations for Generalized Hypergeometric Functions _{p}F_{p−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}F_{p−1}.

• As to the meaning of parameters c_{1}, c_{2}, c_{3}, … see the paper Ohara, Kyushu J. Math. Vol. 51 PP.123.

• Algorithm: Ohara, Sugiki, Takayama, Quadratic Relations for Generalized Hypergeometric Functions _{p}F_{p−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)

[0] MP = pfphom_monodromy_pair_kyushu(3)$

You get a pair of monodromy matricies for _{3}F_{2} 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:~$ asir
This 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 は代数方程式系を解くためにいろいろな戦略をえらぶことができるが, このインタフェース関数では, 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 by homotopy 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 は微分作用素環で計算するためのシステムである. 計算代数幾何のいろいろな不変量の計算が微分作用素の計算に帰着する. sm1 についての文書は OpenXM/doc/kan96xx にある. とくに断りがないかぎりこの節のすべての関数は, 有理数係数の式を入力としてうけつけない. すべての多項式の係数は整数でないといけない.

nobuki@yama:~$ asir
This 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 Hypergeometric Differential 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
参照 ox launch(), sm1.push int0(), sm1.push poly0(), ord
137. 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]
Reference
ox_push_cmo
139. sm1.gb([f,v,w]|proc=p,sorted=q,dehomogenize=r)

:: v 上の微分作用素環において f のグレブナ基底を計算する

140. sm1.gb d([f,v,w]|proc=p)

:: v 上の微分作用素環において f のグレブナ基底を計算する. 結果を分散多項式のリストで戻す.

• 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)

:: 空間 ℂ^{n} − (the zero set of f = 0) で前命題のドラームコホモロジ群の次元を計算してくれるようにサーバに頼む.

• この函数は空間 X = C^{n} \ V (f) のドラームコホモロジ群の次元を計算する. すなわち, [dim H^{0}(X, ℂ), dim H^{1}(X, ℂ), dim H^{2}(X, ℂ), …, dim H^{n}(X, ℂ)] を戻す.

• 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 complement of an affine 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) = dim_{ℚ}(F_{k}/I ∩ F_{k})

ここで F_{k} は次数が 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>>]
[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 の左イデアルであっても, 一般に, 出力は自由加群 D^{r} の部分加群である.

[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 =[g_{1}, ..., g_{m}] であり, c_{0}f + c_{1}g_{1} + ⋯ + c_{m}g_{m} = r がなりたつ. r/c_{0} が 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 を前置記法になおす • この函数は 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]);
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 に ff の distraction を計算してもらう • 識別子 p の sm1 サーバに, f の distraction を v 上の微分作用素環で計算してもらう.

• x, d は, それぞれ, distract すべき x 変数, d 変数のリスト. Distraction したら, s を変数として結果を表す.

• Distraction というのは x*dx を x で置き換えることである. 詳しくは Saito, Sturmfels, Takayama : Grobner Deformations of Hypergeometric Differential 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)

:: F_{1} または F_{D} に対応する方程式系を戻す

• Appell の関数 F_{1} およびその n 変数化である Lauricella の関数 F_{D}(a, b_{1}, b_{2}, …, b_{n}, c; x_{1}, …, x_{n}) のみたす微分方程式系を戻す. ここで, a = (a, c, b_{1}, …, b_{n}). パラメータは有理数でもよい.

• 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,
 (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]));
4
152. sm1.appell4(a|proc=p)

:: F_{4} または F_{C} に対応する方程式系を戻す

• Appell の関数 F_{4} およびその n 変数化である Lauricella の関数 F_{C}(a, b, c_{1}, c_{2}, …, c_{n}; x_{1}…. , x_{n}) のみたす微分方程式系を戻す. ここで, a = (a, b, c_{1}, …, c_{n}).

• 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(@);
5
154. sm1.auto reduce(s|proc=p)

:: フラグ ”AutoReduce” を s に設定 • s が 1 のとき, 以後計算されるグレブナ基底はすべて, reduced グレブナ基底となる.

• s が 0 のとき, 計算されるグレブナ基底は reduced グレブナ基底とはかぎらない. こちらがデ

フォールト.

155. sm1.slope(ii,v,f_{filtration},v_{filtration}|proc=p)

:: 微分方程式系 ii の slope を戻す

• 微分方程式系 ii の V filtratio v_{filtration} で指定する超平面に沿っての (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]$
[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 the generators 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 algorithm h[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);
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 D_{alg} (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=key_{0})

:: It computes the restriction of I as a D-module to the set defined 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)$
 [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 個のグレブナ基底がある. [[i_{1}, i_{2}, …],[j_{1}, j_{2} …]] は二つのモノミアルの exponent をならべたものであり, 2 項式をあらわす. たとえば, S[0] は次の多項式の

集合{x1 x3 - x2^2, x1 x4 - x2 x3, x2 x4 - x3^2} であり, <x1 x3, x1 x4, x2 x4> がその

initial ideal である.

3.4.19 Mathematica 函数

この節では Mathematica の ox サーバ ox math とのインタフェース関数を解説する. これらの関数はファイル `m' で定義されているのでこのファイルを

 [0] load("m")$
でこのファイルをロードしてから使用しないといけない. `m' は `$(OpenXM HOME)/lib/asir-contrib'

にある. 注意: ox reset は動かない.

nobuki@yama:~$ asir
This 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.
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 の行

列を 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 file F as a string.

179. util read file as a string(F)

:: It reads a file F as a string.

180. util write string to a file(Fname,S)

:: It writes a string S to a file Fname.

参照： fcat()
181. util filter(Command,Input|env=key_{0})

:: It executes the filter program Command with the Input and returns the output of the filter 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.

• 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"));
 1
184. 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=key_{0})

:: It tries to find 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)

:: 有理曲線のパラメータ表示をみつける

• パッケージ 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)]

参考文献

[Apéri] R. Apéry, Irrationalité de ζ(2) et ζ(3), Journées arithmétiques de Luminy, Asté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

Painlevé-type equations, MSJ Memoirs vol.37, Mathematical Society of Japan, 2018. [Hiroe-Oshima] K. Hiroe and T. Oshima, A classification of roots of symmetric Kac-Moody root systems

and its application, Symmetries, Integrable Systems and Representations, Springer Proceedings in Mathematics and Statistics 40 (2012), 195–241.

[Morier-Genoud and Ovsienko] S. Morier-Genoud and V. Ovsienko, q-deformed rationals and q-

continued 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 honor of Roger Howe, Vol. 12, Lecture Notes Series, 2007, 277-319, National University of Singapore.

[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 differential 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 Kôkyûroku Bessatsu B61 (2017), 141–162.

[O6] T. Oshima, os muldif.rr, a library of the calculation of differential 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 Diff. Equations, Springer Proceedings in Mathematics and Statistics 256(2018) 189-199,

[O8] 大島利雄，個数を数える, 数学書房, 2019, 226 pp.

[O9] T. Oshima, Confluence and versal unfolding of Pfaffian systems, Josai Mathematical Journal 12(2020), 117–151.

[O10] T. Oshima, Versal unfolding of irregular singularities of a linear differential equation on the Riemann sphere, Publ. RIMS Kyoto Univ. 57 (2021), 893–920.

[OSe] T. Oshima and J. Sekiguchi, Eigenspaces of invariant differential operators on an affine symmetric spaces, Invent. Math. 57(1980), 1–81.

[OSh] T. Oshima and N. Shimeno, Heckman-Opdam hypergeometric functions and their specializations, RIMS Kôkyûroku Bessatsu B20 (2010), 129–162.

[Saito-Sturmfels-Takayama] M. Saito, B. Sturmfels, N. Takayama, Groebner deformations of hypergeometric differential equations, Algorithms and Computation in Mathematics 6, Springer-Verlag (2000).

[Shimoyama-Yokoyama] T. Shimoyama, K. Yokoyama, Localization and primary decomposition of poly-

nomial 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.

[Traverso] C. Traverso, Groebner trace algorithms, Proc. ISSAC ’88(LNCS 358), 125-138.

[Yokoyama] K. Yokoyama, Prime decomposition of polynomial ideals over finite fields, Proc. ICMS, (2002), 217–227.

[Weber] K. Weber, The accelerated Integer GCD Algorithm, ACM TOMS, 21, 1(1995), 111–122.

索引

1–2. Functions in os muldif.rr, 6, 99 1.1 Fundamental Function, 6, 99 1.2 Fractional calculus, 7, 118 1.3 Some operators, 9, 171 2.1 Extended function, 10, 174 2.2 Numbers, 12, 197 2.3 Polynomials and rational functions, 14, 209 2.4 Functions with real/complex variables, 16, 245 2.5 List and vectors, 17, 248 2.6 Matrices, 19, 266 2.7 Strings, 21, 289 2.8 Permutations, 22, 298 2.9 TEX, 22, 302 2.10 Lines and curves, 23, 316 2.11 Drawing curves and graphs, 25, 341 2.12 Applications, 26, 375 2.12.1 表の作成, 375 2.12.2 表や行列の変形, 377 2.12.3 函数値の数表, 379 2.12.4 点数分布表, 381 2.12.5 Taylor 展開, 382 2.12.6 計算尺, 384 2.13 Environments, 26, 387 2.14 補足, 396 2.14.1 行列の入力, 396 2.14.2 平面図形, 398 2.14.3 リスト形式函数, 403 2.14.4 函数値の解析, 406

3. Functions in the original library, 27, 410 3.1 数の演算, 27, 410 3.2 多項式，有理式の演算, 29, 418 3.3 リスト，ベクトル，配列の演算, 31, 431 3.4 行列の演算, 32, 434 3.5 文字列に関する演算, 32, 439 3.6 構造体に関する函数, 33, 441 3.7 入出力, 33, 444 3.8 型や函数，モジュールに関わる函数, 34, 448 3.9 数値函数, 34, 450 3.10 描画函数, 35, 452 3.11 有限体に関する函数, 36, 455 3.12 代数的数に関する函数, 37, 462 3.13 グレブナー基底に関する函数, 37, 466 3.14 分散計算に関する関数, 40, 480 3.15 その他の函数, 41, 488

4. Functions in the contributed library, 42, 494 4.1 基礎 (標準関数), 42, 494 4.2 数（数学標準関数） , 43, 497 4.3 行列（数学標準函数） , 43, 498 4.4 表示（数学標準函数） , 44, 500 4.5 多項式（数学標準函数） , 45, 502 4.6 グラフィックライブラリ（2 次元） , 46, 506 4.7 OpenXM-Conrib 一般函数, 46, 507 4.8 OXShell の関数, 46, 507 4.9 OpenMath 函数, 47, 508 4.10 Differential equations (by Okutani), 47, 509 4.11 D-module (by Okutani), 47, 511 4.12 DSOLV 函数, 47, 513 4.13 GNUPLOT 函数, 48, 514 4.14 _{p}F_{q} に関するコホモロジー, 48, 517 4.15 PHC 函数, 48, 518 4.16 Plucker 関係式, 48, 520 4.17 SM1 函数, 48, 520 4.18 TIGERS 函数, 50, 531 4.19 Mathematica 函数, 50, 531 4.20 便利な関数, 50, 533 4.21 その他, 51, 535

%, 425 .asirrc, 97 .muldif, 391 abs, 197 access, 446 ad, 118 add, 118 addIL, 262 addl, 118 adj, 102 af, 464 af noalg, 464 alg, 462 algptorat, 463 algtodalg, 465 algv, 462 AMSTeX, 388 anal2sp, 152 ann, 480 ann0, 480 append, 431 appldo, 102 appledo, 103 areabezier, 336 arfreg, 441 arg, 247 args, 449 asciitostr, 440 asq, 464 average, 250

b2e, 173 base cancel, 494 base choose, 494 base flatten, 494 base intersection, 494 base makelist, 495 base memberq, 495 base permutation, 495 base position, 495 base product, 495 base prune, 495 base rebuild opt, 496 base replace, 496 base replace n, 496 base set minus, 496 base set union, 496 base subsetq, 496 base subsets of size, 496 base sum, 496 base var list, 497 baseODE, 218 bernoulli, 244 bfct, 480 bfunction, 479 binom, 216 bload, 445 bsave, 445 btree, 259 c2m, 269 calc, 197 caldo, 100 call, 448 Canvas, 387 car, 431 catalan, 198 cdr, 431 ceil, 450 cfrac, 204 cfrac2n, 204 characteristic ff, 456 chkexp, 113 chkfun, 174 chkspt, 120 clear canvas, 454 close file, 447 cmpf, 188 cmpsimple, 182 coef, 419 cola, 437 colm, 437 colx, 437 compdf, 187 conf1sp, 142 confexp, 143 conj, 413 conplot, 452 cons, 431 cont, 426 cotr, 119 countin, 248 cputime, 490 cr gcda, 463 cterm, 228 ctrl, 488 currenttime, 491 cutf, 187 cyclic, 478

dabs, 450 dacos, 450 dalgtoalg, 466 dalgtodp, 466 darg, 317 dasin, 450 datan, 450 dceil, 450 dcos, 450 debug, 489 defpoly, 462 defpoly mod2, 460 deg, 419 delete history, 493 delopt, 249 det, 436 deval, 413 dexp, 450 dext, 317 df2big, 186 dfloor, 450 dform, 116 dgr, 466 diagm, 281 diff, 423 difflog, 230 digamma, 247 dilog, 247 DIROUT, 389 distpoint, 381 divdo, 103 divmattex, 315 dlog, 450 dlog10, 246 dn, 411 dnorm, 317 dp dehomo, 472 dp dtop, 472 dp etov, 475 dp f4 main, 469 dp f4 mod main, 469 dp gr f main, 469 dp gr flags, 470 dp gr main, 469 dp gr mod main, 469 dp gr print, 470 dp hc, 474 dp hm, 474 dp homo, 472 dp ht, 474 dp lcm, 475 dp mag, 476 dp mbase, 475 dp mod, 472 dp nf, 473 dp nf mod, 473 dp ord, 471 dp prim, 472 dp ptod, 471 dp ptozp, 472 dp rat, 472 dp red, 476 dp red mod, 476 dp redble, 475 dp rest, 474 dp set top weight, 471 dp set weight, 471 dp sp, 476 dp sp mod, 476 dp subd, 475 dp sugar, 474 dp td, 474 dp true nf, 473 dp true nf mod, 473 dp vtoe, 475 dp weyl f4 main, 469 dp weyl f4 mod main, 469 dp weyl gr f main, 469 dp weyl gr main, 469 dp weyl gr mod main, 469 dp weyl nf, 473 dp weyl nf mod, 473 dp weyl set weight, 471 dptodalg, 466 draw bezier, 351 draw obj, 454 draw string, 454 drint, 451 dsin, 450 dsolv dual, 513 dsolv starting term, 513 dsqrt, 450 dtan, 450 dupmat, 266 dvangle, 319 dviout, 304 dviout0, 304 DVIOUTA, 389 DVIOUTB, 370, 389, 392 DVIOUTH, 389 DVIOUTL, 389 dvprod, 251 dwinding, 318

easierpol, 214 ecm add ff, 461 ecm chsgn ff, 461 ecm sub ff, 461 end, 444 eofamily, 173 eqs2tex, 307 erfc, 245 error, 489 eta, 248 etos, 115 ev4s, 173 eval, 413 eval str, 440 evalcoord, 295 evalma, 296 evalred, 183 evals, 183 even4e, 172 execdraw, 371 execproc, 190 expat, 112 expower, 216 extdeg ff, 456 extra6e, 173

f2df, 185 fac, 411 fcat, 177 fcont, 196 fctr, 423 fctr ff, 460 fctri, 215 fctrtos, 223 field order ff, 456 field type ff, 455 fimag, 192 findin, 248 fint, 191 flim, 195 flist, 493 floor, 450 fmmx, 195 fmult, 181 fouriers, 245 fprintf, 446 frac, 245 frac2n, 208 fractrans, 112 fresidue, 196 fromeul, 112 fshorter, 194 fsum, 190 fuchs3e, 171 funargs, 449 functor, 449 fzero, 194

gamma, 247 gb comp, 477 gcd, 426 gcdz, 426 generate port, 482 generic bfct, 480 get byte, 447 get line, 447 get rootdir, 493 getbygrs, 129 getbyshell, 177 getCatalan, 199 getel, 182 getenv, 494 getline, 176 getopt, 494 getroot, 214 getSSE, 116 gf2nton, 458 gf2ntop, 459 ghg, 171 ghg2, 172 glib clear, 506 glib flush, 507 glib line, 506 glib open, 506 glib plot, 507 glib print, 506 glib ps form, 507 glib putpixel, 506 glib remove last, 507 glib set pixel size, 507 glib tops, 507 glib window, 506 gnuplot.gnuplot, 515 gnuplot.heat, 516 gnuplot.output, 516 gnuplot.plot dots, 515 gnuplot.plot function, 516 gnuplot.setenv, 517 gnuplot.start, 515 gnuplot.stop, 517 gr, 466 gr minipoly, 468 gr mod, 466

hcyclic, 478 heap, 491 hessian, 231 heun, 173 hgr, 466 hkatsura, 478

i2hex, 293 iand, 415 idiv, 410 ifplot, 452 igcd, 411 igcdcntl, 411 ilcm, 412 imag, 413 int32ton, 415 integrate, 233 intpoly, 232 inv, 412 invf, 226 invmat, 436 ior, 415 irem, 410 irredcheck ff, 460 isall, 175 isalpha, 198 isalphanum, 198 iscoef, 227 iscombox, 331 iscrat, 198 isdecimal, 198 isdif, 179 isfctr, 222 ishift, 416 isint, 197 isMs, 174 isnum, 198 isqrt, 412 israt, 198 isshortneg, 194 issquaremodp, 203 isvar, 178 isyes, 174 ixor, 415

jacobian, 231 jell, 248 jis2sjis, 293

katsura, 478 keyin, 176 kmul, 428 ksquare, 428 ktmul, 428 kzext, 168

l2min, 261 l2os, 295 l2p, 250 ladd, 316 laplace, 118 laplace1, 118 lbezier, 335 lchange, 252 lcount, 249 lcut, 248 ldev, 254 ldict, 298 length, 431 lex hensel, 467 lex tl, 467 lext2, 263 lft01, 169 lgcd, 253 linfrac01, 169 llbase, 251 llcm, 253 llget, 254 llselect, 254 llsize, 248 lmax, 253 lmin, 253 lmptop, 457 lngamma, 247 lninbox, 332 lnsol, 252 load, 444 lpair, 262 lpgcd, 231 lrandom, 412 lsol, 251 lsort, 255 lsub, 317 lsum, 252 ltotex, 307 ltov, 433 lv2m, 267

m1div, 105 m2l, 267 m2ll, 267 m2lv, 267 m2mc, 162 m2v, 267 madj, 281 madjust, 271 makenewv, 178 makev, 177 map, 493 mat, 435 matc, 435 mathematica.rtomstr, 533 mathematica.start, 532 mathematica.tree to string, 532 matr, 435 matrix, 434 matrix adjugate, 498 matrix clone, 498 matrix det, 499 matrix diagonal matrix, 499 matrix eigenavalues, 500 matrix identity matrix, 499 matrix image, 498 matrix inner product, 499 matrix inverse, 499 matrix kernel, 500 matrix list to matrix, 498 matrix matrix to list, 498 matrix rank, 500 matrix solve linear, 499 matrix submatrix, 499 matrix transpose, 499 mc, 118 mc2grs, 153 mce, 118 mcgrs, 128 mcmgrs, 166 mcolor, 341 mcop, 129 mcvm, 144 mdivisor, 105 mdsimplify, 287 meigen, 286 mext2, 288 mgen, 281 midKZ, 161 mindeg, 419 minipoly, 468 minipolym, 469 mmc, 168 mmod, 281 mmulbys, 181 modfctr, 425 module definedp, 449 module list, 449 monotos, 305 monototex, 305 mperm, 270 mpower, 271 mrot, 318 msort, 260 mt load, 412 mt save, 412 mtotex, 313 mtoupper, 272 mtransbys, 181 mtranspose, 270 muldo, 99 muledo, 100 mulpolyMod, 210 mulseries, 250 mulsubst, 180 my tex form, 302 myacos, 246 myarg, 246 myasin, 246 myatan, 246 mycat, 249 mycat0, 249 mycoef, 227 mycos, 246 mydeg, 226 mydet, 279 mydet2, 279 mydeval, 183 mydiff, 229 myediff, 229 myeval, 183 myexp, 246 myf2deval, 189 myf2eval, 189 myf3deval, 189 myf3eval, 189 myfdeval, 189 myfeval, 189 mygcd, 103 myhelp, 174 myimage, 280 myinv, 281 mykernel, 280 mylcm, 105 mylog, 246 mymindeg, 226 mymod, 281 mypdiff, 229 mypow, 246 myrank, 280 mysin, 246 mysubst, 179 myswap, 179 mytan, 246 mytrace, 279 myval, 184 n2a, 292 nd det, 436 nd f4, 469 nd f4 trace, 469 nd gr, 469 nd gr trace, 469 nd weyl gr, 469 nd weyl gr trace, 469 ndict, 299 newalg, 462 newbmat, 285 newbytearray, 433 newKZmat, 161 newmat, 434 newstruct, 441 newvect, 432 nextpart, 300 nextsub, 299 nlog, 246 nm, 411 nmono, 420 ntable, 379 nthmodp, 202 ntogf2n, 458 ntoint32, 415 ntype, 448 number abs, 497 number ceiling, 497 number factor, 497 number float to rational, 497 number floor, 497 number imaginary part, 498 number is integer, 498 number real part, 498

odd5e, 172 odiff act, 510 odiff act appell4, 510 odiff op appell4, 509 odiff op fromasir, 510 odiff op toasir, 510 odiff op tosm1, 509 odiff poly solve, 510 odiff poly solve appell4, 511 odiff poly solve hg1, 510 odiff rat solve, 511 odmodule ch ideal, 512 odmodule d op fromasir, 512 odmodule d op toasir, 512 odmodule d op tosm1, 511 odmodule elimination, 512 odmodule restriction, 512 okubo3e, 171 okuboetos, 113 om start, 508 om xml, 509 om xml to cmo, 509 open canvas, 454 open file, 446 openGlib, 341 ord, 420 orthpoly, 216 output, 444 ox asir, 483 ox check errors2, 507 ox cmo rpc, 484 ox execute string, 484 ox flush, 487 ox get, 486 ox get serverinfo, 487 ox intr, 484 ox launch, 480 ox launch generic, 482 ox launch nox, 480 ox pop cmo, 485 ox pop local, 485 ox pops, 486 ox push cmd, 485 ox push cmo, 485 ox push local, 485 ox reset, 484 ox rpc, 484 ox select, 486 ox shutdown, 480 ox sync, 485 oxshell.get value, 508 oxshell.oxshell, 508 oxshell.set value, 508

p nf, 477 p nf mod, 477 p terms, 477 p true nf, 477 p true nf mod, 477 paracmpl, 265 pari, 414

abs, 418 adj, 438 arg, 451 bigomega, 417 binary, 416 cf, 418 conj, 418 content, 430 dilog, 451 disc, 431 eigen, 439 erfc, 451 eta, 452 factor, 416 frac, 417 gamh, 451 gamma, 451 hess, 439 indexrank, 438 isprime, 417 ispsp, 417 issquare, 416 jacobi, 439 jell, 452 lngamma, 451 mu, 418 nextprime, 417 numdiv, 417 omega, 417 phi, 418 psi, 451 roots, 430 round, 430 sigma, 417 signat, 438 sqrt, 451 supplement, 438 trace, 438 wp, 452 wp2, 452 zeta, 452

partspt, 261 pcoef, 227 periodicf, 188 permanent, 280 pf2kz, 142 pfargs, 179 pfctr, 228 pfp omega, 517 pfpcoh intersection, 517 pfphom intersection, 518 pfphom monodromy pair kyushu, 518 pfrac, 230 pg2tg, 324 pgen, 210 pgpart, 325 phc.phc, 519 phc.start, 519 plot, 452 plotover, 452 plucker index, 520 plucker y, 520 pluspower, 250 pmaj, 228 pol2sft, 215 polarplo, 452 polbyroot, 210 polbyvalue, 210 polcut, 229 polinsft, 215 polinsym, 215 polinvsym, 215 polrealroots, 213 polroots, 213 polstrum, 212 poly coefficient, 506 poly degree, 503 poly elimination ideal, 502 poly expand, 502 poly factor, 502 poly gcd, 502 poly gr w, 504 poly grobner basis, 502 poly hilbert polynomial, 503 poly ideal colon, 505 poly ideal intersection, 505 poly ideal saturation, 506 poly in, 503 poly in w, 504 poly in w , 504 poly initial, 503 poly initial coefficients, 503 poly initial term, 503 poly ord w, 504 poly prime dec, 505 poly r omatrix, 504 poly solve linear, 505 poly sort, 505 poly toric ideal, 505 poly weight to omatrix, 505 powprimroot, 375 powsum, 244 prehombf, 232 prim, 426 primadec, 479 primedec, 479 primedec mod, 479 primroot, 203 print, 446 print dvi form, 500 print em, 500 print gif form, 500 print input form, 500 print open math tfb form, 502 print open math xml form, 501 print output, 501 print ox rfc100 xml form, 501 print png form, 501 print terminal form, 501 print tex form, 501 print tfb form, 501 print xdvi form, 501 print xv form, 501 printf, 446 psubst, 422 psymbol, 103 pt5center, 323 ptaffine, 319 pTaylor, 221 ptbbox, 331 ptbezier, 336 ptcombezier, 340 ptcombz, 340 ptcommon, 321 ptcontain, 324 ptconvex, 331 ptcopy, 321 pterm, 228 ptinversion, 323 ptlattice, 321 ptogf2n, 459 ptol, 230 ptosfp, 459 ptozp, 425 ptpolygon, 320 ptwindow, 331 ptype, 176 purge stdin, 447 put byte, 447 pweight, 229 pwTaylor, 239

qdo, 105 qsort, 434 qsortn, 254 quit, 444

r2ma, 296 r2os, 295 rabin, 204 radd, 209 random, 412 random ff, 457 randpoly ff, 461 rattoalgp, 463 rcotr, 119 readcsv, 297 readTikZ, 295 real, 413 red, 426 rede, 118 redgrs, 129 register handler, 484 register server, 482 regress, 251 remove file, 446 remove module, 449 res, 423 res0, 211 reverse, 431 rigid211, 172 rint, 451 risaout.tex, 391 risatex.bat, 391 rmul, 210 rootmodp, 203 rowa, 437 rowm, 437 rowx, 437 rpdiv, 211 rsort, 254 rtostr, 439 rtotex, 305 rungeKutta, 238

s2csp, 120 s2euc, 294 s2m, 268 s2os, 293 s2sjis, 294 s2sp, 119 sadj, 301 scale, 332 schurpoly, 217 sdiv, 420 sdivm, 420 seriesHG, 222 seriesMc, 217 seriesTaylor, 382 set field, 465 set upfft, 429 set upkara, 428 set uptkara, 428 setmod ff, 455 setmode, 415 setprec, 414 sexps, 301 sffctr, 460 sfptop, 459 sftexp, 112 sftpexp, 103 sftpow, 216 sftpowext, 216 sgn, 197 sgnstrum, 212 shell, 492 shiftop, 141 shiftPfaff, 141 shortv, 178 show, 303 showbyshell, 177 simp ff, 457 simpalg, 462 simplify, 182 sint, 207 sinv, 301 size, 433 sjis2jis, 293 sleep, 491 slen, 301 sm1.ahg, 528 sm1.appell1, 527 sm1.appell4, 527 sm1.auto reduce, 528 sm1.bfunction, 528 sm1.call sm1, 528 sm1.deRham, 523 sm1.distraction, 526 sm1.ecart homogenize01Ideal, 529 sm1.ecartd gb, 529 sm1.ecartd gb oxRingStructure, 529 sm1.ecartd isSameIdeal h, 529 sm1.ecartd reduction, 529 sm1.ecartd reduction noh, 529 sm1.ecartd syz, 529 sm1.gb, 522 sm1.gb d, 522 sm1.gb oxRingStructure, 530 sm1.gb reduction, 530 sm1.gb reduction noh, 530 sm1.generalized bfunction, 530 sm1.genericAnn, 524 sm1.gkz, 526 sm1.hilbert, 523 sm1.isSameIdeal in Dalg, 530 sm1.mul, 526 sm1.push int0, 521 sm1.rank, 527 sm1.reduction, 525 sm1.restriction, 530 sm1.saturation, 531 sm1.slope, 528 sm1.sm1, 521 sm1.start, 520 sm1.syz, 525 sm1.wTensor0, 524 sm1.xml tree to prefix string, 525 smallmattex, 316 soldif, 113 solpokubo, 116 solveEq, 217 sord, 301 sort2, 255 sp, 465 sp noalg, 465 sp norm, 463 sp2grs, 127 spantree, 260 spbasic, 125 spgen, 122 sprintf, 446 sprod, 300 sproot, 122 spslm, 140 sqfr, 423 sqr, 421 sqrm, 421 sqrt, 247 sqrt2rat, 207 sqrtdo, 111 sqrtrat, 206 srem, 420 sremm, 421 ssubgrs, 128 stoe, 114 str addc, 291 str char, 289 str chr, 440 str cut, 290 str insert, 291 str len, 440 str pair, 289 str str, 290 str subst, 291 str tb, 294 str times, 291 str type, 443 strip, 292 strtoascii, 440 strtov, 440 sub str, 441 subst, 422 substblock, 225 substnum, 180 symtournament, 201

taylorODE, 220

tdiv, 421 terms, 228 texbegin, 306 texcr, 306 TeXEq, 388 texket, 306 texlen, 316 TeXLim, 388 texlim, 316 TeXPages, 388 texsp, 306 tigers.tigers, 531 TikZ, 388 time, 490 timer, 491 tobezier, 334 tobig, 202 tocsv, 298 todf, 186 todo parametrize, 535 toeul, 111 tohomog, 225 tolex, 467 tolex d, 467 tolex tl, 467 tolexm, 468 translpdo, 101 transm, 288 transpart, 300 transpdo, 100 transppow, 101 trcolor, 341 trig2exp, 192 trpos, 300 try accept, 482 try bind listen, 482 try connect, 482 tstart, 490 tstop, 490 type, 448

uc, 419 udecomp, 429 udiv, 429 ufctrhint, 424 ugcd, 430 uinv as power series, 429 umul, 427 umul ff, 427 unim, 282 urem, 430 urembymul, 430 urembymul precomp, 430 ureverse, 429 ureverse inv as power series, 429 usquare, 427 usquare ff, 427 util damepathq, 535 util file exists, 534 util filter, 534 util find and replace, 534 util find start, 534 util find substr, 534 util index, 534 util load file as a string, 534 util part, 534 util read file as a string, 534 util remove cr, 534 util timing, 533 util v, 534 util write string to a file, 534 utmul, 427 utmul ff, 427 utrunc, 429

vadd, 118 var, 418 varargs, 178 vars, 418 vect, 432 vector, 432 velbezier, 335 verb tex form, 305 version, 492 vgen, 264 vnext, 263 vprod, 251 vtol, 433 vtozv, 250 vtype, 448

which, 444 wronskian, 231

xy2curve, 370 xy2graph, 367 xyang, 356 xyarrow, 345 xyarrows, 348 xyaxis, 361 xybezier, 350 xybox, 349 xycirc, 349 xycircuit, 359 XYcm, 389 xygraph, 362 xygrid, 358 XYLim, 389 xyline, 344 xylines, 351 xyoval, 357 xypg2tg, 326 xyplot, 361 xypoch, 361 xypos, 342 XYPrec, 389 xyproc, 342 xyput, 344 xytournament, 329

zeta, 248

応用 Taylor 展開, 382 函数値の数表, 379 三角函数表, 381 常用対数表, 380 行列の行基本変形, 276 グラフ

円グラフ, 313 折線グラフ, 312 棒グラフ, 312 原始根の表, 375 点数分布表, 381 不定積分の解法, 237

型変換 CSV 形式 → リスト, 297 DAlg ↔ 代数的数, 466 DAlg ↔ 分散多項式, 466 EUC/JIS 文 →ShiftJIS 文, 294 JIS code → ShiftJIS code, 293 root → 不定元, 463 ShiftJIS code → JIS code, 293 ShiftJIS/JIS 文 →EUC 文, 294 TikZ→ 描画実行形式, 295 数 → 文字列, 207 函数 → リスト形式函数, 185, 186 行列 → TEX, 313 行列 → リスト, 267 互換 → 置換, 300 式 → 文字列, 296, 439 自然数 → 一文字, 292 実数 → 整数, 450 実数 → 分数, 204 数式 → TEX, 305, 307 数式 → 入力可能文字列, 295 スペクトル型

GRS → 重複度リストのリスト, 120 GRS ← 重複度リストのリスト, 127 文字列 ↔ 重複度リストのリスト, 119

整数 →16 進文字列, 293 整数のリスト → 文字列, 440 多項式 → リスト, 250 多項式 → 分散多項式, 471 微分作用素 → TEX, 223, 225 不定元 → root, 463 分散多項式 → 多項式, 471 分数 → 実数, 208 分数の有理化, 207 ベクトル → TEX, 307, 313 ベクトル → リスト, 433 変数 → 文字列, 534 文字列 → 色コード, 341 文字列 → 行列, 268 文字列 → 座標, 295 文字列 → 式, 296, 440 文字列 → 整数のリスト, 440 文字列 → 入力可能文字列, 293 文字列 → バイト列, 433 文字列 → 変数, 177, 440, 534 有理式 → TEX, 223, 305 有理式 → 文字列, 223 有理数 → bigfloat, 202 リスト →CSV 形式, 298 リスト → TEX, 307 リスト → 行列, 267, 268 リスト → 座標文字列, 342 リスト → 多項式, 250 リスト → 入力可能文字列, 295 リスト → ベクトル, 432, 433 リスト形式函数 →bigfloat リスト形式函数, 186 連分数 → 分数, 204

函数値を得る, 189 オプション, 494 オプションリストの変更, 249 函数子, 449 自明簡略化, 183 スカラー演算を行列演算に拡張, 181 定義済みかとうかのチェック, 174 定義済み函数, 493 引数リスト, 449 評価, 183 含まれる初等函数のリスト, 179 含まれる変数と初等関数, 178 呼び出し, 448 リスト形式函数, 403 リスト形式手続きの実行, 190 リスト，配列に拡張, 181, 493

逆変換, 217 行列

permanent, 280 trace, 279, 438 演習用の整数行列生成, 282 階数, 280, 500 回転行列, 318 核, 280, 500 簡単化, 287 基本変形, 288 逆行列, 281, 436, 499 行基本変形, 272, 437

演習問題生成, 282 問題解法生成, 272

行の交換, 437 行のスカラー倍, 437 共役変換, 281 行列式, 279, 436, 499 係数行列, 269 固有値, 286, 500 固有ベクトル, 439 固有値ベクトル, 286 サイズ, 433 実対称行列の符号, 438 小行列, 270 商写像, 281 正則拡張, 438 正則小行列, 438 線型変換の外積, 288 線形方程式の解, 499 像, 280, 498 単因子, 105 置換行列で変換, 270 定義, 268, 434, 435 一般行列, 281 対角行列, 281, 499 対称行列, 281 置換行列, 281 ブロック行列, 285

転置, 271, 499

同時スペクトル, 152

複製, 266, 498 部分行列, 499 べき, 271 ヘッセンベルグ行列, 439 ユニモジュラー行列生成, 282 余因子行列, 438, 498 列基本変形, 437 列数調整, 271 列の交換, 437 列のスカラー倍, 437

グレブナー基底, 466, 469 b 関数, 480 F4 アルゴリズム, 469 S-多項式, 476 sugar, 474 weight, 471 Weyl 代数, 469 頭項の商, 475 頭項の全次数, 474 一回の簡約, 476 イデアルの分解, 479 基底変換, 467, 468 係数の型変換, 472 係数のビット長の和, 476 係数の標準化, 473 最小公倍項, 475 最小多項式, 468, 469 指数ベクトル, 475 正規化, 473, 477 先頭部分, 474 多項式 → 分散多項式, 471 多項式リスト生成, 478 パラメータの設定，表示, 470 比較, 477 非斉次化, 472 分散多項式 → 多項式, 472 変数順序型の設定, 参照, 471 リスト化, 477

座標

Bézier 曲線, 334 キャンバスに描画, 351 結合, 319 交点, 340 最大速度, 335 座標と速度, 336 データ変換, 335 Bounding box, 331 Window, 331 アフィン変換, 319 回転行列, 318 回転数, 318 角度, 321 共通部分の有無, 332 距離, 317 格子点, 321 交点, 321 コピー, 321 差の座標, 317 三角形

五心, 323 三角形内, 324 垂線の足, 321 正多角形, 320 接円, 323 接点, 321 直線と箱内の共通部分, 332 凸包, 331 内分点, 321 反転, 323 描画実行形式, 319 平行移動, 321 偏角, 246 方向転換進行点, 321 面積, 336 和や差や一時結合の座標, 316

GRS, 129 CSV 形式, 297, 298 システム

Asir のバージョン, 492 Asir のルートディレクトリ, 493 CPU time, 490

開始, 490 終了, 490

ガベジコレクション, 488 環境変数, 494 時刻, 491 制限時間つき実行, 491 設定の表示, 305 デバッグモード, 489

エラー表示, 489 ヒープサイズ, 491 ヒストリの消去, 493 プロセスの一時停止, 491 プロンプト, 488 マニュアル表示, 174

常微分作用素

addition, 118

versal, 118 Basic スペクトル型の生成, 125 Euler 型から変換, 112 Euler 型の積, 100 Euler 型へ変換, 111 middle convolution, 118

留数行列の和, 128 Riemann scheme

middle convolution and addition, 128 reduction, 129 解析, 120 生成, 127 部分特性指数和, 128

一次分数変換, 112 合流, 142

特性指数, 143 合流スペクトル型

文字列との変換, 120 固有多項式, 116 最小公倍元, 105 最大公約元, 103 スペクトル型

Riemann scheme 生成, 127 解析, 120, 122 生成, 122 並べ替え, 119 文字列との変換, 119

単因子, 105 割り算, 103

常微分方程式

KZ 系 residue matrices, 161 全留数行列, 168

middle convolution

合流, 144 Okubo 型に変換, 113 Pfaff 系を KZ 系に変換, 142 Runge-Kutta 法, 220 一階線型システムを高階単独へ変換, 114 基底の変換, 105 形式解, 113 数値解析, 238, 239 双有理変換, 218 単独化, 218 単独高階線形を一階システムへ変換, 115 特性指数, 112 半局所モノドロミー, 128, 140 Fuchs 型の解析, 129 べき級数解, 221 隣接関係式, 141

数式符号反転との表示比較, 194 不定変数, 404

数値函数 arccos, 450 arcsin, 450 arctan, 450 cos, 246, 450 log, 246, 450 log_{10}, 246 acos, 246 asin, 246 atan, 246 sin, 246, 450 tan, 246, 450 x^{y}, 246 erf, 245 Maclaurin 展開, 217 sgn, 197 Taylor 展開, 217, 382

常微分方程式, 220, 221 値を得る, 183, 184, 189, 413 回帰直線, 251 函数形式削除, 185 函数値の変更, 187 ガンマ函数, 247 級数の和, 190 極限値, 195 極値, 195 切り上げ整数, 450 合成関数の微分, 229 最大値，最小値, 195 三角函数と指数函数の簡単化, 192, 194 四捨五入

桁指定, 207

整数に, 451 指数函数, 246, 450 実数の小数部分, 245 周期函数に拡張, 188 小数部分, 418 数値積分, 191, 336, 406

Bezier 曲線法, 191

Romberg 積分, 191

シンプソンの公式, 191

台形公式, 191 整数部分, 450 積分区間変更, 188 絶対値, 197, 450 零点, 194 相関係数, 250, 251 相補誤差関数, 451 対数ガンマ函数, 247 ダイログ函数, 247 ディガンマ函数, 247 特異点, 196 任意精度浮動小数, 414, 488 標準偏差, 250 複素積分, 191 不定積分, 233

解法生成, 233 平均値, 250 平方根, 247, 450 ヘシアン, 231 偏角, 246 ヤコビアン, 231 有限フーリエ級数, 245 リスト形式函数, 403 リスト形式函数の合成, 187 リスト形式函数の生成, 186 ロンスキアン, 231

整数 16 進表示, 293 2 進数, 416 and, 28, 415 bit shift, 416 Catalan 数, 198

許容 01 列, 199

トーナメント表, 199

凸多角形の三角形分割, 199 or, 28, 415 pPq, pCq, pHq, 198 Stirling 数, 198 xor, 28, 415 オイラーの φ 函数, 418 階乗, 411 原始根, 203

表作成, 375 合同式

逆数, 412

平方剰余, 203

べき, 202

べき乗根, 203 最小公倍数, 105, 412 最大公約数, 103, 411 自然数

一文字表記, 292 商, 410 剰余, 410, 425 素因数の個数, 417 素因数分解, 416, 497 素数

生成, 417 判定, 204, 417

単因子, 105

トーナメント図のタイプ数, 201 トーナメント戦の場合の数, 201 場合の数, 198 分割

生成, 300 双対, 300 分割数, 198 平方根, 412 平方数, 416 ベルヌーイ数, 198 メビウス函数, 418 約数の個数, 417 約数の和, 417 乱数, 412

双有理変換, 217 ソート, 434

2 成分, 255 逆順, 254 二分木, 259 マルチキー, 260 リカーシブ, 254 リストのリスト, 255

対数尺, 332 代数的数

DAlg ↔ 代数的数, 466 DAlg ↔ 分散多項式, 466 GCD, 463

                                                        root, 462

root → 不定元, 463

因数分解, 464 簡単化, 463 基礎体, 465 最小分解体, 465 生成, 462 定義多項式, 462 ノルム, 463 不定元, 462 不定元 → root, 463

代数方程式連立

数値解, 213, 519 有理式解, 217 有理数解, 213

多角形

三角形分割, 324, 325

表示, 326 凸包, 331

多項式 Schur 多項式, 217 shifted power, 216 一変数

Gauss 整数体上の既約分解, 215 Gegenbauer 多項式, 216 Hermite 多項式, 216 Jacobi 多項式, 216 Laguerre 多項式, 216 Legendre 多項式, 216 shifted power, 215 strum 列と実根の個数, 212 strum 列の符号変化数, 212 因数分解, 228 共通根の存在条件, 211 係数の最大公約元, 430 原始函数, 232 高次の項を無視した積, 210 根, 210, 213, 214, 431 最小公倍式, 105 最大公約式, 103 最低次数, 419 次数, 226, 419 実根, 213 終結式, 423 選点直交多項式, 216 素因子の個数, 417 単因子, 105 チェビシェフ多項式, 216 直交多項式, 216 判別式, 431 べき和多項式, 244 ベルヌーイ多項式, 245 割り算, 211

因数分解, 423 重み付き斉次式に分解, 229 基本対称式, 215 共通因子, 231 共通根, 213 係数, 227, 419 係数抽出, 227 係数のチェック, 227 係数のリスト, 230 係数を整数に丸める, 430 項数, 420 合成関数の微分, 229 項の抽出, 229 最低次数, 226 斉次化, 225 生成, 210 定数項, 228 べき指数の項, 228 べき指数のリスト, 228 優多項式, 228 割り算, 421

チェック Windows 環境, 174 アルファベット/数字の文字コード, 198 アルファベットの文字コード, 198 実部虚部共に有理数数, 198 小数を表す文字列, 198 数字の文字コード, 198 整数, 197 多項式の係数, 227 定義済み函数, 174 微分作用素, 179 平方式, 416 平方数, 416 変数, 178 有理数, 198 有理数係数, 222

置換 Bruhat order, 302 完約表現, 301 逆元, 301 共役変換, 301 互換, 300 積, 300 次の置換, 298 長さ, 301

TEX Pfaff 形式, 307 Pochhammer cycle, 361 Riemann scheme, 307 xypic, 392

2 変数関数の 3D グラフ, 367 Bézier 曲線, 350 円, 349 円弧, 356 扇形, 356 折線, 352 開始と終了, 342 角の記号, 356 関数のグラフ, 362 曲線, 352 空間曲線の描画, 370 座標，式, 343 座標軸, 362 線種, 345, 401 方眼紙, 358 楕円の弧, 357 多角形, 352 長方形, 349 直線, 344 通過点のアフィン変換, 319 通過点の複数コピー, 356 塗りつぶし, 350, 401 描画実行形式の実行, 371 表示, 342 閉曲線, 352 平行四辺形, 349 目盛, 332 文字列，式, 344 文字列表示, 342 矢印, 345, 348, 356

因数分解, 223 改行, 305 改ページ, 305 数, 207 括弧のサイズ調整, 306 画面表示, 304, 305

自動制御, 303 制御, 304

キーワード, 306 行分割, 316 行列, 313

小サイズ, 316 分割と並べ替え, 315

行列の行基本変形, 272, 276 グラフ

2 変数関数, 367 円グラフ, 309, 313 折線グラフ, 309, 312 関数のグラフ, 362 座標軸, 362 点のプロット, 361 棒グラフ, 309, 312

消去, 305 常微分方程式の解析, 129 数式, 305 改行文字列, 306 ページ内行数閾値, 388

電気回路, 359 微分形式, 307 微分作用素, 223, 225 表, 308

変形, 377 例, 311, 312, 375

部分分数展開, 230 ベクトル, 313 文字数幅, 316, 388 有理式, 223, 305 リスト, 307 列ベクトル, 307

トーナメント図, 329 トーナメント戦

タイプ, 201 トーナメント表の数, 199 場合の数, 201

入出力

shell, 492 結果の表示, 177 結果を文字列として取得, 177

１行入力, 176 環境変数, 494 キー入力, 176 出力

切り替え, 444 CPU time, 488 表示, 249, 446

実数, 489 標準入力

バッファクリア, 447 ファイル

1 行読む, 447 1 バイト書く, 447 1 バイト読む, 447 CSV 形式に変換, 298 CSV 形式読み込み, 297 出力, 177 消去, 446 存在チェック, 446 閉じる, 447 バイナリ読み書き, 445 開く, 447

フォーマットつき表示, 446 プログラム

読み込みパス名, 444 読み込み, 444

パッフ形式 addition, middle convolution, 162 変換

Riemann scheme, 153, 166 パラメータ

基底の完備化, 265

微分形式外微分, 116 TEX, 307

微分作用素 formal adjoint, 102 principal symbol, 103 一般準同型変換, 100 座標のベキ函数変換公式, 101 積, 99 積と和, 100 線形座標変換, 101 双有理座標変換, 100 有理式への作用, 103 有理式への作用積, 103 ラプラス変換, 118

描画

1 変数函数, 452

TEX, 362 2 変数函数

TEX, 367

零点, 452

等高線, 452 Bézier 曲線, 351 Pochhammer cycle, 361 円弧, 356 扇形, 356 角の記号, 356 重ね書き, 319, 373, 374 極形式, 452 空間曲線, 370 座標軸, 362 三角形

外接円, 356

内接円, 356 垂線, 356 方眼紙, 358 楕円, 357 点，線分, 454 電気回路, 359 描画実行形式, 373

種別番号, 373 描画実行形式の実行, 371 複数の点

TEX, 361 文字列, 454 矢印, 356

描画キャンバス

glib クリア, 341, 506 座標対応, 506 線分, 506 点, 506 開く, 506 窓サイズ, 341 文字列, 506

色変換, 341 クリア, 454 生成, 454 中間色, 341 デフォルトサイズ, 387

複素変数 Appell の超幾何級数, 222 Dedekind の Eta 函数, 248, 452 digamma 函数, 451 dilogarithm 函数, 451 elliptic j-invariant, 248 一般超幾何級数, 222 ウエーバー函数 𝔣(τ), 452 ウエーバー函数 𝔣_{2}(τ), 452 ガンマ函数, 247, 451 逆三角関数, 246 共役複素数, 413, 418 虚部, 413 三角函数, 246 指数函数, 246 指数関数を実変数に, 192 実部, 413 常用対数, 246 絶対値, 197, 418 対数関数, 246 対数ガンマ函数, 247 ダイログ函数, 247 ディガンマ函数, 247 2 変数超幾何級数, 222 複素積分, 191 平方根, 247, 451 べき函数, 216 巾関数, 246 偏角, 246, 247, 451 リーマンの ζ 函数, 248, 452 留数, 196

不定元型, 448 順序, 420 生成, 177, 178, 440, 534 添え字番号をはずす, 178 チェック, 178 含まれる不定元のリスト, 178

分散計算遠隔プロセス終了, 480 遠隔プロセス起動, 480, 482 コマンド送信, 41, 485 送信, 41, 485 送信バッファフラッシュ, 487 データ削除, 486 データ受信, 485, 486 動作中のプロセス識別子, 487 プリミティブ, 482 プロセス函数呼び出し, 484 プロセスリセット, 484 読み出し可能プロセス, 486

分数 q-変形, 204 循環連分数, 204 有理化, 207 連分数, 204 連分数展開, 204, 418

巾級数, 250 Appell の超幾何級数, 222 Maclaurin 展開, 217 Taylor 級数, 382 一般超幾何級数, 222 逆元, 429 高次のカット, 229 積, 250 2 変数超幾何級数, 222 巾関数, 250

ベクトル外積, 317 成分の置き換え, 180 ソート, 434

マルチキー, 260 次の並び替えたベクトル, 263 定義, 432 内積, 251 成す角に応じた数, 317 ノルム, 317 鋏む角の余弦, 319 範囲内の成分数, 248 偏角に応じた数, 317 要素の値の個数分布表, 248

変数｜ see 不定元, 59

Mathematica, 296

目盛, 332

文字列 cr/lf/tabs を削除, 534 EUC/JIS 文を ShiftJIS 文に変換, 294 ShiftJIS/JIS 文を EUC 文に変換, 294 繰り返し, 291 差し込み印刷, 291 数式を入力可能文字列に, 295 外側の括弧を外す, 292 テキスト用バッファ, 294 長さ, 440 部分文字列検索, 290, 534 部分文字列対応検索, 289 部分文字列置換, 291, 534 部分文字列抽出, 290, 441 文字検索, 289, 440 文字挿入, 291

ユークリッドの互除法, 103, 211 有限体

基礎体位数, 456 拡大次数, 456 種類, 455 元の定義, 457 設定, 455 多項式, 457

既約判定, 460 既約分解, 460 生成, 460, 461 多項式の変換, 459 標数, 456 変換, 458, 459 乱数, 457

有理式 TEX, 223 因数分解, 228 項数, 420 主変数, 418 双有理変換, 217 対数微分, 230 代入, 179, 180, 422 不定元の巡回置換, 180 部分分数展開, 230 分子, 411 分母, 411 変数のリスト, 419 偏微分, 102 文字列へ, 223 約分, 426, 494 有理数係数？, 222 有理変換の合成, 180

有理数近似実数から変換, 204 分子, 411 分母, 411 平方根, 206 リスト

2 次の外積の並べ替え, 263 2 成分のソート, 255 pair のリスト, 262 合併，共通部分，除外, 255, 494–496 逆順, 431 繰り返し, 291 繰り返しを用いたリストの生成, 495 最小公倍数（元） , 253 最小の成分, 253 最大公約数（元） , 253 最大の成分, 253 細分関係, 261 整数商での割り算, 254 成分の置き換え, 180, 252 成分の削除・抽出・付加, 249 成分の和, 252 先頭, 431 先頭に追加, 431 先頭を除く, 431 ソート, 434

逆順, 254 成分, 261 二分木, 259 マルチキー, 260 リカーシブ, 254

次の並び替え, 299 転倒数, 197 内部のリストをほどく, 267, 494 長さ, 431 並び替え番目, 299 二分木, 259

函数による生成, 260 入力可能文字列に変換, 295 範囲内の要素数, 248 表形式データの操作, 254, 255 符号, 197 部分リスト, 248 部分リストの列挙, 494 分数のリストの簡略化, 494 有限区間の集合, 262 要素検索, 248 要素数調整, 271 要素の値の分布個数表, 248 要素の重複度, 249 リスト形式函数, 183–186 リストのリストのサイズ, 248 リストのリストを転置, 271 連結, 267, 431

リスト形式データ, 408

Runge-Kutta 法, 238 解析, 220, 221

連立一次方程式, 251 簡易化, 251 有理数解, 252

Risa/Asir, 52 コマンドラインオプション, 53 環境変数, 53 起動から終了まで, 53 割り込み, 54 エラー処理, 55 計算結果，特殊な数, 55 型, 56 Asir で使用可能な型, 56 数の型, 58 不定元の型, 59

ユーザ言語 Asir, 60 文法 (C 言語との違い), 60 ユーザ定義函数, 61 変数および不定元, 62 引数, 63 コメント, 63 文, 64 return 文, 64 if 文, 65 ループ, 65 構造体定義, 66 さまざまな式, 66 プリプロセッサ, 67 オプション指定, 68

モジュール, 70 デバッガ, 72

デバッガとは, 72 コマンドの解説, 72 デバッガの使用例, 74 デバッガの初期化の例, 75

文法の詳細, 75 有限体における演算, 78

有限体の表現および演算, 78 有限体上での 1 変数多項式環の演算, 79 小標数有限体上での多項式環の演算, 79 有限体上の楕円曲線に関する演算, 79

代数的数に関する演算, 80 代数的数の表現, 80 分散多項式による代数的数の表現, 81 代数的数の演算, 82 代数体上での 1 変数多項式の演算, 83

グレブナー基底の計算, 85 分散表現多項式, 85 ファイルの読み込み, 85 基本的な関数, 85 計算および表示の制御, 86 項順序の設定, 88 Weight, 89 有理式を係数とするグレブナ基底, 90 基底変換, 90 Weyl 代数, 91

分散計算, 91 OpenXM, 91 Mathap, 92 スタックマシンコマンド, 92 デバッグ, 93

Asir-Contrib, 94 Risa/Asir と os muldif.rr, 96

os muldif.rr のインストール, 97