75 CLO_RELATIVE_TOLERANCE,
85char *option[N_OPTIONS] = {
99char *USAGE1 =
"Usage: sddsdiff <file1> <file2>\n\
100 [-compareCommon[=column|parameter|array]]\n\
101 [-columns=<col1>[,<col2>...]]\n\
102 [-parameters=<par1][,<par2>...]]\n\
103 [-arrays=<array1>[,<array2>...]]\n\
104 [-tolerance=<value>]\n\
105 [-relativeTolerance=<value>]\n\
106 [-precision=<integer>]\n\
107 [-format=float=<string>|double=<string>|longdouble=<string>|string=<string>]\n\
110 [-rowlabel=<column-name>[,nocomparison]]\n\
113 -compareCommon[=column|parameter|array] Compare only the common items.\n\
114 -columns=<col1>[,<col2>...] Specify columns to compare.\n\
115 -parameters=<par1>[,<par2>...] Specify parameters to compare.\n\
116 -arrays=<array1>[,<array2>...] Specify arrays to compare.\n\
117 -tolerance=<value> Set absolute tolerance for numerical comparisons.\n\
118 -relativeTolerance=<value> Set relative tolerance using min(abs(value1), abs(value2))*value.\n\
119 -precision=<integer> Set precision for floating-point comparisons.\n\
120 -format=float=<string> Set print format for float data.\n\
121 -format=double=<string> Set print format for double data.\n\
122 -format=longdouble=<string> Set print format for long double data.\n\
123 -format=string=<string> Set print format for string data.\n\
124 -exact Compare values exactly.\n\
125 -absolute Compare absolute values, ignoring signs.\n\
126 -rowlabel=<column-name>[,nocomparison] Use a column to label rows.\n\
127 -ignoreUnits Do not compare units of items.\n";
131 sddsdiff compares two SDDS files by checking their definitions and data. It reports differences in columns,\n\
132 parameters, and arrays based on the specified options.\n\
135 sddsdiff data1.sdds data2.sdds -compareCommon=column -tolerance=1e-5 -absolute\n\
137Program by Hairong Shang. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
139#define SDDS_COLUMN_TYPE 0
140#define SDDS_PARAMETER_TYPE 1
141#define SDDS_ARRAY_TYPE 2
143long CompareDefinitions(
SDDS_DATASET *dataset1,
SDDS_DATASET *dataset2,
char *file1,
char *file2, int32_t *names,
char ***name, int32_t **dataType,
long type,
long compareCommon,
char *rowLabelColumn,
long notCompareRowLabel,
short ignoreUnits);
144long CompareData(
SDDS_DATASET *dataset1,
SDDS_DATASET *dataset2,
char *file1,
char *file2,
long names,
char **name, int32_t *dataType,
long type,
long page,
long double tolerance,
long double relativeTolerance,
long double precisionTolerance,
char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
char *stringFormat,
145 long absolute,
void *rowLabel,
long rowLabelType,
char *labelName);
146long compare_two_data(
void *data1,
void *data2,
long index,
long datatype,
long first,
long flags,
char *name,
long page,
long double tolerance,
long double relativeTolerance,
long double precisionTolerance,
char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
char *stringFormat,
char *longFormat,
char *ulongFormat,
147 char *shortFormat,
char *ushortFormat,
char *charFormat,
long absolute,
long parameter,
char *labelName);
148void printTitle(
long flags,
char *name,
long page,
long absolute,
char *labelName);
150#define COMPARE_COMMON_COLUMN 0x0001U
151#define COMPARE_COMMON_PARAMETER 0x0002U
152#define COMPARE_COMMON_ARRAY 0x0004U
154int main(
int argc,
char **argv) {
158 long different = 0, i, pages1, pages2, pagediff = 0, i_arg, absolute = 0;
159 int32_t *columnDataType, *parDataType, *arrayDataType;
160 int32_t columns, parameters, arrays, columnMatches, parameterMatches, arrayMatches;
161 int64_t rows1, rows2;
162 char **columnName, **parameterName, **arrayName, **columnMatch, **parameterMatch, **arrayMatch;
163 long column_provided, parameter_provided, array_provided, precision, labelFromSecondFile = 0, rowLabelType = 0, rowLabelIndex = -1, notCompareRowLabel = 0;
164 long double tolerance = 0.0L, relativeTolerance = 0.0L, precisionTolerance = 0.0L;
165 unsigned long compareCommonFlags = 0, dummyFlags = 0;
166 char *floatFormat, *doubleFormat, *ldoubleFormat, *stringFormat, *rowLabelColumn;
168 short ignoreUnits = 0;
170 rowLabelColumn = NULL;
172 floatFormat = doubleFormat = ldoubleFormat = stringFormat = NULL;
174 columnDataType = parDataType = arrayDataType = NULL;
175 columnName = parameterName = arrayName = NULL;
176 columnMatch = parameterMatch = arrayMatch = NULL;
177 columnMatches = parameterMatches = arrayMatches = 0;
178 columns = parameters = arrays = 0;
179 file1 = file2 = NULL;
181 column_provided = parameter_provided = array_provided = 0;
183 argc =
scanargs(&s_arg, argc, argv);
185 fprintf(stderr,
"%s%s", USAGE1, USAGE2);
188 for (i_arg = 1; i_arg < argc; i_arg++) {
189 if (s_arg[i_arg].arg_type == OPTION) {
191 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
193 if (s_arg[i_arg].n_items < 2)
195 rowLabelColumn = s_arg[i_arg].list[1];
196 if (s_arg[i_arg].n_items > 2 &&
198 notCompareRowLabel = 1;
207 if (s_arg[i_arg].n_items != 2)
210 SDDS_Bomb(
"Invalid -tolerance syntax (not a number given)");
212 case CLO_RELATIVE_TOLERANCE:
213 if (s_arg[i_arg].n_items != 2)
214 SDDS_Bomb(
"Invalid -relativeTolerance syntax");
216 SDDS_Bomb(
"Invalid -relativeTolerance syntax (not a number given)");
219 if (s_arg[i_arg].n_items != 2)
221 if (!
get_long(&precision, s_arg[i_arg].list[1]))
222 SDDS_Bomb(
"Invalid -precision syntax (not a number given)");
227 if (s_arg[i_arg].n_items < 2)
229 s_arg[i_arg].n_items--;
230 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
236 s_arg[i_arg].n_items++;
238 fprintf(stderr,
"Error: Given print format (\"%s\") for float data is invalid.\n", floatFormat);
242 fprintf(stderr,
"Error: Given print format (\"%s\") for double data is invalid.\n", doubleFormat);
246 fprintf(stderr,
"Error: Given print format (\"%s\") for long double data is invalid.\n", ldoubleFormat);
250 fprintf(stderr,
"Error: Given print format (\"%s\") for string data is invalid.\n", stringFormat);
254 case CLO_COMPARECOMMON:
255 if (s_arg[i_arg].n_items == 1)
256 compareCommonFlags |= COMPARE_COMMON_COLUMN | COMPARE_COMMON_PARAMETER | COMPARE_COMMON_ARRAY;
258 s_arg[i_arg].n_items--;
259 if (!
scanItemList(&compareCommonFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
260 "column", -1, NULL, 0, COMPARE_COMMON_COLUMN,
261 "parameter", -1, NULL, 0, COMPARE_COMMON_PARAMETER,
262 "array", -1, NULL, 0, COMPARE_COMMON_ARRAY, NULL))
263 SDDS_Bomb(
"Invalid -compareCommon syntax");
264 s_arg[i_arg].n_items++;
268 if (s_arg[i_arg].n_items < 2)
270 columnMatch =
tmalloc(
sizeof(*columnMatch) * (columnMatches = s_arg[i_arg].n_items - 1));
271 for (i = 0; i < columnMatches; i++)
272 columnMatch[i] = s_arg[i_arg].list[i + 1];
276 if (s_arg[i_arg].n_items < 2)
278 parameterMatch =
tmalloc(
sizeof(*parameterMatch) * (parameterMatches = s_arg[i_arg].n_items - 1));
279 for (i = 0; i < parameterMatches; i++)
280 parameterMatch[i] = s_arg[i_arg].list[i + 1];
281 parameter_provided = 1;
284 if (s_arg[i_arg].n_items < 2)
286 arrayMatch =
tmalloc(
sizeof(*arrayMatch) * (arrayMatches = s_arg[i_arg].n_items - 1));
287 for (i = 0; i < arrayMatches; i++)
288 arrayMatch[i] = s_arg[i_arg].list[i + 1];
291 case CLO_IGNORE_UNITS:
295 fprintf(stderr,
"Unknown option given (sddsdiff): %s\n", s_arg[i_arg].list[0]);
301 file1 = s_arg[i_arg].list[0];
303 file2 = s_arg[i_arg].list[0];
317 if ((tolerance || relativeTolerance) && precision > 0) {
318 SDDS_Bomb(
"Tolerance, relativeTolerance, and precision options are not compatible. Only one of tolerance, relativeTolerance, precision, or exact may be given.");
320 if (tolerance && relativeTolerance) {
321 SDDS_Bomb(
"Tolerance and relativeTolerance options are not compatible. Only one may be given.");
323 if (!file1 || !file2) {
324 fprintf(stderr,
"Error: Two files must be provided for comparison.\n");
327 if (strcmp(file1, file2) == 0) {
328 printf(
"\"%s\" and \"%s\" are identical.\n", file1, file2);
339 if (rowLabelColumn) {
342 fprintf(stdout,
"Warning: Row label column \"%s\" does not exist in the input files. The number of rows will be labeled instead.\n", rowLabelColumn);
343 rowLabelColumn = NULL;
345 labelFromSecondFile = 1;
346 notCompareRowLabel = 1;
350 notCompareRowLabel = 1;
353 if (rowLabelColumn) {
354 if (labelFromSecondFile)
361 precisionTolerance = powl(10L, -1L * fabsl(log10l(LDBL_EPSILON)));
363 precisionTolerance = powl(10L, -1L * precision);
365 if (column_provided) {
366 columnName =
getMatchingSDDSNames(&table1, columnMatch, columnMatches, &columns, SDDS_MATCH_COLUMN);
367 if (CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits))
370 if (parameter_provided) {
371 parameterName =
getMatchingSDDSNames(&table1, parameterMatch, parameterMatches, ¶meters, SDDS_MATCH_PARAMETER);
373 if (CompareDefinitions(&table1, &table2, file1, file2, ¶meters, ¶meterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits))
376 if (array_provided) {
378 if (CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits))
381 if (!columns && !parameters && !arrays) {
382 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_COLUMN)
383 different += CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits);
384 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_PARAMETER)
385 different += CompareDefinitions(&table1, &table2, file1, file2, ¶meters, ¶meterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits);
386 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_ARRAY)
387 different += CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits);
390 if (!columns && !parameters && !arrays) {
391 fprintf(stderr,
"There are no common columns, parameters, or arrays in the two files.\n");
399 if (pages1 > 0 && pages2 > 0) {
403 if (rows1 != rows2) {
406 fprintf(stderr,
"The two files have different numbers of rows on page %ld: \"%s\" has %" PRId64
" rows, while \"%s\" has %" PRId64
" rows.\n",
407 pages1, file1, rows1, file2, rows2);
411 pagediff += CompareData(&table1, &table2, file1, file2, parameters, parameterName, parDataType, SDDS_PARAMETER_TYPE, pages1, tolerance, relativeTolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
413 if (columns && rows1) {
414 if (rowLabelColumn) {
415 if (labelFromSecondFile) {
423 pagediff += CompareData(&table1, &table2, file1, file2, columns, columnName, columnDataType, SDDS_COLUMN_TYPE, pages1, tolerance, relativeTolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, rowLabel, rowLabelType, rowLabelColumn);
424 if (rowLabelColumn) {
433 pagediff += CompareData(&table1, &table2, file1, file2, arrays, arrayName, arrayDataType, SDDS_ARRAY_TYPE, pages1, tolerance, relativeTolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
434 different += pagediff;
436 }
else if (pages1 > 0 && pages2 <= 0) {
437 fprintf(stderr,
"\"%s\" has fewer pages than \"%s\".\n", file2, file1);
440 }
else if (pages1 < 0 && pages2 > 0) {
442 fprintf(stderr,
"\"%s\" has fewer pages than \"%s\".\n", file1, file2);
453 printf(
"\"%s\" and \"%s\" are identical.\n", file1, file2);
455 fprintf(stderr,
"\"%s\" and \"%s\" are different.\n", file1, file2);
458 for (i = 0; i < columns; i++)
461 free(columnDataType);
465 for (i = 0; i < parameters; i++)
466 free(parameterName[i]);
469 free(parameterMatch);
472 for (i = 0; i < arrays; i++)
491long CompareDefinitions(
SDDS_DATASET *dataset1,
SDDS_DATASET *dataset2,
char *file1,
char *file2, int32_t *names,
char ***name, int32_t **dataType,
long type,
long compareCommon,
char *rowLabelColumn,
long notCompareRowLabel,
short ignoreUnits) {
493 long sames, free_same_name = 0;
494 int32_t *same, *datatype;
495 int32_t names1, names2;
496 char **name1, **name2, *def, **same_name;
497 long type1, type2, i, returnValue = 0, first = 1;
498 int32_t index1, index2;
499 char *units1, *units2;
500 units1 = units2 = NULL;
501 name1 = name2 = same_name = NULL;
505 same = datatype = NULL;
510 case SDDS_COLUMN_TYPE:
515 case SDDS_PARAMETER_TYPE:
520 case SDDS_ARRAY_TYPE:
526 fprintf(stderr,
"Unknown type given for CompareDefinitions().\n");
529 if (names1 == 0 && names2 == 0)
532 if (!names1 || !names2) {
533 fprintf(stderr,
"Error: One of the files does not have any %s.\n", def);
537 for (i = 0; i < *names; i++) {
538 if (rowLabelColumn && notCompareRowLabel && strcmp((*name)[i], rowLabelColumn) == 0)
540 if (-1 ==
match_string((*name)[i], name1, names1, EXACT_MATCH)) {
541 fprintf(stderr,
"Error: File \"%s\" does not have %s \"%s\".\n", file1, def, (*name)[i]);
545 if (-1 ==
match_string((*name)[i], name2, names2, EXACT_MATCH)) {
546 fprintf(stderr,
"Error: File \"%s\" does not have %s \"%s\".\n", file2, def, (*name)[i]);
553 for (i = 0; i < names1; i++)
556 for (i = 0; i < names2; i++)
566 if (!names1 && !names2) {
570 if (compareCommon && (!names1 || !names2)) {
572 for (i = 0; i < names1; i++)
577 for (i = 0; i < names2; i++)
584 if (names1 != names2 && !compareCommon && !notCompareRowLabel)
587 fprintf(stderr,
"Error: Two files have different numbers of %ss:\n \"%s\" has %" PRId32
" %ss while \"%s\" has %" PRId32
" %ss.\n", def, file1, names1, def, file2, names2, def);
588 for (i = 0; i < names2; i++)
591 for (i = 0; i < names1; i++)
598 for (i = 0; i < names1; i++) {
599 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name1[i]) == 0)
601 if (-1 ==
match_string(name1[i], name2, names2, EXACT_MATCH)) {
602 if (!compareCommon) {
604 fprintf(stderr,
" Following %ss of \"%s\" are not in \"%s\":\n", def, file1, file2);
607 fprintf(stderr,
" %s\n", name1[i]);
611 same_name = (
char **)
SDDS_Realloc(same_name,
sizeof(*same_name) * (same_items + 1));
612 same_name[same_items] = name1[i];
616 if (!compareCommon) {
618 fprintf(stderr,
"\n");
620 for (i = 0; i < names2; i++) {
621 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name2[i]) == 0)
623 if (-1 ==
match_string(name2[i], name1, names1, EXACT_MATCH)) {
625 fprintf(stderr,
" Following %ss of \"%s\" are not in \"%s\":\n", def, file2, file1);
628 fprintf(stderr,
" %s\n", name2[i]);
633 fprintf(stderr,
"\n");
640 datatype = (int32_t *)malloc(
sizeof(*datatype) * same_items);
641 same = (int32_t *)malloc(
sizeof(*same) * same_items);
643 for (i = 0; i < same_items; i++) {
646 case SDDS_COLUMN_TYPE:
664 case SDDS_PARAMETER_TYPE:
671 SDDS_SetError(
"Units field of parameter has wrong data type!");
676 SDDS_SetError(
"Units field of parameter has wrong data type!");
682 case SDDS_ARRAY_TYPE:
702 if (type1 != type2) {
703 if (first && !compareCommon) {
704 fprintf(stderr,
"The type of the following %ss do not match in the two files:\n", def);
705 fprintf(stderr,
"%20s\t%20s\t%20s\n",
"Name", file1, file2);
708 if (!compareCommon) {
714 }
else if ((units1 && units2 && strcasecmp(units1, units2) != 0) || (units1 && !units2) || (!units1 && units2)) {
715 if (first && !compareCommon) {
716 fprintf(stderr,
"The units of the following %ss do not match in the two files:\n", def);
717 fprintf(stderr,
"%20s\t%20s\t%20s\n",
"Name", file1, file2);
720 if (!compareCommon) {
721 if (units1 && units2)
722 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i], units1, units2);
724 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i], units1,
" ");
726 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i],
" ", units2);
734 units1 = units2 = NULL;
735 if (returnValue && !compareCommon)
738 if (!compareCommon && returnValue) {
744 for (i = 0; i < same_items; i++) {
746 *name = (
char **)
SDDS_Realloc(*name,
sizeof(**name) * (*names + 1));
747 *dataType = (int32_t *)
SDDS_Realloc(*dataType,
sizeof(**dataType) * (*names + 1));
749 (*dataType)[*names] = datatype[i];
755 *dataType = datatype;
758 for (i = 0; i < names2; i++)
761 for (i = 0; i < names1; i++)
769 return compareCommon ? 0 : returnValue;
773 long names,
char **name, int32_t *dataType,
long type,
long page,
long double tolerance,
774 long double relativeTolerance,
long double precisionTolerance,
char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
775 char *stringFormat,
long absolute,
void *rowLabel,
long rowLabelType,
char *rowLabelColumn) {
776 long diff = 0, i, first = 1;
778 char fFormat[2048], dFormat[2048], ldFormat[2048], strFormat[2048], lFormat[2048], ulFormat[2048], ushortFormat[2048], shortFormat[2048], cFormat[2048], labelFormat[1024];
782 array1 = array2 = NULL;
783 data1 = data2 = NULL;
786 snprintf(fFormat,
sizeof(fFormat),
"%%20ld%s%s%s\n", floatFormat, floatFormat, floatFormat);
787 snprintf(dFormat,
sizeof(dFormat),
"%%20ld%s%s%s\n", doubleFormat, doubleFormat, doubleFormat);
788 snprintf(ldFormat,
sizeof(ldFormat),
"%%20ld%s%s%s\n", ldoubleFormat, ldoubleFormat, ldoubleFormat);
789 snprintf(strFormat,
sizeof(strFormat),
"%%20ld%s%s%%25ld\n", stringFormat, stringFormat);
790 snprintf(lFormat,
sizeof(lFormat),
"%s",
"%20ld%25ld%25ld\n");
791 snprintf(ulFormat,
sizeof(ulFormat),
"%s",
"%20ld%25lu%25lu%25ld\n");
792 snprintf(shortFormat,
sizeof(shortFormat),
"%s",
"%20ld%25hd%25hd%25hd\n");
793 snprintf(ushortFormat,
sizeof(ushortFormat),
"%s",
"%20ld%25hu%25hu%25hd\n");
794 snprintf(cFormat,
sizeof(cFormat),
"%s",
"%20ld%25c%25c%25d\n");
797 case SDDS_COLUMN_TYPE:
801 for (i = 0; i < names; i++) {
807 for (j = 0; j < rows; j++) {
809 switch (rowLabelType) {
811 snprintf(labelFormat,
sizeof(labelFormat),
"%20s", ((
char **)rowLabel)[j]);
814 snprintf(labelFormat,
sizeof(labelFormat),
"%20.15Le", ((
long double *)rowLabel)[j]);
817 snprintf(labelFormat,
sizeof(labelFormat),
"%20.10e", ((
double *)rowLabel)[j]);
820 snprintf(labelFormat,
sizeof(labelFormat),
"%20.5e", ((
float *)rowLabel)[j]);
823 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRIu64, ((uint64_t *)rowLabel)[j]);
826 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRId64, ((int64_t *)rowLabel)[j]);
829 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRIu32, ((uint32_t *)rowLabel)[j]);
832 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRId32, ((int32_t *)rowLabel)[j]);
835 snprintf(labelFormat,
sizeof(labelFormat),
"%20hu", ((
unsigned short *)rowLabel)[j]);
838 snprintf(labelFormat,
sizeof(labelFormat),
"%20hd", ((
short *)rowLabel)[j]);
841 snprintf(labelFormat,
sizeof(labelFormat),
"%20c", ((
char *)rowLabel)[j]);
844 fprintf(stderr,
"Unknown data type for rowlabel.\n");
847 snprintf(fFormat,
sizeof(fFormat),
"%s%s%s%s\n", labelFormat, floatFormat, floatFormat, floatFormat);
848 snprintf(dFormat,
sizeof(dFormat),
"%s%s%s%s\n", labelFormat, doubleFormat, doubleFormat, doubleFormat);
849 snprintf(ldFormat,
sizeof(ldFormat),
"%s%s%s%s\n", labelFormat, ldoubleFormat, ldoubleFormat, ldoubleFormat);
850 snprintf(strFormat,
sizeof(strFormat),
"%s%s%s%%25ld\n", labelFormat, stringFormat, stringFormat);
851 snprintf(lFormat,
sizeof(lFormat),
"%s%%25ld%%25ld%%25ld\n", labelFormat);
852 snprintf(ulFormat,
sizeof(ulFormat),
"%s%%25lu%%25lu%%25ld\n", labelFormat);
853 snprintf(shortFormat,
sizeof(shortFormat),
"%s%%25hd%%25hd%%25hd\n", labelFormat);
854 snprintf(ushortFormat,
sizeof(ushortFormat),
"%s%%25hu%%25hu%%25hd\n", labelFormat);
855 snprintf(cFormat,
sizeof(cFormat),
"%s%%25c%%25c%%25d\n", labelFormat);
857 if (compare_two_data(data1, data2, j, dataType[i], first, SDDS_COLUMN_TYPE, name[i], page, tolerance, relativeTolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, rowLabelColumn) != 0) {
863 free((
char *)((
char **)data1)[j]);
864 free((
char *)((
char **)data2)[j]);
867 free((
char **)data1);
868 free((
char **)data2);
869 data1 = data2 = NULL;
872 case SDDS_PARAMETER_TYPE:
873 for (i = 0; i < names; i++) {
879 if (compare_two_data(data1, data2, 0, dataType[i], first, SDDS_PARAMETER_TYPE, name[i], page, tolerance, relativeTolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 1, NULL) != 0) {
885 free(*((
char **)data1));
886 free(*((
char **)data2));
890 data1 = data2 = NULL;
893 case SDDS_ARRAY_TYPE:
894 for (i = 0; i < names; i++) {
900 if (array1->elements != array2->elements) {
901 fprintf(stderr,
"Array \"%s\" has %" PRId32
" elements in \"%s\", but %" PRId32
" elements in \"%s\".\n", name[i], array1->elements, file1, array2->elements, file2);
904 for (j = 0; j < array1->elements; j++) {
905 if (compare_two_data(array1->data, array2->data, j, dataType[i], first, SDDS_ARRAY_TYPE, name[i], page, tolerance, relativeTolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, NULL) != 0) {
914 array1 = array2 = NULL;
921void printTitle(
long flags,
char *name,
long page,
long absolute,
char *labelName) {
923 char *element = NULL;
926 case SDDS_COLUMN_TYPE:
933 case SDDS_PARAMETER_TYPE:
937 case SDDS_ARRAY_TYPE:
943 fprintf(stdout,
"\nDifferences found in %s \"%s\" on page %ld:\n", type, name, page);
945 fprintf(stdout,
"%20s%25s%25s%25s\n", element,
"Value in file1",
"Value in file2",
"Difference (abs)");
947 fprintf(stdout,
"%20s%25s%25s%25s\n", element,
"Value in file1",
"Value in file2",
"Difference (file1 - file2)");
953long compare_two_data(
void *data1,
void *data2,
long index,
long datatype,
954 long first,
long flags,
char *name,
long page,
955 long double tolerance,
long double relativeTolerance,
long double precisionTolerance,
956 char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
957 char *stringFormat,
char *longFormat,
char *ulongFormat,
958 char *shortFormat,
char *ushortFormat,
char *charFormat,
959 long absolute,
long parameter,
char *labelName) {
961 long double ldval1, ldval2, ldenominator, ldabs1, ldabs2, lddiff;
962 double dval1, dval2, denominator, dabs1, dabs2, ddiff;
963 float fval1, fval2, fabs1, fabs2, fdenominator, fdiff;
964 int32_t lval1, lval2, labs1, labs2, ldiff, uldiff;
965 uint32_t ulval1, ulval2;
966 int64_t llval1, llval2, llabs1, llabs2, lldiff, ulldiff;
967 uint64_t ullval1, ullval2;
968 short sval1, sval2, sabs1, sabs2, sdiff, usdiff;
969 unsigned short usval1, usval2;
971 long returnValue = 0, printIndex;
972 long double tol, scale;
974 printIndex = index + 1;
985 str1 = *((
char **)data1 + index);
986 str2 = *((
char **)data2 + index);
988 if (returnValue != 0) {
990 printTitle(flags, name, page, absolute, labelName);
992 fprintf(stdout, stringFormat, str1, str2, returnValue);
994 fprintf(stdout, stringFormat, printIndex, str1, str2, returnValue);
998 ldval1 = *((
long double *)data1 + index);
999 ldval2 = *((
long double *)data2 + index);
1001 ldabs1 = fabsl(ldval1);
1002 ldabs2 = fabsl(ldval2);
1007 lddiff = ldabs1 - ldabs2;
1008 if ((isnan(ldval1) && !isnan(ldval2)) || (isinf(ldval1) && !isinf(ldval2)))
1010 else if (ldabs1 != ldabs2) {
1011 if (relativeTolerance) {
1012 scale = MIN(fabsl(ldval1), fabsl(ldval2));
1013 if (fabsl(lddiff) > scale * relativeTolerance)
1015 }
else if (tolerance) {
1016 if (fabsl(lddiff) > tol)
1019 if (ldabs1 == 0L || ldabs2 == 0L) {
1020 if (fabsl(ldabs1 - ldabs2) > precisionTolerance)
1023 ldabs1 = fabsl(ldval1);
1024 ldabs2 = fabsl(ldval2);
1025 ldenominator = (ldabs1 < ldabs2) ? ldabs1 : ldabs2;
1026 if (fabsl(ldval1 - ldval2) / ldenominator > precisionTolerance)
1033 printTitle(flags, name, page, absolute, labelName);
1035 fprintf(stdout, ldoubleFormat, ldval1, ldval2, lddiff);
1037 fprintf(stdout, ldoubleFormat, printIndex, ldval1, ldval2, lddiff);
1041 dval1 = *((
double *)data1 + index);
1042 dval2 = *((
double *)data2 + index);
1044 dabs1 = fabs(dval1);
1045 dabs2 = fabs(dval2);
1050 ddiff = dabs1 - dabs2;
1051 if ((isnan(dval1) && !isnan(dval2)) || (isinf(dval1) && !isinf(dval2)))
1053 else if (dabs1 != dabs2) {
1054 if (relativeTolerance) {
1055 scale = MIN(fabs(dval1), fabs(dval2));
1056 if (fabs(ddiff) > scale * relativeTolerance)
1058 }
else if (tolerance) {
1059 if (fabs(ddiff) > tol)
1062 if (dabs1 == 0 || dabs2 == 0) {
1063 if (fabs(dabs1 - dabs2) > precisionTolerance)
1066 dabs1 = fabs(dval1);
1067 dabs2 = fabs(dval2);
1068 denominator = (dabs1 < dabs2) ? dabs1 : dabs2;
1069 if (fabs(dval1 - dval2) / denominator > precisionTolerance)
1076 printTitle(flags, name, page, absolute, labelName);
1078 fprintf(stdout, doubleFormat, dval1, dval2, ddiff);
1080 fprintf(stdout, doubleFormat, printIndex, dval1, dval2, ddiff);
1084 fval1 = *((
float *)data1 + index);
1085 fval2 = *((
float *)data2 + index);
1087 fabs1 = fabs(fval1);
1088 fabs2 = fabs(fval2);
1093 fdiff = fabs1 - fabs2;
1094 if ((isnan(fval1) && !isnan(fval2)) || (isinf(fval1) && !isinf(fval2)))
1096 else if (fabs1 != fabs2) {
1097 if (relativeTolerance) {
1098 scale = MIN(fabs(fval1), fabs(fval2));
1099 if (fabs(fdiff) > scale * relativeTolerance)
1101 }
else if (tolerance) {
1102 if (fabs(fdiff) > tol)
1105 if (fabs1 == 0 || fabs2 == 0) {
1106 if (fabs(fabs1 - fabs2) > precisionTolerance)
1109 fabs1 = fabs(fval1);
1110 fabs2 = fabs(fval2);
1111 fdenominator = (fabs1 < fabs2) ? fabs1 : fabs2;
1112 if (fabs(fval1 - fval2) / fdenominator > precisionTolerance)
1119 printTitle(flags, name, page, absolute, labelName);
1121 fprintf(stdout, floatFormat, fval1, fval2, fdiff);
1123 fprintf(stdout, floatFormat, printIndex, fval1, fval2, fdiff);
1127 ullval1 = *((uint64_t *)data1 + index);
1128 ullval2 = *((uint64_t *)data2 + index);
1129 ulldiff = ullval1 - ullval2;
1130 if (labs(ulldiff) > tol)
1134 printTitle(flags, name, page, absolute, labelName);
1136 fprintf(stdout, ulongFormat, ullval1, ullval2, ulldiff);
1138 fprintf(stdout, ulongFormat, printIndex, ullval1, ullval2, ulldiff);
1142 llval1 = *((int64_t *)data1 + index);
1143 llval2 = *((int64_t *)data2 + index);
1145 llabs1 = labs(llval1);
1146 llabs2 = labs(llval2);
1151 lldiff = llabs1 - llabs2;
1152 if (llabs(lldiff) > tol)
1156 printTitle(flags, name, page, absolute, labelName);
1158 fprintf(stdout, longFormat, llval1, llval2, lldiff);
1160 fprintf(stdout, longFormat, printIndex, llval1, llval2, lldiff);
1164 ulval1 = *((uint32_t *)data1 + index);
1165 ulval2 = *((uint32_t *)data2 + index);
1166 uldiff = ulval1 - ulval2;
1167 if (labs(uldiff) > tol)
1171 printTitle(flags, name, page, absolute, labelName);
1173 fprintf(stdout, ulongFormat, ulval1, ulval2, uldiff);
1175 fprintf(stdout, ulongFormat, printIndex, ulval1, ulval2, uldiff);
1179 lval1 = *((int32_t *)data1 + index);
1180 lval2 = *((int32_t *)data2 + index);
1188 ldiff = labs1 - labs2;
1189 if (labs(ldiff) > tol)
1193 printTitle(flags, name, page, absolute, labelName);
1195 fprintf(stdout, longFormat, lval1, lval2, ldiff);
1197 fprintf(stdout, longFormat, printIndex, lval1, lval2, ldiff);
1201 sval1 = *((
short *)data1 + index);
1202 sval2 = *((
short *)data2 + index);
1210 sdiff = sabs1 - sabs2;
1211 if (abs(sdiff) > tol)
1215 printTitle(flags, name, page, absolute, labelName);
1217 fprintf(stdout, shortFormat, sval1, sval2, sdiff);
1219 fprintf(stdout, shortFormat, printIndex, sval1, sval2, sdiff);
1223 usval1 = *((
unsigned short *)data1 + index);
1224 usval2 = *((
unsigned short *)data2 + index);
1225 usdiff = usval1 - usval2;
1226 if (abs(usdiff) > tol)
1230 printTitle(flags, name, page, absolute, labelName);
1232 fprintf(stdout, ushortFormat, usval1, usval2, usdiff);
1234 fprintf(stdout, ushortFormat, printIndex, usval1, usval2, usdiff);
1238 cval1 = *((
char *)data1 + index);
1239 cval2 = *((
char *)data2 + index);
1240 if (cval1 != cval2) {
1243 printTitle(flags, name, page, absolute, labelName);
1245 fprintf(stdout, charFormat, cval1, cval2, cval1 - cval2);
1247 fprintf(stdout, charFormat, printIndex, cval1, cval2, cval1 - cval2);
1251 fprintf(stderr,
"Unknown data type %ld.\n", datatype);
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
char * SDDS_type_name[SDDS_NUM_TYPES]
Array of supported data type names.
int32_t SDDS_GetArrayInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified array in the SDDS dataset.
int32_t SDDS_GetParameterInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified parameter in the SDDS dataset.
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
void SDDS_FreeArray(SDDS_ARRAY *array)
Frees memory allocated for an SDDS array structure.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
int32_t SDDS_GetParameterType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a parameter in the SDDS dataset by its index.
int32_t SDDS_VerifyPrintfFormat(const char *string, int32_t type)
Verifies that a printf format string is compatible with a specified data type.
int32_t SDDS_GetArrayIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named array in the SDDS dataset.
char ** getMatchingSDDSNames(SDDS_DATASET *dataset, char **matchName, int32_t matches, int32_t *names, short type)
Retrieves an array of matching SDDS entity names based on specified criteria.
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
int32_t SDDS_GetArrayType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of an array in the SDDS dataset by its index.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
char ** SDDS_GetArrayNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all arrays in the SDDS dataset.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
#define SDDS_FLOAT
Identifier for the float data type.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_SHORT
Identifier for the signed short integer data type.
#define SDDS_CHARACTER
Identifier for the character data type.
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Utility functions for SDDS dataset manipulation and string array operations.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
int get_longdouble(long double *dptr, char *s)
Parses a long double value from the given string.
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int strncmp_case_insensitive(char *s1, char *s2, long n)
Compares up to a specified number of characters of two strings in a case-insensitive manner.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
void free_scanargs(SCANNED_ARG **scanned, int argc)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
char * trim_spaces(char *s)
Trims leading and trailing spaces from a string.