28 #ifndef SIMPLE_FIND_ZERO_H 29 #define SIMPLE_FIND_ZERO_H 67 template<
typename ValueType,
typename Po
intType,
typename Fn,
typename LoggerType = Logger::VacuumLogger>
68 inline static PointType simpleFindZero(
const Fn & fn, PointType pt1, PointType pt2,
70 ValueType valtolerance = 1e-6,
71 ValueType * final_value = NULL,
72 int * final_numiters = NULL,
73 LoggerType & logger = Logger::vacuum_logger)
75 int num_recover_iters = 0;
76 int max_recover_iters = 10*maxiters;
79 if (final_value != NULL) {
82 if (final_numiters != NULL) {
87 ValueType val1 = fn(pt1);
88 ValueType val2 = fn(pt2);
89 while (
std::isnan(val2) && num_recover_iters < max_recover_iters) {
90 logger.longdebug(
"simpleFindZero()", [pt2](
std::ostream & str) {
91 str <<
"function returned NaN for given pt2 = " << pt2 <<
", attempting to recover...";
94 pt2 = pt1 + (pt2 - pt1) / 2.0;
99 if (
std::fabs(val2 - val1) <= valtolerance) {
100 logger.warning(
"simpleFindZero()", [pt1,pt2,val1,val2](
std::ostream & str) {
101 str <<
"the two initial points x1="<<pt1<<
" and x2="<<pt2<<
" give values too close: y1="<<val1
102 <<
" and y2=" << val2;
107 PointType pt3 = pt1 - val1 * (pt2 - pt1)/(val2 - val1);
108 ValueType val3 = fn(pt3);
110 std::fabs(val3 - val1) <= valtolerance)) {
111 logger.longdebug(
"simpleFindZero()", [pt3,val3](
std::ostream & str) {
112 str <<
"function returned NaN, or value too close to x1 or x2, for guessed x3=" << pt3
113 <<
" (y3="<<val3<<
"), attempting to recover...";
116 pt3 = pt1 + (pt2 - pt1) / 2.0;
120 logger.longdebug(
"simpleFindZero()", [&](
std::ostream& str) {
121 str <<
"Starting with\n" 122 <<
"\t x1="<<pt1<<
" \tf(x1)="<<val1<<
"\n" 123 <<
"\t x2="<<pt2<<
" \tf(x2)="<<val2<<
"\n" 124 <<
"\t --> x3="<<pt3<<
"\tf(x3)="<<val3;
130 for (
int k = 0; k < maxiters; ++k) {
132 newpt = pt1 * val2*val3 / ((val1 - val2)*(val1 - val3))
133 + pt2 * val1*val3 / ((val2 - val1)*(val2 - val3))
134 + pt3 * val1*val2 / ((val3 - val1)*(val3 - val2)) ;
139 while (
std::isnan(newval) && num_recover_iters < max_recover_iters) {
141 logger.longdebug(
"simpleFindZero()", [newpt](
std::ostream & str) {
142 str <<
"function returned NaN for new point " << newpt <<
", attempting to recover...";
144 newpt = pt3 + (newpt - pt3) / 2;
149 logger.longdebug(
"simpleFindZero()", [&](
std::ostream& str) {
150 str <<
"Iter #" << k <<
": x = " << newpt <<
" y = " << newval;
155 if (
std::fabs(newval) < valtolerance || num_recover_iters >= max_recover_iters) {
156 if (final_value != NULL) {
157 *final_value = newval;
159 if (final_numiters != NULL) {
165 pt1 = pt2; val1 = val2;
166 pt2 = pt3; val2 = val3;
167 pt3 = newpt; val3 = newval;
170 if (final_value != NULL) {
171 *final_value = newval;
173 if (final_numiters != NULL) {
174 *final_numiters = maxiters;
Base namespace for the Tomographer project.
Utilities for logging messages.