1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
43 /* ////////////////////////////////////////////////////////////////////
45 // Filling CvMat/IplImage instances with random numbers
54 ///////////////////////////// Functions Declaration //////////////////////////////////////
57 Multiply-with-carry generator is used here:
58 temp = ( A*X(n) + carry )
59 X(n+1) = temp mod (2^32)
63 #define RNG_NEXT(x) ((uint64)(unsigned)(x)*RNG::A + ((x) >> 32))
65 /***************************************************************************************\
66 * Pseudo-Random Number Generators (PRNGs) *
67 \***************************************************************************************/
69 template<typename T> static void
70 RandBits_( Mat& _arr, uint64* state, const void* _param )
73 const int* param = (const int*)_param;
74 int small_flag = (param[12]|param[13]|param[14]|param[15]) <= 255;
75 Size size = getContinuousSize(_arr,_arr.channels());
77 for( int y = 0; y < size.height; y++ )
79 T* arr = (T*)(_arr.data + _arr.step*y);
85 for( i = 0; i <= size.width - 4; i += 4 )
89 temp = RNG_NEXT(temp);
90 t0 = ((int)temp & p[i + 12]) + p[i];
91 temp = RNG_NEXT(temp);
92 t1 = ((int)temp & p[i + 13]) + p[i+1];
93 arr[i] = saturate_cast<T>(t0);
94 arr[i+1] = saturate_cast<T>(t1);
96 temp = RNG_NEXT(temp);
97 t0 = ((int)temp & p[i + 14]) + p[i+2];
98 temp = RNG_NEXT(temp);
99 t1 = ((int)temp & p[i + 15]) + p[i+3];
100 arr[i+2] = saturate_cast<T>(t0);
101 arr[i+3] = saturate_cast<T>(t1);
112 for( i = 0; i <= size.width - 4; i += 4 )
116 temp = RNG_NEXT(temp);
118 t0 = (t & p[i + 12]) + p[i];
119 t1 = ((t >> 8) & p[i + 13]) + p[i+1];
120 arr[i] = saturate_cast<T>(t0);
121 arr[i+1] = saturate_cast<T>(t1);
123 t0 = ((t >> 16) & p[i + 14]) + p[i + 2];
124 t1 = ((t >> 24) & p[i + 15]) + p[i + 3];
125 arr[i+2] = saturate_cast<T>(t0);
126 arr[i+3] = saturate_cast<T>(t1);
136 for( ; i < size.width; i++ )
139 temp = RNG_NEXT(temp);
141 t0 = ((int)temp & p[i + 12]) + p[i];
142 arr[i] = saturate_cast<T>(t0);
150 template<typename T, typename PT> static void
151 Randi_( Mat& _arr, uint64* state, const void* _param )
153 uint64 temp = *state;
154 const PT* param = (const PT*)_param;
155 Size size = getContinuousSize(_arr,_arr.channels());
157 for( int y = 0; y < size.height; y++ )
159 T* arr = (T*)(_arr.data + _arr.step*y);
163 for( i = 0; i <= size.width - 4; i += 4 )
166 temp = RNG_NEXT(temp);
167 f0 = (int)temp * p[i+12] + p[i];
168 temp = RNG_NEXT(temp);
169 f1 = (int)temp * p[i+13] + p[i+1];
170 arr[i] = saturate_cast<T>(cvFloor(f0));
171 arr[i+1] = saturate_cast<T>(cvFloor(f1));
173 temp = RNG_NEXT(temp);
174 f0 = (int)temp * p[i+14] + p[i+2];
175 temp = RNG_NEXT(temp);
176 f1 = (int)temp * p[i+15] + p[i+3];
177 arr[i+2] = saturate_cast<T>(cvFloor(f0));
178 arr[i+3] = saturate_cast<T>(cvFloor(f1));
187 for( ; i < size.width; i++ )
189 temp = RNG_NEXT(temp);
190 arr[i] = saturate_cast<T>(cvFloor((int)temp * p[i + 12] + p[i]));
198 static void Randf_( Mat& _arr, uint64* state, const void* _param )
200 uint64 temp = *state;
201 const float* param = (const float*)_param;
202 Size size = getContinuousSize(_arr,_arr.channels());
204 for( int y = 0; y < size.height; y++ )
206 float* arr = (float*)(_arr.data + _arr.step*y);
208 const float* p = param;
209 for( i = 0; i <= size.width - 4; i += 4 )
213 temp = RNG_NEXT(temp);
214 f0 = (int)temp*p[i+12] + p[i];
215 temp = RNG_NEXT(temp);
216 f1 = (int)temp*p[i+13] + p[i+1];
217 arr[i] = f0; arr[i+1] = f1;
219 temp = RNG_NEXT(temp);
220 f0 = (int)temp*p[i+14] + p[i+2];
221 temp = RNG_NEXT(temp);
222 f1 = (int)temp*p[i+15] + p[i+3];
223 arr[i+2] = f0; arr[i+3] = f1;
232 for( ; i < size.width; i++ )
234 temp = RNG_NEXT(temp);
235 arr[i] = (int)temp*p[i+12] + p[i];
244 Randd_( Mat& _arr, uint64* state, const void* _param )
246 uint64 temp = *state;
247 const double* param = (const double*)_param;
248 Size size = getContinuousSize(_arr,_arr.channels());
251 for( int y = 0; y < size.height; y++ )
253 double* arr = (double*)(_arr.data + _arr.step*y);
255 const double* p = param;
257 for( i = 0; i <= size.width - 4; i += 4 )
261 temp = RNG_NEXT(temp);
262 v = (temp >> 32)|(temp << 32);
263 f0 = v*p[i+12] + p[i];
264 temp = RNG_NEXT(temp);
265 v = (temp >> 32)|(temp << 32);
266 f1 = v*p[i+12] + p[i];
267 arr[i] = f0; arr[i+1] = f1;
269 temp = RNG_NEXT(temp);
270 v = (temp >> 32)|(temp << 32);
271 f0 = v*p[i+12] + p[i];
272 temp = RNG_NEXT(temp);
273 v = (temp >> 32)|(temp << 32);
274 f1 = v*p[i+12] + p[i];
275 arr[i+2] = f0; arr[i+3] = f1;
284 for( ; i < size.width; i++ )
286 temp = RNG_NEXT(temp);
287 v = (temp >> 32)|(temp << 32);
288 arr[i] = v*p[i+12] + p[i];
297 The code below implements the algorithm described in
298 "The Ziggurat Method for Generating Random Variables"
299 by Marsaglia and Tsang, Journal of Statistical Software.
302 Randn_0_1_32f_C1R( float* arr, int len, uint64* state )
304 const float r = 3.442620f; // The start of the right tail
305 const float rng_flt = 2.3283064365386962890625e-10f; // 2^-32
306 static unsigned kn[127];
307 static float wn[128], fn[128];
308 uint64 temp = *state;
309 static bool initialized=false;
314 const double m1 = 2147483648.0;
315 double dn = 3.442619855899, tn = dn, vn = 9.91256303526217e-3;
318 double q = vn/std::exp(-.5*dn*dn);
319 kn[0] = (unsigned)((dn/q)*m1);
322 wn[0] = (float)(q/m1);
323 wn[127] = (float)(dn/m1);
326 fn[127] = (float)std::exp(-.5*dn*dn);
330 dn = std::sqrt(-2.*std::log(vn/dn+std::exp(-.5*dn*dn)));
331 kn[i+1] = (unsigned)((dn/tn)*m1);
333 fn[i] = (float)std::exp(-.5*dn*dn);
334 wn[i] = (float)(dn/m1);
339 for( i = 0; i < len; i++ )
345 temp = RNG_NEXT(temp);
348 if( (unsigned)std::abs(hz) < kn[iz] )
350 if( iz == 0) // iz==0, handles the base strip
354 x = (unsigned)temp*rng_flt;
355 temp = RNG_NEXT(temp);
356 y = (unsigned)temp*rng_flt;
357 temp = RNG_NEXT(temp);
358 x = (float)(-std::log(x+FLT_MIN)*0.2904764);
359 y = (float)-std::log(y+FLT_MIN);
361 while( y + y < x*x );
362 x = hz > 0 ? r + x : -r - x;
365 // iz > 0, handle the wedges of other strips
366 y = (unsigned)temp*rng_flt;
367 temp = RNG_NEXT(temp);
368 if( fn[iz] + y*(fn[iz - 1] - fn[iz]) < std::exp(-.5*x*x) )
377 template<typename T, typename PT> static void
378 Randn_( Mat& _arr, uint64* state, const void* _param )
380 const int RAND_BUF_SIZE = 96;
381 float buffer[RAND_BUF_SIZE];
382 const PT* param = (const PT*)_param;
383 Size size = getContinuousSize(_arr, _arr.channels());
385 for( int y = 0; y < size.height; y++ )
387 T* arr = (T*)(_arr.data + _arr.step*y);
388 int i, j, len = RAND_BUF_SIZE;
389 for( i = 0; i < size.width; i += RAND_BUF_SIZE )
394 if( i + len > size.width )
395 len = size.width - i;
397 Randn_0_1_32f_C1R( buffer, len, state );
399 for( j = 0; j <= len - 4; j += 4 )
403 f0 = buffer[j]*p[j+12] + p[j];
404 f1 = buffer[j+1]*p[j+13] + p[j+1];
405 arr[i+j] = saturate_cast<T>(f0);
406 arr[i+j+1] = saturate_cast<T>(f1);
408 f0 = buffer[j+2]*p[j+14] + p[j+2];
409 f1 = buffer[j+3]*p[j+15] + p[j+3];
410 arr[i+j+2] = saturate_cast<T>(f0);
411 arr[i+j+3] = saturate_cast<T>(f1);
420 for( ; j < len; j++ )
421 arr[i+j] = saturate_cast<T>(buffer[j]*p[j+12] + p[j]);
427 typedef void (*RandFunc)(Mat& dst, uint64* state, const void* param);
429 void RNG::fill( Mat& mat, int disttype, const Scalar& param1, const Scalar& param2 )
431 static RandFunc rngtab[3][8] =
438 RandBits_<int>, 0, 0, 0},
440 {Randi_<uchar,float>,
442 Randi_<ushort,float>,
447 {Randn_<uchar,float>,
449 Randn_<ushort,float>,
453 Randn_<double,double>, 0}
456 int depth = mat.depth(), channels = mat.channels();
457 double dparam[2][12];
460 void* param = dparam;
461 int i, fast_int_mode = 0;
464 CV_Assert( channels <= 4 );
466 if( disttype == UNIFORM )
468 if( depth <= CV_32S )
470 for( i = 0, fast_int_mode = 1; i < channels; i++ )
472 int t0 = iparam[0][i] = cvCeil(param1.val[i]);
473 int t1 = iparam[1][i] = cvFloor(param2.val[i]) - t0;
474 double diff = param1.val[i] - param2.val[i];
476 fast_int_mode &= INT_MIN <= diff && diff <= INT_MAX && (t1 & (t1 - 1)) == 0;
482 for( i = 0; i < channels; i++ )
487 int t0 = iparam[0][i - channels];
488 int t1 = iparam[1][i - channels];
494 func = rngtab[0][depth];
499 double scale = depth == CV_64F ?
500 5.4210108624275221700372640043497e-20 : // 2**-64
501 2.3283064365386962890625e-10; // 2**-32
503 // for each channel i compute such dparam[0][i] & dparam[1][i],
504 // so that a signed 32/64-bit integer X is transformed to
505 // the range [param1.val[i], param2.val[i]) using
506 // dparam[1][i]*X + dparam[0][i]
507 for( i = 0; i < channels; i++ )
509 double t0 = param1.val[i];
510 double t1 = param2.val[i];
511 dparam[0][i] = (t1 + t0)*0.5;
512 dparam[1][i] = (t1 - t0)*scale;
515 func = rngtab[1][depth];
519 else if( disttype == CV_RAND_NORMAL )
521 for( i = 0; i < channels; i++ )
523 double t0 = param1.val[i];
524 double t1 = param2.val[i];
530 func = rngtab[2][depth];
534 CV_Error( CV_StsBadArg, "Unknown distribution type" );
538 for( i = channels; i < 12; i++ )
540 double t0 = dparam[0][i - channels];
541 double t1 = dparam[1][i - channels];
547 if( depth != CV_64F )
549 for( i = 0; i < 12; i++ )
551 fparam[0][i] = (float)dparam[0][i];
552 fparam[1][i] = (float)dparam[1][i];
558 CV_Assert( func != 0);
560 func( mat, &state, param );
566 # define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
568 static DWORD tlsRNGKey = TLS_OUT_OF_INDEXES;
570 void deleteThreadRNGData()
572 if( tlsRNGKey != TLS_OUT_OF_INDEXES )
573 delete (RNG*)TlsGetValue( tlsRNGKey );
578 if( tlsRNGKey == TLS_OUT_OF_INDEXES )
580 tlsRNGKey = TlsAlloc();
581 CV_Assert(tlsRNGKey != TLS_OUT_OF_INDEXES);
583 RNG* rng = (RNG*)TlsGetValue( tlsRNGKey );
587 TlsSetValue( tlsRNGKey, rng );
594 static pthread_key_t tlsRNGKey = 0;
596 static void deleteRNG(void* data)
605 pthread_key_create(&tlsRNGKey, deleteRNG);
606 CV_Assert(tlsRNGKey != 0);
608 RNG* rng = (RNG*)pthread_getspecific(tlsRNGKey);
612 pthread_setspecific(tlsRNGKey, rng);
619 template<typename T> static void
620 randShuffle_( Mat& _arr, RNG& rng, double iterFactor )
622 int sz = _arr.rows*_arr.cols, iters = cvRound(iterFactor*sz);
623 if( _arr.isContinuous() )
625 T* arr = (T*)_arr.data;
626 for( int i = 0; i < iters; i++ )
628 int j = (unsigned)rng % sz, k = (unsigned)rng % sz;
629 std::swap( arr[j], arr[k] );
634 uchar* data = _arr.data;
635 size_t step = _arr.step;
636 int cols = _arr.cols;
637 for( int i = 0; i < iters; i++ )
639 int j1 = (unsigned)rng % sz, k1 = (unsigned)rng % sz;
640 int j0 = j1/cols, k0 = k1/cols;
641 j1 -= j0*cols; k1 -= k0*cols;
642 std::swap( ((T*)(data + step*j0))[j1], ((T*)(data + step*k0))[k1] );
647 typedef void (*RandShuffleFunc)( Mat& dst, RNG& rng, double iterFactor );
649 void randShuffle( Mat& dst, double iterFactor, RNG* _rng )
651 RandShuffleFunc tab[] =
654 randShuffle_<uchar>, // 1
655 randShuffle_<ushort>, // 2
656 randShuffle_<Vec<uchar,3> >, // 3
657 randShuffle_<int>, // 4
659 randShuffle_<Vec<ushort,3> >, // 6
661 randShuffle_<int64>, // 8
663 randShuffle_<Vec<int,3> >, // 12
665 randShuffle_<Vec<int64,2> >, // 16
667 randShuffle_<Vec<int64,3> >, // 24
669 randShuffle_<Vec<int64,4> > // 32
672 RNG& rng = _rng ? *_rng : theRNG();
673 CV_Assert( dst.elemSize() <= 32 );
674 RandShuffleFunc func = tab[dst.elemSize()];
675 CV_Assert( func != 0 );
676 func( dst, rng, iterFactor );
682 cvRandArr( CvRNG* _rng, CvArr* arr, int disttype, CvScalar param1, CvScalar param2 )
684 cv::Mat mat = cv::cvarrToMat(arr);
685 // !!! this will only work for current 64-bit MWC RNG !!!
686 cv::RNG& rng = _rng ? (cv::RNG&)*_rng : cv::theRNG();
687 rng.fill(mat, disttype == CV_RAND_NORMAL ?
688 cv::RNG::NORMAL : cv::RNG::UNIFORM, param1, param2 );
691 CV_IMPL void cvRandShuffle( CvArr* arr, CvRNG* _rng, double iter_factor )
693 cv::Mat dst = cv::cvarrToMat(arr);
694 cv::RNG& rng = _rng ? (cv::RNG&)*_rng : cv::theRNG();
695 cv::randShuffle( dst, iter_factor, &rng );