ポコム(POrtable COMpiler)は C/C++ を使った、小型のフレームワークです。 数値計算、なかでも待ち行列網、グラフ理論や統計分析に向いています。 ポコムは軽くて速いプログラムを、 手っ取り早く開発するのに向いています。 ポコムを使う効果はつぎのとおりです。
ポコムが供給するファイルはつぎのとおりです。
pocom.html このファイル pocom.h ポコムのシステムを記述した C 言語ファイル Example1.c 連立方程式を解く例題 test.txt 例題データ ファイル
「連立方程式を解く」という例題を用いて、 ポコムの簡単な開発例を示します。 例題は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:\>Example1 test.txt 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
以下に、ポコムのプログラム(Example1.c)を示します。
/* Example1.c */ #define FILE_NAME "Example1.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 マクロを使用することを推奨します。)
ポコムは幾つかのデータ型を用意しています。ここではその一部を紹介します。 他のデータ型は第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_ のように _ で終わってはいけません。 これらの名前は、計算ルーチンで、 大域整数変数や関数として、扱うことができます。
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 は real**A; のように宣言したことになります。
厳密にはコンパイラによって real*const __restrict*__restrict A; となります。
ただし、#include "pocom.h" の前に #define NO_RESTRICT とすると、
常に real*const*A; となります。
real は通常 double です。#define FLOAT_REAL とすると real は float になります。
C++コンパイラで #define HALF_REAL とすると real は half になります。
例えば、行列 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 マクロを使って日本語が使えないときに備えて下さい。
なお、32/64ビットコンパイラで JPN が無効な時は、
プログラムやデータファイルの文字コードから推測して、
出力桁数を自動調整するようになります。一方、JPN が有効な時は pocom.h の文字コードに
従って出力桁数を調整します。なお、16ビットのコンパイラの場合で WINUTF8 と JPN が無効の場合は、
デフォルトで後で説明する NO_ADJUST が有効になり桁の調整を行いません。
この場合、シフトJISのみ対応となります。
16ビットのコンパイラで他の文字コードで自動桁調整を行いたい場合は pocom.h をインクルードする前に、
#define USE_ADJUST
としてください。
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","連立方程式を解く"))
計算ルーチン部分を以下に示します。
#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 マクロのファイル名が本当に、それ自身のファイル名かどうか 確認するのに必要です。
計算ルーチンで定義する変数名や関数名も i_ や i__ のように _ で終わってはいけません。
関数 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( ) がないと閉じるボタンも反応しなくなります。
この場合プログラムを終了するには、タスクマネージャーを起動して止めるしかありません。
データファイルにおいて、変数の順序にはある程度自由度があります。 以下のようなデータファイルでも、結果は最初の例と変わりはありません。
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( ) はこのように原因を詳しく報告します。
最初に説明した開発例で作業用行列 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 以外の値になると Check() でエラーとなるようにできます。 (FIX は以前は INTF と同じでしたが、現在は異なります)
また、初期化処理など、起動時に実行したい処理がある場合は、 その処理を行う関数を用意して、AUTO で呼び出すようにします。
さらに、下の test.txt には Print 関数の表示変数名変更機能の例も示します。 これは、.csv ファイルを作成してエクセルに読み込ませる時に、列の名前を日本語化するのに便利です。
/* Example2.c */ #define FILE_NAME "Example2.c" #if defined(PDEF_H) LIST("# " FILE_NAME " version 8.14") 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]; } #endiftest.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; が整数オーバーフローを起こしている場合に エラーとしてプログラムを終了します。
また、今まで例題では単純化するため 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 のさらに高度な使い方を説明します。
データを別ファイルに書かずに、データをプログラムに埋め込んで計算を実行したい場合があります。 それを実現する定義の例(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以外に設定すると、変数のリストを表示する動作を抑止できます。
また、ポコムバージョン 7.02 からはファイルを指定せずに起動すると、通常は ファイル選択ダイアログが出現しますが、NoList を0以外にすると、これも抑止できます。
以下に例を示します。これはこの章の最初のプログラムと全く同じ動作をします。
/* 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
LAST にはプログラムが終了するときに実行するコマンド記述します。 これにより、データファイルに Solve と Print を記述していたのを、 省略することができるようになります。
/* Example1.c */ #define FILE_NAME "Example1.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); } } #endiftest.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
Linux の場合ならば
$ g++ -O4 -Wall -DJPN -o Example1 Example1.c
pocom.zip を解凍したら、まず最初に $DoFirst.bat を実行してください。 共通ファイルが必要なフォルダにコピーされます。
処理が終わりました 続行するには何かキーを押してください ...でキーを押す前に端末のウィンドウのタイトルバーを右クリックして、 [プロパティ]を選びます。
C:\ ... \Pocom\Example>bcc32 -O2 -DJPN -P Example1.c
C:\ ... \Pocom\Example>cl /O2 /EHsc /D JPN /Tp Example1.cのようにしてコンパイルします。
私は Windows と Ubuntu マシンしか所有していないので、確認できませんが、それ以外のマシンでは
64ビットでコンパイルする場合は SYSTEM64 を定義する必要があります。
32ビットでコンパイルする場合は SYSTEM64 を定義する必要はありません。
$ cc -DJPN -DSYSTEM64 Example1.c -lm
pocom.h 内の SYSTEM64 の定義は以下のようになっています。
#if !defined(SYSTEM64) #if defined(_M_X64)||defined(__x86_64__) #define SYSTEM64 1 #elif defined(__SIZEOF_SIZE_T__) && __SIZEOF_SIZE_T__ == 8 #define SYSTEM64 1 #else #define SYSTEM64 0 #endif #endif
これでインテルCPUのコンパイラは SYSTEM64 の自動判別はほとんど上手くいくはずですが、念のため。
また、GNUC 以外のコンパイラでビッグエンディアンのプログラムをコンパイルするには、 BIG_E を定義するしなければならないようになりました。
Example1 [-b] [-<num>] [<ファイル名>] [<ファイル名>] ...
$ ./Example1 test.txt C:\ ... \Pocom\Example>Example1 test.txt
TDM-GCC-64 がインストールされているならば M.bat というバッチファイルをダブルクリックするだけで Example1.exe を作成できます。
TDM-GCC-64 をインストーラーは以下のリンク先で入手できます。
https://jmeubank.github.io/tdm-gcc/C:\ ... \Pocom\Example>m -DJPN
C:\ ... \Pocom\Example>m gcccまたは、省略して
C:\ ... \Pocom\Example>m gc
C:\ ... \Pocom\Example>m 2017または、省略して
C:\ ... \Pocom\Example>m 17
C:\ ... \Pocom\Example>m 2017cまたは、省略して
C:\ ... \Pocom\Example>m 17c
C:\ ... \Pocom\Example>m 2017 /GL /D JPN
C:\ ... \Pocom\Example>m Traとします。
C:\ ... \Pocom\Example>m 32のようにも指定できます。
C:\ ... \Pocom\Example>m -D"ALIGN_MEM=32"のようにダブルクォーテーションで囲みます。
C:\ ... \Pocom\Example>mの代わりに
C:\ ... \Pocom\Example>Mのように大文字にするとコンパイルが終わった後、キーを押されるのを待ちます。 そして、完成するプログラムも終了するときに改行キーが押されるのを待ちます。 また M.bat のアイコンをダブルクリックしてもキーが押されるのを待ちます。 そして、コンパイルエラーが起きた場合は m でも M でもキーが押されるのを待ちます。
C:\ ... \Pocom\Example>.\mとすると M と同様に改行キーが押されるのを待ちますが、
C:\ ... \Pocom\Example>.\m +のように、コマンドラインのどこかに + を入れると改行キーを待ちません。
C:\ ... \Pocom\Example>m +-のように、コマンドラインのどこかに +- を入れるとC言語としてコンパイルします。
C:\ ... \Pocom\Example>m ++のように、コマンドラインのどこかに ++ を入れるとC++としてコンパイルします。
@echo off echo off set SELF=m set ARG0=%0 set COMPILER=Gcc set PG=Example1 set EXE= set SUBSRCS= set OPTIONS= set HIT_OPTIONS=-DHIT_ENTER set OPTIONSVC=/EHsc /O2 set OPTIONSGC=-O4 set OPTIONSBC=-O2 set OPTIONSTC= set OPTIONSLC= set LIBSVC= set LIBSGC= set LIBSBC= set LIBSTC= set LIBSLC= set UTF8=0 set BIT=64 set WINDOWS=0 set OPENMP=0 set CPP=1 set HIT=1 set ANLZ=0 set RUN=0 set PARAM= set TOOLS=.\tools if not exist %TOOLS%\AddVer.bat set TOOLS=..\tools if not exist %TOOLS%\AddVer.bat set TOOLS=..\..\tools if not exist %TOOLS%\AddVer.bat set TOOLS=..\..\..\tools if not exist %TOOLS%\AddVer.bat set TOOLS=..\..\..\..\tools if not exist %TOOLS%\AddVer.bat set TOOLS=..\..\..\..\..\tools if not exist %TOOLS%\AddVer.bat set TOOLS=..\..\..\..\..\..\tools if not exist %TOOLS%\AddVer.bat set TOOLS=..\..\..\..\..\..\..\tools if not exist %TOOLS%\AddVer.bat echo Pocom tools folder is not found. if not exist %TOOLS%\AddVer.bat pause if not exist %TOOLS%\AddVer.bat goto EndOfBat set ARG= :DoLoop if '%1' == '' goto ArgDone set ARG=%ARG% %1 shift goto DoLoop :ArgDone call %TOOLS%\Mk^$Base %ARG% :EndOfBat set PG=
+ パワーシェル等から m ではなく.\m のように起動してもキー入力を待たない ++ C++言語としてコンパイルする(+-の反対) +- C言語としてコンパイルする(++の反対) +a リンクせずにアセンブラのプログラムを出力する +b 続く引数を SUBSRCS に追加する +c コンソールプログラムとしてコンパイルする(+wの反対) +d 環境変数を設定して、続くコマンドを実行する。(Direct) 例: m 2019c 32 +d cl Example1.c +e +e foo のように指定すると、foo.exe を作成する +h 端末からから m と起動してもキー入力を待つ(Hit key)(+の反対) +k コンパイルが終わった後も環境変数 PATH, INCLUDE, LIB を保持する(Keep env) exit コマンドで元の PATH, INCLUDE, LIB に戻る +l 続く引数をリンカオプションやライブラリとして追加する +n OpenMp を無効にする(No OpenMp)(+oの反対) +o OpenMp を有効にする(+nの反対) +r 成功したら自動的にプログラムを %PARAM% をパラメータにして実行する(+qの反対) version 8.18 以降は +r の右の文字列をパラメータに加える。 +q M.bat 等に RUN=1 としている時に自動実行を取り消す(+rの反対) +s Utf8 ではなくシフトJISとしてコンパイルする(+uの反対) +u Utf8 としてコンパイルする(+sの反対) +w ウィンドウズモードでコンパイルする(+cの反対) +y M.bat 等に ANLZ=1 としている時にコード分析を取り消す(+zの反対) +z 可能ならコード分析を実行する(+yの反対)
C++ | C | コンパイラ | ||
---|---|---|---|---|
正式名 | 省略名 | 正式名 | 省略名 | |
50 | 50c | Visual C++ 5.0 | ||
60 | 60c | Visual C++ 6.0 | ||
2002 | 02 | 2002c | 02c | Visual C++ 2002 |
2003 | 03 | 2003c | 03c | Visual C++ 2003 |
2005 | 05 | 2005c | 05c | Visual C++ 2005 |
2008 | 08 | 2008c | 08c | Visual C++ 2008 |
2010 | 10 | 2010c | 10c | Visual C++ 2010 |
2013 | 13 | 2013c | 13c | Visual C++ 2013 |
2017 | 17 | 2017c | 17c | Visual C++ 2017 |
2019 | 19 | 2019c | 19c | Visual C++ 2019 |
2022 | 22 | 2022c | 22c | Visual C++ 2022 |
Bcc | B | Bccc | Bc | Borland C++ 5.5.1 |
Gcc | G | Gccc | Gc | C:\TDM-GCC-64 |
Gucc | Gu | Guccc | Guc | C:\TDM-GCC-64(UTF-8ソース) |
G1cc | G1 | G1ccc | G1c | C:\mingw64,C:\mingw32 |
Gu1cc | Gu1 | Gu1ccc | Gu1c | C:\mingw64,C:\mingw32(UTF-8ソース) |
G2cc | G2 | G2ccc | G2c | C:\msys64\ucrt64 |
Gu2cc | Gu2 | Gu2ccc | Gu2c | C:\msys64\ucrt64(UTF-8ソース) |
Lcc | L | Lsic86 | ||
Tcc | T | TurboC 1.5 | ||
Tc2 | TurboC 2.01 |
# LSI C-86 compiler's configuration file -DLSI_C -h -XC:\APP16\LSIC86\BIN -LC:\APP16\LSIC86\LIB -IC:\APP16\LSIC86\INCLUDE -T -O -acdos.obj $LSICOPTS & #Command line argument will be inserted here -lknjlib -ldoslib -v
-DMSDOS_EXEという行を追加します。
-IC:\APP16\tcc -LC:\APP16\tcc
-IC:\APP16\tc2 -LC:\APP16\tc2
-DMSDOS_EXE=1という行を追加します。 ただし msdos.exe 上で Lsic86 を使用する場合はコンパイルに非常に時間がかかります。
C:\ ... \Pocom\Example>Example1 test.txt
C:\ ... \Pocom\Example>chcp 932とすると、実行できるようになります。
C:\ ... \Pocom\Example\Example1 -b ...
C:\ ... \Pocom\Example>bcc32 -W -DWINDOWS -P Example1.c C:\ ... \Pocom\Example>cl /D WINDOWS /Tp Example1.c kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.libのようにしても、ウィンドウズモードでコンパイルすることができます。
C:\ ... \Pocom\Example>mkとすると m と同様、改行キーが押されるのを待ちません。
C:\ ... \Pocom\Example>Mkなどのように大文字を混ぜると改行キーが押されるのを待ちます。
ウィンドウズモードでコンパイルした .exe ファイルを Ubuntu+wine 実行する場合、
sudo apt-get install fonts-horai-umefont
として梅フォントをインストールすることを推奨します。
データファイルの中身やファイル名にASCII文字しか使用しない場合は、
-DASCII としたり、/D ASCII として、ASCII を定義すると
非ASCII文字の処理を全て無効にしてプログラムを小さくできます。
ASCIIモードとUTF8モードが同時に指定された場合はUTF8モードの方が優先されます。
ASCIIモードとは具体的には
ポコムは、多くのデータ型を持っています。
構造 | 整数型 | コード型 | バイト型 | 2バイト整数型 | 4バイト整数型 | 8バイト整数型 | 半精度型 | 単精度型 | 倍精度型 | 浮動小数点数型 | 文字列型 | コード定義型 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
単純変数 | INT、INTF、FIX | CODE | BYTE | TINT | NINT | LINT | HALF | FLT | DBL | REAL | STR | |
ベクトル(vector) | IVEC | CVEC | BVEC | TVEC | NVEC | LVEC | HVEC | FVEC | DVEC | RVEC | SVEC | CDEF |
固定列行列(matrix) | IMAT | CMAT | BMAT | TMAT | NMAT | LMAT | HMAT | FMAT | DMAT | RMAT | SMAT | |
可変列行列(jagged) | IJAG | CJAG | BJAG | TJAG | NJAG | LJAG | HJAG | FJAG | DJAG | RJAG | SJAG |
空白 # ; $ , を含む文字列やコードの名前を指定する時は、 " か ' で囲みます。 また、変数名/関数名と一致する文字列やコード定義を指定する時も " か ' で囲みます。" でクォートを開始した場合は "" を入れると " 1文字を表します。同様に ' でクォートを開始した場合は '' を入れると ' 1文字を表します。
整数を 0x または 0X で始めると16進数と見なします。 新しいポコムでは 0 から始めても10進数と見なします。 以前のバージョンのポコムのように8進数と見なしたい場合は、 #include "pocom.h" の前に #define ENABLE_OCTAL とします。
コード型については、次の章で詳しく説明します。
ベクトルの大きさは整数変数で制御されます。
固定列行列の大きさは、2つの整数変数で制御されます。 行数も列数も0にできます。
可変列行列は整数と整数ベクトルで行数と各行の長さが決ります。 行数も列数も0にできます。
整数演算と、文字列演算の性能を比較すると、 整数演算の方が速度・メモリ効率ともに優れています。 だからといって、プログラムやデータを整数で記述すると、 読みやすさをそこないます。 速度・メモリ効率と読みやすさを両立するために、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++) { fputc(' ',fp); fputs(DayOfWeek[ DayMat[i][j] ],fp); } 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++) { fputc(' ',fp); fputs(CmatStr(DayMat,i,j),fp); } 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 を定義してください。
ポコムには、以下に示す5種類の行があります。
原則として # より右側は無視しますが、1.# の場合は無視しません。
古い Visual C++ では、浮動小数点数のでエラーが起きた場合 -1.#INF00 等が出力
されるからです。
変数行を書く時は、次の順番を守って変数を並べなければなりません。
[単純変数] [ベクトル・固定列行列] [可変列行列]
さらに、ベクトル、固定列行列、可変列行列を複数並べる時は、 行サイズを指定する整数変数が同じものでなければなりません。 また、可変列行列を複数並べる時は、 列サイズを示す整数ベクトル変数も同じものでなければなりません。
変数行の後には、それに応じた量のデータが必要になります。 この行をデータ行と呼びます。 データ行での読み込みの順番は、変数行での順序から次のように決ります。
順番さえあっていれば、改行や注釈は自由に配置できます。 したがって、工夫次第で、読みやすく、 かつページ数が少ないデータ ファイルを書くことができます。
次のデータは、ベクトルと固定列行列を表現します。 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 が設定される
まれに、計算ルーチンで 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,EJ("abcefg","あいうえお")); SetSvec(SV,0,ZeroStr) SetSvec(SV,1,EJ("abcefg","あいうえお")) AllocSvec(SV,2,11); memset(SV[2],'-',10);
SetStr、SetSvec、AllocSvec を使用すると NO_FAST_STR が有効の時も無効の時もOKです。 過去のバージョンの StrDup( ) や GetMemStr( ) は廃止しました。 他に SetSmat、SetSjag、AllocStr、AllocSmat、AllocSjag が使用可能です。
データ定義では、マクロで変数・関数・初期化データを指定します。 以下にこれらのマクロの書式を示します。
マクロ | 説明 |
---|---|
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 を実行したときに表示する |
記号 | 説明 | 例 |
---|---|---|
n | C 言語上での変数名・関数名 | N または、Solve |
w | 表示する時の桁数 | 10 または、-310 |
f | 固定値整数値 | 3など(0x から始めると16進数) |
r | 行の数 | N |
c | 列の数 | N |
s | 大きさを決める ivec | Len |
d | コード定義 cdef | Node |
m | コメント | "行列の大きさ" |
t | データ | "Range N > 0" |
n は C の識別子として許され、かつ _ で終わってはなりません。 w は、データを表示する時の桁数を決めています。 詳しくは第10章の Format を参照してください。
ポコム関数は、データ ファイルからでも、AUTO からでも、LAST からでも、 計算ルーチン等のCの関数からでも呼び出すことができます。
ポコム関数はCの関数として呼び出す時は、文字列を引数とします。
名前 | 説明 |
---|---|
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 | 変数の出力桁数を変更する。
出力の精度を高くしたり、
画面にたくさんのデータを表示したりするときに使用する。
整数 100〜199:10進法で3桁ごとにカンマで区切った形式で表示する。下2桁で指定した幅で表示する。 0〜99 :10進法で指定した幅で表示する。 −1〜−99 :16進法で表示し、絶対値の幅で表示する。 (100〜199にしなくても Print N;; のように ; を2つ指定すれば3桁ごとにカンマで区切った形式で表示する) 文字列・コード型 0〜99 :Print では指定した幅で表示する。 PrintCSV,TSV では必要に応じて引用符で囲み、常に文字列として一致した表示をする。 −1〜−99:Print では絶対値の幅で表示する。 PrintCSV,TSV で値として表示するために、空文字列以外常に引用符で囲まない。 ※PrintCSV,TSV では、 ・32/64ビットコンパイラの場合で0以上の時 NO_CSVTSV_STR が有効なら必ず引用符で囲む。 ・16ビットコンパイラの場合で0以上の時、必ず引用符で囲む。 ただし、USE_CSVTSV_STR が有効のときは、必要に応じて引用符で囲む。 (負にして PrintCSV,TSV で作成したデータはポコムの入力ファイルとして矛盾が生じる) (負にしなくても 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、100、−2 を指定した場合は、 単独で表示したときでも要素ごとに改行される。 同時に複数の変数の桁数を変えることができる。 例 Format A 408 B 408 X 408 |
Free | 変数のメモリを開放して初期化する。Free を使うとサイズの変数を変えずに、 メモリを開放して、RowSize(...) を0にする。 |
Lap | 最初に呼び出された場合は Clock と同じように起動時からの経過時間を表示する。 2回目以降は前回の Lap の呼び出しからの経過時間を表示する。 引数をコメントとして表示する。コメントが不要な場合は引数に ZeorStr か "" を渡す。 |
Limit | Print するときに、一番右の配列を並べて表示する数を制限して折り返す。 @一番右の配列がベクトルならば、左には単純変数のみを指定できる。 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 | 以降の出力を指定されたファイルへ書く。 同じ名前のファイルがあるときは上書きされる。 - を指定すると標準出力へ書く。+ を指定すると標準エラーへ書く。 ファイル名の始まりや終わりがカンマの場合は " で囲む必要がある。 |
変数の表示。複数の変数を同時に指定する時は、
読み込みと同様変数の順番とサイズが合ってなければならない。 変数名に続けて ; と任意の文字列を指定することによって、 出力される変数名を一時的にその文字列に変更することが可能。 更に浮動小数点数型変数(例えば A) に対して Print A;; や Print A;SrcM; のように ; を 2つ指定すると、一時的に16進数で表示する。(SrcM は出力される変数名) また、整数型変数に対して Print N;; や Print N;数; のように ; を2つ指定すると、 一時的に3桁ごとにカンマで区切った表示をする。('数'は出力される変数名) 折り返しの詳細については Limit の説明を参照。 | |
PrintCSV | CSVフォーマットに従って変数の値を表示する。
エクセルで読み込ませるために使用する。例えば「Output result.csv」のように
した後 PrintCSV を行えば、
エクセルで開くことのできる CSV ファイルを作成できる。 この CSV ファイルはシフトJISモードでもUTF8モードでも、 ダブルクリックで正しく開くことができる。 変数名に続けて ; と任意の文字列を指定することによって、 出力される変数名を一時的にその文字列に変更することが可能。 更に文字列・コード型変数(例えば Title) に対して PrintCSV Title;; や Print Title;タイトル; のように ; を 2つ指定すると、一時的に引用符で囲まない。(タイトル は出力される変数名) また、整数型変数に対して Print N;; や Print N;数; のように ; を2つ指定すると、 一時的に3桁ごとにカンマで区切った表示をする。('数'は出力される変数名) 折り返しの詳細については Limit の説明を参照。 文字列・コード型の引用符で囲む条件については Format の説明を参照。 |
PrintTSV | データの区切りをカンマからタブになることを除けば PrintCSV とほぼ同じ。 例えば「Output result.tsv」のように した後 PrintTSV を行えばエクセルで開くことのできる TSV ファイルを作成できる。 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以外という範囲指定があるとエラーとなる。 行列の場合 pocom バージョン 6.05 までは列数を0にしていたが 7.01 では列数は変更しない。 |
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 TempSystem は他のポコムプログラムと連携するのを主な目的として用意した。 System から呼び出されたポコムプログラムから、さらに System を使ってプログラムを 呼び出すことはできない。2重呼び出しを禁止した理由は 循環参照して無数にプログラムを実行する危険を回避するため。 例えば、 no-good.txt: System Example1 no-good.txtという自分自身を繰り返し実行しようとするファイル(no-good.txt)を用意して、 C:\ ... \Pocom> Example1 no-good.txtとするとエラーとなる。
プログラムは2重呼び出しが行われるかどうかを判断するために System を実行すると最初に、
System.tmp という名前の空のファイルを作成し、実行が終了した後に消去する。 System Example1 test.txtとして、カレントフォルダに Example1 という名前のファイルがある場合 ./ が補われ、 system("./Example1 test.txt"); が呼び出される。 |
標準変数・定数・型は計算ルーチン等 C の関数から参照できます。
名前 | 説明 |
---|---|
__POCOM__ | ポコムのバージョン。ver 8.19 ならば 819。 |
__VERSTR__ | ポコムのバージョン。ver 8.19 ならば "8.19" |
ALWAYS_FALSE | 常に偽。 |
big_t | コンパイラの扱う最大の整数型。16ビットコンパイラなら long。32・64ビットコンパイラなら long long または __int64 |
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なら英語に切り替えるマクロ 例:Echo(EJ("# English","# 日本語")); データ構造の記述時や、Error、Echo、Alias 等 pocom.h で記述された関数の引数として日本語を渡すときは EJP ではなく、この EJ を使う。 |
EJP(E,J) | マクロ JPN が1なら日本語、0なら英語に切り替えるマクロ。
BorlandC++ や古い 2008 以前の Visual C++ でUTF8モードで埋め込まれる日本語がシフトJISの場合。UTF8に変換する。 シフトJISモードの場合、または新しい Visual C++ や Ubuntu の g++ や16ビットコンパイラの場合は変換しない。 例:fputs(EJP("English\n","日本語\n"),fp); printf、fprintf、fputs、strcpy など、pocom.h に記述されていない関数の引数として日本語を渡すときは EJ ではなく、この EJP を使う。 |
bool EndOfLine | バッファの終わりまで読んだら true。 |
JP(J) | BorlandC++ や古い 2008 以前の Visual C++ でUTF8モードで埋め込まれる日本語がシフトJISの場合。UTF8に変換する。 シフトJISモードの場合、または新しい Visual C++ や Ubuntu の g++ や16ビットコンパイラの場合は何もしない。 EJP(E,J) マクロの E のないもの。 例:fputs(JP("日本語\n"),fp); |
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コンパイラでは使用不可。または IEEE754 以外の浮動小数点数でないシステムでも使用不可) |
bool HaveCmdLineFile | コマンドラインで入力ファイルを指定すると true。指定しないと false。 コマンドラインで入力ファイルを指定せずに現れたダイアログでファイルをキャンセルせずに選択すると、LAST() から 呼び出される関数内では HaveCmdLineFile は true になる。 |
Int,ivec,imat,ijag | 通常の場合 int で、
#include "pocom.h" の前に #define INT_64 とすると long long または __int64。 16ビットコンパイラで、 #include "pocom.h" の前に #define INT_32 とすると long。 |
Int32_t | 32ビット符号付整数。 |
Int64_t | 64ビット符号付整数。 |
Int LastIndex | 最後に呼んだ MapIndex(K,V,S), MapValue(K,V,S), MapSetSvec(K,V,S,X) で使われたインデックス値。 |
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_RAW(A,B,C,D) | メモリモデル別に選ぶ
A:16ビット:スモールモデル・ミディアムモデル B:16ビット:ラージモデル・コンパクトモデル C:32ビット D:64ビット |
MODEL_SIZE(A,B,C,D) | メモリモデル別に値を選ぶ (MODEL_RAW(A,B,C,D) を括弧で囲ったもの) |
Int MulAdd(Int n,Int mul,Int add) | n*mul+add を返す。 オーバフローのチェックをする。 |
nint,nvec,nmat,njag | 常に 32ビット符号付整数。 |
int NoList | 0以外に設定すると変数のリストを表示する動作を抑止する。 また、ファイル選択ダイアログの出現も抑止できます。 |
double PETA | #define PETA (1000.0*1000000.0*1000000.0) 乱数をジャンプさせるときに便利。 EXA と違い50ビットなので Jump(PETA+1.0) としても正しくジャンプする。 同じ種で PETA ずつ間隔を開けて初期化した場合4スレッドまでのマルチスレッドで正しくジャンプする。 |
PRI32 | 32・64ビットコンパイラなら "" 16ビットコンパイラなら "l"。 32ビット整数(Int32_t, NINT, NVEC, NMAT, NJAG) の値を出力する時に使う。 fprintf(fp,"# %" PRI32 "d\n",(Int32_t)x); のように使う。 |
PRI64 | "ll" または "I64"。 64ビット整数(Int64_t, LINT, LVEC, LMAT, LJAG) の値を出力する時に使う。 fprintf(fp,"# %" PRI64 "d\n",(Int64_t)x); のように使う。 |
PRIb | 16ビットコンパイラなら "l"。32・64ビットコンパイラなら "ll" または "I64"。 コンパイラの扱う最大の整数型 big_t を表示するのに使用する。 fprintf(fp,"# %" PRIb "d\n",(big_t)x); のように使う。 |
PRIz | Int が 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_t | 32ビット符号なし整数。 |
Uint64_t | 64ビット符号なし整数。 |
UNIF_STEP | Unif(),Unif_r()1回当り、何回 Rand_r() を呼び出すかを示す。 |
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); |
void Alloc(const char*) | 配列の確保を行う。例 Alloc("C X") ; |
void AllocWord(VAR) | 配列の確保を行う。例 AllocWord( C ) ; |
void AllocWord__(wptr) | 配列の確保を行う。例 AllocWord__((wptr)C_ ) ; |
void AllocStr(str,size_t) | 文字列領域の確保を行う。例 AllocStr(S,11);(S=malloc(11); のイメージ。) |
void AllocSvec(svec,Int,size_t) | 文字列領域の確保を行う。例 AllocSvec(SV,1,11);(SV[1]=malloc(11); のイメージ。) |
void AllocSmat(smat,Int,Int,size_t) | 文字列領域の確保を行う。例 AllocSmat(SM,1,2,11);(SM[1][2]=malloc(11); のイメージ。) |
void AllocSjag(sjag,Int,Int,size_t) | 文字列領域の確保を行う。例 AllocSjag(SJ,1,2,11);(SJ[1][2]=malloc(11); のイメージ。) |
unsigned BackRand() | 整数乱数を逆順に生成する。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある) |
unsigned BackRand64() | 32/64ビットコンパイラで64ビット整数乱数を逆順に生成する。 |
unsigned BackRand_r(Rand_t) | 整数乱数を逆順に生成する。マルチスレッド用。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある) |
unsigned BackRand64_r(Rand_t) | 32/64ビットコンパイラで64ビット整数乱数を逆順に生成する。マルチスレッド用。 |
double BackUnif() | 浮動小数点乱数を逆順に生成する。FLOAT_REAL が定義されているなら 24ビット精度、HALF_REAL が定義されているなら 11ビット精度。FAST_UNIF が定義されていれば 32ビット精度。それ以外は 53ビット精度。(16ビットコンパイラで使用するには BACK_RAND か ASIF32 を定義する必要がある) |
double BackUnif_r(Rand_t) | 浮動小数点乱数を逆順に生成する。FLOAT_REAL が定義されているなら 24ビット精度、HALF_RAL が定義されているなら 11ビット精度。FAST_UNIF が定義されていれば 32ビット精度。それ以外は 53ビット精度。マルチスレッド用。(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 を定義する必要がある) |
Int CdefIndex(cdef,const char*) | コード定義に文字列がどの位置に登録されているかを返す。 登録されてなければ -1 を返す。 AddTo???? と組み合わせると、連想配列と呼ばれる機能を実装するのが楽になる。 |
Int CdefIndex__(cdef_ K_,const char*S) | コード定義 K_ に文字列 S がどの位置に登録されているかを返えす。登録されてなければ -1 を返えす。 |
Int CdefIndex2(cdef K,const char*S) | コード定義 K に文字列 S がどの位置に登録されているかを返す。 未登録ならば、エラーメッセージを表示してプログラムを終了する。 |
Int CdefIndex2__(cdef_ K_,const char*) | コード定義 K_ に文字列 S がどの位置に登録されているかを返す。 未登録ならば、エラーメッセージを表示してプログラムを終了する。 |
char*CjagStr(cjag,Int,Int) | コード型である可変列列整数行列の要素を対応する文字列に変換する。 |
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(cmat,I,J) | コード型である固定列整数行列の要素を対応する文字列に変換する。 |
char*CodeStr(code) | コード型である単純整数を対応する文字列に変換する。 |
void CopyArg(const char*,const char*) | 引数をバッファに転送する。
第一引数は親関数名、第二引数は転送する文字列。 例 CopyArg("foo",argument) ; |
char*CvecStr(CV,I) | コード型である整数ベクトルの要素を対応する文字列に変換する。 |
void DoEvents() | ウィンドウズモードで時間のかかる処理をするときに、途中でこれを適当な間隔で呼び出す
ことにより、閉じるボタンで終了できるようにする。 コンソールモードではなにもしない。 |
half dtoh(double) | 倍精度浮動小数点数を半精度浮動小数点数へ変換する。(C++のみ) |
void FlushFp() | ウィンドウズモードで fprintf(fp, ...) 等で溜まった文字列を画面に表示する。 ウィンドウズモードでは DoEvents() を内部で呼び出すので、閉じるボタンが有効になる。 これは、ウィンドウズモードの時は Print、PrintCSV、PrintTSV、Echo、List、Progress、Progress2、Clock、Lap、Error で呼び出される。 ウィンドウズモードでないときは、fflush(fp) が呼び出される。 コンソールモードでも fflush(fp); の代わりに FlushFp() を使用した方が好ましい。 |
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) | 単精度浮動小数点数を半精度浮動小数点数へ変換する。(C++のみ) |
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(size_t) にアライメントされる。SVEC, SMAT, SJAG 専用。 エラーが起きたらプログラムは終了する。 |
char*GetMemRaw(size_t) | calloc( ) または、new[ ] の代わりに使う。領域は0で埋められる。 エラーが起きたら0を返すだけで何もしない。 使い終わったら FreeMemRaw(p) しなければならない。マルススレッドでも使用可能。 |
vmj*GetVmj() | 高速線形リストを一つ確保する。使い終わったら FreeVmj(p) しなければならない |
double htod(half) | 半精度浮動小数点数を単精度浮動小数点数へ変換する。(C++のみ) |
float htof(half) | 半精度浮動小数点数を単精度浮動小数点数へ変換する。(C++のみ) |
real htor(half) | 半精度浮動小数点数を real 型精度浮動小数点数へ変換する。(C++のみ) |
char*IntStr(Int) | Int, unsigned char, short,unsigned short, int, unsigned, __int64, long long 型を文字列に変換する。 |
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 MapAdd(cdef K,?vec V,const char*S,? X) | 連想配列に X を追加する。 S が既に登録済みならメッセージを表示してプログラムを終了する。 X の型は第2引数の基本型。 memo.html を参照。 |
void MapAddSvec(cdef K,svec V,const char*S,const char*X) | 文字列連想配列に (S,X) を追加する。 S が既に登録済みならエラーメッセージを表示してプログラムを終了する。 memo.html を参照。 |
Int MapIndex(cdef K,?vec V,const char*S) | 連想配列のインデックスを返す。 memo.html を参照。 |
void MapSetSvec(cdef,svec,const char*,const char*) | 例:MapSetSvec(Key,ValueSV,"ABC","Abc");は(ValueSV["ABC"]="Abc"; のイメージ。memo.html を参照。) |
? MapValue(cdef K,?vec V,const char*S) | 連想配列の値を返す。返り値の型は V の基本型。memo.html を参照。 |
? MapValue2(cdef K,?vec V,const char*S) | 連想配列の値を返す。返り値の型は V の基本型。 S が未登録済ならエラーメッセージを表示してプログラムを終了する。memo.html を参照。 |
void PrintSec(double,const char*) | 第一引数で指定した秒単位の時間を表示する。 時間表示の右に第二引数の文字列も表示する。 |
int Progress(const char*msg,Int i,Int n) | 時間のかかる計算等で stderr に n が1以上なら進捗率を 0.5 秒ごとに表示する。 n が0の場合は i を表示する。特別に i が -1 ならば、"END" と表示する。 n に負の値を指定してはいけない。 ウィンドウズモードではウィンドウのタイトルバーに表示する。 ウィンドウズモードでは 0.5 秒の間に DoEvents() を4回〜7回 Progress() 内部で呼び出すので、閉じるボタンが有効になる。 マクロ NO_PROGRESS が0以外なら何も表示しない。この時ウィンドウズモードならば、DoEvents() のみ呼び出す。 msg には長さ71より長い文字列を渡しても71までしか表示されない。 日本語を渡すには EJ( ) マクロを使用すること。 進捗率を 250 ミリ秒ごとに表示するよう変更するには、pocom.h をインクルードする前に、 OLD_PROGRESS を定義すると i+1 が n ならば 100% と表示して改行する。 n が0で i が -1 ならば、"END" と表示する。 #define PROGRESS_TICK 250 を書き加える。 またはマクロ NO_INTERVAL 定義されていないか0ならば SetInterval(250); を Progress() を使用する前に呼び出すことでも変更できる。 このように頻度を SetInterval(x) として変更する場合、x は 33 ミリ秒以上でなければならない。 表示を行った時には1を返し、表示を行わなかった場合は0を返す。表示した文字列は SubBuffer__ に格納されている。 |
int Progress2(const char*msg,Int i,Int n,Int j,Int m) |
Progress( ) の2重ループ版。 i は外側のループのカウンター。n は外側のループの大きさ。 j は内側のループのカウンター。m は内側のループの大きさ。 i, n, j や m に負の値を指定してはいけない。 OLD_PROGRESS を定義すると i+1==n&&j+1==m ならば 100% と表示して改行する。 表示を行った時には1を返し、表示を行わなかった場合は0を返す。表示した文字列は SubBuffer__ に格納されている。 |
Uint32_t Rand() | 32ビットの符号なし整数乱数を返す。 |
Uint64_t Rand64() | 32/64ビットコンパイラで64ビットの符号なし整数乱数を返す。 |
Uint32_t Rand_f() | 0以外の32ビットの符号なし整数乱数を返す(高速低品質)。 |
Uint32_t Rand_m(N) | 0以外の32ビットの符号なし整数乱数を返す(高速低品質)。マルチスレッド用。N は0以上 FAST_RAND 未満。 |
Uint32_t Rand_r(Rand_t) | マルチスレッド用の32ビットの符号なし整数乱数。 |
Uint64_t Rand64_r() | マルチスレッド用の64ビットの符号なし整数乱数を返す。 |
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 は整数変数のいずれか) |
nint ReadNint() | バッファから int を読む。(範囲チェックなし) |
nint 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 ResetLap() | Lap() や LapSec() の計測開始時刻を現在時刻にする。 |
void ResetWord(VAR) | 配列を空にする。サイズを決める変数も0になる。例 ResetWord( A ) ; |
void ResetWord__(wptr) | 配列を空にする。サイズを決める変数も0になる。例 ResetWord__((wptr)A_ ) ; |
char*RealStr(real) | half, float, double 型を文字列に変換する。 |
size_t RowSize(VAR) | 配列が持つ要素数を返す。ベクトルならば要素数、固定/可変列行列ならば行数を返す。 |
half rtoh(real) | real 型浮動小数点数を半精度浮動小数点数へ変換する。(C++のみ) |
int SetInterval(int) | Progress(), Progress2() の設定をする。 引数が33以上の場合は Progress(), Progress2() の表示頻度をミリ秒単位で設定する。 引数が0〜32の場合は Progress(), Progress2() の初期高速化マスクをビット単位で設定する。 例えば SetInterval(9) とすると初期高速化マスクは511となり、 Progress(), Progress2() は最初の511回は時計を見にいかなくなる。 Progress(i,n) の場合は i が0の時、Progress2(i,n,j,m) の場合は i と j の両方が0の時に 高速化マスクを初期高速化マスクに設定する。 既定では初期高速化マスクは0であるが、Progress(), Progress2() を実行していくと 高速化マスクは自動調整されていく。 引数が−1〜−32の場合は Progress() あるいは Progress2() が表示をするときに 前回の表示から何回時計を見にいくかの目標値を設定する。 −1なら1回、−2なら2回〜3回、−3なら4回〜7回、−4なら8回〜15回、 −5なら16回〜31回、−6なら32回〜64回、−7なら64回〜127回となる。 指定しない時の既定値は−3の4〜7回となる。 SetInterval(-1〜-32) はあまり必要とはならないだろう。 |
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(array,int,int) | 行列の二つの列やベクトルの要素を入れ替える。CDEF や可変列行列には使用しないこと。 |
double Unif() | 0以上1未満の浮動小数点乱数を返す。FLOAT_REAL が定義されているなら 24ビット精度、HALF_RAL が定義されているなら 11ビット精度。FAST_UNIF が定義されていれば 32ビット精度。それ以外は 53ビット精度。 |
double Unif_f() | 0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。FLOAT_REAL が定義されているなら 24ビット精度、HALF_RAL が定義されているなら 11ビット精度。FAST_UNIF が定義されていれば 32ビット精度。それ以外は 53ビット精度。 |
double Unif_h() | 0より大きく1未満の浮動小数点数乱数を返す(ハードウエア乱数)。FLOAT_REAL が定義されているなら 24ビット精度、HALF_RAL が定義されているなら 11ビット精度。FAST_UNIF が定義されていれば 32ビット精度。それ以外は 53ビット精度。 |
double Unif_m(N) | 0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。FLOAT_REAL が定義されているなら 24ビット精度、HALF_RAL が定義されているなら 11ビット精度。FAST_UNIF が定義されていれば 32ビット精度。それ以外は 53ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。 |
double Unif_r(Rand_t) | マルチスレッド用の0以上1未満の浮動小数点乱数。FLOAT_REAL が定義されているなら 24ビット精度、HALF_RAL が定義されているなら 11ビット精度。FAST_UNIF が定義されていれば 32ビット精度。それ以外は 53ビット精度。 |
double Unif11() | 0以上1未満の浮動小数点乱数を返す。11ビット精度。 |
double Unif11_f() | 0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。11ビット精度。 |
double Unif11_h() | 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_h() | 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_h() | 0より大きく1未満の浮動小数点数乱数を返す(ハードウエア乱数)。32ビット精度。 |
double Unif32_m(N) | 0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。32ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。 |
double Unif32_r(Rand_t) | マルチスレッド用の0以上1未満の浮動小数点乱数。32ビット精度。 |
double Unif53() | 0以上1未満の浮動小数点乱数を返す。53/52ビット精度。 |
double Unif53_f() | 0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。53/52ビット精度。 |
double Unif53_h() | 0より大きく1未満の浮動小数点数乱数を返す(ハードウエア乱数)。53/52ビット精度。 |
double Unif53_m(N) | 0より大きく1未満の浮動小数点数乱数を返す(高速低品質)。53/52ビット精度。マルチスレッド用。N は0以上 FAST_RAND 未満。 |
double Unif53_r(Rand_t) | マルチスレッド用の0以上1未満の浮動小数点乱数。53/52ビット精度。 |
void UpdateCvar(CVAR) | CVAR は CODE,CVEC,CMAT,CJAG 変数のどれかである。 計算ルーチンでで CVAR の値を ReadCode() 等で変更した後に UpdateCvar() を呼び出す。 NO_CHECK_CDEF が無効で CVAR の参照している CDEF 変数が縮小したときに、 CVAR 変数を表示してもエラーが出ないようにする。 データファイルから CVAR が読み込まれる場合、自動的に UpdateCvar( ) と同様の処理が行われるので、 これをプログラムに書く必要になる場面は滅多にないだろう。 |
pocom.h をインクルードする前に #define X86_INTRIN のように定義すれば、 以下の関数が使用可能になります。
これらはコンパイラやアセンブラを使わず、機械語をプログラムに埋め込んだので、 Borland C++ 5.5.1 でも使用可能です。もちろん16ビットコンパイラやインテルや AMDのCPU上以外では使うことはできません。
ポコムのバージョン 8.15 より gcc 9 かそれ以降、または VisualC++2013 かそれ以降の
新しいコンパイラ場合、機械語ではなく組み込み関数で実現するようにしました。
これによって X86_INTRIN を定義しても Clang-Tidy 等によるコード分析が可能になりました。
ただし、NO_BUILTIN を定義すると、新しいコンパイラでも従来通りの機械語で実現します。
また、新しく RdtscpAux, MmPause1 を追加しました。
そして、32ビットでコンパイルしても Bsf64, Bsr64, Bswap64 が使用可能になりました。
名前 | 説明 |
---|---|
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等で使用可能 |
int HaveRdseed( ) | ハードウェア乱数 Rdseed32( ) と Rdseed64( ) が使用可能なら1。 第5世代の Core i7,i5,i3 以降のCPU等で使用可能 |
Int64_t Rdtsc( ) | rdtsc 命令を使って現在のクロックカウンターを得る |
Int64_t CpuidRdtsc( ) | cpuid 命令を実行した後 rdtsc 命令を使って現在のクロックカウンターを得る。 Rdtsc( ) より時間がかかるが、より正確に計測することができる。 |
Int64_t Rdtscp(Uint32_t*aux) | rdtscp 命令を使って現在のクロックカウンターを得る。 aux で示された場所に TSC_AUX(使用しているプロセッサの番号)を保存する。aux を0にすると保存しない。 工夫すれば Rdtscp(unsigned*aux) のほうが CpuidRdtsc( ) よりもさらに正確なクロック数を得ることができる。 |
unsigned RdtscpAux(void) | rdtscp 命令を使って TSC_AUX(使用しているプロセッサの番号)を返す。 |
int Bsf(size_t) | Bit scan forward を行う。0の結果は未定義。 |
int Bsf32(Uint32_t) | Bit scan forward を行う。0の結果は未定義。 |
int Bsf64(Uint64_t) | Bit scan forward を行う。0の結果は未定義。 |
int Bsr(size_t) | Bit scan reverse を行う。0の結果は未定義。 |
int Bsr32(Uint32_t) | Bit scan reverse を行う。0の結果は未定義。 |
int Bsr64(Uint64_t) | Bit scan reverse を行う。0の結果は未定義。 |
int Bswap32(Uint32_t) | バイトの順番を並び替える。intel486 以降 |
int Bswap64(Uint64_t) | バイトの順番を並び替える。 |
void MmPause1(void) | 約 10 クロックだけCPUを待機させる。 CPUにより約 70 クロックのように待機時間は大きく変化する。 |
void MmPause(unsigned num) | 約 num×10 クロックだけCPUを待機させる。 CPUにより約 num×70 クロックのように待機時間は大きく変化する。 |
Uint32_t NextRdrand32(void), Rand_h() | rdrand 命令を使って32ビットのハードウェア乱数を返す。エラー処理付き。 |
Uint64_t NextRdrand64(void), Rand64_h() | NextRdrand32( ) の64ビット版。 |
Uint32_t NextRdseed32(void), Rand_s() | rdseed 命令を使って32ビットのハードウェア乱数を返す。エラー処理付き。 |
Uint64_t NextRdseed64(void), Rand64_s() | NextRdseed32( ) の64ビット版。 |
int Rdrand32(Uint32_t*val) | rdrand 命令を使って32ビットのハードウェア乱数を val で示された場所に得る。 失敗すると0が返り、成功すると1が返る。 |
int Rdrand64(Uint64_t*val) | Rdrand32() の64ビット版。 |
int Rdseed32(Uint32_t*val) | rdseed 命令を使って32ビットのハードウェア乱数を val で示された場所に得る。 失敗すると0が返り、成功すると1が返る。 |
int Rdseed64(Uint64_t*val) | Rdseed32() の64ビット版。 |
double Unif11_h() | 11ビット精度[0,1)の浮動小数点数ハードウエア乱数を返す |
double Unif24_h() | 24ビット精度[0,1)の浮動小数点数ハードウエア乱数を返す |
double Unif32_h() | 32ビット精度[0,1)の浮動小数点数ハードウエア乱数を返す |
double Unif53_h() | 53/52ビット精度[0,1)の浮動小数点数ハードウエア乱数を返す |
double Unif_h() | 53/52ビット精度[0,1)の浮動小数点数ハードウエア乱数を返す。 ただし FAST_UNIF が定義されてれる時は 32 ビット精度、 FLOAT_REAL が定義されていれば 24 ビット精度、 HALF_REAL が定義されていれば 11 ビット精度になる。 |
32/64ビットコンパイラでのデフォルト。
16ビットコンパイラの場合は CHECK_MEM, ASIF32 のいずれかを有効にすると該当する。
32/64/16ビットのいずれでも NO_STR を有効にすると NO_FAST_STR が有効になるので該当せず、Aになる。
アライメント | サイズのアライメント | OpenMP 並列リージョン内 | |
---|---|---|---|
GetMem(),値の配列 | ALIGN_MEM(0:sizeof(size_t)) | ALIGN_MEM(0:しない) | 使用不可 |
GetMemSvec(),ポインタの配列 | sizeof(size_t) | sizeof(size_t) | 使用不可 |
GetMemNoAlign() | sizeof(size_t) | sizeof(size_t) | 使用不可 |
GetMemRaw() | しない | しない | 使用可 |
Strdup() | sizeof(size_t) | 1 | 使用不可 |
SetStr(),AllocStr() 等 | 1 | 1 | 使用不可 |
32/64ビットコンパイラでは、NO_FAST_STR か NO_STR を有効にすると該当する。
16ビットコンパイラの場合は CHECK_MEM, ASIF32 のいずれかを有効にして、
NO_FAST_STR か NO_STR を有効にすると該当する。
アライメント | サイズのアライメント | OpenMP 並列リージョン内 | |
---|---|---|---|
GetMem(),値の配列 | ALIGN_MEM(0:sizeof(size_t)) | ALIGN_MEM(0:しない) | 使用不可 |
GetMemSvec(),ポインタの配列 | sizeof(size_t) | sizeof(size_t) | 使用不可 |
GetMemNoAlign() | sizeof(size_t) | sizeof(size_t) | 使用不可 |
GetMemRaw() | しない | しない | 使用可 |
Strdup() | sizeof(size_t) | 1 | 使用不可 |
SetStr() 等 | sizeof(size_t) | 1 | 使用不可 |
AllocStr() 等 | ALIGN_MEM(0:sizeof(size_t)) | ALIGN_MEM(0:しない) | 使用不可 |
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:しない) | 使用不可 |
GetMemNoAlign() | ALIGN_MEM(0:しない) | ALIGN_MEM(0:しない) | 使用不可 |
GetMemRaw() | しない | しない | 使用可 |
Strdup() | ALIGN_MEM(0:しない) | ALIGN_MEM(0:しない) | 使用不可 |
SetStr(),AllocStr() 等 | 1 | 1 | 使用不可 |
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:しない) | 使用不可 |
GetMemNoAlign() | 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*) を足したポインタを返すことを意味します。
ポコムのデータをグラフにしたり、計算式を埋め込んだりする時は、 エクセルが便利です。Ubuntu ではエクセルの代わりに LibreOffice calc を使います。 LibreOffice calc ではあらかじめ、「ツール」→「オートコレクトオプション」で 「言語固有のオプション」のでクォーテーションマークが全角にならないように 置換のチェックを二つとも外しておくと便利です。(https://4thsight.xyz/3253) ポコムのバージョン 5.01 からは、 カンマ区切りのデータである .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 ファイルを読み込んで開いた場合は、データを修正した後閉じるボタン「×」を
押せばそのまま修正後のデータが .csv 形式で上書きされます。
ただしUTF8モードでエクセル2013の場合は、
ユニコードテキスト(タブ区切り)でしか保存できません。
エクセル2015以降からは、
UTF8のカンマ区切り .csv ファイルに保存可能になったようです。
(私は新しいエクセルを所持していないので未確認です。)
.tsv ファイルを読み込んで開いた場合は、データを修正した後閉じるボタン「×」を
押せばそのまま修正後のデータを、エクセルは保存しようとします。
ただし、そのままだと拡張子が .txt がファイル名に加えられます。
例えば、修正前の読み込んだファイルが test.tsv ならば test.tsv.txt となります。
これを test.tsv に上書きしたい場合は、ファイル名を入力するときに「test.tsv」
ではなく「"test.tsv"」のようにダブルクォーテーションで囲みます。
.tsv ファイルを書き出すには「名前を付けて保存」で
ファイルの種類:「Unicodeテキスト(*.txt)」を選んで保存してエクセルを終了します。
ポコム バージョン 5.03 からはUTF16のデータを受け付けるようになったので、 UTF16からUTF8に変更する必要はなくなりました。 ポコムでUTF16を変換する条件は次の通り。
LibreOffice calc で .csv ファイルから読み込んだデータを修正して .csv に保存するときは、
そのまま閉じるボタン「×」を押せばそのまま修正後のデータが .csv 形式で上書きされます。
LibreOffice calc で .tsv ファイルから読み込んだデータを修正して .tsv に保存するときは、
「名前を付けて保存」でファイルの種類を「テキストCSV(.csv)」を選んで、
区切り子を「タブ」にして保存します。区切り子がタブの場合でも、拡張子は必ず .csv になるので、
面倒ですが、ファイル名の拡張子を .csv から .tsv に手動で変更します。
ただし、CではなくC++ならば
static char*msg=JP("日本語");
のように main() 関数が呼び出される前に変換が行われる場合、戻り値の指す領域は
プログラムが終了するまで有効です。
fputs(EJ("English\n","日本語\n"),fp); #if JPN fputs("日本語\n",fp); #else fputs("English\n",fp); #endifとしていたならば、 UTF8モードで古い Visual C++ や Borland C++ 5.5.1 にも対応するためには、
fputs(EJP("English\n","日本語\n"),fp); #if JPN fputs(JP("日本語\n"),fp); #else fputs("English\n",fp); #endifと書き換える必要があります。
●X86_INTRIN Windows の32/64bitコンパイラでこれを定義するとハードウエア乱数を使うことができます。
Version 8.12 以降なら Rand_h() Rand64_h() Unif_h() Unif53_h() Unif32_h() Unif24_h() Unif11_h() が使用可能になります。ただし、CPUが第3世代以降の Core i シリーズである必要があります。
Version 8.15 以降なら Rand_s()、Rand64_s() が使用可能になります。ただし、CPUが第5世代以降の Core i シリーズである必要があります。
●TINYMT64 TINYMT64 を定義すると以下の乱数関数の生成方法を TinyMT32 から TinyMT64 に変更します。 Rand Rand_r BackRand BackRand_r Rand64 Rand64_r BackRand64 BackRand64_r Unif Unif_r BackUnif BackUnif_r Unif11 Unif11_r BackUnif11 BackUnif11_r Unif24 Unif24_r BackUnif24 BackUnif24_r Unif32 Unif32_r BackUnif32 BackUnif32_r Unif53 Unif53_r BackUnif53 BackUnif53_r バージョン 8.12 以降、32/64bit コンパイラならば、TinyMT32 でも Rand64, Rand64_r, BackRand64, BackRand64_r が使用可能になります。 また16 bit コンパイラの場合でも TINYMT64 を定義することができます。 TinyMT64 と TinyMT32 は異なる値を生成します。 64/16ビットコンパイラの場合 Unif()、Unif_r()、Unif53()、Unif53_r が速くなります。 32ビットコンパイラの場合や、FAST_UNIF、HALF_REAL、FLOAT_REAL が有効な場合は 遅くなります。また、ほとんどのコンパイラで Rand()、Rand_r() が遅くなり プログラムサイズが大きくなります。 ●OLD_UNIF53 TINYMT64 以外の 53/52 ビット乱数は ver 8.12 以降は ver 8.11 以前と比較して、 上位 27 ビットが同じで下位 26 ビットが異なります。 OLD_UNIF53 を定義すると ver 8.11 以前と同じになりますが少しだけ遅くなります。 ●RAND_16, RAND_32 RAND_16 を定義すると乱数の計算を16ビットで行います。 16ビットコンパイラでコンパイルすると既定で RAND_16 は定義されます。 そして全ての乱数発生が高速化します。 しかし、プログラムサイズは大きくなります。16ビットコンパイラで RAND_32 を 定義すると RAND_16 は非定義となりプログラムサイズが小さくなることがあります。 逆に32/64ビットコンパイラで RAND_16 を定義すると最大で8倍くらい遅くなります。 ●FAST_UNIF これを定義すると Unif(),Unif_m(),Unif_f(),Unif_r(),BackUnif(),BackUnif_r(), Unif_h() 関数がポコム・バージョン 8.02 以前と同じように32ビット精度になります。 FAST_UNIF を定義しない場合 ・これらの関数は53または52ビット精度になる。 ・浮動小数点数の乱数を1個発生する度に2回整数乱数を呼び出すようになる。 ただし TINYMT64, HALF_REAL, FLOAT_REAL を定義した場合1回である。 Jump(),Jump_r() を使っている場合注意が必要。 ●UNIF53_UNION, UNIF52_UNION これら2つは IEEE754 に対応したCPUで使用可能です。 さらに UNIF53_UNION は long double が 80 ビットである必要があります。 全ての Visual C++, TurboC 1.5 は long double が double と同じため、 UNIF53_UNION は使用できません。一方 TurboC 2.0、LSI-C、Borland C++、gcc は UNIF53_UNION は使用可能です。 これら2つは整数と浮動小数点数の共用体を使用して、まず [1,2) の乱数を求めて、 それから 1.0 を引いて [0,1) の乱数を返します。 UNIF52_UNION を定義すると Unif〜() 等の精度が53ビットから52ビットに減ります。 具体的には確率2分の1で53ビットの結果と比較して約1京分の1(1.1102e-16) 小さな結果を返します。一方、UNIF53_UNION の場合は53ビットのままです。 浮動小数点数演算をソフトウエアで行う16ビットコンパイラの場合はかなり高速化 します。さらに UNIF52_UNION の方が精度が落ちますが UNIF53_UNION よりも 少しだけ高速化します。 32/64ビットコンパイラの場合はどちらもほとんど高速化しません。
Visual C++ の統合開発環境からコンソールモードで、かつ、UTF8モードの時に文字化けを 起こす場合は、一回UTF8モードを解除して実行し、端末画面のタイトルバーを右クリックして、 [既定] を選び、[フォント]を[MS ゴシック]を選択すると、UTF8モードにしても文字化けしなくなります。 ただし Windows 8.1 以前の Windows の場合、全角文字のごく一部が文字化けを起こすようになります。
プログラムの最初で、例えば void Init(void) という関数を実行したい場合は、 以下のようにします。 まず、その関数をマクロ PROC(Init,"初期化") のように登録します。 さらに、マクロ AUTO("Init") のように登録すると、プログラムの 最初に関数 Init() が実行されます。 あるいはマクロ CUSTOM_MAIN を1にして、 main( ) ルーチンを自分で用意します。
pocom.h をインクルードする前に #define OLD_PRINT のように定義すれば、
Print( ), PrintCSV( ), PrintTSV( ) が非常に古い形式で書き出すようになります。
非常に古い形式とはデータ行の終わりで $ を書きだし、$ の直前の ; を省略したデータです。
このオプションは古い pocom.h でコンパイルした実行ファイルに、データを
エラー無く読み込ませるためだけに用意しました。それ以外の目的では使わないようにしてください。
そして、できるなら OLD_PRINT を使用する代わりに、古い計算ルーチンを新しい pocom.h でコンパイルし直してください。
理由は、古い形式は行数が0になる可変列行列を作成できない等の仕様上の欠陥があるからです。
新しい形式のデータはそれらの問題が起きません。
#define OLD_PRINT3 を定義すると、ポコム Ver.3.02 〜 Ver.4.01 まで形式で書き出します。
この場合データ行の終わりで $ を書きだし、$ の直前の ; を省略しないデータです。
新しい pocom.h でコンパイルした実行ファイルは、新しい形式でも、古い形式でも殆どの場合読み込むことができます。
ただし、古い形式のデータファイルでデータ行とデータ行の間に空白行が含まれる場合は失敗します。これを読み込めるように
するには #define OLD_READ を定義してください。古い形式のデータファイルでデータ行の間に空白行がある場合は、
その空白行をコメント行に置き換えることを推奨します。コメント行は配列の終わりとはならないからです。
また、バージョン 5.01 以降ではCSVファイルも直接読み込めるようになりました。この副作用で、
古いデータファイルで「,」をクォートしない文字列があった場合に読み込みエラーになります。これを
回避するには #define NO_CSV_READ を定義してください。
Load されているファイルの中から Load を呼出すことができます。 ただし、最大の深さは 5 に制限されています。
CHECK_MEM が有効の場合メモリが正しく使われているかどうか検査します。
32/64ビットのコンパイラではデフォルトで検査します。 16ビットのコンパイラではデフォルトで検査しませんです。 32/64ビットのコンパイラで無効にするには NO_CHECK_MEM を定義します。 16ビットのコンパイラで有効にするには CHECK_MEM, ASIF32 のいずれかを定義します。 有効にすると GetMem( )、FreeMem( ) が正しく使われているかどうかがわかり、 メモリリークも検出します。また、ソースファイルのどこでエラーが発生したかがわかります。 バグのない計算ルーチンを開発したならばメモリの検査は必要ないので無効で問題ありません。 32/64ビットのコンパイラで巨大なデータを処理する場合 NO_CHECK_MEM を有効にして、 メモリの検査をスキップするとパフォーマンスが向上します。
NO_FAST_STR が無効の場合、STR、SVEC、SMAT、SJAG、CDEF、Range、Alias の 文字列の配置場所をまとめて確保します。 16/32/64ビットのコンパイラ、つまり全てのコンパイラについてデフォルトでまとめます。 32/64ビットコンパイラで SVEC、SMAT、SJAG、CDEF の場合 4096 バイト毎にまとめます。 この場合、#define PAGESIZE 8192 のようにすれば、まとめるサイズを変更できます。 無効にするには NO_FAST_STR を定義します。無効にすると少しだけプログラムが小さくなりますが、 パフォーマンスは大きく下がります。
NO_FAST_MATJAG が無効の場合、固定列行列・可変列行列の各行を 4096 バイト毎にまとめて確保します。
32/64ビットのコンパイラではデフォルトで NO_FAST_MATJAG が無効でまとめて確保します。 まとめるメリットは、列数が小さく行数が多い行列を確保するときに、 ヒープの使用量を減らすことと、ヒープの断片化を防ぐことにあります。 NO_SAVE と NO_FULL_MATJAG が無効の時は Alloc() の場合やデータファイル中、 固定列行列で行数と列数が確定している場合、 行列全体に要求されるメモリとちょうど同じ大きさだけの連続したメモリ領域に確保します。 巨大な行列全体を連続したメモリ領域に確保したくない場合は、NO_FULL_MATJAG を有効にします。 すると、行列は PAGESIZE 毎にメモリを確保するようになります。 NO_FULL_MATJAG は多くの場合、有効にするとパフォーマンスが落ちます。 16ビットのコンパイラでは NO_FAST_MATJAG は既定で有効です。 つまり、16ビットのコンパイラでは固定列行列・可変列行列は 1行毎に確保されます。 FAST_MATJAG を定義すれば NO_FAST_MATJAG を無効にして、 16ビットのコンパイラでもまとめてメモリを確保できます。 ただし16ビットのコンパイラでまとめる長所はありません。 欠点はプログラムが大きくなること。 そして使用可能メモリの量が少ないので、 まとめることによる性能の向上がほとんど無いか、かえって遅くなること。 STATIC, SEMISTATIC が有効な場合、常に NO_FAST_MATJAG は有効です。 これは STATIC, SEMISTATIC が有効な場合、 元々行列全体が連続した領域に確保されるからです。 #define MATJAG_PAGE_SIZE 1000 のように定義をするとまとめて確保するメモリの大きさを変更できます。 この場合 malloc() で確保される大きさは 1000 にアライメントや制御用の領域を 加算したものになります。 32/64ビットのコンパイラで #define PAGE_SIZE32 8192 /* 32ビットコンパイラの場合 */ #define PAGE_SIZE64 16384 /* 64ビットコンパイラの場合 */ とすればまとめて確保する大きさを変更できます。 PAGE_SIZE32 と PAGE_SIZE64 が同じならば #define PAGESIZE 8192 のようにすることもできます。 MATJAG_PAGE_SIZE を定義せずに PAGESIZE, PAGE_SIZE32, PAGE_SIZE64 で 領域の大きさを指定した場合、 malloc() で確保するメモリの大きさは ちょうど PAGESIZE, PAGE_SIZE32, PAGE_SIZE64 になります。 列数が多い場合や確保するときに行列の大きさが決定している場合は、 malloc() で確保する大きさが PAGESIZE 等を越えることがあります。
16 ビットの MS-DOS コンパイラで使う時は、 メモリの制限によるエラーが発生する場合があります。
まず考えられる原因は、 一度に64Kバイト以上のメモリを確保しようとした場合です。 例えば、rvec の場合、一度に確保できる最大要素数は 8191 個までです。 これは CHECK_MEM を有効にしたり、ALIGN_MEM を指定すると減ります。 また、スモールモデルやミディアムモデルの場合は全体で64Kバイト以下でなくてはなりません。
次に考えられる原因は、
プログラム全体で確保できるメモリの制限を超えた場合です。
コンパクトモデルやラージ モデル等で使えるメモリは、
Windows10 64bit+msdos.exe の場合約 686K バイトです。
例えば Example1.exe の限界は、
タイニーモデル(tcc -mt -DJPN example1.c)で N=13
タイニーモデル(tcc -mt -DNO_ALL example1.c)で N=38
スモールモデル(tcc -DJPN example1.c) で N=57。
コンパクトモデル(tcc -mc -DJPN example1.c)で N=198 です。
また、1行の長さも約16キロバイトに制限されます。
16ビットコンパイラ MS-DOS 用に作成したプログラムで24時間以上 Clock()、Lap()、Progress()、Progress2() 等を呼び出さずに計算し Clock()、Lap() で経過時間を表示させようとすると24時間単位で 短い時間が表示される不具合があります。
この不具合は QUIET24H を定義すると回避できます。 ただし、QUIET24H を定義するとコンパイル時に消費するメモリが約13キロバイト 大きくなり、Clock() や Lap() などの実行時間が数百倍遅くなります。
ポコムは MS-DOS の全てのメモリ モデルに対応しています。 実際は、データ サイズの制限が緩く、関数呼び出しが速いコンパクトモデルが便利です。 小さなデータで速度を求めるならばスモールモデルも有効です。 メモリ モデルに限らず、数値演算プロセッサやCPUのモード等、 Cコンパイラのオプションは、ポコムの性能や限界を上げるのに便利です。
32ビットでコンパイルした場合は通常1Gバイト以上のメモリを確保することはできません。
64ビットでコンパイルした場合は通常5Gバイト以上のメモリを確保することはできません。
これを変更するには、pocom.h をインクルードする前に、例えば、 #define MEM_LIMIT32 0.125 とします。
この場合、32ビットの時に確保できるメモリを 128Mバイト未満に制限できます。
64ビットなら、#define MEM_LIMIT64 8 のようにすれば、8Gバイトに拡張できます。
これはプログラムを起動するときにコマンドラインに -0.125 や -8 のようにすれば、
コンパイルし直さなくても変更できます。
空白として認識されるのは半角スペースとタブです。カンマでもデータを区切ることもできます。 全角の空白はアルファベット等と同じように扱われ、 トラブルの原因となります。
INT、INTF、FIX、IVEC、IMAT、IJAG を使う場合、 MS-DOS では -32768 〜 32767 までしか扱えないことに注意してください。 移植性を高めるため、ベクトルや行列のサイズを制御する場合を除いて、 大きい数値を扱う場合は、NINT、NVEC、NMAT、NJAG の使用を推奨します。 または、#include "pocom.h" の前に #define INT_32 としてください。 それよりも大きな数字を扱う場合は REAL、RVEC、RMAT、RJAG を使用してください。 これらは53ビット整数値として扱うこともできます。
コンパイルするときに gcc -DJPN ...、 cl /D JPN ... のように
マクロ JPN を定義したり。
pocom.h をインクルードする前に #define JPN のように定義すれば、
エラーメッセージが日本語になります。JPN を定義しなければ英語になります。
また、PrintCSV で日付の文字列を書きだすときに'平成28年10月15日'のように、日本語の元号を'で囲むようになります。
デフォルトでエラーメッセージを日本語にしたいときは、pocom.h の
#if !defined(JPN) #define JPN 0 #endif
の 0 を 1 に書き直します。この場合 gcc -DJPN=0 ...、 cl /D JPN=0 と
すれば、一時的にエラーメッセージを英語に戻すことができます。
日本語の場合は、桁を揃えるための前提となる文字コードの種類は pocom.h の
文字コードで静的に決まりますが、英語の場合にはデータファイルの文字コードで動的に決まります。
2013/1/5 の改良によって EUC-jp での半角カナ文字に対応しました。
Ubuntu の端末の文字コードをシフトJISや EUC-jp にして、
シフトJISや EUC-jp のデータファイルを
を処理する時に UBUNTU を定義すると桁ズレが起こらなくなります。
(2023/7/29 の改良によって Ubuntu 22.04 の端末に対応しました。)
(ただし、JPN、UTF8 または WINUTF8 を定義するとシフトJISや EUC-jp のデータファイルを読み込ませると
桁ズレが起こります。)
UBUNTU を定義しない場合、端末の設定->プロファイル->互換性->曖昧幅の文字->全角 にします。
UBUNTU を定義した場合、端末の設定->プロファイル->互換性->曖昧幅の文字->半角 にします。
2012/12/23 の改良によってUTF8で桁ずれが起こりにくいように修正しました。
現在の pocom ではシフトJIS文字のみで書かれたUTF8ファイルは桁ずれが起きないことを確認しています。
シフトJIS文字以外のユニコードの文字幅のルールは非常に複雑なので妥協しました。
半角文字を全角と誤判定したり全角文字を半角文字と誤判定したり、半角でも全角でもない文字等、
桁ずれの起きる文字が多数あると思います。(例えばアラビア文字)
UTF8の桁揃えは(@Windows用,AUbuntu用)の2種類のルールがあります。
Windows の場合、@Windows用のみ使用可能です。
Ubuntu の場合、WINUTF8 を定義すると@Windows用になります。
この場合、端末の設定->プロファイル->互換性->曖昧幅の文字->全角 にします。
WINUTF8 を定義しない場合AUbuntu用になります。
この場合、端末の設定->プロファイル->互換性->曖昧幅の文字->半角 にします。
AUbuntu用の場合、例えば文字 §¨°±´μ¶×÷、U+1CD〜U+1DC、 ギリシャ文字、キリル文字、全角罫線文字等は半角文字とみなします。
Ubuntu で結果を端末で表示したり、作成したファイルを端末内で more や vi で使用するときには、
gcc で通常コンパイルをし、AUbuntu用のルールを適用したものを使用してください。
一方、Ubuntu で端末に表示せずに@Windows用のルールで "MS ゴシック" と
互換性のある "梅ゴシック" 等のフォントを使って編集する場合は、
$ gcc -DWINUTF8 ...
のようにしてコンパイルし@Windows用のルールを適用して、
$ ./a.out test.txt > result.txt
のようにリダイレクトしたり、Output や Append 関数と Print 関数によってファイルを作成してください。
例えば、作成されたファイル名が result.txt ならば、
$ soffice result.txt
として LibreOffice Writer を起動し、Ctrl-A で全て選択し、フォントを "梅ゴシック" 等にします。
wine がインストールされていて、wine のメモ帳で編集するならば、
$ gcc -DWINUTF8 ...
$ ./a.out -b test.txt > result.txt
$ notepad result.txt
としてください。BOMがないと、wine のメモ帳はUTF8ファイルとみなしてくれません。
マッキントッシュによくある濁点・半濁点の結合文字や、IVS異体字セレクター付き文字
(例えば「辻」のしんにょうの点が1つのもの)は1文字の全角文字とみなします
(つまり正しく処理します)。
IVS異体字セレクター付き文字に対応しているのはメモ帳なら Windows7 以降。
ワードやエクセルならば、2013以降のバージョンからです。
コマンドプロンプトでは Windows10 でも対応していません。
ウィンドウズモードの時に、pocom.h をインクルードする前に
#define EDIT_FONT_SIZE 16
としたり、コマンドラインで -DEDIT_FONT_SIZE=16、/D EDIT_FONT_SIZE=16 とした場合、
ウィンドウズモードのウィンドウのフォントのサイズを変更できます。デフォルトは16です。
12〜24の偶数を指定できます。
メモ帳の場合 [書式(V)]->[フォント(F)]の設定で、
[フォント名(F):] -> "MS ゴシック"、[スタイル(Y):]->"標準"、[サイズ(S):]->"12"
にすると、EDIT_FONT_SIZE がデフォルトの16のときと一致します。
同様に EDIT_X、EDIT_Y を指定すれば
ウィンドウズモード場合のウィンドウの横・縦方向の文字数を変更できます。
デフォルトは EDIT_X が80、EDIT_Y が24です。
また、EDIT_BUF_SIZE を指定すれば、スクロールして表示できる行数も変更できます。
デフォルトは200行です。大きくし過ぎると表示速度が遅くなります。
ウィンドウズモードでない場合の横・縦方向の文字数を変更するには TERMINAL_X、TERMINAL_Y を 指定します。デフォルトは TERMINAL_X が80、TERMINAL_Y が24です。 しかし、これを変更することは推奨しません。
32/64ビットコンパイラの場合UTF16ファイルを読み込むことができます。
これを無効にしたいときは #define NO_UTF16 としてください。
16ビットコンパイラの場合、デフォルトではUTF16ファイルを読み込むことは
できません。#define USE_UTF16 とすると読み込むことができます。ただし、
UTF16ファイルに日本語がある場合はUTF8モードにする必要があります。
(※16ビットコンパイラの場合UTF16ファイルをシフトJISに変更できないため)
pocom.h をインクルードする前に #define HIT_ENTER のように定義すれば、
実行が終了した時に [ENTER] キーの入力を待ちます。
gcc -DHIT_ENTER や cl /D HIT_ENTER のようにしても有効です。
ウィンドウズモードにすると常に無効になります。
ウィンドウズでコンソールで WINUTF8 を有効で、HIT_ENTER を定義しなくても、
強制的に有効になります。ただしこの場合、開始時のコードページが 65001 ならば
[ENTER] キーの入力を待ちません。
pocom.h をインクルードする前に #define REPORT_MEM のように定義すれば、 終了時にメモリの使用状況を表示します。 これは、私がデバッグ用に使用するための機能です。
pocom.h をインクルードする前に #define FLOAT_REAL のように定義すれば、
real, rvec, rmat, rjag を float にすることができます。
gcc -DFLOAT_REAL や cl /D FLOAT_REAL のようにしてもできます。
使用メモリをできるだけ節約したい時や、OpenCL、SSE、AVX などで速度を上げたいときに指定します。
FLOAT_REAL の代わりに HALF_REAL を定義すると real, rvec, rmat, rjag は half となり、
半精度浮動小数点数となります。
pocom.h をインクルードする前に #define ALIGN_REAL のように定義をすれば、
16 bit コンパイラと Borland C++ 5.5.1 で double に合わせてアライメントされます。
16 bit コンパイラならば次の項で説明する ALIGN_MEM が8になります。
pocom ver 6.05 までは、Range と Vmj の real フィールドもアライメントされており
スモールモデルでの vmj 構造体の大きさも10バイトから16バイトに増加しましたが、
pocom ver 7.01 以降は real フィールドはアライメントされません。
16 bit コンパイラと Borland C++ 5.5.1 を特別にした理由は
calloc( ) が8バイトにアライメントされないので、
double を高速に読み書きするには8バイトにアライメントする必要があるからです。
それ以外のコンパイラの場合は浮動小数点は ALIGN_REAL を定義しなくても
アライメントされていると考えられます。
pocom.h をインクルードする前に #define ALIGN_MEM 8 のように 4 8 16 32 64 128等に定義をすれば、
GetMem( ) の返すアドレスをアライメントすることができます。
また、確保する領域の大きさもアライメントされます。例えば ALIGN_MEM が 16 の時に、GetMem(3,8) を行うと、
24 バイト確保するのではなく、32 バイト確保します。
4 にすれば、16 bit コンパイラで FLOAT_REAL が定義されているされているときに浮動小数点演算(f87)が高速になります。
8 にすれば、16 bit コンパイラと Borland C++ 5.5.1 で FLOAT_REAL が定義されていないときに
浮動小数点演算(f87)が高速になります。
16 にすれば、32 bit コンパイラでも SSE 〜 SSE4 に対応できます。
32 にすれば AVX 〜 AVX2 に対応できます。
64 にすれば AVX512 に対応できます。
ALIGN4、ALIGN8、ALIGN16、ALIGN32、ALIGN64、ALIGN128 を定義すると、
それに対応した値が ALIGN_MEM に設定されます。
pocom.h をインクルードする前に #define FAST_RAND 4 のように定義をすれば、 Unif_m(N)、Rand_m(N) の引数に0〜3までの整数値で系列を指定できます。 高速乱数をマルチスレッドで使うとき等にスレッド数を指定します。 デフォルトでは1です。Unif_f() は Unif_m(0) と、Rand_f() は Rand_m(0) と同じです。
pocom.h をインクルードする前に #define FAST_UNIF のように定義をすれば、 Unif(), Unif_r(R), Unif_f(), Unif_m(N), BackUnif(), BackUnif_m() の精度を53ビットから32ビットに変更できます。
INT(N,3,EJ("Size","大きさ ")) RMAT(A,307,N,N,EJ("Matrix","行列 ")) Swap(Int i,Int j) { rvec temp=A[i]; A[i]=A[j]; A[j]=temp; } /* コンパイルエラー */この場合は標準関数(マクロ)で SwapRow(A,i,j); とするとコンパイルエラーを回避できます。
pocom.h をインクルードする前に #define OLD_FOR 1 のように定義すれば、古いC++コンパイラでも、
Int x=0; for (Int i=0;i<10;i++) x+=i; for (Int i=0;i<10;i++) x+=i;
としてもエラーにならなくなります。
Visual C++ 5.0 や Visual C++ 6.0 の場合、自動的に OLD_FOR は1に設定されます。
実際には、
#define for if (0) ; else for
と定義しています。
pocom.h をインクルードする前に #define STDERR_STDOUT のように定義すれば、
エラーメッセージを stderr ではなく、stdout に変更できます。
出力をファイルへリダイレクトするときに、
エラーメッセージもファイルへ書き出したいときに利用します。
Windows10 以外でUTF8モード、コンソールモードで実行する場合、
Visual C++ 2019 で作成したプログラムには stderr にバグがあります。
これを避ける方法として、
等が考えられます。
pocom.h をインクルードする前に #define FIX_EXE_SIZE のように定義すれば、
pocom.h のファイル名を pocom-2.h としたり、
Example1.c のファイル名を Exam.c のようにして名前の長さが変わっても
実行ファイルの大きさが変わらなくなります。
これを指定するとファイル名の長さだけが変化た同じプログラムで
ベンチマークの実行時間が変化するのを防ぎます。
FIX_EXE_SIZE を定義すると CHECK_MEM を無効化します。
また、MulAdd() のチェックも無効化します。
pocom.h をインクルードする前に #define PC9801 のように定義すれば、 Progress( )、Progress2( ) で使用する時間の計測を INT 1AH から INT 21H へ変更します。NEC PC9801 シリーズで使用するには定義してください。
配列をデータファイルに書く場合に、配列の大きさを同時に指定すれば、 作業メモリを節約することができます。以下に例を示します。
INT(N,3,EJ("Size","大きさ ")) RVEC(A,307,N,EJ("vector","ベクトル ")) # 節約が行われないデータファイルの書き方 A 1 2 3 4 5 # 節約が行われるデータファイルの書き方 N A 5 1 2 3 4 5 # 以下のように N と A を別々に指定すると節約は行われません N 5 A 1 2 3 4 5 # N が決まっていれば、以下のようにしても節約できます Range N == 5 A 1 2 3 4 5
上の例はベクトルですが、 行列や可変列行列の読み込み時に作業メモリを節約するには以下のようにします。
INT(N,3,EJ("Num of Lines", "行数")) INT(M,3,EJ("Num of Columns","列数")) IVEC(L,3,N,EJ("Jagged matrix's size","可変列行列の列数")) RMAT(A,307,N,M,EJ("Matrix","行列")) RJAG(B,307,L,EJ("Jagged matrix","可変列行列")) # 節約が行われないデータファイルの書き方 A B 1 2 3 ; 1 2 3 ; 4 5 6 ; 4 5 6 7 ; # 節約が行われるデータファイルの書き方 N M A L B 2 3 1 2 3 ; 3 1 2 3 ; 4 5 6 ; 4 4 5 6 7 ;
Limit の使用例
Print するときに、一番右の配列を横に並べて表示する数を制限して折り返します。
@一番右の配列がベクトルならば、左には単純変数のみを指定できます。
A一番右の配列が固定列行列・可変列行列ならば、左には単純変数とベクトルを指定できます。
大きな配列を長さ79文字以内の行に収めたい場合などに使います。
Limit 0 とすると折り返しは行われません。
Limit -79 のように負の値を指定するとその桁数以下になるように調整します。
デフォルトは -79 です。ただし、ウィンドウズモードならば -1024 です。
Limit -1 としてもデフォルトに戻します。
例@ INT(N,3,EJ("Size","大きさ ")) IVEC(L,3,N,EJ("Vector","ベクトル ")) 入力 L 1 2 3 4 5 6 7 8 9 10 Limit 3 Print N L 出力 N L 10 1 2 3 4 5 6 7 8 9 10
例A INT(N,3,EJ("Size","大きさ ")) IVEC(L,3,N,EJ("Vector","ベクトル ")) IJAG(U,3,L,EJ("Jagged matrix","可変列行列 ")) 入力 U 1 2 3 4 5 6; 7 8 9 10 11 12 13; Limit 3 Print N L U 出力 N L U 2 6 1 2 3 4 5 6 ; 7 7 8 9 10 11 12 13 ;
pocom.h をインクルードする前に #define NO_ALIAS のように定義すれば、
ポコム関数 Alias を組み込みません。
コンパイル時にコマンドラインで -DNO_ALIAS や /D NO_ALIAS のように定義しても組み込みません。
大きなプログラムをメモリの制約の厳しいコンパイラでコンパイルするときに指定します。
以下は NO_ALIAS のようなプログラムを小さくするためのマクロの一覧です。
使用できるメモリが非常に小さいシステムの以外は指定する必要はないでしょう。
最近加わった System( ) 関数や Add( ) 関数は不要な場合が多く、しかも大きいので NO_SYSTEM や NO_ADD を 定義すると、かなり節約できます。
名前 | 説明 |
---|---|
NO_ADD | Add 関数と Reset 関数を無効にする。下請けの AddToIvec 等も組み込まない。 |
NO_ADJUST | UTF8やEUC−jpでの桁ずれ防止の機能を組み込まない。 NO_ADJUST と WINUTF8 や ASCII を同時に定義すると WINUTF8 や ASCII の方が優先される。 以前は NO_UTF8 という名前だったが、混乱を招くので NO_ADJUST にした。 |
NO_ALIAS | Alias 関数を無効にする |
NO_ADD | 32/64ビットコンパイラで Add 関数群を無効にする |
NO_APPEND | Append 関数を無効にする |
NO_BACK | BackRand, BackUnif 関数などを無効にする |
NO_BOM | -b オプションでBOMを書きだす機能を無効にする |
NO_BUILTIN | X86_INTRIN を定義したとき、gcc 9 以降、または VC++2013 以降でも組込み関数を使わない |
NO_BYTE | BYTE,BVEC,BMAT,BJAG を無効にする。 |
NO_CDEF | CDEF,CODE,CVEC,CMAT,CJAG を使わない |
NO_CHCP | WINUTF8 が有効なコンソールアプリケーションでコードページ変更を抑止する。( NO_ALL の例外)。 |
NO_CHECK_CDEF | CDEF のサイズが縮小しても、それに関連する CODE,CVEC,CMAT,CJAG をエラーとしない。 |
NO_CHECK_MEM | 32/64ビットコンパイラで CHECK_MEM を無効にする。 |
NO_CLOCK | Clock 関数と ClockSec 関数と LastClock を無効にする |
NO_COMMA | 1,234,567 のようにカンマが入った整数の読み書きを無効にする |
NO_CSV | PrintCSV 関数を無効にする |
NO_CSV_READ | CSV ファイルを読み込み不可能にします。カンマを含む文字列をクォートする必要が無くなります。 |
NO_CSVTSV_STR | PrintCSV,PrintTSV で文字列・コード型を表示するとき Format が0以上ならば、必ず引用符で囲む |
NO_DBL | DBL,DVEC,DMAT,DJAG を無効にする |
NO_DELETE | Delete 関数を無効にする |
NO_ECHO | Echo 関数を無効にする |
NO_END_MSG | ウィンドウズモードの場合に、計算終了時のメッセージボックスを出さない。( NO_ALL の例外) |
NO_FAST_MATJAG | 行列をまとめて確保する機能を組み込まない。 |
NO_FAST_STR | 文字列処理の高速割り当てを組み込まない。 以前は OLD_STRDUP という名前だったが、NO_FAST_STR にした。 |
NO_FIT | pocom.h 6.04 以前のように長い変数名を持つ値の幅を調整しない。 NO_FIT が0で SMART_FIT を定義すると(#define SMART_FIT) より適切に幅を調整する(最後の変数を調整しないなど) |
NO_FORMAT | Format 関数を無効にする |
NO_FREE | Free 関数を無効にする |
NO_FLT | FLT,FVEC,FMAT,FJAG を無効にする |
NO_FULL_MATJAG | 行列全体をまとめて一つの領域に確保する機能を組み込まない。 |
NO_HALF | HALF,HVEC,HMAT,HJAG を無効にする |
NO_HANGUL | UTF8モードのときに、イ文字(Yi文字)とハングル文字の調整を無効にする |
NO_INTERVAL | SetInterval() を無効にする。Progress() と Progress2() が遅くなる。 |
NO_JAG | IJAG,CJAG,RJAG,SJAG を使わない |
NO_JUMP | Jump, Jump_r 関数を使わない |
NO_LAP | Lap 関数と LapSec 関数と LastLap を無効にする |
NO_LIMIT | Limit 関数を無効にする |
NO_LINT | LINT,LVEC,LMAT,LJAG を無効にする |
NO_LIST | List 関数を無効にする |
NO_MULADD | MulAdd 関数でオーバーフローのチェックを行わなくする |
NO_NINT | NINT,NVEC,NMAT,NJAG を無効にする |
NO_OPEN | 読み込みファイルを指定しなかった時に現れるダイアログを抑止する |
NO_OUTPUT | Output 関数を無効にする |
NO_PERIOD | timeBeginPeriod(1) と timeEndPeriod(1) を抑止する。 |
NO_PROGRESS | Progress 関数と Progress2 関数を無効にする |
NO_QUIT | Quit 関数を使わない。 |
NO_RAND | 乱数のログラムを使わない(高速乱数には影響しない) |
NO_RANGE | Range 関数を使わない。INTF、FIX 型でエラーチェックをしない |
NO_RESET | Reset 関数を無効にする |
NO_RESTRICT | ポインタの宣言に __restrict を付けない |
NO_SAVE | 作業メモリの節約を行う機能を組み込まない |
NO_SJIS_UTF8 | Windows でUTF8モードの時に、データファイルの SJIS 文字を UTF8 文字に変換しない |
NO_SORT | 32/64ビットコンパイラで Sort 関数を無効にする |
NO_STR | STR、SVEC、SMAT、SJAG を使わない。NO_FAST_STR も有効になり高速文字列処理を組み込まない |
NO_SYSTEM | System 関数を無効にする |
NO_TINT | TINT,TVEC,TMAT,TJAG を無効にする |
NO_TSV | PrintTSV 関数を無効にする |
NO_UTF16 | UTF16ファイルを読み込む機能を無効にする |
NO_VERSION | List 関数で pocom.h と anneal.h のバージョンを出力しない( NO_ALL の例外)。 |
NO_VMJ | メモリの高速割り当ての機能を組み込まない |
NO_ALL を定義すると上の表のほとんどのマクロを定義します。
また ASCII も定義され、NO_ADJUST は2になり、JPN も無効になります。
(NO_CHCP、NO_CSV_READ、NO_END_MSG、NO_RESTRICT, NO_VERSION, だけ例外にしました。)
「Alias を使いたいので NO_ALIAS だけ例外にしたい」場合は
-DNO_ALL -D"NO_ALIAS=0"
のようにします。
NO_AFTER_VER2 を定義するとポコムのバージョン2以降の機能を無効にします。
NO_BYTE, NO_TINT, NO_LINT, NO_HALF, NO_FLT, NO_DBL, NO_TSV, NO_ADD, NO_HANGUL, NO_INTERVAL, NO_SORT,
NO_BOM, NO_CHECK_CDEF, NO_CSVTSV_STR, NO_FAST_MATJAG, NO_FAST_STR, NO_FREE, NO_LAP, NO_LIMIT, NO_MULADD, NO_PROGRESS, NO_QUIT,
NO_SAVE, NO_SYSTEM, NO_DELETE, NO_VMJ, NO_VERSION, NO_COMMA, NO_FIT, NO_OPEN, NO_PERIOD が定義されます。
また、CHECK_MEM も無効になります。
NO_HANGUL が定義されているとハングルは全角、イ文字(Yi文字)は半角にとみなして桁揃えします。
NO_HANGUL が定義されていない場合、実行するウィンドウズの各バージョン、EDIT_FONT_SIZE に合わせて、
イ文字を2文字で半角3文字分に桁揃えしたり、
ハングル文字を8文字で半角11文字分に桁揃えしたり等します。
これらの割合は実行するウィンドウズの各バージョン、EDIT_FONT_SIZE によって異なります。
また、これらの割合はフォントが "MS ゴシック" であることを前提にしています。
UTF8モードでない時は、この NO_HANGUL の有効/無効は何も影響もしません。
UTF8モードで NO_HANGUL を定義するデメリットは、 ハングルを含むデータファイルの表示桁が大きくずれることです。特にエラーが起きた時に エラーの位置を知らせる'^'マークが正しい位置を示さなくなります。 ハングルはユニコード多言語基本面に1万文字以上登録されているので無視できないと考えました。
UTF8モードで NO_HANGUL を定義するメリットは以下の通りです。