1 /* compare ints - a test utility */
2 
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <errno.h>
8 #include <inttypes.h>
9 
10 /*  Declarations */
11 
12 /* Globals */
13 
14 /* Functions */
get_data(FILE * f,int64_t * dd,int signed_flag,int bytes)15 int get_data(FILE *f, int64_t *dd, int signed_flag, int bytes) {
16     int res;
17     int8_t   d_8;
18     int16_t  d_16;
19     uint8_t  d_u8;
20     uint16_t d_u16;
21     // TODO Loop on reads until, but catch EOF!!
22     if (signed_flag) {
23         switch (bytes) {
24             case 1:
25                 res = fread(&d_8, bytes, 1, f);
26                 *dd = d_8;
27                 break;
28             case 2:
29                 res = fread(&d_16, bytes, 1, f);
30                 *dd = d_16;
31                 break;
32             default:
33                 fprintf(stderr, "Error: unsupported size %d bytes\n", bytes);
34                 exit(1);
35             }
36         }
37     else {  // unsigned
38         switch (bytes) {
39             case 1:
40                 res = fread(&d_u8, bytes, 1, f);
41                 *dd = d_u8;
42                 break;
43             case 2:
44                 res = fread(&d_u16, bytes, 1, f);
45                 *dd = d_u16;
46                 break;
47             default:
48                 fprintf(stderr, "Error: unsupported size %d bytes\n", bytes);
49                 exit(1);
50             }
51         }
52 
53     if (res != 1) return(0);
54     else return(1);
55     }
56 
57 
58 /* Main */
59 
main(int argc,char * argv[])60 int main(int argc, char *argv[]) {
61 
62     char usage[] = "Usage: %s [-b size_in_bytes] [-c] [-s] [-t tolerance] [-n numerrorstoexit] file1 file2\n";
63 
64     int bytes = 1;
65     int count_errors = 0;
66     int signed_flag = 0;
67     int tol = 1;
68     int numerrorstoexit = -1;
69 
70     int opt;
71     while ((opt = getopt(argc, argv, "b:cst:n:")) != -1) {
72         switch (opt) {
73             case 'b':
74                 bytes = atoi(optarg);
75                 break;
76             case 'c':
77                 count_errors = 1;
78                 break;
79             case 's':
80                 signed_flag = 1;
81                 break;
82             case 'n':
83                 numerrorstoexit = atoi(optarg);
84                 break;
85             case 't':
86                 tol = atof(optarg);
87                 break;
88             default:
89                 fprintf(stderr, usage, argv[0]);
90                 exit(1);
91             }
92         }
93 
94     if ((optind + 2) > argc) {
95         fprintf(stderr, usage, argv[0]);
96         exit(1);
97         }
98     char *fname1 = argv[optind++];
99     char *fname2 = argv[optind++];
100 
101     FILE *f1 = fopen(fname1, "rb");
102     if (f1 == NULL) {
103         fprintf(stderr, "Error opening file1 \"%s\": ", fname1);
104         perror(NULL);
105         exit(1);
106         }
107 
108     FILE *f2 = fopen(fname2, "rb");
109     if (f2 == NULL) {
110         fprintf(stderr, "Error opening file2 \"%s\": ", fname2);
111         perror(NULL);
112         exit(1);
113         }
114 
115     // Convert inputs to SIGNED long values
116     int64_t data1, data2;
117 
118     int count = 0;
119     int errors = 0;
120     int rms_sum = 0;
121 
122     while (get_data(f1, &data1, signed_flag, bytes)) {
123         if (!get_data(f2, &data2, signed_flag, bytes)) {
124             fprintf(stderr, "Error: file2 is shorter\n");
125             exit(1);
126         }
127         uint64_t err = llabs(data1 - data2);
128         if (err > tol) {
129             errors ++;
130             printf("%d %" PRId64 " %" PRId64 "\n", count, data1, data2);
131 	    if (numerrorstoexit != -1)
132 	        if (errors > numerrorstoexit) {
133 		    printf("reached errors: %d, bailing!", numerrorstoexit);
134 		    exit(1);
135 		}
136         }
137         rms_sum += (err * err);
138         count ++;
139     }
140     if (get_data(f2, &data2, signed_flag, bytes)) {
141         fprintf(stderr, "Error: file1 is shorter\n");
142         exit(1);
143     }
144 
145     if (count_errors) exit(errors);
146     else {
147         if (errors) {
148             printf("Fail: %d errors\n", errors);
149             printf("      rms error = %f\n", ((double)rms_sum/count));
150             exit(1);
151             }
152         else printf("Pass\n");
153         exit(0);
154         }
155 
156     } // main
157 
158 
159 /* vi:set ts=4 et sts=4: */
160