ASSERT_EQ(param1, -9);
ASSERT_EQ(param2, 2);
}
+
+namespace {
+
+class RandRowFillParallelLoopBody : public cv::ParallelLoopBody
+{
+public:
+ RandRowFillParallelLoopBody(Mat& dst) : dst_(dst) {}
+ ~RandRowFillParallelLoopBody() {}
+ void operator()(const cv::Range& r) const
+ {
+ cv::RNG rng = cv::theRNG(); // copy state
+ for (int y = r.start; y < r.end; y++)
+ {
+ cv::theRNG() = cv::RNG(rng.state + y); // seed is based on processed row
+ cv::randu(dst_.row(y), Scalar(-100), Scalar(100));
+ }
+ // theRNG() state is changed here (but state collision has low probability, so we don't check this)
+ }
+protected:
+ Mat& dst_;
+};
+
+TEST(Core_Rand, parallel_for_stable_results)
+{
+ cv::RNG rng = cv::theRNG(); // save rng state
+ Mat dst1(1000, 100, CV_8SC1);
+ parallel_for_(cv::Range(0, dst1.rows), RandRowFillParallelLoopBody(dst1));
+
+ cv::theRNG() = rng; // restore rng state
+ Mat dst2(1000, 100, CV_8SC1);
+ parallel_for_(cv::Range(0, dst2.rows), RandRowFillParallelLoopBody(dst2));
+
+ ASSERT_EQ(0, countNonZero(dst1 != dst2));
+}
+
+} // namespace