[libcxx] r339969 - [libc++] Use correct rand.eng.mers all-zeroes seed sequence fallback

Hubert Tong via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 16 16:56:54 PDT 2018


Author: hubert.reinterpretcast
Date: Thu Aug 16 16:56:54 2018
New Revision: 339969

URL: http://llvm.org/viewvc/llvm-project?rev=339969&view=rev
Log:
[libc++] Use correct rand.eng.mers all-zeroes seed sequence fallback

Summary:
When a seed sequence would lead to having no non-zero significant bits
in the initial state of a `mersenne_twister_engine`, the fallback is to
flip the most significant bit of the first value that appears in the
textual representation of the initial state.

rand.eng.mers describes this as setting the value to be 2 to the power
of one less than w; the previous value encoded in the implementation,
namely one less than "2 to the power of w", is replaced by the correct
value in this patch.

Reviewers: mclow.lists, EricWF, jasonliu

Reviewed By: mclow.lists

Subscribers: mclow.lists, jasonliu, EricWF, christof, ldionne, cfe-commits

Differential Revision: https://reviews.llvm.org/D50736

Added:
    libcxx/trunk/test/std/numerics/rand/rand.eng/rand.eng.mers/ctor_sseq_all_zero.pass.cpp
Modified:
    libcxx/trunk/include/random

Modified: libcxx/trunk/include/random
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/random?rev=339969&r1=339968&r2=339969&view=diff
==============================================================================
--- libcxx/trunk/include/random (original)
+++ libcxx/trunk/include/random Thu Aug 16 16:56:54 2018
@@ -2337,7 +2337,7 @@ mersenne_twister_engine<_UIntType, __w,
         for (size_t __i = 1; __i < __n; ++__i)
             if (__x_[__i] != 0)
                 return;
-        __x_[0] = _Max;
+        __x_[0] = result_type(1) << (__w - 1);
     }
 }
 
@@ -2363,7 +2363,7 @@ mersenne_twister_engine<_UIntType, __w,
         for (size_t __i = 1; __i < __n; ++__i)
             if (__x_[__i] != 0)
                 return;
-        __x_[0] = _Max;
+        __x_[0] = result_type(1) << (__w - 1);
     }
 }
 

Added: libcxx/trunk/test/std/numerics/rand/rand.eng/rand.eng.mers/ctor_sseq_all_zero.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/numerics/rand/rand.eng/rand.eng.mers/ctor_sseq_all_zero.pass.cpp?rev=339969&view=auto
==============================================================================
--- libcxx/trunk/test/std/numerics/rand/rand.eng/rand.eng.mers/ctor_sseq_all_zero.pass.cpp (added)
+++ libcxx/trunk/test/std/numerics/rand/rand.eng/rand.eng.mers/ctor_sseq_all_zero.pass.cpp Thu Aug 16 16:56:54 2018
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <random>
+
+// template <class UIntType, size_t w, size_t n, size_t m, size_t r,
+//           UIntType a, size_t u, UIntType d, size_t s,
+//           UIntType b, size_t t,
+//           UIntType c, size_t l, UIntType f>
+// class mersenne_twister_engine;
+
+// template <class Sseq> explicit mersenne_twister_engine(Sseq &q);
+//
+//     [ ... ] Finally, if the most significant $w-r$ bits of $X_{-n}$ are zero,
+//     and if each of the other resulting $X_i$ is $0$, changes $X_{-n}$ to
+//     $ 2^{w-1} $.
+
+#include <random>
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#if TEST_STD_VER >= 11
+#include <initializer_list>
+#endif
+
+struct all_zero_seed_seq {
+  typedef unsigned int result_type;
+
+  all_zero_seed_seq() {}
+
+  template <typename InputIterator>
+  all_zero_seed_seq(InputIterator, InputIterator) {}
+#if TEST_STD_VER >= 11
+  all_zero_seed_seq(std::initializer_list<result_type>) {}
+#endif
+
+  template <typename RandomAccessIterator>
+  void generate(RandomAccessIterator rb, RandomAccessIterator re) {
+    std::fill(rb, re, 0u);
+  }
+
+  std::size_t size() const { return 0u; }
+  template <typename OutputIterator> void param(OutputIterator) const {}
+};
+
+template <typename result_type, std::size_t word_size>
+void test(void) {
+  const std::size_t state_size = 1u;
+  const std::size_t shift_size = 1u;
+  const std::size_t tempering_l = word_size;
+
+  all_zero_seed_seq q;
+  std::mersenne_twister_engine<result_type, word_size, state_size,
+                               shift_size,
+                               0u,
+                               0x0,
+                               0u, 0x0, 0u, 0x0, 0u, 0x0,
+                               tempering_l,
+                               0u>
+      e(q);
+
+  const result_type Xneg1 = result_type(1) << (word_size - 1);
+  const result_type Y = Xneg1;
+  const result_type X0 = Xneg1 ^ (Y >> 1);
+  assert(e() == X0);
+}
+
+int main() {
+  // Test for k == 1: word_size <= 32.
+  test<unsigned short, 3u>();
+
+  // Test for k == 2: (32 < word_size <= 64).
+  test<unsigned long long, 33u>();
+}




More information about the cfe-commits mailing list