h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

tool.h (5106B)


      1 #include <time.h>
      2 #include <stdarg.h>
      3 #include <stdbool.h>
      4 #include <inttypes.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #include "../src/nissy.h"
     10 #include "nissy_extra.h"
     11 
     12 static void log_stderr(const char *, ...);
     13 static void log_stdout(const char *, ...);
     14 static double timerun(void (*)(void));
     15 static void writetable(const char *, int64_t, const char *);
     16 static long long int generatetable(const char *, char **);
     17 static long long int derivetable(
     18     const char *, const char *, const char *, char **);
     19 static int getdata(const char *, char **, const char *);
     20 static void gendata_run(const char *, uint64_t[static 21]);
     21 static void derivedata_run(
     22     const char *, const char *, const char *, const char *);
     23 
     24 static void
     25 log_stderr(const char *str, ...)
     26 {
     27 	va_list args;
     28 
     29 	va_start(args, str);
     30 	vfprintf(stderr, str, args);
     31 	va_end(args);
     32 }
     33 
     34 static void
     35 write_stdout(const char *str, ...)
     36 {
     37 	va_list args;
     38 
     39 	va_start(args, str);
     40 	vfprintf(stdout, str, args);
     41 	va_end(args);
     42 }
     43 
     44 static double
     45 timerun(void (*run)(void))
     46 {
     47 	struct timespec start, end;
     48 	double tdiff, tdsec, tdnano;
     49 
     50 	fflush(stdout);
     51 
     52 	if (run == NULL) {
     53 		printf("nothing to run!\n");
     54 		fflush(stdout);
     55 		return -1.0;
     56 	}
     57 
     58 	clock_gettime(CLOCK_MONOTONIC, &start);
     59 	run();
     60 	clock_gettime(CLOCK_MONOTONIC, &end);
     61 
     62 	tdsec = end.tv_sec - start.tv_sec;
     63 	tdnano = end.tv_nsec - start.tv_nsec;
     64 	tdiff = tdsec + 1e-9 * tdnano;
     65 
     66 	printf("---------\n");
     67 	printf("\nTotal time: %.4fs\n", tdiff);
     68 	fflush(stdout);
     69 
     70 	return tdiff;
     71 }
     72 
     73 static void
     74 writetable(const char *buf, int64_t size, const char *filename)
     75 {
     76 	FILE *f;
     77 
     78 	if ((f = fopen(filename, "wb")) == NULL) {
     79 		printf("Could not write tables to file %s"
     80 		    ", will be regenerated next time.\n", filename);
     81 	} else {
     82 		fwrite(buf, size, 1, f);
     83 		fclose(f);
     84 		printf("Table written to %s.\n", filename);
     85 	}
     86 }
     87 
     88 static long long int
     89 generatetable(const char *solver, char **buf)
     90 {
     91 	long long int size, gensize;
     92 
     93 	size = nissy_datasize(solver);
     94 	if (size < 0) {
     95 		printf("Error getting table size.\n");
     96 		return -1;
     97 	}
     98 
     99 	*buf = malloc(size);
    100 	gensize = nissy_gendata(solver, size, *buf);
    101 
    102 	if (gensize != size) {
    103 		printf("Error generating table");
    104 		if (gensize == NISSY_OK)
    105 			printf(" (got %lld bytes)", gensize);
    106 		printf("\n");
    107 		return -2;
    108 	}
    109 
    110 	return gensize;
    111 }
    112 
    113 static long long int
    114 derivetable(
    115 	const char *solver_large,
    116 	const char *solver_small,
    117 	const char *filename_large,
    118 	char **buf
    119 )
    120 {
    121 	uint8_t h, k;
    122 	long long int size, gensize;
    123 	char *fulltable;
    124 
    125 	if (getdata(solver_large, &fulltable, filename_large) != 0) {
    126 		printf("Error reading full table.\n");
    127 		gensize = -1;
    128 		goto derivetable_error_nofree;
    129 	}
    130 
    131 	size = nissy_datasize(solver_small);
    132 	if (size == -1) {
    133 		printf("Error getting table size.\n");
    134 		gensize = -2;
    135 		goto derivetable_error;
    136 	}
    137 
    138 	if (parse_h48_solver(solver_small, &h, &k) != 0) {
    139 		gensize = -3;
    140 		goto derivetable_error;
    141 	}
    142 
    143 	*buf = malloc(size);
    144 	gensize = gendata_h48_derive(h, fulltable, *buf);
    145 
    146 	if (gensize != size) {
    147 		printf("Error deriving table\n");
    148 		gensize = -4;
    149 		goto derivetable_error;
    150 	}
    151 
    152 derivetable_error:
    153 	free(fulltable);
    154 
    155 derivetable_error_nofree:
    156 	return gensize;
    157 }
    158 
    159 static int
    160 getdata(
    161 	const char *solver,
    162 	char **buf,
    163 	const char *filename
    164 ) {
    165 	long long int size, sizeread;
    166 	FILE *f;
    167 
    168 	if ((f = fopen(filename, "rb")) == NULL) {
    169 		printf("Table file not found, generating it.\n");
    170 		size = generatetable(solver, buf);
    171 		switch (size) {
    172 		case -1:
    173 			goto getdata_error_nofree;
    174 		case -2:
    175 			goto getdata_error;
    176 		default:
    177 			writetable(*buf, size, filename);
    178 			break;
    179 		}
    180 	} else {
    181 		printf("Reading tables from file %s\n", filename);
    182 		size = nissy_datasize(solver);
    183 		*buf = malloc(size);
    184 		sizeread = fread(*buf, size, 1, f);
    185 		fclose(f);
    186 		if (sizeread != 1) {
    187 			printf("Error reading table, stopping\n");
    188 			goto getdata_error;
    189 		}
    190 	}
    191 
    192 	return 0;
    193 
    194 getdata_error:
    195 	free(*buf);
    196 getdata_error_nofree:
    197 	return 1;
    198 }
    199 
    200 static void
    201 gendata_run(
    202 	const char *solver,
    203 	uint64_t expected[static 21]
    204 ) {
    205 	long long int size;
    206 	char *buf, filename[1024];
    207 
    208 	sprintf(filename, "tables/%s", solver);
    209 	size = generatetable(solver, &buf);
    210 	switch (size) {
    211 	case -1:
    212 		return;
    213 	case -2:
    214 		goto gendata_run_finish;
    215 	default:
    216 		nissy_datainfo(size, buf, write_stdout);
    217 		printf("\n");
    218 		printf("Succesfully generated %lld bytes. "
    219 		       "See above for details on the tables.\n", size);
    220 
    221 		/* TODO: check that the table is correct */
    222 		writetable(buf, size, filename);
    223 		break;
    224 	}
    225 
    226 gendata_run_finish:
    227 	free(buf);
    228 }
    229 
    230 static void
    231 derivedata_run(
    232 	const char *solver_large,
    233 	const char *solver_small,
    234 	const char *filename_large,
    235 	const char *filename_small
    236 )
    237 {
    238 	long long int size;
    239 	char *buf;
    240 
    241 	buf = NULL;
    242 	size = derivetable(solver_large, solver_small, filename_large, &buf);
    243 	switch (size) {
    244 	case -1:
    245 		return;
    246 	case -2:
    247 		goto derivedata_run_finish;
    248 	default:
    249 		nissy_datainfo(size, buf, write_stdout);
    250 		printf("\n");
    251 		printf("Succesfully generated %lld bytes. "
    252 		       "See above for details on the tables.\n", size);
    253 
    254 		writetable(buf, size, filename_small);
    255 		break;
    256 	}
    257 
    258 derivedata_run_finish:
    259 	free(buf);
    260 }