/**********************************************
	ksort.c 
	  sort program presented by E.Kokubo

***********************************************/
#include "./sticky.h"
/* (original form)
void sort_particles(first, last, particle, index)
int first, last;
particle_data particle[];
int index[];
{
  double ref_dt;
  int ref_index;
  int i, j;
  int tmp;

  ref_index = (first + last)/2;
  ref_dt = particle[index[ref_index]].dt;

  i = first;
  j = last;

  for( ; ; ){
    while(particle[index[i]].dt < ref_dt) i++;
    while(particle[index[j]].dt > ref_dt) j--;
    if(i >= j) break;
    tmp = index[i];
    index[i] = index[j];
    index[j] = tmp;
    i++;
    j--;
  }
  if (first < i-1) sort_particles(first, i-1, particle, index);
  if (j+1 < last) sort_particles(j+1, last, particle, index);
}
*/

void sort_timestep(first, last, value1, value2,index)
int first, last;
REAL value1[];
REAL value2[];
int index[];
{
  double ref_value;
  int ref_index;
  int i, j;
  int tmp,tmplast;

  tmplast = last;		

  ref_index = (first + last)/2;
  ref_value = value1[index[ref_index]]+value2[index[ref_index]];

  i = first;
  j = last;

  for( ; ; ){
    while((value1[index[i]]+value2[index[i]]) < ref_value) i++;
    while((value1[index[j]]+value2[index[j]]) > ref_value) j--;
    if(i >= j) break;
    tmp = index[i];
    index[i] = index[j];
    index[j] = tmp;
    i++;
    j--;
  }
  if (first < i-1) sort_timestep(first, i-1, value1,value2, index);
  if (j+1 < last) sort_timestep(j+1, last, value1,value2, index);

/*printf("last %e\n",tmplast);
for(i=0;i<=tmplast;i++){
printf("i ti dti %d %d %e %e %e\n",i,index[i],value1[index[i]],value2[index[i]],(value1[index[i]]+value2[index[i]]));
}
*/

}

void sort_timestep_m(first, last, value1, index)
int first, last;
REAL value1[];
int index[];
{
  double ref_value;
  int ref_index;
  int i, j;
  int tmp,tmplast;

  tmplast = last;		

  ref_index = (first + last)/2;
  ref_value = value1[index[ref_index]];

  i = first;
  j = last;

  for( ; ; ){
    while(value1[index[i]] < ref_value) i++;
    while(value1[index[j]] > ref_value) j--;
    if(i >= j) break;
    tmp = index[i];
    index[i] = index[j];
    index[j] = tmp;
    i++;
    j--;
  }
  if (first < i-1) sort_timestep_m(first, i-1, value1, index);
  if (j+1 < last) sort_timestep_m(j+1, last, value1, index);

/*printf("last %e\n",tmplast);
for(i=0;i<=tmplast;i++){
printf("i ti dti %d %d %e %e %e\n",i,index[i],value1[index[i]],value2[index[i]],(value1[index[i]]+value2[index[i]]));
}
*/

}

void make_timestep_list(n, dti, index, bl_list,dt0)
int n;
REAL dti[];
int index[];
int bl_list[100];
REAL *dt0;
{
	int i=0,ibl=0,n_block; 	
	REAL dtmax,log10();
	sort_timestep_m(0,n-1,dti,index);
	
	*dt0 = dti[index[0]];
	dtmax = dti[index[n-1]];
	n_block = (int)(log10(dtmax / *dt0)/log10(2.0));
/*printf("nblock %d %e %e \n",n_block,dtmax,*dt0);*/
	i=0;	
	for(ibl=0;ibl<n_block;ibl++){
	  for(;dti[index[i]]== *dt0 *pow(2.0,(double)(ibl));i++);
	  bl_list[ibl] = i-1;
	}
	bl_list[n_block] = n-1;

	for(i=0;i<n;i++) printf("i index dti %d %d %e \n",i,index[i],dti[index[i]]);
	for(i=0;i<7;i++) printf("i bl_list %d %d\n",i,bl_list[i]);

}

void sort_particles(first, last, value, index)
int first, last;
REAL value[];
int index[];
{
  double ref_value;
  int ref_index;
  int i, j;
  int tmp;

  ref_index = (first + last)/2;
  ref_value = value[index[ref_index]];

  i = first;
  j = last;

  for( ; ; ){
    while(value[index[i]] < ref_value) i++;
    while(value[index[j]] > ref_value) j--;
    if(i >= j) break;
    tmp = index[i];
    index[i] = index[j];
    index[j] = tmp;
    i++;
    j--;
  }
  if (first < i-1) sort_particles(first, i-1, value, index);
  if (j+1 < last) sort_particles(j+1, last, value, index);
}

void sort_value(first, last, value)
int first, last;
REAL value[];
{
  double ref_value;
  int ref_index;
  int i, j;
  REAL tmp;

  ref_index = (first + last)/2;
  ref_value = value[ref_index];

  i = first;
  j = last;

  for( ; ; ){
    while(value[i] < ref_value) i++;
    while(value[j] > ref_value) j--;
    if(i >= j) break;
    tmp = value[i];
    value[i] = value[j];
    value[j] = tmp;
    i++;
    j--;
  }
  if (first < i-1) sort_value(first, i-1, value);
  if (j+1 < last) sort_value(j+1, last, value);
}

void sort_two_values(first, last, value, value2)
int first, last;
REAL value[];
int value2[];
{
  double ref_value;
  int ref_index;
  int i, j;
  REAL tmp;
  int itmp;

  ref_index = (first + last)/2;
  ref_value = value[ref_index];

  i = first;
  j = last;

  for( ; ; ){
    while(value[i] < ref_value) i++;
    while(value[j] > ref_value) j--;
    if(i >= j) break;
    tmp = value[i];
    value[i] = value[j];
    value[j] = tmp;
    itmp = value2[i];
    value2[i] = value2[j];
    value2[j] = itmp;
    i++;
    j--;
  }
  if (first < i-1) sort_two_values(first, i-1, value,value2);
  if (j+1 < last) sort_two_values(j+1, last, value,value2);
}
void swap_index(index1,index2)
int *index1;
int *index2;
{
	int tmp;
	
	tmp = *index1;
	*index1 = *index2;
	*index2 = tmp;
}

void correct_bl_list(i,ibl,dt0,dtmax,index,bl_list)		
int i;
int ibl;
REAL *dt0;
REAL dtmax;
int index[];
int bl_list[];
{
	int n_block,j;

	swap_index(&index[i],&index[0]);
	
/*	n_block = (int)(log2(dtmax/ *dt0));*/
	for(j=n_block;j>=(-ibl);j--){
	  bl_list[j-ibl] = bl_list[j];
	}
	for(j=0;j<(-ibl);j++) bl_list[j] = 0;
	*dt0 *= pow(2.0,(double)(ibl)); 
}

void mod_timestep_list(i,index,dti,olddti,bl_list,dt0,dtmax)	
int i;
int index[];
REAL dti[],olddti;
int bl_list[];
REAL *dt0;
REAL dtmax;
{
	int ibl,oldibl;
	REAL log10();
	
	printf("mod i index %d %d dti %e -> %e\n",i,index[i],olddti,dti[index[i]]); 
	ibl = (int)(log10(dti[index[i]]/ *dt0)/log10(2.0));
	oldibl = (int)(log10(olddti/ *dt0)/log10(2.0));

	if(ibl > oldibl){
	  swap_index(&index[i],&index[bl_list[ibl-1]]); 
          if(dti[index[bl_list[ibl-1]+1]] != dti[index[bl_list[ibl-1]]]){
	    bl_list[ibl] = bl_list[ibl-1];
	  }
	  bl_list[ibl-1] -= 1;
	}

	if(ibl < oldibl){
	  if(oldibl == 0){
	    correct_bl_list(i,ibl,dt0,dtmax,index,bl_list);		
	  }else{
	    swap_index(&index[i],&index[bl_list[oldibl-1]+1]);
	    bl_list[oldibl-1] += 1;	      		  
	    oldibl--;
     	    for(;ibl < oldibl;oldibl--){
	      if(oldibl == 0){	    	
	        correct_bl_list(bl_list[oldibl],ibl,dt0,dtmax,index,bl_list);		
		oldibl = ibl;  
	      }else{
	        swap_index(&index[bl_list[oldibl]],&index[bl_list[oldibl-1]+1]);
	        bl_list[oldibl-1] += 1;
	      }
	    }
	  }
	}	  
	for(i=0;i<10;i++) printf("i index dti %d %d %e \n",i,index[i],dti[index[i]]);
	for(i=0;i<5;i++) printf("i bl_list %d %d\n",i,bl_list[i]);
}

