//
//
//
//
// Lab. Calcolo II - Esempio di codice
//
//
//
//
//
//
//
// Example code: Function zero search.
// (francesco.prelz@mi.infn.it 20060814)
#include
#include
#include
#include
#include
template
class FunctionZeroSearch
{
public:
struct bracket
{
DT x1;
DT x2;
};
typedef DT value_type;
typedef DT (*function_ptr_type)(DT); // Normal - nonmember function pointer
typedef std::function functor_type;
typedef std::vector bracket_container_type;
// Creator
FunctionZeroSearch(functor_type &f);
FunctionZeroSearch(function_ptr_type f);
// Destructor
~FunctionZeroSearch();
DT operator() (DT argument);
int find_bracket_expand(bracket &bra);
int find_bracket_partition(const bracket &bra, int n_partitions);
void clear_brackets();
const bracket_container_type &get_brackets();
std::vector get_zeros(double tolerance=1e-6);
private:
functor_type m_f;
bracket_container_type m_brackets;
};
template
FunctionZeroSearch::FunctionZeroSearch(functor_type &f) : m_f(f) {}
template
FunctionZeroSearch::FunctionZeroSearch(function_ptr_type f) : m_f(f) {}
template
FunctionZeroSearch::~FunctionZeroSearch() {}
template
DT FunctionZeroSearch::operator() (DT argument)
{
return m_f(argument);
}
template
int FunctionZeroSearch::find_bracket_expand(bracket &bra)
{
m_brackets.clear();
const DT expansion_factor=1.6;
const int expansion_max_retries=50;
for (int i=0;i
int FunctionZeroSearch::find_bracket_partition(const bracket &bra, int n_partitions)
{
m_brackets.clear();
int n_results = 0;
DT cur_x1,cur_x2;
DT segment_size = (bra.x2 - bra.x1) / static_cast(n_partitions);
cur_x1 = bra.x1;
cur_x2 = cur_x1 + segment_size;
for (int i=0; i
void FunctionZeroSearch::clear_brackets()
{
m_brackets.clear();
}
template
const typename FunctionZeroSearch::bracket_container_type &
FunctionZeroSearch::get_brackets()
{
return m_brackets;
}
template
std::vector FunctionZeroSearch::get_zeros(double tolerance)
{
const int maximum_bisections=100;
std::vector results;
for (typename FunctionZeroSearch::bracket_container_type::const_iterator bra = m_brackets.begin();
bra != m_brackets.end(); ++bra)
{
double xmiddle;
double fleft, fmiddle, fright;
// Computing f might be expensive
fleft = m_f(bra->x1);
fright = m_f(bra->x2);
if (fleft*fright >= 0) continue; // Not a valid bracket.
bracket cbra(*bra); // Modifiable copy.
for (int i=0; i fzcos(std::cos);
FunctionZeroSearch::bracket test;
test.x1 = 0;
test.x2 = M_PI/4;
int result = fzcos.find_bracket_expand(test);
std::cout << "find_bracket_expand cos with initial interval (0,PI/4) returns "
<< result << std::endl;
std::cout << " Bracket: [" << test.x1/M_PI << " PI," << test.x2/M_PI
<< " PI]" << std::endl;
std::vector zeros = fzcos.get_zeros();
for (std::vector::const_iterator it = zeros.begin();
it != zeros.end(); ++it)
{
std::cout << " zero = " << (*it)/M_PI << " PI (+/- 1E-6)" << std::endl;
}
test.x1 = 0;
test.x2 = 4*M_PI;
result = fzcos.find_bracket_partition(test, 20);
std::cout << "get_bracket_partition cos with initial interval (0,4*PI) returns "
<< result << std::endl;
const FunctionZeroSearch::bracket_container_type &brackets =
fzcos.get_brackets();
FunctionZeroSearch::bracket_container_type::const_iterator bra;
for (bra=brackets.begin();bra!=brackets.end();++bra)
{
std::cout << " Bracket: [" << bra->x1/M_PI << " PI," << bra->x2/M_PI
<< " PI]" << std::endl;
}
zeros = fzcos.get_zeros();
for (std::vector::const_iterator it = zeros.begin();
it != zeros.end(); ++it)
{
std::cout << " zero = " << (*it)/M_PI << " PI (+/- 1E-6)" << std::endl;
}
return 0;
}