aboutsummaryrefslogtreecommitdiff
path: root/src/cube_portable.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/cube_portable.h')
-rw-r--r--src/cube_portable.h224
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 @@
1typedef 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
23fastcube(
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
61cubetofast(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
69fasttocube(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
77equal_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
92issolved_fast(cube_fast_t cube)
93{
94 return equal_fast(cube, solved_fast);
95}
96
97_static_inline cube_fast_t
98invertco_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
114compose_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
143coord_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/*
155For corner separation, we consider the axis (a.k.a. tetrad) each
156corner belongs to as 0 or 1 and we translate this sequence into binary.
157Ignoring the last bit, we have a value up to 2^7, but not all values are
158possible. Encoding this as a number from 0 to C(8,4) would save about 40%
159of space, but we are not going to use this coordinate in large tables.
160*/
161_static_inline int64_t
162coord_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
174coord_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
180coord_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/*
192We encode the edge separation as a number from 0 to C(12,4)*C(8,4).
193It can be seen as the composition of two "subset index" coordinates.
194*/
195_static_inline int64_t
196coord_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}

Generated with cgit - Back to sebastiano.tronto.net