aboutsummaryrefslogtreecommitdiffstats
path: root/methods/linmin/mnbrak.hpp
blob: 9871473cf313dc21be97289e46c695d5d355d2a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifndef MNBRAK_HPP
#define MNBRAK_HPP 
#define OPT_HEADER
//#include "optimizer.hpp"
#include "bas_util.hpp"
namespace opt_utilities
{

  
  template <typename T>
  void mnbrak(T& ax,T& bx,T& cx,T& fa,T& fb,T& fc,func_obj<T,T>& func)
  {
    const T GOLD=1.618034;
    const T GLIMIT=100;
    const T TINY=std::numeric_limits<T>::epsilon();
    T ulim,u,r,q,fu;
    fa=func.eval(ax);
    fb=func.eval(bx);
    
    if(fb>fa)
      {
	//shft(dum,ax,bx,dum);
	//shft(dum,fb,fa,dum);
	std::swap(ax,bx);
	std::swap(fa,fb);
      }

    cx=bx+GOLD*(bx-ax);
    fc=func.eval(cx);
    while(fb>fc)
      {
	r=(bx-ax)*(fb-fc);
	q=(bx-cx)*(fb-fa);
	u=bx-T((bx-cx)*q-(bx-ax)*r)/
	  T(T(2.)*sign(T(max(T(tabs(T(q-r))),T(TINY))),T(q-r)));
	ulim=bx+GLIMIT*(cx-bx);
	if((bx-u)*(u-cx)>0.)
	  {
	    fu=func.eval(u);
	    if(fu<fc)
	      {
		ax=bx;
		bx=u;
		fa=fb;
		fb=fu;
		return;
	      }
	    else if(fu>fb)
	      {
		cx=u;
		fc=fu;
		return;
	      }
	    u=cx+GOLD*(cx-bx);
	    fu=func.eval(u);
	  }
	else if((cx-u)*(u-ulim)>0.)
	  {
	    fu=func.eval(u);
	    if(fu<fc)
	      {
		shft3(bx,cx,u,T(cx+GOLD*(cx-bx)));
		shft3(fb,fc,fu,func.eval(u));
	      }
	  }
	else if((u-ulim)*(ulim-cx)>=0)
	  {
	    u=ulim;
	    fu=func.eval(u);
	  }
	else
	  {
	    u=cx+GOLD*(cx-bx);
	    fu=func.eval(u);
	  }
	shft3(ax,bx,cx,u);
	shft3(fa,fb,fc,fu);
      }
  }
}

#endif