// ----------------------------------------------------------------------------
//
// Copyright (C) Columbia University, 1994. All Rights Reserved.
// Sameer A. Nene, Shree K. Nayar, Hiroshi Murase
//
// See file LICENSE for details of software license agreement.
//
// ----------------------------------------------------------------------------
//
// fullsearch.C
//
// Author:               Sameer Nene
// Date:                 05/26/94
// Version:              1.0
// Modification History:
//   06/26/94: Changes necessary because of change in interface.
//   08/18/94: Fixed bug which was not copying dimensionality info. to dataset
//             inside FullSearch
//   04/09/96: Fixed for scoping problems for compatibility with ANSI C++
//
// Bugs:
//
// Classes:
//   FullSearch
//
// Notes:
//   This module contains implementation of classes declared in fullsearch.h
//
// ----------------------------------------------------------------------------

#include <stdio.h>
#include <values.h>
#include "errorscope.h"
#include "registry.h"
#include "persistent.h"
#include "vector.h"
#include "dataset.h"
#include "persscheme.h"
#include "fullsearch.h"

void* FullSearch::d_protocol = (void*)(&FullSearch::d_protocol);
char* FullSearch::d_name_p = "FullSearch";
Registrar FullSearch::d_registrar(FullSearch::d_name_p,
				  &(FullSearch::createFunc));
				  
Persistent* FullSearch::createFunc()
{
  return new FullSearch;
}

int FullSearch::hasProtocol(void* protocol) const
{
  return d_protocol == protocol || PersistentSearchScheme::hasProtocol(protocol);
}

FullSearch::FullSearch(const DataSet &ds, const Vector &rangemin,
		       const Vector &rangemax) :
		       d_data(ds.getSize(), ds().getSize()),
		       d_rangemin(rangemin), d_rangemax(rangemax)
{
  int i, j;
  const VectAry &vaSrc = ds();
  VectAry &vaDst = d_data();
  
  for(i = 0, j = vaSrc.getSize(); i < j; ++i)
    vaDst[i] = vaSrc[i];
  for(i = 0, j = ds.getSize(); i < j; ++i)
    d_data.setSize(i, ds.getSize(i));
}

FullSearch* FullSearch::safeCast(Persistent *p)
{
  return p -> hasProtocol(d_protocol) ? (FullSearch*)p : 0;
}

Vector FullSearch::search(const Vector &v) const
{
  int i, j, k, n;
  double min = MAXDOUBLE, t;
  Vector r(d_data.getSize());
  VectAry &va = d_data();

  for(i = 0, j = va.getSize(); i < j; ++i)
    if((t = va[i].distance(v)) < min) {
      min = t;
      n = i;
    }

  for(i = 0, j = d_data.getSize(), k = 1; i < j; k *= d_data.getSize(i++));

  for(i = 0; i < j; ++i) {
    k /= d_data.getSize(i);
    r.element(i, (n / k) * (d_rangemax.element(i) - d_rangemin.element(i)) /
	      (d_data.getSize(i) - 1.) + d_rangemin.element(i));
    n %= k;
  }
  
  return r;
}

ErrorScope::Error FullSearch::get(FILE *file)
{
  ErrorScope::Error error;
  
  if((error = d_rangemin.get(file)) != OK)
    return error;
  
  if((error = d_rangemax.get(file)) != OK)
    return error;

  if((error = d_data.get(file)) != OK)
    return error;

  return OK;
}

ErrorScope::Error FullSearch::put(FILE *file) const
{
  ErrorScope::Error error;
  
  if((error = d_rangemin.put(file)) != OK)
    return error;
  
  if((error = d_rangemax.put(file)) != OK)
    return error;

  if((error = d_data.put(file)) != OK)
    return error;

  return OK;
}

const char* FullSearch::name() const
{
  return d_name_p;
}

const VectAry& FullSearch::getData() const
{
  return d_data();
}
