1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 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. 8 // 9 // 10 // Intel License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000, Intel Corporation, all rights reserved. 14 // Third party copyrights are property of their respective owners. 15 // 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistribution's of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // 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. 25 // 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. 28 // 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. 39 // 40 //M*/ 41 42 /* //////////////////////////////////////////////////////////////////// 43 // 44 // Filling CvMat/IplImage instances with random numbers 45 // 46 // */ 47 48 #include "_cxcore.h" 49 50 51 ///////////////////////////// Functions Declaration ////////////////////////////////////// 52 53 /* 54 Multiply-with-carry generator is used here: 55 temp = ( A*X(n) + carry ) 56 X(n+1) = temp mod (2^32) 57 carry = temp / (2^32) 58 */ 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) 63 64 /***************************************************************************************\ 65 * Pseudo-Random Number Generators (PRNGs) * 66 \***************************************************************************************/ 67 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 ) \ 72 { \ 73 uint64 temp = *state; \ 74 int small_flag = (param[12]|param[13]|param[14]|param[15]) <= 255; \ 75 step /= sizeof(arr[0]); \ 76 \ 77 for( ; size.height--; arr += step ) \ 78 { \ 79 int i, k = 3; \ 80 const int* p = param; \ 81 \ 82 if( !small_flag ) \ 83 { \ 84 for( i = 0; i <= size.width - 4; i += 4 ) \ 85 { \ 86 unsigned t0, t1; \ 87 \ 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); \ 94 \ 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); \ 101 \ 102 if( !--k ) \ 103 { \ 104 k = 3; \ 105 p -= 12; \ 106 } \ 107 } \ 108 } \ 109 else \ 110 { \ 111 for( i = 0; i <= size.width - 4; i += 4 ) \ 112 { \ 113 unsigned t0, t1, t; \ 114 \ 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); \ 121 \ 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); \ 126 \ 127 if( !--k ) \ 128 { \ 129 k = 3; \ 130 p -= 12; \ 131 } \ 132 } \ 133 } \ 134 \ 135 for( ; i < size.width; i++ ) \ 136 { \ 137 unsigned t0; \ 138 temp = ICV_RNG_NEXT(temp); \ 139 \ 140 t0 = ((unsigned)temp & p[i + 12]) + p[i]; \ 141 arr[i] = cast_macro((int)t0); \ 142 } \ 143 } \ 144 \ 145 *state = temp; \ 146 return CV_OK; \ 147 } 148 149 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 ) \ 154 { \ 155 uint64 temp = *state; \ 156 step /= sizeof(arr[0]); \ 157 \ 158 for( ; size.height--; arr += step ) \ 159 { \ 160 int i, k = 3; \ 161 const double* p = param; \ 162 \ 163 for( i = 0; i <= size.width - 4; i += 4 ) \ 164 { \ 165 worktype f0, f1; \ 166 Cv32suf t0, t1; \ 167 \ 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); \ 176 \ 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); \ 185 \ 186 if( !--k ) \ 187 { \ 188 k = 3; \ 189 p -= 12; \ 190 } \ 191 } \ 192 \ 193 for( ; i < size.width; i++ ) \ 194 { \ 195 worktype f0; \ 196 Cv32suf t0; \ 197 \ 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); \ 202 } \ 203 } \ 204 \ 205 *state = temp; \ 206 return CV_OK; \ 207 } 208 209 210 static CvStatus CV_STDCALL 211 icvRand_64f_C1R( double* arr, int step, CvSize size, 212 uint64* state, const double* param ) 213 { 214 uint64 temp = *state; 215 step /= sizeof(arr[0]); 216 217 for( ; size.height--; arr += step ) 218 { 219 int i, k = 3; 220 const double* p = param; 221 222 for( i = 0; i <= size.width - 4; i += 4 ) 223 { 224 double f0, f1; 225 Cv64suf t0, t1; 226 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]; 233 arr[i] = f0; 234 arr[i+1] = f1; 235 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]; 242 arr[i+2] = f0; 243 arr[i+3] = f1; 244 245 if( !--k ) 246 { 247 k = 3; 248 p -= 12; 249 } 250 } 251 252 for( ; i < size.width; i++ ) 253 { 254 double f0; 255 Cv64suf t0; 256 257 temp = ICV_RNG_NEXT(temp); 258 t0.u = ICV_CVT_DBL(temp); 259 f0 = t0.f * p[i + 12] + p[i]; 260 arr[i] = f0; 261 } 262 } 263 264 *state = temp; 265 return CV_OK; 266 } 267 268 269 /***************************************************************************************\ 270 The code below implements algorithm from the paper: 271 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 \***************************************************************************************/ 277 278 static CvStatus CV_STDCALL 279 icvRandn_0_1_32f_C1R( float* arr, int len, uint64* state ) 280 { 281 uint64 temp = *state; 282 int i; 283 temp = ICV_RNG_NEXT(temp); 284 285 for( i = 0; i < len; i++ ) 286 { 287 double x, y, v, ax, bx; 288 289 for(;;) 290 { 291 x = ((int)temp)*1.167239e-9; 292 temp = ICV_RNG_NEXT(temp); 293 ax = fabs(x); 294 v = 2.8658 - ax*(2.0213 - 0.3605*ax); 295 y = ((unsigned)temp)*2.328306e-10; 296 temp = ICV_RNG_NEXT(temp); 297 298 if( y < v || ax < 1.17741 ) 299 break; 300 301 bx = x; 302 x = bx > 0 ? 0.8857913*(2.506628 - ax) : -0.8857913*(2.506628 - ax); 303 304 if( y > v + 0.0506 ) 305 break; 306 307 if( log(y) < .6931472 - .5*bx*bx ) 308 { 309 x = bx; 310 break; 311 } 312 313 if( log(1.8857913 - y) < .5718733-.5*x*x ) 314 break; 315 316 do 317 { 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); 323 } 324 while( y+y < x*x ); 325 326 x = v > 0 ? 2.506628 + x : -2.506628 - x; 327 break; 328 } 329 330 arr[i] = (float)x; 331 } 332 *state = temp; 333 return CV_OK; 334 } 335 336 337 #define RAND_BUF_SIZE 96 338 339 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 ) \ 344 { \ 345 float buffer[RAND_BUF_SIZE]; \ 346 step /= sizeof(arr[0]); \ 347 \ 348 for( ; size.height--; arr += step ) \ 349 { \ 350 int i, j, len = RAND_BUF_SIZE; \ 351 \ 352 for( i = 0; i < size.width; i += RAND_BUF_SIZE ) \ 353 { \ 354 int k = 3; \ 355 const double* p = param; \ 356 \ 357 if( i + len > size.width ) \ 358 len = size.width - i; \ 359 \ 360 icvRandn_0_1_32f_C1R( buffer, len, state ); \ 361 \ 362 for( j = 0; j <= len - 4; j += 4 ) \ 363 { \ 364 worktype f0, f1; \ 365 \ 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); \ 370 \ 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); \ 375 \ 376 if( --k == 0 ) \ 377 { \ 378 k = 3; \ 379 p -= 12; \ 380 } \ 381 } \ 382 \ 383 for( ; j < len; j++ ) \ 384 { \ 385 worktype f0 = cast_macro1( buffer[j]*p[j+12] + p[j] ); \ 386 arr[i+j] = cast_macro2(f0); \ 387 } \ 388 } \ 389 } \ 390 \ 391 return CV_OK; \ 392 } 393 394 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 ) 399 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 ) 405 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 ) 412 413 static void icvInitRandTable( CvFuncTable* fastrng_tab, 414 CvFuncTable* rng_tab, 415 CvFuncTable* normal_tab ) 416 { 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; 422 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; 430 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; 438 } 439 440 441 CV_IMPL void 442 cvRandArr( CvRNG* rng, CvArr* arr, int disttype, CvScalar param1, CvScalar param2 ) 443 { 444 static CvFuncTable rng_tab[2], fastrng_tab; 445 static int inittab = 0; 446 447 CV_FUNCNAME( "cvRandArr" ); 448 449 __BEGIN__; 450 451 int is_nd = 0; 452 CvMat stub, *mat = (CvMat*)arr; 453 int type, depth, channels; 454 double dparam[2][12]; 455 int iparam[2][12]; 456 void* param = dparam; 457 int i, fast_int_mode = 0; 458 int mat_step = 0; 459 CvSize size; 460 CvFunc2D_1A2P func = 0; 461 CvMatND stub_nd; 462 CvNArrayIterator iterator_state, *iterator = 0; 463 464 if( !inittab ) 465 { 466 icvInitRandTable( &fastrng_tab, &rng_tab[CV_RAND_UNI], 467 &rng_tab[CV_RAND_NORMAL] ); 468 inittab = 1; 469 } 470 471 if( !rng ) 472 CV_ERROR( CV_StsNullPtr, "Null pointer to RNG state" ); 473 474 if( CV_IS_MATND(mat) ) 475 { 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; 480 is_nd = 1; 481 } 482 else 483 { 484 if( !CV_IS_MAT(mat)) 485 { 486 int coi = 0; 487 CV_CALL( mat = cvGetMat( mat, &stub, &coi )); 488 489 if( coi != 0 ) 490 CV_ERROR( CV_BadCOI, "COI is not supported" ); 491 } 492 493 type = CV_MAT_TYPE( mat->type ); 494 size = cvGetMatSize( mat ); 495 mat_step = mat->step; 496 497 if( mat->height > 1 && CV_IS_MAT_CONT( mat->type )) 498 { 499 size.width *= size.height; 500 mat_step = CV_STUB_STEP; 501 size.height = 1; 502 } 503 } 504 505 depth = CV_MAT_DEPTH( type ); 506 channels = CV_MAT_CN( type ); 507 size.width *= channels; 508 509 if( disttype == CV_RAND_UNI ) 510 { 511 if( depth <= CV_32S ) 512 { 513 for( i = 0, fast_int_mode = 1; i < channels; i++ ) 514 { 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]; 518 519 fast_int_mode &= INT_MIN <= diff && diff <= INT_MAX && (t1 & (t1 - 1)) == 0; 520 } 521 } 522 523 if( fast_int_mode ) 524 { 525 for( i = 0; i < channels; i++ ) 526 iparam[1][i]--; 527 528 for( ; i < 12; i++ ) 529 { 530 int t0 = iparam[0][i - channels]; 531 int t1 = iparam[1][i - channels]; 532 533 iparam[0][i] = t0; 534 iparam[1][i] = t1; 535 } 536 537 CV_GET_FUNC_PTR( func, (CvFunc2D_1A2P)(fastrng_tab.fn_2d[depth])); 538 param = iparam; 539 } 540 else 541 { 542 for( i = 0; i < channels; i++ ) 543 { 544 double t0 = param1.val[i]; 545 double t1 = param2.val[i]; 546 547 dparam[0][i] = t0 - (t1 - t0); 548 dparam[1][i] = t1 - t0; 549 } 550 551 CV_GET_FUNC_PTR( func, (CvFunc2D_1A2P)(rng_tab[0].fn_2d[depth])); 552 } 553 } 554 else if( disttype == CV_RAND_NORMAL ) 555 { 556 for( i = 0; i < channels; i++ ) 557 { 558 double t0 = param1.val[i]; 559 double t1 = param2.val[i]; 560 561 dparam[0][i] = t0; 562 dparam[1][i] = t1; 563 } 564 565 CV_GET_FUNC_PTR( func, (CvFunc2D_1A2P)(rng_tab[1].fn_2d[depth])); 566 } 567 else 568 { 569 CV_ERROR( CV_StsBadArg, "Unknown distribution type" ); 570 } 571 572 if( !fast_int_mode ) 573 { 574 for( i = channels; i < 12; i++ ) 575 { 576 double t0 = dparam[0][i - channels]; 577 double t1 = dparam[1][i - channels]; 578 579 dparam[0][i] = t0; 580 dparam[1][i] = t1; 581 } 582 } 583 584 if( !is_nd ) 585 { 586 IPPI_CALL( func( mat->data.ptr, mat_step, size, rng, param )); 587 } 588 else 589 { 590 do 591 { 592 IPPI_CALL( func( iterator->ptr[0], CV_STUB_STEP, size, rng, param )); 593 } 594 while( cvNextNArraySlice( iterator )); 595 } 596 597 __END__; 598 } 599 600 /* End of file. */ 601