Project

General

Profile

« Previous | Next » 

Revision bdcb662f

Added by Leszek Koltunski about 1 year ago

Progress with TablebasesPruning

View differences:

src/main/java/org/distorted/objectlib/tablebases/PruningTable.java
327 327

  
328 328
///////////////////////////////////////////////////////////////////////////////////////////////////
329 329

  
330
  boolean belongs(int number)
330
  boolean contains(int number)
331 331
    {
332 332
    int bucket = (number>>mNumBits);
333 333
    int offset1 = getBucketOffset(bucket);
src/main/java/org/distorted/objectlib/tablebases/TBCube2.java
11 11

  
12 12
import android.content.res.Resources;
13 13

  
14
import org.distorted.library.main.QuatHelper;
15 14
import org.distorted.library.type.Static3D;
16
import org.distorted.library.type.Static4D;
17 15
import org.distorted.objectlib.R;
18 16

  
19 17
///////////////////////////////////////////////////////////////////////////////////////////////////
20 18

  
21 19
public class TBCube2 extends TablebasesPruning
22 20
{
23
  private static final int[][] P =
24
      {
25
            { 2,-1,-1},
26
            { 2,-1, 1},
27
            { 2, 1,-1},
28
            { 2, 1, 1},
29
            {-2,-1,-1},
30
            {-2,-1, 1},
31
            {-2, 1,-1},
32
            {-2, 1, 1},
33

  
34
            {-1, 2,-1},
35
            { 1, 2,-1},
36
            {-1, 2, 1},
37
            { 1, 2, 1},
38
            {-1,-2,-1},
39
            { 1,-2,-1},
40
            {-1,-2, 1},
41
            { 1,-2, 1},
42

  
43
            {-1,-1, 2},
44
            { 1,-1, 2},
45
            {-1, 1, 2},
46
            { 1, 1, 2},
47
            {-1,-1,-2},
48
            { 1,-1,-2},
49
            {-1, 1,-2},
50
            { 1, 1,-2},
51
      };
52

  
53
  private static final int[][] PT =
54
      {
55
          {4,0},{5,0},{6,0},{7,0},
56
          {0,0},{1,0},{2,0},{3,0},
57
          {2,2},{6,1},{3,1},{7,2},
58
          {0,1},{4,2},{1,2},{5,1},
59
          {1,1},{5,2},{3,2},{7,1},
60
          {0,2},{4,1},{2,1},{6,2}
61
      };
62

  
63
  private int[][][] mQuatsMap;
21
  private final int[][][] mQuatsMap =
22
    {
23
     { { 0,21,13},  { 1, 6,18},  { 3,17, 7},  { 2,12,22},  {14, 4, 9},  { 5,10,15},  { 8,20,23},  {11,16,19} },
24
     { { 3,18, 4},  { 0,22,10},  { 2,13,20},  { 1, 7,16},  { 5,23,21},  {11, 9, 6},  {14,19,17},  { 8,15,12} },
25
     { { 1, 9,17},  { 2,15,21},  { 0,23,12},  { 3,19, 6},  { 8,13,10},  {14,18,16},  {11, 7, 4},  { 5,22,20} },
26
     { { 2,10,23},  { 3,16, 9},  { 1, 4,19},  { 0,20,15},  {11,17,18},  { 8,21,22},  { 5,12,13},  {14, 6, 7} },
27
     { {14, 7, 6},  { 5,13,12},  { 8,22,21},  {11,18,17},  { 0,15,20},  { 1,19, 4},  { 3, 9,16},  { 2,23,10} },
28
     { { 5,20,22},  {11, 4, 7},  {14,16,18},  { 8,10,13},  { 3, 6,19},  { 0,12,23},  { 2,21,15},  { 1,17, 9} },
29
     { { 8,12,15},  {14,17,19},  {11, 6, 9},  { 5,21,23},  { 1,16, 7},  { 2,20,13},  { 0,10,22},  { 3, 4,18} },
30
     { {11,19,16},  { 8,23,20},  { 5,15,10},  {14, 9, 4},  { 2,22,12},  { 3, 7,17},  { 1,18, 6},  { 0,13,21} },
31
    };
64 32

  
65 33
///////////////////////////////////////////////////////////////////////////////////////////////////
66 34

  
......
167 135

  
168 136
///////////////////////////////////////////////////////////////////////////////////////////////////
169 137

  
170
  private int[] getPermTwist(float[] point)
171
    {
172
    float ERR = 0.01f;
173

  
174
    for(int i=0; i<24; i++)
175
      {
176
      float dx = point[0]-P[i][0];
177
      float dy = point[1]-P[i][1];
178
      float dz = point[2]-P[i][2];
179

  
180
      if( dx*dx + dy*dy + dz*dz < ERR ) return PT[i];
181
      }
182

  
183
    return null;
184
    }
185

  
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

  
188
  private void fillOutMap(float[] buffer, int[][] map, float[] point, Static4D quat, int quatIndex)
138
  boolean moveCanProceed(int lastA, int lastR, int currA, int currR)
189 139
    {
190
    QuatHelper.rotateVectorByQuat(buffer,point[0],point[1],point[2],1,quat);
191
    int[] pt = getPermTwist(buffer);
192
    map[pt[0]][pt[1]] = quatIndex;
193
    }
194

  
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196

  
197
  private void computeMap()
198
    {
199
    final float[][] POINTS =
200
        {
201
            {-2,-1,-1},
202
            {-2,-1, 1},
203
            {-2, 1,-1},
204
            {-2, 1, 1},
205
            { 2,-1,-1},
206
            { 2,-1, 1},
207
            { 2, 1,-1},
208
            { 2, 1, 1},
209
        };
210

  
211
    mQuatsMap = new int[8][8][3];
212
    Static4D[] quats = getQuats();
213
    float[] buffer = new float[4];
214

  
215
    for(int c=0; c<8; c++)
216
      for(int q=0; q<24; q++)
217
        fillOutMap(buffer,mQuatsMap[c],POINTS[c],quats[q],q);
140
    return lastA!=currA;
218 141
    }
219 142

  
220 143
///////////////////////////////////////////////////////////////////////////////////////////////////
......
303 226

  
304 227
  public int[] getQuats(int index)
305 228
    {
306
    if( mQuatsMap==null ) computeMap();
307

  
308 229
    int twistNum = index%729;
309 230
    int permuNum = index/729;
310 231

  
......
335 256

  
336 257
  public int getIndex(int[] quats)
337 258
    {
338
    if( mQuatsMap==null ) computeMap();
339

  
340 259
    int[] twist = new int[8];
341 260
    int[] perm8 = new int[8];
342 261

  
......
346 265
    int twistNum = twist[0] + 3*(twist[2] + 3*(twist[3] + 3*(twist[4] + 3*(twist[5] + 3*twist[6]))));
347 266
    int permNum  = TablebaseHelpers.computePermutationNum(perm7);
348 267

  
268
if( permNum<0 )
269
  {
270
  android.util.Log.e("D", " permNum="+permNum );
271

  
272
  StringBuilder sb2 = new StringBuilder();
273
  for(int i=0; i<8; i++) { sb2.append(' '); sb2.append(perm8[i]); }
274
  android.util.Log.e("D", " perm8="+sb2 );
275

  
276
  StringBuilder sb3 = new StringBuilder();
277
  for(int i=0; i<8; i++) { sb3.append(' '); sb3.append(quats[i]); }
278
  android.util.Log.e("D", " quats="+sb3 );
279
  }
280

  
349 281
    return twistNum + 729*permNum;
350 282
    }
351 283
}  
src/main/java/org/distorted/objectlib/tablebases/TablebasesAbstract.java
29 29
  private final Static3D[] mAxis;
30 30
  private final int mSize, mMinScramble;
31 31
  private final int[][] mAngles;
32
  private final int mNumAxis;
33 32
  private final int[] mNumLayers;
34 33
  private final int mNumQuats;
35 34
  private final Static4D[] mQuats;
36
  private final int[][] mRotRow;
37
  private final int mNumCubits;
38
  private final float[][] mPosition;
39 35
  private final float[][] mCuts;
40 36
  private final int[] mNumCuts;
41
  private final boolean[][] mRotatable;
42
  private final int mScalingFactor;
43 37

  
44 38
  private int[][] mQuatMult;
45 39
  private boolean mInitialized;
46 40

  
47 41
  Tablebase mTablebase;
42
  final int mScalingFactor;
43
  final int mNumAxis;
44
  final float[][] mPosition;
45
  final int[][] mRotRow;
46
  final int mNumCubits;
47
  final boolean[][] mRotatable;
48 48

  
49 49
  private static final float[] mTmp = new float[4];
50 50

  
......
127 127

  
128 128
///////////////////////////////////////////////////////////////////////////////////////////////////
129 129

  
130
  private int computeRow(float[] pos, int quat, int axisIndex)
130
  int computeRow(float[] pos, int quat, int axisIndex)
131 131
    {
132 132
    int ret=0;
133 133
    int len = pos.length/3;
......
205 205

  
206 206
///////////////////////////////////////////////////////////////////////////////////////////////////
207 207

  
208
  private int getMultQuat(int index1, int index2)
208
  int getMultQuat(int index1, int index2)
209 209
    {
210 210
    if( mQuatMult==null )
211 211
      {
......
323 323
    return new byte[][] { data };
324 324
    }
325 325

  
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

  
328
  void convertMoves(int[][] moves)
329
    {
330
    for(int[] move : moves )
331
      {
332
      int axis = move[0];
333
      int layer= move[1];
334
      int angle= move[2];
335

  
336
      int maxAngle = mAngles[axis][layer];
337
      angle = maxAngle-angle;
338
      if( angle> 0.5f*maxAngle ) angle -= maxAngle;
339

  
340
      move[1] = (1<<layer);
341
      move[2] = angle;
342
      }
343
    }
344

  
326 345
///////////////////////////////////////////////////////////////////////////////////////////////////
327 346

  
328 347
  private void addMove(ArrayList<int[]> moves, int axis, int layer, int angle)
......
347 366

  
348 367
///////////////////////////////////////////////////////////////////////////////////////////////////
349 368

  
350
  private void getNextAxisLayerAngleQuat(int[] data)
369
  void getNextAxisLayerAngleQuat(int[] data)
351 370
    {
352 371
    int axis = data[0];
353 372
    int layer= data[1];
......
377 396
    return moves;
378 397
    }
379 398

  
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

  
382
  Static4D[] getQuats()
383
    {
384
    return mQuats;
385
    }
386

  
387 399
///////////////////////////////////////////////////////////////////////////////////////////////////
388 400

  
389 401
  public int[][] solution(int index, int[] extra)
......
558 570

  
559 571
        for(int i=0; i<size; i++)
560 572
          {
561
          if (table.belongs(i))
573
          if (table.contains(i))
562 574
            {
563 575
            if ((num % 10) == 0) sb.append("\n");
564 576
            num++;
src/main/java/org/distorted/objectlib/tablebases/TablebasesPruning.java
19 19

  
20 20
public abstract class TablebasesPruning extends TablebasesAbstract
21 21
{
22
  private final int mGodsNumber;
23

  
22 24
  private boolean mInitialized;
23 25
  private PruningTable[] mHighTables;
24 26
  private PruningTable[] mMidTables;
25
  private int mGodsNumber, mLowestHigh, mHighestMid, mLowestMid;
27
  private int mLowestHigh, mHighestMid, mLowestMid;
26 28

  
27 29
///////////////////////////////////////////////////////////////////////////////////////////////////
28 30

  
29 31
  abstract int[] getMidPruningLevels();
30 32
  abstract int[] getHighPruningLevels();
31 33
  abstract int getGodsNumber();
34
  abstract boolean moveCanProceed(int lastA, int lastL, int currA, int currL);
32 35

  
33 36
///////////////////////////////////////////////////////////////////////////////////////////////////
34 37

  
......
83 86

  
84 87
    for(int i=0; i<mid ; i++) mMidTables[i] = createPruningTable(res,midIDs[i] );
85 88
    for(int i=0; i<high; i++) mHighTables[i]= createPruningTable(res,highIDs[i]);
89

  
90
    computeLowHigh();
86 91
    }
87 92

  
88 93
///////////////////////////////////////////////////////////////////////////////////////////////////
......
118 123
      for(int i=0; i<numHighLevels; i++)
119 124
        mHighTables[i] = new PruningTable(mTablebase,highLevels[i]);
120 125

  
126
      computeLowHigh();
127

  
121 128
      mInitialized = true;
122 129
      }
123 130

  
......
133 140

  
134 141
///////////////////////////////////////////////////////////////////////////////////////////////////
135 142

  
136
  public int[][] solution(int index, int[] extra)
143
  private void computeLowHigh()
144
    {
145
    mLowestHigh = mGodsNumber+1;
146
    int numHigh = mHighTables==null ? 0 : mHighTables.length;
147

  
148
    for( int i=0; i<numHigh; i++ )
149
      {
150
      int level = mHighTables[i].getLevel();
151
      if( i==0 || level<mLowestHigh ) mLowestHigh=level;
152
      }
153

  
154
    mLowestMid = 0;
155
    mHighestMid= 0;
156
    int numMid = mMidTables==null ? 0 : mMidTables.length;
157

  
158
    for( int i=0; i<numMid; i++ )
159
      {
160
      int level = mMidTables[i].getLevel();
161
      if( i==0 || level<mLowestMid  ) mLowestMid =level;
162
      if( i==0 || level>mHighestMid ) mHighestMid=level;
163
      }
164
    }
165

  
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

  
168
  public int traverseDownTable(int index, PruningTable[] tables, int tableIndex, int lastA, int lastR, int[] move, int[] tmpQuats)
169
    {
170
    int[] quats = getQuats(index);
171
    int numQuats = quats.length;
172

  
173
    move[0]=0;
174
    move[1]=0;
175
    move[2]=1;
176
    move[3]=1;
177

  
178
    for(int ax=0; ax<mNumAxis; ax++)
179
      for(int cubit=0; cubit<mNumCubits; cubit++)
180
        mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax);
181

  
182
    for(int s=0; s<mScalingFactor; s++)
183
      {
184
      int ax    = move[0];
185
      int layer = move[1];
186
      int quat  = move[3];
187

  
188
      if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) )
189
        {
190
        int bitLayer = (1<<layer);
191
        System.arraycopy(quats, 0, tmpQuats, 0, numQuats);
192

  
193
        for(int cubit=0; cubit<mNumCubits; cubit++)
194
          if( mRotRow[cubit][ax]==bitLayer )
195
            {
196
            int currQuat = tmpQuats[cubit];
197
            int newQuat = getMultQuat(quat,currQuat);
198
            tmpQuats[cubit] = newQuat;
199
            }
200

  
201
        int childIndex = getIndex(tmpQuats);
202

  
203
        if( tableIndex>0 )
204
          {
205
          if( tables[tableIndex-1].contains(childIndex) ) return childIndex;
206
          }
207
        else if( !tables[0].contains(childIndex) )
208
          {
209
          if( tables.length<=1 || !tables[1].contains(childIndex) ) return childIndex;
210
          }
211
        }
212

  
213
      getNextAxisLayerAngleQuat(move);
214
      }
215

  
216
    return -1;
217
    }
218

  
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

  
221
  private int traversePruningBlock(int[][] moves, PruningTable[] tables, int tableIndex, int index, int lastA, int lastR)
137 222
    {
223
    int movesIndex = 1;
224
    int[] move = moves[movesIndex];
225
    int[] tmpQuats = new int[4];
226

  
227
    do
228
      {
229
      index = traverseDownTable(index,tables,tableIndex,lastA,lastR,move,tmpQuats);
230
      lastA = move[0];
231
      lastR = move[1];
232
      tableIndex--;
233
      movesIndex++;
234
      move = moves[movesIndex];
235
      }
236
    while( tableIndex>=0 );
237

  
238
    return index;
239
    }
240

  
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242
// ret: [0][] --> (new index,new depth,?,?) ; [1...N-1][] --> moves. (or null if index not in High)
243

  
244
  private int[][] traverseBlock(int index, PruningTable[] tables, int lastA, int lastR)
245
    {
246
    int num = (tables==null) ? 0 : tables.length;
247
    int tableIndex = -1;
248

  
249
    for( int i=0; i<num; i++ )
250
      if( tables[i].contains(index) )
251
        {
252
        tableIndex = i;
253
        break;
254
        }
255

  
256
    if( tableIndex<0 ) return null;
257

  
258
    int[][] ret = new int[tableIndex+2][4];
259
    ret[0][1] = tables[0].getLevel()-1;
260
    ret[0][0] = traversePruningBlock(ret,tables,tableIndex,index,lastA, lastR);
261

  
262
    return ret;
263
    }
264

  
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

  
267
  private int midTablesContain(int index)
268
    {
269
    int num = mMidTables.length;
270

  
271
    for( int i=0; i<num; i++ )
272
      if( mMidTables[i].contains(index) )
273
        return i;
274

  
275
    return -1;
276
    }
277

  
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279

  
280
  private boolean jumpMidZeroRecursive(int index, int jump, int depth, int lastA, int lastR, int[][] solution)
281
    {
282
    int[] quats  = getQuats(index);
283
    int numQuats = quats.length;
284
    int[] move   = solution[depth];
285
    int[] tmp    = new int[mNumCubits];
286

  
287
    move[0]=0;
288
    move[1]=0;
289
    move[2]=1;
290
    move[3]=1;
291

  
292
    for(int ax=0; ax<mNumAxis; ax++)
293
      for(int cubit=0; cubit<mNumCubits; cubit++)
294
        mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax);
295

  
296
    for(int s=0; s<mScalingFactor; s++)
297
      {
298
      int ax    = move[0];
299
      int layer = move[1];
300
      int quat  = move[3];
301

  
302
      if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,ax,layer) )
303
        {
304
        int bitLayer = (1<<layer);
305
        System.arraycopy(quats, 0, tmp, 0, numQuats);
306

  
307
        for(int cubit=0; cubit<mNumCubits; cubit++)
308
          if( mRotRow[cubit][ax]==bitLayer )
309
            {
310
            int currQuat = tmp[cubit];
311
            int newQuat = getMultQuat(quat,currQuat);
312
            tmp[cubit] = newQuat;
313
            }
314

  
315
        int childIndex = getIndex(tmp);
316

  
317
        if( childIndex==0 )
318
          {
319
          solution[0][0] = childIndex;
320
          solution[0][1] = 0;
321
          return true;
322
          }
323

  
324
        int containingTable = midTablesContain(childIndex);
325

  
326
        if( containingTable>=0 )
327
          {
328
          solution[0][0] = childIndex;
329
          solution[0][1] = mMidTables[containingTable].getLevel();
330
          return true;
331
          }
332

  
333
        if( jump>1 && jumpMidZeroRecursive(childIndex, jump-1, depth+1, ax, layer, solution) )
334
          {
335
          return true;
336
          }
337
        }
338

  
339
      getNextAxisLayerAngleQuat(move);
340
      }
341

  
342
    return false;
343
    }
344

  
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346
// ret: [0][] --> (?,old depth,?,?) ; [1...N-1][] --> moves.
347

  
348
  private int[][] jumpToMidOrZero(int index, int maxJump, int lastA, int lastR)
349
    {
350
    int[][] solution = new int[maxJump+1][4];
351

  
352
    for(int i=1; i<maxJump; i++)
353
      if( jumpMidZeroRecursive(index,i,1,lastA,lastR,solution) )
354
        return solution;
355

  
356
    return null;
357
    }
358

  
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

  
361
  private boolean jumpZeroRecursive(int index, int jump, int depth, int lastA, int lastR, int[][] solution)
362
    {
363
    int[] quats  = getQuats(index);
364
    int numQuats = quats.length;
365
    int[] move   = solution[depth];
366
    int[] tmp    = new int[mNumCubits];
367

  
368
    android.util.Log.e("D", "trying 0rec: index="+index);
369

  
370
    move[0]=0;
371
    move[1]=0;
372
    move[2]=1;
373
    move[3]=1;
374

  
375
    for(int ax=0; ax<mNumAxis; ax++)
376
      for(int cubit=0; cubit<mNumCubits; cubit++)
377
        mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax);
378

  
379
    for(int s=0; s<mScalingFactor; s++)
380
      {
381
      int ax    = move[0];
382
      int layer = move[1];
383
      int quat  = move[3];
384

  
385
      if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) )
386
        {
387
        int bitLayer = (1<<layer);
388
        System.arraycopy(quats, 0, tmp, 0, numQuats);
389

  
390
        for(int cubit=0; cubit<mNumCubits; cubit++)
391
          if( mRotRow[cubit][ax]==bitLayer )
392
            {
393
            int currQuat = tmp[cubit];
394
            int newQuat = getMultQuat(quat,currQuat);
395
            tmp[cubit] = newQuat;
396
            }
397

  
398
        int childIndex = getIndex(tmp);
399
        if( childIndex==0 )
400
          {
401
          android.util.Log.e("D", "END: ax="+ax+" layer="+layer+" angle: "+move[2]);
402
          return true;
403
          }
404
        if( jump>1 && jumpZeroRecursive(childIndex, jump-1, depth+1, ax, layer, solution) )
405
          {
406
          android.util.Log.e("D", "REC: ax="+ax+" layer="+layer+" angle: "+move[2]);
407
          return true;
408
          }
409
        }
410

  
411
      getNextAxisLayerAngleQuat(move);
412
      }
413

  
414
    return false;
415
    }
416

  
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418
// ret: [0][] --> (?,old depth,?,?) ; [1...N-1][] --> moves.
419

  
420
  private int[][] jumpToZero(int index, int maxJump, int lastA, int lastR)
421
    {
422
    int[][] solution = new int[maxJump+1][4];
423

  
424
    for(int i=1; i<maxJump; i++)
425
      if( jumpZeroRecursive(index,i,1,lastA,lastR,solution) )
426
        return solution;
427

  
138 428
    return null;
139 429
    }
430

  
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432

  
433
  private int[][] concatenateMoves(int[][] high, int[][] jump1, int[][] mid, int[][] jump2)
434
    {
435
    int len1 = high ==null ? 0 : high.length-1;
436
    int len2 = jump1==null ? 0 : jump1[0][1];
437
    int len3 = mid  ==null ? 0 : mid.length-1;
438
    int len4 = jump2==null ? 0 : jump2[0][1];
439

  
440
    int[][] moves = new int[len1+len2+len3+len4][];
441
    int index = 0;
442

  
443
    for(int i=0; i<len1; i++) moves[index++] =  high[i+1];
444
    for(int i=0; i<len2; i++) moves[index++] = jump1[i+1];
445
    for(int i=0; i<len3; i++) moves[index++] =   mid[i+1];
446
    for(int i=0; i<len4; i++) moves[index++] = jump2[i+1];
447

  
448
    convertMoves(moves);
449

  
450
    return moves;
451
    }
452

  
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

  
455
  public int[][] solution(int index, int[] extra)
456
    {
457
    if( index==0 ) return null;
458
    int lastA=-1, lastR=0;
459
    int[][] highMoves = traverseBlock(index,mHighTables,lastA,lastR);
460

  
461
    if( highMoves!=null )
462
      {
463
      index = highMoves[0][0];
464
      int len = highMoves.length;
465
      lastA = highMoves[len-1][0];
466
      lastR = highMoves[len-1][1];
467
      }
468

  
469
    int maxJump = Math.max(mLowestHigh-1-mHighestMid,mLowestMid/2);
470
    int[][] jump1Moves = jumpToMidOrZero(index,maxJump,lastA,lastR);
471

  
472
    if( jump1Moves!=null )
473
      {
474
      if( jump1Moves[0][0]==0 )
475
        {
476
        return concatenateMoves(null,null,null,jump1Moves);
477
        }
478
      if( jump1Moves[0][1]==mLowestMid )
479
        {
480
        int[][] jump2Moves = jumpToZero(index,mLowestMid-1,-1,0);
481
        if( jump2Moves==null ) throw new RuntimeException("1 error jumping to 0");
482
        return concatenateMoves(null,null,null,jump2Moves);
483
        }
484

  
485
      index = jump1Moves[0][0];
486
      int len = jump1Moves.length;
487
      lastA = jump1Moves[len-1][0];
488
      lastR = jump1Moves[len-1][1];
489
      }
490

  
491
    int[][] midMoves = traverseBlock(index,mMidTables,lastA,lastR);
492
    if( midMoves!=null )
493
      {
494
      index = midMoves[0][0];
495
      int len = midMoves.length;
496
      lastA = midMoves[len-1][0];
497
      lastR = midMoves[len-1][1];
498
      }
499
    else throw new RuntimeException("error traversing mid Tables");
500

  
501
    int[][] jump2Moves = jumpToZero(index,mLowestMid-1,lastA,lastR);
502
    if( jump2Moves==null ) throw new RuntimeException("2 error jumping to 0");
503
    return concatenateMoves(highMoves,jump1Moves,midMoves,jump2Moves);
504
    }
140 505
}

Also available in: Unified diff