| 444 | } |
| 445 | |
| 446 | Estimate<double> |
| 447 | bootstrap( double confidence_level, |
| 448 | double* first, |
| 449 | double* last, |
| 450 | sample const& resample, |
| 451 | double ( *estimator )( double const*, double const* ) ) { |
| 452 | auto n_samples = last - first; |
| 453 | |
| 454 | double point = estimator( first, last ); |
| 455 | // Degenerate case with a single sample |
| 456 | if ( n_samples == 1 ) |
| 457 | return { point, point, point, confidence_level }; |
| 458 | |
| 459 | sample jack = jackknife( estimator, first, last ); |
| 460 | double jack_mean = |
| 461 | mean( jack.data(), jack.data() + jack.size() ); |
| 462 | double sum_squares = 0, sum_cubes = 0; |
| 463 | for ( double x : jack ) { |
| 464 | auto difference = jack_mean - x; |
| 465 | auto square = difference * difference; |
| 466 | auto cube = square * difference; |
| 467 | sum_squares += square; |
| 468 | sum_cubes += cube; |
| 469 | } |
| 470 | |
| 471 | double accel = sum_cubes / ( 6 * std::pow( sum_squares, 1.5 ) ); |
| 472 | long n = static_cast<long>( resample.size() ); |
| 473 | double prob_n = static_cast<double>( |
| 474 | std::count_if( resample.begin(), |
| 475 | resample.end(), |
| 476 | [point]( double x ) { return x < point; } )) / |
| 477 | static_cast<double>( n ); |
| 478 | // degenerate case with uniform samples |
| 479 | if ( Catch::Detail::directCompare( prob_n, 0. ) ) { |
| 480 | return { point, point, point, confidence_level }; |
| 481 | } |
| 482 | |
| 483 | double bias = normal_quantile( prob_n ); |
| 484 | double z1 = normal_quantile( ( 1. - confidence_level ) / 2. ); |
| 485 | |
| 486 | auto cumn = [n]( double x ) -> long { |
| 487 | return std::lround( normal_cdf( x ) * |
| 488 | static_cast<double>( n ) ); |
| 489 | }; |
| 490 | auto a = [bias, accel]( double b ) { |
| 491 | return bias + b / ( 1. - accel * b ); |
| 492 | }; |
| 493 | double b1 = bias + z1; |
| 494 | double b2 = bias - z1; |
| 495 | double a1 = a( b1 ); |
| 496 | double a2 = a( b2 ); |
| 497 | auto lo = static_cast<size_t>( (std::max)( cumn( a1 ), 0l ) ); |
| 498 | auto hi = |
| 499 | static_cast<size_t>( (std::min)( cumn( a2 ), n - 1 ) ); |
| 500 | |
| 501 | return { point, resample[lo], resample[hi], confidence_level }; |
| 502 | } |
| 503 |
no test coverage detected