なぜuniform_int_distribution <uintmax_t>は62ビット数では動作しますが、63または64ビットでは動作しませんか?

I'm having difficulty understanding why this code, an attempt to use the new header in C++11, is correctly generating random numbers in [0, 2**62 - 1] but not [0, 2**63 - 1] or [0, 2**64 - 1].

#include 
#include 
#include 
#include 
#include 

static std::mt19937 engine;//Mersenne twister MT19937

void print_n_random_bits (unsigned int n);

int main (void) {
  engine.seed(time(0));
  print_n_random_bits(64);
  print_n_random_bits(63);
  print_n_random_bits(62);
  return 0;
}

void print_n_random_bits (unsigned int n)
{
  uintmax_t max;

  if (n == 8 * sizeof(uintmax_t)) {
    max = 0;
  } else {
    max = 1;
    max <<= n;
  }
  --max;

  std::uniform_int_distribution distribution(0, max);

  std::cout << n << " bits, max: " << max << std::endl;
  std::cout << distribution(engine) << std::endl;
}

さて、もう少し掘り下げていくと、正しい動作をしている std :: mt19937_64 が明らかになりましたが、62ビットの数字で動作するものが64ビットのもので動作しないのはなぜですか?

Edit: Sorry, I didn't even specify the problem. The problem is that for 63 and 64 bit max values, the output is consistently a number in the range [0, 2**32 - 1], e.g.:

% ./rand                       
64 bits, max: 18446744073709551615
1803260654
63 bits, max: 9223372036854775807
3178301365
62 bits, max: 4611686018427387903
2943926730538475327

% ./rand                                
64 bits, max: 18446744073709551615
1525658116
63 bits, max: 9223372036854775807
2093351390
62 bits, max: 4611686018427387903
1513326512211312260

% ./rand                                                       
64 bits, max: 18446744073709551615
884934896
63 bits, max: 9223372036854775807
683284805
62 bits, max: 4611686018427387903
2333288494897435595       

Edit 2: I'm using clang++ (Apple clang version 2.1 (tags/Apple/clang-163.7.1)) and "libc++". I can't easily test the above with GCC as my version doesn't have c++0x support.

20
多分それだけの悪い幸運を考えてください:)
追加された 著者 Dani,
GCC4.6.1では、3つのテスト(62/63/64ビット)すべてが64ビット値を返します。
追加された 著者 Mike Seymour,
GCC4.5.1では、3つのテスト(62/63/64ビット)すべてが32ビット値を返します。 ideone.com/3GZ9S
追加された 著者 interjay,
予期せぬことは正確に何をしているのですか?つまり、あなたの期待と異なる結果をあなたにどのくらい提示しているのですか?
追加された 著者 andand,
また、どの標準ライブラリ実装を使用していますか?
追加された 著者 Fanael,

2 答え

libc ++にバグが見つかりました。ありがとう!!!

私はトランクリビジョン143104のヒントに次の修正をコミットしました:

Index: include/algorithm
===================================================================
--- include/algorithm   (revision 143102)
+++ include/algorithm   (working copy)
@@ -2548,7 +2548,7 @@
         {
             __u = __e_() - _Engine::min();
         } while (__u >= __y0_);
-        if (__w0_ < _EDt)
+        if (__w0_ < _WDt)
             _S <<= __w0_;
         else
             _S = 0;
@@ -2561,7 +2561,7 @@
         {
             __u = __e_() - _Engine::min();
         } while (__u >= __y1_);
-        if (__w0_ < _EDt - 1)
+        if (__w0_ < _WDt - 1)
             _S <<= __w0_ + 1;
         else
             _S = 0;

この修正では、バイナリlibc ++。dylibの再コンパイルは必要ありません。

23
追加された
知りません。このアルゴリズムは、independent_bits_engineの標準仕様で指定されています。
追加された 著者 Howard Hinnant,
libc ++で使用されているアルゴリズムには、それを読むための既知の名前がありますか?
追加された 著者 Mateusz Drost,
うわー、速い仕事! Howardに感謝します。
追加された 著者 Qchmqs,

std :: mt19937 は32ビット版であるため、次の番号を生成するときに「作業空間」でどのビットが重要かどうかを前提にしている可能性があります。これにより、最後の2ビットを含む可能性のある数を生成するときにオーバーフローが生じます。実際のディストリビューションは、32ビットエンジンで 2 ** 32 - 1 よりも高い最大数では実際には一様ではないことがわかります。

0
追加された
mt19937 が32ビットの数値を返す場合でも、62/63/64ビットの数値を作成するために uniform_int_distribution
追加された 著者 interjay,
これについてはわかりません。簡単な調査によれば、分布は、1,000,000個の生成された整数に基づいて、 2 ** 62 - 1 の最大値を持つ均一または近似値であることが示唆されています。
追加された 著者 Qchmqs,