|
|
|
@ -382,3 +382,39 @@ TEST(Core_Rand, Regression_Stack_Corruption) |
|
|
|
|
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
|
|
|
|
|