double root_find_solution( const MatrixFactory &mf, const interval_t &region,
                           const std::vector< double > lower_vals,
                           const std::vector< double > upper_vals,
                           double epsilon ) {
    int index = std::upper_bound( lower_vals.begin(), lower_vals.end(),
            region.lower() ) - lower_vals.begin();
    double flower = lower_vals[index] - region.lower();
    double fupper = upper_vals[index] - region.upper();
    return util::false_position(
            boost::bind( base_root_function, _1, boost::cref(mf),
                index ),
            region.lower(), region.upper(), flower, fupper, epsilon ); }
Example #2
0
static void get_closed_bounds(const interval_t &interval, channel_t &lower, channel_t &upper)
{
    lower = interval.lower();
    upper = interval.upper();

    if(!(interval.bounds().bits() & 2)) {
        lower += 1;
    }
    if(!(interval.bounds().bits() & 1)) {
        upper -= 1;
    }
}
// This is the main search algorithm for the (D)ERPA.
std::vector< double >
solve_region( const MatrixFactory &mf, const interval_t &region,
              const std::vector< double > lower_vals,
              const std::vector< double > upper_vals,
              double epsilon ) {
    // Determine # solutions
    int num_solutions = get_num_solutions( lower_vals, region.lower(),
                                           upper_vals, region.upper() );
    // If no solutions, return empty.
    if ( 0 == num_solutions ) {
        return std::vector< double >(); }

    // If the interval has no width, but has solutions, return the value.
    if ( std::abs( region.upper() - region.lower() ) < epsilon ) {
        return std::vector< double >( 1, region.lower() ); }

    // If 1 solution, root_find.
    if ( 1 == num_solutions ) {
        std::vector< double > temp( 1,
                root_find_solution( mf, region, lower_vals, upper_vals,
                    epsilon ) );
        return temp; }

    // If > 1 solution, sub-divide region.
    double center = boost::numeric::median( region );
    std::vector< double > center_vals
        = util::sorted_eigenvalues( mf.build( center ) );
    std::vector< double > solutions
        = solve_region( mf, interval_t( region.lower(), center ),
                        lower_vals, center_vals, epsilon );
    { std::vector< double > upper_solutions
        = solve_region( mf, interval_t( center, region.upper() ),
                        center_vals, upper_vals, epsilon );
        solutions.insert( solutions.end(), upper_solutions.begin(),
                upper_solutions.end() ); }
    return solutions; }