cube.h (3874B)
1 STATIC cube_t solvecube(void); 2 STATIC cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]); 3 STATIC bool isconsistent(cube_t); 4 STATIC bool issolvable(cube_t); 5 STATIC bool issolved(cube_t); 6 STATIC bool iserror(cube_t); 7 STATIC void getcube_fix(long long *, long long *, long long *, long long *); 8 STATIC cube_t getcube(int64_t, int64_t, int64_t, int64_t); 9 10 /* This is used only in tests, use SOLVED_CUBE directly everywhere else */ 11 STATIC cube_t 12 solvedcube(void) 13 { 14 return SOLVED_CUBE; 15 } 16 17 STATIC cube_t 18 cubefromarray(uint8_t c[static 8], uint8_t e[static 12]) 19 { 20 return STATIC_CUBE( 21 c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], 22 e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], 23 e[8], e[9], e[10], e[11]); 24 } 25 26 STATIC bool 27 isconsistent(cube_t cube) 28 { 29 uint8_t i, p, e, piece, corner[8], edge[12]; 30 bool found[12]; 31 32 pieces(&cube, corner, edge); 33 34 for (i = 0; i < 12; i++) 35 found[i] = false; 36 for (i = 0; i < 12; i++) { 37 piece = edge[i]; 38 p = piece & PBITS; 39 e = piece & EOBIT; 40 if (p >= 12) 41 goto inconsistent_ep; 42 if (e != 0 && e != EOBIT) 43 goto inconsistent_eo; 44 found[p] = true; 45 } 46 for (i = 0; i < 12; i++) 47 if (!found[i]) 48 goto inconsistent_ep; 49 50 for (i = 0; i < 8; i++) 51 found[i] = false; 52 for (i = 0; i < 8; i++) { 53 piece = corner[i]; 54 p = piece & PBITS; 55 e = piece & COBITS; 56 if (p >= 8) 57 goto inconsistent_cp; 58 if (e != 0 && e != CTWIST_CW && e != CTWIST_CCW) 59 goto inconsistent_co; 60 found[p] = true; 61 } 62 for (i = 0; i < 8; i++) 63 if (!found[i]) 64 goto inconsistent_co; 65 66 return true; 67 68 inconsistent_ep: 69 inconsistent_cp: 70 inconsistent_eo: 71 inconsistent_co: 72 /* We used to do more logging here, hence the 4 different labels */ 73 return false; 74 } 75 76 STATIC bool 77 issolvable(cube_t cube) 78 { 79 uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8]; 80 81 DBG_ASSERT(isconsistent(cube), false, 82 "issolvable: cube is inconsistent\n"); 83 84 pieces(&cube, corner, edge); 85 for (i = 0; i < 12; i++) 86 ep[i] = edge[i] & PBITS; 87 for (i = 0; i < 8; i++) 88 cp[i] = corner[i] & PBITS; 89 90 if (permsign(ep, 12) != permsign(cp, 8)) 91 goto issolvable_parity; 92 93 eo = 0; 94 for (i = 0; i < 12; i++) { 95 piece = edge[i]; 96 eo += (piece & EOBIT) >> EOSHIFT; 97 } 98 if (eo % 2 != 0) 99 goto issolvable_eo; 100 101 co = 0; 102 for (i = 0; i < 8; i++) { 103 piece = corner[i]; 104 co += (piece & COBITS) >> COSHIFT; 105 } 106 if (co % 3 != 0) 107 goto issolvable_co; 108 109 return true; 110 111 issolvable_parity: 112 issolvable_eo: 113 issolvable_co: 114 /* We used to do more logging here, hence the 3 different labels */ 115 return false; 116 } 117 118 bool 119 issolved(cube_t cube) 120 { 121 return equal(cube, SOLVED_CUBE); 122 } 123 124 bool 125 iserror(cube_t cube) 126 { 127 return equal(cube, ZERO_CUBE); 128 } 129 130 STATIC void 131 getcube_fix(long long *ep, long long *eo, long long *cp, long long *co) 132 { 133 uint8_t e[12], c[8], coarr[8]; 134 135 *ep = (*ep % FACT_12 + FACT_12) % FACT_12; 136 *eo = (*eo % POW_2_11 + POW_2_11) % POW_2_11; 137 *cp = (*cp % FACT_8 + FACT_8) % FACT_8; 138 *co = (*cp % POW_3_7 + POW_3_7) % POW_3_7; 139 140 indextoperm(*ep, 12, e); 141 indextoperm(*cp, 8, c); 142 if (permsign(e, 12) != permsign(c, 8)) { 143 SWAP(c[0], c[1]); 144 *cp = permtoindex(c, 8); 145 146 sumzerotodigits(*co, 8, 3, coarr); 147 SWAP(coarr[0], coarr[1]); 148 *co = digitstosumzero(coarr, 8, 3); 149 } 150 } 151 152 STATIC cube_t 153 getcube(int64_t ep, int64_t eo, int64_t cp, int64_t co) 154 { 155 uint8_t i, earr[12], carr[8], eoarr[12], coarr[8]; 156 157 sumzerotodigits(eo, 12, 2, eoarr); 158 DBG_ASSERT(eoarr[0] != UINT8_ERROR, ZERO_CUBE, "Error making EO"); 159 indextoperm(ep, 12, earr); 160 DBG_ASSERT(earr[0] != UINT8_ERROR, ZERO_CUBE, "Error making EP"); 161 for (i = 0; i < 12; i++) 162 earr[i] |= eoarr[i] << EOSHIFT; 163 164 sumzerotodigits(co, 8, 3, coarr); 165 DBG_ASSERT(coarr[0] != UINT8_ERROR, ZERO_CUBE, "Error making CO"); 166 indextoperm(cp, 8, carr); 167 DBG_ASSERT(carr[0] != UINT8_ERROR, ZERO_CUBE, "Error making CP"); 168 for (i = 0; i < 8; i++) 169 carr[i] |= coarr[i] << COSHIFT; 170 171 return cubefromarray(carr, earr); 172 }