nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

commit de04d37e8520079f5bba3b1a87d42313297543db
parent d5c60236c06e67e8da45e63843b37e5d619e9d7b
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 19 Dec 2025 07:32:09 +0100

Add coordinate solvers for corners

Diffstat:
Mdoc/solvers.md | 11+++++++++++
Msrc/arch/avx2.h | 12+++++++++++-
Msrc/arch/common.h | 1+
Msrc/arch/neon.h | 10++++++++++
Msrc/arch/portable.h | 13+++++++++++++
Msrc/core/cube.h | 9+++++++++
Msrc/solvers/coord/common.h | 12++++++++++++
Msrc/solvers/coord/coord.h | 1+
Asrc/solvers/coord/corners.h | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solvers/coord/list.h | 1+
Msrc/solvers/coord/types_macros.h | 1+
Msrc/solvers/dispatch.h | 1+
Msrc/solvers/solvers.h | 2+-
13 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/doc/solvers.md b/doc/solvers.md @@ -129,6 +129,17 @@ NISS will not be used. * Moveset: {U, U', U2, D, D', D2, R2, L2, F2, B2}. * Data size: 54MB. +### Solve corners + +Solve the corners of the cube. Note: centers are considered fixed, +this is not the same as solving a 2x2x2 cube. + +* Name: `coord_DRFIN_UF`. Other rotations in place of `UF` are allowed, + but they are irrelevant to the solver. Provided alias: `corners`. +* Requisites: none. +* Moveset: HTM (all 18 basic moves). +* Data size: 1.2MB. + ### Undocumented coordinate solvers There are some coordinate solvers that have not been listed above. These diff --git a/src/arch/avx2.h b/src/arch/avx2.h @@ -160,6 +160,16 @@ coord_co(cube_t c) return ret; } +STATIC_INLINE void +copy_co(cube_t cube[static 1], cube_t co) +{ + cube_t coclean; + + coclean = _mm256_and_si256(co, CO2_AVX2); + *cube = _mm256_andnot_si256(CO2_AVX2, *cube); + *cube = _mm256_or_si256(*cube, coclean); +} + STATIC_INLINE cube_t invcoord_co(uint64_t coord) { @@ -174,7 +184,7 @@ invcoord_co(uint64_t coord) cc = _mm256_loadu_si256((__m256i *)mem); cube = SOLVED_CUBE; - copy_corners(&cube, cc); + copy_co(&cube, cc); return cube; } diff --git a/src/arch/common.h b/src/arch/common.h @@ -35,6 +35,7 @@ STATIC_INLINE cube_t invcoord_epudsep(uint64_t); STATIC_INLINE bool is_eo_even(cube_t); STATIC_INLINE void copy_corners(cube_t [static 1], cube_t); +STATIC_INLINE void copy_co(cube_t [static 1], cube_t); STATIC_INLINE void copy_edges(cube_t [static 1], cube_t); STATIC_INLINE void set_eo(cube_t [static 1], uint64_t); diff --git a/src/arch/neon.h b/src/arch/neon.h @@ -232,6 +232,16 @@ coord_co(cube_t c) return ret; } +STATIC_INLINE void +copy_co(cube_t cube[static 1], cube_t co) +{ + uint8x8_t coclean; + + coclean = vand_u8(co.corner, CO2_NEON); + cube->corner = vbic_u8(cube->corner, CO2_NEON); + cube->corner = vorr_u8(cube->corner, coclean); +} + STATIC_INLINE cube_t invcoord_co(uint64_t coord) { diff --git a/src/arch/portable.h b/src/arch/portable.h @@ -154,6 +154,19 @@ inverse(cube_t cube) return ret; } +STATIC_INLINE void +copy_co(cube_t cube[static 1], cube_t co) +{ + uint8_t c; + size_t i; + + for (i = 0; i < 8; i++) { + c = cube->corner[i] & COBITS; + cube->corner[i] ^= c; + cube->corner[i] |= co.corner[i] & COBITS; + } +} + STATIC_INLINE uint64_t coord_co(cube_t c) { diff --git a/src/core/cube.h b/src/core/cube.h @@ -1,3 +1,5 @@ +STATIC bool cube_true(cube_t); + STATIC cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]); STATIC bool isconsistent(oriented_cube_t); STATIC bool issolvable(oriented_cube_t); @@ -19,6 +21,13 @@ STATIC uint8_t b32tocorner(char); STATIC char edgetob32(uint8_t); STATIC char cornertob32(uint8_t); +/* Used e.g. by the CORNERS coordinate, when a function pointer is needed */ +STATIC bool +cube_true(cube_t cube) +{ + return true; +} + STATIC cube_t cubefromarray(uint8_t c[static 8], uint8_t e[static 12]) { diff --git a/src/solvers/coord/common.h b/src/solvers/coord/common.h @@ -14,6 +14,7 @@ STATIC bool coord_is_solved( STATIC cube_t coordinate_merge_ce(cube_t, cube_t); STATIC cube_t coordinate_merge_ec(cube_t, cube_t); +STATIC cube_t coordinate_merge_cpco(cube_t, cube_t); STATIC uint64_t coord_coord_generic( @@ -215,3 +216,14 @@ coordinate_merge_ec(cube_t edges, cube_t corners) { return coordinate_merge_ce(corners, edges); } + +STATIC cube_t +coordinate_merge_cpco(cube_t cp, cube_t co) +{ + cube_t merged; + + merged = cp; + copy_co(&merged, co); + + return merged; +} diff --git a/src/solvers/coord/coord.h b/src/solvers/coord/coord.h @@ -8,6 +8,7 @@ #include "cpepe.h" #include "drfin.h" #include "htr.h" +#include "corners.h" #include "list.h" #include "utils.h" #include "gendata.h" diff --git a/src/solvers/coord/corners.h b/src/solvers/coord/corners.h @@ -0,0 +1,72 @@ +#define CLASSES_CP_48 984 + +STATIC uint64_t coordinate_corners_coord(const cube_t, const unsigned char *); +STATIC cube_t coordinate_corners_cube(uint64_t, const unsigned char *); +STATIC bool coordinate_corners_isnasty(uint64_t, const unsigned char *); +STATIC size_t coordinate_corners_gendata(unsigned char *); + +STATIC coord_t coordinate_corners = { + .name = "CORNERS", + .coord = &coordinate_corners_coord, + .cube = &coordinate_corners_cube, + .isnasty = &coordinate_corners_isnasty, + .gendata = coordinate_corners_gendata, + .max = CLASSES_CP_48 * POW_3_7, + .trans_mask = TM_ALLTRANS, + .moves_mask_gendata = MM18_ALLMOVES, + .moves_mask_solve = MM18_ALLMOVES, + .is_admissible = &solution_always_valid, + .solution_prune = NULL, + .is_solvable = &cube_true, + .is_solved = NULL, + .allow_niss = false, + .pruning_distribution = { + [0] = 1, + [1] = 2, + [2] = 9, + [3] = 76, + [4] = 708, + [5] = 5022, + [6] = 28248, + [7] = 132076, + [8] = 505705, + [9] = 1102421, + [10] = 375380, + [11] = 2360, + }, + .pruning_max = 11, + .sym = { + .classes = CLASSES_CP_48, + .max = FACT_8, + .coord = &coord_cp, + .cube = &invcoord_cp, + .max2 = POW_3_7, + .coord2 = &coord_co, + .cube2 = &invcoord_co, + .merge = &coordinate_merge_cpco, + }, +}; + +STATIC uint64_t +coordinate_corners_coord(const cube_t cube, const unsigned char *data) +{ + return coord_coord_generic(&coordinate_corners, cube, data); +} + +STATIC cube_t +coordinate_corners_cube(uint64_t i, const unsigned char *data) +{ + return coord_cube_generic(&coordinate_corners, i, data); +} + +STATIC bool +coordinate_corners_isnasty(uint64_t i, const unsigned char *data) +{ + return coord_isnasty_generic(&coordinate_corners, i, data); +} + +STATIC size_t +coordinate_corners_gendata(unsigned char *data) +{ + return coord_gendata_generic(&coordinate_corners, data); +} diff --git a/src/solvers/coord/list.h b/src/solvers/coord/list.h @@ -6,6 +6,7 @@ coord_t *all_coordinates[] = { &coordinate_drslice, &coordinate_cpepe, &coordinate_htr, + &coordinate_corners, NULL }; diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h @@ -30,6 +30,7 @@ typedef struct { bool (*is_admissible)(const solution_moves_t[static 1]); bool (*solution_prune)(const solution_moves_t[static 1]); bool (*is_solvable)(cube_t); + /* if is_solved is nulle, coord == 0 is used */ bool (*is_solved)(uint64_t, const unsigned char *); uint64_t pruning_distribution[INFO_DISTRIBUTION_LEN]; uint8_t pruning_max; diff --git a/src/solvers/dispatch.h b/src/solvers/dispatch.h @@ -65,6 +65,7 @@ const char *solver_aliases[][2] = { { "htr-drud", "coord_HTR_UF" }, { "htr-drrl", "coord_HTR_LF" }, { "htr-drfb", "coord_HTR_BU" }, + { "corners", "coord_CORNERS_UF" }, { NULL, NULL } }; diff --git a/src/solvers/solvers.h b/src/solvers/solvers.h @@ -3,6 +3,6 @@ #include "tables_types_macros.h" #include "tables.h" #include "distribution.h" -#include "h48/h48.h" #include "coord/coord.h" +#include "h48/h48.h" #include "dispatch.h"