60char *option[N_OPTIONS] = {
73char *USAGE1 =
"Usage: sddsdiff <file1> <file2> [options]\n\
75 -compareCommon[=column|parameter|array] Compare only the common items.\n\
76 -columns=<col1>[,<col2>...] Specify columns to compare.\n\
77 -parameters=<par1>[,<par2>...] Specify parameters to compare.\n\
78 -arrays=<array1>[,<array2>...] Specify arrays to compare.\n\
79 -tolerance=<value> Set tolerance for numerical comparisons.\n\
80 -precision=<integer> Set precision for floating-point comparisons.\n\
81 -format=float=<string> Set print format for float data.\n\
82 -format=double=<string> Set print format for double data.\n\
83 -format=longdouble=<string> Set print format for long double data.\n\
84 -format=string=<string> Set print format for string data.\n\
85 -exact Compare values exactly.\n\
86 -absolute Compare absolute values, ignoring signs.\n\
87 -rowlabel=<column-name>[,nocomparison] Use a column to label rows.\n\
88 -ignoreUnits Do not compare units of items.\n";
92 sddsdiff compares two SDDS files by checking their definitions and data. It reports differences in columns,\n\
93 parameters, and arrays based on the specified options.\n\
96 sddsdiff data1.sdds data2.sdds -compareCommon=column -tolerance=1e-5 -absolute\n\
98Program by Hairong Shang. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
100#define SDDS_COLUMN_TYPE 0
101#define SDDS_PARAMETER_TYPE 1
102#define SDDS_ARRAY_TYPE 2
104long 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);
105long 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 precisionTolerance,
char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
char *stringFormat,
106 long absolute,
void *rowLabel,
long rowLabelType,
char *labelName);
107long compare_two_data(
void *data1,
void *data2,
long index,
long datatype,
long first,
long flags,
char *name,
long page,
long double tolerance,
long double precisionTolerance,
char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
char *stringFormat,
char *longFormat,
char *ulongFormat,
108 char *shortFormat,
char *ushortFormat,
char *charFormat,
long absolute,
long parameter,
char *labelName);
109void printTitle(
long flags,
char *name,
long page,
long absolute,
char *labelName);
111#define COMPARE_COMMON_COLUMN 0x0001U
112#define COMPARE_COMMON_PARAMETER 0x0002U
113#define COMPARE_COMMON_ARRAY 0x0004U
115int main(
int argc,
char **argv) {
119 long different = 0, i, pages1, pages2, pagediff = 0, i_arg, absolute = 0;
120 int32_t *columnDataType, *parDataType, *arrayDataType;
121 int32_t columns, parameters, arrays, columnMatches, parameterMatches, arrayMatches;
122 int64_t rows1, rows2;
123 char **columnName, **parameterName, **arrayName, **columnMatch, **parameterMatch, **arrayMatch;
124 long column_provided, parameter_provided, array_provided, precision, labelFromSecondFile = 0, rowLabelType = 0, rowLabelIndex = -1, notCompareRowLabel = 0;
125 long double tolerance = 0.0L, precisionTolerance = 0.0L;
126 unsigned long compareCommonFlags = 0, dummyFlags = 0;
127 char *floatFormat, *doubleFormat, *ldoubleFormat, *stringFormat, *rowLabelColumn;
129 short ignoreUnits = 0;
131 rowLabelColumn = NULL;
133 floatFormat = doubleFormat = ldoubleFormat = stringFormat = NULL;
135 columnDataType = parDataType = arrayDataType = NULL;
136 columnName = parameterName = arrayName = NULL;
137 columnMatch = parameterMatch = arrayMatch = NULL;
138 columnMatches = parameterMatches = arrayMatches = 0;
139 columns = parameters = arrays = 0;
140 file1 = file2 = NULL;
142 column_provided = parameter_provided = array_provided = 0;
144 argc =
scanargs(&s_arg, argc, argv);
146 fprintf(stderr,
"%s%s", USAGE1, USAGE2);
149 for (i_arg = 1; i_arg < argc; i_arg++) {
150 if (s_arg[i_arg].arg_type == OPTION) {
152 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
154 if (s_arg[i_arg].n_items < 2)
156 rowLabelColumn = s_arg[i_arg].list[1];
157 if (s_arg[i_arg].n_items > 2 &&
159 notCompareRowLabel = 1;
168 if (s_arg[i_arg].n_items != 2)
171 SDDS_Bomb(
"Invalid -tolerance syntax (not a number given)");
174 if (s_arg[i_arg].n_items != 2)
176 if (!
get_long(&precision, s_arg[i_arg].list[1]))
177 SDDS_Bomb(
"Invalid -precision syntax (not a number given)");
182 if (s_arg[i_arg].n_items < 2)
184 s_arg[i_arg].n_items--;
185 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
191 s_arg[i_arg].n_items++;
193 fprintf(stderr,
"Error: Given print format (\"%s\") for float data is invalid.\n", floatFormat);
197 fprintf(stderr,
"Error: Given print format (\"%s\") for double data is invalid.\n", doubleFormat);
201 fprintf(stderr,
"Error: Given print format (\"%s\") for long double data is invalid.\n", ldoubleFormat);
205 fprintf(stderr,
"Error: Given print format (\"%s\") for string data is invalid.\n", stringFormat);
209 case CLO_COMPARECOMMON:
210 if (s_arg[i_arg].n_items == 1)
211 compareCommonFlags |= COMPARE_COMMON_COLUMN | COMPARE_COMMON_PARAMETER | COMPARE_COMMON_ARRAY;
213 s_arg[i_arg].n_items--;
214 if (!
scanItemList(&compareCommonFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
215 "column", -1, NULL, 0, COMPARE_COMMON_COLUMN,
216 "parameter", -1, NULL, 0, COMPARE_COMMON_PARAMETER,
217 "array", -1, NULL, 0, COMPARE_COMMON_ARRAY, NULL))
218 SDDS_Bomb(
"Invalid -compareCommon syntax");
219 s_arg[i_arg].n_items++;
223 if (s_arg[i_arg].n_items < 2)
225 columnMatch =
tmalloc(
sizeof(*columnMatch) * (columnMatches = s_arg[i_arg].n_items - 1));
226 for (i = 0; i < columnMatches; i++)
227 columnMatch[i] = s_arg[i_arg].list[i + 1];
231 if (s_arg[i_arg].n_items < 2)
233 parameterMatch =
tmalloc(
sizeof(*parameterMatch) * (parameterMatches = s_arg[i_arg].n_items - 1));
234 for (i = 0; i < parameterMatches; i++)
235 parameterMatch[i] = s_arg[i_arg].list[i + 1];
236 parameter_provided = 1;
239 if (s_arg[i_arg].n_items < 2)
241 arrayMatch =
tmalloc(
sizeof(*arrayMatch) * (arrayMatches = s_arg[i_arg].n_items - 1));
242 for (i = 0; i < arrayMatches; i++)
243 arrayMatch[i] = s_arg[i_arg].list[i + 1];
246 case CLO_IGNORE_UNITS:
250 fprintf(stderr,
"Unknown option given (sddsdiff): %s\n", s_arg[i_arg].list[0]);
256 file1 = s_arg[i_arg].list[0];
258 file2 = s_arg[i_arg].list[0];
272 if (tolerance && precision > 0) {
273 SDDS_Bomb(
"Tolerance and precision options are not compatible. Only one of tolerance, precision, or exact may be given.");
275 if (!file1 || !file2) {
276 fprintf(stderr,
"Error: Two files must be provided for comparison.\n");
279 if (strcmp(file1, file2) == 0) {
280 printf(
"\"%s\" and \"%s\" are identical.\n", file1, file2);
291 if (rowLabelColumn) {
294 fprintf(stdout,
"Warning: Row label column \"%s\" does not exist in the input files. The number of rows will be labeled instead.\n", rowLabelColumn);
295 rowLabelColumn = NULL;
297 labelFromSecondFile = 1;
298 notCompareRowLabel = 1;
302 notCompareRowLabel = 1;
305 if (rowLabelColumn) {
306 if (labelFromSecondFile)
313 precisionTolerance = powl(10L, -1L * fabsl(log10l(LDBL_EPSILON)));
315 precisionTolerance = powl(10L, -1L * precision);
317 if (column_provided) {
318 columnName =
getMatchingSDDSNames(&table1, columnMatch, columnMatches, &columns, SDDS_MATCH_COLUMN);
319 if (CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits))
322 if (parameter_provided) {
323 parameterName =
getMatchingSDDSNames(&table1, parameterMatch, parameterMatches, ¶meters, SDDS_MATCH_PARAMETER);
325 if (CompareDefinitions(&table1, &table2, file1, file2, ¶meters, ¶meterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits))
328 if (array_provided) {
330 if (CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits))
333 if (!columns && !parameters && !arrays) {
334 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_COLUMN)
335 different += CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits);
336 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_PARAMETER)
337 different += CompareDefinitions(&table1, &table2, file1, file2, ¶meters, ¶meterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits);
338 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_ARRAY)
339 different += CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits);
342 if (!columns && !parameters && !arrays) {
343 fprintf(stderr,
"There are no common columns, parameters, or arrays in the two files.\n");
351 if (pages1 > 0 && pages2 > 0) {
355 if (rows1 != rows2) {
358 fprintf(stderr,
"The two files have different numbers of rows on page %ld: \"%s\" has %" PRId64
" rows, while \"%s\" has %" PRId64
" rows.\n",
359 pages1, file1, rows1, file2, rows2);
363 pagediff += CompareData(&table1, &table2, file1, file2, parameters, parameterName, parDataType, SDDS_PARAMETER_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
364 if (columns && rows1) {
365 if (rowLabelColumn) {
366 if (labelFromSecondFile) {
374 pagediff += CompareData(&table1, &table2, file1, file2, columns, columnName, columnDataType, SDDS_COLUMN_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, rowLabel, rowLabelType, rowLabelColumn);
375 if (rowLabelColumn) {
384 pagediff += CompareData(&table1, &table2, file1, file2, arrays, arrayName, arrayDataType, SDDS_ARRAY_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
385 different += pagediff;
387 }
else if (pages1 > 0 && pages2 <= 0) {
388 fprintf(stderr,
"\"%s\" has fewer pages than \"%s\".\n", file2, file1);
391 }
else if (pages1 < 0 && pages2 > 0) {
393 fprintf(stderr,
"\"%s\" has fewer pages than \"%s\".\n", file1, file2);
404 printf(
"\"%s\" and \"%s\" are identical.\n", file1, file2);
406 fprintf(stderr,
"\"%s\" and \"%s\" are different.\n", file1, file2);
409 for (i = 0; i < columns; i++)
412 free(columnDataType);
416 for (i = 0; i < parameters; i++)
417 free(parameterName[i]);
420 free(parameterMatch);
423 for (i = 0; i < arrays; i++)
442long 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) {
444 long sames, free_same_name = 0;
445 int32_t *same, *datatype;
446 int32_t names1, names2;
447 char **name1, **name2, *def, **same_name;
448 long type1, type2, i, returnValue = 0, first = 1;
449 int32_t index1, index2;
450 char *units1, *units2;
451 units1 = units2 = NULL;
452 name1 = name2 = same_name = NULL;
456 same = datatype = NULL;
461 case SDDS_COLUMN_TYPE:
466 case SDDS_PARAMETER_TYPE:
471 case SDDS_ARRAY_TYPE:
477 fprintf(stderr,
"Unknown type given for CompareDefinitions().\n");
480 if (names1 == 0 && names2 == 0)
483 if (!names1 || !names2) {
484 fprintf(stderr,
"Error: One of the files does not have any %s.\n", def);
488 for (i = 0; i < *names; i++) {
489 if (rowLabelColumn && notCompareRowLabel && strcmp((*name)[i], rowLabelColumn) == 0)
491 if (-1 ==
match_string((*name)[i], name1, names1, EXACT_MATCH)) {
492 fprintf(stderr,
"Error: File \"%s\" does not have %s \"%s\".\n", file1, def, (*name)[i]);
496 if (-1 ==
match_string((*name)[i], name2, names2, EXACT_MATCH)) {
497 fprintf(stderr,
"Error: File \"%s\" does not have %s \"%s\".\n", file2, def, (*name)[i]);
504 for (i = 0; i < names1; i++)
507 for (i = 0; i < names2; i++)
517 if (!names1 && !names2) {
521 if (compareCommon && (!names1 || !names2)) {
523 for (i = 0; i < names1; i++)
528 for (i = 0; i < names2; i++)
535 if (names1 != names2 && !compareCommon && !notCompareRowLabel)
538 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);
539 for (i = 0; i < names2; i++)
542 for (i = 0; i < names1; i++)
549 for (i = 0; i < names1; i++) {
550 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name1[i]) == 0)
552 if (-1 ==
match_string(name1[i], name2, names2, EXACT_MATCH)) {
553 if (!compareCommon) {
555 fprintf(stderr,
" Following %ss of \"%s\" are not in \"%s\":\n", def, file1, file2);
558 fprintf(stderr,
" %s\n", name1[i]);
562 same_name = (
char **)
SDDS_Realloc(same_name,
sizeof(*same_name) * (same_items + 1));
563 same_name[same_items] = name1[i];
567 if (!compareCommon) {
569 fprintf(stderr,
"\n");
571 for (i = 0; i < names2; i++) {
572 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name2[i]) == 0)
574 if (-1 ==
match_string(name2[i], name1, names1, EXACT_MATCH)) {
576 fprintf(stderr,
" Following %ss of \"%s\" are not in \"%s\":\n", def, file2, file1);
579 fprintf(stderr,
" %s\n", name2[i]);
584 fprintf(stderr,
"\n");
591 datatype = (int32_t *)malloc(
sizeof(*datatype) * same_items);
592 same = (int32_t *)malloc(
sizeof(*same) * same_items);
594 for (i = 0; i < same_items; i++) {
597 case SDDS_COLUMN_TYPE:
615 case SDDS_PARAMETER_TYPE:
622 SDDS_SetError(
"Units field of parameter has wrong data type!");
627 SDDS_SetError(
"Units field of parameter has wrong data type!");
633 case SDDS_ARRAY_TYPE:
653 if (type1 != type2) {
654 if (first && !compareCommon) {
655 fprintf(stderr,
"The type of the following %ss do not match in the two files:\n", def);
656 fprintf(stderr,
"%20s\t%20s\t%20s\n",
"Name", file1, file2);
659 if (!compareCommon) {
665 }
else if ((units1 && units2 && strcasecmp(units1, units2) != 0) || (units1 && !units2) || (!units1 && units2)) {
666 if (first && !compareCommon) {
667 fprintf(stderr,
"The units of the following %ss do not match in the two files:\n", def);
668 fprintf(stderr,
"%20s\t%20s\t%20s\n",
"Name", file1, file2);
671 if (!compareCommon) {
672 if (units1 && units2)
673 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i], units1, units2);
675 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i], units1,
" ");
677 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i],
" ", units2);
685 units1 = units2 = NULL;
686 if (returnValue && !compareCommon)
689 if (!compareCommon && returnValue) {
695 for (i = 0; i < same_items; i++) {
697 *name = (
char **)
SDDS_Realloc(*name,
sizeof(**name) * (*names + 1));
698 *dataType = (int32_t *)
SDDS_Realloc(*dataType,
sizeof(**dataType) * (*names + 1));
700 (*dataType)[*names] = datatype[i];
706 *dataType = datatype;
709 for (i = 0; i < names2; i++)
712 for (i = 0; i < names1; i++)
720 return compareCommon ? 0 : returnValue;
724 long names,
char **name, int32_t *dataType,
long type,
long page,
long double tolerance,
725 long double precisionTolerance,
char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
726 char *stringFormat,
long absolute,
void *rowLabel,
long rowLabelType,
char *rowLabelColumn) {
727 long diff = 0, i, first = 1;
729 char fFormat[2048], dFormat[2048], ldFormat[2048], strFormat[2048], lFormat[2048], ulFormat[2048], ushortFormat[2048], shortFormat[2048], cFormat[2048], labelFormat[1024];
733 array1 = array2 = NULL;
734 data1 = data2 = NULL;
737 snprintf(fFormat,
sizeof(fFormat),
"%%20ld%s%s%s\n", floatFormat, floatFormat, floatFormat);
738 snprintf(dFormat,
sizeof(dFormat),
"%%20ld%s%s%s\n", doubleFormat, doubleFormat, doubleFormat);
739 snprintf(ldFormat,
sizeof(ldFormat),
"%%20ld%s%s%s\n", ldoubleFormat, ldoubleFormat, ldoubleFormat);
740 snprintf(strFormat,
sizeof(strFormat),
"%%20ld%s%s%%25ld\n", stringFormat, stringFormat);
741 snprintf(lFormat,
sizeof(lFormat),
"%s",
"%20ld%25ld%25ld\n");
742 snprintf(ulFormat,
sizeof(ulFormat),
"%s",
"%20ld%25lu%25lu%25ld\n");
743 snprintf(shortFormat,
sizeof(shortFormat),
"%s",
"%20ld%25hd%25hd%25hd\n");
744 snprintf(ushortFormat,
sizeof(ushortFormat),
"%s",
"%20ld%25hu%25hu%25hd\n");
745 snprintf(cFormat,
sizeof(cFormat),
"%s",
"%20ld%25c%25c%25d\n");
748 case SDDS_COLUMN_TYPE:
752 for (i = 0; i < names; i++) {
758 for (j = 0; j < rows; j++) {
760 switch (rowLabelType) {
762 snprintf(labelFormat,
sizeof(labelFormat),
"%20s", ((
char **)rowLabel)[j]);
765 snprintf(labelFormat,
sizeof(labelFormat),
"%20.15Le", ((
long double *)rowLabel)[j]);
768 snprintf(labelFormat,
sizeof(labelFormat),
"%20.10e", ((
double *)rowLabel)[j]);
771 snprintf(labelFormat,
sizeof(labelFormat),
"%20.5e", ((
float *)rowLabel)[j]);
774 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRIu64, ((uint64_t *)rowLabel)[j]);
777 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRId64, ((int64_t *)rowLabel)[j]);
780 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRIu32, ((uint32_t *)rowLabel)[j]);
783 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRId32, ((int32_t *)rowLabel)[j]);
786 snprintf(labelFormat,
sizeof(labelFormat),
"%20hu", ((
unsigned short *)rowLabel)[j]);
789 snprintf(labelFormat,
sizeof(labelFormat),
"%20hd", ((
short *)rowLabel)[j]);
792 snprintf(labelFormat,
sizeof(labelFormat),
"%20c", ((
char *)rowLabel)[j]);
795 fprintf(stderr,
"Unknown data type for rowlabel.\n");
798 snprintf(fFormat,
sizeof(fFormat),
"%s%s%s%s\n", labelFormat, floatFormat, floatFormat, floatFormat);
799 snprintf(dFormat,
sizeof(dFormat),
"%s%s%s%s\n", labelFormat, doubleFormat, doubleFormat, doubleFormat);
800 snprintf(ldFormat,
sizeof(ldFormat),
"%s%s%s%s\n", labelFormat, ldoubleFormat, ldoubleFormat, ldoubleFormat);
801 snprintf(strFormat,
sizeof(strFormat),
"%s%s%s%%25ld\n", labelFormat, stringFormat, stringFormat);
802 snprintf(lFormat,
sizeof(lFormat),
"%s%%25ld%%25ld%%25ld\n", labelFormat);
803 snprintf(ulFormat,
sizeof(ulFormat),
"%s%%25lu%%25lu%%25ld\n", labelFormat);
804 snprintf(shortFormat,
sizeof(shortFormat),
"%s%%25hd%%25hd%%25hd\n", labelFormat);
805 snprintf(ushortFormat,
sizeof(ushortFormat),
"%s%%25hu%%25hu%%25hd\n", labelFormat);
806 snprintf(cFormat,
sizeof(cFormat),
"%s%%25c%%25c%%25d\n", labelFormat);
808 if (compare_two_data(data1, data2, j, dataType[i], first, SDDS_COLUMN_TYPE, name[i], page, tolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, rowLabelColumn) != 0) {
814 free((
char *)((
char **)data1)[j]);
815 free((
char *)((
char **)data2)[j]);
818 free((
char **)data1);
819 free((
char **)data2);
820 data1 = data2 = NULL;
823 case SDDS_PARAMETER_TYPE:
824 for (i = 0; i < names; i++) {
830 if (compare_two_data(data1, data2, 0, dataType[i], first, SDDS_PARAMETER_TYPE, name[i], page, tolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 1, NULL) != 0) {
836 free(*((
char **)data1));
837 free(*((
char **)data2));
841 data1 = data2 = NULL;
844 case SDDS_ARRAY_TYPE:
845 for (i = 0; i < names; i++) {
851 if (array1->elements != array2->elements) {
852 fprintf(stderr,
"Array \"%s\" has %" PRId32
" elements in \"%s\", but %" PRId32
" elements in \"%s\".\n", name[i], array1->elements, file1, array2->elements, file2);
855 for (j = 0; j < array1->elements; j++) {
856 if (compare_two_data(array1->data, array2->data, j, dataType[i], first, SDDS_ARRAY_TYPE, name[i], page, tolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, NULL) != 0) {
865 array1 = array2 = NULL;
872void printTitle(
long flags,
char *name,
long page,
long absolute,
char *labelName) {
874 char *element = NULL;
877 case SDDS_COLUMN_TYPE:
884 case SDDS_PARAMETER_TYPE:
888 case SDDS_ARRAY_TYPE:
894 fprintf(stdout,
"\nDifferences found in %s \"%s\" on page %ld:\n", type, name, page);
896 fprintf(stdout,
"%20s%25s%25s%25s\n", element,
"Value in file1",
"Value in file2",
"Difference (abs)");
898 fprintf(stdout,
"%20s%25s%25s%25s\n", element,
"Value in file1",
"Value in file2",
"Difference (file1 - file2)");
904long compare_two_data(
void *data1,
void *data2,
long index,
long datatype,
905 long first,
long flags,
char *name,
long page,
906 long double tolerance,
long double precisionTolerance,
907 char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
908 char *stringFormat,
char *longFormat,
char *ulongFormat,
909 char *shortFormat,
char *ushortFormat,
char *charFormat,
910 long absolute,
long parameter,
char *labelName) {
912 long double ldval1, ldval2, ldenominator, ldabs1, ldabs2, lddiff;
913 double dval1, dval2, denominator, dabs1, dabs2, ddiff;
914 float fval1, fval2, fabs1, fabs2, fdenominator, fdiff;
915 int32_t lval1, lval2, labs1, labs2, ldiff, uldiff;
916 uint32_t ulval1, ulval2;
917 int64_t llval1, llval2, llabs1, llabs2, lldiff, ulldiff;
918 uint64_t ullval1, ullval2;
919 short sval1, sval2, sabs1, sabs2, sdiff, usdiff;
920 unsigned short usval1, usval2;
922 long returnValue = 0, printIndex;
925 printIndex = index + 1;
936 str1 = *((
char **)data1 + index);
937 str2 = *((
char **)data2 + index);
939 if (returnValue != 0) {
941 printTitle(flags, name, page, absolute, labelName);
943 fprintf(stdout, stringFormat, str1, str2, returnValue);
945 fprintf(stdout, stringFormat, printIndex, str1, str2, returnValue);
949 ldval1 = *((
long double *)data1 + index);
950 ldval2 = *((
long double *)data2 + index);
952 ldabs1 = fabsl(ldval1);
953 ldabs2 = fabsl(ldval2);
958 lddiff = ldabs1 - ldabs2;
959 if ((isnan(ldval1) && !isnan(ldval2)) || (isinf(ldval1) && !isinf(ldval2)))
961 else if (ldabs1 != ldabs2) {
963 if (fabsl(lddiff) > tol)
966 if (ldabs1 == 0L || ldabs2 == 0L) {
967 if (fabsl(ldabs1 - ldabs2) > precisionTolerance)
970 ldabs1 = fabsl(ldval1);
971 ldabs2 = fabsl(ldval2);
972 ldenominator = (ldabs1 < ldabs2) ? ldabs1 : ldabs2;
973 if (fabsl(ldval1 - ldval2) / ldenominator > precisionTolerance)
980 printTitle(flags, name, page, absolute, labelName);
982 fprintf(stdout, ldoubleFormat, ldval1, ldval2, lddiff);
984 fprintf(stdout, ldoubleFormat, printIndex, ldval1, ldval2, lddiff);
988 dval1 = *((
double *)data1 + index);
989 dval2 = *((
double *)data2 + index);
997 ddiff = dabs1 - dabs2;
998 if ((isnan(dval1) && !isnan(dval2)) || (isinf(dval1) && !isinf(dval2)))
1000 else if (dabs1 != dabs2) {
1002 if (fabs(ddiff) > tol)
1005 if (dabs1 == 0 || dabs2 == 0) {
1006 if (fabs(dabs1 - dabs2) > precisionTolerance)
1009 dabs1 = fabs(dval1);
1010 dabs2 = fabs(dval2);
1011 denominator = (dabs1 < dabs2) ? dabs1 : dabs2;
1012 if (fabs(dval1 - dval2) / denominator > precisionTolerance)
1019 printTitle(flags, name, page, absolute, labelName);
1021 fprintf(stdout, doubleFormat, dval1, dval2, ddiff);
1023 fprintf(stdout, doubleFormat, printIndex, dval1, dval2, ddiff);
1027 fval1 = *((
float *)data1 + index);
1028 fval2 = *((
float *)data2 + index);
1030 fabs1 = fabs(fval1);
1031 fabs2 = fabs(fval2);
1036 fdiff = fabs1 - fabs2;
1037 if ((isnan(fval1) && !isnan(fval2)) || (isinf(fval1) && !isinf(fval2)))
1039 else if (fabs1 != fabs2) {
1041 if (fabs(fdiff) > tol)
1044 if (fabs1 == 0 || fabs2 == 0) {
1045 if (fabs(fabs1 - fabs2) > precisionTolerance)
1048 fabs1 = fabs(fval1);
1049 fabs2 = fabs(fval2);
1050 fdenominator = (fabs1 < fabs2) ? fabs1 : fabs2;
1051 if (fabs(fval1 - fval2) / fdenominator > precisionTolerance)
1058 printTitle(flags, name, page, absolute, labelName);
1060 fprintf(stdout, floatFormat, fval1, fval2, fdiff);
1062 fprintf(stdout, floatFormat, printIndex, fval1, fval2, fdiff);
1066 ullval1 = *((uint64_t *)data1 + index);
1067 ullval2 = *((uint64_t *)data2 + index);
1068 ulldiff = ullval1 - ullval2;
1069 if (labs(ulldiff) > tol)
1073 printTitle(flags, name, page, absolute, labelName);
1075 fprintf(stdout, ulongFormat, ullval1, ullval2, ulldiff);
1077 fprintf(stdout, ulongFormat, printIndex, ullval1, ullval2, ulldiff);
1081 llval1 = *((int64_t *)data1 + index);
1082 llval2 = *((int64_t *)data2 + index);
1084 llabs1 = labs(llval1);
1085 llabs2 = labs(llval2);
1090 lldiff = llabs1 - llabs2;
1091 if (llabs(lldiff) > tol)
1095 printTitle(flags, name, page, absolute, labelName);
1097 fprintf(stdout, longFormat, llval1, llval2, lldiff);
1099 fprintf(stdout, longFormat, printIndex, llval1, llval2, lldiff);
1103 ulval1 = *((uint32_t *)data1 + index);
1104 ulval2 = *((uint32_t *)data2 + index);
1105 uldiff = ulval1 - ulval2;
1106 if (labs(uldiff) > tol)
1110 printTitle(flags, name, page, absolute, labelName);
1112 fprintf(stdout, ulongFormat, ulval1, ulval2, uldiff);
1114 fprintf(stdout, ulongFormat, printIndex, ulval1, ulval2, uldiff);
1118 lval1 = *((int32_t *)data1 + index);
1119 lval2 = *((int32_t *)data2 + index);
1127 ldiff = labs1 - labs2;
1128 if (labs(ldiff) > tol)
1132 printTitle(flags, name, page, absolute, labelName);
1134 fprintf(stdout, longFormat, lval1, lval2, ldiff);
1136 fprintf(stdout, longFormat, printIndex, lval1, lval2, ldiff);
1140 sval1 = *((
short *)data1 + index);
1141 sval2 = *((
short *)data2 + index);
1149 sdiff = sabs1 - sabs2;
1150 if (abs(sdiff) > tol)
1154 printTitle(flags, name, page, absolute, labelName);
1156 fprintf(stdout, shortFormat, sval1, sval2, sdiff);
1158 fprintf(stdout, shortFormat, printIndex, sval1, sval2, sdiff);
1162 usval1 = *((
unsigned short *)data1 + index);
1163 usval2 = *((
unsigned short *)data2 + index);
1164 usdiff = usval1 - usval2;
1165 if (abs(usdiff) > tol)
1169 printTitle(flags, name, page, absolute, labelName);
1171 fprintf(stdout, ushortFormat, usval1, usval2, usdiff);
1173 fprintf(stdout, ushortFormat, printIndex, usval1, usval2, usdiff);
1177 cval1 = *((
char *)data1 + index);
1178 cval2 = *((
char *)data2 + index);
1179 if (cval1 != cval2) {
1182 printTitle(flags, name, page, absolute, labelName);
1184 fprintf(stdout, charFormat, cval1, cval2, cval1 - cval2);
1186 fprintf(stdout, charFormat, printIndex, cval1, cval2, cval1 - cval2);
1190 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.
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.