/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * This file is distributed subject to a Software License Agreement found * in the file LICENSE that is included with this distribution. \*************************************************************************/ /* program: sddsdiff * purpose: compare two sdds file. $Log: sddsdiff.c,v $ Revision 1.27 2009/09/10 17:13:44 shang modified to print errors and warnings to the standard error, and print the difference to stdout so that it can be piped out easily. Revision 1.26 2008/02/22 22:06:18 shang now it ignores the pre and post spaces when compare two strings. Revision 1.25 2007/10/05 19:11:53 shang modified to accept SDDS_ULONG and SDDS_USHORT type Revision 1.24 2007/04/02 19:00:07 soliday Removed call to isnan and isinf for integer numbers. Revision 1.23 2006/10/19 17:55:39 soliday Updated to work with linux-x86_64. Revision 1.22 2006/09/06 16:00:43 soliday Modified so that it uses the list of valid types from SDDS_type_name which comes from SDDSlib instead of a local copy which no longer matches SDDS_type_name Revision 1.21 2006/08/08 17:04:04 emery Removed unused variables to remove compilation warnings. Revision 1.20 2006/06/20 21:09:16 soliday Fixed a small sprintf bug. Revision 1.19 2006/05/02 18:16:12 soliday Fixed problems on WIN32. Revision 1.18 2006/04/05 18:22:27 shang added noComparison to rowlabel option to skip the comparison of row label column if it is specified. And the rowlabel column will not be compared if it only exists in one file no matter whether nocomparison is specified. Revision 1.17 2006/04/05 15:51:17 shang remvoed secondFile from rowlabel option, instead, program will check which file has rowlabel column automatically. If none of the input files has rowlabel column, a warning message will be printed out and use number of rows for labeling. Revision 1.16 2006/04/04 21:58:20 shang added -rowlabel=elementName[,secondFile] option to printout the row by label. The rowlabel column can any type of data. Revision 1.15 2006/03/24 21:20:15 shang fixed bug in printing out message for parameter difference that only the first different parameter name was printed out. Revision 1.14 2006/03/17 15:50:52 shang recommit because the previous statement was wrong. This version adds -absolute option to compare the different to absolute values. Revision 1.13 2006/03/17 15:47:34 shang This comment is actually for sddsrowstats. added positionColumn option to minimum, maximum, smallest and largest option to write the column name that has the option specified value in each row to the output file in the column name provided by positionColumn. Revision 1.12 2006/03/15 20:22:28 shang added -exact for exact comparison and -format for providing the print format for double, float and string data; fixed the bug that parameters or arrays are not compared if the page is empty (no rows). Revision 1.11 2005/11/29 18:34:33 shang replaced get_names by getMatchingSDDSNames Revision 1.10 2005/11/29 18:28:27 shang added precision option to compare given number of digits for floating point values. Revision 1.9 2005/11/07 21:48:10 soliday Updated to remove Linux compiler warnings. Revision 1.8 2005/11/04 22:46:13 soliday Updated code to be compiled by a 64 bit processor. Revision 1.7 2005/11/01 15:15:27 shang added -tolerance option and modified to accept NaN and Inf as numerical values. Revision 1.6 2005/09/30 18:23:41 shang removed linux warnings. Revision 1.5 2005/09/30 18:04:34 shang modified to compare data with different data types and added displaying of the difference, added -columns, -parameters and -arrays option to compare provided column[s], parameter[s] and/or array[s]. Revision 1.4 2005/04/28 18:34:50 shang fixed a bug in compare definitions Revision 1.3 2005/04/25 21:30:03 shang fixed bug in getting parameter infomation Revision 1.2 2005/04/25 21:13:23 shang fixed bug in compare definitons function and added compareCommon option to compare the common columns, parameters and arrays in two files. Revision 1.1 2005/03/16 16:30:42 shang first version for comparing two sdds files. */ #include "mdb.h" #include "SDDS.h" #include "scan.h" #include "SDDSutils.h" #include #define CLO_COMPARECOMMON 0 #define CLO_COLUMNS 1 #define CLO_PARAMETERS 2 #define CLO_ARRAYS 3 #define CLO_TOLERANCE 4 #define CLO_PRECISION 5 #define CLO_FORMAT 6 #define CLO_EXACT 7 #define CLO_ABSOLUTE 8 #define CLO_ROWLABEL 9 #define N_OPTIONS 10 char *option[N_OPTIONS] = {"compareCommon", "columns", "parameters", "arrays", "tolerance", "precision", "format", "exact", "absolute", "rowlabel"} ; char *USAGE1 = "sddsdiff [-compareCommon[=column|parameter|array]] [-columns=[,...]]\n\ [-parameters=...]] [-arrays=[,...]] [-tolerance=] \n\ [-precision= [-format=float=|double=|string=] [-exact] \n\ [-absolute] [-rowlabel=[,nocomparison]] \n\ sddsdiff compare two SDDS file.\n\ tolerance if given and greater than zero, \n\ two numerical values will be considered to be the same \n\ if their absolute difference is within the tolerance. \n\ if given and less than zero, \n\ two numerical values will be considered to be the same \n\ only if they equal to each other. \n\ precision if given, the number of digits compared for floating points values. \n\ exact if given, two values will be considered to be the same only if they are.\n\ only one of tolerance, precision, and exact should be given.\n"; char *USAGE2 = "absolute if given, the absolute of the values are compared, i.e., the signs are ignored.\n\ format provides the print format for float, double and/or string data. \n\ the default print format for float, double and string data are \n\ %25.8e %25.16e and %25s respectively. \n\ rowlabel specifies a column that will be printed out to label the rows. \n\ The rowlabel column has to exist in one of the input files. Otherwise, \n\ the rows are labeled by the row number (by default). \n\ if nocomparison is provided, then this rowlabel column will be used as \n\ labeling only and will not be compared. \n\ compareCommon if given, only compares the common columns, parameters and arrays.\n\ if compareCommon=column, only compares the common columns, and ect. \n\ columns if given, compares the given columns. \n\ parameters if given, compares the given parameters. \n\ arrays if given, compares the given arrays. \n\ columns, parameters and arrays option overwrites compareCommon option, i.e. \n\ only given columns, parameters and arrays in two file will be compared. \n\ Program by Hairong Shang. (This is version 1.0, March 2005)\n"; #define SDDS_COLUMN_TYPE 0 #define SDDS_PARAMETER_TYPE 1 #define SDDS_ARRAY_TYPE 2 /*type=0,1,2, for Column, Parameter, Array*/ long CompareDefinitions(SDDS_DATASET *dataset1, SDDS_DATASET *dataset2, char *file1, char *file2, long *names, char ***name, int32_t **dataType, long type, long compareCommon, char *rowLabelColumn, long notCompareRowLabelCol); long CompareData(SDDS_DATASET *dataset1, SDDS_DATASET *dataset2, char *file1, char *file2, long names, char **name, int32_t *dataType, long type, long page, double tolerance, double precisionTolerance, char *floatFormat, char *doubleFormat, char *stringFormat, long absolute, void *rowLabel, long rowLabelType, char *labelName); long compare_two_data(void *data1, void *data2, long index, long datatype, long first, long flags, char *name, long page, double tolerance, double precisionTolerance, char *floatFormat, char *doubleFormat, char *stringFormat, char *longFormat, char *ulongFormat, char *shortFormat, char *ushortFormat, char *charFormat, long absolute, long parameter, char *labelName); void printTitle(long flags, char *name, long page, long absolute, char *labelName); #define COMPARE_COMMON_COLUMN 0x0001U #define COMPARE_COMMON_PARAMETER 0x0002U #define COMPARE_COMMON_ARRAY 0x0004U int main(int argc, char **argv) { SCANNED_ARG *s_arg; SDDS_DATASET table1, table2; char *file1, *file2; long different=0, columns, parameters, arrays, i, pages1,pages2, rows1, rows2, pagediff=0, i_arg, columnMatches, parameterMatches, arrayMatches, absolute=0; int32_t *columnDataType, *parDataType, *arrayDataType; char **columnName, **parameterName, **arrayName, **columnMatch, **parameterMatch, **arrayMatch; long column_provided, parameter_provided, array_provided, precision, labelFromSecondFile=0, rowLabelType=0, rowLabelIndex=-1, notCompareRowLabel=0; double tolerance=0.0, precisionTolerance=0.0; unsigned long compareCommonFlags=0, dummyFlags=0; char *floatFormat, *doubleFormat, *stringFormat, *rowLabelColumn; void *rowLabel; rowLabelColumn = NULL; rowLabel = NULL; floatFormat = doubleFormat = stringFormat = NULL; precision = 0; columnDataType=parDataType=arrayDataType=NULL; columnName=parameterName=arrayName=NULL; columnMatch=parameterMatch=arrayMatch=NULL; columnMatches=parameterMatches=arrayMatches=0; columns=parameters=arrays=0; file1=file2=NULL; pages1=pages2=0; column_provided=parameter_provided=array_provided=0; SDDS_RegisterProgramName(argv[0]); argc = scanargs(&s_arg, argc, argv); if (argc<3) { fprintf(stderr, "%s%s", USAGE1, USAGE2); exit(1); } for (i_arg=1; i_arg2 && strncmp_case_insensitive("nocomparison", s_arg[i_arg].list[2], strlen(s_arg[i_arg].list[2]))==0) notCompareRowLabel = 1; break; case CLO_EXACT: tolerance = -1.0; break; case CLO_ABSOLUTE: absolute = 1; break; case CLO_TOLERANCE: if (s_arg[i_arg].n_items!=2) SDDS_Bomb("invalid -tolerance syntax"); if (!get_double(&tolerance, s_arg[i_arg].list[1])) SDDS_Bomb("invalid -tolerance syntax (not a number given)"); break; case CLO_PRECISION: if (s_arg[i_arg].n_items!=2) SDDS_Bomb("invalid -precision syntax"); if (!get_long(&precision, s_arg[i_arg].list[1])) SDDS_Bomb("invalid -precision syntax (not a number given)"); if (precision<0) precision=0; break; case CLO_FORMAT: if (s_arg[i_arg].n_items<2) SDDS_Bomb("Invalid -format syntax."); s_arg[i_arg].n_items--; if (!scanItemList(&dummyFlags, s_arg[i_arg].list+1, &s_arg[i_arg].n_items, 0, "float", SDDS_STRING, &floatFormat, 1, 0, "double", SDDS_STRING, &doubleFormat, 1, 0, "array", SDDS_STRING, &stringFormat, 1, 0, NULL)) SDDS_Bomb("Invalid -format syntax"); s_arg[i_arg].n_items++; if (floatFormat && !SDDS_VerifyPrintfFormat(floatFormat, SDDS_FLOAT)) { fprintf(stderr, "Error: given print format (\"%s\") for float data is invalid.\n", floatFormat); exit(1); } if (doubleFormat && !SDDS_VerifyPrintfFormat(doubleFormat, SDDS_DOUBLE)) { fprintf(stderr, "Error: given print format (\"%s\") for double data is invalid.\n", doubleFormat); exit(1); } if (stringFormat && !SDDS_VerifyPrintfFormat(stringFormat, SDDS_STRING)) { fprintf(stderr, "Error: given print format (\"%s\") for string data is invalid.\n", stringFormat); exit(1); } break; case CLO_COMPARECOMMON: if (s_arg[i_arg].n_items==1) compareCommonFlags |= COMPARE_COMMON_COLUMN | COMPARE_COMMON_PARAMETER | COMPARE_COMMON_ARRAY; else { s_arg[i_arg].n_items--; if (!scanItemList(&compareCommonFlags, s_arg[i_arg].list+1, &s_arg[i_arg].n_items, 0, "column", -1, NULL, 0, COMPARE_COMMON_COLUMN, "parameter", -1, NULL, 0, COMPARE_COMMON_PARAMETER, "array", -1, NULL, 0, COMPARE_COMMON_ARRAY, NULL)) SDDS_Bomb("Invalid -compareCommon syntax"); s_arg[i_arg].n_items++; } break; case CLO_COLUMNS: if (s_arg[i_arg].n_items<2) SDDS_Bomb("invalid -columns syntax"); columnMatch = tmalloc(sizeof(*columnMatch)*(columnMatches = s_arg[i_arg].n_items-1)); for (i=0; i0) { SDDS_Bomb("Tolerance and precision option are not compatible, only one of tolerance, precision and exact may be given."); } if (!file1 || !file2) { fprintf(stderr,"Two files must be provided for comparision.\n"); exit(1); } if (strcmp(file1,file2)==0) { printf("%s and %s are identical.\n", file1, file2); return 0; } if (!SDDS_InitializeInput(&table1, file1)) { SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors); exit(1); } if (!SDDS_InitializeInput(&table2, file2)) { SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors); exit(1); } if (rowLabelColumn) { if ((rowLabelIndex = SDDS_GetColumnIndex(&table1, rowLabelColumn))<0) { if ((rowLabelIndex =SDDS_GetColumnIndex(&table2, rowLabelColumn))<0) { fprintf(stdout,"Warning: row label column %s does not exist in the input files. The number of rows will be labeled instead.\n", rowLabelColumn); rowLabelColumn = NULL; } else { labelFromSecondFile = 1; notCompareRowLabel = 1; } } else { if (SDDS_GetColumnIndex(&table2, rowLabelColumn)<0) notCompareRowLabel = 1; } if (rowLabelColumn) { if (labelFromSecondFile) rowLabelType = SDDS_GetColumnType(&table2, rowLabelIndex); else rowLabelType = SDDS_GetColumnType(&table1, rowLabelIndex); } } if (!precision) precision = fabs(log10(DBL_EPSILON)); precisionTolerance = pow(10, -precision); if (column_provided) { columnName = getMatchingSDDSNames(&table1, columnMatch, columnMatches, &columns, SDDS_MATCH_COLUMN); if (CompareDefinitions(&table1,&table2,file1,file2,&columns,&columnName, &columnDataType,SDDS_COLUMN_TYPE, compareCommonFlags&COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel)) different=1; } if (parameter_provided) { parameterName = getMatchingSDDSNames(&table1, parameterMatch, parameterMatches, ¶meters, SDDS_MATCH_PARAMETER); if (CompareDefinitions(&table1,&table2,file1,file2,¶meters,¶meterName, &parDataType,SDDS_PARAMETER_TYPE, compareCommonFlags&COMPARE_COMMON_PARAMETER, NULL, 1)) different=1; } if (array_provided) { arrayName = getMatchingSDDSNames(&table1, arrayMatch, arrayMatches, &arrays, SDDS_MATCH_ARRAY); if (CompareDefinitions(&table1,&table2,file1,file2,&arrays, &arrayName,&arrayDataType,SDDS_ARRAY_TYPE, compareCommonFlags&COMPARE_COMMON_ARRAY, NULL, 1)) different=1; } if (!columns && !parameters && !arrays) { if (!compareCommonFlags || compareCommonFlags&COMPARE_COMMON_COLUMN) different += CompareDefinitions(&table1,&table2,file1,file2,&columns,&columnName, &columnDataType,SDDS_COLUMN_TYPE, compareCommonFlags&COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel); if (!compareCommonFlags || compareCommonFlags&COMPARE_COMMON_PARAMETER) different += CompareDefinitions(&table1,&table2,file1,file2,¶meters,¶meterName, &parDataType,SDDS_PARAMETER_TYPE, compareCommonFlags&COMPARE_COMMON_PARAMETER, NULL, 1); if (!compareCommonFlags || compareCommonFlags&COMPARE_COMMON_ARRAY) different += CompareDefinitions(&table1,&table2,file1,file2,&arrays, &arrayName,&arrayDataType,SDDS_ARRAY_TYPE, compareCommonFlags&COMPARE_COMMON_ARRAY, NULL, 1); } if (!different) { if (!columns && !parameters && !arrays) { fprintf(stderr,"There are no common columns, parameters or arrays in two files.\n"); different=1; } else { /*definitions are the same, now compare the data */ while (1) { pagediff=0; pages1=SDDS_ReadPage(&table1); pages2=SDDS_ReadPage(&table2); if (pages1>0 && pages2>0) { /*compare data */ rows1=SDDS_CountRowsOfInterest(&table1); rows2=SDDS_CountRowsOfInterest(&table2); if (rows1!=rows2) { pagediff=1; different=1; fprintf(stderr,"Two files have different rows in page %ld, %s has %ld rows, while %s has %ld rows.\n", pages1, file1, rows1, file2, rows2); break; } else { if (parameters) pagediff +=CompareData(&table1,&table2,file1,file2,parameters,parameterName,parDataType,SDDS_PARAMETER_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL); if (columns && rows1) { if (rowLabelColumn) { if (labelFromSecondFile) { if (!(rowLabel=SDDS_GetColumn(&table2, rowLabelColumn))) SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors); } else { if (!(rowLabel=SDDS_GetColumn(&table1, rowLabelColumn))) SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors); } } pagediff +=CompareData(&table1,&table2,file1,file2,columns,columnName,columnDataType,SDDS_COLUMN_TYPE,pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, stringFormat, absolute, rowLabel, rowLabelType, rowLabelColumn); if (rowLabelColumn) { if (rowLabelType==SDDS_STRING) SDDS_FreeStringArray((char**)rowLabel, rows1); else free(rowLabel); rowLabel = NULL; } } if (arrays) pagediff +=CompareData(&table1,&table2,file1,file2,arrays,arrayName,arrayDataType,SDDS_ARRAY_TYPE,pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL); different +=pagediff; } /*if (!pagediff) printf("%s and %s are same at page %ld\n",file1, file2, pages1);*/ } else if (pages1>0 && pages2<=0) { fprintf(stderr,"%s has less pages than %s.\n",file2,file1); different=1; break; } else if (pages1<0 && pages2>0) { different=1; fprintf(stderr,"%s has less pages than %s.\n",file1,file2); break; } else { break; } } } } else { different=1; } if (!different) printf("%s and %s are identical.\n",file1,file2); else fprintf(stderr, "%s and %s are different.\n", file1, file2); if (columns) { for (i=0;ielements != array2->elements) { fprintf(stderr,"Array %s has %" PRId32 " elements in file1, but %" PRId32 " elements in file2.\n", name[i],array1->elements,array2->elements); diff++; } else { for (j=0;jelements;j++) { if (compare_two_data(array1->data, array2->data, j, dataType[i], first, SDDS_ARRAY_TYPE, name[i], page, tolerance, precisionTolerance, fFormat, dFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, NULL)!=0) { diff++; if (first) first=0; } } } SDDS_FreeArray(array1); SDDS_FreeArray(array2); array1=array2=NULL; } break; } return diff; } void printTitle(long flags, char *name, long page, long absolute, char *labelName) { char *type=NULL; char *element=NULL; switch (flags) { case SDDS_COLUMN_TYPE: SDDS_CopyString(&type, "column"); if (labelName) SDDS_CopyString(&element, labelName); else SDDS_CopyString(&element, "row"); break; case SDDS_PARAMETER_TYPE: SDDS_CopyString(&type, "parameter"); SDDS_CopyString(&element, "page number"); break; case SDDS_ARRAY_TYPE: SDDS_CopyString(&type, "array"); SDDS_CopyString(&element, "element number"); break; } if (type) { fprintf(stdout,"\nThe value of %s %s at page %ld are different in two files:\n",type, name,page); if (absolute) fprintf(stdout,"%20s%25s%25s%25s\n", element, "value in file1", "value in file2", "abs(file1)-abs(file2)"); else fprintf(stdout,"%20s%25s%25s%25s\n", element, "value in file1", "value in file2", "file1-file2"); free(type); free(element); } } long compare_two_data(void *data1, void *data2, long index, long datatype, long first, long flags, char *name, long page, double tolerance, double precisionTolerance, char *floatFormat, char *doubleFormat, char *stringFormat, char *longFormat, char *ulongFormat, char *shortFormat, char *ushortFormat, char *charFormat, long absolute, long parameter, char *labelName) { char *str1, *str2; double dval1, dval2, denominator, dabs1, dabs2, ddiff; float fval1, fval2, fabs1, fabs2, fdenominator, fdiff; int32_t lval1, lval2, labs1, labs2, ldiff; uint32_t ulval1, ulval2, uldiff; short sval1, sval2, sabs1, sabs2, sdiff; unsigned short usval1, usval2, usdiff; char cval1, cval2; long returnValue=0, printIndex; double tol; printIndex = index + 1; if (parameter) printIndex = page; if (tolerance<0) tol = 0; else tol = tolerance; switch (datatype) { case SDDS_STRING: str1=*((char**)data1+index); str2=*((char**)data2+index); returnValue=strcmp(trim_spaces(str1), trim_spaces(str2)); if (returnValue!=0) { if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) { fprintf(stdout, stringFormat, str1, str2,returnValue); } else fprintf(stdout, stringFormat, printIndex, str1, str2,returnValue); } break; case SDDS_DOUBLE: dval1=*((double*)data1+index); dval2=*((double*)data2+index); if (absolute) { dabs1 = fabs(dval1); dabs2 = fabs(dval2); } else { dabs1 = dval1; dabs2 = dval2; } ddiff = dabs1-dabs2; if ((isnan(dval1)&& !isnan(dval2)) || (isinf(dval1) && !isinf(dval2))) returnValue=1; else if (dabs1!=dabs2) { if (tolerance) { if (fabs(ddiff)>tol) returnValue = 1; } else { if (dabs1==0 || dabs2==0) { if (fabs(dabs1-dabs2)>precisionTolerance) returnValue = 1; } else { dabs1 = fabs(dval1); dabs2 = fabs(dval2); denominator = (dabs1precisionTolerance) returnValue = 1; } } } if (returnValue) { if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) fprintf(stdout, doubleFormat, dval1, dval2, ddiff); else fprintf(stdout, doubleFormat, printIndex, dval1, dval2, ddiff); } break; case SDDS_FLOAT: fval1=*((float*)data1+index); fval2=*((float*)data2+index); if (absolute) { fabs1 = fabs(fval1); fabs2 = fabs(fval2); } else { fabs1 = fval1; fabs2 = fval2; } fdiff = fabs1 - fabs2; if ((isnan(fval1) && !isnan(fval2)) || (isinf(fval1) && !isinf(fval2))) returnValue=1; else if (fabs1 != fabs2) { if (tolerance) { if (fabs(fdiff)>tol) returnValue = 1; } else { if (fabs1==0 || fabs2==0) { if (fabs(fabs1-fabs2)>precisionTolerance) returnValue = 1; } else { fabs1 = fabs(fval1); fabs2 = fabs(fval2); fdenominator = (fabs1precisionTolerance) returnValue = 1; } } } if (returnValue) { if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) fprintf(stdout, floatFormat, fval1, fval2, fdiff); else fprintf(stdout, floatFormat , printIndex, fval1, fval2, fdiff); } break; case SDDS_ULONG: ulval1=*((uint32_t*)data1+index); ulval2=*((uint32_t*)data2+index); uldiff = ulval1 - ulval2; if (labs(uldiff)>tol) returnValue=1; if (returnValue) { if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) fprintf(stdout, ulongFormat, ulval1, ulval2, uldiff); else fprintf(stdout, ulongFormat, printIndex, ulval1, ulval2, uldiff); } break; case SDDS_LONG: lval1=*((int32_t*)data1+index); lval2=*((int32_t*)data2+index); if (absolute) { labs1 = abs(lval1); labs2 = abs(lval2); } else { labs1 = lval1; labs2 = lval2; } ldiff = labs1 - labs2; if (labs(ldiff)>tol) returnValue=1; if (returnValue) { if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) fprintf(stdout, longFormat, lval1, lval2, ldiff); else fprintf(stdout, longFormat, printIndex, lval1, lval2, ldiff); } break; case SDDS_SHORT: sval1=*((short*)data1+index); sval2=*((short*)data2+index); if (absolute) { sabs1 = abs(sval1); sabs2 = abs(sval2); } else { sabs1 = sval1; sabs2 = sval2; } sdiff = sabs1 - sabs2; if (abs(sdiff)>tol) returnValue=1; if (returnValue) { if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) fprintf(stdout, shortFormat, sval1, sval2, sdiff); else fprintf(stdout, shortFormat, printIndex, sval1, sval2, sdiff); } break; case SDDS_USHORT: usval1=*((unsigned short*)data1+index); usval2=*((unsigned short*)data2+index); usdiff = usval1 - usval2; if (abs(usdiff)>tol) returnValue=1; if (returnValue) { if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) fprintf(stdout, ushortFormat, usval1, usval2, usdiff); else fprintf(stdout, ushortFormat, printIndex, usval1, usval2, usdiff); } break; case SDDS_CHARACTER: cval1=*((char*)data1+index); cval2=*((char*)data2+index); if (cval1!=cval2) { returnValue=1; if (first) printTitle(flags, name, page, absolute, labelName); if (labelName) fprintf(stdout, charFormat, cval1, cval2, cval1-cval2); else fprintf(stdout, charFormat, printIndex, cval1, cval2, cval1-cval2); } break; default: fprintf(stderr,"unknown data type %ld.\n",datatype); exit(1); } return returnValue; }