commit 618f3d756c7b237c2f43c74c04153bab8db1b8d2
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Mar 12 23:45:37 2023 +0100

    Cube2 tablebases solver finished.

diff --git a/src/main/java/org/distorted/objectlib/tablebases/TablebasesAbstract.java b/src/main/java/org/distorted/objectlib/tablebases/TablebasesAbstract.java
index 5695e776..83f9e39e 100644
--- a/src/main/java/org/distorted/objectlib/tablebases/TablebasesAbstract.java
+++ b/src/main/java/org/distorted/objectlib/tablebases/TablebasesAbstract.java
@@ -367,6 +367,13 @@ public abstract class TablebasesAbstract
     return moves;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  Static4D[] getQuats()
+    {
+    return mQuats;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int[][] solution(int index, int[] extra)
diff --git a/src/main/java/org/distorted/objectlib/tablebases/TablebasesCube2.java b/src/main/java/org/distorted/objectlib/tablebases/TablebasesCube2.java
index 806c2a83..8726b87b 100644
--- a/src/main/java/org/distorted/objectlib/tablebases/TablebasesCube2.java
+++ b/src/main/java/org/distorted/objectlib/tablebases/TablebasesCube2.java
@@ -11,12 +11,58 @@ package org.distorted.objectlib.tablebases;
 
 import android.content.res.Resources;
 
+import org.distorted.library.main.QuatHelper;
 import org.distorted.library.type.Static3D;
+import org.distorted.library.type.Static4D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class TablebasesCube2 extends TablebasesAbstract
 {
+  private static final int[][] P =
+      {
+            { 2,-1,-1},
+            { 2,-1, 1},
+            { 2, 1,-1},
+            { 2, 1, 1},
+            {-2,-1,-1},
+            {-2,-1, 1},
+            {-2, 1,-1},
+            {-2, 1, 1},
+
+            {-1, 2,-1},
+            { 1, 2,-1},
+            {-1, 2, 1},
+            { 1, 2, 1},
+            {-1,-2,-1},
+            { 1,-2,-1},
+            {-1,-2, 1},
+            { 1,-2, 1},
+
+            {-1,-1, 2},
+            { 1,-1, 2},
+            {-1, 1, 2},
+            { 1, 1, 2},
+            {-1,-1,-2},
+            { 1,-1,-2},
+            {-1, 1,-2},
+            { 1, 1,-2},
+      };
+
+  private static final int[][] PT =
+      {
+          {4,0},{5,0},{6,0},{7,0},
+          {0,0},{1,0},{2,0},{3,0},
+          {2,2},{6,1},{3,1},{7,2},
+          {0,1},{4,2},{1,2},{5,1},
+          {1,1},{5,2},{3,2},{7,1},
+          {0,2},{4,1},{2,1},{6,2}
+      };
+
+  private int[][][] mQuatsMap;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
   public TablebasesCube2()
     {
     super();
@@ -26,7 +72,7 @@ public class TablebasesCube2 extends TablebasesAbstract
 
   public TablebasesCube2(Resources res)
     {
-    super(res,org.distorted.objectlib.R.raw.cu_232_tablebase);
+    super(res,org.distorted.objectlib.R.raw.cube_2_tablebase);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -92,26 +138,193 @@ public class TablebasesCube2 extends TablebasesAbstract
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
- int getMinScramble()
+  int getMinScramble()
     {
     return 9;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int[] getPermTwist(float[] point)
+    {
+    float ERR = 0.01f;
+
+    for(int i=0; i<24; i++)
+      {
+      float dx = point[0]-P[i][0];
+      float dy = point[1]-P[i][1];
+      float dz = point[2]-P[i][2];
+
+      if( dx*dx + dy*dy + dz*dz < ERR ) return PT[i];
+      }
+
+    return null;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void fillOutMap(float[] buffer, int[][] map, float[] point, Static4D quat, int quatIndex)
+    {
+    QuatHelper.rotateVectorByQuat(buffer,point[0],point[1],point[2],1,quat);
+    int[] pt = getPermTwist(buffer);
+    map[pt[0]][pt[1]] = quatIndex;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void computeMap()
+    {
+    final float[][] POINTS =
+        {
+            {-2,-1,-1},
+            {-2,-1, 1},
+            {-2, 1,-1},
+            {-2, 1, 1},
+            { 2,-1,-1},
+            { 2,-1, 1},
+            { 2, 1,-1},
+            { 2, 1, 1},
+        };
+
+    mQuatsMap = new int[8][8][3];
+    Static4D[] quats = getQuats();
+    float[] buffer = new float[4];
+
+    for(int c=0; c<8; c++)
+      for(int q=0; q<24; q++)
+        fillOutMap(buffer,mQuatsMap[c],POINTS[c],quats[q],q);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static int[] shrinkPerm(int[] perm8)
+    {
+    int[] perm7 = new int[7];
+
+    int tmp = perm8[0];
+    perm7[0] = tmp>1 ? tmp-1 : tmp;
+    tmp = perm8[2];
+    perm7[1] = tmp>1 ? tmp-1 : tmp;
+    tmp = perm8[3];
+    perm7[2] = tmp>1 ? tmp-1 : tmp;
+    tmp = perm8[4];
+    perm7[3] = tmp>1 ? tmp-1 : tmp;
+    tmp = perm8[5];
+    perm7[4] = tmp>1 ? tmp-1 : tmp;
+    tmp = perm8[6];
+    perm7[5] = tmp>1 ? tmp-1 : tmp;
+    tmp = perm8[7];
+    perm7[6] = tmp>1 ? tmp-1 : tmp;
+
+    return perm7;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private static int[] growPerm(int[] perm7)
+    {
+    int[] perm8 = new int[8];
+    int tmp = perm7[0];
+    perm8[0] = tmp>=1 ? tmp+1 : tmp;
+    perm8[1] = 1;
+    tmp = perm7[1];
+    perm8[2] = tmp>=1 ? tmp+1 : tmp;
+    tmp = perm7[2];
+    perm8[3] = tmp>=1 ? tmp+1 : tmp;
+    tmp = perm7[3];
+    perm8[4] = tmp>=1 ? tmp+1 : tmp;
+    tmp = perm7[4];
+    perm8[5] = tmp>=1 ? tmp+1 : tmp;
+    tmp = perm7[5];
+    perm8[6] = tmp>=1 ? tmp+1 : tmp;
+    tmp = perm7[6];
+    perm8[7] = tmp>=1 ? tmp+1 : tmp;
+
+    return perm8;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int[] getPerm(int permNum)
+    {
+    int[] perm7 = new int[7];
+    TablebaseHelpers.getPermutationFromNum(perm7,7,permNum);
+    return growPerm(perm7);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int[] getTwist(int twistNum)
+    {
+    int[] twist = new int[8];
+    twist[0] = twistNum%3;
+    twist[1] = 0;
+    twistNum /=3;
+    twist[2] = twistNum%3;
+    twistNum /=3;
+    twist[3] = twistNum%3;
+    twistNum /=3;
+    twist[4] = twistNum%3;
+    twistNum /=3;
+    twist[5] = twistNum%3;
+    twistNum /=3;
+    twist[6] = twistNum%3;
+
+    int total = (twist[0]+twist[2]+twist[3]+twist[4]+twist[5]+twist[6])%3;
+    if( total==0 ) twist[7] = 0;
+    else twist[7] = 3-total;
+
+    return twist;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int[] getQuats(int index)
     {
+    if( mQuatsMap==null ) computeMap();
+
+    int twistNum = index%729;
+    int permuNum = index/729;
+
+    int[] twist = getTwist(twistNum);
+    int[] perm  = getPerm(permuNum);
+
     int[] quats = new int[8];
+    for(int i=0; i<8; i++) quats[i] = mQuatsMap[i][perm[i]][twist[i]];
 
     return quats;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void extractTwistAndPerm(int quat, int[][] map, int[] twist, int[] perm, int index)
+    {
+    for(int i=0; i<8; i++)
+      for(int j=0; j<3; j++)
+        if( map[i][j]==quat )
+          {
+          twist[index] = j;
+          perm[index] = i;
+          break;
+          }
+    }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getIndex(int[] quats)
     {
-    return 0;
+    if( mQuatsMap==null ) computeMap();
+
+    int[] twist = new int[8];
+    int[] perm8 = new int[8];
+
+    for(int i=0; i<8; i++) extractTwistAndPerm(quats[i],mQuatsMap[i],twist,perm8,i);
+
+    int[] perm7 = shrinkPerm(perm8);
+    int twistNum = twist[0] + 3*(twist[2] + 3*(twist[3] + 3*(twist[4] + 3*(twist[5] + 3*twist[6]))));
+    int permNum  = TablebaseHelpers.computePermutationNum(perm7);
+
+    return twistNum + 729*permNum;
     }
 }  
 
diff --git a/src/main/res/raw/cube_2_tablebase.db b/src/main/res/raw/cube_2_tablebase.db
new file mode 100644
index 00000000..1c603a1b
Binary files /dev/null and b/src/main/res/raw/cube_2_tablebase.db differ
