
//   Various datastructures and functions used by the global optimizer

#ifndef TOOLS_H
#define TOOLS_H

#include <float.h>
#include <iostream>

#include <algorithm>
#include <iterator>
#include <list>

#include "linalg.h"

#ifndef FALSE
const int FALSE=(1==0); // boolean FALSE
#endif
#ifndef FALSE
const int TRUE=(1==1); // boolean TRUE
#endif

typedef const class Trial CTrial;
typedef CTrial& RCTrial;
typedef CTrial* PCTrial;

class Trial{
public:
  RVector xvals;
  double objval;

  Trial();
  Trial(int);
  Trial(RCTrial); // Copy constructor
  RCTrial operator=(RCTrial) ; // assignment operator
  friend ostream & operator << (ostream &, RCTrial) ;
};

#if (!defined(_MSC_VER) && (__cplusplus < 201103L)) || (defined(_MSC_VER) && (_MSVC_LANG < 201103L))
class TrialGT : public unary_function<Trial, bool>
#else
class TrialGT
#endif
// Predicate for Trial (needed for remove_if)
{
public:
  explicit TrialGT(double val) : _val(val) {}
  bool operator()(Trial& foo) { 
    return foo.objval > _val;
  }
private:
  double _val;
};

typedef class VBox& RVBox;
typedef const class VBox CVBox;
typedef CVBox* PCVBox;
typedef CVBox& RCVBox;

class VBox{
public:
  RVector lb, ub;

  VBox();        // Construct a box
  VBox(int);
  VBox(RCVBox);  // Copy constructor
  RCVBox operator=(RCVBox);      // assignment operator

  int GetDim();                  // Returns the dimension of the box
  double Width(int) ;            // Returns the width of the i-th interval
  void Midpoint(RCRVector);      // Returns the midpoint

  friend ostream & operator << (ostream &, const VBox &);
};

typedef class TBox& RTBox;
typedef const class TBox CTBox;
typedef CTBox* PCTBox;
typedef CTBox& RCTBox;

class TBox: public VBox {
public:
  double minf;   // Smallest function value found so far
  list<Trial> TList; // List of trials

  TBox();        // Construct a box
  TBox(int);
  TBox(RCTBox);  // Copy constructor

  RCTBox operator=(RCTBox);      // assignment operator

  double GetMin();               // Returns 'minf'
  bool EmptyBox();               // Returns TRUE if Box contains no trials
  void AddTrial(RCTrial);        // Add a trial to the (back of) box
  void RemoveTrial(Trial &);     // Remove a trial from the (back of) box
  void GetLastTrial(Trial &);    // Return a trial from the back of the box

  list<Trial>::const_iterator FirstTrial();
  list<Trial>::const_iterator LastTrial();

  void GetTrial(list<Trial>::const_iterator, Trial&);
  void ClearBox();            
  bool CloseToMin(RVector&, double*, double);

  int NStationary();      // Returns the number of stationary points

  void split(RTBox, RTBox);     // Split a box
  void dispTrials();

  bool InsideBox(RCRVector);
  int  OutsideBox(RCRVector, RCTBox);
  double ShortestSide(int*);    // Returns the shortest side
  double LongestSide(int*);     // Returns the longest side
  double ClosestSide(RCRVector x);
  double FarthestSide(RCRVector x);
  bool Intersection(RCRVector, RCRVector, RCRVector);
  double LowerBound(double);

  bool operator<(const TBox & x) const {return (minf>x.minf);}
  friend ostream & operator << (ostream &, const TBox &);
};

#endif
