#include "tree.h"
#include "dist.h"
#include "minint.h"
#include <stdlib.h>

#define min(a,b) (((a)<(b))?(a):(b))

double mininter(             /* Calculates the minimum inter-point distance 
				without edge correction */
		coord *points,       /* An array of positions */
		int n)               /* Number of points */
{
  int i,j;
  double estimate=5000.0;      /* Current estimate min-inter */
  double dist;       /* Euclidean distance between two points */

  if(points == NULL)
    return 0.0;

  for(i=n; i>0; --i){
    for(j=i-1; j>0; --j){
      dist=edist(points+i-1,points+j-1);
      if(dist<=estimate){
	estimate=dist;
      }
    }
  }

  return estimate;
}

double mininter_tor(      /* Calculates min-inter on a torus */
		    coord *points,       /* An array of positions */
		    int n,               /* Number of points */
		    double a,            /* Length of box in x-direction */
		    double b)            /* Length of box in y-direction */
{
  int i,j;
  double estimate=5000.0;      /* Current estimate of min-inter */
  double dist;       /* Euclidean distance between two points */

  if(points == NULL)
    return 0.0;

  for(i=n; i>0; --i){
    for(j=i-1; j>0; --j){
      dist=tdist(points+i-1,points+j-1,a,b);
      if(dist<estimate){
	estimate=dist;
      }
    }
  }

  return estimate;
}

double secinter(             /* Calculates the second smallest inter-point 
				distance without edge correction */
		coord *points,       /* An array of positions */
		int n)               /* Number of points */
{
  int i,j;
  double min=5000.0;      /* Current estimate of min-inter */
  double min2=5000.0;      /* Current estimate of sec-inter */
  double dist;       /* Euclidean distance between two points */

  if(points == NULL)
    return 0.0;

  for(i=n; i>0; --i){
    for(j=i-1; j>0; --j){
      dist=edist(points+i-1,points+j-1);
      if(dist<=min){
	min2=min;
	min=dist;
      }
      else if(dist<min2){
	min2=dist;
      }
    }
  }

  return min2;
}

double secinter_tor(      /* Calculates sec-inter on a torus */
		    coord *points,       /* An array of positions */
		    int n,               /* Number of points */
		    double a,            /* Length of box in x-direction */
		    double b)            /* Length of box in y-direction */
{
  int i,j;
  double min=5000.0;      /* Current estimate of min-inter */
  double min2=5000.0;     /* Current estimate of sec-inter */
  double dist;       /* Euclidean distance between two points */

  if(points == NULL)
    return 0.0;

  for(i=n; i>0; --i){
    for(j=i-1; j>0; --j){
      dist=tdist(points+i-1,points+j-1,a,b);
      if(dist<=min){
	min2=min;
	min=dist;
      }
      else if(dist<min2){
	min2=dist;
      }
    }
  }

  return min2;
}

void inter(             /* Calculates the 1st, 2nd, 3rd and 4th smallest 
			   inter-point distances without edge correction */
	   coord *points,       /* An array of positions */
	   int n,               /* Number of points */
	   double *first,
	   double *second,
	   double *third,
	   double *fourth)
{
  int i,j;
  double min=5000.0;      /* Current estimate of min-inter */
  double min2=5000.0;      /* Current estimate of sec-inter */
  double min3=5000.0;      /* Current estimate of thi-inter */
  double min4=5000.0;      /* Current estimate of fou-inter */
  double dist;       /* Euclidean distance between two points */

  if(points == NULL)
    return;

  for(i=n; i>0; --i){
    for(j=i-1; j>0; --j){
      dist=edist(points+i-1,points+j-1);
      if(dist<=min){
	min4=min3;
	min3=min2;
	min2=min;
	min=dist;
      }
      else if(dist<=min2){
	min4=min3;
	min3=min2;
	min2=dist;
      }
      else if(dist<=min3){
	min4=min3;
	min3=dist;
      }
      else if(dist<min4){
	min4=dist;
      }
    }
  }
  *first=min;
  *second=min2;
  *third=min3;
  *fourth=min4;
}

void inter_tor(             /* Calculates the 1st, 2nd, 3rd and 4th smallest 
			       inter-point distances on a torus */
	       coord *points,       /* An array of positions */
	       int n,               /* Number of points */
	       double a,            /* Length of box in x-direction */
	       double b,            /* Length of box in y-direction */
	       double *first,
	       double *second,
	       double *third,
	       double *fourth)
{
  int i,j;
  double min=5000.0;      /* Current estimate of min-inter */
  double min2=5000.0;      /* Current estimate of sec-inter */
  double min3=5000.0;      /* Current estimate of thi-inter */
  double min4=5000.0;      /* Current estimate of fou-inter */
  double dist;       /* Euclidean distance between two points */

  if(points == NULL)
    return;

  for(i=n; i>0; --i){
    for(j=i-1; j>0; --j){
      dist=tdist(points+i-1,points+j-1,a,b);
      if(dist<=min){
	min4=min3;
	min3=min2;
	min2=min;
	min=dist;
      }
      else if(dist<=min2){
	min4=min3;
	min3=min2;
	min2=dist;
      }
      else if(dist<=min3){
	min4=min3;
	min3=dist;
      }
      else if(dist<min4){
	min4=dist;
      }
    }
  }
  *first=min;
  *second=min2;
  *third=min3;
  *fourth=min4;
}
