SDDSlib
Loading...
Searching...
No Matches
sddsdiff.c
Go to the documentation of this file.
1/**
2 * @file sddsdiff.c
3 * @brief Compare two SDDS files.
4 *
5 * This program compares two SDDS (Self Describing Data Sets) files by checking their definitions and data.
6 * It supports various options to customize the comparison, such as specifying which columns, parameters,
7 * or arrays to compare, setting tolerance levels for numerical comparisons, and more.
8 *
9 * @section Usage
10 * ```
11 * sddsdiff <file1> <file2> [options]
12 * ```
13 *
14 * @section Options
15 * -compareCommon[=column|parameter|array]
16 * -columns=<col1>[,<col2>...]
17 * -parameters=<par1>[,<par2>...]
18 * -arrays=<array1>[,<array2>...]
19 * -tolerance=<value>
20 * -precision=<integer>
21 * -format=float=<string>|double=<string>|longdouble=<string>|string=<string>
22 * -exact
23 * -absolute
24 * -rowlabel=<column-name>[,nocomparison]
25 * -ignoreUnits
26 *
27 * @copyright
28 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
29 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
30 *
31 * @license
32 * This file is distributed under the terms of the Software License Agreement
33 * found in the file LICENSE included with this distribution.
34 *
35 * @author H. Shang, R. Soliday, L. Emery, M. Borland
36 */
37
38#include "mdb.h"
39#include "SDDS.h"
40#include "scan.h"
41#include "SDDSutils.h"
42#include <float.h>
43
44/* Enumeration for option types */
45enum option_type {
46 CLO_COMPARECOMMON,
47 CLO_COLUMNS,
48 CLO_PARAMETERS,
49 CLO_ARRAYS,
50 CLO_TOLERANCE,
51 CLO_PRECISION,
52 CLO_FORMAT,
53 CLO_EXACT,
54 CLO_ABSOLUTE,
55 CLO_ROWLABEL,
56 CLO_IGNORE_UNITS,
57 N_OPTIONS
58};
59
60char *option[N_OPTIONS] = {
61 "compareCommon",
62 "columns",
63 "parameters",
64 "arrays",
65 "tolerance",
66 "precision",
67 "format",
68 "exact",
69 "absolute",
70 "rowlabel",
71 "ignoreUnits"};
72
73char *USAGE1 = "Usage: sddsdiff <file1> <file2> [options]\n\
74Options:\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";
89
90char *USAGE2 = "\n\
91Description:\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\
94\n\
95Example:\n\
96 sddsdiff data1.sdds data2.sdds -compareCommon=column -tolerance=1e-5 -absolute\n\
97\n\
98Program by Hairong Shang. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
99
100#define SDDS_COLUMN_TYPE 0
101#define SDDS_PARAMETER_TYPE 1
102#define SDDS_ARRAY_TYPE 2
103/* type=0,1,2 for Column, Parameter, Array */
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);
110
111#define COMPARE_COMMON_COLUMN 0x0001U
112#define COMPARE_COMMON_PARAMETER 0x0002U
113#define COMPARE_COMMON_ARRAY 0x0004U
114
115int main(int argc, char **argv) {
116 SCANNED_ARG *s_arg;
117 SDDS_DATASET table1, table2;
118 char *file1, *file2;
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;
128 void *rowLabel;
129 short ignoreUnits = 0;
130
131 rowLabelColumn = NULL;
132 rowLabel = NULL;
133 floatFormat = doubleFormat = ldoubleFormat = stringFormat = NULL;
134 precision = 0;
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;
141 pages1 = pages2 = 0;
142 column_provided = parameter_provided = array_provided = 0;
144 argc = scanargs(&s_arg, argc, argv);
145 if (argc < 3) {
146 fprintf(stderr, "%s%s", USAGE1, USAGE2);
147 exit(EXIT_FAILURE);
148 }
149 for (i_arg = 1; i_arg < argc; i_arg++) {
150 if (s_arg[i_arg].arg_type == OPTION) {
151 delete_chars(s_arg[i_arg].list[0], "_");
152 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
153 case CLO_ROWLABEL:
154 if (s_arg[i_arg].n_items < 2)
155 SDDS_Bomb("Invalid -rowlabel syntax");
156 rowLabelColumn = s_arg[i_arg].list[1];
157 if (s_arg[i_arg].n_items > 2 &&
158 strncmp_case_insensitive("nocomparison", s_arg[i_arg].list[2], strlen(s_arg[i_arg].list[2])) == 0)
159 notCompareRowLabel = 1;
160 break;
161 case CLO_EXACT:
162 tolerance = -1.0L;
163 break;
164 case CLO_ABSOLUTE:
165 absolute = 1;
166 break;
167 case CLO_TOLERANCE:
168 if (s_arg[i_arg].n_items != 2)
169 SDDS_Bomb("Invalid -tolerance syntax");
170 if (!get_longdouble(&tolerance, s_arg[i_arg].list[1]))
171 SDDS_Bomb("Invalid -tolerance syntax (not a number given)");
172 break;
173 case CLO_PRECISION:
174 if (s_arg[i_arg].n_items != 2)
175 SDDS_Bomb("Invalid -precision syntax");
176 if (!get_long(&precision, s_arg[i_arg].list[1]))
177 SDDS_Bomb("Invalid -precision syntax (not a number given)");
178 if (precision < 0)
179 precision = 0;
180 break;
181 case CLO_FORMAT:
182 if (s_arg[i_arg].n_items < 2)
183 SDDS_Bomb("Invalid -format syntax.");
184 s_arg[i_arg].n_items--;
185 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
186 "float", SDDS_STRING, &floatFormat, 1, 0,
187 "double", SDDS_STRING, &doubleFormat, 1, 0,
188 "longdouble", SDDS_STRING, &ldoubleFormat, 1, 0,
189 "string", SDDS_STRING, &stringFormat, 1, 0, NULL))
190 SDDS_Bomb("Invalid -format syntax");
191 s_arg[i_arg].n_items++;
192 if (floatFormat && !SDDS_VerifyPrintfFormat(floatFormat, SDDS_FLOAT)) {
193 fprintf(stderr, "Error: Given print format (\"%s\") for float data is invalid.\n", floatFormat);
194 exit(EXIT_FAILURE);
195 }
196 if (doubleFormat && !SDDS_VerifyPrintfFormat(doubleFormat, SDDS_DOUBLE)) {
197 fprintf(stderr, "Error: Given print format (\"%s\") for double data is invalid.\n", doubleFormat);
198 exit(EXIT_FAILURE);
199 }
200 if (ldoubleFormat && !SDDS_VerifyPrintfFormat(ldoubleFormat, SDDS_LONGDOUBLE)) {
201 fprintf(stderr, "Error: Given print format (\"%s\") for long double data is invalid.\n", ldoubleFormat);
202 exit(EXIT_FAILURE);
203 }
204 if (stringFormat && !SDDS_VerifyPrintfFormat(stringFormat, SDDS_STRING)) {
205 fprintf(stderr, "Error: Given print format (\"%s\") for string data is invalid.\n", stringFormat);
206 exit(EXIT_FAILURE);
207 }
208 break;
209 case CLO_COMPARECOMMON:
210 if (s_arg[i_arg].n_items == 1)
211 compareCommonFlags |= COMPARE_COMMON_COLUMN | COMPARE_COMMON_PARAMETER | COMPARE_COMMON_ARRAY;
212 else {
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++;
220 }
221 break;
222 case CLO_COLUMNS:
223 if (s_arg[i_arg].n_items < 2)
224 SDDS_Bomb("Invalid -columns syntax");
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];
228 column_provided = 1;
229 break;
230 case CLO_PARAMETERS:
231 if (s_arg[i_arg].n_items < 2)
232 SDDS_Bomb("Invalid -parameters syntax");
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;
237 break;
238 case CLO_ARRAYS:
239 if (s_arg[i_arg].n_items < 2)
240 SDDS_Bomb("Invalid -arrays syntax");
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];
244 array_provided = 1;
245 break;
246 case CLO_IGNORE_UNITS:
247 ignoreUnits = 1;
248 break;
249 default:
250 fprintf(stderr, "Unknown option given (sddsdiff): %s\n", s_arg[i_arg].list[0]);
251 exit(EXIT_FAILURE);
252 break;
253 }
254 } else {
255 if (!file1)
256 file1 = s_arg[i_arg].list[0];
257 else if (!file2)
258 file2 = s_arg[i_arg].list[0];
259 else
260 SDDS_Bomb("Too many files given.");
261 }
262 }
263 if (!floatFormat)
264 SDDS_CopyString(&floatFormat, "%25.8e");
265 if (!doubleFormat)
266 SDDS_CopyString(&doubleFormat, "%25.16e");
267 if (!ldoubleFormat)
268 SDDS_CopyString(&ldoubleFormat, "%26.18Le");
269 if (!stringFormat)
270 SDDS_CopyString(&stringFormat, "%25s");
271
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.");
274 }
275 if (!file1 || !file2) {
276 fprintf(stderr, "Error: Two files must be provided for comparison.\n");
277 exit(EXIT_FAILURE);
278 }
279 if (strcmp(file1, file2) == 0) {
280 printf("\"%s\" and \"%s\" are identical.\n", file1, file2);
281 return EXIT_SUCCESS;
282 }
283 if (!SDDS_InitializeInput(&table1, file1)) {
284 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
285 exit(EXIT_FAILURE);
286 }
287 if (!SDDS_InitializeInput(&table2, file2)) {
288 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
289 exit(EXIT_FAILURE);
290 }
291 if (rowLabelColumn) {
292 if ((rowLabelIndex = SDDS_GetColumnIndex(&table1, rowLabelColumn)) < 0) {
293 if ((rowLabelIndex = SDDS_GetColumnIndex(&table2, rowLabelColumn)) < 0) {
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;
296 } else {
297 labelFromSecondFile = 1;
298 notCompareRowLabel = 1;
299 }
300 } else {
301 if (SDDS_GetColumnIndex(&table2, rowLabelColumn) < 0)
302 notCompareRowLabel = 1;
303 }
304
305 if (rowLabelColumn) {
306 if (labelFromSecondFile)
307 rowLabelType = SDDS_GetColumnType(&table2, rowLabelIndex);
308 else
309 rowLabelType = SDDS_GetColumnType(&table1, rowLabelIndex);
310 }
311 }
312 if (!precision) {
313 precisionTolerance = powl(10L, -1L * fabsl(log10l(LDBL_EPSILON)));
314 } else {
315 precisionTolerance = powl(10L, -1L * precision);
316 }
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))
320 different = 1;
321 }
322 if (parameter_provided) {
323 parameterName = getMatchingSDDSNames(&table1, parameterMatch, parameterMatches, &parameters, SDDS_MATCH_PARAMETER);
324
325 if (CompareDefinitions(&table1, &table2, file1, file2, &parameters, &parameterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits))
326 different = 1;
327 }
328 if (array_provided) {
329 arrayName = getMatchingSDDSNames(&table1, arrayMatch, arrayMatches, &arrays, SDDS_MATCH_ARRAY);
330 if (CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits))
331 different = 1;
332 }
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, &parameters, &parameterName, &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);
340 }
341 if (!different) {
342 if (!columns && !parameters && !arrays) {
343 fprintf(stderr, "There are no common columns, parameters, or arrays in the two files.\n");
344 different = 1;
345 } else {
346 /* Definitions are the same, now compare the data */
347 while (1) {
348 pagediff = 0;
349 pages1 = SDDS_ReadPage(&table1);
350 pages2 = SDDS_ReadPage(&table2);
351 if (pages1 > 0 && pages2 > 0) {
352 /* Compare data */
353 rows1 = SDDS_CountRowsOfInterest(&table1);
354 rows2 = SDDS_CountRowsOfInterest(&table2);
355 if (rows1 != rows2) {
356 pagediff = 1;
357 different = 1;
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);
360 break;
361 } else {
362 if (parameters)
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) {
367 if (!(rowLabel = SDDS_GetColumn(&table2, rowLabelColumn)))
368 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
369 } else {
370 if (!(rowLabel = SDDS_GetColumn(&table1, rowLabelColumn)))
371 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
372 }
373 }
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) {
376 if (rowLabelType == SDDS_STRING)
377 SDDS_FreeStringArray((char **)rowLabel, rows1);
378 else
379 free(rowLabel);
380 rowLabel = NULL;
381 }
382 }
383 if (arrays)
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;
386 }
387 } else if (pages1 > 0 && pages2 <= 0) {
388 fprintf(stderr, "\"%s\" has fewer pages than \"%s\".\n", file2, file1);
389 different = 1;
390 break;
391 } else if (pages1 < 0 && pages2 > 0) {
392 different = 1;
393 fprintf(stderr, "\"%s\" has fewer pages than \"%s\".\n", file1, file2);
394 break;
395 } else {
396 break;
397 }
398 }
399 }
400 } else {
401 different = 1;
402 }
403 if (!different)
404 printf("\"%s\" and \"%s\" are identical.\n", file1, file2);
405 else
406 fprintf(stderr, "\"%s\" and \"%s\" are different.\n", file1, file2);
407
408 if (columns) {
409 for (i = 0; i < columns; i++)
410 free(columnName[i]);
411 free(columnName);
412 free(columnDataType);
413 free(columnMatch);
414 }
415 if (parameters) {
416 for (i = 0; i < parameters; i++)
417 free(parameterName[i]);
418 free(parameterName);
419 free(parDataType);
420 free(parameterMatch);
421 }
422 if (arrays) {
423 for (i = 0; i < arrays; i++)
424 free(arrayName[i]);
425 free(arrayName);
426 free(arrayDataType);
427 free(arrayMatch);
428 }
429 free_scanargs(&s_arg, argc);
430 free(stringFormat);
431 free(floatFormat);
432 free(doubleFormat);
433 free(ldoubleFormat);
434
435 if (!SDDS_Terminate(&table1) || !SDDS_Terminate(&table2)) {
436 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
437 exit(EXIT_FAILURE);
438 }
439 return EXIT_SUCCESS;
440}
441
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) {
443 size_t same_items;
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;
453 names1 = names2 = 0;
454 def = NULL;
455 same_items = 0;
456 same = datatype = NULL;
457
458 type1 = type2 = -1;
459
460 switch (type) {
461 case SDDS_COLUMN_TYPE:
462 name1 = SDDS_GetColumnNames(dataset1, &names1);
463 name2 = SDDS_GetColumnNames(dataset2, &names2);
464 SDDS_CopyString(&def, "column");
465 break;
466 case SDDS_PARAMETER_TYPE:
467 name1 = SDDS_GetParameterNames(dataset1, &names1);
468 name2 = SDDS_GetParameterNames(dataset2, &names2);
469 SDDS_CopyString(&def, "parameter");
470 break;
471 case SDDS_ARRAY_TYPE:
472 name1 = SDDS_GetArrayNames(dataset1, &names1);
473 name2 = SDDS_GetArrayNames(dataset2, &names2);
474 SDDS_CopyString(&def, "array");
475 break;
476 default:
477 fprintf(stderr, "Unknown type given for CompareDefinitions().\n");
478 return 1;
479 }
480 if (names1 == 0 && names2 == 0)
481 return 0;
482 if (*names) {
483 if (!names1 || !names2) {
484 fprintf(stderr, "Error: One of the files does not have any %s.\n", def);
485 returnValue = 1;
486 }
487 if (!returnValue) {
488 for (i = 0; i < *names; i++) {
489 if (rowLabelColumn && notCompareRowLabel && strcmp((*name)[i], rowLabelColumn) == 0)
490 continue;
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]);
493 returnValue = 1;
494 break;
495 }
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]);
498 returnValue = 1;
499 break;
500 }
501 }
502 }
503 if (returnValue) {
504 for (i = 0; i < names1; i++)
505 free(name1[i]);
506 free(name1);
507 for (i = 0; i < names2; i++)
508 free(name2[i]);
509 free(name2);
510 free(def);
511 return returnValue;
512 }
513 same_items = *names;
514 same_name = *name;
515 compareCommon = 0;
516 } else {
517 if (!names1 && !names2) {
518 free(def);
519 return 0;
520 }
521 if (compareCommon && (!names1 || !names2)) {
522 if (names1) {
523 for (i = 0; i < names1; i++)
524 free(name1[i]);
525 free(name1);
526 }
527 if (names2) {
528 for (i = 0; i < names2; i++)
529 free(name2[i]);
530 free(name2);
531 }
532 *names = 0;
533 return 0;
534 }
535 if (names1 != names2 && !compareCommon && !notCompareRowLabel)
536 returnValue = 1;
537 if (returnValue) {
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++)
540 free(name2[i]);
541 free(name2);
542 for (i = 0; i < names1; i++)
543 free(name1[i]);
544 free(name1);
545 free(def);
546 return returnValue;
547 }
548 same_items = 0;
549 for (i = 0; i < names1; i++) {
550 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name1[i]) == 0)
551 continue;
552 if (-1 == match_string(name1[i], name2, names2, EXACT_MATCH)) {
553 if (!compareCommon) {
554 if (first) {
555 fprintf(stderr, " Following %ss of \"%s\" are not in \"%s\":\n", def, file1, file2);
556 first = 0;
557 }
558 fprintf(stderr, " %s\n", name1[i]);
559 returnValue++;
560 }
561 } else {
562 same_name = (char **)SDDS_Realloc(same_name, sizeof(*same_name) * (same_items + 1));
563 same_name[same_items] = name1[i];
564 same_items++;
565 }
566 }
567 if (!compareCommon) {
568 if (!first)
569 fprintf(stderr, "\n");
570 first = 1;
571 for (i = 0; i < names2; i++) {
572 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name2[i]) == 0)
573 continue;
574 if (-1 == match_string(name2[i], name1, names1, EXACT_MATCH)) {
575 if (first) {
576 fprintf(stderr, " Following %ss of \"%s\" are not in \"%s\":\n", def, file2, file1);
577 first = 0;
578 }
579 fprintf(stderr, " %s\n", name2[i]);
580 returnValue++;
581 }
582 }
583 if (!first)
584 fprintf(stderr, "\n");
585 }
586 if (same_items)
587 free_same_name = 1;
588 }
589 sames = same_items;
590 if (same_items) {
591 datatype = (int32_t *)malloc(sizeof(*datatype) * same_items);
592 same = (int32_t *)malloc(sizeof(*same) * same_items);
593 /* Check the units and type */
594 for (i = 0; i < same_items; i++) {
595 same[i] = 1;
596 switch (type) {
597 case SDDS_COLUMN_TYPE:
598 index1 = SDDS_GetColumnIndex(dataset1, same_name[i]);
599 index2 = SDDS_GetColumnIndex(dataset2, same_name[i]);
600 type1 = SDDS_GetColumnType(dataset1, index1);
601 type2 = SDDS_GetColumnType(dataset2, index2);
602 if (!ignoreUnits) {
603 if (SDDS_GetColumnInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
604 SDDS_SetError("Units field of column has wrong data type!");
605 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
606 exit(EXIT_FAILURE);
607 }
608 if (SDDS_GetColumnInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
609 SDDS_SetError("Units field of column has wrong data type!");
610 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
611 exit(EXIT_FAILURE);
612 }
613 }
614 break;
615 case SDDS_PARAMETER_TYPE:
616 index1 = SDDS_GetParameterIndex(dataset1, same_name[i]);
617 index2 = SDDS_GetParameterIndex(dataset2, same_name[i]);
618 type1 = SDDS_GetParameterType(dataset1, index1);
619 type2 = SDDS_GetParameterType(dataset2, index2);
620 if (!ignoreUnits) {
621 if (SDDS_GetParameterInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
622 SDDS_SetError("Units field of parameter has wrong data type!");
623 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
624 exit(EXIT_FAILURE);
625 }
626 if (SDDS_GetParameterInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
627 SDDS_SetError("Units field of parameter has wrong data type!");
628 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
629 exit(EXIT_FAILURE);
630 }
631 }
632 break;
633 case SDDS_ARRAY_TYPE:
634 index1 = SDDS_GetArrayIndex(dataset1, same_name[i]);
635 index2 = SDDS_GetArrayIndex(dataset2, same_name[i]);
636 type1 = SDDS_GetArrayType(dataset1, index1);
637 type2 = SDDS_GetArrayType(dataset2, index2);
638 if (!ignoreUnits) {
639 if (SDDS_GetArrayInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
640 SDDS_SetError("Units field of array has wrong data type!");
641 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
642 exit(EXIT_FAILURE);
643 }
644 if (SDDS_GetArrayInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
645 SDDS_SetError("Units field of array has wrong data type!");
646 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
647 exit(EXIT_FAILURE);
648 }
649 }
650 break;
651 }
652 datatype[i] = type1;
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);
657 first = 0;
658 }
659 if (!compareCommon) {
660 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], SDDS_type_name[type1 - 1], SDDS_type_name[type2 - 1]);
661 returnValue++;
662 }
663 sames--;
664 same[i] = 0;
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);
669 first = 0;
670 }
671 if (!compareCommon) {
672 if (units1 && units2)
673 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], units1, units2);
674 else if (units1)
675 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], units1, " ");
676 else if (units2)
677 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], " ", units2);
678 returnValue++;
679 }
680 sames--;
681 same[i] = 0;
682 }
683 free(units1);
684 free(units2);
685 units1 = units2 = NULL;
686 if (returnValue && !compareCommon)
687 break;
688 }
689 if (!compareCommon && returnValue) {
690 sames = 0;
691 }
692 }
693 if (sames) {
694 if (!(*names)) {
695 for (i = 0; i < same_items; i++) {
696 if (same[i]) {
697 *name = (char **)SDDS_Realloc(*name, sizeof(**name) * (*names + 1));
698 *dataType = (int32_t *)SDDS_Realloc(*dataType, sizeof(**dataType) * (*names + 1));
699 SDDS_CopyString(*name + *names, same_name[i]);
700 (*dataType)[*names] = datatype[i];
701 (*names)++;
702 }
703 }
704 free(datatype);
705 } else
706 *dataType = datatype;
707 }
708
709 for (i = 0; i < names2; i++)
710 free(name2[i]);
711 free(name2);
712 for (i = 0; i < names1; i++)
713 free(name1[i]);
714 free(name1);
715 if (same)
716 free(same);
717 if (free_same_name)
718 free(same_name);
719 free(def);
720 return compareCommon ? 0 : returnValue;
721}
722
723long CompareData(SDDS_DATASET *dataset1, SDDS_DATASET *dataset2, char *file1, char *file2,
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;
728 int64_t rows, j;
729 char fFormat[2048], dFormat[2048], ldFormat[2048], strFormat[2048], lFormat[2048], ulFormat[2048], ushortFormat[2048], shortFormat[2048], cFormat[2048], labelFormat[1024];
730 SDDS_ARRAY *array1, *array2;
731 void *data1, *data2;
732
733 array1 = array2 = NULL;
734 data1 = data2 = NULL;
735
736 if (!rowLabel) {
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");
746 }
747 switch (type) {
748 case SDDS_COLUMN_TYPE:
749 rows = SDDS_CountRowsOfInterest(dataset1);
750 if (!rows)
751 break;
752 for (i = 0; i < names; i++) {
753 first = 1;
754 if (!(data1 = SDDS_GetColumn(dataset1, name[i])) || !(data2 = SDDS_GetColumn(dataset2, name[i]))) {
755 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
756 exit(EXIT_FAILURE);
757 }
758 for (j = 0; j < rows; j++) {
759 if (rowLabel) {
760 switch (rowLabelType) {
761 case SDDS_STRING:
762 snprintf(labelFormat, sizeof(labelFormat), "%20s", ((char **)rowLabel)[j]);
763 break;
764 case SDDS_LONGDOUBLE:
765 snprintf(labelFormat, sizeof(labelFormat), "%20.15Le", ((long double *)rowLabel)[j]);
766 break;
767 case SDDS_DOUBLE:
768 snprintf(labelFormat, sizeof(labelFormat), "%20.10e", ((double *)rowLabel)[j]);
769 break;
770 case SDDS_FLOAT:
771 snprintf(labelFormat, sizeof(labelFormat), "%20.5e", ((float *)rowLabel)[j]);
772 break;
773 case SDDS_ULONG64:
774 snprintf(labelFormat, sizeof(labelFormat), "%20" PRIu64, ((uint64_t *)rowLabel)[j]);
775 break;
776 case SDDS_LONG64:
777 snprintf(labelFormat, sizeof(labelFormat), "%20" PRId64, ((int64_t *)rowLabel)[j]);
778 break;
779 case SDDS_ULONG:
780 snprintf(labelFormat, sizeof(labelFormat), "%20" PRIu32, ((uint32_t *)rowLabel)[j]);
781 break;
782 case SDDS_LONG:
783 snprintf(labelFormat, sizeof(labelFormat), "%20" PRId32, ((int32_t *)rowLabel)[j]);
784 break;
785 case SDDS_USHORT:
786 snprintf(labelFormat, sizeof(labelFormat), "%20hu", ((unsigned short *)rowLabel)[j]);
787 break;
788 case SDDS_SHORT:
789 snprintf(labelFormat, sizeof(labelFormat), "%20hd", ((short *)rowLabel)[j]);
790 break;
791 case SDDS_CHARACTER:
792 snprintf(labelFormat, sizeof(labelFormat), "%20c", ((char *)rowLabel)[j]);
793 break;
794 default:
795 fprintf(stderr, "Unknown data type for rowlabel.\n");
796 exit(EXIT_FAILURE);
797 }
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);
807 }
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) {
809 diff++;
810 if (first)
811 first = 0;
812 }
813 if (dataType[i] == SDDS_STRING) {
814 free((char *)((char **)data1)[j]);
815 free((char *)((char **)data2)[j]);
816 }
817 }
818 free((char **)data1);
819 free((char **)data2);
820 data1 = data2 = NULL;
821 }
822 break;
823 case SDDS_PARAMETER_TYPE:
824 for (i = 0; i < names; i++) {
825 first = 1;
826 if (!(data1 = SDDS_GetParameter(dataset1, name[i], NULL)) || !(data2 = SDDS_GetParameter(dataset2, name[i], NULL))) {
827 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
828 exit(EXIT_FAILURE);
829 }
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) {
831 diff++;
832 if (first)
833 first = 0;
834 }
835 if (dataType[i] == SDDS_STRING) {
836 free(*((char **)data1));
837 free(*((char **)data2));
838 }
839 free(data1);
840 free(data2);
841 data1 = data2 = NULL;
842 }
843 break;
844 case SDDS_ARRAY_TYPE:
845 for (i = 0; i < names; i++) {
846 first = 1;
847 if (!(array1 = SDDS_GetArray(dataset1, name[i], NULL)) || !(array2 = SDDS_GetArray(dataset2, name[i], NULL))) {
848 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
849 exit(EXIT_FAILURE);
850 }
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);
853 diff++;
854 } else {
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) {
857 diff++;
858 if (first)
859 first = 0;
860 }
861 }
862 }
863 SDDS_FreeArray(array1);
864 SDDS_FreeArray(array2);
865 array1 = array2 = NULL;
866 }
867 break;
868 }
869 return diff;
870}
871
872void printTitle(long flags, char *name, long page, long absolute, char *labelName) {
873 char *type = NULL;
874 char *element = NULL;
875
876 switch (flags) {
877 case SDDS_COLUMN_TYPE:
878 SDDS_CopyString(&type, "column");
879 if (labelName)
880 SDDS_CopyString(&element, labelName);
881 else
882 SDDS_CopyString(&element, "row");
883 break;
884 case SDDS_PARAMETER_TYPE:
885 SDDS_CopyString(&type, "parameter");
886 SDDS_CopyString(&element, "page number");
887 break;
888 case SDDS_ARRAY_TYPE:
889 SDDS_CopyString(&type, "array");
890 SDDS_CopyString(&element, "element number");
891 break;
892 }
893 if (type) {
894 fprintf(stdout, "\nDifferences found in %s \"%s\" on page %ld:\n", type, name, page);
895 if (absolute)
896 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (abs)");
897 else
898 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (file1 - file2)");
899 free(type);
900 free(element);
901 }
902}
903
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) {
911 char *str1, *str2;
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;
921 char cval1, cval2;
922 long returnValue = 0, printIndex;
923 long double tol;
924
925 printIndex = index + 1;
926 if (parameter)
927 printIndex = page;
928
929 if (tolerance < 0)
930 tol = 0L;
931 else
932 tol = tolerance;
933
934 switch (datatype) {
935 case SDDS_STRING:
936 str1 = *((char **)data1 + index);
937 str2 = *((char **)data2 + index);
938 returnValue = strcmp(trim_spaces(str1), trim_spaces(str2));
939 if (returnValue != 0) {
940 if (first)
941 printTitle(flags, name, page, absolute, labelName);
942 if (labelName) {
943 fprintf(stdout, stringFormat, str1, str2, returnValue);
944 } else
945 fprintf(stdout, stringFormat, printIndex, str1, str2, returnValue);
946 }
947 break;
948 case SDDS_LONGDOUBLE:
949 ldval1 = *((long double *)data1 + index);
950 ldval2 = *((long double *)data2 + index);
951 if (absolute) {
952 ldabs1 = fabsl(ldval1);
953 ldabs2 = fabsl(ldval2);
954 } else {
955 ldabs1 = ldval1;
956 ldabs2 = ldval2;
957 }
958 lddiff = ldabs1 - ldabs2;
959 if ((isnan(ldval1) && !isnan(ldval2)) || (isinf(ldval1) && !isinf(ldval2)))
960 returnValue = 1;
961 else if (ldabs1 != ldabs2) {
962 if (tolerance) {
963 if (fabsl(lddiff) > tol)
964 returnValue = 1;
965 } else {
966 if (ldabs1 == 0L || ldabs2 == 0L) {
967 if (fabsl(ldabs1 - ldabs2) > precisionTolerance)
968 returnValue = 1;
969 } else {
970 ldabs1 = fabsl(ldval1);
971 ldabs2 = fabsl(ldval2);
972 ldenominator = (ldabs1 < ldabs2) ? ldabs1 : ldabs2;
973 if (fabsl(ldval1 - ldval2) / ldenominator > precisionTolerance)
974 returnValue = 1;
975 }
976 }
977 }
978 if (returnValue) {
979 if (first)
980 printTitle(flags, name, page, absolute, labelName);
981 if (labelName)
982 fprintf(stdout, ldoubleFormat, ldval1, ldval2, lddiff);
983 else
984 fprintf(stdout, ldoubleFormat, printIndex, ldval1, ldval2, lddiff);
985 }
986 break;
987 case SDDS_DOUBLE:
988 dval1 = *((double *)data1 + index);
989 dval2 = *((double *)data2 + index);
990 if (absolute) {
991 dabs1 = fabs(dval1);
992 dabs2 = fabs(dval2);
993 } else {
994 dabs1 = dval1;
995 dabs2 = dval2;
996 }
997 ddiff = dabs1 - dabs2;
998 if ((isnan(dval1) && !isnan(dval2)) || (isinf(dval1) && !isinf(dval2)))
999 returnValue = 1;
1000 else if (dabs1 != dabs2) {
1001 if (tolerance) {
1002 if (fabs(ddiff) > tol)
1003 returnValue = 1;
1004 } else {
1005 if (dabs1 == 0 || dabs2 == 0) {
1006 if (fabs(dabs1 - dabs2) > precisionTolerance)
1007 returnValue = 1;
1008 } else {
1009 dabs1 = fabs(dval1);
1010 dabs2 = fabs(dval2);
1011 denominator = (dabs1 < dabs2) ? dabs1 : dabs2;
1012 if (fabs(dval1 - dval2) / denominator > precisionTolerance)
1013 returnValue = 1;
1014 }
1015 }
1016 }
1017 if (returnValue) {
1018 if (first)
1019 printTitle(flags, name, page, absolute, labelName);
1020 if (labelName)
1021 fprintf(stdout, doubleFormat, dval1, dval2, ddiff);
1022 else
1023 fprintf(stdout, doubleFormat, printIndex, dval1, dval2, ddiff);
1024 }
1025 break;
1026 case SDDS_FLOAT:
1027 fval1 = *((float *)data1 + index);
1028 fval2 = *((float *)data2 + index);
1029 if (absolute) {
1030 fabs1 = fabs(fval1);
1031 fabs2 = fabs(fval2);
1032 } else {
1033 fabs1 = fval1;
1034 fabs2 = fval2;
1035 }
1036 fdiff = fabs1 - fabs2;
1037 if ((isnan(fval1) && !isnan(fval2)) || (isinf(fval1) && !isinf(fval2)))
1038 returnValue = 1;
1039 else if (fabs1 != fabs2) {
1040 if (tolerance) {
1041 if (fabs(fdiff) > tol)
1042 returnValue = 1;
1043 } else {
1044 if (fabs1 == 0 || fabs2 == 0) {
1045 if (fabs(fabs1 - fabs2) > precisionTolerance)
1046 returnValue = 1;
1047 } else {
1048 fabs1 = fabs(fval1);
1049 fabs2 = fabs(fval2);
1050 fdenominator = (fabs1 < fabs2) ? fabs1 : fabs2;
1051 if (fabs(fval1 - fval2) / fdenominator > precisionTolerance)
1052 returnValue = 1;
1053 }
1054 }
1055 }
1056 if (returnValue) {
1057 if (first)
1058 printTitle(flags, name, page, absolute, labelName);
1059 if (labelName)
1060 fprintf(stdout, floatFormat, fval1, fval2, fdiff);
1061 else
1062 fprintf(stdout, floatFormat, printIndex, fval1, fval2, fdiff);
1063 }
1064 break;
1065 case SDDS_ULONG64:
1066 ullval1 = *((uint64_t *)data1 + index);
1067 ullval2 = *((uint64_t *)data2 + index);
1068 ulldiff = ullval1 - ullval2;
1069 if (labs(ulldiff) > tol)
1070 returnValue = 1;
1071 if (returnValue) {
1072 if (first)
1073 printTitle(flags, name, page, absolute, labelName);
1074 if (labelName)
1075 fprintf(stdout, ulongFormat, ullval1, ullval2, ulldiff);
1076 else
1077 fprintf(stdout, ulongFormat, printIndex, ullval1, ullval2, ulldiff);
1078 }
1079 break;
1080 case SDDS_LONG64:
1081 llval1 = *((int64_t *)data1 + index);
1082 llval2 = *((int64_t *)data2 + index);
1083 if (absolute) {
1084 llabs1 = labs(llval1);
1085 llabs2 = labs(llval2);
1086 } else {
1087 llabs1 = llval1;
1088 llabs2 = llval2;
1089 }
1090 lldiff = llabs1 - llabs2;
1091 if (llabs(lldiff) > tol)
1092 returnValue = 1;
1093 if (returnValue) {
1094 if (first)
1095 printTitle(flags, name, page, absolute, labelName);
1096 if (labelName)
1097 fprintf(stdout, longFormat, llval1, llval2, lldiff);
1098 else
1099 fprintf(stdout, longFormat, printIndex, llval1, llval2, lldiff);
1100 }
1101 break;
1102 case SDDS_ULONG:
1103 ulval1 = *((uint32_t *)data1 + index);
1104 ulval2 = *((uint32_t *)data2 + index);
1105 uldiff = ulval1 - ulval2;
1106 if (labs(uldiff) > tol)
1107 returnValue = 1;
1108 if (returnValue) {
1109 if (first)
1110 printTitle(flags, name, page, absolute, labelName);
1111 if (labelName)
1112 fprintf(stdout, ulongFormat, ulval1, ulval2, uldiff);
1113 else
1114 fprintf(stdout, ulongFormat, printIndex, ulval1, ulval2, uldiff);
1115 }
1116 break;
1117 case SDDS_LONG:
1118 lval1 = *((int32_t *)data1 + index);
1119 lval2 = *((int32_t *)data2 + index);
1120 if (absolute) {
1121 labs1 = abs(lval1);
1122 labs2 = abs(lval2);
1123 } else {
1124 labs1 = lval1;
1125 labs2 = lval2;
1126 }
1127 ldiff = labs1 - labs2;
1128 if (labs(ldiff) > tol)
1129 returnValue = 1;
1130 if (returnValue) {
1131 if (first)
1132 printTitle(flags, name, page, absolute, labelName);
1133 if (labelName)
1134 fprintf(stdout, longFormat, lval1, lval2, ldiff);
1135 else
1136 fprintf(stdout, longFormat, printIndex, lval1, lval2, ldiff);
1137 }
1138 break;
1139 case SDDS_SHORT:
1140 sval1 = *((short *)data1 + index);
1141 sval2 = *((short *)data2 + index);
1142 if (absolute) {
1143 sabs1 = abs(sval1);
1144 sabs2 = abs(sval2);
1145 } else {
1146 sabs1 = sval1;
1147 sabs2 = sval2;
1148 }
1149 sdiff = sabs1 - sabs2;
1150 if (abs(sdiff) > tol)
1151 returnValue = 1;
1152 if (returnValue) {
1153 if (first)
1154 printTitle(flags, name, page, absolute, labelName);
1155 if (labelName)
1156 fprintf(stdout, shortFormat, sval1, sval2, sdiff);
1157 else
1158 fprintf(stdout, shortFormat, printIndex, sval1, sval2, sdiff);
1159 }
1160 break;
1161 case SDDS_USHORT:
1162 usval1 = *((unsigned short *)data1 + index);
1163 usval2 = *((unsigned short *)data2 + index);
1164 usdiff = usval1 - usval2;
1165 if (abs(usdiff) > tol)
1166 returnValue = 1;
1167 if (returnValue) {
1168 if (first)
1169 printTitle(flags, name, page, absolute, labelName);
1170 if (labelName)
1171 fprintf(stdout, ushortFormat, usval1, usval2, usdiff);
1172 else
1173 fprintf(stdout, ushortFormat, printIndex, usval1, usval2, usdiff);
1174 }
1175 break;
1176 case SDDS_CHARACTER:
1177 cval1 = *((char *)data1 + index);
1178 cval2 = *((char *)data2 + index);
1179 if (cval1 != cval2) {
1180 returnValue = 1;
1181 if (first)
1182 printTitle(flags, name, page, absolute, labelName);
1183 if (labelName)
1184 fprintf(stdout, charFormat, cval1, cval2, cval1 - cval2);
1185 else
1186 fprintf(stdout, charFormat, printIndex, cval1, cval2, cval1 - cval2);
1187 }
1188 break;
1189 default:
1190 fprintf(stderr, "Unknown data type %ld.\n", datatype);
1191 exit(EXIT_FAILURE);
1192 }
1193 return returnValue;
1194}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
char * SDDS_type_name[SDDS_NUM_TYPES]
Array of supported data type names.
Definition SDDS_data.c:43
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
SDDS_ARRAY * SDDS_GetArray(SDDS_DATASET *SDDS_dataset, char *array_name, SDDS_ARRAY *memory)
Retrieves an array from the current data table of an SDDS dataset.
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
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.
Definition SDDS_info.c:192
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.
Definition SDDS_info.c:117
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.
Definition SDDS_info.c:41
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *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.
Definition SDDS_utils.c:379
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.
Definition SDDS_utils.c:750
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.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
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.
Definition SDDS_utils.c:342
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.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
Definition SDDStypes.h:31
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
int get_longdouble(long double *dptr, char *s)
Parses a long double value from the given string.
Definition data_scan.c:88
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
Definition data_scan.c:255
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)
Definition scanargs.c:36
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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.
Definition trim_spaces.c:28