マニュアルページ 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
     試験をクリアします。