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 (3795B)


      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 <time.h>
      8 
      9 #include "../src/nissy.h"
     10 
     11 static void log_stderr(const char *, ...);
     12 static void log_stdout(const char *, ...);
     13 static double timerun(void (*)(void), const char *);
     14 static void writetable(const char *, int64_t, const char *);
     15 static int64_t generatetable(const char *, const char *, char **);
     16 static int getdata(const char *, const char *, char **, const char *);
     17 static void gendata_run(const char *, const char *, const char *, uint64_t[static 21]);
     18 
     19 static void
     20 log_stderr(const char *str, ...)
     21 {
     22 	va_list args;
     23 
     24 	va_start(args, str);
     25 	vfprintf(stderr, str, args);
     26 	va_end(args);
     27 }
     28 
     29 static void
     30 write_stdout(const char *str, ...)
     31 {
     32 	va_list args;
     33 
     34 	va_start(args, str);
     35 	vfprintf(stdout, str, args);
     36 	va_end(args);
     37 }
     38 
     39 static double
     40 timerun(void (*run)(void), const char *name)
     41 {
     42 	struct timespec start, end;
     43 	double tdiff, tdsec, tdnano;
     44 
     45 	printf("\n");
     46 	fflush(stdout);
     47 
     48 	if (run == NULL) {
     49 		printf("> %s: nothing to run!\n", name);
     50 		fflush(stdout);
     51 		return -1.0;
     52 	}
     53 
     54 	printf("Running tool: %s\n", name);
     55 	printf("==========\n");
     56 	fflush(stdout);
     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 		fprintf(stderr, "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 		fprintf(stderr, "Table written to %s.\n", filename);
     85 	}
     86 }
     87 
     88 static int64_t
     89 generatetable(const char *solver, const char *options, char **buf)
     90 {
     91 	int64_t size, gensize;
     92 
     93 	size = nissy_datasize(solver, options);
     94 	if (size == -1) {
     95 		printf("Error getting table size.\n");
     96 		return -1;
     97 	}
     98 
     99 	*buf = malloc(size);
    100 	gensize = nissy_gendata(solver, options, *buf);
    101 
    102 	if (gensize != size) {
    103 		fprintf(stderr, "Error generating table");
    104 		if (gensize != -1)
    105 			fprintf(stderr, " (got %" PRId64 " bytes)", gensize);
    106 		fprintf(stderr, "\n");
    107 		return -2;
    108 	}
    109 
    110 	return gensize;
    111 }
    112 
    113 static int
    114 getdata(
    115 	const char *solver,
    116 	const char *options,
    117 	char **buf,
    118 	const char *filename
    119 ) {
    120 	int64_t size, sizeread;
    121 	FILE *f;
    122 
    123 	if ((f = fopen(filename, "rb")) == NULL) {
    124 		fprintf(stderr, "Table file not found, generating it.\n");
    125 		size = generatetable(solver, options, buf);
    126 		switch (size) {
    127 		case -1:
    128 			goto getdata_error_nofree;
    129 		case -2:
    130 			goto getdata_error;
    131 		default:
    132 			writetable(filename, size, *buf);
    133 			break;
    134 		}
    135 	} else {
    136 		fprintf(stderr, "Reading tables from file %s\n", filename);
    137 		size = nissy_datasize(solver, options);
    138 		*buf = malloc(size);
    139 		sizeread = fread(*buf, size, 1, f);
    140 		fclose(f);
    141 		if (sizeread != 1) {
    142 			fprintf(stderr, "Error reading table, stopping\n");
    143 			goto getdata_error;
    144 		}
    145 	}
    146 
    147 	return 0;
    148 
    149 getdata_error:
    150 	free(*buf);
    151 getdata_error_nofree:
    152 	return 1;
    153 }
    154 
    155 static void
    156 gendata_run(
    157 	const char *solver,
    158 	const char *options,
    159 	const char *filename, /* TODO: remove filename, use solver name */
    160 	uint64_t expected[static 21]
    161 ) {
    162 	int64_t size;
    163 	char *buf;
    164 
    165 	
    166 	size = generatetable(solver, options, &buf);
    167 	switch (size) {
    168 	case -1:
    169 		return;
    170 	case -2:
    171 		goto gendata_run_finish;
    172 	default:
    173 		nissy_datainfo(buf, write_stdout);
    174 		printf("\n");
    175 		printf("Succesfully generated %" PRId64 " bytes. "
    176 		       "See above for details on the tables.\n", size);
    177 
    178 		/* TODO: check that the table is correct */
    179 		writetable(buf, size, filename);
    180 		break;
    181 	}
    182 
    183 gendata_run_finish:
    184 	free(buf);
    185 }