#include "head.h"
#include "maxmeasure.h"

/* Calculates $m[(x\oplus G)\setminus(X\oplus G)]$ */
void maxmeasure(long i,           /* Label of point x */
		long length,        /* Number of points in process */
		double *maxmeasure, /* Returns 
				       $m[(x\oplus G)\setminus(X\oplus G)]$ */
		location points[]   /* All info for all the points */
	     )
{
  long temp,size,j,nextcount,counter;
  long lastcount,llastcount,lchild,rightdad;

  *maxmeasure=9;
  temp=length;
/* Find out length of a row */
  for(size=0;temp>0;++size)
    temp -= pow(2,(double) size);
  size -= 1;

/* Deal with bottom row first */
  lastcount=-1;
  counter = pow(2,(double) size)-1;
  nextcount=counter+pow(2,(double) size-1);
  if(i==0){
    *maxmeasure -= 4;

    if(points[0].XplusG.max > 0)
      --*maxmeasure;

    if(points[1].XplusG.max > 0)
      --*maxmeasure;

    if(points[counter].XplusG.max > 0)
      --*maxmeasure;

    if(points[counter+1].XplusG.max > 0)
      --*maxmeasure;

    if(points[nextcount].XplusG.max > 0)
      --*maxmeasure;
  }

/* Bottom row minus end points. */
  else if(1<=i && i<counter){
    rightdad=counter+1+(i+(i%2))/2;
    *maxmeasure -= 4;

    if(points[i].XplusG.max > 0)
      --*maxmeasure;

    if(points[i-1].XplusG.max > 0)
      --*maxmeasure;

    if(points[i+1].XplusG.max > 0)
      --*maxmeasure;

    if(points[rightdad-1].XplusG.max > 0)
      --*maxmeasure;

    if(points[rightdad].XplusG.max > 0)
      --*maxmeasure;
  }

  else if(i==counter){
    *maxmeasure -= 4;

    if(points[0].XplusG.max > 0)
      --*maxmeasure;

    if(points[counter-1].XplusG.max > 0)
      --*maxmeasure;

    if(points[counter].XplusG.max > 0)
      --*maxmeasure;

    if(points[counter+1].XplusG.max > 0)
      --*maxmeasure;

    if(points[nextcount].XplusG.max > 0)
      --*maxmeasure;
  }

/* The middle bit. */
  else{
    for(j=1;j<size-1;++j){
      llastcount=lastcount;
      lastcount=counter;
      counter=nextcount;
      nextcount+=pow(2,(double) (size-j-1));

      if(i==lastcount+1){
	if(points[lastcount+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lastcount+2].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lastcount].XplusG.max > 0)
	  --*maxmeasure;

	if(points[counter].XplusG.max > 0)
	  --*maxmeasure;

	if(points[llastcount+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[llastcount+2].XplusG.max > 0)
	  --*maxmeasure;

	if(points[llastcount+3].XplusG.max > 0)
	  --*maxmeasure;

	if(points[counter+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[nextcount].XplusG.max > 0)
	  --*maxmeasure;
      }

/* The middle bit minus end points. */
      else if(i>=(lastcount+2) && i<counter){
	rightdad=counter+1+(i-lastcount-1+(i%2))/2;
	lchild=llastcount+(i-lastcount)*2-1;

	if(points[i-1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[i+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[rightdad-1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[rightdad].XplusG.max > 0)
	  --*maxmeasure;

	if(points[i].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lchild].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lchild+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lchild+2].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lchild-1].XplusG.max > 0)
	  --*maxmeasure;
      }

      else if(i==counter){
	if(points[lastcount+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[counter-1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lastcount].XplusG.max > 0)
	  --*maxmeasure;

	if(points[counter].XplusG.max > 0)
	  --*maxmeasure;

	if(points[llastcount+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lastcount-1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[lastcount-2].XplusG.max > 0)
	  --*maxmeasure;

	if(points[counter+1].XplusG.max > 0)
	  --*maxmeasure;

	if(points[nextcount].XplusG.max > 0)
	  --*maxmeasure;
      }
    }
/* Finally, deal with the last three points. */
    llastcount=lastcount;
    lastcount=counter;
    counter=nextcount;
    nextcount+=pow(2,(double) (size-j-1));
    if(i==lastcount+1||i==counter){
      *maxmeasure -= 2;

      if(points[lastcount+1].XplusG.max > 0)
	--*maxmeasure;

      if(points[lastcount].XplusG.max > 0)
	--*maxmeasure;

      if(points[counter].XplusG.max > 0)
	--*maxmeasure;

      if(points[llastcount+1].XplusG.max > 0)
	--*maxmeasure;

      if(points[llastcount+2].XplusG.max > 0)
	--*maxmeasure;

      if(points[llastcount+3].XplusG.max > 0)
	--*maxmeasure;

      if(points[nextcount].XplusG.max > 0)
	--*maxmeasure;
    }

    else if(i==nextcount){
      *maxmeasure -= 6;

      if(points[nextcount].XplusG.max > 0)
	--*maxmeasure;

      if(points[counter].XplusG.max > 0)
	--*maxmeasure;

      if(points[lastcount+1].XplusG.max > 0)
	--*maxmeasure;
    }
  }
}
