マニュアルページ mwcrans.3m
名前
mwcrans - 繰り上げ付き乗算による疑似乱数生成関数
形式
cc [ flag ... ] file ... -lsunmath -lm [ library ... ]
#include <sunmath.h>
int i_mwcran_(void);
unsigned int u_mwcran_(void);
long i_lmwcran_(void);
unsigned long u_lmwcran_(void);
long long i_llmwcran_(void);
unsigned long long u_llmwcran_(void);
float r_mwcran_(void);
double d_mwcran_(void);
void i_mwcrans_(int *x, const int *n, const int *l, const
int *u);
void u_mwcrans_(unsigned *x, const int *n, const unsigned
*l, const unsigned *u);
void i_lmwcrans_(long *x, const int *n, const long *l, const
long *u);
void u_lmwcrans_(unsigned long *x, const int *n, const
unsigned long *l, const unsigned long *u);
void i_llmwcrans_(long long *x, const int *n, const long
long *l, const long long *u);
void u_llmwcrans_(unsigned long long *x, const int *n, const
unsigned long long *l, const unsigned long long *u);
void r_mwcrans_(float *x, const int *n, const float *l,
const float *u);
void d_mwcrans_(double *x, const int *n, const double *l,
const double *u);
void i_init_mwcrans_(void);
void smwcran_(const int *seed);
void i_set_mwcrans_(const int *p);
void i_get_mwcrans_(int *p);
機能説明
これらの関数は、Marsaglia により開発された繰り上げ付き 乗 算
(multiply-with-carry) アルゴリズムを使用し、疑似乱数のシーケ
ンスを生成します。乗数を M、シードの初期値を X、キャリーの初
期 値 を C (すべて 32 ビット整数) とすると、このアルゴリズム
は、次のようにして新しいシードとキャリーを生成します。
1. Z = X*M + C (Z 64 ビット整数)
2. 新しいシード X = Z の下位 32 ビット
3. 新しいキャリー C = Z の上位 32 ビット
(M*2**32 - 1) と (M*2**31 - 1) は両方とも素数であると仮定 す
る と、 シ ードとキャリーのシーケンスの周期は M*2**31 - 1 で
す。
上記関数は内部的に 32 ビットの繰り上げ付き乗算による生成関数
mwcran0 と mwcran1 を使用します。mwcran0 で使用される乗数は
526533 (0x808C5) で、mwcran1 で使用さ れ る 乗 数 は 557325
(0x8810D) で す。 これら生成関数の周期は両方とも約 2**50 で
す。これらの生成関数については、次の説明を参照してください。
u_mwcran_() は mwcran0 を呼び出し、32 ビット符号なし整数の疑
似乱数 (0 から 2**32 - 1 まで) を戻します。
i_mwcran_() は u_mwcran_() を呼び出し、その結果の最上位 ビッ
ト を マ スクオフし、32 ビット符号付き整数の疑似乱数 (0 から
2**31 - 1 まで) を戻します。
u_llmwcran_() は mwcran0 と mwcran1 の両方を呼び出し、2 つの
32 ビット値を一緒に連結し、64 ビット符号なし整数の疑似乱 数
(0 から 2**64 - 1 まで ) を戻します。この乱数生成関数の周期
は約 2**100 です。
i_llmwcran_() は u_llmwcran_() を呼び出し、その結果の最上 位
ビッ トをマスクオフし、64 ビット符号付き整数の疑似乱数 (0 か
ら 2**63 - 1 まで) を戻します。
関数 i_lmwcran_() と u_lmwcran_() はロング整数型の疑似乱数を
戻します。これらの数の範囲は、ロング整数型の幅によって異なり
ます。つまり、long int が
32 ビット幅 (つまり、ILP32 データモデル) の場合、これらの関
数はそれぞれ i_mwcran_() や u_mwcran_() と同じです。long int
が 64 ビット幅 (LP64 データモデル) の場合、これらの関数は そ
れぞれ i_llmwcran_() や u_llmwcran_() と同じです。
r_mwcran_() は単精度浮動小数点の疑似乱数 (範囲は [0,1)) を戻
し ま す。この関数は、mwcran0 を繰り返し呼び出し、ランダムな
ビットのシーケンスを生成し、その結果 を バ イ ナ リ 小 数 部
0.xxxxxxxxxxxxxxx... として解釈し、浮動小数点形式に切り捨て
ることにより、この値を生成します。結果の浮動小数点数のシーケ
ンスは範囲 [0,1) で均一に分散されます。
d_mwcran_() は倍精度浮動小数点の疑似乱数 (範囲は [0,1)) を戻
し ます。この関数は、mwcran0 と mwcran1 を繰り返し呼び出し、
ランダムなビットのシーケンスを生成し、その結果をバイナリ小数
部 0.xxxxxxxxxxxxxxx... として解釈し、倍精度浮動小数点形式に
切り捨てることにより、この値を生成します。結果の浮動小数点数
のシーケンスは範囲 [0,1) で均一に分散されます。
i_mwcrans_(x, n, l, u) は mwcran0 を繰り返し呼び出し、*l と
*u の間に均一に分散される 32 ビット整数の疑似乱数 *n (x[0],
x[1], ... x[*n - 1]) を生成します。[*l,*u] = [0,0x7fffffff]
の 場合、i_mwcrans_() は、i_mwcran_() を *n 回呼び出したとき
に生成される結果と同じ *n 乱数を生成します。
u_mwcrans_(x, n, l, u) は mwcran0 を繰り返し呼び出し、*l と
*u の間に均一に分散される 32 ビット符号なし整数の疑似乱数 *n
(x[0], x[1], ... x[*n - 1]) を 生 成 し ま す。 [*l,*u] =
[0,0xffffffff] の場合、u_mwcrans_() は、u_mwcran_() を *n 回
呼び出したときに生成される結果と同じ *n 乱数を生成します。
i_llmwcrans_(x, n, l, u) は mwcran0 と mwcran1 を繰り返し 呼
び 出し、*l と *u の間に均一に分散される 64 ビット整数の疑似
乱数 *n (x[0], x[1], ... x[*n - 1] ) を生成します。[*l,*u] =
[0,0x7fffffffffffffff] の 場 合、 i_llmwcrans_() は、
i_llmwcran_() を *n 回呼び出したときに生成される結果と 同 じ
*n 乱数を生成します。
u_llmwcrans_(x, n, l, u) は mwcran0 と mwcran1 を繰り返し 呼
び 出し、*l と *u の間に均一に分散される 64 ビット符号なし整
数の疑似乱数 *n (x[0], x[1], ... x[*n - 1]) を生成し ま す。
[*l,*u] = [0,0xffffffffffffffff] の場合、u_llmwcrans_() は、
u_llmwcran_() を *n 回呼び出したときに生成される結果と 同 じ
*n 乱数を生成します。
関数 i_lmwcrans_() と u_lmwcrans_() は、ロング整数型の疑似乱
数の配列を生成します。生成される数の範囲は、ロング整数型の幅
によって異なります。つまり、long int が 32 ビット幅 ( つ ま
り、 ILP32 デー タ モ デ ル) の場合、これらの関数はそれぞれ
i_mwcrans_() や u_mwcrans_() と同じです。long int が 64 ビッ
ト 幅 (LP64 デー タ モデル) の場合、これらの関数はそれぞれ
i_llmwcrans_() や u_llmwcrans_() と同じです。
r_mwcrans_(x, n, l, u) は mwcran0 を繰り返し呼び出し、(切 り
捨 てエラーがでるまで) *l と *u の間に均一に分散される単精度
浮動小数点の疑似乱数 *n (x[0], x[1], ... x[*n - 1]) を生成し
ま す。*l がゼロで、*u が 1 よりも少ない最大の単精度浮動小数
点数である場合、r_mwcrans_() は、r_mwcran_() を *n 回呼び 出
したときに生成される結果と同じ *n 乱数を生成します。
d_mwcrans_(x, n, l, u) は mwcran0 と mwcran1 を繰り返し呼 び
出し、(切り捨てエラーがでるまで) *l と *u の間に均一に分散さ
れる倍精度浮動小数点の疑似乱数 *n (x[0], x[1], ... x[*n -
1]) を生成します。*l がゼロで、*u が 1 よりも少ない最大の倍
精度浮動小数点数である場合、d_mwcrans_() は、d_mwcran_() を
*n 回呼び出したときに生成される結果と同じ *n 乱数を生成しま
す。
i_init_mwcrans_() は、mwcran0 と mwcran1 のシードとキャ リー
をデフォルト値に初期化します。
smwcran_(m) は、次の公式に従い、*m のスクラ ン ブ ル 値 で、
mwcran0 と mwcran1 のシードとキャリーを初期化します。
mwcran0 の場合:
X0 = MWCRAN_SEED0 + (*m)*0x110005
C0 = MWCRAN_CARRY0 + (*m)*0x110005
mwcran1 の場合:
X1 = MWCRAN_SEED1 + (*m)*0x100021
C1 = MWCRAN_CARRY1 + (*m)*0x100021
ここで、MWCRAN_SEED0、MWCRAN_CARRY0、MWCRAN_SEED1、 お よ び
MWCRAN_CARRY1 は、 そ れぞれ、mwcran0 と mwcran1 のシードと
キャリーに対して i_init_mwcrans_() で確立されるデフォルト の
初期値です。特に、ゼロと等しい
*m で smwcran_(m) を呼び出すことは、i_init_mwcrans_() を 呼
び出すことと等価です。この関数は、異なるシーケンスの乱数を取
得するための簡単な方法です。より精密にシードとキャリーを制御
するには、i_set_mwcrans_() を使用します。
i_get_mwcrans_(p) と i_set_mwcrans_(p) は、それぞれ、mwcran0
と mwcran1 の状態テーブルを取得および設定します。このテーブ
ルは、両方の生成関数のシードとキャリーが入っている 4 つの 整
数 (p[0] から p[3] まで) の配列です。つまり、p[0] と p[1] に
は、mwcran0 用のシードとキャリーが入っています。p[2] と p[3]
には、mwcran1 用のシードとキャリーが入っています。
使用例
次の例は、u_mwcran_() と u_mwcrans_() が整合性があることを検
証し、これらの関数が生成する数が均一に分散されているかどうか
を調べます。
/* u_mwcran*() を確認するサンプルプログラム */
#include <sunmath.h>
int main() {
unsigned x[1000],y[1000],i,lb,ub;
int n,hex1[16],hex2[16],hex3[16],seed,j;
double t1,t2,t3,v;
seed = 40;
/* 40 に初期化されたシードで、1000 個の符号なし整数の乱数を生成する。 */
smwcran_(&seed);
for (i=0;i<1000;i++) x[i] = u_mwcran_();
/* u_mwcrans_() で、同じ 1000 個の符号なし整数の乱数を生成する。 */
n = 1000; lb = 0; ub = 0xffffffff;
smwcran_(&seed); /* reset seed */
u_mwcrans_(y,&n,&lb,&ub);
/* x と y が等しいことを検証する */
for (n=0,i=0;i<1000;i++) n |= (x[i]-y[i]);
if(n==0) printf("Array x is equal to array y.\n\n");
else printf("***Error: array x is not equal to array y.\n\n");
/* 1000 個の乱数の 16 進数字の出現をカウントすることにより、
均一性を確認する。予想される値は 500。カウントは異なるシード値で
3 回繰り返される。*/
/* カウント配列 hex1[]、hex2[]、hex3[] を初期化する。*/
n = 1000; for (i=0;i<16;i++) hex1[i]=hex2[i]=hex3[i]=0;
/* シード値 1 で、1000 個の乱数の 16 進数字をカウントする。 */
seed = 1; smwcran_(&seed);
u_mwcrans_(x,&n,&lb,&ub);
for (i=0;i<n;i++) {
j = x[i]; hex1[j&0xf] += 1; hex1[(j>>4)&0xf] += 1;
hex1[(j>>8)&0xf] += 1; hex1[(j>>12)&0xf] += 1;
hex1[(j>>16)&0xf] += 1; hex1[(j>>20)&0xf] += 1;
hex1[(j>>24)&0xf] += 1; hex1[(j>>28)&0xf] += 1;
}
/* シード値 2 で、1000 個の乱数の 16 進数字をカウントする。 */
seed = 2; smwcran_(&seed);
u_mwcrans_(x,&n,&lb,&ub);
for (i=0;i<n;i++) {
j = x[i]; hex2[j&0xf] += 1; hex2[(j>>4)&0xf] += 1;
hex2[(j>>8)&0xf] += 1; hex2[(j>>12)&0xf] += 1;
hex2[(j>>16)&0xf] += 1; hex2[(j>>20)&0xf] += 1;
hex2[(j>>24)&0xf] += 1; hex2[(j>>28)&0xf] += 1;
}
/* シード値 3 で、1000 個の乱数の 16 進数字をカウントする。 */
seed = 3; smwcran_(&seed);
u_mwcrans_(x,&n,&lb,&ub);
for (i=0;i<n;i++) {
j = x[i]; hex3[j&0xf] += 1; hex3[(j>>4)&0xf] += 1;
hex3[(j>>8)&0xf] += 1; hex3[(j>>12)&0xf] += 1;
hex3[(j>>16)&0xf] += 1; hex3[(j>>20)&0xf] += 1;
hex3[(j>>24)&0xf] += 1; hex3[(j>>28)&0xf] += 1;
}
/* 各テストのカイ二乗を計算する。 */
t1 = t2 = t3 = 0.0;
for (i=0;i<16;i++) {
v = hex1[i]-500; t1 += v*v/500.0;
v = hex2[i]-500; t2 += v*v/500.0;
v = hex3[i]-500; t3 += v*v/500.0;
}
/* 結果を出力する。 */
printf("Expected value of each hex digit's appearance is 500.\n");
printf("Observed result with seed=1,2, and 3:\n");
printf(" Hex digit Number of appearances with\n");
printf(" seed=1 seed=2 seed=3\n");
for (i=0;i<16;i++) {
printf(" %01X: %4d %4d %4d\n",
i,hex1[i],hex2[i],hex3[i]);
}
printf(" ----------------------------\n");
printf("Chi-square value%7.2g %8.2g %8.2g\n",t1,t2,t3);
printf("Note: A reasonable range of the Chi-square value is\n");
printf(" within [7.26, 25.00] which corresponds to the 5\n");
printf(" percent and 95 percent points of the Chi-square\n");
printf(" distribution with degree of freedom equal to 15.\n");
return 0;
}
上記プログラムからの出力は次のようになります。
Array x is equal to array y.
Expected value of each hex digit's appearance is 500.
Observed result with seed=1,2, and 3:
Hex digit Number of appearances with
seed=1 seed=2 seed=3
0: 514 493 521
1: 529 507 480
2: 477 495 493
3: 495 541 517
4: 518 504 486
5: 496 464 484
6: 467 488 484
7: 511 487 540
8: 517 499 525
9: 500 489 490
A: 492 506 511
B: 475 504 482
C: 499 504 504
D: 485 514 493
E: 520 531 515
F: 505 474 475
----------------------------
Chi-square value 9.5 11 11
Note: A reasonable range of the Chi-square value is
within [7.26, 25.00] which corresponds to the 5
percent and 95 percent points of the Chi-square
distribution with degree of freedom equal to 15.
属性
次の属性については、 attributes(5) を参照してください。
__________________________________________________________________
| 属性タイプ | 属性値 |
|_____________________|___________________________________________|
| 使用条件 | SPROsunms、SPROlang (32 ビットライブラリ)|
| | SP64sunms、SP64lang (64 ビットライブラリ)|
| インタフェース安定性| 開発中 |
| MT レベル | MT-安全 |
|_____________________|___________________________________________|
関連項目
addrans(3M), lcrans(3M), shufrans(3M), attributes(5)
注意事項
これらの関数は内部生成関数 mwcran0 と mwcran1 を共有するため
に、 お互いに独立していません。たとえば、i_init_mwcran_() を
呼び出し、その後に d_mwcran_() を呼び出したときの 結 果 は、
i_init_mwcran_() を呼び出し、i_mwcran_() を呼び出し、その後
に d_mwcran_() を呼び出したときの結果とは異なります。( た だ
し、異なるスレッドの生成関数は独立しています。)
mwcran0 と mwcran1 で生成される乱数は、Marsaglia の Diehard
試験をクリアします。