commit 5cf18fa4694ab9f082813d04e3ec5b78a061d9df
parent cecdb7c5a0fc4821bc56c6aae5428925ec1baa15
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Mon, 26 Dec 2022 19:27:21 +0100
Implemented faster fst_ep_to_epos
Diffstat:
4 files changed, 83 insertions(+), 78 deletions(-)
diff --git a/TODO.md b/TODO.md
@@ -4,6 +4,9 @@ This is a list of things that I would like to add or change at some point.
 It's more of a personal reminder than anything else.
 
 ## After symcoord
+### Fixing stuff + completing new optimal solver
+- clean up fst, check if more can be improved
+- fst inverse tables: save to file
 ### generic:
 * all files should have an init function, calling the ones
   of the files includes + doing more stuff. A static "initiliazed"
diff --git a/src/fst.c b/src/fst.c
@@ -3,7 +3,6 @@
 #include "fst.h"
 
 static FstCube          ep_to_fst_epos(int *ep);
-static void             transform_ep_only(Trans t, int *ep, Cube *dst);
 static void             init_fst_corner_invtables();
 static void             init_fst_eo_invtables();
 static void             init_fst_eo_update(uint64_t, uint64_t, int, Cube *);
@@ -54,24 +53,12 @@ cube_to_fst(Cube *cube)
 static FstCube
 ep_to_fst_epos(int *ep)
 {
-	/* TODO: maybe optimize */
 
-/* TODO: this version if faster, but broken
-	 probably need to fix transform_ep_only()
-
-	FstCube ret;
-	Cube c;
-
-	memcpy(c.ep, ep, 12 * sizeof(int));
-	ret.uf_eposepe = coord_eposepe.i[0]->index(&c);
-
-	transform_ep_only(fr, ep, &c);
-	ret.fr_eposepe = coord_eposepe.i[0]->index(&c);
-
-	transform_ep_only(rd, ep, &c);
-	ret.rd_eposepe = coord_eposepe.i[0]->index(&c);
-*/
+/* The block of commented code works, but it is slower.
+   The actual code is mysterious, and there is some overlap with coord.c
+   (coord_eposepe.i), and trans.c, butbut it is faster. */
 
+/*
 	FstCube ret;
 	Cube c, d;
 
@@ -90,16 +77,89 @@ ep_to_fst_epos(int *ep)
 	ret.rd_eposepe = coord_eposepe.i[0]->index(&d);
 
 	return ret;
+*/
+
+	static int eind[12] = {
+		[FR] = 0, [FL] = 1, [BL] = 2, [BR] = 3,
+		[UR] = 0, [DR] = 1, [DL] = 2, [UL] = 3,
+		[DB] = 0, [DF] = 1, [UF] = 2, [UB] = 3
+	};
+	static int eptrans_fr[12] = {
+		[FR] = UF, [DF] = UL, [FL] = UB, [UF] = UR,
+		[BR] = DF, [DB] = DL, [BL] = DB, [UB] = DR,
+		[UR] = FR, [DR] = FL, [DL] = BL, [UL] = BR
+	};
+	static int eptrans_rd[12] = {
+		[DR] = UF, [FR] = UL, [UR] = UB, [BR] = UR,
+		[DL] = DF, [FL] = DL, [UL] = DB, [BL] = DR,
+		[DB] = FR, [DF] = FL, [UF] = BL, [UB] = BR
+	};
+
+	FstCube ret;
+	int i, ce, cs, cm;
+	int epe[4], eps[4], epm[4], epose[12], eposs[12], eposm[12];
+
+	memset(epose, 0, 12*sizeof(int));
+	memset(eposs, 0, 12*sizeof(int));
+	memset(eposm, 0, 12*sizeof(int));
+
+	for (i = 0, ce = 0; i < 12; i++) {
+		switch (edge_slice[ep[i]]) {
+		case 0:
+			epose[i] = 1;
+			epe[ce++] = eind[ep[i]];
+			break;
+		case 1:
+			eposs[eptrans_fr[i]] = eind[ep[i]] + 1;
+			break;
+		default:
+			eposm[eptrans_rd[i]] = eind[ep[i]] + 1;
+			break;
+		}
+	}
+
+	for (i = 0, cs = 0, cm = 0; i < 12; i++) {
+		if (eposs[i]) {
+			eps[cs++] = eposs[i] - 1;
+			eposs[i] = 1;
+		}
+		if (eposm[i]) {
+			epm[cm++] = eposm[i] - 1;
+			eposm[i] = 1;
+		}
+	}
+
+	ret.uf_eposepe = subset_to_index(epose, 12, 4) * FACTORIAL4 +
+	                 perm_to_index(epe, 4);
+	ret.fr_eposepe = subset_to_index(eposs, 12, 4) * FACTORIAL4 +
+	                 perm_to_index(eps, 4);
+	ret.rd_eposepe = subset_to_index(eposm, 12, 4) * FACTORIAL4 +
+	                 perm_to_index(epm, 4);
+
+	return ret;
 }
 
 FstCube
 fst_inverse(FstCube fst)
 {
 	FstCube ret;
-	int i, ep_inv[12];
+	int ep_inv[12];
+
+	ep_inv[FR] = fst_where_is_edge_arr[0][FR][fst.uf_eposepe];
+	ep_inv[FL] = fst_where_is_edge_arr[0][FL][fst.uf_eposepe];
+	ep_inv[BL] = fst_where_is_edge_arr[0][BL][fst.uf_eposepe];
+	ep_inv[BR] = fst_where_is_edge_arr[0][BR][fst.uf_eposepe];
+
+	ep_inv[UR] = fst_where_is_edge_arr[1][UR][fst.fr_eposepe];
+	ep_inv[UL] = fst_where_is_edge_arr[1][UL][fst.fr_eposepe];
+	ep_inv[DR] = fst_where_is_edge_arr[1][DR][fst.fr_eposepe];
+	ep_inv[DL] = fst_where_is_edge_arr[1][DL][fst.fr_eposepe];
+
+	ep_inv[UF] = fst_where_is_edge_arr[2][UF][fst.rd_eposepe];
+	ep_inv[UB] = fst_where_is_edge_arr[2][UB][fst.rd_eposepe];
+	ep_inv[DF] = fst_where_is_edge_arr[2][DF][fst.rd_eposepe];
+	ep_inv[DB] = fst_where_is_edge_arr[2][DB][fst.rd_eposepe];
 
-	for (i = 0; i < 12; i++)
-		ep_inv[i] = fst_where_is_edge(i, fst);
 	ret = ep_to_fst_epos(ep_inv);
 
 	ret.uf_eofb = ((uint16_t)eo_invtable[0][fst.uf_eofb][fst.uf_eposepe]) |
@@ -175,30 +235,6 @@ fst_to_cube(FstCube fst, Cube *cube)
 		cube->xp[i] = i;
 }
 
-int
-fst_where_is_edge(int e, FstCube fst)
-{
-	switch (edge_slice[e]) {
-	case 0:
-		return fst_where_is_edge_arr[0][e][fst.uf_eposepe];
-	case 1:
-		return fst_where_is_edge_arr[1][e][fst.fr_eposepe];
-	default:
-		return fst_where_is_edge_arr[2][e][fst.rd_eposepe];
-	}
-
-	return -1;
-}
-
-static void
-transform_ep_only(Trans t, int *ep, Cube *dst)
-{
-	int i;
-
-	for (i = 0; i < 12; i++)
-		dst->ep[i] = trans_ep_alg[t][ep[trans_ep_inv[t][i]]];
-}
-
 void
 init_fst()
 {
diff --git a/src/fst.h b/src/fst.h
@@ -7,7 +7,6 @@ FstCube     cube_to_fst(Cube *cube);
 FstCube     fst_inverse(FstCube fst);
 FstCube     fst_move(Move m, FstCube fst);
 void        fst_to_cube(FstCube fst, Cube *cube);
-int         fst_where_is_edge(int e, FstCube fst);
 void        init_fst();
 
 #endif
diff --git a/tests/fst_post_init_tests.c b/tests/fst_post_init_tests.c
@@ -4,19 +4,16 @@ static bool fst_move_testcase(Cube *c, Alg *a);
 static bool fst_inverse_testcase(Cube *c, Alg *a);
 
 static bool fst_move_test();
-static bool fst_where_is_edge_test();
 static bool fst_inverse_test();
 
 static Tester test[] = {
 	fst_move_test,
-	fst_where_is_edge_test,
 	fst_inverse_test,
 	NULL
 };
 
 static char *name[] = {
 	"FST move",
-	"FST where is edge",
 	"FST inverse",
 };
 
@@ -62,36 +59,6 @@ fst_move_test()
 }
 
 static bool
-fst_where_is_edge_test()
-{
-	int i;
-	Alg *scr;
-	Cube c, d;
-	FstCube fst;
-
-	/* Testing on a single scramble is fine for now */
-	scr = new_alg("RUFDL2B2FRD");
-	make_solved(&c);
-	apply_alg(scr, &c);
-	fst = cube_to_fst(&c);
-
-	for (i = 0; i < 12; i++) {
-		if (fst_where_is_edge(c.ep[i], fst) != i) {
-			fst_to_cube(fst, &d);
-			printf("Alg: ");
-			print_alg(scr, false);
-			printf("Expected:\n");
-			print_cube(&c);
-			printf("But got:\n");
-			print_cube(&d);
-			return false;
-		}
-	}
-
-	return true;
-}
-
-static bool
 fst_inverse_test()
 {
 	return try_all_str(fst_inverse_testcase, "FST test incorrect");