diff options
Diffstat (limited to 'src/cube_portable.h')
| -rw-r--r-- | src/cube_portable.h | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/cube_portable.h b/src/cube_portable.h new file mode 100644 index 0000000..281faa0 --- /dev/null +++ b/src/cube_portable.h | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | typedef cube_t cube_fast_t; | ||
| 2 | |||
| 3 | _static_inline cube_fast_t fastcube( | ||
| 4 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, | ||
| 5 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, | ||
| 6 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, | ||
| 7 | uint8_t, uint8_t, uint8_t, uint8_t, uint8_t | ||
| 8 | ); | ||
| 9 | _static cube_fast_t cubetofast(cube_t); | ||
| 10 | _static cube_t fasttocube(cube_fast_t); | ||
| 11 | _static_inline bool equal_fast(cube_fast_t, cube_fast_t); | ||
| 12 | _static_inline bool issolved_fast(cube_fast_t); | ||
| 13 | _static_inline cube_fast_t invertco_fast(cube_fast_t); | ||
| 14 | _static_inline cube_fast_t compose_fast(cube_fast_t, cube_fast_t); | ||
| 15 | |||
| 16 | _static_inline int64_t coord_fast_co(cube_fast_t); | ||
| 17 | _static_inline int64_t coord_fast_csep(cube_fast_t); | ||
| 18 | _static_inline int64_t coord_fast_cocsep(cube_fast_t); | ||
| 19 | _static_inline int64_t coord_fast_eo(cube_fast_t); | ||
| 20 | _static_inline int64_t coord_fast_esep(cube_fast_t); | ||
| 21 | |||
| 22 | _static_inline cube_fast_t | ||
| 23 | fastcube( | ||
| 24 | uint8_t c_ufr, | ||
| 25 | uint8_t c_ubl, | ||
| 26 | uint8_t c_dfl, | ||
| 27 | uint8_t c_dbr, | ||
| 28 | uint8_t c_ufl, | ||
| 29 | uint8_t c_ubr, | ||
| 30 | uint8_t c_dfr, | ||
| 31 | uint8_t c_dbl, | ||
| 32 | |||
| 33 | uint8_t e_uf, | ||
| 34 | uint8_t e_ub, | ||
| 35 | uint8_t e_db, | ||
| 36 | uint8_t e_df, | ||
| 37 | uint8_t e_ur, | ||
| 38 | uint8_t e_ul, | ||
| 39 | uint8_t e_dl, | ||
| 40 | uint8_t e_dr, | ||
| 41 | uint8_t e_fr, | ||
| 42 | uint8_t e_fl, | ||
| 43 | uint8_t e_bl, | ||
| 44 | uint8_t e_br | ||
| 45 | ) | ||
| 46 | { | ||
| 47 | cube_fast_t cube = { | ||
| 48 | .corner = { | ||
| 49 | c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl | ||
| 50 | }, | ||
| 51 | .edge = { | ||
| 52 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, | ||
| 53 | e_dl, e_dr, e_fr, e_fl, e_bl, e_br | ||
| 54 | } | ||
| 55 | }; | ||
| 56 | |||
| 57 | return cube; | ||
| 58 | } | ||
| 59 | |||
| 60 | _static cube_fast_t | ||
| 61 | cubetofast(cube_t cube) | ||
| 62 | { | ||
| 63 | cube_fast_t fast; | ||
| 64 | memcpy(&fast, &cube, sizeof(cube_fast_t)); | ||
| 65 | return fast; | ||
| 66 | } | ||
| 67 | |||
| 68 | _static cube_t | ||
| 69 | fasttocube(cube_fast_t fast) | ||
| 70 | { | ||
| 71 | cube_t cube; | ||
| 72 | memcpy(&cube, &fast, sizeof(cube_fast_t)); | ||
| 73 | return cube; | ||
| 74 | } | ||
| 75 | |||
| 76 | _static_inline bool | ||
| 77 | equal_fast(cube_fast_t c1, cube_fast_t c2) | ||
| 78 | { | ||
| 79 | uint8_t i; | ||
| 80 | bool ret; | ||
| 81 | |||
| 82 | ret = true; | ||
| 83 | for (i = 0; i < 8; i++) | ||
| 84 | ret = ret && c1.corner[i] == c2.corner[i]; | ||
| 85 | for (i = 0; i < 12; i++) | ||
| 86 | ret = ret && c1.edge[i] == c2.edge[i]; | ||
| 87 | |||
| 88 | return ret; | ||
| 89 | } | ||
| 90 | |||
| 91 | _static_inline bool | ||
| 92 | issolved_fast(cube_fast_t cube) | ||
| 93 | { | ||
| 94 | return equal_fast(cube, solved_fast); | ||
| 95 | } | ||
| 96 | |||
| 97 | _static_inline cube_fast_t | ||
| 98 | invertco_fast(cube_fast_t c) | ||
| 99 | { | ||
| 100 | uint8_t i, piece, orien; | ||
| 101 | cube_fast_t ret; | ||
| 102 | |||
| 103 | ret = c; | ||
| 104 | for (i = 0; i < 8; i++) { | ||
| 105 | piece = c.corner[i]; | ||
| 106 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | ||
| 107 | ret.corner[i] = (piece & _pbits) | orien; | ||
| 108 | } | ||
| 109 | |||
| 110 | return ret; | ||
| 111 | } | ||
| 112 | |||
| 113 | _static_inline cube_fast_t | ||
| 114 | compose_fast(cube_fast_t c1, cube_fast_t c2) | ||
| 115 | { | ||
| 116 | cube_fast_t ret; | ||
| 117 | uint8_t i, piece1, piece2, p, orien, aux, auy; | ||
| 118 | |||
| 119 | ret = zero_fast; | ||
| 120 | |||
| 121 | for (i = 0; i < 12; i++) { | ||
| 122 | piece2 = c2.edge[i]; | ||
| 123 | p = piece2 & _pbits; | ||
| 124 | piece1 = c1.edge[p]; | ||
| 125 | orien = (piece2 ^ piece1) & _eobit; | ||
| 126 | ret.edge[i] = (piece1 & _pbits) | orien; | ||
| 127 | } | ||
| 128 | |||
| 129 | for (i = 0; i < 8; i++) { | ||
| 130 | piece2 = c2.corner[i]; | ||
| 131 | p = piece2 & _pbits; | ||
| 132 | piece1 = c1.corner[p]; | ||
| 133 | aux = (piece2 & _cobits) + (piece1 & _cobits); | ||
| 134 | auy = (aux + _ctwist_cw) >> 2U; | ||
| 135 | orien = (aux + auy) & _cobits2; | ||
| 136 | ret.corner[i] = (piece1 & _pbits) | orien; | ||
| 137 | } | ||
| 138 | |||
| 139 | return ret; | ||
| 140 | } | ||
| 141 | |||
| 142 | _static_inline int64_t | ||
| 143 | coord_fast_co(cube_fast_t c) | ||
| 144 | { | ||
| 145 | int i, p; | ||
| 146 | int64_t ret; | ||
| 147 | |||
| 148 | for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 3) | ||
| 149 | ret += p * (c.corner[i] >> _coshift); | ||
| 150 | |||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 155 | For corner separation, we consider the axis (a.k.a. tetrad) each | ||
| 156 | corner belongs to as 0 or 1 and we translate this sequence into binary. | ||
| 157 | Ignoring the last bit, we have a value up to 2^7, but not all values are | ||
| 158 | possible. Encoding this as a number from 0 to C(8,4) would save about 40% | ||
| 159 | of space, but we are not going to use this coordinate in large tables. | ||
| 160 | */ | ||
| 161 | _static_inline int64_t | ||
| 162 | coord_fast_csep(cube_fast_t c) | ||
| 163 | { | ||
| 164 | int i, p; | ||
| 165 | int64_t ret; | ||
| 166 | |||
| 167 | for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 2) | ||
| 168 | ret += p * ((c.corner[i] & _csepbit) >> 2U); | ||
| 169 | |||
| 170 | return ret; | ||
| 171 | } | ||
| 172 | |||
| 173 | _static_inline int64_t | ||
| 174 | coord_fast_cocsep(cube_fast_t c) | ||
| 175 | { | ||
| 176 | return (coord_fast_co(c) << 7) + coord_fast_csep(c); | ||
| 177 | } | ||
| 178 | |||
| 179 | _static_inline int64_t | ||
| 180 | coord_fast_eo(cube_fast_t c) | ||
| 181 | { | ||
| 182 | int i, p; | ||
| 183 | int64_t ret; | ||
| 184 | |||
| 185 | for (ret = 0, i = 1, p = 1; i < 12; i++, p *= 2) | ||
| 186 | ret += p * (c.edge[i] >> _eoshift); | ||
| 187 | |||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* | ||
| 192 | We encode the edge separation as a number from 0 to C(12,4)*C(8,4). | ||
| 193 | It can be seen as the composition of two "subset index" coordinates. | ||
| 194 | */ | ||
| 195 | _static_inline int64_t | ||
| 196 | coord_fast_esep(cube_fast_t c) | ||
| 197 | { | ||
| 198 | int64_t i, j, k, l, ret1, ret2, bit1, bit2, is1; | ||
| 199 | |||
| 200 | for (i = 0, j = 0, k = 4, l = 4, ret1 = 0, ret2 = 0; i < 12; i++) { | ||
| 201 | /* Simple version: | ||
| 202 | if (c.edge[i] & _esepbit2) { | ||
| 203 | ret1 += binomial[11-i][k--]; | ||
| 204 | } else { | ||
| 205 | if (c.edge[i] & _esepbit1) | ||
| 206 | ret2 += binomial[7-j][l--]; | ||
| 207 | j++; | ||
| 208 | } | ||
| 209 | */ | ||
| 210 | |||
| 211 | bit1 = (c.edge[i] & _esepbit1) >> 2U; | ||
| 212 | bit2 = (c.edge[i] & _esepbit2) >> 3U; | ||
| 213 | is1 = (1 - bit2) * bit1; | ||
| 214 | |||
| 215 | ret1 += bit2 * binomial[11-i][k]; | ||
| 216 | k -= bit2; | ||
| 217 | |||
| 218 | ret2 += is1 * binomial[7-j][l]; | ||
| 219 | l -= is1; | ||
| 220 | j += (1-bit2); | ||
| 221 | } | ||
| 222 | |||
| 223 | return ret1 * 70 + ret2; | ||
| 224 | } | ||
