|
Shinya Kitaoka |
810553 |
#pragma once
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef TZEROFINDER_H
|
|
Toshihiro Shimizu |
890ddd |
#define TZEROFINDER_H
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <cmath></cmath>
|
|
Toshihiro Shimizu |
890ddd |
#include <assert.h></assert.h>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
enum { FZ_OK = 0, FZ_FTOL = 1, FZ_XTOL = 2, FZ_MAX_ITER = 3, FZ_NOT_ZERO = 4 };
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Daniele
|
|
Toshihiro Shimizu |
890ddd |
// Use the one at the end instead. This may overshoot - plus, it does not
|
|
Toshihiro Shimizu |
890ddd |
// bisecate the interval... (I suppose it has never been used much :) )
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template< class unaryOp ,
|
|
Toshihiro Shimizu |
890ddd |
class unaryOpDerivate>
|
|
Toshihiro Shimizu |
890ddd |
bool findZero_Newton ( double x0 ,
|
|
Toshihiro Shimizu |
890ddd |
double x1 ,
|
|
Toshihiro Shimizu |
890ddd |
unaryOp f ,
|
|
Toshihiro Shimizu |
890ddd |
unaryOpDerivate fd1 ,
|
|
Toshihiro Shimizu |
890ddd |
double xtol ,
|
|
Toshihiro Shimizu |
890ddd |
double ftol ,
|
|
Toshihiro Shimizu |
890ddd |
int maxIter ,
|
|
Toshihiro Shimizu |
890ddd |
double &x ,
|
|
Toshihiro Shimizu |
890ddd |
int &err )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double f_x_n_plus_1 = 0.0 ;
|
|
Toshihiro Shimizu |
890ddd |
double f_x_n = f(x1) ;
|
|
Toshihiro Shimizu |
890ddd |
double f_x_n_minus_1 = f(x0) ;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if( f_x_n*f_x_n_minus_1 > 0 )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
err = FZ_NOT_ZERO;
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
err=FZ_OK;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if( f_x_n == 0 ||
|
|
Shinya Kitaoka |
120a6e |
f_x_n_minus_1 == 0 )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
x = (f_x_n == 0.0) ? x1 : x0;
|
|
Shinya Kitaoka |
120a6e |
err = FZ_OK;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double x_n_plus_1 ;
|
|
Toshihiro Shimizu |
890ddd |
double x_n ;
|
|
Toshihiro Shimizu |
890ddd |
double x_n_minus_1 ;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
x_n = x1;
|
|
Toshihiro Shimizu |
890ddd |
x_n_minus_1 = x0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for(i=0;i
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
luz paz |
6454c4 |
// the first time x_n = x1
|
|
Toshihiro Shimizu |
890ddd |
double fd1_x_n = fd1(x_n);
|
|
Toshihiro Shimizu |
890ddd |
assert( fd1_x_n != 0.0 );
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x_n_plus_1 = x_n - f_x_n / fd1_x_n;
|
|
Toshihiro Shimizu |
890ddd |
if( fabs(x_n - x_n_plus_1) < xtol )
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Toshihiro Shimizu |
890ddd |
err=FZ_XTOL;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Toshihiro Shimizu |
890ddd |
f_x_n_plus_1 = f(x_n_plus_1);
|
|
Toshihiro Shimizu |
890ddd |
if( fabs(f_x_n_plus_1) < ftol )
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Toshihiro Shimizu |
890ddd |
err=FZ_FTOL;
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x_n_minus_1 = x_n;
|
|
Toshihiro Shimizu |
890ddd |
x_n = x_n_plus_1;
|
|
Toshihiro Shimizu |
890ddd |
f_x_n = f_x_n_plus_1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Toshihiro Shimizu |
890ddd |
x=x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
err = (i == maxIter ? FZ_MAX_ITER : err);
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Bisection algorithm.
|
|
Toshihiro Shimizu |
890ddd |
Get an object and a method of object class.
|
|
Toshihiro Shimizu |
890ddd |
x1 and x2 are extremes of test and xtol
|
|
Toshihiro Shimizu |
890ddd |
is the accuracy.
|
|
Shinya Kitaoka |
120a6e |
|
|
Toshihiro Shimizu |
890ddd |
Return:
|
|
Toshihiro Shimizu |
890ddd |
the minimum or,
|
|
luz paz |
6454c4 |
-2 if min it's unreachable.
|
|
Toshihiro Shimizu |
890ddd |
-1 if min does not exist
|
|
Toshihiro Shimizu |
890ddd |
Remark:
|
|
Toshihiro Shimizu |
890ddd |
Max iterations numbers is fixed to 100 in in maxIter.
|
|
Toshihiro Shimizu |
890ddd |
This value fix the accuracy to 2e-100.
|
|
Shinya Kitaoka |
120a6e |
|
|
Toshihiro Shimizu |
890ddd |
From Numerical Recipes.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <class unaryop=""></class>
|
|
Shinya Kitaoka |
120a6e |
bool findZero_bisection(double x0, double x1, unaryOp f, double xtol,
|
|
Shinya Kitaoka |
120a6e |
int maxIter, double &x, int &err) {
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
err = FZ_OK;
|
|
Shinya Kitaoka |
120a6e |
double dx, fx0, fmid, xmid, rtb;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
fx0 = f(x0);
|
|
Shinya Kitaoka |
120a6e |
fmid = f(x1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (fx0 * fmid > 0.0) {
|
|
Shinya Kitaoka |
120a6e |
err = FZ_NOT_ZERO;
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (fx0 == 0 || fmid == 0) {
|
|
Shinya Kitaoka |
120a6e |
x = (fmid == 0.0) ? x1 : x0;
|
|
Shinya Kitaoka |
120a6e |
err = FZ_OK;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rtb = fx0 < 0.0 ? (dx = x1 - x0, x0) : (dx = x0 - x1, x1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (i = 1; i <= maxIter; i++) {
|
|
Shinya Kitaoka |
120a6e |
fmid = f(xmid = rtb + (dx *= 0.5));
|
|
Shinya Kitaoka |
120a6e |
if (fmid <= 0.0) rtb = xmid;
|
|
Shinya Kitaoka |
120a6e |
if (fabs(dx) < xtol || fmid == 0.0) {
|
|
Shinya Kitaoka |
120a6e |
x = rtb;
|
|
Shinya Kitaoka |
120a6e |
err = FZ_XTOL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
err = (i == maxIter ? FZ_MAX_ITER : err);
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <class unaryop=""></class>
|
|
Shinya Kitaoka |
120a6e |
bool findZero_secant(double x0, double x1, unaryOp f, double xtol, double ftol,
|
|
Shinya Kitaoka |
120a6e |
int maxIter, double &x, int &err) {
|
|
Shinya Kitaoka |
120a6e |
double f_x_n_plus_1 = 0.0, f_x_n = f(x1), f_x_n_minus_1 = f(x0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (f_x_n * f_x_n_minus_1 > 0) {
|
|
Shinya Kitaoka |
120a6e |
err = FZ_NOT_ZERO;
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
err = FZ_OK;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (f_x_n == 0 || f_x_n_minus_1 == 0) {
|
|
Shinya Kitaoka |
120a6e |
x = (f_x_n == 0.0) ? x1 : x0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double x_n_plus_1 = x1, x_n = x1, x_n_minus_1 = x0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < maxIter; ++i) {
|
|
Shinya Kitaoka |
120a6e |
double den = f_x_n - f_x_n_minus_1;
|
|
Shinya Kitaoka |
120a6e |
assert(den != 0.0);
|
|
Shinya Kitaoka |
120a6e |
if (den == 0.0) {
|
|
Shinya Kitaoka |
120a6e |
x_n = x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
err = FZ_FTOL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
x_n_plus_1 = x_n - (x_n - x_n_minus_1) * f_x_n / den;
|
|
Shinya Kitaoka |
120a6e |
if (fabs(x_n - x_n_plus_1) < xtol) {
|
|
Shinya Kitaoka |
120a6e |
err = FZ_XTOL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
f_x_n_plus_1 = f(x_n_plus_1);
|
|
Shinya Kitaoka |
120a6e |
if (fabs(f_x_n_plus_1) < ftol) {
|
|
Shinya Kitaoka |
120a6e |
err = FZ_FTOL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
x_n_minus_1 = x_n;
|
|
Shinya Kitaoka |
120a6e |
x_n = x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
f_x_n_minus_1 = f_x_n;
|
|
Shinya Kitaoka |
120a6e |
f_x_n = f_x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
x = x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
err = (i == maxIter ? FZ_MAX_ITER : err);
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <class class="" unaryop1,="" unaryop2=""></class>
|
|
Shinya Kitaoka |
120a6e |
bool findZero_Newton(double x0, double x1, unaryOp1 f, unaryOp2 f1, double xtol,
|
|
Shinya Kitaoka |
120a6e |
double ftol, int maxIter, double &x, int &err) {
|
|
Shinya Kitaoka |
120a6e |
double f_0 = f(x0);
|
|
Shinya Kitaoka |
120a6e |
double f_1 = f(x1);
|
|
Shinya Kitaoka |
120a6e |
double f_x_n = f_0, f_x_n_plus_1 = 0.0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool s_0 = (f_0 > 0);
|
|
Shinya Kitaoka |
120a6e |
bool s_1 = (f_1 > 0);
|
|
Shinya Kitaoka |
120a6e |
bool s_n;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (s_0 && s_1) {
|
|
Shinya Kitaoka |
120a6e |
err = FZ_NOT_ZERO;
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
err = FZ_OK;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (f_0 == 0 || f_1 == 0) {
|
|
Shinya Kitaoka |
120a6e |
x = (f_1 == 0.0) ? x1 : x0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double x_n = x1, x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < maxIter; ++i) {
|
|
Shinya Kitaoka |
120a6e |
double den = f1(x_n);
|
|
Shinya Kitaoka |
120a6e |
if (den > 1e-2) x_n_plus_1 = x_n - f_x_n / den;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (den <= 1e-2 || x0 > x_n_plus_1 || x1 < x_n_plus_1)
|
|
Shinya Kitaoka |
120a6e |
x_n_plus_1 = 0.5 * (x0 + x1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (fabs(x_n - x_n_plus_1) < xtol) {
|
|
Shinya Kitaoka |
120a6e |
err = FZ_XTOL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
f_x_n_plus_1 = f(x_n_plus_1);
|
|
Shinya Kitaoka |
120a6e |
if (fabs(f_x_n_plus_1) < ftol) {
|
|
Shinya Kitaoka |
120a6e |
err = FZ_FTOL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
x_n = x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
f_x_n = f_x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
s_n = (f_x_n > 0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (s_n == s_0)
|
|
Shinya Kitaoka |
120a6e |
x0 = x_n;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
x1 = x_n;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
x = x_n_plus_1;
|
|
Shinya Kitaoka |
120a6e |
err = (i == maxIter ? FZ_MAX_ITER : err);
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|