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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
42 /* ////////////////////////////////////////////////////////////////////
44 // Filling CvMat/IplImage instances with random numbers
51 ///////////////////////////// Functions Declaration //////////////////////////////////////
54 Multiply-with-carry generator is used here:
55 temp = ( A*X(n) + carry )
56 X(n+1) = temp mod (2^32)
59 #define ICV_RNG_NEXT(x) ((uint64)(unsigned)(x)*1554115554 + ((x) >> 32))
60 #define ICV_CVT_FLT(x) (((unsigned)(x) >> 9)|CV_1F)
61 #define ICV_1D CV_BIG_INT(0x3FF0000000000000)
62 #define ICV_CVT_DBL(x) (((uint64)(unsigned)(x) << 20)|((x) >> 44)|ICV_1D)
64 /***************************************************************************************\
65 * Pseudo-Random Number Generators (PRNGs) *
66 \***************************************************************************************/
68 #define ICV_IMPL_RAND_BITS( flavor, arrtype, cast_macro ) \
69 static CvStatus CV_STDCALL \
70 icvRandBits_##flavor##_C1R( arrtype* arr, int step, CvSize size, \
71 uint64* state, const int* param ) \
73 uint64 temp = *state; \
74 int small_flag = (param[12]|param[13]|param[14]|param[15]) <= 255; \
75 step /= sizeof(arr[0]); \
77 for( ; size.height--; arr += step ) \
80 const int* p = param; \
84 for( i = 0; i <= size.width - 4; i += 4 ) \
88 temp = ICV_RNG_NEXT(temp); \
89 t0 = ((unsigned)temp & p[i + 12]) + p[i]; \
90 temp = ICV_RNG_NEXT(temp); \
91 t1 = ((unsigned)temp & p[i + 13]) + p[i+1]; \
92 arr[i] = cast_macro((int)t0); \
93 arr[i+1] = cast_macro((int)t1); \
95 temp = ICV_RNG_NEXT(temp); \
96 t0 = ((unsigned)temp & p[i + 14]) + p[i+2]; \
97 temp = ICV_RNG_NEXT(temp); \
98 t1 = ((unsigned)temp & p[i + 15]) + p[i+3]; \
99 arr[i+2] = cast_macro((int)t0); \
100 arr[i+3] = cast_macro((int)t1); \
111 for( i = 0; i <= size.width - 4; i += 4 ) \
113 unsigned t0, t1, t; \
115 temp = ICV_RNG_NEXT(temp); \
116 t = (unsigned)temp; \
117 t0 = (t & p[i + 12]) + p[i]; \
118 t1 = ((t >> 8) & p[i + 13]) + p[i+1]; \
119 arr[i] = cast_macro((int)t0); \
120 arr[i+1] = cast_macro((int)t1); \
122 t0 = ((t >> 16) & p[i + 14]) + p[i + 2]; \
123 t1 = ((t >> 24) & p[i + 15]) + p[i + 3]; \
124 arr[i+2] = cast_macro((int)t0); \
125 arr[i+3] = cast_macro((int)t1); \
135 for( ; i < size.width; i++ ) \
138 temp = ICV_RNG_NEXT(temp); \
140 t0 = ((unsigned)temp & p[i + 12]) + p[i]; \
141 arr[i] = cast_macro((int)t0); \
150 #define ICV_IMPL_RAND( flavor, arrtype, worktype, cast_macro1, cast_macro2 )\
151 static CvStatus CV_STDCALL \
152 icvRand_##flavor##_C1R( arrtype* arr, int step, CvSize size, \
153 uint64* state, const double* param ) \
155 uint64 temp = *state; \
156 step /= sizeof(arr[0]); \
158 for( ; size.height--; arr += step ) \
161 const double* p = param; \
163 for( i = 0; i <= size.width - 4; i += 4 ) \
168 temp = ICV_RNG_NEXT(temp); \
169 t0.u = ICV_CVT_FLT(temp); \
170 temp = ICV_RNG_NEXT(temp); \
171 t1.u = ICV_CVT_FLT(temp); \
172 f0 = cast_macro1( t0.f * p[i + 12] + p[i] ); \
173 f1 = cast_macro1( t1.f * p[i + 13] + p[i + 1] ); \
174 arr[i] = cast_macro2(f0); \
175 arr[i+1] = cast_macro2(f1); \
177 temp = ICV_RNG_NEXT(temp); \
178 t0.u = ICV_CVT_FLT(temp); \
179 temp = ICV_RNG_NEXT(temp); \
180 t1.u = ICV_CVT_FLT(temp); \
181 f0 = cast_macro1( t0.f * p[i + 14] + p[i + 2] ); \
182 f1 = cast_macro1( t1.f * p[i + 15] + p[i + 3] ); \
183 arr[i+2] = cast_macro2(f0); \
184 arr[i+3] = cast_macro2(f1); \
193 for( ; i < size.width; i++ ) \
198 temp = ICV_RNG_NEXT(temp); \
199 t0.u = ICV_CVT_FLT(temp); \
200 f0 = cast_macro1( t0.f * p[i + 12] + p[i] ); \
201 arr[i] = cast_macro2(f0); \
210 static CvStatus CV_STDCALL
211 icvRand_64f_C1R( double* arr, int step, CvSize size,
212 uint64* state, const double* param )
214 uint64 temp = *state;
215 step /= sizeof(arr[0]);
217 for( ; size.height--; arr += step )
220 const double* p = param;
222 for( i = 0; i <= size.width - 4; i += 4 )
227 temp = ICV_RNG_NEXT(temp);
228 t0.u = ICV_CVT_DBL(temp);
229 temp = ICV_RNG_NEXT(temp);
230 t1.u = ICV_CVT_DBL(temp);
231 f0 = t0.f * p[i + 12] + p[i];
232 f1 = t1.f * p[i + 13] + p[i + 1];
236 temp = ICV_RNG_NEXT(temp);
237 t0.u = ICV_CVT_DBL(temp);
238 temp = ICV_RNG_NEXT(temp);
239 t1.u = ICV_CVT_DBL(temp);
240 f0 = t0.f * p[i + 14] + p[i + 2];
241 f1 = t1.f * p[i + 15] + p[i + 3];
252 for( ; i < size.width; i++ )
257 temp = ICV_RNG_NEXT(temp);
258 t0.u = ICV_CVT_DBL(temp);
259 f0 = t0.f * p[i + 12] + p[i];
269 /***************************************************************************************\
270 The code below implements algorithm from the paper:
272 G. Marsaglia and W.W. Tsang,
273 The Monty Python method for generating random variables,
274 ACM Transactions on Mathematical Software, Vol. 24, No. 3,
275 Pages 341-350, September, 1998.
276 \***************************************************************************************/
278 static CvStatus CV_STDCALL
279 icvRandn_0_1_32f_C1R( float* arr, int len, uint64* state )
281 uint64 temp = *state;
283 temp = ICV_RNG_NEXT(temp);
285 for( i = 0; i < len; i++ )
287 double x, y, v, ax, bx;
291 x = ((int)temp)*1.167239e-9;
292 temp = ICV_RNG_NEXT(temp);
294 v = 2.8658 - ax*(2.0213 - 0.3605*ax);
295 y = ((unsigned)temp)*2.328306e-10;
296 temp = ICV_RNG_NEXT(temp);
298 if( y < v || ax < 1.17741 )
302 x = bx > 0 ? 0.8857913*(2.506628 - ax) : -0.8857913*(2.506628 - ax);
307 if( log(y) < .6931472 - .5*bx*bx )
313 if( log(1.8857913 - y) < .5718733-.5*x*x )
318 v = ((int)temp)*4.656613e-10;
319 x = -log(fabs(v))*.3989423;
320 temp = ICV_RNG_NEXT(temp);
321 y = -log(((unsigned)temp)*2.328306e-10);
322 temp = ICV_RNG_NEXT(temp);
326 x = v > 0 ? 2.506628 + x : -2.506628 - x;
337 #define RAND_BUF_SIZE 96
340 #define ICV_IMPL_RANDN( flavor, arrtype, worktype, cast_macro1, cast_macro2 ) \
341 static CvStatus CV_STDCALL \
342 icvRandn_##flavor##_C1R( arrtype* arr, int step, CvSize size, \
343 uint64* state, const double* param ) \
345 float buffer[RAND_BUF_SIZE]; \
346 step /= sizeof(arr[0]); \
348 for( ; size.height--; arr += step ) \
350 int i, j, len = RAND_BUF_SIZE; \
352 for( i = 0; i < size.width; i += RAND_BUF_SIZE ) \
355 const double* p = param; \
357 if( i + len > size.width ) \
358 len = size.width - i; \
360 icvRandn_0_1_32f_C1R( buffer, len, state ); \
362 for( j = 0; j <= len - 4; j += 4 ) \
366 f0 = cast_macro1( buffer[j]*p[j+12] + p[j] ); \
367 f1 = cast_macro1( buffer[j+1]*p[j+13] + p[j+1] ); \
368 arr[i+j] = cast_macro2(f0); \
369 arr[i+j+1] = cast_macro2(f1); \
371 f0 = cast_macro1( buffer[j+2]*p[j+14] + p[j+2] ); \
372 f1 = cast_macro1( buffer[j+3]*p[j+15] + p[j+3] ); \
373 arr[i+j+2] = cast_macro2(f0); \
374 arr[i+j+3] = cast_macro2(f1); \
383 for( ; j < len; j++ ) \
385 worktype f0 = cast_macro1( buffer[j]*p[j+12] + p[j] ); \
386 arr[i+j] = cast_macro2(f0); \
395 ICV_IMPL_RAND_BITS( 8u, uchar, CV_CAST_8U )
396 ICV_IMPL_RAND_BITS( 16u, ushort, CV_CAST_16U )
397 ICV_IMPL_RAND_BITS( 16s, short, CV_CAST_16S )
398 ICV_IMPL_RAND_BITS( 32s, int, CV_CAST_32S )
400 ICV_IMPL_RAND( 8u, uchar, int, cvFloor, CV_CAST_8U )
401 ICV_IMPL_RAND( 16u, ushort, int, cvFloor, CV_CAST_16U )
402 ICV_IMPL_RAND( 16s, short, int, cvFloor, CV_CAST_16S )
403 ICV_IMPL_RAND( 32s, int, int, cvFloor, CV_CAST_32S )
404 ICV_IMPL_RAND( 32f, float, float, CV_CAST_32F, CV_NOP )
406 ICV_IMPL_RANDN( 8u, uchar, int, cvRound, CV_CAST_8U )
407 ICV_IMPL_RANDN( 16u, ushort, int, cvRound, CV_CAST_16U )
408 ICV_IMPL_RANDN( 16s, short, int, cvRound, CV_CAST_16S )
409 ICV_IMPL_RANDN( 32s, int, int, cvRound, CV_CAST_32S )
410 ICV_IMPL_RANDN( 32f, float, float, CV_CAST_32F, CV_NOP )
411 ICV_IMPL_RANDN( 64f, double, double, CV_CAST_64F, CV_NOP )
413 static void icvInitRandTable( CvFuncTable* fastrng_tab,
414 CvFuncTable* rng_tab,
415 CvFuncTable* normal_tab )
417 fastrng_tab->fn_2d[CV_8U] = (void*)icvRandBits_8u_C1R;
418 fastrng_tab->fn_2d[CV_8S] = 0;
419 fastrng_tab->fn_2d[CV_16U] = (void*)icvRandBits_16u_C1R;
420 fastrng_tab->fn_2d[CV_16S] = (void*)icvRandBits_16s_C1R;
421 fastrng_tab->fn_2d[CV_32S] = (void*)icvRandBits_32s_C1R;
423 rng_tab->fn_2d[CV_8U] = (void*)icvRand_8u_C1R;
424 rng_tab->fn_2d[CV_8S] = 0;
425 rng_tab->fn_2d[CV_16U] = (void*)icvRand_16u_C1R;
426 rng_tab->fn_2d[CV_16S] = (void*)icvRand_16s_C1R;
427 rng_tab->fn_2d[CV_32S] = (void*)icvRand_32s_C1R;
428 rng_tab->fn_2d[CV_32F] = (void*)icvRand_32f_C1R;
429 rng_tab->fn_2d[CV_64F] = (void*)icvRand_64f_C1R;
431 normal_tab->fn_2d[CV_8U] = (void*)icvRandn_8u_C1R;
432 normal_tab->fn_2d[CV_8S] = 0;
433 normal_tab->fn_2d[CV_16U] = (void*)icvRandn_16u_C1R;
434 normal_tab->fn_2d[CV_16S] = (void*)icvRandn_16s_C1R;
435 normal_tab->fn_2d[CV_32S] = (void*)icvRandn_32s_C1R;
436 normal_tab->fn_2d[CV_32F] = (void*)icvRandn_32f_C1R;
437 normal_tab->fn_2d[CV_64F] = (void*)icvRandn_64f_C1R;
442 cvRandArr( CvRNG* rng, CvArr* arr, int disttype, CvScalar param1, CvScalar param2 )
444 static CvFuncTable rng_tab[2], fastrng_tab;
445 static int inittab = 0;
447 CV_FUNCNAME( "cvRandArr" );
452 CvMat stub, *mat = (CvMat*)arr;
453 int type, depth, channels;
454 double dparam[2][12];
456 void* param = dparam;
457 int i, fast_int_mode = 0;
460 CvFunc2D_1A2P func = 0;
462 CvNArrayIterator iterator_state, *iterator = 0;
466 icvInitRandTable( &fastrng_tab, &rng_tab[CV_RAND_UNI],
467 &rng_tab[CV_RAND_NORMAL] );
472 CV_ERROR( CV_StsNullPtr, "Null pointer to RNG state" );
474 if( CV_IS_MATND(mat) )
476 iterator = &iterator_state;
477 CV_CALL( cvInitNArrayIterator( 1, &arr, 0, &stub_nd, iterator ));
478 type = CV_MAT_TYPE(iterator->hdr[0]->type);
479 size = iterator->size;
487 CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
490 CV_ERROR( CV_BadCOI, "COI is not supported" );
493 type = CV_MAT_TYPE( mat->type );
494 size = cvGetMatSize( mat );
495 mat_step = mat->step;
497 if( mat->height > 1 && CV_IS_MAT_CONT( mat->type ))
499 size.width *= size.height;
500 mat_step = CV_STUB_STEP;
505 depth = CV_MAT_DEPTH( type );
506 channels = CV_MAT_CN( type );
507 size.width *= channels;
509 if( disttype == CV_RAND_UNI )
511 if( depth <= CV_32S )
513 for( i = 0, fast_int_mode = 1; i < channels; i++ )
515 int t0 = iparam[0][i] = cvCeil( param1.val[i] );
516 int t1 = iparam[1][i] = cvFloor( param2.val[i] ) - t0;
517 double diff = param1.val[i] - param2.val[i];
519 fast_int_mode &= INT_MIN <= diff && diff <= INT_MAX && (t1 & (t1 - 1)) == 0;
525 for( i = 0; i < channels; i++ )
530 int t0 = iparam[0][i - channels];
531 int t1 = iparam[1][i - channels];
537 CV_GET_FUNC_PTR( func, (CvFunc2D_1A2P)(fastrng_tab.fn_2d[depth]));
542 for( i = 0; i < channels; i++ )
544 double t0 = param1.val[i];
545 double t1 = param2.val[i];
547 dparam[0][i] = t0 - (t1 - t0);
548 dparam[1][i] = t1 - t0;
551 CV_GET_FUNC_PTR( func, (CvFunc2D_1A2P)(rng_tab[0].fn_2d[depth]));
554 else if( disttype == CV_RAND_NORMAL )
556 for( i = 0; i < channels; i++ )
558 double t0 = param1.val[i];
559 double t1 = param2.val[i];
565 CV_GET_FUNC_PTR( func, (CvFunc2D_1A2P)(rng_tab[1].fn_2d[depth]));
569 CV_ERROR( CV_StsBadArg, "Unknown distribution type" );
574 for( i = channels; i < 12; i++ )
576 double t0 = dparam[0][i - channels];
577 double t1 = dparam[1][i - channels];
586 IPPI_CALL( func( mat->data.ptr, mat_step, size, rng, param ));
592 IPPI_CALL( func( iterator->ptr[0], CV_STUB_STEP, size, rng, param ));
594 while( cvNextNArraySlice( iterator ));