diff --git a/makefile b/makefile index 927575a800..2c2f81449f 100644 --- a/makefile +++ b/makefile @@ -60,7 +60,7 @@ $(LIB): $(OBJECTS) $(AR) $(ARFLAGS) $(LIB) $^ test: $(EXECUTABLE) - ./$(EXECUTABLE) data/zort_111_160_15.dat data/zort_111_160_15.mgard 11 160 15 1e-3 0 + ./$(EXECUTABLE) data/zort_111_160_15.dat data/zort_111_160_15.mgard 111 160 15 1e-3 0 test2: $(EXECUTABLE) ./$(EXECUTABLE) data/u3_513x513_orig data/u3_513x513.mgard 513 513 1 1e-3 0 diff --git a/src/mgard_test.c b/src/mgard_test.c index a3b439ea03..6bd04101b4 100644 --- a/src/mgard_test.c +++ b/src/mgard_test.c @@ -39,117 +39,148 @@ #include "mgard_capi.h" -#define print_red "\e[31m" +#define ANSI_RED "\x1b[31m" +#define ANSI_GREEN "\x1b[32m" +#define ANSI_RESET "\x1b[0m" + +void print_usage_message(char *argv[], FILE *fp) { + fprintf(fp, "Usage: %s infile outfile nrow ncol nfib tolerance s\n", argv[0]); +} + +void print_for_more_details_message(char *argv[], FILE *fp) { + fprintf(fp, "\nFor more details, run: %s --help\n", argv[0]); +} + +void print_help_message(char *argv[], FILE *fp) { + fprintf( + fp, + "\nThe input file `infile` should contain a double[`nrow`][`ncol`][`nfib`] array.\n" + "The array will be compressed so that the error as measured in the H^`s` norm is\n" + "no more than `tolerance`. (Use `s` = inf for the L^infty norm and `s` = 0 for the\n" + "L^2 norm.) The compressed array will be written to the output file `outfile`.\n" + ); +} int main(int argc, char *argv[]) { - int i, j, nrow, ncol, nfib; - double tol, s; + size_t result; - if(argc < 7) - { - fprintf (stderr, "%s: Not enough arguments! Usage: %s infile outfile nrow ncol tolerance, s\n", argv[0], argv[0]); - return 1; - } - else - { - nrow = atoi(argv[3]); - ncol = atoi(argv[4]); - nfib = atoi(argv[5]); - tol = atof(argv[6]); - s = atof(argv[7]); - } - + if (argc == 2 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) { + print_usage_message(argv, stdout); + print_help_message(argv, stdout); + return 0; + } - FILE * pFile; - long lSize; - char * buffer; - size_t result; + char *infile, *outfile; + int nrow, ncol, nfib; + double tol, s; + if (argc != 8) { + if (argc < 8) { + fprintf (stderr, "%s: Not enough arguments! ", argv[0]); + } else { + fprintf (stderr, "%s: Too many arguments! ", argv[0]); + } + print_usage_message(argv, stderr); + print_for_more_details_message(argv, stderr); + return 1; + } else { + infile = argv[1]; + outfile = argv[2]; + nrow = atoi(argv[3]); + ncol = atoi(argv[4]); + nfib = atoi(argv[5]); + tol = atof(argv[6]); + s = atof(argv[7]); + } + long num_doubles = nrow * ncol * nfib; + long num_bytes = sizeof(double) * num_doubles; - pFile = fopen ( argv[1] , "rb" ); + FILE *pFile; + pFile = fopen ( infile , "rb" ); if (pFile==NULL) {fputs ("File error",stderr); exit (1);} - fseek (pFile , 0 , SEEK_END); - lSize = ftell (pFile); + long lSize = ftell (pFile); rewind (pFile); - buffer = (char*) malloc (sizeof(char)*lSize); + if (lSize != num_bytes) { + fprintf( + stderr, + "%s contains %lu bytes when %lu were expected. Exiting.\n", + infile, + lSize, + num_bytes + ); + return 1; + } + + double *buffer = (double *) malloc (sizeof(char)*lSize); if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);} result = fread (buffer,1,lSize,pFile); if (result != lSize) {fputs ("Reading error",stderr); exit (3);} - - fclose (pFile); - - double* in_buff = (double*) malloc (sizeof(char)*lSize); + double data_L_inf_norm = 0; + for(int i = 0; i < num_doubles; ++i) + { + double temp = fabs(buffer[i]); + if(temp > data_L_inf_norm) data_L_inf_norm = temp; + } - memcpy (in_buff, buffer, lSize); - - - unsigned char* mgard_comp_buff; - - double norm0 = 0; - for(i = 0; i norm0) norm0 = temp; - } - } + double *in_buff = (double *) malloc(sizeof(double) * num_doubles); + memcpy(in_buff, buffer, sizeof(double) * num_doubles); int iflag = 1; //0 -> float, 1 -> double int out_size; - mgard_comp_buff = mgard_compress(iflag, in_buff, &out_size, nrow, ncol, nfib, &tol, s ); - + unsigned char *mgard_comp_buff; + mgard_comp_buff = mgard_compress(iflag, in_buff, &out_size, nrow, ncol, nfib, &tol, s); + free(in_buff); - FILE *qfile; - /* qfile = fopen ( argv[2] , "wb" ); */ - - /* char* outbuffer = ((char*)mgard_comp_buff); */ - - /* result = fwrite (outbuffer, 1, out_size, qfile); */ - /* fclose(qfile); */ - - printf ("In size: %10ld Out size: %10d Compression ratio: %10ld \n", lSize, out_size, lSize/out_size); - + double* mgard_out_buff; - mgard_out_buff = mgard_decompress(iflag, mgard_comp_buff, out_size, nrow, ncol, nfib, s); - - qfile = fopen ( argv[2] , "wb" ); - - char * outbuffer = ((char*)mgard_out_buff); - + FILE *qfile; + qfile = fopen ( outfile , "wb" ); result = fwrite (mgard_out_buff, 1, lSize, qfile); - /* result = fwrite (outbuffer, 1, lSize, qfile); */ fclose(qfile); + if (result != lSize) {fputs ("Writing error",stderr); exit (4);} - double norm = 0; - - for(i = 0; i < nrow*ncol*nfib; ++i) - { - double temp = fabs( in_buff[i] - mgard_out_buff[i] ); - if(temp > norm) norm = temp; - } - - printf ("Rel. L-infty error tolerance: %10.5E \n", tol); - printf ("Rel. L-infty error: %10.5E \n", norm/norm0); + double error_L_inf_norm = 0; + for(int i = 0; i < num_doubles; ++i) + { + double temp = fabs( buffer[i] - mgard_out_buff[i] ); + if(temp > error_L_inf_norm) error_L_inf_norm = temp; + } + double relative_L_inf_error = error_L_inf_norm / data_L_inf_norm; + + //Maximum length (plus one for terminating byte) of norm name. + size_t N = 10; + char norm_name[N]; + int num_chars_written; + if (isinf(s)) { + num_chars_written = snprintf(norm_name, N, "L^infty"); + } else if (s == 0) { + num_chars_written = snprintf(norm_name, N, "L^2"); + } else { + num_chars_written = snprintf(norm_name, N, "H^%.1f", s); + } + if (num_chars_written <= 0 || num_chars_written >= N) { + norm_name[0] = '?'; + norm_name[1] = 0; + } + printf ("Rel. %s error tolerance: %10.5E \n", norm_name, tol); + printf ("Rel. L^infty error: %10.5E \n", relative_L_inf_error); - if( norm/norm0 < tol) + if( relative_L_inf_error < tol) { - printf("\x1b[32mSUCCESS: Error tolerance met! \x1b[0m \n"); + printf(ANSI_GREEN "SUCCESS: Error tolerance met!" ANSI_RESET "\n"); return 0; } else{ - printf("\x1b[31mFAILURE: Error tolerance NOT met! \x1b[0m \n"); + printf(ANSI_RED "FAILURE: Error tolerance NOT met!" ANSI_RESET "\n"); return 1; } - - }