ポコム プログラマーズ ガイド

目次

第1章 ポコムとは

ポコム(POrtable COMpiler)は C/C++ を使った、小型のフレームワークです。 数値計算、なかでも待ち行列網、グラフ理論や統計分析に向いています。 ポコムは軽くて速いプログラムを、 手っ取り早く開発するのに向いています。 ポコムを使う効果はつぎのとおりです。

ポコムが供給するファイルはつぎのとおりです。

pocom.htmlこのファイル
pocom.h ポコムのシステムを記述した C 言語ファイル
Example.c 連立方程式を解く例題
test.txt 例題データ ファイル

第2章 ポコムによる開発例

「連立方程式を解く」という例題を用いて、 ポコムの簡単な開発例を示します。 例題はN=3個の未知数 X[0]、X[1]、X[2] についての連立方程式

      A[0][0]*X[0] + A[0][1]*X[1] + A[0][2]*X[2] == B[0]
      A[1][0]*X[0] + A[1][1]*X[1] + A[1][2]*X[2] == B[1]
      A[2][0]*X[0] + A[2][1]*X[1] + A[2][2]*X[2] == B[2]

を解きます。(係数行列 A[ ][ ] と B[ ] は与えられる) 説明は、つぎのような順序で示します。

これから示す例題は次のようなデータ ファイル test.txt を使います。

         A                         B
           2.000   5.000   7.000 ;  23.000
           4.000  13.000  20.000 ;  58.000
           8.000  29.000  50.000 ; 132.000

        Solve
        Print N A X B

そして、次のように計算をし、結果を出力します。( X が解です)

        C:\>Example test.txt
        #Solve 100.000% 
         N   A                         X       B
           3   2.000   5.000   7.000 ;   3.000  23.000
               4.000  13.000  20.000 ;   2.000  58.000
               8.000  29.000  50.000 ;   1.000 132.000

; は行列の行末を表します。空白行は配列の終わりを表します。 空白行の代わりに $ を使うこともできます。 データ ファイルで配列 A を処理すれば、変数 N は自動的に設定されます。 ポコムでは入力ファイルと出力ファイルの形式は同じです。

ポコムバージョン5.01から以下のようなCSVファイルも読み込めるようになりました。

test.csv:

    A,B
    2, 5, 7,;, 23
    4,13,20,;, 58
    8,29,50,;,132

    Solve
    Print,N,A,X,B

以下に、ポコムのプログラム(Example.c)を示します。

   /* Example.c */
   #define FILE_NAME "Example.c"

   #if defined(PDEF_H)

    INT(N,3,       "Size of matrix")
    RMAT(A,307,N,N,"Coefficient matrix")
    RVEC(B,307,N,  "Right side vector")
    RMAT(C,307,N,N,"Work matrix")
    RVEC(X,307,N,  "Solution vector")
    PROC(Solve,    "Solve linear equation")

   #else

    #include "pocom.h"
    CHECK_FILE_NAME

    void Solve(void) {
        Int i,j,k;
        Check("A B"); Alloc("C X");
        for (i=0;i<N;i++) for (j=0;j<N;j++) C[i][j]=A[i][j];
        for (i=0;i<N;i++) X[i]=B[i];
        for (k=0;k<N;k++) {
            if (C[k][k]==0) Error("Solve","Denominator is 0");
            for (j=k+1;j<N;j++) C[k][j]/=C[k][k];
            X[k]/=C[k][k];
            for (i=0;i<N;i++) if (i!=k) {
                for (j=k+1;j<N;j++) C[i][j]-=C[i][k]*C[k][j];
                X[i]-=C[i][k]*X[k];
            }
            Progress("#Solve ",k,N);
        }
    }

   #endif
マクロ FILE_NAME に、必ずそのファイル自身のファイル名を指定します。 (以前のバージョンでは THIS_IS マクロで指定していて、現在でも引き続き使用できますが、 トラブルを防ぐため、よりチェックの厳しい FILE_NAME マクロを使用することを推奨します。)

2.1 データ構造の記述

ポコムは幾つかのデータ型を用意しています。ここではその一部を紹介します。 他のデータ型は第4章 データの種類を参照してください。

「連立方程式を解く」のには、どのような変数が必要でしょうか?。 もちろん、係数行列が必要です。そして、行列の大きさを示す整数も必要です。 N が行列の大きさを示し、A が係数行列を示し、B に方程式の右辺が入り、 X に未知数が求まります。また、作業用に行列 C も使います。 計算ルーチンも変数と同様に宣言します。 ここでは、Solve を計算を実行する C 言語の関数名とします。 ポコム用にこれらのデータ構造を書くと、

    INT(N,3,       "Size of matrix")
    RMAT(A,307,N,N,"Coefficient matrix")
    RVEC(B,307,N,  "Right side vector")
    RMAT(C,307,N,N,"Work matrix")
    RVEC(X,307,N,  "Solution vector")
    PROC(Solve,    "Solve linear equation")

のようになります。これらを左から順に説明します。

の最初の INT、RMAT、RVEC、PROC は C 言語のマクロです。 ポコムで変数や関数を宣言する時は、必ずこれらのマクロを使います。 INT は整数型を示し、RMAT は浮動小数点の行列を示し、 RVEC は浮動小数点のベクトルを示しています。

2行目以降の N、A、B、C、X、Solve は、プログラムで使用する名前を決めています。 これは、_ で終わってはいけません。 これらの名前は、計算ルーチンで、 大域整数変数や関数として、扱うことができます。

N は Int N; と宣言されます。 これは、通常の場合 int N; と宣言したのと同じで、 #include "pocom.h" の前に #define INT_64 とすると、 long long N; と宣言したのと同じになります。(Visual C++なら __int64) ポコムの以前のバージョンでは常に int としていましたが、新しいポコムでは Int 型を使います。 32ビットと16ビットのコンパイラでは int 型が一番高速な型でしたが。 64ビットのコンパイラでは int 型よりも long long 型の方が高速になることがあるので、 新しく導入しました。

さらに16ビットのコンパイラで、 #include "pocom.h" の前に #define INT_32 とすると、 long N; と宣言したのと同じになります。

A は double**A; のように宣言したことになります。 (厳密にはコンパイラによって double*const __restrict*__restrict A; となります) 例えば、行列 A の転置行列Cを作るルーチンでは、

        for (i=0;i<N;i++) for (j=0;j<N;j++) C[i][j]=A[j][i];

のように書くことができます。

計算ルーチン Solve を PROC マクロで登録すると、 同じ名前の C 言語の関数 Solve( ) は、 データ ファイルから呼び出すことができるようになります。 ポコム関数 Print や Load も同様に C 言語で記述された関数です。 しかし、これらは、pocom.h に記述されています。

2行目以降の数字、2 と 307 は、データを表示する時の桁数を決めています。 関数の宣言では指定しません。 この 2 はスペースを含まない最大の桁数を指定しています。 したがって N は -9 から 99 までは桁ずれを起こさずに表示できます。 数字の下位2桁のみが桁数として有効です。 百の桁は、小数点以下の桁数を表すのに使われます。 307 は小数点以下3桁、全体で7桁を使って表示することを意味しています。 この桁数はポコム関数 Format により、 実行時に変更できます。

RMAT と RVEC の中央にある N は、 行列の大きさが整数変数 N で決まることを表しています。 ポコムでは、どんな種類の配列でも、大きさは変数で決まります。 配列以外の単純型の宣言では大きさは指定しません。

1番右のの"Size of matrix"は、 ファイルを指定せずに起動する時に表示されるコメントを決めています。 "Coefficient matrix"...も同様です。
これを、コメントだけを表示しない場合は空文字列、"" あるいは ZeroStr とします。
0(NULL) にすると、ファイルを指定せずに起動する時に変数の表示の一覧から除外されます。
英語と日本語の両方に対応するには。 以下のように EJ マクロを使います。コンパイル時に JPN マクロが0以外だと、 EJ マクロは日本語のメッセージを有効にし、JPN マクロが定義されていなかったり、 0と定義されていれば英語のメッセージを有効にします。プログラムに日本語を 埋め込む場合はできるだけ EJ マクロを使って日本語が使えないときに備えて下さい。 具体的には Windows で /D WINUTF8 を定義したり、-DWINUTF8 と定義したりして UTF8のデータファイルに対応させようと する場合にプログラムに日本語が埋め込まれると、UTF8に対応していないコンパイラ を使うと文字化けが起きるので、JPN は自動的に無効になります。 なお、32/64ビットコンパイラで JPN が無効な時は、データファイルの文字コードから推測して、 出力桁数を自動調整するようになります。一方、JPN が有効な時は pocom.h の文字コードに 従って出力桁数を調整します。なお、16ビットのコンパイラの場合で WINUTF8 と JPN が無効の場合は、 デフォルトで後で説明する NO_ADJUST が有効になり桁の調整を行いません。 この場合、シフトJISのみ対応となります。 16ビットのコンパイラで他の文字コードで自動桁調整を行いたい場合は pocom.h をインクルードする前に、
#define NO_ADJUST 0
としてください。

    LIST("# " FILE_NAME " version 5.02")
    INT(N,3,       EJ("Size of matrix",       "行列の大きさ"    ))
    RMAT(A,307,N,N,EJ("Coefficient matrix",   "係数行列"        ))
    RVEC(B,307,N,  EJ("Right side vector",    "右辺"            ))
    RMAT(C,307,N,N,EJ("Work matrix",          "作業用の行列"    ))
    RVEC(X,307,N,  EJ("Solution vector",      "計算結果"        ))
    PROC(Solve,    EJ("Solve linear equation","連立方程式を解く"))

2.2 計算ルーチンの記述

計算ルーチン部分を以下に示します。

    #include "pocom.h"
    CHECK_FILE_NAME

    void Solve(void) {
        Int i,j,k;
        Check("A B"); Alloc("C X");
        for (i=0;i<N;i++) for (j=0;j<N;j++) C[i][j]=A[i][j];
        for (i=0;i<N;i++) X[i]=B[i];
        for (k=0;k<N;k++) {
            if (C[k][k]==0) Error("Solve","Denominator is 0");
            for (j=k+1;j<N;j++) C[k][j]/=C[k][k];
            X[k]/=C[k][k];
            for (i=0;i<N;i++) if (i!=k) {
                for (j=k+1;j<N;j++) C[i][j]-=C[i][k]*C[k][j];
                X[i]-=C[i][k]*X[k];
            }
            Progress("#Solve ",k,N);
        }
    }

pocom.h をインクルードした直後に CHECK_FILE_NAME を書きます。 これは、FILE_NAME マクロのファイル名が本当に、それ自身のファイル名かどうか 確認するのに必要です。

関数 Check("A B") は、指定した配列のサイズが矛盾した場合、 エラー メッセージを表示して、プログラムを終了します。 Check( ) は暴走しないプログラムを書くためには、非常に重要な関数です。 後で詳しく説明します。

関数 Alloc("C X") は指定した配列変数に必要なメモリを確保します。 この関数もエラーが起きれば中止します。 例えば、サイズを示す変数がマイナスであったり、 MS-DOS ならば、メモリが足りなくなった時にエラーになります。 Alloc( ) で確保された領域は0で初期化されます。 ただし、文字列の場合は、長さ0の文字列定数 ZeroStr を指します。 Alloc( ) は、以前に確保されていた領域をいったん解放し、 その後、新しい領域を確保します。

関数 Error( ) は2つのエラーメッセージを表示して、 プログラムを終了します。英語にも日本語にも対応するには以下のようにします。

         if (C[k][k]==0) Error("Solve", EJ("Denominator is 0","分母が0"));

関数 Progress( ) は進捗率を 0.5 秒ごとに表示します。この例題のデータは N が 3なので意味がありません。 しかし、N が 5000 や 10000 になると、計算時間は N の3乗に比例するので数分間画面に 全く変化が見られなくなり、暴走しているのかいないのかが分からなくなってしまいます。
また、後で説明するウィンドウズモードの場合は Progress( ) がないと閉じるボタンも反応しなくなります。
この場合プログラムを終了するには、タスクマネージャーを起動して止めるしかありません。

2.3 データ読み込みの順序

データファイルにおいて、変数の順序にはある程度自由度があります。 以下のようなデータファイルでも、結果は最初の例と変わりはありません。

        N  B        A
         3  23.000   2.000   5.000   7.000 ;
            58.000   4.000  13.000  20.000 ;
           132.000   8.000  29.000  50.000 ;

        Solve
        Print N A X B

空白行や $ の 直前の ; は省略することができます。
省略した形式は古い形式のデータです。 新しい pocom.h は、新しい形式でも古い形式でも読み込むことができます。

また、後で説明するポコム関数 Add と Reset を使用して、以下のように書くことも可能です。

        Reset A B
        Add B  23.000  A 2.000   5.000   7.000 $
        Add B  58.000  A 4.000  13.000  20.000 $
        Add B 132.000  A 8.000  29.000  50.000 $
        Solve
        Print N A X B

一度に指定する必要もなく、以下のように分けて書くことも、 内容を変更して繰り返し書くことも可能です。

        A
          2.000   5.000   7.000 ;
          4.000  13.000  20.000 ;
          8.000  29.000  50.000 ;


        B
         23.000  58.000 132.000

        Solve
        Print N A X B

        B
        132.000  58.000  23.000

        Solve
        Print X

ここで、エラーのあるデータファイルの例を示します。

        A
          2.000   5.000   7.000 ;
          4.000  13.000  20.000 ;
          8.000  29.000  50.000 ;

        B
         23.000  58.000 40.000 132.000

        Solve
        Print N A X B

変数AとBは共に変数Nで大きさが決まっています。 Aを読み込んだときはNは3になるのに、Bを読み込むとNは4になります。 計算ルーチンSolveでNが4であると、行列Aを処理するときに、 Aの範囲を外れた場所にアクセスして、プログラムが暴走する危険があります。

この暴走の危険を回避するためにあるのが、関数 Check( )です。 このデータファイルを処理した時のエラーメッセージは以下のようになります。

        test.txt(9)でエラーが発生!

        Solve
        Check("A B")
               ^
        A:'B'によってサイズ'N'が 3 から 4 へ変化した

Check( ) はこのように原因を詳しく報告します。

2.4 プログラムの改良例

最初に説明した開発例で作業用行列 C は N×N でしたが、 これを N×(N+1) にするとより簡素に計算ルーチンを書くことができます。 この場合、新たに N+1 を表す整数変数NP1を作り、行列 C の列サイズとします。 そして、行列 C を Alloc( ) するまえに、NP1 に N+1 を代入しておきます。

また、ここでは文字列変数 Debug を使った、途中経過の表示の例も示します。

AUTO はプログラムが起動された時に自動的に実行されるデータを決めます。 ここでは、ポコム関数 Range を呼び出して、 N は0以上という制限を加えています。 これにより、配列が読まれなかった場合、 N は初期値0のままなので Check("A B") ; でエラーメッセージが表示されるようになります。

AUTO は変数の初期値を設定する時にも使います。

さらに INT(N,3,EJ("Matrix size","行列の大きさ")) を INTF(N,3,10,EJ("Matrix size","行列の大きさ")) のように書くと N が 10 以外の値になることを 防ぐことができます。 (FIX は以前は INTF と同じでしたが、現在は異なります)

また、初期化処理など、起動時に実行したい処理がある場合は、 その処理を行う関数を用意して、AUTO で呼び出すようにします。

さらに、下の test.txt には Print 関数の表示変数名変更機能の例も示します。 これは、.csv ファイルを作成してエクセルに読み込ませる時に、列の名前を日本語化するのに便利です。

   /* Example2.c */
   #define FILE_NAME "Example2.c"

   #if defined(PDEF_H)

    LIST("# " FILE_NAME " version 5.02")
    INT(N,3,         EJ("Size of matrix",       "行列の大きさ"    ))
    INT(NP1,3,       "N + 1")
    INT(K,3,         EJ("Loop control variable","ループの制御変数"))
    STR(Debug,5,     EJ("Outputs for Debug",    "デバッグ用の出力変数名"))
    RMAT(A,307,N,N,  EJ("Coefficient matrix",   "係数行列"        ))
    RVEC(B,307,N,    EJ("Right side vector",    "右辺"            ))
    RMAT(C,307,N,NP1,EJ("Work matrix",          "作業用の行列"    ))
    RVEC(X,307,N,    EJ("Solution vector",      "計算結果"        ))
    PROC(Solve,      EJ("Solve linear equation","連立方程式を解く"))
    AUTO("Range N > 0")

   #else

    #include "pocom.h"
    CHECK_FILE_NAME

    void Solve(void) {
        Int i,j,nn=MulAdd(N,N,0);
        Check("A B"); NP1=MulAdd(N,1,1); SizeChangedBy(NP1,Solve); Alloc("C X");
        for (i=0;i<N;i++) for (j=0;j<N;j++) C[i][j]=A[i][j];
        for (i=0;i<N;i++) C[i][N]=B[i];
        for (K=0;K<N;K++) {
            if (C[K][K]==0) Error("Solve", EJ("Denominator is 0","分母が0"));
            for (j=K+1;j<=N;j++) C[K][j]/=C[K][K];
            for (i=0;i<N;i++) if (i!=K) 
                for (j=K+1;j<=N;j++) C[i][j]-=C[i][K]*C[K][j];
            if (*Debug) Print(Debug);
            else Progress("#Solve ",K*(2*N-K),nn);
        }
        for (i=0;i<N;i++) X[i]=C[i][N];
    }

   #endif

test.txt
     Debug
	 'K C'

      A                         B
        2.000   5.000   7.000 ;  23.000
        4.000  13.000  20.000 ;  58.000
        8.000  29.000  50.000 ; 132.000

     Solve
     Print N A;係数行列 X;解 B;右辺

出力結果
     K   C
       0   2.000   2.500   3.500  11.500 ;
           4.000   3.000   6.000  12.000 ;
           8.000   9.000  22.000  40.000 ;

     K   C
       1   2.000   2.500  -1.500   1.500 ;
           4.000   3.000   2.000   4.000 ;
           8.000   9.000   4.000   4.000 ;

     K   C
       2   2.000   2.500  -1.500   3.000 ;
           4.000   3.000   2.000   2.000 ;
           8.000   9.000   4.000   1.000 ;

     N   係数行列                  解      右辺
       3   2.000   5.000   7.000 ;   3.000  23.000
           4.000  13.000  20.000 ;   2.000  58.000
           8.000  29.000  50.000 ;   1.000 132.000


先頭の LIST マクロは有っても無くてもかまいません。 これはパラメータを無しで起動したときや List コマンドを実行した時に表示する変数リストと 一緒に表示するバージョン情報などを加えます。

nn=MulAdd(N,N,0); と NP1=MulAdd(N,1,1) は、それぞれ nn=N*N; NP1=N+1; を これは N*N や N+1 が整数オーバーフローを起こしている場合に エラーとしてプログラムを終了します。

また、今まで例題では単純化するため Progress("#Solve ",K,N); としていました。 この場合 K が小さい時は進み方が遅く、K が N に近づくと早く進むようになります。
そこで Progress("#Solve ",K*(2*N-K),nn); と変更すると、進捗率の表示が、 ほぼ実行時間に比例して表示されるようになります。

SizeChangedBy(NP1,Solve); はこの例では意味を持ちません。ただ、習慣として書いておきます。
例えば、NP1 が他の配列のサイズになっていて、関数 Solve( ) によって整合性が取れなくなった場合を考えます。
ほかの計算ルーチンで Check( ) がその矛盾を発見した時に、その原因が Solve( ) であることを報告するのに、 SizeChangedBy(NP1,Solve); は役立ちます。
Print(Debug); を呼び出した時に Progress("#Solve ",K*(2*N-K),N*N); が呼び出さないのは、 Print(Debug); が Progress( ) の役割をはたしているからです。

AUTO は Range で変数の範囲を指定する以外にも、 Alias で変数に日本語の別名をつける時にも便利です。

次の節で、AUTO のさらに高度な使い方を説明します。

2.5 データファイルを埋め込む場合

データを別ファイルに書かずに、データをプログラムに埋め込んで計算を実行したい場合があります。 それを実現する定義の例(Example3.c)を示します。

   /* Example3.c */
   #define FILE_NAME "Example3.c"

   #if defined(PDEF_H)

    INT(N,3,     EJ("Number of random value","出力する乱数の数"))
    REAL(MAX,307,EJ("Max value",             "出力する乱数の最大値"))
    RVEC(X,307,N,EJ("Where to store numbers","乱数の格納場所"))
    PROC(Gen,    EJ("Generate numbers",      "乱数の生成"))
    AUTO("N MAX")
    AUTO("5 100.0")
    AUTO("Seed")
    AUTO("Gen")
    AUTO("Print X")

   #else

    #include "pocom.h"
    CHECK_FILE_NAME

    void Gen(void) {
        Int i;
        NoList=1; Alloc("X");
        for (i=0;i<N;i++) X[i]=Unif()*MAX;
    }

   #endif

これを実行するとデータファイルを用意しなくても、計算を実行できます。

計算ルーチンで、NoList という int 変数を1に設定しています。 普段は、ポコムではファイルを指定せずにプログラムを起動すると変数のリストを表示します。 NoList を0以外に設定すると、変数のリストを表示する動作を抑止できます。

2.6 メインルーチンを自分で書く場合

以下に例を示します。これはこの章の最初のプログラムと全く同じ動作をします。

   /* Example4.c */
   #define FILE_NAME "Example4.c"

   #if defined(PDEF_H)

    INT(N,3,       "Size of matrix")
    RMAT(A,307,N,N,"Coefficient matrix")
    RVEC(B,307,N,  "Right side vector")
    RMAT(C,307,N,N,"Work matrix")
    RVEC(X,307,N,  "Solution vector")
    PROC(Solve,    "Solve linear equation")

   #else

    #define CUSTOM_MAIN 1
    #include "pocom.h"
    CHECK_FILE_NAME

    void Solve(void) {
        Int i,j,k;

        Check("A B"); Alloc("C X");
        for (i=0;i<N;i++) for (j=0;j<N;j++) C[i][j]=A[i][j];
        for (i=0;i<N;i++) X[i]=B[i];
        for (k=0;k<N;k++) {
            if (C[k][k]==0) Error("Solve","Denominator is 0");
            for (j=k+1;j<N;j++) C[k][j]/=C[k][k];
            X[k]/=C[k][k];
            for (i=0;i<N;i++) if (i!=k) {
                for (j=k+1;j<N;j++) C[i][j]-=C[i][k]*C[k][j];
                X[i]-=C[i][k]*X[k];
            }
            Progress("#Solve ",k,N);
        }
    }

    int main(int argc,char**argv) {
        InitPocom();
        LoadFiles(argc,argv);
        ExitPocom();
        return 0;
    }

   #endif

2.7 LAST マクロでデータのみを渡して計算する

LAST にはプログラムが終了するときに実行するコマンド記述します。 これにより、データファイルに Solve と Print を記述していたのを、 省略することができるようになります。

   /* Example.c */
   #define FILE_NAME "Example.c"

   #if defined(PDEF_H)

    INT(N,3,       "Size of matrix")
    RMAT(A,307,N,N,"Coefficient matrix")
    RVEC(B,307,N,  "Right side vector")
    RMAT(C,307,N,N,"Work matrix")
    RVEC(X,307,N,  "Solution vector")
    PROC(Solve,    "Solve linear equation")
    LAST("Solve")
    LAST("Print N A X B")

   #else

    #include "pocom.h"
    CHECK_FILE_NAME

    void Solve(void) {
        Int i,j,k;

        Check("A B"); Alloc("C X");
        for (i=0;i<N;i++) for (j=0;j<N;j++) C[i][j]=A[i][j];
        for (i=0;i<N;i++) X[i]=B[i];
        for (k=0;k<N;k++) {
            if (C[k][k]==0) Error("Solve","Denominator is 0");
            for (j=k+1;j<N;j++) C[k][j]/=C[k][k];
            X[k]/=C[k][k];
            for (i=0;i<N;i++) if (i!=k) {
                for (j=k+1;j<N;j++) C[i][j]-=C[i][k]*C[k][j];
                X[i]-=C[i][k]*X[k];
            }
            Progress("#Solve ",k,N);
        }
    }

   #endif

test.txt
         A                         B
           2.000   5.000   7.000 ;  23.000
           4.000  13.000  20.000 ;  58.000
           8.000  29.000  50.000 ; 132.000

第3章 コンパイル方法と起動方法

前の章で作った Example.c をコンパイルすることで、ポコムのプログラムは完成します。

Linux の場合

Linux の場合ならば

    $ g++ -O4 -Wall -DJPN -o Example Example.c

のようにします。すると Example という名の ポコム コマンドを作ることができます。 ( -DJPN は pocom.h が報告するエラーメッセージを日本語にします。)

Windows でコマンドプロンプトから直接コンパイルする方法

pocom.zip を解凍したら、まず最初に $DoFirst.bat を実行してください。 共通ファイルが必要なフォルダにコピーされます。

処理が終わりました

続行するには何かキーを押してください ...
でキーを押す前に端末のウィンドウのタイトルバーを右クリックして、 [プロパティ]を選びます。
[フォント]タブの[フォント(F)]で[MS ゴシック]を選びます。

次に、コマンドプロンプトを起動します。
そして、例えば、Borland C++ 5.5.1 がインストールされているならば
    C:\...\Pocom\Example>bcc32 -O2 -DJPN -P Example.c

のようにコンパイルとリンクをすれば、 Example.exe という名の ポコム コマンドを作ることができます。
Visual C++ ならば、
    C:\...\Pocom\Example>cl /O2 /EHsc /D JPN /Tp Example.c
のようにしてコンパイルします。

その他のシステム場合

私は Windows と Ubuntu マシンしか所有していないので、確認できませんが、
64ビットでコンパイルする場合は SYSTEM64 を定義する必要があります。
32ビットでコンパイルする場合は SYSTEM64 を定義する必要はありません。

    $ cc -DJPN -DSYSTEM64 Example.c -lm

SYSTEM64 の定義は以下のようになっています。

#if !defined(SYSTEM64)
 #if defined(_M_X64)||defined(__x86_64__)
  #define SYSTEM64 1
 #else
  #define SYSTEM64 0
 #endif
#endif

これでインテルCPUのコンパイラは SYSTEM64 の自動判別はほとんど上手くいくはずですが、念のため。

実行の方法

こうして作った Example または、Example.exe の起動形式はつぎのようになります。
    Example [-b] [-<num>] [<ファイル名>]  [<ファイル名>] ...

起動時にファイルを全く指定しないと、変数のコメントを表示します。 ファイルを指定した場合、左から順番に読み込まれ処理されます。
    $ ./Example test.txt
    C:\...\Pocom\Example>Example test.txt

データファイルのアイコンを Example.exe のアイコンにドラッグしても、 プログラムを実行することもできます。引数のファイル名に "-" を指定すると、 標準入力から読み込みます。
-b オプションを指定するとファイルの先頭にUTF8のBOMを書きだします。
-<num> オプションを指定すると32/64ビットコンパイラの場合、 ポコムが実行時に確保するメモリの上限をギガバイト単位で指定できます。
例えば、 -0.0001 とすると 100,000 バイト(100キロバイト)に制限します。
また、-2 とすると2ギガバイトまでメモリを使うことができます。
32ビットコンパイラの既定値は -1 で -0.0001 が最小値で、-4.275 が最大値です。 ウィンドウズの32ビットプログラムでは2ギガバイト前後しか確保できませんが、Ubuntu の 32ビットプログラムは4ギガバイト前後まで確保できます。
64ビットコンパイラの場合の既定値は -6 で -0.0001 が最小値で、-1000.0 が最大値です。 つまり1テラバイトが最大値です。 このオプションの目的はプログラムのミスでメモリを使いすぎてスワップを起こすのを防ぐことです。

Windows でバッチファイルからコンパイルする方法

Borland C++ 5.5.1 がインストールされているならば M.bat というバッチファイルをダブルクリックするだけで Example.exe を作成できます。

他のコンパイラの場合は、フォルダにある $CmdSJIS というショートカットをダブルクリックしてコマンドプロンプトを起動します。
そして Visual C++ 2017 の場合は
    C:\...\Pocom\Example>m 2017

とします。そして、続けてコンパイラオプションも指定することもできます。
    C:\...\Pocom\Example>m 2017 /O2 /GL

とします。また、同じフォルダの中に Tra.c または Tra.cpp というファイルがあって、 それをコンパイルしたい場合は、
    C:\...\Pocom\Example>m Tra
や
    C:\...\Pocom\Example>m 2017 Tra
や
    C:\...\Pocom\Example>m 2017 Tra /O2 /GL
2017 と Tra を入れ替えて
    C:\...\Pocom\Example>m Tra 2017
や
    C:\...\Pocom\Example>m Tra 2017 /O2 /GL


のようにします。 M.bat を複製するなどして、それを編集すると便利です。M.bat の最初の方は
@echo off
if exist M.pif del M.pif
set COMPILER=Bcc
set PG=Example
set OPTIONS=-DHIT_ENTER -DJPN
set OPTIONSVC=/D HIT_ENTER /D JPN
set LIBS=
set BIT=64
set WINDOWS=0
set OPENMP=0
 ...

となっており、これを編集すればデフォルトのコンパイラ(COMPILER)やソースファイル(PG)や オプション(OPTIONS)や追加のライブラリ(LIBS)の設定を変えて対応できます。
例えば、WINDOWS モードをオンにしたい場合は set WINDOWS=0 を set WINDOWS=1 に書き換えます。
※ M.bat の代わりに Mk.bat を使えば WINDOWS=1 になっています。
set PG=Example という行を set PG=Tra と書き換えます。
M.bat で指定できるコンパイラの一覧は以下の通りです。
50 Visual C++ 5.0
60 Visual C++ 6.0
200202Visual C++ 2002
200303Visual C++ 2003
200505Visual C++ 2005
200808Visual C++ 2008
201010Visual C++ 2010
201313Visual C++ 2013
201717Visual C++ 2017
201919Visual C++ 2019
Bcc B Borland C++ 5.5.1
Gcc G TDM-GCC-64
Lcc L Lsic86
Tcc T TurboC

Lsic86 と TurboC を64ビット Windows で使う場合は「TAKEDA, toshiya's HOME PAGE」の 「MS-DOS Player for Win32-x64」から msdos.exe をダウンロードして Pocom\tools に置く必要があります。
http://takeda-toshiya.my.coocan.jp/
msdos.zip → msdos → binary → i86_x86 → msdos.exe が高速です。
32ビット Windows でも 64ビット Windows でも、Lsic86 や TurboC を使う場合は、 Lsic86 や TurboC の本体を C:\app16 というフォルダを作成して、そこに置く必要があります。
Lsic86 は http://www.lsi-j.co.jp/freesoft/
にあります。 Lsic86 の場合は C:\app16\lsic86\bin\_LCC を編集して
# LSI C-86 compiler's configuration file

-DLSI_C
-h
-X\APP16\LSIC86\BIN -L\APP16\LSIC86\LIB -I\APP16\LSIC86\INCLUDE -T -O
-acdos.obj $LSICOPTS
&		#Command line argument will be inserted here
-lknjlib -ldoslib -v

のようにします。
TurboC の場合は C:\app16\tcc\TURBOC.CFG を編集して
-I\APP16\tcc
-L\APP16\tcc

のようにします。
ただし msdos.exe 上で Lsic86 を使用する場合非常に時間がかかります。
例えば、CPUが Intel Atom330 で example.c のコンパイル時間は約2分でした。
(486版の msdos.exe 上ならば約10分)

Windows でUTF8モードでコンパイルする方法

Ubuntu はUTF8で作られているので、これから述べる Windows のような面倒な手続き無しでユニコード文字を処理することができます。
一方、Windows はデータファイルにシフトJIS以外のユニコード文字を含めたい場合にはUTF8モードにする必要があります。
シフトJISで用が足りるならばUTF8モードは使わない方が無難です。 以下、ウィンドウズでUTF8モード以外の場合をシフトJISモードと呼びます。
UTF8モードを使う場合は Windows XP 以降の Windows である必要があります。
16ビットコンパイラならば Load 関数、Output 関数、Append 関数でアスキー文字以外のファイル名処理することはできません。 ただし、後で説明する32/64ビットコンパイラならばユニコードのファイル名を処理することができます。
また、UTF8モードを使用する場合は事前に nkf.exe をダウンロードするなどして Pocom\tools フォルダに置く必要があります。
http://hp.vector.co.jp/authors/VA007219/
をスクロールさせて、「nkfwin.zip version 2.1.1 download」をクリックします。
nkf.exe を置いたら、Example フォルダにある SetUTF8.bat をダブルクリックするとUTF8モードになります。
すると Example フォルダにある全てのテキストファイル(*.txt)がUTF8に変換され、 $CmdSJIS というショートカットが $CmdUTF8 に変化します。
元のシフトJISモードに戻すには SetSJIS.bat をダブルクリックします。
SetUTF8.bat 2回連続して実行したり、SetSJIS.bat を2回連続して実行しても問題はありません。
$CmdUTF8 をダブルクリックして開いたコマンドプロンプトでは、起動時に chcp 65001 が実行され、UTF8文字を文字化けすることなく表示できます。
UTF8モードの状態で M.bat でコンパイルすると、UTF8に対応した Example.exe が作成されます。
M.bat は現在UTF8モードかどうかを、$CmdUTF8 が存在するかどうかで判断してコンパイルします。
(※コンパイラによっては JPN オプションが無効にされ、日本語をプログラムの中に埋め込むのが不可能な場合があります。
その場合でも、データファイルの日本語のUTF8文字は正しく処理されます。)
そうしてコンパイルできた Example.exe の実行は、
    C:\...\Pocom\Example>Example test.txt

のようにします。
Windows Vista 以前の場合、$CmdUTF8 でコマンドプロンプトを使用するときは結果に日本語があると桁位置がずれます。
リダイレクトして作ったテキストファイルや、ポコムの Output コマンドで作ったテキストファイルを、 メモ帳などで開くと桁位置はきちんと調整されているにもかかわらずです。 また、Windows Vista 以前だと、コマンドラインからバッチファイルを実行することができません。その場合、
    C:\...\Pocom\Example>chcp 932
とすると、実行できるようになります。
一方、Windows 7 以降ならばまた、3バイトUTF8文字(基本多言語面文字)の桁位置がずれることもありません。
しかし、Windows7 や Windows 8.1 の場合でも画面がスクロールすると表示が乱れる場合があります。
さらに残念なことに、Windows 10 でも4バイトUTF8文字(サロゲートペア文字)や ひらがなカタカナ濁半濁点結合文字やIVS異体字セレクター付き文字は表示桁位置がずれます。
ただし、後で説明するウィンドウズモードにすれば、XP ならば3バイトUTF8文字(基本多言語面文字)、 Vista ならば4バイトUTF8文字(サロゲートペア文字)も正しく表示できます。
UTF8で以下のようにコマンドの最初の引数に -b オプションを指定すると
C:\...\Pocom\Example\Example -b ...

Output( )、または Append( ) でファイルを作成する場合やリダイレクトした時にBOMがファイルの先頭に書き出されます。
また、-b オプションを指定しなくても、Output( ) や Append( ) で指定するファイル名の拡張子が '.csv' と '.tsv' の時はBOMが先頭に書き出されます。
なお、UTF8のCSVファイルを正しく表示するにはエクセルは2007以降が必要です。
CSVファイルでIVS異体字セレクター付き文字等を正しく表示するにはエクセルは2013以降が必要です。

ウィンドウズモード

M.bat の代わりに WINDOWS=1 となった Mk.bat を使用すると、対応したコンパイラならばウィンドウズモードでコンパイルします。
また、コマンドラインで直接、
    C:\...\Pocom\Example>bcc32 -W -DWINDOWS -P Example.c
    C:\...\Pocom\Example>cl /D WINDOWS /EHsc /Tp Example.c kernel32.lib user32.lib gdi32.lib

のようにしても、ウィンドウズモードでコンパイルすることができます。
このホームページの build1.exe を使ってコンパイルする場合は '/* WinMain */' をソースファイルのどこかに 書いておくことで、自動的に bcc32.exe に -W オプションが渡されます。
このホームページの build2.exe も最新の build2.exe なら対応しています。
ウィンドウズモードの長所は、 です。ウィンドウズモードの短所は、 です。

ウィンドウズモードでコンパイルした .exe ファイルを Ubuntu 18.04+wine 実行する場合、 梅フォントをダウンロードして ~/.local/share/fonts に置くことを推奨します。 (fonts フォルダがない場合は作成します。)

ASCIIモード

データファイルの中身やファイル名にASCII文字しか使用しない場合は、 -DASCII としたり、/D ASCII として、ASCII を定義すると 非ASCII文字の処理を全て無効にしてプログラムを小さくできます。 ASCIIモードとUTF8モードが同時に指定された場合はUTF8モードの方が優先されます。
ASCIIモードとは具体的には


また、JPN マクロが有効な時は JPN マクロは無効になります。

第4章 データの種類

ポコムは、多くのデータ型を持っています。

整数型コード型バイト型2バイト整数型4バイト整数型8バイト整数型半精度型単精度型倍精度型浮動小数点数型文字列型コード定義型
単純変数 INT、INTF、FIXCODEBYTETINTNINTLINTHALFFLTDBLREALSTR
ベクトル(vector) IVECCVECBVECTVECNVECLVECHVECFVECDVECRVECSVECCDEF
固定列行列(matrix) IMATCMATBMATTMATNMATLMATHMATFMATDMATRMATSMAT
可変列行列(jagged) IJAGCJAGBJAGTJAGNJAGLJAGHJAGFJAGDJAGRJAGSJAG

空白 # ; $ , を含む文字列やコードの名前を指定する時は、 " か ' で囲みます。 また、変数名/関数名と一致する文字列やコード定義を指定する時も " か ' で囲みます。" でクォートを開始した場合は "" を入れると " 1文字を表します。同様に ' でクォートを開始した場合は '' を入れると ' 1文字を表します。

整数を 0x または 0X で始めると16進数と見なします。 新しいポコムでは 0 から始めても10進数と見なします。 以前のバージョンのポコムのように8進数と見なしたい場合は、 #include "pocom.h" の前に #define ENABLE_OCTAL とします。

コード型については、次の章で詳しく説明します。

ベクトルの大きさは整数変数で制御されます。

固定列行列の大きさは、2つの整数変数で制御されます。 行数も列数も0にできます。

可変列行列は整数と整数ベクトルで行数と各行の長さが決ります。 行数も列数も0にできます。

第5章 コード型の使い方

整数演算と、文字列演算の性能を比較すると、 整数演算の方が速度・メモリ効率ともに優れています。 だからといって、プログラムやデータを整数で記述すると、 読みやすさをそこないます。 速度・メモリ効率と読みやすさを両立するために、C 言語では

    enum { SUN, MON, TUE, WED, THR, FRI, SAT };
    int DayMat[N][N] = { { SUN, MON, TUE },
                         { MON, TUE, WED },
                         { TUE, WED, THR } };

とするテクニックがよく使われます。 上の例は曜日型の行列の宣言もしています。 これは、曜日しか要素に持たない N×N 行列を表します。 計算機の内部では、SUN や MON といった文字列は使われずに、 0や1が配列に格納されます。 したがって、速度・メモリ効率とプログラムの読みやすさを両立します。

C 言語の enum、#define では、文字列 SUN、MON 等は、 コンパイラがプログラムを解釈するときだけ使われます。 コンパイルで得られたコマンドの入力や出力では、 SUN や MON を利用することはできません。 したがって、プログラムを読みやすくすることはできても、 データを読みやすくするには、 自分で読み込みプログラムと出力プログラムを書かなければなりません。

ポコムのコード型 (code、cvec、cmat、cjag) を使うと、 速度とデータの読みやすさを両立することができます。 たとえば、上の曜日型の行列を ポコムのコード型で実現するには

    FIX(7)
    CDEF(DayOfWeek,9,FIX7,      EJ("Day of week definition","曜日のコード定義"))
    INT(N,2,                    EJ("Size of matrix",        "行列の大きさ"))
    CMAT(DayMat,3,N,N,DayOfWeek,EJ("Day of week matrix",    "曜日の行列"))
    AUTO("DayOfWeek")
    AUTO("SUN MON TUE WED THR FRI SAT $")

を書いておきます。 こうすれば、データ ファイル上での曜日型の行列の入出力は

    DayMat
    SUN MON TUE ;
    MON TUE WED ;
    TUE WED THR ;

の形式になります。 この時、SUN から SAT には0から順に番号がふられます。 行列 DayMat にはふられた番号が格納されます。 N には3が設定されます。 この行列を Print 関数を使わずに、直接表示するプログラムは以下のようになります。

    for (i=0;i<N;i++) {
        for (j=0;j<N;j++)
            fprintf(fp," %s",DayOfWeek[ DayMat[i][j] ]);
        fprintf(fp,"\n");
    }
    FlushFp();

上の例の場合 DayMat[][] の値が DayOfWeek[] を超えると、プログラムがクラッシュ する可能性があります。以下のように書くと同じことをクラッシュせず安全に表示することができます。 以下の例では CmatStr(VAR,I,J) を使用していますが、似たような関数として
CodeStr(VAR)、CvecStr(VAR,I)、CjagStr(VAR,I,J) があります。

    for (i=0;i<N;i++) {
        for (j=0;j<N;j++)
            fprintf(fp," %s",CmatStr(DayMat,i,j));
        fprintf(fp,"\n");
    }
    FlushFp();

コードの名前には、数字・日本語等も登録できます。 社員名簿の社員番号のように数字だけの場合も登録できますし、 個人の住所録のように漢字の氏名を登録することもできます。 ただし、1つのコード定義に、同じ名前を複数登録することはできません。

Alloc("DayOfWeek") としたときには [0] [1] [2] [3] [4] [5] [6] が自動的に、 登録されます。また Print( ) で範囲外のコード型を表示させると [10] のように表示されます。 これはコード型の生の値に括弧をつけたものですが、これを [1] [2] [3] [4] [5] [6] [7] のように [1] から始めるには CDEF_BASE を1に定義してください。

32/64ビットのコンパイラで CDEF の要素数が縮小すると、それ以前に読み込んだコード型の変数はエラーになります。 縮小した場合にエラーにしたくない場合は NO_CHECK_CDEF を0以外に定義してください。
16ビットのコンパイラで縮小したときにエラーにしたいときは、CHECK_CDEF を0以外に定義してください。

第6章 データ ファイルの形式

ポコムには、以下に示す5種類の行があります。

空白行
行が空か、スペースかタブかカンマのみの行。データ行の終わりを表します。
注釈行
注釈行は # で始まります。注釈行は無視されます。
関数行
関数名が先頭に来て、後にパラメータが続く行です。
変数行
データを読み込む順番を決める行です。 # より右は読み込みません。
データ行
変数行で指定した順番にならんだデータの集まりです。 # より右は読み込みません。 空白 # ; $ , を含む文字列やコードの名前を指定する時は " か ' で囲みます。 また、変数名や関数名と一致する文字列やコード定義を指定する時も、 " か ' で囲みます。 また、0xで始めると16進数と見なします。 ; で行列の行末を決めます。 固定列行列を複数並べた時は、 それぞれの行末に ; を付ける必要がありますが、 可変列行列を複数並べた場合は、1つだけ ; を付けます。 空白行または $ またはファイルの終わりは配列の終わりを決めます。$ より右は読み込みません。

変数行を書く時は、次の順番を守って変数を並べなければなりません。

      [単純変数]  [ベクトル・固定列行列]  [可変列行列]

さらに、ベクトル、固定列行列、可変列行列を複数並べる時は、 行サイズを指定する整数変数が同じものでなければなりません。 また、可変列行列を複数並べる時は、 列サイズを示す整数ベクトル変数も同じものでなければなりません。

変数行の後には、それに応じた量のデータが必要になります。 この行をデータ行と呼びます。 データ行での読み込みの順番は、変数行での順序から次のように決ります。

順番さえあっていれば、改行や注釈は自由に配置できます。 したがって、工夫次第で、読みやすく、 かつページ数が少ないデータ ファイルを書くことができます。

第7章 データ ファイルの例

次のデータは、ベクトルと固定列行列を表現します。 N は Int、X は rvec[N]、A、C は rmat[N,N] です。

     A             C             X     # これが変数行
     1.2 6.6 2.2 ; 2.3 4.4 5.5 ; 3.0   #  *------------------*
     4.3 6.4 0.4 ; 5.3 2.3 6.4 ; 2.0   #  | これらがデータ行 |
     3.2 0.5 7.2 ; 2.3 3.4 2.7 ; 1.0   #  *------------------*

     # この上の空白行がデータ行の終わりを示す

次のデータは、可変列行列の例を示しています。 N は Int、Lenは ivec[N]、X は rvec[N]、U、V は rjag[Len] です。 最初に U に下三角行列を入力する例を示します。

     U
      1.2 ;       # Len には(1、2、3)が設定されます。
      4.3   6.4 ;
      3.2   0.5   7.2 ;

次に、X、U、V を同時に入力する例を示します。 上の A、C との順序の違いに注意してください。

     X   U   V 
     3.0 1.2 2.3 ;
     2.0 4.3 5.3
         6.4 2.3 ;
     1.0 3.2 2.3
         0.5 3.4
         7.2 2.7 ;

ポコムは、ネットワークを表現するのに適しています。 例えば有向グラフは、2つの cvec による枝集合でも、 svec による隣接行列でも、表現できます。 下に例として、ノード数4のサーキットの場合を示します。

    #    [N1] → [N2]
    #     ↑      ↓
    #    [N4] ← [N3]

    Node                  #  N    : Int     ノードの数
    [N1] [N2] [N3] [N4]   #  Node : cdef[N] コード定義

    From To               # cvec、 From と To によるサーキット
    [N1] [N2]             #
    [N2] [N3]             #  E    : Int           枝の数
    [N3] [N4]             #  From : cvec[E]<Node> 枝の出発点を表す
    [N4] [N1]             #  To   : cvec[E]<Node> 枝の到達点を表す


    Adj                   #  svec による隣接行列
    -*--                  #
    --*-                  #  Adj  : svec[N]  隣接行列
    ---*                  #  [i][j]に * があれば i から j への枝
    *---                  #  があることになる。Format は0にする。
                          #  そうしないと改行されない  
                          # N と E には自動的に 4 が設定される

第8章 文字列変数の扱い

まれに、計算ルーチンで STR、SVEC、SMAT、SJAG 変数に 文字列を割り当てる必要がでできます。 (以前のバージョンではStrDup( )を使用して効率が悪かったので仕様を変更しました。)

例題としてデータ定義が以下の場合を考えます。

    STR(S,10,    EJ("String variable","文字列変数"))
    INT(N,2,     EJ("Size",           "大きさ"))
    SVEC(SV,10,N,EJ("String vector",  "文字列ベクトル"))

新しいポコムで、文字列を動的に確保する場合は以下のようにします。

    N=3; Alloc("SV"); 
    SetStr(S,"abc");
    SetSvec(SV,0,ZeroStr)
    SetSvec(SV,1,"abc")
    AllocSvec(SV,2,11);
    memset(SV[2],'-',10);

SetStr、SetSvec、AllocSvec を使用すると NO_FAST_STR が有効の時も無効の時もOKです。 過去のバージョンの StrDup( ) や GetMemStr( ) は廃止しました。 他に SetSmat、SetSjag、AllocStr、AllocSmat、AllocSjag が使用可能です。

第9章 データ定義マクロ リファレンス

データ定義では、マクロで変数・関数・初期化データを指定します。 以下にこれらのマクロの書式を示します。

PROC(n,m) 引数を持たない関数
FUNC(n,m) 引数を持った関数
INT(n,w,m) 整数
INTF(n,w,f,m) 固定値整数
FIX(f) 固定値整数(簡略表現)(非負)
CODE(n,w,d,m) コード
NINT(n,w,m) 4バイト整数
LINT(n,w,m) 8バイト整数
HALF(n,w,m) 半精度浮動小数点
FLT(n,w,m) 単精度浮動小数点
DBL(n,w,m) 倍精度浮動小数点
REAL(n,w,m) 浮動小数点
STR(n,w,m) 文字列
IVEC(n,w,r,m) 整数ベクトル
CVEC(n,w,r,d,m) コード ベクトル
BVEC(n,w,r,m) 1バイト符号なし整数ベクトル
TVEC(n,w,r,m) 2バイト符号付き整数ベクトル
NVEC(n,w,r,m) 4バイト符号付き整数ベクトル
LVEC(n,w,r,m) 8バイト符号付き整数ベクトル
HVEC(n,w,r,m) 半精度浮動小数点ベクトル
FVEC(n,w,r,m) 単精度浮動小数点ベクトル
DVEC(n,w,r,m) 倍精度浮動小数点ベクトル
RVEC(n,w,r,m) 浮動小数点ベクトル
SVEC(n,w,r,m) 文字列ベクトル
CDEF(n,w,r,m) コード定義
IMAT(n,w,r,c,m) 整数固定列行列
CMAT(n,w,r,c,d,m) コード固定列行列
BMAT(n,w,r,c,m) 1バイト符号なし整数固定列行列
TMAT(n,w,r,c,m) 2バイト符号付き整数固定列行列
NMAT(n,w,r,c,m) 4バイト符号付き整数固定列行列
LMAT(n,w,r,c,m) 8バイト符号付き整数固定列行列
HMAT(n,w,r,c,m) 半精度浮動小数点固定列行列
FMAT(n,w,r,c,m) 単精度浮動小数点固定列行列
DMAT(n,w,r,c,m) 倍精度浮動小数点固定列行列
RMAT(n,w,r,c,m) 浮動小数点固定列行列
SMAT(n,w,r,c,m) 文字列固定列行列
IJAG(n,w,s,m) 整数可変列行列
CJAG(n,w,s,d,m) コード可変列行列
BJAG(n,w,s,m) 1バイト符号なし整数可変列行列
TJAG(n,w,s,m) 2バイト符号付き整数可変列行列
NJAG(n,w,s,m) 4バイト符号付き整数可変列行列
LJAG(n,w,s,m) 8バイト符号付き整数可変列行列
HJAG(n,w,s,m) 半精度浮動小数点可変列行列
FJAG(n,w,s,m) 単精度浮動小数点可変列行列
DJAG(n,w,s,m) 倍精度浮動小数点可変列行列
RJAG(n,w,s,m) 浮動小数点可変列行列
SJAG(n,w,s,m) 文字列可変列行列
AUTO(t) 起動時に自動実行するデータを書く
LAST(t) 終了時に自動実行するデータを書く
LIST(t) パラメータを無しで起動したときや List を実行したときに表示する

記号説明
nC 言語上での変数名・関数名 N または、Solve
w表示する時の桁数 10 または、-310
f固定値整数値 3など(0x から始めると16進数)
r行の数 N
c列の数 N
s大きさを決める ivecLen
dコード定義 cdef Node
mコメント "行列の大きさ"
tデータ "Range N > 0"

n は C の識別子として許され、かつ _ で終わってはなりません。 w は、データを表示する時の桁数を決めています。 詳しくは第10章の Format を参照してください。

第11章 ポコム関数、標準関数、標準変数リファレンス

ポコム関数は、データ ファイルからでも、AUTO からでも、LAST からでも、 計算ルーチン等のCの関数からでも呼び出すことができます。

ポコム関数はCの関数として呼び出す時は、文字列を引数とします。 C言語から呼び出すときは、引数を0(NULL)にしてはなりません。

Add配列に要素を追加する。
  例:INT(N,3,"")
      IVEC(L,3,N,"")
      SVEC(SVec,8,N,"")
      RVEC(RVec,308,N,"")
      RJAG(RJag,308,L,"")

      Add SVec "This is a pen." RVec 1.23 RJag 1.0 2.0 3.0

    
ベクトル型に追加するときは、一つの Add に対して複数の変数を追加することができる。
行列・可変列行列の場合は、一つの Add に対して一つの行列、しかも、最後に指定しなければならない。 また、データファイルでは、$ か空白行で終わらせる。複数行あっても許される。
行列・可変列行列でプログラムから Add を呼び出す時は
	Add("SVec "This is a pen." RVec 1.23 RJag 1.0 2.0 3.0 $");
    
のように、一行でしかも $ で終わらせなければならない。(ベクトル型の場合は $ は不要)
Range 関数で指定した列数範囲に違反すればエラーとなるが、行数が違反してもエラーとはならない。
Alias変数/関数に別名をつける。日本語も指定できる。 主に AUTO マクロ内で使用される。
         例   Alias N 数 A 係数行列 B 右辺 C 作業用 X 解 Solve 実行
		      Alias Alias alias Echo echo Print print System ! Format format
    
Append以降の出力を指定されたファイルへ追加書き込みする。- を指定すると標準出力へ書く。 + を指定すると標準エラーへ書く。 ファイル名の始まりや終わりがカンマの場合は " で囲む必要がある。
Clock起動した時からの経過時間を表示する。引数をコメントとして表示する。 コメントが不要な場合は引数に ZeorStr か "" を渡す。
Deleteファイルを削除する。 ファイル名の始まりや終わりがカンマの場合は " で囲む必要がある。
Echo文字列の表示。# よりも後ろの文字列も出力される。
Format変数の出力桁数を変更する。 出力の精度を高くしたり、 画面にたくさんのデータを表示したりするときに使用する。
          整数
            1〜:10進法で指定した幅で表示する
            0 :ベクトル・可変列行列単独で指定しても、要素ごとに改行する。10進法で表示する。
            −1:16進法で表示する。
            −2:16進法で表示し、ベクトル・可変列行列単独で指定しても、要素ごとに改行する。
            -3〜:16進法で表示し、絶対値の幅で表示する。

          文字列・コード型
            1〜:Print では指定した幅で表示する。
                    PrintCSV,TSV では必要に応じて引用符で囲み、常に文字列として一致した表示をする。
            0  :ベクトル・可変列行列単独で指定しても、要素ごとに改行する。
                    PrintCSV,TSV では必要に応じて引用符で囲み、常に文字列として一致した表示をする。
            −1:PrintCSV,TSV で値として表示するために、空文字列以外常に引用符で囲まない。
            −2:PrintCSV,TSV で値として表示するために、空文字列以外常に引用符で囲まない。
               ベクトル・可変列行列単独で指定しても、要素ごとに改行する。
            -3〜:Print では絶対値の幅で表示する。
               PrintCSV,TSV で値として表示するために、空文字列以外常に引用符で囲まない。
              ※PrintCSV,TSV では、
               ・32/64ビットコンパイラの場合で0以上の時 NO_CSVTSV_STR が有効なら必ず引用符で囲む。
               ・16ビットコンパイラの場合で0以上の時、必ず引用符で囲む。
                ただし、USE_CSVTSV_STR が有効のときは、必要に応じて引用符で囲む。
             (負にして PrintTSV で作成したデータはポコムの入力ファイルとして矛盾が生じる)
             (負にしなくても PrintCSV Title;; のように ; を2つ指定すれば引用符で囲まないようにできる)

          浮動小数点数
            下2桁が全体の桁数を表し、百の桁が小数点以下の桁数を示す。
            -209 のように負の符号を付けると、3.14e+000 の形式で出力する。
            0または -1 に指定した時は、必要に応じた精度で表示する。

            -2 または -3 に指定した時は、16進数で表示する。幅は half:6, flt:10, dbl:18 になる。
              16進数で表示すると、浮動小数点数の値が正確に受け渡しできる。
              (-1、-2 を指定しなくても Print A;; のように ; を2つ指定すれば16進数で一時的に表示できる)

              ベクトル・可変列行列で、0、−2に指定した場合は、
            単独で表示したときでも要素ごとに改行される。

    
同時に複数の変数の桁数を変えることができる。
         例  Format  A 408   B 408   X 408
    
Free変数のメモリを開放して初期化する。Free を使うとサイズの変数を変えずに、 メモリを開放して、配列名のポインタを NULL にできる。
Lap最初に呼び出された場合は Clock と同じように起動時からの経過時間を表示する。 2回目以降は前回の Lap の呼び出しからの経過時間を表示する。 引数をコメントとして表示する。コメントが不要な場合は引数に ZeorStr か "" を渡す。
LimitPrint するときに、一番右の配列を並べて表示する数を制限して折り返す。
@一番右の配列がベクトルならば、左には単純変数のみを指定できる。
A一番右の配列が固定列行列・可変列行列ならば、左には単純変数とベクトルを指定できる。
Limit 0 とすると折り返さない。 (計算ルーチンから折り返さないようにするには Limit("0"); か Limit__=0; とする。)
Limit -79 のように負の数を指定するとできるだけ79文字以内に収める(デフォルト・厳密には -(TERMINAL_X-1) )
ただし、ウィンドウズモードのときのデフォルトは -1024。
PrintCSV, PrintTSV は Limit が負の場合は OLD_EXCEL が有効なら255で折り返す。 OLD_EXCEL が無効な場合、__unix__ が定義されていれば1023で折り返す。それ以外は は16383で折り返す。
Limit 0 とすると折り返さない。 (計算ルーチンから折り返さないようにするには Limit("0"); か Limit__=0; とする。)
エクセル以外のソフトでCSV/TSVファイルを適切に折り返すためには、
例えば「libre office calc」の場合、
#define MAX_EXCEL_COL 1024
のようにする。すると1023で折り返す。あるいは、データファイルに
Limit 1023
や Limit 1020
のように書く。
Limit -1 を実行するとデフォルトに戻す。 (計算ルーチンからデフォルトに戻すには Limit("-1"); か Limit__=DEF_LIMIT__; とする。)
List変数と関数の一覧を表示する。引数は取らない。 標準変数 NoList が0以外の場合でも表示する。
Load指定されたファイルを読む。- を指定すると標準入力を読む。
Output以降の出力を指定されたファイルへ書く。 同じ名前のファイルがあるときは上書きされる。 - を指定すると標準出力へ書く。+ を指定すると標準エラーへ書く。 ファイル名の始まりや終わりがカンマの場合は " で囲む必要がある。
Print変数の表示。複数の変数を同時に指定する時は、 読み込みと同様変数の順番とサイズが合ってなければならない。
変数名に続けて ; と任意の文字列を指定することによって、 出力される変数名を一時的にその文字列に変更することが可能。
更に浮動小数点数型変数(例えば A) に対して Print A;; や Print A;SrcM; のように ; を 2つ指定すると、一時的に16進数で表示する。(SrcM は出力される変数名)
折り返しの詳細については Limit の説明を参照。
PrintCSVCSVフォーマットに従って変数の値を表示する。 エクセルで読み込ませるために使用する。例えば「Output result.csv」のように した後 PrintCSV を行えば、 エクセルで開くことのできる CSV ファイルを作成できる。
この CSV ファイルはシフトJISモードでもUTF8モードでも、 ダブルクリックで正しく開くことができる。
変数名に続けて ; と任意の文字列を指定することによって、 出力される変数名を一時的にその文字列に変更することが可能。
更に文字列・コード型変数(例えば Title) に対して PrintCSV Title;; や Print Title;タイトル; のように ; を 2つ指定すると、一時的に引用符で囲まない。(タイトル は出力される変数名)
折り返しの詳細については Limit の説明を参照。
文字列・コード型の引用符で囲む条件については Format の説明を参照。
PrintTSVデータの区切りをカンマからタブになることを除けば PrintCSV とほぼ同じ。
例えば「Output result.tsv」のように した後 PrintTSV を行えばエクセルで開くことのできる TSV ファイルを作成できる。 PrintCSV と違い、PrintTSV で作成した TSV ファイルはポコムのプログラムで読み込むことが可能。
拡張子 .tsv をエクセルに関連付けてあればシフトJISモードではダブルクリック するだけで開くことができる。UTF8モードではあらかじめ用意した「タスクバーのピン止め」や 「クイック起動」などからエクセルを起動して、そこから TSV ファイルを開けば 正しく開くことができる。
Quitプログラムを直ちに終了する。
ウィンドウズモードではログは消される。 HIT_ENTER を指定してコンパイルしても、プロンプトを表示しない。 REPORT_MEM を指定してコンパイルしても、メモリ状態を報告しない。
Range 整数、浮動小数点、コード型変数の取る値を制限する。 主に AUTO マクロ内で使用される。 範囲条件の種類として ==、!=、>、>=、<、<= が使える。
    例  Range N >= 0  # N は 0 以上に制限される。
   
また、複数の範囲条件を設定することができる。
    例  Range N > 0 <= 10 != 5
   
この場合 N は 1,2,3,4,6,7,8,9,10 に制限される。 (注意! 範囲条件を表す記号の前後に必ず空白を置くこと。)
例えば、Range N == 5 とすると N に 5 代入される。
Pocom Version 3 より前は何度も解除/設定できたが、 Version 3 以降は一つの変数に対して1回だけしか設定できなくなった。 理由は AUTO マクロで暴走しないように Range を設定したのに、データファイルで Range を変更することにより、 暴走するデータが作れることを防ぐため。
Reset配列を空にする。 サイズを決める変数も0になる。例えば配列 A,B を空にするには、
Reset A B
とする。これは Add 関数群を使用する前に配列 A B を初期化するのに使う。Add 関数群を使わないなら必要になる場面はない。 サイズを決める変数に0以外という Range 関数による範囲指定があったり FIX 変数であっても無視する。
ちなみに、この例と似たようなことをデーターファイル上で行うには、明示的には、
       A B
       $
分かりにくいが、空白行が配列の終わりであることを利用して単に
       A B

のように書く。ただし、これらのように書くとサイズを決める変数に0以外という範囲指定があるとエラーとなる。
Seed乱数の種を設定する。 これにより、標準関数 Unif( ) の返す乱数系列を違うものに変更できる。 引数がない場合は、現在時刻を種とする。 Seed を呼び出さずに Unif( ) を呼び出すと Seed("1") の状態から実行される。
Sort配列をソートする。
最初にオプションを指定する。省略すると -a を指定したのと同じになる。
次にソートのキーを指定する。Ivec,Cvec,Rvec,Svec が指定可能。Cdef は指定できない。
キーを Cvec にした場合は、オプションとして -a,-d,-A,-D が指定可能。
キーを Ivec,Rvec,Svec にした場合は、オプションとして -a,-d が指定可能。
以降、同時にソートする配列を指定する。なくてもかまわない。Cdef は指定できない。
       N:Int DN:Int DV:Cdef[DN], L:Ivec[N], RV:Rvec[N], CV[N]<DV> SM:Smat[N][M], SJ:Sjag[N][L}
       Sort RV SJ SM       # RV をキーに RV SJ SM を昇順にソートする(ascend)-a
       Sort -d RV SJ SM    # RV をキーに RV SJ SM を降順にソートする(descend)-d
       Sort CV RV SJ SM    # CV の値をキーに CV RV SJ SM を昇順にソートする(ascend)-a
       Sort -d CV RV SJ SM # CV の値をキーに CV RV SJ SM を降順にソートする(descend)-d
       Sort -A CV RV SJ SM # CV の文字列をキーに CV RV SJ SM を昇順にソートする(ascend)-A
       Sort -D CV RV SJ SM # CV の文字列をキーに CV RV SJ SM を降順にソートする(descend)-D
System他のプログラムを実行する。
例:
       System mkdir Temp
System は他のポコムプログラムと連携するのを主な目的として用意した。
System から呼び出されたポコムプログラムから、さらに System を使ってプログラムを 呼び出すことはできない。2重呼び出しを禁止した理由は 循環参照して無数にプログラムを実行する危険を回避するため。 例えば、
no-good.txt:

    System Example no-good.txt

という自分自身を繰り返し実行しようとするファイル(no-good.txt)を用意して、
    C:\...\Pocom> Example no-good.txt
とするとエラーとなる。

プログラムは2重呼び出しが行われるかどうかを判断するために System を実行すると最初に、 System.tmp という名前の空のファイルを作成し、実行が終了した後に消去する。
(エラー終了した場合は System.tmp に '$' を書き込み、親のプログラムに報せる。)
そして System.tmp という名前のファイルがある場合、 プログラムは System を実行できないようになっている。
従って、何らかの原因で System.tmp という名前のファイルが残ってしまった場合は、 プログラムから System を実行できなくなる。 このトラブルは、System.tmp という名前のファイルを消すことにより解決する。 System に渡すコマンドがひとつ又は複数のカンマの並びで終わる場合は、 そのカンマかカンマの並びは削除される。

Ubuntu では、

System Example test.txt
として、カレントフォルダに Example という名前のファイルがある場合 ./ が補われ、 system("./Example test.txt"); が呼び出される。

Load、Output、Append の行にコメントを入れる場合は、ファイル名の後に[TAB]を入れ、 その右にコメントを書くか、ファイル名を " で囲みます。

標準変数・定数・型は計算ルーチン等 C の関数から参照できます。

__POCOM__ポコムのバージョン。ver 5.02 ならば 502。
ALWAYS_FALSE常に偽。
byte,bvec,bmat,bjag常に8ビット符号なし整数。(16ビットコンパイラでは USE_BYTE、または USE_ALL_TYPES、または ASIF32 を定義する必要がある)
dbl,dvec,dmat,djag倍精度浮動小数点数。(16ビットコンパイラの場合は USE_DBL、または USE_ALL_TYPES、または ASIF32 を定義する必要がある)
EJ(E,J)マクロ JPN が1なら日本語、0なら英語に切り替えるマクロ
例:fprintf(fp,EJ("English\n","日本語\n"));
bool EndOfLineバッファの終わりまで読んだら true。
double EXA#define EXA (1000000.0*1000000.0*1000000.0)
乱数をジャンプさせるときに便利。
ただし、Jump(EXA+1.0) のように指定しても 1.0 は丸められて Jump(EXA) と結果は変わらない。何故なら、 多くの場合 double は53ビットの仮数部を持つのに対し EXA は60ビットだからである。
flt,fvec,fmat,fjag単精度浮動小数点数。(16ビットコンパイラの場合は USE_FLT、または USE_ALL_TYPES、または ASIF32 を定義する必要がある)
FILE*fp出力ファイル。通常は stdout に設定されている。Append、Output で変更する。
half,hvec,hmat,hjag半精度浮動小数点数。(C++でないCコンパイラでは USE_HALF を指定する必要がある)
bool HaveCmdLineFileコマンドラインで入力ファイルを指定すると true。指定しないと false。
Int,ivec,imat,ijag通常の場合 int で、 #include "pocom.h" の前に #define INT_64 とすると long long または __int64。
16ビットコンパイラで、 #include "pocom.h" の前に #define INT_32 とすると long。
Int32_t32ビット符号付整数。
Int64_t64ビット符号付整数。
lint,lvec,lmat,ljag常に long long か __int64。
int Limit__Print, PrintCSV, PrintTSV をするときに、一番右の配列を並べて表示する数を制限して折り返す。
@一番右の配列がベクトルならば、左には単純変数のみを指定できる。
A一番右の配列が固定列行列・可変列行列ならば、左には単純変数とベクトルを指定できる。
大きな配列を長さ80文字以内の行に収めたい場合などに使う。 Limit__=0; とすると解除される。
Limit__=-79 のように負の値を指定すると79文字を超えないように調整する。(デフォルト)
ウィンドウズモードではデフォルトは -1024 となる。 Limit__=DEF_LIMIT__; のようにするとデフォルトの -79 か -1024 となる。
MODEL_SIZE(A,B,C,D)、MSメモリモデル別に値を選ぶ
A:16ビット:スモールモデル・ミディアムモデル
B:16ビット:ラージモデル・コンパクトモデル
C:32ビット
D:64ビット
#define MODEL_SIZE(A,B,C,D) (sizeof(int)<=2?(sizeof(int*)<=2?A:B):sizeof(int*)<=4?C:D)
Int MulAdd(Int n,Int mul,Int add)n*mul+add を返す。 オーバフローのチェックをする。
nint,nvec,nmat,njag常に 32ビット符号付整数。
int NoList0以外に設定すると変数のリストを表示する動作を抑止する。
double PETA#define PETA (1000.0*1000000.0*1000000.0)
乱数をジャンプさせるときに便利。
EXA と違い50ビットなので Jump(PETA+1.0) としても正しくジャンプする。 同じ種で PETA ずつ間隔を開けて初期化した場合4スレッドまでのマルチスレッドで正しくジャンプする。
PRI3232・64ビットコンパイラなら "" 16ビットコンパイラなら "l"。
fprintf(fp,"# %" PRI32 "d\n",(Int32_t)x); のように使う。
PRI64"ll" または "I64"。
fprintf(fp,"# %" PRI64 "d\n",(Int64_t)x); のように使う。
PRIzInt が int なら ""。
Int が long long または __int64 なら "ll" または "I64"。
16ビットコンパイラで Int が long なら "l"。
fprintf(fp,"# %" PRIz "d\n",(Int)x); のように使う。
Rand_t乱数のワークエリアを確保するとき宣言する。
   Rand_t LocalSeq;  /* ローカルに乱数の状態を確保 */
   Srand_r(1,LocalSeq); /* 1を種に領域の初期化 */

   /* スレッドの番号を利用して、他のスレッドから十分に離れた場所へジャンプ */
   Jump_r(TERA*ThreadNo,LocalSeq);
   
のように使う。
real,rvec,rmat,rjag通常の場合 double で、 #include "pocom.h" の前に #define FLOAT_REAL とすると float。#define HALF_REAL とすると half。
FILE*Stderrエラー出力ファイル。通常は stderr が設定されている。
double TERA#define TERA (1000000.0*1000000.0)
乱数をジャンプさせるときに便利。
EXA と違い40ビットなので Jump(TERA+1.0) としても正しくジャンプする。 同じ種で TERA ずつ間隔を開けて初期化した場合4096スレッドまでのマルチスレッドで正しくジャンプする。
tint,tvec,tmat,tjag常に 16ビット符号付整数。 (16ビットコンパイラでは USE_TINT、または USE_ALL_TYPES、または ASIF32 を定義する必要がある)
Uint32_t32ビット符号なし整数。
Uint64_t64ビット符号なし整数。
Unsigned通常の場合 unsigned で、 #include "pocom.h" の前に #define INT_64 とすると unsigned long long または unsigned __int64。
16ビットコンパイラで、 #include "pocom.h" の前に #define INT_32 とすると unsigned long。
wptr制御構造体の共用体へのポインタ
char ZeroStr[1]長さ0の文字列定数

標準関数は計算ルーチン等 C の関数から呼び出します。

AddTo???? 関数群ポコム関数 Add の下請け関数。値をベクトル型に追加したり、ベクトルを固定列・可変列行列に追加する。
void AddToIvec(ivec,Int),   void AddToImat(imat,Int,ivec), void AddToIjag(ijag,Int,ivec),
void AddToCvec(cvec,code),  void AddToCmat(cmat,Int,cvec), void AddToCjag(cjag,Int,cvec), 
void AddToBvec(bvec,byte),  void AddToBmat(bmat,Int,bvec), void AddToBjag(bjag,Int,bvec), 
void AddToTvec(tvec,short), void AddToTmat(tmat,Int,tvec), void AddToTjag(tjag,Int,tvec), 
void AddToNvec(nvec,nint),  void AddToNmat(nmat,Int,nvec), void AddToNjag(njag,Int,nvec), 
void AddToLvec(lvec,lint),  void AddToLmat(lmat,Int,lvec), void AddToLjag(ljag,Int,lvec), 
void AddToHvec(hvec,half),  void AddToHmat(hmat,Int,hvec), void AddToHjag(hjag,Int,hvec),
void AddToFvec(fvec,float), void AddToFmat(fmat,Int,fvec), void AddToFjag(fjag,Int,fvec),
void AddToDvec(fvec,double),void AddToDmat(dmat,Int,dvec), void AddToDjag(djag,Int,dvec),
void AddToRvec(rvec,real),  void AddToRmat(rmat,Int,rvec), void AddToRjag(rjag,Int,rvec),
void AddToSvec(svec,str),   void AddToSmat(smat,Int,svec), void AddToSjag(sjag,Int,svec),
void AddToCdef(cdef,str)

  例:INT(N,3,"")
      IVEC(L,3,N,"")
      IJAG(J,3,L,"")

      const Int vec[4]={1,2,3,4};
      AddToIvec(L,3);
      AddToIjag(J,4,vec);
AddTo????__ 関数群AddTo???? 関数群のさらに下請け関数。値をベクトル型に追加したり、ベクトルを固定列・可変列行列に追加する。
void AddToIvec__(ivec_*,Int),   void AddToImat__(imat_*,Int,ivec), void AddToIjag__(ijag_*,Int,ivec),
void AddToCvec__(cvec_*,code),  void AddToCmat__(cmat_*,Int,cvec), void AddToCjag__(cjag_*,Int,cvec), 
void AddToBvec__(bvec_*,byte),  void AddToBmat__(bmat_*,Int,bvec), void AddToBjag__(bjag_*,Int,bvec), 
void AddToTvec__(tvec_*,short), void AddToTmat__(tmat_*,Int,tvec), void AddToTjag__(tjag_*,Int,tvec), 
void AddToNvec__(nvec_*,nint),  void AddToNmat__(nmat_*,Int,nvec), void AddToNjag__(njag_*,Int,nvec), 
void AddToLvec__(lvec_*,lint),  void AddToLmat__(lmat_*,Int,lvec), void AddToLjag__(ljag_*,Int,lvec), 
void AddToHvec__(hvec_*,half),  void AddToHmat__(hmat_*,Int,hvec), void AddToHjag__(hjag_*,Int,hvec),
void AddToFvec__(fvec_*,float), void AddToFmat__(fmat_*,Int,fvec), void AddToFjag__(fjag_*,Int,fvec),
void AddToDvec__(fvec_*,double),void AddToDmat__(dmat_*,Int,dvec), void AddToDjag__(djag_*,Int,dvec),
void AddToRvec__(rvec_*,real),  void AddToRmat__(rmat_*,Int,rvec), void AddToRjag__(rjag_*,Int,rvec),
void AddToSvec__(svec_*,str),   void AddToSmat__(smat_*,Int,svec), void AddToSjag__(sjag_*,Int,svec),
void AddToCdef__(cdef_*,str)
  例:INT(N,3,"")
      IVEC(L,3,N,"")
      IJAG(J,3,L,"")

      const Int vec[4]={1,2,3,4};
      AddToIvec__(L_,3);
      AddToIjag__(J_,4,vec);
void Alloc(const char*)配列の確保を行う。例 Alloc("C X") ;
void AllocWord(VAR)配列の確保を行う。例 AllocWord( C ) ;
void AllocWord__(wptr)配列の確保を行う。例 AllocWord__((wptr)C_ ) ;
void AllocStr(SVAR,size_t)文字列領域の確保を行う。例 AllocStr(S,11);(S=malloc(11); のイメージ。)
void AllocSvec(SVAR,Int,size_t)文字列領域の確保を行う。例 AllocSvec(SV,1,11);(SV[1]=malloc(11); のイメージ。)
void AllocSmat(SVAR,Int,Int,size_t)文字列領域の確保を行う。例 AllocSmat(SM,1,2,11);(SM[1][2]=malloc(11); のイメージ。)
void AllocSjag(SVAR,Int,Int,size_t)文字列領域の確保を行う。例 AllocSjag(SJ,1,2,11);(SJ[1][2]=malloc(11); のイメージ。)
unsigned BackRand()整数乱数を逆順に生成する。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
unsigned BackRand_r(Rand_t)整数乱数を逆順に生成する。マルチスレッド用。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif()浮動小数点乱数を逆順に生成する。FLOAT_REAL が有効なら 24ビット精度、HALF_RAL が有効なら 11ビット精度。それ以外は 32ビット精度。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif_r(Rand_t)浮動小数点乱数を逆順に生成する。FLOAT_REAL が有効なら 24ビット精度、HALF_RAL が有効なら 11ビット精度。それ以外は 32ビット精度。マルチスレッド用。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif11()浮動小数点乱数を逆順に生成する。11ビット精度。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif11_r(Rand_t)浮動小数点乱数を逆順に生成する。11ビット精度。マルチスレッド用。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif24()浮動小数点乱数を逆順に生成する。24ビット精度。(16ビットコンパイラで使用するには BACK_RAND を定義する必要がある)
double BackUnif24_r(Rand_t)浮動小数点乱数を逆順に生成する。24ビット精度。マルチスレッド用。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif32()浮動小数点乱数を逆順に生成する。32ビット精度。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif32_r(Rand_t)浮動小数点乱数を逆順に生成する。32ビット精度。マルチスレッド用。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
double BackUnif53()浮動小数点乱数を逆順に生成する。53ビット精度。(16ビットコンパイラで使用するには BACK_RAND を定義する必要がある)
double BackUnif53_r(Rand_t)浮動小数点乱数を逆順に生成する。53ビット精度。マルチスレッド用。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある)
char*CjagStr(CJ,I,J)コード型である可変列列整数行列の要素を対応する文字列に変換する。
void Check(const char*)配列のエラーチェックを行う。例 Check("A B") ;
bool CheckIntOverflow(n,mul,add) n*mul+add の結果がオーバーフローしたら1を返す。
バージョン 5.02 からは、この代わりに MulAdd() を使用してください。
n、add は Int 型。mul は1以上の Int 型。以下のように定義されている。
#define CheckIntOverflow(n,mul,add) ((mul)<0||(mul&&(Unsigned)(n)>\
((((Unsigned)1)<<(sizeof(Int)*8-1))-1-(add))/(mul)))
void CheckWord(VAR)配列のエラーチェックを行う。例 CheckWord( A ) ;
void CheckWord__(wptr)配列のエラーチェックを行う。例 CheckWord__((wptr)A_ ) ;
double ClockSec()プログラム開始からの経過時間を秒単位で返す。
char*CmatStr(CM,I,J)コード型である固定列整数行列の要素を対応する文字列に変換する。
char*CodeStr(C)コード型である単純整数を対応する文字列に変換する。
void CopyArg(const char*,const char*)引数をバッファに転送する。 第一引数は親関数名、第二引数は転送する文字列。
例 CopyArg("foo",argument) ;
char*CvecStr(CV,I)コード型である整数ベクトルの要素を対応する文字列に変換する。
void DoEvents()ウィンドウズモードで時間のかかる処理をするときに、途中でこれを適当な間隔で呼び出す ことにより、閉じるボタンで終了できるようにする。
half dtoh(double)倍精度浮動小数点数を半精度浮動小数点数へ変換する。
void FlushFp()ウィンドウズモードで fprintf(fp, ...) 等で溜まった文字列を画面に表示する。
ウィンドウズモードでは DoEvents() を内部で呼び出すので、閉じるボタンが有効になる。
これは、ウィンドウズモードの時は Print、PrintCSV、PrintTSV、Echo、List、Progress、Progress2、Clock、Lap、Error で呼び出される。
ウィンドウズモードでないときは、fflush(fp) が呼び出される。
void EndArg()引数の処理が終わったことをシステムに知らせる。
void Error(const char*,const char*)エラーメッセージを表示して終了する。
void FreeMem(void*)free( ) または、delete[ ] の代わりに使う。
void FreeMemRaw(void*)GetMemRaw(size_t) で確保したメモリを開放する。マルススレッドでも使用可能。
void FreeVmj(vmj*)高速線形リストを一つ開放する
void FreeWord(VAR)メモリの開放を行う。サイズを決める変数は影響を受けない。例 FreeWord( A ) ;
void FreeWord__(wptr)メモリの開放を行う。サイズを決める変数は影響を受けない。例 FreeWord__((wptr)A_ ) ;
half ftoh(float)単精度浮動小数点数を半精度浮動小数点数へ変換する。
char*GetMem(Int,size_t)calloc( ) または、new[ ] の代わりに使う。領域は0で埋められる。
使い終わったら FreeMem(p) しなければならない。 ALIGN_MEM が0ならば sizeof(size_t) にアライメントされる。 ALIGN_MEM が0以外ならば、その値で返されるポインタの値とサイズがアライメントされる。
エラーが起きたらプログラムは終了する。
char*GetMemSvec(Int)calloc( ) または、new[ ] の代わりに使う。領域は0で埋められる。 使い終わったら FreeMem(p) しなければならない。 ALIGN_MEM が0以外でも sizeof(int*) にアライメントされる。SVEC, SMAT, SJAG 専用。
エラーが起きたらプログラムは終了する。
char*GetMemRaw(size_t)calloc( ) または、new[ ] の代わりに使う。領域は0で埋められる。
エラーが起きたら0を返すだけで何もしない。 使い終わったら FreeMemRaw(p) しなければならない。マルススレッドでも使用可能。
vmj*GetVmj()高速線形リストを一つ確保する。使い終わったら FreeVmj(p) しなければならない
double htod(half)半精度浮動小数点数を単精度浮動小数点数へ変換する。
float htof(half)半精度浮動小数点数を単精度浮動小数点数へ変換する。
real htor(half)半精度浮動小数点数を real 型精度浮動小数点数へ変換する。
void Jump(double)乱数をジャンプさせる。 (16ビットのコンパイラの場合 pocom.h をインクルードする前に JUMP_RAND か ASIF32 を定義すると使用可能。 BACK_RAND か ASIF32 を0以外に定義すると負の値で逆方向へジャンプできる。)
void Jump_r(double,Rand_t)乱数をジャンプさせる。マルチスレッド用。(16ビットのコンパイラの場合 pocom.h をインクルードする前に JUMP_RAND か ASIF32 を0以外に定義すると使用可能。 JUMP_RAND か ASIF32 を定義すると負の値で逆方向へジャンプできる。)
double LapSec()直前の Lap 関数の呼び出しからの経過時間を秒単位で返す。
double LastClock直前の Clock 関数が表示した時間を秒単位で記録している。
double LastLap直前の Lap 関数が表示した時間を秒単位で記録している。
void PrintSec(double,const char*)第一引数で指定した秒単位の時間を表示する。 時間表示の右に第二引数の文字列も表示する。
void Progress(const char*msg,Int i,Int n) 時間のかかる計算等で stderr に n が1以上なら進捗率を 0.5 秒ごとに表示する。
i+1 が n ならば 100% と表示して改行する。
n が0の場合は i を表示する。特別に i が -1 ならば、"END" と表示して改行する。
n が負の場合は何も表示しない。
ウィンドウズモードではウィンドウのタイトルバーに表示する。
ウィンドウズモードでは DoEvents() を Progress() 内部で呼び出すので、閉じるボタンが有効になる。
マクロ NO_PROGRESS が0以外なら何も表示しない。この時ウィンドウズモードならば、DoEvents() のみ呼び出す。
msg には長さ64より長い文字列を渡しても64までしか表示されない。 日本語を渡すには EJ( ) マクロを使用すること。
進捗率を 0.250 秒ごとに表示するよう変更するには、pocom.h をインクルードする前に、
#define PROGRESS_TICK 250
を書き加える。
void Progress2(const char*msg,Int i,Int n,Int j,Int m) Progress( ) の2重ループ用。
i は外側のループのカウンター。n は外側のループの大きさ。j は内側のループのカウンター。m は内側のループの大きさ。
n や m が0以下ならば何も表示しない。
Uint32_t Rand()32ビットの符号なし整数乱数を返す。
Uint32_t Rand_f()0以外の32ビットの符号なし整数乱数を返す(高速低品質)。
Uint32_t Rand_m(N)0以外の32ビットの符号なし整数乱数を返す(高速低品質)。マルチスレッド用。N は0以上 FAST_RAND 未満。
Uint32_t Rand_r(Rand_t)マルチスレッド用の32ビットの符号なし整数乱数。
byte ReadByte()バッファから byte を読む。(範囲チェックなし)
byte ReadByteRange(IVAR)バッファから byte を読む。 (範囲チェックを行う。IVAR は整数変数のいずれか)
code ReadCode(CDEF)バッファからコードを読む。(範囲チェックなし)
例 i = ReadCode( Node ) ;
code ReadCodeRange(CDEF,IVAR)バッファからコードを読む。 (範囲チェックを行う。IVAR は整数変数のいずれか)
例 i = ReadCodeRange( Node,From ) ;
float ReadDbl()バッファから倍精度浮動小数点数を読む。(範囲チェックなし)
float ReadDblRange(RVAR)バッファから倍精度浮動小数点数を読む。 (範囲チェックを行う。RVAR は浮動小数点数のいずれか)
float ReadFlt()バッファから単精度浮動小数点数を読む。(範囲チェックなし)
float ReadFltRange(RVAR)バッファから単精度浮動小数点数を読む。 (範囲チェックを行う。RVAR は浮動小数点数のいずれか)
half ReadHalf()バッファから半精度浮動小数点数を読む。(範囲チェックなし)
half ReadHalfRange(RVAR)バッファから半精度浮動小数点数を読む。 (範囲チェックを行う。RVAR は浮動小数点数のいずれか)
int ReadInt()バッファから整数を読む。(範囲チェックなし)
int ReadIntRange(IVAR)バッファから整数を読む。 (範囲チェックを行う。IVAR は整数変数のいずれか)
例 i = ReadIntRange( N ) ;
lint ReadLint()バッファから long long を読む。(範囲チェックなし)
lint ReadLintRange(IVAR)バッファから long long を読む。 (範囲チェックを行う。IVAR は整数変数のいずれか)
lint ReadNint()バッファから int を読む。(範囲チェックなし)
lint ReadNintRange(IVAR)バッファから int を読む。 (範囲チェックを行う。IVAR は整数変数のいずれか)
real ReadReal()バッファから浮動小数点を読む。(範囲チェックなし)
real ReadRealRange(RVAR)バッファから浮動小数点を読む。 (範囲チェックを行う。RVAR は浮動小数点数の変数のいずれか)
例 r = ReadRealRange( A ) ;
char*ReadStr()バッファから文字列を読む。
short ReadTint()バッファから short を読む。(範囲チェックなし)
short ReadTintRange(IVAR)バッファから short を読む。 (範囲チェックを行う。IVAR は整数変数のいずれか)
wptr ReadWord()バッファから変数名・関数名を読む。
void ResetWord(VAR)配列を空にする。サイズを決める変数も0になる。例 ResetWord( A ) ;
void ResetWord__(wptr)配列を空にする。サイズを決める変数も0になる。例 ResetWord__((wptr)A_ ) ;
size_t RowSize(VAR)配列が持つ要素数を返す。ベクトルならば要素数、固定/可変列行列ならば行数を返す。
half rtoh(float)real 型浮動小数点数を半精度浮動小数点数へ変換する。
void SetStr(SVAR,const char*)例:SetStr(S,"abc");(S=strdup("abc"); のイメージ。)
void SetSvec(SVAR,int,const char*)例:SetSvec(SV,1,"abc");(SV[1]=strdup("abc"); のイメージ。)
void SetSmat(SVAR,int,int,const char*)例:SetSmat(SM,1,2,"abc");(SM[1][2]=strdup("abc"); のイメージ。)
void SetSjag(SVAR,int,int,const char*)例:SetSjag(SJ,1,2,"abc");(SJ[1][2]=strdup("abc"); のイメージ。)
void SizeChangedBy(SIZE,BY)SIZE:INTまたはIVEC、BY:変数または関数。SIZEを変化させた原因を記録する。
void Srand(Uint32_t)乱数初期化。第一引数に種を指定する。
void Srand_r(unsigned,Rand_t)マルチスレッド用の乱数初期化。第一引数に種を指定する。
char*Strdup(const char*)strdup( ) の代わりに使う。ポコムの文字列型変数では使用しないこと。使い終わったら FreeMem( ) で解放する必要がある。
例:char*s=Strdup("abc"); ... FreeMem(s);
void SwapRow(mat,int,int)行列の二つの列やベクトルの要素を入れ替える。可変列行列には使用しないこと。
double Unif()0以上1未満の浮動小数点乱数を返す。FLOAT_REAL が有効なら 24ビット精度、HALF_RAL が有効なら 11ビット精度。それ以外は 32ビット精度。
double Unif_f()0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。FLOAT_REAL が有効なら 24ビット精度、HALF_RAL が有効なら 11ビット精度。それ以外は 32ビット精度。
double Unif_m(N)0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。FLOAT_REAL が有効なら 24ビット精度、HALF_RAL が有効なら 11ビット精度。それ以外は 32ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。
double Unif_r(Rand_t)マルチスレッド用の0以上1未満の浮動小数点乱数。FLOAT_REAL が有効なら 24ビット精度、HALF_RAL が有効なら 11ビット精度。それ以外は 32ビット精度。
double Unif11()0以上1未満の浮動小数点乱数を返す。11ビット精度。
double Unif11_f()0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。11ビット精度。
double Unif11_m(N)0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。11ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。
double Unif11_r(Rand_t)マルチスレッド用の0以上1未満の浮動小数点乱数。11ビット精度。
double Unif24()0以上1未満の浮動小数点乱数を返す。24ビット精度。
double Unif24_f()0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。24ビット精度。
double Unif24_m(N)0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。24ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。
double Unif24_r(Rand_t)マルチスレッド用の0以上1未満の浮動小数点乱数。24ビット精度。
double Unif32()0以上1未満の浮動小数点乱数を返す。32ビット精度。
double Unif32_f()0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。32ビット精度。
double Unif32_m(N)0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。32ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。
double Unif32_r(Rand_t)マルチスレッド用の0以上1未満の浮動小数点乱数。32ビット精度。
double Unif530以上1未満の浮動小数点乱数を返す。53ビット精度。
double Unif53_f()0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。53ビット精度。
double Unif53_m(N)0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。53ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。
double Unif53_r(Rand_t)マルチスレッド用の0以上1未満の浮動小数点乱数。53ビット精度。
void UpdateCvar(CVAR)CVAR は CODE,CVEC,CMAT,CJAG 変数のどれかである。
NO_CHECK_CDEF が無効で CVAR の参照している CDEF 変数が縮小したときに、CVAR 変数を表示してもエラーが出ないようにする。
データファイルから CVAR が読み込まれる場合、自動的に UpdateCvar( ) が行われるので、 これをプログラムに書く必要になる場面は滅多にないだろう。

第11章 X86_INTRIN について

pocom.h をインクルードする前に #define X86_INTRIN のように定義すれば、 以下の関数が使用可能になります。

これらはコンパイラやアセンブラを使わず、機械語をプログラムに埋め込んだので、 Borland C++ 5.5.1 でも使用可能です。もちろん16ビットコンパイラやインテルや AMDのCPU上以外では使うことはできません。

void RetOnly( )何もしない。すぐに返る。
関数呼び出しのオーバーヘッドを計測するため。
int HaveCpuid( )Cpuid が使用可能なら1
int HaveSSE( )SSE が使用可能なら1
int HaveSSE2( )SSE2 が使用可能なら1
int HaveSSE3( )SSE3 が使用可能なら1
int HaveSSSE3( )SSSE3 が使用可能なら1
int HaveSSE4_1( )SSE4.1 が使用可能なら1
int HaveSSE4_2( )SSE4.2 が使用可能なら1
int HaveAVX( )AVX が使用可能なら1
int HaveAVX2( )AVX2 が使用可能なら1
int HaveRdtsc( )Rdtsc( ) が使用可能なら1
int HaveRdtscp( )Rdtscp(Uint32_t*aux) が使用可能なら1。
( core i7,i5,i3 等のCPUで使用可能 )
int HaveRdrand( )物理乱数 Rdrand32( ) と Rdrand64( ) が使用可能なら1。
第3世代の Core i7,i5,i3 以降のCPU等で使用可能
Int64_t Rdtsc( )CPUの rdtsc 命令を使って現在のクロックカウンターを得る
Int64_t CpuidRdtsc( )CPUの cpuid 命令を実行した後 rdtsc 命令を使って現在のクロックカウンターを得る。
Rdtsc( ) より時間がかかるが、より正確に計測することができる。
Int64_t Rdtscp(Uint32_t*aux)CPUの rdtscp 命令を使って現在のクロックカウンターを得る。
aux で示された場所に IA32_TSC_AUX MSR(使用しているプロセッサの番号) を保存する。aux を0にすると保存しない。
工夫すれば Rdtscp(unsigned*aux) のほうが CpuidRdtsc( ) よりもさらに正確なクロック数を得ることができる。
int Bsf(size_t)Bit scan forward を行う。0の結果は未定義。
int Bsf32(Uint32_t)Bit scan forward を行う。0の結果は未定義。
int Bsf64(Uint64_t)Bit scan forward を行う。64ビットのプログラムのみ使用可能。0の結果は未定義。
int Bsr(size_t)Bit scan reverse を行う。0の結果は未定義。
int Bsr32(Uint32_t)Bit scan reverse を行う。0の結果は未定義。
int Bsr64(Uint64_t)Bit scan reverse を行う。64ビットのプログラムのみ使用可能。0の結果は未定義。
int Bswap32(Uint32_t)バイトの順番を並び替える。intel486 以降
int Bswap64(Uint64_t)バイトの順番を並び替える。64ビットのプログラムのみ使用可能。
int Rdrand32(Uint32_t*val)CPUの rdrand 命令を使って32ビットの物理乱数を val で示された場所に得る。
失敗すると0が返り、成功すると1が返る。
int Rdrand64(Uint64_t*val) Rdrand32( ) の64ビット版。32ビットのコンパイラでも使用可能。
void MmPause(unsigned num) 約 num×10 クロックだけCPUを待機させる。SSE2を持たないCPUでは REP NOP が num 回繰り返される。
Uint32_t NextRdrand32(void)CPUの rdrand 命令を使って32ビットの物理乱数を返す。エラー処理付き。
Uint64_t NextRdrand64(void) NextRdrand32( ) の64ビット版。32ビットのコンパイラでも使用可能。

第12章 メモリのアライメント等の詳細

@CHECK_MEM が有効で NO_FAST_STR が無効な場合

32/64ビットコンパイラでのデフォルト。CHECK_HEAP も有効になっている。
16ビットコンパイラの場合は CHECK_MEM, CHECK_HEAP, ASIF32 のいずれかを有効にすると該当する。
32/64/16ビットのいずれでも NO_STR を有効にすると NO_FAST_STR が有効になるので該当せず、Aになる。

アライメント サイズのアライメントヒープオバーフローの検査OpenMP 並列リージョン内
GetMem(),値の配列 ALIGN_MEM(0:sizeof(size_t))ALIGN_MEM(0:しない) CHECK_HEAPによる 使用不可
GetMemSvec(),ポインタの配列sizeof(int*) sizeof(int*) CHECK_HEAPによる 使用不可
GetMemNoCheck() sizeof(size_t) sizeof(size_t) しない 使用不可
GetMemRaw() しない しない しない 使用可
Strdup() sizeof(size_t) 1 しない 使用不可
SetStr(),AllocStr() 等 1 1 しない 使用不可

ACHECK_MEM が有効で NO_FAST_STR が有効な場合

32/64ビットコンパイラでは、NO_FAST_STR か NO_STR を有効にすると該当する。
16ビットコンパイラの場合は CHECK_MEM, CHECK_HEAP, ASIF32 のいずれかを有効にして、
NO_FAST_STR か NO_STR を有効にすると該当する。

アライメント サイズのアライメントヒープオバーフローの検査OpenMP 並列リージョン内
GetMem(),値の配列 ALIGN_MEM(0:sizeof(size_t))ALIGN_MEM(0:しない) CHECK_HEAPによる 使用不可
GetMemSvec(),ポインタの配列sizeof(int*) sizeof(int*) CHECK_HEAPによる 使用不可
GetMemNoCheck() sizeof(size_t) sizeof(size_t) しない 使用不可
GetMemRaw() しない しない しない 使用可
Strdup() sizeof(size_t) 1 CHECK_HEAPによる 使用不可
SetStr() 等 sizeof(size_t) 1 CHECK_HEAPによる 使用不可
AllocStr() 等 ALIGN_MEM(0:sizeof(size_t))ALIGN_MEM(0:しない) CHECK_HEAPによる 使用不可

BCHECK_MEM が無効で NO_FAST_STR が無効な場合

32/64ビットコンパイラでは NO_CHECK_MEM を有効にすると該当する。
16ビットコンパイラの場合はデフォルトで該当する。
32/64/16ビットのいずれでも NO_STR を有効にすると NO_FAST_STR が有効になるので該当せず、Cになる。

アライメント サイズのアライメントヒープオバーフローの検査OpenMP 並列リージョン内
GetMem(),値の配列 ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
GetMemSvec(),ポインタの配列ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
GetMemNoCheck() ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
GetMemRaw() しない しない しない 使用可
Strdup() ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
SetStr(),AllocStr() 等 1 1 しない 使用不可

CCHECK_MEM が無効で NO_FAST_STR が有効な場合

32/64ビットコンパイラでは NO_CHECK_MEM 有効にし、NO_FAST_STR か NO_STR を有効にすると該当する。
16ビットコンパイラの場合は NO_FAST_STR か NO_STR を有効にすると該当する。

アライメント サイズのアライメント ヒープオバーフローの検査OpenMP 並列リージョン内
GetMem(),値の配列 ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
GetMemSvec(),ポインタの配列ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
GetMemNoCheck() ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
GetMemRaw() しない しない しない 使用可
Strdup() ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可
SetStr(),AllocStr() 等 ALIGN_MEM(0:しない)ALIGN_MEM(0:しない) しない 使用不可

ALIGN_MEM(0:sizeof(size_t)) とは ALIGN_MEM が0以外ならば ALIGN_MEM で、 ALIGN_MEM が0ならば sizeof(size_t) でアライメントすることを表します。
ALIGN_MEM(0:しない) とは ALIGN_MEM が0以外ならば ALIGN_MEM で、 ALIGN_MEM が0ならばアライメントせず new char[n] や、calloc(n,m) の返すポインタをそのまま返すか、 あるいは、返されたポインタに sizeof(size_t)+sizeof(int*) を足したポインタを返すことを意味します。

第13章 エクセルとのやり取り

ポコムのデータをグラフにしたり、計算式を埋め込んだりする時は、 エクセルが便利です。Ubuntu ではエクセルの代わりに LibreOffice calc を使います。 LibreOffice calc ではあらかじめ、「ツール」→「オートコレクトオプション」で 「言語固有のオプション」のでクォーテーションマークが全角にならないように 置換のチェックを二つとも外しておくと便利です。(https://4thsight.xyz/3253) ポコムのバージョン 5.01 からは、 カンマ区切りのデータである .csv ファイルもポコムで読み込むことができるようになったので、 タブ区切りのデータである .tsv ファイルはあまり使わなくなることと思います。

ポコムからエクセル用の .csv、.tsv データを作成して開く

ポコムのデータファイルに Output test.csv のような行を書いて、 出力先を test.csv にします。そして PrintCSV 関数や Echo 関数を使ってデータを書き出します。 すると PrintCSV はカンマ区切りのデータを作成できます。 .csv ファイルは、シフトJISモードでもUTF8モードでもダブルクリックして開くことができます。
同様に Output test.tsv のようにして PrintTSV 関数や Echo 関数を使えばタブ区切りのデータを作成できます。 .tsv ファイルはエクセルと関連付けてあればシフトJISモードであればダブルクリックして開くことができます。 .tsv ファイルはUTF8モードの場合、 エクセルと関連付けてあってダブルクリックして開くと正しく読む込むことができません。 代わりにエクセルを起動してから「ファイル」リボンなどから .tsv ファイルを開くと、 区切り文字を選ぶように要求されるので、区切り子をタブにすれば正しく読むことができます。
LibreOffice calc の場合は .csv ファイルも .tsv ファイルもダブルクリックで開くことができます。 LibreOffice calc は必要に応じて、文字コードの種類を選んだり、区切り子を選ぶことができます。 .csv ファイルの場合は「カンマ」を選び、.tsv ファイル場合「タブ」を選びます。

エクセルで表示されているデータから .csv、.tsv ファイルを書き出す方法

.csv ファイルを読み込んで開いた場合は、データを修正した後閉じるボタン「×」を 押せばそのまま修正後のデータが .csv 形式で上書きされます。
ただしUTF8モードでエクセル2013の場合は、 ユニコードテキスト(タブ区切り)でしか保存できません。
エクセル2015以降からは、 UTF8のカンマ区切り .csv ファイルに保存可能になったようです。 (私は新しいエクセルを所持していないので未確認です。)

.tsv ファイルを読み込んで開いた場合は、データを修正した後閉じるボタン「×」を 押せばそのまま修正後のデータを、エクセルは保存しようとします。 ただし、そのままだと拡張子が .txt がファイル名に加えられます。 例えば、修正前の読み込んだファイルが test.tsv ならば test.tsv.txt となります。 これを test.tsv に上書きしたい場合は、ファイル名を入力するときに「test.tsv」 ではなく「"test.tsv"」のようにダブルクォーテーションで囲みます。
UTF8でタブ区切りの .tsv ファイルを書き出すには「名前を付けて保存」で ファイルの種類:「Unicodeテキスト(*.txt)」を選んで保存して一旦エクセルを終了します。 そして、新しいファイルをメモ帳で開き「名前を付けて保存」し、 ファイルの種類:を Windows10 ならば「UTF-8(Bom付き)」それ以前のOSならば「UTF-8」にして、 拡張子を .tsv に変更して保存します。

LibreOffice calc で .csv ファイルから読み込んだデータを修正して .csv に保存するときは、 そのまま閉じるボタン「×」を押せばそのまま修正後のデータが .csv 形式で上書きされます。
LibreOffice calc で .tsv ファイルから読み込んだデータを修正して .tsv に保存するときは、 「名前を付けて保存」でファイルの種類を「テキストCSV(.csv)」を選んで、 区切り子を「タブ」にして保存します。区切り子がタブの場合でも、拡張子は必ず .csv になるので、 面倒ですが、ファイル名の拡張子を .csv から .tsv に手動で変更します。

第14章 諸注意