/******************************************************************************
* NOMAD -  Nonlinear Optimization for Mixed vAriables and Derivatives.        *
* Copyright (C) 2001-2004  Gilles Couture - Ecole Polytechnique,              *
*                          Charles Audet - Ecole Polytechnique,               *
*		           John Dennis - Rice University.                     *
*                                                                             *
* Author: Gilles Couture                                                      *
* École Polytechnique de Montréal - GERAD                                     *
* C.P. 6079, Succ. Centre-ville, Montréal (Québec) H3C 3A7 Canada             *
* Tel:  (514) 340-6053 x6928                                                  *
* Email: Gilles.Couture@gerad.ca                                              *
* Fax: (514) 340-5665                                                         *
*                                                                             *
* This program is free software; you can redistribute it and/or               *
* modify it under the terms of the GNU General Public License                 *
* as published by the Free Software Foundation. You can find the              *
* GNU General Public License at:                                              *
*             http://www.gnu.org/copyleft/gpl.html                            *
*                                                                             *
* This program is distributed in the hope that it will be useful,             *
* but WITHOUT ANY WARRANTY; without even the implied warranty of              *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
* GNU General Public License for more details.                                *
*                                                                             *
* You should have received a copy of the GNU General Public License           *
* along with this program; if not, write to the Free Software                 *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. *
*                                                                             *
* You can find information on the NOMAD software at:                          *
*             http://www.gerad.ca/NOMAD/                                      *
******************************************************************************/

// point.cpp -- Point class methods.

#include <fstream>
#include <iostream>
using namespace std;
#include "defines.h"
#include "point.h"

// Constructor used to build the starting point.
Point::Point(const int dim, const double * coord, const double * scales_add,
	     const double * scales_mult)
  : dimension(dim)
{
  // The coordinates array is created.
  coordinates = new double[dimension];
  // The coordinates array of the starting point is scaled.
  for (int i = 0; i < dimension; i++)
    coordinates[i] = (coord[i] / scales_mult[i]) + scales_add[i];
}

// Constructor used to build most points in the program.
Point::Point(const int dim, const double * coord)
  : dimension(dim)
{
  // The coordinates array is created.
  coordinates = new double[dimension];
  // The coordinates array is copied.
  for (int i = 0; i < dimension; i++)
    coordinates[i] = coord[i];
}

// Copy constructor: used to build the points in the filter.
Point::Point(const Point & p)
  : dimension(p.dimension)
{
  // The coordinates array is created.
  coordinates = new double[dimension];
  // The coordinates array is copied.
  for (int i = 0; i < dimension; i++)
    coordinates[i] = p.coordinates[i];
}

// Destructor. The memory allocated for the array is freed.
Point::~Point()
{
  // cout << "Destroying point...\n";
  delete [] coordinates;
}

// This method overloads the '<' operator.
bool Point::operator<(const Point & p) const
{
  // If the object is compared to itself the return value is false.
  if (this == &p)
    return false;

  // The points are compared in this loop.
  for (int i = 0; i < dimension; i++)
    {
      // If 'this' coordinate is less than point p's coordinate,
      // true is returned.
      if (coordinates[i] < p.coordinates[i])
	return true;
      else
	// If 'this' coordinate is greater than point p's coordinate,
	// false is returned.
	if (coordinates[i] > p.coordinates[i])
	  return false;
    }

  // If the loop ended it means that the points are the same.
  return false;
}

// This method overloads the assignment operator.
Point & Point::operator=(const Point & p)
{
  // If the object is assigned to itself, nothing is done.
  if (this == &p)
    return *this;

  // If the dimensions are different, the coordinates array is freed, then
  // rebuilt.
  if (dimension != p.dimension)
    {
      delete [] coordinates;
      dimension = p.dimension;
      coordinates = new double[dimension];
    }

  // The coordinates array is copied.
  for (int i = 0; i < dimension; i++)
    coordinates[i] = p.coordinates[i];

  // A reference to the invoking object is returned.
  return *this;
}

// This method outputs the point in the history file.
void Point::showHistory(ofstream & fout, const double * scales_add,
			const double * scales_mult) const
{
  // Check to see if the file is open.
  if (!fout.is_open())
    return;

  // The point is written, unscaled, in the history file.
  for (int i = 0; i < dimension; i++)
    fout << (coordinates[i] - scales_add[i]) * scales_mult[i] << "\t";
}

// This method outputs the point in the result file and the best point file.
void Point::showResults(ofstream & fout, const double * scales_add,
			const double * scales_mult) const
{
  // Check to see if the file is open.
  if (!fout.is_open())
    return;

	int i;
	// This file will contain the best point found during the run.
	ofstream fbest("LIBRARY/best_point.txt");
	
  // The point is written, unscaled, in the results file. It's written in the
  // form: (x1, x2, ..., xn)
  fout << "(";
  for (i = 0; i < dimension - 1; i++)
		fout << (coordinates[i] - scales_add[i]) * scales_mult[i]  << ", ";
  fout << (coordinates[dimension - 1] - scales_add[i]) * scales_mult[i] << ")\n";
	
	for (i = 0; i < dimension; i++)
		fbest << coordinates[i] << "\t";
	fbest << endl;
	
	// The file is closed.
	fbest.close();
}

// Non-member functions.
// ****************************************************************************

// This method outputs this object's attributes.
ostream & operator<<(ostream & os, const Point & p)
{
  // The coordinates are written in scaled form. This is useful for debugging.
  // They're written as follow: 'Scaled coordinates: (x1, x2, ..., xn)'
  os << "(";
  for (int i = 0; i < p.dimension - 1; i++)
    os << p.coordinates[i] << ", ";
  os << p.coordinates[p.dimension - 1] << ")";

  return os;
}
