aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cube.c2
-rw-r--r--src/cube_avx2.h53
-rw-r--r--src/cube_generic.h488
-rw-r--r--src/cube_portable.h22
-rw-r--r--src/io_cube.h359
-rw-r--r--src/io_move_trans.h87
6 files changed, 537 insertions, 474 deletions
diff --git a/src/cube.c b/src/cube.c
index 0083acc..fce0683 100644
--- a/src/cube.c
+++ b/src/cube.c
@@ -31,8 +31,10 @@
31#include "cube_portable.h" 31#include "cube_portable.h"
32#endif 32#endif
33 33
34#include "io_move_trans.h"
34#include "constant_cubes.h" 35#include "constant_cubes.h"
35#include "cube_generic.h" 36#include "cube_generic.h"
37#include "io_cube.h"
36 38
37/* TODO: work in progress */ 39/* TODO: work in progress */
38#if 0 40#if 0
diff --git a/src/cube_avx2.h b/src/cube_avx2.h
index 42ca9b5..b189023 100644
--- a/src/cube_avx2.h
+++ b/src/cube_avx2.h
@@ -25,6 +25,7 @@ _static_inline cube_t compose_epcpeo(cube_t, cube_t);
25_static_inline cube_t compose_edges(cube_t, cube_t); 25_static_inline cube_t compose_edges(cube_t, cube_t);
26_static_inline cube_t compose_corners(cube_t, cube_t); 26_static_inline cube_t compose_corners(cube_t, cube_t);
27_static_inline cube_t compose(cube_t, cube_t); 27_static_inline cube_t compose(cube_t, cube_t);
28_static_inline cube_t inverse(cube_t);
28 29
29_static_inline int64_t coord_co(cube_t); 30_static_inline int64_t coord_co(cube_t);
30_static_inline int64_t coord_csep(cube_t); 31_static_inline int64_t coord_csep(cube_t);
@@ -135,6 +136,58 @@ compose(cube_t c1, cube_t c2)
135 return s; 136 return s;
136} 137}
137 138
139_static_inline cube_t
140cleanaftershuffle(cube_t c)
141{
142 __m256i b;
143
144 b = _mm256_set_epi8(
145 ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
146 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0
147 );
148
149 return _mm256_andnot_si256(b, c);
150}
151
152_static_inline cube_t
153inverse(cube_t c)
154{
155 /* Method taken from Andrew Skalski's vcube[1]. The addition sequence
156 * was generated using [2].
157 * [1] https://github.com/Voltara/vcube
158 * [2] http://wwwhomes.uni-bielefeld.de/achim/addition_chain.html
159 */
160 cube_t v3, vi, vo, vp, ret;
161
162 v3 = _mm256_shuffle_epi8(c, c);
163 v3 = _mm256_shuffle_epi8(v3, c);
164 vi = _mm256_shuffle_epi8(v3, v3);
165 vi = _mm256_shuffle_epi8(vi, vi);
166 vi = _mm256_shuffle_epi8(vi, vi);
167 vi = _mm256_shuffle_epi8(vi, v3);
168 vi = _mm256_shuffle_epi8(vi, vi);
169 vi = _mm256_shuffle_epi8(vi, vi);
170 vi = _mm256_shuffle_epi8(vi, vi);
171 vi = _mm256_shuffle_epi8(vi, vi);
172 vi = _mm256_shuffle_epi8(vi, c);
173 vi = _mm256_shuffle_epi8(vi, vi);
174 vi = _mm256_shuffle_epi8(vi, vi);
175 vi = _mm256_shuffle_epi8(vi, vi);
176 vi = _mm256_shuffle_epi8(vi, vi);
177 vi = _mm256_shuffle_epi8(vi, vi);
178 vi = _mm256_shuffle_epi8(vi, v3);
179 vi = _mm256_shuffle_epi8(vi, vi);
180 vi = _mm256_shuffle_epi8(vi, c);
181
182 vo = _mm256_and_si256(c, _mm256_or_si256(_eo_avx2, _co2_avx2));
183 vo = _mm256_shuffle_epi8(vo, vi);
184 vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi);
185 ret = _mm256_or_si256(vp, vo);
186 ret = cleanaftershuffle(ret);
187
188 return invertco(ret);
189}
190
138_static_inline int64_t 191_static_inline int64_t
139coord_co(cube_t c) 192coord_co(cube_t c)
140{ 193{
diff --git a/src/cube_generic.h b/src/cube_generic.h
index a90aa17..844b328 100644
--- a/src/cube_generic.h
+++ b/src/cube_generic.h
@@ -1,62 +1,27 @@
1#define _move(M, c) compose(c, _move_cube_ ## M) 1#define _move(M, c) compose(c, _move_cube_ ## M)
2#define _premove(M, c) compose(_move_cube_ ## M, c) 2#define _premove(M, c) compose(_move_cube_ ## M, c)
3 3
4_static cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]); 4_static cube_t solvedcube();
5_static bool isconsistent(cube_t);
6_static bool issolvable(cube_t);
7_static bool issolved(cube_t);
8_static bool iserror(cube_t);
9_static cube_t applymoves(cube_t, const char *);
10_static cube_t applytrans(cube_t, const char *);
11
5_static int permsign(uint8_t *, int); 12_static int permsign(uint8_t *, int);
6_static uint8_t readco(const char *);
7_static uint8_t readcp(const char *);
8_static uint8_t readeo(const char *);
9_static uint8_t readep(const char *);
10_static cube_t readcube_B32(const char *);
11_static cube_t readcube_H48(const char *);
12_static uint8_t readpiece_LST(const char **);
13_static cube_t readcube_LST(const char *);
14_static int writepiece_LST(uint8_t, char *);
15_static void writecube_B32(cube_t, char *);
16_static void writecube_H48(cube_t, char *);
17_static void writecube_LST(cube_t, char *);
18_static uint8_t b32toedge(char);
19_static uint8_t b32tocorner(char);
20_static char edgetob32(uint8_t);
21_static char cornertob32(uint8_t);
22_static uint8_t readmove(char);
23_static uint8_t readmodifier(char);
24_static uint8_t readtrans(const char *);
25_static int writemoves(uint8_t *, int, char *);
26_static void writetrans(uint8_t, char *);
27_static cube_t move(cube_t, uint8_t); 13_static cube_t move(cube_t, uint8_t);
28_static cube_t transform_edges(cube_t, uint8_t); 14_static cube_t transform_edges(cube_t, uint8_t);
29_static cube_t transform_corners(cube_t, uint8_t); 15_static cube_t transform_corners(cube_t, uint8_t);
30_static cube_t transform(cube_t, uint8_t); 16_static cube_t transform(cube_t, uint8_t);
31 17
32_static struct { 18_static cube_t
33 const char *name; 19solvedcube()
34 cube_t (*read)(const char *);
35 void (*write)(cube_t, char *);
36} ioformat[] =
37{
38 { .name = "B32", .read = readcube_B32, .write = writecube_B32 },
39 { .name = "LST", .read = readcube_LST, .write = writecube_LST },
40 { .name = "H48", .read = readcube_H48, .write = writecube_H48 },
41 { .name = "NONE", .read = NULL, .write = NULL },
42};
43
44_static_inline cube_t
45cubefromarray(uint8_t c[static 8], uint8_t e[static 12])
46{
47 return static_cube(
48 c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
49 e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7],
50 e[8], e[9], e[10], e[11]);
51}
52
53cube_t
54solvedcube(void)
55{ 20{
56 return solved; 21 return solved;
57} 22}
58 23
59bool 24_static bool
60isconsistent(cube_t cube) 25isconsistent(cube_t cube)
61{ 26{
62 uint8_t i, p, e, piece, corner[8], edge[12]; 27 uint8_t i, p, e, piece, corner[8], edge[12];
@@ -112,7 +77,7 @@ inconsistent_co:
112 return false; 77 return false;
113} 78}
114 79
115bool 80_static bool
116issolvable(cube_t cube) 81issolvable(cube_t cube)
117{ 82{
118 uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8]; 83 uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8];
@@ -170,32 +135,7 @@ iserror(cube_t cube)
170 return equal(cube, zero); 135 return equal(cube, zero);
171} 136}
172 137
173cube_t 138_static cube_t
174inverse(cube_t cube)
175{
176 uint8_t i, piece, orien, e[12], c[8], edge[12], corner[8];
177
178 DBG_ASSERT(isconsistent(cube), zero,
179 "inverse error: inconsistent cube\n");
180
181 pieces(&cube, corner, edge);
182
183 for (i = 0; i < 12; i++) {
184 piece = edge[i];
185 orien = piece & _eobit;
186 e[piece & _pbits] = i | orien;
187 }
188
189 for (i = 0; i < 8; i++) {
190 piece = corner[i];
191 orien = ((piece << 1) | (piece >> 1)) & _cobits2;
192 c[piece & _pbits] = i | orien;
193 }
194
195 return cubefromarray(c, e);
196}
197
198cube_t
199applymoves(cube_t cube, const char *buf) 139applymoves(cube_t cube, const char *buf)
200{ 140{
201 uint8_t r, m; 141 uint8_t r, m;
@@ -224,7 +164,7 @@ applymoves_error:
224 return zero; 164 return zero;
225} 165}
226 166
227cube_t 167_static cube_t
228applytrans(cube_t cube, const char *buf) 168applytrans(cube_t cube, const char *buf)
229{ 169{
230 uint8_t t; 170 uint8_t t;
@@ -237,49 +177,6 @@ applytrans(cube_t cube, const char *buf)
237 return transform(cube, t); 177 return transform(cube, t);
238} 178}
239 179
240cube_t
241readcube(const char *format, const char *buf)
242{
243 int i;
244
245 for (i = 0; ioformat[i].read != NULL; i++)
246 if (!strcmp(format, ioformat[i].name))
247 return ioformat[i].read(buf);
248
249 DBG_LOG("Cannot read cube in the given format\n");
250 return zero;
251}
252
253void
254writecube(const char *format, cube_t cube, char *buf)
255{
256 char *errormsg;
257 size_t len;
258
259 if (!isconsistent(cube)) {
260 errormsg = "ERROR: cannot write inconsistent cube";
261 goto writecube_error;
262 }
263
264 int i;
265
266 for (i = 0; ioformat[i].write != NULL; i++) {
267 if (!strcmp(format, ioformat[i].name)) {
268 ioformat[i].write(cube, buf);
269 return;
270 }
271 }
272
273 errormsg = "ERROR: cannot write cube in the given format";
274
275writecube_error:
276 DBG_LOG("writecube error, see stdout for details\n");
277 len = strlen(errormsg);
278 memcpy(buf, errormsg, len);
279 buf[len] = '\n';
280 buf[len+1] = '\0';
281}
282
283_static int 180_static int
284permsign(uint8_t *a, int n) 181permsign(uint8_t *a, int n)
285{ 182{
@@ -293,363 +190,6 @@ permsign(uint8_t *a, int n)
293 return ret % 2; 190 return ret % 2;
294} 191}
295 192
296_static uint8_t
297readco(const char *str)
298{
299 if (*str == '0')
300 return 0;
301 if (*str == '1')
302 return _ctwist_cw;
303 if (*str == '2')
304 return _ctwist_ccw;
305
306 DBG_LOG("Error reading CO\n");
307 return _error;
308}
309
310_static uint8_t
311readcp(const char *str)
312{
313 uint8_t c;
314
315 for (c = 0; c < 8; c++)
316 if (!strncmp(str, cornerstr[c], 3) ||
317 !strncmp(str, cornerstralt[c], 3))
318 return c;
319
320 DBG_LOG("Error reading CP\n");
321 return _error;
322}
323
324_static uint8_t
325readeo(const char *str)
326{
327 if (*str == '0')
328 return 0;
329 if (*str == '1')
330 return _eflip;
331
332 DBG_LOG("Error reading EO\n");
333 return _error;
334}
335
336_static uint8_t
337readep(const char *str)
338{
339 uint8_t e;
340
341 for (e = 0; e < 12; e++)
342 if (!strncmp(str, edgestr[e], 2))
343 return e;
344
345 DBG_LOG("Error reading EP\n");
346 return _error;
347}
348
349_static cube_t
350readcube_B32(const char *buf)
351{
352 int i;
353 uint8_t c[8], e[12];
354
355 for (i = 0; i < 8; i++) {
356 c[i] = b32tocorner(buf[i]);
357 DBG_ASSERT(c[i] < 255, zero,
358 "Error reading B32 corner %d (char %d)\n", i, i);
359 }
360
361 for (i = 0; i < 12; i++) {
362 e[i] = b32toedge(buf[i+9]);
363 DBG_ASSERT(e[i] < 255, zero,
364 "Error reading B32 edge %d (char %d)\n", i, i+9);
365 }
366
367 return cubefromarray(c, e);
368}
369
370_static cube_t
371readcube_H48(const char *buf)
372{
373 int i;
374 uint8_t piece, orient, c[8], e[12];
375 const char *b;
376
377 b = buf;
378
379 for (i = 0; i < 12; i++) {
380 while (*b == ' ' || *b == '\t' || *b == '\n')
381 b++;
382 if ((piece = readep(b)) == _error)
383 return zero;
384 b += 2;
385 if ((orient = readeo(b)) == _error)
386 return zero;
387 b++;
388 e[i] = piece | orient;
389 }
390 for (i = 0; i < 8; i++) {
391 while (*b == ' ' || *b == '\t' || *b == '\n')
392 b++;
393 if ((piece = readcp(b)) == _error)
394 return zero;
395 b += 3;
396 if ((orient = readco(b)) == _error)
397 return zero;
398 b++;
399 c[i] = piece | orient;
400 }
401
402 return cubefromarray(c, e);
403}
404
405_static uint8_t
406readpiece_LST(const char **b)
407{
408 uint8_t ret;
409 bool read;
410
411 while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n')
412 (*b)++;
413
414 for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) {
415 read = true;
416 ret = ret * 10 + (**b) - '0';
417 }
418
419 return read ? ret : _error;
420}
421
422_static cube_t
423readcube_LST(const char *buf)
424{
425 int i;
426 uint8_t c[8], e[12];
427
428 for (i = 0; i < 8; i++)
429 c[i] = readpiece_LST(&buf);
430
431 for (i = 0; i < 12; i++)
432 e[i] = readpiece_LST(&buf);
433
434 return cubefromarray(c, e);
435}
436
437_static int
438writepiece_LST(uint8_t piece, char *buf)
439{
440 char digits[3];
441 int i, len;
442
443 len = 0;
444 while (piece != 0) {
445 digits[len++] = (piece % 10) + '0';
446 piece /= 10;
447 }
448
449 if (len == 0)
450 digits[len++] = '0';
451
452 for (i = 0; i < len; i++)
453 buf[i] = digits[len-i-1];
454
455 buf[len] = ',';
456 buf[len+1] = ' ';
457
458 return len+2;
459}
460
461_static void
462writecube_B32(cube_t cube, char *buf)
463{
464 int i;
465 uint8_t corner[8], edge[12];
466
467 pieces(&cube, corner, edge);
468
469 for (i = 0; i < 8; i++)
470 buf[i] = cornertob32(corner[i]);
471
472 buf[8] = '=';
473
474 for (i = 0; i < 12; i++)
475 buf[i+9] = edgetob32(edge[i]);
476
477 buf[21] = '\0';
478}
479
480_static void
481writecube_H48(cube_t cube, char *buf)
482{
483 uint8_t piece, perm, orient, corner[8], edge[12];
484 int i;
485
486 pieces(&cube, corner, edge);
487
488 for (i = 0; i < 12; i++) {
489 piece = edge[i];
490 perm = piece & _pbits;
491 orient = (piece & _eobit) >> _eoshift;
492 buf[4*i ] = edgestr[perm][0];
493 buf[4*i + 1] = edgestr[perm][1];
494 buf[4*i + 2] = orient + '0';
495 buf[4*i + 3] = ' ';
496 }
497 for (i = 0; i < 8; i++) {
498 piece = corner[i];
499 perm = piece & _pbits;
500 orient = (piece & _cobits) >> _coshift;
501 buf[48 + 5*i ] = cornerstr[perm][0];
502 buf[48 + 5*i + 1] = cornerstr[perm][1];
503 buf[48 + 5*i + 2] = cornerstr[perm][2];
504 buf[48 + 5*i + 3] = orient + '0';
505 buf[48 + 5*i + 4] = ' ';
506 }
507
508 buf[48+39] = '\0';
509}
510
511_static void
512writecube_LST(cube_t cube, char *buf)
513{
514 int i;
515 size_t ptr;
516 uint8_t piece, corner[8], edge[12];
517
518 ptr = 0;
519 pieces(&cube, corner, edge);
520
521 for (i = 0; i < 8; i++) {
522 piece = corner[i];
523 ptr += writepiece_LST(piece, buf + ptr);
524 }
525
526 for (i = 0; i < 12; i++) {
527 piece = edge[i];
528 ptr += writepiece_LST(piece, buf + ptr);
529 }
530
531 *(buf+ptr-2) = 0;
532}
533
534_static uint8_t
535b32toedge(char c)
536{
537 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'))
538 return 255;
539
540 return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a');
541}
542
543_static uint8_t
544b32tocorner(char c) {
545 uint8_t val;
546
547 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'))
548 return 255;
549
550 val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
551
552 return (val & 7) | ((val & 24) << 2);
553}
554
555_static char
556edgetob32(uint8_t edge)
557{
558 return edge <= 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
559}
560
561_static char
562cornertob32(uint8_t corner)
563{
564 uint8_t val;
565
566 val = (corner & 7) | ((corner & 96) >> 2);
567
568 return val <= 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
569}
570
571_static uint8_t
572readmove(char c)
573{
574 switch (c) {
575 case 'U':
576 return _move_U;
577 case 'D':
578 return _move_D;
579 case 'R':
580 return _move_R;
581 case 'L':
582 return _move_L;
583 case 'F':
584 return _move_F;
585 case 'B':
586 return _move_B;
587 default:
588 return _error;
589 }
590}
591
592_static uint8_t
593readmodifier(char c)
594{
595 switch (c) {
596 case '1': /* Fallthrough */
597 case '2': /* Fallthrough */
598 case '3':
599 return c - '0' - 1;
600 case '\'':
601 return 2;
602 default:
603 return 0;
604 }
605}
606
607_static uint8_t
608readtrans(const char *buf)
609{
610 uint8_t t;
611
612 for (t = 0; t < 48; t++)
613 if (!strncmp(buf, transstr[t], 11))
614 return t;
615
616 DBG_LOG("readtrans error\n");
617 return _error;
618}
619
620_static int
621writemoves(uint8_t *m, int n, char *buf)
622{
623 int i;
624 size_t len;
625 const char *s;
626 char *b;
627
628 for (i = 0, b = buf; i < n; i++, b++) {
629 s = movestr[m[i]];
630 len = strlen(s);
631 memcpy(b, s, len);
632 b += len;
633 *b = ' ';
634 }
635
636 if (b != buf)
637 b--; /* Remove last space */
638 *b = '\0';
639
640 return b - buf;
641}
642
643_static void
644writetrans(uint8_t t, char *buf)
645{
646 if (t >= 48)
647 memcpy(buf, "error trans", 11);
648 else
649 memcpy(buf, transstr[t], 11);
650 buf[11] = '\0';
651}
652
653_static cube_t 193_static cube_t
654move(cube_t c, uint8_t m) 194move(cube_t c, uint8_t m)
655{ 195{
diff --git a/src/cube_portable.h b/src/cube_portable.h
index 71a7e41..77e803b 100644
--- a/src/cube_portable.h
+++ b/src/cube_portable.h
@@ -22,6 +22,7 @@ _static_inline void compose_corners_inplace(cube_t, cube_t, cube_t *);
22_static_inline cube_t compose_edges(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); 23_static_inline cube_t compose_corners(cube_t, cube_t);
24_static_inline cube_t compose(cube_t, cube_t); 24_static_inline cube_t compose(cube_t, cube_t);
25_static_inline cube_t inverse(cube_t);
25 26
26_static_inline int64_t coord_co(cube_t); 27_static_inline int64_t coord_co(cube_t);
27_static_inline int64_t coord_csep(cube_t); 28_static_inline int64_t coord_csep(cube_t);
@@ -133,6 +134,27 @@ compose(cube_t c1, cube_t c2)
133 return ret; 134 return ret;
134} 135}
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
136_static_inline int64_t 158_static_inline int64_t
137coord_co(cube_t c) 159coord_co(cube_t c)
138{ 160{
diff --git a/src/io_cube.h b/src/io_cube.h
new file mode 100644
index 0000000..63c9f53
--- /dev/null
+++ b/src/io_cube.h
@@ -0,0 +1,359 @@
1_static cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]);
2
3_static uint8_t readco(const char *);
4_static uint8_t readcp(const char *);
5_static uint8_t readeo(const char *);
6_static uint8_t readep(const char *);
7_static cube_t readcube_B32(const char *);
8_static cube_t readcube_H48(const char *);
9_static uint8_t readpiece_LST(const char **);
10_static cube_t readcube_LST(const char *);
11
12_static int writepiece_LST(uint8_t, char *);
13_static void writecube_B32(cube_t, char *);
14_static void writecube_H48(cube_t, char *);
15_static void writecube_LST(cube_t, char *);
16
17_static uint8_t b32toedge(char);
18_static uint8_t b32tocorner(char);
19_static char edgetob32(uint8_t);
20_static char cornertob32(uint8_t);
21
22_static struct {
23 const char *name;
24 cube_t (*read)(const char *);
25 void (*write)(cube_t, char *);
26} ioformat[] =
27{
28 { .name = "B32", .read = readcube_B32, .write = writecube_B32 },
29 { .name = "LST", .read = readcube_LST, .write = writecube_LST },
30 { .name = "H48", .read = readcube_H48, .write = writecube_H48 },
31 { .name = "NONE", .read = NULL, .write = NULL },
32};
33
34_static_inline cube_t
35cubefromarray(uint8_t c[static 8], uint8_t e[static 12])
36{
37 return static_cube(
38 c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
39 e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7],
40 e[8], e[9], e[10], e[11]);
41}
42
43cube_t
44readcube(const char *format, const char *buf)
45{
46 int i;
47
48 for (i = 0; ioformat[i].read != NULL; i++)
49 if (!strcmp(format, ioformat[i].name))
50 return ioformat[i].read(buf);
51
52 DBG_LOG("Cannot read cube in the given format\n");
53 return zero;
54}
55
56void
57writecube(const char *format, cube_t cube, char *buf)
58{
59 char *errormsg;
60 size_t len;
61
62 if (!isconsistent(cube)) {
63 errormsg = "ERROR: cannot write inconsistent cube";
64 goto writecube_error;
65 }
66
67 int i;
68
69 for (i = 0; ioformat[i].write != NULL; i++) {
70 if (!strcmp(format, ioformat[i].name)) {
71 ioformat[i].write(cube, buf);
72 return;
73 }
74 }
75
76 errormsg = "ERROR: cannot write cube in the given format";
77
78writecube_error:
79 DBG_LOG("writecube error, see stdout for details\n");
80 len = strlen(errormsg);
81 memcpy(buf, errormsg, len);
82 buf[len] = '\n';
83 buf[len+1] = '\0';
84}
85
86_static uint8_t
87readco(const char *str)
88{
89 if (*str == '0')
90 return 0;
91 if (*str == '1')
92 return _ctwist_cw;
93 if (*str == '2')
94 return _ctwist_ccw;
95
96 DBG_LOG("Error reading CO\n");
97 return _error;
98}
99
100_static uint8_t
101readcp(const char *str)
102{
103 uint8_t c;
104
105 for (c = 0; c < 8; c++)
106 if (!strncmp(str, cornerstr[c], 3) ||
107 !strncmp(str, cornerstralt[c], 3))
108 return c;
109
110 DBG_LOG("Error reading CP\n");
111 return _error;
112}
113
114_static uint8_t
115readeo(const char *str)
116{
117 if (*str == '0')
118 return 0;
119 if (*str == '1')
120 return _eflip;
121
122 DBG_LOG("Error reading EO\n");
123 return _error;
124}
125
126_static uint8_t
127readep(const char *str)
128{
129 uint8_t e;
130
131 for (e = 0; e < 12; e++)
132 if (!strncmp(str, edgestr[e], 2))
133 return e;
134
135 DBG_LOG("Error reading EP\n");
136 return _error;
137}
138
139_static cube_t
140readcube_B32(const char *buf)
141{
142 int i;
143 uint8_t c[8], e[12];
144
145 for (i = 0; i < 8; i++) {
146 c[i] = b32tocorner(buf[i]);
147 DBG_ASSERT(c[i] < 255, zero,
148 "Error reading B32 corner %d (char %d)\n", i, i);
149 }
150
151 for (i = 0; i < 12; i++) {
152 e[i] = b32toedge(buf[i+9]);
153 DBG_ASSERT(e[i] < 255, zero,
154 "Error reading B32 edge %d (char %d)\n", i, i+9);
155 }
156
157 return cubefromarray(c, e);
158}
159
160_static cube_t
161readcube_H48(const char *buf)
162{
163 int i;
164 uint8_t piece, orient, c[8], e[12];
165 const char *b;
166
167 b = buf;
168
169 for (i = 0; i < 12; i++) {
170 while (*b == ' ' || *b == '\t' || *b == '\n')
171 b++;
172 if ((piece = readep(b)) == _error)
173 return zero;
174 b += 2;
175 if ((orient = readeo(b)) == _error)
176 return zero;
177 b++;
178 e[i] = piece | orient;
179 }
180 for (i = 0; i < 8; i++) {
181 while (*b == ' ' || *b == '\t' || *b == '\n')
182 b++;
183 if ((piece = readcp(b)) == _error)
184 return zero;
185 b += 3;
186 if ((orient = readco(b)) == _error)
187 return zero;
188 b++;
189 c[i] = piece | orient;
190 }
191
192 return cubefromarray(c, e);
193}
194
195_static uint8_t
196readpiece_LST(const char **b)
197{
198 uint8_t ret;
199 bool read;
200
201 while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n')
202 (*b)++;
203
204 for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) {
205 read = true;
206 ret = ret * 10 + (**b) - '0';
207 }
208
209 return read ? ret : _error;
210}
211
212_static cube_t
213readcube_LST(const char *buf)
214{
215 int i;
216 uint8_t c[8], e[12];
217
218 for (i = 0; i < 8; i++)
219 c[i] = readpiece_LST(&buf);
220
221 for (i = 0; i < 12; i++)
222 e[i] = readpiece_LST(&buf);
223
224 return cubefromarray(c, e);
225}
226
227_static int
228writepiece_LST(uint8_t piece, char *buf)
229{
230 char digits[3];
231 int i, len;
232
233 len = 0;
234 while (piece != 0) {
235 digits[len++] = (piece % 10) + '0';
236 piece /= 10;
237 }
238
239 if (len == 0)
240 digits[len++] = '0';
241
242 for (i = 0; i < len; i++)
243 buf[i] = digits[len-i-1];
244
245 buf[len] = ',';
246 buf[len+1] = ' ';
247
248 return len+2;
249}
250
251_static void
252writecube_B32(cube_t cube, char *buf)
253{
254 int i;
255 uint8_t corner[8], edge[12];
256
257 pieces(&cube, corner, edge);
258
259 for (i = 0; i < 8; i++)
260 buf[i] = cornertob32(corner[i]);
261
262 buf[8] = '=';
263
264 for (i = 0; i < 12; i++)
265 buf[i+9] = edgetob32(edge[i]);
266
267 buf[21] = '\0';
268}
269
270_static void
271writecube_H48(cube_t cube, char *buf)
272{
273 uint8_t piece, perm, orient, corner[8], edge[12];
274 int i;
275
276 pieces(&cube, corner, edge);
277
278 for (i = 0; i < 12; i++) {
279 piece = edge[i];
280 perm = piece & _pbits;
281 orient = (piece & _eobit) >> _eoshift;
282 buf[4*i ] = edgestr[perm][0];
283 buf[4*i + 1] = edgestr[perm][1];
284 buf[4*i + 2] = orient + '0';
285 buf[4*i + 3] = ' ';
286 }
287 for (i = 0; i < 8; i++) {
288 piece = corner[i];
289 perm = piece & _pbits;
290 orient = (piece & _cobits) >> _coshift;
291 buf[48 + 5*i ] = cornerstr[perm][0];
292 buf[48 + 5*i + 1] = cornerstr[perm][1];
293 buf[48 + 5*i + 2] = cornerstr[perm][2];
294 buf[48 + 5*i + 3] = orient + '0';
295 buf[48 + 5*i + 4] = ' ';
296 }
297
298 buf[48+39] = '\0';
299}
300
301_static void
302writecube_LST(cube_t cube, char *buf)
303{
304 int i;
305 size_t ptr;
306 uint8_t piece, corner[8], edge[12];
307
308 ptr = 0;
309 pieces(&cube, corner, edge);
310
311 for (i = 0; i < 8; i++) {
312 piece = corner[i];
313 ptr += writepiece_LST(piece, buf + ptr);
314 }
315
316 for (i = 0; i < 12; i++) {
317 piece = edge[i];
318 ptr += writepiece_LST(piece, buf + ptr);
319 }
320
321 *(buf+ptr-2) = 0;
322}
323
324_static uint8_t
325b32toedge(char c)
326{
327 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'))
328 return 255;
329
330 return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a');
331}
332
333_static uint8_t
334b32tocorner(char c) {
335 uint8_t val;
336
337 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'))
338 return 255;
339
340 val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
341
342 return (val & 7) | ((val & 24) << 2);
343}
344
345_static char
346edgetob32(uint8_t edge)
347{
348 return edge <= 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
349}
350
351_static char
352cornertob32(uint8_t corner)
353{
354 uint8_t val;
355
356 val = (corner & 7) | ((corner & 96) >> 2);
357
358 return val <= 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
359}
diff --git a/src/io_move_trans.h b/src/io_move_trans.h
new file mode 100644
index 0000000..e36b8e5
--- /dev/null
+++ b/src/io_move_trans.h
@@ -0,0 +1,87 @@
1_static uint8_t readmove(char);
2_static uint8_t readmodifier(char);
3_static uint8_t readtrans(const char *);
4_static int writemoves(uint8_t *, int, char *);
5_static void writetrans(uint8_t, char *);
6
7_static uint8_t
8readmove(char c)
9{
10 switch (c) {
11 case 'U':
12 return _move_U;
13 case 'D':
14 return _move_D;
15 case 'R':
16 return _move_R;
17 case 'L':
18 return _move_L;
19 case 'F':
20 return _move_F;
21 case 'B':
22 return _move_B;
23 default:
24 return _error;
25 }
26}
27
28_static uint8_t
29readmodifier(char c)
30{
31 switch (c) {
32 case '1': /* Fallthrough */
33 case '2': /* Fallthrough */
34 case '3':
35 return c - '0' - 1;
36 case '\'':
37 return 2;
38 default:
39 return 0;
40 }
41}
42
43_static uint8_t
44readtrans(const char *buf)
45{
46 uint8_t t;
47
48 for (t = 0; t < 48; t++)
49 if (!strncmp(buf, transstr[t], 11))
50 return t;
51
52 DBG_LOG("readtrans error\n");
53 return _error;
54}
55
56_static int
57writemoves(uint8_t *m, int n, char *buf)
58{
59 int i;
60 size_t len;
61 const char *s;
62 char *b;
63
64 for (i = 0, b = buf; i < n; i++, b++) {
65 s = movestr[m[i]];
66 len = strlen(s);
67 memcpy(b, s, len);
68 b += len;
69 *b = ' ';
70 }
71
72 if (b != buf)
73 b--; /* Remove last space */
74 *b = '\0';
75
76 return b - buf;
77}
78
79_static void
80writetrans(uint8_t t, char *buf)
81{
82 if (t >= 48)
83 memcpy(buf, "error trans", 11);
84 else
85 memcpy(buf, transstr[t], 11);
86 buf[11] = '\0';
87}

Generated with cgit - Back to sebastiano.tronto.net