81char *option[N_OPTIONS] = {
94char *USAGE1 =
"Usage: sddsdiff <file1> <file2>\n\
95 [-compareCommon[=column|parameter|array]]\n\
96 [-columns=<col1>[,<col2>...]]\n\
97 [-parameters=<par1][,<par2>...]]\n\
98 [-arrays=<array1>[,<array2>...]]\n\
99 [-tolerance=<value>]\n\
100 [-precision=<integer>]\n\
101 [-format=float=<string>|double=<string>|longdouble=<string>|string=<string>]\n\
104 [-rowlabel=<column-name>[,nocomparison]]\n\
107 -compareCommon[=column|parameter|array] Compare only the common items.\n\
108 -columns=<col1>[,<col2>...] Specify columns to compare.\n\
109 -parameters=<par1>[,<par2>...] Specify parameters to compare.\n\
110 -arrays=<array1>[,<array2>...] Specify arrays to compare.\n\
111 -tolerance=<value> Set tolerance for numerical comparisons.\n\
112 -precision=<integer> Set precision for floating-point comparisons.\n\
113 -format=float=<string> Set print format for float data.\n\
114 -format=double=<string> Set print format for double data.\n\
115 -format=longdouble=<string> Set print format for long double data.\n\
116 -format=string=<string> Set print format for string data.\n\
117 -exact Compare values exactly.\n\
118 -absolute Compare absolute values, ignoring signs.\n\
119 -rowlabel=<column-name>[,nocomparison] Use a column to label rows.\n\
120 -ignoreUnits Do not compare units of items.\n";
124 sddsdiff compares two SDDS files by checking their definitions and data. It reports differences in columns,\n\
125 parameters, and arrays based on the specified options.\n\
128 sddsdiff data1.sdds data2.sdds -compareCommon=column -tolerance=1e-5 -absolute\n\
130Program by Hairong Shang. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
132#define SDDS_COLUMN_TYPE 0
133#define SDDS_PARAMETER_TYPE 1
134#define SDDS_ARRAY_TYPE 2
136long 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);
137long 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,
138 long absolute,
void *rowLabel,
long rowLabelType,
char *labelName);
139long 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,
140 char *shortFormat,
char *ushortFormat,
char *charFormat,
long absolute,
long parameter,
char *labelName);
141void printTitle(
long flags,
char *name,
long page,
long absolute,
char *labelName);
143#define COMPARE_COMMON_COLUMN 0x0001U
144#define COMPARE_COMMON_PARAMETER 0x0002U
145#define COMPARE_COMMON_ARRAY 0x0004U
147int main(
int argc,
char **argv) {
151 long different = 0, i, pages1, pages2, pagediff = 0, i_arg, absolute = 0;
152 int32_t *columnDataType, *parDataType, *arrayDataType;
153 int32_t columns, parameters, arrays, columnMatches, parameterMatches, arrayMatches;
154 int64_t rows1, rows2;
155 char **columnName, **parameterName, **arrayName, **columnMatch, **parameterMatch, **arrayMatch;
156 long column_provided, parameter_provided, array_provided, precision, labelFromSecondFile = 0, rowLabelType = 0, rowLabelIndex = -1, notCompareRowLabel = 0;
157 long double tolerance = 0.0L, precisionTolerance = 0.0L;
158 unsigned long compareCommonFlags = 0, dummyFlags = 0;
159 char *floatFormat, *doubleFormat, *ldoubleFormat, *stringFormat, *rowLabelColumn;
161 short ignoreUnits = 0;
163 rowLabelColumn = NULL;
165 floatFormat = doubleFormat = ldoubleFormat = stringFormat = NULL;
167 columnDataType = parDataType = arrayDataType = NULL;
168 columnName = parameterName = arrayName = NULL;
169 columnMatch = parameterMatch = arrayMatch = NULL;
170 columnMatches = parameterMatches = arrayMatches = 0;
171 columns = parameters = arrays = 0;
172 file1 = file2 = NULL;
174 column_provided = parameter_provided = array_provided = 0;
176 argc =
scanargs(&s_arg, argc, argv);
178 fprintf(stderr,
"%s%s", USAGE1, USAGE2);
181 for (i_arg = 1; i_arg < argc; i_arg++) {
182 if (s_arg[i_arg].arg_type == OPTION) {
184 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
186 if (s_arg[i_arg].n_items < 2)
188 rowLabelColumn = s_arg[i_arg].list[1];
189 if (s_arg[i_arg].n_items > 2 &&
191 notCompareRowLabel = 1;
200 if (s_arg[i_arg].n_items != 2)
203 SDDS_Bomb(
"Invalid -tolerance syntax (not a number given)");
206 if (s_arg[i_arg].n_items != 2)
208 if (!
get_long(&precision, s_arg[i_arg].list[1]))
209 SDDS_Bomb(
"Invalid -precision syntax (not a number given)");
214 if (s_arg[i_arg].n_items < 2)
216 s_arg[i_arg].n_items--;
217 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
223 s_arg[i_arg].n_items++;
225 fprintf(stderr,
"Error: Given print format (\"%s\") for float data is invalid.\n", floatFormat);
229 fprintf(stderr,
"Error: Given print format (\"%s\") for double data is invalid.\n", doubleFormat);
233 fprintf(stderr,
"Error: Given print format (\"%s\") for long double data is invalid.\n", ldoubleFormat);
237 fprintf(stderr,
"Error: Given print format (\"%s\") for string data is invalid.\n", stringFormat);
241 case CLO_COMPARECOMMON:
242 if (s_arg[i_arg].n_items == 1)
243 compareCommonFlags |= COMPARE_COMMON_COLUMN | COMPARE_COMMON_PARAMETER | COMPARE_COMMON_ARRAY;
245 s_arg[i_arg].n_items--;
246 if (!
scanItemList(&compareCommonFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
247 "column", -1, NULL, 0, COMPARE_COMMON_COLUMN,
248 "parameter", -1, NULL, 0, COMPARE_COMMON_PARAMETER,
249 "array", -1, NULL, 0, COMPARE_COMMON_ARRAY, NULL))
250 SDDS_Bomb(
"Invalid -compareCommon syntax");
251 s_arg[i_arg].n_items++;
255 if (s_arg[i_arg].n_items < 2)
257 columnMatch =
tmalloc(
sizeof(*columnMatch) * (columnMatches = s_arg[i_arg].n_items - 1));
258 for (i = 0; i < columnMatches; i++)
259 columnMatch[i] = s_arg[i_arg].list[i + 1];
263 if (s_arg[i_arg].n_items < 2)
265 parameterMatch =
tmalloc(
sizeof(*parameterMatch) * (parameterMatches = s_arg[i_arg].n_items - 1));
266 for (i = 0; i < parameterMatches; i++)
267 parameterMatch[i] = s_arg[i_arg].list[i + 1];
268 parameter_provided = 1;
271 if (s_arg[i_arg].n_items < 2)
273 arrayMatch =
tmalloc(
sizeof(*arrayMatch) * (arrayMatches = s_arg[i_arg].n_items - 1));
274 for (i = 0; i < arrayMatches; i++)
275 arrayMatch[i] = s_arg[i_arg].list[i + 1];
278 case CLO_IGNORE_UNITS:
282 fprintf(stderr,
"Unknown option given (sddsdiff): %s\n", s_arg[i_arg].list[0]);
288 file1 = s_arg[i_arg].list[0];
290 file2 = s_arg[i_arg].list[0];
304 if (tolerance && precision > 0) {
305 SDDS_Bomb(
"Tolerance and precision options are not compatible. Only one of tolerance, precision, or exact may be given.");
307 if (!file1 || !file2) {
308 fprintf(stderr,
"Error: Two files must be provided for comparison.\n");
311 if (strcmp(file1, file2) == 0) {
312 printf(
"\"%s\" and \"%s\" are identical.\n", file1, file2);
323 if (rowLabelColumn) {
326 fprintf(stdout,
"Warning: Row label column \"%s\" does not exist in the input files. The number of rows will be labeled instead.\n", rowLabelColumn);
327 rowLabelColumn = NULL;
329 labelFromSecondFile = 1;
330 notCompareRowLabel = 1;
334 notCompareRowLabel = 1;
337 if (rowLabelColumn) {
338 if (labelFromSecondFile)
345 precisionTolerance = powl(10L, -1L * fabsl(log10l(LDBL_EPSILON)));
347 precisionTolerance = powl(10L, -1L * precision);
349 if (column_provided) {
350 columnName =
getMatchingSDDSNames(&table1, columnMatch, columnMatches, &columns, SDDS_MATCH_COLUMN);
351 if (CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits))
354 if (parameter_provided) {
355 parameterName =
getMatchingSDDSNames(&table1, parameterMatch, parameterMatches, ¶meters, SDDS_MATCH_PARAMETER);
357 if (CompareDefinitions(&table1, &table2, file1, file2, ¶meters, ¶meterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits))
360 if (array_provided) {
362 if (CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits))
365 if (!columns && !parameters && !arrays) {
366 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_COLUMN)
367 different += CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits);
368 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_PARAMETER)
369 different += CompareDefinitions(&table1, &table2, file1, file2, ¶meters, ¶meterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits);
370 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_ARRAY)
371 different += CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits);
374 if (!columns && !parameters && !arrays) {
375 fprintf(stderr,
"There are no common columns, parameters, or arrays in the two files.\n");
383 if (pages1 > 0 && pages2 > 0) {
387 if (rows1 != rows2) {
390 fprintf(stderr,
"The two files have different numbers of rows on page %ld: \"%s\" has %" PRId64
" rows, while \"%s\" has %" PRId64
" rows.\n",
391 pages1, file1, rows1, file2, rows2);
395 pagediff += CompareData(&table1, &table2, file1, file2, parameters, parameterName, parDataType, SDDS_PARAMETER_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
396 if (columns && rows1) {
397 if (rowLabelColumn) {
398 if (labelFromSecondFile) {
406 pagediff += CompareData(&table1, &table2, file1, file2, columns, columnName, columnDataType, SDDS_COLUMN_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, rowLabel, rowLabelType, rowLabelColumn);
407 if (rowLabelColumn) {
416 pagediff += CompareData(&table1, &table2, file1, file2, arrays, arrayName, arrayDataType, SDDS_ARRAY_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
417 different += pagediff;
419 }
else if (pages1 > 0 && pages2 <= 0) {
420 fprintf(stderr,
"\"%s\" has fewer pages than \"%s\".\n", file2, file1);
423 }
else if (pages1 < 0 && pages2 > 0) {
425 fprintf(stderr,
"\"%s\" has fewer pages than \"%s\".\n", file1, file2);
436 printf(
"\"%s\" and \"%s\" are identical.\n", file1, file2);
438 fprintf(stderr,
"\"%s\" and \"%s\" are different.\n", file1, file2);
441 for (i = 0; i < columns; i++)
444 free(columnDataType);
448 for (i = 0; i < parameters; i++)
449 free(parameterName[i]);
452 free(parameterMatch);
455 for (i = 0; i < arrays; i++)
474long 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) {
476 long sames, free_same_name = 0;
477 int32_t *same, *datatype;
478 int32_t names1, names2;
479 char **name1, **name2, *def, **same_name;
480 long type1, type2, i, returnValue = 0, first = 1;
481 int32_t index1, index2;
482 char *units1, *units2;
483 units1 = units2 = NULL;
484 name1 = name2 = same_name = NULL;
488 same = datatype = NULL;
493 case SDDS_COLUMN_TYPE:
498 case SDDS_PARAMETER_TYPE:
503 case SDDS_ARRAY_TYPE:
509 fprintf(stderr,
"Unknown type given for CompareDefinitions().\n");
512 if (names1 == 0 && names2 == 0)
515 if (!names1 || !names2) {
516 fprintf(stderr,
"Error: One of the files does not have any %s.\n", def);
520 for (i = 0; i < *names; i++) {
521 if (rowLabelColumn && notCompareRowLabel && strcmp((*name)[i], rowLabelColumn) == 0)
523 if (-1 ==
match_string((*name)[i], name1, names1, EXACT_MATCH)) {
524 fprintf(stderr,
"Error: File \"%s\" does not have %s \"%s\".\n", file1, def, (*name)[i]);
528 if (-1 ==
match_string((*name)[i], name2, names2, EXACT_MATCH)) {
529 fprintf(stderr,
"Error: File \"%s\" does not have %s \"%s\".\n", file2, def, (*name)[i]);
536 for (i = 0; i < names1; i++)
539 for (i = 0; i < names2; i++)
549 if (!names1 && !names2) {
553 if (compareCommon && (!names1 || !names2)) {
555 for (i = 0; i < names1; i++)
560 for (i = 0; i < names2; i++)
567 if (names1 != names2 && !compareCommon && !notCompareRowLabel)
570 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);
571 for (i = 0; i < names2; i++)
574 for (i = 0; i < names1; i++)
581 for (i = 0; i < names1; i++) {
582 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name1[i]) == 0)
584 if (-1 ==
match_string(name1[i], name2, names2, EXACT_MATCH)) {
585 if (!compareCommon) {
587 fprintf(stderr,
" Following %ss of \"%s\" are not in \"%s\":\n", def, file1, file2);
590 fprintf(stderr,
" %s\n", name1[i]);
594 same_name = (
char **)
SDDS_Realloc(same_name,
sizeof(*same_name) * (same_items + 1));
595 same_name[same_items] = name1[i];
599 if (!compareCommon) {
601 fprintf(stderr,
"\n");
603 for (i = 0; i < names2; i++) {
604 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name2[i]) == 0)
606 if (-1 ==
match_string(name2[i], name1, names1, EXACT_MATCH)) {
608 fprintf(stderr,
" Following %ss of \"%s\" are not in \"%s\":\n", def, file2, file1);
611 fprintf(stderr,
" %s\n", name2[i]);
616 fprintf(stderr,
"\n");
623 datatype = (int32_t *)malloc(
sizeof(*datatype) * same_items);
624 same = (int32_t *)malloc(
sizeof(*same) * same_items);
626 for (i = 0; i < same_items; i++) {
629 case SDDS_COLUMN_TYPE:
647 case SDDS_PARAMETER_TYPE:
654 SDDS_SetError(
"Units field of parameter has wrong data type!");
659 SDDS_SetError(
"Units field of parameter has wrong data type!");
665 case SDDS_ARRAY_TYPE:
685 if (type1 != type2) {
686 if (first && !compareCommon) {
687 fprintf(stderr,
"The type of the following %ss do not match in the two files:\n", def);
688 fprintf(stderr,
"%20s\t%20s\t%20s\n",
"Name", file1, file2);
691 if (!compareCommon) {
697 }
else if ((units1 && units2 && strcasecmp(units1, units2) != 0) || (units1 && !units2) || (!units1 && units2)) {
698 if (first && !compareCommon) {
699 fprintf(stderr,
"The units of the following %ss do not match in the two files:\n", def);
700 fprintf(stderr,
"%20s\t%20s\t%20s\n",
"Name", file1, file2);
703 if (!compareCommon) {
704 if (units1 && units2)
705 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i], units1, units2);
707 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i], units1,
" ");
709 fprintf(stderr,
"%20s\t%20s\t%20s\n", same_name[i],
" ", units2);
717 units1 = units2 = NULL;
718 if (returnValue && !compareCommon)
721 if (!compareCommon && returnValue) {
727 for (i = 0; i < same_items; i++) {
729 *name = (
char **)
SDDS_Realloc(*name,
sizeof(**name) * (*names + 1));
730 *dataType = (int32_t *)
SDDS_Realloc(*dataType,
sizeof(**dataType) * (*names + 1));
732 (*dataType)[*names] = datatype[i];
738 *dataType = datatype;
741 for (i = 0; i < names2; i++)
744 for (i = 0; i < names1; i++)
752 return compareCommon ? 0 : returnValue;
756 long names,
char **name, int32_t *dataType,
long type,
long page,
long double tolerance,
757 long double precisionTolerance,
char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
758 char *stringFormat,
long absolute,
void *rowLabel,
long rowLabelType,
char *rowLabelColumn) {
759 long diff = 0, i, first = 1;
761 char fFormat[2048], dFormat[2048], ldFormat[2048], strFormat[2048], lFormat[2048], ulFormat[2048], ushortFormat[2048], shortFormat[2048], cFormat[2048], labelFormat[1024];
765 array1 = array2 = NULL;
766 data1 = data2 = NULL;
769 snprintf(fFormat,
sizeof(fFormat),
"%%20ld%s%s%s\n", floatFormat, floatFormat, floatFormat);
770 snprintf(dFormat,
sizeof(dFormat),
"%%20ld%s%s%s\n", doubleFormat, doubleFormat, doubleFormat);
771 snprintf(ldFormat,
sizeof(ldFormat),
"%%20ld%s%s%s\n", ldoubleFormat, ldoubleFormat, ldoubleFormat);
772 snprintf(strFormat,
sizeof(strFormat),
"%%20ld%s%s%%25ld\n", stringFormat, stringFormat);
773 snprintf(lFormat,
sizeof(lFormat),
"%s",
"%20ld%25ld%25ld\n");
774 snprintf(ulFormat,
sizeof(ulFormat),
"%s",
"%20ld%25lu%25lu%25ld\n");
775 snprintf(shortFormat,
sizeof(shortFormat),
"%s",
"%20ld%25hd%25hd%25hd\n");
776 snprintf(ushortFormat,
sizeof(ushortFormat),
"%s",
"%20ld%25hu%25hu%25hd\n");
777 snprintf(cFormat,
sizeof(cFormat),
"%s",
"%20ld%25c%25c%25d\n");
780 case SDDS_COLUMN_TYPE:
784 for (i = 0; i < names; i++) {
790 for (j = 0; j < rows; j++) {
792 switch (rowLabelType) {
794 snprintf(labelFormat,
sizeof(labelFormat),
"%20s", ((
char **)rowLabel)[j]);
797 snprintf(labelFormat,
sizeof(labelFormat),
"%20.15Le", ((
long double *)rowLabel)[j]);
800 snprintf(labelFormat,
sizeof(labelFormat),
"%20.10e", ((
double *)rowLabel)[j]);
803 snprintf(labelFormat,
sizeof(labelFormat),
"%20.5e", ((
float *)rowLabel)[j]);
806 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRIu64, ((uint64_t *)rowLabel)[j]);
809 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRId64, ((int64_t *)rowLabel)[j]);
812 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRIu32, ((uint32_t *)rowLabel)[j]);
815 snprintf(labelFormat,
sizeof(labelFormat),
"%20" PRId32, ((int32_t *)rowLabel)[j]);
818 snprintf(labelFormat,
sizeof(labelFormat),
"%20hu", ((
unsigned short *)rowLabel)[j]);
821 snprintf(labelFormat,
sizeof(labelFormat),
"%20hd", ((
short *)rowLabel)[j]);
824 snprintf(labelFormat,
sizeof(labelFormat),
"%20c", ((
char *)rowLabel)[j]);
827 fprintf(stderr,
"Unknown data type for rowlabel.\n");
830 snprintf(fFormat,
sizeof(fFormat),
"%s%s%s%s\n", labelFormat, floatFormat, floatFormat, floatFormat);
831 snprintf(dFormat,
sizeof(dFormat),
"%s%s%s%s\n", labelFormat, doubleFormat, doubleFormat, doubleFormat);
832 snprintf(ldFormat,
sizeof(ldFormat),
"%s%s%s%s\n", labelFormat, ldoubleFormat, ldoubleFormat, ldoubleFormat);
833 snprintf(strFormat,
sizeof(strFormat),
"%s%s%s%%25ld\n", labelFormat, stringFormat, stringFormat);
834 snprintf(lFormat,
sizeof(lFormat),
"%s%%25ld%%25ld%%25ld\n", labelFormat);
835 snprintf(ulFormat,
sizeof(ulFormat),
"%s%%25lu%%25lu%%25ld\n", labelFormat);
836 snprintf(shortFormat,
sizeof(shortFormat),
"%s%%25hd%%25hd%%25hd\n", labelFormat);
837 snprintf(ushortFormat,
sizeof(ushortFormat),
"%s%%25hu%%25hu%%25hd\n", labelFormat);
838 snprintf(cFormat,
sizeof(cFormat),
"%s%%25c%%25c%%25d\n", labelFormat);
840 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) {
846 free((
char *)((
char **)data1)[j]);
847 free((
char *)((
char **)data2)[j]);
850 free((
char **)data1);
851 free((
char **)data2);
852 data1 = data2 = NULL;
855 case SDDS_PARAMETER_TYPE:
856 for (i = 0; i < names; i++) {
862 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) {
868 free(*((
char **)data1));
869 free(*((
char **)data2));
873 data1 = data2 = NULL;
876 case SDDS_ARRAY_TYPE:
877 for (i = 0; i < names; i++) {
883 if (array1->elements != array2->elements) {
884 fprintf(stderr,
"Array \"%s\" has %" PRId32
" elements in \"%s\", but %" PRId32
" elements in \"%s\".\n", name[i], array1->elements, file1, array2->elements, file2);
887 for (j = 0; j < array1->elements; j++) {
888 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) {
897 array1 = array2 = NULL;
904void printTitle(
long flags,
char *name,
long page,
long absolute,
char *labelName) {
906 char *element = NULL;
909 case SDDS_COLUMN_TYPE:
916 case SDDS_PARAMETER_TYPE:
920 case SDDS_ARRAY_TYPE:
926 fprintf(stdout,
"\nDifferences found in %s \"%s\" on page %ld:\n", type, name, page);
928 fprintf(stdout,
"%20s%25s%25s%25s\n", element,
"Value in file1",
"Value in file2",
"Difference (abs)");
930 fprintf(stdout,
"%20s%25s%25s%25s\n", element,
"Value in file1",
"Value in file2",
"Difference (file1 - file2)");
936long compare_two_data(
void *data1,
void *data2,
long index,
long datatype,
937 long first,
long flags,
char *name,
long page,
938 long double tolerance,
long double precisionTolerance,
939 char *floatFormat,
char *doubleFormat,
char *ldoubleFormat,
940 char *stringFormat,
char *longFormat,
char *ulongFormat,
941 char *shortFormat,
char *ushortFormat,
char *charFormat,
942 long absolute,
long parameter,
char *labelName) {
944 long double ldval1, ldval2, ldenominator, ldabs1, ldabs2, lddiff;
945 double dval1, dval2, denominator, dabs1, dabs2, ddiff;
946 float fval1, fval2, fabs1, fabs2, fdenominator, fdiff;
947 int32_t lval1, lval2, labs1, labs2, ldiff, uldiff;
948 uint32_t ulval1, ulval2;
949 int64_t llval1, llval2, llabs1, llabs2, lldiff, ulldiff;
950 uint64_t ullval1, ullval2;
951 short sval1, sval2, sabs1, sabs2, sdiff, usdiff;
952 unsigned short usval1, usval2;
954 long returnValue = 0, printIndex;
957 printIndex = index + 1;
968 str1 = *((
char **)data1 + index);
969 str2 = *((
char **)data2 + index);
971 if (returnValue != 0) {
973 printTitle(flags, name, page, absolute, labelName);
975 fprintf(stdout, stringFormat, str1, str2, returnValue);
977 fprintf(stdout, stringFormat, printIndex, str1, str2, returnValue);
981 ldval1 = *((
long double *)data1 + index);
982 ldval2 = *((
long double *)data2 + index);
984 ldabs1 = fabsl(ldval1);
985 ldabs2 = fabsl(ldval2);
990 lddiff = ldabs1 - ldabs2;
991 if ((isnan(ldval1) && !isnan(ldval2)) || (isinf(ldval1) && !isinf(ldval2)))
993 else if (ldabs1 != ldabs2) {
995 if (fabsl(lddiff) > tol)
998 if (ldabs1 == 0L || ldabs2 == 0L) {
999 if (fabsl(ldabs1 - ldabs2) > precisionTolerance)
1002 ldabs1 = fabsl(ldval1);
1003 ldabs2 = fabsl(ldval2);
1004 ldenominator = (ldabs1 < ldabs2) ? ldabs1 : ldabs2;
1005 if (fabsl(ldval1 - ldval2) / ldenominator > precisionTolerance)
1012 printTitle(flags, name, page, absolute, labelName);
1014 fprintf(stdout, ldoubleFormat, ldval1, ldval2, lddiff);
1016 fprintf(stdout, ldoubleFormat, printIndex, ldval1, ldval2, lddiff);
1020 dval1 = *((
double *)data1 + index);
1021 dval2 = *((
double *)data2 + index);
1023 dabs1 = fabs(dval1);
1024 dabs2 = fabs(dval2);
1029 ddiff = dabs1 - dabs2;
1030 if ((isnan(dval1) && !isnan(dval2)) || (isinf(dval1) && !isinf(dval2)))
1032 else if (dabs1 != dabs2) {
1034 if (fabs(ddiff) > tol)
1037 if (dabs1 == 0 || dabs2 == 0) {
1038 if (fabs(dabs1 - dabs2) > precisionTolerance)
1041 dabs1 = fabs(dval1);
1042 dabs2 = fabs(dval2);
1043 denominator = (dabs1 < dabs2) ? dabs1 : dabs2;
1044 if (fabs(dval1 - dval2) / denominator > precisionTolerance)
1051 printTitle(flags, name, page, absolute, labelName);
1053 fprintf(stdout, doubleFormat, dval1, dval2, ddiff);
1055 fprintf(stdout, doubleFormat, printIndex, dval1, dval2, ddiff);
1059 fval1 = *((
float *)data1 + index);
1060 fval2 = *((
float *)data2 + index);
1062 fabs1 = fabs(fval1);
1063 fabs2 = fabs(fval2);
1068 fdiff = fabs1 - fabs2;
1069 if ((isnan(fval1) && !isnan(fval2)) || (isinf(fval1) && !isinf(fval2)))
1071 else if (fabs1 != fabs2) {
1073 if (fabs(fdiff) > tol)
1076 if (fabs1 == 0 || fabs2 == 0) {
1077 if (fabs(fabs1 - fabs2) > precisionTolerance)
1080 fabs1 = fabs(fval1);
1081 fabs2 = fabs(fval2);
1082 fdenominator = (fabs1 < fabs2) ? fabs1 : fabs2;
1083 if (fabs(fval1 - fval2) / fdenominator > precisionTolerance)
1090 printTitle(flags, name, page, absolute, labelName);
1092 fprintf(stdout, floatFormat, fval1, fval2, fdiff);
1094 fprintf(stdout, floatFormat, printIndex, fval1, fval2, fdiff);
1098 ullval1 = *((uint64_t *)data1 + index);
1099 ullval2 = *((uint64_t *)data2 + index);
1100 ulldiff = ullval1 - ullval2;
1101 if (labs(ulldiff) > tol)
1105 printTitle(flags, name, page, absolute, labelName);
1107 fprintf(stdout, ulongFormat, ullval1, ullval2, ulldiff);
1109 fprintf(stdout, ulongFormat, printIndex, ullval1, ullval2, ulldiff);
1113 llval1 = *((int64_t *)data1 + index);
1114 llval2 = *((int64_t *)data2 + index);
1116 llabs1 = labs(llval1);
1117 llabs2 = labs(llval2);
1122 lldiff = llabs1 - llabs2;
1123 if (llabs(lldiff) > tol)
1127 printTitle(flags, name, page, absolute, labelName);
1129 fprintf(stdout, longFormat, llval1, llval2, lldiff);
1131 fprintf(stdout, longFormat, printIndex, llval1, llval2, lldiff);
1135 ulval1 = *((uint32_t *)data1 + index);
1136 ulval2 = *((uint32_t *)data2 + index);
1137 uldiff = ulval1 - ulval2;
1138 if (labs(uldiff) > tol)
1142 printTitle(flags, name, page, absolute, labelName);
1144 fprintf(stdout, ulongFormat, ulval1, ulval2, uldiff);
1146 fprintf(stdout, ulongFormat, printIndex, ulval1, ulval2, uldiff);
1150 lval1 = *((int32_t *)data1 + index);
1151 lval2 = *((int32_t *)data2 + index);
1159 ldiff = labs1 - labs2;
1160 if (labs(ldiff) > tol)
1164 printTitle(flags, name, page, absolute, labelName);
1166 fprintf(stdout, longFormat, lval1, lval2, ldiff);
1168 fprintf(stdout, longFormat, printIndex, lval1, lval2, ldiff);
1172 sval1 = *((
short *)data1 + index);
1173 sval2 = *((
short *)data2 + index);
1181 sdiff = sabs1 - sabs2;
1182 if (abs(sdiff) > tol)
1186 printTitle(flags, name, page, absolute, labelName);
1188 fprintf(stdout, shortFormat, sval1, sval2, sdiff);
1190 fprintf(stdout, shortFormat, printIndex, sval1, sval2, sdiff);
1194 usval1 = *((
unsigned short *)data1 + index);
1195 usval2 = *((
unsigned short *)data2 + index);
1196 usdiff = usval1 - usval2;
1197 if (abs(usdiff) > tol)
1201 printTitle(flags, name, page, absolute, labelName);
1203 fprintf(stdout, ushortFormat, usval1, usval2, usdiff);
1205 fprintf(stdout, ushortFormat, printIndex, usval1, usval2, usdiff);
1209 cval1 = *((
char *)data1 + index);
1210 cval2 = *((
char *)data2 + index);
1211 if (cval1 != cval2) {
1214 printTitle(flags, name, page, absolute, labelName);
1216 fprintf(stdout, charFormat, cval1, cval2, cval1 - cval2);
1218 fprintf(stdout, charFormat, printIndex, cval1, cval2, cval1 - cval2);
1222 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.