// This file was generated by scm2java from source file "hilb.scm"
/**********************************************
** "Hilb.java": Hilbert space filling mapping
** Copyright (C) 2003, 2005, 2010 Aubrey Jaffer
**
** 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, either version 3 of the License, or (at
** your option) any later version.
**
** 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.
**********************************************/
package edu.mit.csail.people.jaffer;

public class Hilb {

public static int integerToGrayCode(int k)
{
  return (k)^((k)>>1);
}


public static int grayCodeToInteger(int k)
{
  {
    int kln = integerLength(k);
    {
      int d = 1;
      int ans = (k)^((k)>>1);
      while (!((2*(d))>=(kln))) {
	{
	  int T_d = (d)*2;
	  ans = (ans)^((ans)>>(2*(d)));
	  d = T_d;
	}
      }
      return ans;
    }
  }
}


public static int intlen(int n,int tot)
{
Lintlen:while (true) {
  switch (n) {
  case 0:
  case  -1:
    return 0+(tot);
  case 1:
  case  -2:
    return 1+(tot);
  case 2:
  case 3:
  case  -3:
  case  -4:
    return 2+(tot);
  case 4:
  case 5:
  case 6:
  case 7:
  case  -5:
  case  -6:
  case  -7:
  case  -8:
    return 3+(tot);
  default:
    {
      n = (n)>>4;
      tot = 4+(tot);
      continue Lintlen;
    }
  }
}
}

public static int integerLength(int n)
{
  return intlen(n, 0);
}


public static int log2BinaryFactors(int n)
{
  return  -1+(integerLength((n)&(-(n))));
}


public static int rotateBitField(int n,int cnt,int start,int end)
{
  int width = (end)-(start);
  cnt = ((cnt)+(width))%(width);
  {
    int mask = ~( -1<<(width));
    int azn = (mask)&((n)>>(start));
    {
      int ans = ((((mask)&((azn)<<(cnt)))|((azn)>>((width)-(cnt))))<<(start))|((~((mask)<<(start)))&(n));
      return ans;
    }
  }
}


public static int shuffle(int cnt,int ks)
{
  {
    int kdx = 0;
    int agg = 0;
    while (!((kdx)>=(cnt))) {
      {
	int T_kdx = 1+(kdx);
	agg = ((agg)<<3)|(((0 != ((1<<(0x10+(kdx))) & (ks)))
	   ?4
	   :0))|(((0 != ((1<<(8+(kdx))) & (ks)))
	   ?2
	   :0))|(((0 != ((1<<(0+(kdx))) & (ks)))
	   ?1
	   :0));
	kdx = T_kdx;
      }
    }
    return agg;
  }
}


public static int mapIntegerToGrayCode(int coords)
{
  if (0==(coords))
    return 0;
  else return ((mapIntegerToGrayCode((coords)>>8))<<8)|(integerToGrayCode(0xff&(coords)));
}


public static int hilbertIndex(int coords)
{
  int agi = shuffle(8, mapIntegerToGrayCode(coords));
  int rnk = 1<<2;
  {
    int cnt =  -1+8;
    int agg = (agi)>>3;
    int rotation = ((log2BinaryFactors((agi)&7))+2)%3;
    int flipbit = 1;
    int scalar = (agi)&7;
Lloop: while (true) {
    if (0==(cnt))
      return grayCodeToInteger(scalar);
    else {
      int chnk = rotateBitField((flipbit)^((agg)&7), -(rotation), 0, 3);
      {
	int T_rotation = ((log2BinaryFactors(chnk))+2+(rotation))%3;
	cnt =  -1+(cnt);
	agg = (agg)>>3;
	flipbit = 1<<(rotation);
	scalar = ((rnk)^(chnk))|((scalar)<<3);
	rotation = T_rotation;
	continue Lloop;
      }
    }
    }
  }
}



public static void main(String[] args)
{
  {
    int idx = 0;
    while (!((idx)>0x1000000)) {
      System.out.print(""+(idx)+": "+(hilbertIndex(idx))+"\n");
      {
	idx = 0x20a5f+(idx);
      }
    }
    return;
  }
}

}

