cube.h (4044B)
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(int64_t *, int64_t *, int64_t *, int64_t *); 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 LOG("Inconsistent EP\n"); 70 return false; 71 inconsistent_cp: 72 LOG("Inconsistent CP\n"); 73 return false; 74 inconsistent_eo: 75 LOG("Inconsistent EO\n"); 76 return false; 77 inconsistent_co: 78 LOG("Inconsistent CO\n"); 79 return false; 80 } 81 82 STATIC bool 83 issolvable(cube_t cube) 84 { 85 uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8]; 86 87 DBG_ASSERT(isconsistent(cube), false, 88 "issolvable: cube is inconsistent\n"); 89 90 pieces(&cube, corner, edge); 91 for (i = 0; i < 12; i++) 92 ep[i] = edge[i] & PBITS; 93 for (i = 0; i < 8; i++) 94 cp[i] = corner[i] & PBITS; 95 96 if (permsign(ep, 12) != permsign(cp, 8)) 97 goto issolvable_parity; 98 99 eo = 0; 100 for (i = 0; i < 12; i++) { 101 piece = edge[i]; 102 eo += (piece & EOBIT) >> EOSHIFT; 103 } 104 if (eo % 2 != 0) 105 goto issolvable_eo; 106 107 co = 0; 108 for (i = 0; i < 8; i++) { 109 piece = corner[i]; 110 co += (piece & COBITS) >> COSHIFT; 111 } 112 if (co % 3 != 0) 113 goto issolvable_co; 114 115 return true; 116 117 issolvable_parity: 118 LOG("EP and CP parities are different\n"); 119 return false; 120 issolvable_eo: 121 LOG("Odd number of flipped edges\n"); 122 return false; 123 issolvable_co: 124 LOG("Sum of corner orientation is not multiple of 3\n"); 125 return false; 126 } 127 128 bool 129 issolved(cube_t cube) 130 { 131 return equal(cube, SOLVED_CUBE); 132 } 133 134 bool 135 iserror(cube_t cube) 136 { 137 return equal(cube, ZERO_CUBE); 138 } 139 140 STATIC void 141 getcube_fix(int64_t *ep, int64_t *eo, int64_t *cp, int64_t *co) 142 { 143 uint8_t e[12], c[8], coarr[8]; 144 145 *ep = (*ep % FACT_12 + FACT_12) % FACT_12; 146 *eo = (*eo % POW_2_11 + POW_2_11) % POW_2_11; 147 *cp = (*cp % FACT_8 + FACT_8) % FACT_8; 148 *co = (*cp % POW_3_7 + POW_3_7) % POW_3_7; 149 150 indextoperm(*ep, 12, e); 151 indextoperm(*cp, 8, c); 152 if (permsign(e, 12) != permsign(c, 8)) { 153 SWAP(c[0], c[1]); 154 *cp = permtoindex(c, 8); 155 156 sumzerotodigits(*co, 8, 3, coarr); 157 SWAP(coarr[0], coarr[1]); 158 *co = digitstosumzero(coarr, 8, 3); 159 } 160 } 161 162 STATIC cube_t 163 getcube(int64_t ep, int64_t eo, int64_t cp, int64_t co) 164 { 165 uint8_t i, earr[12], carr[8], eoarr[12], coarr[8]; 166 167 sumzerotodigits(eo, 12, 2, eoarr); 168 DBG_ASSERT(eoarr[0] != UINT8_ERROR, ZERO_CUBE, "Error making EO"); 169 indextoperm(ep, 12, earr); 170 DBG_ASSERT(earr[0] != UINT8_ERROR, ZERO_CUBE, "Error making EP"); 171 for (i = 0; i < 12; i++) 172 earr[i] |= eoarr[i] << EOSHIFT; 173 174 sumzerotodigits(co, 8, 3, coarr); 175 DBG_ASSERT(coarr[0] != UINT8_ERROR, ZERO_CUBE, "Error making CO"); 176 indextoperm(cp, 8, carr); 177 DBG_ASSERT(carr[0] != UINT8_ERROR, ZERO_CUBE, "Error making CP"); 178 for (i = 0; i < 8; i++) 179 carr[i] |= coarr[i] << COSHIFT; 180 181 return cubefromarray(carr, earr); 182 }