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