00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef MORE_NONLINEAR_H
00032 #define MORE_NONLINEAR_H
00033
00034 #include <utility>
00035 #include <stdexcept>
00036 #include <cmath>
00037
00038 namespace more {
00039 namespace num {
00040
00041 template<typename T, typename Function>
00042 std::pair<T, bool>
00043 bisection_root(Function f, T xl, T xh, T precx, T precf, int maxit=128) {
00044 maxit /= 8;
00045 const bool signl = f(xl) > 0;
00046 T fm, xm;
00047 if(signl == (f(xh) > 0))
00048 throw std::logic_error("bisection_roots: f(xl)*f(xh) > 0");
00049 do {
00050 xm = .5*(xl+xh);
00051 if((f(xm) > 0) == signl) xl = xm; else xh = xm;
00052 xm = .5*(xl+xh);
00053 if((f(xm) > 0) == signl) xl = xm; else xh = xm;
00054 xm = .5*(xl+xh);
00055 if((f(xm) > 0) == signl) xl = xm; else xh = xm;
00056 xm = .5*(xl+xh);
00057 if((f(xm) > 0) == signl) xl = xm; else xh = xm;
00058 xm = .5*(xl+xh);
00059 if((f(xm) > 0) == signl) xl = xm; else xh = xm;
00060 xm = .5*(xl+xh);
00061 if((f(xm) > 0) == signl) xl = xm; else xh = xm;
00062 xm = .5*(xl+xh);
00063 if((f(xm) > 0) == signl) xl = xm; else xh = xm;
00064 xm = .5*(xl+xh);
00065 fm = f(xm);
00066 if(xm == xh || xm == xl) break;
00067 if(!--maxit) return std::pair<T, bool>(xm, false);
00068 if((fm > 0) == signl) xl = xm; else xh = xm;
00069 } while(std::fabs(fm) > precf || std::fabs(xh-xl) > precx);
00070 return std::pair<T, bool>(xm, true);
00071 }
00072
00073 template<typename T, typename Function, typename OutputIterator>
00074 std::pair<OutputIterator, bool>
00075 bisection_roots(Function f, T xl, T xh, T dx, int n,
00076 T precx, T precf, OutputIterator it_out) {
00077 bool isconv = true;
00078 bool signdx = dx > 0;
00079 bool signl = f(xl) > 0;
00080 while((xl < xh) == signdx) {
00081 xl += dx;
00082 bool signm = f(xl) > 0;
00083 if(signl != signm) {
00084 std::pair<T, bool>
00085 root = bisection_root(f, xl-dx, xl, precx, precf);
00086 isconv = isconv && root.second;
00087 (*it_out) = root.first;
00088 ++it_out;
00089 signl = signm;
00090 }
00091 }
00092 return std::pair<OutputIterator, bool>(it_out, isconv);
00093 }
00094
00095 template<typename T, typename Function, typename OutputIterator>
00096 std::pair<OutputIterator, bool>
00097 bisection_roots(Function f, T xl, T xh, T dx, int n,
00098 OutputIterator it_out) {
00099 return bisection_roots(f, xl, xh, dx, n, 0.0, 1.0, it_out);
00100 }
00101 }}
00102
00103 #endif