_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first != __last)
- for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
- {
- // XXX rand() % N is not uniformly distributed
- _RandomAccessIterator __j = __first
- + std::rand() % ((__i - __first) + 1);
- if (__i != __j)
- std::iter_swap(__i, __j);
- }
+ if (__first == __last)
+ return;
+
+#if RAND_MAX < __INT_MAX__
+ if (__builtin_expect((__last - __first) >= RAND_MAX / 4, 0))
+ {
+ // Use a xorshift implementation seeded by two calls to rand()
+ // instead of using rand() for all the random numbers needed.
+ unsigned __xss
+ = (unsigned)std::rand() ^ ((unsigned)std::rand() << 15);
+ for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
+ {
+ __xss += !__xss;
+ __xss ^= __xss << 13;
+ __xss ^= __xss >> 17;
+ __xss ^= __xss << 5;
+ _RandomAccessIterator __j = __first
+ + (__xss % ((__i - __first) + 1));
+ if (__i != __j)
+ std::iter_swap(__i, __j);
+ }
+ return;
+ }
+#endif
+
+ for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
+ {
+ // XXX rand() % N is not uniformly distributed
+ _RandomAccessIterator __j = __first
+ + (std::rand() % ((__i - __first) + 1));
+ if (__i != __j)
+ std::iter_swap(__i, __j);
+ }
}
/**
--- /dev/null
+// { dg-do run }
+// { dg-options "-Wno-deprecated-declarations" }
+
+// Bug 88935 std::random_shuffle does not work if the sequence
+// is longer than RAND_MAX elements
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ const std::size_t N = 30000;
+ std::vector<unsigned char> v(N, (unsigned char)0);
+ std::fill(v.begin() + (N / 5 * 4), v.end(), (unsigned char)1);
+ std::random_shuffle(v.begin(), v.end());
+ double sum = 0;
+ for (std::size_t i = 0; i < v.size(); ++i)
+ {
+ sum += v[i];
+ if (i > 0 && i % (N / 100) == 0)
+ VERIFY( (sum / i) < 0.3 );
+ }
+}