最終更新日時: 2025年07月12日 02時16分44秒 (JST)
Koichi Murase が更新

履歴 編集

class template
<random>

# std::discard_block_engine(C++11)

    namespace std {
      template <class Engine, size_t p, size_t r>
      class discard_block_engine;

      using ranlux24 = …;
      using ranlux48 = …;
    }

## 概要

`discard_block_engine`クラスは、乱数生成エンジンが生成する乱数を調整し、捨てるブロックと使用するブロックに分ける生成器アダプタである。
テンプレートパラメータ`p`はブロックの全体サイズ、`r`は使用するブロックサイズである。`p - r`が破棄するブロックサイズとなる。

この生成器アダプタは、標準内においては`subtract_with_carry_engine`クラスと組み合わせて、RANLUX(LUXury RANdom numbers)法を実装するために使われる。RANLUX法は、重複のない独立した乱数列を生成することで知られている。

## 要件

`0 < r`かつ`r <= p`であること。

## メンバ関数

### 構築・シード

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++11
`~discard_block_engine() = default;` | デストラクタ | C++11
`seed` | シードを設定する | C++11

### 生成

名前 | 説明 | 対応バージョン
--- | --- | ---
`operator()` | 乱数を生成する | C++11
`discard` | 指定した回数だけ乱数を生成し、内部状態を進める | C++11

### エンジンの特性

名前 | 説明 | 対応バージョン
--- | --- | ---
`base` | 元となる乱数生成器を取得する | C++11

## 静的メンバ関数

### エンジンの特性

名前 | 説明 | 対応バージョン
--- | --- | ---
`min` | 生成し得る値の最小値を取得する | C++11
`max` | 生成し得る値の最大値を取得する | C++11

## メンバ型

型 | 説明 | 対応バージョン
--- | --- | ---
`result_type` | 擬似乱数生成結果型 `typename Engine::result_type`。 | C++11

## メンバ定数

定数 | 説明 | 対応バージョン
--- | --- | ---
`static constexpr size_t block_size` | ブロックサイズ。テンプレートパラメータ`p`。 | C++11
`static constexpr size_t used_size` | 使用するブロックサイズ。テンプレートパラメータ`r`。 | C++11

## 非メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`operator==` | 等値比較 | C++11
`operator!=` | 非等値比較 | C++11
`operator<<` | ストリームへの出力 | C++11
`operator>>` | ストリームからの入力 | C++11

## 例

    #include <iostream>
    #include <random>

    // [0, 1, 2, 3.....)のように、単にカウンタを進めていくだけのエセ乱数生成器
    class sequence_generator {
      size_t value_ = 0;
    public:
      using result_type = size_t;

      sequence_generator(result_type = 0) {}
      void seed(result_type) {}

      constexpr static result_type min() { return 0; }
      constexpr static result_type max() { return 65537; }

      result_type operator()()
      {
        return value_++;
      }

      void discard(unsigned long long z)
      {
        for (size_t i = 0; i < z; ++i) {
          (*this)();
        }
      }
    };

    int main()
    {
      // ブロック全体のサイズp : 3
      // 使用するサイズr : 2
      // 破棄するサイズ : p - r == 1
      std::discard_block_engine<sequence_generator, 3, 2> engine;

      for (int i = 0; i < 10; ++i) {
        std::cout << engine() << std::endl;
      }
    }

### 出力

    0
    1
    3
    4
    6
    7
    9
    10
    12
    13

出力結果から、使用するブロック(0, 1)が選択されたあと、破棄するブロック(2)が出力されず、そのあと使用するブロック、破棄するブロック・・・のようにサイクルしていることがわかる。

## バージョン

### 言語

- C++11

### 処理系

- Clang:
- GCC: 4.7.2 ✅
- ICC:
- Visual C++: