aboutsummaryrefslogtreecommitdiff
path: root/src/arch/portable.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/portable.h')
-rw-r--r--src/arch/portable.h272
1 files changed, 272 insertions, 0 deletions
diff --git a/src/arch/portable.h b/src/arch/portable.h
new file mode 100644
index 0000000..b8330af
--- /dev/null
+++ b/src/arch/portable.h
@@ -0,0 +1,272 @@
1#define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \
2 e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \
3 ((cube_t) { \
4 .corner = { c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl }, \
5 .edge = { e_uf, e_ub, e_db, e_df, e_ur, e_ul, \
6 e_dl, e_dr, e_fr, e_fl, e_bl, e_br } })
7#define zero static_cube( \
8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
9#define solved static_cube( \
10 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
11
12_static void
13pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12])
14{
15 memcpy(c, cube->corner, 8);
16 memcpy(e, cube->edge, 12);
17}
18
19_static_inline bool
20equal(cube_t c1, cube_t c2)
21{
22 uint8_t i;
23 bool ret;
24
25 ret = true;
26 for (i = 0; i < 8; i++)
27 ret = ret && c1.corner[i] == c2.corner[i];
28 for (i = 0; i < 12; i++)
29 ret = ret && c1.edge[i] == c2.edge[i];
30
31 return ret;
32}
33
34_static_inline cube_t
35invertco(cube_t c)
36{
37 uint8_t i, piece, orien;
38 cube_t ret;
39
40 ret = c;
41 for (i = 0; i < 8; i++) {
42 piece = c.corner[i];
43 orien = ((piece << 1) | (piece >> 1)) & _cobits2;
44 ret.corner[i] = (piece & _pbits) | orien;
45 }
46
47 return ret;
48}
49
50_static_inline void
51compose_edges_inplace(cube_t c1, cube_t c2, cube_t *ret)
52{
53 uint8_t i, piece1, piece2, p, orien;
54
55 for (i = 0; i < 12; i++) {
56 piece2 = c2.edge[i];
57 p = piece2 & _pbits;
58 piece1 = c1.edge[p];
59 orien = (piece2 ^ piece1) & _eobit;
60 ret->edge[i] = (piece1 & _pbits) | orien;
61 }
62}
63
64_static_inline void
65compose_corners_inplace(cube_t c1, cube_t c2, cube_t *ret)
66{
67 uint8_t i, piece1, piece2, p, orien, aux, auy;
68
69 for (i = 0; i < 8; i++) {
70 piece2 = c2.corner[i];
71 p = piece2 & _pbits;
72 piece1 = c1.corner[p];
73 aux = (piece2 & _cobits) + (piece1 & _cobits);
74 auy = (aux + _ctwist_cw) >> 2;
75 orien = (aux + auy) & _cobits2;
76 ret->corner[i] = (piece1 & _pbits) | orien;
77 }
78}
79
80_static_inline cube_t
81compose_edges(cube_t c1, cube_t c2)
82{
83 cube_t ret = zero;
84
85 compose_edges_inplace(c1, c2, &ret);
86
87 return ret;
88}
89
90_static_inline cube_t
91compose_corners(cube_t c1, cube_t c2)
92{
93 cube_t ret = zero;
94
95 compose_corners_inplace(c1, c2, &ret);
96
97 return ret;
98}
99
100_static_inline cube_t
101compose(cube_t c1, cube_t c2)
102{
103 cube_t ret = zero;
104
105 compose_edges_inplace(c1, c2, &ret);
106 compose_corners_inplace(c1, c2, &ret);
107
108 return ret;
109}
110
111cube_t
112inverse(cube_t cube)
113{
114 uint8_t i, piece, orien;
115 cube_t ret;
116
117 for (i = 0; i < 12; i++) {
118 piece = cube.edge[i];
119 orien = piece & _eobit;
120 ret.edge[piece & _pbits] = i | orien;
121 }
122
123 for (i = 0; i < 8; i++) {
124 piece = cube.corner[i];
125 orien = ((piece << 1) | (piece >> 1)) & _cobits2;
126 ret.corner[piece & _pbits] = i | orien;
127 }
128
129 return ret;
130}
131
132_static_inline int64_t
133coord_co(cube_t c)
134{
135 int i, p;
136 int64_t ret;
137
138 for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 3)
139 ret += p * (c.corner[i] >> _coshift);
140
141 return ret;
142}
143
144/*
145For corner separation, we consider the axis (a.k.a. tetrad) each
146corner belongs to as 0 or 1 and we translate this sequence into binary.
147Ignoring the last bit, we have a value up to 2^7, but not all values are
148possible. Encoding this as a number from 0 to C(8,4) would save about 40%
149of space, but we are not going to use this coordinate in large tables.
150*/
151_static_inline int64_t
152coord_csep(cube_t c)
153{
154 int i, p;
155 int64_t ret;
156
157 for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 2)
158 ret += p * ((c.corner[i] & _csepbit) >> 2);
159
160 return ret;
161}
162
163_static_inline int64_t
164coord_cocsep(cube_t c)
165{
166 return (coord_co(c) << 7) + coord_csep(c);
167}
168
169_static_inline int64_t
170coord_eo(cube_t c)
171{
172 int i, p;
173 int64_t ret;
174
175 for (ret = 0, i = 1, p = 1; i < 12; i++, p *= 2)
176 ret += p * (c.edge[i] >> _eoshift);
177
178 return ret;
179}
180
181/*
182We encode the edge separation as a number from 0 to C(12,4)*C(8,4).
183It can be seen as the composition of two "subset index" coordinates.
184*/
185_static_inline int64_t
186coord_esep(cube_t c)
187{
188 int64_t i, j, jj, k, l, ret1, ret2, bit1, bit2, is1;
189
190 for (i = 0, j = 0, k = 4, l = 4, ret1 = 0, ret2 = 0; i < 12; i++) {
191 /* Simple version:
192 if (c.edge[i] & _esepbit2) {
193 ret1 += binomial[11-i][k--];
194 } else {
195 if (c.edge[i] & _esepbit1)
196 ret2 += binomial[7-j][l--];
197 j++;
198 }
199 */
200
201 bit1 = (c.edge[i] & _esepbit1) >> 2;
202 bit2 = (c.edge[i] & _esepbit2) >> 3;
203 is1 = (1 - bit2) * bit1;
204
205 ret1 += bit2 * binomial[11-i][k];
206 k -= bit2;
207
208 jj = j < 8;
209 ret2 += jj * is1 * binomial[7-(j*jj)][l];
210 l -= is1;
211 j += (1-bit2);
212 }
213
214 return ret1 * 70 + ret2;
215}
216
217_static_inline void
218copy_corners(cube_t *dest, cube_t src)
219{
220 memcpy(&dest->corner, src.corner, sizeof(src.corner));
221}
222
223_static_inline void
224copy_edges(cube_t *dest, cube_t src)
225{
226 memcpy(&dest->edge, src.edge, sizeof(src.edge));
227}
228
229_static_inline void
230set_eo(cube_t *cube, int64_t eo)
231{
232 uint8_t i, sum, flip;
233
234 for (sum = 0, i = 1; i < 12; i++, eo >>= 1) {
235 flip = eo % 2;
236 sum += flip;
237 cube->edge[i] = (cube->edge[i] & ~_eobit) | (_eobit * flip);
238 }
239 cube->edge[0] = (cube->edge[0] & ~_eobit) | (_eobit * (sum % 2));
240}
241
242_static_inline cube_t
243invcoord_esep(int64_t esep)
244{
245 cube_t ret;
246 int64_t bit1, bit2, i, j, jj, k, l, s, v, w, is1, set1, set2;
247 uint8_t slice[3] = {0};
248
249 ret = solved;
250 set1 = esep % 70;
251 set2 = esep / 70;
252
253 for (i = 0, j = 0, k = 4, l = 4; i < 12; i++) {
254 v = binomial[11-i][k];
255 jj = j < 8;
256 w = jj * binomial[7-(j*jj)][l];
257 bit2 = set2 >= v;
258 bit1 = set1 >= w;
259 is1 = (1 - bit2) * bit1;
260
261 set2 -= bit2 * v;
262 k -= bit2;
263 set1 -= is1 * w;
264 l -= is1;
265 j += (1-bit2);
266 s = 2*bit2 + (1-bit2)*bit1;
267
268 ret.edge[i] = (slice[s]++) | (uint8_t)(s << 2);
269 }
270
271 return ret;
272}

Generated with cgit - Back to sebastiano.tronto.net