27 #ifndef SIMPLE_FIND_ZERO_H
28 #define SIMPLE_FIND_ZERO_H
66 template<
typename ValueType,
typename Po
intType,
typename Fn,
typename LoggerType = Logger::VacuumLogger>
67 inline static PointType simpleFindZero(
const Fn & fn, PointType pt1, PointType pt2,
69 ValueType valtolerance = 1e-6,
70 ValueType * final_value = NULL,
71 int * final_numiters = NULL,
72 LoggerType & logger = Logger::vacuum_logger)
74 int num_recover_iters = 0;
75 int max_recover_iters = 10*maxiters;
78 if (final_value != NULL) {
81 if (final_numiters != NULL) {
86 ValueType val1 = fn(pt1);
87 ValueType val2 = fn(pt2);
88 while (
std::isnan(val2) && num_recover_iters < max_recover_iters) {
89 logger.longdebug(
"simpleFindZero()", [pt2](
std::ostream & str) {
90 str <<
"function returned NaN for given pt2 = " << pt2 <<
", attempting to recover...";
93 pt2 = pt1 + (pt2 - pt1) / 2.0;
98 if (
std::fabs(val2 - val1) <= valtolerance) {
99 logger.warning(
"simpleFindZero()", [pt1,pt2,val1,val2](
std::ostream & str) {
100 str <<
"the two initial points x1="<<pt1<<
" and x2="<<pt2<<
" give values too close: y1="<<val1
101 <<
" and y2=" << val2;
106 PointType pt3 = pt1 - val1 * (pt2 - pt1)/(val2 - val1);
107 ValueType val3 = fn(pt3);
109 std::fabs(val3 - val1) <= valtolerance)) {
110 logger.longdebug(
"simpleFindZero()", [pt3,val3](
std::ostream & str) {
111 str <<
"function returned NaN, or value too close to x1 or x2, for guessed x3=" << pt3
112 <<
" (y3="<<val3<<
"), attempting to recover...";
115 pt3 = pt1 + (pt2 - pt1) / 2.0;
119 logger.longdebug(
"simpleFindZero()", [&](
std::ostream& str) {
120 str <<
"Starting with\n"
121 <<
"\t x1="<<pt1<<
" \tf(x1)="<<val1<<
"\n"
122 <<
"\t x2="<<pt2<<
" \tf(x2)="<<val2<<
"\n"
123 <<
"\t --> x3="<<pt3<<
"\tf(x3)="<<val3;
129 for (
int k = 0; k < maxiters; ++k) {
131 newpt = pt1 * val2*val3 / ((val1 - val2)*(val1 - val3))
132 + pt2 * val1*val3 / ((val2 - val1)*(val2 - val3))
133 + pt3 * val1*val2 / ((val3 - val1)*(val3 - val2)) ;
138 while (
std::isnan(newval) && num_recover_iters < max_recover_iters) {
140 logger.longdebug(
"simpleFindZero()", [newpt](
std::ostream & str) {
141 str <<
"function returned NaN for new point " << newpt <<
", attempting to recover...";
143 newpt = pt3 + (newpt - pt3) / 2;
148 logger.longdebug(
"simpleFindZero()", [&](
std::ostream& str) {
149 str <<
"Iter #" << k <<
": x = " << newpt <<
" y = " << newval;
154 if (
std::fabs(newval) < valtolerance || num_recover_iters >= max_recover_iters) {
155 if (final_value != NULL) {
156 *final_value = newval;
158 if (final_numiters != NULL) {
164 pt1 = pt2; val1 = val2;
165 pt2 = pt3; val2 = val3;
166 pt3 = newpt; val3 = newval;
169 if (final_value != NULL) {
170 *final_value = newval;
172 if (final_numiters != NULL) {
173 *final_numiters = maxiters;
Base namespace for the Tomographer project.
Utilities for logging messages.