void ImageHistogram<T>::toAscii( QTextStream& out ) const { const QString LINE_END( "\n"); QString centerStr( "#Bin Center("); casa::Unit unit = ImageHistogram::m_image->units(); QString unitStr( unit.getName().c_str()); centerStr.append( unitStr + ")"); out << centerStr << "Count"; out << LINE_END; out.flush(); int count = m_xValues.size(); for ( int i = 0; i < count; i++ ) { out << QString::number(m_xValues[i]) << QString::number( m_yValues[i]); out << LINE_END; out.flush(); } }
int main(int argc, char **argv) { bool nufftMode = false; int arg; while ((arg = getopt(argc, argv, "nh")) != -1) { switch (arg) { case 'n': nufftMode = true; break; default: case 'h': usage(argv); } } unsigned numFiles = argc - optind; if(numFiles < 2) { usage(argv); } if(nufftMode && (numFiles != 2)) { printf("***NUFFT mode requires two input files.\n"); exit(1); } /* open TextParsers for each input file */ char *fileName[numFiles]; TextParser *parser[numFiles]; for(unsigned dex=0; dex<numFiles; dex++) { fileName[dex] = argv[optind + dex]; parser[dex] = new TextParser(fileName[dex]); } /* * The header of all outputs looks like this: * * Library : MatrixFFT * FFT type : Two-dimension complex * Precision : Single * Signal type : Chirp * Loops : 10 * Threads : 8 * Options : Don't time first loop, In-place * System : Version 10.6 (Build 10A110) * CPU : Intel(R) Xeon(R) CPU X5482 @ 3.20GHz * Built as : 64 bit * Complex : Interleaved * Test time : 14:02:29 Oct 6 2008 * * "Loops", "Threads", and "Options" lines are optional. * Do basic validation by getting "Library Type" for each file. */ char libType[numFiles][LINE_LENGTH_MAX]; for(unsigned dex=0; dex<numFiles; dex++) { if(fineLineWithTitle(*parser[dex], "Library", libType[dex])) { printf("***%s is not an FFT output file\n", fileName[dex]); exit(1); } } /* * Make sure precisions, FFT types, and signal types match; * log them as well as log test time for the first file. */ char lineBuf[LINE_LENGTH_MAX]; bool match; for(unsigned dex=1; dex<numFiles; dex++) { if(compareLines(*parser[0], *parser[dex], "FFT type", match, lineBuf)) { printf("***No FFT type line found\n"); exit(1); } if(!match) { printf("***%s and %s measure different FFT types\n", fileName[0], fileName[dex]); exit(1); } } printf("%s\n", lineBuf); bool isConvolve = false; if(strstr(lineBuf, "Convolve")) { isConvolve = true; } for(unsigned dex=1; dex<numFiles; dex++) { if(compareLines(*parser[0], *parser[dex], "Precision", match, lineBuf)) { printf("***No Precision line found\n"); exit(1); } if(!match) { printf("***%s and %s measure different Precision\n", fileName[0], fileName[dex]); exit(1); } } printf("%s\n", lineBuf); for(unsigned dex=1; dex<numFiles; dex++) { if(compareLines(*parser[0], *parser[dex], "Signal type", match, lineBuf)) { printf("***No Signal type line found\n"); exit(1); } if(!match) { printf("***%s and %s measure different Signal types\n", fileName[0], fileName[dex]); exit(1); } } printf("%s\n", lineBuf); /* Optional "Threads" line - print it */ if(parser[0]->findLine("Threads", lineBuf)) { printf("%s\n", lineBuf); } /* and rewind this one in any case; we may be past the Test time line */ parser[0]->setCursor(0); /* * print following required fields: * system version (S/W) * CPU * Built as (32/64 bit) * Complex format * Test time * * NOTE: the Complex Format line anly applies to MatrixFFT; we generally * reuse data from one run of FFTW and vDSP for both Split and Interleaved * format MFFT builds. So, the MFFT file really needs to be specified * first to get the correct COmplex format in the collated output. */ if(!parser[0]->findLine("System", lineBuf)) { printf("***No System found\n"); exit(1); } printf("%s\n", lineBuf); if(!parser[0]->findLine("CPU", lineBuf)) { printf("***No CPU found\n"); exit(1); } printf("%s\n", lineBuf); if(!parser[0]->findLine("Built as", lineBuf)) { printf("***No Built as found\n"); exit(1); } printf("%s\n", lineBuf); if(!parser[0]->findLine("Complex", lineBuf)) { printf("***No Complex found\n"); exit(1); } printf("%s\n", lineBuf); if(!parser[0]->findLine("Test time", lineBuf)) { printf("***No Test Time found\n"); exit(1); } printf("%s\n\n", lineBuf); /* * The output we're parsing looks like this 2-D: * * Width | Height | Samples | Wall time (s) | CTGs * -----------+--------+------------+---------------+--------- * 1024 | 1024 | 1048576 | 0.606012 | 3.46058 * ... * * And for 1-D: * * Samples | Wall time (s) | CTGs * -----------+---------------+-------- * 1024 | 0.000013 | 3.86415 * * For convolve: * * Image Rows | Image Cols | Kernel size | Convolution time (s) * -----------+------------+-------------+--------------------- * * For NUFFT: * * Samples | Wall time (s) | ms/loop * ---------+---------------+---------- * 2^5 | 0.002 | 0.16 * * 1000 | 1000 | 3 | 0.07004 * * So, we generally use the column header line to figure out what kind of output we're * dealing with. */ if(!isConvolve && !nufftMode) { if(!parser[0]->findLine("Samples", lineBuf)) { printf("***Malformed input file (no Samples line)\n"); exit(1); } } unsigned totalTokens = 0; /* expected tokens per line */ unsigned ctgToken = 0; /* index of CTGs/time token */ unsigned matchTokens = 0; /* % of tokens that must match exactly */ bool is2Dim = false; const char **tokens = NULL; unsigned numTokens = parser[0]->parseLine(lineBuf, tokens); char *numStrings[3] = {NULL, NULL, NULL}; if(isConvolve) { is2Dim = true; totalTokens = 7; ctgToken = 6; matchTokens = 6; } else if(nufftMode) { is2Dim = false; totalTokens = 5; matchTokens = 2; ctgToken = 4; // not CTGs, but ms/loop, and we print it as a string } else { switch(numTokens) { case 7: /* 1-dim */ is2Dim = false; totalTokens = 5; ctgToken = 4; matchTokens = 2; break; case 11: /* 2-dim */ is2Dim = true; totalTokens = 9; ctgToken = 8; matchTokens = 6; break; default: printf("***Malformed input file (3)\n"); exit(1); } } parser[0]->freeTokens(numTokens, tokens); /* Skip ahead to first actual data in all files */ for(unsigned dex=0; dex<numFiles; dex++) { if(!parser[dex]->findLine("-----------+", lineBuf)) { printf("***Malformed input file %s (1)\n", fileName[dex]); exit(1); } } if(isConvolve) { printf(" Image Rows | Image Cols | Kernel size "); for(unsigned dex=0; dex<numFiles; dex++) { printf("| %6s time (s) ", libType[dex]); } printf("\n"); printf(" -----------+------------+-------------"); for(unsigned dex=0; dex<numFiles; dex++) { printf("+-----------------"); } printf("\n"); } else if(nufftMode) { printf(" reference optimized\n"); printf(" Samples | ms/loop | ms/loop ratio\n"); printf(" ---------+-------------+-----------+--------\n"); } else if(is2Dim) { printf(" Width | Height | Samples "); for(unsigned dex=0; dex<numFiles; dex++) { char *title = centerStr(libType[dex], "CTGs", 11); printf("|%s", title); free(title); } printf("\n"); printf(" -------+--------+---------"); for(unsigned dex=0; dex<numFiles; dex++) { printf("+-----------"); } printf("\n"); } else { printf(" Samples "); for(unsigned dex=0; dex<numFiles; dex++) { char *title = centerStr(libType[dex], "CTGs", 11); printf("|%s", title); free(title); } printf("\n"); printf(" ---------"); for(unsigned dex=0; dex<numFiles; dex++) { printf("+-----------"); } printf("\n"); } while(1) { unsigned numTokensArr[numFiles]; const char **tokensArr[numFiles]; /* We quit when any file runs out of data */ bool outOfData = false; for(unsigned dex=0; dex<numFiles; dex++) { if(parser[dex]->getTokens(numTokensArr[dex], tokensArr[dex])) { /* no more data */ outOfData = true; break; } if(numTokensArr[dex] == 0) { /* empty line */ outOfData = true; break; } } if(outOfData) { break; } /* verify all files have the right number of tokens */ for(unsigned dex=0; dex<numFiles; dex++) { if(numTokensArr[dex] != totalTokens) { printf("***Malformed input file %s (2)\n", fileName[dex]); exit(1); } } /* the first matchTokens tokens must match exactly */ for(unsigned fileDex=1; fileDex<numFiles; fileDex++) { for(unsigned tokenDex=0; tokenDex<matchTokens; tokenDex++) { if(strcmp(tokensArr[0][tokenDex], tokensArr[fileDex][tokenDex])) { /* maybe they are numbers printed with different representations.. */ size_t num1 = fftParseStringRep(tokensArr[0][tokenDex]); size_t num2 = fftParseStringRep(tokensArr[fileDex][tokenDex]); if((num1 != 0) && (num1 != num2)) { printf("***Mismatched input files\n"); exit(1); } } } } if(isConvolve) { printf(" %6s | %6s | %6s ", tokensArr[0][0], tokensArr[0][2], tokensArr[0][4]); for(unsigned dex=0; dex<numFiles; dex++) { printf("| %10s ", tokensArr[dex][ctgToken]); } printf("\n"); } else if(nufftMode) { /* * Though we print the ms/loop values as uninterpreted strings, we have to parse * them into floats in order to calculate the ratio. */ float f0 = strtof(tokensArr[0][ctgToken], NULL); float f1 = strtof(tokensArr[1][ctgToken], NULL); float ratio = f0 / f1; printf(" %6s | %8s | %8s | %5.1f\n", tokensArr[0][0], tokensArr[0][ctgToken], tokensArr[1][ctgToken], ratio); } else { /* * Convert all numbers to canonical form, no matter how they appear in * input files */ size_t n = fftParseStringRep(tokensArr[0][0]); numStrings[0] = fftStringRepPow2(n); if(is2Dim) { n = fftParseStringRep(tokensArr[0][2]); numStrings[1] = fftStringRepPow2(n); n = fftParseStringRep(tokensArr[0][4]); numStrings[2] = fftStringRepPow2(n); } if(is2Dim) { printf(" %-6s | %-6s | %-6s ", numStrings[0], numStrings[1], numStrings[2]); for(unsigned dex=0; dex<numFiles; dex++) { printf("| %8s ", tokensArr[dex][ctgToken]); } printf("\n"); } else { printf(" %-6s ", numStrings[0]); for(unsigned dex=0; dex<numFiles; dex++) { printf("| %7s ", tokensArr[dex][ctgToken]); } printf("\n"); } free(numStrings[0]); if(is2Dim) { free(numStrings[1]); free(numStrings[2]); } } for(unsigned dex=0; dex<numFiles; dex++) { parser[dex]->freeTokens(numTokensArr[dex], tokensArr[dex]); } } printf("\n"); /* clean up */ for(unsigned dex=0; dex<numFiles; dex++) { delete parser[dex]; } return 0; }