aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cube_neon.h521
1 files changed, 254 insertions, 267 deletions
diff --git a/src/cube_neon.h b/src/cube_neon.h
index 4739593..e01ea4c 100644
--- a/src/cube_neon.h
+++ b/src/cube_neon.h
@@ -1,36 +1,36 @@
1// cube_t 1// cube_t
2typedef struct 2typedef struct
3{ 3{
4 uint8x16_t corner; 4 uint8x16_t corner;
5 uint8x16_t edge; 5 uint8x16_t edge;
6} cube_t; 6} cube_t;
7 7
8// static cube 8// static cube
9#define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ 9#define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \
10 e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ 10 e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \
11 ((cube_t){ \ 11 ((cube_t){ \
12 .corner = {c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, 0, 0, 0, 0, 0, 0, 0, 0}, \ 12 .corner = {c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, 0, 0, 0, 0, 0, 0, 0, 0}, \
13 .edge = {e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br, 0, 0, 0, 0}}) 13 .edge = {e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br, 0, 0, 0, 0}})
14 14
15// zero cube 15// zero cube
16#define zero \ 16#define zero \
17 (cube_t) \ 17 (cube_t) \
18 { \ 18 { \
19 .corner = vdupq_n_u8(0), \ 19 .corner = vdupq_n_u8(0), \
20 .edge = vdupq_n_u8(0) \ 20 .edge = vdupq_n_u8(0) \
21 } 21 }
22 22
23// solved cube 23// solved cube
24#define solved static_cube( \ 24#define solved static_cube( \
25 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) 25 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
26 26
27// Functions 27// Functions
28_static void pieces(cube_t *, uint8_t[static 8], uint8_t[static 12]); 28_static void pieces(cube_t *, uint8_t[static 8], uint8_t[static 12]);
29_static_inline bool equal(cube_t, cube_t); 29_static_inline bool equal(cube_t, cube_t);
30_static_inline cube_t invertco(cube_t); 30_static_inline cube_t invertco(cube_t);
31_static_inline cube_t compose_edges(cube_t, cube_t); // implementation similar to portable compose_edges_inplace 31_static_inline cube_t compose_edges(cube_t, cube_t); // implementation similar to portable compose_edges_inplace
32_static_inline cube_t compose_corners(cube_t, cube_t); // implementation similar to portable compose_corners_inplace 32_static_inline cube_t compose_corners(cube_t, cube_t); // implementation similar to portable compose_corners_inplace
33_static_inline uint8x16_t compose_edges_slim(uint8x16_t, uint8x16_t); // similar to compose_edges but without the cube_t struct 33_static_inline uint8x16_t compose_edges_slim(uint8x16_t, uint8x16_t); // similar to compose_edges but without the cube_t struct
34_static_inline uint8x16_t compose_corners_slim(uint8x16_t, uint8x16_t); // similar to compose_corners but without the cube_t struct 34_static_inline uint8x16_t compose_corners_slim(uint8x16_t, uint8x16_t); // similar to compose_corners but without the cube_t struct
35_static_inline cube_t compose(cube_t, cube_t); 35_static_inline cube_t compose(cube_t, cube_t);
36_static_inline cube_t inverse(cube_t); 36_static_inline cube_t inverse(cube_t);
@@ -45,392 +45,379 @@ _static_inline void copy_corners(cube_t *, cube_t);
45_static_inline void copy_edges(cube_t *, cube_t); 45_static_inline void copy_edges(cube_t *, cube_t);
46_static_inline void set_eo(cube_t *, int64_t); 46_static_inline void set_eo(cube_t *, int64_t);
47_static_inline cube_t invcoord_esep(int64_t); 47_static_inline cube_t invcoord_esep(int64_t);
48/*
49_static void pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12]) {
50 uint8_t aux[32];
51 48
52 // Store the corner and edge vectors into the aux array 49_static void
53 vst1q_u8(aux, cube->corner);
54 vst1q_u8(aux + 16, cube->edge);
55
56 // Copy the required parts to the output arrays
57 memcpy(c, aux, 8);
58 memcpy(e, aux + 16, 12);
59}
60*/
61
62_static void
63pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12]) 50pieces(cube_t *cube, uint8_t c[static 8], uint8_t e[static 12])
64{ 51{
65 // First 8 bytes of the corner vector are copied from the c array 52 // First 8 bytes of the corner vector are copied from the c array
66 vst1_u8(c, vget_low_u8(cube->corner)); 53 vst1_u8(c, vget_low_u8(cube->corner));
67 54
68 // 12 bytes of the edge vector are copied from the e array 55 // 12 bytes of the edge vector are copied from the e array
69 // First 8 bytes 56 // First 8 bytes
70 vst1_u8(e, vget_low_u8(cube->edge)); 57 vst1_u8(e, vget_low_u8(cube->edge));
71 // Next 4 bytes 58 // Next 4 bytes
72 vst1_lane_u32((uint32_t *)(e + 8), vreinterpret_u32_u8(vget_high_u8(cube->edge)), 0); 59 vst1_lane_u32((uint32_t *)(e + 8), vreinterpret_u32_u8(vget_high_u8(cube->edge)), 0);
73} 60}
74 61
75_static_inline bool 62_static_inline bool
76equal(cube_t c1, cube_t c2) 63equal(cube_t c1, cube_t c2)
77{ 64{
78 uint8x16_t cmp_corner, cmp_edge; 65 uint8x16_t cmp_corner, cmp_edge;
79 uint64x2_t cmp_corner_u64, cmp_edge_u64; 66 uint64x2_t cmp_corner_u64, cmp_edge_u64;
80 uint64x2_t cmp_result; 67 uint64x2_t cmp_result;
81 68
82 // compare the corner vectors 69 // compare the corner vectors
83 cmp_corner = vceqq_u8(c1.corner, c2.corner); 70 cmp_corner = vceqq_u8(c1.corner, c2.corner);
84 // compare the edge vectors 71 // compare the edge vectors
85 cmp_edge = vceqq_u8(c1.edge, c2.edge); 72 cmp_edge = vceqq_u8(c1.edge, c2.edge);
86 73
87 // convert the comparison vectors to 64-bit vectors 74 // convert the comparison vectors to 64-bit vectors
88 cmp_corner_u64 = vreinterpretq_u64_u8(cmp_corner); 75 cmp_corner_u64 = vreinterpretq_u64_u8(cmp_corner);
89 cmp_edge_u64 = vreinterpretq_u64_u8(cmp_edge); 76 cmp_edge_u64 = vreinterpretq_u64_u8(cmp_edge);
90 77
91 // combine the comparison vectors 78 // combine the comparison vectors
92 cmp_result = vandq_u64(cmp_corner_u64, cmp_edge_u64); 79 cmp_result = vandq_u64(cmp_corner_u64, cmp_edge_u64);
93 80
94 // check if all the bits are set 81 // check if all the bits are set
95 return vgetq_lane_u64(cmp_result, 0) == ~0ULL && vgetq_lane_u64(cmp_result, 1) == ~0ULL; 82 return vgetq_lane_u64(cmp_result, 0) == ~0ULL && vgetq_lane_u64(cmp_result, 1) == ~0ULL;
96} 83}
97 84
98_static_inline cube_t invertco(cube_t c) 85_static_inline cube_t invertco(cube_t c)
99{ 86{
100 cube_t ret; 87 cube_t ret;
101 88
102 // Copy the corner vector to an array 89 // Copy the corner vector to an array
103 uint8_t corners[16]; 90 uint8_t corners[16];
104 vst1q_u8(corners, c.corner); 91 vst1q_u8(corners, c.corner);
105 92
106 uint8_t corner_result[16] = {0}; 93 uint8_t corner_result[16] = {0};
107 94
108 // Process the corners 95 // Process the corners
109 for (uint8_t i = 0; i < 8; i++) 96 for (uint8_t i = 0; i < 8; i++)
110 { 97 {
111 uint8_t piece = corners[i]; 98 uint8_t piece = corners[i];
112 uint8_t orien = ((piece << 1) | (piece >> 1)) & _cobits2; 99 uint8_t orien = ((piece << 1) | (piece >> 1)) & _cobits2;
113 corner_result[i] = (piece & _pbits) | orien; 100 corner_result[i] = (piece & _pbits) | orien;
114 } 101 }
115 102
116 // Copy the results back to the NEON corner vector 103 // Copy the results back to the NEON corner vector
117 ret.corner = vld1q_u8(corner_result); 104 ret.corner = vld1q_u8(corner_result);
118 105
119 // Mask to clear the last 64 bits of the corner field 106 // Mask to clear the last 64 bits of the corner field
120 uint8x16_t mask_last_64 = vsetq_lane_u64(0, vreinterpretq_u64_u8(ret.corner), 1); 107 uint8x16_t mask_last_64 = vsetq_lane_u64(0, vreinterpretq_u64_u8(ret.corner), 1);
121 ret.corner = vreinterpretq_u8_u64(mask_last_64); 108 ret.corner = vreinterpretq_u8_u64(mask_last_64);
122 109
123 // Copy the edge vector as it is 110 // Copy the edge vector as it is
124 ret.edge = c.edge; 111 ret.edge = c.edge;
125 112
126 // Mask to clear the last 32 bits of the edge field 113 // Mask to clear the last 32 bits of the edge field
127 uint8x16_t mask_last_32 = vsetq_lane_u32(0, vreinterpretq_u32_u8(ret.edge), 3); 114 uint8x16_t mask_last_32 = vsetq_lane_u32(0, vreinterpretq_u32_u8(ret.edge), 3);
128 ret.edge = vreinterpretq_u8_u32(mask_last_32); 115 ret.edge = vreinterpretq_u8_u32(mask_last_32);
129 116
130 return ret; 117 return ret;
131} 118}
132 119
133_static_inline cube_t compose_edges(cube_t c1, cube_t c2) 120_static_inline cube_t compose_edges(cube_t c1, cube_t c2)
134{ 121{
135 cube_t ret = {0}; 122 cube_t ret = {0};
136 123
137 uint8x16_t edge1 = c1.edge; 124 uint8x16_t edge1 = c1.edge;
138 uint8x16_t edge2 = c2.edge; 125 uint8x16_t edge2 = c2.edge;
139 126
140 // Masks 127 // Masks
141 uint8x16_t p_bits = vdupq_n_u8(_pbits); 128 uint8x16_t p_bits = vdupq_n_u8(_pbits);
142 uint8x16_t eo_bit = vdupq_n_u8(_eobit); 129 uint8x16_t eo_bit = vdupq_n_u8(_eobit);
143 130
144 // Find the index and permutation 131 // Find the index and permutation
145 uint8x16_t p = vandq_u8(edge2, p_bits); 132 uint8x16_t p = vandq_u8(edge2, p_bits);
146 uint8x16_t piece1 = vqtbl1q_u8(edge1, p); 133 uint8x16_t piece1 = vqtbl1q_u8(edge1, p);
147 134
148 // Calculate the orientation through XOR 135 // Calculate the orientation through XOR
149 uint8x16_t orien = vandq_u8(veorq_u8(edge2, piece1), eo_bit); 136 uint8x16_t orien = vandq_u8(veorq_u8(edge2, piece1), eo_bit);
150 137
151 // Combine the results 138 // Combine the results
152 uint8x16_t result = vorrq_u8(vandq_u8(piece1, p_bits), orien); 139 uint8x16_t result = vorrq_u8(vandq_u8(piece1, p_bits), orien);
153 140
154 // Mask to clear the last 32 bits of the result 141 // Mask to clear the last 32 bits of the result
155 uint8x16_t mask_last_32 = vsetq_lane_u32(0, vreinterpretq_u32_u8(result), 3); 142 uint8x16_t mask_last_32 = vsetq_lane_u32(0, vreinterpretq_u32_u8(result), 3);
156 result = vreinterpretq_u8_u32(mask_last_32); 143 result = vreinterpretq_u8_u32(mask_last_32);
157 144
158 ret.edge = result; 145 ret.edge = result;
159 return ret; 146 return ret;
160} 147}
161 148
162_static_inline cube_t compose_corners(cube_t c1, cube_t c2) 149_static_inline cube_t compose_corners(cube_t c1, cube_t c2)
163{ 150{
164 cube_t ret = {0}; 151 cube_t ret = {0};
165 uint8x16_t corner1 = c1.corner; 152 uint8x16_t corner1 = c1.corner;
166 uint8x16_t corner2 = c2.corner; 153 uint8x16_t corner2 = c2.corner;
167 154
168 // Masks 155 // Masks
169 uint8x16_t p_bits = vdupq_n_u8(_pbits); 156 uint8x16_t p_bits = vdupq_n_u8(_pbits);
170 uint8x16_t cobits = vdupq_n_u8(_cobits); 157 uint8x16_t cobits = vdupq_n_u8(_cobits);
171 uint8x16_t cobits2 = vdupq_n_u8(_cobits2); 158 uint8x16_t cobits2 = vdupq_n_u8(_cobits2);
172 uint8x16_t twist_cw = vdupq_n_u8(_ctwist_cw); 159 uint8x16_t twist_cw = vdupq_n_u8(_ctwist_cw);
173 160
174 // Find the index and permutation 161 // Find the index and permutation
175 uint8x16_t p = vandq_u8(corner2, p_bits); 162 uint8x16_t p = vandq_u8(corner2, p_bits);
176 uint8x16_t piece1 = vqtbl1q_u8(corner1, p); 163 uint8x16_t piece1 = vqtbl1q_u8(corner1, p);
177 164
178 // Calculate the orientation 165 // Calculate the orientation
179 uint8x16_t aux = vaddq_u8(vandq_u8(corner2, cobits), vandq_u8(piece1, cobits)); 166 uint8x16_t aux = vaddq_u8(vandq_u8(corner2, cobits), vandq_u8(piece1, cobits));
180 uint8x16_t auy = vshrq_n_u8(vaddq_u8(aux, twist_cw), 2); 167 uint8x16_t auy = vshrq_n_u8(vaddq_u8(aux, twist_cw), 2);
181 uint8x16_t orien = vandq_u8(vaddq_u8(aux, auy), cobits2); 168 uint8x16_t orien = vandq_u8(vaddq_u8(aux, auy), cobits2);
182 169
183 // Combine the results 170 // Combine the results
184 uint8x16_t result = vorrq_u8(vandq_u8(piece1, p_bits), orien); 171 uint8x16_t result = vorrq_u8(vandq_u8(piece1, p_bits), orien);
185 172
186 // Mask to clear the last 64 bits of the result 173 // Mask to clear the last 64 bits of the result
187 uint8x16_t mask_last_64 = vsetq_lane_u64(0, vreinterpretq_u64_u8(result), 1); 174 uint8x16_t mask_last_64 = vsetq_lane_u64(0, vreinterpretq_u64_u8(result), 1);
188 result = vreinterpretq_u8_u64(mask_last_64); 175 result = vreinterpretq_u8_u64(mask_last_64);
189 176
190 ret.corner = result; 177 ret.corner = result;
191 return ret; 178 return ret;
192} 179}
193_static_inline uint8x16_t compose_edges_slim(uint8x16_t edge1, uint8x16_t edge2) 180_static_inline uint8x16_t compose_edges_slim(uint8x16_t edge1, uint8x16_t edge2)
194{ 181{
195 // Masks 182 // Masks
196 uint8x16_t p_bits = vdupq_n_u8(_pbits); 183 uint8x16_t p_bits = vdupq_n_u8(_pbits);
197 uint8x16_t eo_bit = vdupq_n_u8(_eobit); 184 uint8x16_t eo_bit = vdupq_n_u8(_eobit);
198 185
199 // Find the index and permutation 186 // Find the index and permutation
200 uint8x16_t p = vandq_u8(edge2, p_bits); 187 uint8x16_t p = vandq_u8(edge2, p_bits);
201 uint8x16_t piece1 = vqtbl1q_u8(edge1, p); 188 uint8x16_t piece1 = vqtbl1q_u8(edge1, p);
202 189
203 // Calculate the orientation through XOR 190 // Calculate the orientation through XOR
204 uint8x16_t orien = vandq_u8(veorq_u8(edge2, piece1), eo_bit); 191 uint8x16_t orien = vandq_u8(veorq_u8(edge2, piece1), eo_bit);
205 192
206 // Combine the results 193 // Combine the results
207 uint8x16_t ret = vorrq_u8(vandq_u8(piece1, p_bits), orien); 194 uint8x16_t ret = vorrq_u8(vandq_u8(piece1, p_bits), orien);
208 195
209 // Mask to clear the last 32 bits of the result 196 // Mask to clear the last 32 bits of the result
210 uint8x16_t mask_last_32 = vsetq_lane_u32(0, vreinterpretq_u32_u8(ret), 3); 197 uint8x16_t mask_last_32 = vsetq_lane_u32(0, vreinterpretq_u32_u8(ret), 3);
211 ret = vreinterpretq_u8_u32(mask_last_32); 198 ret = vreinterpretq_u8_u32(mask_last_32);
212 199
213 return ret; 200 return ret;
214} 201}
215_static_inline uint8x16_t compose_corners_slim(uint8x16_t corner1, uint8x16_t corner2) 202_static_inline uint8x16_t compose_corners_slim(uint8x16_t corner1, uint8x16_t corner2)
216{ 203{
217 // Masks 204 // Masks
218 uint8x16_t p_bits = vdupq_n_u8(_pbits); 205 uint8x16_t p_bits = vdupq_n_u8(_pbits);
219 uint8x16_t cobits = vdupq_n_u8(_cobits); 206 uint8x16_t cobits = vdupq_n_u8(_cobits);
220 uint8x16_t cobits2 = vdupq_n_u8(_cobits2); 207 uint8x16_t cobits2 = vdupq_n_u8(_cobits2);
221 uint8x16_t twist_cw = vdupq_n_u8(_ctwist_cw); 208 uint8x16_t twist_cw = vdupq_n_u8(_ctwist_cw);
222 209
223 // Find the index and permutation 210 // Find the index and permutation
224 uint8x16_t p = vandq_u8(corner2, p_bits); 211 uint8x16_t p = vandq_u8(corner2, p_bits);
225 uint8x16_t piece1 = vqtbl1q_u8(corner1, p); 212 uint8x16_t piece1 = vqtbl1q_u8(corner1, p);
226 213
227 // Calculate the orientation 214 // Calculate the orientation
228 uint8x16_t aux = vaddq_u8(vandq_u8(corner2, cobits), vandq_u8(piece1, cobits)); 215 uint8x16_t aux = vaddq_u8(vandq_u8(corner2, cobits), vandq_u8(piece1, cobits));
229 uint8x16_t auy = vshrq_n_u8(vaddq_u8(aux, twist_cw), 2); 216 uint8x16_t auy = vshrq_n_u8(vaddq_u8(aux, twist_cw), 2);
230 uint8x16_t orien = vandq_u8(vaddq_u8(aux, auy), cobits2); 217 uint8x16_t orien = vandq_u8(vaddq_u8(aux, auy), cobits2);
231 218
232 // Combine the results 219 // Combine the results
233 uint8x16_t ret = vorrq_u8(vandq_u8(piece1, p_bits), orien); 220 uint8x16_t ret = vorrq_u8(vandq_u8(piece1, p_bits), orien);
234 221
235 // Mask to clear the last 64 bits of the result 222 // Mask to clear the last 64 bits of the result
236 uint8x16_t mask_last_64 = vsetq_lane_u64(0, vreinterpretq_u64_u8(ret), 1); 223 uint8x16_t mask_last_64 = vsetq_lane_u64(0, vreinterpretq_u64_u8(ret), 1);
237 ret = vreinterpretq_u8_u64(mask_last_64); 224 ret = vreinterpretq_u8_u64(mask_last_64);
238 225
239 return ret; 226 return ret;
240} 227}
241_static_inline cube_t compose(cube_t c1, cube_t c2) 228_static_inline cube_t compose(cube_t c1, cube_t c2)
242{ 229{
243 cube_t ret = {0}; 230 cube_t ret = {0};
244 231
245 ret.edge = compose_edges_slim(c1.edge, c2.edge); 232 ret.edge = compose_edges_slim(c1.edge, c2.edge);
246 ret.corner = compose_corners_slim(c1.corner, c2.corner); 233 ret.corner = compose_corners_slim(c1.corner, c2.corner);
247 234
248 return ret; 235 return ret;
249} 236}
250 237
251_static_inline cube_t inverse(cube_t cube) 238_static_inline cube_t inverse(cube_t cube)
252{ 239{
253 uint8_t i, piece, orien; 240 uint8_t i, piece, orien;
254 cube_t ret; 241 cube_t ret;
255 242
256 // Temp arrays to store the NEON vectors 243 // Temp arrays to store the NEON vectors
257 uint8_t edges[16]; 244 uint8_t edges[16];
258 uint8_t corners[16]; 245 uint8_t corners[16];
259 246
260 // Copy the NEON vectors to the arrays 247 // Copy the NEON vectors to the arrays
261 vst1q_u8(edges, cube.edge); 248 vst1q_u8(edges, cube.edge);
262 vst1q_u8(corners, cube.corner); 249 vst1q_u8(corners, cube.corner);
263 250
264 uint8_t edge_result[16] = {0}; 251 uint8_t edge_result[16] = {0};
265 uint8_t corner_result[16] = {0}; 252 uint8_t corner_result[16] = {0};
266 253
267 // Process the edges 254 // Process the edges
268 for (i = 0; i < 12; i++) 255 for (i = 0; i < 12; i++)
269 { 256 {
270 piece = edges[i]; 257 piece = edges[i];
271 orien = piece & _eobit; 258 orien = piece & _eobit;
272 edge_result[piece & _pbits] = i | orien; 259 edge_result[piece & _pbits] = i | orien;
273 } 260 }
274 261
275 // Process the corners 262 // Process the corners
276 for (i = 0; i < 8; i++) 263 for (i = 0; i < 8; i++)
277 { 264 {
278 piece = corners[i]; 265 piece = corners[i];
279 orien = ((piece << 1) | (piece >> 1)) & _cobits2; 266 orien = ((piece << 1) | (piece >> 1)) & _cobits2;
280 corner_result[piece & _pbits] = i | orien; 267 corner_result[piece & _pbits] = i | orien;
281 } 268 }
282 269
283 // Copy the results back to the NEON vectors 270 // Copy the results back to the NEON vectors
284 ret.edge = vld1q_u8(edge_result); 271 ret.edge = vld1q_u8(edge_result);
285 ret.corner = vld1q_u8(corner_result); 272 ret.corner = vld1q_u8(corner_result);
286 273
287 return ret; 274 return ret;
288} 275}
289 276
290_static_inline int64_t coord_co(cube_t c) 277_static_inline int64_t coord_co(cube_t c)
291{ 278{
292 // Temp array to store the NEON vector 279 // Temp array to store the NEON vector
293 uint8_t mem[16]; 280 uint8_t mem[16];
294 vst1q_u8(mem, c.corner); 281 vst1q_u8(mem, c.corner);
295 282
296 int i, p; 283 int i, p;
297 int64_t ret; 284 int64_t ret;
298 285
299 for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 3) 286 for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 3)
300 ret += p * (mem[i] >> _coshift); 287 ret += p * (mem[i] >> _coshift);
301 288
302 return ret; 289 return ret;
303} 290}
304 291
305_static_inline int64_t 292_static_inline int64_t
306coord_csep(cube_t c) 293coord_csep(cube_t c)
307{ 294{
308 // Temp array to store the NEON vector 295 // Temp array to store the NEON vector
309 uint8_t mem[16]; 296 uint8_t mem[16];
310 vst1q_u8(mem, c.corner); 297 vst1q_u8(mem, c.corner);
311 298
312 int64_t ret = 0; 299 int64_t ret = 0;
313 int i, p; 300 int i, p;
314 for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 2) 301 for (ret = 0, i = 0, p = 1; i < 7; i++, p *= 2)
315 ret += p * ((mem[i] & _csepbit) >> 2); 302 ret += p * ((mem[i] & _csepbit) >> 2);
316 303
317 return ret; 304 return ret;
318 return 0; 305 return 0;
319} 306}
320 307
321_static_inline int64_t 308_static_inline int64_t
322coord_cocsep(cube_t c) 309coord_cocsep(cube_t c)
323{ 310{
324 return (coord_co(c) << 7) + coord_csep(c); 311 return (coord_co(c) << 7) + coord_csep(c);
325} 312}
326 313
327_static_inline int64_t coord_eo(cube_t c) 314_static_inline int64_t coord_eo(cube_t c)
328{ 315{
329 int64_t ret = 0; 316 int64_t ret = 0;
330 int64_t p = 1; 317 int64_t p = 1;
331 318
332 // Temp array to store the NEON vector 319 // Temp array to store the NEON vector
333 uint8_t mem[16]; 320 uint8_t mem[16];
334 vst1q_u8(mem, c.edge); 321 vst1q_u8(mem, c.edge);
335 322
336 for (int i = 1; i < 12; i++, p *= 2) 323 for (int i = 1; i < 12; i++, p *= 2)
337 { 324 {
338 ret += p * (mem[i] >> _eoshift); 325 ret += p * (mem[i] >> _eoshift);
339 } 326 }
340 327
341 return ret; 328 return ret;
342} 329}
343 330
344_static_inline int64_t coord_esep(cube_t c) 331_static_inline int64_t coord_esep(cube_t c)
345{ 332{
346 int64_t i, j, jj, k, l, ret1, ret2, bit1, bit2, is1; 333 int64_t i, j, jj, k, l, ret1, ret2, bit1, bit2, is1;
347 334
348 // Temp array to store the NEON vector 335 // Temp array to store the NEON vector
349 uint8_t mem[16]; 336 uint8_t mem[16];
350 vst1q_u8(mem, c.edge); 337 vst1q_u8(mem, c.edge);
351 338
352 for (i = 0, j = 0, k = 4, l = 4, ret1 = 0, ret2 = 0; i < 12; i++) 339 for (i = 0, j = 0, k = 4, l = 4, ret1 = 0, ret2 = 0; i < 12; i++)
353 { 340 {
354 bit1 = (mem[i] & _esepbit1) >> 2; 341 bit1 = (mem[i] & _esepbit1) >> 2;
355 bit2 = (mem[i] & _esepbit2) >> 3; 342 bit2 = (mem[i] & _esepbit2) >> 3;
356 is1 = (1 - bit2) * bit1; 343 is1 = (1 - bit2) * bit1;
357 344
358 ret1 += bit2 * binomial[11 - i][k]; 345 ret1 += bit2 * binomial[11 - i][k];
359 k -= bit2; 346 k -= bit2;
360 347
361 jj = j < 8; 348 jj = j < 8;
362 ret2 += jj * is1 * binomial[7 - (j * jj)][l]; 349 ret2 += jj * is1 * binomial[7 - (j * jj)][l];
363 l -= is1; 350 l -= is1;
364 j += (1 - bit2); 351 j += (1 - bit2);
365 } 352 }
366 353
367 return ret1 * 70 + ret2; 354 return ret1 * 70 + ret2;
368} 355}
369 356
370_static_inline void 357_static_inline void
371copy_corners(cube_t *dst, cube_t src) 358copy_corners(cube_t *dst, cube_t src)
372{ 359{
373 dst->corner = src.corner; 360 dst->corner = src.corner;
374} 361}
375 362
376_static_inline void 363_static_inline void
377copy_edges(cube_t *dst, cube_t src) 364copy_edges(cube_t *dst, cube_t src)
378{ 365{
379 dst->edge = src.edge; 366 dst->edge = src.edge;
380} 367}
381 368
382_static_inline void 369_static_inline void
383set_eo(cube_t *cube, int64_t eo) 370set_eo(cube_t *cube, int64_t eo)
384{ 371{
385 // Temp array to store the NEON vector 372 // Temp array to store the NEON vector
386 uint8_t mem[16]; 373 uint8_t mem[16];
387 vst1q_u8(mem, cube->edge); 374 vst1q_u8(mem, cube->edge);
388 uint8_t i, sum, flip; 375 uint8_t i, sum, flip;
389 376
390 for (sum = 0, i = 1; i < 12; i++, eo >>= 1) 377 for (sum = 0, i = 1; i < 12; i++, eo >>= 1)
391 { 378 {
392 flip = eo % 2; 379 flip = eo % 2;
393 sum += flip; 380 sum += flip;
394 mem[i] = (mem[i] & ~_eobit) | (_eobit * flip); 381 mem[i] = (mem[i] & ~_eobit) | (_eobit * flip);
395 } 382 }
396 mem[0] = (mem[0] & ~_eobit) | (_eobit * (sum % 2)); 383 mem[0] = (mem[0] & ~_eobit) | (_eobit * (sum % 2));
397 384
398 // Copy the results back to the NEON vector 385 // Copy the results back to the NEON vector
399 cube->edge = vld1q_u8(mem); 386 cube->edge = vld1q_u8(mem);
400 return; 387 return;
401} 388}
402 389
403_static_inline cube_t 390_static_inline cube_t
404invcoord_esep(int64_t esep) 391invcoord_esep(int64_t esep)
405{ 392{
406 cube_t ret; 393 cube_t ret;
407 int64_t bit1, bit2, i, j, jj, k, l, s, v, w, is1, set1, set2; 394 int64_t bit1, bit2, i, j, jj, k, l, s, v, w, is1, set1, set2;
408 uint8_t slice[3] = {0}; 395 uint8_t slice[3] = {0};
409 396
410 ret = solved; 397 ret = solved;
411 uint8_t mem[16]; 398 uint8_t mem[16];
412 set1 = esep % 70; 399 set1 = esep % 70;
413 set2 = esep / 70; 400 set2 = esep / 70;
414 401
415 for (i = 0, j = 0, k = 4, l = 4; i < 12; i++) 402 for (i = 0, j = 0, k = 4, l = 4; i < 12; i++)
416 { 403 {
417 v = binomial[11 - i][k]; 404 v = binomial[11 - i][k];
418 jj = j < 8; 405 jj = j < 8;
419 w = jj * binomial[7 - (j * jj)][l]; 406 w = jj * binomial[7 - (j * jj)][l];
420 bit2 = set2 >= v; 407 bit2 = set2 >= v;
421 bit1 = set1 >= w; 408 bit1 = set1 >= w;
422 is1 = (1 - bit2) * bit1; 409 is1 = (1 - bit2) * bit1;
423 410
424 set2 -= bit2 * v; 411 set2 -= bit2 * v;
425 k -= bit2; 412 k -= bit2;
426 set1 -= is1 * w; 413 set1 -= is1 * w;
427 l -= is1; 414 l -= is1;
428 j += (1 - bit2); 415 j += (1 - bit2);
429 s = 2 * bit2 + (1 - bit2) * bit1; 416 s = 2 * bit2 + (1 - bit2) * bit1;
430 417
431 mem[i] = (slice[s]++) | (uint8_t)(s << 2); 418 mem[i] = (slice[s]++) | (uint8_t)(s << 2);
432 } 419 }
433 420
434 ret.edge = vld1q_u8(mem); 421 ret.edge = vld1q_u8(mem);
435 return ret; 422 return ret;
436} 423}

Generated with cgit - Back to sebastiano.tronto.net