はぐれエンジニアつれづれ

デジタルLSI設計(SystemC, SystemVerilog, etc.)の備忘録。はてなダイアリから移行中。

メルセンヌツイスターによるランダムテストデータ作成

ランダムなテストデータを生成する関数randomizeArrayを作成した。
具体的には、指定した区間([min, max))の一様分布にて配列をランダム化する。

疑似乱数であるstd::mt19937_64を使っているため同一環境での再現性あり。
ただし、一様分布生成std::uniform_real_distributionの実装が環境依存であるため、異なる環境での再現性は保証されない。
コンパイルにはC++11オプションの指定が必要。

#include <iostream>
#include <fstream>
#include <random>

template<typename T>
void randomizeArray
(
  T *X,
  const int n,
  T max = 1.0,
  T min = -1.0,
  int seed = 0
)
{
  static std::mt19937_64 mt(seed);
  std::uniform_real_distribution<> dist(min, max);
  for (int i=0; i<n; ++i)
  {
    X[i] = static_cast<T>(dist(mt));
  }
}

template<typename T>
void printMat
(
  T *X,
  const int m,
  const int n,
  std::ostream& os = std::cout
)
{
  for (int i = 0; i < m-1; ++i)
  {
    for (int j = 0; j < n; ++j)
    {
      os << X[i*n+j] << ",";
    }
    os << std::endl;
  }
  for (int j = 0; j < n-1; ++j)
  {
    os << X[(m-1)*n + j] << ",";
  }
  os << X[m*n-1] << std::endl;
}

int main(void)
{
  int M = 5;
  int K = 3;
  int N = 4;

  float *A = new float[M*K];
  float *B = new float[K*N];

  randomizeArray<float>(A, M*K, 100, -100);
  randomizeArray<float>(B, K*N, 100, -100);

  std::cout << "# float A(" << M << "," << K << ")" << std::endl;
  printMat<float>(A, M, K);
  std::cout << "# float B(" << K << "," << N << ")" << std::endl;
  printMat<float>(B, K, N);

  int *A_ = new int[M*K];
  int *B_ = new int[K*N];

  std::cout << "# int A_(" << M << "," << K << ")" << std::endl;
  randomizeArray<int>(A_, M*K, 100, -100);
  std::cout << "# int B_(" << K << "," << N << ")" << std::endl;
  randomizeArray<int>(B_, K*N, 100, -100);

  printMat<int>(A_, M, K);
  printMat<int>(B_, K, N);

  return 0;
}

出力は以下の通り。

# float A(5,3)
-68.0413,98.429,-92.0862,
19.4989,8.45699,-88.568,
26.3057,-15.2859,68.4521,
81.2603,-15.3704,31.1052,
86.0862,-31.1229,-49.077
# float B(3,4)
-11.0658,58.0379,39.0841,11.5361,
-42.5139,-70.8368,15.8528,12.9099,
-70.7164,-69.9669,-96.0132,10.8815
# int A_(5,3)
-68,98,-92,
19,8,-88,
26,-15,68,
81,-15,31,
86,-31,-49
# int B_(3,4)
-11,58,39,11,
-42,-70,15,12,
-70,-69,-96,10

std::mt19937_64にstatic修飾子を付加することで、randomizeArrayのコール毎に異なる値が出力される。配列A、Bで異なる乱数列が生成されている。

ただし、テンプレート引数が異なる場合、内部で同じ乱数列が生成されるため、同じ数値を異なる型でキャストされた値が出力される。配列AとA、BとBはそれぞれ同じ乱数列をfloat、intでキャストした値が生成されている。