00001 #ifndef TOON_BRENT_H
00002 #define TOON_BRENT_H
00003 #include <TooN/TooN.h>
00004 #include <TooN/helpers.h>
00005 #include <limits>
00006 #include <cmath>
00007 #include <cstdlib>
00008 #include <iomanip>
00009
00010
00011 namespace TooN
00012 {
00013 using std::numeric_limits;
00014
00029 template<class Functor, class Precision> Vector<2, Precision> brent_line_search(Precision a, Precision x, Precision b, Precision fx, const Functor& func, int maxiterations, Precision tolerance = sqrt(numeric_limits<Precision>::epsilon()), Precision epsilon = numeric_limits<Precision>::epsilon())
00030 {
00031 using std::min;
00032 using std::max;
00033
00034 using std::abs;
00035
00036
00037 const Precision g = (3.0 - sqrt(5))/2;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 Precision w=x, v=x, fw=fx, fv=fx;
00055
00056 Precision d=0, e=0;
00057 int i=0;
00058
00059 while(abs(b-a) > (abs(a) + abs(b)) * tolerance + epsilon && i < maxiterations)
00060 {
00061 i++;
00062
00063 const Precision xm = (a+b)/2;
00064
00065
00066 const Precision tol1 = abs(x)*tolerance + epsilon;
00067
00068
00069
00070
00071
00072 if(abs(e) > tol1 && w != v)
00073 {
00074
00075
00076
00077
00078
00079
00080
00081 const Precision fxw = fw - fx;
00082 const Precision fxv = fv - fx;
00083 const Precision xw = w-x;
00084 const Precision xv = v-x;
00085
00086
00087
00088
00089
00090
00091
00092
00093 const Precision p = fxv*xw*xw - fxw*xv*xv;
00094 const Precision q = 2*(fxv*xw - fxw*xv);
00095
00096
00097
00098
00099
00100 if(q == 0 || x + p/q < a || x+p/q > b || abs(p/q) > abs(e/2))
00101 {
00102
00103
00104 if(x > xm)
00105 e = a-x;
00106 else
00107 e = b-x;
00108
00109 d = g*e;
00110 }
00111 else
00112 {
00113
00114 e = d;
00115 d = p/q;
00116 }
00117 }
00118 else
00119 {
00120
00121
00122 if(x > xm)
00123 e = a-x;
00124 else
00125 e = b-x;
00126
00127 d = g*e;
00128 }
00129
00130 const Precision u = x+d;
00131
00132 const Precision fu = func(u);
00133
00134 if(fu < fx)
00135 {
00136
00137
00138
00139 if(u > x)
00140 a = x;
00141 else
00142 b = x;
00143
00144
00145 v=w; fv = fw;
00146 w=x; fw = fx;
00147 x=u; fx = fu;
00148 }
00149 else
00150 {
00151
00152
00153 if(u < x)
00154 a = u;
00155 else
00156 b = u;
00157
00158 if(fu <= fw || w == x)
00159 {
00160
00161 v = w; fv = fw;
00162 w = u; fw = fu;
00163 }
00164 else if(fu <= fv || v==x || v == w)
00165 {
00166
00167 v = u; fv = fu;
00168 }
00169 }
00170 }
00171
00172 return makeVector(x, fx);
00173 }
00174 }
00175 #endif