h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

commit 43020af69d6932c7af0bc53b59c492775835a14e
parent 0ebba869512abc8e37e461e7587f686fe7c91c6c
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sat, 25 May 2024 11:50:16 +0200

Small performance improvement in h48 coordinate / transform

Diffstat:
MMakefile | 2+-
MTODO.txt | 14+-------------
Msrc/cube.c | 2++
Msrc/cube_avx2.h | 34++++++++++++++++++++++++++++++++--
Msrc/cube_portable.h | 52++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/cube_routines.h | 117+++++---------------------------------------------------------------------------
Asrc/cube_transform.h | 336+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solve_h48.h | 6++----
8 files changed, 424 insertions(+), 139 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,7 +12,7 @@ debugcube.o: clean ${CC} -D${CUBETYPE} ${DBGFLAGS} -c -o debugcube.o src/cube.c clean: - rm -rf *.o + rm -rf *.o gen debuggen test: debugcube.o CUBETYPE=${CUBETYPE} TEST=${TEST} ./test/test.sh diff --git a/TODO.txt b/TODO.txt @@ -1,16 +1,3 @@ -Table generation: transform only edges - (cube_avx2 and cube_portable) - - implement compose_fast_edges and compose_fast_corners - - tests not needed: just base the full transform on the other two - - cube_portable: easy for compose_fast to call the other two - - cube_avx2: split in (EP+EO+CP) and (CO); compose_edges call - (EP+EO+CP), compose_corners calls the full compose - (cube_routines) - - refactor transform(): use big array of cubes instead of switch - - add transform_edges and transform_corners - (solve_h48) - - uncomment transform_edges() and transform_corners() - Solver - write a solver (how many tricks? some, but not all are needed) @@ -27,6 +14,7 @@ Refactoring - remove cube type and some low-level utilities from interface, rename cube_fast_t to cube_t - add b64 i/o format, base64 encoded cube, one 6-bit word per piece + - transformations: remove switch to make shorter, but keep performance ## H48 optimal solver (some has already been implemented) diff --git a/src/cube.c b/src/cube.c @@ -30,10 +30,12 @@ #elif defined(CUBE_NEON) #include "cube_neon.h" #else +#include <stdlib.h> /* TODO: check if can be removed */ #include "cube_portable.h" #endif #include "cube_routines.h" +#include "cube_transform.h" /* TODO: merge with cube_routines? */ #include "moves.h" #include "solve_h48.h" #include "solve_generic.h" diff --git a/src/cube_avx2.h b/src/cube_avx2.h @@ -17,6 +17,9 @@ _static cube_t fasttocube(cube_fast_t); _static_inline bool equal_fast(cube_fast_t, cube_fast_t); _static_inline bool issolved_fast(cube_fast_t); _static_inline cube_fast_t invertco_fast(cube_fast_t); +_static_inline cube_fast_t compose_epcpeo(cube_fast_t, cube_fast_t); +_static_inline cube_fast_t compose_fast_edges(cube_fast_t, cube_fast_t); +_static_inline cube_fast_t compose_fast_corners(cube_fast_t, cube_fast_t); _static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); _static_inline int64_t coord_fast_co(cube_fast_t); @@ -123,9 +126,9 @@ invertco_fast(cube_fast_t c) } _static_inline cube_fast_t -compose_fast(cube_fast_t c1, cube_fast_t c2) +compose_epcpeo(cube_fast_t c1, cube_fast_t c2) { - cube_fast_t s, b, eo2, co1, co2, aux, auy1, auy2, auz1, auz2; + cube_fast_t b, s, eo2; /* Permute and clean unused bits */ s = _mm256_shuffle_epi8(c1, c2); @@ -139,6 +142,33 @@ compose_fast(cube_fast_t c1, cube_fast_t c2) eo2 = _mm256_and_si256(c2, _eo_avx2); s = _mm256_xor_si256(s, eo2); + return s; +} + +_static_inline cube_fast_t +compose_fast_edges(cube_fast_t c1, cube_fast_t c2) +{ + return compose_epcpeo(c1, c2); +} + +_static_inline cube_fast_t +compose_fast_corners(cube_fast_t c1, cube_fast_t c2) +{ + /* + * We do a full compose. Minor optimizations are possible, like + * saving one instruction by not doing EO, but it should not + * be significant. + */ + return compose_fast(c1, c2); +} + +_static_inline cube_fast_t +compose_fast(cube_fast_t c1, cube_fast_t c2) +{ + cube_fast_t s, co1, co2, aux, auy1, auy2, auz1, auz2; + + s = compose_epcpeo(c1, c2); + /* Change CO */ co1 = _mm256_and_si256(s, _co2_avx2); co2 = _mm256_and_si256(c2, _co2_avx2); diff --git a/src/cube_portable.h b/src/cube_portable.h @@ -11,6 +11,10 @@ _static cube_t fasttocube(cube_fast_t); _static_inline bool equal_fast(cube_fast_t, cube_fast_t); _static_inline bool issolved_fast(cube_fast_t); _static_inline cube_fast_t invertco_fast(cube_fast_t); +_static_inline void compose_edges_inplace(cube_fast_t, cube_fast_t, cube_fast_t *); +_static_inline void compose_corners_inplace(cube_fast_t, cube_fast_t, cube_fast_t *); +_static_inline cube_fast_t compose_fast_edges(cube_fast_t, cube_fast_t); +_static_inline cube_fast_t compose_fast_corners(cube_fast_t, cube_fast_t); _static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); _static_inline int64_t coord_fast_co(cube_fast_t); @@ -115,21 +119,24 @@ invertco_fast(cube_fast_t c) return ret; } -_static_inline cube_fast_t -compose_fast(cube_fast_t c1, cube_fast_t c2) +_static_inline void +compose_edges_inplace(cube_fast_t c1, cube_fast_t c2, cube_fast_t *ret) { - cube_fast_t ret; - uint8_t i, piece1, piece2, p, orien, aux, auy; - - ret = zero_fast; + uint8_t i, piece1, piece2, p, orien; for (i = 0; i < 12; i++) { piece2 = c2.edge[i]; p = piece2 & _pbits; piece1 = c1.edge[p]; orien = (piece2 ^ piece1) & _eobit; - ret.edge[i] = (piece1 & _pbits) | orien; + ret->edge[i] = (piece1 & _pbits) | orien; } +} + +_static_inline void +compose_corners_inplace(cube_fast_t c1, cube_fast_t c2, cube_fast_t *ret) +{ + uint8_t i, piece1, piece2, p, orien, aux, auy; for (i = 0; i < 8; i++) { piece2 = c2.corner[i]; @@ -138,8 +145,37 @@ compose_fast(cube_fast_t c1, cube_fast_t c2) aux = (piece2 & _cobits) + (piece1 & _cobits); auy = (aux + _ctwist_cw) >> 2U; orien = (aux + auy) & _cobits2; - ret.corner[i] = (piece1 & _pbits) | orien; + ret->corner[i] = (piece1 & _pbits) | orien; } +} + +_static_inline cube_fast_t +compose_fast_edges(cube_fast_t c1, cube_fast_t c2) +{ + cube_fast_t ret = zero_fast; + + compose_edges_inplace(c1, c2, &ret); + + return ret; +} + +_static_inline cube_fast_t +compose_fast_corners(cube_fast_t c1, cube_fast_t c2) +{ + cube_fast_t ret = zero_fast; + + compose_corners_inplace(c1, c2, &ret); + + return ret; +} + +_static_inline cube_fast_t +compose_fast(cube_fast_t c1, cube_fast_t c2) +{ + cube_fast_t ret = zero_fast; + + compose_edges_inplace(c1, c2, &ret); + compose_corners_inplace(c1, c2, &ret); return ret; } diff --git a/src/cube_routines.h b/src/cube_routines.h @@ -1,11 +1,5 @@ #define _move(M, c) compose_fast(c, _move_cube_ ## M) #define _premove(M, c) compose_fast(_move_cube_ ## M, c) -#define _trans_rotation(T, c) \ - compose_fast(compose_fast(_trans_cube_ ## T, c), \ - _trans_cube_ ## T ## _inverse) -#define _trans_mirrored(T, c) \ - invertco_fast(compose_fast(compose_fast(_trans_cube_ ## T, c), \ - _trans_cube_ ## T ## _inverse)) _static int permsign(uint8_t *, int); _static uint8_t readco(const char *); @@ -24,6 +18,8 @@ _static uint8_t readtrans(const char *); _static int writemoves(uint8_t *, int, char *); _static void writetrans(uint8_t, char *); _static cube_fast_t move(cube_fast_t, uint8_t); +_static cube_fast_t transform_edges(cube_fast_t, uint8_t); +_static cube_fast_t transform_corners(cube_fast_t, uint8_t); _static cube_fast_t transform(cube_fast_t, uint8_t); cube_t @@ -623,108 +619,7 @@ move(cube_fast_t c, uint8_t m) } } -_static cube_fast_t -transform(cube_fast_t c, uint8_t t) -{ - switch (t) { - case _trans_UFr: - return _trans_rotation(UFr, c); - case _trans_ULr: - return _trans_rotation(ULr, c); - case _trans_UBr: - return _trans_rotation(UBr, c); - case _trans_URr: - return _trans_rotation(URr, c); - case _trans_DFr: - return _trans_rotation(DFr, c); - case _trans_DLr: - return _trans_rotation(DLr, c); - case _trans_DBr: - return _trans_rotation(DBr, c); - case _trans_DRr: - return _trans_rotation(DRr, c); - case _trans_RUr: - return _trans_rotation(RUr, c); - case _trans_RFr: - return _trans_rotation(RFr, c); - case _trans_RDr: - return _trans_rotation(RDr, c); - case _trans_RBr: - return _trans_rotation(RBr, c); - case _trans_LUr: - return _trans_rotation(LUr, c); - case _trans_LFr: - return _trans_rotation(LFr, c); - case _trans_LDr: - return _trans_rotation(LDr, c); - case _trans_LBr: - return _trans_rotation(LBr, c); - case _trans_FUr: - return _trans_rotation(FUr, c); - case _trans_FRr: - return _trans_rotation(FRr, c); - case _trans_FDr: - return _trans_rotation(FDr, c); - case _trans_FLr: - return _trans_rotation(FLr, c); - case _trans_BUr: - return _trans_rotation(BUr, c); - case _trans_BRr: - return _trans_rotation(BRr, c); - case _trans_BDr: - return _trans_rotation(BDr, c); - case _trans_BLr: - return _trans_rotation(BLr, c); - case _trans_UFm: - return _trans_mirrored(UFm, c); - case _trans_ULm: - return _trans_mirrored(ULm, c); - case _trans_UBm: - return _trans_mirrored(UBm, c); - case _trans_URm: - return _trans_mirrored(URm, c); - case _trans_DFm: - return _trans_mirrored(DFm, c); - case _trans_DLm: - return _trans_mirrored(DLm, c); - case _trans_DBm: - return _trans_mirrored(DBm, c); - case _trans_DRm: - return _trans_mirrored(DRm, c); - case _trans_RUm: - return _trans_mirrored(RUm, c); - case _trans_RFm: - return _trans_mirrored(RFm, c); - case _trans_RDm: - return _trans_mirrored(RDm, c); - case _trans_RBm: - return _trans_mirrored(RBm, c); - case _trans_LUm: - return _trans_mirrored(LUm, c); - case _trans_LFm: - return _trans_mirrored(LFm, c); - case _trans_LDm: - return _trans_mirrored(LDm, c); - case _trans_LBm: - return _trans_mirrored(LBm, c); - case _trans_FUm: - return _trans_mirrored(FUm, c); - case _trans_FRm: - return _trans_mirrored(FRm, c); - case _trans_FDm: - return _trans_mirrored(FDm, c); - case _trans_FLm: - return _trans_mirrored(FLm, c); - case _trans_BUm: - return _trans_mirrored(BUm, c); - case _trans_BRm: - return _trans_mirrored(BRm, c); - case _trans_BDm: - return _trans_mirrored(BDm, c); - case _trans_BLm: - return _trans_mirrored(BLm, c); - default: - DBG_LOG("transform error, unknown transformation\n"); - return zero_fast; - } -} +/* +TODO transform is now relegated to a separated file because it is too long. +It would be nice to make it shorter without loosing performance. +*/ diff --git a/src/cube_transform.h b/src/cube_transform.h @@ -0,0 +1,336 @@ +#define _trans_edges_rotation(T, c) \ + compose_fast_edges(compose_fast_edges(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse) +#define _trans_edges_mirrored(T, c) _trans_edges_rotation(T, c) + +#define _trans_corners_rotation(T, c) \ + compose_fast_corners(compose_fast_corners(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse) +#define _trans_corners_mirrored(T, c) \ + invertco_fast(compose_fast_corners( \ + compose_fast_corners(_trans_cube_ ## T, c), _trans_cube_ ## T ## _inverse)) + +#define _trans_rotation(T, c) \ + compose_fast(compose_fast(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse) +#define _trans_mirrored(T, c) \ + invertco_fast(compose_fast(compose_fast(_trans_cube_ ## T, c), \ + _trans_cube_ ## T ## _inverse)) + +_static cube_fast_t +transform_edges(cube_fast_t c, uint8_t t) +{ + switch (t) { + case _trans_UFr: + return _trans_edges_rotation(UFr, c); + case _trans_ULr: + return _trans_edges_rotation(ULr, c); + case _trans_UBr: + return _trans_edges_rotation(UBr, c); + case _trans_URr: + return _trans_edges_rotation(URr, c); + case _trans_DFr: + return _trans_edges_rotation(DFr, c); + case _trans_DLr: + return _trans_edges_rotation(DLr, c); + case _trans_DBr: + return _trans_edges_rotation(DBr, c); + case _trans_DRr: + return _trans_edges_rotation(DRr, c); + case _trans_RUr: + return _trans_edges_rotation(RUr, c); + case _trans_RFr: + return _trans_edges_rotation(RFr, c); + case _trans_RDr: + return _trans_edges_rotation(RDr, c); + case _trans_RBr: + return _trans_edges_rotation(RBr, c); + case _trans_LUr: + return _trans_edges_rotation(LUr, c); + case _trans_LFr: + return _trans_edges_rotation(LFr, c); + case _trans_LDr: + return _trans_edges_rotation(LDr, c); + case _trans_LBr: + return _trans_edges_rotation(LBr, c); + case _trans_FUr: + return _trans_edges_rotation(FUr, c); + case _trans_FRr: + return _trans_edges_rotation(FRr, c); + case _trans_FDr: + return _trans_edges_rotation(FDr, c); + case _trans_FLr: + return _trans_edges_rotation(FLr, c); + case _trans_BUr: + return _trans_edges_rotation(BUr, c); + case _trans_BRr: + return _trans_edges_rotation(BRr, c); + case _trans_BDr: + return _trans_edges_rotation(BDr, c); + case _trans_BLr: + return _trans_edges_rotation(BLr, c); + case _trans_UFm: + return _trans_edges_mirrored(UFm, c); + case _trans_ULm: + return _trans_edges_mirrored(ULm, c); + case _trans_UBm: + return _trans_edges_mirrored(UBm, c); + case _trans_URm: + return _trans_edges_mirrored(URm, c); + case _trans_DFm: + return _trans_edges_mirrored(DFm, c); + case _trans_DLm: + return _trans_edges_mirrored(DLm, c); + case _trans_DBm: + return _trans_edges_mirrored(DBm, c); + case _trans_DRm: + return _trans_edges_mirrored(DRm, c); + case _trans_RUm: + return _trans_edges_mirrored(RUm, c); + case _trans_RFm: + return _trans_edges_mirrored(RFm, c); + case _trans_RDm: + return _trans_edges_mirrored(RDm, c); + case _trans_RBm: + return _trans_edges_mirrored(RBm, c); + case _trans_LUm: + return _trans_edges_mirrored(LUm, c); + case _trans_LFm: + return _trans_edges_mirrored(LFm, c); + case _trans_LDm: + return _trans_edges_mirrored(LDm, c); + case _trans_LBm: + return _trans_edges_mirrored(LBm, c); + case _trans_FUm: + return _trans_edges_mirrored(FUm, c); + case _trans_FRm: + return _trans_edges_mirrored(FRm, c); + case _trans_FDm: + return _trans_edges_mirrored(FDm, c); + case _trans_FLm: + return _trans_edges_mirrored(FLm, c); + case _trans_BUm: + return _trans_edges_mirrored(BUm, c); + case _trans_BRm: + return _trans_edges_mirrored(BRm, c); + case _trans_BDm: + return _trans_edges_mirrored(BDm, c); + case _trans_BLm: + return _trans_edges_mirrored(BLm, c); + default: + DBG_LOG("transform error, unknown transformation\n"); + return zero_fast; + } +} + +_static cube_fast_t +transform_corners(cube_fast_t c, uint8_t t) +{ + switch (t) { + case _trans_UFr: + return _trans_corners_rotation(UFr, c); + case _trans_ULr: + return _trans_corners_rotation(ULr, c); + case _trans_UBr: + return _trans_corners_rotation(UBr, c); + case _trans_URr: + return _trans_corners_rotation(URr, c); + case _trans_DFr: + return _trans_corners_rotation(DFr, c); + case _trans_DLr: + return _trans_corners_rotation(DLr, c); + case _trans_DBr: + return _trans_corners_rotation(DBr, c); + case _trans_DRr: + return _trans_corners_rotation(DRr, c); + case _trans_RUr: + return _trans_corners_rotation(RUr, c); + case _trans_RFr: + return _trans_corners_rotation(RFr, c); + case _trans_RDr: + return _trans_corners_rotation(RDr, c); + case _trans_RBr: + return _trans_corners_rotation(RBr, c); + case _trans_LUr: + return _trans_corners_rotation(LUr, c); + case _trans_LFr: + return _trans_corners_rotation(LFr, c); + case _trans_LDr: + return _trans_corners_rotation(LDr, c); + case _trans_LBr: + return _trans_corners_rotation(LBr, c); + case _trans_FUr: + return _trans_corners_rotation(FUr, c); + case _trans_FRr: + return _trans_corners_rotation(FRr, c); + case _trans_FDr: + return _trans_corners_rotation(FDr, c); + case _trans_FLr: + return _trans_corners_rotation(FLr, c); + case _trans_BUr: + return _trans_corners_rotation(BUr, c); + case _trans_BRr: + return _trans_corners_rotation(BRr, c); + case _trans_BDr: + return _trans_corners_rotation(BDr, c); + case _trans_BLr: + return _trans_corners_rotation(BLr, c); + case _trans_UFm: + return _trans_corners_mirrored(UFm, c); + case _trans_ULm: + return _trans_corners_mirrored(ULm, c); + case _trans_UBm: + return _trans_corners_mirrored(UBm, c); + case _trans_URm: + return _trans_corners_mirrored(URm, c); + case _trans_DFm: + return _trans_corners_mirrored(DFm, c); + case _trans_DLm: + return _trans_corners_mirrored(DLm, c); + case _trans_DBm: + return _trans_corners_mirrored(DBm, c); + case _trans_DRm: + return _trans_corners_mirrored(DRm, c); + case _trans_RUm: + return _trans_corners_mirrored(RUm, c); + case _trans_RFm: + return _trans_corners_mirrored(RFm, c); + case _trans_RDm: + return _trans_corners_mirrored(RDm, c); + case _trans_RBm: + return _trans_corners_mirrored(RBm, c); + case _trans_LUm: + return _trans_corners_mirrored(LUm, c); + case _trans_LFm: + return _trans_corners_mirrored(LFm, c); + case _trans_LDm: + return _trans_corners_mirrored(LDm, c); + case _trans_LBm: + return _trans_corners_mirrored(LBm, c); + case _trans_FUm: + return _trans_corners_mirrored(FUm, c); + case _trans_FRm: + return _trans_corners_mirrored(FRm, c); + case _trans_FDm: + return _trans_corners_mirrored(FDm, c); + case _trans_FLm: + return _trans_corners_mirrored(FLm, c); + case _trans_BUm: + return _trans_corners_mirrored(BUm, c); + case _trans_BRm: + return _trans_corners_mirrored(BRm, c); + case _trans_BDm: + return _trans_corners_mirrored(BDm, c); + case _trans_BLm: + return _trans_corners_mirrored(BLm, c); + default: + DBG_LOG("transform error, unknown transformation\n"); + return zero_fast; + } +} + +_static cube_fast_t +transform(cube_fast_t c, uint8_t t) +{ + switch (t) { + case _trans_UFr: + return _trans_rotation(UFr, c); + case _trans_ULr: + return _trans_rotation(ULr, c); + case _trans_UBr: + return _trans_rotation(UBr, c); + case _trans_URr: + return _trans_rotation(URr, c); + case _trans_DFr: + return _trans_rotation(DFr, c); + case _trans_DLr: + return _trans_rotation(DLr, c); + case _trans_DBr: + return _trans_rotation(DBr, c); + case _trans_DRr: + return _trans_rotation(DRr, c); + case _trans_RUr: + return _trans_rotation(RUr, c); + case _trans_RFr: + return _trans_rotation(RFr, c); + case _trans_RDr: + return _trans_rotation(RDr, c); + case _trans_RBr: + return _trans_rotation(RBr, c); + case _trans_LUr: + return _trans_rotation(LUr, c); + case _trans_LFr: + return _trans_rotation(LFr, c); + case _trans_LDr: + return _trans_rotation(LDr, c); + case _trans_LBr: + return _trans_rotation(LBr, c); + case _trans_FUr: + return _trans_rotation(FUr, c); + case _trans_FRr: + return _trans_rotation(FRr, c); + case _trans_FDr: + return _trans_rotation(FDr, c); + case _trans_FLr: + return _trans_rotation(FLr, c); + case _trans_BUr: + return _trans_rotation(BUr, c); + case _trans_BRr: + return _trans_rotation(BRr, c); + case _trans_BDr: + return _trans_rotation(BDr, c); + case _trans_BLr: + return _trans_rotation(BLr, c); + case _trans_UFm: + return _trans_mirrored(UFm, c); + case _trans_ULm: + return _trans_mirrored(ULm, c); + case _trans_UBm: + return _trans_mirrored(UBm, c); + case _trans_URm: + return _trans_mirrored(URm, c); + case _trans_DFm: + return _trans_mirrored(DFm, c); + case _trans_DLm: + return _trans_mirrored(DLm, c); + case _trans_DBm: + return _trans_mirrored(DBm, c); + case _trans_DRm: + return _trans_mirrored(DRm, c); + case _trans_RUm: + return _trans_mirrored(RUm, c); + case _trans_RFm: + return _trans_mirrored(RFm, c); + case _trans_RDm: + return _trans_mirrored(RDm, c); + case _trans_RBm: + return _trans_mirrored(RBm, c); + case _trans_LUm: + return _trans_mirrored(LUm, c); + case _trans_LFm: + return _trans_mirrored(LFm, c); + case _trans_LDm: + return _trans_mirrored(LDm, c); + case _trans_LBm: + return _trans_mirrored(LBm, c); + case _trans_FUm: + return _trans_mirrored(FUm, c); + case _trans_FRm: + return _trans_mirrored(FRm, c); + case _trans_FDm: + return _trans_mirrored(FDm, c); + case _trans_FLm: + return _trans_mirrored(FLm, c); + case _trans_BUm: + return _trans_mirrored(BUm, c); + case _trans_BRm: + return _trans_mirrored(BRm, c); + case _trans_BDm: + return _trans_mirrored(BDm, c); + case _trans_BLm: + return _trans_mirrored(BLm, c); + default: + DBG_LOG("transform error, unknown transformation\n"); + return zero_fast; + } +} diff --git a/src/solve_h48.h b/src/solve_h48.h @@ -71,8 +71,7 @@ coord_h48_edges(cube_fast_t c, int64_t coclass, uint8_t t, uint8_t h) cube_fast_t d; int64_t esep, eo; - //d = transform_edges(c, t); - d = transform(c, t); + d = transform_edges(c, t); esep = coord_fast_esep(d); eo = coord_fast_eo(d); @@ -181,8 +180,7 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) return 0; for (t = 0, cc = 0; t < 48; t++) { - //d = transform_corners(arg->cube, t); - d = transform(arg->cube, t); + d = transform_corners(arg->cube, t); ii = coord_fast_cocsep(d); arg->selfsim[*arg->n] |= (i == ii) << t; set_visited(arg->visited, ii);