Project

General

Profile

Download (7.79 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TablebasesCreator.java @ a110ebe1

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.tablebases;
11

    
12
import org.distorted.library.main.QuatHelper;
13
import org.distorted.library.type.Static3D;
14
import org.distorted.library.type.Static4D;
15
import org.distorted.objectlib.helpers.QuatGroupGenerator;
16

    
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18

    
19
public abstract class TablebasesCreator
20
{
21
  private Tablebase mTablebase;
22
  private final Static3D[] mAxis;
23
  private final int mSize;
24
  private final int[][] mAngles;
25
  private final int mNumAxis;
26
  private final int[] mNumLayers;
27
  private final int mNumQuats;
28
  private final Static4D[] mQuats;
29
  private final int[][] mRotRow;
30
  private final int mNumCubits;
31
  private final float[][] mPosition;
32
  private final float[][] mCuts;
33
  private final int[] mNumCuts;
34
  private int[][] mQuatMult;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

    
38
  abstract int getSize();
39
  abstract int[][] getBasicAngles();
40
  abstract Static3D[] getRotationAxis();
41
  abstract int[] getQuats(int index);
42
  abstract int getIndex(int[] quats);
43
  abstract float[][] getPosition();
44
  abstract float[][] getCuts();
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

    
48
  public TablebasesCreator()
49
    {
50
    mSize = getSize();
51
    mAngles = getBasicAngles();
52
    mAxis = getRotationAxis();
53
    mNumAxis = mAxis.length;
54
    mNumLayers = new int[mNumAxis];
55
    for(int i=0; i<mNumAxis; i++) mNumLayers[i] = mAngles[i].length;
56
    mQuats = QuatGroupGenerator.computeGroup(mAxis,mAngles);
57
    mNumQuats = mQuats.length;
58
    mPosition = getPosition();
59
    mNumCubits = mPosition.length;
60

    
61
    mCuts = getCuts();
62
    mNumCuts = new int[mNumAxis];
63

    
64
    for(int i=0; i<mNumAxis; i++)
65
      {
66
      mNumCuts[i] = (mCuts==null || mCuts[i]==null ? 0 : mCuts[i].length);
67
      }
68

    
69
    mRotRow = new int[mNumCubits][mNumAxis];
70

    
71
    for(int i=0; i<mNumCubits; i++)
72
      for(int j=0; j<mNumAxis; j++)
73
        {
74
        mRotRow[i][j] = computeRow(mPosition[i],j);
75
        }
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

    
80
  private int computeRow(float[] pos, int axisIndex)
81
    {
82
    int ret=0;
83
    int len = pos.length/3;
84
    Static3D axis = mAxis[axisIndex];
85
    float axisX = axis.get0();
86
    float axisY = axis.get1();
87
    float axisZ = axis.get2();
88
    float casted, xoff=0, yoff=0, zoff=0;
89

    
90
    for(int i=0; i<len; i++)
91
      {
92
      casted = (pos[3*i]+xoff)*axisX + (pos[3*i+1]+yoff)*axisY + (pos[3*i+2]+zoff)*axisZ;
93
      ret |= computeSingleRow(axisIndex,casted);
94
      }
95

    
96
    return ret;
97
    }
98

    
99
///////////////////////////////////////////////////////////////////////////////////////////////////
100

    
101
  private int computeSingleRow(int axisIndex,float casted)
102
    {
103
    int num = mNumCuts[axisIndex];
104

    
105
    for(int i=0; i<num; i++)
106
      {
107
      if( casted<mCuts[axisIndex][i] ) return (1<<i);
108
      }
109

    
110
    return (1<<num);
111
    }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
// remember about the double cover or unit quaternions!
115

    
116
  private int mulQuat(int q1, int q2)
117
    {
118
    Static4D result = QuatHelper.quatMultiply(mQuats[q1],mQuats[q2]);
119

    
120
    float rX = result.get0();
121
    float rY = result.get1();
122
    float rZ = result.get2();
123
    float rW = result.get3();
124

    
125
    final float MAX_ERROR = 0.1f;
126
    float dX,dY,dZ,dW;
127

    
128
    for(int i=0; i<mNumQuats; i++)
129
      {
130
      dX = mQuats[i].get0() - rX;
131
      dY = mQuats[i].get1() - rY;
132
      dZ = mQuats[i].get2() - rZ;
133
      dW = mQuats[i].get3() - rW;
134

    
135
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
136
          dY<MAX_ERROR && dY>-MAX_ERROR &&
137
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
138
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
139

    
140
      dX = mQuats[i].get0() + rX;
141
      dY = mQuats[i].get1() + rY;
142
      dZ = mQuats[i].get2() + rZ;
143
      dW = mQuats[i].get3() + rW;
144

    
145
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
146
          dY<MAX_ERROR && dY>-MAX_ERROR &&
147
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
148
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
149
      }
150

    
151
    return -1;
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
  private int getMultQuat(int index1, int index2)
157
    {
158
    if( mQuatMult==null )
159
      {
160
      mQuatMult = new int[mNumQuats][mNumQuats];
161

    
162
      for(int i=0; i<mNumQuats; i++)
163
        for(int j=0; j<mNumQuats; j++) mQuatMult[i][j] = -1;
164
      }
165

    
166
    if( index1<mNumQuats && index2<mNumQuats )
167
      {
168
      if( mQuatMult[index1][index2]==-1 ) mQuatMult[index1][index2] = mulQuat(index1,index2);
169
      return mQuatMult[index1][index2];
170
      }
171

    
172

    
173
android.util.Log.e("D", "error in getMulQuat: index1="+index1+" index2="+index2+" numQuats="+mNumQuats);
174

    
175

    
176
    return -2;
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
  private boolean belongsToMove(int cubit, int axis, int layer)
182
    {
183
    return mRotRow[cubit][axis] == layer;
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187
// assumption: all layers have the same basicAngles!
188

    
189
  private int insertAllChildren(int index, byte level)
190
    {
191
    int ret = 0;
192
    int[] quats = getQuats(index);
193
    int numQuats = quats.length;
194
    int[] tmpQuats = new int[numQuats];
195
    byte newLevel = (byte)(level+1);
196
    boolean[] belongs = new boolean[mNumCubits];
197
    int quatBasis = 0;
198

    
199
    for(int ax=0; ax<mNumAxis; ax++)
200
      {
201
      for(int layer=0; layer<mNumLayers[ax]; layer++)
202
        {
203
        for(int cubit=0; cubit<mNumCubits; cubit++)
204
          belongs[cubit] = belongsToMove(cubit,ax,layer);
205

    
206
        int maxAngle = mAngles[ax][layer];
207

    
208
        for(int angle=1; angle<maxAngle; angle++ )
209
          {
210
          System.arraycopy(quats, 0, tmpQuats, 0, numQuats);
211
          int quat = quatBasis + angle;
212

    
213
          for(int cubit=0; cubit<mNumCubits; cubit++)
214
            if( belongs[cubit] )
215
              {
216
              int currQuat = tmpQuats[cubit];
217
              int newQuat = getMultQuat(currQuat,quat);
218
              tmpQuats[cubit] = newQuat;
219
              }
220

    
221
android.util.Log.e("D", "quat: "+quat+" numAxis="+mNumAxis+" numLayers="+mNumLayers[ax]+" maxAngle="+maxAngle);
222

    
223
          int childIndex = getIndex(tmpQuats);
224
          if( mTablebase.insertUnpacked(childIndex,newLevel) ) ret++;
225
          }
226
        }
227

    
228
      quatBasis += (mAngles[ax][0]-1);
229
      }
230

    
231
    return ret;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  public void createTablebase()
237
    {
238
    mTablebase = new Tablebase(mSize);
239
    mTablebase.insertUnpacked(0,(byte)0);
240

    
241
    int numInserted;
242
    byte insertingLevel = 0;
243

    
244
    do
245
      {
246
      numInserted = 0;
247

    
248
      for(int i=0; i<mSize; i++)
249
        {
250
        byte level = mTablebase.retrieveUnpacked(i);
251
        if( level==insertingLevel ) numInserted += insertAllChildren(i,level);
252
        }
253

    
254
      insertingLevel++;
255

    
256
android.util.Log.e("D", "inserted "+numInserted+" positions at level "+insertingLevel);
257
      }
258
    while( numInserted>0 );
259
    }
260
}
(2-2/3)