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

Generated with cgit - Back to sebastiano.tronto.net