WTF. Not only will this not work (U U U U = 16.0?) but floating point multiplication is one of the slowest possible commands for a computer. If you are going to do this kind of thing (and I don't recommend it, do what Jakube mentioned), just use an integer counter where U=+1 U'=-1 U2=+2, and check its value modulo 4 if you want to know if the U layer is back to normal.
Also this has nothing to do with a 3-cycle
I never had to worry about the case of U U U ... since my move generator skips moves in triplets on the subsequent depth of search.
I generate U, U', and U2 as a triplet, and in the next level of search, F, F, and F2 are next. U U never occurs, neither does U U' nor U U2 nor U' U2 and all other permutations possible with the other faces and slices.
I finally settled on:
signed short GLOBAL_TOP_FACE_PLUS_MINUS_TRACKER[36] = {-1,-1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0};
signed short GLOBAL_TOP_FACE_DOUBLE_SPIN_TRACKER[36] = {1,1,-1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0};
signed short global_top_face_plus_minus_unchanged_tracker;
signed short global_top_face_double_spin_unchanged_tracker;
signed short GLOBAL_TOP_SLICE_PLUS_MINUS_TRACKER[36] = {1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, -1,-1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0};
signed short GLOBAL_TOP_SLICE_DOUBLE_SPIN_TRACKER[36] = {1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,-1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0};
signed short global_top_slice_plus_minus_unchanged_tracker;
signed short global_top_slice_double_spin_unchanged_tracker;
signed short GLOBAL_BOTTOM_FACE_PLUS_MINUS_TRACKER[36] = {1,1,1, 0,0,0, 0,0,0, -1,-1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0};
signed short GLOBAL_BOTTOM_FACE_DOUBLE_SPIN_TRACKER[36] = {1,1,1, 0,0,0, 0,0,0, 1,1,-1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0};
signed short global_bottom_face_plus_minus_unchanged_tracker;
signed short global_bottom_face_double_spin_unchanged_tracker;
signed short GLOBAL_BOTTOM_SLICE_PLUS_MINUS_TRACKER[36] = {1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, -1,-1,1, 0,0,0, 0,0,0};
signed short GLOBAL_BOTTOM_SLICE_DOUBLE_SPIN_TRACKER[36] = {1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,1, 0,0,0, 0,0,0, 1,1,-1, 0,0,0, 0,0,0};
signed short global_bottom_slice_plus_minus_unchanged_tracker;
signed short global_bottom_slice_double_spin_unchanged_tracker;
... etc., for all of the different faces and slices. That way, all I have to do is this:
unsigned short level_4_prune(unsigned short i, unsigned short j, unsigned short k, unsigned short m)
{
global_top_face_plus_minus_unchanged_tracker = GLOBAL_TOP_FACE_PLUS_MINUS_TRACKER
* GLOBAL_TOP_FACE_PLUS_MINUS_TRACKER[j] * GLOBAL_TOP_FACE_PLUS_MINUS_TRACKER[k] * GLOBAL_TOP_FACE_PLUS_MINUS_TRACKER[m];
global_top_face_double_spin_unchanged_tracker = GLOBAL_TOP_FACE_DOUBLE_SPIN_TRACKER * GLOBAL_TOP_FACE_DOUBLE_SPIN_TRACKER[j] * GLOBAL_TOP_FACE_DOUBLE_SPIN_TRACKER[k] * GLOBAL_TOP_FACE_DOUBLE_SPIN_TRACKER[m];
global_bottom_face_plus_minus_unchanged_tracker = GLOBAL_BOTTOM_FACE_PLUS_MINUS_TRACKER * GLOBAL_BOTTOM_FACE_PLUS_MINUS_TRACKER[j] * GLOBAL_BOTTOM_FACE_PLUS_MINUS_TRACKER[k] * GLOBAL_BOTTOM_FACE_PLUS_MINUS_TRACKER[m];
global_bottom_face_double_spin_unchanged_tracker = GLOBAL_BOTTOM_FACE_DOUBLE_SPIN_TRACKER * GLOBAL_BOTTOM_FACE_DOUBLE_SPIN_TRACKER[j] * GLOBAL_BOTTOM_FACE_DOUBLE_SPIN_TRACKER[k] * GLOBAL_BOTTOM_FACE_DOUBLE_SPIN_TRACKER[m];
global_front_face_plus_minus_unchanged_tracker = GLOBAL_FRONT_FACE_PLUS_MINUS_TRACKER * GLOBAL_FRONT_FACE_PLUS_MINUS_TRACKER[j] * GLOBAL_FRONT_FACE_PLUS_MINUS_TRACKER[k] * GLOBAL_FRONT_FACE_PLUS_MINUS_TRACKER[m];
global_front_face_double_spin_unchanged_tracker = GLOBAL_FRONT_FACE_DOUBLE_SPIN_TRACKER * GLOBAL_FRONT_FACE_DOUBLE_SPIN_TRACKER[j] * GLOBAL_FRONT_FACE_DOUBLE_SPIN_TRACKER[k] * GLOBAL_FRONT_FACE_DOUBLE_SPIN_TRACKER[m];
global_back_face_plus_minus_unchanged_tracker = GLOBAL_BACK_FACE_PLUS_MINUS_TRACKER * GLOBAL_BACK_FACE_PLUS_MINUS_TRACKER[j] * GLOBAL_BACK_FACE_PLUS_MINUS_TRACKER[k] * GLOBAL_BACK_FACE_PLUS_MINUS_TRACKER[m];
global_back_face_double_spin_unchanged_tracker = GLOBAL_BACK_FACE_DOUBLE_SPIN_TRACKER * GLOBAL_BACK_FACE_DOUBLE_SPIN_TRACKER[j] * GLOBAL_BACK_FACE_DOUBLE_SPIN_TRACKER[k] * GLOBAL_BACK_FACE_DOUBLE_SPIN_TRACKER[m];
global_right_face_plus_minus_unchanged_tracker = GLOBAL_RIGHT_FACE_PLUS_MINUS_TRACKER * GLOBAL_RIGHT_FACE_PLUS_MINUS_TRACKER[j] * GLOBAL_RIGHT_FACE_PLUS_MINUS_TRACKER[k] * GLOBAL_RIGHT_FACE_PLUS_MINUS_TRACKER[m];
global_right_face_double_spin_unchanged_tracker = GLOBAL_RIGHT_FACE_DOUBLE_SPIN_TRACKER * GLOBAL_RIGHT_FACE_DOUBLE_SPIN_TRACKER[j] * GLOBAL_RIGHT_FACE_DOUBLE_SPIN_TRACKER[k] * GLOBAL_RIGHT_FACE_DOUBLE_SPIN_TRACKER[m];
global_left_face_plus_minus_unchanged_tracker = GLOBAL_LEFT_FACE_PLUS_MINUS_TRACKER * GLOBAL_LEFT_FACE_PLUS_MINUS_TRACKER[j] * GLOBAL_LEFT_FACE_PLUS_MINUS_TRACKER[k] * GLOBAL_LEFT_FACE_PLUS_MINUS_TRACKER[m];
global_left_face_double_spin_unchanged_tracker = GLOBAL_LEFT_FACE_DOUBLE_SPIN_TRACKER * GLOBAL_LEFT_FACE_DOUBLE_SPIN_TRACKER[j] * GLOBAL_LEFT_FACE_DOUBLE_SPIN_TRACKER[k] * GLOBAL_LEFT_FACE_DOUBLE_SPIN_TRACKER[m];
if((global_top_face_plus_minus_unchanged_tracker + global_top_face_double_spin_unchanged_tracker + global_bottom_face_plus_minus_unchanged_tracker + global_bottom_face_double_spin_unchanged_tracker) == 4) return 1;
if((global_front_face_plus_minus_unchanged_tracker + global_front_face_double_spin_unchanged_tracker + global_back_face_plus_minus_unchanged_tracker + global_back_face_double_spin_unchanged_tracker) == 4) return 1;
if((global_right_face_plus_minus_unchanged_tracker + global_right_face_double_spin_unchanged_tracker + global_left_face_plus_minus_unchanged_tracker + global_left_face_double_spin_unchanged_tracker) == 4) return 1;
return 0;
}
Basically, I track the faces and slices with different variables. I give a clockwise turn a score of -1, and likewise for a counterclockwise turn. I then compute the products. If the answer is -1, then I know they did not cancel out. If it is +1, then I know the starting position has occurred again. If I get a 0 value, that means in the middle of all of the U u d U' d' D u' there must have also been an F,R,B, etc., somewhere along the way, which invalidates the whole thing.
Only parallel faces and slices have the +1/-1 values, the others have zeros.
My move generator can't produce a cycle back to the original position in fewer than 4 plies. Here is the data I collected on the positions that were pruned from the tree:
1st level = 36
2nd level = 1188
3rd level = 39,204
4th level = 1,293,732
5th level = 42,693,156
6th level = 1,408,874,148
With no net progress detection
1st level = 36
2nd level = 1188
3rd level = 39,204
4th level = 1,290,396
5th level = 42,570,468
6th level = 1,404,723,924
The problem was, when pruning at a leaf node (the deepest spot in the tree) you get no further reductions since you are done and the search retreats one ply to start back down with a new move. Also, it took longer to evaluate a leaf node for a no-net-progress scenario than it to would have to just generate the node at the leaf. So, I removed pruning at the leaf nodes, and left pruning in for plies 4 and up. The result: It ran faster, examined slightly fewer nodes, and was an overall winner.
With no net progress detection except leaf nodes
1st level = 36
2nd level = 1188
3rd level = 39,204
4th level = 1,293,732*
5th level = 42,583,068
6th level = 1,404,825,444